diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-03-11 17:53:17 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-03-13 09:23:12 +0000 |
commit | bab4ed7057799a4fadc6283108ab56f389d117d4 (patch) | |
tree | ea1bf495458fd9f7a3ffbed0ea4e1dda5a0b8184 /compiler/optimizing/code_generator.cc | |
parent | 37d4c1db4d705f5a28001f65afdd68d0527948d8 (diff) | |
download | art-bab4ed7057799a4fadc6283108ab56f389d117d4.zip art-bab4ed7057799a4fadc6283108ab56f389d117d4.tar.gz art-bab4ed7057799a4fadc6283108ab56f389d117d4.tar.bz2 |
More code generation for the optimizing compiler.
- Add HReturn instruction
- Generate code for locals/if/return
- Setup infrastructure for register allocation. Currently
emulate a stack.
Change-Id: Ib28c2dba80f6c526177ed9a7b09c0689ac8122fb
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 01fc23b..56342aa 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -26,9 +26,11 @@ namespace art { void CodeGenerator::Compile(CodeAllocator* allocator) { - GenerateFrameEntry(); const GrowableArray<HBasicBlock*>* blocks = graph()->blocks(); - for (size_t i = 0; i < blocks->Size(); i++) { + DCHECK(blocks->Get(0) == graph()->entry_block()); + DCHECK(GoesToNextBlock(graph()->entry_block(), blocks->Get(1))); + CompileEntryBlock(); + for (size_t i = 1; i < blocks->Size(); i++) { CompileBlock(blocks->Get(i)); } size_t code_size = assembler_->CodeSize(); @@ -37,17 +39,54 @@ void CodeGenerator::Compile(CodeAllocator* allocator) { assembler_->FinalizeInstructions(code); } +void CodeGenerator::CompileEntryBlock() { + HGraphVisitor* location_builder = GetLocationBuilder(); + // The entry block contains all locals for this method. By visiting the entry block, + // we're computing the required frame size. + for (HInstructionIterator it(graph()->entry_block()); !it.Done(); it.Advance()) { + HInstruction* current = it.Current(); + // Instructions in the entry block should not generate code. + if (kIsDebugBuild) { + current->Accept(location_builder); + DCHECK(current->locations() == nullptr); + } + current->Accept(this); + } + GenerateFrameEntry(); +} + void CodeGenerator::CompileBlock(HBasicBlock* block) { Bind(GetLabelOf(block)); + HGraphVisitor* location_builder = GetLocationBuilder(); for (HInstructionIterator it(block); !it.Done(); it.Advance()) { - it.Current()->Accept(this); + // For each instruction, we emulate a stack-based machine, where the inputs are popped from + // the runtime stack, and the result is pushed on the stack. We currently can do this because + // we do not perform any code motion, and the Dex format does not reference individual + // instructions but uses registers instead (our equivalent of HLocal). + HInstruction* current = it.Current(); + current->Accept(location_builder); + InitLocations(current); + current->Accept(this); + if (current->locations() != nullptr && current->locations()->Out().IsValid()) { + Push(current, current->locations()->Out()); + } + } +} + +void CodeGenerator::InitLocations(HInstruction* instruction) { + if (instruction->locations() == nullptr) return; + for (int i = 0; i < instruction->InputCount(); i++) { + Location location = instruction->locations()->InAt(i); + if (location.IsValid()) { + // Move the input to the desired location. + Move(instruction->InputAt(i), location); + } } } -bool CodeGenerator::GoesToNextBlock(HGoto* goto_instruction) const { - HBasicBlock* successor = goto_instruction->GetSuccessor(); +bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const { // We currently iterate over the block in insertion order. - return goto_instruction->block()->block_id() + 1 == successor->block_id(); + return current->block_id() + 1 == next->block_id(); } Label* CodeGenerator::GetLabelOf(HBasicBlock* block) const { |