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