[wasm][anyref] Decode anyref globals
Add support for decoding anyref globals, and some drive-by cleanups. R=titzer@chromium.org Bug: v8:7581 Change-Id: I3527f996a3fa1a890918a5924e951fbafa394cf2 Reviewed-on: https://chromium-review.googlesource.com/997655 Reviewed-by: Ben Titzer <titzer@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#52391}
This commit is contained in:
parent
7401022460
commit
ae958346a0
@ -113,6 +113,8 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
|
||||
return kWasmF32;
|
||||
case WasmInitExpr::kF64Const:
|
||||
return kWasmF64;
|
||||
case WasmInitExpr::kAnyRefConst:
|
||||
return kWasmAnyRef;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -945,30 +947,26 @@ class ModuleDecoderImpl : public Decoder {
|
||||
global->mutability = consume_mutability();
|
||||
const byte* pos = pc();
|
||||
global->init = consume_init_expr(module, kWasmStmt);
|
||||
switch (global->init.kind) {
|
||||
case WasmInitExpr::kGlobalIndex: {
|
||||
uint32_t other_index = global->init.val.global_index;
|
||||
if (other_index >= index) {
|
||||
errorf(pos,
|
||||
"invalid global index in init expression, "
|
||||
"index %u, other_index %u",
|
||||
index, other_index);
|
||||
} else if (module->globals[other_index].type != global->type) {
|
||||
errorf(pos,
|
||||
"type mismatch in global initialization "
|
||||
"(from global #%u), expected %s, got %s",
|
||||
other_index, WasmOpcodes::TypeName(global->type),
|
||||
WasmOpcodes::TypeName(module->globals[other_index].type));
|
||||
}
|
||||
break;
|
||||
if (global->init.kind == WasmInitExpr::kGlobalIndex) {
|
||||
uint32_t other_index = global->init.val.global_index;
|
||||
if (other_index >= index) {
|
||||
errorf(pos,
|
||||
"invalid global index in init expression, "
|
||||
"index %u, other_index %u",
|
||||
index, other_index);
|
||||
} else if (module->globals[other_index].type != global->type) {
|
||||
errorf(pos,
|
||||
"type mismatch in global initialization "
|
||||
"(from global #%u), expected %s, got %s",
|
||||
other_index, WasmOpcodes::TypeName(global->type),
|
||||
WasmOpcodes::TypeName(module->globals[other_index].type));
|
||||
}
|
||||
} else {
|
||||
if (global->type != TypeOf(module, global->init)) {
|
||||
errorf(pos, "type error in global initialization, expected %s, got %s",
|
||||
WasmOpcodes::TypeName(global->type),
|
||||
WasmOpcodes::TypeName(TypeOf(module, global->init)));
|
||||
}
|
||||
default:
|
||||
if (global->type != TypeOf(module, global->init)) {
|
||||
errorf(pos,
|
||||
"type error in global initialization, expected %s, got %s",
|
||||
WasmOpcodes::TypeName(global->type),
|
||||
WasmOpcodes::TypeName(TypeOf(module, global->init)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,6 +1203,14 @@ class ModuleDecoderImpl : public Decoder {
|
||||
len = operand.length;
|
||||
break;
|
||||
}
|
||||
case kExprRefNull: {
|
||||
if (FLAG_experimental_wasm_anyref) {
|
||||
expr.kind = WasmInitExpr::kAnyRefConst;
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
V8_FALLTHROUGH;
|
||||
}
|
||||
default: {
|
||||
error("invalid opcode in initialization expression");
|
||||
expr.kind = WasmInitExpr::kNone;
|
||||
|
@ -862,7 +862,8 @@ struct WasmInitExpr {
|
||||
kI32Const,
|
||||
kI64Const,
|
||||
kF32Const,
|
||||
kF64Const
|
||||
kF64Const,
|
||||
kAnyRefConst,
|
||||
} kind;
|
||||
|
||||
union {
|
||||
|
@ -328,6 +328,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
|
||||
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 40), \
|
||||
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 48), \
|
||||
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 56)
|
||||
|
||||
#define WASM_REF_NULL kExprRefNull
|
||||
|
||||
#define WASM_GET_LOCAL(index) kExprGetLocal, static_cast<byte>(index)
|
||||
#define WASM_SET_LOCAL(index, val) val, kExprSetLocal, static_cast<byte>(index)
|
||||
#define WASM_TEE_LOCAL(index, val) val, kExprTeeLocal, static_cast<byte>(index)
|
||||
|
@ -25,6 +25,7 @@ namespace module_decoder_unittest {
|
||||
#define WASM_INIT_EXPR_F32(val) WASM_F32(val), kExprEnd
|
||||
#define WASM_INIT_EXPR_I64(val) WASM_I64(val), kExprEnd
|
||||
#define WASM_INIT_EXPR_F64(val) WASM_F64(val), kExprEnd
|
||||
#define WASM_INIT_EXPR_ANYREF WASM_REF_NULL, kExprEnd
|
||||
#define WASM_INIT_EXPR_GLOBAL(index) WASM_GET_GLOBAL(index), kExprEnd
|
||||
|
||||
#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
|
||||
@ -212,6 +213,67 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
|
||||
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, AnyRefGlobal) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(anyref);
|
||||
static const byte data[] = {
|
||||
SECTION(Global, 5), // --
|
||||
1,
|
||||
kLocalAnyRef, // local type
|
||||
0, // immutable
|
||||
WASM_INIT_EXPR_ANYREF // init
|
||||
};
|
||||
|
||||
{
|
||||
// Should decode to exactly one global.
|
||||
ModuleResult result = DecodeModule(data, data + sizeof(data));
|
||||
EXPECT_OK(result);
|
||||
EXPECT_EQ(1u, result.val->globals.size());
|
||||
EXPECT_EQ(0u, result.val->functions.size());
|
||||
EXPECT_EQ(0u, result.val->data_segments.size());
|
||||
|
||||
const WasmGlobal* global = &result.val->globals.back();
|
||||
|
||||
EXPECT_EQ(kWasmAnyRef, global->type);
|
||||
EXPECT_FALSE(global->mutability);
|
||||
EXPECT_EQ(WasmInitExpr::kAnyRefConst, global->init.kind);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, AnyRefGlobalWithGlobalInit) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(anyref);
|
||||
static const byte data[] = {
|
||||
SECTION(Import, 8), // section header
|
||||
1, // number of imports
|
||||
NAME_LENGTH(1), // --
|
||||
'm', // module name
|
||||
NAME_LENGTH(1), // --
|
||||
'f', // global name
|
||||
kExternalGlobal, // import kind
|
||||
kLocalAnyRef, // type
|
||||
0, // mutability
|
||||
SECTION(Global, 6), // --
|
||||
1,
|
||||
kLocalAnyRef, // local type
|
||||
0, // immutable
|
||||
WASM_INIT_EXPR_GLOBAL(0),
|
||||
};
|
||||
|
||||
{
|
||||
// Should decode to exactly one global.
|
||||
ModuleResult result = DecodeModule(data, data + sizeof(data));
|
||||
EXPECT_OK(result);
|
||||
EXPECT_EQ(2u, result.val->globals.size());
|
||||
EXPECT_EQ(0u, result.val->functions.size());
|
||||
EXPECT_EQ(0u, result.val->data_segments.size());
|
||||
|
||||
const WasmGlobal* global = &result.val->globals.back();
|
||||
|
||||
EXPECT_EQ(kWasmAnyRef, global->type);
|
||||
EXPECT_FALSE(global->mutability);
|
||||
EXPECT_EQ(WasmInitExpr::kGlobalIndex, global->init.kind);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, Global_invalid_type) {
|
||||
static const byte data[] = {
|
||||
SECTION(Global, 6), // --
|
||||
@ -1696,6 +1758,13 @@ TEST_F(WasmModuleVerifyTest, InitExpr_f64) {
|
||||
EXPECT_INIT_EXPR(F64, f64, 77999.1, WASM_F64(77999.1));
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, InitExpr_AnyRef) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(anyref);
|
||||
static const byte data[] = {kExprRefNull, kExprEnd};
|
||||
WasmInitExpr expr = DecodeWasmInitExprForTesting(data, data + sizeof(data));
|
||||
EXPECT_EQ(WasmInitExpr::kAnyRefConst, expr.kind);
|
||||
}
|
||||
|
||||
#undef EXPECT_INIT_EXPR
|
||||
|
||||
#define EXPECT_INIT_EXPR_FAIL(...) \
|
||||
@ -1819,6 +1888,7 @@ TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
|
||||
#undef WASM_INIT_EXPR_F32
|
||||
#undef WASM_INIT_EXPR_I64
|
||||
#undef WASM_INIT_EXPR_F64
|
||||
#undef WASM_INIT_EXPR_ANYREF
|
||||
#undef WASM_INIT_EXPR_GLOBAL
|
||||
#undef SIZEOF_EMPTY_FUNCTION
|
||||
#undef EMPTY_BODY
|
||||
|
Loading…
Reference in New Issue
Block a user