summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-03-11 17:53:17 +0000
committerNicolas Geoffray <ngeoffray@google.com>2014-03-13 09:23:12 +0000
commitbab4ed7057799a4fadc6283108ab56f389d117d4 (patch)
treeea1bf495458fd9f7a3ffbed0ea4e1dda5a0b8184 /compiler/optimizing/code_generator.cc
parent37d4c1db4d705f5a28001f65afdd68d0527948d8 (diff)
downloadart-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.cc51
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 {