Commit 01e59c4b authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm-gc] Refactoring in preparation of generalizing WasmInitExpr

Motivation: With rtt.sub now allowed in constant expressions, we have
to generalize WasmInitExpr to be able to handle expressions with
operands. This CL prepares the ground for this change and adds no
functionality.

Changes:
- ValueType::heap_representation and HeapType::representation now
  return HeapType::Representation.
- Add ValueType::is_rtt().
- WasmInitExpr:
  - Make kind private. Rename val -> operator, make it private. Add
    accessors.
  - Rename kGlobalIndex -> kGlobalGet.
  - Squash global_index and function_index into index.
  - Add heap_type Immediate. Use it for RefNullConst. TypeOf in
    module-decoder.cc can now fully determine the type of a
    WasmInitExpr.
  - Add class constructors/static method constructors for each Operator
    kind.
  - Delete copy constructor. WasmInitExpr will use std::unique_ptr for
    its operands.
- consume_init_expr now uses a stack.
- A few minor improvements.

Bug: v8:7748
Change-Id: I3ba3ee7ac2d6bc58e887790c37110ceb80658985
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284483
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68759}
parent 607452dc
...@@ -250,10 +250,10 @@ void AsmJsParser::AddGlobalImport(Vector<const char> name, AsmType* type, ...@@ -250,10 +250,10 @@ void AsmJsParser::AddGlobalImport(Vector<const char> name, AsmType* type,
void AsmJsParser::DeclareGlobal(VarInfo* info, bool mutable_variable, void AsmJsParser::DeclareGlobal(VarInfo* info, bool mutable_variable,
AsmType* type, ValueType vtype, AsmType* type, ValueType vtype,
const WasmInitExpr& init) { WasmInitExpr init) {
info->kind = VarKind::kGlobal; info->kind = VarKind::kGlobal;
info->type = type; info->type = type;
info->index = module_builder_->AddGlobal(vtype, true, init); info->index = module_builder_->AddGlobal(vtype, true, std::move(init));
info->mutable_variable = mutable_variable; info->mutable_variable = mutable_variable;
} }
......
...@@ -313,8 +313,7 @@ class AsmJsParser { ...@@ -313,8 +313,7 @@ class AsmJsParser {
VarInfo* GetVarInfo(AsmJsScanner::token_t token); VarInfo* GetVarInfo(AsmJsScanner::token_t token);
uint32_t VarIndex(VarInfo* info); uint32_t VarIndex(VarInfo* info);
void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type, void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type,
ValueType vtype, ValueType vtype, WasmInitExpr init = WasmInitExpr());
const WasmInitExpr& init = WasmInitExpr());
void DeclareStdlibFunc(VarInfo* info, VarKind kind, AsmType* type); void DeclareStdlibFunc(VarInfo* info, VarKind kind, AsmType* type);
void AddGlobalImport(Vector<const char> name, AsmType* type, ValueType vtype, void AddGlobalImport(Vector<const char> name, AsmType* type, ValueType vtype,
bool mutable_variable, VarInfo* info); bool mutable_variable, VarInfo* info);
......
...@@ -3809,7 +3809,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -3809,7 +3809,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values); CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
} }
inline Value* Push(ValueType type) { V8_INLINE Value* Push(ValueType type) {
DCHECK_NE(kWasmStmt, type); DCHECK_NE(kWasmStmt, type);
stack_.emplace_back(this->pc_, type); stack_.emplace_back(this->pc_, type);
return &stack_.back(); return &stack_.back();
......
...@@ -107,12 +107,12 @@ bool validate_utf8(Decoder* decoder, WireBytesRef string) { ...@@ -107,12 +107,12 @@ bool validate_utf8(Decoder* decoder, WireBytesRef string) {
} }
ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
switch (expr.kind) { switch (expr.kind()) {
case WasmInitExpr::kNone: case WasmInitExpr::kNone:
return kWasmStmt; return kWasmStmt;
case WasmInitExpr::kGlobalIndex: case WasmInitExpr::kGlobalGet:
return expr.val.global_index < module->globals.size() return expr.immediate().index < module->globals.size()
? module->globals[expr.val.global_index].type ? module->globals[expr.immediate().index].type
: kWasmStmt; : kWasmStmt;
case WasmInitExpr::kI32Const: case WasmInitExpr::kI32Const:
return kWasmI32; return kWasmI32;
...@@ -125,11 +125,7 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { ...@@ -125,11 +125,7 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
case WasmInitExpr::kRefFuncConst: case WasmInitExpr::kRefFuncConst:
return ValueType::Ref(HeapType::kFunc, kNonNullable); return ValueType::Ref(HeapType::kFunc, kNonNullable);
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
// It is not possible to retrieve the full {ValueType} of a {WasmInitExpr} return ValueType::Ref(expr.immediate().heap_type, kNullable);
// of kind {kRefNullConst}. As WasmInitExpr of kind {krefNullConst} is
// only valid in globals, the {ValueType} has to be retrieved from the
// global definition itself.
UNREACHABLE();
} }
} }
...@@ -940,7 +936,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -940,7 +936,7 @@ class ModuleDecoderImpl : public Decoder {
uint32_t num_elem = uint32_t num_elem =
consume_count("number of elements", max_table_init_entries()); consume_count("number of elements", max_table_init_entries());
if (status == WasmElemSegment::kStatusActive) { if (status == WasmElemSegment::kStatusActive) {
module_->elem_segments.emplace_back(table_index, offset); module_->elem_segments.emplace_back(table_index, std::move(offset));
} else { } else {
module_->elem_segments.emplace_back( module_->elem_segments.emplace_back(
status == WasmElemSegment::kStatusDeclarative); status == WasmElemSegment::kStatusDeclarative);
...@@ -1043,7 +1039,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1043,7 +1039,7 @@ class ModuleDecoderImpl : public Decoder {
uint32_t source_offset = pc_offset(); uint32_t source_offset = pc_offset();
if (is_active) { if (is_active) {
module_->data_segments.emplace_back(dest_addr); module_->data_segments.emplace_back(std::move(dest_addr));
} else { } else {
module_->data_segments.emplace_back(); module_->data_segments.emplace_back();
} }
...@@ -1399,8 +1395,8 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1399,8 +1395,8 @@ class ModuleDecoderImpl : public Decoder {
global->mutability = consume_mutability(); global->mutability = consume_mutability();
const byte* pos = pc(); const byte* pos = pc();
global->init = consume_init_expr(module, global->type); global->init = consume_init_expr(module, global->type);
if (global->init.kind == WasmInitExpr::kGlobalIndex) { if (global->init.kind() == WasmInitExpr::kGlobalGet) {
uint32_t other_index = global->init.val.global_index; uint32_t other_index = global->init.immediate().index;
if (other_index >= index) { if (other_index >= index) {
errorf(pos, errorf(pos,
"invalid global index in init expression, " "invalid global index in init expression, "
...@@ -1610,108 +1606,118 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1610,108 +1606,118 @@ class ModuleDecoderImpl : public Decoder {
} }
WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) { WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
const byte* pos = pc(); constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
uint8_t opcode = consume_u8("opcode"); WasmOpcode opcode = kExprNop;
WasmInitExpr expr; std::vector<WasmInitExpr> stack;
uint32_t len = 0; while (pc() < end() && opcode != kExprEnd) {
switch (opcode) { uint32_t len = 1;
case kExprGlobalGet: { opcode = static_cast<WasmOpcode>(read_u8<validate>(pc(), "opcode"));
GlobalIndexImmediate<Decoder::kValidate> imm(this, pc()); switch (opcode) {
if (module->globals.size() <= imm.index) { case kExprGlobalGet: {
error("global index is out of bounds"); GlobalIndexImmediate<validate> imm(this, pc() + 1);
expr.kind = WasmInitExpr::kNone; len = 1 + imm.length;
expr.val.i32_const = 0; if (V8_UNLIKELY(module->globals.size() <= imm.index)) {
error(pc() + 1, "global index is out of bounds");
break;
}
WasmGlobal* global = &module->globals[imm.index];
if (V8_UNLIKELY(global->mutability || !global->imported)) {
error(pc() + 1,
"only immutable imported globals can be used in initializer "
"expressions");
break;
}
stack.push_back(WasmInitExpr::GlobalGet(imm.index));
break; break;
} }
WasmGlobal* global = &module->globals[imm.index]; case kExprI32Const: {
if (global->mutability || !global->imported) { ImmI32Immediate<Decoder::kValidate> imm(this, pc() + 1);
error( stack.emplace_back(imm.value);
"only immutable imported globals can be used in initializer " len = 1 + imm.length;
"expressions");
expr.kind = WasmInitExpr::kNone;
expr.val.i32_const = 0;
break; break;
} }
expr.kind = WasmInitExpr::kGlobalIndex; case kExprF32Const: {
expr.val.global_index = imm.index; ImmF32Immediate<Decoder::kValidate> imm(this, pc() + 1);
len = imm.length; stack.emplace_back(imm.value);
break; len = 1 + imm.length;
} break;
case kExprI32Const: { }
ImmI32Immediate<Decoder::kValidate> imm(this, pc()); case kExprI64Const: {
expr.kind = WasmInitExpr::kI32Const; ImmI64Immediate<Decoder::kValidate> imm(this, pc() + 1);
expr.val.i32_const = imm.value; stack.emplace_back(imm.value);
len = imm.length; len = 1 + imm.length;
break; break;
} }
case kExprF32Const: { case kExprF64Const: {
ImmF32Immediate<Decoder::kValidate> imm(this, pc()); ImmF64Immediate<Decoder::kValidate> imm(this, pc() + 1);
expr.kind = WasmInitExpr::kF32Const; stack.emplace_back(imm.value);
expr.val.f32_const = imm.value; len = 1 + imm.length;
len = imm.length; break;
break; }
} case kExprRefNull: {
case kExprI64Const: { if (V8_UNLIKELY(!enabled_features_.has_reftypes() &&
ImmI64Immediate<Decoder::kValidate> imm(this, pc()); !enabled_features_.has_eh())) {
expr.kind = WasmInitExpr::kI64Const; errorf(pc(),
expr.val.i64_const = imm.value; "invalid opcode 0x%x in global initializer, enable with "
len = imm.length; "--experimental-wasm-reftypes or --experimental-wasm-eh",
break; kExprRefNull);
} break;
case kExprF64Const: {
ImmF64Immediate<Decoder::kValidate> imm(this, pc());
expr.kind = WasmInitExpr::kF64Const;
expr.val.f64_const = imm.value;
len = imm.length;
break;
}
case kExprRefNull: {
if (enabled_features_.has_reftypes() || enabled_features_.has_eh()) {
HeapTypeImmediate<Decoder::kValidate> imm(WasmFeatures::All(), this,
pc());
expr.kind = WasmInitExpr::kRefNullConst;
len = imm.length;
ValueType type = ValueType::Ref(imm.type, kNullable);
if (expected != kWasmStmt &&
!IsSubtypeOf(type, expected, module_.get())) {
errorf(pos, "type error in init expression, expected %s, got %s",
expected.type_name().c_str(), type.type_name().c_str());
} }
HeapTypeImmediate<Decoder::kValidate> imm(enabled_features_, this,
pc() + 1);
stack.push_back(
WasmInitExpr::RefNullConst(imm.type.representation()));
len = 1 + imm.length;
break; break;
} }
V8_FALLTHROUGH; case kExprRefFunc: {
} if (V8_UNLIKELY(!enabled_features_.has_reftypes())) {
case kExprRefFunc: { errorf(pc(),
if (enabled_features_.has_reftypes()) { "invalid opcode 0x%x in global initializer, enable with "
FunctionIndexImmediate<Decoder::kValidate> imm(this, pc()); "--experimental-wasm-reftypes",
if (module->functions.size() <= imm.index) { kExprRefFunc);
errorf(pc() - 1, "invalid function index: %u", imm.index);
break; break;
} }
expr.kind = WasmInitExpr::kRefFuncConst;
expr.val.function_index = imm.index; FunctionIndexImmediate<Decoder::kValidate> imm(this, pc() + 1);
len = 1 + imm.length;
if (V8_UNLIKELY(module->functions.size() <= imm.index)) {
errorf(pc(), "invalid function index: %u", imm.index);
break;
}
stack.push_back(WasmInitExpr::RefFuncConst(imm.index));
// Functions referenced in the globals section count as "declared". // Functions referenced in the globals section count as "declared".
module->functions[imm.index].declared = true; module->functions[imm.index].declared = true;
len = imm.length;
break; break;
} }
V8_FALLTHROUGH; case kExprEnd:
} if (V8_UNLIKELY(stack.size() != 1)) {
default: { errorf(pc(),
error("invalid opcode in initialization expression"); "Found 'end' in global initalizer, but %s expressions were "
expr.kind = WasmInitExpr::kNone; "found on the stack",
expr.val.i32_const = 0; stack.size() > 1 ? "more than one" : "no");
}
break;
default: {
errorf(pc(), "invalid opcode 0x%x in global initializer", opcode);
return {};
}
} }
pc_ += len;
} }
consume_bytes(len, "init code");
if (!expect_u8("end opcode", kExprEnd)) { if (V8_UNLIKELY(pc() > end())) {
expr.kind = WasmInitExpr::kNone; error(end(), "Global initializer extending beyond code end");
return {};
} }
if (V8_UNLIKELY(this->failed())) return {};
DCHECK_EQ(stack.size(), 1);
// The type check of ref.null is special, and already done above. WasmInitExpr expr = std::move(stack.back());
if (expected != kWasmStmt && opcode != kExprRefNull && if (expected != kWasmStmt &&
!IsSubtypeOf(TypeOf(module, expr), expected, module_.get())) { !IsSubtypeOf(TypeOf(module, expr), expected, module)) {
errorf(pos, "type error in init expression, expected %s, got %s", errorf(pc(), "type error in init expression, expected %s, got %s",
expected.type_name().c_str(), expected.type_name().c_str(),
TypeOf(module, expr).type_name().c_str()); TypeOf(module, expr).type_name().c_str());
} }
...@@ -1927,8 +1933,8 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1927,8 +1933,8 @@ class ModuleDecoderImpl : public Decoder {
if (flag != 0 && !enabled_features_.has_bulk_memory() && if (flag != 0 && !enabled_features_.has_bulk_memory() &&
!enabled_features_.has_reftypes()) { !enabled_features_.has_reftypes()) {
error( error(
"Invalid segment flag. Did you forget " "Invalid segment flag. Enable with --experimental-wasm-bulk-memory "
"--experimental-wasm-bulk-memory or --experimental-wasm-reftypes?"); "or --experimental-wasm-reftypes");
return; return;
} }
if ((flag & kFullMask) != flag) { if ((flag & kFullMask) != flag) {
......
...@@ -37,12 +37,12 @@ byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { ...@@ -37,12 +37,12 @@ byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance, uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
const WasmInitExpr& expr) { const WasmInitExpr& expr) {
switch (expr.kind) { switch (expr.kind()) {
case WasmInitExpr::kI32Const: case WasmInitExpr::kI32Const:
return expr.val.i32_const; return expr.immediate().i32_const;
case WasmInitExpr::kGlobalIndex: { case WasmInitExpr::kGlobalGet: {
uint32_t offset = uint32_t offset =
instance->module()->globals[expr.val.global_index].offset; instance->module()->globals[expr.immediate().index].offset;
auto raw_addr = reinterpret_cast<Address>( auto raw_addr = reinterpret_cast<Address>(
instance->untagged_globals_buffer().backing_store()) + instance->untagged_globals_buffer().backing_store()) +
offset; offset;
...@@ -1404,27 +1404,27 @@ T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) { ...@@ -1404,27 +1404,27 @@ T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
// Process initialization of globals. // Process initialization of globals.
void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
for (auto global : module_->globals) { for (const WasmGlobal& global : module_->globals) {
if (global.mutability && global.imported) { if (global.mutability && global.imported) {
continue; continue;
} }
switch (global.init.kind) { switch (global.init.kind()) {
case WasmInitExpr::kI32Const: case WasmInitExpr::kI32Const:
WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
global.init.val.i32_const); global.init.immediate().i32_const);
break; break;
case WasmInitExpr::kI64Const: case WasmInitExpr::kI64Const:
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
global.init.val.i64_const); global.init.immediate().i64_const);
break; break;
case WasmInitExpr::kF32Const: case WasmInitExpr::kF32Const:
WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
global.init.val.f32_const); global.init.immediate().f32_const);
break; break;
case WasmInitExpr::kF64Const: case WasmInitExpr::kF64Const:
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
global.init.val.f64_const); global.init.immediate().f64_const);
break; break;
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
DCHECK(enabled_.has_reftypes() || enabled_.has_eh()); DCHECK(enabled_.has_reftypes() || enabled_.has_eh());
...@@ -1437,15 +1437,15 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { ...@@ -1437,15 +1437,15 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
case WasmInitExpr::kRefFuncConst: { case WasmInitExpr::kRefFuncConst: {
DCHECK(enabled_.has_reftypes()); DCHECK(enabled_.has_reftypes());
auto function = WasmInstanceObject::GetOrCreateWasmExternalFunction( auto function = WasmInstanceObject::GetOrCreateWasmExternalFunction(
isolate_, instance, global.init.val.function_index); isolate_, instance, global.init.immediate().index);
tagged_globals_->set(global.offset, *function); tagged_globals_->set(global.offset, *function);
break; break;
} }
case WasmInitExpr::kGlobalIndex: { case WasmInitExpr::kGlobalGet: {
// Initialize with another global. // Initialize with another global.
uint32_t new_offset = global.offset; uint32_t new_offset = global.offset;
uint32_t old_offset = uint32_t old_offset =
module_->globals[global.init.val.global_index].offset; module_->globals[global.init.immediate().index].offset;
TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset); TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
if (global.type.is_reference_type()) { if (global.type.is_reference_type()) {
DCHECK(enabled_.has_reftypes() || enabled_.has_eh()); DCHECK(enabled_.has_reftypes() || enabled_.has_eh());
......
...@@ -51,7 +51,7 @@ class HeapType { ...@@ -51,7 +51,7 @@ class HeapType {
kEq, // shorthand: q kEq, // shorthand: q
kExn, // shorthand: x kExn, // shorthand: x
kI31, // shorthand: j kI31, // shorthand: j
// This code is used to represent failures in the parsing of heap types and // This value is used to represent failures in the parsing of heap types and
// does not correspond to a wasm heap type. // does not correspond to a wasm heap type.
kBottom kBottom
}; };
...@@ -90,7 +90,7 @@ class HeapType { ...@@ -90,7 +90,7 @@ class HeapType {
return representation_ != other.representation_; return representation_ != other.representation_;
} }
constexpr uint32_t representation() const { return representation_; } constexpr Representation representation() const { return representation_; }
constexpr uint32_t ref_index() const { constexpr uint32_t ref_index() const {
CONSTEXPR_DCHECK(is_index()); CONSTEXPR_DCHECK(is_index());
return representation_; return representation_;
...@@ -183,7 +183,8 @@ class ValueType { ...@@ -183,7 +183,8 @@ class ValueType {
constexpr bool has_index() const { constexpr bool has_index() const {
return is_reference_type() && heap_type().is_index(); return is_reference_type() && heap_type().is_index();
} }
constexpr bool has_depth() const { return kind() == kRtt; } constexpr bool is_rtt() const { return kind() == kRtt; }
constexpr bool has_depth() const { return is_rtt(); }
constexpr ValueType() : bit_field_(KindField::encode(kStmt)) {} constexpr ValueType() : bit_field_(KindField::encode(kStmt)) {}
static constexpr ValueType Primitive(Kind kind) { static constexpr ValueType Primitive(Kind kind) {
...@@ -219,9 +220,10 @@ class ValueType { ...@@ -219,9 +220,10 @@ class ValueType {
} }
constexpr Kind kind() const { return KindField::decode(bit_field_); } constexpr Kind kind() const { return KindField::decode(bit_field_); }
constexpr uint32_t heap_representation() const { constexpr HeapType::Representation heap_representation() const {
CONSTEXPR_DCHECK(is_reference_type()); CONSTEXPR_DCHECK(is_reference_type());
return HeapTypeField::decode(bit_field_); return static_cast<HeapType::Representation>(
HeapTypeField::decode(bit_field_));
} }
constexpr HeapType heap_type() const { constexpr HeapType heap_type() const {
return HeapType(heap_representation()); return HeapType(heap_representation());
......
...@@ -144,7 +144,7 @@ class DebugEvaluatorProxy { ...@@ -144,7 +144,7 @@ class DebugEvaluatorProxy {
void GetGlobal(uint32_t global, uint32_t result_offset) { void GetGlobal(uint32_t global, uint32_t result_offset) {
DCHECK(frame_->is_wasm()); DCHECK(frame_->is_wasm());
WasmGlobal global_variable = const WasmGlobal& global_variable =
WasmFrame::cast(frame_)->native_module()->module()->globals.at(global); WasmFrame::cast(frame_)->native_module()->module()->globals.at(global);
Handle<WasmInstanceObject> instance( Handle<WasmInstanceObject> instance(
......
...@@ -376,9 +376,9 @@ void WasmModuleBuilder::AddExport(Vector<const char> name, ...@@ -376,9 +376,9 @@ void WasmModuleBuilder::AddExport(Vector<const char> name,
} }
uint32_t WasmModuleBuilder::AddExportedGlobal(ValueType type, bool mutability, uint32_t WasmModuleBuilder::AddExportedGlobal(ValueType type, bool mutability,
const WasmInitExpr& init, WasmInitExpr init,
Vector<const char> name) { Vector<const char> name) {
uint32_t index = AddGlobal(type, mutability, init); uint32_t index = AddGlobal(type, mutability, std::move(init));
AddExport(name, kExternalGlobal, index); AddExport(name, kExternalGlobal, index);
return index; return index;
} }
...@@ -395,8 +395,8 @@ void WasmModuleBuilder::ExportImportedFunction(Vector<const char> name, ...@@ -395,8 +395,8 @@ void WasmModuleBuilder::ExportImportedFunction(Vector<const char> name,
} }
uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool mutability, uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool mutability,
const WasmInitExpr& init) { WasmInitExpr init) {
globals_.push_back({type, mutability, init}); globals_.push_back({type, mutability, std::move(init)});
return static_cast<uint32_t>(globals_.size() - 1); return static_cast<uint32_t>(globals_.size() - 1);
} }
...@@ -542,34 +542,35 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const { ...@@ -542,34 +542,35 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
for (const WasmGlobal& global : globals_) { for (const WasmGlobal& global : globals_) {
WriteValueType(buffer, global.type); WriteValueType(buffer, global.type);
buffer->write_u8(global.mutability ? 1 : 0); buffer->write_u8(global.mutability ? 1 : 0);
switch (global.init.kind) { switch (global.init.kind()) {
case WasmInitExpr::kI32Const: case WasmInitExpr::kI32Const:
DCHECK_EQ(kWasmI32, global.type); DCHECK_EQ(kWasmI32, global.type);
buffer->write_u8(kExprI32Const); buffer->write_u8(kExprI32Const);
buffer->write_i32v(global.init.val.i32_const); buffer->write_i32v(global.init.immediate().i32_const);
break; break;
case WasmInitExpr::kI64Const: case WasmInitExpr::kI64Const:
DCHECK_EQ(kWasmI64, global.type); DCHECK_EQ(kWasmI64, global.type);
buffer->write_u8(kExprI64Const); buffer->write_u8(kExprI64Const);
buffer->write_i64v(global.init.val.i64_const); buffer->write_i64v(global.init.immediate().i64_const);
break; break;
case WasmInitExpr::kF32Const: case WasmInitExpr::kF32Const:
DCHECK_EQ(kWasmF32, global.type); DCHECK_EQ(kWasmF32, global.type);
buffer->write_u8(kExprF32Const); buffer->write_u8(kExprF32Const);
buffer->write_f32(global.init.val.f32_const); buffer->write_f32(global.init.immediate().f32_const);
break; break;
case WasmInitExpr::kF64Const: case WasmInitExpr::kF64Const:
DCHECK_EQ(kWasmF64, global.type); DCHECK_EQ(kWasmF64, global.type);
buffer->write_u8(kExprF64Const); buffer->write_u8(kExprF64Const);
buffer->write_f64(global.init.val.f64_const); buffer->write_f64(global.init.immediate().f64_const);
break; break;
case WasmInitExpr::kGlobalIndex: case WasmInitExpr::kGlobalGet:
buffer->write_u8(kExprGlobalGet); buffer->write_u8(kExprGlobalGet);
buffer->write_u32v(global.init.val.global_index); buffer->write_u32v(global.init.immediate().index);
break; break;
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
buffer->write_u8(kExprRefNull); buffer->write_u8(kExprRefNull);
buffer->write_i32v(global.type.heap_type().code()); buffer->write_i32v(
HeapType(global.init.immediate().heap_type).code());
break; break;
case WasmInitExpr::kRefFuncConst: case WasmInitExpr::kRefFuncConst:
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -607,6 +608,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const { ...@@ -607,6 +608,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
case ValueType::kRtt: case ValueType::kRtt:
UNREACHABLE(); UNREACHABLE();
} }
break;
} }
} }
buffer->write_u8(kExprEnd); buffer->write_u8(kExprEnd);
......
...@@ -238,7 +238,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -238,7 +238,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
Vector<const char> module = {}); Vector<const char> module = {});
WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr); WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr);
uint32_t AddGlobal(ValueType type, bool mutability = true, uint32_t AddGlobal(ValueType type, bool mutability = true,
const WasmInitExpr& init = WasmInitExpr()); WasmInitExpr init = WasmInitExpr());
uint32_t AddGlobalImport(Vector<const char> name, ValueType type, uint32_t AddGlobalImport(Vector<const char> name, ValueType type,
bool mutability, Vector<const char> module = {}); bool mutability, Vector<const char> module = {});
void AddDataSegment(const byte* data, uint32_t size, uint32_t dest); void AddDataSegment(const byte* data, uint32_t size, uint32_t dest);
...@@ -259,8 +259,8 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -259,8 +259,8 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
void AddExport(Vector<const char> name, WasmFunctionBuilder* builder) { void AddExport(Vector<const char> name, WasmFunctionBuilder* builder) {
AddExport(name, kExternalFunction, builder->func_index()); AddExport(name, kExternalFunction, builder->func_index());
} }
uint32_t AddExportedGlobal(ValueType type, bool mutability, uint32_t AddExportedGlobal(ValueType type, bool mutability, WasmInitExpr init,
const WasmInitExpr& init, Vector<const char> name); Vector<const char> name);
void ExportImportedFunction(Vector<const char> name, int import_index); void ExportImportedFunction(Vector<const char> name, int import_index);
void SetMinMemorySize(uint32_t value); void SetMinMemorySize(uint32_t value);
void SetMaxMemorySize(uint32_t value); void SetMaxMemorySize(uint32_t value);
...@@ -314,6 +314,8 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -314,6 +314,8 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
}; };
struct WasmGlobal { struct WasmGlobal {
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmGlobal);
ValueType type; ValueType type;
bool mutability; bool mutability;
WasmInitExpr init; WasmInitExpr init;
......
...@@ -91,7 +91,7 @@ struct WasmException { ...@@ -91,7 +91,7 @@ struct WasmException {
struct WasmDataSegment { struct WasmDataSegment {
// Construct an active segment. // Construct an active segment.
explicit WasmDataSegment(WasmInitExpr dest_addr) explicit WasmDataSegment(WasmInitExpr dest_addr)
: dest_addr(dest_addr), active(true) {} : dest_addr(std::move(dest_addr)), active(true) {}
// Construct a passive segment, which has no dest_addr. // Construct a passive segment, which has no dest_addr.
WasmDataSegment() : active(false) {} WasmDataSegment() : active(false) {}
...@@ -120,7 +120,7 @@ struct WasmElemSegment { ...@@ -120,7 +120,7 @@ struct WasmElemSegment {
WasmElemSegment(uint32_t table_index, WasmInitExpr offset) WasmElemSegment(uint32_t table_index, WasmInitExpr offset)
: type(ValueType::Ref(HeapType::kFunc, kNullable)), : type(ValueType::Ref(HeapType::kFunc, kNullable)),
table_index(table_index), table_index(table_index),
offset(offset), offset(std::move(offset)),
status(kStatusActive) {} status(kStatusActive) {}
// Construct a passive or declarative segment, which has no table index or // Construct a passive or declarative segment, which has no table index or
......
...@@ -747,47 +747,71 @@ class V8_EXPORT_PRIVATE WasmOpcodes { ...@@ -747,47 +747,71 @@ class V8_EXPORT_PRIVATE WasmOpcodes {
}; };
// Representation of an initializer expression. // Representation of an initializer expression.
struct WasmInitExpr { class WasmInitExpr {
enum WasmInitKind { public:
enum Operator {
kNone, kNone,
kGlobalIndex, kGlobalGet,
kI32Const, kI32Const,
kI64Const, kI64Const,
kF32Const, kF32Const,
kF64Const, kF64Const,
kRefNullConst, kRefNullConst,
kRefFuncConst, kRefFuncConst
} kind; };
union { union Immediate {
int32_t i32_const; int32_t i32_const;
int64_t i64_const; int64_t i64_const;
float f32_const; float f32_const;
double f64_const; double f64_const;
uint32_t global_index; uint32_t index;
uint32_t function_index; HeapType::Representation heap_type;
} val; };
WasmInitExpr() : kind(kNone) {} WasmInitExpr() : kind_(kNone) { immediate_.i32_const = 0; }
explicit WasmInitExpr(int32_t v) : kind(kI32Const) { val.i32_const = v; } explicit WasmInitExpr(int32_t v) : kind_(kI32Const) {
explicit WasmInitExpr(int64_t v) : kind(kI64Const) { val.i64_const = v; } immediate_.i32_const = v;
explicit WasmInitExpr(float v) : kind(kF32Const) { val.f32_const = v; } }
explicit WasmInitExpr(double v) : kind(kF64Const) { val.f64_const = v; } explicit WasmInitExpr(int64_t v) : kind_(kI64Const) {
immediate_.i64_const = v;
explicit WasmInitExpr(WasmInitKind kind) : kind(kind) { }
DCHECK_EQ(kind, kRefNullConst); explicit WasmInitExpr(float v) : kind_(kF32Const) {
immediate_.f32_const = v;
}
explicit WasmInitExpr(double v) : kind_(kF64Const) {
immediate_.f64_const = v;
}
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmInitExpr);
static WasmInitExpr GlobalGet(uint32_t index) {
WasmInitExpr expr;
expr.kind_ = kGlobalGet;
expr.immediate_.index = index;
return expr;
}
static WasmInitExpr RefFuncConst(uint32_t index) {
WasmInitExpr expr;
expr.kind_ = kRefFuncConst;
expr.immediate_.index = index;
return expr;
} }
WasmInitExpr(WasmInitKind kind, uint32_t index) : kind(kind) { static WasmInitExpr RefNullConst(HeapType::Representation heap_type) {
if (kind == kGlobalIndex) { WasmInitExpr expr;
val.global_index = index; expr.kind_ = kRefNullConst;
} else if (kind == kRefFuncConst) { expr.immediate_.heap_type = heap_type;
val.function_index = index; return expr;
} else {
// For the other types, the other initializers should be used.
UNREACHABLE();
}
} }
Immediate immediate() const { return immediate_; }
Operator kind() const { return kind_; }
private:
Immediate immediate_;
Operator kind_;
}; };
} // namespace wasm } // namespace wasm
......
...@@ -44,7 +44,7 @@ class WasmGCTester { ...@@ -44,7 +44,7 @@ class WasmGCTester {
} }
uint32_t AddGlobal(ValueType type, bool mutability, WasmInitExpr init) { uint32_t AddGlobal(ValueType type, bool mutability, WasmInitExpr init) {
return builder_.AddGlobal(type, mutability, init); return builder_.AddGlobal(type, mutability, std::move(init));
} }
uint32_t DefineFunction(FunctionSig* sig, uint32_t DefineFunction(FunctionSig* sig,
...@@ -220,8 +220,10 @@ TEST(WasmRefAsNonNull) { ...@@ -220,8 +220,10 @@ TEST(WasmRefAsNonNull) {
ValueType kOptRefType = optref(type_index); ValueType kOptRefType = optref(type_index);
FunctionSig sig_q_v(1, 0, kRefTypes); FunctionSig sig_q_v(1, 0, kRefTypes);
uint32_t global_index = tester.AddGlobal( uint32_t global_index =
kOptRefType, true, WasmInitExpr(WasmInitExpr::kRefNullConst)); tester.AddGlobal(kOptRefType, true,
WasmInitExpr::RefNullConst(
static_cast<HeapType::Representation>(type_index)));
uint32_t field_index = 0; uint32_t field_index = 0;
const uint32_t kFunc = tester.DefineFunction( const uint32_t kFunc = tester.DefineFunction(
tester.sigs.i_v(), {}, tester.sigs.i_v(), {},
......
...@@ -315,8 +315,7 @@ ZoneBuffer GetModuleWithInvalidSection(Zone* zone) { ...@@ -315,8 +315,7 @@ ZoneBuffer GetModuleWithInvalidSection(Zone* zone) {
TestSignatures sigs; TestSignatures sigs;
WasmModuleBuilder builder(zone); WasmModuleBuilder builder(zone);
// Add an invalid global to the module. The decoder will fail there. // Add an invalid global to the module. The decoder will fail there.
builder.AddGlobal(kWasmStmt, true, builder.AddGlobal(kWasmStmt, true, WasmInitExpr::GlobalGet(12));
WasmInitExpr(WasmInitExpr::kGlobalIndex, 12));
{ {
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
uint8_t code[] = {kExprLocalGet, 0, kExprEnd}; uint8_t code[] = {kExprLocalGet, 0, kExprEnd};
......
...@@ -204,12 +204,12 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes, ...@@ -204,12 +204,12 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
for (const WasmElemSegment& elem_segment : module->elem_segments) { for (const WasmElemSegment& elem_segment : module->elem_segments) {
os << "builder.addElementSegment("; os << "builder.addElementSegment(";
os << elem_segment.table_index << ", "; os << elem_segment.table_index << ", ";
switch (elem_segment.offset.kind) { switch (elem_segment.offset.kind()) {
case WasmInitExpr::kGlobalIndex: case WasmInitExpr::kGlobalGet:
os << elem_segment.offset.val.global_index << ", true"; os << elem_segment.offset.immediate().index << ", true";
break; break;
case WasmInitExpr::kI32Const: case WasmInitExpr::kI32Const:
os << elem_segment.offset.val.i32_const << ", false"; os << elem_segment.offset.immediate().i32_const << ", false";
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -261,8 +261,8 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) { ...@@ -261,8 +261,8 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
EXPECT_EQ(kWasmI32, global->type); EXPECT_EQ(kWasmI32, global->type);
EXPECT_EQ(0u, global->offset); EXPECT_EQ(0u, global->offset);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kI32Const, global->init.kind); EXPECT_EQ(WasmInitExpr::kI32Const, global->init.kind());
EXPECT_EQ(13, global->init.val.i32_const); EXPECT_EQ(13, global->init.immediate().i32_const);
} }
EXPECT_OFF_END_FAILURE(data, 1); EXPECT_OFF_END_FAILURE(data, 1);
...@@ -307,13 +307,13 @@ TEST_F(WasmModuleVerifyTest, ExternRefGlobal) { ...@@ -307,13 +307,13 @@ TEST_F(WasmModuleVerifyTest, ExternRefGlobal) {
const WasmGlobal* global = &result.value()->globals[0]; const WasmGlobal* global = &result.value()->globals[0];
EXPECT_EQ(kWasmExternRef, global->type); EXPECT_EQ(kWasmExternRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind); EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind());
global = &result.value()->globals[1]; global = &result.value()->globals[1];
EXPECT_EQ(kWasmFuncRef, global->type); EXPECT_EQ(kWasmFuncRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind); EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind());
EXPECT_EQ(uint32_t{1}, global->init.val.function_index); EXPECT_EQ(uint32_t{1}, global->init.immediate().index);
} }
} }
...@@ -355,13 +355,13 @@ TEST_F(WasmModuleVerifyTest, FuncRefGlobal) { ...@@ -355,13 +355,13 @@ TEST_F(WasmModuleVerifyTest, FuncRefGlobal) {
const WasmGlobal* global = &result.value()->globals[0]; const WasmGlobal* global = &result.value()->globals[0];
EXPECT_EQ(kWasmFuncRef, global->type); EXPECT_EQ(kWasmFuncRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind); EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind());
global = &result.value()->globals[1]; global = &result.value()->globals[1];
EXPECT_EQ(kWasmFuncRef, global->type); EXPECT_EQ(kWasmFuncRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind); EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind());
EXPECT_EQ(uint32_t{1}, global->init.val.function_index); EXPECT_EQ(uint32_t{1}, global->init.immediate().index);
} }
} }
...@@ -410,7 +410,7 @@ TEST_F(WasmModuleVerifyTest, ExternRefGlobalWithGlobalInit) { ...@@ -410,7 +410,7 @@ TEST_F(WasmModuleVerifyTest, ExternRefGlobalWithGlobalInit) {
EXPECT_EQ(kWasmExternRef, global->type); EXPECT_EQ(kWasmExternRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kGlobalIndex, global->init.kind); EXPECT_EQ(WasmInitExpr::kGlobalGet, global->init.kind());
} }
} }
...@@ -444,7 +444,7 @@ TEST_F(WasmModuleVerifyTest, NullGlobalWithGlobalInit) { ...@@ -444,7 +444,7 @@ TEST_F(WasmModuleVerifyTest, NullGlobalWithGlobalInit) {
EXPECT_EQ(kWasmExternRef, global->type); EXPECT_EQ(kWasmExternRef, global->type);
EXPECT_FALSE(global->mutability); EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kGlobalIndex, global->init.kind); EXPECT_EQ(WasmInitExpr::kGlobalGet, global->init.kind());
} }
} }
...@@ -582,14 +582,14 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) { ...@@ -582,14 +582,14 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
EXPECT_EQ(kWasmF32, g0->type); EXPECT_EQ(kWasmF32, g0->type);
EXPECT_EQ(0u, g0->offset); EXPECT_EQ(0u, g0->offset);
EXPECT_FALSE(g0->mutability); EXPECT_FALSE(g0->mutability);
EXPECT_EQ(WasmInitExpr::kF32Const, g0->init.kind); EXPECT_EQ(WasmInitExpr::kF32Const, g0->init.kind());
const WasmGlobal* g1 = &result.value()->globals[1]; const WasmGlobal* g1 = &result.value()->globals[1];
EXPECT_EQ(kWasmF64, g1->type); EXPECT_EQ(kWasmF64, g1->type);
EXPECT_EQ(8u, g1->offset); EXPECT_EQ(8u, g1->offset);
EXPECT_TRUE(g1->mutability); EXPECT_TRUE(g1->mutability);
EXPECT_EQ(WasmInitExpr::kF64Const, g1->init.kind); EXPECT_EQ(WasmInitExpr::kF64Const, g1->init.kind());
} }
EXPECT_OFF_END_FAILURE(data, 1); EXPECT_OFF_END_FAILURE(data, 1);
...@@ -826,9 +826,9 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) { ...@@ -826,9 +826,9 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) {
}; };
ModuleResult result = DecodeModule(data, data + sizeof(data)); ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result); EXPECT_OK(result);
WasmInitExpr expr = result.value()->data_segments.back().dest_addr; WasmInitExpr expr = std::move(result.value()->data_segments.back()).dest_addr;
EXPECT_EQ(WasmInitExpr::kGlobalIndex, expr.kind); EXPECT_EQ(WasmInitExpr::kGlobalGet, expr.kind());
EXPECT_EQ(1u, expr.val.global_index); EXPECT_EQ(1u, expr.immediate().index);
} }
TEST_F(WasmModuleVerifyTest, DataSegmentWithMutableImportedGlobal) { TEST_F(WasmModuleVerifyTest, DataSegmentWithMutableImportedGlobal) {
...@@ -885,8 +885,8 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) { ...@@ -885,8 +885,8 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
const WasmDataSegment* segment = &result.value()->data_segments.back(); const WasmDataSegment* segment = &result.value()->data_segments.back();
EXPECT_EQ(WasmInitExpr::kI32Const, segment->dest_addr.kind); EXPECT_EQ(WasmInitExpr::kI32Const, segment->dest_addr.kind());
EXPECT_EQ(0x9BBAA, segment->dest_addr.val.i32_const); EXPECT_EQ(0x9BBAA, segment->dest_addr.immediate().i32_const);
EXPECT_EQ(kDataSegmentSourceOffset, segment->source.offset()); EXPECT_EQ(kDataSegmentSourceOffset, segment->source.offset());
EXPECT_EQ(3u, segment->source.length()); EXPECT_EQ(3u, segment->source.length());
} }
...@@ -922,13 +922,13 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) { ...@@ -922,13 +922,13 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
const WasmDataSegment* s0 = &result.value()->data_segments[0]; const WasmDataSegment* s0 = &result.value()->data_segments[0];
const WasmDataSegment* s1 = &result.value()->data_segments[1]; const WasmDataSegment* s1 = &result.value()->data_segments[1];
EXPECT_EQ(WasmInitExpr::kI32Const, s0->dest_addr.kind); EXPECT_EQ(WasmInitExpr::kI32Const, s0->dest_addr.kind());
EXPECT_EQ(0x7FFEE, s0->dest_addr.val.i32_const); EXPECT_EQ(0x7FFEE, s0->dest_addr.immediate().i32_const);
EXPECT_EQ(kDataSegment0SourceOffset, s0->source.offset()); EXPECT_EQ(kDataSegment0SourceOffset, s0->source.offset());
EXPECT_EQ(4u, s0->source.length()); EXPECT_EQ(4u, s0->source.length());
EXPECT_EQ(WasmInitExpr::kI32Const, s1->dest_addr.kind); EXPECT_EQ(WasmInitExpr::kI32Const, s1->dest_addr.kind());
EXPECT_EQ(0x6DDCC, s1->dest_addr.val.i32_const); EXPECT_EQ(0x6DDCC, s1->dest_addr.immediate().i32_const);
EXPECT_EQ(kDataSegment1SourceOffset, s1->source.offset()); EXPECT_EQ(kDataSegment1SourceOffset, s1->source.offset());
EXPECT_EQ(10u, s1->source.length()); EXPECT_EQ(10u, s1->source.length());
} }
...@@ -2259,15 +2259,15 @@ class WasmInitExprDecodeTest : public TestWithZone { ...@@ -2259,15 +2259,15 @@ class WasmInitExprDecodeTest : public TestWithZone {
{ \ { \
static const byte data[] = {__VA_ARGS__, kExprEnd}; \ static const byte data[] = {__VA_ARGS__, kExprEnd}; \
WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \ WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \
EXPECT_EQ(WasmInitExpr::k##Type##Const, expr.kind); \ EXPECT_EQ(WasmInitExpr::k##Type##Const, expr.kind()); \
EXPECT_EQ(value, expr.val.type##_const); \ EXPECT_EQ(value, expr.immediate().type##_const); \
} }
#define EXPECT_INIT_EXPR_FAIL(...) \ #define EXPECT_INIT_EXPR_FAIL(...) \
{ \ { \
static const byte data[] = {__VA_ARGS__, kExprEnd}; \ static const byte data[] = {__VA_ARGS__, kExprEnd}; \
WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \ WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \
EXPECT_EQ(WasmInitExpr::kNone, expr.kind); \ EXPECT_EQ(WasmInitExpr::kNone, expr.kind()); \
} }
TEST_F(WasmInitExprDecodeTest, InitExpr_i32) { TEST_F(WasmInitExprDecodeTest, InitExpr_i32) {
...@@ -2302,7 +2302,7 @@ TEST_F(WasmInitExprDecodeTest, InitExpr_ExternRef) { ...@@ -2302,7 +2302,7 @@ TEST_F(WasmInitExprDecodeTest, InitExpr_ExternRef) {
WASM_FEATURE_SCOPE(reftypes); WASM_FEATURE_SCOPE(reftypes);
static const byte data[] = {kExprRefNull, kLocalExternRef, kExprEnd}; static const byte data[] = {kExprRefNull, kLocalExternRef, kExprEnd};
WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data));
EXPECT_EQ(WasmInitExpr::kRefNullConst, expr.kind); EXPECT_EQ(WasmInitExpr::kRefNullConst, expr.kind());
} }
TEST_F(WasmInitExprDecodeTest, InitExpr_illegal) { TEST_F(WasmInitExprDecodeTest, InitExpr_illegal) {
......
...@@ -34,9 +34,9 @@ TEST_F(WasmCapiTest, HostRef) { ...@@ -34,9 +34,9 @@ TEST_F(WasmCapiTest, HostRef) {
FunctionSig r_i_sig(1, 1, ri_reps); FunctionSig r_i_sig(1, 1, ri_reps);
uint32_t func_index = builder()->AddImport(CStrVector("f"), &r_r_sig); uint32_t func_index = builder()->AddImport(CStrVector("f"), &r_r_sig);
const bool kMutable = true; const bool kMutable = true;
const WasmInitExpr global_init(WasmInitExpr::kRefNullConst);
uint32_t global_index = builder()->AddExportedGlobal( uint32_t global_index = builder()->AddExportedGlobal(
kWasmExternRef, kMutable, global_init, CStrVector("global")); kWasmExternRef, kMutable, WasmInitExpr::RefNullConst(HeapType::kExtern),
CStrVector("global"));
uint32_t table_index = builder()->AddTable(kWasmExternRef, 10); uint32_t table_index = builder()->AddTable(kWasmExternRef, 10);
builder()->AddExport(CStrVector("table"), kExternalTable, table_index); builder()->AddExport(CStrVector("table"), kExternalTable, table_index);
byte global_set_code[] = {WASM_SET_GLOBAL(global_index, WASM_GET_LOCAL(0))}; byte global_set_code[] = {WASM_SET_GLOBAL(global_index, WASM_GET_LOCAL(0))};
......
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