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,
map_index++;
}
}
CallDescriptor* call_descriptor =
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,
Node* s = CALL_BUILTIN(
WasmAllocateStruct,
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++) {
StoreStructFieldUnchecked(mcgraph(), gasm_.get(), s, type, i, fields[i]);
}
......
......@@ -2072,8 +2072,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprSelectWithType: {
CHECK_PROTOTYPE_OPCODE(anyref);
SelectTypeImmediate<validate> imm(WasmFeatures::All(), this,
this->pc_);
SelectTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
if (this->failed()) break;
auto cond = Pop(2, kWasmI32);
auto fval = Pop(1, imm.type);
......
......@@ -535,7 +535,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
buffer->write_size(globals_.size());
for (const WasmGlobal& global : globals_) {
buffer->write_u8(global.type.value_type_code());
WriteValueType(buffer, global.type);
buffer->write_u8(global.mutability ? 1 : 0);
switch (global.init.kind) {
case WasmInitExpr::kI32Const:
......@@ -589,6 +589,12 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const {
buffer->write_u8(kExprF64Const);
buffer->write_f64(0.);
break;
case ValueType::kOptRef:
case ValueType::kFuncRef:
case ValueType::kExnRef:
case ValueType::kEqRef:
buffer->write_u8(kExprRefNull);
break;
default:
UNREACHABLE();
}
......
......@@ -44,6 +44,7 @@ WASM_EXEC_TEST(BasicStruct) {
ValueType kOptRefType = ValueType(ValueType::kOptRef, type_index);
FunctionSig sig_q_v(1, 0, kRefTypes);
// Test struct.new and struct.get.
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
f->builder()->AddExport(CStrVector("f"), f);
byte f_code[] = {WASM_STRUCT_GET(type_index, 0,
......@@ -52,6 +53,7 @@ WASM_EXEC_TEST(BasicStruct) {
kExprEnd};
f->EmitCode(f_code, sizeof(f_code));
// Test struct.new and struct.get.
WasmFunctionBuilder* g = builder->AddFunction(sigs.i_v());
g->builder()->AddExport(CStrVector("g"), g);
byte g_code[] = {WASM_STRUCT_GET(type_index, 1,
......@@ -60,24 +62,41 @@ WASM_EXEC_TEST(BasicStruct) {
kExprEnd};
g->EmitCode(g_code, sizeof(g_code));
// Test struct.new, returning struct references to JS.
WasmFunctionBuilder* h = builder->AddFunction(&sig_q_v);
h->builder()->AddExport(CStrVector("h"), h);
byte h_code[] = {WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64)),
kExprEnd};
h->EmitCode(h_code, sizeof(h_code));
// Test struct.set, struct refs types in locals.
WasmFunctionBuilder* j = builder->AddFunction(sigs.i_v());
uint32_t local_index = j->AddLocal(kOptRefType);
uint32_t field_index = 0;
uint32_t j_local_index = j->AddLocal(kOptRefType);
uint32_t j_field_index = 0;
j->builder()->AddExport(CStrVector("j"), j);
byte i_code[] = {
WASM_SET_LOCAL(local_index,
byte j_code[] = {
WASM_SET_LOCAL(j_local_index,
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_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};
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);
builder->WriteTo(&buffer);
......@@ -109,6 +128,9 @@ WASM_EXEC_TEST(BasicStruct) {
CHECK_EQ(-99, testing::CallWasmFunctionForTesting(isolate, instance, &thrower,
"j", 0, nullptr));
CHECK_EQ(55, testing::CallWasmFunctionForTesting(isolate, instance, &thrower,
"k", 0, nullptr));
}
WASM_EXEC_TEST(BasicArray) {
......
......@@ -89,10 +89,15 @@
#define WASM_BLOCK_F(...) kExprBlock, kLocalF32, __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, ...) \
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
#define WASM_INFINITE_LOOP kExprLoop, kLocalVoid, kExprBr, DEPTH_0, kExprEnd
......@@ -106,7 +111,9 @@
#define WASM_LOOP_T(t, ...) \
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
#define WASM_IF(cond, ...) cond, kExprIf, kLocalVoid, __VA_ARGS__, kExprEnd
......@@ -114,6 +121,9 @@
#define WASM_IF_T(t, cond, ...) \
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, ...) \
cond, kExprIf, static_cast<byte>(index), __VA_ARGS__, kExprEnd
......@@ -133,12 +143,17 @@
cond, kExprIf, static_cast<byte>((t).value_type_code()), tstmt, kExprElse, \
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) \
cond, kExprIf, static_cast<byte>(index), tstmt, kExprElse, fstmt, kExprEnd
#define WASM_TRY_CATCH_T(t, trystmt, catchstmt) \
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprCatch, \
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_I(tval, fval, cond) \
......@@ -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)) >> 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_SET_LOCAL(index, val) val, kExprLocalSet, 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) {
#define TABLE_ZERO 0
//------------------------------------------------------------------------------
// Heap-allocated object operations.
//------------------------------------------------------------------------------
#define WASM_GC_OP(op) kGCPrefix, static_cast<byte>(op)
#define WASM_STRUCT_NEW(index, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructNew), static_cast<byte>(index)
......@@ -418,6 +432,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_STRUCT_SET(typeidx, fieldidx, ...) \
__VA_ARGS__, WASM_GC_OP(kExprStructSet), static_cast<byte>(typeidx), \
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) \
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