Skip to content

Commit 595a459

Browse files
committed
Support all gc tests
1 parent 076528b commit 595a459

37 files changed

+2367
-23
lines changed

include/wabt/interp/interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,7 @@ class Thread {
12371237
void Push(Ref);
12381238

12391239
bool CheckRefCast(Ref ref, Type expected);
1240+
bool CheckRefFunc(Ref ref, Index expected_index, Func* new_func);
12401241

12411242
template <typename R, typename T>
12421243
using UnopFunc = R WABT_VECTORCALL(T);

include/wabt/shared-validator.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ class SharedValidator {
9797
Result OnTable(const Location&, Type elem_type, const Limits&, TableImportStatus import_status, TableInitExprStatus init_provided);
9898
Result OnMemory(const Location&, const Limits&, uint32_t page_size);
9999
Result OnGlobalImport(const Location&, Type type, bool mutable_);
100-
Result OnGlobal(const Location&, Type type, bool mutable_);
100+
Result BeginGlobal(const Location&, Type type, bool mutable_);
101+
Result EndGlobal(const Location&);
101102
Result OnTag(const Location&, Var sig_var);
102103

103104
Result OnExport(const Location&,
@@ -391,7 +392,7 @@ class SharedValidator {
391392
std::vector<TagType> tags_; // Includes imported and defined.
392393
std::vector<ElemType> elems_;
393394
Index starts_ = 0;
394-
Index num_imported_globals_ = 0;
395+
Index last_initialized_global_ = 0;
395396
Index data_segments_ = 0;
396397
Index last_rec_type_end_ = 0;
397398
// Recursive type checks may enter to infinite loop for invalid values.

src/binary-writer-spec.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ void BinaryWriterSpec::WriteVar(const Var& var) {
161161
void BinaryWriterSpec::WriteTypeObject(Type type) {
162162
json_stream_->Writef("{");
163163
WriteKey("type");
164+
if (type.IsReferenceWithIndex()) {
165+
// This should happen only for invalid modules.
166+
type = Type::AnyRef;
167+
}
164168
WriteString(type.GetName().c_str());
165169
json_stream_->Writef("}");
166170
}
@@ -284,6 +288,7 @@ void BinaryWriterSpec::WriteConst(const Const& const_) {
284288
break;
285289
}
286290

291+
case Type::NullFuncRef:
287292
case Type::FuncRef: {
288293
WriteString("funcref");
289294
WriteSeparator();

src/interp/binary-reader-interp.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ Result BinaryReaderInterp::OnGlobalCount(Index count) {
814814
}
815815

816816
Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) {
817-
CHECK_RESULT(validator_.OnGlobal(GetLocation(), type, mutable_));
817+
CHECK_RESULT(validator_.BeginGlobal(GetLocation(), type, mutable_));
818818
GlobalType global_type{type, ToMutability(mutable_)};
819819
FuncDesc init_func{FuncType{{}, {type}}, {}, Istream::kInvalidOffset, {}};
820820
module_.globals.push_back(GlobalDesc{global_type, init_func});
@@ -847,6 +847,7 @@ Result BinaryReaderInterp::BeginInitExpr(FuncDesc* func) {
847847
}
848848

849849
Result BinaryReaderInterp::EndGlobalInitExpr(Index index) {
850+
CHECK_RESULT(validator_.EndGlobal(GetLocation()));
850851
return EndInitExpr();
851852
}
852853

@@ -1473,7 +1474,8 @@ Result BinaryReaderInterp::OnCallIndirectExpr(Index sig_index,
14731474
CHECK_RESULT(validator_.OnCallIndirect(GetLocation(),
14741475
Var(sig_index, GetLocation()),
14751476
Var(table_index, GetLocation())));
1476-
istream_.Emit(Opcode::CallIndirect, table_index, sig_index);
1477+
istream_.Emit(Opcode::CallIndirect, table_index,
1478+
module_.func_types[sig_index].canonical_index);
14771479
return Result::Ok;
14781480
}
14791481

@@ -1538,7 +1540,8 @@ Result BinaryReaderInterp::OnReturnCallIndirectExpr(Index sig_index,
15381540
Var(table_index, GetLocation())));
15391541
istream_.EmitDropKeep(drop_count, keep_count);
15401542
istream_.EmitCatchDrop(catch_drop_count);
1541-
istream_.Emit(Opcode::ReturnCallIndirect, table_index, sig_index);
1543+
istream_.Emit(Opcode::ReturnCallIndirect, table_index,
1544+
module_.func_types[sig_index].canonical_index);
15421545
return Result::Ok;
15431546
}
15441547

src/interp/interp.cc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,31 @@ bool Thread::CheckRefCast(Ref ref, Type expected) {
15981598
return false;
15991599
}
16001600

1601+
bool Thread::CheckRefFunc(Ref ref, Index expected_type_index, Func* new_func) {
1602+
// Validator checks that the table contains funcrefs.
1603+
assert(!ref.IsI31OrHostVal());
1604+
Object* object = store_.UnsafeGet<Object>(ref).get();
1605+
assert(Func::classof(object));
1606+
1607+
const FuncType& type = cast<Func>(object)->type();
1608+
if (type.func_types != &mod_->desc().func_types) {
1609+
auto&& func_type = mod_->desc().func_types[expected_type_index];
1610+
return Succeeded(Match(new_func->type(), func_type, nullptr));
1611+
}
1612+
Index actual_type_index = type.canonical_index;
1613+
1614+
do {
1615+
if (expected_type_index == actual_type_index) {
1616+
return true;
1617+
}
1618+
1619+
actual_type_index =
1620+
mod_->desc().func_types[actual_type_index].canonical_sub_index;
1621+
} while (actual_type_index != kInvalidIndex);
1622+
1623+
return false;
1624+
}
1625+
16011626
RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
16021627
using O = Opcode;
16031628

@@ -1668,15 +1693,14 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
16681693
case O::CallIndirect:
16691694
case O::ReturnCallIndirect: {
16701695
Table::Ptr table{store_, inst_->tables()[instr.imm_u32x2.fst]};
1671-
auto&& func_type = mod_->desc().func_types[instr.imm_u32x2.snd];
16721696
u64 entry = PopPtr(table);
16731697
TRAP_IF(entry >= table->elements().size(), "undefined table index");
16741698
auto new_func_ref = table->elements()[entry];
16751699
TRAP_IF(new_func_ref == Ref::Null, "uninitialized table element");
16761700
Func::Ptr new_func{store_, new_func_ref};
1677-
TRAP_IF(
1678-
Failed(Match(new_func->type(), func_type, nullptr)),
1679-
"indirect call signature mismatch"); // TODO: don't use "signature"
1701+
// TODO: don't use "signature"
1702+
TRAP_IF(!CheckRefFunc(new_func_ref, instr.imm_u32x2.snd, new_func.get()),
1703+
"indirect call signature mismatch");
16801704
if (instr.op == O::ReturnCallIndirect) {
16811705
return DoReturnCall(new_func, out_trap);
16821706
} else {

src/shared-validator.cc

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ Result SharedValidator::OnFuncType(const Location& loc,
8585
}
8686

8787
type_validation_result_ |= result;
88-
result |= CheckSupertypes(loc, supertypes);
8988
}
89+
result |= CheckSupertypes(loc, supertypes);
9090

9191
return result;
9292
}
@@ -233,19 +233,26 @@ Result SharedValidator::OnGlobalImport(const Location& loc,
233233
result |= PrintError(loc, "mutable globals cannot be imported");
234234
}
235235
globals_.push_back(GlobalType{type, mutable_});
236-
++num_imported_globals_;
236+
++last_initialized_global_;
237237
return result;
238238
}
239239

240-
Result SharedValidator::OnGlobal(const Location& loc,
241-
Type type,
242-
bool mutable_) {
240+
Result SharedValidator::BeginGlobal(const Location& loc,
241+
Type type,
242+
bool mutable_) {
243243
CHECK_RESULT(
244244
CheckReferenceType(loc, type, type_fields_.NumTypes(), "globals"));
245245
globals_.push_back(GlobalType{type, mutable_});
246246
return Result::Ok;
247247
}
248248

249+
Result SharedValidator::EndGlobal(const Location&) {
250+
if (options_.features.gc_enabled()) {
251+
last_initialized_global_++;
252+
}
253+
return Result::Ok;
254+
}
255+
249256
Result SharedValidator::CheckType(const Location& loc,
250257
Type actual,
251258
Type expected,
@@ -274,8 +281,6 @@ Result SharedValidator::CheckReferenceType(const Location& loc,
274281

275282
Result SharedValidator::CheckSupertypes(const Location& loc,
276283
SupertypesInfo* supertypes) {
277-
assert(options_.features.function_references_enabled());
278-
279284
TypeEntry& entry = type_fields_.type_entries.back();
280285
Index current_index = type_fields_.NumTypes() - 1;
281286
Index end_index;
@@ -783,8 +788,7 @@ Index SharedValidator::GetCanonicalTypeIndex(Index type_index) {
783788
return kInvalidIndex;
784789
}
785790

786-
if (options_.features.function_references_enabled() &&
787-
Succeeded(type_validation_result_)) {
791+
if (Succeeded(type_validation_result_)) {
788792
return type_fields_.type_entries[type_index].canonical_index;
789793
}
790794

@@ -1207,7 +1211,7 @@ Result SharedValidator::OnCallIndirect(const Location& loc,
12071211
TableType table_type;
12081212
result |= CheckFuncTypeIndex(sig_var, &func_type);
12091213
result |= CheckTableIndex(table_var, &table_type);
1210-
if (table_type.element != Type::FuncRef) {
1214+
if (Failed(typechecker_.CheckType(table_type.element, Type::FuncRef))) {
12111215
result |= PrintError(
12121216
loc,
12131217
"type mismatch: call_indirect must reference table of funcref type");
@@ -1316,7 +1320,7 @@ Result SharedValidator::OnGlobalGet(const Location& loc, Var global_var) {
13161320
result |= CheckGlobalIndex(global_var, &global_type);
13171321
result |= typechecker_.OnGlobalGet(global_type.type);
13181322
if (Succeeded(result) && in_init_expr_) {
1319-
if (global_var.index() >= num_imported_globals_) {
1323+
if (global_var.index() >= last_initialized_global_) {
13201324
result |= PrintError(
13211325
global_var.loc,
13221326
"initializer expression can only reference an imported global");

src/tools/spectest-interp.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,8 @@ wabt::Result CommandRunner::CheckAssertReturnResult(
20032003
ok = obj->kind() == ObjectKind::Array ||
20042004
obj->kind() == ObjectKind::Struct;
20052005
}
2006+
} else {
2007+
ok = expected.value.type == Type::AnyRef;
20062008
}
20072009
break;
20082010
}

src/validator.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,14 +1080,15 @@ Result Validator::CheckModule() {
10801080
for (const ModuleField& field : module->fields) {
10811081
if (auto* f = dyn_cast<GlobalModuleField>(&field)) {
10821082
result_ |=
1083-
validator_.OnGlobal(field.loc, f->global.type, f->global.mutable_);
1083+
validator_.BeginGlobal(field.loc, f->global.type, f->global.mutable_);
10841084

10851085
// Init expr.
10861086
result_ |= validator_.BeginInitExpr(field.loc, f->global.type);
10871087
ExprVisitor visitor(this);
10881088
result_ |=
10891089
visitor.VisitExprList(const_cast<ExprList&>(f->global.init_expr));
10901090
result_ |= validator_.EndInitExpr();
1091+
result_ |= validator_.EndGlobal(field.loc);
10911092
}
10921093
}
10931094

test/spec/call_indirect.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ out/test/spec/call_indirect.wast:776: assert_malformed passed:
8686
^^^^^^^^^^^^^
8787
out/test/spec/call_indirect.wast:791: assert_invalid passed:
8888
out/test/spec/call_indirect/call_indirect.13.wasm:000001c: error: table variable out of range: 0 (max 0)
89-
out/test/spec/call_indirect/call_indirect.13.wasm:000001c: error: type mismatch: call_indirect must reference table of funcref type
9089
000001c: error: OnCallIndirectExpr callback failed
9190
out/test/spec/call_indirect.wast:799: assert_invalid passed:
9291
out/test/spec/call_indirect/call_indirect.14.wasm:0000023: error: type mismatch in i32.eqz, expected [i32] but got []

test/spec/gc/array_new_data.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
;;; TOOL: run-interp-spec
2+
;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_new_data.wast
3+
;;; ARGS*: --enable-gc
4+
(;; STDOUT ;;;
5+
out/test/spec/gc/array_new_data.wast:18: assert_trap passed: invalid range
6+
out/test/spec/gc/array_new_data.wast:19: assert_trap passed: invalid range
7+
out/test/spec/gc/array_new_data.wast:20: assert_trap passed: invalid range
8+
out/test/spec/gc/array_new_data.wast:21: assert_trap passed: invalid range
9+
15/15 tests passed.
10+
;;; STDOUT ;;)

0 commit comments

Comments
 (0)