[Liftoff] Allow f64 parameters and arguments
This allows liftoff compiled functions to receive f64 values as parameters and pass f64 values as arguments to called functions. R=titzer@chromium.org Bug: v8:6600 Change-Id: Ie7467b424ccdf1ec8b7f7625d9439ab4ea427022 Reviewed-on: https://chromium-review.googlesource.com/926105 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51414}
This commit is contained in:
parent
3b9d548c65
commit
a65e007623
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -684,15 +684,20 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
RegPairHalf half) {
|
||||
switch (src.loc()) {
|
||||
case VarState::kStack:
|
||||
DCHECK_NE(kWasmF64, src.type()); // TODO(clemensh): Implement this.
|
||||
push(liftoff::GetHalfStackSlot(2 * src_index +
|
||||
(half == kLowWord ? 0 : 1)));
|
||||
if (src.type() == kWasmF64) {
|
||||
DCHECK_EQ(kLowWord, half);
|
||||
push(liftoff::GetHalfStackSlot(2 * src_index + 1));
|
||||
}
|
||||
break;
|
||||
case VarState::kRegister:
|
||||
PushCallerFrameSlot(
|
||||
src.type() == kWasmI64
|
||||
? (half == kLowWord ? src.reg().low() : src.reg().high())
|
||||
: src.reg());
|
||||
if (src.type() == kWasmI64) {
|
||||
PushCallerFrameSlot(
|
||||
half == kLowWord ? src.reg().low() : src.reg().high(), kWasmI32);
|
||||
} else {
|
||||
PushCallerFrameSlot(src.reg(), src.type());
|
||||
}
|
||||
break;
|
||||
case VarState::KIntConst:
|
||||
// The high word is the sign extension of the low word.
|
||||
@ -702,12 +707,23 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
if (reg.is_gp()) {
|
||||
push(reg.gp());
|
||||
} else {
|
||||
sub(esp, Immediate(kPointerSize));
|
||||
movss(Operand(esp, 0), reg.fp());
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
switch (type) {
|
||||
case kWasmI32:
|
||||
push(reg.gp());
|
||||
break;
|
||||
case kWasmF32:
|
||||
sub(esp, Immediate(sizeof(float)));
|
||||
movss(Operand(esp, 0), reg.fp());
|
||||
break;
|
||||
case kWasmF64:
|
||||
sub(esp, Immediate(sizeof(double)));
|
||||
movsd(Operand(esp, 0), reg.fp());
|
||||
break;
|
||||
default:
|
||||
// Also kWasmI64 is unreachable, as it will always be pushed as two halfs.
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -544,7 +544,7 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
|
||||
kWasmIntPtr);
|
||||
*target = new_target.gp();
|
||||
} else {
|
||||
PushCallerFrameSlot(LiftoffRegister(*target));
|
||||
PushCallerFrameSlot(LiftoffRegister(*target), kWasmIntPtr);
|
||||
*target = no_reg;
|
||||
}
|
||||
}
|
||||
@ -594,8 +594,9 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src,
|
||||
ValueType type) {
|
||||
DCHECK_EQ(dst.reg_class(), src.reg_class());
|
||||
if (kNeedI64RegPair && dst.is_pair()) {
|
||||
if (dst.low() != src.low()) Move(dst.low_gp(), src.low_gp(), kWasmI32);
|
||||
if (dst.high() != src.high()) Move(dst.high_gp(), src.high_gp(), kWasmI32);
|
||||
// Use the {StackTransferRecipe} to move pairs, as the registers in the
|
||||
// pairs might overlap.
|
||||
StackTransferRecipe(this).MoveRegister(dst, src, type);
|
||||
} else if (dst.is_gp()) {
|
||||
Move(dst.gp(), src.gp(), type);
|
||||
} else {
|
||||
|
@ -401,7 +401,7 @@ class LiftoffAssembler : public TurboAssembler {
|
||||
// Push a value to the stack (will become a caller frame slot).
|
||||
inline void PushCallerFrameSlot(const VarState& src, uint32_t src_index,
|
||||
RegPairHalf half);
|
||||
inline void PushCallerFrameSlot(LiftoffRegister reg);
|
||||
inline void PushCallerFrameSlot(LiftoffRegister reg, ValueType type);
|
||||
inline void PushRegisters(LiftoffRegList);
|
||||
inline void PopRegisters(LiftoffRegList);
|
||||
|
||||
|
@ -78,6 +78,8 @@ compiler::CallDescriptor* GetLoweredCallDescriptor(
|
||||
|
||||
constexpr ValueType kTypesArr_ilf[] = {kWasmI32, kWasmI64, kWasmF32};
|
||||
constexpr Vector<const ValueType> kTypes_ilf = ArrayVector(kTypesArr_ilf);
|
||||
constexpr ValueType kTypesArr_ilfd[] = {kWasmI32, kWasmI64, kWasmF32, kWasmF64};
|
||||
constexpr Vector<const ValueType> kTypes_ilfd = ArrayVector(kTypesArr_ilfd);
|
||||
|
||||
class LiftoffCompiler {
|
||||
public:
|
||||
@ -284,7 +286,7 @@ class LiftoffCompiler {
|
||||
uint32_t num_params =
|
||||
static_cast<uint32_t>(decoder->sig_->parameter_count());
|
||||
for (uint32_t i = 0; i < __ num_locals(); ++i) {
|
||||
if (!CheckSupportedType(decoder, kTypes_ilf, __ local_type(i), "param"))
|
||||
if (!CheckSupportedType(decoder, kTypes_ilfd, __ local_type(i), "param"))
|
||||
return;
|
||||
}
|
||||
// Input 0 is the call target, the context is at 1.
|
||||
@ -316,13 +318,15 @@ class LiftoffCompiler {
|
||||
__ cache_state()->stack_state.emplace_back(kWasmI64, uint32_t{0});
|
||||
break;
|
||||
case kWasmF32:
|
||||
case kWasmF64:
|
||||
if (zero_double_reg.is_gp()) {
|
||||
// Note: This might spill one of the registers used to hold
|
||||
// parameters.
|
||||
zero_double_reg = __ GetUnusedRegister(kFpReg);
|
||||
__ LoadConstant(zero_double_reg, WasmValue(0.f));
|
||||
// Zero is represented by the bit pattern 0 for both f32 and f64.
|
||||
__ LoadConstant(zero_double_reg, WasmValue(0.));
|
||||
}
|
||||
__ PushRegister(kWasmF32, zero_double_reg);
|
||||
__ PushRegister(type, zero_double_reg);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
@ -1011,7 +1015,8 @@ class LiftoffCompiler {
|
||||
LiftoffAssembler::kWasmIntPtr);
|
||||
} else {
|
||||
DCHECK(param_loc.IsCallerFrameSlot());
|
||||
__ PushCallerFrameSlot(LiftoffRegister(args[0]));
|
||||
__ PushCallerFrameSlot(LiftoffRegister(args[0]),
|
||||
LiftoffAssembler::kWasmIntPtr);
|
||||
}
|
||||
|
||||
// Allocate the codegen zone if not done before.
|
||||
@ -1099,7 +1104,7 @@ class LiftoffCompiler {
|
||||
if (operand.sig->return_count() > 1)
|
||||
return unsupported(decoder, "multi-return");
|
||||
if (operand.sig->return_count() == 1 &&
|
||||
!CheckSupportedType(decoder, kTypes_ilf, operand.sig->GetReturn(0),
|
||||
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
|
||||
"return"))
|
||||
return;
|
||||
|
||||
@ -1141,7 +1146,7 @@ class LiftoffCompiler {
|
||||
if (operand.sig->return_count() > 1)
|
||||
return unsupported(decoder, "multi-return");
|
||||
if (operand.sig->return_count() == 1 &&
|
||||
!CheckSupportedType(decoder, kTypes_ilf, operand.sig->GetReturn(0),
|
||||
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
|
||||
"return"))
|
||||
return;
|
||||
|
||||
|
@ -261,7 +261,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
BAILOUT("PushCallerFrameSlot");
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
BAILOUT("PushCallerFrameSlot reg");
|
||||
}
|
||||
|
||||
|
@ -620,7 +620,7 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
pushq(liftoff::GetStackSlot(src_index));
|
||||
break;
|
||||
case VarState::kRegister:
|
||||
PushCallerFrameSlot(src.reg());
|
||||
PushCallerFrameSlot(src.reg(), src.type());
|
||||
break;
|
||||
case VarState::KIntConst:
|
||||
pushq(Immediate(src.i32_const()));
|
||||
@ -628,12 +628,23 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
||||
if (reg.is_gp()) {
|
||||
pushq(reg.gp());
|
||||
} else {
|
||||
subp(rsp, Immediate(kPointerSize));
|
||||
Movsd(Operand(rsp, 0), reg.fp());
|
||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||
ValueType type) {
|
||||
switch (type) {
|
||||
case kWasmI32:
|
||||
case kWasmI64:
|
||||
pushq(reg.gp());
|
||||
break;
|
||||
case kWasmF32:
|
||||
subp(rsp, Immediate(kPointerSize));
|
||||
Movss(Operand(rsp, 0), reg.fp());
|
||||
break;
|
||||
case kWasmF64:
|
||||
subp(rsp, Immediate(kPointerSize));
|
||||
Movsd(Operand(rsp, 0), reg.fp());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user