summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-04-07 13:20:42 +0100
committerNicolas Geoffray <ngeoffray@google.com>2014-04-07 15:24:23 +0100
commitf583e5976e1de9aa206fb8de4f91000180685066 (patch)
tree0e7c2d30af5c713012f0a33e6dd7d8f71e7fc85d /compiler
parent7ab4e5c5288e04b7beb6d8ddfd5e8bf878002732 (diff)
downloadart-f583e5976e1de9aa206fb8de4f91000180685066.zip
art-f583e5976e1de9aa206fb8de4f91000180685066.tar.gz
art-f583e5976e1de9aa206fb8de4f91000180685066.tar.bz2
Add support for taking parameters in optimizing compiler.
- Fix stack layout to mimic Quick's. - Implement some sub operations. Change-Id: I8cf75a4d29b662381a64f02c0bc61d859482fc4e
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/builder.cc135
-rw-r--r--compiler/optimizing/builder.h11
-rw-r--r--compiler/optimizing/code_generator.cc13
-rw-r--r--compiler/optimizing/code_generator_arm.cc83
-rw-r--r--compiler/optimizing/code_generator_x86.cc83
-rw-r--r--compiler/optimizing/nodes.h60
6 files changed, 336 insertions, 49 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index d90405a..f89583d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -25,7 +25,8 @@
namespace art {
-void HGraphBuilder::InitializeLocals(int count) {
+void HGraphBuilder::InitializeLocals(uint16_t count) {
+ graph_->SetNumberOfVRegs(count);
locals_.SetSize(count);
for (int i = 0; i < count; i++) {
HLocal* local = new (arena_) HLocal(i);
@@ -34,11 +35,54 @@ void HGraphBuilder::InitializeLocals(int count) {
}
}
+bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
+ // dex_compilation_unit_ is null only when unit testing.
+ if (dex_compilation_unit_ == nullptr) {
+ return true;
+ }
+
+ graph_->SetNumberOfInVRegs(number_of_parameters);
+ const char* shorty = dex_compilation_unit_->GetShorty();
+ int locals_index = locals_.Size() - number_of_parameters;
+ HBasicBlock* first_block = entry_block_->GetSuccessors()->Get(0);
+ int parameter_index = 0;
+
+ if (!dex_compilation_unit_->IsStatic()) {
+ // Add the implicit 'this' argument, not expressed in the signature.
+ HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++);
+ first_block->AddInstruction(parameter);
+ HLocal* local = GetLocalAt(locals_index++);
+ first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ number_of_parameters--;
+ }
+
+ uint32_t pos = 1;
+ for (int i = 0; i < number_of_parameters; i++) {
+ switch (shorty[pos++]) {
+ case 'F':
+ case 'D':
+ case 'J': {
+ return false;
+ }
+
+ default: {
+ // integer and reference parameters.
+ HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++);
+ first_block->AddInstruction(parameter);
+ HLocal* local = GetLocalAt(locals_index++);
+ // Store the parameter value in the local that the dex code will use
+ // to reference that parameter.
+ first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ break;
+ }
+ }
+ }
+ return true;
+}
+
static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) {
if (code_item.tries_size_ > 0) {
return false;
- } else if (code_item.ins_size_ > 0) {
- return false;
}
return true;
}
@@ -66,6 +110,10 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
// start a new block, and create these blocks.
ComputeBranchTargets(code_ptr, code_end);
+ if (!InitializeParameters(code_item.ins_size_)) {
+ return nullptr;
+ }
+
size_t dex_offset = 0;
while (code_ptr < code_end) {
// Update the current block if dex_offset starts a new block.
@@ -139,6 +187,44 @@ HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
return branch_targets_.Get(index);
}
+template<typename T>
+void HGraphBuilder::Binop_32x(const Instruction& instruction) {
+ HInstruction* first = LoadLocal(instruction.VRegB());
+ HInstruction* second = LoadLocal(instruction.VRegC());
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
+template<typename T>
+void HGraphBuilder::Binop_12x(const Instruction& instruction) {
+ HInstruction* first = LoadLocal(instruction.VRegA());
+ HInstruction* second = LoadLocal(instruction.VRegB());
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
+template<typename T>
+void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
+ HInstruction* first = LoadLocal(instruction.VRegB());
+ HInstruction* second = GetConstant(instruction.VRegC_22s());
+ if (reverse) {
+ std::swap(first, second);
+ }
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
+template<typename T>
+void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
+ HInstruction* first = LoadLocal(instruction.VRegB());
+ HInstruction* second = GetConstant(instruction.VRegC_22b());
+ if (reverse) {
+ std::swap(first, second);
+ }
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
if (current_block_ == nullptr) {
return true; // Dead code
@@ -185,7 +271,8 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
break;
}
- case Instruction::RETURN: {
+ case Instruction::RETURN:
+ case Instruction::RETURN_OBJECT: {
HInstruction* value = LoadLocal(instruction.VRegA());
current_block_->AddInstruction(new (arena_) HReturn(value));
current_block_->AddSuccessor(exit_block_);
@@ -250,34 +337,42 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
}
case Instruction::ADD_INT: {
- HInstruction* first = LoadLocal(instruction.VRegB());
- HInstruction* second = LoadLocal(instruction.VRegC());
- current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ Binop_32x<HAdd>(instruction);
+ break;
+ }
+
+ case Instruction::SUB_INT: {
+ Binop_32x<HSub>(instruction);
break;
}
case Instruction::ADD_INT_2ADDR: {
- HInstruction* first = LoadLocal(instruction.VRegA());
- HInstruction* second = LoadLocal(instruction.VRegB());
- current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ Binop_12x<HAdd>(instruction);
+ break;
+ }
+
+ case Instruction::SUB_INT_2ADDR: {
+ Binop_12x<HSub>(instruction);
break;
}
case Instruction::ADD_INT_LIT16: {
- HInstruction* first = LoadLocal(instruction.VRegB());
- HInstruction* second = GetConstant(instruction.VRegC_22s());
- current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ Binop_22s<HAdd>(instruction, false);
+ break;
+ }
+
+ case Instruction::RSUB_INT: {
+ Binop_22s<HSub>(instruction, true);
break;
}
case Instruction::ADD_INT_LIT8: {
- HInstruction* first = LoadLocal(instruction.VRegB());
- HInstruction* second = GetConstant(instruction.VRegC_22b());
- current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ Binop_22b<HAdd>(instruction, false);
+ break;
+ }
+
+ case Instruction::RSUB_INT_LIT8: {
+ Binop_22b<HSub>(instruction, true);
break;
}
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 46ca9aa..df64d71 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -66,11 +66,20 @@ class HGraphBuilder : public ValueObject {
HIntConstant* GetConstant0();
HIntConstant* GetConstant1();
HIntConstant* GetConstant(int constant);
- void InitializeLocals(int count);
+ void InitializeLocals(uint16_t count);
HLocal* GetLocalAt(int register_index) const;
void UpdateLocal(int register_index, HInstruction* instruction) const;
HInstruction* LoadLocal(int register_index) const;
+ // Temporarily returns whether the compiler supports the parameters
+ // of the method.
+ bool InitializeParameters(uint16_t number_of_parameters);
+
+ template<typename T> void Binop_32x(const Instruction& instruction);
+ template<typename T> void Binop_12x(const Instruction& instruction);
+ template<typename T> void Binop_22b(const Instruction& instruction, bool reverse);
+ template<typename T> void Binop_22s(const Instruction& instruction, bool reverse);
+
ArenaAllocator* const arena_;
// A list of the size of the dex code holding block information for
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index d6295db..40a7b6f 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -30,7 +30,6 @@
namespace art {
void CodeGenerator::Compile(CodeAllocator* allocator) {
- frame_size_ = GetGraph()->GetMaximumNumberOfOutVRegs() * GetWordSize();
const GrowableArray<HBasicBlock*>* blocks = GetGraph()->GetBlocks();
DCHECK(blocks->Get(0) == GetGraph()->GetEntryBlock());
DCHECK(GoesToNextBlock(GetGraph()->GetEntryBlock(), blocks->Get(1)));
@@ -47,16 +46,14 @@ void CodeGenerator::Compile(CodeAllocator* allocator) {
void CodeGenerator::CompileEntryBlock() {
HGraphVisitor* location_builder = GetLocationBuilder();
HGraphVisitor* instruction_visitor = GetInstructionVisitor();
- // The entry block contains all locals for this method. By visiting the entry block,
- // we're computing the required frame size.
- for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) {
- HInstruction* current = it.Current();
- // Instructions in the entry block should not generate code.
- if (kIsDebugBuild) {
+ if (kIsDebugBuild) {
+ for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
+ // Instructions in the entry block should not generate code.
current->Accept(location_builder);
DCHECK(current->GetLocations() == nullptr);
+ current->Accept(instruction_visitor);
}
- current->Accept(instruction_visitor);
}
GenerateFrameEntry();
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index cb77f57..2364bc8 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -38,9 +38,11 @@ void CodeGeneratorARM::GenerateFrameEntry() {
core_spill_mask_ |= (1 << LR);
__ PushList((1 << LR));
- // Add the current ART method to the frame size and the return PC.
- SetFrameSize(RoundUp(GetFrameSize() + 2 * kArmWordSize, kStackAlignment));
- // The retrn PC has already been pushed on the stack.
+ // Add the current ART method to the frame size, the return PC, and the filler.
+ SetFrameSize(RoundUp((
+ GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kArmWordSize,
+ kStackAlignment));
+ // The return PC has already been pushed on the stack.
__ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize));
__ str(R0, Address(SP, 0));
}
@@ -55,7 +57,20 @@ void CodeGeneratorARM::Bind(Label* label) {
}
int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
- return (GetGraph()->GetMaximumNumberOfOutVRegs() + local->GetRegNumber()) * kArmWordSize;
+ uint16_t reg_number = local->GetRegNumber();
+ uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
+ uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
+ if (reg_number >= number_of_vregs - number_of_in_vregs) {
+ // Local is a parameter of the method. It is stored in the caller's frame.
+ return GetFrameSize() + kArmWordSize // ART method
+ + (reg_number - number_of_vregs + number_of_in_vregs) * kArmWordSize;
+ } else {
+ // Local is a temporary in this method. It is stored in this method's frame.
+ return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
+ - kArmWordSize // filler.
+ - (number_of_vregs * kArmWordSize)
+ + (reg_number * kArmWordSize);
+ }
}
void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
@@ -187,18 +202,18 @@ void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
-class InvokeStaticCallingConvention : public CallingConvention<Register> {
+class InvokeDexCallingConvention : public CallingConvention<Register> {
public:
- InvokeStaticCallingConvention()
+ InvokeDexCallingConvention()
: CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
private:
- DISALLOW_COPY_AND_ASSIGN(InvokeStaticCallingConvention);
+ DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
};
void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) {
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
- InvokeStaticCallingConvention calling_convention;
+ InvokeDexCallingConvention calling_convention;
if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) {
Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex()));
locations->SetInAt(0, location);
@@ -211,7 +226,7 @@ void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) {
void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) {
uint8_t argument_index = argument->GetArgumentIndex();
- InvokeStaticCallingConvention calling_convention;
+ InvokeDexCallingConvention calling_convention;
size_t parameter_registers = calling_convention.GetNumberOfRegisters();
LocationSummary* locations = argument->GetLocations();
if (argument_index >= parameter_registers) {
@@ -287,6 +302,34 @@ void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
}
}
+void LocationsBuilderARM::VisitSub(HSub* sub) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
+ switch (sub->GetResultType()) {
+ case Primitive::kPrimInt: {
+ locations->SetInAt(0, Location(R0));
+ locations->SetInAt(1, Location(R1));
+ locations->SetOut(Location(R0));
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unimplemented";
+ }
+ sub->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
+ LocationSummary* locations = sub->GetLocations();
+ switch (sub->GetResultType()) {
+ case Primitive::kPrimInt:
+ __ sub(locations->Out().reg<Register>(),
+ locations->InAt(0).reg<Register>(),
+ ShifterOperand(locations->InAt(1).reg<Register>()));
+ break;
+ default:
+ LOG(FATAL) << "Unimplemented";
+ }
+}
+
static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1 };
static constexpr size_t kRuntimeParameterCoreRegistersLength =
arraysize(kRuntimeParameterCoreRegisters);
@@ -319,5 +362,27 @@ void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
codegen_->RecordPcInfo(instruction->GetDexPc());
}
+void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ InvokeDexCallingConvention calling_convention;
+ uint32_t argument_index = instruction->GetIndex();
+ if (argument_index < calling_convention.GetNumberOfRegisters()) {
+ locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index)));
+ } else {
+ locations->SetOut(Location(R0));
+ }
+ instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ InvokeDexCallingConvention calling_convention;
+ uint8_t argument_index = instruction->GetIndex();
+ if (argument_index >= calling_convention.GetNumberOfRegisters()) {
+ uint8_t offset = calling_convention.GetStackOffsetOf(argument_index);
+ __ ldr(locations->Out().reg<Register>(), Address(SP, offset + codegen_->GetFrameSize()));
+ }
+}
+
} // namespace arm
} // namespace art
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index c695e26..540a72a 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -39,11 +39,13 @@ void CodeGeneratorX86::GenerateFrameEntry() {
static const int kFakeReturnRegister = 8;
core_spill_mask_ |= (1 << kFakeReturnRegister);
- // Add the current ART method to the frame size and the return PC.
- SetFrameSize(RoundUp(GetFrameSize() + 2 * kX86WordSize, kStackAlignment));
+ // Add the current ART method to the frame size, the return PC, and the filler.
+ SetFrameSize(RoundUp((
+ GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kX86WordSize,
+ kStackAlignment));
// The return PC has already been pushed on the stack.
__ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
- __ movl(Address(ESP, 0), EAX);
+ __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
}
void CodeGeneratorX86::GenerateFrameExit() {
@@ -59,7 +61,20 @@ void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
}
int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
- return (GetGraph()->GetMaximumNumberOfOutVRegs() + local->GetRegNumber()) * kX86WordSize;
+ uint16_t reg_number = local->GetRegNumber();
+ uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
+ uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
+ if (reg_number >= number_of_vregs - number_of_in_vregs) {
+ // Local is a parameter of the method. It is stored in the caller's frame.
+ return GetFrameSize() + kX86WordSize // ART method
+ + (reg_number - number_of_vregs + number_of_in_vregs) * kX86WordSize;
+ } else {
+ // Local is a temporary in this method. It is stored in this method's frame.
+ return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
+ - kX86WordSize // filler.
+ - (number_of_vregs * kX86WordSize)
+ + (reg_number * kX86WordSize);
+ }
}
void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
@@ -122,7 +137,6 @@ void LocationsBuilderX86::VisitLocal(HLocal* local) {
void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
- codegen_->SetFrameSize(codegen_->GetFrameSize() + kX86WordSize);
}
void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
@@ -190,13 +204,13 @@ void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX };
static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
-class InvokeStaticCallingConvention : public CallingConvention<Register> {
+class InvokeDexCallingConvention : public CallingConvention<Register> {
public:
- InvokeStaticCallingConvention()
+ InvokeDexCallingConvention()
: CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
private:
- DISALLOW_COPY_AND_ASSIGN(InvokeStaticCallingConvention);
+ DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
};
static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
@@ -215,7 +229,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) {
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
- InvokeStaticCallingConvention calling_convention;
+ InvokeDexCallingConvention calling_convention;
if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) {
Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex()));
locations->SetInAt(0, location);
@@ -228,7 +242,7 @@ void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) {
void InstructionCodeGeneratorX86::VisitPushArgument(HPushArgument* argument) {
uint8_t argument_index = argument->GetArgumentIndex();
- InvokeStaticCallingConvention calling_convention;
+ InvokeDexCallingConvention calling_convention;
size_t parameter_registers = calling_convention.GetNumberOfRegisters();
if (argument_index >= parameter_registers) {
uint8_t offset = calling_convention.GetStackOffsetOf(argument_index);
@@ -298,6 +312,33 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
}
}
+void LocationsBuilderX86::VisitSub(HSub* sub) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
+ switch (sub->GetResultType()) {
+ case Primitive::kPrimInt: {
+ locations->SetInAt(0, Location(EAX));
+ locations->SetInAt(1, Location(ECX));
+ locations->SetOut(Location(EAX));
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unimplemented";
+ }
+ sub->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
+ LocationSummary* locations = sub->GetLocations();
+ switch (sub->GetResultType()) {
+ case Primitive::kPrimInt:
+ DCHECK_EQ(locations->InAt(0).reg<Register>(), locations->Out().reg<Register>());
+ __ subl(locations->InAt(0).reg<Register>(), locations->InAt(1).reg<Register>());
+ break;
+ default:
+ LOG(FATAL) << "Unimplemented";
+ }
+}
+
void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
locations->SetOut(Location(EAX));
@@ -316,5 +357,27 @@ void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
codegen_->RecordPcInfo(instruction->GetDexPc());
}
+void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ InvokeDexCallingConvention calling_convention;
+ uint32_t argument_index = instruction->GetIndex();
+ if (argument_index < calling_convention.GetNumberOfRegisters()) {
+ locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index)));
+ } else {
+ locations->SetOut(Location(EAX));
+ }
+ instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ InvokeDexCallingConvention calling_convention;
+ uint32_t argument_index = instruction->GetIndex();
+ if (argument_index >= calling_convention.GetNumberOfRegisters()) {
+ uint8_t offset = calling_convention.GetStackOffsetOf(argument_index);
+ __ movl(locations->Out().reg<Register>(), Address(ESP, offset + codegen_->GetFrameSize()));
+ }
+}
+
} // namespace x86
} // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 830d0c7..d1f672f 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -42,6 +42,8 @@ class HGraph : public ArenaObject {
blocks_(arena, kDefaultNumberOfBlocks),
dominator_order_(arena, kDefaultNumberOfBlocks),
maximum_number_of_out_vregs_(0),
+ number_of_vregs_(0),
+ number_of_in_vregs_(0),
current_instruction_id_(0) { }
ArenaAllocator* GetArena() const { return arena_; }
@@ -68,6 +70,23 @@ class HGraph : public ArenaObject {
maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
}
+ void SetNumberOfVRegs(uint16_t number_of_vregs) {
+ number_of_vregs_ = number_of_vregs;
+ }
+
+ uint16_t GetNumberOfVRegs() const {
+ return number_of_vregs_;
+ }
+
+ void SetNumberOfInVRegs(uint16_t value) {
+ number_of_in_vregs_ = value;
+ }
+
+ uint16_t GetNumberOfInVRegs() const {
+ return number_of_in_vregs_;
+ }
+
+
private:
HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
void VisitBlockForDominatorTree(HBasicBlock* block,
@@ -90,9 +109,15 @@ class HGraph : public ArenaObject {
HBasicBlock* entry_block_;
HBasicBlock* exit_block_;
- // The maximum number of arguments passed to a HInvoke in this graph.
+ // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
uint16_t maximum_number_of_out_vregs_;
+ // The number of virtual registers in this method. Contains the parameters.
+ uint16_t number_of_vregs_;
+
+ // The number of virtual registers used by parameters of this method.
+ uint16_t number_of_in_vregs_;
+
// The current id to assign to a newly added instruction. See HInstruction.id_.
int current_instruction_id_;
@@ -202,10 +227,12 @@ class HBasicBlock : public ArenaObject {
M(LoadLocal) \
M(Local) \
M(NewInstance) \
+ M(ParameterValue) \
M(PushArgument) \
M(Return) \
M(ReturnVoid) \
M(StoreLocal) \
+ M(Sub) \
#define FORWARD_DECLARATION(type) class H##type;
FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
@@ -682,6 +709,37 @@ class HAdd : public HBinaryOperation {
DISALLOW_COPY_AND_ASSIGN(HAdd);
};
+class HSub : public HBinaryOperation {
+ public:
+ HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ virtual bool IsCommutative() { return false; }
+
+ DECLARE_INSTRUCTION(Sub);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HSub);
+};
+
+// The value of a parameter in this method. Its location depends on
+// the calling convention.
+class HParameterValue : public HTemplateInstruction<0> {
+ public:
+ explicit HParameterValue(uint8_t index) : index_(index) {}
+
+ uint8_t GetIndex() const { return index_; }
+
+ DECLARE_INSTRUCTION(ParameterValue);
+
+ private:
+ // The index of this parameter in the parameters list. Must be less
+ // than HGraph::number_of_in_vregs_;
+ const uint8_t index_;
+
+ DISALLOW_COPY_AND_ASSIGN(HParameterValue);
+};
+
class HGraphVisitor : public ValueObject {
public:
explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }