Commit 742b6d1b authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Add support for globals

The wasm context will always be stored on the stack, and will be loaded
from there whenever needed (for accessing globals or the memory). We
can still improve this later by caching the context address or specific
information loaded from it.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Idd7fb1ccff28a73beaf545997e3dfdb74757b686
Reviewed-on: https://chromium-review.googlesource.com/779145
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49540}
parent fae23618
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -17,10 +17,16 @@ namespace wasm { ...@@ -17,10 +17,16 @@ namespace wasm {
namespace liftoff { namespace liftoff {
inline Operand GetStackSlot(uint32_t index) { inline Operand GetStackSlot(uint32_t index) {
// ebp-8 holds the stack marker, first stack slot is located at ebp-16. // ebp-8 holds the stack marker, ebp-16 is the wasm context, first stack slot
return Operand(ebp, -16 - 8 * index); // is located at ebp-24.
constexpr int32_t kStackSlotSize = 8;
constexpr int32_t kFirstStackSlotOffset = -24;
return Operand(ebp, kFirstStackSlotOffset - index * kStackSlotSize);
} }
// TODO(clemensh): Make this a constexpr variable once Operand is constexpr.
inline Operand GetContextOperand() { return Operand(ebp, -16); }
} // namespace liftoff } // namespace liftoff
void LiftoffAssembler::ReserveStackSpace(uint32_t space) { void LiftoffAssembler::ReserveStackSpace(uint32_t space) {
...@@ -42,20 +48,52 @@ void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) { ...@@ -42,20 +48,52 @@ void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {
} }
} }
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) { int size) {
mov(dst, Operand(reinterpret_cast<uint32_t>(addr), reloc_mode)); DCHECK_LE(offset, kMaxInt);
mov(dst, liftoff::GetContextOperand());
DCHECK_EQ(4, size);
mov(dst, Operand(dst, offset));
}
void LiftoffAssembler::SpillContext(Register context) {
mov(liftoff::GetContextOperand(), context);
} }
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::Load(Register dst, Register src_addr,
PinnedRegisterScope pinned_regs, uint32_t offset_imm, int size,
RelocInfo::Mode reloc_mode) { PinnedRegisterScope pinned) {
mov(Operand(reinterpret_cast<uint32_t>(addr), reloc_mode), reg); Operand src_op = Operand(src_addr, offset_imm);
if (offset_imm > kMaxInt) {
// The immediate can not be encoded in the operand. Load it to a register
// first.
Register src = GetUnusedRegister(kWasmPtrSizeInt, pinned);
mov(src, Immediate(offset_imm));
src_op = Operand(src_addr, src, times_1, 0);
}
DCHECK_EQ(4, size);
mov(dst, src_op);
}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {
Operand dst_op = Operand(dst_addr, offset_imm);
if (offset_imm > kMaxInt) {
// The immediate can not be encoded in the operand. Load it to a register
// first.
Register dst = GetUnusedRegister(kWasmPtrSizeInt, pinned);
mov(dst, Immediate(offset_imm));
dst_op = Operand(dst_addr, dst, times_1, 0);
}
DCHECK_EQ(4, size);
mov(dst_op, src);
} }
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) { uint32_t caller_slot_idx) {
mov(dst, Operand(ebp, 4 + 4 * caller_slot_idx)); constexpr int32_t kCallerStackSlotSize = 4;
mov(dst, Operand(ebp, kCallerStackSlotSize * (caller_slot_idx + 1)));
} }
void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index,
......
...@@ -358,7 +358,7 @@ Register LiftoffAssembler::PopToRegister(ValueType type, ...@@ -358,7 +358,7 @@ Register LiftoffAssembler::PopToRegister(ValueType type,
Register LiftoffAssembler::SpillRegister(ValueType type, Register LiftoffAssembler::SpillRegister(ValueType type,
PinnedRegisterScope pinned_regs) { PinnedRegisterScope pinned_regs) {
DCHECK_EQ(kWasmI32, type); DCHECK(type == kWasmI32 || type == kWasmI64);
// Spill one cached value to free a register. // Spill one cached value to free a register.
Register spill_reg = cache_state_.GetNextSpillReg(pinned_regs); Register spill_reg = cache_state_.GetNextSpillReg(pinned_regs);
......
...@@ -44,6 +44,8 @@ namespace wasm { ...@@ -44,6 +44,8 @@ namespace wasm {
// Forward declarations. // Forward declarations.
struct ModuleEnv; struct ModuleEnv;
constexpr ValueType kWasmPtrSizeInt = kPointerSize == 8 ? kWasmI64 : kWasmI32;
class LiftoffAssembler : public TurboAssembler { class LiftoffAssembler : public TurboAssembler {
public: public:
class PinnedRegisterScope { class PinnedRegisterScope {
...@@ -200,7 +202,7 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -200,7 +202,7 @@ class LiftoffAssembler : public TurboAssembler {
Register GetUnusedRegister(ValueType type, Register GetUnusedRegister(ValueType type,
PinnedRegisterScope pinned_regs = {}) { PinnedRegisterScope pinned_regs = {}) {
DCHECK_EQ(kWasmI32, type); DCHECK(type == kWasmI32 || type == kWasmI64);
if (cache_state_.has_unused_register(pinned_regs)) { if (cache_state_.has_unused_register(pinned_regs)) {
return cache_state_.unused_register(pinned_regs); return cache_state_.unused_register(pinned_regs);
} }
...@@ -230,9 +232,12 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -230,9 +232,12 @@ class LiftoffAssembler : public TurboAssembler {
inline void ReserveStackSpace(uint32_t); inline void ReserveStackSpace(uint32_t);
inline void LoadConstant(Register, WasmValue); inline void LoadConstant(Register, WasmValue);
inline void Load(Register, Address, RelocInfo::Mode = RelocInfo::NONE32); inline void LoadFromContext(Register dst, uint32_t offset, int size);
inline void Store(Address, Register, PinnedRegisterScope, inline void SpillContext(Register context);
RelocInfo::Mode = RelocInfo::NONE32); inline void Load(Register dst, Register src_addr, uint32_t offset_imm,
int size, PinnedRegisterScope = {});
inline void Store(Register dst_addr, uint32_t offset_imm, Register src,
int size, PinnedRegisterScope = {});
inline void LoadCallerFrameSlot(Register, uint32_t caller_slot_idx); inline void LoadCallerFrameSlot(Register, uint32_t caller_slot_idx);
inline void MoveStackValue(uint32_t dst_index, uint32_t src_index, ValueType); inline void MoveStackValue(uint32_t dst_index, uint32_t src_index, ValueType);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/counters.h" #include "src/counters.h"
#include "src/macro-assembler-inl.h" #include "src/macro-assembler-inl.h"
#include "src/wasm/function-body-decoder-impl.h" #include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h" #include "src/wasm/wasm-opcodes.h"
namespace v8 { namespace v8 {
...@@ -52,10 +53,7 @@ class LiftoffCompiler { ...@@ -52,10 +53,7 @@ class LiftoffCompiler {
LiftoffCompiler(LiftoffAssembler* liftoff_asm, LiftoffCompiler(LiftoffAssembler* liftoff_asm,
compiler::CallDescriptor* call_desc, compiler::ModuleEnv* env) compiler::CallDescriptor* call_desc, compiler::ModuleEnv* env)
: asm_(liftoff_asm), call_desc_(call_desc), env_(env) { : asm_(liftoff_asm), call_desc_(call_desc), env_(env) {}
// The ModuleEnv will be used once we implement calls.
USE(env_);
}
bool ok() const { return ok_; } bool ok() const { return ok_; }
...@@ -102,10 +100,9 @@ class LiftoffCompiler { ...@@ -102,10 +100,9 @@ class LiftoffCompiler {
__ EnterFrame(StackFrame::WASM_COMPILED); __ EnterFrame(StackFrame::WASM_COMPILED);
__ ReserveStackSpace(kPointerSize * __ ReserveStackSpace(kPointerSize *
(__ num_locals() + kMaxValueStackHeight)); (__ num_locals() + kMaxValueStackHeight));
// Param #0 is the wasm context. // Parameter 0 is the wasm context.
constexpr uint32_t kFirstActualParameterIndex = 1; uint32_t num_params =
uint32_t num_params = static_cast<uint32_t>(call_desc_->ParameterCount()) - static_cast<uint32_t>(call_desc_->ParameterCount()) - 1;
kFirstActualParameterIndex;
for (uint32_t i = 0; i < __ num_locals(); ++i) { for (uint32_t i = 0; i < __ num_locals(); ++i) {
// We can currently only handle i32 parameters and locals. // We can currently only handle i32 parameters and locals.
if (__ local_type(i) != kWasmI32) { if (__ local_type(i) != kWasmI32) {
...@@ -113,12 +110,20 @@ class LiftoffCompiler { ...@@ -113,12 +110,20 @@ class LiftoffCompiler {
return; return;
} }
} }
// Input 0 is the call target, the context is at 1.
constexpr int kContextParameterIndex = 1;
// Store the context parameter to a special stack slot.
compiler::LinkageLocation context_loc =
call_desc_->GetInputLocation(kContextParameterIndex);
DCHECK(context_loc.IsRegister());
DCHECK(!context_loc.IsAnyRegister());
Register context_reg = Register::from_code(context_loc.AsRegister());
__ SpillContext(context_reg);
uint32_t param_idx = 0; uint32_t param_idx = 0;
for (; param_idx < num_params; ++param_idx) { for (; param_idx < num_params; ++param_idx) {
// First input is the call target. constexpr uint32_t kFirstActualParamIndex = kContextParameterIndex + 1;
constexpr int kParameterStartInInputs = kFirstActualParameterIndex + 1;
compiler::LinkageLocation param_loc = compiler::LinkageLocation param_loc =
call_desc_->GetInputLocation(param_idx + kParameterStartInInputs); call_desc_->GetInputLocation(param_idx + kFirstActualParamIndex);
if (param_loc.IsRegister()) { if (param_loc.IsRegister()) {
DCHECK(!param_loc.IsAnyRegister()); DCHECK(!param_loc.IsAnyRegister());
Register param_reg = Register::from_code(param_loc.AsRegister()); Register param_reg = Register::from_code(param_loc.AsRegister());
...@@ -270,9 +275,10 @@ class LiftoffCompiler { ...@@ -270,9 +275,10 @@ class LiftoffCompiler {
__ cache_state()->Steal(func_block->label_state); __ cache_state()->Steal(func_block->label_state);
} }
if (!values.is_empty()) { if (!values.is_empty()) {
if (values.size() > 1) unsupported(decoder, "multi-return"); if (values.size() > 1) return unsupported(decoder, "multi-return");
// TODO(clemensh): Handle other types. // TODO(clemensh): Handle other types.
DCHECK_EQ(kWasmI32, values[0].type); if (values[0].type != kWasmI32)
return unsupported(decoder, "non-i32 return");
Register reg = __ PopToRegister(kWasmI32); Register reg = __ PopToRegister(kWasmI32);
__ MoveToReturnRegister(reg); __ MoveToReturnRegister(reg);
} }
...@@ -350,30 +356,32 @@ class LiftoffCompiler { ...@@ -350,30 +356,32 @@ class LiftoffCompiler {
void GetGlobal(Decoder* decoder, Value* result, void GetGlobal(Decoder* decoder, Value* result,
const GlobalIndexOperand<validate>& operand) { const GlobalIndexOperand<validate>& operand) {
unsupported(decoder, "get_global"); const auto* global = &env_->module->globals[operand.index];
/* if (global->type != kWasmI32 && global->type != kWasmI64)
auto* global = &env_->module->globals[operand.index]; return unsupported(decoder, "non-int global");
Address global_addr = LiftoffAssembler::PinnedRegisterScope pinned;
reinterpret_cast<Address>(env_->globals_start + global->offset); Register addr = pinned.pin(__ GetUnusedRegister(kWasmPtrSizeInt));
if (global->type != kWasmI32) return unsupported(decoder, "non-i32 global"); __ LoadFromContext(addr, offsetof(WasmContext, globals_start),
Register dst = __ GetUnusedRegister(global->type); kPointerSize);
__ Load(dst, global_addr, RelocInfo::WASM_GLOBAL_REFERENCE); Register value = pinned.pin(__ GetUnusedRegister(global->type, pinned));
__ PushRegister(dst); int size = 1 << ElementSizeLog2Of(global->type);
*/ if (size > kPointerSize)
return unsupported(decoder, "global > kPointerSize");
__ Load(value, addr, global->offset, size, pinned);
__ PushRegister(value);
} }
void SetGlobal(Decoder* decoder, const Value& value, void SetGlobal(Decoder* decoder, const Value& value,
const GlobalIndexOperand<validate>& operand) { const GlobalIndexOperand<validate>& operand) {
unsupported(decoder, "set_global");
/*
auto* global = &env_->module->globals[operand.index]; auto* global = &env_->module->globals[operand.index];
Address global_addr =
reinterpret_cast<Address>(env_->globals_start + global->offset);
if (global->type != kWasmI32) return unsupported(decoder, "non-i32 global"); if (global->type != kWasmI32) return unsupported(decoder, "non-i32 global");
LiftoffAssembler::PinnedRegisterScope pinned_regs; LiftoffAssembler::PinnedRegisterScope pinned;
Register reg = pinned_regs.pin(__ PopToRegister(global->type)); Register addr = pinned.pin(__ GetUnusedRegister(kWasmPtrSizeInt));
__ Store(global_addr, reg, pinned_regs, RelocInfo::WASM_GLOBAL_REFERENCE); __ LoadFromContext(addr, offsetof(WasmContext, globals_start),
*/ kPointerSize);
Register reg = pinned.pin(__ PopToRegister(global->type, pinned));
int size = 1 << ElementSizeLog2Of(global->type);
__ Store(addr, global->offset, reg, size, pinned);
} }
void Unreachable(Decoder* decoder) { unsupported(decoder, "unreachable"); } void Unreachable(Decoder* decoder) { unsupported(decoder, "unreachable"); }
......
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); } ...@@ -15,12 +15,18 @@ void LiftoffAssembler::ReserveStackSpace(uint32_t space) { USE(stack_space_); }
void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {} void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {}
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) {} int size) {}
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {}
PinnedRegisterScope pinned_regs,
RelocInfo::Mode reloc_mode) {} void LiftoffAssembler::Load(Register dst, Register src_addr,
uint32_t offset_imm, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {}
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) {} uint32_t caller_slot_idx) {}
...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {} ...@@ -36,13 +42,12 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {}
void LiftoffAssembler::Fill(Register reg, uint32_t index) {} void LiftoffAssembler::Fill(Register reg, uint32_t index) {}
void LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) {}
#define DEFAULT_I32_BINOP(name, internal_name) \ #define DEFAULT_I32_BINOP(name, internal_name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) {} Register rhs) {}
// clang-format off // clang-format off
DEFAULT_I32_BINOP(add, add)
DEFAULT_I32_BINOP(sub, sub) DEFAULT_I32_BINOP(sub, sub)
DEFAULT_I32_BINOP(mul, imul) DEFAULT_I32_BINOP(mul, imul)
DEFAULT_I32_BINOP(and, and) DEFAULT_I32_BINOP(and, and)
......
...@@ -17,10 +17,16 @@ namespace wasm { ...@@ -17,10 +17,16 @@ namespace wasm {
namespace liftoff { namespace liftoff {
inline Operand GetStackSlot(uint32_t index) { inline Operand GetStackSlot(uint32_t index) {
// rbp-8 holds the stack marker, first stack slot is located at rbp-16. // rbp-8 holds the stack marker, rbp-16 is the wasm context, first stack slot
return Operand(rbp, -16 - 8 * index); // is located at rbp-24.
constexpr int32_t kStackSlotSize = 8;
constexpr int32_t kFirstStackSlotOffset = -24;
return Operand(rbp, kFirstStackSlotOffset - index * kStackSlotSize);
} }
// TODO(clemensh): Make this a constexpr variable once Operand is constexpr.
inline Operand GetContextOperand() { return Operand(rbp, -16); }
} // namespace liftoff } // namespace liftoff
void LiftoffAssembler::ReserveStackSpace(uint32_t space) { void LiftoffAssembler::ReserveStackSpace(uint32_t space) {
...@@ -42,25 +48,64 @@ void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) { ...@@ -42,25 +48,64 @@ void LiftoffAssembler::LoadConstant(Register reg, WasmValue value) {
} }
} }
void LiftoffAssembler::Load(Register dst, Address addr, void LiftoffAssembler::LoadFromContext(Register dst, uint32_t offset,
RelocInfo::Mode reloc_mode) { int size) {
movp(dst, bit_cast<void*>(addr), reloc_mode); DCHECK_LE(offset, kMaxInt);
movl(dst, Operand(dst, 0)); movp(dst, liftoff::GetContextOperand());
DCHECK(size == 4 || size == 8);
if (size == 4) {
movl(dst, Operand(dst, offset));
} else {
movq(dst, Operand(dst, offset));
}
} }
void LiftoffAssembler::Store(Address addr, Register reg, void LiftoffAssembler::SpillContext(Register context) {
PinnedRegisterScope pinned_regs, movp(liftoff::GetContextOperand(), context);
RelocInfo::Mode reloc_mode) { }
// TODO(clemensh): Change this to kPointerSizeT or something.
Register global_addr_reg = GetUnusedRegister(kWasmI32, pinned_regs); void LiftoffAssembler::Load(Register dst, Register src_addr,
DCHECK_NE(reg, global_addr_reg); uint32_t offset_imm, int size,
movp(global_addr_reg, static_cast<void*>(addr), reloc_mode); PinnedRegisterScope pinned) {
movl(Operand(global_addr_reg, 0), reg); Operand src_op = Operand(src_addr, offset_imm);
if (offset_imm > kMaxInt) {
// The immediate can not be encoded in the operand. Load it to a register
// first.
Register src = GetUnusedRegister(kWasmPtrSizeInt, pinned);
movl(src, Immediate(offset_imm));
src_op = Operand(src_addr, src, times_1, 0);
}
DCHECK(size == 4 || size == 8);
if (size == 4) {
movl(dst, src_op);
} else {
movq(dst, src_op);
}
}
void LiftoffAssembler::Store(Register dst_addr, uint32_t offset_imm,
Register src, int size,
PinnedRegisterScope pinned) {
Operand dst_op = Operand(dst_addr, offset_imm);
if (offset_imm > kMaxInt) {
// The immediate can not be encoded in the operand. Load it to a register
// first.
Register dst = GetUnusedRegister(kWasmPtrSizeInt, pinned);
movl(dst, Immediate(offset_imm));
dst_op = Operand(dst_addr, dst, times_1, 0);
}
DCHECK(size == 4 || size == 8);
if (size == 4) {
movl(dst_op, src);
} else {
movp(dst_op, src);
}
} }
void LiftoffAssembler::LoadCallerFrameSlot(Register dst, void LiftoffAssembler::LoadCallerFrameSlot(Register dst,
uint32_t caller_slot_idx) { uint32_t caller_slot_idx) {
movl(dst, Operand(rbp, 8 + 8 * caller_slot_idx)); constexpr int32_t kStackSlotSize = 8;
movl(dst, Operand(rbp, kStackSlotSize * (caller_slot_idx + 1)));
} }
void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index,
......
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