Commit 7a693437 authored by ahaas's avatar ahaas Committed by Commit bot

[turbofan] Add the StackSlot operator to turbofan.

The StackSlot operator allows to allocate a spill slot on the stack. We
are going to use this operator to pass floats through pointers to c
functions, which we need for floating point rounding in the case where
the architecture does not provide rounding instructions.

R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-ppc-ports@googlegroups.com, v8-mips-ports@googlegroups.com

Review URL: https://codereview.chromium.org/1645653002

Cr-Commit-Position: refs/heads/master@{#33600}
parent 3251a03e
...@@ -535,6 +535,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -535,6 +535,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
Register base;
if (offset.from_stack_pointer()) {
base = sp;
} else {
base = fp;
}
__ add(i.OutputRegister(0), base, Operand(offset.offset()));
break;
}
case kArmAdd: case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit()); i.OutputSBit());
......
...@@ -646,6 +646,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -646,6 +646,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Bind(ool->exit()); __ Bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
Register base;
if (offset.from_stack_pointer()) {
base = __ StackPointer();
} else {
base = fp;
}
__ Add(i.OutputRegister(0), base, Operand(offset.offset()));
break;
}
case kArm64Float32RoundDown: case kArm64Float32RoundDown:
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0)); __ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
break; break;
......
...@@ -499,6 +499,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -499,6 +499,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
Register base;
if (offset.from_stack_pointer()) {
base = esp;
} else {
base = ebp;
}
__ lea(i.OutputRegister(), Operand(base, offset.offset()));
break;
}
case kIA32Add: case kIA32Add:
if (HasImmediateInput(instr, 1)) { if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1)); __ add(i.InputOperand(0), i.InputImmediate(1));
......
...@@ -72,7 +72,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny }; ...@@ -72,7 +72,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(CheckedStoreWord32) \ V(CheckedStoreWord32) \
V(CheckedStoreWord64) \ V(CheckedStoreWord64) \
V(CheckedStoreFloat32) \ V(CheckedStoreFloat32) \
V(CheckedStoreFloat64) V(CheckedStoreFloat64) \
V(ArchStackSlot)
#define ARCH_OPCODE_LIST(V) \ #define ARCH_OPCODE_LIST(V) \
COMMON_ARCH_OPCODE_LIST(V) \ COMMON_ARCH_OPCODE_LIST(V) \
......
...@@ -175,6 +175,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const { ...@@ -175,6 +175,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchStackPointer: case kArchStackPointer:
case kArchFramePointer: case kArchFramePointer:
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
case kArchStackSlot:
return kNoOpcodeFlags; return kNoOpcodeFlags;
case kArchPrepareCallCFunction: case kArchPrepareCallCFunction:
......
...@@ -21,7 +21,7 @@ namespace compiler { ...@@ -21,7 +21,7 @@ namespace compiler {
InstructionSelector::InstructionSelector( InstructionSelector::InstructionSelector(
Zone* zone, size_t node_count, Linkage* linkage, Zone* zone, size_t node_count, Linkage* linkage,
InstructionSequence* sequence, Schedule* schedule, InstructionSequence* sequence, Schedule* schedule,
SourcePositionTable* source_positions, SourcePositionTable* source_positions, Frame* frame,
SourcePositionMode source_position_mode, Features features) SourcePositionMode source_position_mode, Features features)
: zone_(zone), : zone_(zone),
linkage_(linkage), linkage_(linkage),
...@@ -36,7 +36,8 @@ InstructionSelector::InstructionSelector( ...@@ -36,7 +36,8 @@ InstructionSelector::InstructionSelector(
used_(node_count, false, zone), used_(node_count, false, zone),
virtual_registers_(node_count, virtual_registers_(node_count,
InstructionOperand::kInvalidVirtualRegister, zone), InstructionOperand::kInvalidVirtualRegister, zone),
scheduler_(nullptr) { scheduler_(nullptr),
frame_(frame) {
instructions_.reserve(node_count); instructions_.reserve(node_count);
} }
...@@ -1066,6 +1067,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1066,6 +1067,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64InsertLowWord32(node); return MarkAsFloat64(node), VisitFloat64InsertLowWord32(node);
case IrOpcode::kFloat64InsertHighWord32: case IrOpcode::kFloat64InsertHighWord32:
return MarkAsFloat64(node), VisitFloat64InsertHighWord32(node); return MarkAsFloat64(node), VisitFloat64InsertHighWord32(node);
case IrOpcode::kStackSlot:
return VisitStackSlot(node);
case IrOpcode::kLoadStackPointer: case IrOpcode::kLoadStackPointer:
return VisitLoadStackPointer(node); return VisitLoadStackPointer(node);
case IrOpcode::kLoadFramePointer: case IrOpcode::kLoadFramePointer:
...@@ -1133,6 +1136,14 @@ void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw, ...@@ -1133,6 +1136,14 @@ void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw,
Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr);
} }
void InstructionSelector::VisitStackSlot(Node* node) {
int size = 1 << ElementSizeLog2Of(StackSlotRepresentationOf(node->op()));
int slot = frame_->AllocateSpillSlot(size);
OperandGenerator g(this);
Emit(kArchStackSlot, g.DefineAsRegister(node),
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
// 32 bit targets do not implement the following instructions. // 32 bit targets do not implement the following instructions.
#if V8_TARGET_ARCH_32_BIT #if V8_TARGET_ARCH_32_BIT
......
...@@ -52,7 +52,7 @@ class InstructionSelector final { ...@@ -52,7 +52,7 @@ class InstructionSelector final {
InstructionSelector( InstructionSelector(
Zone* zone, size_t node_count, Linkage* linkage, Zone* zone, size_t node_count, Linkage* linkage,
InstructionSequence* sequence, Schedule* schedule, InstructionSequence* sequence, Schedule* schedule,
SourcePositionTable* source_positions, SourcePositionTable* source_positions, Frame* frame,
SourcePositionMode source_position_mode = kCallSourcePositions, SourcePositionMode source_position_mode = kCallSourcePositions,
Features features = SupportedFeatures()); Features features = SupportedFeatures());
...@@ -271,6 +271,7 @@ class InstructionSelector final { ...@@ -271,6 +271,7 @@ class InstructionSelector final {
BoolVector used_; BoolVector used_;
IntVector virtual_registers_; IntVector virtual_registers_;
InstructionScheduler* scheduler_; InstructionScheduler* scheduler_;
Frame* frame_;
}; };
} // namespace compiler } // namespace compiler
......
...@@ -91,6 +91,10 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) { ...@@ -91,6 +91,10 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
return OpParameter<CheckedStoreRepresentation>(op); return OpParameter<CheckedStoreRepresentation>(op);
} }
MachineRepresentation StackSlotRepresentationOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kStackSlot, op->opcode());
return OpParameter<MachineRepresentation>(op);
}
#define PURE_OP_LIST(V) \ #define PURE_OP_LIST(V) \
V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
...@@ -281,6 +285,18 @@ struct MachineOperatorGlobalCache { ...@@ -281,6 +285,18 @@ struct MachineOperatorGlobalCache {
MACHINE_TYPE_LIST(LOAD) MACHINE_TYPE_LIST(LOAD)
#undef LOAD #undef LOAD
#define STACKSLOT(Type) \
struct StackSlot##Type##Operator final \
: public Operator1<MachineRepresentation> { \
StackSlot##Type##Operator() \
: Operator1<MachineRepresentation>( \
IrOpcode::kStackSlot, Operator::kNoThrow, "StackSlot", 0, 0, 0, \
1, 0, 0, MachineType::Type().representation()) {} \
}; \
StackSlot##Type##Operator kStackSlot##Type;
MACHINE_TYPE_LIST(STACKSLOT)
#undef STACKSLOT
#define STORE(Type) \ #define STORE(Type) \
struct Store##Type##Operator : public Operator1<StoreRepresentation> { \ struct Store##Type##Operator : public Operator1<StoreRepresentation> { \
explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind) \ explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind) \
...@@ -381,6 +397,16 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) { ...@@ -381,6 +397,16 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
return nullptr; return nullptr;
} }
const Operator* MachineOperatorBuilder::StackSlot(MachineRepresentation rep) {
#define STACKSLOT(Type) \
if (rep == MachineType::Type().representation()) { \
return &cache_.kStackSlot##Type; \
}
MACHINE_TYPE_LIST(STACKSLOT)
#undef STACKSLOT
UNREACHABLE();
return nullptr;
}
const Operator* MachineOperatorBuilder::Store(StoreRepresentation store_rep) { const Operator* MachineOperatorBuilder::Store(StoreRepresentation store_rep) {
switch (store_rep.representation()) { switch (store_rep.representation()) {
......
...@@ -102,6 +102,7 @@ typedef MachineRepresentation CheckedStoreRepresentation; ...@@ -102,6 +102,7 @@ typedef MachineRepresentation CheckedStoreRepresentation;
CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const*); CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const*);
MachineRepresentation StackSlotRepresentationOf(Operator const* op);
// Interface for building machine-level operators. These operators are // Interface for building machine-level operators. These operators are
// machine-level but machine-independent and thus define a language suitable // machine-level but machine-independent and thus define a language suitable
...@@ -305,6 +306,8 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -305,6 +306,8 @@ class MachineOperatorBuilder final : public ZoneObject {
// store [base + index], value // store [base + index], value
const Operator* Store(StoreRepresentation rep); const Operator* Store(StoreRepresentation rep);
const Operator* StackSlot(MachineRepresentation rep);
// Access to the machine stack. // Access to the machine stack.
const Operator* LoadStackPointer(); const Operator* LoadStackPointer();
const Operator* LoadFramePointer(); const Operator* LoadFramePointer();
......
...@@ -625,6 +625,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -625,6 +625,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
__ Addu(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
Operand(offset.offset()));
break;
}
case kMipsAdd: case kMipsAdd:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
......
...@@ -635,6 +635,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -635,6 +635,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
__ Daddu(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
Operand(offset.offset()));
break;
}
case kMips64Add: case kMips64Add:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
......
...@@ -227,6 +227,7 @@ ...@@ -227,6 +227,7 @@
MACHINE_COMPARE_BINOP_LIST(V) \ MACHINE_COMPARE_BINOP_LIST(V) \
V(Load) \ V(Load) \
V(Store) \ V(Store) \
V(StackSlot) \
V(Word32And) \ V(Word32And) \
V(Word32Or) \ V(Word32Or) \
V(Word32Xor) \ V(Word32Xor) \
......
...@@ -276,11 +276,8 @@ class PipelineData { ...@@ -276,11 +276,8 @@ class PipelineData {
info()->isolate(), instruction_zone(), instruction_blocks); info()->isolate(), instruction_zone(), instruction_blocks);
} }
void InitializeRegisterAllocationData(const RegisterConfiguration* config, void InitializeFrameData(CallDescriptor* descriptor) {
CallDescriptor* descriptor,
const char* debug_name) {
DCHECK(frame_ == nullptr); DCHECK(frame_ == nullptr);
DCHECK(register_allocation_data_ == nullptr);
int fixed_frame_size = 0; int fixed_frame_size = 0;
if (descriptor != nullptr) { if (descriptor != nullptr) {
fixed_frame_size = (descriptor->IsCFunctionCall()) fixed_frame_size = (descriptor->IsCFunctionCall())
...@@ -289,6 +286,12 @@ class PipelineData { ...@@ -289,6 +286,12 @@ class PipelineData {
: StandardFrameConstants::kFixedSlotCount; : StandardFrameConstants::kFixedSlotCount;
} }
frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor); frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor);
}
void InitializeRegisterAllocationData(const RegisterConfiguration* config,
CallDescriptor* descriptor,
const char* debug_name) {
DCHECK(register_allocation_data_ == nullptr);
register_allocation_data_ = new (register_allocation_zone()) register_allocation_data_ = new (register_allocation_zone())
RegisterAllocationData(config, register_allocation_zone(), frame(), RegisterAllocationData(config, register_allocation_zone(), frame(),
sequence(), debug_name); sequence(), debug_name);
...@@ -816,7 +819,7 @@ struct InstructionSelectionPhase { ...@@ -816,7 +819,7 @@ struct InstructionSelectionPhase {
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
InstructionSelector selector( InstructionSelector selector(
temp_zone, data->graph()->NodeCount(), linkage, data->sequence(), temp_zone, data->graph()->NodeCount(), linkage, data->sequence(),
data->schedule(), data->source_positions(), data->schedule(), data->source_positions(), data->frame(),
data->info()->is_source_positions_enabled() data->info()->is_source_positions_enabled()
? InstructionSelector::kAllSourcePositions ? InstructionSelector::kAllSourcePositions
: InstructionSelector::kCallSourcePositions); : InstructionSelector::kCallSourcePositions);
...@@ -1282,6 +1285,7 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, ...@@ -1282,6 +1285,7 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
PipelineData data(&zone_pool, &info, sequence); PipelineData data(&zone_pool, &info, sequence);
Pipeline pipeline(&info); Pipeline pipeline(&info);
pipeline.data_ = &data; pipeline.data_ = &data;
pipeline.data_->InitializeFrameData(nullptr);
pipeline.AllocateRegisters(config, nullptr, run_verifier); pipeline.AllocateRegisters(config, nullptr, run_verifier);
return !data.compilation_failed(); return !data.compilation_failed();
} }
...@@ -1304,6 +1308,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( ...@@ -1304,6 +1308,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
data->InitializeInstructionSequence(); data->InitializeInstructionSequence();
data->InitializeFrameData(call_descriptor);
// Select and schedule instructions covering the scheduled graph. // Select and schedule instructions covering the scheduled graph.
Linkage linkage(call_descriptor); Linkage linkage(call_descriptor);
Run<InstructionSelectionPhase>(&linkage); Run<InstructionSelectionPhase>(&linkage);
...@@ -1325,6 +1330,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( ...@@ -1325,6 +1330,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
BeginPhaseKind("register allocation"); BeginPhaseKind("register allocation");
bool run_verifier = FLAG_turbo_verify_allocation; bool run_verifier = FLAG_turbo_verify_allocation;
// Allocate registers. // Allocate registers.
AllocateRegisters( AllocateRegisters(
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
......
...@@ -823,6 +823,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -823,6 +823,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
__ addi(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
Operand(offset.offset()));
break;
}
case kPPC_And: case kPPC_And:
if (HasRegisterInput(instr, 1)) { if (HasRegisterInput(instr, 1)) {
__ and_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1), __ and_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
......
...@@ -79,6 +79,9 @@ class RawMachineAssembler { ...@@ -79,6 +79,9 @@ class RawMachineAssembler {
Node* Int32Constant(int32_t value) { Node* Int32Constant(int32_t value) {
return AddNode(common()->Int32Constant(value)); return AddNode(common()->Int32Constant(value));
} }
Node* StackSlot(MachineRepresentation rep) {
return AddNode(machine()->StackSlot(rep));
}
Node* Int64Constant(int64_t value) { Node* Int64Constant(int64_t value) {
return AddNode(common()->Int64Constant(value)); return AddNode(common()->Int64Constant(value));
} }
......
...@@ -1962,6 +1962,7 @@ Type* Typer::Visitor::TypeObjectIsSmi(Node* node) { ...@@ -1962,6 +1962,7 @@ Type* Typer::Visitor::TypeObjectIsSmi(Node* node) {
Type* Typer::Visitor::TypeLoad(Node* node) { return Type::Any(); } Type* Typer::Visitor::TypeLoad(Node* node) { return Type::Any(); }
Type* Typer::Visitor::TypeStackSlot(Node* node) { return Type::Any(); }
Type* Typer::Visitor::TypeStore(Node* node) { Type* Typer::Visitor::TypeStore(Node* node) {
UNREACHABLE(); UNREACHABLE();
......
...@@ -831,6 +831,7 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -831,6 +831,7 @@ void Verifier::Visitor::Check(Node* node) {
// ----------------------- // -----------------------
case IrOpcode::kLoad: case IrOpcode::kLoad:
case IrOpcode::kStore: case IrOpcode::kStore:
case IrOpcode::kStackSlot:
case IrOpcode::kWord32And: case IrOpcode::kWord32And:
case IrOpcode::kWord32Or: case IrOpcode::kWord32Or:
case IrOpcode::kWord32Xor: case IrOpcode::kWord32Xor:
......
...@@ -740,6 +740,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -740,6 +740,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
Register base;
if (offset.from_stack_pointer()) {
base = rsp;
} else {
base = rbp;
}
__ leaq(i.OutputRegister(), Operand(base, offset.offset()));
break;
}
case kX64Add32: case kX64Add32:
ASSEMBLE_BINOP(addl); ASSEMBLE_BINOP(addl);
break; break;
......
...@@ -587,6 +587,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -587,6 +587,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ bind(ool->exit()); __ bind(ool->exit());
break; break;
} }
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
Register base;
if (offset.from_stack_pointer()) {
base = esp;
} else {
base = ebp;
}
__ lea(i.OutputRegister(), Operand(base, offset.offset()));
break;
}
case kX87Add: case kX87Add:
if (HasImmediateInput(instr, 1)) { if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1)); __ add(i.InputOperand(0), i.InputImmediate(1));
......
...@@ -96,7 +96,6 @@ class BufferedRawMachineAssemblerTester ...@@ -96,7 +96,6 @@ class BufferedRawMachineAssemblerTester
return parameter_nodes_[index]; return parameter_nodes_[index];
} }
// The BufferedRawMachineAssemblerTester adds a Store node to the IR graph // The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
// to store the graph's return value in memory. The memory address for the // to store the graph's return value in memory. The memory address for the
// Store node is provided as a parameter. By storing the return value in // Store node is provided as a parameter. By storing the return value in
...@@ -245,7 +244,6 @@ class BufferedRawMachineAssemblerTester<void> ...@@ -245,7 +244,6 @@ class BufferedRawMachineAssemblerTester<void>
: Load(p3, RawMachineAssembler::Parameter(3)); : Load(p3, RawMachineAssembler::Parameter(3));
} }
// The BufferedRawMachineAssemblerTester does not pass parameters directly // The BufferedRawMachineAssemblerTester does not pass parameters directly
// to the constructed IR graph. Instead it passes a pointer to the parameter // to the constructed IR graph. Instead it passes a pointer to the parameter
// to the IR graph, and adds Load nodes to the IR graph to load the // to the IR graph, and adds Load nodes to the IR graph to load the
......
...@@ -72,7 +72,6 @@ TEST(RunWord32Ctz) { ...@@ -72,7 +72,6 @@ TEST(RunWord32Ctz) {
CHECK_EQ(0, m.Call(uint32_t(0x9afdbc81))); CHECK_EQ(0, m.Call(uint32_t(0x9afdbc81)));
} }
TEST(RunWord32Clz) { TEST(RunWord32Clz) {
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32()); BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
m.Return(m.Word32Clz(m.Parameter(0))); m.Return(m.Word32Clz(m.Parameter(0)));
......
...@@ -1157,6 +1157,86 @@ TEST(MixedParams_1) { MixedParamTest(1); } ...@@ -1157,6 +1157,86 @@ TEST(MixedParams_1) { MixedParamTest(1); }
TEST(MixedParams_2) { MixedParamTest(2); } TEST(MixedParams_2) { MixedParamTest(2); }
TEST(MixedParams_3) { MixedParamTest(3); } TEST(MixedParams_3) { MixedParamTest(3); }
template <typename T>
void TestStackSlot(MachineType slot_type, T expected) {
// Test: Generate with a function f which reserves a stack slot, call an inner
// function g from f which writes into the stack slot of f.
if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->num_double_registers() < 2)
return;
Isolate* isolate = CcTest::InitIsolateOnce();
// Lots of code to generate the build descriptor for the inner function.
int parray_gp[] = {
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableGeneralCode(0),
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableGeneralCode(1)};
int rarray_gp[] = {
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableGeneralCode(0)};
int parray_fp[] = {
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableDoubleCode(0),
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableDoubleCode(1)};
int rarray_fp[] = {
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
->GetAllocatableDoubleCode(0)};
Allocator palloc(parray_gp, 2, parray_fp, 2);
Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
RegisterConfig config(palloc, ralloc);
Zone zone;
HandleScope scope(isolate);
MachineSignature::Builder builder(&zone, 1, 12);
builder.AddReturn(MachineType::Int32());
for (int i = 0; i < 10; i++) {
builder.AddParam(MachineType::Int32());
}
builder.AddParam(slot_type);
builder.AddParam(MachineType::Pointer());
MachineSignature* sig = builder.Build();
CallDescriptor* desc = config.Create(&zone, sig);
// Create inner function g. g has lots of parameters so that they are passed
// over the stack.
Handle<Code> inner;
Graph graph(&zone);
RawMachineAssembler g(isolate, &graph, desc);
g.Store(slot_type.representation(), g.Parameter(11), g.Parameter(10),
WriteBarrierKind::kNoWriteBarrier);
g.Return(g.Parameter(9));
inner = CompileGraph("Compute", desc, &graph, g.Export());
// Create function f with a stack slot which calls the inner function g.
BufferedRawMachineAssemblerTester<T> f(slot_type);
Node* target = f.HeapConstant(inner);
Node* stack_slot = f.StackSlot(slot_type.representation());
Node* args[12];
for (int i = 0; i < 10; i++) {
args[i] = f.Int32Constant(i);
}
args[10] = f.Parameter(0);
args[11] = stack_slot;
f.CallN(desc, target, args);
f.Return(f.Load(slot_type, stack_slot, f.IntPtrConstant(0)));
CHECK_EQ(expected, f.Call(expected));
}
TEST(RunStackSlotInt32) { TestStackSlot(MachineType::Int32(), 0x12345678); }
#if !V8_TARGET_ARCH_32_BIT
TEST(RunStackSlotInt64) {
TestStackSlot(MachineType::Int64(), 0x123456789abcdef0);
}
#endif
TEST(RunStackSlotFloat32) { TestStackSlot(MachineType::Float32(), 1234.125f); }
TEST(RunStackSlotFloat64) { TestStackSlot(MachineType::Float64(), 3456.375); }
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -40,7 +40,7 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build( ...@@ -40,7 +40,7 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
instruction_blocks); instruction_blocks);
SourcePositionTable source_position_table(graph()); SourcePositionTable source_position_table(graph());
InstructionSelector selector(test_->zone(), node_count, &linkage, &sequence, InstructionSelector selector(test_->zone(), node_count, &linkage, &sequence,
schedule, &source_position_table, schedule, &source_position_table, nullptr,
source_position_mode, features); source_position_mode, features);
selector.SelectInstructions(); selector.SelectInstructions();
if (FLAG_trace_turbo) { if (FLAG_trace_turbo) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment