Commit 1b297d6e authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm][gc] Add tests for ref types in blocks and globals.

Changes:
- Extend wasm/wasm-module-builder.cc to handle reference types.
- Add testing infrastructure to wasm-macro-gen.h for reference types.
- Add cc tests for ref types in blocks and globals.

Bug: v8:7748
Change-Id: I527252a768469e1493ecee9ecf4b4afaf8a8013b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2182377Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67679}
parent 7f29c48e
...@@ -5059,19 +5059,10 @@ Node* WasmGraphBuilder::StructNew(uint32_t struct_index, ...@@ -5059,19 +5059,10 @@ Node* WasmGraphBuilder::StructNew(uint32_t struct_index,
map_index++; map_index++;
} }
} }
Node* s = CALL_BUILTIN(
CallDescriptor* call_descriptor = WasmAllocateStruct,
GetBuiltinCallDescriptor<WasmAllocateStructDescriptor>(
this, StubCallMode::kCallBuiltinPointer);
Node* call_target = graph()->NewNode(
mcgraph()->common()->NumberConstant(Builtins::kWasmAllocateStruct));
Node* native_context =
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer());
Node* s = gasm_->Call(
call_descriptor, call_target,
graph()->NewNode(mcgraph()->common()->NumberConstant(map_index)), graph()->NewNode(mcgraph()->common()->NumberConstant(map_index)),
native_context); LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
for (uint32_t i = 0; i < type->field_count(); i++) { for (uint32_t i = 0; i < type->field_count(); i++) {
StoreStructFieldUnchecked(mcgraph(), gasm_.get(), s, type, i, fields[i]); StoreStructFieldUnchecked(mcgraph(), gasm_.get(), s, type, i, fields[i]);
} }
......
...@@ -2072,8 +2072,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2072,8 +2072,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
case kExprSelectWithType: { case kExprSelectWithType: {
CHECK_PROTOTYPE_OPCODE(anyref); CHECK_PROTOTYPE_OPCODE(anyref);
SelectTypeImmediate<validate> imm(WasmFeatures::All(), this, SelectTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
this->pc_);
if (this->failed()) break; if (this->failed()) break;
auto cond = Pop(2, kWasmI32); auto cond = Pop(2, kWasmI32);
auto fval = Pop(1, imm.type); auto fval = Pop(1, imm.type);
......
...@@ -535,7 +535,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const { ...@@ -535,7 +535,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
buffer->write_size(globals_.size()); buffer->write_size(globals_.size());
for (const WasmGlobal& global : globals_) { for (const WasmGlobal& global : globals_) {
buffer->write_u8(global.type.value_type_code()); 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:
...@@ -589,6 +589,12 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const { ...@@ -589,6 +589,12 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
buffer->write_u8(kExprF64Const); buffer->write_u8(kExprF64Const);
buffer->write_f64(0.); buffer->write_f64(0.);
break; break;
case ValueType::kOptRef:
case ValueType::kFuncRef:
case ValueType::kExnRef:
case ValueType::kEqRef:
buffer->write_u8(kExprRefNull);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -44,6 +44,7 @@ WASM_EXEC_TEST(BasicStruct) { ...@@ -44,6 +44,7 @@ WASM_EXEC_TEST(BasicStruct) {
ValueType kOptRefType = ValueType(ValueType::kOptRef, type_index); ValueType kOptRefType = ValueType(ValueType::kOptRef, type_index);
FunctionSig sig_q_v(1, 0, kRefTypes); FunctionSig sig_q_v(1, 0, kRefTypes);
// Test struct.new and struct.get.
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
f->builder()->AddExport(CStrVector("f"), f); f->builder()->AddExport(CStrVector("f"), f);
byte f_code[] = {WASM_STRUCT_GET(type_index, 0, byte f_code[] = {WASM_STRUCT_GET(type_index, 0,
...@@ -52,6 +53,7 @@ WASM_EXEC_TEST(BasicStruct) { ...@@ -52,6 +53,7 @@ WASM_EXEC_TEST(BasicStruct) {
kExprEnd}; kExprEnd};
f->EmitCode(f_code, sizeof(f_code)); f->EmitCode(f_code, sizeof(f_code));
// Test struct.new and struct.get.
WasmFunctionBuilder* g = builder->AddFunction(sigs.i_v()); WasmFunctionBuilder* g = builder->AddFunction(sigs.i_v());
g->builder()->AddExport(CStrVector("g"), g); g->builder()->AddExport(CStrVector("g"), g);
byte g_code[] = {WASM_STRUCT_GET(type_index, 1, byte g_code[] = {WASM_STRUCT_GET(type_index, 1,
...@@ -60,24 +62,41 @@ WASM_EXEC_TEST(BasicStruct) { ...@@ -60,24 +62,41 @@ WASM_EXEC_TEST(BasicStruct) {
kExprEnd}; kExprEnd};
g->EmitCode(g_code, sizeof(g_code)); g->EmitCode(g_code, sizeof(g_code));
// Test struct.new, returning struct references to JS.
WasmFunctionBuilder* h = builder->AddFunction(&sig_q_v); WasmFunctionBuilder* h = builder->AddFunction(&sig_q_v);
h->builder()->AddExport(CStrVector("h"), h); h->builder()->AddExport(CStrVector("h"), h);
byte h_code[] = {WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64)), byte h_code[] = {WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64)),
kExprEnd}; kExprEnd};
h->EmitCode(h_code, sizeof(h_code)); h->EmitCode(h_code, sizeof(h_code));
// Test struct.set, struct refs types in locals.
WasmFunctionBuilder* j = builder->AddFunction(sigs.i_v()); WasmFunctionBuilder* j = builder->AddFunction(sigs.i_v());
uint32_t local_index = j->AddLocal(kOptRefType); uint32_t j_local_index = j->AddLocal(kOptRefType);
uint32_t field_index = 0; uint32_t j_field_index = 0;
j->builder()->AddExport(CStrVector("j"), j); j->builder()->AddExport(CStrVector("j"), j);
byte i_code[] = { byte j_code[] = {
WASM_SET_LOCAL(local_index, WASM_SET_LOCAL(j_local_index,
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64))), WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64))),
WASM_STRUCT_SET(type_index, field_index, WASM_GET_LOCAL(local_index), WASM_STRUCT_SET(type_index, j_field_index, WASM_GET_LOCAL(j_local_index),
WASM_I32V(-99)), WASM_I32V(-99)),
WASM_STRUCT_GET(type_index, field_index, WASM_GET_LOCAL(local_index)), WASM_STRUCT_GET(type_index, j_field_index, WASM_GET_LOCAL(j_local_index)),
kExprEnd}; kExprEnd};
j->EmitCode(i_code, sizeof(i_code)); j->EmitCode(j_code, sizeof(j_code));
// Test struct.set, struct refs types in globals and if-results.
uint32_t k_global_index = builder->AddGlobal(kOptRefType, true);
WasmFunctionBuilder* k = builder->AddFunction(sigs.i_v());
uint32_t k_field_index = 0;
k->builder()->AddExport(CStrVector("k"), k);
byte k_code[] = {
WASM_SET_GLOBAL(k_global_index, WASM_STRUCT_NEW(type_index, WASM_I32V(55),
WASM_I32V(66))),
WASM_STRUCT_GET(
type_index, k_field_index,
WASM_IF_ELSE_R(kOptRefType, WASM_I32V(1),
WASM_GET_GLOBAL(k_global_index), WASM_REF_NULL)),
kExprEnd};
k->EmitCode(k_code, sizeof(k_code));
ZoneBuffer buffer(&zone); ZoneBuffer buffer(&zone);
builder->WriteTo(&buffer); builder->WriteTo(&buffer);
...@@ -109,6 +128,9 @@ WASM_EXEC_TEST(BasicStruct) { ...@@ -109,6 +128,9 @@ WASM_EXEC_TEST(BasicStruct) {
CHECK_EQ(-99, testing::CallWasmFunctionForTesting(isolate, instance, &thrower, CHECK_EQ(-99, testing::CallWasmFunctionForTesting(isolate, instance, &thrower,
"j", 0, nullptr)); "j", 0, nullptr));
CHECK_EQ(55, testing::CallWasmFunctionForTesting(isolate, instance, &thrower,
"k", 0, nullptr));
} }
WASM_EXEC_TEST(BasicArray) { WASM_EXEC_TEST(BasicArray) {
......
...@@ -89,10 +89,15 @@ ...@@ -89,10 +89,15 @@
#define WASM_BLOCK_F(...) kExprBlock, kLocalF32, __VA_ARGS__, kExprEnd #define WASM_BLOCK_F(...) kExprBlock, kLocalF32, __VA_ARGS__, kExprEnd
#define WASM_BLOCK_D(...) kExprBlock, kLocalF64, __VA_ARGS__, kExprEnd #define WASM_BLOCK_D(...) kExprBlock, kLocalF64, __VA_ARGS__, kExprEnd
#define TYPE_IMM(t) \
static_cast<byte>((t).value_type_code()), U32V_1((t).ref_index())
#define WASM_BLOCK_T(t, ...) \ #define WASM_BLOCK_T(t, ...) \
kExprBlock, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd kExprBlock, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd
#define WASM_BLOCK_X(index, ...) \ #define WASM_BLOCK_R(t, ...) kExprBlock, TYPE_IMM(t), __VA_ARGS__, kExprEnd
#define WASM_BLOCK_X(index, ...) \
kExprBlock, static_cast<byte>(index), __VA_ARGS__, kExprEnd kExprBlock, static_cast<byte>(index), __VA_ARGS__, kExprEnd
#define WASM_INFINITE_LOOP kExprLoop, kLocalVoid, kExprBr, DEPTH_0, kExprEnd #define WASM_INFINITE_LOOP kExprLoop, kLocalVoid, kExprBr, DEPTH_0, kExprEnd
...@@ -106,7 +111,9 @@ ...@@ -106,7 +111,9 @@
#define WASM_LOOP_T(t, ...) \ #define WASM_LOOP_T(t, ...) \
kExprLoop, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd kExprLoop, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd
#define WASM_LOOP_X(index, ...) \ #define WASM_LOOP_R(t, ...) kExprLoop, TYPE_IMM(t), __VA_ARGS__, kExprEnd
#define WASM_LOOP_X(index, ...) \
kExprLoop, static_cast<byte>(index), __VA_ARGS__, kExprEnd kExprLoop, static_cast<byte>(index), __VA_ARGS__, kExprEnd
#define WASM_IF(cond, ...) cond, kExprIf, kLocalVoid, __VA_ARGS__, kExprEnd #define WASM_IF(cond, ...) cond, kExprIf, kLocalVoid, __VA_ARGS__, kExprEnd
...@@ -114,6 +121,9 @@ ...@@ -114,6 +121,9 @@
#define WASM_IF_T(t, cond, ...) \ #define WASM_IF_T(t, cond, ...) \
cond, kExprIf, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd cond, kExprIf, static_cast<byte>((t).value_type_code()), __VA_ARGS__, kExprEnd
#define WASM_IF_R(t, cond, ...) \
cond, kExprIf, TYPE_IMM(t), __VA_ARGS__, kExprEnd
#define WASM_IF_X(index, cond, ...) \ #define WASM_IF_X(index, cond, ...) \
cond, kExprIf, static_cast<byte>(index), __VA_ARGS__, kExprEnd cond, kExprIf, static_cast<byte>(index), __VA_ARGS__, kExprEnd
...@@ -133,12 +143,17 @@ ...@@ -133,12 +143,17 @@
cond, kExprIf, static_cast<byte>((t).value_type_code()), tstmt, kExprElse, \ cond, kExprIf, static_cast<byte>((t).value_type_code()), tstmt, kExprElse, \
fstmt, kExprEnd fstmt, kExprEnd
#define WASM_IF_ELSE_R(t, cond, tstmt, fstmt) \
cond, kExprIf, TYPE_IMM(t), tstmt, kExprElse, fstmt, kExprEnd
#define WASM_IF_ELSE_X(index, cond, tstmt, fstmt) \ #define WASM_IF_ELSE_X(index, cond, tstmt, fstmt) \
cond, kExprIf, static_cast<byte>(index), tstmt, kExprElse, fstmt, kExprEnd cond, kExprIf, static_cast<byte>(index), tstmt, kExprElse, fstmt, kExprEnd
#define WASM_TRY_CATCH_T(t, trystmt, catchstmt) \ #define WASM_TRY_CATCH_T(t, trystmt, catchstmt) \
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprCatch, \ kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprCatch, \
catchstmt, kExprEnd catchstmt, kExprEnd
#define WASM_TRY_CATCH_R(t, trystmt, catchstmt) \
kExprTry, TYPE_IMM(t), trystmt, kExprCatch, catchstmt, kExprEnd
#define WASM_SELECT(tval, fval, cond) tval, fval, cond, kExprSelect #define WASM_SELECT(tval, fval, cond) tval, fval, cond, kExprSelect
#define WASM_SELECT_I(tval, fval, cond) \ #define WASM_SELECT_I(tval, fval, cond) \
...@@ -358,10 +373,6 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -358,10 +373,6 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 48), \ static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 48), \
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 56) static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 56)
#define WASM_REF_NULL kExprRefNull
#define WASM_REF_FUNC(val) kExprRefFunc, val
#define WASM_REF_IS_NULL(val) val, kExprRefIsNull
#define WASM_GET_LOCAL(index) kExprLocalGet, static_cast<byte>(index) #define WASM_GET_LOCAL(index) kExprLocalGet, static_cast<byte>(index)
#define WASM_SET_LOCAL(index, val) val, kExprLocalSet, static_cast<byte>(index) #define WASM_SET_LOCAL(index, val) val, kExprLocalSet, static_cast<byte>(index)
#define WASM_TEE_LOCAL(index, val) val, kExprLocalTee, static_cast<byte>(index) #define WASM_TEE_LOCAL(index, val) val, kExprLocalTee, static_cast<byte>(index)
...@@ -409,6 +420,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -409,6 +420,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define TABLE_ZERO 0 #define TABLE_ZERO 0
//------------------------------------------------------------------------------
// Heap-allocated object operations.
//------------------------------------------------------------------------------
#define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op) #define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op)
#define WASM_STRUCT_NEW(index, ...) \ #define WASM_STRUCT_NEW(index, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructNew), static_cast<byte>(index) __VA_ARGS__, WASM_GC_OP(kExprStructNew), static_cast<byte>(index)
...@@ -418,6 +432,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -418,6 +432,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_STRUCT_SET(typeidx, fieldidx, ...) \ #define WASM_STRUCT_SET(typeidx, fieldidx, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructSet), static_cast<byte>(typeidx), \ __VA_ARGS__, WASM_GC_OP(kExprStructSet), static_cast<byte>(typeidx), \
static_cast<byte>(fieldidx) static_cast<byte>(fieldidx)
#define WASM_REF_NULL kExprRefNull
#define WASM_REF_FUNC(val) kExprRefFunc, val
#define WASM_REF_IS_NULL(val) val, kExprRefIsNull
#define WASM_ARRAY_NEW(index, default_value, length) \ #define WASM_ARRAY_NEW(index, default_value, length) \
default_value, length, WASM_GC_OP(kExprArrayNew), static_cast<byte>(index) default_value, length, WASM_GC_OP(kExprArrayNew), static_cast<byte>(index)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment