AddressingMode kImmMode, AddressingMode kRegMode>
bool TryMatchShift(InstructionSelector* selector,
InstructionCode* opcode_return, Node* node,
- InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
ArmOperandGenerator g(selector);
if (node->opcode() == kOpcode) {
Int32BinopMatcher m(node);
bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
- Node* node, InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ Node* node, InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I,
kMode_Operand2_R_ROR_R>(selector, opcode_return, node,
value_return, shift_return);
bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return,
- Node* node, InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ Node* node, InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I,
kMode_Operand2_R_ASR_R>(selector, opcode_return, node,
value_return, shift_return);
bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return,
- Node* node, InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ Node* node, InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I,
kMode_Operand2_R_LSL_R>(selector, opcode_return, node,
value_return, shift_return);
bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
- Node* node, InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ Node* node, InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I,
kMode_Operand2_R_LSR_R>(selector, opcode_return, node,
value_return, shift_return);
bool TryMatchShift(InstructionSelector* selector,
InstructionCode* opcode_return, Node* node,
- InstructionOperand** value_return,
- InstructionOperand** shift_return) {
+ InstructionOperand* value_return,
+ InstructionOperand* shift_return) {
return (
TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
bool TryMatchImmediateOrShift(InstructionSelector* selector,
InstructionCode* opcode_return, Node* node,
size_t* input_count_return,
- InstructionOperand** inputs) {
+ InstructionOperand* inputs) {
ArmOperandGenerator g(selector);
if (g.CanBeImmediate(node, *opcode_return)) {
*opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
- InstructionOperand* inputs[5];
+ InstructionOperand inputs[5];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
if (m.left().node() == m.right().node()) {
// mov r0, r1, asr #16
// adds r0, r0, r1, asr #16
// bvs label
- InstructionOperand* const input = g.UseRegister(m.left().node());
+ InstructionOperand const input = g.UseRegister(m.left().node());
opcode |= AddressingModeField::encode(kMode_Operand2_R);
inputs[input_count++] = input;
inputs[input_count++] = input;
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(r5), g.TempRegister(r6)};
- Emit(kArmStoreWriteBarrier, NULL, g.UseFixed(base, r4),
- g.UseFixed(index, r5), g.UseFixed(value, r6), arraysize(temps),
- temps);
+ InstructionOperand temps[] = {g.TempRegister(r5), g.TempRegister(r6)};
+ Emit(kArmStoreWriteBarrier, g.NoOutput(), g.UseFixed(base, r4),
+ g.UseFixed(index, r5), g.UseFixed(value, r6), arraysize(temps), temps);
return;
}
DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
}
if (g.CanBeImmediate(index, opcode)) {
- Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), g.NoOutput(),
g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
} else {
- Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
}
}
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.UseRegister(offset);
- InstructionOperand* length_operand = g.CanBeImmediate(length, kArmCmp)
- ? g.UseImmediate(length)
- : g.UseRegister(length);
+ InstructionOperand offset_operand = g.UseRegister(offset);
+ InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length);
Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
g.DefineAsRegister(node), offset_operand, length_operand,
g.UseRegister(buffer), offset_operand);
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.UseRegister(offset);
- InstructionOperand* length_operand = g.CanBeImmediate(length, kArmCmp)
- ? g.UseImmediate(length)
- : g.UseRegister(length);
- Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), nullptr,
+ InstructionOperand offset_operand = g.UseRegister(offset);
+ InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length);
+ Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
offset_operand, length_operand, g.UseRegister(value),
g.UseRegister(buffer), offset_operand);
}
Node* right) {
ArmOperandGenerator g(selector);
InstructionCode opcode = kArmBic;
- InstructionOperand* value_operand;
- InstructionOperand* shift_operand;
+ InstructionOperand value_operand;
+ InstructionOperand shift_operand;
if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
value_operand, shift_operand);
Int32BinopMatcher m(node);
if (m.right().Is(-1)) {
InstructionCode opcode = kArmMvn;
- InstructionOperand* value_operand;
- InstructionOperand* shift_operand;
+ InstructionOperand value_operand;
+ InstructionOperand shift_operand;
if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
&shift_operand)) {
Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
TryMatchShift try_match_shift, FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
InstructionCode opcode = kArmMov;
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 2;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
void InstructionSelector::VisitUint32MulHigh(Node* node) {
ArmOperandGenerator g(this);
- InstructionOperand* outputs[] = {g.TempRegister(), g.DefineAsRegister(node)};
- InstructionOperand* inputs[] = {g.UseRegister(node->InputAt(0)),
- g.UseRegister(node->InputAt(1))};
+ InstructionOperand outputs[] = {g.TempRegister(), g.DefineAsRegister(node)};
+ InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
+ g.UseRegister(node->InputAt(1))};
Emit(kArmUmull, arraysize(outputs), outputs, arraysize(inputs), inputs);
}
static void EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode,
ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode,
- InstructionOperand* result_operand,
- InstructionOperand* left_operand,
- InstructionOperand* right_operand) {
+ InstructionOperand result_operand,
+ InstructionOperand left_operand,
+ InstructionOperand right_operand) {
ArmOperandGenerator g(selector);
if (selector->IsSupported(SUDIV)) {
selector->Emit(div_opcode, result_operand, left_operand, right_operand);
return;
}
- InstructionOperand* left_double_operand = g.TempDoubleRegister();
- InstructionOperand* right_double_operand = g.TempDoubleRegister();
- InstructionOperand* result_double_operand = g.TempDoubleRegister();
+ InstructionOperand left_double_operand = g.TempDoubleRegister();
+ InstructionOperand right_double_operand = g.TempDoubleRegister();
+ InstructionOperand result_double_operand = g.TempDoubleRegister();
selector->Emit(f64i32_opcode, left_double_operand, left_operand);
selector->Emit(f64i32_opcode, right_double_operand, right_operand);
selector->Emit(kArmVdivF64, result_double_operand, left_double_operand,
ArchOpcode i32f64_opcode) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
- InstructionOperand* div_operand = g.TempRegister();
- InstructionOperand* result_operand = g.DefineAsRegister(node);
- InstructionOperand* left_operand = g.UseRegister(m.left().node());
- InstructionOperand* right_operand = g.UseRegister(m.right().node());
+ InstructionOperand div_operand = g.TempRegister();
+ InstructionOperand result_operand = g.DefineAsRegister(node);
+ InstructionOperand left_operand = g.UseRegister(m.left().node());
+ InstructionOperand right_operand = g.UseRegister(m.right().node());
EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
left_operand, right_operand);
if (selector->IsSupported(MLS)) {
left_operand);
return;
}
- InstructionOperand* mul_operand = g.TempRegister();
+ InstructionOperand mul_operand = g.TempRegister();
selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
selector->Emit(kArmSub, result_operand, left_operand, mul_operand);
}
// Push any stack arguments.
for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
++i) {
- Emit(kArmPush, nullptr, g.UseRegister(*i));
+ Emit(kArmPush, g.NoOutput(), g.UseRegister(*i));
}
// Select the appropriate opcode based on the call type.
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
- InstructionOperand** first_output =
+ InstructionOperand* first_output =
buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
Emit(opcode, buffer.outputs.size(), first_output,
FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
Float64BinopMatcher m(node);
- InstructionOperand* rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node())
- : g.UseRegister(m.right().node());
+ InstructionOperand rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node())
+ : g.UseRegister(m.right().node());
if (cont->IsBranch()) {
- selector->Emit(cont->Encode(kArmVcmpF64), nullptr,
+ selector->Emit(cont->Encode(kArmVcmpF64), g.NoOutput(),
g.UseRegister(m.left().node()), rhs,
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
InstructionCode opcode, FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
- InstructionOperand* inputs[5];
+ InstructionOperand inputs[5];
size_t input_count = 0;
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
size_t output_count = 0;
if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
ArmOperandGenerator g(selector);
InstructionCode const opcode =
cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
- InstructionOperand* const value_operand = g.UseRegister(value);
+ InstructionOperand const value_operand = g.UseRegister(value);
if (cont->IsBranch()) {
- selector->Emit(opcode, nullptr, value_operand, value_operand,
+ selector->Emit(opcode, g.NoOutput(), value_operand, value_operand,
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
explicit Arm64OperandGenerator(InstructionSelector* selector)
: OperandGenerator(selector) {}
- InstructionOperand* UseOperand(Node* node, ImmediateMode mode) {
+ InstructionOperand UseOperand(Node* node, ImmediateMode mode) {
if (CanBeImmediate(node, mode)) {
return UseImmediate(node);
}
FlagsContinuation* cont) {
Arm64OperandGenerator g(selector);
Matcher m(node);
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
bool try_ror_operand = true;
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(x11), g.TempRegister(x12)};
- Emit(kArm64StoreWriteBarrier, NULL, g.UseFixed(base, x10),
+ InstructionOperand temps[] = {g.TempRegister(x11), g.TempRegister(x12)};
+ Emit(kArm64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, x10),
g.UseFixed(index, x11), g.UseFixed(value, x12), arraysize(temps),
temps);
return;
return;
}
if (g.CanBeImmediate(index, immediate_mode)) {
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
} else {
- Emit(opcode | AddressingModeField::encode(kMode_MRR), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(),
g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
}
}
UNREACHABLE();
return;
}
- Emit(opcode, nullptr, g.UseRegister(buffer), g.UseRegister(offset),
+ Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset),
g.UseOperand(length, kArithmeticImm), g.UseRegister(value));
}
void InstructionSelector::VisitInt32MulHigh(Node* node) {
// TODO(arm64): Can we do better here?
Arm64OperandGenerator g(this);
- InstructionOperand* const smull_operand = g.TempRegister();
+ InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)),
g.UseRegister(node->InputAt(1)));
Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32));
void InstructionSelector::VisitUint32MulHigh(Node* node) {
// TODO(arm64): Can we do better here?
Arm64OperandGenerator g(this);
- InstructionOperand* const smull_operand = g.TempRegister();
+ InstructionOperand const smull_operand = g.TempRegister();
Emit(kArm64Umull, smull_operand, g.UseRegister(node->InputAt(0)),
g.UseRegister(node->InputAt(1)));
Emit(kArm64Lsr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32));
if (aligned_push_count > 0) {
// TODO(dcarney): it would be better to bump the csp here only
// and emit paired stores with increment for non c frames.
- Emit(kArm64Claim | MiscField::encode(aligned_push_count), NULL);
+ Emit(kArm64Claim | MiscField::encode(aligned_push_count), g.NoOutput());
}
// Move arguments to the stack.
{
// Emit the uneven pushes.
if (pushed_count_uneven) {
Node* input = buffer.pushed_nodes[slot];
- Emit(kArm64Poke | MiscField::encode(slot), NULL, g.UseRegister(input));
+ Emit(kArm64Poke | MiscField::encode(slot), g.NoOutput(),
+ g.UseRegister(input));
slot--;
}
// Now all pushes can be done in pairs.
for (; slot >= 0; slot -= 2) {
- Emit(kArm64PokePair | MiscField::encode(slot), NULL,
+ Emit(kArm64PokePair | MiscField::encode(slot), g.NoOutput(),
g.UseRegister(buffer.pushed_nodes[slot]),
g.UseRegister(buffer.pushed_nodes[slot - 1]));
}
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
- InstructionOperand** first_output =
+ InstructionOperand* first_output =
buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
Emit(opcode, buffer.outputs.size(), first_output,
// Shared routine for multiple compare operations.
static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
- InstructionOperand* left, InstructionOperand* right,
+ InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) {
Arm64OperandGenerator g(selector);
opcode = cont->Encode(opcode);
if (cont->IsBranch()) {
- selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()),
+ selector->Emit(opcode, g.NoOutput(), left, right,
+ g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
DCHECK(cont->IsSet());
// If the mask has only one bit set, we can use tbz/tbnz.
DCHECK((cont.condition() == kEqual) ||
(cont.condition() == kNotEqual));
- Emit(cont.Encode(kArm64TestAndBranch32), NULL,
+ Emit(cont.Encode(kArm64TestAndBranch32), g.NoOutput(),
g.UseRegister(m.left().node()),
g.TempImmediate(
base::bits::CountTrailingZeros32(m.right().Value())),
// If the mask has only one bit set, we can use tbz/tbnz.
DCHECK((cont.condition() == kEqual) ||
(cont.condition() == kNotEqual));
- Emit(cont.Encode(kArm64TestAndBranch), NULL,
+ Emit(cont.Encode(kArm64TestAndBranch), g.NoOutput(),
g.UseRegister(m.left().node()),
g.TempImmediate(
base::bits::CountTrailingZeros64(m.right().Value())),
}
// Branch could not be combined with a compare, compare against 0 and branch.
- Emit(cont.Encode(kArm64CompareAndBranch32), NULL, g.UseRegister(value),
- g.Label(cont.true_block()),
+ Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(),
+ g.UseRegister(value), g.Label(cont.true_block()),
g.Label(cont.false_block()))->MarkAsControl();
}
explicit IA32OperandGenerator(InstructionSelector* selector)
: OperandGenerator(selector) {}
- InstructionOperand* UseByteRegister(Node* node) {
+ InstructionOperand UseByteRegister(Node* node) {
// TODO(dcarney): relax constraint.
return UseFixed(node, edx);
}
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base,
Node* displacement_node,
- InstructionOperand* inputs[],
+ InstructionOperand inputs[],
size_t* input_count) {
AddressingMode mode = kMode_MRI;
int32_t displacement = (displacement_node == NULL)
}
AddressingMode GetEffectiveAddressMemoryOperand(Node* node,
- InstructionOperand* inputs[],
+ InstructionOperand inputs[],
size_t* input_count) {
BaseWithIndexAndDisplacement32Matcher m(node, true);
DCHECK(m.matches());
}
IA32OperandGenerator g(this);
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
outputs[0] = g.DefineAsRegister(node);
- InstructionOperand* inputs[3];
+ InstructionOperand inputs[3];
size_t input_count = 0;
AddressingMode mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
- Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx),
+ InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
+ Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx),
g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
temps);
return;
return;
}
- InstructionOperand* val;
+ InstructionOperand val;
if (g.CanBeImmediate(value)) {
val = g.UseImmediate(value);
} else if (rep == kRepWord8 || rep == kRepBit) {
val = g.UseRegister(value);
}
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
AddressingMode mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
InstructionCode code = opcode | AddressingModeField::encode(mode);
inputs[input_count++] = val;
- Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
+ Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
}
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.UseRegister(offset);
- InstructionOperand* length_operand =
+ InstructionOperand offset_operand = g.UseRegister(offset);
+ InstructionOperand length_operand =
g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
if (g.CanBeImmediate(buffer)) {
Emit(opcode | AddressingModeField::encode(kMode_MRI),
UNREACHABLE();
return;
}
- InstructionOperand* value_operand =
+ InstructionOperand value_operand =
g.CanBeImmediate(value)
? g.UseImmediate(value)
: ((rep == kRepWord8 || rep == kRepBit) ? g.UseByteRegister(value)
: g.UseRegister(value));
- InstructionOperand* offset_operand = g.UseRegister(offset);
- InstructionOperand* length_operand =
+ InstructionOperand offset_operand = g.UseRegister(offset);
+ InstructionOperand length_operand =
g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
if (g.CanBeImmediate(buffer)) {
- Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr,
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
offset_operand, length_operand, value_operand, offset_operand,
g.UseImmediate(buffer));
} else {
- Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr,
+ Emit(opcode | AddressingModeField::encode(kMode_MR1), g.NoOutput(),
offset_operand, length_operand, value_operand, g.UseRegister(buffer),
offset_operand);
}
Int32BinopMatcher m(node);
Node* left = m.left().node();
Node* right = m.right().node();
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
// TODO(turbofan): match complex addressing modes.
// mov eax, [ebp-0x10]
// add eax, [ebp-0x10]
// jo label
- InstructionOperand* const input = g.UseRegister(left);
+ InstructionOperand const input = g.UseRegister(left);
inputs[input_count++] = input;
inputs[input_count++] = input;
} else if (g.CanBeImmediate(right)) {
void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
IA32OperandGenerator g(selector);
- InstructionOperand* temps[] = {g.TempRegister(edx)};
+ InstructionOperand temps[] = {g.TempRegister(edx)};
selector->Emit(opcode, g.DefineAsFixed(node, eax),
g.UseFixed(node->InputAt(0), eax),
g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
void EmitLea(InstructionSelector* selector, Node* result, Node* index,
int scale, Node* base, Node* displacement) {
IA32OperandGenerator g(selector);
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
AddressingMode mode = g.GenerateMemoryOperandInputs(
index, scale, base, displacement, inputs, &input_count);
DCHECK_NE(0, static_cast<int>(input_count));
DCHECK_GE(arraysize(inputs), input_count);
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
outputs[0] = g.DefineAsRegister(result);
InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
BaseWithIndexAndDisplacement32Matcher m(node);
if (m.matches() &&
(m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) {
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
AddressingMode mode = g.GenerateMemoryOperandInputs(
m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count);
DCHECK_NE(0, static_cast<int>(input_count));
DCHECK_GE(arraysize(inputs), input_count);
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
outputs[0] = g.DefineAsRegister(node);
InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
void InstructionSelector::VisitFloat64Mod(Node* node) {
IA32OperandGenerator g(this);
- InstructionOperand* temps[] = {g.TempRegister(eax)};
+ InstructionOperand temps[] = {g.TempRegister(eax)};
Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
temps);
for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
++i) {
// TODO(titzer): handle pushing double parameters.
- InstructionOperand* value =
+ InstructionOperand value =
g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM)
? g.UseRegister(*i)
: g.Use(*i);
- Emit(kIA32Push, nullptr, value);
+ Emit(kIA32Push, g.NoOutput(), value);
}
// Select the appropriate opcode based on the call type.
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
- InstructionOperand** first_output =
+ InstructionOperand* first_output =
buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
Emit(opcode, buffer.outputs.size(), first_output,
// Shared routine for multiple compare operations.
void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
- InstructionOperand* left, InstructionOperand* right,
+ InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) {
IA32OperandGenerator g(selector);
if (cont->IsBranch()) {
- selector->Emit(cont->Encode(opcode), NULL, left, right,
+ selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right,
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
explicit OperandGenerator(InstructionSelector* selector)
: selector_(selector) {}
- InstructionOperand* DefineAsRegister(Node* node) {
+ InstructionOperand NoOutput() {
+ return InstructionOperand(); // Generates an invalid operand.
+ }
+
+ InstructionOperand DefineAsRegister(Node* node) {
return Define(node,
- new (zone()) UnallocatedOperand(
- UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node)));
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
+ GetVReg(node)));
}
- InstructionOperand* DefineSameAsFirst(Node* node) {
+ InstructionOperand DefineSameAsFirst(Node* node) {
return Define(node,
- new (zone()) UnallocatedOperand(
- UnallocatedOperand::SAME_AS_FIRST_INPUT, GetVReg(node)));
+ UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT,
+ GetVReg(node)));
}
- InstructionOperand* DefineAsFixed(Node* node, Register reg) {
- return Define(node, new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_REGISTER,
- Register::ToAllocationIndex(reg), GetVReg(node)));
+ InstructionOperand DefineAsFixed(Node* node, Register reg) {
+ return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg),
+ GetVReg(node)));
}
- InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) {
+ InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) {
return Define(node,
- new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_DOUBLE_REGISTER,
- DoubleRegister::ToAllocationIndex(reg), GetVReg(node)));
+ UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg),
+ GetVReg(node)));
}
- InstructionOperand* DefineAsConstant(Node* node) {
+ InstructionOperand DefineAsConstant(Node* node) {
selector()->MarkAsDefined(node);
int virtual_register = GetVReg(node);
sequence()->AddConstant(virtual_register, ToConstant(node));
- return ConstantOperand::Create(virtual_register, zone());
+ return ConstantOperand(virtual_register);
}
- InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location,
- MachineType type) {
+ InstructionOperand DefineAsLocation(Node* node, LinkageLocation location,
+ MachineType type) {
return Define(node, ToUnallocatedOperand(location, type, GetVReg(node)));
}
- InstructionOperand* Use(Node* node) {
- return Use(node, new (zone()) UnallocatedOperand(
- UnallocatedOperand::NONE,
- UnallocatedOperand::USED_AT_START, GetVReg(node)));
+ InstructionOperand Use(Node* node) {
+ return Use(node, UnallocatedOperand(UnallocatedOperand::NONE,
+ UnallocatedOperand::USED_AT_START,
+ GetVReg(node)));
}
- InstructionOperand* UseRegister(Node* node) {
- return Use(node, new (zone()) UnallocatedOperand(
- UnallocatedOperand::MUST_HAVE_REGISTER,
- UnallocatedOperand::USED_AT_START, GetVReg(node)));
+ InstructionOperand UseRegister(Node* node) {
+ return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
+ UnallocatedOperand::USED_AT_START,
+ GetVReg(node)));
}
// Use register or operand for the node. If a register is chosen, it won't
// alias any temporary or output registers.
- InstructionOperand* UseUnique(Node* node) {
- return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::NONE,
- GetVReg(node)));
+ InstructionOperand UseUnique(Node* node) {
+ return Use(node,
+ UnallocatedOperand(UnallocatedOperand::NONE, GetVReg(node)));
}
// Use a unique register for the node that does not alias any temporary or
// output registers.
- InstructionOperand* UseUniqueRegister(Node* node) {
- return Use(node,
- new (zone()) UnallocatedOperand(
- UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node)));
+ InstructionOperand UseUniqueRegister(Node* node) {
+ return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
+ GetVReg(node)));
}
- InstructionOperand* UseFixed(Node* node, Register reg) {
- return Use(node, new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_REGISTER,
- Register::ToAllocationIndex(reg), GetVReg(node)));
+ InstructionOperand UseFixed(Node* node, Register reg) {
+ return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg),
+ GetVReg(node)));
}
- InstructionOperand* UseFixed(Node* node, DoubleRegister reg) {
+ InstructionOperand UseFixed(Node* node, DoubleRegister reg) {
return Use(node,
- new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_DOUBLE_REGISTER,
- DoubleRegister::ToAllocationIndex(reg), GetVReg(node)));
+ UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg),
+ GetVReg(node)));
}
- InstructionOperand* UseImmediate(Node* node) {
+ InstructionOperand UseImmediate(Node* node) {
int index = sequence()->AddImmediate(ToConstant(node));
- return ImmediateOperand::Create(index, zone());
+ return ImmediateOperand(index);
}
- InstructionOperand* UseLocation(Node* node, LinkageLocation location,
- MachineType type) {
+ InstructionOperand UseLocation(Node* node, LinkageLocation location,
+ MachineType type) {
return Use(node, ToUnallocatedOperand(location, type, GetVReg(node)));
}
- InstructionOperand* TempRegister() {
- return new (zone()) UnallocatedOperand(
- UnallocatedOperand::MUST_HAVE_REGISTER,
- UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
+ InstructionOperand TempRegister() {
+ return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
+ UnallocatedOperand::USED_AT_START,
+ sequence()->NextVirtualRegister());
}
- InstructionOperand* TempDoubleRegister() {
- UnallocatedOperand* op = new (zone()) UnallocatedOperand(
+ InstructionOperand TempDoubleRegister() {
+ UnallocatedOperand op = UnallocatedOperand(
UnallocatedOperand::MUST_HAVE_REGISTER,
UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
- sequence()->MarkAsDouble(op->virtual_register());
+ sequence()->MarkAsDouble(op.virtual_register());
return op;
}
- InstructionOperand* TempRegister(Register reg) {
- return new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_REGISTER, Register::ToAllocationIndex(reg),
- UnallocatedOperand::kInvalidVirtualRegister);
+ InstructionOperand TempRegister(Register reg) {
+ return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg),
+ UnallocatedOperand::kInvalidVirtualRegister);
}
- InstructionOperand* TempImmediate(int32_t imm) {
+ InstructionOperand TempImmediate(int32_t imm) {
int index = sequence()->AddImmediate(Constant(imm));
- return ImmediateOperand::Create(index, zone());
+ return ImmediateOperand(index);
}
- InstructionOperand* TempLocation(LinkageLocation location, MachineType type) {
+ InstructionOperand TempLocation(LinkageLocation location, MachineType type) {
return ToUnallocatedOperand(location, type,
sequence()->NextVirtualRegister());
}
- InstructionOperand* Label(BasicBlock* block) {
+ InstructionOperand Label(BasicBlock* block) {
int index = sequence()->AddImmediate(Constant(block->GetRpoNumber()));
- return ImmediateOperand::Create(index, zone());
+ return ImmediateOperand(index);
}
protected:
return Constant(static_cast<int32_t>(0));
}
- UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) {
+ UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
DCHECK_NOT_NULL(node);
- DCHECK_NOT_NULL(operand);
- DCHECK_EQ(operand->virtual_register(), GetVReg(node));
+ DCHECK_EQ(operand.virtual_register(), GetVReg(node));
selector()->MarkAsDefined(node);
return operand;
}
- UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) {
+ UnallocatedOperand Use(Node* node, UnallocatedOperand operand) {
DCHECK_NOT_NULL(node);
- DCHECK_NOT_NULL(operand);
- DCHECK_EQ(operand->virtual_register(), GetVReg(node));
+ DCHECK_EQ(operand.virtual_register(), GetVReg(node));
selector()->MarkAsUsed(node);
return operand;
}
- UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location,
- MachineType type,
- int virtual_register) {
+ UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
+ MachineType type,
+ int virtual_register) {
if (location.location_ == LinkageLocation::ANY_REGISTER) {
// any machine register.
- return new (zone()) UnallocatedOperand(
- UnallocatedOperand::MUST_HAVE_REGISTER, virtual_register);
+ return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
+ virtual_register);
}
if (location.location_ < 0) {
// a location on the caller frame.
- return new (zone()) UnallocatedOperand(
- UnallocatedOperand::FIXED_SLOT, location.location_, virtual_register);
+ return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
+ location.location_, virtual_register);
}
if (location.location_ > LinkageLocation::ANY_REGISTER) {
// a spill location on this (callee) frame.
- return new (zone()) UnallocatedOperand(
+ return UnallocatedOperand(
UnallocatedOperand::FIXED_SLOT,
location.location_ - LinkageLocation::ANY_REGISTER - 1,
virtual_register);
}
// a fixed register.
if (RepresentationOf(type) == kRepFloat64) {
- return new (zone())
- UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
- location.location_, virtual_register);
+ return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
+ location.location_, virtual_register);
}
- return new (zone())
- UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
- location.location_, virtual_register);
+ return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
+ location.location_, virtual_register);
}
InstructionSelector* selector_;
Instruction* InstructionSelector::Emit(InstructionCode opcode,
- InstructionOperand* output,
+ InstructionOperand output,
size_t temp_count,
- InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
+ InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
return Emit(opcode, output_count, &output, 0, NULL, temp_count, temps);
}
Instruction* InstructionSelector::Emit(InstructionCode opcode,
- InstructionOperand* output,
- InstructionOperand* a, size_t temp_count,
- InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
+ InstructionOperand output,
+ InstructionOperand a, size_t temp_count,
+ InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
return Emit(opcode, output_count, &output, 1, &a, temp_count, temps);
}
Instruction* InstructionSelector::Emit(InstructionCode opcode,
- InstructionOperand* output,
- InstructionOperand* a,
- InstructionOperand* b, size_t temp_count,
- InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
- InstructionOperand* inputs[] = {a, b};
+ InstructionOperand output,
+ InstructionOperand a,
+ InstructionOperand b, size_t temp_count,
+ InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
+ InstructionOperand inputs[] = {a, b};
size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
Instruction* InstructionSelector::Emit(InstructionCode opcode,
- InstructionOperand* output,
- InstructionOperand* a,
- InstructionOperand* b,
- InstructionOperand* c, size_t temp_count,
- InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
- InstructionOperand* inputs[] = {a, b, c};
+ InstructionOperand output,
+ InstructionOperand a,
+ InstructionOperand b,
+ InstructionOperand c, size_t temp_count,
+ InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
+ InstructionOperand inputs[] = {a, b, c};
size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
Instruction* InstructionSelector::Emit(
- InstructionCode opcode, InstructionOperand* output, InstructionOperand* a,
- InstructionOperand* b, InstructionOperand* c, InstructionOperand* d,
- size_t temp_count, InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
- InstructionOperand* inputs[] = {a, b, c, d};
+ InstructionCode opcode, InstructionOperand output, InstructionOperand a,
+ InstructionOperand b, InstructionOperand c, InstructionOperand d,
+ size_t temp_count, InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
+ InstructionOperand inputs[] = {a, b, c, d};
size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
Instruction* InstructionSelector::Emit(
- InstructionCode opcode, InstructionOperand* output, InstructionOperand* a,
- InstructionOperand* b, InstructionOperand* c, InstructionOperand* d,
- InstructionOperand* e, size_t temp_count, InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
- InstructionOperand* inputs[] = {a, b, c, d, e};
+ InstructionCode opcode, InstructionOperand output, InstructionOperand a,
+ InstructionOperand b, InstructionOperand c, InstructionOperand d,
+ InstructionOperand e, size_t temp_count, InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
+ InstructionOperand inputs[] = {a, b, c, d, e};
size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
Instruction* InstructionSelector::Emit(
- InstructionCode opcode, InstructionOperand* output, InstructionOperand* a,
- InstructionOperand* b, InstructionOperand* c, InstructionOperand* d,
- InstructionOperand* e, InstructionOperand* f, size_t temp_count,
- InstructionOperand** temps) {
- size_t output_count = output == NULL ? 0 : 1;
- InstructionOperand* inputs[] = {a, b, c, d, e, f};
+ InstructionCode opcode, InstructionOperand output, InstructionOperand a,
+ InstructionOperand b, InstructionOperand c, InstructionOperand d,
+ InstructionOperand e, InstructionOperand f, size_t temp_count,
+ InstructionOperand* temps) {
+ size_t output_count = output.IsInvalid() ? 0 : 1;
+ InstructionOperand inputs[] = {a, b, c, d, e, f};
size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
Instruction* InstructionSelector::Emit(
- InstructionCode opcode, size_t output_count, InstructionOperand** outputs,
- size_t input_count, InstructionOperand** inputs, size_t temp_count,
- InstructionOperand** temps) {
+ InstructionCode opcode, size_t output_count, InstructionOperand* outputs,
+ size_t input_count, InstructionOperand* inputs, size_t temp_count,
+ InstructionOperand* temps) {
Instruction* instr =
Instruction::New(instruction_zone(), opcode, output_count, outputs,
input_count, inputs, temp_count, temps);
void InstructionSelector::MarkAsRepresentation(MachineType rep,
- InstructionOperand* op) {
- UnallocatedOperand* unalloc = UnallocatedOperand::cast(op);
+ const InstructionOperand& op) {
+ UnallocatedOperand unalloc = UnallocatedOperand::cast(op);
switch (RepresentationOf(rep)) {
case kRepFloat32:
case kRepFloat64:
- sequence()->MarkAsDouble(unalloc->virtual_register());
+ sequence()->MarkAsDouble(unalloc.virtual_register());
break;
case kRepTagged:
- sequence()->MarkAsReference(unalloc->virtual_register());
+ sequence()->MarkAsReference(unalloc.virtual_register());
break;
default:
break;
buffer->descriptor->GetReturnLocation(static_cast<int>(i));
Node* output = buffer->output_nodes[i];
- InstructionOperand* op =
+ InstructionOperand op =
output == NULL ? g.TempLocation(location, type)
: g.DefineAsLocation(output, location, type);
MarkAsRepresentation(type, op);
DCHECK(iter != call->inputs().end());
DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
if (index == 0) continue; // The first argument (callee) is already done.
- InstructionOperand* op =
+ InstructionOperand op =
g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index),
buffer->descriptor->GetInputType(index));
- if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) {
- int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1;
+ if (UnallocatedOperand::cast(op).HasFixedSlotPolicy()) {
+ int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1;
if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
buffer->pushed_nodes.resize(stack_index + 1, NULL);
}
void InstructionSelector::VisitGoto(BasicBlock* target) {
// jump to the next block.
OperandGenerator g(this);
- Emit(kArchJmp, NULL, g.Label(target))->MarkAsControl();
+ Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl();
}
void InstructionSelector::VisitReturn(Node* value) {
OperandGenerator g(this);
if (value != NULL) {
- Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation(),
- linkage()->GetReturnType()));
+ Emit(kArchRet, g.NoOutput(),
+ g.UseLocation(value, linkage()->GetReturnLocation(),
+ linkage()->GetReturnType()));
} else {
- Emit(kArchRet, NULL);
+ Emit(kArchRet, g.NoOutput());
}
}
void InstructionSelector::VisitThrow(Node* value) {
- Emit(kArchNop, NULL); // TODO(titzer)
+ OperandGenerator g(this);
+ Emit(kArchNop, g.NoOutput()); // TODO(titzer)
}
}
-static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) {
+static InstructionOperand UseOrImmediate(OperandGenerator* g, Node* input) {
switch (input->opcode()) {
case IrOpcode::kInt32Constant:
case IrOpcode::kNumberConstant:
class Linkage;
+typedef ZoneVector<InstructionOperand> InstructionOperandVector;
+
+
// Instruction selection generates an InstructionSequence for a given Schedule.
class InstructionSelector FINAL {
public:
// ============= Architecture-independent code emission methods. =============
// ===========================================================================
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- size_t temp_count = 0, InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, size_t temp_count = 0,
- InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, InstructionOperand* b,
- size_t temp_count = 0, InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, InstructionOperand* b,
- InstructionOperand* c, size_t temp_count = 0,
- InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, InstructionOperand* b,
- InstructionOperand* c, InstructionOperand* d,
- size_t temp_count = 0, InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, InstructionOperand* b,
- InstructionOperand* c, InstructionOperand* d,
- InstructionOperand* e, size_t temp_count = 0,
- InstructionOperand* *temps = NULL);
- Instruction* Emit(InstructionCode opcode, InstructionOperand* output,
- InstructionOperand* a, InstructionOperand* b,
- InstructionOperand* c, InstructionOperand* d,
- InstructionOperand* e, InstructionOperand* f,
- size_t temp_count = 0, InstructionOperand* *temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ size_t temp_count = 0, InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, size_t temp_count = 0,
+ InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, InstructionOperand b,
+ size_t temp_count = 0, InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, InstructionOperand b,
+ InstructionOperand c, size_t temp_count = 0,
+ InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, InstructionOperand b,
+ InstructionOperand c, InstructionOperand d,
+ size_t temp_count = 0, InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, InstructionOperand b,
+ InstructionOperand c, InstructionOperand d,
+ InstructionOperand e, size_t temp_count = 0,
+ InstructionOperand* temps = NULL);
+ Instruction* Emit(InstructionCode opcode, InstructionOperand output,
+ InstructionOperand a, InstructionOperand b,
+ InstructionOperand c, InstructionOperand d,
+ InstructionOperand e, InstructionOperand f,
+ size_t temp_count = 0, InstructionOperand* temps = NULL);
Instruction* Emit(InstructionCode opcode, size_t output_count,
- InstructionOperand** outputs, size_t input_count,
- InstructionOperand** inputs, size_t temp_count = 0,
- InstructionOperand* *temps = NULL);
+ InstructionOperand* outputs, size_t input_count,
+ InstructionOperand* inputs, size_t temp_count = 0,
+ InstructionOperand* temps = NULL);
Instruction* Emit(Instruction* instr);
// ===========================================================================
// Inform the register allocation of the representation of the unallocated
// operand {op}.
- void MarkAsRepresentation(MachineType rep, InstructionOperand* op);
+ void MarkAsRepresentation(MachineType rep, const InstructionOperand& op);
// Initialize the call buffer with the InstructionOperands, nodes, etc,
// corresponding
}
-static void SetOperand(UnallocatedOperand* loc, InstructionOperand* value) {
- if (value->IsUnallocated()) {
- loc[0] = *UnallocatedOperand::cast(value);
- } else {
- InstructionOperand* casted = static_cast<InstructionOperand*>(loc);
- casted[0] = *value;
- }
-}
-
-
Instruction::Instruction(InstructionCode opcode)
: opcode_(opcode),
bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
Instruction::Instruction(InstructionCode opcode, size_t output_count,
- InstructionOperand** outputs, size_t input_count,
- InstructionOperand** inputs, size_t temp_count,
- InstructionOperand** temps)
+ InstructionOperand* outputs, size_t input_count,
+ InstructionOperand* inputs, size_t temp_count,
+ InstructionOperand* temps)
: opcode_(opcode),
bit_field_(OutputCountField::encode(output_count) |
InputCountField::encode(input_count) |
pointer_map_(NULL) {
size_t offset = 0;
for (size_t i = 0; i < output_count; ++i) {
- SetOperand(&operands_[offset++], outputs[i]);
+ DCHECK(!outputs[i].IsInvalid());
+ operands_[offset++] = outputs[i];
}
for (size_t i = 0; i < input_count; ++i) {
- SetOperand(&operands_[offset++], inputs[i]);
+ DCHECK(!inputs[i].IsInvalid());
+ operands_[offset++] = inputs[i];
}
for (size_t i = 0; i < temp_count; ++i) {
- SetOperand(&operands_[offset++], temps[i]);
+ DCHECK(!temps[i].IsInvalid());
+ operands_[offset++] = temps[i];
}
}
V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
-class InstructionOperand : public ZoneObject {
+class InstructionOperand {
public:
static const int kInvalidVirtualRegister = -1;
DOUBLE_REGISTER
};
+ InstructionOperand() : virtual_register_(kInvalidVirtualRegister) {
+ ConvertTo(INVALID, 0);
+ }
+
InstructionOperand(Kind kind, int index)
: virtual_register_(kInvalidVirtualRegister) {
DCHECK(kind != INVALID);
bool Is##name() const { return kind() == type; }
INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
+ INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID, 0)
#undef INSTRUCTION_OPERAND_PREDICATE
bool Equals(const InstructionOperand* other) const {
return value_ == other->value_;
static void SetUpCaches();
static void TearDownCaches();
+ // TODO(dcarney): get rid of these
+ void* operator new(size_t, void* location) { return location; }
+ void* operator new(size_t size, Zone* zone) {
+ return zone->New(static_cast<int>(size));
+ }
+
protected:
InstructionOperand(Kind kind, int index, int virtual_register)
: virtual_register_(virtual_register) {
int32_t virtual_register_;
};
-typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
-
struct PrintableInstructionOperand {
const RegisterConfiguration* register_configuration_;
const InstructionOperand* op_;
// TODO(dcarney): remove this.
static const int kInvalidVirtualRegister = -1;
- // This is only for array initialization.
- UnallocatedOperand()
- : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
-
UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
: InstructionOperand(UNALLOCATED, 0, virtual_register) {
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
return static_cast<UnallocatedOperand*>(op);
}
+ static UnallocatedOperand cast(const InstructionOperand& op) {
+ DCHECK(op.IsUnallocated());
+ return *static_cast<const UnallocatedOperand*>(&op);
+ }
+
// The encoding used for UnallocatedOperand operands depends on the policy
// that is
// stored within the operand. The FIXED_SLOT policy uses a compact encoding
template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
class SubKindOperand FINAL : public InstructionOperand {
public:
+ explicit SubKindOperand(int index)
+ : InstructionOperand(kOperandKind, index) {}
+
static SubKindOperand* Create(int index, Zone* zone) {
DCHECK(index >= 0);
if (index < kNumCachedOperands) return &cache[index];
return reinterpret_cast<const SubKindOperand*>(op);
}
+ static SubKindOperand cast(const InstructionOperand& op) {
+ DCHECK(op.kind() == kOperandKind);
+ return *static_cast<const SubKindOperand*>(&op);
+ }
+
static void SetUpCache();
static void TearDownCache();
static SubKindOperand* cache;
SubKindOperand() : InstructionOperand(kOperandKind, 0) {} // For the caches.
- explicit SubKindOperand(int index)
- : InstructionOperand(kOperandKind, index) {}
};
}
static Instruction* New(Zone* zone, InstructionCode opcode,
- size_t output_count, InstructionOperand** outputs,
- size_t input_count, InstructionOperand** inputs,
- size_t temp_count, InstructionOperand** temps) {
+ size_t output_count, InstructionOperand* outputs,
+ size_t input_count, InstructionOperand* inputs,
+ size_t temp_count, InstructionOperand* temps) {
DCHECK(opcode >= 0);
DCHECK(output_count == 0 || outputs != NULL);
DCHECK(input_count == 0 || inputs != NULL);
size_t total_extra_ops = output_count + input_count + temp_count;
if (total_extra_ops != 0) total_extra_ops--;
int size = static_cast<int>(
- RoundUp(sizeof(Instruction), sizeof(UnallocatedOperand)) +
- total_extra_ops * sizeof(UnallocatedOperand));
+ RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
+ total_extra_ops * sizeof(InstructionOperand));
return new (zone->New(size)) Instruction(
opcode, output_count, outputs, input_count, inputs, temp_count, temps);
}
protected:
explicit Instruction(InstructionCode opcode);
Instruction(InstructionCode opcode, size_t output_count,
- InstructionOperand** outputs, size_t input_count,
- InstructionOperand** inputs, size_t temp_count,
- InstructionOperand** temps);
+ InstructionOperand* outputs, size_t input_count,
+ InstructionOperand* inputs, size_t temp_count,
+ InstructionOperand* temps);
protected:
typedef BitField<size_t, 0, 8> OutputCountField;
InstructionCode opcode_;
uint32_t bit_field_;
PointerMap* pointer_map_;
- UnallocatedOperand operands_[1];
+ InstructionOperand operands_[1];
};
explicit MipsOperandGenerator(InstructionSelector* selector)
: OperandGenerator(selector) {}
- InstructionOperand* UseOperand(Node* node, InstructionCode opcode) {
+ InstructionOperand UseOperand(Node* node, InstructionCode opcode) {
if (CanBeImmediate(node, opcode)) {
return UseImmediate(node);
}
InstructionCode opcode, FlagsContinuation* cont) {
MipsOperandGenerator g(selector);
Int32BinopMatcher m(node);
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
inputs[input_count++] = g.UseRegister(m.left().node());
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
} else {
- InstructionOperand* addr_reg = g.TempRegister();
+ InstructionOperand addr_reg = g.TempRegister();
Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired load opcode, using temp addr_reg.
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(t1), g.TempRegister(t2)};
- Emit(kMipsStoreWriteBarrier, NULL, g.UseFixed(base, t0),
+ InstructionOperand temps[] = {g.TempRegister(t1), g.TempRegister(t2)};
+ Emit(kMipsStoreWriteBarrier, g.NoOutput(), g.UseFixed(base, t0),
g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps);
return;
}
}
if (g.CanBeImmediate(index, opcode)) {
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
} else {
- InstructionOperand* addr_reg = g.TempRegister();
+ InstructionOperand addr_reg = g.TempRegister();
Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired store opcode, using temp addr_reg.
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, addr_reg,
- g.TempImmediate(0), g.UseRegister(value));
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+ addr_reg, g.TempImmediate(0), g.UseRegister(value));
}
}
return;
}
if (base::bits::IsPowerOfTwo32(value - 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value - 1)));
return;
}
if (base::bits::IsPowerOfTwo32(value + 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value + 1)));
// Possibly align stack here for functions.
int push_count = buffer.pushed_nodes.size();
if (push_count > 0) {
- Emit(kMipsStackClaim | MiscField::encode(push_count), NULL);
+ Emit(kMipsStackClaim | MiscField::encode(push_count), g.NoOutput());
}
int slot = buffer.pushed_nodes.size() - 1;
for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
++i) {
- Emit(kMipsStoreToStackSlot | MiscField::encode(slot), nullptr,
+ Emit(kMipsStoreToStackSlot | MiscField::encode(slot), g.NoOutput(),
g.UseRegister(*i));
slot--;
}
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
- InstructionOperand** first_output =
+ InstructionOperand* first_output =
buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
Emit(opcode, buffer.outputs.size(), first_output,
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode)
- ? g.UseImmediate(offset)
- : g.UseRegister(offset);
+ InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode)
+ ? g.UseImmediate(offset)
+ : g.UseRegister(offset);
- InstructionOperand* length_operand =
- (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode)
- ? g.UseImmediate(length)
- : g.UseRegister(length)
- : g.UseRegister(length);
+ InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode))
+ ? g.CanBeImmediate(length, opcode)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length)
+ : g.UseRegister(length);
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), offset_operand, length_operand,
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode)
- ? g.UseImmediate(offset)
- : g.UseRegister(offset);
-
- InstructionOperand* length_operand =
- (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode)
- ? g.UseImmediate(length)
- : g.UseRegister(length)
- : g.UseRegister(length);
-
- Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand,
- length_operand, g.UseRegister(value), g.UseRegister(buffer));
+ InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode)
+ ? g.UseImmediate(offset)
+ : g.UseRegister(offset);
+
+ InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode))
+ ? g.CanBeImmediate(length, opcode)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length)
+ : g.UseRegister(length);
+
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+ offset_operand, length_operand, g.UseRegister(value),
+ g.UseRegister(buffer));
}
// Shared routine for multiple compare operations.
static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
- InstructionOperand* left, InstructionOperand* right,
+ InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) {
MipsOperandGenerator g(selector);
opcode = cont->Encode(opcode);
if (cont->IsBranch()) {
- selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()),
+ selector->Emit(opcode, g.NoOutput(), left, right,
+ g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
DCHECK(cont->IsSet());
// Continuation could not be combined with a compare, emit compare against 0.
MipsOperandGenerator g(selector);
InstructionCode const opcode = cont->Encode(kMipsCmp);
- InstructionOperand* const value_operand = g.UseRegister(value);
+ InstructionOperand const value_operand = g.UseRegister(value);
if (cont->IsBranch()) {
- selector->Emit(opcode, nullptr, value_operand, g.TempImmediate(0),
+ selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0),
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
explicit Mips64OperandGenerator(InstructionSelector* selector)
: OperandGenerator(selector) {}
- InstructionOperand* UseOperand(Node* node, InstructionCode opcode) {
+ InstructionOperand UseOperand(Node* node, InstructionCode opcode) {
if (CanBeImmediate(node, opcode)) {
return UseImmediate(node);
}
InstructionCode opcode, FlagsContinuation* cont) {
Mips64OperandGenerator g(selector);
Int32BinopMatcher m(node);
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
inputs[input_count++] = g.UseRegister(m.left().node());
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
} else {
- InstructionOperand* addr_reg = g.TempRegister();
+ InstructionOperand addr_reg = g.TempRegister();
Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired load opcode, using temp addr_reg.
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(t1), g.TempRegister(t2)};
- Emit(kMips64StoreWriteBarrier, NULL, g.UseFixed(base, t0),
+ InstructionOperand temps[] = {g.TempRegister(t1), g.TempRegister(t2)};
+ Emit(kMips64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, t0),
g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps);
return;
}
}
if (g.CanBeImmediate(index, opcode)) {
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
} else {
- InstructionOperand* addr_reg = g.TempRegister();
+ InstructionOperand addr_reg = g.TempRegister();
Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired store opcode, using temp addr_reg.
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, addr_reg,
- g.TempImmediate(0), g.UseRegister(value));
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+ addr_reg, g.TempImmediate(0), g.UseRegister(value));
}
}
return;
}
if (base::bits::IsPowerOfTwo32(value - 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value - 1)));
return;
}
if (base::bits::IsPowerOfTwo32(value + 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value + 1)));
void InstructionSelector::VisitUint32MulHigh(Node* node) {
Mips64OperandGenerator g(this);
- InstructionOperand* const dmul_operand = g.TempRegister();
+ InstructionOperand const dmul_operand = g.TempRegister();
Emit(kMips64MulHighU, dmul_operand, g.UseRegister(node->InputAt(0)),
g.UseRegister(node->InputAt(1)));
Emit(kMips64Ext, g.DefineAsRegister(node), dmul_operand, g.TempImmediate(0),
return;
}
if (base::bits::IsPowerOfTwo32(value - 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value - 1)));
return;
}
if (base::bits::IsPowerOfTwo32(value + 1)) {
- InstructionOperand* temp = g.TempRegister();
+ InstructionOperand temp = g.TempRegister();
Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp,
g.UseRegister(m.left().node()),
g.TempImmediate(WhichPowerOf2(value + 1)));
int push_count = buffer.pushed_nodes.size();
if (push_count > 0) {
- Emit(kMips64StackClaim | MiscField::encode(push_count), NULL);
+ Emit(kMips64StackClaim | MiscField::encode(push_count), g.NoOutput());
}
int slot = buffer.pushed_nodes.size() - 1;
for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
++i) {
- Emit(kMips64StoreToStackSlot | MiscField::encode(slot), nullptr,
+ Emit(kMips64StoreToStackSlot | MiscField::encode(slot), g.NoOutput(),
g.UseRegister(*i));
slot--;
}
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode)
- ? g.UseImmediate(offset)
- : g.UseRegister(offset);
+ InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode)
+ ? g.UseImmediate(offset)
+ : g.UseRegister(offset);
- InstructionOperand* length_operand =
- (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode)
- ? g.UseImmediate(length)
- : g.UseRegister(length)
- : g.UseRegister(length);
+ InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode))
+ ? g.CanBeImmediate(length, opcode)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length)
+ : g.UseRegister(length);
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), offset_operand, length_operand,
UNREACHABLE();
return;
}
- InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode)
- ? g.UseImmediate(offset)
- : g.UseRegister(offset);
-
- InstructionOperand* length_operand =
- (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode)
- ? g.UseImmediate(length)
- : g.UseRegister(length)
- : g.UseRegister(length);
-
- Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand,
- length_operand, g.UseRegister(value), g.UseRegister(buffer));
+ InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode)
+ ? g.UseImmediate(offset)
+ : g.UseRegister(offset);
+
+ InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode))
+ ? g.CanBeImmediate(length, opcode)
+ ? g.UseImmediate(length)
+ : g.UseRegister(length)
+ : g.UseRegister(length);
+
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+ offset_operand, length_operand, g.UseRegister(value),
+ g.UseRegister(buffer));
}
// Shared routine for multiple compare operations.
static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
- InstructionOperand* left, InstructionOperand* right,
+ InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) {
Mips64OperandGenerator g(selector);
opcode = cont->Encode(opcode);
if (cont->IsBranch()) {
- selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()),
+ selector->Emit(opcode, g.NoOutput(), left, right,
+ g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
DCHECK(cont->IsSet());
Node* value, FlagsContinuation* cont) {
Mips64OperandGenerator g(selector);
opcode = cont->Encode(opcode);
- InstructionOperand* const value_operand = g.UseRegister(value);
+ InstructionOperand const value_operand = g.UseRegister(value);
if (cont->IsBranch()) {
- selector->Emit(opcode, nullptr, value_operand, g.TempImmediate(0),
+ selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0),
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent,
Node* base, Node* displacement,
- InstructionOperand* inputs[],
+ InstructionOperand inputs[],
size_t* input_count) {
AddressingMode mode = kMode_MRI;
if (base != NULL) {
}
AddressingMode GetEffectiveAddressMemoryOperand(Node* operand,
- InstructionOperand* inputs[],
+ InstructionOperand inputs[],
size_t* input_count) {
BaseWithIndexAndDisplacement64Matcher m(operand, true);
DCHECK(m.matches());
return;
}
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
outputs[0] = g.DefineAsRegister(node);
- InstructionOperand* inputs[3];
+ InstructionOperand inputs[3];
size_t input_count = 0;
AddressingMode mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
// TODO(dcarney): refactor RecordWrite function to take temp registers
// and pass them here instead of using fixed regs
// TODO(dcarney): handle immediate indices.
- InstructionOperand* temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)};
- Emit(kX64StoreWriteBarrier, NULL, g.UseFixed(base, rbx),
+ InstructionOperand temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)};
+ Emit(kX64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, rbx),
g.UseFixed(index, rcx), g.UseFixed(value, rdx), arraysize(temps),
temps);
return;
UNREACHABLE();
return;
}
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
AddressingMode mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
InstructionCode code = opcode | AddressingModeField::encode(mode);
- InstructionOperand* value_operand =
+ InstructionOperand value_operand =
g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
inputs[input_count++] = value_operand;
- Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
+ Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
}
return;
}
}
- InstructionOperand* length_operand =
+ InstructionOperand length_operand =
g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer),
g.UseRegister(offset), g.TempImmediate(0), length_operand);
UNREACHABLE();
return;
}
- InstructionOperand* value_operand =
+ InstructionOperand value_operand =
g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) {
Int32Matcher mlength(length);
if (mlength.HasValue() && moffset.right().HasValue() &&
moffset.right().Value() >= 0 &&
mlength.Value() >= moffset.right().Value()) {
- Emit(opcode, nullptr, g.UseRegister(buffer),
+ Emit(opcode, g.NoOutput(), g.UseRegister(buffer),
g.UseRegister(moffset.left().node()),
g.UseImmediate(moffset.right().node()), g.UseImmediate(length),
value_operand);
return;
}
}
- InstructionOperand* length_operand =
+ InstructionOperand length_operand =
g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
- Emit(opcode, nullptr, g.UseRegister(buffer), g.UseRegister(offset),
+ Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset),
g.TempImmediate(0), length_operand, value_operand);
}
Int32BinopMatcher m(node);
Node* left = m.left().node();
Node* right = m.right().node();
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
- InstructionOperand* outputs[2];
+ InstructionOperand outputs[2];
size_t output_count = 0;
// TODO(turbofan): match complex addressing modes.
// mov rax, [rbp-0x10]
// add rax, [rbp-0x10]
// jo label
- InstructionOperand* const input = g.UseRegister(left);
+ InstructionOperand const input = g.UseRegister(left);
inputs[input_count++] = input;
inputs[input_count++] = input;
} else if (g.CanBeImmediate(right)) {
Node* displacement) {
X64OperandGenerator g(selector);
- InstructionOperand* inputs[4];
+ InstructionOperand inputs[4];
size_t input_count = 0;
AddressingMode mode = g.GenerateMemoryOperandInputs(
index, scale, base, displacement, inputs, &input_count);
DCHECK_NE(0, static_cast<int>(input_count));
DCHECK_GE(arraysize(inputs), input_count);
- InstructionOperand* outputs[1];
+ InstructionOperand outputs[1];
outputs[0] = g.DefineAsRegister(result);
opcode = AddressingModeField::encode(mode) | opcode;
void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
X64OperandGenerator g(selector);
- InstructionOperand* temps[] = {g.TempRegister(rdx)};
+ InstructionOperand temps[] = {g.TempRegister(rdx)};
selector->Emit(
opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax),
g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
void InstructionSelector::VisitFloat64Mod(Node* node) {
X64OperandGenerator g(this);
- InstructionOperand* temps[] = {g.TempRegister(rax)};
+ InstructionOperand temps[] = {g.TempRegister(rax)};
Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
temps);
for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
++i) {
// TODO(titzer): handle pushing double parameters.
- InstructionOperand* value =
+ InstructionOperand value =
g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM)
? g.UseRegister(*i)
: g.Use(*i);
- Emit(kX64Push, nullptr, value);
+ Emit(kX64Push, g.NoOutput(), value);
}
// Select the appropriate opcode based on the call type.
opcode |= MiscField::encode(descriptor->flags());
// Emit the call instruction.
- InstructionOperand** first_output =
+ InstructionOperand* first_output =
buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
Instruction* call_instr =
Emit(opcode, buffer.outputs.size(), first_output,
// Shared routine for multiple compare operations.
static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
- InstructionOperand* left, InstructionOperand* right,
+ InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) {
X64OperandGenerator g(selector);
opcode = cont->Encode(opcode);
if (cont->IsBranch()) {
- selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()),
+ selector->Emit(opcode, g.NoOutput(), left, right,
+ g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
DCHECK(cont->IsSet());
}
int vreg = 15;
- InstructionOperand* outputs[] = {
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
-
- InstructionOperand* inputs[] = {
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
-
- InstructionOperand* temps[] = {
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
- new (&zone)
- UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
+ InstructionOperand outputs[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
+
+ InstructionOperand inputs[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
+
+ InstructionOperand temps[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
for (size_t i = 0; i < arraysize(outputs); i++) {
for (size_t j = 0; j < arraysize(inputs); j++) {
CHECK(k == m->TempCount());
for (size_t z = 0; z < i; z++) {
- CHECK(outputs[z]->Equals(m->OutputAt(z)));
+ CHECK(outputs[z].Equals(m->OutputAt(z)));
}
for (size_t z = 0; z < j; z++) {
- CHECK(inputs[z]->Equals(m->InputAt(z)));
+ CHECK(inputs[z].Equals(m->InputAt(z)));
}
for (size_t z = 0; z < k; z++) {
- CHECK(temps[z]->Equals(m->TempAt(z)));
+ CHECK(temps[z].Equals(m->TempAt(z)));
}
}
}
int Jump(int target) {
Start();
- InstructionOperand* ops[] = {UseRpo(target)};
+ InstructionOperand ops[] = {UseRpo(target)};
sequence_.AddInstruction(Instruction::New(main_zone(), kArchJmp, 0, NULL, 1,
ops, 0, NULL)->MarkAsControl());
int pos = static_cast<int>(sequence_.instructions().size() - 1);
}
int Branch(int ttarget, int ftarget) {
Start();
- InstructionOperand* ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
+ InstructionOperand ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
InstructionCode code = 119 | FlagsModeField::encode(kFlags_branch) |
FlagsConditionField::encode(kEqual);
sequence_.AddInstruction(Instruction::New(main_zone(), code, 0, NULL, 2,
current_ = NULL;
rpo_number_ = RpoNumber::FromInt(rpo_number_.ToInt() + 1);
}
- InstructionOperand* UseRpo(int num) {
+ InstructionOperand UseRpo(int num) {
int index = sequence_.AddImmediate(Constant(RpoNumber::FromInt(num)));
- return ImmediateOperand::Create(index, main_zone());
+ return ImmediateOperand(index);
}
void Start(bool deferred = false) {
if (current_ == NULL) {
InstructionSequenceTest::VReg InstructionSequenceTest::Define(
TestOperand output_op) {
VReg vreg = NewReg();
- InstructionOperand* outputs[1]{ConvertOutputOp(vreg, output_op)};
+ InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)};
Emit(vreg.value_, kArchNop, 1, outputs);
return vreg;
}
int InstructionSequenceTest::Return(TestOperand input_op_0) {
block_returns_ = true;
- InstructionOperand* inputs[1]{ConvertInputOp(input_op_0)};
+ InstructionOperand inputs[1]{ConvertInputOp(input_op_0)};
return Emit(NewIndex(), kArchRet, 0, nullptr, 1, inputs);
}
int32_t imm) {
VReg vreg = NewReg();
sequence()->AddConstant(vreg.value_, Constant(imm));
- InstructionOperand* outputs[1]{ConstantOperand::Create(vreg.value_, zone())};
+ InstructionOperand outputs[1]{ConstantOperand(vreg.value_)};
Emit(vreg.value_, kArchNop, 1, outputs);
return vreg;
}
int InstructionSequenceTest::EmitI(size_t input_size, TestOperand* inputs) {
- InstructionOperand** mapped_inputs = ConvertInputs(input_size, inputs);
+ InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
return Emit(NewIndex(), kArchNop, 0, nullptr, input_size, mapped_inputs);
}
InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
TestOperand output_op, size_t input_size, TestOperand* inputs) {
VReg output_vreg = NewReg();
- InstructionOperand* outputs[1]{ConvertOutputOp(output_vreg, output_op)};
- InstructionOperand** mapped_inputs = ConvertInputs(input_size, inputs);
+ InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
+ InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
Emit(output_vreg.value_, kArchNop, 1, outputs, input_size, mapped_inputs);
return output_vreg;
}
InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
TestOperand output_op, size_t input_size, TestOperand* inputs) {
VReg output_vreg = NewReg();
- InstructionOperand* outputs[1]{ConvertOutputOp(output_vreg, output_op)};
- CHECK(UnallocatedOperand::cast(outputs[0])->HasFixedPolicy());
- InstructionOperand** mapped_inputs = ConvertInputs(input_size, inputs);
+ InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
+ CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy());
+ InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
Emit(output_vreg.value_, kArchCallCodeObject, 1, outputs, input_size,
mapped_inputs, 0, nullptr, true);
return output_vreg;
int InstructionSequenceTest::EmitBranch(TestOperand input_op) {
- InstructionOperand* inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
- ConvertInputOp(Imm()), ConvertInputOp(Imm())};
+ InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
+ ConvertInputOp(Imm()), ConvertInputOp(Imm())};
InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) |
FlagsConditionField::encode(kEqual);
auto instruction =
int InstructionSequenceTest::EmitJump() {
- InstructionOperand* inputs[1]{ConvertInputOp(Imm())};
+ InstructionOperand inputs[1]{ConvertInputOp(Imm())};
auto instruction =
NewInstruction(kArchJmp, 0, nullptr, 1, inputs)->MarkAsControl();
return AddInstruction(NewIndex(), instruction);
Instruction* InstructionSequenceTest::NewInstruction(
- InstructionCode code, size_t outputs_size, InstructionOperand** outputs,
- size_t inputs_size, InstructionOperand** inputs, size_t temps_size,
- InstructionOperand** temps) {
+ InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
+ size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
+ InstructionOperand* temps) {
CHECK(current_block_);
return Instruction::New(zone(), code, outputs_size, outputs, inputs_size,
inputs, temps_size, temps);
}
-InstructionOperand* InstructionSequenceTest::Unallocated(
+InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy) {
- return new (zone()) UnallocatedOperand(policy, op.vreg_.value_);
+ return UnallocatedOperand(policy, op.vreg_.value_);
}
-InstructionOperand* InstructionSequenceTest::Unallocated(
+InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy,
UnallocatedOperand::Lifetime lifetime) {
- return new (zone()) UnallocatedOperand(policy, lifetime, op.vreg_.value_);
+ return UnallocatedOperand(policy, lifetime, op.vreg_.value_);
}
-InstructionOperand* InstructionSequenceTest::Unallocated(
+InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy, int index) {
- return new (zone()) UnallocatedOperand(policy, index, op.vreg_.value_);
+ return UnallocatedOperand(policy, index, op.vreg_.value_);
}
-InstructionOperand* InstructionSequenceTest::Unallocated(
+InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::BasicPolicy policy, int index) {
- return new (zone()) UnallocatedOperand(policy, index, op.vreg_.value_);
+ return UnallocatedOperand(policy, index, op.vreg_.value_);
}
-InstructionOperand** InstructionSequenceTest::ConvertInputs(
+InstructionOperand* InstructionSequenceTest::ConvertInputs(
size_t input_size, TestOperand* inputs) {
- InstructionOperand** mapped_inputs =
- zone()->NewArray<InstructionOperand*>(static_cast<int>(input_size));
+ InstructionOperand* mapped_inputs =
+ zone()->NewArray<InstructionOperand>(static_cast<int>(input_size));
for (size_t i = 0; i < input_size; ++i) {
mapped_inputs[i] = ConvertInputOp(inputs[i]);
}
}
-InstructionOperand* InstructionSequenceTest::ConvertInputOp(TestOperand op) {
+InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
if (op.type_ == kImmediate) {
CHECK_EQ(op.vreg_.value_, kNoValue);
- return ImmediateOperand::Create(op.value_, zone());
+ return ImmediateOperand(op.value_);
}
CHECK_NE(op.vreg_.value_, kNoValue);
switch (op.type_) {
break;
}
CHECK(false);
- return NULL;
+ return InstructionOperand();
}
-InstructionOperand* InstructionSequenceTest::ConvertOutputOp(VReg vreg,
- TestOperand op) {
+InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
+ TestOperand op) {
CHECK_EQ(op.vreg_.value_, kNoValue);
op.vreg_ = vreg;
switch (op.type_) {
break;
}
CHECK(false);
- return NULL;
+ return InstructionOperand();
}
int InstructionSequenceTest::Emit(int instruction_index, InstructionCode code,
size_t outputs_size,
- InstructionOperand** outputs,
+ InstructionOperand* outputs,
size_t inputs_size,
- InstructionOperand** inputs,
- size_t temps_size, InstructionOperand** temps,
- bool is_call) {
+ InstructionOperand* inputs, size_t temps_size,
+ InstructionOperand* temps, bool is_call) {
auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size,
inputs, temps_size, temps);
if (is_call) instruction->MarkAsCall();
int EmitFallThrough();
int EmitJump();
Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
- InstructionOperand** outputs,
+ InstructionOperand* outputs,
size_t inputs_size = 0,
- InstructionOperand* *inputs = nullptr,
+ InstructionOperand* inputs = nullptr,
size_t temps_size = 0,
- InstructionOperand* *temps = nullptr);
- InstructionOperand* Unallocated(TestOperand op,
- UnallocatedOperand::ExtendedPolicy policy);
- InstructionOperand* Unallocated(TestOperand op,
- UnallocatedOperand::ExtendedPolicy policy,
- UnallocatedOperand::Lifetime lifetime);
- InstructionOperand* Unallocated(TestOperand op,
- UnallocatedOperand::ExtendedPolicy policy,
- int index);
- InstructionOperand* Unallocated(TestOperand op,
- UnallocatedOperand::BasicPolicy policy,
- int index);
- InstructionOperand** ConvertInputs(size_t input_size, TestOperand* inputs);
- InstructionOperand* ConvertInputOp(TestOperand op);
- InstructionOperand* ConvertOutputOp(VReg vreg, TestOperand op);
+ InstructionOperand* temps = nullptr);
+ InstructionOperand Unallocated(TestOperand op,
+ UnallocatedOperand::ExtendedPolicy policy);
+ InstructionOperand Unallocated(TestOperand op,
+ UnallocatedOperand::ExtendedPolicy policy,
+ UnallocatedOperand::Lifetime lifetime);
+ InstructionOperand Unallocated(TestOperand op,
+ UnallocatedOperand::ExtendedPolicy policy,
+ int index);
+ InstructionOperand Unallocated(TestOperand op,
+ UnallocatedOperand::BasicPolicy policy,
+ int index);
+ InstructionOperand* ConvertInputs(size_t input_size, TestOperand* inputs);
+ InstructionOperand ConvertInputOp(TestOperand op);
+ InstructionOperand ConvertOutputOp(VReg vreg, TestOperand op);
InstructionBlock* NewBlock();
void WireBlock(size_t block_offset, int jump_offset);
int Emit(int instruction_index, InstructionCode code, size_t outputs_size = 0,
- InstructionOperand* *outputs = nullptr, size_t inputs_size = 0,
- InstructionOperand* *inputs = nullptr, size_t temps_size = 0,
- InstructionOperand* *temps = nullptr, bool is_call = false);
+ InstructionOperand* outputs = nullptr, size_t inputs_size = 0,
+ InstructionOperand* inputs = nullptr, size_t temps_size = 0,
+ InstructionOperand* temps = nullptr, bool is_call = false);
int AddInstruction(int instruction_index, Instruction* instruction);