diff --git a/src/wasm/baseline/arm/liftoff-assembler-arm.h b/src/wasm/baseline/arm/liftoff-assembler-arm.h index e280d06473..38a9b286d9 100644 --- a/src/wasm/baseline/arm/liftoff-assembler-arm.h +++ b/src/wasm/baseline/arm/liftoff-assembler-arm.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/arm64/liftoff-assembler-arm64.h b/src/wasm/baseline/arm64/liftoff-assembler-arm64.h index 57d99fbf7d..6901a40e9c 100644 --- a/src/wasm/baseline/arm64/liftoff-assembler-arm64.h +++ b/src/wasm/baseline/arm64/liftoff-assembler-arm64.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/ia32/liftoff-assembler-ia32.h b/src/wasm/baseline/ia32/liftoff-assembler-ia32.h index cfefd1c7cb..cdc36d0fad 100644 --- a/src/wasm/baseline/ia32/liftoff-assembler-ia32.h +++ b/src/wasm/baseline/ia32/liftoff-assembler-ia32.h @@ -176,12 +176,13 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, } } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { DCHECK_NE(dst_index, src_index); if (cache_state_.has_unused_register(kGpReg)) { LiftoffRegister reg = GetUnusedRegister(kGpReg); - Fill(reg, src_index); - Spill(dst_index, reg); + Fill(reg, src_index, type); + Spill(dst_index, reg, type); } else { push(liftoff::GetStackSlot(src_index)); pop(liftoff::GetStackSlot(dst_index)); @@ -210,13 +211,21 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { } } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { Operand dst = liftoff::GetStackSlot(index); - // TODO(clemensh): Handle different sizes here. - if (reg.is_gp()) { - mov(dst, reg.gp()); - } else { - movsd(dst, reg.fp()); + switch (type) { + case kWasmI32: + mov(dst, reg.gp()); + break; + case kWasmF32: + movss(dst, reg.fp()); + break; + case kWasmF64: + movsd(dst, reg.fp()); + break; + default: + UNREACHABLE(); } } @@ -234,13 +243,21 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { } } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { Operand src = liftoff::GetStackSlot(index); - // TODO(clemensh): Handle different sizes here. - if (reg.is_gp()) { - mov(reg.gp(), src); - } else { - movsd(reg.fp(), src); + switch (type) { + case kWasmI32: + mov(reg.gp(), src); + break; + case kWasmF32: + movss(reg.fp(), src); + break; + case kWasmF64: + movsd(reg.fp(), src); + break; + default: + UNREACHABLE(); } } diff --git a/src/wasm/baseline/liftoff-assembler.cc b/src/wasm/baseline/liftoff-assembler.cc index 4dfae7c02d..646153a2a2 100644 --- a/src/wasm/baseline/liftoff-assembler.cc +++ b/src/wasm/baseline/liftoff-assembler.cc @@ -31,20 +31,23 @@ class StackTransferRecipe { struct RegisterMove { LiftoffRegister dst; LiftoffRegister src; - constexpr RegisterMove(LiftoffRegister dst, LiftoffRegister src) - : dst(dst), src(src) {} + ValueType type; + constexpr RegisterMove(LiftoffRegister dst, LiftoffRegister src, + ValueType type) + : dst(dst), src(src), type(type) {} }; struct RegisterLoad { LiftoffRegister dst; bool is_constant_load; // otherwise load it from the stack. - union { - uint32_t stack_slot; - WasmValue constant; - }; + ValueType type; + uint32_t value; // i32 constant if {is_constant_load}, else stack slot. RegisterLoad(LiftoffRegister dst, WasmValue constant) - : dst(dst), is_constant_load(true), constant(constant) {} - RegisterLoad(LiftoffRegister dst, uint32_t stack_slot) - : dst(dst), is_constant_load(false), stack_slot(stack_slot) {} + : dst(dst), + is_constant_load(true), + type(kWasmI32), + value(constant.to_i32()) {} + RegisterLoad(LiftoffRegister dst, uint32_t stack_slot, ValueType type) + : dst(dst), is_constant_load(false), type(type), value(stack_slot) {} }; public: @@ -89,10 +92,11 @@ class StackTransferRecipe { if (executed_moves == 0) { // There is a cycle. Spill one register, then continue. // TODO(clemensh): Use an unused register if available. - LiftoffRegister spill_reg = register_moves_.back().src; - asm_->Spill(next_spill_slot, spill_reg); + RegisterMove& rm = register_moves_.back(); + LiftoffRegister spill_reg = rm.src; + asm_->Spill(next_spill_slot, spill_reg, rm.type); // Remember to reload into the destination register later. - LoadStackSlot(register_moves_.back().dst, next_spill_slot); + LoadStackSlot(register_moves_.back().dst, next_spill_slot, rm.type); DCHECK_EQ(1, src_reg_use_count[spill_reg.liftoff_code()]); src_reg_use_count[spill_reg.liftoff_code()] = 0; ++next_spill_slot; @@ -105,9 +109,9 @@ class StackTransferRecipe { for (RegisterLoad& rl : register_loads_) { if (rl.is_constant_load) { - asm_->LoadConstant(rl.dst, rl.constant); + asm_->LoadConstant(rl.dst, WasmValue(rl.value)); } else { - asm_->Fill(rl.dst, rl.stack_slot); + asm_->Fill(rl.dst, rl.value, rl.type); } } register_loads_.clear(); @@ -117,15 +121,16 @@ class StackTransferRecipe { uint32_t dst_index, uint32_t src_index) { const VarState& dst = dst_state.stack_state[dst_index]; const VarState& src = __ cache_state()->stack_state[src_index]; + DCHECK_EQ(dst.type(), src.type()); switch (dst.loc()) { case VarState::kStack: switch (src.loc()) { case VarState::kStack: if (src_index == dst_index) break; - asm_->MoveStackValue(dst_index, src_index); + asm_->MoveStackValue(dst_index, src_index, src.type()); break; case VarState::kRegister: - asm_->Spill(dst_index, src.reg()); + asm_->Spill(dst_index, src.reg(), src.type()); break; case VarState::kI32Const: asm_->Spill(dst_index, WasmValue(src.i32_const())); @@ -146,11 +151,11 @@ class StackTransferRecipe { uint32_t src_index) { switch (src.loc()) { case VarState::kStack: - LoadStackSlot(dst, src_index); + LoadStackSlot(dst, src_index, src.type()); break; case VarState::kRegister: DCHECK_EQ(dst.reg_class(), src.reg_class()); - if (dst != src.reg()) MoveRegister(dst, src.reg()); + if (dst != src.reg()) MoveRegister(dst, src.reg(), src.type()); break; case VarState::kI32Const: LoadConstant(dst, WasmValue(src.i32_const())); @@ -158,20 +163,23 @@ class StackTransferRecipe { } } - void MoveRegister(LiftoffRegister dst, LiftoffRegister src) { + void MoveRegister(LiftoffRegister dst, LiftoffRegister src, ValueType type) { DCHECK_NE(dst, src); + DCHECK_EQ(dst.reg_class(), src.reg_class()); + DCHECK_EQ(reg_class_for(type), src.reg_class()); DCHECK(!move_dst_regs_.has(dst)); move_dst_regs_.set(dst); move_src_regs_.set(src); - register_moves_.emplace_back(dst, src); + register_moves_.emplace_back(dst, src, type); } void LoadConstant(LiftoffRegister dst, WasmValue value) { register_loads_.emplace_back(dst, value); } - void LoadStackSlot(LiftoffRegister dst, uint32_t stack_index) { - register_loads_.emplace_back(dst, stack_index); + void LoadStackSlot(LiftoffRegister dst, uint32_t stack_index, + ValueType type) { + register_loads_.emplace_back(dst, stack_index, type); } private: @@ -183,6 +191,9 @@ class StackTransferRecipe { LiftoffAssembler* const asm_; }; +static constexpr ValueType kWasmIntPtr = + kPointerSize == 8 ? kWasmI64 : kWasmI32; + } // namespace // TODO(clemensh): Don't copy the full parent state (this makes us N^2). @@ -301,7 +312,7 @@ LiftoffRegister LiftoffAssembler::PopToRegister(RegClass rc, switch (slot.loc()) { case VarState::kStack: { LiftoffRegister reg = GetUnusedRegister(rc, pinned); - Fill(reg, cache_state_.stack_height()); + Fill(reg, cache_state_.stack_height(), slot.type()); return reg; } case VarState::kRegister: @@ -352,7 +363,7 @@ void LiftoffAssembler::Spill(uint32_t index) { case VarState::kStack: return; case VarState::kRegister: - Spill(index, slot.reg()); + Spill(index, slot.reg(), slot.type()); cache_state_.dec_used(slot.reg()); break; case VarState::kI32Const: @@ -372,7 +383,7 @@ void LiftoffAssembler::SpillAllRegisters() { for (uint32_t i = 0, e = cache_state_.stack_height(); i < e; ++i) { auto& slot = cache_state_.stack_state[i]; if (!slot.is_reg()) continue; - Spill(i, slot.reg()); + Spill(i, slot.reg(), slot.type()); slot.MakeStack(); } cache_state_.reset_used_registers(); @@ -395,7 +406,7 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig, idx < end; ++idx) { VarState& slot = cache_state_.stack_state[idx]; if (!slot.is_reg()) continue; - Spill(idx, slot.reg()); + Spill(idx, slot.reg(), slot.type()); slot.MakeStack(); } @@ -439,7 +450,8 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig, LiftoffRegList free_regs = kGpCacheRegList.MaskOut(param_regs); if (!free_regs.is_empty()) { LiftoffRegister new_target = free_regs.GetFirstRegSet(); - stack_transfers.MoveRegister(new_target, LiftoffRegister(*target)); + stack_transfers.MoveRegister(new_target, LiftoffRegister(*target), + kWasmIntPtr); *target = new_target.gp(); } else { PushCallerFrameSlot(LiftoffRegister(*target)); @@ -488,7 +500,7 @@ void LiftoffAssembler::SpillRegister(LiftoffRegister reg) { DCHECK_GT(cache_state_.stack_height(), idx); auto* slot = &cache_state_.stack_state[idx]; if (!slot->is_reg() || slot->reg() != reg) continue; - Spill(idx, reg); + Spill(idx, reg, slot->type()); slot->MakeStack(); if (--remaining_uses == 0) break; } diff --git a/src/wasm/baseline/liftoff-assembler.h b/src/wasm/baseline/liftoff-assembler.h index ae965f363b..b4f01c83e0 100644 --- a/src/wasm/baseline/liftoff-assembler.h +++ b/src/wasm/baseline/liftoff-assembler.h @@ -294,15 +294,15 @@ class LiftoffAssembler : public TurboAssembler { LiftoffRegister src, StoreType type, LiftoffRegList pinned, uint32_t* protected_store_pc = nullptr); inline void LoadCallerFrameSlot(LiftoffRegister, uint32_t caller_slot_idx); - inline void MoveStackValue(uint32_t dst_index, uint32_t src_index); + inline void MoveStackValue(uint32_t dst_index, uint32_t src_index, ValueType); inline void MoveToReturnRegister(LiftoffRegister); // TODO(clemensh): Pass the type to {Move}, to emit more efficient code. inline void Move(LiftoffRegister dst, LiftoffRegister src); - inline void Spill(uint32_t index, LiftoffRegister); + inline void Spill(uint32_t index, LiftoffRegister, ValueType); inline void Spill(uint32_t index, WasmValue); - inline void Fill(LiftoffRegister, uint32_t index); + inline void Fill(LiftoffRegister, uint32_t index, ValueType); // i32 binops. inline void emit_i32_add(Register dst, Register lhs, Register rhs); diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc index c0251fe1f0..4a3fdc43ac 100644 --- a/src/wasm/baseline/liftoff-compiler.cc +++ b/src/wasm/baseline/liftoff-compiler.cc @@ -141,6 +141,17 @@ class LiftoffCompiler { BindUnboundLabels(decoder); } + bool CheckSupportedType(Decoder* decoder, ValueType type, + const char* context) { + char buffer[128]; + // Check supported types. + if (type == kWasmI32 || type == kWasmF32) return true; + SNPrintF(ArrayVector(buffer), "%s %s", WasmOpcodes::TypeName(type), + context); + unsupported(decoder, buffer); + return false; + } + int GetSafepointTableOffset() const { return safepoint_table_builder_.GetCodeOffset(); } @@ -235,21 +246,7 @@ class LiftoffCompiler { uint32_t num_params = static_cast(call_desc_->ParameterCount()) - 1; for (uint32_t i = 0; i < __ num_locals(); ++i) { - switch (__ local_type(i)) { - case kWasmI32: - case kWasmF32: - // supported. - break; - case kWasmI64: - unsupported(decoder, "i64 param/local"); - return; - case kWasmF64: - unsupported(decoder, "f64 param/local"); - return; - default: - unsupported(decoder, "exotic param/local"); - return; - } + if (!CheckSupportedType(decoder, __ local_type(i), "param")) return; } // Input 0 is the call target, the context is at 1. constexpr int kContextParameterIndex = 1; @@ -638,7 +635,7 @@ class LiftoffCompiler { case kStack: { auto rc = reg_class_for(operand.type); LiftoffRegister reg = __ GetUnusedRegister(rc); - __ Fill(reg, operand.index); + __ Fill(reg, operand.index, operand.type); __ PushRegister(slot.type(), reg); break; } @@ -649,19 +646,19 @@ class LiftoffCompiler { void SetLocalFromStackSlot(LiftoffAssembler::VarState& dst_slot, uint32_t local_index) { auto& state = *__ cache_state(); + ValueType type = dst_slot.type(); if (dst_slot.is_reg()) { LiftoffRegister slot_reg = dst_slot.reg(); if (state.get_use_count(slot_reg) == 1) { - __ Fill(dst_slot.reg(), state.stack_height() - 1); + __ Fill(dst_slot.reg(), state.stack_height() - 1, type); return; } state.dec_used(slot_reg); } - ValueType type = dst_slot.type(); DCHECK_EQ(type, __ local_type(local_index)); RegClass rc = reg_class_for(type); LiftoffRegister dst_reg = __ GetUnusedRegister(rc); - __ Fill(dst_reg, __ cache_state()->stack_height() - 1); + __ Fill(dst_reg, __ cache_state()->stack_height() - 1, type); dst_slot = LiftoffAssembler::VarState(type, dst_reg); __ cache_state()->inc_used(dst_reg); } @@ -889,8 +886,7 @@ class LiftoffCompiler { const MemoryAccessOperand& operand, const Value& index_val, Value* result) { ValueType value_type = type.value_type(); - if (value_type != kWasmI32 && value_type != kWasmF32) - return unsupported(decoder, "unsupported load type"); + if (!CheckSupportedType(decoder, value_type, "load")) return; LiftoffRegList pinned; Register index = pinned.set(__ PopToRegister(kGpReg)).gp(); if (!env_->use_trap_handler) { @@ -923,8 +919,7 @@ class LiftoffCompiler { const MemoryAccessOperand& operand, const Value& index_val, const Value& value_val) { ValueType value_type = type.value_type(); - if (value_type != kWasmI32 && value_type != kWasmF32) - return unsupported(decoder, "unsupported store type"); + if (!CheckSupportedType(decoder, value_type, "store")) return; RegClass rc = reg_class_for(value_type); LiftoffRegList pinned; LiftoffRegister value = pinned.set(__ PopToRegister(rc)); @@ -962,6 +957,9 @@ class LiftoffCompiler { const Value args[], Value returns[]) { if (operand.sig->return_count() > 1) return unsupported(decoder, "multi-return"); + if (operand.sig->return_count() == 1 && + !CheckSupportedType(decoder, operand.sig->GetReturn(0), "return")) + return; compiler::CallDescriptor* call_desc = compiler::GetWasmCallDescriptor(compilation_zone_, operand.sig); diff --git a/src/wasm/baseline/mips/liftoff-assembler-mips.h b/src/wasm/baseline/mips/liftoff-assembler-mips.h index df3d08db0e..afe136e9fa 100644 --- a/src/wasm/baseline/mips/liftoff-assembler-mips.h +++ b/src/wasm/baseline/mips/liftoff-assembler-mips.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h index 2f67f7f002..7543bf2a31 100644 --- a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h +++ b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/ppc/liftoff-assembler-ppc.h b/src/wasm/baseline/ppc/liftoff-assembler-ppc.h index f046560e46..c979352ff9 100644 --- a/src/wasm/baseline/ppc/liftoff-assembler-ppc.h +++ b/src/wasm/baseline/ppc/liftoff-assembler-ppc.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/s390/liftoff-assembler-s390.h b/src/wasm/baseline/s390/liftoff-assembler-s390.h index fef6c54845..8abbded6e9 100644 --- a/src/wasm/baseline/s390/liftoff-assembler-s390.h +++ b/src/wasm/baseline/s390/liftoff-assembler-s390.h @@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, UNIMPLEMENTED(); } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { UNIMPLEMENTED(); } @@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { UNIMPLEMENTED(); } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { UNIMPLEMENTED(); } @@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { UNIMPLEMENTED(); } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { UNIMPLEMENTED(); } diff --git a/src/wasm/baseline/x64/liftoff-assembler-x64.h b/src/wasm/baseline/x64/liftoff-assembler-x64.h index 0fc56ac97c..cc3db1b0ed 100644 --- a/src/wasm/baseline/x64/liftoff-assembler-x64.h +++ b/src/wasm/baseline/x64/liftoff-assembler-x64.h @@ -178,12 +178,13 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, } } -void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index) { +void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, + ValueType type) { DCHECK_NE(dst_index, src_index); if (cache_state_.has_unused_register(kGpReg)) { LiftoffRegister reg = GetUnusedRegister(kGpReg); - Fill(reg, src_index); - Spill(dst_index, reg); + Fill(reg, src_index, type); + Spill(dst_index, reg, type); } else { pushq(liftoff::GetStackSlot(src_index)); popq(liftoff::GetStackSlot(dst_index)); @@ -212,13 +213,24 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { } } -void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { +void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg, + ValueType type) { Operand dst = liftoff::GetStackSlot(index); - // TODO(clemensh): Handle different sizes here. - if (reg.is_gp()) { - movq(dst, reg.gp()); - } else { - Movsd(dst, reg.fp()); + switch (type) { + case kWasmI32: + movl(dst, reg.gp()); + break; + case kWasmI64: + movq(dst, reg.gp()); + break; + case kWasmF32: + Movss(dst, reg.fp()); + break; + case kWasmF64: + Movsd(dst, reg.fp()); + break; + default: + UNREACHABLE(); } } @@ -236,13 +248,24 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { } } -void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { +void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index, + ValueType type) { Operand src = liftoff::GetStackSlot(index); - // TODO(clemensh): Handle different sizes here. - if (reg.is_gp()) { - movq(reg.gp(), src); - } else { - Movsd(reg.fp(), src); + switch (type) { + case kWasmI32: + movl(reg.gp(), src); + break; + case kWasmI64: + movq(reg.gp(), src); + break; + case kWasmF32: + Movss(reg.fp(), src); + break; + case kWasmF64: + Movsd(reg.fp(), src); + break; + default: + UNREACHABLE(); } } diff --git a/test/mjsunit/regress/wasm/regress-7353.js b/test/mjsunit/regress/wasm/regress-7353.js new file mode 100644 index 0000000000..d41cbabf36 --- /dev/null +++ b/test/mjsunit/regress/wasm/regress-7353.js @@ -0,0 +1,29 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --wasm-lazy-compilation + +load('test/mjsunit/wasm/wasm-constants.js'); +load('test/mjsunit/wasm/wasm-module-builder.js'); + +const builder = new WasmModuleBuilder(); +builder.addMemory(16, 32); +builder.addFunction('grow', kSig_i_i).addBody([ + kExprGetLocal, 0, + kExprGrowMemory, 0, +]).exportFunc(); +builder.addFunction('main', kSig_i_i).addBody([ + ...wasmI32Const(0x41), + kExprSetLocal, 0, + // Enter loop, such that values are spilled to the stack. + kExprLoop, kWasmStmt, + kExprEnd, + // Reload value. This must be loaded as 32 bit value. + kExprGetLocal, 0, + kExprI32LoadMem, 0, 0, +]).exportFunc(); +const instance = builder.instantiate(); +// Execute grow, such that the stack contains garbage data afterwards. +instance.exports.grow(1); +instance.exports.main();