Commit 7b785f33 authored by Milad Fa's avatar Milad Fa Committed by V8 LUCI CQ

PPC: Fix offset calculation to CallCFunction return

Currently we are calculating the offset manually. This method
uses code patching to re-emit the instruction with correct offset
when the value is available.

Change-Id: Ie68580398df92ed2ab57c3972f408cfde8e60432
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3264746
Commit-Queue: Milad Fa <mfarazma@redhat.com>
Reviewed-by: 's avatarJunliang Yan <junyan@redhat.com>
Cr-Commit-Position: refs/heads/main@{#77745}
parent b9ddcbc8
......@@ -1322,6 +1322,15 @@ void Assembler::bitwise_add32(Register dst, Register src, int32_t value) {
}
}
void Assembler::patch_wasm_cpi_return_address(Register dst, int pc_offset,
int return_address_offset) {
DCHECK(is_int16(return_address_offset));
Assembler patching_assembler(
AssemblerOptions{},
ExternalAssemblerBuffer(buffer_start_ + pc_offset, kInstrSize + kGap));
patching_assembler.addi(dst, dst, Operand(return_address_offset));
}
void Assembler::mov_label_offset(Register dst, Label* label) {
int position = link(label);
if (label->is_bound()) {
......
......@@ -968,6 +968,10 @@ class Assembler : public AssemblerBase {
void bitwise_mov32(Register dst, int32_t value);
void bitwise_add32(Register dst, Register src, int32_t value);
// Patch the offset to the return address after CallCFunction.
void patch_wasm_cpi_return_address(Register dst, int pc_offset,
int return_address_offset);
// Load the position of the label relative to the generated code object
// pointer in a register.
void mov_label_offset(Register dst, Label* label);
......
......@@ -904,44 +904,28 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
int const fp_param_field = FPParamField::decode(instr->opcode());
int num_fp_parameters = fp_param_field;
bool has_function_descriptor = false;
int offset = 19 * kInstrSize;
if (instr->InputAt(0)->IsImmediate() &&
!FLAG_enable_embedded_constant_pool) {
// If loading an immediate without constant pool then 4 instructions get
// emitted instead of a single load (which makes it 3 extra).
offset = 22 * kInstrSize;
}
if (!instr->InputAt(0)->IsImmediate() && !ABI_CALL_VIA_IP) {
// On Linux and Sim, there will be an extra
// instruction to pass the input using the `ip` register. This
// instruction gets emitted under `CallCFunction` or
// `CallCFunctionHelper` depending on the type of the input (immediate
// or register). This extra move is only emitted on AIX if the input is
// an immediate and not a register.
offset -= kInstrSize;
}
#if ABI_USES_FUNCTION_DESCRIPTORS
// AIX/PPC64BE Linux uses a function descriptor
int kNumFPParametersMask = kHasFunctionDescriptorBitMask - 1;
num_fp_parameters = kNumFPParametersMask & fp_param_field;
has_function_descriptor =
(fp_param_field & kHasFunctionDescriptorBitMask) != 0;
// AIX may emit 2 extra Load instructions under CallCFunctionHelper
// due to having function descriptor.
if (has_function_descriptor) {
offset += 2 * kInstrSize;
}
#endif
#if V8_ENABLE_WEBASSEMBLY
Label start_call;
int start_pc_offset = 0;
bool isWasmCapiFunction =
linkage()->GetIncomingDescriptor()->IsWasmCapiFunction();
if (isWasmCapiFunction) {
__ mflr(r0);
__ LoadPC(kScratchReg);
__ bind(&start_call);
__ addi(kScratchReg, kScratchReg, Operand(offset));
start_pc_offset = __ pc_offset();
// We are going to patch this instruction after emitting
// CallCFunction, using a zero offset here as placeholder for now.
// patch_wasm_cpi_return_address assumes `addi` is used here to
// add the offset to pc.
__ addi(kScratchReg, kScratchReg, Operand::Zero());
__ StoreU64(kScratchReg,
MemOperand(fp, WasmExitFrameConstants::kCallingPCOffset));
__ mtlr(r0);
......@@ -956,21 +940,17 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ 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
// offset is counted from where we are binding to the label and ends at
// this spot. If failed, replace it with the correct offset suggested.
// More info on f5ab7d3.
#if V8_ENABLE_WEBASSEMBLY
if (isWasmCapiFunction) {
// The offset calculated is from pc returned by LoadPC above, until this
// location.
int offset_since_start_call = __ SizeOfCodeGeneratedSince(&start_call);
// Here we are going to patch the `addi` instruction above to use the
// correct offset.
// LoadPC emits two instructions and pc is the address of its
// second emitted instruction. `start_call` is binding to the address
// right after the above retrieved pc, therefore there is one less
// instruction to count when summing the total size of generated code.
int generated_size = offset - kInstrSize;
CHECK_EQ(generated_size, __ SizeOfCodeGeneratedSince(&start_call));
// second emitted instruction therefore there is one more instruction to
// count.
offset_since_start_call += kInstrSize;
__ patch_wasm_cpi_return_address(kScratchReg, start_pc_offset,
offset_since_start_call);
RecordSafepoint(instr->reference_map());
}
#endif // V8_ENABLE_WEBASSEMBLY
......
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