[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");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
BAILOUT("PushCallerFrameSlot");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,15 +684,20 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
RegPairHalf half) {
|
RegPairHalf half) {
|
||||||
switch (src.loc()) {
|
switch (src.loc()) {
|
||||||
case VarState::kStack:
|
case VarState::kStack:
|
||||||
DCHECK_NE(kWasmF64, src.type()); // TODO(clemensh): Implement this.
|
|
||||||
push(liftoff::GetHalfStackSlot(2 * src_index +
|
push(liftoff::GetHalfStackSlot(2 * src_index +
|
||||||
(half == kLowWord ? 0 : 1)));
|
(half == kLowWord ? 0 : 1)));
|
||||||
|
if (src.type() == kWasmF64) {
|
||||||
|
DCHECK_EQ(kLowWord, half);
|
||||||
|
push(liftoff::GetHalfStackSlot(2 * src_index + 1));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VarState::kRegister:
|
case VarState::kRegister:
|
||||||
PushCallerFrameSlot(
|
if (src.type() == kWasmI64) {
|
||||||
src.type() == kWasmI64
|
PushCallerFrameSlot(
|
||||||
? (half == kLowWord ? src.reg().low() : src.reg().high())
|
half == kLowWord ? src.reg().low() : src.reg().high(), kWasmI32);
|
||||||
: src.reg());
|
} else {
|
||||||
|
PushCallerFrameSlot(src.reg(), src.type());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VarState::KIntConst:
|
case VarState::KIntConst:
|
||||||
// The high word is the sign extension of the low word.
|
// 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) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
if (reg.is_gp()) {
|
ValueType type) {
|
||||||
push(reg.gp());
|
switch (type) {
|
||||||
} else {
|
case kWasmI32:
|
||||||
sub(esp, Immediate(kPointerSize));
|
push(reg.gp());
|
||||||
movss(Operand(esp, 0), reg.fp());
|
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);
|
kWasmIntPtr);
|
||||||
*target = new_target.gp();
|
*target = new_target.gp();
|
||||||
} else {
|
} else {
|
||||||
PushCallerFrameSlot(LiftoffRegister(*target));
|
PushCallerFrameSlot(LiftoffRegister(*target), kWasmIntPtr);
|
||||||
*target = no_reg;
|
*target = no_reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,8 +594,9 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src,
|
|||||||
ValueType type) {
|
ValueType type) {
|
||||||
DCHECK_EQ(dst.reg_class(), src.reg_class());
|
DCHECK_EQ(dst.reg_class(), src.reg_class());
|
||||||
if (kNeedI64RegPair && dst.is_pair()) {
|
if (kNeedI64RegPair && dst.is_pair()) {
|
||||||
if (dst.low() != src.low()) Move(dst.low_gp(), src.low_gp(), kWasmI32);
|
// Use the {StackTransferRecipe} to move pairs, as the registers in the
|
||||||
if (dst.high() != src.high()) Move(dst.high_gp(), src.high_gp(), kWasmI32);
|
// pairs might overlap.
|
||||||
|
StackTransferRecipe(this).MoveRegister(dst, src, type);
|
||||||
} else if (dst.is_gp()) {
|
} else if (dst.is_gp()) {
|
||||||
Move(dst.gp(), src.gp(), type);
|
Move(dst.gp(), src.gp(), type);
|
||||||
} else {
|
} else {
|
||||||
|
@ -401,7 +401,7 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
// Push a value to the stack (will become a caller frame slot).
|
// Push a value to the stack (will become a caller frame slot).
|
||||||
inline void PushCallerFrameSlot(const VarState& src, uint32_t src_index,
|
inline void PushCallerFrameSlot(const VarState& src, uint32_t src_index,
|
||||||
RegPairHalf half);
|
RegPairHalf half);
|
||||||
inline void PushCallerFrameSlot(LiftoffRegister reg);
|
inline void PushCallerFrameSlot(LiftoffRegister reg, ValueType type);
|
||||||
inline void PushRegisters(LiftoffRegList);
|
inline void PushRegisters(LiftoffRegList);
|
||||||
inline void PopRegisters(LiftoffRegList);
|
inline void PopRegisters(LiftoffRegList);
|
||||||
|
|
||||||
|
@ -78,6 +78,8 @@ compiler::CallDescriptor* GetLoweredCallDescriptor(
|
|||||||
|
|
||||||
constexpr ValueType kTypesArr_ilf[] = {kWasmI32, kWasmI64, kWasmF32};
|
constexpr ValueType kTypesArr_ilf[] = {kWasmI32, kWasmI64, kWasmF32};
|
||||||
constexpr Vector<const ValueType> kTypes_ilf = ArrayVector(kTypesArr_ilf);
|
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 {
|
class LiftoffCompiler {
|
||||||
public:
|
public:
|
||||||
@ -284,7 +286,7 @@ class LiftoffCompiler {
|
|||||||
uint32_t num_params =
|
uint32_t num_params =
|
||||||
static_cast<uint32_t>(decoder->sig_->parameter_count());
|
static_cast<uint32_t>(decoder->sig_->parameter_count());
|
||||||
for (uint32_t i = 0; i < __ num_locals(); ++i) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// Input 0 is the call target, the context is at 1.
|
// 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});
|
__ cache_state()->stack_state.emplace_back(kWasmI64, uint32_t{0});
|
||||||
break;
|
break;
|
||||||
case kWasmF32:
|
case kWasmF32:
|
||||||
|
case kWasmF64:
|
||||||
if (zero_double_reg.is_gp()) {
|
if (zero_double_reg.is_gp()) {
|
||||||
// Note: This might spill one of the registers used to hold
|
// Note: This might spill one of the registers used to hold
|
||||||
// parameters.
|
// parameters.
|
||||||
zero_double_reg = __ GetUnusedRegister(kFpReg);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
@ -1011,7 +1015,8 @@ class LiftoffCompiler {
|
|||||||
LiftoffAssembler::kWasmIntPtr);
|
LiftoffAssembler::kWasmIntPtr);
|
||||||
} else {
|
} else {
|
||||||
DCHECK(param_loc.IsCallerFrameSlot());
|
DCHECK(param_loc.IsCallerFrameSlot());
|
||||||
__ PushCallerFrameSlot(LiftoffRegister(args[0]));
|
__ PushCallerFrameSlot(LiftoffRegister(args[0]),
|
||||||
|
LiftoffAssembler::kWasmIntPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the codegen zone if not done before.
|
// Allocate the codegen zone if not done before.
|
||||||
@ -1099,7 +1104,7 @@ class LiftoffCompiler {
|
|||||||
if (operand.sig->return_count() > 1)
|
if (operand.sig->return_count() > 1)
|
||||||
return unsupported(decoder, "multi-return");
|
return unsupported(decoder, "multi-return");
|
||||||
if (operand.sig->return_count() == 1 &&
|
if (operand.sig->return_count() == 1 &&
|
||||||
!CheckSupportedType(decoder, kTypes_ilf, operand.sig->GetReturn(0),
|
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
|
||||||
"return"))
|
"return"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1141,7 +1146,7 @@ class LiftoffCompiler {
|
|||||||
if (operand.sig->return_count() > 1)
|
if (operand.sig->return_count() > 1)
|
||||||
return unsupported(decoder, "multi-return");
|
return unsupported(decoder, "multi-return");
|
||||||
if (operand.sig->return_count() == 1 &&
|
if (operand.sig->return_count() == 1 &&
|
||||||
!CheckSupportedType(decoder, kTypes_ilf, operand.sig->GetReturn(0),
|
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
|
||||||
"return"))
|
"return"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -261,7 +261,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
BAILOUT("PushCallerFrameSlot");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +256,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
BAILOUT("PushCallerFrameSlot");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
BAILOUT("PushCallerFrameSlot");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,8 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
BAILOUT("PushCallerFrameSlot");
|
BAILOUT("PushCallerFrameSlot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
|
ValueType type) {
|
||||||
BAILOUT("PushCallerFrameSlot reg");
|
BAILOUT("PushCallerFrameSlot reg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
pushq(liftoff::GetStackSlot(src_index));
|
pushq(liftoff::GetStackSlot(src_index));
|
||||||
break;
|
break;
|
||||||
case VarState::kRegister:
|
case VarState::kRegister:
|
||||||
PushCallerFrameSlot(src.reg());
|
PushCallerFrameSlot(src.reg(), src.type());
|
||||||
break;
|
break;
|
||||||
case VarState::KIntConst:
|
case VarState::KIntConst:
|
||||||
pushq(Immediate(src.i32_const()));
|
pushq(Immediate(src.i32_const()));
|
||||||
@ -628,12 +628,23 @@ void LiftoffAssembler::PushCallerFrameSlot(const VarState& src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg) {
|
void LiftoffAssembler::PushCallerFrameSlot(LiftoffRegister reg,
|
||||||
if (reg.is_gp()) {
|
ValueType type) {
|
||||||
pushq(reg.gp());
|
switch (type) {
|
||||||
} else {
|
case kWasmI32:
|
||||||
subp(rsp, Immediate(kPointerSize));
|
case kWasmI64:
|
||||||
Movsd(Operand(rsp, 0), reg.fp());
|
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