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)); __ 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()) {

View File

@ -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)

View File

@ -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();

View File

@ -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;