Commit 3685fd86 authored by Milad Fa's avatar Milad Fa Committed by V8 LUCI CQ

PPC/s390: [fastcall] Enable float support

Port 098f31f4

Original Commit Message:

    This CL adds support for handling calls to C functions with arbitrary
    signatures on native arm64. It introduces a new ExternalReference type
    FAST_C_CALL.

    The CL also splits the 10 bits used by kArchCallCFunction instruction to
    store the total number of parameters into two 5-bit values, representing
    the number of general purpose and floating point parameters.

    Design doc:
    https://docs.google.com/document/d/1ZxOF3GSyNmtU0C0YJvrsydPJj35W_tTJZymeXwfDxoI/edit

    This CL is partially based on the previous attempt:
    https://chromium-review.googlesource.com/c/v8/v8/+/2343072

R=mslekova@chromium.org, joransiu@ca.ibm.com, junyan@redhat.com, midawson@redhat.com
BUG=
LOG=N

Change-Id: I3da5a9ef01f8de050a377e120ffcfbef6f2d31b5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3198748Reviewed-by: 's avatarJunliang Yan <junyan@redhat.com>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Milad Fa <mfarazma@redhat.com>
Cr-Commit-Position: refs/heads/main@{#77203}
parent ed7e3de9
......@@ -64,7 +64,7 @@ constexpr size_t kMaxPCRelativeCodeRangeInMB = 0;
// Used to encode a boolean value when emitting 32 bit
// opcodes which will indicate the presence of function descriptors
constexpr int kHasFunctionDescriptorBitShift = 9;
constexpr int kHasFunctionDescriptorBitShift = 4;
constexpr int kHasFunctionDescriptorBitMask = 1
<< kHasFunctionDescriptorBitShift;
......
......@@ -2921,8 +2921,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
#if ABI_USES_FUNCTION_DESCRIPTORS
// Highest fp_param_count bit is used on AIX to indicate if a CFunction
// call has function descriptor or not.
STATIC_ASSERT(ParamField::kSize + FPParamField::kSize ==
kHasFunctionDescriptorBitShift + 1);
STATIC_ASSERT(FPParamField::kSize == kHasFunctionDescriptorBitShift + 1);
if (!call_descriptor->NoFunctionDescriptor()) {
fp_param_count |= 1 << kHasFunctionDescriptorBitShift;
}
......
......@@ -854,8 +854,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg);
int const num_gp_parameters = ParamField::decode(instr->opcode());
int const num_fp_parameters = FPParamField::decode(instr->opcode());
__ PrepareCallCFunction(num_gp_parameters + num_fp_parameters,
kScratchReg);
// Frame alignment requires using FP-relative frame addressing.
frame_access_state()->SetFrameAccessToFP();
break;
......@@ -898,8 +900,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif
break;
case kArchCallCFunction: {
int misc_field = MiscField::decode(instr->opcode());
int num_parameters = misc_field;
int const num_gp_parameters = ParamField::decode(instr->opcode());
int const fp_param_field = FPParamField::decode(instr->opcode());
int num_fp_parameters = fp_param_field;
bool has_function_descriptor = false;
int offset = 20 * kInstrSize;
......@@ -920,10 +923,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
#if ABI_USES_FUNCTION_DESCRIPTORS
// AIX/PPC64BE Linux uses a function descriptor
int kNumParametersMask = kHasFunctionDescriptorBitMask - 1;
num_parameters = kNumParametersMask & misc_field;
int kNumFPParametersMask = kHasFunctionDescriptorBitMask - 1;
num_fp_parameters = kNumFPParametersMask & fp_param_field;
has_function_descriptor =
(misc_field & kHasFunctionDescriptorBitMask) != 0;
(fp_param_field & kHasFunctionDescriptorBitMask) != 0;
// AIX may emit 2 extra Load instructions under CallCFunctionHelper
// due to having function descriptor.
if (has_function_descriptor) {
......@@ -946,10 +949,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif // V8_ENABLE_WEBASSEMBLY
if (instr->InputAt(0)->IsImmediate()) {
ExternalReference ref = i.InputExternalReference(0);
__ CallCFunction(ref, num_parameters, has_function_descriptor);
__ CallCFunction(ref, num_gp_parameters, num_fp_parameters,
has_function_descriptor);
} else {
Register func = i.InputRegister(0);
__ CallCFunction(func, num_parameters, has_function_descriptor);
__ CallCFunction(func, num_gp_parameters, num_fp_parameters,
has_function_descriptor);
}
// TODO(miladfar): In the above block, kScratchReg must be populated with
// the strictly-correct PC, which is the return address at this spot. The
......
......@@ -1174,8 +1174,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg);
int const num_gp_parameters = ParamField::decode(instr->opcode());
int const num_fp_parameters = FPParamField::decode(instr->opcode());
__ PrepareCallCFunction(num_gp_parameters + num_fp_parameters,
kScratchReg);
// Frame alignment requires using FP-relative frame addressing.
frame_access_state()->SetFrameAccessToFP();
break;
......@@ -1211,7 +1213,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
AssemblePrepareTailCall();
break;
case kArchCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode());
int const num_gp_parameters = ParamField::decode(instr->opcode());
int const num_fp_parameters = FPParamField::decode(instr->opcode());
Label return_location;
// Put the return address in a stack slot.
#if V8_ENABLE_WEBASSEMBLY
......@@ -1224,10 +1227,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif // V8_ENABLE_WEBASSEMBLY
if (instr->InputAt(0)->IsImmediate()) {
ExternalReference ref = i.InputExternalReference(0);
__ CallCFunction(ref, num_parameters);
__ CallCFunction(ref, num_gp_parameters, num_fp_parameters);
} else {
Register func = i.InputRegister(0);
__ CallCFunction(func, num_parameters);
__ CallCFunction(func, num_gp_parameters, num_fp_parameters);
}
__ bind(&return_location);
#if V8_ENABLE_WEBASSEMBLY
......
......@@ -1193,7 +1193,18 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
set_register(r3, result_buffer);
}
} else {
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
// FAST_C_CALL is temporarily handled here as well, because we lack
// proper support for direct C calls with FP params in the simulator.
// The generic BUILTIN_CALL path assumes all parameters are passed in
// the GP registers, thus supporting calling the slow callback without
// crashing. The reason for that is that in the mjsunit tests we check
// the `fast_c_api.supports_fp_params` (which is false on
// non-simulator builds for arm/arm64), thus we expect that the slow
// path will be called. And since the slow path passes the arguments
// as a `const FunctionCallbackInfo<Value>&` (which is a GP argument),
// the call is made correctly.
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
redirection->type() == ExternalReference::FAST_C_CALL);
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
intptr_t result = target(arg[0], arg[1], arg[2], arg[3], arg[4],
......
......@@ -2207,7 +2207,18 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
set_register(r2, result_buffer);
}
} else {
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
// FAST_C_CALL is temporarily handled here as well, because we lack
// proper support for direct C calls with FP params in the simulator.
// The generic BUILTIN_CALL path assumes all parameters are passed in
// the GP registers, thus supporting calling the slow callback without
// crashing. The reason for that is that in the mjsunit tests we check
// the `fast_c_api.supports_fp_params` (which is false on
// non-simulator builds for arm/arm64), thus we expect that the slow
// path will be called. And since the slow path passes the arguments
// as a `const FunctionCallbackInfo<Value>&` (which is a GP argument),
// the call is made correctly.
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
redirection->type() == ExternalReference::FAST_C_CALL);
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
intptr_t result = target(arg[0], arg[1], arg[2], arg[3], arg[4],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment