Commit ecb3afca authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Fill registers as the right type

When spilling a value to the stack, make sure to fill it as the same
type later. Otherwise, we might load garbage from the stack and violate
the assumption that the upper 32 bits of a 64 bit register are zero if
it currently holds a 32 bit value.

R=titzer@chromium.org

Bug: v8:7353, v8:6600
Change-Id: I7f2b1b31b7f3c13aa152c682cb59400fb5a3ebf0
Reviewed-on: https://chromium-review.googlesource.com/880682
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50797}
parent daff6e7a
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -176,12 +176,13 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -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); DCHECK_NE(dst_index, src_index);
if (cache_state_.has_unused_register(kGpReg)) { if (cache_state_.has_unused_register(kGpReg)) {
LiftoffRegister reg = GetUnusedRegister(kGpReg); LiftoffRegister reg = GetUnusedRegister(kGpReg);
Fill(reg, src_index); Fill(reg, src_index, type);
Spill(dst_index, reg); Spill(dst_index, reg, type);
} else { } else {
push(liftoff::GetStackSlot(src_index)); push(liftoff::GetStackSlot(src_index));
pop(liftoff::GetStackSlot(dst_index)); pop(liftoff::GetStackSlot(dst_index));
...@@ -210,13 +211,21 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -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); Operand dst = liftoff::GetStackSlot(index);
// TODO(clemensh): Handle different sizes here. switch (type) {
if (reg.is_gp()) { case kWasmI32:
mov(dst, reg.gp()); mov(dst, reg.gp());
} else { break;
movsd(dst, reg.fp()); 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) { ...@@ -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); Operand src = liftoff::GetStackSlot(index);
// TODO(clemensh): Handle different sizes here. switch (type) {
if (reg.is_gp()) { case kWasmI32:
mov(reg.gp(), src); mov(reg.gp(), src);
} else { break;
movsd(reg.fp(), src); case kWasmF32:
movss(reg.fp(), src);
break;
case kWasmF64:
movsd(reg.fp(), src);
break;
default:
UNREACHABLE();
} }
} }
......
...@@ -31,20 +31,23 @@ class StackTransferRecipe { ...@@ -31,20 +31,23 @@ class StackTransferRecipe {
struct RegisterMove { struct RegisterMove {
LiftoffRegister dst; LiftoffRegister dst;
LiftoffRegister src; LiftoffRegister src;
constexpr RegisterMove(LiftoffRegister dst, LiftoffRegister src) ValueType type;
: dst(dst), src(src) {} constexpr RegisterMove(LiftoffRegister dst, LiftoffRegister src,
ValueType type)
: dst(dst), src(src), type(type) {}
}; };
struct RegisterLoad { struct RegisterLoad {
LiftoffRegister dst; LiftoffRegister dst;
bool is_constant_load; // otherwise load it from the stack. bool is_constant_load; // otherwise load it from the stack.
union { ValueType type;
uint32_t stack_slot; uint32_t value; // i32 constant if {is_constant_load}, else stack slot.
WasmValue constant;
};
RegisterLoad(LiftoffRegister dst, WasmValue constant) RegisterLoad(LiftoffRegister dst, WasmValue constant)
: dst(dst), is_constant_load(true), constant(constant) {} : dst(dst),
RegisterLoad(LiftoffRegister dst, uint32_t stack_slot) is_constant_load(true),
: dst(dst), is_constant_load(false), stack_slot(stack_slot) {} 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: public:
...@@ -89,10 +92,11 @@ class StackTransferRecipe { ...@@ -89,10 +92,11 @@ class StackTransferRecipe {
if (executed_moves == 0) { if (executed_moves == 0) {
// There is a cycle. Spill one register, then continue. // There is a cycle. Spill one register, then continue.
// TODO(clemensh): Use an unused register if available. // TODO(clemensh): Use an unused register if available.
LiftoffRegister spill_reg = register_moves_.back().src; RegisterMove& rm = register_moves_.back();
asm_->Spill(next_spill_slot, spill_reg); LiftoffRegister spill_reg = rm.src;
asm_->Spill(next_spill_slot, spill_reg, rm.type);
// Remember to reload into the destination register later. // 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()]); DCHECK_EQ(1, src_reg_use_count[spill_reg.liftoff_code()]);
src_reg_use_count[spill_reg.liftoff_code()] = 0; src_reg_use_count[spill_reg.liftoff_code()] = 0;
++next_spill_slot; ++next_spill_slot;
...@@ -105,9 +109,9 @@ class StackTransferRecipe { ...@@ -105,9 +109,9 @@ class StackTransferRecipe {
for (RegisterLoad& rl : register_loads_) { for (RegisterLoad& rl : register_loads_) {
if (rl.is_constant_load) { if (rl.is_constant_load) {
asm_->LoadConstant(rl.dst, rl.constant); asm_->LoadConstant(rl.dst, WasmValue(rl.value));
} else { } else {
asm_->Fill(rl.dst, rl.stack_slot); asm_->Fill(rl.dst, rl.value, rl.type);
} }
} }
register_loads_.clear(); register_loads_.clear();
...@@ -117,15 +121,16 @@ class StackTransferRecipe { ...@@ -117,15 +121,16 @@ class StackTransferRecipe {
uint32_t dst_index, uint32_t src_index) { uint32_t dst_index, uint32_t src_index) {
const VarState& dst = dst_state.stack_state[dst_index]; const VarState& dst = dst_state.stack_state[dst_index];
const VarState& src = __ cache_state()->stack_state[src_index]; const VarState& src = __ cache_state()->stack_state[src_index];
DCHECK_EQ(dst.type(), src.type());
switch (dst.loc()) { switch (dst.loc()) {
case VarState::kStack: case VarState::kStack:
switch (src.loc()) { switch (src.loc()) {
case VarState::kStack: case VarState::kStack:
if (src_index == dst_index) break; if (src_index == dst_index) break;
asm_->MoveStackValue(dst_index, src_index); asm_->MoveStackValue(dst_index, src_index, src.type());
break; break;
case VarState::kRegister: case VarState::kRegister:
asm_->Spill(dst_index, src.reg()); asm_->Spill(dst_index, src.reg(), src.type());
break; break;
case VarState::kI32Const: case VarState::kI32Const:
asm_->Spill(dst_index, WasmValue(src.i32_const())); asm_->Spill(dst_index, WasmValue(src.i32_const()));
...@@ -146,11 +151,11 @@ class StackTransferRecipe { ...@@ -146,11 +151,11 @@ class StackTransferRecipe {
uint32_t src_index) { uint32_t src_index) {
switch (src.loc()) { switch (src.loc()) {
case VarState::kStack: case VarState::kStack:
LoadStackSlot(dst, src_index); LoadStackSlot(dst, src_index, src.type());
break; break;
case VarState::kRegister: case VarState::kRegister:
DCHECK_EQ(dst.reg_class(), src.reg_class()); 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; break;
case VarState::kI32Const: case VarState::kI32Const:
LoadConstant(dst, WasmValue(src.i32_const())); LoadConstant(dst, WasmValue(src.i32_const()));
...@@ -158,20 +163,23 @@ class StackTransferRecipe { ...@@ -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_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)); DCHECK(!move_dst_regs_.has(dst));
move_dst_regs_.set(dst); move_dst_regs_.set(dst);
move_src_regs_.set(src); move_src_regs_.set(src);
register_moves_.emplace_back(dst, src); register_moves_.emplace_back(dst, src, type);
} }
void LoadConstant(LiftoffRegister dst, WasmValue value) { void LoadConstant(LiftoffRegister dst, WasmValue value) {
register_loads_.emplace_back(dst, value); register_loads_.emplace_back(dst, value);
} }
void LoadStackSlot(LiftoffRegister dst, uint32_t stack_index) { void LoadStackSlot(LiftoffRegister dst, uint32_t stack_index,
register_loads_.emplace_back(dst, stack_index); ValueType type) {
register_loads_.emplace_back(dst, stack_index, type);
} }
private: private:
...@@ -183,6 +191,9 @@ class StackTransferRecipe { ...@@ -183,6 +191,9 @@ class StackTransferRecipe {
LiftoffAssembler* const asm_; LiftoffAssembler* const asm_;
}; };
static constexpr ValueType kWasmIntPtr =
kPointerSize == 8 ? kWasmI64 : kWasmI32;
} // namespace } // namespace
// TODO(clemensh): Don't copy the full parent state (this makes us N^2). // TODO(clemensh): Don't copy the full parent state (this makes us N^2).
...@@ -301,7 +312,7 @@ LiftoffRegister LiftoffAssembler::PopToRegister(RegClass rc, ...@@ -301,7 +312,7 @@ LiftoffRegister LiftoffAssembler::PopToRegister(RegClass rc,
switch (slot.loc()) { switch (slot.loc()) {
case VarState::kStack: { case VarState::kStack: {
LiftoffRegister reg = GetUnusedRegister(rc, pinned); LiftoffRegister reg = GetUnusedRegister(rc, pinned);
Fill(reg, cache_state_.stack_height()); Fill(reg, cache_state_.stack_height(), slot.type());
return reg; return reg;
} }
case VarState::kRegister: case VarState::kRegister:
...@@ -352,7 +363,7 @@ void LiftoffAssembler::Spill(uint32_t index) { ...@@ -352,7 +363,7 @@ void LiftoffAssembler::Spill(uint32_t index) {
case VarState::kStack: case VarState::kStack:
return; return;
case VarState::kRegister: case VarState::kRegister:
Spill(index, slot.reg()); Spill(index, slot.reg(), slot.type());
cache_state_.dec_used(slot.reg()); cache_state_.dec_used(slot.reg());
break; break;
case VarState::kI32Const: case VarState::kI32Const:
...@@ -372,7 +383,7 @@ void LiftoffAssembler::SpillAllRegisters() { ...@@ -372,7 +383,7 @@ void LiftoffAssembler::SpillAllRegisters() {
for (uint32_t i = 0, e = cache_state_.stack_height(); i < e; ++i) { for (uint32_t i = 0, e = cache_state_.stack_height(); i < e; ++i) {
auto& slot = cache_state_.stack_state[i]; auto& slot = cache_state_.stack_state[i];
if (!slot.is_reg()) continue; if (!slot.is_reg()) continue;
Spill(i, slot.reg()); Spill(i, slot.reg(), slot.type());
slot.MakeStack(); slot.MakeStack();
} }
cache_state_.reset_used_registers(); cache_state_.reset_used_registers();
...@@ -395,7 +406,7 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig, ...@@ -395,7 +406,7 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
idx < end; ++idx) { idx < end; ++idx) {
VarState& slot = cache_state_.stack_state[idx]; VarState& slot = cache_state_.stack_state[idx];
if (!slot.is_reg()) continue; if (!slot.is_reg()) continue;
Spill(idx, slot.reg()); Spill(idx, slot.reg(), slot.type());
slot.MakeStack(); slot.MakeStack();
} }
...@@ -439,7 +450,8 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig, ...@@ -439,7 +450,8 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
LiftoffRegList free_regs = kGpCacheRegList.MaskOut(param_regs); LiftoffRegList free_regs = kGpCacheRegList.MaskOut(param_regs);
if (!free_regs.is_empty()) { if (!free_regs.is_empty()) {
LiftoffRegister new_target = free_regs.GetFirstRegSet(); 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(); *target = new_target.gp();
} else { } else {
PushCallerFrameSlot(LiftoffRegister(*target)); PushCallerFrameSlot(LiftoffRegister(*target));
...@@ -488,7 +500,7 @@ void LiftoffAssembler::SpillRegister(LiftoffRegister reg) { ...@@ -488,7 +500,7 @@ void LiftoffAssembler::SpillRegister(LiftoffRegister reg) {
DCHECK_GT(cache_state_.stack_height(), idx); DCHECK_GT(cache_state_.stack_height(), idx);
auto* slot = &cache_state_.stack_state[idx]; auto* slot = &cache_state_.stack_state[idx];
if (!slot->is_reg() || slot->reg() != reg) continue; if (!slot->is_reg() || slot->reg() != reg) continue;
Spill(idx, reg); Spill(idx, reg, slot->type());
slot->MakeStack(); slot->MakeStack();
if (--remaining_uses == 0) break; if (--remaining_uses == 0) break;
} }
......
...@@ -294,15 +294,15 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -294,15 +294,15 @@ class LiftoffAssembler : public TurboAssembler {
LiftoffRegister src, StoreType type, LiftoffRegList pinned, LiftoffRegister src, StoreType type, LiftoffRegList pinned,
uint32_t* protected_store_pc = nullptr); uint32_t* protected_store_pc = nullptr);
inline void LoadCallerFrameSlot(LiftoffRegister, uint32_t caller_slot_idx); 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); inline void MoveToReturnRegister(LiftoffRegister);
// TODO(clemensh): Pass the type to {Move}, to emit more efficient code. // TODO(clemensh): Pass the type to {Move}, to emit more efficient code.
inline void Move(LiftoffRegister dst, LiftoffRegister src); 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 Spill(uint32_t index, WasmValue);
inline void Fill(LiftoffRegister, uint32_t index); inline void Fill(LiftoffRegister, uint32_t index, ValueType);
// i32 binops. // i32 binops.
inline void emit_i32_add(Register dst, Register lhs, Register rhs); inline void emit_i32_add(Register dst, Register lhs, Register rhs);
......
...@@ -141,6 +141,17 @@ class LiftoffCompiler { ...@@ -141,6 +141,17 @@ class LiftoffCompiler {
BindUnboundLabels(decoder); 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 { int GetSafepointTableOffset() const {
return safepoint_table_builder_.GetCodeOffset(); return safepoint_table_builder_.GetCodeOffset();
} }
...@@ -235,21 +246,7 @@ class LiftoffCompiler { ...@@ -235,21 +246,7 @@ class LiftoffCompiler {
uint32_t num_params = uint32_t num_params =
static_cast<uint32_t>(call_desc_->ParameterCount()) - 1; static_cast<uint32_t>(call_desc_->ParameterCount()) - 1;
for (uint32_t i = 0; i < __ num_locals(); ++i) { for (uint32_t i = 0; i < __ num_locals(); ++i) {
switch (__ local_type(i)) { if (!CheckSupportedType(decoder, __ local_type(i), "param")) return;
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;
}
} }
// Input 0 is the call target, the context is at 1. // Input 0 is the call target, the context is at 1.
constexpr int kContextParameterIndex = 1; constexpr int kContextParameterIndex = 1;
...@@ -638,7 +635,7 @@ class LiftoffCompiler { ...@@ -638,7 +635,7 @@ class LiftoffCompiler {
case kStack: { case kStack: {
auto rc = reg_class_for(operand.type); auto rc = reg_class_for(operand.type);
LiftoffRegister reg = __ GetUnusedRegister(rc); LiftoffRegister reg = __ GetUnusedRegister(rc);
__ Fill(reg, operand.index); __ Fill(reg, operand.index, operand.type);
__ PushRegister(slot.type(), reg); __ PushRegister(slot.type(), reg);
break; break;
} }
...@@ -649,19 +646,19 @@ class LiftoffCompiler { ...@@ -649,19 +646,19 @@ class LiftoffCompiler {
void SetLocalFromStackSlot(LiftoffAssembler::VarState& dst_slot, void SetLocalFromStackSlot(LiftoffAssembler::VarState& dst_slot,
uint32_t local_index) { uint32_t local_index) {
auto& state = *__ cache_state(); auto& state = *__ cache_state();
ValueType type = dst_slot.type();
if (dst_slot.is_reg()) { if (dst_slot.is_reg()) {
LiftoffRegister slot_reg = dst_slot.reg(); LiftoffRegister slot_reg = dst_slot.reg();
if (state.get_use_count(slot_reg) == 1) { 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; return;
} }
state.dec_used(slot_reg); state.dec_used(slot_reg);
} }
ValueType type = dst_slot.type();
DCHECK_EQ(type, __ local_type(local_index)); DCHECK_EQ(type, __ local_type(local_index));
RegClass rc = reg_class_for(type); RegClass rc = reg_class_for(type);
LiftoffRegister dst_reg = __ GetUnusedRegister(rc); 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); dst_slot = LiftoffAssembler::VarState(type, dst_reg);
__ cache_state()->inc_used(dst_reg); __ cache_state()->inc_used(dst_reg);
} }
...@@ -889,8 +886,7 @@ class LiftoffCompiler { ...@@ -889,8 +886,7 @@ class LiftoffCompiler {
const MemoryAccessOperand<validate>& operand, const MemoryAccessOperand<validate>& operand,
const Value& index_val, Value* result) { const Value& index_val, Value* result) {
ValueType value_type = type.value_type(); ValueType value_type = type.value_type();
if (value_type != kWasmI32 && value_type != kWasmF32) if (!CheckSupportedType(decoder, value_type, "load")) return;
return unsupported(decoder, "unsupported load type");
LiftoffRegList pinned; LiftoffRegList pinned;
Register index = pinned.set(__ PopToRegister(kGpReg)).gp(); Register index = pinned.set(__ PopToRegister(kGpReg)).gp();
if (!env_->use_trap_handler) { if (!env_->use_trap_handler) {
...@@ -923,8 +919,7 @@ class LiftoffCompiler { ...@@ -923,8 +919,7 @@ class LiftoffCompiler {
const MemoryAccessOperand<validate>& operand, const MemoryAccessOperand<validate>& operand,
const Value& index_val, const Value& value_val) { const Value& index_val, const Value& value_val) {
ValueType value_type = type.value_type(); ValueType value_type = type.value_type();
if (value_type != kWasmI32 && value_type != kWasmF32) if (!CheckSupportedType(decoder, value_type, "store")) return;
return unsupported(decoder, "unsupported store type");
RegClass rc = reg_class_for(value_type); RegClass rc = reg_class_for(value_type);
LiftoffRegList pinned; LiftoffRegList pinned;
LiftoffRegister value = pinned.set(__ PopToRegister(rc)); LiftoffRegister value = pinned.set(__ PopToRegister(rc));
...@@ -962,6 +957,9 @@ class LiftoffCompiler { ...@@ -962,6 +957,9 @@ class LiftoffCompiler {
const Value args[], Value returns[]) { const Value args[], Value returns[]) {
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 &&
!CheckSupportedType(decoder, operand.sig->GetReturn(0), "return"))
return;
compiler::CallDescriptor* call_desc = compiler::CallDescriptor* call_desc =
compiler::GetWasmCallDescriptor(compilation_zone_, operand.sig); compiler::GetWasmCallDescriptor(compilation_zone_, operand.sig);
......
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -46,7 +46,8 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
UNIMPLEMENTED(); 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(); UNIMPLEMENTED();
} }
...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -58,7 +59,8 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg) { void LiftoffAssembler::Spill(uint32_t index, LiftoffRegister reg,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) { ...@@ -66,7 +68,8 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) { void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index,
ValueType type) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -178,12 +178,13 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -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); DCHECK_NE(dst_index, src_index);
if (cache_state_.has_unused_register(kGpReg)) { if (cache_state_.has_unused_register(kGpReg)) {
LiftoffRegister reg = GetUnusedRegister(kGpReg); LiftoffRegister reg = GetUnusedRegister(kGpReg);
Fill(reg, src_index); Fill(reg, src_index, type);
Spill(dst_index, reg); Spill(dst_index, reg, type);
} else { } else {
pushq(liftoff::GetStackSlot(src_index)); pushq(liftoff::GetStackSlot(src_index));
popq(liftoff::GetStackSlot(dst_index)); popq(liftoff::GetStackSlot(dst_index));
...@@ -212,13 +213,24 @@ void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src) { ...@@ -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); Operand dst = liftoff::GetStackSlot(index);
// TODO(clemensh): Handle different sizes here. switch (type) {
if (reg.is_gp()) { case kWasmI32:
movq(dst, reg.gp()); movl(dst, reg.gp());
} else { break;
Movsd(dst, reg.fp()); 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) { ...@@ -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); Operand src = liftoff::GetStackSlot(index);
// TODO(clemensh): Handle different sizes here. switch (type) {
if (reg.is_gp()) { case kWasmI32:
movq(reg.gp(), src); movl(reg.gp(), src);
} else { break;
Movsd(reg.fp(), src); case kWasmI64:
movq(reg.gp(), src);
break;
case kWasmF32:
Movss(reg.fp(), src);
break;
case kWasmF64:
Movsd(reg.fp(), src);
break;
default:
UNREACHABLE();
} }
} }
......
// 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();
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