[Liftoff][mips] Add support for C fallbacks in Liftoff

Implement methods for calling C functions in Liftoff on MIPS and
MIPS64.

Bug: v8:6600
Change-Id: I43f43dc3d1e13f15dc8359ce7a8a8b2273f0ff62
Reviewed-on: https://chromium-review.googlesource.com/966282
Reviewed-by: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Commit-Queue: Sreten Kovacevic <sreten.kovacevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#51996}
This commit is contained in:
sreten.kovacevic 2018-03-16 12:48:33 +01:00 committed by Commit Bot
parent d852096f15
commit c123114619
2 changed files with 73 additions and 12 deletions

View File

@ -33,6 +33,11 @@ inline MemOperand GetHalfStackSlot(uint32_t half_index) {
inline MemOperand GetContextOperand() { return MemOperand(fp, -16); }
// Use this register to store the address of the last argument pushed on the
// stack for a call to C. This register must be callee saved according to the c
// calling convention.
static constexpr Register kCCallLastArgAddrReg = s1;
inline void Load(LiftoffAssembler* assm, LiftoffRegister dst, MemOperand src,
ValueType type) {
switch (type) {
@ -630,30 +635,57 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
void LiftoffAssembler::PrepareCCall(wasm::FunctionSig* sig,
const LiftoffRegister* args,
ValueType out_argument_type) {
BAILOUT("PrepareCCall");
int pushed_bytes = 0;
for (ValueType param_type : sig->parameters()) {
pushed_bytes += RoundUp<kPointerSize>(WasmOpcodes::MemSize(param_type));
liftoff::push(this, *args++, param_type);
}
if (out_argument_type != kWasmStmt) {
int size = RoundUp<kPointerSize>(WasmOpcodes::MemSize(out_argument_type));
addiu(sp, sp, -size);
pushed_bytes += size;
}
// Save the original sp (before the first push), such that we can later
// compute pointers to the pushed values. Do this only *after* pushing the
// values, because {kCCallLastArgAddrReg} might collide with an arg register.
addiu(liftoff::kCCallLastArgAddrReg, sp, pushed_bytes);
constexpr Register kScratch = at;
static_assert(kScratch != liftoff::kCCallLastArgAddrReg, "collision");
int num_c_call_arguments = static_cast<int>(sig->parameter_count()) +
(out_argument_type != kWasmStmt);
PrepareCallCFunction(num_c_call_arguments, kScratch);
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, int param_byte_offset,
ValueType type) {
BAILOUT("SetCCallRegParamAddr");
// Check that we don't accidentally override kCCallLastArgAddrReg.
DCHECK_NE(liftoff::kCCallLastArgAddrReg, dst);
addiu(dst, liftoff::kCCallLastArgAddrReg, -param_byte_offset);
}
void LiftoffAssembler::SetCCallStackParamAddr(int stack_param_idx,
int param_byte_offset,
ValueType type) {
BAILOUT("SetCCallStackParamAddr");
static constexpr Register kScratch = at;
SetCCallRegParamAddr(kScratch, param_byte_offset, type);
sw(kScratch, MemOperand(sp, stack_param_idx * kPointerSize));
}
void LiftoffAssembler::LoadCCallOutArgument(LiftoffRegister dst, ValueType type,
int param_byte_offset) {
BAILOUT("LoadCCallOutArgument");
// Check that we don't accidentally override kCCallLastArgAddrReg.
DCHECK_NE(LiftoffRegister(liftoff::kCCallLastArgAddrReg), dst);
MemOperand src(liftoff::kCCallLastArgAddrReg, -param_byte_offset);
liftoff::Load(this, dst, src, type);
}
void LiftoffAssembler::CallC(ExternalReference ext_ref, uint32_t num_params) {
BAILOUT("CallC");
CallCFunction(ext_ref, static_cast<int>(num_params));
}
void LiftoffAssembler::FinishCCall() { BAILOUT("FinishCCall"); }
void LiftoffAssembler::FinishCCall() {
TurboAssembler::Move(sp, liftoff::kCCallLastArgAddrReg);
}
void LiftoffAssembler::CallNativeWasmCode(Address addr) {
Call(addr, RelocInfo::WASM_CALL);

View File

@ -28,6 +28,11 @@ inline MemOperand GetStackSlot(uint32_t index) {
inline MemOperand GetContextOperand() { return MemOperand(fp, -16); }
// Use this register to store the address of the last argument pushed on the
// stack for a call to C. This register must be callee saved according to the c
// calling convention.
static constexpr Register kCCallLastArgAddrReg = s1;
inline void Load(LiftoffAssembler* assm, LiftoffRegister dst, MemOperand src,
ValueType type) {
switch (type) {
@ -562,30 +567,54 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
void LiftoffAssembler::PrepareCCall(wasm::FunctionSig* sig,
const LiftoffRegister* args,
ValueType out_argument_type) {
BAILOUT("PrepareCCall");
for (ValueType param_type : sig->parameters()) {
liftoff::push(this, *args++, param_type);
}
if (out_argument_type != kWasmStmt) {
daddiu(sp, sp, -kPointerSize);
}
// Save the original sp (before the first push), such that we can later
// compute pointers to the pushed values. Do this only *after* pushing the
// values, because {kCCallLastArgAddrReg} might collide with an arg register.
int num_c_call_arguments = static_cast<int>(sig->parameter_count()) +
(out_argument_type != kWasmStmt);
int pushed_bytes = kPointerSize * num_c_call_arguments;
daddiu(liftoff::kCCallLastArgAddrReg, sp, pushed_bytes);
constexpr Register kScratch = at;
static_assert(kScratch != liftoff::kCCallLastArgAddrReg, "collision");
PrepareCallCFunction(num_c_call_arguments, kScratch);
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, int param_byte_offset,
ValueType type) {
BAILOUT("SetCCallRegParamAddr");
// Check that we don't accidentally override kCCallLastArgAddrReg.
DCHECK_NE(liftoff::kCCallLastArgAddrReg, dst);
daddiu(dst, liftoff::kCCallLastArgAddrReg, -param_byte_offset);
}
void LiftoffAssembler::SetCCallStackParamAddr(int stack_param_idx,
int param_byte_offset,
ValueType type) {
BAILOUT("SetCCallStackParamAddr");
static constexpr Register kScratch = at;
SetCCallRegParamAddr(kScratch, param_byte_offset, type);
sd(kScratch, MemOperand(sp, stack_param_idx * kPointerSize));
}
void LiftoffAssembler::LoadCCallOutArgument(LiftoffRegister dst, ValueType type,
int param_byte_offset) {
BAILOUT("LoadCCallOutArgument");
// Check that we don't accidentally override kCCallLastArgAddrReg.
DCHECK_NE(LiftoffRegister(liftoff::kCCallLastArgAddrReg), dst);
MemOperand src(liftoff::kCCallLastArgAddrReg, -param_byte_offset);
liftoff::Load(this, dst, src, type);
}
void LiftoffAssembler::CallC(ExternalReference ext_ref, uint32_t num_params) {
BAILOUT("CallC");
CallCFunction(ext_ref, static_cast<int>(num_params));
}
void LiftoffAssembler::FinishCCall() { BAILOUT("FinishCCall"); }
void LiftoffAssembler::FinishCCall() {
TurboAssembler::Move(sp, liftoff::kCCallLastArgAddrReg);
}
void LiftoffAssembler::CallNativeWasmCode(Address addr) {
Call(addr, RelocInfo::WASM_CALL);