[turbofan] add new x64 addressing modes
R=bmeurer@chromium.org, titzer@chromium.org BUG= Review URL: https://codereview.chromium.org/605693002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24267 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ad24cdae72
commit
d3a021bbe0
@ -107,10 +107,10 @@ typedef int32_t InstructionCode;
|
||||
// continuation into a single InstructionCode which is stored as part of
|
||||
// the instruction.
|
||||
typedef BitField<ArchOpcode, 0, 7> ArchOpcodeField;
|
||||
typedef BitField<AddressingMode, 7, 4> AddressingModeField;
|
||||
typedef BitField<FlagsMode, 11, 2> FlagsModeField;
|
||||
typedef BitField<FlagsCondition, 13, 5> FlagsConditionField;
|
||||
typedef BitField<int, 13, 19> MiscField;
|
||||
typedef BitField<AddressingMode, 7, 5> AddressingModeField;
|
||||
typedef BitField<FlagsMode, 12, 2> FlagsModeField;
|
||||
typedef BitField<FlagsCondition, 14, 5> FlagsConditionField;
|
||||
typedef BitField<int, 14, 18> MiscField;
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
@ -145,22 +145,79 @@ class X64OperandConverter : public InstructionOperandConverter {
|
||||
return result;
|
||||
}
|
||||
|
||||
Operand MemoryOperand(int* first_input) {
|
||||
const int offset = *first_input;
|
||||
switch (AddressingModeField::decode(instr_->opcode())) {
|
||||
case kMode_MR1I: {
|
||||
*first_input += 2;
|
||||
Register index = InputRegister(offset + 1);
|
||||
return Operand(InputRegister(offset + 0), index, times_1,
|
||||
0); // TODO(dcarney): K != 0
|
||||
static int NextOffset(int* offset) {
|
||||
int i = *offset;
|
||||
(*offset)++;
|
||||
return i;
|
||||
}
|
||||
|
||||
static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
|
||||
STATIC_ASSERT(0 == static_cast<int>(times_1));
|
||||
STATIC_ASSERT(1 == static_cast<int>(times_2));
|
||||
STATIC_ASSERT(2 == static_cast<int>(times_4));
|
||||
STATIC_ASSERT(3 == static_cast<int>(times_8));
|
||||
int scale = static_cast<int>(mode - one);
|
||||
DCHECK(scale >= 0 && scale < 4);
|
||||
return static_cast<ScaleFactor>(scale);
|
||||
}
|
||||
|
||||
Operand MemoryOperand(int* offset) {
|
||||
AddressingMode mode = AddressingModeField::decode(instr_->opcode());
|
||||
switch (mode) {
|
||||
case kMode_MR: {
|
||||
Register base = InputRegister(NextOffset(offset));
|
||||
int32_t disp = 0;
|
||||
return Operand(base, disp);
|
||||
}
|
||||
case kMode_MRI:
|
||||
*first_input += 2;
|
||||
return Operand(InputRegister(offset + 0), InputInt32(offset + 1));
|
||||
default:
|
||||
case kMode_MRI: {
|
||||
Register base = InputRegister(NextOffset(offset));
|
||||
int32_t disp = InputInt32(NextOffset(offset));
|
||||
return Operand(base, disp);
|
||||
}
|
||||
case kMode_MR1:
|
||||
case kMode_MR2:
|
||||
case kMode_MR4:
|
||||
case kMode_MR8: {
|
||||
Register base = InputRegister(NextOffset(offset));
|
||||
Register index = InputRegister(NextOffset(offset));
|
||||
ScaleFactor scale = ScaleFor(kMode_MR1, mode);
|
||||
int32_t disp = 0;
|
||||
return Operand(base, index, scale, disp);
|
||||
}
|
||||
case kMode_MR1I:
|
||||
case kMode_MR2I:
|
||||
case kMode_MR4I:
|
||||
case kMode_MR8I: {
|
||||
Register base = InputRegister(NextOffset(offset));
|
||||
Register index = InputRegister(NextOffset(offset));
|
||||
ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
|
||||
int32_t disp = InputInt32(NextOffset(offset));
|
||||
return Operand(base, index, scale, disp);
|
||||
}
|
||||
case kMode_M1:
|
||||
case kMode_M2:
|
||||
case kMode_M4:
|
||||
case kMode_M8: {
|
||||
Register index = InputRegister(NextOffset(offset));
|
||||
ScaleFactor scale = ScaleFor(kMode_M1, mode);
|
||||
int32_t disp = 0;
|
||||
return Operand(index, scale, disp);
|
||||
}
|
||||
case kMode_M1I:
|
||||
case kMode_M2I:
|
||||
case kMode_M4I:
|
||||
case kMode_M8I: {
|
||||
Register index = InputRegister(NextOffset(offset));
|
||||
ScaleFactor scale = ScaleFor(kMode_M1I, mode);
|
||||
int32_t disp = InputInt32(NextOffset(offset));
|
||||
return Operand(index, scale, disp);
|
||||
}
|
||||
case kMode_None:
|
||||
UNREACHABLE();
|
||||
return Operand(no_reg, 0);
|
||||
}
|
||||
UNREACHABLE();
|
||||
return Operand(no_reg, 0);
|
||||
}
|
||||
|
||||
Operand MemoryOperand() {
|
||||
|
@ -79,22 +79,30 @@ namespace compiler {
|
||||
//
|
||||
// We use the following local notation for addressing modes:
|
||||
//
|
||||
// R = register
|
||||
// O = register or stack slot
|
||||
// D = double register
|
||||
// I = immediate (handle, external, int32)
|
||||
// MR = [register]
|
||||
// MI = [immediate]
|
||||
// MRN = [register + register * N in {1, 2, 4, 8}]
|
||||
// MRI = [register + immediate]
|
||||
// MRNI = [register + register * N in {1, 2, 4, 8} + immediate]
|
||||
// M = memory operand
|
||||
// R = base register
|
||||
// N = index register * N for N in {1, 2, 4, 8}
|
||||
// I = immediate displacement (int32_t)
|
||||
|
||||
#define TARGET_ADDRESSING_MODE_LIST(V) \
|
||||
V(MR) /* [%r1] */ \
|
||||
V(MRI) /* [%r1 + K] */ \
|
||||
V(MR1I) /* [%r1 + %r2 + K] */ \
|
||||
V(MR) /* [%r1 ] */ \
|
||||
V(MRI) /* [%r1 + K] */ \
|
||||
V(MR1) /* [%r1 + %r2*1 ] */ \
|
||||
V(MR2) /* [%r1 + %r2*2 ] */ \
|
||||
V(MR4) /* [%r1 + %r2*4 ] */ \
|
||||
V(MR8) /* [%r1 + %r2*8 ] */ \
|
||||
V(MR1I) /* [%r1 + %r2*1 + K] */ \
|
||||
V(MR2I) /* [%r1 + %r2*2 + K] */ \
|
||||
V(MR4I) /* [%r1 + %r2*4 + K] */ \
|
||||
V(MR8I) /* [%r1 + %r2*8 + K] */
|
||||
V(MR4I) /* [%r1 + %r2*3 + K] */ \
|
||||
V(MR8I) /* [%r1 + %r2*4 + K] */ \
|
||||
V(M1) /* [ %r2*1 ] */ \
|
||||
V(M2) /* [ %r2*2 ] */ \
|
||||
V(M4) /* [ %r2*4 ] */ \
|
||||
V(M8) /* [ %r2*8 ] */ \
|
||||
V(M1I) /* [ %r2*1 + K] */ \
|
||||
V(M2I) /* [ %r2*2 + K] */ \
|
||||
V(M4I) /* [ %r2*4 + K] */ \
|
||||
V(M8I) /* [ %r2*8 + K] */
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
@ -161,6 +161,134 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
|
||||
InstructionSelectorMemoryAccessTest,
|
||||
::testing::ValuesIn(kMemoryAccesses));
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AddressingMode for loads and stores.
|
||||
|
||||
class AddressingModeUnitTest : public InstructionSelectorTest {
|
||||
public:
|
||||
AddressingModeUnitTest() : m(NULL) { Reset(); }
|
||||
~AddressingModeUnitTest() { delete m; }
|
||||
|
||||
void Run(Node* base, Node* index, AddressingMode mode) {
|
||||
Node* load = m->Load(kMachInt32, base, index);
|
||||
m->Store(kMachInt32, base, index, load);
|
||||
m->Return(m->Int32Constant(0));
|
||||
Stream s = m->Build();
|
||||
ASSERT_EQ(2U, s.size());
|
||||
EXPECT_EQ(mode, s[0]->addressing_mode());
|
||||
EXPECT_EQ(mode, s[1]->addressing_mode());
|
||||
}
|
||||
|
||||
Node* zero;
|
||||
Node* null_ptr;
|
||||
Node* non_zero;
|
||||
Node* base_reg; // opaque value to generate base as register
|
||||
Node* index_reg; // opaque value to generate index as register
|
||||
Node* scales[4];
|
||||
StreamBuilder* m;
|
||||
|
||||
void Reset() {
|
||||
delete m;
|
||||
m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32);
|
||||
zero = m->Int32Constant(0);
|
||||
null_ptr = m->Int64Constant(0);
|
||||
non_zero = m->Int32Constant(127);
|
||||
base_reg = m->Parameter(0);
|
||||
index_reg = m->Parameter(0);
|
||||
|
||||
scales[0] = m->Int32Constant(1);
|
||||
scales[1] = m->Int32Constant(2);
|
||||
scales[2] = m->Int32Constant(4);
|
||||
scales[3] = m->Int32Constant(8);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MR) {
|
||||
Node* base = base_reg;
|
||||
Node* index = zero;
|
||||
Run(base, index, kMode_MR);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MRI) {
|
||||
Node* base = base_reg;
|
||||
Node* index = non_zero;
|
||||
Run(base, index, kMode_MRI);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MR1) {
|
||||
Node* base = base_reg;
|
||||
Node* index = index_reg;
|
||||
Run(base, index, kMode_MR1);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MRN) {
|
||||
AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8};
|
||||
for (size_t i = 0; i < arraysize(scales); ++i) {
|
||||
Reset();
|
||||
Node* base = base_reg;
|
||||
Node* index = m->Int32Mul(index_reg, scales[i]);
|
||||
Run(base, index, expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) {
|
||||
Node* base = base_reg;
|
||||
Node* index = m->Int32Add(index_reg, non_zero);
|
||||
Run(base, index, kMode_MR1I);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) {
|
||||
AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I};
|
||||
for (size_t i = 0; i < arraysize(scales); ++i) {
|
||||
Reset();
|
||||
Node* base = base_reg;
|
||||
Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
|
||||
Run(base, index, expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_M1) {
|
||||
Node* base = null_ptr;
|
||||
Node* index = index_reg;
|
||||
Run(base, index, kMode_M1);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
|
||||
AddressingMode expected[] = {kMode_M1, kMode_M2, kMode_M4, kMode_M8};
|
||||
for (size_t i = 0; i < arraysize(scales); ++i) {
|
||||
Reset();
|
||||
Node* base = null_ptr;
|
||||
Node* index = m->Int32Mul(index_reg, scales[i]);
|
||||
Run(base, index, expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_M1I) {
|
||||
Node* base = null_ptr;
|
||||
Node* index = m->Int32Add(index_reg, non_zero);
|
||||
Run(base, index, kMode_M1I);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
|
||||
AddressingMode expected[] = {kMode_M1I, kMode_M2I, kMode_M4I, kMode_M8I};
|
||||
for (size_t i = 0; i < arraysize(scales); ++i) {
|
||||
Reset();
|
||||
Node* base = null_ptr;
|
||||
Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
|
||||
Run(base, index, expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -20,11 +20,6 @@ class X64OperandGenerator FINAL : public OperandGenerator {
|
||||
Register::ToAllocationIndex(reg));
|
||||
}
|
||||
|
||||
InstructionOperand* UseByteRegister(Node* node) {
|
||||
// TODO(dcarney): relax constraint.
|
||||
return UseFixed(node, rdx);
|
||||
}
|
||||
|
||||
InstructionOperand* UseImmediate64(Node* node) { return UseImmediate(node); }
|
||||
|
||||
bool CanBeImmediate(Node* node) {
|
||||
@ -59,10 +54,173 @@ class X64OperandGenerator FINAL : public OperandGenerator {
|
||||
};
|
||||
|
||||
|
||||
// Matches nodes of form [x * N] for N in {1,2,4,8}
|
||||
class ScaleFactorMatcher : public NodeMatcher {
|
||||
public:
|
||||
explicit ScaleFactorMatcher(Node* node)
|
||||
: NodeMatcher(node), left_(NULL), power_(0) {
|
||||
Match();
|
||||
}
|
||||
|
||||
bool Matches() { return left_ != NULL; }
|
||||
int Power() {
|
||||
DCHECK(Matches());
|
||||
return power_;
|
||||
}
|
||||
Node* Left() {
|
||||
DCHECK(Matches());
|
||||
return left_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Match() {
|
||||
if (opcode() != IrOpcode::kInt32Mul) return;
|
||||
Int32BinopMatcher m(node());
|
||||
if (!m.right().HasValue()) return;
|
||||
int32_t value = m.right().Value();
|
||||
switch (value) {
|
||||
case 8:
|
||||
power_++; // Fall through.
|
||||
case 4:
|
||||
power_++; // Fall through.
|
||||
case 2:
|
||||
power_++; // Fall through.
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
left_ = m.left().node();
|
||||
}
|
||||
|
||||
Node* left_;
|
||||
int power_;
|
||||
};
|
||||
|
||||
|
||||
// Matches nodes of form:
|
||||
// [x * N]
|
||||
// [x * N + K]
|
||||
// [x + K]
|
||||
// [x] -- fallback case
|
||||
// for N in {1,2,4,8} and K int32_t
|
||||
class IndexAndDisplacementMatcher : public NodeMatcher {
|
||||
public:
|
||||
explicit IndexAndDisplacementMatcher(Node* node)
|
||||
: NodeMatcher(node), index_node_(node), displacement_(0), power_(0) {
|
||||
Match();
|
||||
}
|
||||
|
||||
Node* index_node() { return index_node_; }
|
||||
int displacement() { return displacement_; }
|
||||
int power() { return power_; }
|
||||
|
||||
private:
|
||||
void Match() {
|
||||
if (opcode() == IrOpcode::kInt32Add) {
|
||||
// Assume reduction has put constant on the right.
|
||||
Int32BinopMatcher m(node());
|
||||
if (m.right().HasValue()) {
|
||||
displacement_ = m.right().Value();
|
||||
index_node_ = m.left().node();
|
||||
}
|
||||
}
|
||||
// Test scale factor.
|
||||
ScaleFactorMatcher scale_matcher(index_node_);
|
||||
if (scale_matcher.Matches()) {
|
||||
index_node_ = scale_matcher.Left();
|
||||
power_ = scale_matcher.Power();
|
||||
}
|
||||
}
|
||||
|
||||
Node* index_node_;
|
||||
int displacement_;
|
||||
int power_;
|
||||
};
|
||||
|
||||
|
||||
class AddressingModeMatcher {
|
||||
public:
|
||||
AddressingModeMatcher(X64OperandGenerator* g, Node* base, Node* index)
|
||||
: base_operand_(NULL),
|
||||
index_operand_(NULL),
|
||||
displacement_operand_(NULL),
|
||||
mode_(kMode_None) {
|
||||
Int32Matcher index_imm(index);
|
||||
if (index_imm.HasValue()) {
|
||||
int32_t value = index_imm.Value();
|
||||
if (value == 0) {
|
||||
mode_ = kMode_MR;
|
||||
} else {
|
||||
mode_ = kMode_MRI;
|
||||
index_operand_ = g->UseImmediate(index);
|
||||
}
|
||||
base_operand_ = g->UseRegister(base);
|
||||
} else {
|
||||
// Compute base operand.
|
||||
Int64Matcher base_imm(base);
|
||||
if (!base_imm.HasValue() || base_imm.Value() != 0) {
|
||||
base_operand_ = g->UseRegister(base);
|
||||
}
|
||||
// Compute index and displacement.
|
||||
IndexAndDisplacementMatcher matcher(index);
|
||||
index_operand_ = g->UseRegister(matcher.index_node());
|
||||
if (matcher.displacement() != 0) {
|
||||
displacement_operand_ = g->TempImmediate(matcher.displacement());
|
||||
}
|
||||
// Compute mode with scale factor one.
|
||||
if (base_operand_ == NULL) {
|
||||
if (displacement_operand_ == NULL) {
|
||||
mode_ = kMode_M1;
|
||||
} else {
|
||||
mode_ = kMode_M1I;
|
||||
}
|
||||
} else {
|
||||
if (displacement_operand_ == NULL) {
|
||||
mode_ = kMode_MR1;
|
||||
} else {
|
||||
mode_ = kMode_MR1I;
|
||||
}
|
||||
}
|
||||
// Adjust mode to actual scale factor.
|
||||
mode_ = GetMode(mode_, matcher.power());
|
||||
}
|
||||
DCHECK_NE(kMode_None, mode_);
|
||||
}
|
||||
|
||||
AddressingMode GetMode(AddressingMode one, int power) {
|
||||
return static_cast<AddressingMode>(static_cast<int>(one) + power);
|
||||
}
|
||||
|
||||
size_t SetInputs(InstructionOperand** inputs) {
|
||||
size_t input_count = 0;
|
||||
// Compute inputs_ and input_count.
|
||||
if (base_operand_ != NULL) {
|
||||
inputs[input_count++] = base_operand_;
|
||||
}
|
||||
if (index_operand_ != NULL) {
|
||||
inputs[input_count++] = index_operand_;
|
||||
}
|
||||
if (displacement_operand_ != NULL) {
|
||||
// Pure displacement mode not supported by x64.
|
||||
DCHECK_NE(input_count, 0);
|
||||
inputs[input_count++] = displacement_operand_;
|
||||
}
|
||||
DCHECK_NE(input_count, 0);
|
||||
return input_count;
|
||||
}
|
||||
|
||||
static const int kMaxInputCount = 3;
|
||||
InstructionOperand* base_operand_;
|
||||
InstructionOperand* index_operand_;
|
||||
InstructionOperand* displacement_operand_;
|
||||
AddressingMode mode_;
|
||||
};
|
||||
|
||||
|
||||
void InstructionSelector::VisitLoad(Node* node) {
|
||||
MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
|
||||
MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
|
||||
X64OperandGenerator g(this);
|
||||
Node* base = node->InputAt(0);
|
||||
Node* index = node->InputAt(1);
|
||||
|
||||
@ -93,18 +251,14 @@ void InstructionSelector::VisitLoad(Node* node) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
if (g.CanBeImmediate(base)) {
|
||||
// load [#base + %index]
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MRI),
|
||||
g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base));
|
||||
} else if (g.CanBeImmediate(index)) { // load [%base + #index]
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MRI),
|
||||
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
|
||||
} else { // load [%base + %index + K]
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MR1I),
|
||||
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
|
||||
}
|
||||
// TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
|
||||
|
||||
X64OperandGenerator g(this);
|
||||
AddressingModeMatcher matcher(&g, base, index);
|
||||
InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
|
||||
InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
|
||||
InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
|
||||
int input_count = matcher.SetInputs(inputs);
|
||||
Emit(code, 1, outputs, input_count, inputs);
|
||||
}
|
||||
|
||||
|
||||
@ -128,14 +282,6 @@ void InstructionSelector::VisitStore(Node* node) {
|
||||
return;
|
||||
}
|
||||
DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
|
||||
InstructionOperand* val;
|
||||
if (g.CanBeImmediate(value)) {
|
||||
val = g.UseImmediate(value);
|
||||
} else if (rep == kRepWord8 || rep == kRepBit) {
|
||||
val = g.UseByteRegister(value);
|
||||
} else {
|
||||
val = g.UseRegister(value);
|
||||
}
|
||||
ArchOpcode opcode;
|
||||
switch (rep) {
|
||||
case kRepFloat32:
|
||||
@ -162,18 +308,20 @@ void InstructionSelector::VisitStore(Node* node) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
if (g.CanBeImmediate(base)) {
|
||||
// store [#base + %index], %|#value
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
|
||||
g.UseRegister(index), g.UseImmediate(base), val);
|
||||
} else if (g.CanBeImmediate(index)) { // store [%base + #index], %|#value
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
|
||||
g.UseRegister(base), g.UseImmediate(index), val);
|
||||
} else { // store [%base + %index], %|#value
|
||||
Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
|
||||
g.UseRegister(base), g.UseRegister(index), val);
|
||||
|
||||
InstructionOperand* val;
|
||||
if (g.CanBeImmediate(value)) {
|
||||
val = g.UseImmediate(value);
|
||||
} else {
|
||||
val = g.UseRegister(value);
|
||||
}
|
||||
// TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
|
||||
|
||||
AddressingModeMatcher matcher(&g, base, index);
|
||||
InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
|
||||
InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
|
||||
int input_count = matcher.SetInputs(inputs);
|
||||
inputs[input_count++] = val;
|
||||
Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
|
||||
}
|
||||
|
||||
|
||||
@ -702,8 +850,6 @@ void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
|
||||
// Compute InstructionOperands for inputs and outputs.
|
||||
InitializeCallBuffer(call, &buffer, true, true);
|
||||
|
||||
// TODO(dcarney): stack alignment for c calls.
|
||||
// TODO(dcarney): shadow space on window for c calls.
|
||||
// Push any stack arguments.
|
||||
for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
|
||||
input != buffer.pushed_nodes.rend(); input++) {
|
||||
|
Loading…
Reference in New Issue
Block a user