diff --git a/include/wabt/wast-parser.h b/include/wabt/wast-parser.h index e071c5c8df..24676d951b 100644 --- a/include/wabt/wast-parser.h +++ b/include/wabt/wast-parser.h @@ -262,7 +262,7 @@ class WastParser { Result ParseCatchInstrList(CatchVector* catches); Result ParseCatchExprList(CatchVector* catches); Result ParseGlobalType(Global*); - Result ParseField(Field*); + Result ParseField(Field*, Var* out_type, bool* defer_named_ref); Result ParseFieldList(std::vector*); template diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 9272de391b..6d90ddabd4 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1790,7 +1790,12 @@ Result WastParser::ParseTypeModuleField(Module* module) { Error(loc, "array type not allowed"); } auto array_type = std::make_unique(name); - CHECK_RESULT(ParseField(&array_type->field)); + Var type_var; + bool defer_named_ref = false; + CHECK_RESULT(ParseField(&array_type->field, &type_var, &defer_named_ref)); + if (defer_named_ref) { + VarToType(type_var, &array_type->field.type); + } field->type = std::move(array_type); } else { return ErrorExpected({"func", "struct", "array"}); @@ -1802,21 +1807,28 @@ Result WastParser::ParseTypeModuleField(Module* module) { return Result::Ok; } -Result WastParser::ParseField(Field* field) { +Result WastParser::ParseField(Field* field, + Var* out_type, + bool* defer_named_ref) { WABT_TRACE(ParseField); auto parse_mut_valuetype = [&]() -> Result { // TODO: Share with ParseGlobalType? if (MatchLpar(TokenType::Mut)) { field->mutable_ = true; - Var type; - CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.opt_type()); + CHECK_RESULT(ParseValueType(out_type)); EXPECT(Rpar); } else { field->mutable_ = false; - Var type; - CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.opt_type()); + CHECK_RESULT(ParseValueType(out_type)); + } + + if (!Type::EnumIsReferenceWithIndex(out_type->opt_type()) || + out_type->is_index()) { + field->type = out_type->to_type(); + *defer_named_ref = false; + } else { + field->type = Type(out_type->opt_type(), kInvalidIndex); + *defer_named_ref = true; } return Result::Ok; }; @@ -1834,11 +1846,26 @@ Result WastParser::ParseField(Field* field) { Result WastParser::ParseFieldList(std::vector* fields) { WABT_TRACE(ParseFieldList); + struct Deferred { + size_t index; + Var var; + }; + std::vector deferred; + while (PeekMatch(TokenType::ValueType) || PeekMatch(TokenType::Lpar)) { Field field; - CHECK_RESULT(ParseField(&field)); + Var type_var; + bool defer_named_ref = false; + CHECK_RESULT(ParseField(&field, &type_var, &defer_named_ref)); + if (defer_named_ref) { + deferred.push_back({fields->size(), type_var}); + } fields->push_back(field); } + + for (const auto& d : deferred) { + VarToType(d.var, &(*fields)[d.index].type); + } return Result::Ok; } diff --git a/test/regress/regress-2750.txt b/test/regress/regress-2750.txt new file mode 100644 index 0000000000..c40759165c --- /dev/null +++ b/test/regress/regress-2750.txt @@ -0,0 +1,23 @@ +;;; TOOL: run-roundtrip +;;; ARGS: --stdout --enable-gc --enable-function-references + +(module + (type $t0 (struct)) + (type $t1 (func)) + + (type + (struct + (field (ref 1)) + (field (mut (ref null 1))) + (field (ref $t1)))) + + (type + (array (ref 1)))) + +(;; STDOUT ;;; +(module + (type (;0;) (struct)) + (type (;1;) (func)) + (type (;2;) (struct (field (;0;) (ref 1)) (field (;1;) (mut (ref null 1))) (field (;2;) (ref 1)))) + (type (;3;) (array (ref 1)))) +;;; STDOUT ;;) diff --git a/test/run-roundtrip.py b/test/run-roundtrip.py index 95e1e0a7b3..c27be1d22e 100755 --- a/test/run-roundtrip.py +++ b/test/run-roundtrip.py @@ -107,6 +107,7 @@ def main(args): parser.add_argument('--enable-exceptions', action='store_true') parser.add_argument('--enable-saturating-float-to-int', action='store_true') parser.add_argument('--enable-function-references', action='store_true') + parser.add_argument('--enable-gc', action='store_true') parser.add_argument('--enable-threads', action='store_true') parser.add_argument('--enable-sign-extension', action='store_true') parser.add_argument('--enable-multi-value', action='store_true') @@ -136,6 +137,7 @@ def main(args): options.enable_saturating_float_to_int, '--enable-sign-extension': options.enable_sign_extension, '--enable-function-references': options.enable_function_references, + '--enable-gc': options.enable_gc, '--enable-threads': options.enable_threads, '--enable-tail-call': options.enable_tail_call, '--disable-reference-types': options.disable_reference_types, @@ -160,6 +162,7 @@ def main(args): '--enable-sign-extension': options.enable_sign_extension, '--enable-tail-call': options.enable_tail_call, '--enable-function-references': options.enable_function_references, + '--enable-gc': options.enable_gc, '--disable-reference-types': options.disable_reference_types, '--enable-threads': options.enable_threads, '--enable-memory64': options.enable_memory64,