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:
chunyang.dai 2015-07-01 04:31:47 -07:00 committed by Commit bot
parent 68020ce546
commit 4ed8444e73
4 changed files with 62 additions and 13 deletions

View File

@ -385,6 +385,22 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
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:
AssembleArchJump(i.InputRpo(0));
break;
@ -1100,6 +1116,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ push(i.InputOperand(0));
}
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:
__ lea(esp, Operand(esp, -kFloatSize));
if (instr->InputAt(0)->IsDoubleStackSlot()) {

View File

@ -77,6 +77,7 @@ namespace compiler {
V(X87Push) \
V(X87PushFloat64) \
V(X87PushFloat32) \
V(X87Poke) \
V(X87StoreWriteBarrier) \
V(X87StackCheck)

View File

@ -814,14 +814,33 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// 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);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
InstructionOperand temps[] = {g.TempRegister()};
size_t const temp_count = arraysize(temps);
Emit(kArchPrepareCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount())),
0, nullptr, 0, nullptr, temp_count, temps);
// 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.
@ -839,18 +858,21 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
case CallDescriptor::kCallCodeObject: {
opcode = kArchCallCodeObject;
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
}
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction;
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
default:
UNREACHABLE();
return;
}
opcode |= MiscField::encode(flags);
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();

View File

@ -24,6 +24,7 @@ struct X87LinkageHelperTraits {
}
static Register CRegisterParameter(int i) { return no_reg; }
static int CRegisterParametersLength() { return 0; }
static int CStackBackingStoreLength() { return 0; }
};
typedef LinkageHelper<X87LinkageHelperTraits> LH;