Commit 2c0edb48 authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[wasm] Rename XXXOperand to XXXImmediate

R=clemensh@chromium.org
CC=ahaas@chromium.org

Change-Id: Ibcbc5e43e7095d9783f49ad2c3f27338100c4fdf
Reviewed-on: https://chromium-review.googlesource.com/1039489
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52953}
parent 39496a95
......@@ -1089,21 +1089,20 @@ class LiftoffCompiler {
}
void GetLocal(Decoder* decoder, Value* result,
const LocalIndexOperand<validate>& operand) {
auto& slot = __ cache_state()->stack_state[operand.index];
DCHECK_EQ(slot.type(), operand.type);
const LocalIndexImmediate<validate>& imm) {
auto& slot = __ cache_state()->stack_state[imm.index];
DCHECK_EQ(slot.type(), imm.type);
switch (slot.loc()) {
case kRegister:
__ PushRegister(slot.type(), slot.reg());
break;
case KIntConst:
__ cache_state()->stack_state.emplace_back(operand.type,
slot.i32_const());
__ cache_state()->stack_state.emplace_back(imm.type, slot.i32_const());
break;
case kStack: {
auto rc = reg_class_for(operand.type);
auto rc = reg_class_for(imm.type);
LiftoffRegister reg = __ GetUnusedRegister(rc);
__ Fill(reg, operand.index, operand.type);
__ Fill(reg, imm.index, imm.type);
__ PushRegister(slot.type(), reg);
break;
}
......@@ -1152,13 +1151,13 @@ class LiftoffCompiler {
}
void SetLocal(Decoder* decoder, const Value& value,
const LocalIndexOperand<validate>& operand) {
SetLocal(operand.index, false);
const LocalIndexImmediate<validate>& imm) {
SetLocal(imm.index, false);
}
void TeeLocal(Decoder* decoder, const Value& value, Value* result,
const LocalIndexOperand<validate>& operand) {
SetLocal(operand.index, true);
const LocalIndexImmediate<validate>& imm) {
SetLocal(imm.index, true);
}
LiftoffRegister GetGlobalBaseAndOffset(const WasmGlobal* global,
......@@ -1179,8 +1178,8 @@ class LiftoffCompiler {
}
void GetGlobal(Decoder* decoder, Value* result,
const GlobalIndexOperand<validate>& operand) {
const auto* global = &env_->module->globals[operand.index];
const GlobalIndexImmediate<validate>& imm) {
const auto* global = &env_->module->globals[imm.index];
if (!CheckSupportedType(decoder, kTypes_ilfd, global->type, "global"))
return;
LiftoffRegList pinned;
......@@ -1194,8 +1193,8 @@ class LiftoffCompiler {
}
void SetGlobal(Decoder* decoder, const Value& value,
const GlobalIndexOperand<validate>& operand) {
auto* global = &env_->module->globals[operand.index];
const GlobalIndexImmediate<validate>& imm) {
auto* global = &env_->module->globals[imm.index];
if (!CheckSupportedType(decoder, kTypes_ilfd, global->type, "global"))
return;
LiftoffRegList pinned;
......@@ -1301,22 +1300,22 @@ class LiftoffCompiler {
br_targets);
}
void BrTable(Decoder* decoder, const BranchTableOperand<validate>& operand,
void BrTable(Decoder* decoder, const BranchTableImmediate<validate>& imm,
const Value& key) {
LiftoffRegList pinned;
LiftoffRegister value = pinned.set(__ PopToRegister());
BranchTableIterator<validate> table_iterator(decoder, operand);
BranchTableIterator<validate> table_iterator(decoder, imm);
std::map<uint32_t, MovableLabel> br_targets;
if (operand.table_count > 0) {
if (imm.table_count > 0) {
LiftoffRegister tmp = __ GetUnusedRegister(kGpReg, pinned);
__ LoadConstant(tmp, WasmValue(uint32_t{operand.table_count}));
__ LoadConstant(tmp, WasmValue(uint32_t{imm.table_count}));
Label case_default;
__ emit_cond_jump(kUnsignedGreaterEqual, &case_default, kWasmI32,
value.gp(), tmp.gp());
GenerateBrTable(decoder, tmp, value, 0, operand.table_count,
table_iterator, br_targets);
GenerateBrTable(decoder, tmp, value, 0, imm.table_count, table_iterator,
br_targets);
__ bind(&case_default);
}
......@@ -1467,13 +1466,13 @@ class LiftoffCompiler {
}
void LoadMem(Decoder* decoder, LoadType type,
const MemoryAccessOperand<validate>& operand,
const MemoryAccessImmediate<validate>& imm,
const Value& index_val, Value* result) {
ValueType value_type = type.value_type();
if (!CheckSupportedType(decoder, kTypes_ilfd, value_type, "load")) return;
LiftoffRegList pinned;
Register index = pinned.set(__ PopToRegister()).gp();
if (BoundsCheckMem(decoder, type.size(), operand.offset, index, pinned)) {
if (BoundsCheckMem(decoder, type.size(), imm.offset, index, pinned)) {
return;
}
LiftoffRegister addr = pinned.set(__ GetUnusedRegister(kGpReg, pinned));
......@@ -1481,7 +1480,7 @@ class LiftoffCompiler {
RegClass rc = reg_class_for(value_type);
LiftoffRegister value = pinned.set(__ GetUnusedRegister(rc, pinned));
uint32_t protected_load_pc = 0;
__ Load(value, addr.gp(), index, operand.offset, type, pinned,
__ Load(value, addr.gp(), index, imm.offset, type, pinned,
&protected_load_pc, true);
if (env_->use_trap_handler) {
AddOutOfLineTrap(decoder->position(),
......@@ -1492,25 +1491,25 @@ class LiftoffCompiler {
if (FLAG_wasm_trace_memory) {
TraceMemoryOperation(false, type.mem_type().representation(), index,
operand.offset, decoder->position());
imm.offset, decoder->position());
}
}
void StoreMem(Decoder* decoder, StoreType type,
const MemoryAccessOperand<validate>& operand,
const MemoryAccessImmediate<validate>& imm,
const Value& index_val, const Value& value_val) {
ValueType value_type = type.value_type();
if (!CheckSupportedType(decoder, kTypes_ilfd, value_type, "store")) return;
LiftoffRegList pinned;
LiftoffRegister value = pinned.set(__ PopToRegister());
Register index = pinned.set(__ PopToRegister(pinned)).gp();
if (BoundsCheckMem(decoder, type.size(), operand.offset, index, pinned)) {
if (BoundsCheckMem(decoder, type.size(), imm.offset, index, pinned)) {
return;
}
LiftoffRegister addr = pinned.set(__ GetUnusedRegister(kGpReg, pinned));
LOAD_INSTANCE_FIELD(addr, MemoryStart, kPointerLoadType);
uint32_t protected_store_pc = 0;
__ Store(addr.gp(), index, operand.offset, value, type, pinned,
__ Store(addr.gp(), index, imm.offset, value, type, pinned,
&protected_store_pc, true);
if (env_->use_trap_handler) {
AddOutOfLineTrap(decoder->position(),
......@@ -1518,7 +1517,7 @@ class LiftoffCompiler {
protected_store_pc);
}
if (FLAG_wasm_trace_memory) {
TraceMemoryOperation(true, type.mem_rep(), index, operand.offset,
TraceMemoryOperation(true, type.mem_rep(), index, imm.offset,
decoder->position());
}
}
......@@ -1540,22 +1539,21 @@ class LiftoffCompiler {
unsupported(decoder, "grow_memory");
}
void CallDirect(Decoder* decoder,
const CallFunctionOperand<validate>& operand,
void CallDirect(Decoder* decoder, const CallFunctionImmediate<validate>& imm,
const Value args[], Value returns[]) {
if (operand.sig->return_count() > 1)
if (imm.sig->return_count() > 1)
return unsupported(decoder, "multi-return");
if (operand.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
if (imm.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kTypes_ilfd, imm.sig->GetReturn(0),
"return"))
return;
auto call_descriptor =
compiler::GetWasmCallDescriptor(compilation_zone_, operand.sig);
compiler::GetWasmCallDescriptor(compilation_zone_, imm.sig);
call_descriptor =
GetLoweredCallDescriptor(compilation_zone_, call_descriptor);
if (operand.index < env_->module->num_imported_functions) {
if (imm.index < env_->module->num_imported_functions) {
// A direct call to an imported function.
LiftoffRegList pinned;
LiftoffRegister tmp = pinned.set(__ GetUnusedRegister(kGpReg, pinned));
......@@ -1565,55 +1563,54 @@ class LiftoffCompiler {
LOAD_INSTANCE_FIELD(imported_targets, ImportedFunctionTargets,
kPointerLoadType);
__ Load(target, imported_targets.gp(), no_reg,
operand.index * sizeof(Address), kPointerLoadType, pinned);
imm.index * sizeof(Address), kPointerLoadType, pinned);
LiftoffRegister imported_instances = tmp;
LOAD_INSTANCE_FIELD(imported_instances, ImportedFunctionInstances,
kPointerLoadType);
LiftoffRegister target_instance = tmp;
__ Load(target_instance, imported_instances.gp(), no_reg,
compiler::FixedArrayOffsetMinusTag(operand.index),
kPointerLoadType, pinned);
compiler::FixedArrayOffsetMinusTag(imm.index), kPointerLoadType,
pinned);
LiftoffRegister* explicit_instance = &target_instance;
Register target_reg = target.gp();
__ PrepareCall(operand.sig, call_descriptor, &target_reg,
explicit_instance);
__ PrepareCall(imm.sig, call_descriptor, &target_reg, explicit_instance);
source_position_table_builder_->AddPosition(
__ pc_offset(), SourcePosition(decoder->position()), false);
__ CallIndirect(operand.sig, call_descriptor, target_reg);
__ CallIndirect(imm.sig, call_descriptor, target_reg);
safepoint_table_builder_.DefineSafepoint(asm_, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ FinishCall(operand.sig, call_descriptor);
__ FinishCall(imm.sig, call_descriptor);
} else {
// A direct call within this module just gets the current instance.
__ PrepareCall(operand.sig, call_descriptor);
__ PrepareCall(imm.sig, call_descriptor);
source_position_table_builder_->AddPosition(
__ pc_offset(), SourcePosition(decoder->position()), false);
// Just encode the function index. This will be patched at instantiation.
Address addr = static_cast<Address>(operand.index);
Address addr = static_cast<Address>(imm.index);
__ CallNativeWasmCode(addr);
safepoint_table_builder_.DefineSafepoint(asm_, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ FinishCall(operand.sig, call_descriptor);
__ FinishCall(imm.sig, call_descriptor);
}
}
void CallIndirect(Decoder* decoder, const Value& index_val,
const CallIndirectOperand<validate>& operand,
const CallIndirectImmediate<validate>& imm,
const Value args[], Value returns[]) {
if (operand.sig->return_count() > 1) {
if (imm.sig->return_count() > 1) {
return unsupported(decoder, "multi-return");
}
if (operand.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kTypes_ilfd, operand.sig->GetReturn(0),
if (imm.sig->return_count() == 1 &&
!CheckSupportedType(decoder, kTypes_ilfd, imm.sig->GetReturn(0),
"return")) {
return;
}
......@@ -1640,7 +1637,7 @@ class LiftoffCompiler {
Label* invalid_func_label = AddOutOfLineTrap(
decoder->position(), Builtins::kThrowWasmTrapFuncInvalid);
uint32_t canonical_sig_num = env_->module->signature_ids[operand.sig_index];
uint32_t canonical_sig_num = env_->module->signature_ids[imm.sig_index];
DCHECK_GE(canonical_sig_num, 0);
DCHECK_GE(kMaxInt, canonical_sig_num);
......@@ -1691,18 +1688,18 @@ class LiftoffCompiler {
__ pc_offset(), SourcePosition(decoder->position()), false);
auto call_descriptor =
compiler::GetWasmCallDescriptor(compilation_zone_, operand.sig);
compiler::GetWasmCallDescriptor(compilation_zone_, imm.sig);
call_descriptor =
GetLoweredCallDescriptor(compilation_zone_, call_descriptor);
Register target = scratch.gp();
__ PrepareCall(operand.sig, call_descriptor, &target, explicit_instance);
__ CallIndirect(operand.sig, call_descriptor, target);
__ PrepareCall(imm.sig, call_descriptor, &target, explicit_instance);
__ CallIndirect(imm.sig, call_descriptor, target);
safepoint_table_builder_.DefineSafepoint(asm_, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ FinishCall(operand.sig, call_descriptor);
__ FinishCall(imm.sig, call_descriptor);
}
void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
......@@ -1710,32 +1707,32 @@ class LiftoffCompiler {
unsupported(decoder, "simd");
}
void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
const SimdLaneOperand<validate>& operand,
const SimdLaneImmediate<validate>& imm,
const Vector<Value> inputs, Value* result) {
unsupported(decoder, "simd");
}
void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
const SimdShiftOperand<validate>& operand,
const Value& input, Value* result) {
const SimdShiftImmediate<validate>& imm, const Value& input,
Value* result) {
unsupported(decoder, "simd");
}
void Simd8x16ShuffleOp(Decoder* decoder,
const Simd8x16ShuffleOperand<validate>& operand,
const Simd8x16ShuffleImmediate<validate>& imm,
const Value& input0, const Value& input1,
Value* result) {
unsupported(decoder, "simd");
}
void Throw(Decoder* decoder, const ExceptionIndexOperand<validate>&,
void Throw(Decoder* decoder, const ExceptionIndexImmediate<validate>&,
Control* block, const Vector<Value>& args) {
unsupported(decoder, "throw");
}
void CatchException(Decoder* decoder,
const ExceptionIndexOperand<validate>& operand,
const ExceptionIndexImmediate<validate>& imm,
Control* block, Vector<Value> caught_values) {
unsupported(decoder, "catch");
}
void AtomicOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
const MemoryAccessOperand<validate>& operand, Value* result) {
const MemoryAccessImmediate<validate>& imm, Value* result) {
unsupported(decoder, "atomicop");
}
......
......@@ -126,53 +126,52 @@ Vector<T> vec2vec(std::vector<T, Allocator>& vec) {
return Vector<T>(vec.data(), vec.size());
}
// Helpers for decoding different kinds of operands which follow bytecodes.
// Helpers for decoding different kinds of immediates which follow bytecodes.
template <Decoder::ValidateFlag validate>
struct LocalIndexOperand {
struct LocalIndexImmediate {
uint32_t index;
ValueType type = kWasmStmt;
unsigned length;
inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
}
};
template <Decoder::ValidateFlag validate>
struct ExceptionIndexOperand {
struct ExceptionIndexImmediate {
uint32_t index;
const WasmException* exception = nullptr;
unsigned length;
inline ExceptionIndexOperand(Decoder* decoder, const byte* pc) {
inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
}
};
template <Decoder::ValidateFlag validate>
struct ImmI32Operand {
struct ImmI32Immediate {
int32_t value;
unsigned length;
inline ImmI32Operand(Decoder* decoder, const byte* pc) {
inline ImmI32Immediate(Decoder* decoder, const byte* pc) {
value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
}
};
template <Decoder::ValidateFlag validate>
struct ImmI64Operand {
struct ImmI64Immediate {
int64_t value;
unsigned length;
inline ImmI64Operand(Decoder* decoder, const byte* pc) {
inline ImmI64Immediate(Decoder* decoder, const byte* pc) {
value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
}
};
template <Decoder::ValidateFlag validate>
struct ImmF32Operand {
struct ImmF32Immediate {
float value;
unsigned length = 4;
inline ImmF32Operand(Decoder* decoder, const byte* pc) {
inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
// Avoid bit_cast because it might not preserve the signalling bit of a NaN.
uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
memcpy(&value, &tmp, sizeof(value));
......@@ -180,10 +179,10 @@ struct ImmF32Operand {
};
template <Decoder::ValidateFlag validate>
struct ImmF64Operand {
struct ImmF64Immediate {
double value;
unsigned length = 8;
inline ImmF64Operand(Decoder* decoder, const byte* pc) {
inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
// Avoid bit_cast because it might not preserve the signalling bit of a NaN.
uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
memcpy(&value, &tmp, sizeof(value));
......@@ -191,25 +190,25 @@ struct ImmF64Operand {
};
template <Decoder::ValidateFlag validate>
struct GlobalIndexOperand {
struct GlobalIndexImmediate {
uint32_t index;
ValueType type = kWasmStmt;
const WasmGlobal* global = nullptr;
unsigned length;
inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
}
};
template <Decoder::ValidateFlag validate>
struct BlockTypeOperand {
struct BlockTypeImmediate {
unsigned length = 1;
ValueType type = kWasmStmt;
uint32_t sig_index = 0;
FunctionSig* sig = nullptr;
inline BlockTypeOperand(Decoder* decoder, const byte* pc) {
inline BlockTypeImmediate(Decoder* decoder, const byte* pc) {
uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
if (!decode_local_type(val, &type)) {
// Handle multi-value blocks.
......@@ -280,21 +279,21 @@ struct BlockTypeOperand {
};
template <Decoder::ValidateFlag validate>
struct BreakDepthOperand {
struct BreakDepthImmediate {
uint32_t depth;
unsigned length;
inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
inline BreakDepthImmediate(Decoder* decoder, const byte* pc) {
depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth");
}
};
template <Decoder::ValidateFlag validate>
struct CallIndirectOperand {
struct CallIndirectImmediate {
uint32_t table_index;
uint32_t sig_index;
FunctionSig* sig = nullptr;
unsigned length = 0;
inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
unsigned len = 0;
sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
if (!VALIDATE(decoder->ok())) return;
......@@ -308,20 +307,20 @@ struct CallIndirectOperand {
};
template <Decoder::ValidateFlag validate>
struct CallFunctionOperand {
struct CallFunctionImmediate {
uint32_t index;
FunctionSig* sig = nullptr;
unsigned length;
inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
}
};
template <Decoder::ValidateFlag validate>
struct MemoryIndexOperand {
struct MemoryIndexImmediate {
uint32_t index;
unsigned length = 1;
inline MemoryIndexOperand(Decoder* decoder, const byte* pc) {
inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
index = decoder->read_u8<validate>(pc + 1, "memory index");
if (!VALIDATE(index == 0)) {
decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
......@@ -330,11 +329,11 @@ struct MemoryIndexOperand {
};
template <Decoder::ValidateFlag validate>
struct BranchTableOperand {
struct BranchTableImmediate {
uint32_t table_count;
const byte* start;
const byte* table;
inline BranchTableOperand(Decoder* decoder, const byte* pc) {
inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
start = pc + 1;
unsigned len = 0;
......@@ -358,7 +357,7 @@ class BranchTableIterator {
pc_ += length;
return result;
}
// length, including the length of the {BranchTableOperand}, but not the
// length, including the length of the {BranchTableImmediate}, but not the
// opcode.
unsigned length() {
while (has_next()) next();
......@@ -367,12 +366,12 @@ class BranchTableIterator {
const byte* pc() { return pc_; }
BranchTableIterator(Decoder* decoder,
const BranchTableOperand<validate>& operand)
const BranchTableImmediate<validate>& imm)
: decoder_(decoder),
start_(operand.start),
pc_(operand.table),
start_(imm.start),
pc_(imm.table),
index_(0),
table_count_(operand.table_count) {}
table_count_(imm.table_count) {}
private:
Decoder* decoder_;
......@@ -383,12 +382,12 @@ class BranchTableIterator {
};
template <Decoder::ValidateFlag validate>
struct MemoryAccessOperand {
struct MemoryAccessImmediate {
uint32_t alignment;
uint32_t offset;
unsigned length = 0;
inline MemoryAccessOperand(Decoder* decoder, const byte* pc,
uint32_t max_alignment) {
inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
uint32_t max_alignment) {
unsigned alignment_length;
alignment =
decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
......@@ -406,34 +405,34 @@ struct MemoryAccessOperand {
}
};
// Operand for SIMD lane operations.
// Immediate for SIMD lane operations.
template <Decoder::ValidateFlag validate>
struct SimdLaneOperand {
struct SimdLaneImmediate {
uint8_t lane;
unsigned length = 1;
inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
lane = decoder->read_u8<validate>(pc + 2, "lane");
}
};
// Operand for SIMD shift operations.
// Immediate for SIMD shift operations.
template <Decoder::ValidateFlag validate>
struct SimdShiftOperand {
struct SimdShiftImmediate {
uint8_t shift;
unsigned length = 1;
inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
shift = decoder->read_u8<validate>(pc + 2, "shift");
}
};
// Operand for SIMD S8x16 shuffle operations.
// Immediate for SIMD S8x16 shuffle operations.
template <Decoder::ValidateFlag validate>
struct Simd8x16ShuffleOperand {
struct Simd8x16ShuffleImmediate {
uint8_t shuffle[kSimd128Size] = {0};
inline Simd8x16ShuffleOperand(Decoder* decoder, const byte* pc) {
inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
for (uint32_t i = 0; i < kSimd128Size; ++i) {
shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
if (!VALIDATE(decoder->ok())) return;
......@@ -590,72 +589,71 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
// This is the list of callback functions that an interface for the
// WasmFullDecoder should implement.
// F(Name, args...)
#define INTERFACE_FUNCTIONS(F) \
/* General: */ \
F(StartFunction) \
F(StartFunctionBody, Control* block) \
F(FinishFunction) \
F(OnFirstError) \
F(NextInstruction, WasmOpcode) \
/* Control: */ \
F(Block, Control* block) \
F(Loop, Control* block) \
F(Try, Control* block) \
F(If, const Value& cond, Control* if_block) \
F(FallThruTo, Control* c) \
F(PopControl, Control* block) \
F(EndControl, Control* block) \
/* Instructions: */ \
F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs, \
const Value& rhs, Value* result) \
F(I32Const, Value* result, int32_t value) \
F(I64Const, Value* result, int64_t value) \
F(F32Const, Value* result, float value) \
F(F64Const, Value* result, double value) \
F(RefNull, Value* result) \
F(Drop, const Value& value) \
F(DoReturn, Vector<Value> values, bool implicit) \
F(GetLocal, Value* result, const LocalIndexOperand<validate>& operand) \
F(SetLocal, const Value& value, const LocalIndexOperand<validate>& operand) \
F(TeeLocal, const Value& value, Value* result, \
const LocalIndexOperand<validate>& operand) \
F(GetGlobal, Value* result, const GlobalIndexOperand<validate>& operand) \
F(SetGlobal, const Value& value, \
const GlobalIndexOperand<validate>& operand) \
F(Unreachable) \
F(Select, const Value& cond, const Value& fval, const Value& tval, \
Value* result) \
F(Br, Control* target) \
F(BrIf, const Value& cond, Control* target) \
F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \
F(Else, Control* if_block) \
F(LoadMem, LoadType type, const MemoryAccessOperand<validate>& operand, \
const Value& index, Value* result) \
F(StoreMem, StoreType type, const MemoryAccessOperand<validate>& operand, \
const Value& index, const Value& value) \
F(CurrentMemoryPages, Value* result) \
F(GrowMemory, const Value& value, Value* result) \
F(CallDirect, const CallFunctionOperand<validate>& operand, \
const Value args[], Value returns[]) \
F(CallIndirect, const Value& index, \
const CallIndirectOperand<validate>& operand, const Value args[], \
Value returns[]) \
F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \
F(SimdLaneOp, WasmOpcode opcode, const SimdLaneOperand<validate>& operand, \
const Vector<Value> inputs, Value* result) \
F(SimdShiftOp, WasmOpcode opcode, const SimdShiftOperand<validate>& operand, \
const Value& input, Value* result) \
F(Simd8x16ShuffleOp, const Simd8x16ShuffleOperand<validate>& operand, \
const Value& input0, const Value& input1, Value* result) \
F(Throw, const ExceptionIndexOperand<validate>&, Control* block, \
const Vector<Value>& args) \
F(CatchException, const ExceptionIndexOperand<validate>& operand, \
Control* block, Vector<Value> caught_values) \
F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
const MemoryAccessOperand<validate>& operand, Value* result)
// Generic Wasm bytecode decoder with utilities for decoding operands,
#define INTERFACE_FUNCTIONS(F) \
/* General: */ \
F(StartFunction) \
F(StartFunctionBody, Control* block) \
F(FinishFunction) \
F(OnFirstError) \
F(NextInstruction, WasmOpcode) \
/* Control: */ \
F(Block, Control* block) \
F(Loop, Control* block) \
F(Try, Control* block) \
F(If, const Value& cond, Control* if_block) \
F(FallThruTo, Control* c) \
F(PopControl, Control* block) \
F(EndControl, Control* block) \
/* Instructions: */ \
F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs, \
const Value& rhs, Value* result) \
F(I32Const, Value* result, int32_t value) \
F(I64Const, Value* result, int64_t value) \
F(F32Const, Value* result, float value) \
F(F64Const, Value* result, double value) \
F(RefNull, Value* result) \
F(Drop, const Value& value) \
F(DoReturn, Vector<Value> values, bool implicit) \
F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm) \
F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm) \
F(TeeLocal, const Value& value, Value* result, \
const LocalIndexImmediate<validate>& imm) \
F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm) \
F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
F(Unreachable) \
F(Select, const Value& cond, const Value& fval, const Value& tval, \
Value* result) \
F(Br, Control* target) \
F(BrIf, const Value& cond, Control* target) \
F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \
F(Else, Control* if_block) \
F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \
const Value& index, Value* result) \
F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \
const Value& index, const Value& value) \
F(CurrentMemoryPages, Value* result) \
F(GrowMemory, const Value& value, Value* result) \
F(CallDirect, const CallFunctionImmediate<validate>& imm, \
const Value args[], Value returns[]) \
F(CallIndirect, const Value& index, \
const CallIndirectImmediate<validate>& imm, const Value args[], \
Value returns[]) \
F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \
F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \
const Vector<Value> inputs, Value* result) \
F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm, \
const Value& input, Value* result) \
F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm, \
const Value& input0, const Value& input1, Value* result) \
F(Throw, const ExceptionIndexImmediate<validate>&, Control* block, \
const Vector<Value>& args) \
F(CatchException, const ExceptionIndexImmediate<validate>& imm, \
Control* block, Vector<Value> caught_values) \
F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
const MemoryAccessImmediate<validate>& imm, Value* result)
// Generic Wasm bytecode decoder with utilities for decoding immediates,
// lengths, etc.
template <Decoder::ValidateFlag validate>
class WasmDecoder : public Decoder {
......@@ -762,13 +760,13 @@ class WasmDecoder : public Decoder {
break;
case kExprSetLocal: // fallthru
case kExprTeeLocal: {
LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
if (assigned->length() > 0 &&
operand.index < static_cast<uint32_t>(assigned->length())) {
imm.index < static_cast<uint32_t>(assigned->length())) {
// Unverified code might have an out-of-bounds index.
assigned->Add(operand.index);
assigned->Add(imm.index);
}
length = 1 + operand.length;
length = 1 + imm.length;
break;
}
case kExprGrowMemory:
......@@ -793,96 +791,94 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc,
LocalIndexOperand<Decoder::kValidate>& operand) {
if (!VALIDATE(operand.index < total_locals())) {
errorf(pc + 1, "invalid local index: %u", operand.index);
LocalIndexImmediate<Decoder::kValidate>& imm) {
if (!VALIDATE(imm.index < total_locals())) {
errorf(pc + 1, "invalid local index: %u", imm.index);
return false;
}
operand.type = local_types_ ? local_types_->at(operand.index) : kWasmStmt;
imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
return true;
}
inline bool Validate(const byte* pc,
ExceptionIndexOperand<validate>& operand) {
inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
if (!VALIDATE(module_ != nullptr &&
operand.index < module_->exceptions.size())) {
errorf(pc + 1, "Invalid exception index: %u", operand.index);
imm.index < module_->exceptions.size())) {
errorf(pc + 1, "Invalid exception index: %u", imm.index);
return false;
}
operand.exception = &module_->exceptions[operand.index];
imm.exception = &module_->exceptions[imm.index];
return true;
}
inline bool Validate(const byte* pc, GlobalIndexOperand<validate>& operand) {
if (!VALIDATE(module_ != nullptr &&
operand.index < module_->globals.size())) {
errorf(pc + 1, "invalid global index: %u", operand.index);
inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
errorf(pc + 1, "invalid global index: %u", imm.index);
return false;
}
operand.global = &module_->globals[operand.index];
operand.type = operand.global->type;
imm.global = &module_->globals[imm.index];
imm.type = imm.global->type;
return true;
}
inline bool Complete(const byte* pc, CallFunctionOperand<validate>& operand) {
inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
if (!VALIDATE(module_ != nullptr &&
operand.index < module_->functions.size())) {
imm.index < module_->functions.size())) {
return false;
}
operand.sig = module_->functions[operand.index].sig;
imm.sig = module_->functions[imm.index].sig;
return true;
}
inline bool Validate(const byte* pc, CallFunctionOperand<validate>& operand) {
if (Complete(pc, operand)) {
inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
if (Complete(pc, imm)) {
return true;
}
errorf(pc + 1, "invalid function index: %u", operand.index);
errorf(pc + 1, "invalid function index: %u", imm.index);
return false;
}
inline bool Complete(const byte* pc, CallIndirectOperand<validate>& operand) {
inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
if (!VALIDATE(module_ != nullptr &&
operand.sig_index < module_->signatures.size())) {
imm.sig_index < module_->signatures.size())) {
return false;
}
operand.sig = module_->signatures[operand.sig_index];
imm.sig = module_->signatures[imm.sig_index];
return true;
}
inline bool Validate(const byte* pc, CallIndirectOperand<validate>& operand) {
inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
if (!VALIDATE(module_ != nullptr && !module_->function_tables.empty())) {
error("function table has to exist to execute call_indirect");
return false;
}
if (!Complete(pc, operand)) {
errorf(pc + 1, "invalid signature index: #%u", operand.sig_index);
if (!Complete(pc, imm)) {
errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
return false;
}
return true;
}
inline bool Validate(const byte* pc, BreakDepthOperand<validate>& operand,
inline bool Validate(const byte* pc, BreakDepthImmediate<validate>& imm,
size_t control_depth) {
if (!VALIDATE(operand.depth < control_depth)) {
errorf(pc + 1, "invalid break depth: %u", operand.depth);
if (!VALIDATE(imm.depth < control_depth)) {
errorf(pc + 1, "invalid break depth: %u", imm.depth);
return false;
}
return true;
}
bool Validate(const byte* pc, BranchTableOperand<validate>& operand,
bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
size_t block_depth) {
if (!VALIDATE(operand.table_count < kV8MaxWasmFunctionSize)) {
if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
errorf(pc + 1, "invalid table count (> max function size): %u",
operand.table_count);
imm.table_count);
return false;
}
return checkAvailable(operand.table_count);
return checkAvailable(imm.table_count);
}
inline bool Validate(const byte* pc, WasmOpcode opcode,
SimdLaneOperand<validate>& operand) {
SimdLaneImmediate<validate>& imm) {
uint8_t num_lanes = 0;
switch (opcode) {
case kExprF32x4ExtractLane:
......@@ -903,7 +899,7 @@ class WasmDecoder : public Decoder {
UNREACHABLE();
break;
}
if (!VALIDATE(operand.lane >= 0 && operand.lane < num_lanes)) {
if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
error(pc_ + 2, "invalid lane index");
return false;
} else {
......@@ -912,7 +908,7 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, WasmOpcode opcode,
SimdShiftOperand<validate>& operand) {
SimdShiftImmediate<validate>& imm) {
uint8_t max_shift = 0;
switch (opcode) {
case kExprI32x4Shl:
......@@ -934,7 +930,7 @@ class WasmDecoder : public Decoder {
UNREACHABLE();
break;
}
if (!VALIDATE(operand.shift >= 0 && operand.shift < max_shift)) {
if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
error(pc_ + 2, "invalid shift amount");
return false;
} else {
......@@ -943,10 +939,10 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc,
Simd8x16ShuffleOperand<validate>& operand) {
Simd8x16ShuffleImmediate<validate>& imm) {
uint8_t max_lane = 0;
for (uint32_t i = 0; i < kSimd128Size; ++i)
max_lane = std::max(max_lane, operand.shuffle[i]);
max_lane = std::max(max_lane, imm.shuffle[i]);
// Shuffle indices must be in [0..31] for a 16 lane shuffle.
if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
error(pc_ + 2, "invalid shuffle mask");
......@@ -963,69 +959,69 @@ class WasmDecoder : public Decoder {
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE
{
MemoryAccessOperand<validate> operand(decoder, pc, UINT32_MAX);
return 1 + operand.length;
MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
return 1 + imm.length;
}
case kExprBr:
case kExprBrIf: {
BreakDepthOperand<validate> operand(decoder, pc);
return 1 + operand.length;
BreakDepthImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprSetGlobal:
case kExprGetGlobal: {
GlobalIndexOperand<validate> operand(decoder, pc);
return 1 + operand.length;
GlobalIndexImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprCallFunction: {
CallFunctionOperand<validate> operand(decoder, pc);
return 1 + operand.length;
CallFunctionImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprCallIndirect: {
CallIndirectOperand<validate> operand(decoder, pc);
return 1 + operand.length;
CallIndirectImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprTry:
case kExprIf: // fall through
case kExprLoop:
case kExprBlock: {
BlockTypeOperand<validate> operand(decoder, pc);
return 1 + operand.length;
BlockTypeImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprThrow:
case kExprCatch: {
ExceptionIndexOperand<validate> operand(decoder, pc);
return 1 + operand.length;
ExceptionIndexImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprSetLocal:
case kExprTeeLocal:
case kExprGetLocal: {
LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
return 1 + operand.length;
LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprBrTable: {
BranchTableOperand<validate> operand(decoder, pc);
BranchTableIterator<validate> iterator(decoder, operand);
BranchTableImmediate<validate> imm(decoder, pc);
BranchTableIterator<validate> iterator(decoder, imm);
return 1 + iterator.length();
}
case kExprI32Const: {
ImmI32Operand<validate> operand(decoder, pc);
return 1 + operand.length;
ImmI32Immediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprI64Const: {
ImmI64Operand<validate> operand(decoder, pc);
return 1 + operand.length;
ImmI64Immediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprRefNull: {
return 1;
}
case kExprGrowMemory:
case kExprMemorySize: {
MemoryIndexOperand<validate> operand(decoder, pc);
return 1 + operand.length;
MemoryIndexImmediate<validate> imm(decoder, pc);
return 1 + imm.length;
}
case kExprF32Const:
return 5;
......@@ -1050,8 +1046,8 @@ class WasmDecoder : public Decoder {
FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE
{
MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
return 2 + operand.length;
MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
return 2 + imm.length;
}
// Shuffles require a byte per lane, or 16 immediate bytes.
case kExprS8x16Shuffle:
......@@ -1070,8 +1066,8 @@ class WasmDecoder : public Decoder {
FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE
{
MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
return 2 + operand.length;
MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
return 2 + imm.length;
}
default:
decoder->error(pc, "invalid Atomics opcode");
......@@ -1118,16 +1114,16 @@ class WasmDecoder : public Decoder {
case kExprMemorySize:
return {0, 1};
case kExprCallFunction: {
CallFunctionOperand<validate> operand(this, pc);
CHECK(Complete(pc, operand));
return {operand.sig->parameter_count(), operand.sig->return_count()};
CallFunctionImmediate<validate> imm(this, pc);
CHECK(Complete(pc, imm));
return {imm.sig->parameter_count(), imm.sig->return_count()};
}
case kExprCallIndirect: {
CallIndirectOperand<validate> operand(this, pc);
CHECK(Complete(pc, operand));
CallIndirectImmediate<validate> imm(this, pc);
CHECK(Complete(pc, imm));
// Indirect calls pop an additional argument for the table index.
return {operand.sig->parameter_count() + 1,
operand.sig->return_count()};
return {imm.sig->parameter_count() + 1,
imm.sig->return_count()};
}
case kExprBr:
case kExprBlock:
......@@ -1413,14 +1409,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprNop:
break;
case kExprBlock: {
BlockTypeOperand<validate> operand(this, this->pc_);
if (!LookupBlockType(&operand)) break;
PopArgs(operand.sig);
BlockTypeImmediate<validate> imm(this, this->pc_);
if (!LookupBlockType(&imm)) break;
PopArgs(imm.sig);
auto* block = PushBlock();
SetBlockType(block, operand);
SetBlockType(block, imm);
CALL_INTERFACE_IF_REACHABLE(Block, block);
PushMergeValues(block, &block->start_merge);
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
case kExprRethrow: {
......@@ -1431,23 +1427,23 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprThrow: {
CHECK_PROTOTYPE_OPCODE(eh);
ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
PopArgs(operand.exception->ToFunctionSig());
CALL_INTERFACE_IF_REACHABLE(Throw, operand, &control_.back(),
ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, imm)) break;
PopArgs(imm.exception->ToFunctionSig());
CALL_INTERFACE_IF_REACHABLE(Throw, imm, &control_.back(),
vec2vec(args_));
EndControl();
break;
}
case kExprTry: {
CHECK_PROTOTYPE_OPCODE(eh);
BlockTypeOperand<validate> operand(this, this->pc_);
if (!LookupBlockType(&operand)) break;
PopArgs(operand.sig);
BlockTypeImmediate<validate> imm(this, this->pc_);
if (!LookupBlockType(&imm)) break;
PopArgs(imm.sig);
auto* try_block = PushTry();
SetBlockType(try_block, operand);
len = 1 + operand.length;
SetBlockType(try_block, imm);
len = 1 + imm.length;
CALL_INTERFACE_IF_REACHABLE(Try, try_block);
PushMergeValues(try_block, &try_block->start_merge);
break;
......@@ -1455,10 +1451,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprCatch: {
// TODO(kschimpf): Fix to use type signature of exception.
CHECK_PROTOTYPE_OPCODE(eh);
ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
len = 1 + operand.length;
ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, operand)) break;
if (!this->Validate(this->pc_, imm)) break;
if (!VALIDATE(!control_.empty())) {
this->error("catch does not match any try");
......@@ -1478,14 +1474,13 @@ class WasmFullDecoder : public WasmDecoder<validate> {
c->kind = kControlTryCatch;
FallThruTo(c);
stack_.resize(c->stack_depth);
const WasmExceptionSig* sig = operand.exception->sig;
const WasmExceptionSig* sig = imm.exception->sig;
for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
Push(sig->GetParam(i));
}
Vector<Value> values(stack_.data() + c->stack_depth,
sig->parameter_count());
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, operand, c,
values);
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, imm, c, values);
c->reachability = control_at(1)->innerReachability();
break;
}
......@@ -1496,26 +1491,26 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprLoop: {
BlockTypeOperand<validate> operand(this, this->pc_);
if (!LookupBlockType(&operand)) break;
PopArgs(operand.sig);
BlockTypeImmediate<validate> imm(this, this->pc_);
if (!LookupBlockType(&imm)) break;
PopArgs(imm.sig);
auto* block = PushLoop();
SetBlockType(&control_.back(), operand);
len = 1 + operand.length;
SetBlockType(&control_.back(), imm);
len = 1 + imm.length;
CALL_INTERFACE_IF_REACHABLE(Loop, block);
PushMergeValues(block, &block->start_merge);
break;
}
case kExprIf: {
BlockTypeOperand<validate> operand(this, this->pc_);
if (!LookupBlockType(&operand)) break;
BlockTypeImmediate<validate> imm(this, this->pc_);
if (!LookupBlockType(&imm)) break;
auto cond = Pop(0, kWasmI32);
PopArgs(operand.sig);
PopArgs(imm.sig);
if (!this->ok()) break;
auto* if_block = PushIf();
SetBlockType(if_block, operand);
SetBlockType(if_block, imm);
CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
len = 1 + operand.length;
len = 1 + imm.length;
PushMergeValues(if_block, &if_block->start_merge);
break;
}
......@@ -1588,38 +1583,38 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprBr: {
BreakDepthOperand<validate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand, control_.size())) break;
Control* c = control_at(operand.depth);
BreakDepthImmediate<validate> imm(this, this->pc_);
if (!this->Validate(this->pc_, imm, control_.size())) break;
Control* c = control_at(imm.depth);
if (!TypeCheckBreak(c)) break;
if (control_.back().reachable()) {
CALL_INTERFACE(Br, c);
c->br_merge()->reached = true;
}
len = 1 + operand.length;
len = 1 + imm.length;
EndControl();
break;
}
case kExprBrIf: {
BreakDepthOperand<validate> operand(this, this->pc_);
BreakDepthImmediate<validate> imm(this, this->pc_);
auto cond = Pop(0, kWasmI32);
if (this->failed()) break;
if (!this->Validate(this->pc_, operand, control_.size())) break;
Control* c = control_at(operand.depth);
if (!this->Validate(this->pc_, imm, control_.size())) break;
Control* c = control_at(imm.depth);
if (!TypeCheckBreak(c)) break;
if (control_.back().reachable()) {
CALL_INTERFACE(BrIf, cond, c);
c->br_merge()->reached = true;
}
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
case kExprBrTable: {
BranchTableOperand<validate> operand(this, this->pc_);
BranchTableIterator<validate> iterator(this, operand);
BranchTableImmediate<validate> imm(this, this->pc_);
BranchTableIterator<validate> iterator(this, imm);
auto key = Pop(0, kWasmI32);
if (this->failed()) break;
if (!this->Validate(this->pc_, operand, control_.size())) break;
if (!this->Validate(this->pc_, imm, control_.size())) break;
uint32_t br_arity = 0;
std::vector<bool> br_targets(control_.size());
while (iterator.has_next()) {
......@@ -1651,7 +1646,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (this->failed()) break;
if (control_.back().reachable()) {
CALL_INTERFACE(BrTable, operand, key);
CALL_INTERFACE(BrTable, imm, key);
for (uint32_t depth = control_depth(); depth-- > 0;) {
if (!br_targets[depth]) continue;
......@@ -1673,31 +1668,31 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprI32Const: {
ImmI32Operand<validate> operand(this, this->pc_);
ImmI32Immediate<validate> imm(this, this->pc_);
auto* value = Push(kWasmI32);
CALL_INTERFACE_IF_REACHABLE(I32Const, value, operand.value);
len = 1 + operand.length;
CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
len = 1 + imm.length;
break;
}
case kExprI64Const: {
ImmI64Operand<validate> operand(this, this->pc_);
ImmI64Immediate<validate> imm(this, this->pc_);
auto* value = Push(kWasmI64);
CALL_INTERFACE_IF_REACHABLE(I64Const, value, operand.value);
len = 1 + operand.length;
CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
len = 1 + imm.length;
break;
}
case kExprF32Const: {
ImmF32Operand<validate> operand(this, this->pc_);
ImmF32Immediate<validate> imm(this, this->pc_);
auto* value = Push(kWasmF32);
CALL_INTERFACE_IF_REACHABLE(F32Const, value, operand.value);
len = 1 + operand.length;
CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
len = 1 + imm.length;
break;
}
case kExprF64Const: {
ImmF64Operand<validate> operand(this, this->pc_);
ImmF64Immediate<validate> imm(this, this->pc_);
auto* value = Push(kWasmF64);
CALL_INTERFACE_IF_REACHABLE(F64Const, value, operand.value);
len = 1 + operand.length;
CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
len = 1 + imm.length;
break;
}
case kExprRefNull: {
......@@ -1708,28 +1703,28 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprGetLocal: {
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto* value = Push(operand.type);
CALL_INTERFACE_IF_REACHABLE(GetLocal, value, operand);
len = 1 + operand.length;
LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
if (!this->Validate(this->pc_, imm)) break;
auto* value = Push(imm.type);
CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
len = 1 + imm.length;
break;
}
case kExprSetLocal: {
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto value = Pop(0, local_type_vec_[operand.index]);
CALL_INTERFACE_IF_REACHABLE(SetLocal, value, operand);
len = 1 + operand.length;
LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
if (!this->Validate(this->pc_, imm)) break;
auto value = Pop(0, local_type_vec_[imm.index]);
CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
len = 1 + imm.length;
break;
}
case kExprTeeLocal: {
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto value = Pop(0, local_type_vec_[operand.index]);
LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
if (!this->Validate(this->pc_, imm)) break;
auto value = Pop(0, local_type_vec_[imm.index]);
auto* result = Push(value.type);
CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, operand);
len = 1 + operand.length;
CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
len = 1 + imm.length;
break;
}
case kExprDrop: {
......@@ -1738,24 +1733,24 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprGetGlobal: {
GlobalIndexOperand<validate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
auto* result = Push(operand.type);
CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, operand);
GlobalIndexImmediate<validate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, imm)) break;
auto* result = Push(imm.type);
CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
break;
}
case kExprSetGlobal: {
GlobalIndexOperand<validate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
if (!VALIDATE(operand.global->mutability)) {
GlobalIndexImmediate<validate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, imm)) break;
if (!VALIDATE(imm.global->mutability)) {
this->errorf(this->pc_, "immutable global #%u cannot be assigned",
operand.index);
imm.index);
break;
}
auto value = Pop(0, operand.type);
CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, operand);
auto value = Pop(0, imm.type);
CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
break;
}
case kExprI32LoadMem8S:
......@@ -1829,8 +1824,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
case kExprGrowMemory: {
if (!CheckHasMemory()) break;
MemoryIndexOperand<validate> operand(this, this->pc_);
len = 1 + operand.length;
MemoryIndexImmediate<validate> imm(this, this->pc_);
len = 1 + imm.length;
DCHECK_NOT_NULL(this->module_);
if (!VALIDATE(this->module_->is_wasm())) {
this->error("grow_memory is not supported for asmjs modules");
......@@ -1843,32 +1838,31 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprMemorySize: {
if (!CheckHasMemory()) break;
MemoryIndexOperand<validate> operand(this, this->pc_);
MemoryIndexImmediate<validate> imm(this, this->pc_);
auto* result = Push(kWasmI32);
len = 1 + operand.length;
len = 1 + imm.length;
CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
break;
}
case kExprCallFunction: {
CallFunctionOperand<validate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
CallFunctionImmediate<validate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, imm)) break;
// TODO(clemensh): Better memory management.
PopArgs(operand.sig);
auto* returns = PushReturns(operand.sig);
CALL_INTERFACE_IF_REACHABLE(CallDirect, operand, args_.data(),
returns);
PopArgs(imm.sig);
auto* returns = PushReturns(imm.sig);
CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
break;
}
case kExprCallIndirect: {
CallIndirectOperand<validate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
CallIndirectImmediate<validate> imm(this, this->pc_);
len = 1 + imm.length;
if (!this->Validate(this->pc_, imm)) break;
auto index = Pop(0, kWasmI32);
PopArgs(operand.sig);
auto* returns = PushReturns(operand.sig);
CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, operand,
args_.data(), returns);
PopArgs(imm.sig);
auto* returns = PushReturns(imm.sig);
CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
returns);
break;
}
case kNumericPrefix: {
......@@ -1960,26 +1954,26 @@ class WasmFullDecoder : public WasmDecoder<validate> {
TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
static_cast<int>(val.pc - this->start_),
WasmOpcodes::OpcodeName(opcode));
// If the decoder failed, don't try to decode the operands, as this
// If the decoder failed, don't try to decode the immediates, as this
// can trigger a DCHECK failure.
if (this->failed()) continue;
switch (opcode) {
case kExprI32Const: {
ImmI32Operand<Decoder::kNoValidate> operand(this, val.pc);
TRACE_PART("[%d]", operand.value);
ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
TRACE_PART("[%d]", imm.value);
break;
}
case kExprGetLocal:
case kExprSetLocal:
case kExprTeeLocal: {
LocalIndexOperand<Decoder::kNoValidate> operand(this, val.pc);
TRACE_PART("[%u]", operand.index);
LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
TRACE_PART("[%u]", imm.index);
break;
}
case kExprGetGlobal:
case kExprSetGlobal: {
GlobalIndexOperand<Decoder::kNoValidate> operand(this, val.pc);
TRACE_PART("[%u]", operand.index);
GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
TRACE_PART("[%u]", imm.index);
break;
}
default:
......@@ -2001,18 +1995,18 @@ class WasmFullDecoder : public WasmDecoder<validate> {
current->reachability = kUnreachable;
}
bool LookupBlockType(BlockTypeOperand<validate>* operand) {
if (operand->type == kWasmVar) {
bool LookupBlockType(BlockTypeImmediate<validate>* imm) {
if (imm->type == kWasmVar) {
if (!VALIDATE(this->module_ &&
operand->sig_index < this->module_->signatures.size())) {
imm->sig_index < this->module_->signatures.size())) {
this->errorf(
this->pc_, "block type index %u out of bounds (%d signatures)",
operand->sig_index,
static_cast<int>(this->module_
? this->module_->signatures.size() : 0));
imm->sig_index,
static_cast<int>(this->module_ ? this->module_->signatures.size()
: 0));
return false;
}
operand->sig = this->module_->signatures[operand->sig_index];
imm->sig = this->module_->signatures[imm->sig_index];
}
return true;
}
......@@ -2030,14 +2024,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
}
void SetBlockType(Control* c, BlockTypeOperand<validate>& operand) {
DCHECK_EQ(operand.in_arity(), this->args_.size());
void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
DCHECK_EQ(imm.in_arity(), this->args_.size());
const byte* pc = this->pc_;
Value* args = this->args_.data();
InitMerge(&c->end_merge, operand.out_arity(), [pc, &operand](uint32_t i) {
return Value::New(pc, operand.out_type(i));
InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
return Value::New(pc, imm.out_type(i));
});
InitMerge(&c->start_merge, operand.in_arity(),
InitMerge(&c->start_merge, imm.in_arity(),
[args](uint32_t i) { return args[i]; });
}
......@@ -2093,65 +2087,65 @@ class WasmFullDecoder : public WasmDecoder<validate> {
int DecodeLoadMem(LoadType type, int prefix_len = 0) {
if (!CheckHasMemory()) return 0;
MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
type.size_log_2());
MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
type.size_log_2());
auto index = Pop(0, kWasmI32);
auto* result = Push(type.value_type());
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, operand, index, result);
return operand.length;
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
return imm.length;
}
int DecodeStoreMem(StoreType store, int prefix_len = 0) {
if (!CheckHasMemory()) return 0;
MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
store.size_log_2());
MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
store.size_log_2());
auto value = Pop(1, store.value_type());
auto index = Pop(0, kWasmI32);
CALL_INTERFACE_IF_REACHABLE(StoreMem, store, operand, index, value);
return operand.length;
CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
return imm.length;
}
unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
SimdLaneOperand<validate> operand(this, this->pc_);
if (this->Validate(this->pc_, opcode, operand)) {
SimdLaneImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, opcode, imm)) {
Value inputs[] = {Pop(0, ValueType::kSimd128)};
auto* result = Push(type);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
ArrayVector(inputs), result);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
result);
}
return operand.length;
return imm.length;
}
unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
SimdLaneOperand<validate> operand(this, this->pc_);
if (this->Validate(this->pc_, opcode, operand)) {
SimdLaneImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, opcode, imm)) {
Value inputs[2];
inputs[1] = Pop(1, type);
inputs[0] = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
ArrayVector(inputs), result);
CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
result);
}
return operand.length;
return imm.length;
}
unsigned SimdShiftOp(WasmOpcode opcode) {
SimdShiftOperand<validate> operand(this, this->pc_);
if (this->Validate(this->pc_, opcode, operand)) {
SimdShiftImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, opcode, imm)) {
auto input = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, operand, input, result);
CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
}
return operand.length;
return imm.length;
}
unsigned Simd8x16ShuffleOp() {
Simd8x16ShuffleOperand<validate> operand(this, this->pc_);
if (this->Validate(this->pc_, operand)) {
Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
if (this->Validate(this->pc_, imm)) {
auto input1 = Pop(1, ValueType::kSimd128);
auto input0 = Pop(0, ValueType::kSimd128);
auto* result = Push(ValueType::kSimd128);
CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, operand, input0, input1,
CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
result);
}
return 16;
......@@ -2244,14 +2238,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
this->error("invalid atomic opcode");
return 0;
}
MemoryAccessOperand<validate> operand(
MemoryAccessImmediate<validate> imm(
this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
len += operand.length;
len += imm.length;
PopArgs(sig);
auto result = ret_type == MachineRepresentation::kNone
? nullptr
: Push(GetReturnType(sig));
CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), operand,
CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), imm,
result);
} else {
this->error("invalid atomic opcode");
......
......@@ -251,32 +251,32 @@ class WasmGraphBuildingInterface {
}
void GetLocal(Decoder* decoder, Value* result,
const LocalIndexOperand<validate>& operand) {
const LocalIndexImmediate<validate>& imm) {
if (!ssa_env_->locals) return; // unreachable
result->node = ssa_env_->locals[operand.index];
result->node = ssa_env_->locals[imm.index];
}
void SetLocal(Decoder* decoder, const Value& value,
const LocalIndexOperand<validate>& operand) {
const LocalIndexImmediate<validate>& imm) {
if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.node;
ssa_env_->locals[imm.index] = value.node;
}
void TeeLocal(Decoder* decoder, const Value& value, Value* result,
const LocalIndexOperand<validate>& operand) {
const LocalIndexImmediate<validate>& imm) {
result->node = value.node;
if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.node;
ssa_env_->locals[imm.index] = value.node;
}
void GetGlobal(Decoder* decoder, Value* result,
const GlobalIndexOperand<validate>& operand) {
result->node = BUILD(GetGlobal, operand.index);
const GlobalIndexImmediate<validate>& imm) {
result->node = BUILD(GetGlobal, imm.index);
}
void SetGlobal(Decoder* decoder, const Value& value,
const GlobalIndexOperand<validate>& operand) {
BUILD(SetGlobal, operand.index, value.node);
const GlobalIndexImmediate<validate>& imm) {
BUILD(SetGlobal, imm.index, value.node);
}
void Unreachable(Decoder* decoder) {
......@@ -308,28 +308,28 @@ class WasmGraphBuildingInterface {
ssa_env_ = fenv;
}
void BrTable(Decoder* decoder, const BranchTableOperand<validate>& operand,
void BrTable(Decoder* decoder, const BranchTableImmediate<validate>& imm,
const Value& key) {
if (operand.table_count == 0) {
if (imm.table_count == 0) {
// Only a default target. Do the equivalent of br.
uint32_t target = BranchTableIterator<validate>(decoder, operand).next();
uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
Br(decoder, decoder->control_at(target));
return;
}
SsaEnv* break_env = ssa_env_;
// Build branches to the various blocks based on the table.
TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
SsaEnv* copy = Steal(decoder->zone(), break_env);
ssa_env_ = copy;
BranchTableIterator<validate> iterator(decoder, operand);
BranchTableIterator<validate> iterator(decoder, imm);
while (iterator.has_next()) {
uint32_t i = iterator.cur_index();
uint32_t target = iterator.next();
ssa_env_ = Split(decoder, copy);
ssa_env_->control = (i == operand.table_count) ? BUILD(IfDefault, sw)
: BUILD(IfValue, i, sw);
ssa_env_->control =
(i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
Br(decoder, decoder->control_at(target));
}
DCHECK(decoder->ok());
......@@ -341,19 +341,18 @@ class WasmGraphBuildingInterface {
}
void LoadMem(Decoder* decoder, LoadType type,
const MemoryAccessOperand<validate>& operand, const Value& index,
const MemoryAccessImmediate<validate>& imm, const Value& index,
Value* result) {
result->node =
BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
operand.offset, operand.alignment, decoder->position());
imm.offset, imm.alignment, decoder->position());
}
void StoreMem(Decoder* decoder, StoreType type,
const MemoryAccessOperand<validate>& operand,
const Value& index, const Value& value) {
BUILD(StoreMem, type.mem_rep(), index.node, operand.offset,
operand.alignment, value.node, decoder->position(),
type.value_type());
const MemoryAccessImmediate<validate>& imm, const Value& index,
const Value& value) {
BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
value.node, decoder->position(), type.value_type());
}
void CurrentMemoryPages(Decoder* decoder, Value* result) {
......@@ -366,16 +365,15 @@ class WasmGraphBuildingInterface {
LoadContextIntoSsa(ssa_env_);
}
void CallDirect(Decoder* decoder,
const CallFunctionOperand<validate>& operand,
void CallDirect(Decoder* decoder, const CallFunctionImmediate<validate>& imm,
const Value args[], Value returns[]) {
DoCall(decoder, nullptr, operand.sig, operand.index, args, returns);
DoCall(decoder, nullptr, imm.sig, imm.index, args, returns);
}
void CallIndirect(Decoder* decoder, const Value& index,
const CallIndirectOperand<validate>& operand,
const CallIndirectImmediate<validate>& imm,
const Value args[], Value returns[]) {
DoCall(decoder, index.node, operand.sig, operand.sig_index, args, returns);
DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
}
void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
......@@ -386,48 +384,48 @@ class WasmGraphBuildingInterface {
}
void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
const SimdLaneOperand<validate> operand, Vector<Value> inputs,
const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
Value* result) {
TFNode** nodes = GetNodes(inputs);
result->node = BUILD(SimdLaneOp, opcode, operand.lane, nodes);
result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
}
void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
const SimdShiftOperand<validate> operand, const Value& input,
const SimdShiftImmediate<validate> imm, const Value& input,
Value* result) {
TFNode* inputs[] = {input.node};
result->node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
}
void Simd8x16ShuffleOp(Decoder* decoder,
const Simd8x16ShuffleOperand<validate>& operand,
const Simd8x16ShuffleImmediate<validate>& imm,
const Value& input0, const Value& input1,
Value* result) {
TFNode* input_nodes[] = {input0.node, input1.node};
result->node = BUILD(Simd8x16ShuffleOp, operand.shuffle, input_nodes);
result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
}
TFNode* GetExceptionTag(Decoder* decoder,
const ExceptionIndexOperand<validate>& operand) {
const ExceptionIndexImmediate<validate>& imm) {
// TODO(kschimpf): Need to get runtime exception tag values. This
// code only handles non-imported/exported exceptions.
return BUILD(Int32Constant, operand.index);
return BUILD(Int32Constant, imm.index);
}
void Throw(Decoder* decoder, const ExceptionIndexOperand<validate>& operand,
void Throw(Decoder* decoder, const ExceptionIndexImmediate<validate>& imm,
Control* block, const Vector<Value>& value_args) {
int count = value_args.length();
ZoneVector<TFNode*> args(count, decoder->zone());
for (int i = 0; i < count; ++i) {
args[i] = value_args[i].node;
}
BUILD(Throw, operand.index, operand.exception, vec2vec(args));
BUILD(Throw, imm.index, imm.exception, vec2vec(args));
Unreachable(decoder);
EndControl(decoder, block);
}
void CatchException(Decoder* decoder,
const ExceptionIndexOperand<validate>& operand,
const ExceptionIndexImmediate<validate>& imm,
Control* block, Vector<Value> values) {
DCHECK(block->is_try_catch());
current_catch_ = block->previous_catch;
......@@ -447,8 +445,7 @@ class WasmGraphBuildingInterface {
} else {
// Get the exception and see if wanted exception.
TFNode* caught_tag = BUILD(GetExceptionRuntimeId);
TFNode* exception_tag =
BUILD(ConvertExceptionTagToRuntimeId, operand.index);
TFNode* exception_tag = BUILD(ConvertExceptionTagToRuntimeId, imm.index);
compare_i32 = BUILD(Binop, kExprI32Eq, caught_tag, exception_tag);
}
......@@ -479,7 +476,7 @@ class WasmGraphBuildingInterface {
} else {
// TODO(kschimpf): Can't use BUILD() here, GetExceptionValues() returns
// TFNode** rather than TFNode*. Fix to add landing pads.
TFNode** caught_values = builder_->GetExceptionValues(operand.exception);
TFNode** caught_values = builder_->GetExceptionValues(imm.exception);
for (size_t i = 0, e = values.size(); i < e; ++i) {
values[i].node = caught_values[i];
}
......@@ -487,10 +484,10 @@ class WasmGraphBuildingInterface {
}
void AtomicOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
const MemoryAccessOperand<validate>& operand, Value* result) {
const MemoryAccessImmediate<validate>& imm, Value* result) {
TFNode** inputs = GetNodes(args);
TFNode* node = BUILD(AtomicOp, opcode, inputs, operand.alignment,
operand.offset, decoder->position());
TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
decoder->position());
if (result) result->node = node;
}
......@@ -996,10 +993,10 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
BlockTypeImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // @" << i.pc_offset();
for (unsigned i = 0; i < operand.out_arity(); i++) {
os << " " << ValueTypes::TypeName(operand.out_type(i));
for (unsigned i = 0; i < imm.out_arity(); i++) {
os << " " << ValueTypes::TypeName(imm.out_type(i));
}
control_depth++;
break;
......@@ -1009,33 +1006,33 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
control_depth--;
break;
case kExprBr: {
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // depth=" << operand.depth;
BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // depth=" << imm.depth;
break;
}
case kExprBrIf: {
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // depth=" << operand.depth;
BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // depth=" << imm.depth;
break;
}
case kExprBrTable: {
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // entries=" << operand.table_count;
BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // entries=" << imm.table_count;
break;
}
case kExprCallIndirect: {
CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // sig #" << operand.sig_index;
if (decoder.Complete(i.pc(), operand)) {
os << ": " << *operand.sig;
CallIndirectImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // sig #" << imm.sig_index;
if (decoder.Complete(i.pc(), imm)) {
os << ": " << *imm.sig;
}
break;
}
case kExprCallFunction: {
CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // function #" << operand.index;
if (decoder.Complete(i.pc(), operand)) {
os << ": " << *operand.sig;
CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << " // function #" << imm.index;
if (decoder.Complete(i.pc(), imm)) {
os << ": " << *imm.sig;
}
break;
}
......
......@@ -1159,14 +1159,14 @@ class ModuleDecoderImpl : public Decoder {
unsigned len = 0;
switch (opcode) {
case kExprGetGlobal: {
GlobalIndexOperand<Decoder::kValidate> operand(this, pc() - 1);
if (module->globals.size() <= operand.index) {
GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
if (module->globals.size() <= imm.index) {
error("global index is out of bounds");
expr.kind = WasmInitExpr::kNone;
expr.val.i32_const = 0;
break;
}
WasmGlobal* global = &module->globals[operand.index];
WasmGlobal* global = &module->globals[imm.index];
if (global->mutability || !global->imported) {
error(
"only immutable imported globals can be used in initializer "
......@@ -1176,36 +1176,36 @@ class ModuleDecoderImpl : public Decoder {
break;
}
expr.kind = WasmInitExpr::kGlobalIndex;
expr.val.global_index = operand.index;
len = operand.length;
expr.val.global_index = imm.index;
len = imm.length;
break;
}
case kExprI32Const: {
ImmI32Operand<Decoder::kValidate> operand(this, pc() - 1);
ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
expr.kind = WasmInitExpr::kI32Const;
expr.val.i32_const = operand.value;
len = operand.length;
expr.val.i32_const = imm.value;
len = imm.length;
break;
}
case kExprF32Const: {
ImmF32Operand<Decoder::kValidate> operand(this, pc() - 1);
ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
expr.kind = WasmInitExpr::kF32Const;
expr.val.f32_const = operand.value;
len = operand.length;
expr.val.f32_const = imm.value;
len = imm.length;
break;
}
case kExprI64Const: {
ImmI64Operand<Decoder::kValidate> operand(this, pc() - 1);
ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
expr.kind = WasmInitExpr::kI64Const;
expr.val.i64_const = operand.value;
len = operand.length;
expr.val.i64_const = imm.value;
len = imm.length;
break;
}
case kExprF64Const: {
ImmF64Operand<Decoder::kValidate> operand(this, pc() - 1);
ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
expr.kind = WasmInitExpr::kF64Const;
expr.val.f64_const = operand.value;
len = operand.length;
expr.val.f64_const = imm.value;
len = imm.length;
break;
}
case kExprRefNull: {
......
......@@ -787,35 +787,33 @@ class SideTable : public ZoneObject {
case kExprBlock:
case kExprLoop: {
bool is_loop = opcode == kExprLoop;
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
if (operand.type == kWasmVar) {
operand.sig = module->signatures[operand.sig_index];
BlockTypeImmediate<Decoder::kNoValidate> imm(&i, i.pc());
if (imm.type == kWasmVar) {
imm.sig = module->signatures[imm.sig_index];
}
TRACE("control @%u: %s, arity %d->%d\n", i.pc_offset(),
is_loop ? "Loop" : "Block",
operand.in_arity(), operand.out_arity());
CLabel* label = CLabel::New(&control_transfer_zone, stack_height,
is_loop ? operand.in_arity()
: operand.out_arity());
control_stack.emplace_back(i.pc(), label, operand.out_arity());
is_loop ? "Loop" : "Block", imm.in_arity(), imm.out_arity());
CLabel* label =
CLabel::New(&control_transfer_zone, stack_height,
is_loop ? imm.in_arity() : imm.out_arity());
control_stack.emplace_back(i.pc(), label, imm.out_arity());
copy_unreachable();
if (is_loop) label->Bind(i.pc());
break;
}
case kExprIf: {
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
if (operand.type == kWasmVar) {
operand.sig = module->signatures[operand.sig_index];
BlockTypeImmediate<Decoder::kNoValidate> imm(&i, i.pc());
if (imm.type == kWasmVar) {
imm.sig = module->signatures[imm.sig_index];
}
TRACE("control @%u: If, arity %d->%d\n", i.pc_offset(),
operand.in_arity(), operand.out_arity());
CLabel* end_label =
CLabel::New(&control_transfer_zone, stack_height,
operand.out_arity());
imm.in_arity(), imm.out_arity());
CLabel* end_label = CLabel::New(&control_transfer_zone, stack_height,
imm.out_arity());
CLabel* else_label =
CLabel::New(&control_transfer_zone, stack_height, 0);
control_stack.emplace_back(i.pc(), end_label, else_label,
operand.out_arity());
imm.out_arity());
copy_unreachable();
if (!unreachable) else_label->Ref(i.pc(), stack_height);
break;
......@@ -851,24 +849,24 @@ class SideTable : public ZoneObject {
break;
}
case kExprBr: {
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), operand.depth);
Control* c = &control_stack[control_stack.size() - operand.depth - 1];
BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), imm.depth);
Control* c = &control_stack[control_stack.size() - imm.depth - 1];
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
break;
}
case kExprBrIf: {
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), operand.depth);
Control* c = &control_stack[control_stack.size() - operand.depth - 1];
BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), imm.depth);
Control* c = &control_stack[control_stack.size() - imm.depth - 1];
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
break;
}
case kExprBrTable: {
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, operand);
BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, imm);
TRACE("control @%u: BrTable[count=%u]\n", i.pc_offset(),
operand.table_count);
imm.table_count);
if (!unreachable) {
while (iterator.has_next()) {
uint32_t j = iterator.cur_index();
......@@ -1332,14 +1330,12 @@ class ThreadImpl {
pc_t ReturnPc(Decoder* decoder, InterpreterCode* code, pc_t pc) {
switch (code->orig_start[pc]) {
case kExprCallFunction: {
CallFunctionOperand<Decoder::kNoValidate> operand(decoder,
code->at(pc));
return pc + 1 + operand.length;
CallFunctionImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
return pc + 1 + imm.length;
}
case kExprCallIndirect: {
CallIndirectOperand<Decoder::kNoValidate> operand(decoder,
code->at(pc));
return pc + 1 + operand.length;
CallIndirectImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
return pc + 1 + imm.length;
}
default:
UNREACHABLE();
......@@ -1413,10 +1409,10 @@ class ThreadImpl {
template <typename ctype, typename mtype>
bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
MachineRepresentation rep) {
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc),
sizeof(ctype));
MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc),
sizeof(ctype));
uint32_t index = Pop().to<uint32_t>();
Address addr = BoundsCheckMem<mtype>(operand.offset, index);
Address addr = BoundsCheckMem<mtype>(imm.offset, index);
if (!addr) {
DoTrap(kTrapMemOutOfBounds, pc);
return false;
......@@ -1425,10 +1421,10 @@ class ThreadImpl {
converter<ctype, mtype>{}(ReadLittleEndianValue<mtype>(addr)));
Push(result);
len = 1 + operand.length;
len = 1 + imm.length;
if (FLAG_wasm_trace_memory) {
wasm::MemoryTracingInfo info(operand.offset + index, false, rep);
wasm::MemoryTracingInfo info(imm.offset + index, false, rep);
TraceMemoryOperation(ExecutionEngine::kInterpreter, &info,
code->function->func_index, static_cast<int>(pc),
instance_object_->memory_start());
......@@ -1440,21 +1436,21 @@ class ThreadImpl {
template <typename ctype, typename mtype>
bool ExecuteStore(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
MachineRepresentation rep) {
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc),
sizeof(ctype));
MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc),
sizeof(ctype));
ctype val = Pop().to<ctype>();
uint32_t index = Pop().to<uint32_t>();
Address addr = BoundsCheckMem<mtype>(operand.offset, index);
Address addr = BoundsCheckMem<mtype>(imm.offset, index);
if (!addr) {
DoTrap(kTrapMemOutOfBounds, pc);
return false;
}
WriteLittleEndianValue<mtype>(addr, converter<mtype, ctype>{}(val));
len = 1 + operand.length;
len = 1 + imm.length;
if (FLAG_wasm_trace_memory) {
wasm::MemoryTracingInfo info(operand.offset + index, true, rep);
wasm::MemoryTracingInfo info(imm.offset + index, true, rep);
TraceMemoryOperation(ExecutionEngine::kInterpreter, &info,
code->function->func_index, static_cast<int>(pc),
instance_object_->memory_start());
......@@ -1467,17 +1463,17 @@ class ThreadImpl {
bool ExtractAtomicOpParams(Decoder* decoder, InterpreterCode* code,
Address& address, pc_t pc, int& len,
type* val = nullptr, type* val2 = nullptr) {
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc + 1),
sizeof(type));
MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc + 1),
sizeof(type));
if (val2) *val2 = Pop().to<uint32_t>();
if (val) *val = Pop().to<uint32_t>();
uint32_t index = Pop().to<uint32_t>();
address = BoundsCheckMem<type>(operand.offset, index);
address = BoundsCheckMem<type>(imm.offset, index);
if (!address) {
DoTrap(kTrapMemOutOfBounds, pc);
return false;
}
len = 2 + operand.length;
len = 2 + imm.length;
return true;
}
......@@ -1727,25 +1723,22 @@ class ThreadImpl {
case kExprNop:
break;
case kExprBlock: {
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = 1 + operand.length;
BlockTypeImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
len = 1 + imm.length;
break;
}
case kExprLoop: {
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = 1 + operand.length;
BlockTypeImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
len = 1 + imm.length;
break;
}
case kExprIf: {
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
BlockTypeImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
// fall through to the true block.
len = 1 + operand.length;
len = 1 + imm.length;
TRACE(" true => fallthrough\n");
} else {
len = LookupTargetDelta(code, pc);
......@@ -1766,33 +1759,31 @@ class ThreadImpl {
break;
}
case kExprBr: {
BreakDepthOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = DoBreak(code, pc, operand.depth);
BreakDepthImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
len = DoBreak(code, pc, imm.depth);
TRACE(" br => @%zu\n", pc + len);
break;
}
case kExprBrIf: {
BreakDepthOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
BreakDepthImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
len = DoBreak(code, pc, operand.depth);
len = DoBreak(code, pc, imm.depth);
TRACE(" br_if => @%zu\n", pc + len);
} else {
TRACE(" false => fallthrough\n");
len = 1 + operand.length;
len = 1 + imm.length;
}
break;
}
case kExprBrTable: {
BranchTableOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
BranchTableIterator<Decoder::kNoValidate> iterator(&decoder, operand);
BranchTableImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
BranchTableIterator<Decoder::kNoValidate> iterator(&decoder, imm);
uint32_t key = Pop().to<uint32_t>();
uint32_t depth = 0;
if (key >= operand.table_count) key = operand.table_count;
if (key >= imm.table_count) key = imm.table_count;
for (uint32_t i = 0; i <= key; i++) {
DCHECK(iterator.has_next());
depth = iterator.next();
......@@ -1814,51 +1805,48 @@ class ThreadImpl {
break;
}
case kExprI32Const: {
ImmI32Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
ImmI32Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
Push(WasmValue(imm.value));
len = 1 + imm.length;
break;
}
case kExprI64Const: {
ImmI64Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
ImmI64Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
Push(WasmValue(imm.value));
len = 1 + imm.length;
break;
}
case kExprF32Const: {
ImmF32Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
ImmF32Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
Push(WasmValue(imm.value));
len = 1 + imm.length;
break;
}
case kExprF64Const: {
ImmF64Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
ImmF64Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
Push(WasmValue(imm.value));
len = 1 + imm.length;
break;
}
case kExprGetLocal: {
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
Push(GetStackValue(frames_.back().sp + operand.index));
len = 1 + operand.length;
LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
Push(GetStackValue(frames_.back().sp + imm.index));
len = 1 + imm.length;
break;
}
case kExprSetLocal: {
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
len = 1 + operand.length;
SetStackValue(frames_.back().sp + imm.index, val);
len = 1 + imm.length;
break;
}
case kExprTeeLocal: {
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
SetStackValue(frames_.back().sp + imm.index, val);
Push(val);
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
case kExprDrop: {
......@@ -1866,9 +1854,9 @@ class ThreadImpl {
break;
}
case kExprCallFunction: {
CallFunctionOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
InterpreterCode* target = codemap()->GetCode(operand.index);
CallFunctionImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
InterpreterCode* target = codemap()->GetCode(imm.index);
if (target->function->imported) {
CommitPc(pc);
ExternalCallResult result =
......@@ -1885,7 +1873,7 @@ class ThreadImpl {
UNREACHABLE();
case ExternalCallResult::EXTERNAL_RETURNED:
PAUSE_IF_BREAK_FLAG(AfterCall);
len = 1 + operand.length;
len = 1 + imm.length;
break;
case ExternalCallResult::EXTERNAL_UNWOUND:
return;
......@@ -1899,13 +1887,13 @@ class ThreadImpl {
continue; // don't bump pc
} break;
case kExprCallIndirect: {
CallIndirectOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
CallIndirectImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
uint32_t entry_index = Pop().to<uint32_t>();
// Assume only one table for now.
DCHECK_LE(module()->function_tables.size(), 1u);
ExternalCallResult result =
CallIndirectFunction(0, entry_index, operand.sig_index);
CallIndirectFunction(0, entry_index, imm.sig_index);
switch (result.type) {
case ExternalCallResult::INTERNAL:
// The import is a function of this instance. Call it directly.
......@@ -1920,16 +1908,16 @@ class ThreadImpl {
return DoTrap(kTrapFuncSigMismatch, pc);
case ExternalCallResult::EXTERNAL_RETURNED:
PAUSE_IF_BREAK_FLAG(AfterCall);
len = 1 + operand.length;
len = 1 + imm.length;
break;
case ExternalCallResult::EXTERNAL_UNWOUND:
return;
}
} break;
case kExprGetGlobal: {
GlobalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[imm.index];
byte* ptr = GetGlobalPtr(global);
WasmValue val;
switch (global->type) {
......@@ -1943,13 +1931,13 @@ class ThreadImpl {
UNREACHABLE();
}
Push(val);
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
case kExprSetGlobal: {
GlobalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[imm.index];
byte* ptr = GetGlobalPtr(global);
WasmValue val = Pop();
switch (global->type) {
......@@ -1962,7 +1950,7 @@ class ThreadImpl {
default:
UNREACHABLE();
}
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
......@@ -2053,25 +2041,25 @@ class ThreadImpl {
ASMJS_STORE_CASE(F64AsmjsStoreMem, double, double);
#undef ASMJS_STORE_CASE
case kExprGrowMemory: {
MemoryIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
MemoryIndexImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
uint32_t delta_pages = Pop().to<uint32_t>();
Handle<WasmMemoryObject> memory(instance_object_->memory_object());
Isolate* isolate = memory->GetIsolate();
int32_t result = WasmMemoryObject::Grow(isolate, memory, delta_pages);
Push(WasmValue(result));
len = 1 + operand.length;
len = 1 + imm.length;
// Treat one grow_memory instruction like 1000 other instructions,
// because it is a really expensive operation.
if (max > 0) max = std::max(0, max - 1000);
break;
}
case kExprMemorySize: {
MemoryIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
MemoryIndexImmediate<Decoder::kNoValidate> imm(&decoder,
code->at(pc));
Push(WasmValue(static_cast<uint32_t>(instance_object_->memory_size() /
kWasmPageSize)));
len = 1 + operand.length;
len = 1 + imm.length;
break;
}
// We need to treat kExprI32ReinterpretF32 and kExprI64ReinterpretF64
......
......@@ -100,20 +100,20 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
BlockTypeImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode);
if (operand.type == kWasmVar) {
os << " (type " << operand.sig_index << ")";
} else if (operand.out_arity() > 0) {
os << " " << ValueTypes::TypeName(operand.out_type(0));
if (imm.type == kWasmVar) {
os << " (type " << imm.sig_index << ")";
} else if (imm.out_arity() > 0) {
os << " " << ValueTypes::TypeName(imm.out_type(0));
}
control_depth++;
break;
}
case kExprBr:
case kExprBrIf: {
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.depth;
BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.depth;
break;
}
case kExprElse:
......@@ -124,47 +124,47 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
os << "end";
break;
case kExprBrTable: {
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, operand);
BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, imm);
os << "br_table";
while (iterator.has_next()) os << ' ' << iterator.next();
break;
}
case kExprCallIndirect: {
CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
DCHECK_EQ(0, operand.table_index);
os << "call_indirect " << operand.sig_index;
CallIndirectImmediate<Decoder::kNoValidate> imm(&i, i.pc());
DCHECK_EQ(0, imm.table_index);
os << "call_indirect " << imm.sig_index;
break;
}
case kExprCallFunction: {
CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << "call " << operand.index;
CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << "call " << imm.index;
break;
}
case kExprGetLocal:
case kExprSetLocal:
case kExprTeeLocal: {
LocalIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
LocalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprThrow:
case kExprCatch: {
ExceptionIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
ExceptionIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprGetGlobal:
case kExprSetGlobal: {
GlobalIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
GlobalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
#define CASE_CONST(type, str, cast_type) \
case kExpr##type##Const: { \
Imm##type##Operand<Decoder::kNoValidate> operand(&i, i.pc()); \
os << #str ".const " << static_cast<cast_type>(operand.value); \
break; \
#define CASE_CONST(type, str, cast_type) \
case kExpr##type##Const: { \
Imm##type##Immediate<Decoder::kNoValidate> imm(&i, i.pc()); \
os << #str ".const " << static_cast<cast_type>(imm.value); \
break; \
}
CASE_CONST(I32, i32, int32_t)
CASE_CONST(I64, i64, int64_t)
......@@ -175,10 +175,10 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
#define CASE_OPCODE(opcode, _, __) case kExpr##opcode:
FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
MemoryAccessOperand<Decoder::kNoValidate> operand(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(opcode) << " offset=" << operand.offset
<< " align=" << (1ULL << operand.alignment);
MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(opcode) << " offset=" << imm.offset
<< " align=" << (1ULL << imm.alignment);
break;
}
......@@ -196,11 +196,11 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
WasmOpcode atomic_opcode = i.prefixed_opcode();
switch (atomic_opcode) {
FOREACH_ATOMIC_OPCODE(CASE_OPCODE) {
MemoryAccessOperand<Decoder::kNoValidate> operand(&i, i.pc(),
kMaxUInt32);
MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(atomic_opcode)
<< " offset=" << operand.offset
<< " align=" << (1ULL << operand.alignment);
<< " offset=" << imm.offset
<< " align=" << (1ULL << imm.alignment);
break;
}
default:
......
......@@ -2692,14 +2692,14 @@ class BranchTableIteratorTest : public TestWithZone {
BranchTableIteratorTest() : TestWithZone() {}
void CheckBrTableSize(const byte* start, const byte* end) {
Decoder decoder(start, end);
BranchTableOperand<Decoder::kValidate> operand(&decoder, start);
BranchTableImmediate<Decoder::kValidate> operand(&decoder, start);
BranchTableIterator<Decoder::kValidate> iterator(&decoder, operand);
EXPECT_EQ(end - start - 1u, iterator.length());
EXPECT_TRUE(decoder.ok());
}
void CheckBrTableError(const byte* start, const byte* end) {
Decoder decoder(start, end);
BranchTableOperand<Decoder::kValidate> operand(&decoder, start);
BranchTableImmediate<Decoder::kValidate> operand(&decoder, start);
BranchTableIterator<Decoder::kValidate> iterator(&decoder, operand);
iterator.length();
EXPECT_FALSE(decoder.ok());
......
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