X87: [turbofan] Add basic support for calling to (a subset of) C functions.
port a58ba8d801
(r29279).
original commit message:
This introduces some initial building blocks for calling out to
C/C++ functions directly from TurboFan generated code objects.
BUG=
Review URL: https://codereview.chromium.org/1214903007
Cr-Commit-Position: refs/heads/master@{#29408}
This commit is contained in:
parent
68020ce546
commit
4ed8444e73
@ -385,6 +385,22 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
|
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kArchPrepareCallCFunction: {
|
||||||
|
int const num_parameters = MiscField::decode(instr->opcode());
|
||||||
|
__ PrepareCallCFunction(num_parameters, i.TempRegister(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kArchCallCFunction: {
|
||||||
|
int const num_parameters = MiscField::decode(instr->opcode());
|
||||||
|
if (HasImmediateInput(instr, 0)) {
|
||||||
|
ExternalReference ref = i.InputExternalReference(0);
|
||||||
|
__ CallCFunction(ref, num_parameters);
|
||||||
|
} else {
|
||||||
|
Register func = i.InputRegister(0);
|
||||||
|
__ CallCFunction(func, num_parameters);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kArchJmp:
|
case kArchJmp:
|
||||||
AssembleArchJump(i.InputRpo(0));
|
AssembleArchJump(i.InputRpo(0));
|
||||||
break;
|
break;
|
||||||
@ -1100,6 +1116,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
__ push(i.InputOperand(0));
|
__ push(i.InputOperand(0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case kX87Poke: {
|
||||||
|
int const slot = MiscField::decode(instr->opcode());
|
||||||
|
if (HasImmediateInput(instr, 0)) {
|
||||||
|
__ mov(Operand(esp, slot * kPointerSize), i.InputImmediate(0));
|
||||||
|
} else {
|
||||||
|
__ mov(Operand(esp, slot * kPointerSize), i.InputRegister(0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kX87PushFloat32:
|
case kX87PushFloat32:
|
||||||
__ lea(esp, Operand(esp, -kFloatSize));
|
__ lea(esp, Operand(esp, -kFloatSize));
|
||||||
if (instr->InputAt(0)->IsDoubleStackSlot()) {
|
if (instr->InputAt(0)->IsDoubleStackSlot()) {
|
||||||
|
@ -77,6 +77,7 @@ namespace compiler {
|
|||||||
V(X87Push) \
|
V(X87Push) \
|
||||||
V(X87PushFloat64) \
|
V(X87PushFloat64) \
|
||||||
V(X87PushFloat32) \
|
V(X87PushFloat32) \
|
||||||
|
V(X87Poke) \
|
||||||
V(X87StoreWriteBarrier) \
|
V(X87StoreWriteBarrier) \
|
||||||
V(X87StackCheck)
|
V(X87StackCheck)
|
||||||
|
|
||||||
|
@ -814,14 +814,33 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
|
|||||||
// Compute InstructionOperands for inputs and outputs.
|
// Compute InstructionOperands for inputs and outputs.
|
||||||
InitializeCallBuffer(node, &buffer, true, true);
|
InitializeCallBuffer(node, &buffer, true, true);
|
||||||
|
|
||||||
// Push any stack arguments.
|
// Prepare for C function call.
|
||||||
for (Node* node : base::Reversed(buffer.pushed_nodes)) {
|
if (descriptor->IsCFunctionCall()) {
|
||||||
// TODO(titzer): handle pushing double parameters.
|
InstructionOperand temps[] = {g.TempRegister()};
|
||||||
InstructionOperand value =
|
size_t const temp_count = arraysize(temps);
|
||||||
g.CanBeImmediate(node)
|
Emit(kArchPrepareCallCFunction |
|
||||||
? g.UseImmediate(node)
|
MiscField::encode(static_cast<int>(descriptor->CParameterCount())),
|
||||||
: IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node);
|
0, nullptr, 0, nullptr, temp_count, temps);
|
||||||
Emit(kX87Push, g.NoOutput(), value);
|
|
||||||
|
// Poke any stack arguments.
|
||||||
|
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
|
||||||
|
if (Node* node = buffer.pushed_nodes[n]) {
|
||||||
|
int const slot = static_cast<int>(n);
|
||||||
|
InstructionOperand value =
|
||||||
|
g.CanBeImmediate(node) ? g.UseImmediate(node) : g.UseRegister(node);
|
||||||
|
Emit(kX87Poke | MiscField::encode(slot), g.NoOutput(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Push any stack arguments.
|
||||||
|
for (Node* node : base::Reversed(buffer.pushed_nodes)) {
|
||||||
|
// TODO(titzer): handle pushing double parameters.
|
||||||
|
InstructionOperand value =
|
||||||
|
g.CanBeImmediate(node)
|
||||||
|
? g.UseImmediate(node)
|
||||||
|
: IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node);
|
||||||
|
Emit(kX87Push, g.NoOutput(), value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass label of exception handler block.
|
// Pass label of exception handler block.
|
||||||
@ -839,18 +858,21 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
|
|||||||
// Select the appropriate opcode based on the call type.
|
// Select the appropriate opcode based on the call type.
|
||||||
InstructionCode opcode;
|
InstructionCode opcode;
|
||||||
switch (descriptor->kind()) {
|
switch (descriptor->kind()) {
|
||||||
case CallDescriptor::kCallCodeObject: {
|
case CallDescriptor::kCallAddress:
|
||||||
opcode = kArchCallCodeObject;
|
opcode =
|
||||||
|
kArchCallCFunction |
|
||||||
|
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
|
||||||
|
break;
|
||||||
|
case CallDescriptor::kCallCodeObject:
|
||||||
|
opcode = kArchCallCodeObject | MiscField::encode(flags);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CallDescriptor::kCallJSFunction:
|
case CallDescriptor::kCallJSFunction:
|
||||||
opcode = kArchCallJSFunction;
|
opcode = kArchCallJSFunction | MiscField::encode(flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
opcode |= MiscField::encode(flags);
|
|
||||||
|
|
||||||
// Emit the call instruction.
|
// Emit the call instruction.
|
||||||
size_t const output_count = buffer.outputs.size();
|
size_t const output_count = buffer.outputs.size();
|
||||||
|
@ -24,6 +24,7 @@ struct X87LinkageHelperTraits {
|
|||||||
}
|
}
|
||||||
static Register CRegisterParameter(int i) { return no_reg; }
|
static Register CRegisterParameter(int i) { return no_reg; }
|
||||||
static int CRegisterParametersLength() { return 0; }
|
static int CRegisterParametersLength() { return 0; }
|
||||||
|
static int CStackBackingStoreLength() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef LinkageHelper<X87LinkageHelperTraits> LH;
|
typedef LinkageHelper<X87LinkageHelperTraits> LH;
|
||||||
|
Loading…
Reference in New Issue
Block a user