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
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 356e909..62bf7ba 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -24,28 +24,52 @@
namespace arm {
void CodeGeneratorARM::GenerateFrameEntry() {
- RegList registers = (1 << LR) | (1 << FP);
- __ PushList(registers);
+ __ PushList((1 << FP) | (1 << LR));
+ __ mov(FP, ShifterOperand(SP));
+ if (frame_size_ != 0) {
+ __ AddConstant(SP, -frame_size_);
+ }
}
void CodeGeneratorARM::GenerateFrameExit() {
- RegList registers = (1 << PC) | (1 << FP);
- __ PopList(registers);
+ __ mov(SP, ShifterOperand(FP));
+ __ PopList((1 << FP) | (1 << PC));
}
void CodeGeneratorARM::Bind(Label* label) {
__ Bind(label);
}
+void CodeGeneratorARM::Push(HInstruction* instruction, Location location) {
+ __ Push(location.reg<Register>());
+}
+
+void CodeGeneratorARM::Move(HInstruction* instruction, Location location) {
+ HIntConstant* constant = instruction->AsIntConstant();
+ if (constant != nullptr) {
+ __ LoadImmediate(location.reg<Register>(), constant->value());
+ } else {
+ __ Pop(location.reg<Register>());
+ }
+}
+
+void LocationsBuilderARM::VisitGoto(HGoto* got) {
+ got->set_locations(nullptr);
+}
+
void CodeGeneratorARM::VisitGoto(HGoto* got) {
HBasicBlock* successor = got->GetSuccessor();
if (graph()->exit_block() == successor) {
GenerateFrameExit();
- } else if (!GoesToNextBlock(got)) {
+ } else if (!GoesToNextBlock(got->block(), successor)) {
__ b(GetLabelOf(successor));
}
}
+void LocationsBuilderARM::VisitExit(HExit* exit) {
+ exit->set_locations(nullptr);
+}
+
void CodeGeneratorARM::VisitExit(HExit* exit) {
if (kIsDebugBuild) {
__ Comment("Unreachable");
@@ -53,33 +77,101 @@
}
}
+void LocationsBuilderARM::VisitIf(HIf* if_instr) {
+ LocationSummary* locations = new (graph()->arena()) LocationSummary(if_instr);
+ locations->SetInAt(0, Location(R0));
+ if_instr->set_locations(locations);
+}
+
void CodeGeneratorARM::VisitIf(HIf* if_instr) {
- LOG(FATAL) << "UNIMPLEMENTED";
+ // TODO: Generate the input as a condition, instead of materializing in a register.
+ __ cmp(if_instr->locations()->InAt(0).reg<Register>(), ShifterOperand(0));
+ __ b(GetLabelOf(if_instr->IfFalseSuccessor()), EQ);
+ if (!GoesToNextBlock(if_instr->block(), if_instr->IfTrueSuccessor())) {
+ __ b(GetLabelOf(if_instr->IfTrueSuccessor()));
+ }
+}
+
+void LocationsBuilderARM::VisitEqual(HEqual* equal) {
+ LocationSummary* locations = new (graph()->arena()) LocationSummary(equal);
+ locations->SetInAt(0, Location(R0));
+ locations->SetInAt(1, Location(R1));
+ locations->SetOut(Location(R0));
+ equal->set_locations(locations);
}
void CodeGeneratorARM::VisitEqual(HEqual* equal) {
- LOG(FATAL) << "UNIMPLEMENTED";
+ LocationSummary* locations = equal->locations();
+ __ teq(locations->InAt(0).reg<Register>(),
+ ShifterOperand(locations->InAt(1).reg<Register>()));
+ __ mov(locations->Out().reg<Register>(), ShifterOperand(1), EQ);
+ __ mov(locations->Out().reg<Register>(), ShifterOperand(0), NE);
+}
+
+void LocationsBuilderARM::VisitLocal(HLocal* local) {
+ local->set_locations(nullptr);
}
void CodeGeneratorARM::VisitLocal(HLocal* local) {
- LOG(FATAL) << "UNIMPLEMENTED";
+ DCHECK_EQ(local->block(), graph()->entry_block());
+ frame_size_ += kWordSize;
}
-void CodeGeneratorARM::VisitLoadLocal(HLoadLocal* local) {
- LOG(FATAL) << "UNIMPLEMENTED";
+void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
+ LocationSummary* locations = new (graph()->arena()) LocationSummary(load);
+ locations->SetOut(Location(R0));
+ load->set_locations(locations);
}
-void CodeGeneratorARM::VisitStoreLocal(HStoreLocal* local) {
- LOG(FATAL) << "UNIMPLEMENTED";
+static int32_t GetStackSlot(HLocal* local) {
+ // We are currently using FP to access locals, so the offset must be negative.
+ return (local->reg_number() + 1) * -kWordSize;
+}
+
+void CodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
+ LocationSummary* locations = load->locations();
+ __ LoadFromOffset(kLoadWord, locations->Out().reg<Register>(),
+ FP, GetStackSlot(load->GetLocal()));
+}
+
+void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
+ LocationSummary* locations = new (graph()->arena()) LocationSummary(store);
+ locations->SetInAt(1, Location(R0));
+ store->set_locations(locations);
+}
+
+void CodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
+ LocationSummary* locations = store->locations();
+ __ StoreToOffset(kStoreWord, locations->InAt(1).reg<Register>(),
+ FP, GetStackSlot(store->GetLocal()));
+}
+
+void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
+ constant->set_locations(nullptr);
}
void CodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
- LOG(FATAL) << "UNIMPLEMENTED";
+ // Will be generated at use site.
+}
+
+void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
+ ret->set_locations(nullptr);
}
void CodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
GenerateFrameExit();
}
+void LocationsBuilderARM::VisitReturn(HReturn* ret) {
+ LocationSummary* locations = new (graph()->arena()) LocationSummary(ret);
+ locations->SetInAt(0, Location(R0));
+ ret->set_locations(locations);
+}
+
+void CodeGeneratorARM::VisitReturn(HReturn* ret) {
+ DCHECK_EQ(ret->locations()->InAt(0).reg<Register>(), R0);
+ GenerateFrameExit();
+}
+
} // namespace arm
} // namespace art