From cacacc7992ff4a0a9e1fe323bff2f46017f73270 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Fri, 7 Mar 2025 10:39:19 +0000 Subject: [PATCH 1/6] Add support for function references proposal Support named references for globals, locals, tables, elems Support named references for call_ref, ref_null Extend Var variables with an optional type field --- include/wabt/binary-reader-logging.h | 2 +- include/wabt/binary-reader-nop.h | 2 +- include/wabt/binary-reader.h | 2 +- include/wabt/interp/interp-inl.h | 2 +- include/wabt/interp/interp.h | 4 + include/wabt/ir.h | 44 ++- include/wabt/shared-validator.h | 29 +- include/wabt/token.def | 1 + include/wabt/type-checker.h | 24 +- include/wabt/type.h | 62 +++- include/wabt/wast-parser.h | 62 ++-- src/binary-reader-ir.cc | 16 +- src/binary-reader-logging.cc | 2 +- src/binary-reader-objdump.cc | 2 +- src/binary-reader.cc | 77 ++++- src/binary-writer.cc | 21 +- src/c-writer.cc | 21 +- src/interp/binary-reader-interp.cc | 17 +- src/interp/interp-util.cc | 2 + src/interp/interp.cc | 109 ++++++- src/ir-util.cc | 2 +- src/ir.cc | 55 +++- src/leb128.cc | 12 +- src/lexer-keywords.txt | 3 +- src/prebuilt/lexer-keywords.cc | 134 ++++---- src/resolve-names.cc | 12 + src/shared-validator.cc | 181 +++++++++-- src/type-checker.cc | 118 +++++-- src/validator.cc | 48 ++- src/wast-parser.cc | 295 +++++++++++------- src/wat-writer.cc | 8 +- test/binary/bad-reference-indicies.txt | 8 +- test/dump/call_ref.txt | 58 ++-- test/dump/typed-func-ref-signature.txt | 6 +- test/dump/typed-func-refs-locals.txt | 86 ++--- test/dump/typed_func_refs_params.txt | 106 ++++--- test/dump/typed_func_refs_results.txt | 23 +- test/parse/bad-references.txt | 22 +- test/parse/expr/callref-imported-function.txt | 5 +- test/parse/expr/callref-internal-function.txt | 6 +- ...element-followed-by-illegal-expression.txt | 4 +- test/roundtrip/fold-callref.txt | 30 +- test/roundtrip/ref-types.txt | 37 +++ test/roundtrip/typed-func-refs.txt | 11 +- test/spec/function-references/br_table.txt | 78 +++++ test/spec/function-references/call_ref.txt | 19 ++ test/spec/function-references/func.txt | 257 +++++++++++++++ test/spec/function-references/global.txt | 141 +++++++++ test/spec/function-references/local_init.txt | 18 ++ test/spec/function-references/ref.txt | 43 +++ .../function-references/type-equivalence.txt | 12 + test/typecheck/bad-callref-empty.txt | 8 +- test/typecheck/bad-callref-int32.txt | 10 +- test/typecheck/bad-callref-nosubtype.txt | 18 ++ test/typecheck/bad-callref-null.txt | 10 +- 55 files changed, 1825 insertions(+), 560 deletions(-) create mode 100644 test/roundtrip/ref-types.txt create mode 100644 test/spec/function-references/br_table.txt create mode 100644 test/spec/function-references/call_ref.txt create mode 100644 test/spec/function-references/func.txt create mode 100644 test/spec/function-references/global.txt create mode 100644 test/spec/function-references/local_init.txt create mode 100644 test/spec/function-references/ref.txt create mode 100644 test/spec/function-references/type-equivalence.txt create mode 100644 test/typecheck/bad-callref-nosubtype.txt diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 4a031f74bb..12fdaa1c72 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -181,7 +181,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnCatchExpr(Index tag_index) override; Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index, Index table_index) override; - Result OnCallRefExpr() override; + Result OnCallRefExpr(Type sig_type) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; Result OnDelegateExpr(Index depth) override; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index fdb7d14a41..d10691fbbc 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -250,7 +250,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; } - Result OnCallRefExpr() override { return Result::Ok; } + Result OnCallRefExpr(Type sig_type) override { return Result::Ok; } Result OnCatchExpr(Index tag_index) override { return Result::Ok; } Result OnCatchAllExpr() override { return Result::Ok; } Result OnCompareExpr(Opcode opcode) override { return Result::Ok; } diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index 94b19c1100..d7135141b9 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -255,7 +255,7 @@ class BinaryReaderDelegate { Index default_target_depth) = 0; virtual Result OnCallExpr(Index func_index) = 0; virtual Result OnCallIndirectExpr(Index sig_index, Index table_index) = 0; - virtual Result OnCallRefExpr() = 0; + virtual Result OnCallRefExpr(Type sig_type) = 0; virtual Result OnCatchExpr(Index tag_index) = 0; virtual Result OnCatchAllExpr() = 0; virtual Result OnCompareExpr(Opcode opcode) = 0; diff --git a/include/wabt/interp/interp-inl.h b/include/wabt/interp/interp-inl.h index a9ac4a3488..074fc9fc9f 100644 --- a/include/wabt/interp/interp-inl.h +++ b/include/wabt/interp/interp-inl.h @@ -42,7 +42,7 @@ inline bool FuncType::classof(const ExternType* type) { } inline FuncType::FuncType(ValueTypes params, ValueTypes results) - : ExternType(ExternKind::Func), params(params), results(results) {} + : ExternType(ExternKind::Func), params(params), results(results), func_types(nullptr) {} //// TableType //// // static diff --git a/include/wabt/interp/interp.h b/include/wabt/interp/interp.h index 9ce7b1815e..4e376eb327 100644 --- a/include/wabt/interp/interp.h +++ b/include/wabt/interp/interp.h @@ -184,6 +184,10 @@ struct FuncType : ExternType { ValueTypes params; ValueTypes results; + // When params or results contain references, the referenced + // types are also needed for type equality comparisons. + // An example for these comparisons is import validation. + std::vector* func_types; }; struct TableType : ExternType { diff --git a/include/wabt/ir.h b/include/wabt/ir.h index 5fa4439a0c..2f4a245216 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -36,24 +36,43 @@ namespace wabt { struct Module; -enum class VarType { +// VarType (16 bit) and the opt_type_ (16 bit) +// fields of Var forms a 32 bit field. +enum class VarType : uint16_t { Index, Name, }; struct Var { + // Var can represent variables or types. + + // Represent a variable: + // has_opt_type() is false + // Only used by wast-parser + + // Represent a type: + // has_opt_type() is true, is_index() is true + // type can be get by to_type() + // Binary reader only constructs this variant + + // Represent both a variable and a type: + // has_opt_type() is true, is_name() is true + // A reference, which index is unknown + // Only used by wast-parser + explicit Var(); explicit Var(Index index, const Location& loc); explicit Var(std::string_view name, const Location& loc); + explicit Var(Type type, const Location& loc); Var(Var&&); Var(const Var&); Var& operator=(const Var&); Var& operator=(Var&&); ~Var(); - VarType type() const { return type_; } bool is_index() const { return type_ == VarType::Index; } bool is_name() const { return type_ == VarType::Name; } + bool has_opt_type() const { return opt_type_ < 0; } Index index() const { assert(is_index()); @@ -63,10 +82,16 @@ struct Var { assert(is_name()); return name_; } + Type::Enum opt_type() const { + assert(has_opt_type()); + return static_cast(opt_type_); + } void set_index(Index); void set_name(std::string&&); void set_name(std::string_view); + void set_opt_type(Type::Enum); + Type to_type() const; Location loc; @@ -74,6 +99,8 @@ struct Var { void Destroy(); VarType type_; + // Can be set to Type::Enum types, Type::Any represent no optional type. + int16_t opt_type_; union { Index index_; std::string name_; @@ -155,6 +182,7 @@ struct Const { } void set_funcref() { From(Type::FuncRef, 0); } void set_externref(uintptr_t x) { From(Type::ExternRef, x); } + void set_extern(uintptr_t x) { From(Type(Type::ExternRef, Type::ReferenceNonNull), x); } void set_null(Type type) { From(type, kRefNullBits); } bool is_expected_nan(int lane = 0) const { @@ -537,10 +565,10 @@ using MemoryCopyExpr = MemoryBinaryExpr; template class RefTypeExpr : public ExprMixin { public: - RefTypeExpr(Type type, const Location& loc = Location()) + RefTypeExpr(Var type, const Location& loc = Location()) : ExprMixin(loc), type(type) {} - Type type; + Var type; }; using RefNullExpr = RefTypeExpr; @@ -662,8 +690,8 @@ using MemoryInitExpr = MemoryVarExpr; class SelectExpr : public ExprMixin { public: - SelectExpr(TypeVector type, const Location& loc = Location()) - : ExprMixin(loc), result_type(type) {} + SelectExpr(const Location& loc = Location()) + : ExprMixin(loc) {} TypeVector result_type; }; @@ -727,9 +755,7 @@ class CallRefExpr : public ExprMixin { explicit CallRefExpr(const Location& loc = Location()) : ExprMixin(loc) {} - // This field is setup only during Validate phase, - // so keep that in mind when you use it. - Var function_type_index; + Var sig_type; }; template diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index 267a77b276..8478f7da53 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -43,6 +43,7 @@ struct ValidateOptions { class SharedValidator { public: WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator); + using FuncType = TypeChecker::FuncType; SharedValidator(Errors*, const ValidateOptions& options); // TODO: Move into SharedValidator? @@ -72,7 +73,6 @@ class SharedValidator { Index type_index); Result OnStructType(const Location&, Index field_count, TypeMut* fields); Result OnArrayType(const Location&, TypeMut field); - Result EndTypeSection(); Result OnFunction(const Location&, Var sig_var); Result OnTable(const Location&, Type elem_type, const Limits&); @@ -141,7 +141,7 @@ class SharedValidator { Result EndBrTable(const Location&); Result OnCall(const Location&, Var func_var); Result OnCallIndirect(const Location&, Var sig_var, Var table_var); - Result OnCallRef(const Location&, Index* function_type_index); + Result OnCallRef(const Location&, Var function_type_var); Result OnCatch(const Location&, Var tag_var, bool is_catch_all); Result OnCompare(const Location&, Opcode); Result OnConst(const Location&, Type); @@ -178,7 +178,7 @@ class SharedValidator { Result OnNop(const Location&); Result OnRefFunc(const Location&, Var func_var); Result OnRefIsNull(const Location&); - Result OnRefNull(const Location&, Type type); + Result OnRefNull(const Location&, Var func_type_var); Result OnRethrow(const Location&, Var depth); Result OnReturnCall(const Location&, Var func_var); Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var); @@ -221,18 +221,6 @@ class SharedValidator { Result OnUnreachable(const Location&); private: - struct FuncType { - FuncType() = default; - FuncType(const TypeVector& params, - const TypeVector& results, - Index type_index) - : params(params), results(results), type_index(type_index) {} - - TypeVector params; - TypeVector results; - Index type_index; - }; - struct StructType { StructType() = default; StructType(const TypeMutVector& fields) : fields(fields) {} @@ -289,6 +277,11 @@ class SharedValidator { Index end; }; + struct LocalReferenceMap { + Type type; + Index bit_index; + }; + bool ValidInitOpcode(Opcode opcode) const; Result CheckInstr(Opcode opcode, const Location& loc); Result CheckType(const Location&, @@ -336,6 +329,10 @@ class SharedValidator { TypeVector ToTypeVector(Index count, const Type* types); + void SaveLocalRefs(); + void RestoreLocalRefs(Result result); + void IgnoreLocalRefs(); + ValidateOptions options_; Errors* errors_; TypeChecker typechecker_; // TODO: Move into SharedValidator. @@ -361,6 +358,8 @@ class SharedValidator { // Includes parameters, since this is only used for validating // local.{get,set,tee} instructions. std::vector locals_; + std::map local_refs_map_; + std::vector local_ref_is_set_; std::set export_names_; // Used to check for duplicates. std::set declared_funcs_; // TODO: optimize? diff --git a/include/wabt/token.def b/include/wabt/token.def index f2f05aec34..85b36cd988 100644 --- a/include/wabt/token.def +++ b/include/wabt/token.def @@ -55,6 +55,7 @@ WABT_TOKEN(Module, "module") WABT_TOKEN(Mut, "mut") WABT_TOKEN(NanArithmetic, "nan:arithmetic") WABT_TOKEN(NanCanonical, "nan:canonical") +WABT_TOKEN(Null, "null") WABT_TOKEN(Offset, "offset") WABT_TOKEN(Output, "output") WABT_TOKEN(PageSize, "pagesize") diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h index 85575c3c8b..e2c315e746 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "wabt/common.h" #include "wabt/feature.h" @@ -31,6 +32,18 @@ class TypeChecker { public: using ErrorCallback = std::function; + struct FuncType { + FuncType() = default; + FuncType(const TypeVector& params, + const TypeVector& results, + Index type_index) + : params(params), results(results), type_index(type_index) {} + + TypeVector params; + TypeVector results; + Index type_index; + }; + struct Label { Label(LabelType, const TypeVector& param_types, @@ -46,9 +59,11 @@ class TypeChecker { TypeVector result_types; size_t type_stack_limit; bool unreachable; + std::vector local_ref_is_set_; }; - explicit TypeChecker(const Features& features) : features_(features) {} + explicit TypeChecker(const Features& features, std::map& func_types) + : features_(features), func_types_(func_types) {} void set_error_callback(const ErrorCallback& error_callback) { error_callback_ = error_callback; @@ -80,7 +95,7 @@ class TypeChecker { Result OnCallIndirect(const TypeVector& param_types, const TypeVector& result_types, const Limits& table_limits); - Result OnIndexedFuncRef(Index* out_index); + Result OnCallRef(Type); Result OnReturnCall(const TypeVector& param_types, const TypeVector& result_types); Result OnReturnCallIndirect(const TypeVector& param_types, @@ -115,7 +130,7 @@ class TypeChecker { Result OnTableGrow(Type elem_type, const Limits& limits); Result OnTableSize(const Limits& limits); Result OnTableFill(Type elem_type, const Limits& limits); - Result OnRefFuncExpr(Index func_type, bool force_generic_funcref); + Result OnRefFuncExpr(Index func_type); Result OnRefNullExpr(Type type); Result OnRefIsNullExpr(); Result OnRethrow(Index depth); @@ -141,7 +156,7 @@ class TypeChecker { Result BeginInitExpr(Type type); Result EndInitExpr(); - static Result CheckType(Type actual, Type expected); + Result CheckType(Type actual, Type expected); private: void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* fmt, ...); @@ -210,6 +225,7 @@ class TypeChecker { // to represent "any". TypeVector* br_table_sig_ = nullptr; Features features_; + std::map& func_types_; }; } // namespace wabt diff --git a/include/wabt/type.h b/include/wabt/type.h index 30234166b3..8ef73112db 100644 --- a/include/wabt/type.h +++ b/include/wabt/type.h @@ -46,6 +46,8 @@ class Type { FuncRef = -0x10, // 0x70 ExternRef = -0x11, // 0x6f Reference = -0x15, // 0x6b + Ref = -0x1c, // 0x64 + RefNull = -0x1d, // 0x63 Func = -0x20, // 0x60 Struct = -0x21, // 0x5f Array = -0x22, // 0x5e @@ -58,17 +60,25 @@ class Type { I32U = 7, // Not actually specified, but used internally with load/store }; + // Used by FuncRef / ExternRef + enum GenericReferenceType : uint32_t { + ReferenceOrNull = 0, + ReferenceNonNull = 1, + }; + Type() = default; // Provided so Type can be member of a union. Type(int32_t code) : enum_(static_cast(code)), type_index_(0) { - assert(!EnumIsReferenceWithIndex(enum_)); + assert(!IsReferenceWithIndex()); } Type(Enum e) : enum_(e), type_index_(0) { - assert(!EnumIsReferenceWithIndex(enum_)); + assert(!IsReferenceWithIndex()); } Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) { - assert(EnumIsReferenceWithIndex(e)); + assert(IsReferenceWithIndex() || + (IsNonTypedRef() && (type_index_ == ReferenceOrNull || type_index_ == ReferenceNonNull))); } + constexpr operator Enum() const { return enum_; } friend constexpr bool operator==(const Type a, const Type b) { @@ -90,14 +100,30 @@ class Type { bool IsRef() const { return enum_ == Type::ExternRef || enum_ == Type::FuncRef || - enum_ == Type::Reference || enum_ == Type::ExnRef; + enum_ == Type::Reference || enum_ == Type::ExnRef || + enum_ == Type::RefNull || enum_ == Type::Ref; + } + + bool IsNullableRef() const { + return enum_ == Type::Reference || enum_ == Type::ExnRef || + enum_ == Type::RefNull || + ((enum_ == Type::ExternRef || enum_ == Type::FuncRef) && type_index_ == ReferenceOrNull); + } + + bool IsNonNullableRef() const { + return enum_ == Type::Ref || + ((enum_ == Type::ExternRef || enum_ == Type::FuncRef) && type_index_ != ReferenceOrNull); } bool IsReferenceWithIndex() const { return EnumIsReferenceWithIndex(enum_); } - bool IsNullableRef() const { - // Currently all reftypes are nullable - return IsRef(); + bool IsNonTypedRef() const { + return EnumIsNonTypedRef(enum_); + } + + bool IsNullableNonTypedRef() const { + assert(EnumIsNonTypedRef(enum_)); + return type_index_ == ReferenceOrNull; } std::string GetName() const { @@ -110,13 +136,18 @@ class Type { case Type::I8: return "i8"; case Type::I16: return "i16"; case Type::ExnRef: return "exnref"; - case Type::FuncRef: return "funcref"; case Type::Func: return "func"; case Type::Void: return "void"; case Type::Any: return "any"; - case Type::ExternRef: return "externref"; + case Type::FuncRef: + return type_index_ == ReferenceOrNull ? "funcref" : "(ref func)"; + case Type::ExternRef: + return type_index_ == ReferenceOrNull ? "externref" : "(ref extern)"; case Type::Reference: + case Type::Ref: return StringPrintf("(ref %d)", type_index_); + case Type::RefNull: + return StringPrintf("(ref null %d)", type_index_); default: return StringPrintf("", enum_); } @@ -153,7 +184,7 @@ class Type { } Index GetReferenceIndex() const { - assert(enum_ == Enum::Reference); + assert(IsReferenceWithIndex()); return type_index_; } @@ -172,6 +203,8 @@ class Type { case Type::ExnRef: case Type::ExternRef: case Type::Reference: + case Type::Ref: + case Type::RefNull: return TypeVector(this, this + 1); default: @@ -179,11 +212,16 @@ class Type { } } - private: static bool EnumIsReferenceWithIndex(Enum value) { - return value == Type::Reference; + return value == Type::Reference || value == Type::Ref || + value == Type::RefNull; + } + + static bool EnumIsNonTypedRef(Enum value) { + return value == Type::ExternRef || value == Type::FuncRef; } + private: Enum enum_; // This index is 0 for non-references, so a zeroed // memory area represents a valid Type::Any type. diff --git a/include/wabt/wast-parser.h b/include/wabt/wast-parser.h index 7a60af23b5..ad1c935da3 100644 --- a/include/wabt/wast-parser.h +++ b/include/wabt/wast-parser.h @@ -56,6 +56,14 @@ class WastParser { Expectation, }; + struct ResolveRefType { + ResolveRefType(Type* target_type, Var var) + : target_type(target_type), var(var) {} + + Type* target_type; + Var var; + }; + struct ReferenceVar { ReferenceVar(uint32_t index, Var var) : index(index), var(var) {} @@ -66,16 +74,16 @@ class WastParser { typedef std::vector ReferenceVars; - struct ResolveTypes { - ResolveTypes(TypeVector* target_types) - : target_types(target_types) {} + struct ResolveTypeVector { + ResolveTypeVector(TypeVector* target_vector) + : target_vector(target_vector) {} - TypeVector* target_types; + TypeVector* target_vector; ReferenceVars vars; }; - struct ResolveFuncs { - ResolveFuncs(Func* target_func) + struct ResolveFunc { + ResolveFunc(Func* target_func) : target_func(target_func) {} Func* target_func; @@ -162,13 +170,14 @@ class WastParser { bool ParseElemExprOpt(ExprList* out_elem_expr); bool ParseElemExprListOpt(ExprListVector* out_list); bool ParseElemExprVarListOpt(ExprListVector* out_list); + Result ParseRefDeclaration(Var* out_type); Result ParseValueType(Var* out_type); Result ParseValueTypeList( TypeVector* out_type_list, ReferenceVars* type_vars); - Result ParseRefKind(Type* out_type); - Result ParseRefType(Type* out_type); - bool ParseRefTypeOpt(Type* out_type); + Result ParseRefKind(Var* out_type); + Result ParseRefType(Var* out_type); + bool ParseRefTypeOpt(Var* out_type, Result& result); Result ParseQuotedText(std::string* text, bool check_utf8 = true); bool ParseOffsetOpt(Address* offset); bool ParseAlignOpt(Address* align); @@ -178,8 +187,9 @@ class WastParser { Result ParsePageSize(uint32_t*); Result ParseNat(uint64_t*, bool is_64); - static Result ResolveRefTypes(const Module&, TypeVector*, - ReferenceVars*, Errors* errors); + static Result ResolveTargetRefType(const Module&, Type*, const Var&, Errors*); + static Result ResolveTargetTypeVector(const Module&, TypeVector*, + ReferenceVars*, Errors*); Result ParseModuleFieldList(Module*); Result ParseModuleField(Module*); Result ParseDataModuleField(Module*); @@ -288,25 +298,29 @@ class WastParser { void CheckImportOrdering(Module*); bool HasError() const; + bool CheckRefType(Type::Enum type); + void VarToType(const Var& var, Type* type); WastLexer* lexer_; Index last_module_index_ = kInvalidIndex; Errors* errors_; WastParseOptions* options_; - // Reference types can have names, for example (ref $foo) represents - // a type which name is $foo. These types are translated to their - // corresponding index after the parsing is completed. The position - // and names of these reference types are stored in a ReferenceVars - // vector. The names are stored as variables, because the error - // message construction requires a location when a name is not found. - std::vector resolve_types_; - - // When some locals are named references, the parser keeps the - // non-compressed local vector until the module parsing is - // completed. After the locals are resolved, local_types are - // constructed from this vector, and then this vector is freed. - std::vector resolve_funcs_; + // Reference types can have names or indicies. For example (ref $foo) + // represents a type which name is $foo, and (ref 5) represents + // the fifth type declaration. Both of these variants needs to + // be validated after the parsing is completed. + + // Single type references are stored in the following vector. + std::vector resolve_ref_types_; + + // Type vectors and their corresponding references are stored in the + // following vector. At least one reference must be present for each vector. + std::vector resolve_type_vectors_; + + // Local vectors and their corresponding references are stored in the + // following vector. At least one reference must be present for each vector. + std::vector resolve_funcs_; // two-element queue of upcoming tokens class TokenQueue { diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 2029b0f7c4..d5f0fab262 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -207,7 +207,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnCatchExpr(Index tag_index) override; Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index, Index table_index) override; - Result OnCallRefExpr() override; + Result OnCallRefExpr(Type sig_type) override; Result OnReturnCallExpr(Index func_index) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; Result OnCompareExpr(Opcode opcode) override; @@ -920,8 +920,10 @@ Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index, Index table_index) { return AppendExpr(std::move(expr)); } -Result BinaryReaderIR::OnCallRefExpr() { - return AppendExpr(std::make_unique()); +Result BinaryReaderIR::OnCallRefExpr(Type sig_type) { + auto expr = std::make_unique(); + expr->sig_type = Var(sig_type, GetLocation()); + return AppendExpr(std::move(expr)); } Result BinaryReaderIR::OnReturnCallExpr(Index func_index) { @@ -1153,7 +1155,7 @@ Result BinaryReaderIR::OnRefFuncExpr(Index func_index) { Result BinaryReaderIR::OnRefNullExpr(Type type) { module_->features_used.exceptions |= (type == Type::ExnRef); - return AppendExpr(std::make_unique(type)); + return AppendExpr(std::make_unique(Var(type, GetLocation()))); } Result BinaryReaderIR::OnRefIsNullExpr() { @@ -1173,9 +1175,9 @@ Result BinaryReaderIR::OnReturnExpr() { } Result BinaryReaderIR::OnSelectExpr(Index result_count, Type* result_types) { - TypeVector results; - results.assign(result_types, result_types + result_count); - return AppendExpr(std::make_unique(results)); + auto expr_ptr = std::make_unique(); + expr_ptr->result_type.assign(result_types, result_types + result_count); + return AppendExpr(std::move(expr_ptr)); } Result BinaryReaderIR::OnGlobalSetExpr(Index global_index) { diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 0c13622576..19dc335cb3 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -842,7 +842,7 @@ DEFINE_LOAD_STORE_OPCODE(OnAtomicNotifyExpr); DEFINE_OPCODE(OnBinaryExpr) DEFINE_INDEX_DESC(OnCallExpr, "func_index") DEFINE_INDEX_INDEX(OnCallIndirectExpr, "sig_index", "table_index") -DEFINE0(OnCallRefExpr) +DEFINE_TYPE(OnCallRefExpr) DEFINE_INDEX_DESC(OnCatchExpr, "tag_index"); DEFINE0(OnCatchAllExpr); DEFINE_OPCODE(OnCompareExpr) diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 34ba068708..e35d1fe5b8 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -901,7 +901,7 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeType(Type type) { if (!in_function_body) { return Result::Ok; } - if (current_opcode == Opcode::SelectT) { + if (current_opcode == Opcode::SelectT || current_opcode == Opcode::CallRef) { LogOpcode(type.GetName().c_str()); } else { LogOpcode(type.GetRefKindName()); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 6828435385..d1f064a3e8 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -145,6 +145,7 @@ class BinaryReader { [[nodiscard]] Result ReadCount(Index* index, const char* desc); [[nodiscard]] Result ReadField(TypeMut* out_value); + bool IsConcreteReferenceType(Type::Enum); bool IsConcreteType(Type); bool IsBlockType(Type); @@ -365,10 +366,25 @@ Result BinaryReader::ReadS64Leb128(uint64_t* out_value, const char* desc) { Result BinaryReader::ReadType(Type* out_value, const char* desc) { uint32_t type = 0; CHECK_RESULT(ReadS32Leb128(&type, desc)); - if (static_cast(type) == Type::Reference) { - uint32_t heap_type = 0; - CHECK_RESULT(ReadS32Leb128(&heap_type, desc)); - *out_value = Type(Type::Reference, heap_type); + if (options_.features.reference_types_enabled() && + Type::EnumIsReferenceWithIndex(static_cast(type))) { + uint64_t heap_type = 0; + CHECK_RESULT(ReadS64Leb128(&heap_type, desc)); + + if (static_cast(heap_type) < 0 || + static_cast(heap_type) >= kInvalidIndex) { + Type::Enum heap_type_code = static_cast(heap_type); + ERROR_UNLESS( + heap_type_code == Type::FuncRef || heap_type_code == Type::ExternRef, + "Reference type is limited to func and extern: %s", desc); + type = (static_cast(type) == Type::Ref) + ? Type::ReferenceNonNull + : Type::ReferenceOrNull; + *out_value = Type(heap_type_code, type); + } else { + *out_value = + Type(static_cast(type), static_cast(heap_type)); + } } else { *out_value = static_cast(type); } @@ -552,6 +568,20 @@ Result BinaryReader::ReadField(TypeMut* out_value) { return Result::Ok; } +bool BinaryReader::IsConcreteReferenceType(Type::Enum type) { + switch (type) { + case Type::FuncRef: + case Type::ExternRef: + return options_.features.reference_types_enabled(); + + case Type::ExnRef: + return options_.features.exceptions_enabled(); + + default: + return false; + } +} + bool BinaryReader::IsConcreteType(Type type) { switch (type) { case Type::I32: @@ -563,18 +593,13 @@ bool BinaryReader::IsConcreteType(Type type) { case Type::V128: return options_.features.simd_enabled(); - case Type::FuncRef: - case Type::ExternRef: - return options_.features.reference_types_enabled(); - - case Type::ExnRef: - return options_.features.exceptions_enabled(); - case Type::Reference: + case Type::Ref: + case Type::RefNull: return options_.features.function_references_enabled(); default: - return false; + return IsConcreteReferenceType(type); } } @@ -1911,8 +1936,23 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { } case Opcode::RefNull: { + uint64_t heap_type; Type type; - CHECK_RESULT(ReadRefType(&type, "ref.null type")); + CHECK_RESULT(ReadS64Leb128(&heap_type, "ref.null type")); + + if (static_cast(heap_type) < 0 || + static_cast(heap_type) >= kInvalidIndex) { + Type::Enum type_code = static_cast(heap_type); + ERROR_UNLESS(IsConcreteReferenceType(type_code), + "expected valid ref.null type (got " PRItypecode ")", + WABT_PRINTF_TYPE_CODE(type_code)); + type = Type(type_code); + } else { + ERROR_UNLESS(options_.features.function_references_enabled(), + "function references are not enabled for ref.null"); + type = Type(Type::RefNull, static_cast(heap_type)); + } + CALLBACK(OnRefNullExpr, type); CALLBACK(OnOpcodeType, type); break; @@ -1923,10 +1963,15 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { CALLBACK(OnOpcodeBare); break; - case Opcode::CallRef: - CALLBACK(OnCallRefExpr); - CALLBACK(OnOpcodeBare); + case Opcode::CallRef: { + uint32_t type; + CHECK_RESULT(ReadU32Leb128(&type, "call_ref type")); + + Type sig_type(Type::RefNull, type); + CALLBACK(OnCallRefExpr, sig_type); + CALLBACK(OnOpcodeType, sig_type); break; + } default: return ReportUnexpectedOpcode(opcode); diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 600154b941..877493b66e 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -57,9 +57,12 @@ void WriteOpcode(Stream* stream, Opcode opcode) { } void WriteType(Stream* stream, Type type, const char* desc) { + if (type.IsNonTypedRef() && !type.IsNullableNonTypedRef()) { + WriteS32Leb128(stream, Type::Ref, "type prefix"); + } WriteS32Leb128(stream, type, desc ? desc : type.GetName().c_str()); if (type.IsReferenceWithIndex()) { - WriteS32Leb128(stream, type.GetReferenceIndex(), + WriteU32Leb128(stream, type.GetReferenceIndex(), desc ? desc : type.GetName().c_str()); } } @@ -797,6 +800,10 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { } case ExprType::CallRef: { WriteOpcode(stream_, Opcode::CallRef); + assert(cast(expr)->sig_type.opt_type() == Type::RefNull); + Index sig_index = cast(expr)->sig_type.index(); + WriteU32Leb128WithReloc(sig_index, "signature index", + RelocType::TypeIndexLEB); break; } case ExprType::ReturnCallIndirect: { @@ -1011,7 +1018,17 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { } case ExprType::RefNull: { WriteOpcode(stream_, Opcode::RefNull); - WriteType(stream_, cast(expr)->type, "ref.null type"); + const RefNullExpr* ref_null_expr = cast(expr); + Type::Enum type = ref_null_expr->type.opt_type(); + + if (type != Type::RefNull) { + WriteType(stream_, type, "ref.null type"); + break; + } + + Index index = module_->GetFuncTypeIndex(ref_null_expr->type); + WriteU32Leb128WithReloc(index, "heap type index", + RelocType::FuncIndexLEB); break; } case ExprType::RefIsNull: diff --git a/src/c-writer.cc b/src/c-writer.cc index da58d1c951..39decb7a8c 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -1517,7 +1517,7 @@ void CWriter::WriteInitExprTerminal(const Expr* expr) { } break; case ExprType::RefNull: - Write(GetReferenceNullValue(cast(expr)->type)); + Write(GetReferenceNullValue(cast(expr)->type.opt_type())); break; default: @@ -2506,16 +2506,17 @@ void CWriter::WriteElemInitializers() { void CWriter::WriteElemTableInit(bool active_initialization, const ElemSegment* src_segment, const Table* dst_table) { - assert(dst_table->elem_type.IsRef() && - dst_table->elem_type != Type::Reference); - assert(dst_table->elem_type == src_segment->elem_type); + Type elem_type = dst_table->elem_type; - Write(GetReferenceTypeName(dst_table->elem_type), "_table_init(", + assert(elem_type.IsRef() && !elem_type.IsReferenceWithIndex()); + assert(elem_type == src_segment->elem_type); + + Write(GetReferenceTypeName(elem_type), "_table_init(", ExternalInstancePtr(ModuleFieldType::Table, dst_table->name), ", "); // elem segment exprs needed only for funcref tables // because externref and exnref tables can only be initialized with ref.null - if (dst_table->elem_type == Type::FuncRef) { + if (elem_type == Type::FuncRef) { if (src_segment->elem_exprs.empty()) { Write("NULL, "); } else { @@ -2540,7 +2541,7 @@ void CWriter::WriteElemTableInit(bool active_initialization, Write(StackVar(2), ", ", StackVar(1), ", ", StackVar(0)); } - if (dst_table->elem_type == Type::FuncRef) { + if (elem_type == Type::FuncRef) { Write(", instance"); } @@ -3973,10 +3974,10 @@ void CWriter::Write(const ExprList& exprs) { } break; case ExprType::RefNull: - PushType(cast(&expr)->type); + PushType(cast(&expr)->type.opt_type()); Write(StackVar(0), " = ", - GetReferenceNullValue(cast(&expr)->type), ";", - Newline()); + GetReferenceNullValue(cast(&expr)->type.opt_type()), + ";", Newline()); break; case ExprType::RefIsNull: diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 9eb54d45da..de5be17ef7 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -187,6 +187,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Index default_target_depth) override; Result OnCallExpr(Index func_index) override; Result OnCallIndirectExpr(Index sig_index, Index table_index) override; + Result OnCallRefExpr(Type sig_type) override; Result OnCatchExpr(Index tag_index) override; Result OnCatchAllExpr() override; Result OnDelegateExpr(Index depth) override; @@ -504,11 +505,11 @@ Result BinaryReaderInterp::OnFuncType(Index index, Type* param_types, Index result_count, Type* result_types) { - CHECK_RESULT(validator_.OnFuncType(GetLocation(), param_count, param_types, - result_count, result_types, index)); + Result result = validator_.OnFuncType(GetLocation(), param_count, param_types, + result_count, result_types, index); module_.func_types.push_back(FuncType(ToInterp(param_count, param_types), ToInterp(result_count, result_types))); - return Result::Ok; + return result; } Result BinaryReaderInterp::OnImportFunc(Index import_index, @@ -1174,6 +1175,14 @@ Result BinaryReaderInterp::OnCallIndirectExpr(Index sig_index, return Result::Ok; } +Result BinaryReaderInterp::OnCallRefExpr(Type sig_type) { + CHECK_RESULT( + validator_.OnCallRef(GetLocation(), Var(sig_type, GetLocation()))); + assert(sig_type == Type::RefNull); + istream_.Emit(Opcode::CallRef); + return Result::Ok; +} + Result BinaryReaderInterp::OnReturnCallExpr(Index func_index) { CHECK_RESULT( validator_.OnReturnCall(GetLocation(), Var(func_index, GetLocation()))); @@ -1404,7 +1413,7 @@ Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) { } Result BinaryReaderInterp::OnRefNullExpr(Type type) { - CHECK_RESULT(validator_.OnRefNull(GetLocation(), type)); + CHECK_RESULT(validator_.OnRefNull(GetLocation(), Var(type, GetLocation()))); istream_.Emit(Opcode::RefNull); return Result::Ok; } diff --git a/src/interp/interp-util.cc b/src/interp/interp-util.cc index fcba2c7f1a..3d21d6d099 100644 --- a/src/interp/interp-util.cc +++ b/src/interp/interp-util.cc @@ -59,6 +59,8 @@ std::string TypedValueToString(const TypedValue& tv) { return StringPrintf("exnref:%" PRIzd, tv.value.Get().index); case Type::Reference: + case Type::Ref: + case Type::RefNull: case Type::Func: case Type::Struct: case Type::Array: diff --git a/src/interp/interp.cc b/src/interp/interp.cc index cc4415fb9f..f49b62970b 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -94,16 +94,91 @@ std::unique_ptr FuncType::Clone() const { return std::make_unique(*this); } +static bool RecursiveMatch(const ValueTypes& expected, + std::vector* expected_func_types, + const ValueTypes& actual, + std::vector* actual_func_types) { + if (expected_func_types == nullptr || actual_func_types == nullptr) { + return false; + } + + size_t size = expected.size(); + if (size != actual.size()) { + return false; + } + + for (size_t i = 0; i < size; i++) { + if (!expected[i].IsReferenceWithIndex()) { + if (expected[i] != actual[i]) { + return false; + } + continue; + } + + if (static_cast(expected[i]) != + static_cast(actual[i])) { + return false; + } + + const FuncType& expected_type = + (*expected_func_types)[expected[i].GetReferenceIndex()]; + const FuncType& actual_type = + (*actual_func_types)[actual[i].GetReferenceIndex()]; + + assert(expected_type.func_types == expected_func_types); + assert(actual_type.func_types == actual_func_types); + + if (!RecursiveMatch(expected_type.params, expected_func_types, + actual_type.params, actual_func_types) || + !RecursiveMatch(expected_type.results, expected_func_types, + actual_type.results, actual_func_types)) { + return false; + } + } + + return true; +} + Result Match(const FuncType& expected, const FuncType& actual, std::string* out_msg) { - if (expected.params != actual.params || expected.results != actual.results) { - if (out_msg) { - *out_msg = "import signature mismatch"; + bool has_reference = false; + + for (auto it : expected.params) { + if (it.IsReferenceWithIndex()) { + has_reference = true; + break; } - return Result::Error; } - return Result::Ok; + + if (!has_reference) { + for (auto it : expected.results) { + if (it.IsReferenceWithIndex()) { + has_reference = true; + break; + } + } + } + + if (!has_reference) { + // Simple function, can be a callback without module. + if (expected.params == actual.params && + expected.results == actual.results) { + return Result::Ok; + } + } else { + if (RecursiveMatch(expected.params, expected.func_types, actual.params, + actual.func_types) && + RecursiveMatch(expected.results, expected.func_types, actual.results, + actual.func_types)) { + return Result::Ok; + } + } + + if (out_msg) { + *out_msg = "import signature mismatch"; + } + return Result::Error; } //// TableType //// @@ -756,10 +831,26 @@ Module::Module(Store&, ModuleDesc desc) : Object(skind), desc_(std::move(desc)) { for (auto&& import : desc_.imports) { import_types_.emplace_back(import.type); + + if (import.type.type->kind == ExternKind::Func) { + cast(import.type.type.get())->func_types = &desc_.func_types; + } } for (auto&& export_ : desc_.exports) { export_types_.emplace_back(export_.type); + + if (export_.type.type->kind == ExternKind::Func) { + cast(export_.type.type.get())->func_types = &desc_.func_types; + } + } + + for (auto& func_type : desc_.func_types) { + func_type.func_types = &desc_.func_types; + } + + for (auto& func : desc_.funcs) { + func.type.func_types = &desc_.func_types; } } @@ -1249,6 +1340,13 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { } } + case O::CallRef: { + Ref new_func_ref = Pop(); + TRAP_IF(new_func_ref == Ref::Null, "null function reference"); + Func::Ptr new_func{store_, new_func_ref}; + return DoCall(new_func, out_trap); + } + case O::Drop: Pop(); break; @@ -2001,7 +2099,6 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { case O::ReturnCall: case O::SelectT: - case O::CallRef: case O::Try: case O::TryTable: case O::Catch: diff --git a/src/ir-util.cc b/src/ir-util.cc index 5266a26457..d0c50588f5 100644 --- a/src/ir-util.cc +++ b/src/ir-util.cc @@ -140,7 +140,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { } case ExprType::CallRef: { - const Var& var = cast(&expr)->function_type_index; + const Var& var = cast(&expr)->sig_type; return {GetFuncParamCount(var) + 1, GetFuncResultCount(var)}; } diff --git a/src/ir.cc b/src/ir.cc index a2f9c48e0c..3135164205 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -107,7 +107,24 @@ const char* GetExprTypeName(const Expr& expr) { } bool FuncSignature::operator==(const FuncSignature& rhs) const { - return param_types == rhs.param_types && result_types == rhs.result_types; + if (param_types.size() != rhs.param_types.size() || + result_types.size() != rhs.result_types.size()) { + return false; + } + + if (param_types.size() > 0 && + memcmp(param_types.data(), rhs.param_types.data(), + param_types.size() * sizeof(Type)) != 0) { + return false; + } + + if (result_types.size() > 0 && + memcmp(result_types.data(), rhs.result_types.data(), + result_types.size() * sizeof(Type)) != 0) { + return false; + } + + return true; } const Export* Module::GetExport(std::string_view name) const { @@ -591,10 +608,24 @@ void MakeTypeBindingReverseMapping( Var::Var() : Var(kInvalidIndex, Location()) {} Var::Var(Index index, const Location& loc) - : loc(loc), type_(VarType::Index), index_(index) {} + : loc(loc), type_(VarType::Index), opt_type_(0), index_(index) {} Var::Var(std::string_view name, const Location& loc) - : loc(loc), type_(VarType::Name), name_(name) {} + : loc(loc), type_(VarType::Name), opt_type_(0), name_(name) {} + +Var::Var(Type type, const Location& loc) + : loc(loc), type_(VarType::Index), index_(0) { + assert(static_cast(type) < 0 && + static_cast(type) >= INT16_MIN); + opt_type_ = static_cast(type); + + if (type.IsReferenceWithIndex()) { + index_ = type.GetReferenceIndex(); + } else if (type.IsNonTypedRef()) { + index_ = type.IsNullableNonTypedRef() ? Type::ReferenceOrNull + : Type::ReferenceNonNull; + } +} Var::Var(Var&& rhs) : Var() { *this = std::move(rhs); @@ -606,6 +637,7 @@ Var::Var(const Var& rhs) : Var() { Var& Var::operator=(Var&& rhs) { loc = rhs.loc; + opt_type_ = rhs.opt_type_; if (rhs.is_index()) { set_index(rhs.index_); } else { @@ -616,6 +648,7 @@ Var& Var::operator=(Var&& rhs) { Var& Var::operator=(const Var& rhs) { loc = rhs.loc; + opt_type_ = rhs.opt_type_; if (rhs.is_index()) { set_index(rhs.index_); } else { @@ -644,6 +677,22 @@ void Var::set_name(std::string_view name) { set_name(std::string(name)); } +void Var::set_opt_type(Type::Enum type) { + assert(static_cast(type) < 0 && + static_cast(type) >= INT16_MIN); + opt_type_ = static_cast(type); +} + +Type Var::to_type() const { + Type::Enum type = static_cast(opt_type_); + + if (Type::EnumIsReferenceWithIndex(type) || Type::EnumIsNonTypedRef(type)) { + return Type(type, index()); + } + + return Type(type); +} + void Var::Destroy() { if (is_name()) { Destruct(name_); diff --git a/src/leb128.cc b/src/leb128.cc index 6c5a650fa9..c4b1dab37c 100644 --- a/src/leb128.cc +++ b/src/leb128.cc @@ -273,10 +273,8 @@ size_t ReadS32Leb128(const uint8_t* p, return 4; } else if (p + 4 < end && (p[4] & 0x80) == 0) { // The top bits should be a sign-extension of the sign bit. - bool sign_bit_set = (p[4] & 0x8); - int top_bits = p[4] & 0xf0; - if ((sign_bit_set && top_bits != 0x70) || - (!sign_bit_set && top_bits != 0)) { + int top_bits = p[4] & 0xf8; + if (top_bits != 0x78 && top_bits != 0) { return 0; } uint32_t result = LEB128_5(uint32_t); @@ -329,10 +327,8 @@ size_t ReadS64Leb128(const uint8_t* p, return 9; } else if (p + 9 < end && (p[9] & 0x80) == 0) { // The top bits should be a sign-extension of the sign bit. - bool sign_bit_set = (p[9] & 0x1); - int top_bits = p[9] & 0xfe; - if ((sign_bit_set && top_bits != 0x7e) || - (!sign_bit_set && top_bits != 0)) { + int top_bits = p[9]; + if (top_bits != 0x7f && top_bits != 0) { return 0; } uint64_t result = LEB128_10(uint64_t); diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt index 5923c7109c..dee1bce521 100644 --- a/src/lexer-keywords.txt +++ b/src/lexer-keywords.txt @@ -183,8 +183,8 @@ f64x2.convert_low_i32x4_u, TokenType::Unary, Opcode::F64X2ConvertLowI32X4U f64x2.promote_low_f32x4, TokenType::Unary, Opcode::F64X2PromoteLowF32X4 f64x2, TokenType::F64X2 field, TokenType::Field -funcref, Type::FuncRef func, Type::FuncRef, TokenType::Func +funcref, Type::FuncRef function, TokenType::Function get, TokenType::Get global.get, TokenType::GlobalGet, Opcode::GlobalGet @@ -556,6 +556,7 @@ mut, TokenType::Mut nan:arithmetic, TokenType::NanArithmetic nan:canonical, TokenType::NanCanonical nop, TokenType::Nop, Opcode::Nop +null, TokenType::Null offset, TokenType::Offset output, TokenType::Output pagesize, TokenType::PageSize diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc index 89f14dbaca..5d02bb0027 100644 --- a/src/prebuilt/lexer-keywords.cc +++ b/src/prebuilt/lexer-keywords.cc @@ -158,7 +158,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 601, + TOTAL_KEYWORDS = 602, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 35, MIN_HASH_VALUE = 37, @@ -188,7 +188,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 122 "src/lexer-keywords.txt" {"f32x4", TokenType::F32X4}, {""}, {""}, {""}, {""}, -#line 586 "src/lexer-keywords.txt" +#line 587 "src/lexer-keywords.txt" {"table", TokenType::Table}, #line 48 "src/lexer-keywords.txt" {"do", TokenType::Do}, @@ -207,7 +207,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 30 "src/lexer-keywords.txt" {"before", TokenType::Before}, {""}, {""}, {""}, {""}, {""}, -#line 187 "src/lexer-keywords.txt" +#line 186 "src/lexer-keywords.txt" {"func", Type::FuncRef, TokenType::Func}, #line 136 "src/lexer-keywords.txt" {"f64.gt", TokenType::Compare, Opcode::F64Gt}, @@ -221,7 +221,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 43 "src/lexer-keywords.txt" {"code", TokenType::Code}, {""}, {""}, {""}, -#line 570 "src/lexer-keywords.txt" +#line 571 "src/lexer-keywords.txt" {"result", TokenType::Result}, {""}, #line 100 "src/lexer-keywords.txt" @@ -230,7 +230,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 102 "src/lexer-keywords.txt" {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, {""}, -#line 578 "src/lexer-keywords.txt" +#line 579 "src/lexer-keywords.txt" {"struct", Type::Struct, TokenType::Struct}, {""}, {""}, {""}, {""}, {""}, #line 555 "src/lexer-keywords.txt" @@ -240,11 +240,11 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 298 "src/lexer-keywords.txt" {"i32.or", TokenType::Binary, Opcode::I32Or}, {""}, {""}, -#line 581 "src/lexer-keywords.txt" +#line 582 "src/lexer-keywords.txt" {"table.get", TokenType::TableGet, Opcode::TableGet}, #line 101 "src/lexer-keywords.txt" {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, -#line 584 "src/lexer-keywords.txt" +#line 585 "src/lexer-keywords.txt" {"table.set", TokenType::TableSet, Opcode::TableSet}, #line 103 "src/lexer-keywords.txt" {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, @@ -310,7 +310,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 310 "src/lexer-keywords.txt" {"i32.store", TokenType::Store, Opcode::I32Store}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 568 "src/lexer-keywords.txt" +#line 569 "src/lexer-keywords.txt" {"ref.null", TokenType::RefNull, Opcode::RefNull}, #line 108 "src/lexer-keywords.txt" {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, @@ -337,9 +337,11 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, #line 120 "src/lexer-keywords.txt" {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, -#line 574 "src/lexer-keywords.txt" +#line 575 "src/lexer-keywords.txt" {"return", TokenType::Return, Opcode::Return}, - {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 559 "src/lexer-keywords.txt" + {"null", TokenType::Null}, #line 453 "src/lexer-keywords.txt" {"i64.store8", TokenType::Store, Opcode::I64Store8}, #line 309 "src/lexer-keywords.txt" @@ -376,7 +378,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 275 "src/lexer-keywords.txt" {"i32.const", TokenType::Const, Opcode::I32Const}, {""}, -#line 575 "src/lexer-keywords.txt" +#line 576 "src/lexer-keywords.txt" {"select", TokenType::Select, Opcode::Select}, {""}, #line 348 "src/lexer-keywords.txt" @@ -475,7 +477,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 585 "src/lexer-keywords.txt" +#line 586 "src/lexer-keywords.txt" {"table.size", TokenType::TableSize, Opcode::TableSize}, {""}, {""}, {""}, #line 104 "src/lexer-keywords.txt" @@ -487,7 +489,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 273 "src/lexer-keywords.txt" {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 563 "src/lexer-keywords.txt" +#line 564 "src/lexer-keywords.txt" {"ref", TokenType::Ref}, {""}, {""}, #line 404 "src/lexer-keywords.txt" @@ -495,7 +497,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 267 "src/lexer-keywords.txt" {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, {""}, {""}, {""}, {""}, {""}, -#line 573 "src/lexer-keywords.txt" +#line 574 "src/lexer-keywords.txt" {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, {""}, {""}, #line 53 "src/lexer-keywords.txt" @@ -506,7 +508,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, #line 98 "src/lexer-keywords.txt" {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, -#line 565 "src/lexer-keywords.txt" +#line 566 "src/lexer-keywords.txt" {"ref.extern", TokenType::RefExtern}, #line 338 "src/lexer-keywords.txt" {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, @@ -573,9 +575,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 270 "src/lexer-keywords.txt" {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 587 "src/lexer-keywords.txt" +#line 588 "src/lexer-keywords.txt" {"then", TokenType::Then}, -#line 583 "src/lexer-keywords.txt" +#line 584 "src/lexer-keywords.txt" {"table.init", TokenType::TableInit, Opcode::TableInit}, {""}, {""}, #line 344 "src/lexer-keywords.txt" @@ -613,7 +615,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 353 "src/lexer-keywords.txt" {"i32x4.shl", TokenType::Binary, Opcode::I32X4Shl}, {""}, {""}, -#line 569 "src/lexer-keywords.txt" +#line 570 "src/lexer-keywords.txt" {"register", TokenType::Register}, #line 379 "src/lexer-keywords.txt" {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, @@ -663,7 +665,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 282 "src/lexer-keywords.txt" {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, {""}, {""}, -#line 566 "src/lexer-keywords.txt" +#line 567 "src/lexer-keywords.txt" {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, #line 134 "src/lexer-keywords.txt" {"f64.floor", TokenType::Unary, Opcode::F64Floor}, @@ -759,9 +761,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {"i64.trunc_f64_s", TokenType::Convert, Opcode::I64TruncF64S}, #line 314 "src/lexer-keywords.txt" {"i32.trunc_f64_s", TokenType::Convert, Opcode::I32TruncF64S}, -#line 567 "src/lexer-keywords.txt" +#line 568 "src/lexer-keywords.txt" {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, -#line 605 "src/lexer-keywords.txt" +#line 606 "src/lexer-keywords.txt" {"v128", Type::V128}, {""}, {""}, #line 469 "src/lexer-keywords.txt" @@ -789,7 +791,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 485 "src/lexer-keywords.txt" {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, {""}, -#line 564 "src/lexer-keywords.txt" +#line 565 "src/lexer-keywords.txt" {"quote", TokenType::Quote}, #line 32 "src/lexer-keywords.txt" {"block", TokenType::Block, Opcode::Block}, @@ -818,21 +820,21 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, #line 345 "src/lexer-keywords.txt" {"i32x4.min_s", TokenType::Binary, Opcode::I32X4MinS}, -#line 600 "src/lexer-keywords.txt" +#line 601 "src/lexer-keywords.txt" {"v128.or", TokenType::Binary, Opcode::V128Or}, {""}, -#line 560 "src/lexer-keywords.txt" +#line 561 "src/lexer-keywords.txt" {"output", TokenType::Output}, {""}, {""}, -#line 559 "src/lexer-keywords.txt" +#line 560 "src/lexer-keywords.txt" {"offset", TokenType::Offset}, {""}, -#line 592 "src/lexer-keywords.txt" +#line 593 "src/lexer-keywords.txt" {"type", TokenType::Type}, -#line 590 "src/lexer-keywords.txt" +#line 591 "src/lexer-keywords.txt" {"try", TokenType::Try, Opcode::Try}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 580 "src/lexer-keywords.txt" +#line 581 "src/lexer-keywords.txt" {"table.fill", TokenType::TableFill, Opcode::TableFill}, {""}, #line 484 "src/lexer-keywords.txt" @@ -876,12 +878,12 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, #line 117 "src/lexer-keywords.txt" {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, -#line 604 "src/lexer-keywords.txt" +#line 605 "src/lexer-keywords.txt" {"v128.store", TokenType::Store, Opcode::V128Store}, #line 537 "src/lexer-keywords.txt" {"input", TokenType::Input}, {""}, {""}, -#line 572 "src/lexer-keywords.txt" +#line 573 "src/lexer-keywords.txt" {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, {""}, #line 356 "src/lexer-keywords.txt" @@ -912,7 +914,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 513 "src/lexer-keywords.txt" {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, {""}, {""}, {""}, {""}, {""}, -#line 598 "src/lexer-keywords.txt" +#line 599 "src/lexer-keywords.txt" {"v128.load", TokenType::Load, Opcode::V128Load}, #line 158 "src/lexer-keywords.txt" {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, @@ -938,7 +940,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, #line 210 "src/lexer-keywords.txt" {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, -#line 611 "src/lexer-keywords.txt" +#line 612 "src/lexer-keywords.txt" {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, #line 406 "src/lexer-keywords.txt" {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, @@ -948,12 +950,12 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 184 "src/lexer-keywords.txt" {"f64x2", TokenType::F64X2}, {""}, {""}, -#line 610 "src/lexer-keywords.txt" +#line 611 "src/lexer-keywords.txt" {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, {""}, -#line 599 "src/lexer-keywords.txt" +#line 600 "src/lexer-keywords.txt" {"v128.not", TokenType::Unary, Opcode::V128Not}, -#line 618 "src/lexer-keywords.txt" +#line 619 "src/lexer-keywords.txt" {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, #line 495 "src/lexer-keywords.txt" {"i64x2", TokenType::I64X2}, @@ -973,15 +975,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 308 "src/lexer-keywords.txt" {"i32.store16", TokenType::Store, Opcode::I32Store16}, {""}, -#line 186 "src/lexer-keywords.txt" +#line 187 "src/lexer-keywords.txt" {"funcref", Type::FuncRef}, #line 196 "src/lexer-keywords.txt" {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, {""}, {""}, {""}, -#line 597 "src/lexer-keywords.txt" +#line 598 "src/lexer-keywords.txt" {"v128.const", TokenType::Const, Opcode::V128Const}, {""}, -#line 606 "src/lexer-keywords.txt" +#line 607 "src/lexer-keywords.txt" {"v128.xor", TokenType::Binary, Opcode::V128Xor}, {""}, {""}, {""}, {""}, {""}, #line 174 "src/lexer-keywords.txt" @@ -1007,7 +1009,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 500 "src/lexer-keywords.txt" {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, {""}, -#line 595 "src/lexer-keywords.txt" +#line 596 "src/lexer-keywords.txt" {"v128.and", TokenType::Binary, Opcode::V128And}, {""}, {""}, {""}, {""}, #line 534 "src/lexer-keywords.txt" @@ -1019,7 +1021,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 57 "src/lexer-keywords.txt" {"externref", Type::ExternRef}, {""}, {""}, -#line 594 "src/lexer-keywords.txt" +#line 595 "src/lexer-keywords.txt" {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, {""}, {""}, #line 384 "src/lexer-keywords.txt" @@ -1095,7 +1097,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 501 "src/lexer-keywords.txt" {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, {""}, {""}, {""}, {""}, -#line 577 "src/lexer-keywords.txt" +#line 578 "src/lexer-keywords.txt" {"start", TokenType::Start}, {""}, #line 123 "src/lexer-keywords.txt" @@ -1108,7 +1110,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, #line 531 "src/lexer-keywords.txt" {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, -#line 616 "src/lexer-keywords.txt" +#line 617 "src/lexer-keywords.txt" {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, {""}, {""}, {""}, {""}, {""}, {""}, #line 119 "src/lexer-keywords.txt" @@ -1117,15 +1119,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 91 "src/lexer-keywords.txt" {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, {""}, -#line 608 "src/lexer-keywords.txt" +#line 609 "src/lexer-keywords.txt" {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, -#line 562 "src/lexer-keywords.txt" +#line 563 "src/lexer-keywords.txt" {"param", TokenType::Param}, #line 357 "src/lexer-keywords.txt" {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, #line 96 "src/lexer-keywords.txt" {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, -#line 602 "src/lexer-keywords.txt" +#line 603 "src/lexer-keywords.txt" {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, #line 322 "src/lexer-keywords.txt" {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, @@ -1156,7 +1158,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 318 "src/lexer-keywords.txt" {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, {""}, {""}, -#line 613 "src/lexer-keywords.txt" +#line 614 "src/lexer-keywords.txt" {"v128.load32_lane", TokenType::SimdLoadLane, Opcode::V128Load32Lane}, {""}, {""}, {""}, {""}, {""}, {""}, #line 499 "src/lexer-keywords.txt" @@ -1164,7 +1166,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 377 "src/lexer-keywords.txt" {"i64.atomic.load32_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad32U}, {""}, -#line 615 "src/lexer-keywords.txt" +#line 616 "src/lexer-keywords.txt" {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, #line 498 "src/lexer-keywords.txt" {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, @@ -1196,7 +1198,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 41 "src/lexer-keywords.txt" {"catch_ref", TokenType::CatchRef}, {""}, {""}, {""}, -#line 579 "src/lexer-keywords.txt" +#line 580 "src/lexer-keywords.txt" {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, {""}, #line 227 "src/lexer-keywords.txt" @@ -1208,7 +1210,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 515 "src/lexer-keywords.txt" {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, {""}, {""}, -#line 576 "src/lexer-keywords.txt" +#line 577 "src/lexer-keywords.txt" {"shared", TokenType::Shared}, #line 130 "src/lexer-keywords.txt" {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, @@ -1227,7 +1229,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, #line 553 "src/lexer-keywords.txt" {"memory", TokenType::Memory}, -#line 593 "src/lexer-keywords.txt" +#line 594 "src/lexer-keywords.txt" {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, {""}, #line 177 "src/lexer-keywords.txt" @@ -1256,15 +1258,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {"exnref", Type::ExnRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 609 "src/lexer-keywords.txt" +#line 610 "src/lexer-keywords.txt" {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, -#line 617 "src/lexer-keywords.txt" +#line 618 "src/lexer-keywords.txt" {"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane}, #line 178 "src/lexer-keywords.txt" {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, -#line 588 "src/lexer-keywords.txt" +#line 589 "src/lexer-keywords.txt" {"throw", TokenType::Throw, Opcode::Throw}, -#line 603 "src/lexer-keywords.txt" +#line 604 "src/lexer-keywords.txt" {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, {""}, {""}, {""}, {""}, #line 37 "src/lexer-keywords.txt" @@ -1286,7 +1288,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 280 "src/lexer-keywords.txt" {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, {""}, {""}, -#line 589 "src/lexer-keywords.txt" +#line 590 "src/lexer-keywords.txt" {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, {""}, #line 203 "src/lexer-keywords.txt" @@ -1295,7 +1297,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 202 "src/lexer-keywords.txt" {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, {""}, {""}, -#line 614 "src/lexer-keywords.txt" +#line 615 "src/lexer-keywords.txt" {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, #line 396 "src/lexer-keywords.txt" {"i64.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw8CmpxchgU}, @@ -1307,10 +1309,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 271 "src/lexer-keywords.txt" {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, {""}, {""}, -#line 591 "src/lexer-keywords.txt" +#line 592 "src/lexer-keywords.txt" {"try_table", TokenType::TryTable, Opcode::TryTable}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 601 "src/lexer-keywords.txt" +#line 602 "src/lexer-keywords.txt" {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, {""}, #line 506 "src/lexer-keywords.txt" @@ -1326,10 +1328,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 49 "src/lexer-keywords.txt" {"drop", TokenType::Drop, Opcode::Drop}, {""}, {""}, {""}, -#line 582 "src/lexer-keywords.txt" +#line 583 "src/lexer-keywords.txt" {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, {""}, {""}, -#line 571 "src/lexer-keywords.txt" +#line 572 "src/lexer-keywords.txt" {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1458,7 +1460,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 522 "src/lexer-keywords.txt" {"i8x16.popcnt", TokenType::Unary, Opcode::I8X16Popcnt}, {""}, {""}, -#line 607 "src/lexer-keywords.txt" +#line 608 "src/lexer-keywords.txt" {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, {""}, {""}, {""}, {""}, {""}, #line 128 "src/lexer-keywords.txt" @@ -1481,10 +1483,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 170 "src/lexer-keywords.txt" {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, {""}, {""}, {""}, {""}, -#line 612 "src/lexer-keywords.txt" +#line 613 "src/lexer-keywords.txt" {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, {""}, -#line 619 "src/lexer-keywords.txt" +#line 620 "src/lexer-keywords.txt" {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, {""}, {""}, #line 359 "src/lexer-keywords.txt" @@ -1525,7 +1527,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 321 "src/lexer-keywords.txt" {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, {""}, {""}, {""}, {""}, -#line 620 "src/lexer-keywords.txt" +#line 621 "src/lexer-keywords.txt" {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1540,7 +1542,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 193 "src/lexer-keywords.txt" {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, {""}, -#line 561 "src/lexer-keywords.txt" +#line 562 "src/lexer-keywords.txt" {"pagesize", TokenType::PageSize}, {""}, {""}, #line 95 "src/lexer-keywords.txt" @@ -1629,7 +1631,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 27 "src/lexer-keywords.txt" {"assert_trap", TokenType::AssertTrap}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 596 "src/lexer-keywords.txt" +#line 597 "src/lexer-keywords.txt" {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, {""}, {""}, {""}, {""}, {""}, {""}, #line 150 "src/lexer-keywords.txt" diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 67fc44e923..0ee5e80526 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -43,6 +43,7 @@ class NameResolver : public ExprVisitor::DelegateNop { Result OnBrTableExpr(BrTableExpr*) override; Result OnCallExpr(CallExpr*) override; Result OnCallIndirectExpr(CallIndirectExpr*) override; + Result OnCallRefExpr(CallRefExpr*) override; Result OnCatchExpr(TryExpr*, Catch*) override; Result OnDelegateExpr(TryExpr*) override; Result OnReturnCallExpr(ReturnCallExpr*) override; @@ -72,6 +73,7 @@ class NameResolver : public ExprVisitor::DelegateNop { Result OnTableSizeExpr(TableSizeExpr*) override; Result OnTableFillExpr(TableFillExpr*) override; Result OnRefFuncExpr(RefFuncExpr*) override; + Result OnRefNullExpr(RefNullExpr*) override; Result OnStoreExpr(StoreExpr*) override; Result BeginTryExpr(TryExpr*) override; Result EndTryExpr(TryExpr*) override; @@ -295,6 +297,11 @@ Result NameResolver::OnCallIndirectExpr(CallIndirectExpr* expr) { return Result::Ok; } +Result NameResolver::OnCallRefExpr(CallRefExpr* expr) { + ResolveFuncTypeVar(&expr->sig_type); + return Result::Ok; +} + Result NameResolver::OnReturnCallExpr(ReturnCallExpr* expr) { ResolveFuncVar(&expr->var); return Result::Ok; @@ -428,6 +435,11 @@ Result NameResolver::OnRefFuncExpr(RefFuncExpr* expr) { return Result::Ok; } +Result NameResolver::OnRefNullExpr(RefNullExpr* expr) { + ResolveFuncTypeVar(&expr->type); + return Result::Ok; +} + Result NameResolver::OnStoreExpr(StoreExpr* expr) { ResolveMemoryVar(&expr->memidx); return Result::Ok; diff --git a/src/shared-validator.cc b/src/shared-validator.cc index ad3a85393b..7e7740601e 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -27,7 +27,9 @@ TypeVector SharedValidator::ToTypeVector(Index count, const Type* types) { } SharedValidator::SharedValidator(Errors* errors, const ValidateOptions& options) - : options_(options), errors_(errors), typechecker_(options.features) { + : options_(options), + errors_(errors), + typechecker_(options.features, func_types_) { typechecker_.set_error_callback( [this](const char* msg) { OnTypecheckerError(msg); }); } @@ -56,6 +58,14 @@ Result SharedValidator::OnFuncType(const Location& loc, "multiple result values are not supported without " "multi-value enabled."); } + if (options_.features.reference_types_enabled()) { + for (Index i = 0; i < param_count; i++) { + result |= CheckReferenceType(loc, param_types[i], "params"); + } + for (Index i = 0; i < result_count; i++) { + result |= CheckReferenceType(loc, result_types[i], "results"); + } + } func_types_.emplace( num_types_++, FuncType{ToTypeVector(param_count, param_types), @@ -76,21 +86,6 @@ Result SharedValidator::OnArrayType(const Location&, TypeMut field) { return Result::Ok; } -Result SharedValidator::EndTypeSection() { - Result result = Result::Ok; - - for (auto func_type : func_types_) { - for (auto type : func_type.second.params) { - result |= CheckReferenceType(Location(), type, "params"); - } - - for (auto type : func_type.second.results) { - result |= CheckReferenceType(Location(), type, "results"); - } - } - return result; -} - Result SharedValidator::OnFunction(const Location& loc, Var sig_var) { Result result = Result::Ok; FuncType type; @@ -129,6 +124,8 @@ Result SharedValidator::OnTable(const Location& loc, Type elem_type, const Limits& limits) { Result result = Result::Ok; + // Must be checked by parser or binary reader. + assert(elem_type.IsRef()); if (tables_.size() > 0 && !options_.features.reference_types_enabled()) { result |= PrintError(loc, "only one table allowed"); } @@ -141,8 +138,13 @@ Result SharedValidator::OnTable(const Location& loc, !options_.features.reference_types_enabled()) { result |= PrintError(loc, "tables must have funcref type"); } - if (!elem_type.IsRef()) { - result |= PrintError(loc, "tables must have reference types"); + + result |= CheckReferenceType(loc, elem_type, "tables"); + + // TODO: support table initializers + if (elem_type.IsRef() && !elem_type.IsNullableRef()) { + result |= + PrintError(loc, "currently non-nullable references are not supported"); } tables_.push_back(TableType{elem_type, limits}); @@ -196,6 +198,7 @@ Result SharedValidator::OnGlobalImport(const Location& loc, Result SharedValidator::OnGlobal(const Location& loc, Type type, bool mutable_) { + CHECK_RESULT(CheckReferenceType(loc, type, "globals")); globals_.push_back(GlobalType{type, mutable_}); return Result::Ok; } @@ -204,7 +207,7 @@ Result SharedValidator::CheckType(const Location& loc, Type actual, Type expected, const char* desc) { - if (Failed(TypeChecker::CheckType(actual, expected))) { + if (Failed(typechecker_.CheckType(actual, expected))) { PrintError(loc, "type mismatch at %s. got %s, expected %s", desc, actual.GetName().c_str(), expected.GetName().c_str()); return Result::Error; @@ -315,6 +318,17 @@ Result SharedValidator::OnElemSegmentElemType(const Location& loc, // it is active. result |= CheckType(loc, elem_type, elem.table_type, "elem segment"); } + + if (elem_type.IsReferenceWithIndex()) { + Index index = elem_type.GetReferenceIndex(); + auto iter = func_types_.find(index); + + if (iter == func_types_.end()) { + result |= + PrintError(loc, "reference %" PRIindex " is out of range", index); + } + } + elem.element = elem_type; return result; } @@ -458,6 +472,16 @@ Result SharedValidator::CheckBlockSignature(const Location& loc, *out_param_types = func_type.params; *out_result_types = func_type.results; } else { + if (sig_type.IsReferenceWithIndex()) { + Index index = sig_type.GetReferenceIndex(); + auto iter = func_types_.find(index); + + if (iter == func_types_.end()) { + result |= + PrintError(loc, "reference %" PRIindex " is out of range", index); + } + } + out_param_types->clear(); *out_result_types = sig_type.GetInlineVector(); } @@ -470,6 +494,33 @@ Index SharedValidator::GetFunctionTypeIndex(Index func_index) const { return funcs_[func_index].type_index; } +void SharedValidator::SaveLocalRefs() { + if (!local_ref_is_set_.empty()) { + Label* label; + typechecker_.GetLabel(0, &label); + label->local_ref_is_set_ = local_ref_is_set_; + } +} + +void SharedValidator::RestoreLocalRefs(Result result) { + if (!local_ref_is_set_.empty()) { + if (Succeeded(result)) { + Label* label; + typechecker_.GetLabel(0, &label); + assert(local_ref_is_set_.size() == label->local_ref_is_set_.size()); + local_ref_is_set_ = label->local_ref_is_set_; + } else { + IgnoreLocalRefs(); + } + } +} + +void SharedValidator::IgnoreLocalRefs() { + if (!local_ref_is_set_.empty()) { + std::fill(local_ref_is_set_.begin(), local_ref_is_set_.end(), true); + } +} + Result SharedValidator::BeginInitExpr(const Location& loc, Type type) { expr_loc_ = loc; in_init_expr_ = true; @@ -513,7 +564,17 @@ Result SharedValidator::OnLocalDecl(const Location& loc, CHECK_RESULT(CheckReferenceType(loc, type, "locals")); - locals_.push_back(LocalDecl{type, GetLocalCount() + count}); + Index local_count = GetLocalCount(); + + if (type.IsNonNullableRef()) { + for (Index i = 0; i < count; i++) { + local_refs_map_[local_count + i] = + LocalReferenceMap{type, static_cast(local_ref_is_set_.size())}; + local_ref_is_set_.push_back(false); + } + } + + locals_.push_back(LocalDecl{type, local_count + count}); return Result::Ok; } @@ -708,12 +769,14 @@ Result SharedValidator::OnBlock(const Location& loc, Type sig_type) { result |= CheckBlockSignature(loc, Opcode::Block, sig_type, ¶m_types, &result_types); result |= typechecker_.OnBlock(param_types, result_types); + SaveLocalRefs(); return result; } Result SharedValidator::OnBr(const Location& loc, Var depth) { Result result = CheckInstr(Opcode::Br, loc); result |= typechecker_.OnBr(depth.index()); + IgnoreLocalRefs(); return result; } @@ -739,6 +802,7 @@ Result SharedValidator::OnBrTableTarget(const Location& loc, Var depth) { Result SharedValidator::EndBrTable(const Location& loc) { Result result = CheckInstr(Opcode::BrTable, loc); result |= typechecker_.EndBrTable(); + IgnoreLocalRefs(); return result; } @@ -768,20 +832,12 @@ Result SharedValidator::OnCallIndirect(const Location& loc, return result; } -Result SharedValidator::OnCallRef(const Location& loc, - Index* function_type_index) { +Result SharedValidator::OnCallRef(const Location& loc, Var function_type_var) { Result result = CheckInstr(Opcode::CallRef, loc); - Index func_index; - result |= typechecker_.OnIndexedFuncRef(&func_index); - if (Failed(result)) { - return result; - } FuncType func_type; - result |= CheckFuncTypeIndex(Var(func_index, loc), &func_type); + result |= typechecker_.OnCallRef(function_type_var.to_type()); + result |= CheckFuncTypeIndex(function_type_var, &func_type); result |= typechecker_.OnCall(func_type.params, func_type.results); - if (Succeeded(result)) { - *function_type_index = func_index; - } return result; } @@ -797,6 +853,7 @@ Result SharedValidator::OnCatch(const Location& loc, result |= CheckTagIndex(tag_var, &tag_type); result |= typechecker_.OnCatch(tag_type.params); } + RestoreLocalRefs(result); return result; } @@ -851,11 +908,13 @@ Result SharedValidator::OnElse(const Location& loc) { // not the else itself. Result result = Result::Ok; result |= typechecker_.OnElse(); + RestoreLocalRefs(result); return result; } Result SharedValidator::OnEnd(const Location& loc) { Result result = CheckInstr(Opcode::End, loc); + RestoreLocalRefs(result); result |= typechecker_.OnEnd(); return result; } @@ -899,6 +958,7 @@ Result SharedValidator::OnIf(const Location& loc, Type sig_type) { result |= CheckBlockSignature(loc, Opcode::If, sig_type, ¶m_types, &result_types); result |= typechecker_.OnIf(param_types, result_types); + SaveLocalRefs(); return result; } @@ -950,6 +1010,13 @@ Result SharedValidator::OnLocalGet(const Location& loc, Var local_var) { Type type = Type::Any; result |= CheckLocalIndex(local_var, &type); result |= typechecker_.OnLocalGet(type); + if (Succeeded(result) && type.IsNonNullableRef()) { + auto it = local_refs_map_.find(local_var.index()); + if (it != local_refs_map_.end() && + !local_ref_is_set_[it->second.bit_index]) { + return PrintError(local_var.loc, "uninitialized local reference"); + } + } return result; } @@ -959,6 +1026,12 @@ Result SharedValidator::OnLocalSet(const Location& loc, Var local_var) { Type type = Type::Any; result |= CheckLocalIndex(local_var, &type); result |= typechecker_.OnLocalSet(type); + if (Succeeded(result) && type.IsNonNullableRef()) { + auto it = local_refs_map_.find(local_var.index()); + if (it != local_refs_map_.end()) { + local_ref_is_set_[it->second.bit_index] = true; + } + } return result; } @@ -968,6 +1041,12 @@ Result SharedValidator::OnLocalTee(const Location& loc, Var local_var) { Type type = Type::Any; result |= CheckLocalIndex(local_var, &type); result |= typechecker_.OnLocalTee(type); + if (Succeeded(result) && type.IsNonNullableRef()) { + auto it = local_refs_map_.find(local_var.index()); + if (it != local_refs_map_.end()) { + local_ref_is_set_[it->second.bit_index] = true; + } + } return result; } @@ -977,6 +1056,7 @@ Result SharedValidator::OnLoop(const Location& loc, Type sig_type) { result |= CheckBlockSignature(loc, Opcode::Loop, sig_type, ¶m_types, &result_types); result |= typechecker_.OnLoop(param_types, result_types); + SaveLocalRefs(); return result; } @@ -1044,7 +1124,7 @@ Result SharedValidator::OnRefFunc(const Location& loc, Var func_var) { check_declared_funcs_.push_back(func_var); } Index func_type = GetFunctionTypeIndex(func_var.index()); - result |= typechecker_.OnRefFuncExpr(func_type, in_init_expr_); + result |= typechecker_.OnRefFuncExpr(func_type); } return result; } @@ -1055,8 +1135,25 @@ Result SharedValidator::OnRefIsNull(const Location& loc) { return result; } -Result SharedValidator::OnRefNull(const Location& loc, Type type) { +Result SharedValidator::OnRefNull(const Location& loc, Var func_type_var) { Result result = CheckInstr(Opcode::RefNull, loc); + + Type type = func_type_var.to_type(); + + switch (type) { + case Type::RefNull: + result |= CheckIndex(func_type_var, num_types_, "function type"); + break; + case Type::FuncRef: + case Type::ExnRef: + case Type::ExternRef: + break; + default: + result |= PrintError( + loc, "Only ref, externref, exnref, funcref are allowed for ref.null"); + break; + } + result |= typechecker_.OnRefNullExpr(type); return result; } @@ -1072,6 +1169,7 @@ Result SharedValidator::OnReturnCall(const Location& loc, Var func_var) { FuncType func_type; result |= CheckFuncIndex(func_var, &func_type); result |= typechecker_.OnReturnCall(func_type.params, func_type.results); + IgnoreLocalRefs(); return result; } @@ -1090,12 +1188,14 @@ Result SharedValidator::OnReturnCallIndirect(const Location& loc, } result |= typechecker_.OnReturnCallIndirect(func_type.params, func_type.results); + IgnoreLocalRefs(); return result; } Result SharedValidator::OnReturn(const Location& loc) { Result result = CheckInstr(Opcode::Return, loc); result |= typechecker_.OnReturn(); + IgnoreLocalRefs(); return result; } @@ -1103,6 +1203,19 @@ Result SharedValidator::OnSelect(const Location& loc, Index result_count, Type* result_types) { Result result = CheckInstr(Opcode::Select, loc); + + for (Index i = 0; i < result_count; i++) { + if (result_types[i].IsReferenceWithIndex()) { + Index index = result_types[i].GetReferenceIndex(); + auto iter = func_types_.find(index); + + if (iter == func_types_.end()) { + result |= + PrintError(loc, "reference %" PRIindex " is out of range", index); + } + } + } + if (result_count > 1) { result |= PrintError(loc, "invalid arity in select instruction: %" PRIindex ".", @@ -1265,6 +1378,7 @@ Result SharedValidator::OnTry(const Location& loc, Type sig_type) { result |= CheckBlockSignature(loc, Opcode::Try, sig_type, ¶m_types, &result_types); result |= typechecker_.OnTry(param_types, result_types); + SaveLocalRefs(); return result; } @@ -1311,6 +1425,7 @@ Result SharedValidator::OnUnary(const Location& loc, Opcode opcode) { Result SharedValidator::OnUnreachable(const Location& loc) { Result result = CheckInstr(Opcode::Unreachable, loc); result |= typechecker_.OnUnreachable(); + IgnoreLocalRefs(); return result; } diff --git a/src/type-checker.cc b/src/type-checker.cc index 90dda71e42..42c0c2951f 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -33,7 +33,7 @@ std::string TypesToString(const TypeVector& types, Type ty = types[i]; // NOTE: Reference (and GetName) is also used by (e.g.) objdump, which does // not apply validation. do this here so as to not break that. - if (ty == Type::Reference && ty.GetReferenceIndex() == kInvalidIndex) { + if (ty.IsReferenceWithIndex() && ty.GetReferenceIndex() == kInvalidIndex) { result += "reference"; } else { result += types[i].GetName(); @@ -228,15 +228,100 @@ Result TypeChecker::CheckTypeStackEnd(const char* desc) { return result; } +static bool CompareTypeVector( + const std::map& func_types, + const TypeVector& left, + const TypeVector& right) { + size_t size = left.size(); + + if (size != right.size()) { + return false; + } + + for (size_t i = 0; i < size; i++) { + const Type& left_type = left[i]; + const Type& right_type = right[i]; + + if (left_type != right_type) { + if (!left_type.IsReferenceWithIndex() || + left_type != static_cast(right_type)) { + return false; + } + + const TypeChecker::FuncType& left_func_type = + func_types.at(left_type.GetReferenceIndex()); + const TypeChecker::FuncType& right_func_type = + func_types.at(right_type.GetReferenceIndex()); + + // Circular references were checked during validation. + if (!CompareTypeVector(func_types, left_func_type.params, + right_func_type.params) || + !CompareTypeVector(func_types, left_func_type.results, + right_func_type.results)) { + return false; + } + } + } + + return true; +} + Result TypeChecker::CheckType(Type actual, Type expected) { if (expected == Type::Any || actual == Type::Any) { return Result::Ok; } - if (actual != expected) { + Type::Enum actual_type = actual; + Type::Enum expected_type = expected; + + if (actual_type == expected_type) { + switch (actual_type) { + case Type::ExternRef: + case Type::FuncRef: + return (expected.IsNullableNonTypedRef() || + !actual.IsNullableNonTypedRef()) + ? Result::Ok + : Result::Error; + + case Type::Reference: + case Type::Ref: + case Type::RefNull: + break; + + default: + return Result::Ok; + } + } + + if (!actual.IsReferenceWithIndex()) { return Result::Error; } - return Result::Ok; + + if (expected_type == Type::FuncRef) { + return (actual == Type::Ref || expected.IsNullableNonTypedRef()) + ? Result::Ok + : Result::Error; + } + + if (!expected.IsReferenceWithIndex()) { + return Result::Error; + } + + if (expected_type == Type::Ref && actual_type == Type::RefNull) { + return Result::Error; + } + + FuncType& actual_func_type = func_types_[actual.GetReferenceIndex()]; + FuncType& expected_func_type = func_types_[expected.GetReferenceIndex()]; + + if (CompareTypeVector(func_types_, actual_func_type.params, + expected_func_type.params) && + CompareTypeVector(func_types_, actual_func_type.results, + expected_func_type.results)) { + return Result::Ok; + } + + return Result::Error; } Result TypeChecker::CheckTypes(const TypeVector& actual, @@ -515,17 +600,8 @@ Result TypeChecker::OnCallIndirect(const TypeVector& param_types, return result; } -Result TypeChecker::OnIndexedFuncRef(Index* out_index) { - Type type; - Result result = PeekType(0, &type); - if (!type.IsReferenceWithIndex()) { - type = Type(Type::Reference, kInvalidIndex); - } - result |= PopAndCheck1Type(type, "call_ref"); - if (Succeeded(result)) { - *out_index = type.GetReferenceIndex(); - } - return result; +Result TypeChecker::OnCallRef(Type type) { + return PopAndCheck1Type(type, "call_ref"); } Result TypeChecker::OnReturnCall(const TypeVector& param_types, @@ -785,18 +861,8 @@ Result TypeChecker::OnTableFill(Type elem_type, const Limits& limits) { "table.fill"); } -Result TypeChecker::OnRefFuncExpr(Index func_type, bool force_generic_funcref) { - /* - * In a const expression, treat ref.func as producing a generic funcref. - * This avoids having to implement funcref subtyping (for now) and matches - * the previous behavior where SharedValidator::OnElemSegmentElemExpr_RefFunc - * examined only the validity of the function index. - */ - if (features_.function_references_enabled() && !force_generic_funcref) { - PushType(Type(Type::Reference, func_type)); - } else { - PushType(Type::FuncRef); - } +Result TypeChecker::OnRefFuncExpr(Index func_type) { + PushType(Type(Type::Ref, func_type)); return Result::Ok; } diff --git a/src/validator.cc b/src/validator.cc index fcb4e69be1..e92f9e5863 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -189,13 +189,47 @@ void ScriptValidator::PrintError(const Location* loc, const char* format, ...) { errors_->emplace_back(ErrorLevel::Error, *loc, buffer); } +static Result CheckType(Type actual, Type expected) { + // Script validator (strict) type compare + if (expected == Type::Any || actual == Type::Any) { + return Result::Ok; + } + + Type::Enum actual_type = actual; + Type::Enum expected_type = expected; + + if (actual_type == expected_type) { + switch (actual_type) { + case Type::ExternRef: + case Type::FuncRef: + return (expected.IsNullableNonTypedRef() || + !actual.IsNullableNonTypedRef()) + ? Result::Ok + : Result::Error; + + case Type::Reference: + case Type::Ref: + case Type::RefNull: + if (actual == expected) { + return Result::Ok; + } + break; + + default: + return Result::Ok; + } + } + + return Result::Error; +} + void ScriptValidator::CheckTypeIndex(const Location* loc, Type actual, Type expected, const char* desc, Index index, const char* index_kind) { - if (Failed(TypeChecker::CheckType(actual, expected))) { + if (Failed(CheckType(actual, expected))) { PrintError(loc, "type mismatch for %s %" PRIindex " of %s. got %s, expected %s", index_kind, index, desc, actual.GetName().c_str(), @@ -321,14 +355,8 @@ Result Validator::OnCallIndirectExpr(CallIndirectExpr* expr) { } Result Validator::OnCallRefExpr(CallRefExpr* expr) { - Index function_type_index; - result_ |= validator_.OnCallRef(expr->loc, &function_type_index); - if (Succeeded(result_)) { - expr->function_type_index = Var{function_type_index, expr->loc}; - return Result::Ok; - } - - return Result::Error; + result_ |= validator_.OnCallRef(expr->loc, expr->sig_type); + return Result::Ok; } Result Validator::OnCodeMetadataExpr(CodeMetadataExpr* expr) { @@ -736,8 +764,6 @@ Result Validator::CheckModule() { } } - result_ |= validator_.EndTypeSection(); - // Import section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast(&field)) { diff --git a/src/wast-parser.cc b/src/wast-parser.cc index b452697bfa..79378aeea2 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -542,11 +542,6 @@ void AppendInlineExportFields(Module* module, module->AppendFields(fields); } -bool IsIndexLikelyType(Index index) { - // TODO: Incorrect values can be misinterpreted by the parser. - return index >= static_cast(Type::Void); -} - } // End of anonymous namespace WastParser::WastParser(WastLexer* lexer, @@ -883,25 +878,47 @@ bool WastParser::ParseElemExprVarListOpt(ExprListVector* out_list) { return !out_list->empty(); } +Result WastParser::ParseRefDeclaration(Var* out_type) { + EXPECT(Lpar); + EXPECT(Ref); + + Type::Enum opt_type = Type::Reference; + + if (options_->features.function_references_enabled()) { + opt_type = Type::Ref; + + if (Match(TokenType::Null)) { + opt_type = Type::RefNull; + } + } + + if (PeekMatch(TokenType::Func) || PeekMatch(TokenType::Extern)) { + TokenType token = Consume().token_type(); + out_type->set_opt_type(token == TokenType::Func ? Type::FuncRef + : Type::ExternRef); + out_type->set_index(opt_type == Type::Ref ? Type::ReferenceNonNull + : Type::ReferenceOrNull); + } else { + CHECK_RESULT(ParseVar(out_type)); + out_type->set_opt_type(opt_type); + } + + EXPECT(Rpar); + return Result::Ok; +} + Result WastParser::ParseValueType(Var* out_type) { WABT_TRACE(ParseValueType); - const bool is_ref_type = PeekMatchRefType(); - const bool is_value_type = PeekMatch(TokenType::ValueType); + if (PeekMatchRefType()) { + return ParseRefDeclaration(out_type); + } - if (!is_value_type && !is_ref_type) { + if (!PeekMatch(TokenType::ValueType)) { return ErrorExpected( {"i32", "i64", "f32", "f64", "v128", "externref", "exnref", "funcref"}); } - if (is_ref_type) { - EXPECT(Lpar); - EXPECT(Ref); - CHECK_RESULT(ParseVar(out_type)); - EXPECT(Rpar); - return Result::Ok; - } - Token token = Consume(); Type type = token.type(); bool is_enabled; @@ -926,7 +943,8 @@ Result WastParser::ParseValueType(Var* out_type) { return Result::Error; } - *out_type = Var(type, GetLocation()); + *out_type = Var(0, GetLocation()); + out_type->set_opt_type(type); return Result::Ok; } @@ -942,25 +960,29 @@ Result WastParser::ParseValueTypeList(TypeVector* out_type_list, CHECK_RESULT(ParseValueType(&type)); if (type.is_index()) { - if (IsIndexLikelyType(type.index())) { - out_type_list->push_back(Type(type.index())); - } else { - type_vars->push_back(ReferenceVar(out_type_list->size(), type)); - out_type_list->push_back(Type(Type::Reference, type.index())); - } + out_type_list->push_back(type.to_type()); } else { assert(type.is_name()); assert(options_->features.function_references_enabled()); type_vars->push_back(ReferenceVar(out_type_list->size(), type)); - out_type_list->push_back(Type(Type::Reference, kInvalidIndex)); + out_type_list->push_back(Type(type.opt_type(), kInvalidIndex)); } } return Result::Ok; } -Result WastParser::ParseRefKind(Type* out_type) { +Result WastParser::ParseRefKind(Var* out_type) { WABT_TRACE(ParseRefKind); + + if (options_->features.function_references_enabled() && + (PeekMatch(TokenType::Nat) || PeekMatch(TokenType::Var))) { + CHECK_RESULT(ParseVar(out_type)); + + out_type->set_opt_type(Type::RefNull); + return Result::Ok; + } + if (!IsTokenTypeRefKind(Peek())) { return ErrorExpected({"func", "extern", "exn"}); } @@ -976,42 +998,55 @@ Result WastParser::ParseRefKind(Type* out_type) { return Result::Error; } - *out_type = type; + *out_type = Var(0, GetLocation()); + out_type->set_opt_type(type); return Result::Ok; } -Result WastParser::ParseRefType(Type* out_type) { +Result WastParser::ParseRefType(Var* out_type) { WABT_TRACE(ParseRefType); + if (PeekMatchRefType()) { + return ParseRefDeclaration(out_type); + } + if (!PeekMatch(TokenType::ValueType)) { return ErrorExpected({"funcref", "externref", "exnref"}); } Token token = Consume(); Type type = token.type(); - if (type == Type::ExternRef && - !options_->features.reference_types_enabled()) { + if (!CheckRefType(type)) { Error(token.loc, "value type not allowed: %s", type.GetName().c_str()); return Result::Error; } - *out_type = type; + *out_type = Var(0, GetLocation()); + out_type->set_opt_type(type); return Result::Ok; } -bool WastParser::ParseRefTypeOpt(Type* out_type) { +bool WastParser::ParseRefTypeOpt(Var* out_type, Result& result) { WABT_TRACE(ParseRefTypeOpt); + + if (PeekMatchRefType()) { + result |= ParseRefDeclaration(out_type); + return true; + } + if (!PeekMatch(TokenType::ValueType)) { return false; } Token token = Consume(); Type type = token.type(); - if (type == Type::ExternRef && - !options_->features.reference_types_enabled()) { - return false; + if (!CheckRefType(type)) { + Error(token.loc, "value type not allowed: %s", type.GetName().c_str()); + result = Result::Error; + return true; } - *out_type = type; + *out_type = Var(0, GetLocation()); + out_type->set_opt_type(type); return true; } @@ -1298,10 +1333,34 @@ bool WastParser::PeekIsCustom() { tokens_.front().text() == "custom"; } -Result WastParser::ResolveRefTypes(const Module& module, - TypeVector* types, - ReferenceVars* ref_vars, - Errors* errors) { +Result WastParser::ResolveTargetRefType(const Module& module, + Type* type, + const Var& var, + Errors* errors) { + assert(type->IsReferenceWithIndex() && !var.is_index()); + + if (type->GetReferenceIndex() != kInvalidIndex) { + // Resolved earlier. + return Result::Ok; + } + + Index type_index = module.type_bindings.FindIndex(var.name()); + + if (type_index != kInvalidIndex) { + *type = Type(static_cast(*type), type_index); + return Result::Ok; + } + + errors->emplace_back( + ErrorLevel::Error, var.loc, + StringPrintf("undefined reference type name %s", var.name().c_str())); + return Result::Ok; +} + +Result WastParser::ResolveTargetTypeVector(const Module& module, + TypeVector* types, + ReferenceVars* ref_vars, + Errors* errors) { Result result = Result::Ok; for (auto& ref_var : *ref_vars) { @@ -1312,40 +1371,11 @@ Result WastParser::ResolveRefTypes(const Module& module, continue; } - assert(index < types->size()); - Type type = (*types)[index]; ref_var.index = kInvalidIndex; - assert(type.IsReferenceWithIndex()); - - if (ref_var.var.is_index()) { - if (type.GetReferenceIndex() >= module.types.size()) { - errors->emplace_back( - ErrorLevel::Error, ref_var.var.loc, - StringPrintf("reference type out of range: %d (max: %d)", - static_cast(type.GetReferenceIndex()), - static_cast(module.types.size()))); - result = Result::Error; - } - continue; - } - - if (type.GetReferenceIndex() != kInvalidIndex) { - // Resolved earlier. - continue; - } - - Index type_index = module.type_bindings.FindIndex(ref_var.var.name()); - - if (type_index == kInvalidIndex) { - errors->emplace_back(ErrorLevel::Error, ref_var.var.loc, - StringPrintf("undefined reference type name %s", - ref_var.var.name().c_str())); - result = Result::Error; - continue; - } - - (*types)[index] = Type(static_cast(type), type_index); + assert(index < types->size()); + result |= ResolveTargetRefType(module, types->data() + index, ref_var.var, + errors); } return Result::Ok; @@ -1355,7 +1385,8 @@ Result WastParser::ParseModuleFieldList(Module* module) { WABT_TRACE(ParseModuleFieldList); // Reset module-specific state. - resolve_types_.clear(); + resolve_ref_types_.clear(); + resolve_type_vectors_.clear(); resolve_funcs_.clear(); while (IsModuleField(PeekPair()) || PeekIsCustom()) { @@ -1371,12 +1402,17 @@ Result WastParser::ParseModuleFieldList(Module* module) { // Module parsing is completed, type names can be resolved now. Result result = Result::Ok; - for (auto it : resolve_types_) { - result |= ResolveRefTypes(*module, it.target_types, &it.vars, errors_); + for (auto it : resolve_ref_types_) { + result |= ResolveTargetRefType(*module, it.target_type, it.var, errors_); + } + + for (auto it : resolve_type_vectors_) { + result |= + ResolveTargetTypeVector(*module, it.target_vector, &it.vars, errors_); } for (auto it : resolve_funcs_) { - result |= ResolveRefTypes(*module, &it.types, &it.vars, errors_); + result |= ResolveTargetTypeVector(*module, &it.types, &it.vars, errors_); it.target_func->local_types.Set(it.types); } @@ -1491,7 +1527,11 @@ Result WastParser::ParseElemModuleField(Module* module) { CHECK_RESULT(ParseOffsetExpr(&field->elem_segment.offset)); } - if (ParseRefTypeOpt(&field->elem_segment.elem_type)) { + Result result; + Var elem_type; + if (ParseRefTypeOpt(&elem_type, result)) { + CHECK_RESULT(result); + VarToType(elem_type, &field->elem_segment.elem_type); ParseElemExprListOpt(&field->elem_segment.elem_exprs); } else { field->elem_segment.elem_type = Type::FuncRef; @@ -1586,7 +1626,7 @@ Result WastParser::ParseFuncModuleField(Module* module) { CHECK_RESULT(ParseTypeUseOpt(&func.decl)); CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.bindings)); - ResolveFuncs references(&func); + ResolveFunc references(&func); CHECK_RESULT(ParseBoundValueTypeList(TokenType::Local, &references.types, &func.bindings, &references.vars, @@ -1659,13 +1699,13 @@ Result WastParser::ParseField(Field* field) { field->mutable_ = true; Var type; CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.index()); + field->type = Type(type.opt_type()); EXPECT(Rpar); } else { field->mutable_ = false; Var type; CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.index()); + field->type = Type(type.opt_type()); } return Result::Ok; }; @@ -1758,7 +1798,9 @@ Result WastParser::ParseImportModuleField(Module* module) { auto import = std::make_unique(name); CHECK_RESULT(ParseLimitsIndex(&import->table.elem_limits)); CHECK_RESULT(ParseLimits(&import->table.elem_limits)); - CHECK_RESULT(ParseRefType(&import->table.elem_type)); + Var elem_type; + CHECK_RESULT(ParseRefType(&elem_type)); + VarToType(elem_type, &import->table.elem_type); EXPECT(Rpar); field = std::make_unique(std::move(import), loc); break; @@ -1908,7 +1950,9 @@ Result WastParser::ParseTableModuleField(Module* module) { CHECK_RESULT(ParseInlineImport(import.get())); CHECK_RESULT(ParseLimitsIndex(&import->table.elem_limits)); CHECK_RESULT(ParseLimits(&import->table.elem_limits)); - CHECK_RESULT(ParseRefType(&import->table.elem_type)); + Var elem_type; + CHECK_RESULT(ParseRefType(&elem_type)); + VarToType(elem_type, &import->table.elem_type); auto field = std::make_unique(std::move(import), GetLocation()); module->AppendField(std::move(field)); @@ -1916,8 +1960,8 @@ Result WastParser::ParseTableModuleField(Module* module) { auto field = std::make_unique(loc, name); auto& table = field->table; CHECK_RESULT(ParseLimitsIndex(&table.elem_limits)); - if (PeekMatch(TokenType::ValueType)) { - Type elem_type; + if (PeekMatch(TokenType::ValueType) || PeekMatchRefType()) { + Var elem_type; CHECK_RESULT(ParseRefType(&elem_type)); EXPECT(Lpar); @@ -1929,7 +1973,7 @@ Result WastParser::ParseTableModuleField(Module* module) { auto offset = table.elem_limits.is_64 ? Const::I64(0) : Const::I32(0); elem_segment.offset.push_back(std::make_unique(offset)); elem_segment.offset.back().loc = loc; - elem_segment.elem_type = elem_type; + VarToType(elem_type, &elem_segment.elem_type); // Syntax is either an optional list of var (legacy), or a non-empty list // of elem expr. ExprList elem_expr; @@ -1945,12 +1989,14 @@ Result WastParser::ParseTableModuleField(Module* module) { table.elem_limits.initial = elem_segment.elem_exprs.size(); table.elem_limits.max = elem_segment.elem_exprs.size(); table.elem_limits.has_max = true; - table.elem_type = elem_type; + VarToType(elem_type, &table.elem_type); module->AppendField(std::move(field)); module->AppendField(std::move(elem_segment_field)); } else { CHECK_RESULT(ParseLimits(&table.elem_limits)); - CHECK_RESULT(ParseRefType(&table.elem_type)); + Var elem_type; + CHECK_RESULT(ParseRefType(&elem_type)); + VarToType(elem_type, &table.elem_type); module->AppendField(std::move(field)); } } @@ -2020,19 +2066,19 @@ Result WastParser::ParseFuncSignature(FuncSignature* sig, BindingHash* param_bindings) { WABT_TRACE(ParseFuncSignature); - ResolveTypes param_references(&sig->param_types); - ResolveTypes result_references(&sig->result_types); + ResolveTypeVector param_references(&sig->param_types); + ResolveTypeVector result_references(&sig->result_types); CHECK_RESULT(ParseBoundValueTypeList(TokenType::Param, &sig->param_types, param_bindings, ¶m_references.vars)); CHECK_RESULT(ParseResultList(&sig->result_types, &result_references.vars)); if (!param_references.vars.empty()) { - resolve_types_.push_back(param_references); + resolve_type_vectors_.push_back(param_references); } if (!result_references.vars.empty()) { - resolve_types_.push_back(result_references); + resolve_type_vectors_.push_back(result_references); } return Result::Ok; @@ -2041,19 +2087,19 @@ Result WastParser::ParseFuncSignature(FuncSignature* sig, Result WastParser::ParseUnboundFuncSignature(FuncSignature* sig) { WABT_TRACE(ParseUnboundFuncSignature); - ResolveTypes param_references(&sig->param_types); - ResolveTypes result_references(&sig->result_types); + ResolveTypeVector param_references(&sig->param_types); + ResolveTypeVector result_references(&sig->result_types); CHECK_RESULT(ParseUnboundValueTypeList(TokenType::Param, &sig->param_types, ¶m_references.vars)); CHECK_RESULT(ParseResultList(&sig->result_types, &result_references.vars)); if (!param_references.vars.empty()) { - resolve_types_.push_back(param_references); + resolve_type_vectors_.push_back(param_references); } if (!result_references.vars.empty()) { - resolve_types_.push_back(result_references); + resolve_type_vectors_.push_back(result_references); } return Result::Ok; @@ -2075,17 +2121,12 @@ Result WastParser::ParseBoundValueTypeList(TokenType token, bindings->emplace(name, Binding(loc, binding_index_offset + types->size())); if (type.is_index()) { - if (IsIndexLikelyType(type.index())) { - types->push_back(Type(type.index())); - } else { - type_vars->push_back(ReferenceVar(types->size(), type)); - types->push_back(Type(Type::Reference, type.index())); - } + types->push_back(type.to_type()); } else { assert(type.is_name()); assert(options_->features.function_references_enabled()); type_vars->push_back(ReferenceVar(types->size(), type)); - types->push_back(Type(Type::Reference, kInvalidIndex)); + types->push_back(Type(type.opt_type(), kInvalidIndex)); } } else { CHECK_RESULT(ParseValueTypeList(types, type_vars)); @@ -2341,12 +2382,13 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { case TokenType::Select: { Consume(); - TypeVector result; + auto expr = std::make_unique(loc); + ResolveTypeVector result_type(&expr->result_type); if (options_->features.reference_types_enabled() && PeekMatchLpar(TokenType::Result)) { - CHECK_RESULT(ParseResultList(&result, nullptr)); + CHECK_RESULT(ParseResultList(&expr->result_type, &result_type.vars)); } - out_expr->reset(new SelectExpr(result, loc)); + *out_expr = std::move(expr); break; } @@ -2392,7 +2434,10 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { case TokenType::CallRef: { ErrorUnlessOpcodeEnabled(Consume()); - out_expr->reset(new CallRefExpr(loc)); + auto expr = std::make_unique(loc); + CHECK_RESULT(ParseVar(&expr->sig_type)); + expr->sig_type.set_opt_type(Type::RefNull); + *out_expr = std::move(expr); break; } @@ -2588,7 +2633,7 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { case TokenType::RefNull: { ErrorUnlessOpcodeEnabled(Consume()); - Type type; + Var type; CHECK_RESULT(ParseRefKind(&type)); out_expr->reset(new RefNullExpr(type, loc)); break; @@ -3009,7 +3054,11 @@ Result WastParser::ParseExternref(Const* const_) { uint64_t ref_bits; Result result = ParseInt64(sv, &ref_bits, ParseIntType::UnsignedOnly); - const_->set_externref(static_cast(ref_bits)); + if (ref_bits != 0 && options_->features.function_references_enabled()) { + const_->set_extern(static_cast(ref_bits)); + } else { + const_->set_externref(static_cast(ref_bits)); + } if (Failed(result)) { Error(const_->loc, "invalid literal \"" PRIstringview "\"", @@ -3034,11 +3083,11 @@ Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { break; case TokenType::RefNull: { auto token = Consume(); - Type type; + Var type; CHECK_RESULT(ParseRefKind(&type)); ErrorUnlessOpcodeEnabled(token); const_.loc = GetLocation(); - const_.set_null(type); + const_.set_null(type.opt_type()); break; } case TokenType::RefFunc: { @@ -3437,13 +3486,13 @@ Result WastParser::ParseGlobalType(Global* global) { global->mutable_ = true; Var type; CHECK_RESULT(ParseValueType(&type)); - global->type = Type(type.index()); + VarToType(type, &global->type); CHECK_RESULT(ErrorIfLpar({"i32", "i64", "f32", "f64"})); EXPECT(Rpar); } else { Var type; CHECK_RESULT(ParseValueType(&type)); - global->type = Type(type.index()); + VarToType(type, &global->type); } return Result::Ok; @@ -3886,6 +3935,30 @@ bool WastParser::HasError() const { }); } +bool WastParser::CheckRefType(Type::Enum type) { + switch (type) { + case Type::FuncRef: + return true; + case Type::ExternRef: + return options_->features.reference_types_enabled(); + case Type::ExnRef: + return options_->features.exceptions_enabled(); + default: + assert(!Type::EnumIsNonTypedRef(type)); + return false; + } +} + +void WastParser::VarToType(const Var& var, Type* type) { + if (!Type::EnumIsReferenceWithIndex(var.opt_type()) || var.is_index()) { + *type = var.to_type(); + return; + } + + *type = Type(var.opt_type(), kInvalidIndex); + resolve_ref_types_.push_back(ResolveRefType(type, var)); +} + void WastParser::TokenQueue::push_back(Token t) { assert(!tokens[!i]); tokens[!i] = t; diff --git a/src/wat-writer.cc b/src/wat-writer.cc index f19e3c3c86..c090b62d6f 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -686,6 +686,7 @@ Result WatWriter::ExprVisitorDelegate::OnCallIndirectExpr( Result WatWriter::ExprVisitorDelegate::OnCallRefExpr(CallRefExpr* expr) { writer_->WritePutsSpace(Opcode::CallRef_Opcode.GetName()); + writer_->WriteVar(expr->sig_type, NextChar::Newline); return Result::Ok; } @@ -890,7 +891,12 @@ Result WatWriter::ExprVisitorDelegate::OnRefFuncExpr(RefFuncExpr* expr) { Result WatWriter::ExprVisitorDelegate::OnRefNullExpr(RefNullExpr* expr) { writer_->WritePutsSpace(Opcode::RefNull_Opcode.GetName()); - writer_->WriteRefKind(expr->type, NextChar::Newline); + if (expr->type.opt_type() != Type::RefNull) { + assert(!Type(expr->type.opt_type()).IsReferenceWithIndex()); + writer_->WriteRefKind(expr->type.opt_type(), NextChar::Newline); + } else { + writer_->WriteVar(expr->type, NextChar::Newline); + } return Result::Ok; } diff --git a/test/binary/bad-reference-indicies.txt b/test/binary/bad-reference-indicies.txt index 06d21a7c8d..fea35b8dfe 100644 --- a/test/binary/bad-reference-indicies.txt +++ b/test/binary/bad-reference-indicies.txt @@ -17,10 +17,10 @@ section(CODE) { } } (;; STDERR ;;; -0000000: error: reference 10 is out of range in params -0000000: error: reference 20 is out of range in results +out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:0000012: error: reference 10 is out of range in params +out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:0000012: error: reference 20 is out of range in results out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:000001d: error: reference 30 is out of range in locals -0000000: error: reference 10 is out of range in params -0000000: error: reference 20 is out of range in results +out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:0000012: error: reference 10 is out of range in params +out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:0000012: error: reference 20 is out of range in results out/test/binary/bad-reference-indicies/bad-reference-indicies.wasm:000001d: error: reference 30 is out of range in locals ;;; STDERR ;;) diff --git a/test/dump/call_ref.txt b/test/dump/call_ref.txt index 5c24aff479..997440c108 100644 --- a/test/dump/call_ref.txt +++ b/test/dump/call_ref.txt @@ -5,13 +5,14 @@ (func (export "main") (result i32) i32.const 10 ref.func $foo - call_ref + call_ref 0 ) (func $foo (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 19)) ) (elem declare funcref (ref.func $foo)) + (type (func (param i32) (result i32))) ) (;; STDERR ;;; @@ -23,13 +24,13 @@ 000000a: 02 ; num types ; func type 0 000000b: 60 ; func -000000c: 00 ; num params -000000d: 01 ; num results -000000e: 7f ; i32 +000000c: 01 ; num params +000000d: 7f ; i32 +000000e: 01 ; num results +000000f: 7f ; i32 ; func type 1 -000000f: 60 ; func -0000010: 01 ; num params -0000011: 7f ; i32 +0000010: 60 ; func +0000011: 00 ; num params 0000012: 01 ; num results 0000013: 7f ; i32 0000009: 0a ; FIXUP section size @@ -37,8 +38,8 @@ 0000014: 03 ; section code 0000015: 00 ; section size (guess) 0000016: 02 ; num functions -0000017: 00 ; function 0 signature index -0000018: 01 ; function 1 signature index +0000017: 01 ; function 0 signature index +0000018: 00 ; function 1 signature index 0000015: 03 ; FIXUP section size ; section "Export" (7) 0000019: 07 ; section code @@ -71,19 +72,20 @@ 0000031: d2 ; ref.func 0000032: 01 ; function index 0000033: 14 ; call_ref -0000034: 0b ; end -000002d: 07 ; FIXUP func body size +0000034: 00 ; signature index +0000035: 0b ; end +000002d: 08 ; FIXUP func body size ; function body 1 -0000035: 00 ; func body size (guess) -0000036: 00 ; local decl count -0000037: 20 ; local.get -0000038: 00 ; local index -0000039: 41 ; i32.const -000003a: 13 ; i32 literal -000003b: 6a ; i32.add -000003c: 0b ; end -0000035: 07 ; FIXUP func body size -000002b: 11 ; FIXUP section size +0000036: 00 ; func body size (guess) +0000037: 00 ; local decl count +0000038: 20 ; local.get +0000039: 00 ; local index +000003a: 41 ; i32.const +000003b: 13 ; i32 literal +000003c: 6a ; i32.add +000003d: 0b ; end +0000036: 07 ; FIXUP func body size +000002b: 12 ; FIXUP section size ;;; STDERR ;;) (;; STDOUT ;;; @@ -94,11 +96,11 @@ Code Disassembly: 00002e func[0]
: 00002f: 41 0a | i32.const 10 000031: d2 01 | ref.func 1 - 000033: 14 | call_ref - 000034: 0b | end -000036 func[1]: - 000037: 20 00 | local.get 0 - 000039: 41 13 | i32.const 19 - 00003b: 6a | i32.add - 00003c: 0b | end + 000033: 14 00 | call_ref (ref null 0) + 000035: 0b | end +000037 func[1]: + 000038: 20 00 | local.get 0 + 00003a: 41 13 | i32.const 19 + 00003c: 6a | i32.add + 00003d: 0b | end ;;; STDOUT ;;) diff --git a/test/dump/typed-func-ref-signature.txt b/test/dump/typed-func-ref-signature.txt index 506affe055..5598f6e02e 100644 --- a/test/dump/typed-func-ref-signature.txt +++ b/test/dump/typed-func-ref-signature.txt @@ -34,19 +34,19 @@ ; func type 3 0000014: 60 ; func 0000015: 01 ; num params -0000016: 6b ; (ref 0) +0000016: 64 ; (ref 0) 0000017: 00 ; (ref 0) 0000018: 00 ; num results ; func type 4 0000019: 60 ; func 000001a: 01 ; num params -000001b: 6b ; (ref 1) +000001b: 64 ; (ref 1) 000001c: 01 ; (ref 1) 000001d: 00 ; num results ; func type 5 000001e: 60 ; func 000001f: 01 ; num params -0000020: 6b ; (ref 2) +0000020: 64 ; (ref 2) 0000021: 02 ; (ref 2) 0000022: 00 ; num results 0000009: 19 ; FIXUP section size diff --git a/test/dump/typed-func-refs-locals.txt b/test/dump/typed-func-refs-locals.txt index cd6363d52b..9a67cec86a 100644 --- a/test/dump/typed-func-refs-locals.txt +++ b/test/dump/typed-func-refs-locals.txt @@ -3,9 +3,9 @@ (module (type $t0 (func)) + (type $t1 (func)) - ;; Self reference - (type $t1 (func (param (ref $t0) (ref $t1) (ref 1)))) + (type $t2 (func (param (ref $t0) (ref $t1) (ref 1)))) (func $f1 (param (ref $t0) (ref 0)) (local (ref $t0) (ref 0) @@ -19,52 +19,56 @@ ; section "Type" (1) 0000008: 01 ; section code 0000009: 00 ; section size (guess) -000000a: 03 ; num types +000000a: 04 ; num types ; func type 0 000000b: 60 ; func 000000c: 00 ; num params 000000d: 00 ; num results ; func type 1 000000e: 60 ; func -000000f: 03 ; num params -0000010: 6b ; (ref 0) -0000011: 00 ; (ref 0) -0000012: 6b ; (ref 1) -0000013: 01 ; (ref 1) -0000014: 6b ; (ref 1) -0000015: 01 ; (ref 1) -0000016: 00 ; num results +000000f: 00 ; num params +0000010: 00 ; num results ; func type 2 -0000017: 60 ; func -0000018: 02 ; num params -0000019: 6b ; (ref 0) -000001a: 00 ; (ref 0) -000001b: 6b ; (ref 0) -000001c: 00 ; (ref 0) -000001d: 00 ; num results -0000009: 14 ; FIXUP section size +0000011: 60 ; func +0000012: 03 ; num params +0000013: 64 ; (ref 0) +0000014: 00 ; (ref 0) +0000015: 64 ; (ref 1) +0000016: 01 ; (ref 1) +0000017: 64 ; (ref 1) +0000018: 01 ; (ref 1) +0000019: 00 ; num results +; func type 3 +000001a: 60 ; func +000001b: 02 ; num params +000001c: 64 ; (ref 0) +000001d: 00 ; (ref 0) +000001e: 64 ; (ref 0) +000001f: 00 ; (ref 0) +0000020: 00 ; num results +0000009: 17 ; FIXUP section size ; section "Function" (3) -000001e: 03 ; section code -000001f: 00 ; section size (guess) -0000020: 01 ; num functions -0000021: 02 ; function 0 signature index -000001f: 02 ; FIXUP section size +0000021: 03 ; section code +0000022: 00 ; section size (guess) +0000023: 01 ; num functions +0000024: 03 ; function 0 signature index +0000022: 02 ; FIXUP section size ; section "Code" (10) -0000022: 0a ; section code -0000023: 00 ; section size (guess) -0000024: 01 ; num functions +0000025: 0a ; section code +0000026: 00 ; section size (guess) +0000027: 01 ; num functions ; function body 0 -0000025: 00 ; func body size (guess) -0000026: 02 ; local decl count -0000027: 02 ; local type count -0000028: 6b ; (ref 0) -0000029: 00 ; (ref 0) +0000028: 00 ; func body size (guess) +0000029: 02 ; local decl count 000002a: 02 ; local type count -000002b: 6b ; (ref 1) -000002c: 01 ; (ref 1) -000002d: 0b ; end -0000025: 08 ; FIXUP func body size -0000023: 0a ; FIXUP section size +000002b: 64 ; (ref 0) +000002c: 00 ; (ref 0) +000002d: 02 ; local type count +000002e: 64 ; (ref 1) +000002f: 01 ; (ref 1) +0000030: 0b ; end +0000028: 08 ; FIXUP func body size +0000026: 0a ; FIXUP section size ;;; STDERR ;;) (;; STDOUT ;;; @@ -72,8 +76,8 @@ typed-func-refs-locals.wasm: file format wasm 0x1 Code Disassembly: -000026 func[0]: - 000027: 02 6b 00 | local[2..3] type=(ref 0) - 00002a: 02 6b 01 | local[4..5] type=(ref 1) - 00002d: 0b | end +000029 func[0]: + 00002a: 02 64 00 | local[2..3] type=(ref 0) + 00002d: 02 64 01 | local[4..5] type=(ref 1) + 000030: 0b | end ;;; STDOUT ;;) diff --git a/test/dump/typed_func_refs_params.txt b/test/dump/typed_func_refs_params.txt index 6bda5d10af..7bbd41f722 100644 --- a/test/dump/typed_func_refs_params.txt +++ b/test/dump/typed_func_refs_params.txt @@ -6,8 +6,8 @@ (func $deriv (param $f (ref $f32-f32)) (param $x f32) (param $delta f32) (result f32) (f32.div - (f32.sub (call_ref (f32.add (local.get $delta) (local.get $x)) (local.get $f)) - (call_ref (local.get $x) (local.get $f)) + (f32.sub (call_ref $f32-f32 (f32.add (local.get $delta) (local.get $x)) (local.get $f)) + (call_ref $f32-f32 (local.get $x) (local.get $f)) ) (local.get $delta) ) @@ -44,7 +44,7 @@ ; func type 1 0000010: 60 ; func 0000011: 03 ; num params -0000012: 6b ; (ref 0) +0000012: 64 ; (ref 0) 0000013: 00 ; (ref 0) 0000014: 7d ; f32 0000015: 7d ; f32 @@ -98,41 +98,43 @@ 000003d: 20 ; local.get 000003e: 00 ; local index 000003f: 14 ; call_ref -0000040: 20 ; local.get -0000041: 01 ; local index -0000042: 20 ; local.get -0000043: 00 ; local index -0000044: 14 ; call_ref -0000045: 93 ; f32.sub -0000046: 20 ; local.get -0000047: 02 ; local index -0000048: 95 ; f32.div -0000049: 0b ; end -0000036: 13 ; FIXUP func body size +0000040: 00 ; signature index +0000041: 20 ; local.get +0000042: 01 ; local index +0000043: 20 ; local.get +0000044: 00 ; local index +0000045: 14 ; call_ref +0000046: 00 ; signature index +0000047: 93 ; f32.sub +0000048: 20 ; local.get +0000049: 02 ; local index +000004a: 95 ; f32.div +000004b: 0b ; end +0000036: 15 ; FIXUP func body size ; function body 1 -000004a: 00 ; func body size (guess) -000004b: 00 ; local decl count -000004c: 20 ; local.get -000004d: 00 ; local index +000004c: 00 ; func body size (guess) +000004d: 00 ; local decl count 000004e: 20 ; local.get 000004f: 00 ; local index -0000050: 94 ; f32.mul -0000051: 0b ; end -000004a: 07 ; FIXUP func body size +0000050: 20 ; local.get +0000051: 00 ; local index +0000052: 94 ; f32.mul +0000053: 0b ; end +000004c: 07 ; FIXUP func body size ; function body 2 -0000052: 00 ; func body size (guess) -0000053: 00 ; local decl count -0000054: d2 ; ref.func -0000055: 01 ; function index -0000056: 43 ; f32.const -0000057: 0000 803f ; f32 literal -000005b: 43 ; f32.const -000005c: 0ad7 233c ; f32 literal -0000060: 10 ; call -0000061: 00 ; function index -0000062: 0b ; end -0000052: 10 ; FIXUP func body size -0000034: 2e ; FIXUP section size +0000054: 00 ; func body size (guess) +0000055: 00 ; local decl count +0000056: d2 ; ref.func +0000057: 01 ; function index +0000058: 43 ; f32.const +0000059: 0000 803f ; f32 literal +000005d: 43 ; f32.const +000005e: 0ad7 233c ; f32 literal +0000062: 10 ; call +0000063: 00 ; function index +0000064: 0b ; end +0000054: 10 ; FIXUP func body size +0000034: 30 ; FIXUP section size ;;; STDERR ;;) (;; STDOUT ;;; @@ -145,23 +147,23 @@ Code Disassembly: 00003a: 20 01 | local.get 1 00003c: 92 | f32.add 00003d: 20 00 | local.get 0 - 00003f: 14 | call_ref - 000040: 20 01 | local.get 1 - 000042: 20 00 | local.get 0 - 000044: 14 | call_ref - 000045: 93 | f32.sub - 000046: 20 02 | local.get 2 - 000048: 95 | f32.div - 000049: 0b | end -00004b func[1]: - 00004c: 20 00 | local.get 0 + 00003f: 14 00 | call_ref (ref null 0) + 000041: 20 01 | local.get 1 + 000043: 20 00 | local.get 0 + 000045: 14 00 | call_ref (ref null 0) + 000047: 93 | f32.sub + 000048: 20 02 | local.get 2 + 00004a: 95 | f32.div + 00004b: 0b | end +00004d func[1]: 00004e: 20 00 | local.get 0 - 000050: 94 | f32.mul - 000051: 0b | end -000053 func[2]
: - 000054: d2 01 | ref.func 1 - 000056: 43 00 00 80 3f | f32.const 0x1p+0 - 00005b: 43 0a d7 23 3c | f32.const 0x1.47ae14p-7 - 000060: 10 00 | call 0 - 000062: 0b | end + 000050: 20 00 | local.get 0 + 000052: 94 | f32.mul + 000053: 0b | end +000055 func[2]
: + 000056: d2 01 | ref.func 1 + 000058: 43 00 00 80 3f | f32.const 0x1p+0 + 00005d: 43 0a d7 23 3c | f32.const 0x1.47ae14p-7 + 000062: 10 00 | call 0 + 000064: 0b | end ;;; STDOUT ;;) diff --git a/test/dump/typed_func_refs_results.txt b/test/dump/typed_func_refs_results.txt index 5acffc39ae..81ff524039 100644 --- a/test/dump/typed_func_refs_results.txt +++ b/test/dump/typed_func_refs_results.txt @@ -33,7 +33,7 @@ ) (func (export "main") (result f32) - (call_ref + (call_ref $f32-f32 (f32.const 2.0) (call $choice (ref.func $square) (ref.func $double) (i32.const 1)) ) @@ -58,13 +58,13 @@ ; func type 1 0000010: 60 ; func 0000011: 03 ; num params -0000012: 6b ; (ref 0) +0000012: 64 ; (ref 0) 0000013: 00 ; (ref 0) -0000014: 6b ; (ref 0) +0000014: 64 ; (ref 0) 0000015: 00 ; (ref 0) 0000016: 7f ; i32 0000017: 01 ; num results -0000018: 6b ; (ref 0) +0000018: 64 ; (ref 0) 0000019: 00 ; (ref 0) ; func type 2 000001a: 60 ; func @@ -114,7 +114,7 @@ 000003f: 01 ; i32 literal 0000040: 46 ; i32.eq 0000041: 04 ; if -0000042: 6b ; (ref 0) +0000042: 64 ; (ref 0) 0000043: 00 ; (ref 0) 0000044: 20 ; local.get 0000045: 00 ; local index @@ -158,9 +158,10 @@ 0000068: 10 ; call 0000069: 00 ; function index 000006a: 14 ; call_ref -000006b: 0b ; end -000005b: 10 ; FIXUP func body size -0000038: 33 ; FIXUP section size +000006b: 00 ; signature index +000006c: 0b ; end +000005b: 11 ; FIXUP func body size +0000038: 34 ; FIXUP section size ;;; STDERR ;;) (;; STDOUT ;;; @@ -172,7 +173,7 @@ Code Disassembly: 00003c: 20 02 | local.get 2 00003e: 41 01 | i32.const 1 000040: 46 | i32.eq - 000041: 04 6b 00 | if (ref 0) + 000041: 04 64 00 | if (ref 0) 000044: 20 00 | local.get 0 000046: 05 | else 000047: 20 01 | local.get 1 @@ -194,6 +195,6 @@ Code Disassembly: 000064: d2 02 | ref.func 2 000066: 41 01 | i32.const 1 000068: 10 00 | call 0 - 00006a: 14 | call_ref - 00006b: 0b | end + 00006a: 14 00 | call_ref (ref null 0) + 00006c: 0b | end ;;; STDOUT ;;) diff --git a/test/parse/bad-references.txt b/test/parse/bad-references.txt index b31e4ce0d6..6ca809ab29 100644 --- a/test/parse/bad-references.txt +++ b/test/parse/bad-references.txt @@ -11,19 +11,19 @@ ) ) (;; STDERR ;;; -out/test/parse/bad-references.txt:6:31: error: reference type out of range: 2 (max: 2) +out/test/parse/bad-references.txt:6:4: error: reference 2 is out of range in params (type $t0 (func (param (ref 2)))) - ^ -out/test/parse/bad-references.txt:7:31: error: reference type out of range: 33 (max: 2) + ^^^^ +out/test/parse/bad-references.txt:7:4: error: reference 33 is out of range in params (type $t1 (func (param (ref 33)) (result (ref 444)))) - ^^ -out/test/parse/bad-references.txt:7:49: error: reference type out of range: 444 (max: 2) + ^^^^ +out/test/parse/bad-references.txt:7:4: error: reference 444 is out of range in results (type $t1 (func (param (ref 33)) (result (ref 444)))) - ^^^ -out/test/parse/bad-references.txt:9:28: error: reference type out of range: 5555 (max: 2) + ^^^^ +out/test/parse/bad-references.txt:9:4: error: reference 5555 is out of range in params (func $f (param $p1 (ref 5555)) - ^^^^ -out/test/parse/bad-references.txt:10:21: error: reference type out of range: 66666 (max: 2) - (local $p2 (ref 66666)) - ^^^^^ + ^^^^ +out/test/parse/bad-references.txt:9:12: error: reference 66666 is out of range in locals + (func $f (param $p1 (ref 5555)) + ^ ;;; STDERR ;;) diff --git a/test/parse/expr/callref-imported-function.txt b/test/parse/expr/callref-imported-function.txt index 255f7c19e9..edabe4354f 100644 --- a/test/parse/expr/callref-imported-function.txt +++ b/test/parse/expr/callref-imported-function.txt @@ -3,9 +3,10 @@ (module (import "" "foo" (func $foo (param i32) (result i32))) (func (export "main") (result i32) - (call_ref (i32.const 10) - (ref.func $foo) + (call_ref $t (i32.const 10) + (ref.func $foo) ) ) (elem declare funcref (ref.func $foo)) + (type $t (func (param i32) (result i32))) ) diff --git a/test/parse/expr/callref-internal-function.txt b/test/parse/expr/callref-internal-function.txt index 5cc27cc682..fc85558345 100644 --- a/test/parse/expr/callref-internal-function.txt +++ b/test/parse/expr/callref-internal-function.txt @@ -2,13 +2,15 @@ ;;; ARGS: --enable-function-references (module (func (export "main") (result i32) - (call_ref (i32.const 10) - (ref.func $foo) + (call_ref 0 (i32.const 10) + (ref.func $foo) ) ) (func $foo (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 19)) ) + (elem declare funcref (ref.func $foo)) + (type (func (param i32) (result i32))) ) diff --git a/test/parse/module/bad-element-followed-by-illegal-expression.txt b/test/parse/module/bad-element-followed-by-illegal-expression.txt index 5243aedc8e..34e3389fe6 100644 --- a/test/parse/module/bad-element-followed-by-illegal-expression.txt +++ b/test/parse/module/bad-element-followed-by-illegal-expression.txt @@ -3,7 +3,7 @@ ;;; ERROR: 1 ( elem f64 ( ) ) (;; STDERR ;;; -out/test/parse/module/bad-element-followed-by-illegal-expression.txt:4:12: error: unexpected token (, expected ). +out/test/parse/module/bad-element-followed-by-illegal-expression.txt:4:8: error: value type not allowed: f64 ( elem f64 ( ) ) - ^ + ^^^ ;;; STDERR ;;) diff --git a/test/roundtrip/fold-callref.txt b/test/roundtrip/fold-callref.txt index fdfbcae052..dbd885b88b 100644 --- a/test/roundtrip/fold-callref.txt +++ b/test/roundtrip/fold-callref.txt @@ -1,26 +1,24 @@ ;;; TOOL: run-roundtrip ;;; ARGS: --stdout --fold-exprs --enable-function-references (module - (type $i_i (func (param i32) (result i32))) - (func $i32_r_i32 (type $i_i) i32.const 1) - (func $i32_f32_r_f32 (param i32 f32) (result f32) + (func $i32_f32_r_f32 (type $if_f) f32.const 0) - (func $f32_f32_f32_f32_r_v (param f32 f32 f32 f32)) + (func $f32_f32_f32_f32_r_v (type $ffff)) (elem declare funcref (ref.func $i32_r_i32) (ref.func $i32_f32_r_f32) (ref.func $f32_f32_f32_f32_r_v)) (func $fold-callref (result i32) i32.const 1 ref.func $i32_r_i32 - call_ref + call_ref $i_i drop i32.const 2 ref.func $i32_r_i32 - call_ref) + call_ref $i_i) (func $fold-call-2 f32.const 0 @@ -29,9 +27,13 @@ i32.const 3 f32.const 4 ref.func $i32_f32_r_f32 - call_ref + call_ref $if_f ref.func $f32_f32_f32_f32_r_v - call_ref) + call_ref $ffff) + + (type $i_i (func (param i32) (result i32))) + (type $if_f (func (param i32 f32) (result f32))) + (type $ffff (func (param f32 f32 f32 f32))) ) (;; STDOUT ;;; @@ -48,15 +50,19 @@ (func (;2;) (type 2) (param f32 f32 f32 f32)) (func (;3;) (type 3) (result i32) (drop - (call_ref (i32.const 1) + (call_ref 0 + (i32.const 1) (ref.func 0))) - (call_ref (i32.const 2) + (call_ref 0 + (i32.const 2) (ref.func 0))) (func (;4;) (type 4) - (call_ref (f32.const 0x0p+0 (;=0;)) + (call_ref 2 + (f32.const 0x0p+0 (;=0;)) (f32.const 0x1p+0 (;=1;)) (f32.const 0x1p+1 (;=2;)) - (call_ref (i32.const 3) + (call_ref 1 + (i32.const 3) (f32.const 0x1p+2 (;=4;)) (ref.func 1)) (ref.func 2))) diff --git a/test/roundtrip/ref-types.txt b/test/roundtrip/ref-types.txt new file mode 100644 index 0000000000..2b010c5e69 --- /dev/null +++ b/test/roundtrip/ref-types.txt @@ -0,0 +1,37 @@ +;;; TOOL: run-roundtrip +;;; ARGS: --stdout --enable-function-references +(module + (type $ii (func)) + (func $dummy) + + (global (ref func) ref.func $dummy) + (global (ref $ii) ref.func $dummy) + (global (ref null func) ref.null $ii) + (global (ref null $ii) ref.null $ii) + + (func $f1 (param (ref func) (ref extern) (ref $ii)) + (local (ref func) (ref func) + (ref extern) (ref extern) + (ref $ii) (ref $ii)) + ) + (func $f2 (param (ref null func) (ref null extern) (ref null $ii)) + (local (ref null func) (ref null func) + (ref null extern) (ref null extern) + (ref null $ii) (ref null $ii)) + ) +) +(;; STDOUT ;;; +(module + (type (;0;) (func)) + (type (;1;) (func (param (ref func) (ref extern) (ref 0)))) + (type (;2;) (func (param funcref externref (ref null 0)))) + (func (;0;) (type 0)) + (func (;1;) (type 1) (param (ref func) (ref extern) (ref 0)) + (local (ref func) (ref func) (ref extern) (ref extern) (ref 0) (ref 0))) + (func (;2;) (type 2) (param funcref externref (ref null 0)) + (local funcref funcref externref externref (ref null 0) (ref null 0))) + (global (;0;) (ref func) (ref.func 0)) + (global (;1;) (ref 0) (ref.func 0)) + (global (;2;) funcref (ref.null 0)) + (global (;3;) (ref null 0) (ref.null 0))) +;;; STDOUT ;;) diff --git a/test/roundtrip/typed-func-refs.txt b/test/roundtrip/typed-func-refs.txt index 25fdfebf1c..c1961de3c5 100644 --- a/test/roundtrip/typed-func-refs.txt +++ b/test/roundtrip/typed-func-refs.txt @@ -2,9 +2,9 @@ ;;; ARGS: --stdout --enable-function-references --debug-names (module (type $t0 (func)) + (type $t1 (func)) - ;; Self reference - (type $t1 (func (param (ref $t0) (ref $t1) (ref 1)))) + (type $t2 (func (param (ref $t0) (ref $t1) (ref 1)))) (func $f1 (param (ref $t0) (ref 0)) (local (ref $t0) (ref 0) @@ -14,8 +14,9 @@ (;; STDOUT ;;; (module (type $t0 (func)) - (type $t1 (func (param (ref 0) (ref 1) (ref 1)))) - (type (;2;) (func (param (ref 0) (ref 0)))) - (func $f1 (type 2) (param (ref 0) (ref 0)) + (type $t1 (func)) + (type $t2 (func (param (ref 0) (ref 1) (ref 1)))) + (type (;3;) (func (param (ref 0) (ref 0)))) + (func $f1 (type 3) (param (ref 0) (ref 0)) (local (ref 0) (ref 0) (ref 1) (ref 1)))) ;;; STDOUT ;;) diff --git a/test/spec/function-references/br_table.txt b/test/spec/function-references/br_table.txt new file mode 100644 index 0000000000..efbc319cfb --- /dev/null +++ b/test/spec/function-references/br_table.txt @@ -0,0 +1,78 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/br_table.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/br_table.wast:1267: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.1.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/br_table.wast:1274: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.2.wasm:000001d: error: type mismatch in br_table, expected [i32] but got [] + 000001d: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1281: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.3.wasm:0000020: error: type mismatch in br_table, expected [i32] but got [] + 0000020: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1287: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.4.wasm:0000023: error: type mismatch in br_table, expected [i32] but got [i64] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1295: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.5.wasm:0000026: error: br_table labels have inconsistent types: expected [f32], got [] + 0000026: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1306: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.6.wasm:0000023: error: type mismatch in br_table, expected [i64] but got [i32] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1317: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.7.wasm:000001f: error: type mismatch in br_table, expected [i32] but got [] + 000001f: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1323: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.8.wasm:000001e: error: type mismatch in br_table, expected [i32] but got [i64] + 000001e: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1329: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.9.wasm:0000021: error: type mismatch in br_table, expected [i32] but got [] + 0000021: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1335: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.10.wasm:0000023: error: type mismatch in br_table, expected [i32] but got [] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1341: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.11.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [... i64] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1350: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.12.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/br_table.wast:1357: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.13.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1369: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.14.wasm:0000024: error: type mismatch in br_table, expected [i32] but got [] + 0000024: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1381: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.15.wasm:000001c: error: type mismatch in br_table, expected [i32] but got [] + 000001c: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1392: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.16.wasm:000001e: error: type mismatch in br_table, expected [i32] but got [] + 000001e: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1404: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.17.wasm:0000025: error: br_table labels have inconsistent types: expected [i32], got [] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1416: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.18.wasm:0000025: error: br_table labels have inconsistent types: expected [], got [i32] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1430: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.19.wasm:000001f: error: invalid depth: 2 (max 1) + 000001f: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1436: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.20.wasm:0000021: error: invalid depth: 5 (max 2) + 0000021: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1442: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.21.wasm:0000024: error: invalid depth: 268435457 (max 1) + 0000024: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1449: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.22.wasm:000001f: error: invalid depth: 2 (max 1) + 000001f: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1455: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.23.wasm:0000021: error: invalid depth: 5 (max 2) + 0000021: error: OnBrTableExpr callback failed +out/test/spec/function-references/br_table.wast:1461: assert_invalid passed: + out/test/spec/function-references/br_table/br_table.24.wasm:0000024: error: invalid depth: 268435457 (max 1) + 0000024: error: OnBrTableExpr callback failed +186/186 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/call_ref.txt b/test/spec/function-references/call_ref.txt new file mode 100644 index 0000000000..b664ef249c --- /dev/null +++ b/test/spec/function-references/call_ref.txt @@ -0,0 +1,19 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/call_ref.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/call_ref.wast:97: assert_trap passed: null function reference +out/test/spec/function-references/call_ref.wast:136: assert_trap passed: unreachable executed +out/test/spec/function-references/call_ref.wast:149: assert_trap passed: unreachable executed +out/test/spec/function-references/call_ref.wast:165: assert_trap passed: unreachable executed +out/test/spec/function-references/call_ref.wast:168: assert_invalid passed: + out/test/spec/function-references/call_ref/call_ref.4.wasm:0000042: error: type mismatch in call, expected [i32] but got [i64] + 0000042: error: OnCallRefExpr callback failed +out/test/spec/function-references/call_ref.wast:184: assert_invalid passed: + out/test/spec/function-references/call_ref/call_ref.5.wasm:0000044: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000044: error: EndFunctionBody callback failed +out/test/spec/function-references/call_ref.wast:201: assert_invalid passed: + out/test/spec/function-references/call_ref/call_ref.6.wasm:000001f: error: type mismatch in call_ref, expected [(ref null 0)] but got [externref] + 000001f: error: OnCallRefExpr callback failed +34/34 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/func.txt b/test/spec/function-references/func.txt new file mode 100644 index 0000000000..0bdff35ff0 --- /dev/null +++ b/test/spec/function-references/func.txt @@ -0,0 +1,257 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/func.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/func.wast:436: assert_invalid passed: + out/test/spec/function-references/func/func.2.wasm:000001a: error: function type variable out of range: 2 (max 2) + 000001a: error: OnFunction callback failed +out/test/spec/function-references/func.wast:448: assert_malformed passed: + out/test/spec/function-references/func/func.3.wat:1:123: error: invalid func type index 2 + ...lt f64) (f64.const 1))(type $t (func (param i32)))(func (type 2) (param i32)) + ^^^^ +out/test/spec/function-references/func.wast:560: assert_malformed passed: + out/test/spec/function-references/func/func.6.wat:1:76: error: unexpected token "param", expected an instr. + ... i32) (result i32)))(func (type $sig) (result i32) (param i32) (i32.const 0)) + ^^^^^ +out/test/spec/function-references/func.wast:567: assert_malformed passed: + out/test/spec/function-references/func/func.7.wat:1:63: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (param i32) (type $sig) (result i32) (i32.const 0)) + ^^^^ +out/test/spec/function-references/func.wast:574: assert_malformed passed: + out/test/spec/function-references/func/func.8.wat:1:76: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (param i32) (result i32) (type $sig) (i32.const 0)) + ^^^^ +out/test/spec/function-references/func.wast:581: assert_malformed passed: + out/test/spec/function-references/func/func.9.wat:1:64: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (result i32) (type $sig) (param i32) (i32.const 0)) + ^^^^ +out/test/spec/function-references/func.wast:588: assert_malformed passed: + out/test/spec/function-references/func/func.10.wat:1:64: error: unexpected token "param", expected an instr. + ... i32) (result i32)))(func (result i32) (param i32) (type $sig) (i32.const 0)) + ^^^^^ + out/test/spec/function-references/func/func.10.wat:1:85: error: unexpected token ), expected (. + ... i32) (result i32)))(func (result i32) (param i32) (type $sig) (i32.const 0)) + ^ +out/test/spec/function-references/func.wast:595: assert_malformed passed: + out/test/spec/function-references/func/func.11.wat:1:21: error: unexpected token "param", expected an instr. + (func (result i32) (param i32) (i32.const 0)) + ^^^^^ +out/test/spec/function-references/func.wast:602: assert_malformed passed: + out/test/spec/function-references/func/func.12.wat:1:20: error: expected 0 results, got 1 + (type $sig (func))(func (type $sig) (result i32) (i32.const 0)) + ^^^^ +out/test/spec/function-references/func.wast:609: assert_malformed passed: + out/test/spec/function-references/func/func.13.wat:1:45: error: expected 1 arguments, got 0 + ...g (func (param i32) (result i32)))(func (type $sig) (result i32) (i32.cons... + ^^^^ +out/test/spec/function-references/func.wast:616: assert_malformed passed: + out/test/spec/function-references/func/func.14.wat:1:45: error: expected 1 results, got 0 + ...g (func (param i32) (result i32)))(func (type $sig) (param i32) (i32.const... + ^^^^ +out/test/spec/function-references/func.wast:623: assert_malformed passed: + out/test/spec/function-references/func/func.15.wat:1:49: error: expected 2 arguments, got 1 + ...unc (param i32 i32) (result i32)))(func (type $sig) (param i32) (result i3... + ^^^^ +out/test/spec/function-references/func.wast:631: assert_invalid passed: + out/test/spec/function-references/func/func.16.wasm:000000c: error: function type variable out of range: 4 (max 0) + 000000c: error: OnFunction callback failed +out/test/spec/function-references/func.wast:635: assert_invalid passed: + out/test/spec/function-references/func/func.17.wasm:0000013: error: function type variable out of range: 4 (max 1) + 0000013: error: OnFunction callback failed +out/test/spec/function-references/func.wast:647: assert_invalid passed: + out/test/spec/function-references/func/func.18.wasm:000001d: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:651: assert_invalid passed: + out/test/spec/function-references/func/func.19.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/func.wast:655: assert_invalid passed: + out/test/spec/function-references/func/func.20.wasm:000001e: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/function-references/func.wast:660: assert_invalid passed: + out/test/spec/function-references/func/func.21.wasm:000001c: error: uninitialized local reference + 000001c: error: OnLocalGetExpr callback failed +out/test/spec/function-references/func.wast:671: assert_invalid passed: + out/test/spec/function-references/func/func.22.wasm:000001c: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:675: assert_invalid passed: + out/test/spec/function-references/func/func.23.wasm:000001b: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001b: error: OnConvertExpr callback failed +out/test/spec/function-references/func.wast:679: assert_invalid passed: + out/test/spec/function-references/func/func.24.wasm:000001c: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001c: error: OnUnaryExpr callback failed +out/test/spec/function-references/func.wast:687: assert_invalid passed: + out/test/spec/function-references/func/func.25.wasm:0000019: error: type mismatch in implicit return, expected [i32] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:691: assert_invalid passed: + out/test/spec/function-references/func/func.26.wasm:0000019: error: type mismatch in implicit return, expected [i64] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:695: assert_invalid passed: + out/test/spec/function-references/func/func.27.wasm:0000019: error: type mismatch in implicit return, expected [f32] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:699: assert_invalid passed: + out/test/spec/function-references/func/func.28.wasm:0000019: error: type mismatch in implicit return, expected [f64] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:703: assert_invalid passed: + out/test/spec/function-references/func/func.29.wasm:000001a: error: type mismatch in implicit return, expected [f64, i32] but got [] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:708: assert_invalid passed: + out/test/spec/function-references/func/func.30.wasm:000001a: error: type mismatch in implicit return, expected [i32] but got [] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:714: assert_invalid passed: + out/test/spec/function-references/func/func.31.wasm:000001b: error: type mismatch in implicit return, expected [i32, i32] but got [] + 000001b: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:720: assert_invalid passed: + out/test/spec/function-references/func/func.32.wasm:000001a: error: type mismatch at end of function, expected [] but got [i32] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:726: assert_invalid passed: + out/test/spec/function-references/func/func.33.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32, i64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:732: assert_invalid passed: + out/test/spec/function-references/func/func.34.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [f32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:738: assert_invalid passed: + out/test/spec/function-references/func/func.35.wasm:000001f: error: type mismatch in implicit return, expected [f32, f32] but got [f32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:744: assert_invalid passed: + out/test/spec/function-references/func/func.36.wasm:0000023: error: type mismatch at end of function, expected [] but got [f32] + 0000023: error: EndFunctionBody callback failed +out/test/spec/function-references/func.wast:751: assert_invalid passed: + out/test/spec/function-references/func/func.37.wasm:0000019: error: type mismatch in return, expected [i32] but got [] + 0000019: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:757: assert_invalid passed: + out/test/spec/function-references/func/func.38.wasm:000001a: error: type mismatch in return, expected [i32, i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:763: assert_invalid passed: + out/test/spec/function-references/func/func.39.wasm:000001a: error: type mismatch in return, expected [i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:769: assert_invalid passed: + out/test/spec/function-references/func/func.40.wasm:000001b: error: type mismatch in return, expected [i32, i64] but got [] + 000001b: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:775: assert_invalid passed: + out/test/spec/function-references/func/func.41.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:781: assert_invalid passed: + out/test/spec/function-references/func/func.42.wasm:000001c: error: type mismatch in return, expected [i64, i64] but got [i64] + 000001c: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:788: assert_invalid passed: + out/test/spec/function-references/func/func.43.wasm:0000019: error: type mismatch in return, expected [i32] but got [] + 0000019: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:794: assert_invalid passed: + out/test/spec/function-references/func/func.44.wasm:000001a: error: type mismatch in return, expected [i32, i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:800: assert_invalid passed: + out/test/spec/function-references/func/func.45.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i32] + 000001c: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:806: assert_invalid passed: + out/test/spec/function-references/func/func.46.wasm:000001a: error: type mismatch in return, expected [i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:812: assert_invalid passed: + out/test/spec/function-references/func/func.47.wasm:000001b: error: type mismatch in return, expected [i32, i32] but got [] + 000001b: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:818: assert_invalid passed: + out/test/spec/function-references/func/func.48.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:824: assert_invalid passed: + out/test/spec/function-references/func/func.49.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i64] + 000001c: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:830: assert_invalid passed: + out/test/spec/function-references/func/func.50.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:836: assert_invalid passed: + out/test/spec/function-references/func/func.51.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i32] + 000001c: error: OnReturnExpr callback failed +out/test/spec/function-references/func.wast:843: assert_invalid passed: + out/test/spec/function-references/func/func.52.wasm:000001a: error: type mismatch in br, expected [i32] but got [] + 000001a: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:849: assert_invalid passed: + out/test/spec/function-references/func/func.53.wasm:000001b: error: type mismatch in br, expected [i32, i32] but got [] + 000001b: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:855: assert_invalid passed: + out/test/spec/function-references/func/func.54.wasm:000001f: error: type mismatch in br, expected [i32] but got [f32] + 000001f: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:861: assert_invalid passed: + out/test/spec/function-references/func/func.55.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001d: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:867: assert_invalid passed: + out/test/spec/function-references/func/func.56.wasm:000001a: error: type mismatch in br, expected [i32] but got [] + 000001a: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:873: assert_invalid passed: + out/test/spec/function-references/func/func.57.wasm:000001b: error: type mismatch in br, expected [i32, i32] but got [] + 000001b: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:879: assert_invalid passed: + out/test/spec/function-references/func/func.58.wasm:000001c: error: type mismatch in br, expected [i32] but got [i64] + 000001c: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:885: assert_invalid passed: + out/test/spec/function-references/func/func.59.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001d: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:891: assert_invalid passed: + out/test/spec/function-references/func/func.60.wasm:000001c: error: type mismatch in br, expected [i32] but got [i64] + 000001c: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:898: assert_invalid passed: + out/test/spec/function-references/func/func.61.wasm:000001c: error: type mismatch in br, expected [i32] but got [] + 000001c: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:904: assert_invalid passed: + out/test/spec/function-references/func/func.62.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [] + 000001d: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:910: assert_invalid passed: + out/test/spec/function-references/func/func.63.wasm:000001d: error: type mismatch in br, expected [i32] but got [] + 000001d: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:916: assert_invalid passed: + out/test/spec/function-references/func/func.64.wasm:000001e: error: type mismatch in br, expected [i32, i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:922: assert_invalid passed: + out/test/spec/function-references/func/func.65.wasm:000001e: error: type mismatch in br, expected [i32] but got [i64] + 000001e: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:928: assert_invalid passed: + out/test/spec/function-references/func/func.66.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001f: error: OnBrExpr callback failed +out/test/spec/function-references/func.wast:938: assert_malformed passed: + out/test/spec/function-references/func/func.67.wat:1:14: error: unexpected token "local", expected an instr. + (func (nop) (local i32)) + ^^^^^ +out/test/spec/function-references/func.wast:942: assert_malformed passed: + out/test/spec/function-references/func/func.68.wat:1:14: error: unexpected token "param", expected an instr. + (func (nop) (param i32)) + ^^^^^ +out/test/spec/function-references/func.wast:946: assert_malformed passed: + out/test/spec/function-references/func/func.69.wat:1:14: error: unexpected token "result", expected an instr. + (func (nop) (result i32)) + ^^^^^^ +out/test/spec/function-references/func.wast:950: assert_malformed passed: + out/test/spec/function-references/func/func.70.wat:1:20: error: unexpected token "param", expected an instr. + (func (local i32) (param i32)) + ^^^^^ +out/test/spec/function-references/func.wast:954: assert_malformed passed: + out/test/spec/function-references/func/func.71.wat:1:20: error: unexpected token "result", expected an instr. + (func (local i32) (result i32) (local.get 0)) + ^^^^^^ +out/test/spec/function-references/func.wast:958: assert_malformed passed: + out/test/spec/function-references/func/func.72.wat:1:21: error: unexpected token "param", expected an instr. + (func (result i32) (param i32) (local.get 0)) + ^^^^^ +out/test/spec/function-references/func.wast:965: assert_malformed passed: + out/test/spec/function-references/func/func.73.wat:1:13: error: redefinition of function "$foo" + (func $foo)(func $foo) + ^^^^ +out/test/spec/function-references/func.wast:969: assert_malformed passed: + out/test/spec/function-references/func/func.74.wat:1:28: error: redefinition of function "$foo" + (import "" "" (func $foo))(func $foo) + ^^^^ +out/test/spec/function-references/func.wast:973: assert_malformed passed: + out/test/spec/function-references/func/func.75.wat:1:28: error: redefinition of function "$foo" + (import "" "" (func $foo))(import "" "" (func $foo)) + ^^^^^^ +out/test/spec/function-references/func.wast:978: assert_malformed passed: + out/test/spec/function-references/func/func.76.wat:1:31: error: redefinition of parameter "$foo" + (func (param $foo i32) (param $foo i32)) + ^^^^ +out/test/spec/function-references/func.wast:982: assert_malformed passed: + out/test/spec/function-references/func/func.77.wat:1:31: error: redefinition of parameter "$foo" + (func (param $foo i32) (local $foo i32)) + ^^^^ +out/test/spec/function-references/func.wast:986: assert_malformed passed: + out/test/spec/function-references/func/func.78.wat:1:31: error: redefinition of local "$foo" + (func (local $foo i32) (local $foo i32)) + ^^^^ +175/175 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/global.txt b/test/spec/function-references/global.txt new file mode 100644 index 0000000000..2810e9015b --- /dev/null +++ b/test/spec/function-references/global.txt @@ -0,0 +1,141 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/global.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/global.wast:251: assert_trap passed: undefined table index +out/test/spec/function-references/global.wast:273: assert_invalid passed: + out/test/spec/function-references/global/global.1.wasm:0000029: error: can't global.set on immutable global at index 0. + 0000029: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:278: assert_invalid passed: + out/test/spec/function-references/global/global.2.wasm:0000035: error: can't global.set on immutable global at index 0. + 0000035: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:287: assert_invalid passed: + out/test/spec/function-references/global/global.5.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg + 0000013: error: OnUnaryExpr callback failed +out/test/spec/function-references/global.wast:292: assert_invalid passed: + out/test/spec/function-references/global/global.6.wasm:000000f: error: invalid initializer: instruction not valid in initializer expression: local.get + 000000f: error: OnLocalGetExpr callback failed +out/test/spec/function-references/global.wast:297: assert_invalid passed: + out/test/spec/function-references/global/global.7.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg + 0000013: error: OnUnaryExpr callback failed +out/test/spec/function-references/global.wast:302: assert_invalid passed: + out/test/spec/function-references/global/global.8.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: nop + 0000010: error: OnNopExpr callback failed +out/test/spec/function-references/global.wast:307: assert_invalid passed: + out/test/spec/function-references/global/global.9.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000010: error: OnUnaryExpr callback failed +out/test/spec/function-references/global.wast:312: assert_invalid passed: + out/test/spec/function-references/global/global.10.wasm:000000e: error: invalid initializer: instruction not valid in initializer expression: nop + 000000e: error: OnNopExpr callback failed +out/test/spec/function-references/global.wast:317: assert_invalid passed: + out/test/spec/function-references/global/global.11.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got [f32] + 0000013: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:322: assert_invalid passed: + out/test/spec/function-references/global/global.12.wasm:0000011: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000012: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:327: assert_invalid passed: + out/test/spec/function-references/global/global.13.wasm:000000d: error: type mismatch in initializer expression, expected [i32] but got [] + 000000e: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:332: assert_invalid passed: + out/test/spec/function-references/global/global.14.wasm:0000017: error: type mismatch in initializer expression, expected [funcref] but got [externref] + 0000018: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:337: assert_invalid passed: + out/test/spec/function-references/global/global.15.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000028: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:342: assert_invalid passed: + out/test/spec/function-references/global/global.16.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000028: error: EndGlobalInitExpr callback failed +out/test/spec/function-references/global.wast:347: assert_invalid passed: + out/test/spec/function-references/global/global.17.wasm:000000f: error: initializer expression can only reference an imported global + 000000f: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:352: assert_invalid passed: + out/test/spec/function-references/global/global.18.wasm:000000f: error: global variable out of range: 1 (max 1) + 000000f: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:357: assert_invalid passed: + out/test/spec/function-references/global/global.19.wasm:0000025: error: global variable out of range: 2 (max 2) + 0000025: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:362: assert_invalid passed: + out/test/spec/function-references/global/global.20.wasm:0000029: error: initializer expression cannot reference a mutable global + 0000029: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:370: assert_malformed passed: + 0000026: error: global mutability must be 0 or 1 +out/test/spec/function-references/global.wast:383: assert_malformed passed: + 0000026: error: global mutability must be 0 or 1 +out/test/spec/function-references/global.wast:400: assert_malformed passed: + 0000011: error: global mutability must be 0 or 1 +out/test/spec/function-references/global.wast:412: assert_malformed passed: + 0000011: error: global mutability must be 0 or 1 +out/test/spec/function-references/global.wast:426: assert_invalid passed: + out/test/spec/function-references/global/global.27.wasm:000001a: error: global variable out of range: 0 (max 0) + 000001a: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:431: assert_invalid passed: + out/test/spec/function-references/global/global.28.wasm:0000022: error: global variable out of range: 1 (max 1) + 0000022: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:439: assert_invalid passed: + out/test/spec/function-references/global/global.29.wasm:0000034: error: global variable out of range: 1 (max 1) + 0000034: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:447: assert_invalid passed: + out/test/spec/function-references/global/global.30.wasm:000003c: error: global variable out of range: 2 (max 2) + 000003c: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/global.wast:457: assert_invalid passed: + out/test/spec/function-references/global/global.31.wasm:000001b: error: global variable out of range: 0 (max 0) + 000001b: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:462: assert_invalid passed: + out/test/spec/function-references/global/global.32.wasm:0000023: error: global variable out of range: 1 (max 1) + 0000023: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:470: assert_invalid passed: + out/test/spec/function-references/global/global.33.wasm:0000035: error: global variable out of range: 1 (max 1) + 0000035: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:478: assert_invalid passed: + out/test/spec/function-references/global/global.34.wasm:000003d: error: global variable out of range: 2 (max 2) + 000003d: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:488: assert_invalid passed: + out/test/spec/function-references/global/global.35.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:497: assert_invalid passed: + out/test/spec/function-references/global/global.36.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:507: assert_invalid passed: + out/test/spec/function-references/global/global.37.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:517: assert_invalid passed: + out/test/spec/function-references/global/global.38.wasm:0000027: error: type mismatch in global.set, expected [i32] but got [] + 0000027: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:527: assert_invalid passed: + out/test/spec/function-references/global/global.39.wasm:000002a: error: type mismatch in global.set, expected [i32] but got [] + 000002a: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:537: assert_invalid passed: + out/test/spec/function-references/global/global.40.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:547: assert_invalid passed: + out/test/spec/function-references/global/global.41.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:557: assert_invalid passed: + out/test/spec/function-references/global/global.42.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:567: assert_invalid passed: + out/test/spec/function-references/global/global.43.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:576: assert_invalid passed: + out/test/spec/function-references/global/global.44.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:585: assert_invalid passed: + out/test/spec/function-references/global/global.45.wasm:0000027: error: type mismatch in global.set, expected [i32] but got [] + 0000027: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:595: assert_invalid passed: + out/test/spec/function-references/global/global.46.wasm:000003e: error: type mismatch in global.set, expected [i32] but got [] + 000003e: error: OnGlobalSetExpr callback failed +out/test/spec/function-references/global.wast:613: assert_malformed passed: + out/test/spec/function-references/global/global.47.wat:1:33: error: redefinition of global "$foo" + (global $foo i32 (i32.const 0))(global $foo i32 (i32.const 0)) + ^^^^^^ +out/test/spec/function-references/global.wast:617: assert_malformed passed: + out/test/spec/function-references/global/global.48.wat:1:34: error: redefinition of global "$foo" + (import "" "" (global $foo i32))(global $foo i32 (i32.const 0)) + ^^^^^^ +out/test/spec/function-references/global.wast:621: assert_malformed passed: + out/test/spec/function-references/global/global.49.wat:1:34: error: redefinition of global "$foo" + (import "" "" (global $foo i32))(import "" "" (global $foo i32)) + ^^^^^^ +108/108 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/local_init.txt b/test/spec/function-references/local_init.txt new file mode 100644 index 0000000000..3c9cdc720d --- /dev/null +++ b/test/spec/function-references/local_init.txt @@ -0,0 +1,18 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/local_init.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/local_init.wast:26: assert_invalid passed: + out/test/spec/function-references/local_init/local_init.1.wasm:000001c: error: uninitialized local reference + 000001c: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_init.wast:30: assert_invalid passed: + out/test/spec/function-references/local_init/local_init.2.wasm:000002a: error: uninitialized local reference + 000002a: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_init.wast:40: assert_invalid passed: + out/test/spec/function-references/local_init/local_init.3.wasm:0000027: error: uninitialized local reference + 0000027: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_init.wast:53: assert_invalid passed: + out/test/spec/function-references/local_init/local_init.4.wasm:000002c: error: uninitialized local reference + 000002c: error: OnLocalGetExpr callback failed +10/10 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/ref.txt b/test/spec/function-references/ref.txt new file mode 100644 index 0000000000..e178a7799a --- /dev/null +++ b/test/spec/function-references/ref.txt @@ -0,0 +1,43 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/ref.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/ref.wast:28: assert_invalid passed: + out/test/spec/function-references/ref/ref.1.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +out/test/spec/function-references/ref.wast:32: assert_invalid passed: + out/test/spec/function-references/ref/ref.2.wasm:0000010: error: reference 1 is out of range in results + 0000010: error: OnFuncType callback failed +out/test/spec/function-references/ref.wast:37: assert_invalid passed: + out/test/spec/function-references/ref/ref.3.wasm:000000e: error: reference 1 is out of range in globals + 000000e: error: BeginGlobal callback failed +out/test/spec/function-references/ref.wast:42: assert_invalid passed: + out/test/spec/function-references/ref/ref.4.wasm:000000f: error: reference 1 is out of range in tables + 000000f: error: OnTable callback failed +out/test/spec/function-references/ref.wast:47: assert_invalid passed: + out/test/spec/function-references/ref/ref.5.wasm:000000e: error: reference 1 is out of range + 000000e: error: OnElemSegmentElemType callback failed +out/test/spec/function-references/ref.wast:52: assert_invalid passed: + out/test/spec/function-references/ref/ref.6.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +out/test/spec/function-references/ref.wast:56: assert_invalid passed: + out/test/spec/function-references/ref/ref.7.wasm:0000010: error: reference 1 is out of range in results + 0000010: error: OnFuncType callback failed +out/test/spec/function-references/ref.wast:60: assert_invalid passed: + out/test/spec/function-references/ref/ref.8.wasm:000001a: error: reference 1 is out of range in locals + 000001a: error: OnLocalDecl callback failed +out/test/spec/function-references/ref.wast:65: assert_invalid passed: + out/test/spec/function-references/ref/ref.9.wasm:000001a: error: reference 1 is out of range + 000001a: error: OnBlockExpr callback failed +out/test/spec/function-references/ref.wast:69: assert_invalid passed: + out/test/spec/function-references/ref/ref.10.wasm:000001a: error: reference 1 is out of range + 000001a: error: OnLoopExpr callback failed +out/test/spec/function-references/ref.wast:73: assert_invalid passed: + out/test/spec/function-references/ref/ref.11.wasm:000001a: error: reference 1 is out of range + out/test/spec/function-references/ref/ref.11.wasm:000001a: error: type mismatch in if, expected [i32] but got [] + 000001a: error: OnIfExpr callback failed +out/test/spec/function-references/ref.wast:78: assert_invalid passed: + out/test/spec/function-references/ref/ref.12.wasm:000001c: error: reference 1 is out of range + 000001c: error: OnSelectExpr callback failed +13/13 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/type-equivalence.txt b/test/spec/function-references/type-equivalence.txt new file mode 100644 index 0000000000..2a704cabdc --- /dev/null +++ b/test/spec/function-references/type-equivalence.txt @@ -0,0 +1,12 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/type-equivalence.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/type-equivalence.wast:31: assert_invalid passed: + out/test/spec/function-references/type-equivalence/type-equivalence.2.wasm:0000010: error: reference 0 is out of range in results + 0000010: error: OnFuncType callback failed +out/test/spec/function-references/type-equivalence.wast:38: assert_invalid passed: + out/test/spec/function-references/type-equivalence/type-equivalence.3.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +12/12 tests passed. +;;; STDOUT ;;) diff --git a/test/typecheck/bad-callref-empty.txt b/test/typecheck/bad-callref-empty.txt index cee3885352..e97e08783b 100644 --- a/test/typecheck/bad-callref-empty.txt +++ b/test/typecheck/bad-callref-empty.txt @@ -2,13 +2,15 @@ ;;; ARGS: --enable-function-references ;;; ERROR: 1 (module + (type (func)) + (func (export "main") - (call_ref + (call_ref 0 ) ) ) (;; STDERR ;;; -out/test/typecheck/bad-callref-empty.txt:6:6: error: type mismatch in call_ref, expected [reference] but got [] - (call_ref +out/test/typecheck/bad-callref-empty.txt:8:6: error: type mismatch in call_ref, expected [(ref null 0)] but got [] + (call_ref 0 ^^^^^^^^ ;;; STDERR ;;) diff --git a/test/typecheck/bad-callref-int32.txt b/test/typecheck/bad-callref-int32.txt index 95401b9504..f598dbd8f0 100644 --- a/test/typecheck/bad-callref-int32.txt +++ b/test/typecheck/bad-callref-int32.txt @@ -2,14 +2,16 @@ ;;; ARGS: --enable-function-references ;;; ERROR: 1 (module + (type $t (func)) + (func (export "main") (result i32) - (call_ref (i32.const 10) - (i32.const 13) + (call_ref $t (i32.const 10) + (i32.const 13) ) ) ) (;; STDERR ;;; -out/test/typecheck/bad-callref-int32.txt:6:6: error: type mismatch in call_ref, expected [reference] but got [... i32] - (call_ref (i32.const 10) +out/test/typecheck/bad-callref-int32.txt:8:6: error: type mismatch in call_ref, expected [(ref null 0)] but got [... i32] + (call_ref $t (i32.const 10) ^^^^^^^^ ;;; STDERR ;;) diff --git a/test/typecheck/bad-callref-nosubtype.txt b/test/typecheck/bad-callref-nosubtype.txt new file mode 100644 index 0000000000..3d6ec7325e --- /dev/null +++ b/test/typecheck/bad-callref-nosubtype.txt @@ -0,0 +1,18 @@ +;;; TOOL: wat2wasm +;;; ARGS: --enable-function-references +;;; ERROR: 1 +(module + (func (export "main") (param (ref $t1)) + (call_ref $t2 (i64.const 10) + (local.get 0) + ) + ) + + (type $t1 (func (param i32))) + (type $t2 (func (param i64))) +) +(;; STDERR ;;; +out/test/typecheck/bad-callref-nosubtype.txt:6:6: error: type mismatch in call_ref, expected [(ref null 1)] but got [... (ref 0)] + (call_ref $t2 (i64.const 10) + ^^^^^^^^ +;;; STDERR ;;) diff --git a/test/typecheck/bad-callref-null.txt b/test/typecheck/bad-callref-null.txt index 6771a89367..314dff8b6d 100644 --- a/test/typecheck/bad-callref-null.txt +++ b/test/typecheck/bad-callref-null.txt @@ -3,13 +3,15 @@ ;;; ERROR: 1 (module (func (export "main") (result i32) - (call_ref (i32.const 10) - (ref.null func) + (call_ref $t (i32.const 10) + (ref.null func) ) ) + + (type $t (func)) ) (;; STDERR ;;; -out/test/typecheck/bad-callref-null.txt:6:6: error: type mismatch in call_ref, expected [reference] but got [... funcref] - (call_ref (i32.const 10) +out/test/typecheck/bad-callref-null.txt:6:6: error: type mismatch in call_ref, expected [(ref null 0)] but got [... funcref] + (call_ref $t (i32.const 10) ^^^^^^^^ ;;; STDERR ;;) From 073a9d80a4a90210310590e96bcc42398b53247f Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 17 Mar 2025 11:23:38 +0000 Subject: [PATCH 2/6] Implement return_call_ref, ref.as_non_null, br_on_[non_]null instructions --- include/wabt/binary-reader-logging.h | 4 + include/wabt/binary-reader-nop.h | 4 + include/wabt/binary-reader.h | 4 + include/wabt/expr-visitor.h | 8 + include/wabt/ir.h | 15 + include/wabt/opcode.def | 4 + include/wabt/shared-validator.h | 4 + include/wabt/token.def | 4 + include/wabt/type-checker.h | 5 + src/apply-names.cc | 14 + src/binary-reader-ir.cc | 24 + src/binary-reader-logging.cc | 12 + src/binary-reader.cc | 31 + src/binary-writer.cc | 38 +- src/c-writer.cc | 20 + src/expr-visitor.cc | 17 + src/interp/binary-reader-interp.cc | 64 +- src/interp/interp.cc | 33 +- src/interp/istream.cc | 6 +- src/ir-util.cc | 16 + src/ir.cc | 4 + src/lexer-keywords.txt | 4 + src/opcode.cc | 4 + src/prebuilt/lexer-keywords.cc | 1194 +++++++++-------- src/resolve-names.cc | 18 + src/shared-validator.cc | 28 + src/type-checker.cc | 72 + src/validator.cc | 24 + src/wast-parser.cc | 28 + src/wat-writer.cc | 30 + .../function-references/br_on_non_null.txt | 7 + test/spec/function-references/br_on_null.txt | 7 + .../function-references/ref_as_non_null.txt | 11 + .../function-references/return_call_ref.txt | 42 + 34 files changed, 1188 insertions(+), 612 deletions(-) create mode 100644 test/spec/function-references/br_on_non_null.txt create mode 100644 test/spec/function-references/br_on_null.txt create mode 100644 test/spec/function-references/ref_as_non_null.txt create mode 100644 test/spec/function-references/return_call_ref.txt diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 12fdaa1c72..bd7ff33fe1 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -174,6 +174,8 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnNonNullExpr(Index depth) override; + Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) override; @@ -218,12 +220,14 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnTableGrowExpr(Index table) override; Result OnTableSizeExpr(Index table) override; Result OnTableFillExpr(Index table) override; + Result OnRefAsNonNullExpr() override; Result OnRefFuncExpr(Index index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; Result OnNopExpr() override; Result OnRethrowExpr(Index depth) override; Result OnReturnCallExpr(Index func_index) override; + Result OnReturnCallRefExpr(Type sig_type) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; Result OnReturnExpr() override; Result OnSelectExpr(Index result_count, Type* result_types) override; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index d10691fbbc..545db127b2 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -241,6 +241,8 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnBlockExpr(Type sig_type) override { return Result::Ok; } Result OnBrExpr(Index depth) override { return Result::Ok; } Result OnBrIfExpr(Index depth) override { return Result::Ok; } + Result OnBrOnNonNullExpr(Index depth) override { return Result::Ok; } + Result OnBrOnNullExpr(Index depth) override { return Result::Ok; } Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) override { @@ -299,6 +301,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnTableGrowExpr(Index table_index) override { return Result::Ok; } Result OnTableSizeExpr(Index table_index) override { return Result::Ok; } Result OnTableFillExpr(Index table_index) override { return Result::Ok; } + Result OnRefAsNonNullExpr() override { return Result::Ok; } Result OnRefFuncExpr(Index func_index) override { return Result::Ok; } Result OnRefNullExpr(Type type) override { return Result::Ok; } Result OnRefIsNullExpr() override { return Result::Ok; } @@ -308,6 +311,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; } + Result OnReturnCallRefExpr(Type sig_type) override { return Result::Ok; } Result OnReturnExpr() override { return Result::Ok; } Result OnSelectExpr(Index result_count, Type* result_types) override { return Result::Ok; diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index d7135141b9..96455f2251 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -250,6 +250,8 @@ class BinaryReaderDelegate { virtual Result OnBlockExpr(Type sig_type) = 0; virtual Result OnBrExpr(Index depth) = 0; virtual Result OnBrIfExpr(Index depth) = 0; + virtual Result OnBrOnNonNullExpr(Index depth) = 0; + virtual Result OnBrOnNullExpr(Index depth) = 0; virtual Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) = 0; @@ -294,6 +296,7 @@ class BinaryReaderDelegate { virtual Result OnTableGrowExpr(Index table_index) = 0; virtual Result OnTableSizeExpr(Index table_index) = 0; virtual Result OnTableFillExpr(Index table_index) = 0; + virtual Result OnRefAsNonNullExpr() = 0; virtual Result OnRefFuncExpr(Index func_index) = 0; virtual Result OnRefNullExpr(Type type) = 0; virtual Result OnRefIsNullExpr() = 0; @@ -303,6 +306,7 @@ class BinaryReaderDelegate { virtual Result OnReturnCallExpr(Index func_index) = 0; virtual Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) = 0; + virtual Result OnReturnCallRefExpr(Type sig_type) = 0; virtual Result OnSelectExpr(Index result_count, Type* result_types) = 0; virtual Result OnStoreExpr(Opcode opcode, Index memidx, diff --git a/include/wabt/expr-visitor.h b/include/wabt/expr-visitor.h index 5be7879391..cef8025baa 100644 --- a/include/wabt/expr-visitor.h +++ b/include/wabt/expr-visitor.h @@ -73,6 +73,8 @@ class ExprVisitor::Delegate { virtual Result EndBlockExpr(BlockExpr*) = 0; virtual Result OnBrExpr(BrExpr*) = 0; virtual Result OnBrIfExpr(BrIfExpr*) = 0; + virtual Result OnBrOnNonNullExpr(BrOnNonNullExpr*) = 0; + virtual Result OnBrOnNullExpr(BrOnNullExpr*) = 0; virtual Result OnBrTableExpr(BrTableExpr*) = 0; virtual Result BeginTryTableExpr(TryTableExpr*) = 0; virtual Result EndTryTableExpr(TryTableExpr*) = 0; @@ -109,6 +111,7 @@ class ExprVisitor::Delegate { virtual Result OnTableGrowExpr(TableGrowExpr*) = 0; virtual Result OnTableSizeExpr(TableSizeExpr*) = 0; virtual Result OnTableFillExpr(TableFillExpr*) = 0; + virtual Result OnRefAsNonNullExpr(RefAsNonNullExpr*) = 0; virtual Result OnRefFuncExpr(RefFuncExpr*) = 0; virtual Result OnRefNullExpr(RefNullExpr*) = 0; virtual Result OnRefIsNullExpr(RefIsNullExpr*) = 0; @@ -116,6 +119,7 @@ class ExprVisitor::Delegate { virtual Result OnReturnExpr(ReturnExpr*) = 0; virtual Result OnReturnCallExpr(ReturnCallExpr*) = 0; virtual Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) = 0; + virtual Result OnReturnCallRefExpr(ReturnCallRefExpr*) = 0; virtual Result OnSelectExpr(SelectExpr*) = 0; virtual Result OnStoreExpr(StoreExpr*) = 0; virtual Result OnUnaryExpr(UnaryExpr*) = 0; @@ -150,6 +154,8 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override { return Result::Ok; } Result OnBrExpr(BrExpr*) override { return Result::Ok; } Result OnBrIfExpr(BrIfExpr*) override { return Result::Ok; } + Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override { return Result::Ok; }; + Result OnBrOnNullExpr(BrOnNullExpr*) override { return Result::Ok; }; Result OnBrTableExpr(BrTableExpr*) override { return Result::Ok; } Result BeginTryTableExpr(TryTableExpr*) override { return Result::Ok; } Result EndTryTableExpr(TryTableExpr*) override { return Result::Ok; } @@ -186,6 +192,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result OnTableGrowExpr(TableGrowExpr*) override { return Result::Ok; } Result OnTableSizeExpr(TableSizeExpr*) override { return Result::Ok; } Result OnTableFillExpr(TableFillExpr*) override { return Result::Ok; } + Result OnRefAsNonNullExpr(RefAsNonNullExpr*) override { return Result::Ok; } Result OnRefFuncExpr(RefFuncExpr*) override { return Result::Ok; } Result OnRefNullExpr(RefNullExpr*) override { return Result::Ok; } Result OnRefIsNullExpr(RefIsNullExpr*) override { return Result::Ok; } @@ -195,6 +202,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override { return Result::Ok; } + Result OnReturnCallRefExpr(ReturnCallRefExpr*) override { return Result::Ok; } Result OnSelectExpr(SelectExpr*) override { return Result::Ok; } Result OnStoreExpr(StoreExpr*) override { return Result::Ok; } Result OnUnaryExpr(UnaryExpr*) override { return Result::Ok; } diff --git a/include/wabt/ir.h b/include/wabt/ir.h index 2f4a245216..9102297dc8 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -394,6 +394,8 @@ enum class ExprType { Block, Br, BrIf, + BrOnNonNull, + BrOnNull, BrTable, Call, CallIndirect, @@ -418,6 +420,7 @@ enum class ExprType { MemoryInit, MemorySize, Nop, + RefAsNonNull, RefIsNull, RefFunc, RefNull, @@ -425,6 +428,7 @@ enum class ExprType { Return, ReturnCall, ReturnCallIndirect, + ReturnCallRef, Select, SimdLaneOp, SimdLoadLane, @@ -588,6 +592,7 @@ using CompareExpr = OpcodeExpr; using ConvertExpr = OpcodeExpr; using UnaryExpr = OpcodeExpr; using TernaryExpr = OpcodeExpr; +using RefAsNonNullExpr = OpcodeExpr; class SimdLaneOpExpr : public ExprMixin { public: @@ -667,6 +672,8 @@ class MemoryVarExpr : public MemoryExpr { using BrExpr = VarExpr; using BrIfExpr = VarExpr; +using BrOnNonNullExpr = VarExpr; +using BrOnNullExpr = VarExpr; using CallExpr = VarExpr; using RefFuncExpr = VarExpr; using GlobalGetExpr = VarExpr; @@ -758,6 +765,14 @@ class CallRefExpr : public ExprMixin { Var sig_type; }; +class ReturnCallRefExpr : public ExprMixin { + public: + explicit ReturnCallRefExpr(const Location& loc = Location()) + : ExprMixin(loc) {} + + Var sig_type; +}; + template class BlockExprBase : public ExprMixin { public: diff --git a/include/wabt/opcode.def b/include/wabt/opcode.def index 4218a30b80..901c0359a8 100644 --- a/include/wabt/opcode.def +++ b/include/wabt/opcode.def @@ -56,6 +56,7 @@ WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x11, CallIndirect, "call_indirect WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x12, ReturnCall, "return_call", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x13, ReturnCallIndirect, "return_call_indirect", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x14, CallRef, "call_ref", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x15, ReturnCallRef, "return_call_ref", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x18, Delegate, "delegate", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x19, CatchAll, "catch_all", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x1a, Drop, "drop", "") @@ -267,6 +268,9 @@ WABT_OPCODE(___, I32, ___, I32, 0, 0xfc, 0x11, TableFill, "table.fill", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd0, RefNull, "ref.null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd1, RefIsNull, "ref.is_null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd2, RefFunc, "ref.func", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd4, RefAsNonNull, "ref.as_non_null", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd5, BrOnNull, "br_on_null", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd6, BrOnNonNull, "br_on_non_null", "") /* Simd opcodes */ WABT_OPCODE(V128, I32, ___, ___, 16, 0xfd, 0x00, V128Load, "v128.load", "") diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index 8478f7da53..d568aac805 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -136,6 +136,8 @@ class SharedValidator { Result OnBlock(const Location&, Type sig_type); Result OnBr(const Location&, Var depth); Result OnBrIf(const Location&, Var depth); + Result OnBrOnNonNull(const Location&, Var depth); + Result OnBrOnNull(const Location&, Var depth); Result BeginBrTable(const Location&); Result OnBrTableTarget(const Location&, Var depth); Result EndBrTable(const Location&); @@ -176,12 +178,14 @@ class SharedValidator { Result OnMemoryInit(const Location&, Var segment_var, Var memidx); Result OnMemorySize(const Location&, Var memidx); Result OnNop(const Location&); + Result OnRefAsNonNull(const Location&); Result OnRefFunc(const Location&, Var func_var); Result OnRefIsNull(const Location&); Result OnRefNull(const Location&, Var func_type_var); Result OnRethrow(const Location&, Var depth); Result OnReturnCall(const Location&, Var func_var); Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var); + Result OnReturnCallRef(const Location&, Var function_type_var); Result OnReturn(const Location&); Result OnSelect(const Location&, Index result_count, Type* result_types); Result OnSimdLaneOp(const Location&, Opcode, uint64_t lane_idx); diff --git a/include/wabt/token.def b/include/wabt/token.def index 85b36cd988..22b333cb73 100644 --- a/include/wabt/token.def +++ b/include/wabt/token.def @@ -99,11 +99,14 @@ WABT_TOKEN(Binary, "BINARY") WABT_TOKEN(Block, "block") WABT_TOKEN(Br, "br") WABT_TOKEN(BrIf, "br_if") +WABT_TOKEN(BrOnNonNull, "br_on_non_null") +WABT_TOKEN(BrOnNull, "br_on_null") WABT_TOKEN(BrTable, "br_table") WABT_TOKEN(Code, "code") WABT_TOKEN(Call, "call") WABT_TOKEN(CallIndirect, "call_indirect") WABT_TOKEN(CallRef, "call_ref") +WABT_TOKEN(ReturnCallRef, "return_call_ref") WABT_TOKEN(Catch, "catch") WABT_TOKEN(CatchAll, "catch_all") WABT_TOKEN(CatchRef, "catch_ref") @@ -130,6 +133,7 @@ WABT_TOKEN(MemoryGrow, "memory.grow") WABT_TOKEN(MemoryInit, "memory.init") WABT_TOKEN(MemorySize, "memory.size") WABT_TOKEN(Nop, "nop") +WABT_TOKEN(RefAsNonNull, "ref.as_non_null") WABT_TOKEN(RefExtern, "ref.extern") WABT_TOKEN(RefFunc, "ref.func") WABT_TOKEN(RefIsNull, "ref.is_null") diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h index e2c315e746..3600212a83 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -88,6 +88,8 @@ class TypeChecker { Result OnBlock(const TypeVector& param_types, const TypeVector& result_types); Result OnBr(Index depth); Result OnBrIf(Index depth); + Result OnBrOnNonNull(Index depth); + Result OnBrOnNull(Index depth); Result BeginBrTable(); Result OnBrTableTarget(Index depth); Result EndBrTable(); @@ -100,6 +102,7 @@ class TypeChecker { const TypeVector& result_types); Result OnReturnCallIndirect(const TypeVector& param_types, const TypeVector& result_types); + Result OnReturnCallRef(Type); Result OnCatch(const TypeVector& sig); Result OnCompare(Opcode); Result OnConst(Type); @@ -131,6 +134,7 @@ class TypeChecker { Result OnTableSize(const Limits& limits); Result OnTableFill(Type elem_type, const Limits& limits); Result OnRefFuncExpr(Index func_type); + Result OnRefAsNonNullExpr(); Result OnRefNullExpr(Type type); Result OnRefIsNullExpr(); Result OnRethrow(Index depth); @@ -193,6 +197,7 @@ class TypeChecker { Type expected2, Type expected3, const char* desc); + Result PopAndCheckReference(Type* actual, const char* desc); Result CheckOpcode1(Opcode opcode, const Limits* limits = nullptr); Result CheckOpcode2(Opcode opcode, const Limits* limits = nullptr); Result CheckOpcode3(Opcode opcode, diff --git a/src/apply-names.cc b/src/apply-names.cc index c8516c8cd9..3d25749ccd 100644 --- a/src/apply-names.cc +++ b/src/apply-names.cc @@ -40,6 +40,8 @@ class NameApplier : public ExprVisitor::DelegateNop { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; + Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; Result OnCallExpr(CallExpr*) override; Result OnRefFuncExpr(RefFuncExpr*) override; @@ -350,6 +352,18 @@ Result NameApplier::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result NameApplier::OnBrOnNonNullExpr(BrOnNonNullExpr* expr) { + std::string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); + return Result::Ok; +} + +Result NameApplier::OnBrOnNullExpr(BrOnNullExpr* expr) { + std::string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); + return Result::Ok; +} + Result NameApplier::OnBrTableExpr(BrTableExpr* expr) { for (Var& target : expr->targets) { std::string_view label = FindLabelByVar(&target); diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index d5f0fab262..855c8a8c16 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -200,6 +200,8 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnNonNullExpr(Index depth) override; + Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) override; @@ -210,6 +212,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnCallRefExpr(Type sig_type) override; Result OnReturnCallExpr(Index func_index) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; + Result OnReturnCallRefExpr(Type sig_type) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; Result OnDelegateExpr(Index depth) override; @@ -246,6 +249,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnTableGrowExpr(Index table_index) override; Result OnTableSizeExpr(Index table_index) override; Result OnTableFillExpr(Index table_index) override; + Result OnRefAsNonNullExpr() override; Result OnRefFuncExpr(Index func_index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; @@ -897,6 +901,15 @@ Result BinaryReaderIR::OnBrIfExpr(Index depth) { return AppendExpr(std::make_unique(Var(depth, GetLocation()))); } +Result BinaryReaderIR::OnBrOnNonNullExpr(Index depth) { + return AppendExpr( + std::make_unique(Var(depth, GetLocation()))); +} + +Result BinaryReaderIR::OnBrOnNullExpr(Index depth) { + return AppendExpr(std::make_unique(Var(depth, GetLocation()))); +} + Result BinaryReaderIR::OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) { @@ -953,6 +966,12 @@ Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index, return AppendExpr(std::move(expr)); } +Result BinaryReaderIR::OnReturnCallRefExpr(Type sig_type) { + auto expr = std::make_unique(); + expr->sig_type = Var(sig_type, GetLocation()); + return AppendExpr(std::move(expr)); +} + Result BinaryReaderIR::OnCompareExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } @@ -1147,6 +1166,11 @@ Result BinaryReaderIR::OnTableFillExpr(Index table_index) { std::make_unique(Var(table_index, GetLocation()))); } +Result BinaryReaderIR::OnRefAsNonNullExpr() { + return AppendExpr( + std::make_unique(Opcode::RefAsNonNull, GetLocation())); +} + Result BinaryReaderIR::OnRefFuncExpr(Index func_index) { module_->used_func_refs.insert(func_index); return AppendExpr( diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 19dc335cb3..89690ca533 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -320,6 +320,16 @@ Result BinaryReaderLogging::OnBrIfExpr(Index depth) { return reader_->OnBrIfExpr(depth); } +Result BinaryReaderLogging::OnBrOnNonNullExpr(Index depth) { + LOGF("OnBrOnNonNullExpr(depth: %" PRIindex ")\n", depth); + return reader_->OnBrOnNonNullExpr(depth); +} + +Result BinaryReaderLogging::OnBrOnNullExpr(Index depth) { + LOGF("OnBrOnNullExpr(depth: %" PRIindex ")\n", depth); + return reader_->OnBrOnNullExpr(depth); +} + Result BinaryReaderLogging::OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) { @@ -871,6 +881,7 @@ DEFINE_INDEX(OnTableGetExpr) DEFINE_INDEX(OnTableGrowExpr) DEFINE_INDEX(OnTableSizeExpr) DEFINE_INDEX_DESC(OnTableFillExpr, "table index") +DEFINE0(OnRefAsNonNullExpr) DEFINE_INDEX(OnRefFuncExpr) DEFINE_TYPE(OnRefNullExpr) DEFINE0(OnRefIsNullExpr) @@ -879,6 +890,7 @@ DEFINE_INDEX_DESC(OnRethrowExpr, "depth"); DEFINE_INDEX_DESC(OnReturnCallExpr, "func_index") DEFINE_INDEX_INDEX(OnReturnCallIndirectExpr, "sig_index", "table_index") +DEFINE_TYPE(OnReturnCallRefExpr) DEFINE0(OnReturnExpr) DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr); DEFINE_LOAD_STORE_OPCODE(OnLoadZeroExpr); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index d1f064a3e8..fdb271c290 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -840,6 +840,22 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { break; } + case Opcode::BrOnNonNull: { + Index depth; + CHECK_RESULT(ReadIndex(&depth, "br_on_non_null depth")); + CALLBACK(OnBrOnNonNullExpr, depth); + CALLBACK(OnOpcodeIndex, depth); + break; + } + + case Opcode::BrOnNull: { + Index depth; + CHECK_RESULT(ReadIndex(&depth, "br_on_null depth")); + CALLBACK(OnBrOnNullExpr, depth); + CALLBACK(OnOpcodeIndex, depth); + break; + } + case Opcode::BrTable: { Index num_targets; CHECK_RESULT(ReadCount(&num_targets, "br_table target count")); @@ -1927,6 +1943,11 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { break; } + case Opcode::RefAsNonNull: + CALLBACK(OnRefAsNonNullExpr); + CALLBACK(OnOpcodeBare); + break; + case Opcode::RefFunc: { Index func; CHECK_RESULT(ReadIndex(&func, "func index")); @@ -1973,6 +1994,16 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { break; } + case Opcode::ReturnCallRef: { + uint32_t type; + CHECK_RESULT(ReadU32Leb128(&type, "return_call_ref type")); + + Type sig_type(Type::RefNull, type); + CALLBACK(OnReturnCallRefExpr, sig_type); + CALLBACK(OnOpcodeType, sig_type); + break; + } + default: return ReportUnexpectedOpcode(opcode); } diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 877493b66e..68b1ba9d31 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -762,6 +762,17 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteU32Leb128(stream_, GetLabelVarDepth(&cast(expr)->var), "break depth"); break; + case ExprType::BrOnNonNull: + WriteOpcode(stream_, Opcode::BrOnNonNull); + WriteU32Leb128(stream_, + GetLabelVarDepth(&cast(expr)->var), + "break depth"); + break; + case ExprType::BrOnNull: + WriteOpcode(stream_, Opcode::BrOnNull); + WriteU32Leb128(stream_, GetLabelVarDepth(&cast(expr)->var), + "break depth"); + break; case ExprType::BrTable: { auto* br_table_expr = cast(expr); WriteOpcode(stream_, Opcode::BrTable); @@ -798,6 +809,17 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteTableNumberWithReloc(table_index, "table index"); break; } + case ExprType::ReturnCallIndirect: { + Index sig_index = + module_->GetFuncTypeIndex(cast(expr)->decl); + Index table_index = + module_->GetTableIndex(cast(expr)->table); + WriteOpcode(stream_, Opcode::ReturnCallIndirect); + WriteU32Leb128WithReloc(sig_index, "signature index", + RelocType::TypeIndexLEB); + WriteTableNumberWithReloc(table_index, "table index"); + break; + } case ExprType::CallRef: { WriteOpcode(stream_, Opcode::CallRef); assert(cast(expr)->sig_type.opt_type() == Type::RefNull); @@ -806,15 +828,13 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { RelocType::TypeIndexLEB); break; } - case ExprType::ReturnCallIndirect: { - Index sig_index = - module_->GetFuncTypeIndex(cast(expr)->decl); - Index table_index = - module_->GetTableIndex(cast(expr)->table); - WriteOpcode(stream_, Opcode::ReturnCallIndirect); + case ExprType::ReturnCallRef: { + WriteOpcode(stream_, Opcode::ReturnCallRef); + assert(cast(expr)->sig_type.opt_type() == + Type::RefNull); + Index sig_index = cast(expr)->sig_type.index(); WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB); - WriteTableNumberWithReloc(table_index, "table index"); break; } case ExprType::Compare: @@ -1010,6 +1030,10 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteTableNumberWithReloc(index, "table.fill table index"); break; } + case ExprType::RefAsNonNull: { + WriteOpcode(stream_, Opcode::RefAsNonNull); + break; + } case ExprType::RefFunc: { WriteOpcode(stream_, Opcode::RefFunc); Index index = module_->GetFuncIndex(cast(expr)->var); diff --git a/src/c-writer.cc b/src/c-writer.cc index 39decb7a8c..8fc565ae7e 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -3611,6 +3611,21 @@ void CWriter::Write(const ExprList& exprs) { Write(GotoLabel(cast(&expr)->var), "}", Newline()); break; + case ExprType::BrOnNonNull: + Write("if (", StackVar(0), ".func != NULL) {"); + Write(GotoLabel(cast(&expr)->var), "}", Newline()); + DropTypes(1); + break; + + case ExprType::BrOnNull: { + Write("if (", StackVar(0), ".func == NULL) {"); + Type type = StackType(0); + DropTypes(1); + Write(GotoLabel(cast(&expr)->var), "}", Newline()); + PushType(type); + break; + } + case ExprType::BrTable: { const auto* bt_expr = cast(&expr); Write("switch (", StackVar(0), ") ", OpenBrace()); @@ -3945,6 +3960,10 @@ void CWriter::Write(const ExprList& exprs) { DropTypes(3); } break; + case ExprType::RefAsNonNull: + Write("if (", StackVar(0), ".func == NULL) { TRAP(NULL_REF); }"); + break; + case ExprType::RefFunc: { const Func* func = module_->GetFunc(cast(&expr)->var); PushType(Type::FuncRef); @@ -4283,6 +4302,7 @@ void CWriter::Write(const ExprList& exprs) { case ExprType::AtomicWait: case ExprType::AtomicNotify: case ExprType::CallRef: + case ExprType::ReturnCallRef: UNIMPLEMENTED("..."); break; } diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc index 217d45cc01..b1e8b8c37d 100644 --- a/src/expr-visitor.cc +++ b/src/expr-visitor.cc @@ -215,6 +215,14 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnBrIfExpr(cast(expr))); break; + case ExprType::BrOnNonNull: + CHECK_RESULT(delegate_->OnBrOnNonNullExpr(cast(expr))); + break; + + case ExprType::BrOnNull: + CHECK_RESULT(delegate_->OnBrOnNullExpr(cast(expr))); + break; + case ExprType::BrTable: CHECK_RESULT(delegate_->OnBrTableExpr(cast(expr))); break; @@ -353,6 +361,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnTableFillExpr(cast(expr))); break; + case ExprType::RefAsNonNull: + CHECK_RESULT(delegate_->OnRefAsNonNullExpr(cast(expr))); + break; + case ExprType::RefFunc: CHECK_RESULT(delegate_->OnRefFuncExpr(cast(expr))); break; @@ -386,6 +398,11 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { cast(expr))); break; + case ExprType::ReturnCallRef: + CHECK_RESULT( + delegate_->OnReturnCallRefExpr(cast(expr))); + break; + case ExprType::Select: CHECK_RESULT(delegate_->OnSelectExpr(cast(expr))); break; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index de5be17ef7..d0dd7863c7 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -182,6 +182,8 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnNonNullExpr(Index depth) override; + Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) override; @@ -193,6 +195,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnDelegateExpr(Index depth) override; Result OnReturnCallExpr(Index func_index) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; + Result OnReturnCallRefExpr(Type sig_type) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; Result OnDropExpr() override; @@ -220,6 +223,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnMemoryFillExpr(Index memidx) override; Result OnMemoryInitExpr(Index segment_index, Index memidx) override; Result OnMemorySizeExpr(Index memidx) override; + Result OnRefAsNonNullExpr() override; Result OnRefFuncExpr(Index func_index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; @@ -321,6 +325,9 @@ class BinaryReaderInterp : public BinaryReaderNop { Index drop_count, Index keep_count, Index catch_drop_count); + + Result EmitBrCond(Opcode opcode, Index depth); + void FixupTopLabel(); u32 GetFuncOffset(Index func_index); @@ -472,6 +479,25 @@ void BinaryReaderInterp::EmitBr(Index depth, istream_.Emit(offset); } +Result BinaryReaderInterp::EmitBrCond(Opcode opcode, Index depth) { + Index drop_count, keep_count, catch_drop_count; + CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); + CHECK_RESULT(validator_.GetCatchCount(depth, &catch_drop_count)); + // The opcode is flipped so if is + // true it can drop values from the stack. + istream_.Emit(opcode); + auto fixup = istream_.EmitFixupU32(); + // The validator for br_on_null keeps the (non-null) reference on + // the stack. This reference needs to be ignored when the branch + // is executed. Note: opcode contains the flipped value. + if (opcode == Opcode::BrOnNonNull && drop_count > 0) { + drop_count--; + } + EmitBr(depth, drop_count, keep_count, catch_drop_count); + istream_.ResolveFixupU32(fixup); + return Result::Ok; +} + void BinaryReaderInterp::FixupTopLabel() { depth_fixups_.Resolve(istream_, label_stack_.size() - 1); } @@ -1107,16 +1133,22 @@ Result BinaryReaderInterp::OnBrExpr(Index depth) { } Result BinaryReaderInterp::OnBrIfExpr(Index depth) { - Index drop_count, keep_count, catch_drop_count; CHECK_RESULT(validator_.OnBrIf(GetLocation(), Var(depth, GetLocation()))); - CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); - CHECK_RESULT(validator_.GetCatchCount(depth, &catch_drop_count)); - // Flip the br_if so if is true it can drop values from the stack. - istream_.Emit(Opcode::InterpBrUnless); - auto fixup = istream_.EmitFixupU32(); - EmitBr(depth, drop_count, keep_count, catch_drop_count); - istream_.ResolveFixupU32(fixup); - return Result::Ok; + // Opcode is flipped. + return EmitBrCond(Opcode::InterpBrUnless, depth); +} + +Result BinaryReaderInterp::OnBrOnNonNullExpr(Index depth) { + CHECK_RESULT( + validator_.OnBrOnNonNull(GetLocation(), Var(depth, GetLocation()))); + // Opcode is flipped. + return EmitBrCond(Opcode::BrOnNull, depth); +} + +Result BinaryReaderInterp::OnBrOnNullExpr(Index depth) { + CHECK_RESULT(validator_.OnBrOnNull(GetLocation(), Var(depth, GetLocation()))); + // Opcode is flipped. + return EmitBrCond(Opcode::BrOnNonNull, depth); } Result BinaryReaderInterp::OnBrTableExpr(Index num_targets, @@ -1240,6 +1272,14 @@ Result BinaryReaderInterp::OnReturnCallIndirectExpr(Index sig_index, return Result::Ok; } +Result BinaryReaderInterp::OnReturnCallRefExpr(Type sig_type) { + CHECK_RESULT( + validator_.OnReturnCallRef(GetLocation(), Var(sig_type, GetLocation()))); + assert(sig_type == Type::RefNull); + istream_.Emit(Opcode::ReturnCallRef); + return Result::Ok; +} + Result BinaryReaderInterp::OnCompareExpr(Opcode opcode) { CHECK_RESULT(validator_.OnCompare(GetLocation(), opcode)); istream_.Emit(opcode); @@ -1405,6 +1445,12 @@ Result BinaryReaderInterp::OnTableFillExpr(Index table_index) { return Result::Ok; } +Result BinaryReaderInterp::OnRefAsNonNullExpr() { + CHECK_RESULT(validator_.OnRefAsNonNull(Location())); + istream_.Emit(Opcode::RefAsNonNull); + return Result::Ok; +} + Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) { CHECK_RESULT( validator_.OnRefFunc(GetLocation(), Var(func_index, GetLocation()))); diff --git a/src/interp/interp.cc b/src/interp/interp.cc index f49b62970b..f18b4d5ed7 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -1299,6 +1299,25 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { } break; + case O::BrOnNonNull: { + Ref ref = Pop(); + if (ref != Ref::Null) { + Push(ref); + pc = instr.imm_u32; + } + break; + } + + case O::BrOnNull: { + Ref ref = Pop(); + if (ref == Ref::Null) { + pc = instr.imm_u32; + } else { + Push(ref); + } + break; + } + case O::BrTable: { auto key = Pop(); if (key >= instr.imm_u32) { @@ -1340,11 +1359,17 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { } } - case O::CallRef: { + case O::CallRef: + case O::ReturnCallRef: { Ref new_func_ref = Pop(); TRAP_IF(new_func_ref == Ref::Null, "null function reference"); Func::Ptr new_func{store_, new_func_ref}; - return DoCall(new_func, out_trap); + + if (instr.op == O::ReturnCallRef) { + return DoReturnCall(new_func, out_trap); + } else { + return DoCall(new_func, out_trap); + } } case O::Drop: @@ -1681,6 +1706,10 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { Push(Pop() == Ref::Null); break; + case O::RefAsNonNull: + TRAP_IF(Pick(1).Get() == Ref::Null, "null reference"); + break; + case O::RefFunc: Push(inst_->funcs()[instr.imm_u32]); break; diff --git a/src/interp/istream.cc b/src/interp/istream.cc index aecc03dbf3..827d1b7c30 100644 --- a/src/interp/istream.cc +++ b/src/interp/istream.cc @@ -246,6 +246,7 @@ Instr Istream::Read(Offset* offset) const { case Opcode::F64X2ConvertLowI32X4U: case Opcode::I8X16Splat: case Opcode::RefIsNull: + case Opcode::RefAsNonNull: case Opcode::V128Not: case Opcode::V128AnyTrue: case Opcode::I8X16Abs: @@ -506,6 +507,8 @@ Instr Istream::Read(Offset* offset) const { break; case Opcode::BrIf: + case Opcode::BrOnNonNull: + case Opcode::BrOnNull: case Opcode::BrTable: case Opcode::InterpBrUnless: // Jump target immediate, 1 operand. @@ -785,8 +788,8 @@ Instr Istream::Read(Offset* offset) const { instr.imm_v128 = ReadAt(offset); break; - case Opcode::CallRef: case Opcode::Block: + case Opcode::CallRef: case Opcode::Catch: case Opcode::CatchAll: case Opcode::Delegate: @@ -799,6 +802,7 @@ Instr Istream::Read(Offset* offset) const { case Opcode::Try: case Opcode::TryTable: case Opcode::ReturnCall: + case Opcode::ReturnCallRef: // Not used. break; } diff --git a/src/ir-util.cc b/src/ir-util.cc index d0c50588f5..16a85cd220 100644 --- a/src/ir-util.cc +++ b/src/ir-util.cc @@ -120,6 +120,16 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { return {arity + 1, arity}; } + case ExprType::BrOnNonNull: { + Index arity = GetLabelArity(cast(&expr)->var); + return {arity + 1, arity}; + } + + case ExprType::BrOnNull: { + Index arity = GetLabelArity(cast(&expr)->var); + return {arity + 1, arity}; + } + case ExprType::BrTable: return {GetLabelArity(cast(&expr)->default_target) + 1, 1, true}; @@ -150,6 +160,11 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { true}; } + case ExprType::ReturnCallRef: { + const Var& var = cast(&expr)->sig_type; + return {GetFuncParamCount(var) + 1, GetFuncResultCount(var), true}; + } + case ExprType::Const: case ExprType::GlobalGet: case ExprType::LocalGet: @@ -186,6 +201,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::RefIsNull: case ExprType::LoadSplat: case ExprType::LoadZero: + case ExprType::RefAsNonNull: return {1, 1}; case ExprType::Drop: diff --git a/src/ir.cc b/src/ir.cc index 3135164205..46713db04c 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -36,6 +36,8 @@ const char* ExprTypeName[] = { "Block", "Br", "BrIf", + "BrOnNonNull", + "BrOnNull", "BrTable", "Call", "CallIndirect", @@ -60,6 +62,7 @@ const char* ExprTypeName[] = { "MemoryInit", "MemorySize", "Nop", + "RefAsNonNull", "RefIsNull", "RefFunc", "RefNull", @@ -67,6 +70,7 @@ const char* ExprTypeName[] = { "Return", "ReturnCall", "ReturnCallIndirect", + "ReturnCallRef", "Select", "SimdLaneOp", "SimdLoadLane", diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt index dee1bce521..eda61a3b7e 100644 --- a/src/lexer-keywords.txt +++ b/src/lexer-keywords.txt @@ -31,6 +31,8 @@ before, TokenType::Before binary, TokenType::Bin block, TokenType::Block, Opcode::Block br_if, TokenType::BrIf, Opcode::BrIf +br_on_non_null, TokenType::BrOnNonNull, Opcode::BrOnNonNull +br_on_null, TokenType::BrOnNull, Opcode::BrOnNull br_table, TokenType::BrTable, Opcode::BrTable br, TokenType::Br, Opcode::Br call_indirect, TokenType::CallIndirect, Opcode::CallIndirect @@ -563,6 +565,7 @@ pagesize, TokenType::PageSize param, TokenType::Param ref, TokenType::Ref quote, TokenType::Quote +ref.as_non_null, TokenType::RefAsNonNull, Opcode::RefAsNonNull ref.extern, TokenType::RefExtern ref.func, TokenType::RefFunc, Opcode::RefFunc ref.is_null, TokenType::RefIsNull, Opcode::RefIsNull @@ -571,6 +574,7 @@ register, TokenType::Register result, TokenType::Result rethrow, TokenType::Rethrow, Opcode::Rethrow return_call_indirect, TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect +return_call_ref, TokenType::ReturnCallRef, Opcode::ReturnCallRef return_call, TokenType::ReturnCall, Opcode::ReturnCall return, TokenType::Return, Opcode::Return select, TokenType::Select, Opcode::Select diff --git a/src/opcode.cc b/src/opcode.cc index 023ae0b2a4..b01e615de5 100644 --- a/src/opcode.cc +++ b/src/opcode.cc @@ -360,6 +360,10 @@ bool Opcode::IsEnabled(const Features& features) const { return features.reference_types_enabled(); case Opcode::CallRef: + case Opcode::ReturnCallRef: + case Opcode::BrOnNonNull: + case Opcode::BrOnNull: + case Opcode::RefAsNonNull: return features.function_references_enabled(); // Interpreter opcodes are never "enabled". diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc index 5d02bb0027..8dd541f499 100644 --- a/src/prebuilt/lexer-keywords.cc +++ b/src/prebuilt/lexer-keywords.cc @@ -158,7 +158,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 602, + TOTAL_KEYWORDS = 606, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 35, MIN_HASH_VALUE = 37, @@ -172,1419 +172,1427 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 35 "src/lexer-keywords.txt" +#line 37 "src/lexer-keywords.txt" {"br", TokenType::Br, Opcode::Br}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 152 "src/lexer-keywords.txt" +#line 154 "src/lexer-keywords.txt" {"f64", Type::F64}, {""}, {""}, -#line 45 "src/lexer-keywords.txt" +#line 47 "src/lexer-keywords.txt" {"data", TokenType::Data}, {""}, {""}, {""}, -#line 464 "src/lexer-keywords.txt" +#line 466 "src/lexer-keywords.txt" {"i64", Type::I64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 122 "src/lexer-keywords.txt" +#line 124 "src/lexer-keywords.txt" {"f32x4", TokenType::F32X4}, {""}, {""}, {""}, {""}, -#line 587 "src/lexer-keywords.txt" +#line 591 "src/lexer-keywords.txt" {"table", TokenType::Table}, -#line 48 "src/lexer-keywords.txt" +#line 50 "src/lexer-keywords.txt" {"do", TokenType::Do}, -#line 364 "src/lexer-keywords.txt" +#line 366 "src/lexer-keywords.txt" {"i32x4", TokenType::I32X4}, {""}, {""}, {""}, -#line 135 "src/lexer-keywords.txt" +#line 137 "src/lexer-keywords.txt" {"f64.ge", TokenType::Compare, Opcode::F64Ge}, -#line 74 "src/lexer-keywords.txt" +#line 76 "src/lexer-keywords.txt" {"f32.ge", TokenType::Compare, Opcode::F32Ge}, -#line 137 "src/lexer-keywords.txt" +#line 139 "src/lexer-keywords.txt" {"f64.le", TokenType::Compare, Opcode::F64Le}, -#line 76 "src/lexer-keywords.txt" +#line 78 "src/lexer-keywords.txt" {"f32.le", TokenType::Compare, Opcode::F32Le}, {""}, {""}, {""}, {""}, {""}, #line 30 "src/lexer-keywords.txt" {"before", TokenType::Before}, {""}, {""}, {""}, {""}, {""}, -#line 186 "src/lexer-keywords.txt" +#line 188 "src/lexer-keywords.txt" {"func", Type::FuncRef, TokenType::Func}, -#line 136 "src/lexer-keywords.txt" +#line 138 "src/lexer-keywords.txt" {"f64.gt", TokenType::Compare, Opcode::F64Gt}, -#line 75 "src/lexer-keywords.txt" +#line 77 "src/lexer-keywords.txt" {"f32.gt", TokenType::Compare, Opcode::F32Gt}, -#line 139 "src/lexer-keywords.txt" +#line 141 "src/lexer-keywords.txt" {"f64.lt", TokenType::Compare, Opcode::F64Lt}, -#line 78 "src/lexer-keywords.txt" +#line 80 "src/lexer-keywords.txt" {"f32.lt", TokenType::Compare, Opcode::F32Lt}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 43 "src/lexer-keywords.txt" +#line 45 "src/lexer-keywords.txt" {"code", TokenType::Code}, {""}, {""}, {""}, -#line 571 "src/lexer-keywords.txt" +#line 574 "src/lexer-keywords.txt" {"result", TokenType::Result}, {""}, -#line 100 "src/lexer-keywords.txt" +#line 102 "src/lexer-keywords.txt" {"f32x4.ge", TokenType::Compare, Opcode::F32X4Ge}, {""}, -#line 102 "src/lexer-keywords.txt" +#line 104 "src/lexer-keywords.txt" {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, {""}, -#line 579 "src/lexer-keywords.txt" +#line 583 "src/lexer-keywords.txt" {"struct", Type::Struct, TokenType::Struct}, {""}, {""}, {""}, {""}, {""}, -#line 555 "src/lexer-keywords.txt" +#line 557 "src/lexer-keywords.txt" {"mut", TokenType::Mut}, -#line 441 "src/lexer-keywords.txt" +#line 443 "src/lexer-keywords.txt" {"i64.or", TokenType::Binary, Opcode::I64Or}, -#line 298 "src/lexer-keywords.txt" +#line 300 "src/lexer-keywords.txt" {"i32.or", TokenType::Binary, Opcode::I32Or}, {""}, {""}, -#line 582 "src/lexer-keywords.txt" +#line 586 "src/lexer-keywords.txt" {"table.get", TokenType::TableGet, Opcode::TableGet}, -#line 101 "src/lexer-keywords.txt" +#line 103 "src/lexer-keywords.txt" {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, -#line 585 "src/lexer-keywords.txt" +#line 589 "src/lexer-keywords.txt" {"table.set", TokenType::TableSet, Opcode::TableSet}, -#line 103 "src/lexer-keywords.txt" +#line 105 "src/lexer-keywords.txt" {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, -#line 330 "src/lexer-keywords.txt" +#line 332 "src/lexer-keywords.txt" {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, {""}, -#line 334 "src/lexer-keywords.txt" +#line 336 "src/lexer-keywords.txt" {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, {""}, -#line 329 "src/lexer-keywords.txt" +#line 331 "src/lexer-keywords.txt" {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, -#line 93 "src/lexer-keywords.txt" +#line 95 "src/lexer-keywords.txt" {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, -#line 333 "src/lexer-keywords.txt" +#line 335 "src/lexer-keywords.txt" {"i32x4.le_s", TokenType::Compare, Opcode::I32X4LeS}, {""}, -#line 332 "src/lexer-keywords.txt" +#line 334 "src/lexer-keywords.txt" {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, {""}, -#line 342 "src/lexer-keywords.txt" +#line 344 "src/lexer-keywords.txt" {"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU}, {""}, -#line 331 "src/lexer-keywords.txt" +#line 333 "src/lexer-keywords.txt" {"i32x4.gt_s", TokenType::Compare, Opcode::I32X4GtS}, {""}, -#line 341 "src/lexer-keywords.txt" +#line 343 "src/lexer-keywords.txt" {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, -#line 145 "src/lexer-keywords.txt" +#line 147 "src/lexer-keywords.txt" {"f64.ne", TokenType::Compare, Opcode::F64Ne}, -#line 84 "src/lexer-keywords.txt" +#line 86 "src/lexer-keywords.txt" {"f32.ne", TokenType::Compare, Opcode::F32Ne}, {""}, {""}, {""}, -#line 554 "src/lexer-keywords.txt" +#line 556 "src/lexer-keywords.txt" {"module", TokenType::Module}, {""}, -#line 440 "src/lexer-keywords.txt" +#line 442 "src/lexer-keywords.txt" {"i64.ne", TokenType::Compare, Opcode::I64Ne}, -#line 297 "src/lexer-keywords.txt" +#line 299 "src/lexer-keywords.txt" {"i32.ne", TokenType::Compare, Opcode::I32Ne}, -#line 46 "src/lexer-keywords.txt" +#line 48 "src/lexer-keywords.txt" {"declare", TokenType::Declare}, {""}, -#line 144 "src/lexer-keywords.txt" +#line 146 "src/lexer-keywords.txt" {"f64.neg", TokenType::Unary, Opcode::F64Neg}, -#line 83 "src/lexer-keywords.txt" +#line 85 "src/lexer-keywords.txt" {"f32.neg", TokenType::Unary, Opcode::F32Neg}, {""}, -#line 149 "src/lexer-keywords.txt" +#line 151 "src/lexer-keywords.txt" {"f64.store", TokenType::Store, Opcode::F64Store}, -#line 87 "src/lexer-keywords.txt" +#line 89 "src/lexer-keywords.txt" {"f32.store", TokenType::Store, Opcode::F32Store}, {""}, -#line 447 "src/lexer-keywords.txt" +#line 449 "src/lexer-keywords.txt" {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, -#line 304 "src/lexer-keywords.txt" +#line 306 "src/lexer-keywords.txt" {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, -#line 446 "src/lexer-keywords.txt" +#line 448 "src/lexer-keywords.txt" {"i64.rotl", TokenType::Binary, Opcode::I64Rotl}, -#line 303 "src/lexer-keywords.txt" +#line 305 "src/lexer-keywords.txt" {"i32.rotl", TokenType::Binary, Opcode::I32Rotl}, -#line 454 "src/lexer-keywords.txt" +#line 456 "src/lexer-keywords.txt" {"i64.store", TokenType::Store, Opcode::I64Store}, -#line 310 "src/lexer-keywords.txt" +#line 312 "src/lexer-keywords.txt" {"i32.store", TokenType::Store, Opcode::I32Store}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 569 "src/lexer-keywords.txt" +#line 572 "src/lexer-keywords.txt" {"ref.null", TokenType::RefNull, Opcode::RefNull}, -#line 108 "src/lexer-keywords.txt" +#line 110 "src/lexer-keywords.txt" {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, {""}, -#line 109 "src/lexer-keywords.txt" +#line 111 "src/lexer-keywords.txt" {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, {""}, {""}, {""}, {""}, -#line 349 "src/lexer-keywords.txt" +#line 351 "src/lexer-keywords.txt" {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, {""}, -#line 350 "src/lexer-keywords.txt" +#line 352 "src/lexer-keywords.txt" {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, {""}, {""}, -#line 151 "src/lexer-keywords.txt" +#line 153 "src/lexer-keywords.txt" {"f64.trunc", TokenType::Unary, Opcode::F64Trunc}, -#line 89 "src/lexer-keywords.txt" +#line 91 "src/lexer-keywords.txt" {"f32.trunc", TokenType::Unary, Opcode::F32Trunc}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 143 "src/lexer-keywords.txt" +#line 145 "src/lexer-keywords.txt" {"f64.nearest", TokenType::Unary, Opcode::F64Nearest}, -#line 82 "src/lexer-keywords.txt" +#line 84 "src/lexer-keywords.txt" {"f32.nearest", TokenType::Unary, Opcode::F32Nearest}, {""}, {""}, {""}, -#line 120 "src/lexer-keywords.txt" +#line 122 "src/lexer-keywords.txt" {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, -#line 575 "src/lexer-keywords.txt" +#line 579 "src/lexer-keywords.txt" {"return", TokenType::Return, Opcode::Return}, {""}, {""}, {""}, {""}, -#line 559 "src/lexer-keywords.txt" +#line 561 "src/lexer-keywords.txt" {"null", TokenType::Null}, -#line 453 "src/lexer-keywords.txt" +#line 455 "src/lexer-keywords.txt" {"i64.store8", TokenType::Store, Opcode::I64Store8}, -#line 309 "src/lexer-keywords.txt" +#line 311 "src/lexer-keywords.txt" {"i32.store8", TokenType::Store, Opcode::I32Store8}, -#line 142 "src/lexer-keywords.txt" +#line 144 "src/lexer-keywords.txt" {"f64.mul", TokenType::Binary, Opcode::F64Mul}, -#line 81 "src/lexer-keywords.txt" +#line 83 "src/lexer-keywords.txt" {"f32.mul", TokenType::Binary, Opcode::F32Mul}, -#line 92 "src/lexer-keywords.txt" +#line 94 "src/lexer-keywords.txt" {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, -#line 107 "src/lexer-keywords.txt" +#line 109 "src/lexer-keywords.txt" {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, {""}, {""}, {""}, -#line 439 "src/lexer-keywords.txt" +#line 441 "src/lexer-keywords.txt" {"i64.mul", TokenType::Binary, Opcode::I64Mul}, -#line 296 "src/lexer-keywords.txt" +#line 298 "src/lexer-keywords.txt" {"i32.mul", TokenType::Binary, Opcode::I32Mul}, -#line 323 "src/lexer-keywords.txt" +#line 325 "src/lexer-keywords.txt" {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, {""}, -#line 38 "src/lexer-keywords.txt" +#line 40 "src/lexer-keywords.txt" {"call", TokenType::Call, Opcode::Call}, {""}, -#line 126 "src/lexer-keywords.txt" +#line 128 "src/lexer-keywords.txt" {"f64.const", TokenType::Const, Opcode::F64Const}, -#line 64 "src/lexer-keywords.txt" +#line 66 "src/lexer-keywords.txt" {"f32.const", TokenType::Const, Opcode::F32Const}, {""}, {""}, {""}, -#line 106 "src/lexer-keywords.txt" +#line 108 "src/lexer-keywords.txt" {"f32x4.mul", TokenType::Binary, Opcode::F32X4Mul}, {""}, -#line 413 "src/lexer-keywords.txt" +#line 415 "src/lexer-keywords.txt" {"i64.const", TokenType::Const, Opcode::I64Const}, -#line 275 "src/lexer-keywords.txt" +#line 277 "src/lexer-keywords.txt" {"i32.const", TokenType::Const, Opcode::I32Const}, {""}, -#line 576 "src/lexer-keywords.txt" +#line 580 "src/lexer-keywords.txt" {"select", TokenType::Select, Opcode::Select}, {""}, -#line 348 "src/lexer-keywords.txt" +#line 350 "src/lexer-keywords.txt" {"i32x4.mul", TokenType::Binary, Opcode::I32X4Mul}, {""}, -#line 543 "src/lexer-keywords.txt" +#line 545 "src/lexer-keywords.txt" {"local", TokenType::Local}, {""}, {""}, {""}, -#line 496 "src/lexer-keywords.txt" +#line 498 "src/lexer-keywords.txt" {"i64.xor", TokenType::Binary, Opcode::I64Xor}, -#line 373 "src/lexer-keywords.txt" +#line 375 "src/lexer-keywords.txt" {"i32.xor", TokenType::Binary, Opcode::I32Xor}, -#line 47 "src/lexer-keywords.txt" +#line 49 "src/lexer-keywords.txt" {"delegate", TokenType::Delegate}, {""}, {""}, {""}, -#line 124 "src/lexer-keywords.txt" +#line 126 "src/lexer-keywords.txt" {"f64.add", TokenType::Binary, Opcode::F64Add}, -#line 62 "src/lexer-keywords.txt" +#line 64 "src/lexer-keywords.txt" {"f32.add", TokenType::Binary, Opcode::F32Add}, -#line 138 "src/lexer-keywords.txt" +#line 140 "src/lexer-keywords.txt" {"f64.load", TokenType::Load, Opcode::F64Load}, -#line 77 "src/lexer-keywords.txt" +#line 79 "src/lexer-keywords.txt" {"f32.load", TokenType::Load, Opcode::F32Load}, {""}, {""}, {""}, -#line 374 "src/lexer-keywords.txt" +#line 376 "src/lexer-keywords.txt" {"i64.add", TokenType::Binary, Opcode::I64Add}, -#line 245 "src/lexer-keywords.txt" +#line 247 "src/lexer-keywords.txt" {"i32.add", TokenType::Binary, Opcode::I32Add}, -#line 436 "src/lexer-keywords.txt" +#line 438 "src/lexer-keywords.txt" {"i64.load", TokenType::Load, Opcode::I64Load}, -#line 293 "src/lexer-keywords.txt" +#line 295 "src/lexer-keywords.txt" {"i32.load", TokenType::Load, Opcode::I32Load}, {""}, {""}, {""}, {""}, -#line 116 "src/lexer-keywords.txt" +#line 118 "src/lexer-keywords.txt" {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, {""}, {""}, {""}, -#line 375 "src/lexer-keywords.txt" +#line 377 "src/lexer-keywords.txt" {"i64.and", TokenType::Binary, Opcode::I64And}, -#line 246 "src/lexer-keywords.txt" +#line 248 "src/lexer-keywords.txt" {"i32.and", TokenType::Binary, Opcode::I32And}, {""}, -#line 352 "src/lexer-keywords.txt" +#line 354 "src/lexer-keywords.txt" {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, {""}, {""}, {""}, -#line 425 "src/lexer-keywords.txt" +#line 427 "src/lexer-keywords.txt" {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, -#line 284 "src/lexer-keywords.txt" +#line 286 "src/lexer-keywords.txt" {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, -#line 429 "src/lexer-keywords.txt" +#line 431 "src/lexer-keywords.txt" {"i64.le_u", TokenType::Compare, Opcode::I64LeU}, -#line 288 "src/lexer-keywords.txt" +#line 290 "src/lexer-keywords.txt" {"i32.le_u", TokenType::Compare, Opcode::I32LeU}, -#line 424 "src/lexer-keywords.txt" +#line 426 "src/lexer-keywords.txt" {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, -#line 283 "src/lexer-keywords.txt" +#line 285 "src/lexer-keywords.txt" {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, -#line 428 "src/lexer-keywords.txt" +#line 430 "src/lexer-keywords.txt" {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, -#line 287 "src/lexer-keywords.txt" +#line 289 "src/lexer-keywords.txt" {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, -#line 427 "src/lexer-keywords.txt" +#line 429 "src/lexer-keywords.txt" {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, -#line 286 "src/lexer-keywords.txt" +#line 288 "src/lexer-keywords.txt" {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, -#line 438 "src/lexer-keywords.txt" +#line 440 "src/lexer-keywords.txt" {"i64.lt_u", TokenType::Compare, Opcode::I64LtU}, -#line 295 "src/lexer-keywords.txt" +#line 297 "src/lexer-keywords.txt" {"i32.lt_u", TokenType::Compare, Opcode::I32LtU}, -#line 426 "src/lexer-keywords.txt" +#line 428 "src/lexer-keywords.txt" {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, -#line 285 "src/lexer-keywords.txt" +#line 287 "src/lexer-keywords.txt" {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, -#line 437 "src/lexer-keywords.txt" +#line 439 "src/lexer-keywords.txt" {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, -#line 294 "src/lexer-keywords.txt" +#line 296 "src/lexer-keywords.txt" {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, {""}, {""}, {""}, -#line 540 "src/lexer-keywords.txt" +#line 542 "src/lexer-keywords.txt" {"local.get", TokenType::LocalGet, Opcode::LocalGet}, {""}, -#line 541 "src/lexer-keywords.txt" +#line 543 "src/lexer-keywords.txt" {"local.set", TokenType::LocalSet, Opcode::LocalSet}, -#line 542 "src/lexer-keywords.txt" +#line 544 "src/lexer-keywords.txt" {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 351 "src/lexer-keywords.txt" +#line 353 "src/lexer-keywords.txt" {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, -#line 324 "src/lexer-keywords.txt" +#line 326 "src/lexer-keywords.txt" {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, {""}, -#line 125 "src/lexer-keywords.txt" +#line 127 "src/lexer-keywords.txt" {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, -#line 63 "src/lexer-keywords.txt" +#line 65 "src/lexer-keywords.txt" {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 586 "src/lexer-keywords.txt" +#line 590 "src/lexer-keywords.txt" {"table.size", TokenType::TableSize, Opcode::TableSize}, {""}, {""}, {""}, -#line 104 "src/lexer-keywords.txt" +#line 106 "src/lexer-keywords.txt" {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, -#line 535 "src/lexer-keywords.txt" +#line 537 "src/lexer-keywords.txt" {"if", TokenType::If, Opcode::If}, -#line 411 "src/lexer-keywords.txt" +#line 413 "src/lexer-keywords.txt" {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, -#line 273 "src/lexer-keywords.txt" +#line 275 "src/lexer-keywords.txt" {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 564 "src/lexer-keywords.txt" +#line 566 "src/lexer-keywords.txt" {"ref", TokenType::Ref}, {""}, {""}, -#line 404 "src/lexer-keywords.txt" +#line 406 "src/lexer-keywords.txt" {"i64.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I64AtomicRmwOr}, -#line 267 "src/lexer-keywords.txt" +#line 269 "src/lexer-keywords.txt" {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, {""}, {""}, {""}, {""}, {""}, -#line 574 "src/lexer-keywords.txt" +#line 578 "src/lexer-keywords.txt" {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, {""}, {""}, -#line 53 "src/lexer-keywords.txt" +#line 55 "src/lexer-keywords.txt" {"else", TokenType::Else, Opcode::Else}, {""}, {""}, {""}, {""}, {""}, -#line 55 "src/lexer-keywords.txt" +#line 57 "src/lexer-keywords.txt" {"tag", TokenType::Tag}, {""}, -#line 98 "src/lexer-keywords.txt" +#line 100 "src/lexer-keywords.txt" {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, -#line 566 "src/lexer-keywords.txt" +#line 569 "src/lexer-keywords.txt" {"ref.extern", TokenType::RefExtern}, -#line 338 "src/lexer-keywords.txt" +#line 340 "src/lexer-keywords.txt" {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, -#line 90 "src/lexer-keywords.txt" +#line 92 "src/lexer-keywords.txt" {"f32", Type::F32}, -#line 337 "src/lexer-keywords.txt" +#line 339 "src/lexer-keywords.txt" {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, {""}, {""}, -#line 328 "src/lexer-keywords.txt" +#line 330 "src/lexer-keywords.txt" {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, {""}, -#line 189 "src/lexer-keywords.txt" +#line 191 "src/lexer-keywords.txt" {"get", TokenType::Get}, -#line 320 "src/lexer-keywords.txt" +#line 322 "src/lexer-keywords.txt" {"i32", Type::I32}, -#line 50 "src/lexer-keywords.txt" +#line 52 "src/lexer-keywords.txt" {"either", TokenType::Either}, {""}, {""}, -#line 391 "src/lexer-keywords.txt" +#line 393 "src/lexer-keywords.txt" {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, -#line 435 "src/lexer-keywords.txt" +#line 437 "src/lexer-keywords.txt" {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, -#line 292 "src/lexer-keywords.txt" +#line 294 "src/lexer-keywords.txt" {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, -#line 434 "src/lexer-keywords.txt" +#line 436 "src/lexer-keywords.txt" {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, -#line 291 "src/lexer-keywords.txt" +#line 293 "src/lexer-keywords.txt" {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, {""}, -#line 410 "src/lexer-keywords.txt" +#line 412 "src/lexer-keywords.txt" {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, -#line 272 "src/lexer-keywords.txt" +#line 274 "src/lexer-keywords.txt" {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, -#line 431 "src/lexer-keywords.txt" +#line 433 "src/lexer-keywords.txt" {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, -#line 290 "src/lexer-keywords.txt" +#line 292 "src/lexer-keywords.txt" {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, -#line 457 "src/lexer-keywords.txt" +#line 459 "src/lexer-keywords.txt" {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, -#line 313 "src/lexer-keywords.txt" +#line 315 "src/lexer-keywords.txt" {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, -#line 430 "src/lexer-keywords.txt" +#line 432 "src/lexer-keywords.txt" {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, -#line 289 "src/lexer-keywords.txt" +#line 291 "src/lexer-keywords.txt" {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, -#line 456 "src/lexer-keywords.txt" +#line 458 "src/lexer-keywords.txt" {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, -#line 312 "src/lexer-keywords.txt" +#line 314 "src/lexer-keywords.txt" {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, -#line 445 "src/lexer-keywords.txt" +#line 447 "src/lexer-keywords.txt" {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, -#line 302 "src/lexer-keywords.txt" +#line 304 "src/lexer-keywords.txt" {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, -#line 444 "src/lexer-keywords.txt" +#line 446 "src/lexer-keywords.txt" {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, -#line 301 "src/lexer-keywords.txt" +#line 303 "src/lexer-keywords.txt" {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, {""}, -#line 54 "src/lexer-keywords.txt" +#line 56 "src/lexer-keywords.txt" {"end", TokenType::End, Opcode::End}, {""}, -#line 407 "src/lexer-keywords.txt" +#line 409 "src/lexer-keywords.txt" {"i64.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I64AtomicRmwXor}, -#line 270 "src/lexer-keywords.txt" +#line 272 "src/lexer-keywords.txt" {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 588 "src/lexer-keywords.txt" +#line 592 "src/lexer-keywords.txt" {"then", TokenType::Then}, -#line 584 "src/lexer-keywords.txt" +#line 588 "src/lexer-keywords.txt" {"table.init", TokenType::TableInit, Opcode::TableInit}, {""}, {""}, -#line 344 "src/lexer-keywords.txt" +#line 346 "src/lexer-keywords.txt" {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, {""}, -#line 343 "src/lexer-keywords.txt" +#line 345 "src/lexer-keywords.txt" {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, - {""}, -#line 390 "src/lexer-keywords.txt" +#line 35 "src/lexer-keywords.txt" + {"br_on_null", TokenType::BrOnNull, Opcode::BrOnNull}, +#line 392 "src/lexer-keywords.txt" {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, -#line 448 "src/lexer-keywords.txt" +#line 450 "src/lexer-keywords.txt" {"i64.shl", TokenType::Binary, Opcode::I64Shl}, -#line 305 "src/lexer-keywords.txt" +#line 307 "src/lexer-keywords.txt" {"i32.shl", TokenType::Binary, Opcode::I32Shl}, {""}, {""}, -#line 114 "src/lexer-keywords.txt" +#line 116 "src/lexer-keywords.txt" {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, {""}, -#line 115 "src/lexer-keywords.txt" +#line 117 "src/lexer-keywords.txt" {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, -#line 140 "src/lexer-keywords.txt" +#line 142 "src/lexer-keywords.txt" {"f64.max", TokenType::Binary, Opcode::F64Max}, -#line 79 "src/lexer-keywords.txt" +#line 81 "src/lexer-keywords.txt" {"f32.max", TokenType::Binary, Opcode::F32Max}, {""}, {""}, -#line 160 "src/lexer-keywords.txt" +#line 162 "src/lexer-keywords.txt" {"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge}, {""}, -#line 162 "src/lexer-keywords.txt" +#line 164 "src/lexer-keywords.txt" {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, {""}, {""}, -#line 387 "src/lexer-keywords.txt" +#line 389 "src/lexer-keywords.txt" {"i64.atomic.rmw32.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AddU}, {""}, -#line 353 "src/lexer-keywords.txt" +#line 355 "src/lexer-keywords.txt" {"i32x4.shl", TokenType::Binary, Opcode::I32X4Shl}, {""}, {""}, -#line 570 "src/lexer-keywords.txt" +#line 573 "src/lexer-keywords.txt" {"register", TokenType::Register}, -#line 379 "src/lexer-keywords.txt" +#line 381 "src/lexer-keywords.txt" {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, -#line 249 "src/lexer-keywords.txt" +#line 251 "src/lexer-keywords.txt" {"i32.atomic.load", TokenType::AtomicLoad, Opcode::I32AtomicLoad}, {""}, {""}, {""}, -#line 161 "src/lexer-keywords.txt" +#line 163 "src/lexer-keywords.txt" {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, -#line 388 "src/lexer-keywords.txt" +#line 390 "src/lexer-keywords.txt" {"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU}, -#line 163 "src/lexer-keywords.txt" +#line 165 "src/lexer-keywords.txt" {"f64x2.lt", TokenType::Compare, Opcode::F64X2Lt}, {""}, -#line 58 "src/lexer-keywords.txt" +#line 60 "src/lexer-keywords.txt" {"exn", Type::ExnRef, TokenType::Exn}, {""}, {""}, -#line 475 "src/lexer-keywords.txt" +#line 477 "src/lexer-keywords.txt" {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, -#line 155 "src/lexer-keywords.txt" +#line 157 "src/lexer-keywords.txt" {"f64x2.ceil", TokenType::Unary, Opcode::F64X2Ceil}, -#line 474 "src/lexer-keywords.txt" +#line 476 "src/lexer-keywords.txt" {"i64x2.le_s", TokenType::Binary, Opcode::I64X2LeS}, {""}, {""}, {""}, {""}, {""}, -#line 473 "src/lexer-keywords.txt" +#line 475 "src/lexer-keywords.txt" {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, {""}, -#line 472 "src/lexer-keywords.txt" +#line 474 "src/lexer-keywords.txt" {"i64x2.lt_s", TokenType::Binary, Opcode::I64X2LtS}, -#line 99 "src/lexer-keywords.txt" +#line 101 "src/lexer-keywords.txt" {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, {""}, {""}, -#line 185 "src/lexer-keywords.txt" +#line 187 "src/lexer-keywords.txt" {"field", TokenType::Field}, -#line 112 "src/lexer-keywords.txt" +#line 114 "src/lexer-keywords.txt" {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, {""}, {""}, {""}, {""}, {""}, -#line 419 "src/lexer-keywords.txt" +#line 421 "src/lexer-keywords.txt" {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, -#line 281 "src/lexer-keywords.txt" +#line 283 "src/lexer-keywords.txt" {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, {""}, -#line 539 "src/lexer-keywords.txt" +#line 541 "src/lexer-keywords.txt" {"item", TokenType::Item}, {""}, {""}, -#line 421 "src/lexer-keywords.txt" +#line 423 "src/lexer-keywords.txt" {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, -#line 282 "src/lexer-keywords.txt" +#line 284 "src/lexer-keywords.txt" {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, {""}, {""}, -#line 567 "src/lexer-keywords.txt" +#line 570 "src/lexer-keywords.txt" {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, -#line 134 "src/lexer-keywords.txt" +#line 136 "src/lexer-keywords.txt" {"f64.floor", TokenType::Unary, Opcode::F64Floor}, -#line 73 "src/lexer-keywords.txt" +#line 75 "src/lexer-keywords.txt" {"f32.floor", TokenType::Unary, Opcode::F32Floor}, {""}, {""}, -#line 412 "src/lexer-keywords.txt" +#line 414 "src/lexer-keywords.txt" {"i64.clz", TokenType::Unary, Opcode::I64Clz}, -#line 274 "src/lexer-keywords.txt" +#line 276 "src/lexer-keywords.txt" {"i32.clz", TokenType::Unary, Opcode::I32Clz}, {""}, {""}, {""}, {""}, -#line 168 "src/lexer-keywords.txt" +#line 170 "src/lexer-keywords.txt" {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, -#line 105 "src/lexer-keywords.txt" +#line 107 "src/lexer-keywords.txt" {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, -#line 169 "src/lexer-keywords.txt" +#line 171 "src/lexer-keywords.txt" {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, -#line 414 "src/lexer-keywords.txt" +#line 416 "src/lexer-keywords.txt" {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, -#line 276 "src/lexer-keywords.txt" +#line 278 "src/lexer-keywords.txt" {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, {""}, {""}, -#line 477 "src/lexer-keywords.txt" +#line 479 "src/lexer-keywords.txt" {"i64x2.neg", TokenType::Unary, Opcode::I64X2Neg}, -#line 452 "src/lexer-keywords.txt" +#line 454 "src/lexer-keywords.txt" {"i64.store32", TokenType::Store, Opcode::I64Store32}, -#line 471 "src/lexer-keywords.txt" +#line 473 "src/lexer-keywords.txt" {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, {""}, -#line 56 "src/lexer-keywords.txt" +#line 58 "src/lexer-keywords.txt" {"extern", Type::ExternRef, TokenType::Extern}, -#line 394 "src/lexer-keywords.txt" +#line 396 "src/lexer-keywords.txt" {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, -#line 257 "src/lexer-keywords.txt" +#line 259 "src/lexer-keywords.txt" {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, {""}, {""}, -#line 392 "src/lexer-keywords.txt" +#line 394 "src/lexer-keywords.txt" {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, {""}, -#line 113 "src/lexer-keywords.txt" +#line 115 "src/lexer-keywords.txt" {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, - {""}, {""}, {""}, {""}, {""}, -#line 395 "src/lexer-keywords.txt" +#line 568 "src/lexer-keywords.txt" + {"ref.as_non_null", TokenType::RefAsNonNull, Opcode::RefAsNonNull}, + {""}, {""}, {""}, {""}, +#line 397 "src/lexer-keywords.txt" {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, -#line 258 "src/lexer-keywords.txt" +#line 260 "src/lexer-keywords.txt" {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, {""}, {""}, -#line 188 "src/lexer-keywords.txt" +#line 190 "src/lexer-keywords.txt" {"function", TokenType::Function}, -#line 401 "src/lexer-keywords.txt" +#line 403 "src/lexer-keywords.txt" {"i64.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I64AtomicRmwAdd}, -#line 264 "src/lexer-keywords.txt" +#line 266 "src/lexer-keywords.txt" {"i32.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I32AtomicRmwAdd}, {""}, -#line 180 "src/lexer-keywords.txt" +#line 182 "src/lexer-keywords.txt" {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, {""}, {""}, -#line 393 "src/lexer-keywords.txt" +#line 395 "src/lexer-keywords.txt" {"i64.atomic.rmw32.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XorU}, {""}, {""}, -#line 557 "src/lexer-keywords.txt" +#line 559 "src/lexer-keywords.txt" {"nan:canonical", TokenType::NanCanonical}, {""}, {""}, -#line 402 "src/lexer-keywords.txt" +#line 404 "src/lexer-keywords.txt" {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, -#line 265 "src/lexer-keywords.txt" +#line 267 "src/lexer-keywords.txt" {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, -#line 154 "src/lexer-keywords.txt" +#line 156 "src/lexer-keywords.txt" {"f64x2.add", TokenType::Binary, Opcode::F64X2Add}, -#line 167 "src/lexer-keywords.txt" +#line 169 "src/lexer-keywords.txt" {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, {""}, {""}, {""}, -#line 141 "src/lexer-keywords.txt" +#line 143 "src/lexer-keywords.txt" {"f64.min", TokenType::Binary, Opcode::F64Min}, -#line 80 "src/lexer-keywords.txt" +#line 82 "src/lexer-keywords.txt" {"f32.min", TokenType::Binary, Opcode::F32Min}, -#line 465 "src/lexer-keywords.txt" +#line 467 "src/lexer-keywords.txt" {"i64x2.add", TokenType::Binary, Opcode::I64X2Add}, {""}, {""}, -#line 400 "src/lexer-keywords.txt" +#line 402 "src/lexer-keywords.txt" {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, -#line 263 "src/lexer-keywords.txt" +#line 265 "src/lexer-keywords.txt" {"i32.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XorU}, {""}, -#line 459 "src/lexer-keywords.txt" +#line 461 "src/lexer-keywords.txt" {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, -#line 315 "src/lexer-keywords.txt" +#line 317 "src/lexer-keywords.txt" {"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U}, {""}, -#line 166 "src/lexer-keywords.txt" +#line 168 "src/lexer-keywords.txt" {"f64x2.mul", TokenType::Binary, Opcode::F64X2Mul}, -#line 458 "src/lexer-keywords.txt" +#line 460 "src/lexer-keywords.txt" {"i64.trunc_f64_s", TokenType::Convert, Opcode::I64TruncF64S}, -#line 314 "src/lexer-keywords.txt" +#line 316 "src/lexer-keywords.txt" {"i32.trunc_f64_s", TokenType::Convert, Opcode::I32TruncF64S}, -#line 568 "src/lexer-keywords.txt" +#line 571 "src/lexer-keywords.txt" {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, -#line 606 "src/lexer-keywords.txt" +#line 610 "src/lexer-keywords.txt" {"v128", Type::V128}, {""}, {""}, -#line 469 "src/lexer-keywords.txt" +#line 471 "src/lexer-keywords.txt" {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, -#line 433 "src/lexer-keywords.txt" +#line 435 "src/lexer-keywords.txt" {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, {""}, {""}, {""}, -#line 432 "src/lexer-keywords.txt" +#line 434 "src/lexer-keywords.txt" {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, {""}, {""}, {""}, {""}, -#line 556 "src/lexer-keywords.txt" +#line 558 "src/lexer-keywords.txt" {"nan:arithmetic", TokenType::NanArithmetic}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 538 "src/lexer-keywords.txt" +#line 540 "src/lexer-keywords.txt" {"invoke", TokenType::Invoke}, {""}, {""}, {""}, {""}, {""}, -#line 378 "src/lexer-keywords.txt" +#line 380 "src/lexer-keywords.txt" {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, -#line 248 "src/lexer-keywords.txt" +#line 250 "src/lexer-keywords.txt" {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, {""}, -#line 176 "src/lexer-keywords.txt" +#line 178 "src/lexer-keywords.txt" {"f64x2.replace_lane", TokenType::SimdLaneOp, Opcode::F64X2ReplaceLane}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 485 "src/lexer-keywords.txt" +#line 487 "src/lexer-keywords.txt" {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, {""}, -#line 565 "src/lexer-keywords.txt" +#line 567 "src/lexer-keywords.txt" {"quote", TokenType::Quote}, #line 32 "src/lexer-keywords.txt" {"block", TokenType::Block, Opcode::Block}, {""}, {""}, -#line 450 "src/lexer-keywords.txt" +#line 452 "src/lexer-keywords.txt" {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, -#line 307 "src/lexer-keywords.txt" +#line 309 "src/lexer-keywords.txt" {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, -#line 449 "src/lexer-keywords.txt" +#line 451 "src/lexer-keywords.txt" {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, -#line 306 "src/lexer-keywords.txt" +#line 308 "src/lexer-keywords.txt" {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, -#line 397 "src/lexer-keywords.txt" +#line 399 "src/lexer-keywords.txt" {"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU}, -#line 260 "src/lexer-keywords.txt" +#line 262 "src/lexer-keywords.txt" {"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU}, -#line 240 "src/lexer-keywords.txt" +#line 242 "src/lexer-keywords.txt" {"i16x8", TokenType::I16X8}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 355 "src/lexer-keywords.txt" +#line 357 "src/lexer-keywords.txt" {"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU}, -#line 346 "src/lexer-keywords.txt" +#line 348 "src/lexer-keywords.txt" {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, -#line 354 "src/lexer-keywords.txt" +#line 356 "src/lexer-keywords.txt" {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, -#line 345 "src/lexer-keywords.txt" +#line 347 "src/lexer-keywords.txt" {"i32x4.min_s", TokenType::Binary, Opcode::I32X4MinS}, -#line 601 "src/lexer-keywords.txt" +#line 605 "src/lexer-keywords.txt" {"v128.or", TokenType::Binary, Opcode::V128Or}, {""}, -#line 561 "src/lexer-keywords.txt" +#line 563 "src/lexer-keywords.txt" {"output", TokenType::Output}, {""}, {""}, -#line 560 "src/lexer-keywords.txt" +#line 562 "src/lexer-keywords.txt" {"offset", TokenType::Offset}, {""}, -#line 593 "src/lexer-keywords.txt" +#line 597 "src/lexer-keywords.txt" {"type", TokenType::Type}, -#line 591 "src/lexer-keywords.txt" +#line 595 "src/lexer-keywords.txt" {"try", TokenType::Try, Opcode::Try}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 581 "src/lexer-keywords.txt" +#line 585 "src/lexer-keywords.txt" {"table.fill", TokenType::TableFill, Opcode::TableFill}, {""}, -#line 484 "src/lexer-keywords.txt" +#line 486 "src/lexer-keywords.txt" {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, -#line 478 "src/lexer-keywords.txt" +#line 480 "src/lexer-keywords.txt" {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, - {""}, {""}, {""}, {""}, {""}, -#line 205 "src/lexer-keywords.txt" +#line 34 "src/lexer-keywords.txt" + {"br_on_non_null", TokenType::BrOnNonNull, Opcode::BrOnNonNull}, + {""}, {""}, {""}, {""}, +#line 207 "src/lexer-keywords.txt" {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, -#line 420 "src/lexer-keywords.txt" +#line 422 "src/lexer-keywords.txt" {"i64.extend32_s", TokenType::Unary, Opcode::I64Extend32S}, -#line 209 "src/lexer-keywords.txt" +#line 211 "src/lexer-keywords.txt" {"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU}, {""}, -#line 204 "src/lexer-keywords.txt" +#line 206 "src/lexer-keywords.txt" {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, -#line 40 "src/lexer-keywords.txt" +#line 42 "src/lexer-keywords.txt" {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, -#line 208 "src/lexer-keywords.txt" +#line 210 "src/lexer-keywords.txt" {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, -#line 336 "src/lexer-keywords.txt" +#line 338 "src/lexer-keywords.txt" {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, -#line 207 "src/lexer-keywords.txt" +#line 209 "src/lexer-keywords.txt" {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, {""}, -#line 213 "src/lexer-keywords.txt" +#line 215 "src/lexer-keywords.txt" {"i16x8.lt_u", TokenType::Compare, Opcode::I16X8LtU}, -#line 335 "src/lexer-keywords.txt" +#line 337 "src/lexer-keywords.txt" {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, -#line 206 "src/lexer-keywords.txt" +#line 208 "src/lexer-keywords.txt" {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, {""}, -#line 212 "src/lexer-keywords.txt" +#line 214 "src/lexer-keywords.txt" {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, {""}, {""}, -#line 70 "src/lexer-keywords.txt" +#line 72 "src/lexer-keywords.txt" {"f32.demote_f64", TokenType::Convert, Opcode::F32DemoteF64}, {""}, -#line 164 "src/lexer-keywords.txt" +#line 166 "src/lexer-keywords.txt" {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, {""}, -#line 117 "src/lexer-keywords.txt" +#line 119 "src/lexer-keywords.txt" {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, -#line 605 "src/lexer-keywords.txt" +#line 609 "src/lexer-keywords.txt" {"v128.store", TokenType::Store, Opcode::V128Store}, -#line 537 "src/lexer-keywords.txt" +#line 539 "src/lexer-keywords.txt" {"input", TokenType::Input}, {""}, {""}, -#line 573 "src/lexer-keywords.txt" +#line 576 "src/lexer-keywords.txt" {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, {""}, -#line 356 "src/lexer-keywords.txt" +#line 358 "src/lexer-keywords.txt" {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, -#line 508 "src/lexer-keywords.txt" +#line 510 "src/lexer-keywords.txt" {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, #line 33 "src/lexer-keywords.txt" {"br_if", TokenType::BrIf, Opcode::BrIf}, -#line 512 "src/lexer-keywords.txt" +#line 514 "src/lexer-keywords.txt" {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, {""}, -#line 507 "src/lexer-keywords.txt" +#line 509 "src/lexer-keywords.txt" {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, {""}, -#line 511 "src/lexer-keywords.txt" +#line 513 "src/lexer-keywords.txt" {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, {""}, -#line 510 "src/lexer-keywords.txt" +#line 512 "src/lexer-keywords.txt" {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, -#line 536 "src/lexer-keywords.txt" +#line 538 "src/lexer-keywords.txt" {"import", TokenType::Import}, -#line 514 "src/lexer-keywords.txt" +#line 516 "src/lexer-keywords.txt" {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, {""}, -#line 509 "src/lexer-keywords.txt" +#line 511 "src/lexer-keywords.txt" {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, {""}, -#line 513 "src/lexer-keywords.txt" +#line 515 "src/lexer-keywords.txt" {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, {""}, {""}, {""}, {""}, {""}, -#line 599 "src/lexer-keywords.txt" +#line 603 "src/lexer-keywords.txt" {"v128.load", TokenType::Load, Opcode::V128Load}, -#line 158 "src/lexer-keywords.txt" +#line 160 "src/lexer-keywords.txt" {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, {""}, {""}, -#line 221 "src/lexer-keywords.txt" +#line 223 "src/lexer-keywords.txt" {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, {""}, -#line 223 "src/lexer-keywords.txt" +#line 225 "src/lexer-keywords.txt" {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, -#line 423 "src/lexer-keywords.txt" +#line 425 "src/lexer-keywords.txt" {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, -#line 466 "src/lexer-keywords.txt" +#line 468 "src/lexer-keywords.txt" {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, -#line 422 "src/lexer-keywords.txt" +#line 424 "src/lexer-keywords.txt" {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, {""}, {""}, -#line 148 "src/lexer-keywords.txt" +#line 150 "src/lexer-keywords.txt" {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, -#line 86 "src/lexer-keywords.txt" +#line 88 "src/lexer-keywords.txt" {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, -#line 211 "src/lexer-keywords.txt" +#line 213 "src/lexer-keywords.txt" {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, {""}, -#line 210 "src/lexer-keywords.txt" +#line 212 "src/lexer-keywords.txt" {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, -#line 612 "src/lexer-keywords.txt" +#line 616 "src/lexer-keywords.txt" {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, -#line 406 "src/lexer-keywords.txt" +#line 408 "src/lexer-keywords.txt" {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, -#line 269 "src/lexer-keywords.txt" +#line 271 "src/lexer-keywords.txt" {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, {""}, {""}, {""}, -#line 184 "src/lexer-keywords.txt" +#line 186 "src/lexer-keywords.txt" {"f64x2", TokenType::F64X2}, {""}, {""}, -#line 611 "src/lexer-keywords.txt" +#line 615 "src/lexer-keywords.txt" {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, {""}, -#line 600 "src/lexer-keywords.txt" +#line 604 "src/lexer-keywords.txt" {"v128.not", TokenType::Unary, Opcode::V128Not}, -#line 619 "src/lexer-keywords.txt" +#line 623 "src/lexer-keywords.txt" {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, -#line 495 "src/lexer-keywords.txt" +#line 497 "src/lexer-keywords.txt" {"i64x2", TokenType::I64X2}, -#line 118 "src/lexer-keywords.txt" +#line 120 "src/lexer-keywords.txt" {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, {""}, -#line 521 "src/lexer-keywords.txt" +#line 523 "src/lexer-keywords.txt" {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, {""}, -#line 523 "src/lexer-keywords.txt" +#line 525 "src/lexer-keywords.txt" {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, -#line 44 "src/lexer-keywords.txt" +#line 46 "src/lexer-keywords.txt" {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 451 "src/lexer-keywords.txt" +#line 453 "src/lexer-keywords.txt" {"i64.store16", TokenType::Store, Opcode::I64Store16}, -#line 308 "src/lexer-keywords.txt" +#line 310 "src/lexer-keywords.txt" {"i32.store16", TokenType::Store, Opcode::I32Store16}, {""}, -#line 187 "src/lexer-keywords.txt" +#line 189 "src/lexer-keywords.txt" {"funcref", Type::FuncRef}, -#line 196 "src/lexer-keywords.txt" +#line 198 "src/lexer-keywords.txt" {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, {""}, {""}, {""}, -#line 598 "src/lexer-keywords.txt" +#line 602 "src/lexer-keywords.txt" {"v128.const", TokenType::Const, Opcode::V128Const}, {""}, -#line 607 "src/lexer-keywords.txt" +#line 611 "src/lexer-keywords.txt" {"v128.xor", TokenType::Binary, Opcode::V128Xor}, {""}, {""}, {""}, {""}, {""}, -#line 174 "src/lexer-keywords.txt" +#line 176 "src/lexer-keywords.txt" {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, {""}, -#line 175 "src/lexer-keywords.txt" +#line 177 "src/lexer-keywords.txt" {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, {""}, -#line 218 "src/lexer-keywords.txt" +#line 220 "src/lexer-keywords.txt" {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, {""}, -#line 376 "src/lexer-keywords.txt" +#line 378 "src/lexer-keywords.txt" {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, -#line 247 "src/lexer-keywords.txt" +#line 249 "src/lexer-keywords.txt" {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, {""}, {""}, {""}, -#line 39 "src/lexer-keywords.txt" +#line 41 "src/lexer-keywords.txt" {"catch", TokenType::Catch, Opcode::Catch}, {""}, {""}, -#line 486 "src/lexer-keywords.txt" +#line 488 "src/lexer-keywords.txt" {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, {""}, {""}, -#line 500 "src/lexer-keywords.txt" +#line 502 "src/lexer-keywords.txt" {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, {""}, -#line 596 "src/lexer-keywords.txt" +#line 600 "src/lexer-keywords.txt" {"v128.and", TokenType::Binary, Opcode::V128And}, {""}, {""}, {""}, {""}, -#line 534 "src/lexer-keywords.txt" +#line 536 "src/lexer-keywords.txt" {"i8x16", TokenType::I8X16}, {""}, {""}, -#line 52 "src/lexer-keywords.txt" +#line 54 "src/lexer-keywords.txt" {"elem", TokenType::Elem}, {""}, -#line 57 "src/lexer-keywords.txt" +#line 59 "src/lexer-keywords.txt" {"externref", Type::ExternRef}, {""}, {""}, -#line 595 "src/lexer-keywords.txt" +#line 599 "src/lexer-keywords.txt" {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, {""}, {""}, -#line 384 "src/lexer-keywords.txt" +#line 386 "src/lexer-keywords.txt" {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, -#line 254 "src/lexer-keywords.txt" +#line 256 "src/lexer-keywords.txt" {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, {""}, -#line 226 "src/lexer-keywords.txt" +#line 228 "src/lexer-keywords.txt" {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, {""}, {""}, -#line 159 "src/lexer-keywords.txt" +#line 161 "src/lexer-keywords.txt" {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, {""}, {""}, -#line 468 "src/lexer-keywords.txt" +#line 470 "src/lexer-keywords.txt" {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, -#line 172 "src/lexer-keywords.txt" +#line 174 "src/lexer-keywords.txt" {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, {""}, {""}, -#line 467 "src/lexer-keywords.txt" +#line 469 "src/lexer-keywords.txt" {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 36 "src/lexer-keywords.txt" +#line 38 "src/lexer-keywords.txt" {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, {""}, -#line 526 "src/lexer-keywords.txt" +#line 528 "src/lexer-keywords.txt" {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, {""}, {""}, {""}, {""}, {""}, -#line 165 "src/lexer-keywords.txt" +#line 167 "src/lexer-keywords.txt" {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, -#line 383 "src/lexer-keywords.txt" +#line 385 "src/lexer-keywords.txt" {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, -#line 253 "src/lexer-keywords.txt" +#line 255 "src/lexer-keywords.txt" {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 224 "src/lexer-keywords.txt" +#line 226 "src/lexer-keywords.txt" {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, -#line 197 "src/lexer-keywords.txt" +#line 199 "src/lexer-keywords.txt" {"i16x8.all_true", TokenType::Unary, Opcode::I16X8AllTrue}, {""}, {""}, #line 21 "src/lexer-keywords.txt" {"after", TokenType::After}, -#line 552 "src/lexer-keywords.txt" +#line 554 "src/lexer-keywords.txt" {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, -#line 173 "src/lexer-keywords.txt" +#line 175 "src/lexer-keywords.txt" {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, -#line 380 "src/lexer-keywords.txt" +#line 382 "src/lexer-keywords.txt" {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, -#line 250 "src/lexer-keywords.txt" +#line 252 "src/lexer-keywords.txt" {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, -#line 399 "src/lexer-keywords.txt" +#line 401 "src/lexer-keywords.txt" {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, -#line 262 "src/lexer-keywords.txt" +#line 264 "src/lexer-keywords.txt" {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, -#line 232 "src/lexer-keywords.txt" +#line 234 "src/lexer-keywords.txt" {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, {""}, {""}, {""}, -#line 231 "src/lexer-keywords.txt" +#line 233 "src/lexer-keywords.txt" {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, {""}, {""}, {""}, -#line 381 "src/lexer-keywords.txt" +#line 383 "src/lexer-keywords.txt" {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, -#line 251 "src/lexer-keywords.txt" +#line 253 "src/lexer-keywords.txt" {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, -#line 347 "src/lexer-keywords.txt" +#line 349 "src/lexer-keywords.txt" {"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S}, {""}, -#line 389 "src/lexer-keywords.txt" +#line 391 "src/lexer-keywords.txt" {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, {""}, {""}, {""}, {""}, {""}, -#line 525 "src/lexer-keywords.txt" +#line 527 "src/lexer-keywords.txt" {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, -#line 501 "src/lexer-keywords.txt" +#line 503 "src/lexer-keywords.txt" {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, {""}, {""}, {""}, {""}, -#line 578 "src/lexer-keywords.txt" +#line 582 "src/lexer-keywords.txt" {"start", TokenType::Start}, {""}, -#line 123 "src/lexer-keywords.txt" +#line 125 "src/lexer-keywords.txt" {"f64.abs", TokenType::Unary, Opcode::F64Abs}, -#line 61 "src/lexer-keywords.txt" +#line 63 "src/lexer-keywords.txt" {"f32.abs", TokenType::Unary, Opcode::F32Abs}, {""}, -#line 532 "src/lexer-keywords.txt" +#line 534 "src/lexer-keywords.txt" {"i8x16.sub_sat_u", TokenType::Binary, Opcode::I8X16SubSatU}, {""}, {""}, {""}, -#line 531 "src/lexer-keywords.txt" +#line 533 "src/lexer-keywords.txt" {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, -#line 617 "src/lexer-keywords.txt" +#line 621 "src/lexer-keywords.txt" {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 119 "src/lexer-keywords.txt" +#line 121 "src/lexer-keywords.txt" {"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub}, {""}, {""}, -#line 91 "src/lexer-keywords.txt" +#line 93 "src/lexer-keywords.txt" {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, {""}, -#line 609 "src/lexer-keywords.txt" +#line 613 "src/lexer-keywords.txt" {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, -#line 563 "src/lexer-keywords.txt" +#line 565 "src/lexer-keywords.txt" {"param", TokenType::Param}, -#line 357 "src/lexer-keywords.txt" +#line 359 "src/lexer-keywords.txt" {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, -#line 96 "src/lexer-keywords.txt" +#line 98 "src/lexer-keywords.txt" {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, -#line 603 "src/lexer-keywords.txt" +#line 607 "src/lexer-keywords.txt" {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, -#line 322 "src/lexer-keywords.txt" +#line 324 "src/lexer-keywords.txt" {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, -#line 34 "src/lexer-keywords.txt" +#line 36 "src/lexer-keywords.txt" {"br_table", TokenType::BrTable, Opcode::BrTable}, {""}, {""}, {""}, -#line 195 "src/lexer-keywords.txt" +#line 197 "src/lexer-keywords.txt" {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, {""}, {""}, {""}, -#line 194 "src/lexer-keywords.txt" +#line 196 "src/lexer-keywords.txt" {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, {""}, -#line 111 "src/lexer-keywords.txt" +#line 113 "src/lexer-keywords.txt" {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, #line 31 "src/lexer-keywords.txt" {"binary", TokenType::Bin}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 463 "src/lexer-keywords.txt" +#line 465 "src/lexer-keywords.txt" {"i64.trunc_sat_f64_u", TokenType::Convert, Opcode::I64TruncSatF64U}, -#line 319 "src/lexer-keywords.txt" +#line 321 "src/lexer-keywords.txt" {"i32.trunc_sat_f64_u", TokenType::Convert, Opcode::I32TruncSatF64U}, -#line 385 "src/lexer-keywords.txt" +#line 387 "src/lexer-keywords.txt" {"i64.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XchgU}, -#line 255 "src/lexer-keywords.txt" +#line 257 "src/lexer-keywords.txt" {"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU}, -#line 462 "src/lexer-keywords.txt" +#line 464 "src/lexer-keywords.txt" {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, -#line 318 "src/lexer-keywords.txt" +#line 320 "src/lexer-keywords.txt" {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, {""}, {""}, -#line 614 "src/lexer-keywords.txt" +#line 618 "src/lexer-keywords.txt" {"v128.load32_lane", TokenType::SimdLoadLane, Opcode::V128Load32Lane}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 499 "src/lexer-keywords.txt" +#line 501 "src/lexer-keywords.txt" {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, -#line 377 "src/lexer-keywords.txt" +#line 379 "src/lexer-keywords.txt" {"i64.atomic.load32_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad32U}, {""}, -#line 616 "src/lexer-keywords.txt" +#line 620 "src/lexer-keywords.txt" {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, -#line 498 "src/lexer-keywords.txt" +#line 500 "src/lexer-keywords.txt" {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, {""}, -#line 386 "src/lexer-keywords.txt" +#line 388 "src/lexer-keywords.txt" {"i64.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XorU}, -#line 256 "src/lexer-keywords.txt" +#line 258 "src/lexer-keywords.txt" {"i32.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XorU}, {""}, -#line 192 "src/lexer-keywords.txt" +#line 194 "src/lexer-keywords.txt" {"global", TokenType::Global}, -#line 215 "src/lexer-keywords.txt" +#line 217 "src/lexer-keywords.txt" {"i16x8.max_u", TokenType::Binary, Opcode::I16X8MaxU}, {""}, -#line 214 "src/lexer-keywords.txt" +#line 216 "src/lexer-keywords.txt" {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, {""}, {""}, {""}, {""}, -#line 488 "src/lexer-keywords.txt" +#line 490 "src/lexer-keywords.txt" {"i64x2.shr_u", TokenType::Binary, Opcode::I64X2ShrU}, {""}, -#line 487 "src/lexer-keywords.txt" +#line 489 "src/lexer-keywords.txt" {"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS}, {""}, -#line 549 "src/lexer-keywords.txt" +#line 551 "src/lexer-keywords.txt" {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, {""}, {""}, {""}, {""}, -#line 326 "src/lexer-keywords.txt" +#line 328 "src/lexer-keywords.txt" {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, -#line 41 "src/lexer-keywords.txt" +#line 43 "src/lexer-keywords.txt" {"catch_ref", TokenType::CatchRef}, {""}, {""}, {""}, -#line 580 "src/lexer-keywords.txt" +#line 584 "src/lexer-keywords.txt" {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, {""}, -#line 227 "src/lexer-keywords.txt" +#line 229 "src/lexer-keywords.txt" {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, {""}, {""}, {""}, {""}, {""}, -#line 516 "src/lexer-keywords.txt" +#line 518 "src/lexer-keywords.txt" {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, {""}, -#line 515 "src/lexer-keywords.txt" +#line 517 "src/lexer-keywords.txt" {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, {""}, {""}, -#line 577 "src/lexer-keywords.txt" +#line 581 "src/lexer-keywords.txt" {"shared", TokenType::Shared}, -#line 130 "src/lexer-keywords.txt" +#line 132 "src/lexer-keywords.txt" {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, -#line 68 "src/lexer-keywords.txt" +#line 70 "src/lexer-keywords.txt" {"f32.convert_i64_u", TokenType::Convert, Opcode::F32ConvertI64U}, {""}, {""}, -#line 129 "src/lexer-keywords.txt" +#line 131 "src/lexer-keywords.txt" {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, -#line 67 "src/lexer-keywords.txt" +#line 69 "src/lexer-keywords.txt" {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, {""}, {""}, {""}, {""}, {""}, -#line 60 "src/lexer-keywords.txt" +#line 62 "src/lexer-keywords.txt" {"export", TokenType::Export}, {""}, {""}, {""}, {""}, {""}, -#line 527 "src/lexer-keywords.txt" +#line 529 "src/lexer-keywords.txt" {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, -#line 553 "src/lexer-keywords.txt" +#line 555 "src/lexer-keywords.txt" {"memory", TokenType::Memory}, -#line 594 "src/lexer-keywords.txt" +#line 598 "src/lexer-keywords.txt" {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, {""}, -#line 177 "src/lexer-keywords.txt" +#line 179 "src/lexer-keywords.txt" {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, -#line 110 "src/lexer-keywords.txt" +#line 112 "src/lexer-keywords.txt" {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, -#line 372 "src/lexer-keywords.txt" +#line 374 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, {""}, -#line 371 "src/lexer-keywords.txt" +#line 373 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, {""}, -#line 190 "src/lexer-keywords.txt" +#line 192 "src/lexer-keywords.txt" {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, -#line 489 "src/lexer-keywords.txt" +#line 491 "src/lexer-keywords.txt" {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, -#line 191 "src/lexer-keywords.txt" +#line 193 "src/lexer-keywords.txt" {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 409 "src/lexer-keywords.txt" +#line 411 "src/lexer-keywords.txt" {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, {""}, {""}, -#line 59 "src/lexer-keywords.txt" +#line 61 "src/lexer-keywords.txt" {"exnref", Type::ExnRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 610 "src/lexer-keywords.txt" +#line 614 "src/lexer-keywords.txt" {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, -#line 618 "src/lexer-keywords.txt" +#line 622 "src/lexer-keywords.txt" {"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane}, -#line 178 "src/lexer-keywords.txt" +#line 180 "src/lexer-keywords.txt" {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, -#line 589 "src/lexer-keywords.txt" +#line 593 "src/lexer-keywords.txt" {"throw", TokenType::Throw, Opcode::Throw}, -#line 604 "src/lexer-keywords.txt" +#line 608 "src/lexer-keywords.txt" {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, {""}, {""}, {""}, {""}, -#line 37 "src/lexer-keywords.txt" +#line 39 "src/lexer-keywords.txt" {"call_ref", TokenType::CallRef, Opcode::CallRef}, {""}, {""}, -#line 551 "src/lexer-keywords.txt" +#line 553 "src/lexer-keywords.txt" {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, -#line 416 "src/lexer-keywords.txt" +#line 418 "src/lexer-keywords.txt" {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, -#line 278 "src/lexer-keywords.txt" +#line 280 "src/lexer-keywords.txt" {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, -#line 415 "src/lexer-keywords.txt" +#line 417 "src/lexer-keywords.txt" {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, -#line 277 "src/lexer-keywords.txt" +#line 279 "src/lexer-keywords.txt" {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, {""}, {""}, {""}, {""}, -#line 418 "src/lexer-keywords.txt" +#line 420 "src/lexer-keywords.txt" {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, -#line 280 "src/lexer-keywords.txt" +#line 282 "src/lexer-keywords.txt" {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, {""}, {""}, -#line 590 "src/lexer-keywords.txt" +#line 594 "src/lexer-keywords.txt" {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, {""}, -#line 203 "src/lexer-keywords.txt" +#line 205 "src/lexer-keywords.txt" {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, {""}, -#line 202 "src/lexer-keywords.txt" +#line 204 "src/lexer-keywords.txt" {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, {""}, {""}, -#line 615 "src/lexer-keywords.txt" +#line 619 "src/lexer-keywords.txt" {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, -#line 396 "src/lexer-keywords.txt" +#line 398 "src/lexer-keywords.txt" {"i64.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw8CmpxchgU}, -#line 259 "src/lexer-keywords.txt" +#line 261 "src/lexer-keywords.txt" {"i32.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw8CmpxchgU}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 408 "src/lexer-keywords.txt" +#line 410 "src/lexer-keywords.txt" {"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16}, -#line 271 "src/lexer-keywords.txt" +#line 273 "src/lexer-keywords.txt" {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, {""}, {""}, -#line 592 "src/lexer-keywords.txt" +#line 596 "src/lexer-keywords.txt" {"try_table", TokenType::TryTable, Opcode::TryTable}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 602 "src/lexer-keywords.txt" +#line 606 "src/lexer-keywords.txt" {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, {""}, -#line 506 "src/lexer-keywords.txt" +#line 508 "src/lexer-keywords.txt" {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, -#line 366 "src/lexer-keywords.txt" +#line 368 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U}, -#line 505 "src/lexer-keywords.txt" +#line 507 "src/lexer-keywords.txt" {"i8x16.extract_lane_s", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneS}, {""}, {""}, -#line 365 "src/lexer-keywords.txt" +#line 367 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f32x4_s", TokenType::Unary, Opcode::I32X4TruncSatF32X4S}, {""}, {""}, {""}, {""}, -#line 49 "src/lexer-keywords.txt" +#line 51 "src/lexer-keywords.txt" {"drop", TokenType::Drop, Opcode::Drop}, {""}, {""}, {""}, -#line 583 "src/lexer-keywords.txt" +#line 587 "src/lexer-keywords.txt" {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, {""}, {""}, -#line 572 "src/lexer-keywords.txt" +#line 575 "src/lexer-keywords.txt" {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 229 "src/lexer-keywords.txt" +#line 231 "src/lexer-keywords.txt" {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, -#line 217 "src/lexer-keywords.txt" +#line 219 "src/lexer-keywords.txt" {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, -#line 228 "src/lexer-keywords.txt" +#line 230 "src/lexer-keywords.txt" {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, -#line 216 "src/lexer-keywords.txt" +#line 218 "src/lexer-keywords.txt" {"i16x8.min_s", TokenType::Binary, Opcode::I16X8MinS}, {""}, {""}, {""}, {""}, {""}, -#line 403 "src/lexer-keywords.txt" +#line 405 "src/lexer-keywords.txt" {"i64.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmwCmpxchg}, -#line 266 "src/lexer-keywords.txt" +#line 268 "src/lexer-keywords.txt" {"i32.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmwCmpxchg}, {""}, -#line 121 "src/lexer-keywords.txt" +#line 123 "src/lexer-keywords.txt" {"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero}, {""}, {""}, -#line 42 "src/lexer-keywords.txt" +#line 44 "src/lexer-keywords.txt" {"catch_all_ref", TokenType::CatchAllRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 529 "src/lexer-keywords.txt" + {""}, +#line 577 "src/lexer-keywords.txt" + {"return_call_ref", TokenType::ReturnCallRef, Opcode::ReturnCallRef}, + {""}, {""}, +#line 531 "src/lexer-keywords.txt" {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, -#line 518 "src/lexer-keywords.txt" +#line 520 "src/lexer-keywords.txt" {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, -#line 528 "src/lexer-keywords.txt" +#line 530 "src/lexer-keywords.txt" {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, -#line 517 "src/lexer-keywords.txt" +#line 519 "src/lexer-keywords.txt" {"i8x16.min_s", TokenType::Binary, Opcode::I8X16MinS}, {""}, {""}, {""}, #line 26 "src/lexer-keywords.txt" {"assert_return", TokenType::AssertReturn}, -#line 550 "src/lexer-keywords.txt" +#line 552 "src/lexer-keywords.txt" {"memory.grow", TokenType::MemoryGrow, Opcode::MemoryGrow}, {""}, {""}, {""}, {""}, -#line 398 "src/lexer-keywords.txt" +#line 400 "src/lexer-keywords.txt" {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, -#line 261 "src/lexer-keywords.txt" +#line 263 "src/lexer-keywords.txt" {"i32.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8SubU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 198 "src/lexer-keywords.txt" +#line 200 "src/lexer-keywords.txt" {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, -#line 230 "src/lexer-keywords.txt" +#line 232 "src/lexer-keywords.txt" {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, {""}, {""}, {""}, -#line 340 "src/lexer-keywords.txt" +#line 342 "src/lexer-keywords.txt" {"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U}, {""}, -#line 558 "src/lexer-keywords.txt" +#line 560 "src/lexer-keywords.txt" {"nop", TokenType::Nop, Opcode::Nop}, {""}, -#line 339 "src/lexer-keywords.txt" +#line 341 "src/lexer-keywords.txt" {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 179 "src/lexer-keywords.txt" +#line 181 "src/lexer-keywords.txt" {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, {""}, {""}, -#line 153 "src/lexer-keywords.txt" +#line 155 "src/lexer-keywords.txt" {"f64x2.abs", TokenType::Unary, Opcode::F64X2Abs}, {""}, {""}, {""}, -#line 490 "src/lexer-keywords.txt" +#line 492 "src/lexer-keywords.txt" {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, -#line 156 "src/lexer-keywords.txt" +#line 158 "src/lexer-keywords.txt" {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, {""}, -#line 476 "src/lexer-keywords.txt" +#line 478 "src/lexer-keywords.txt" {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, -#line 502 "src/lexer-keywords.txt" +#line 504 "src/lexer-keywords.txt" {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, -#line 530 "src/lexer-keywords.txt" +#line 532 "src/lexer-keywords.txt" {"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 171 "src/lexer-keywords.txt" +#line 173 "src/lexer-keywords.txt" {"f64x2.pmin", TokenType::Binary, Opcode::F64X2PMin}, {""}, {""}, -#line 544 "src/lexer-keywords.txt" +#line 546 "src/lexer-keywords.txt" {"loop", TokenType::Loop, Opcode::Loop}, {""}, {""}, {""}, {""}, {""}, -#line 461 "src/lexer-keywords.txt" +#line 463 "src/lexer-keywords.txt" {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, -#line 317 "src/lexer-keywords.txt" +#line 319 "src/lexer-keywords.txt" {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, -#line 133 "src/lexer-keywords.txt" +#line 135 "src/lexer-keywords.txt" {"f64.eq", TokenType::Compare, Opcode::F64Eq}, -#line 72 "src/lexer-keywords.txt" +#line 74 "src/lexer-keywords.txt" {"f32.eq", TokenType::Compare, Opcode::F32Eq}, -#line 460 "src/lexer-keywords.txt" +#line 462 "src/lexer-keywords.txt" {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, -#line 316 "src/lexer-keywords.txt" +#line 318 "src/lexer-keywords.txt" {"i32.trunc_sat_f32_s", TokenType::Convert, Opcode::I32TruncSatF32S}, {""}, {""}, {""}, -#line 417 "src/lexer-keywords.txt" +#line 419 "src/lexer-keywords.txt" {"i64.eq", TokenType::Compare, Opcode::I64Eq}, -#line 279 "src/lexer-keywords.txt" +#line 281 "src/lexer-keywords.txt" {"i32.eq", TokenType::Compare, Opcode::I32Eq}, -#line 325 "src/lexer-keywords.txt" +#line 327 "src/lexer-keywords.txt" {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, {""}, {""}, {""}, {""}, -#line 442 "src/lexer-keywords.txt" +#line 444 "src/lexer-keywords.txt" {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, -#line 299 "src/lexer-keywords.txt" +#line 301 "src/lexer-keywords.txt" {"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt}, {""}, {""}, -#line 382 "src/lexer-keywords.txt" +#line 384 "src/lexer-keywords.txt" {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, -#line 252 "src/lexer-keywords.txt" +#line 254 "src/lexer-keywords.txt" {"i32.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw16CmpxchgU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 97 "src/lexer-keywords.txt" +#line 99 "src/lexer-keywords.txt" {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 327 "src/lexer-keywords.txt" +#line 329 "src/lexer-keywords.txt" {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, {""}, {""}, {""}, {""}, {""}, -#line 482 "src/lexer-keywords.txt" +#line 484 "src/lexer-keywords.txt" {"i64x2.extend_low_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendLowI32X4U}, {""}, -#line 480 "src/lexer-keywords.txt" +#line 482 "src/lexer-keywords.txt" {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, -#line 522 "src/lexer-keywords.txt" +#line 524 "src/lexer-keywords.txt" {"i8x16.popcnt", TokenType::Unary, Opcode::I8X16Popcnt}, {""}, {""}, -#line 608 "src/lexer-keywords.txt" +#line 612 "src/lexer-keywords.txt" {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, {""}, {""}, {""}, {""}, {""}, -#line 128 "src/lexer-keywords.txt" +#line 130 "src/lexer-keywords.txt" {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, -#line 66 "src/lexer-keywords.txt" +#line 68 "src/lexer-keywords.txt" {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, {""}, {""}, -#line 127 "src/lexer-keywords.txt" +#line 129 "src/lexer-keywords.txt" {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, -#line 65 "src/lexer-keywords.txt" +#line 67 "src/lexer-keywords.txt" {"f32.convert_i32_s", TokenType::Convert, Opcode::F32ConvertI32S}, {""}, -#line 368 "src/lexer-keywords.txt" +#line 370 "src/lexer-keywords.txt" {"i32x4.extend_high_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendHighI16X8U}, {""}, -#line 367 "src/lexer-keywords.txt" +#line 369 "src/lexer-keywords.txt" {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 170 "src/lexer-keywords.txt" +#line 172 "src/lexer-keywords.txt" {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, {""}, {""}, {""}, {""}, -#line 613 "src/lexer-keywords.txt" +#line 617 "src/lexer-keywords.txt" {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, {""}, -#line 620 "src/lexer-keywords.txt" +#line 624 "src/lexer-keywords.txt" {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, {""}, {""}, -#line 359 "src/lexer-keywords.txt" +#line 361 "src/lexer-keywords.txt" {"i32x4.extadd_pairwise_i16x8_u", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8U}, {""}, -#line 358 "src/lexer-keywords.txt" +#line 360 "src/lexer-keywords.txt" {"i32x4.extadd_pairwise_i16x8_s", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8S}, {""}, {""}, #line 25 "src/lexer-keywords.txt" {"assert_malformed", TokenType::AssertMalformed}, {""}, {""}, {""}, -#line 51 "src/lexer-keywords.txt" +#line 53 "src/lexer-keywords.txt" {"elem.drop", TokenType::ElemDrop, Opcode::ElemDrop}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 493 "src/lexer-keywords.txt" +#line 495 "src/lexer-keywords.txt" {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, -#line 524 "src/lexer-keywords.txt" +#line 526 "src/lexer-keywords.txt" {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, -#line 491 "src/lexer-keywords.txt" +#line 493 "src/lexer-keywords.txt" {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, {""}, {""}, {""}, {""}, {""}, -#line 370 "src/lexer-keywords.txt" +#line 372 "src/lexer-keywords.txt" {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, {""}, -#line 369 "src/lexer-keywords.txt" +#line 371 "src/lexer-keywords.txt" {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 363 "src/lexer-keywords.txt" +#line 365 "src/lexer-keywords.txt" {"i32x4.extmul_high_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8U}, {""}, -#line 361 "src/lexer-keywords.txt" +#line 363 "src/lexer-keywords.txt" {"i32x4.extmul_high_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8S}, {""}, -#line 147 "src/lexer-keywords.txt" +#line 149 "src/lexer-keywords.txt" {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, {""}, {""}, -#line 321 "src/lexer-keywords.txt" +#line 323 "src/lexer-keywords.txt" {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, {""}, {""}, {""}, {""}, -#line 621 "src/lexer-keywords.txt" +#line 625 "src/lexer-keywords.txt" {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 132 "src/lexer-keywords.txt" +#line 134 "src/lexer-keywords.txt" {"f64.div", TokenType::Binary, Opcode::F64Div}, -#line 71 "src/lexer-keywords.txt" +#line 73 "src/lexer-keywords.txt" {"f32.div", TokenType::Binary, Opcode::F32Div}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 233 "src/lexer-keywords.txt" +#line 235 "src/lexer-keywords.txt" {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, {""}, {""}, -#line 193 "src/lexer-keywords.txt" +#line 195 "src/lexer-keywords.txt" {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, {""}, -#line 562 "src/lexer-keywords.txt" +#line 564 "src/lexer-keywords.txt" {"pagesize", TokenType::PageSize}, {""}, {""}, -#line 95 "src/lexer-keywords.txt" +#line 97 "src/lexer-keywords.txt" {"f32x4.convert_i32x4_u", TokenType::Unary, Opcode::F32X4ConvertI32X4U}, {""}, -#line 94 "src/lexer-keywords.txt" +#line 96 "src/lexer-keywords.txt" {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 362 "src/lexer-keywords.txt" +#line 364 "src/lexer-keywords.txt" {"i32x4.extmul_low_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8U}, {""}, -#line 360 "src/lexer-keywords.txt" +#line 362 "src/lexer-keywords.txt" {"i32x4.extmul_low_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8S}, {""}, {""}, -#line 131 "src/lexer-keywords.txt" +#line 133 "src/lexer-keywords.txt" {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, -#line 69 "src/lexer-keywords.txt" +#line 71 "src/lexer-keywords.txt" {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, -#line 533 "src/lexer-keywords.txt" +#line 535 "src/lexer-keywords.txt" {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, {""}, {""}, -#line 497 "src/lexer-keywords.txt" +#line 499 "src/lexer-keywords.txt" {"i8x16.abs", TokenType::Unary, Opcode::I8X16Abs}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 225 "src/lexer-keywords.txt" +#line 227 "src/lexer-keywords.txt" {"i16x8.relaxed_q15mulr_s", TokenType::Binary, Opcode::I16X8RelaxedQ15mulrS}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 200 "src/lexer-keywords.txt" +#line 202 "src/lexer-keywords.txt" {"i16x8.relaxed_dot_i8x16_i7x16_s", TokenType::Binary, Opcode::I16X8DotI8X16I7X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 443 "src/lexer-keywords.txt" +#line 445 "src/lexer-keywords.txt" {"i64.reinterpret_f64", TokenType::Convert, Opcode::I64ReinterpretF64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 244 "src/lexer-keywords.txt" +#line 246 "src/lexer-keywords.txt" {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, {""}, -#line 243 "src/lexer-keywords.txt" +#line 245 "src/lexer-keywords.txt" {"i16x8.extend_low_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendLowI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1593,36 +1601,36 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 220 "src/lexer-keywords.txt" +#line 222 "src/lexer-keywords.txt" {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, {""}, -#line 219 "src/lexer-keywords.txt" +#line 221 "src/lexer-keywords.txt" {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, {""}, {""}, -#line 238 "src/lexer-keywords.txt" +#line 240 "src/lexer-keywords.txt" {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, {""}, -#line 236 "src/lexer-keywords.txt" +#line 238 "src/lexer-keywords.txt" {"i16x8.extmul_low_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16S}, {""}, {""}, {""}, -#line 548 "src/lexer-keywords.txt" +#line 550 "src/lexer-keywords.txt" {"memory.copy", TokenType::MemoryCopy, Opcode::MemoryCopy}, {""}, -#line 479 "src/lexer-keywords.txt" +#line 481 "src/lexer-keywords.txt" {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 157 "src/lexer-keywords.txt" +#line 159 "src/lexer-keywords.txt" {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 470 "src/lexer-keywords.txt" +#line 472 "src/lexer-keywords.txt" {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 483 "src/lexer-keywords.txt" +#line 485 "src/lexer-keywords.txt" {"i64x2.extend_high_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendHighI32X4U}, {""}, -#line 481 "src/lexer-keywords.txt" +#line 483 "src/lexer-keywords.txt" {"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 20 "src/lexer-keywords.txt" @@ -1631,28 +1639,28 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 27 "src/lexer-keywords.txt" {"assert_trap", TokenType::AssertTrap}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 597 "src/lexer-keywords.txt" +#line 601 "src/lexer-keywords.txt" {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 150 "src/lexer-keywords.txt" +#line 152 "src/lexer-keywords.txt" {"f64.sub", TokenType::Binary, Opcode::F64Sub}, -#line 88 "src/lexer-keywords.txt" +#line 90 "src/lexer-keywords.txt" {"f32.sub", TokenType::Binary, Opcode::F32Sub}, {""}, {""}, {""}, {""}, {""}, -#line 455 "src/lexer-keywords.txt" +#line 457 "src/lexer-keywords.txt" {"i64.sub", TokenType::Binary, Opcode::I64Sub}, -#line 311 "src/lexer-keywords.txt" +#line 313 "src/lexer-keywords.txt" {"i32.sub", TokenType::Binary, Opcode::I32Sub}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 146 "src/lexer-keywords.txt" +#line 148 "src/lexer-keywords.txt" {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 494 "src/lexer-keywords.txt" +#line 496 "src/lexer-keywords.txt" {"i64x2.extmul_high_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U}, {""}, -#line 492 "src/lexer-keywords.txt" +#line 494 "src/lexer-keywords.txt" {"i64x2.extmul_high_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1666,7 +1674,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 22 "src/lexer-keywords.txt" {"assert_exception", TokenType::AssertException}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 199 "src/lexer-keywords.txt" +#line 201 "src/lexer-keywords.txt" {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1674,26 +1682,26 @@ Perfect_Hash::InWordSet (const char *str, size_t len) #line 23 "src/lexer-keywords.txt" {"assert_exhaustion", TokenType::AssertExhaustion}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 503 "src/lexer-keywords.txt" +#line 505 "src/lexer-keywords.txt" {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, {""}, -#line 201 "src/lexer-keywords.txt" +#line 203 "src/lexer-keywords.txt" {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 504 "src/lexer-keywords.txt" +#line 506 "src/lexer-keywords.txt" {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, {""}, {""}, {""}, {""}, {""}, -#line 547 "src/lexer-keywords.txt" +#line 549 "src/lexer-keywords.txt" {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 85 "src/lexer-keywords.txt" +#line 87 "src/lexer-keywords.txt" {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1703,63 +1711,63 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 405 "src/lexer-keywords.txt" +#line 407 "src/lexer-keywords.txt" {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, -#line 268 "src/lexer-keywords.txt" +#line 270 "src/lexer-keywords.txt" {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 545 "src/lexer-keywords.txt" +#line 547 "src/lexer-keywords.txt" {"memory.atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 242 "src/lexer-keywords.txt" +#line 244 "src/lexer-keywords.txt" {"i16x8.extend_high_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendHighI8X16U}, {""}, -#line 241 "src/lexer-keywords.txt" +#line 243 "src/lexer-keywords.txt" {"i16x8.extend_high_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendHighI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 28 "src/lexer-keywords.txt" {"assert_unlinkable", TokenType::AssertUnlinkable}, {""}, {""}, -#line 300 "src/lexer-keywords.txt" +#line 302 "src/lexer-keywords.txt" {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, {""}, {""}, {""}, {""}, -#line 182 "src/lexer-keywords.txt" +#line 184 "src/lexer-keywords.txt" {"f64x2.convert_low_i32x4_u", TokenType::Unary, Opcode::F64X2ConvertLowI32X4U}, {""}, -#line 181 "src/lexer-keywords.txt" +#line 183 "src/lexer-keywords.txt" {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, {""}, -#line 235 "src/lexer-keywords.txt" +#line 237 "src/lexer-keywords.txt" {"i16x8.extadd_pairwise_i8x16_u", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16U}, {""}, -#line 234 "src/lexer-keywords.txt" +#line 236 "src/lexer-keywords.txt" {"i16x8.extadd_pairwise_i8x16_s", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 546 "src/lexer-keywords.txt" +#line 548 "src/lexer-keywords.txt" {"memory.atomic.wait32", TokenType::AtomicWait, Opcode::MemoryAtomicWait32}, {""}, {""}, {""}, {""}, {""}, -#line 520 "src/lexer-keywords.txt" +#line 522 "src/lexer-keywords.txt" {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, {""}, -#line 519 "src/lexer-keywords.txt" +#line 521 "src/lexer-keywords.txt" {"i8x16.narrow_i16x8_s", TokenType::Binary, Opcode::I8X16NarrowI16X8S}, {""}, -#line 222 "src/lexer-keywords.txt" +#line 224 "src/lexer-keywords.txt" {"i16x8.q15mulr_sat_s", TokenType::Binary, Opcode::I16X8Q15mulrSatS}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 29 "src/lexer-keywords.txt" {"atomic.fence", TokenType::AtomicFence, Opcode::AtomicFence}, {""}, {""}, {""}, {""}, -#line 239 "src/lexer-keywords.txt" +#line 241 "src/lexer-keywords.txt" {"i16x8.extmul_high_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16U}, {""}, -#line 237 "src/lexer-keywords.txt" +#line 239 "src/lexer-keywords.txt" {"i16x8.extmul_high_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1777,7 +1785,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 183 "src/lexer-keywords.txt" +#line 185 "src/lexer-keywords.txt" {"f64x2.promote_low_f32x4", TokenType::Unary, Opcode::F64X2PromoteLowF32X4} }; diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 0ee5e80526..d24f2f5c37 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -40,6 +40,8 @@ class NameResolver : public ExprVisitor::DelegateNop { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; + Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; Result OnCallExpr(CallExpr*) override; Result OnCallIndirectExpr(CallIndirectExpr*) override; @@ -48,6 +50,7 @@ class NameResolver : public ExprVisitor::DelegateNop { Result OnDelegateExpr(TryExpr*) override; Result OnReturnCallExpr(ReturnCallExpr*) override; Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override; + Result OnReturnCallRefExpr(ReturnCallRefExpr*) override; Result OnGlobalGetExpr(GlobalGetExpr*) override; Result OnGlobalSetExpr(GlobalSetExpr*) override; Result BeginIfExpr(IfExpr*) override; @@ -277,6 +280,16 @@ Result NameResolver::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result NameResolver::OnBrOnNonNullExpr(BrOnNonNullExpr* expr) { + ResolveLabelVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnBrOnNullExpr(BrOnNullExpr* expr) { + ResolveLabelVar(&expr->var); + return Result::Ok; +} + Result NameResolver::OnBrTableExpr(BrTableExpr* expr) { for (Var& target : expr->targets) ResolveLabelVar(&target); @@ -315,6 +328,11 @@ Result NameResolver::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { return Result::Ok; } +Result NameResolver::OnReturnCallRefExpr(ReturnCallRefExpr* expr) { + ResolveFuncTypeVar(&expr->sig_type); + return Result::Ok; +} + Result NameResolver::OnGlobalGetExpr(GlobalGetExpr* expr) { ResolveGlobalVar(&expr->var); return Result::Ok; diff --git a/src/shared-validator.cc b/src/shared-validator.cc index 7e7740601e..5fac43aa72 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -786,6 +786,18 @@ Result SharedValidator::OnBrIf(const Location& loc, Var depth) { return result; } +Result SharedValidator::OnBrOnNonNull(const Location& loc, Var depth) { + Result result = CheckInstr(Opcode::BrOnNonNull, loc); + result |= typechecker_.OnBrOnNonNull(depth.index()); + return result; +} + +Result SharedValidator::OnBrOnNull(const Location& loc, Var depth) { + Result result = CheckInstr(Opcode::BrOnNull, loc); + result |= typechecker_.OnBrOnNull(depth.index()); + return result; +} + Result SharedValidator::BeginBrTable(const Location& loc) { Result result = CheckInstr(Opcode::BrTable, loc); result |= typechecker_.BeginBrTable(); @@ -1112,6 +1124,12 @@ Result SharedValidator::OnNop(const Location& loc) { return result; } +Result SharedValidator::OnRefAsNonNull(const Location& loc) { + Result result = CheckInstr(Opcode::Nop, loc); + result |= typechecker_.OnRefAsNonNullExpr(); + return result; +} + Result SharedValidator::OnRefFunc(const Location& loc, Var func_var) { Result result = CheckInstr(Opcode::RefFunc, loc); result |= CheckFuncIndex(func_var); @@ -1192,6 +1210,16 @@ Result SharedValidator::OnReturnCallIndirect(const Location& loc, return result; } +Result SharedValidator::OnReturnCallRef(const Location& loc, + Var function_type_var) { + Result result = CheckInstr(Opcode::ReturnCallRef, loc); + FuncType func_type; + result |= typechecker_.OnReturnCallRef(function_type_var.to_type()); + result |= CheckFuncTypeIndex(function_type_var, &func_type); + result |= typechecker_.OnReturnCall(func_type.params, func_type.results); + return result; +} + Result SharedValidator::OnReturn(const Location& loc) { Result result = CheckInstr(Opcode::Return, loc); result |= typechecker_.OnReturn(); diff --git a/src/type-checker.cc b/src/type-checker.cc index 42c0c2951f..c13e3ad4de 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -404,6 +404,21 @@ Result TypeChecker::PopAndCheck3Types(Type expected1, return result; } +Result TypeChecker::PopAndCheckReference(Type* actual, const char* desc) { + *actual = Type::Any; + Result result = PeekType(0, actual); + + // Type::Any is a valid value for dead code, and replacing + // it with anything might break the syntax checker. + if (*actual != Type::Any && !actual->IsRef()) { + result = Result::Error; + } + + PrintStackIfFailed(result, desc, Type::FuncRef); + result |= DropTypes(1); + return result; +} + // Some paramater types depend on the memory being used. // For example load/store operands, or memory.fill operands. static Type GetMemoryParam(Type param, const Limits* limits) { @@ -554,6 +569,49 @@ Result TypeChecker::OnBrIf(Index depth) { return result; } +static Type convertRefNullToRef(Type type) { + if (type == Type::ExternRef || type == Type::FuncRef) { + return Type(type, Type::ReferenceNonNull); + } + + assert(type.IsReferenceWithIndex()); + return Type(Type::Ref, type.GetReferenceIndex()); +} + +Result TypeChecker::OnBrOnNonNull(Index depth) { + Type actual; + CHECK_RESULT(PopAndCheckReference(&actual, "br_on_non_null")); + if (actual != Type::Any) { + PushType(convertRefNullToRef(actual)); + } + + Label* label; + CHECK_RESULT(GetLabel(depth, &label)); + Result result = PopAndCheckSignature(label->br_types(), "br_on_non_null"); + PushTypes(label->br_types()); + + if (actual != Type::Any) { + result |= DropTypes(1); + } + return result; +} + +Result TypeChecker::OnBrOnNull(Index depth) { + Type actual; + CHECK_RESULT(PopAndCheckReference(&actual, "br_on_null")); + + Label* label; + CHECK_RESULT(GetLabel(depth, &label)); + Result result = PopAndCheckSignature(label->br_types(), "br_on_null"); + PushTypes(label->br_types()); + + if (actual != Type::Any) { + actual = convertRefNullToRef(actual); + } + PushType(actual); + return result; +} + Result TypeChecker::BeginBrTable() { br_table_sig_ = nullptr; return PopAndCheck1Type(Type::I32, "br_table"); @@ -630,6 +688,10 @@ Result TypeChecker::OnReturnCallIndirect(const TypeVector& param_types, return result; } +Result TypeChecker::OnReturnCallRef(Type type) { + return PopAndCheck1Type(type, "return_call_ref"); +} + Result TypeChecker::OnCompare(Opcode opcode) { return CheckOpcode2(opcode); } @@ -861,6 +923,16 @@ Result TypeChecker::OnTableFill(Type elem_type, const Limits& limits) { "table.fill"); } +Result TypeChecker::OnRefAsNonNullExpr() { + Type actual; + CHECK_RESULT(PopAndCheckReference(&actual, "ref.as_non_null")); + if (actual != Type::Any) { + actual = convertRefNullToRef(actual); + } + PushType(actual); + return Result::Ok; +} + Result TypeChecker::OnRefFuncExpr(Index func_type) { PushType(Type(Type::Ref, func_type)); return Result::Ok; diff --git a/src/validator.cc b/src/validator.cc index e92f9e5863..76b8f31c40 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -98,6 +98,8 @@ class Validator : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; + Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; Result OnCallExpr(CallExpr*) override; Result OnCallIndirectExpr(CallIndirectExpr*) override; @@ -132,6 +134,7 @@ class Validator : public ExprVisitor::Delegate { Result OnTableGrowExpr(TableGrowExpr*) override; Result OnTableSizeExpr(TableSizeExpr*) override; Result OnTableFillExpr(TableFillExpr*) override; + Result OnRefAsNonNullExpr(RefAsNonNullExpr*) override; Result OnRefFuncExpr(RefFuncExpr*) override; Result OnRefNullExpr(RefNullExpr*) override; Result OnRefIsNullExpr(RefIsNullExpr*) override; @@ -139,6 +142,7 @@ class Validator : public ExprVisitor::Delegate { Result OnReturnExpr(ReturnExpr*) override; Result OnReturnCallExpr(ReturnCallExpr*) override; Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override; + Result OnReturnCallRefExpr(ReturnCallRefExpr*) override; Result OnSelectExpr(SelectExpr*) override; Result OnStoreExpr(StoreExpr*) override; Result OnUnaryExpr(UnaryExpr*) override; @@ -333,6 +337,16 @@ Result Validator::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result Validator::OnBrOnNonNullExpr(BrOnNonNullExpr* expr) { + result_ |= validator_.OnBrOnNonNull(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnBrOnNullExpr(BrOnNullExpr* expr) { + result_ |= validator_.OnBrOnNull(expr->loc, expr->var); + return Result::Ok; +} + Result Validator::OnBrTableExpr(BrTableExpr* expr) { result_ |= validator_.BeginBrTable(expr->loc); for (const Var& var : expr->targets) { @@ -516,6 +530,11 @@ Result Validator::OnTableFillExpr(TableFillExpr* expr) { return Result::Ok; } +Result Validator::OnRefAsNonNullExpr(RefAsNonNullExpr* expr) { + result_ |= validator_.OnRefAsNonNull(expr->loc); + return Result::Ok; +} + Result Validator::OnRefFuncExpr(RefFuncExpr* expr) { result_ |= validator_.OnRefFunc(expr->loc, expr->var); return Result::Ok; @@ -552,6 +571,11 @@ Result Validator::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { return Result::Ok; } +Result Validator::OnReturnCallRefExpr(ReturnCallRefExpr* expr) { + result_ |= validator_.OnReturnCallRef(expr->loc, expr->sig_type); + return Result::Ok; +} + Result Validator::OnSelectExpr(SelectExpr* expr) { result_ |= validator_.OnSelect(expr->loc, expr->result_type.size(), expr->result_type.data()); diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 79378aeea2..ed0b155125 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -157,10 +157,13 @@ bool IsPlainInstr(TokenType token_type) { case TokenType::Select: case TokenType::Br: case TokenType::BrIf: + case TokenType::BrOnNonNull: + case TokenType::BrOnNull: case TokenType::BrTable: case TokenType::Return: case TokenType::ReturnCall: case TokenType::ReturnCallIndirect: + case TokenType::ReturnCallRef: case TokenType::Call: case TokenType::CallIndirect: case TokenType::CallRef: @@ -193,6 +196,7 @@ bool IsPlainInstr(TokenType token_type) { case TokenType::Throw: case TokenType::ThrowRef: case TokenType::Rethrow: + case TokenType::RefAsNonNull: case TokenType::RefFunc: case TokenType::RefNull: case TokenType::RefIsNull: @@ -2402,6 +2406,16 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); break; + case TokenType::BrOnNonNull: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::BrOnNull: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + case TokenType::BrTable: { Consume(); auto expr = std::make_unique(loc); @@ -2456,6 +2470,15 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { break; } + case TokenType::ReturnCallRef: { + ErrorUnlessOpcodeEnabled(Consume()); + auto expr = std::make_unique(loc); + CHECK_RESULT(ParseVar(&expr->sig_type)); + expr->sig_type.set_opt_type(Type::RefNull); + *out_expr = std::move(expr); + break; + } + case TokenType::LocalGet: Consume(); CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); @@ -2626,6 +2649,11 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { break; } + case TokenType::RefAsNonNull: + ErrorUnlessOpcodeEnabled(Consume()); + out_expr->reset(new RefAsNonNullExpr(Opcode::RefAsNonNull, loc)); + break; + case TokenType::RefFunc: ErrorUnlessOpcodeEnabled(Consume()); CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); diff --git a/src/wat-writer.cc b/src/wat-writer.cc index c090b62d6f..5da55e8535 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -554,6 +554,8 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; + Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; Result OnCallExpr(CallExpr*) override; Result OnCallIndirectExpr(CallIndirectExpr*) override; @@ -588,6 +590,7 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result OnTableGrowExpr(TableGrowExpr*) override; Result OnTableSizeExpr(TableSizeExpr*) override; Result OnTableFillExpr(TableFillExpr*) override; + Result OnRefAsNonNullExpr(RefAsNonNullExpr*) override; Result OnRefFuncExpr(RefFuncExpr*) override; Result OnRefNullExpr(RefNullExpr*) override; Result OnRefIsNullExpr(RefIsNullExpr*) override; @@ -595,6 +598,7 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result OnReturnExpr(ReturnExpr*) override; Result OnReturnCallExpr(ReturnCallExpr*) override; Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override; + Result OnReturnCallRefExpr(ReturnCallRefExpr*) override; Result OnSelectExpr(SelectExpr*) override; Result OnStoreExpr(StoreExpr*) override; Result OnUnaryExpr(UnaryExpr*) override; @@ -655,6 +659,19 @@ Result WatWriter::ExprVisitorDelegate::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnBrOnNonNullExpr( + BrOnNonNullExpr* expr) { + writer_->WritePutsSpace(Opcode::BrOnNonNull_Opcode.GetName()); + writer_->WriteBrVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnBrOnNullExpr(BrOnNullExpr* expr) { + writer_->WritePutsSpace(Opcode::BrOnNull_Opcode.GetName()); + writer_->WriteBrVar(expr->var, NextChar::Newline); + return Result::Ok; +} + Result WatWriter::ExprVisitorDelegate::OnBrTableExpr(BrTableExpr* expr) { writer_->WritePutsSpace(Opcode::BrTable_Opcode.GetName()); for (const Var& var : expr->targets) { @@ -883,6 +900,12 @@ Result WatWriter::ExprVisitorDelegate::OnTableFillExpr(TableFillExpr* expr) { return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnRefAsNonNullExpr( + RefAsNonNullExpr* expr) { + writer_->WritePutsNewline(Opcode::RefAsNonNull_Opcode.GetName()); + return Result::Ok; +} + Result WatWriter::ExprVisitorDelegate::OnRefFuncExpr(RefFuncExpr* expr) { writer_->WritePutsSpace(Opcode::RefFunc_Opcode.GetName()); writer_->WriteVar(expr->var, NextChar::Newline); @@ -934,6 +957,13 @@ Result WatWriter::ExprVisitorDelegate::OnReturnCallIndirectExpr( return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnReturnCallRefExpr( + ReturnCallRefExpr* expr) { + writer_->WritePutsSpace(Opcode::ReturnCallRef_Opcode.GetName()); + writer_->WriteVar(expr->sig_type, NextChar::Newline); + return Result::Ok; +} + Result WatWriter::ExprVisitorDelegate::OnSelectExpr(SelectExpr* expr) { writer_->WritePutsSpace(Opcode::Select_Opcode.GetName()); if (!expr->result_type.empty()) { diff --git a/test/spec/function-references/br_on_non_null.txt b/test/spec/function-references/br_on_non_null.txt new file mode 100644 index 0000000000..83dbbe22f4 --- /dev/null +++ b/test/spec/function-references/br_on_non_null.txt @@ -0,0 +1,7 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/br_on_non_null.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/br_on_non_null.wast:37: assert_trap passed: unreachable executed +9/9 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/br_on_null.txt b/test/spec/function-references/br_on_null.txt new file mode 100644 index 0000000000..a81579f1dc --- /dev/null +++ b/test/spec/function-references/br_on_null.txt @@ -0,0 +1,7 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/br_on_null.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/br_on_null.wast:32: assert_trap passed: unreachable executed +9/9 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/ref_as_non_null.txt b/test/spec/function-references/ref_as_non_null.txt new file mode 100644 index 0000000000..99b9e552ae --- /dev/null +++ b/test/spec/function-references/ref_as_non_null.txt @@ -0,0 +1,11 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/ref_as_non_null.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/ref_as_non_null.wast:25: assert_trap passed: unreachable executed +out/test/spec/function-references/ref_as_non_null.wast:27: assert_trap passed: null reference +out/test/spec/function-references/ref_as_non_null.wast:32: assert_invalid passed: + out/test/spec/function-references/ref_as_non_null/ref_as_non_null.1.wasm:000002c: error: type mismatch in call, expected [(ref 0)] but got [(ref null 0)] + 000002c: error: OnCallExpr callback failed +7/7 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/return_call_ref.txt b/test/spec/function-references/return_call_ref.txt new file mode 100644 index 0000000000..7d32cd582a --- /dev/null +++ b/test/spec/function-references/return_call_ref.txt @@ -0,0 +1,42 @@ +;;; SLOW: +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/return_call_ref.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/return_call_ref.wast:183: assert_trap passed: null function reference +out/test/spec/function-references/return_call_ref.wast:232: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.2.wasm:000002d: error: return signatures have inconsistent types: expected [(ref 0)], got [(ref null 0)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:243: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.3.wasm:000002d: error: return signatures have inconsistent types: expected [(ref 0)], got [(ref func)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:254: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.4.wasm:000002c: error: return signatures have inconsistent types: expected [(ref 0)], got [funcref] + 000002c: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:265: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.5.wasm:000002d: error: return signatures have inconsistent types: expected [(ref null 0)], got [(ref func)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:276: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.6.wasm:000002c: error: return signatures have inconsistent types: expected [(ref null 0)], got [funcref] + 000002c: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:287: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.7.wasm:0000029: error: return signatures have inconsistent types: expected [(ref func)], got [funcref] + 0000029: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:306: assert_trap passed: unreachable executed +out/test/spec/function-references/return_call_ref.wast:319: assert_trap passed: unreachable executed +out/test/spec/function-references/return_call_ref.wast:334: assert_trap passed: unreachable executed +out/test/spec/function-references/return_call_ref.wast:337: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.11.wasm:0000042: error: type mismatch in return_call, expected [i32] but got [i64] + 0000042: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:353: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.12.wasm:0000043: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000043: error: EndFunctionBody callback failed +out/test/spec/function-references/return_call_ref.wast:369: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.13.wasm:000001f: error: type mismatch in return_call_ref, expected [(ref null 0)] but got [externref] + 000001f: error: OnReturnCallRefExpr callback failed +out/test/spec/function-references/return_call_ref.wast:379: assert_invalid passed: + out/test/spec/function-references/return_call_ref/return_call_ref.14.wasm:0000022: error: type mismatch in return_call_ref, expected [(ref null 0)] but got [funcref] + out/test/spec/function-references/return_call_ref/return_call_ref.14.wasm:0000022: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000022: error: OnReturnCallRefExpr callback failed +50/50 tests passed. +;;; STDOUT ;;) From a7701de5ed795ad226bcb729f5644e8c27b8f17f Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 8 Apr 2025 08:03:59 +0000 Subject: [PATCH 3/6] Support table initializers --- include/wabt/binary-reader-logging.h | 10 +- include/wabt/binary-reader-nop.h | 10 +- include/wabt/binary-reader.h | 10 +- include/wabt/interp/interp-inl.h | 10 +- include/wabt/interp/interp.h | 9 +- include/wabt/ir.h | 3 +- include/wabt/shared-validator.h | 2 +- src/apply-names.cc | 8 + src/binary-reader-ir.cc | 26 +- src/binary-reader-logging.cc | 12 +- src/binary-reader-objdump.cc | 31 +- src/binary-reader.cc | 32 +- src/binary-writer.cc | 11 +- src/interp/binary-reader-interp.cc | 39 +- src/interp/interp-wasm-c-api.cc | 3 +- src/interp/interp.cc | 43 +- src/ir.cc | 24 +- src/resolve-names.cc | 9 + src/shared-validator.cc | 19 +- src/test-interp.cc | 13 +- src/tools/spectest-interp.cc | 9 +- src/validator.cc | 22 +- src/wast-parser.cc | 16 +- src/wat-writer.cc | 3 +- test/dump/call_ref.txt | 2 +- test/dump/relocations-all-features.txt | 53 ++- test/dump/typed_func_refs_params.txt | 2 +- test/dump/typed_func_refs_results.txt | 2 +- test/roundtrip/fold-callref.txt | 2 +- test/spec/function-references/binary.txt | 238 ++++++++++ test/spec/function-references/data.txt | 66 +++ test/spec/function-references/elem.txt | 90 ++++ test/spec/function-references/global.txt | 4 +- test/spec/function-references/if.txt | 409 ++++++++++++++++++ test/spec/function-references/linking.txt | 118 +++++ test/spec/function-references/local_get.txt | 54 +++ test/spec/function-references/ref.txt | 2 +- test/spec/function-references/ref_is_null.txt | 14 + test/spec/function-references/ref_null.txt | 6 + test/spec/function-references/return_call.txt | 39 ++ .../return_call_indirect.txt | 124 ++++++ test/spec/function-references/select.txt | 102 +++++ test/spec/function-references/table-sub.txt | 12 + test/spec/function-references/table.txt | 75 ++++ .../function-references/unreached-invalid.txt | 371 ++++++++++++++++ .../function-references/unreached-valid.txt | 16 + test/spec/memory64/table.txt | 8 +- test/spec/table.txt | 4 +- 48 files changed, 2060 insertions(+), 127 deletions(-) create mode 100644 test/spec/function-references/binary.txt create mode 100644 test/spec/function-references/data.txt create mode 100644 test/spec/function-references/elem.txt create mode 100644 test/spec/function-references/if.txt create mode 100644 test/spec/function-references/linking.txt create mode 100644 test/spec/function-references/local_get.txt create mode 100644 test/spec/function-references/ref_is_null.txt create mode 100644 test/spec/function-references/ref_null.txt create mode 100644 test/spec/function-references/return_call.txt create mode 100644 test/spec/function-references/return_call_indirect.txt create mode 100644 test/spec/function-references/select.txt create mode 100644 test/spec/function-references/table-sub.txt create mode 100644 test/spec/function-references/table.txt create mode 100644 test/spec/function-references/unreached-invalid.txt create mode 100644 test/spec/function-references/unreached-valid.txt diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index bd7ff33fe1..4c9b24eae0 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -96,9 +96,13 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result BeginTableSection(Offset size) override; Result OnTableCount(Index count) override; - Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) override; + Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) override; + Result BeginTableInitExpr(Index index) override; + Result EndTableInitExpr(Index index) override; + Result EndTable(Index index) override; Result EndTableSection() override; Result BeginMemorySection(Offset size) override; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index 545db127b2..02d2958801 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -121,11 +121,15 @@ class BinaryReaderNop : public BinaryReaderDelegate { /* Table section */ Result BeginTableSection(Offset size) override { return Result::Ok; } Result OnTableCount(Index count) override { return Result::Ok; } - Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) override { + Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) override { return Result::Ok; } + Result BeginTableInitExpr(Index index) override { return Result::Ok; } + Result EndTableInitExpr(Index index) override { return Result::Ok; } + Result EndTable(Index index) override { return Result::Ok; } Result EndTableSection() override { return Result::Ok; } /* Memory section */ diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index 96455f2251..3993a45c94 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -156,9 +156,13 @@ class BinaryReaderDelegate { /* Table section */ virtual Result BeginTableSection(Offset size) = 0; virtual Result OnTableCount(Index count) = 0; - virtual Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) = 0; + virtual Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) = 0; + virtual Result BeginTableInitExpr(Index index) = 0; + virtual Result EndTableInitExpr(Index index) = 0; + virtual Result EndTable(Index index) = 0; virtual Result EndTableSection() = 0; /* Memory section */ diff --git a/include/wabt/interp/interp-inl.h b/include/wabt/interp/interp-inl.h index 074fc9fc9f..6125999a9b 100644 --- a/include/wabt/interp/interp-inl.h +++ b/include/wabt/interp/interp-inl.h @@ -422,12 +422,6 @@ void RequireType(ValueType type) { assert(HasType(type)); } -inline bool TypesMatch(ValueType expected, ValueType actual) { - // Currently there is no subtyping, so expected and actual must match - // exactly. In the future this may be expanded. - return expected == actual; -} - //// Value //// inline Value WABT_VECTORCALL Value::Make(s32 val) { Value res; res.i32_ = val; res.SetType(ValueType::I32); return res; } inline Value WABT_VECTORCALL Value::Make(u32 val) { Value res; res.i32_ = val; res.SetType(ValueType::I32); return res; } @@ -682,8 +676,8 @@ inline bool Table::classof(const Object* obj) { } // static -inline Table::Ptr Table::New(Store& store, TableType type) { - return store.Alloc(store, type); +inline Table::Ptr Table::New(Store& store, TableType type, Ref init_ref) { + return store.Alloc
(store, type, init_ref); } inline const ExternType& Table::extern_type() { diff --git a/include/wabt/interp/interp.h b/include/wabt/interp/interp.h index 4e376eb327..42e6a6b8bb 100644 --- a/include/wabt/interp/interp.h +++ b/include/wabt/interp/interp.h @@ -157,6 +157,10 @@ using u32x2 = Simd; //// Types //// +bool TypesMatch(ValueType expected, ValueType actual); + +//// Limits //// + bool CanGrow(const Limits&, u32 old_size, u32 delta, u32* new_size); Result Match(const Limits& expected, const Limits& actual, @@ -334,6 +338,7 @@ struct FuncDesc { struct TableDesc { TableType type; + FuncDesc init_func; }; struct MemoryDesc { @@ -818,7 +823,7 @@ class Table : public Extern { static const char* GetTypeName() { return "Table"; } using Ptr = RefPtr
; - static Table::Ptr New(Store&, TableType); + static Table::Ptr New(Store&, TableType, Ref); Result Match(Store&, const ImportType&, Trap::Ptr* out_trap) override; @@ -850,7 +855,7 @@ class Table : public Extern { private: friend Store; - explicit Table(Store&, TableType); + explicit Table(Store&, TableType, Ref); void Mark(Store&) override; TableType type_; diff --git a/include/wabt/ir.h b/include/wabt/ir.h index 9102297dc8..c825465034 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -987,13 +987,14 @@ struct Table { std::string name; Limits elem_limits; Type elem_type; + ExprList init_expr; }; using ExprListVector = std::vector; struct ElemSegment { explicit ElemSegment(std::string_view name) : name(name) {} - uint8_t GetFlags(const Module*) const; + uint8_t GetFlags(const Module*, bool) const; SegmentKind kind = SegmentKind::Active; std::string name; diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index d568aac805..6414ccd753 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -75,7 +75,7 @@ class SharedValidator { Result OnArrayType(const Location&, TypeMut field); Result OnFunction(const Location&, Var sig_var); - Result OnTable(const Location&, Type elem_type, const Limits&); + Result OnTable(const Location&, Type elem_type, const Limits&, bool, bool); Result OnMemory(const Location&, const Limits&, uint32_t page_size); Result OnGlobalImport(const Location&, Type type, bool mutable_); Result OnGlobal(const Location&, Type type, bool mutable_); diff --git a/src/apply-names.cc b/src/apply-names.cc index 3d25749ccd..ab91fa42a4 100644 --- a/src/apply-names.cc +++ b/src/apply-names.cc @@ -102,6 +102,7 @@ class NameApplier : public ExprVisitor::DelegateNop { Result VisitGlobal(Global* global); Result VisitTag(Tag* tag); Result VisitExport(Index export_index, Export* export_); + Result VisitTable(Table* table); Result VisitElemSegment(Index elem_segment_index, ElemSegment* segment); Result VisitDataSegment(Index data_segment_index, DataSegment* segment); Result VisitStart(Var* start_var); @@ -559,6 +560,11 @@ Result NameApplier::VisitExport(Index export_index, Export* export_) { return Result::Ok; } +Result NameApplier::VisitTable(Table* table) { + CHECK_RESULT(visitor_.VisitExprList(table->init_expr)); + return Result::Ok; +} + Result NameApplier::VisitElemSegment(Index elem_segment_index, ElemSegment* segment) { CHECK_RESULT(UseNameForTableVar(&segment->table_var)); @@ -594,6 +600,8 @@ Result NameApplier::VisitModule(Module* module) { CHECK_RESULT(VisitTag(module->tags[i])); for (size_t i = 0; i < module->exports.size(); ++i) CHECK_RESULT(VisitExport(i, module->exports[i])); + for (size_t i = 0; i < module->tables.size(); ++i) + CHECK_RESULT(VisitTable(module->tables[i])); for (size_t i = 0; i < module->elem_segments.size(); ++i) CHECK_RESULT(VisitElemSegment(i, module->elem_segments[i])); for (size_t i = 0; i < module->data_segments.size(); ++i) diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 855c8a8c16..c65791fbd8 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -144,9 +144,12 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnFunction(Index index, Index sig_index) override; Result OnTableCount(Index count) override; - Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) override; + Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool) override; + Result BeginTableInitExpr(Index index) override; + Result EndTableInitExpr(Index index) override; Result OnMemoryCount(Index count) override; Result OnMemory(Index index, @@ -700,9 +703,10 @@ Result BinaryReaderIR::OnTableCount(Index count) { return Result::Ok; } -Result BinaryReaderIR::OnTable(Index index, - Type elem_type, - const Limits* elem_limits) { +Result BinaryReaderIR::BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool) { auto field = std::make_unique(GetLocation()); Table& table = field->table; table.elem_limits = *elem_limits; @@ -712,6 +716,16 @@ Result BinaryReaderIR::OnTable(Index index, return Result::Ok; } +Result BinaryReaderIR::BeginTableInitExpr(Index index) { + assert(index == module_->tables.size() - 1); + Table* table = module_->tables[index]; + return BeginInitExpr(&table->init_expr); +} + +Result BinaryReaderIR::EndTableInitExpr(Index index) { + return EndInitExpr(); +} + Result BinaryReaderIR::OnMemoryCount(Index count) { WABT_TRY module_->memories.reserve(module_->num_memory_imports + count); diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 89690ca533..5c98c26b0c 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -255,14 +255,15 @@ Result BinaryReaderLogging::OnImportTag(Index import_index, sig_index); } -Result BinaryReaderLogging::OnTable(Index index, - Type elem_type, - const Limits* elem_limits) { +Result BinaryReaderLogging::BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) { char buf[100]; SPrintLimits(buf, sizeof(buf), elem_limits); LOGF("OnTable(index: %" PRIindex ", elem_type: %s, %s)\n", index, elem_type.GetName().c_str(), buf); - return reader_->OnTable(index, elem_type, elem_limits); + return reader_->BeginTable(index, elem_type, elem_limits, has_init_expr); } Result BinaryReaderLogging::OnMemory(Index index, @@ -816,6 +817,9 @@ DEFINE_END(EndFunctionSection) DEFINE_BEGIN(BeginTableSection) DEFINE_INDEX(OnTableCount) +DEFINE_INDEX(BeginTableInitExpr) +DEFINE_INDEX(EndTableInitExpr) +DEFINE_INDEX(EndTable) DEFINE_END(EndTableSection) DEFINE_BEGIN(BeginMemorySection) diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index e35d1fe5b8..12906dca81 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -1127,9 +1127,10 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnFunction(Index index, Index sig_index) override; Result OnTableCount(Index count) override; - Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) override; + Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool) override; Result OnMemoryCount(Index count) override; Result OnMemory(Index index, @@ -1176,6 +1177,14 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result EndDataSegmentInitExpr(Index index) override { return EndInitExpr(); } + Result BeginTableInitExpr(Index index) override { + reading_table_init_expr_ = true; + BeginInitExpr(); + return Result::Ok; + } + + Result EndTableInitExpr(Index index) override { return EndInitExpr(); } + Result BeginGlobalInitExpr(Index index) override { reading_global_init_expr_ = true; BeginInitExpr(); @@ -1305,6 +1314,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Index elem_index_ = 0; Index table_index_ = 0; Index next_data_reloc_ = 0; + bool reading_table_init_expr_ = false; bool reading_elem_init_expr_ = false; bool reading_data_init_expr_ = false; bool reading_global_init_expr_ = false; @@ -1317,8 +1327,9 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { uint64_t elem_offset_ = 0; bool ReadingInitExpr() { - return reading_elem_init_expr_ || reading_data_init_expr_ || - reading_global_init_expr_ || reading_elem_expr_; + return reading_table_init_expr_ || reading_elem_init_expr_ || + reading_data_init_expr_ || reading_global_init_expr_ || + reading_elem_expr_; } }; @@ -1697,9 +1708,10 @@ Result BinaryReaderObjdump::OnTableCount(Index count) { return OnCount(count); } -Result BinaryReaderObjdump::OnTable(Index index, - Type elem_type, - const Limits* elem_limits) { +Result BinaryReaderObjdump::BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool) { PrintDetails(" - table[%" PRIindex "] type=%s initial=%" PRId64, index, elem_type.GetName().c_str(), elem_limits->initial); if (elem_limits->has_max) { @@ -1922,6 +1934,9 @@ Result BinaryReaderObjdump::EndInitExpr() { if (reading_data_init_expr_) { reading_data_init_expr_ = false; InitExprToConstOffset(current_init_expr_, &data_offset_); + } else if (reading_table_init_expr_) { + reading_table_init_expr_ = false; + InitExprToConstOffset(current_init_expr_, &elem_offset_); } else if (reading_elem_init_expr_) { reading_elem_init_expr_ = false; InitExprToConstOffset(current_init_expr_, &elem_offset_); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index fdb271c290..036428c28b 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -2787,8 +2787,32 @@ Result BinaryReader::ReadTableSection(Offset section_size) { Index table_index = num_table_imports_ + i; Type elem_type; Limits elem_limits; + bool has_init_expr = false; + + if (options_.features.function_references_enabled() && + state_.offset < read_end_ && state_.data[state_.offset] == 0x40) { + state_.offset++; + has_init_expr = true; + + uint8_t value; + CHECK_RESULT(ReadU8(&value, "table init")); + if (value != 0) { + PrintError("unsupported table intializer: 0x%x\n", + static_cast(value)); + return Result::Error; + } + } + CHECK_RESULT(ReadTable(&elem_type, &elem_limits)); - CALLBACK(OnTable, table_index, elem_type, &elem_limits); + CALLBACK(BeginTable, table_index, elem_type, &elem_limits, has_init_expr); + + if (has_init_expr) { + CALLBACK(BeginTableInitExpr, table_index); + CHECK_RESULT(ReadInitExpr(table_index)); + CALLBACK(EndTableInitExpr, table_index); + } + + CALLBACK(EndTable, table_index); } CALLBACK0(EndTableSection); return Result::Ok; @@ -2879,6 +2903,11 @@ Result BinaryReader::ReadElemSection(Offset section_size) { } Type elem_type = Type::FuncRef; + if (options_.features.function_references_enabled() && + !(flags & SegUseElemExprs)) { + elem_type = Type(Type::FuncRef, Type::ReferenceNonNull); + } + CALLBACK(BeginElemSegment, i, table_index, flags); if (!(flags & SegPassive)) { @@ -2897,7 +2926,6 @@ Result BinaryReader::ReadElemSection(Offset section_size) { ERROR_UNLESS(kind == ExternalKind::Func, "segment elem type must be func (%s)", elem_type.GetName().c_str()); - elem_type = Type::FuncRef; } } diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 68b1ba9d31..fbfaf5690c 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -1227,9 +1227,17 @@ void BinaryWriter::WriteFunc(const Func* func) { } void BinaryWriter::WriteTable(const Table* table) { + if (!table->init_expr.empty()) { + stream_->WriteU8(0x40, "initialized table prefix"); + stream_->WriteU8(0x0, "initialized table prefix"); + } WriteType(stream_, table->elem_type); WriteLimitsFlags(stream_, ComputeLimitsFlags(&table->elem_limits)); WriteLimitsData(stream_, &table->elem_limits); + + if (!table->init_expr.empty()) { + WriteInitExpr(table->init_expr); + } } void BinaryWriter::WriteMemory(const Memory* memory) { @@ -1616,7 +1624,8 @@ Result BinaryWriter::WriteModule() { ElemSegment* segment = module_->elem_segments[i]; WriteHeader("elem segment header", i); // 1. flags - uint8_t flags = segment->GetFlags(module_); + uint8_t flags = segment->GetFlags( + module_, options_.features.function_references_enabled()); stream_->WriteU8(flags, "segment flags"); // 2. optional target table if (flags & SegExplicitIndex && segment->kind != SegmentKind::Declared) { diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index d0dd7863c7..57351e531d 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -123,9 +123,12 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnFunction(Index index, Index sig_index) override; Result OnTableCount(Index count) override; - Result OnTable(Index index, - Type elem_type, - const Limits* elem_limits) override; + Result BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) override; + Result BeginTableInitExpr(Index index) override; + Result EndTableInitExpr(Index index) override; Result OnMemoryCount(Index count) override; Result OnMemory(Index index, @@ -558,7 +561,8 @@ Result BinaryReaderInterp::OnImportTable(Index import_index, Index table_index, Type elem_type, const Limits* elem_limits) { - CHECK_RESULT(validator_.OnTable(GetLocation(), elem_type, *elem_limits)); + CHECK_RESULT( + validator_.OnTable(GetLocation(), elem_type, *elem_limits, true, false)); TableType table_type{elem_type, *elem_limits}; module_.imports.push_back(ImportDesc{ImportType( std::string(module_name), std::string(field_name), table_type.Clone())}); @@ -627,16 +631,33 @@ Result BinaryReaderInterp::OnTableCount(Index count) { return Result::Ok; } -Result BinaryReaderInterp::OnTable(Index index, - Type elem_type, - const Limits* elem_limits) { - CHECK_RESULT(validator_.OnTable(GetLocation(), elem_type, *elem_limits)); +Result BinaryReaderInterp::BeginTable(Index index, + Type elem_type, + const Limits* elem_limits, + bool has_init_expr) { + CHECK_RESULT(validator_.OnTable(GetLocation(), elem_type, *elem_limits, false, + has_init_expr)); TableType table_type{elem_type, *elem_limits}; - module_.tables.push_back(TableDesc{table_type}); + FuncDesc init_func{ + FuncType{{}, {elem_type}}, {}, Istream::kInvalidOffset, {}}; + module_.tables.push_back(TableDesc{table_type, init_func}); table_types_.push_back(table_type); return Result::Ok; } +Result BinaryReaderInterp::BeginTableInitExpr(Index index) { + TableDesc& table = module_.tables.back(); + return BeginInitExpr(&table.init_func); +} + +Result BinaryReaderInterp::EndTableInitExpr(Index index) { + FixupTopLabel(); + CHECK_RESULT(validator_.EndInitExpr()); + istream_.Emit(Opcode::Return); + PopLabel(); + return Result::Ok; +} + Result BinaryReaderInterp::OnMemoryCount(Index count) { module_.memories.reserve(count); return Result::Ok; diff --git a/src/interp/interp-wasm-c-api.cc b/src/interp/interp-wasm-c-api.cc index bb4598a472..2d5332269b 100644 --- a/src/interp/interp-wasm-c-api.cc +++ b/src/interp/interp-wasm-c-api.cc @@ -960,7 +960,8 @@ void wasm_global_set(wasm_global_t* global, const wasm_val_t* val) { own wasm_table_t* wasm_table_new(wasm_store_t* store, const wasm_tabletype_t* type, wasm_ref_t* init) { - return new wasm_table_t{Table::New(store->I, *type->As())}; + return new wasm_table_t{ + Table::New(store->I, *type->As(), Ref::Null)}; } own wasm_tabletype_t* wasm_table_type(const wasm_table_t* table) { diff --git a/src/interp/interp.cc b/src/interp/interp.cc index f18b4d5ed7..2944d05f06 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -264,6 +264,30 @@ Result Match(const TagType& expected, return Result::Ok; } +//// Types //// + +bool TypesMatch(ValueType expected, ValueType actual) { + // Currently there is no subtyping, so expected and actual must match + // exactly. In the future this may be expanded. + if (expected == actual) { + return true; + } + + if (expected == Type::FuncRef && + (actual == Type::Ref || + (expected.IsNullableNonTypedRef() && + (actual == Type::FuncRef || actual == Type::RefNull)))) { + return true; + } + + if (actual == Type::Ref && expected == Type::RefNull && + actual.GetReferenceIndex() == expected.GetReferenceIndex()) { + return true; + } + + return false; +} + //// Limits //// template bool CanGrow(const Limits& limits, T old_size, T delta, T* new_size) { @@ -312,6 +336,8 @@ bool Store::HasValueType(Ref ref, ValueType type) const { Object* obj = objects_.Get(ref.index); switch (type) { case ValueType::FuncRef: + case ValueType::Ref: + case ValueType::RefNull: return obj->kind() == ObjectKind::DefinedFunc || obj->kind() == ObjectKind::HostFunc; case ValueType::ExnRef: @@ -549,8 +575,12 @@ Result HostFunc::DoCall(Thread& thread, } //// Table //// -Table::Table(Store&, TableType type) : Extern(skind), type_(type) { +Table::Table(Store& store, TableType type, Ref init_ref) + : Extern(skind), type_(type) { elements_.resize(type.limits.initial); + if (init_ref != Ref::Null) { + Fill(store, 0, init_ref, type.limits.initial); + } } void Table::Mark(Store& store) { @@ -914,7 +944,16 @@ Instance::Ptr Instance::Instantiate(Store& store, // Tables. for (auto&& desc : mod->desc().tables) { - inst->tables_.push_back(Table::New(store, desc.type).ref()); + Ref ref = Ref::Null; + if (desc.init_func.code_offset != Istream::kInvalidOffset) { + Ref func_ref = DefinedFunc::New(store, inst.ref(), desc.init_func).ref(); + Value value; + if (Failed(inst->CallInitFunc(store, func_ref, &value, out_trap))) { + return {}; + } + ref = value.Get(); + } + inst->tables_.push_back(Table::New(store, desc.type, ref).ref()); } // Memories. diff --git a/src/ir.cc b/src/ir.cc index 46713db04c..d4ceef5295 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -703,7 +703,8 @@ void Var::Destroy() { } } -uint8_t ElemSegment::GetFlags(const Module* module) const { +uint8_t ElemSegment::GetFlags(const Module* module, + bool function_references_enabled) const { uint8_t flags = 0; switch (kind) { @@ -724,15 +725,20 @@ uint8_t ElemSegment::GetFlags(const Module* module) const { break; } - bool all_ref_func = - elem_type == Type::FuncRef && - std::all_of(elem_exprs.begin(), elem_exprs.end(), - [](const ExprList& elem_expr) { - return elem_expr.front().type() == ExprType::RefFunc; - }); - - if (!all_ref_func) { + if (function_references_enabled && + elem_type != Type(Type::FuncRef, Type::ReferenceNonNull)) { flags |= SegUseElemExprs; + } else { + bool all_ref_func = + elem_type == Type::FuncRef && + std::all_of(elem_exprs.begin(), elem_exprs.end(), + [](const ExprList& elem_expr) { + return elem_expr.front().type() == ExprType::RefFunc; + }); + + if (!all_ref_func) { + flags |= SegUseElemExprs; + } } return flags; diff --git a/src/resolve-names.cc b/src/resolve-names.cc index d24f2f5c37..606bf781c2 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -111,6 +111,7 @@ class NameResolver : public ExprVisitor::DelegateNop { void VisitExport(Export* export_); void VisitGlobal(Global* global); void VisitTag(Tag* tag); + void VisitTable(Table* table); void VisitElemSegment(ElemSegment* segment); void VisitDataSegment(DataSegment* segment); void VisitScriptModule(ScriptModule* script_module); @@ -582,6 +583,12 @@ void NameResolver::VisitTag(Tag* tag) { } } +void NameResolver::VisitTable(Table* table) { + if (!table->init_expr.empty()) { + visitor_.VisitExprList(table->init_expr); + } +} + void NameResolver::VisitElemSegment(ElemSegment* segment) { ResolveTableVar(&segment->table_var); visitor_.VisitExprList(segment->offset); @@ -616,6 +623,8 @@ Result NameResolver::VisitModule(Module* module) { VisitGlobal(global); for (Tag* tag : module->tags) VisitTag(tag); + for (Table* table : module->tables) + VisitTable(table); for (ElemSegment* elem_segment : module->elem_segments) VisitElemSegment(elem_segment); for (DataSegment* data_segment : module->data_segments) diff --git a/src/shared-validator.cc b/src/shared-validator.cc index 5fac43aa72..c1c098db03 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -122,7 +122,9 @@ Result SharedValidator::CheckLimits(const Location& loc, Result SharedValidator::OnTable(const Location& loc, Type elem_type, - const Limits& limits) { + const Limits& limits, + bool is_import, + bool has_init_expr) { Result result = Result::Ok; // Must be checked by parser or binary reader. assert(elem_type.IsRef()); @@ -134,19 +136,18 @@ Result SharedValidator::OnTable(const Location& loc, if (limits.is_shared) { result |= PrintError(loc, "tables may not be shared"); } - if (elem_type != Type::FuncRef && - !options_.features.reference_types_enabled()) { + if (options_.features.reference_types_enabled()) { + if (!elem_type.IsRef()) { + result |= PrintError(loc, "tables must have reference types"); + } else if (!is_import && !has_init_expr && !elem_type.IsNullableRef()) { + result |= PrintError(loc, "missing table initializer"); + } + } else if (elem_type != Type::FuncRef) { result |= PrintError(loc, "tables must have funcref type"); } result |= CheckReferenceType(loc, elem_type, "tables"); - // TODO: support table initializers - if (elem_type.IsRef() && !elem_type.IsNullableRef()) { - result |= - PrintError(loc, "currently non-nullable references are not supported"); - } - tables_.push_back(TableType{elem_type, limits}); return result; } diff --git a/src/test-interp.cc b/src/test-interp.cc index 9346b7b166..76b5cce13e 100644 --- a/src/test-interp.cc +++ b/src/test-interp.cc @@ -608,9 +608,9 @@ TEST_F(InterpGCTest, Collect_GlobalCycle) { TEST_F(InterpGCTest, Collect_TableCycle) { auto tt = TableType{ValueType::ExternRef, Limits{2}}; - auto t1 = Table::New(store_, tt); - auto t2 = Table::New(store_, tt); - auto t3 = Table::New(store_, tt); + auto t1 = Table::New(store_, tt, Ref::Null); + auto t2 = Table::New(store_, tt, Ref::Null); + auto t3 = Table::New(store_, tt, Ref::Null); t1->Set(store_, 0, t1->self()); // t1 references itself. t2->Set(store_, 0, t3->self()); @@ -659,7 +659,8 @@ TEST_F(InterpGCTest, Collect_InstanceImport) { auto f = HostFunc::New(store_, FuncType{{}, {}}, [](Thread& thread, const Values&, Values&, Trap::Ptr*) -> Result { return Result::Ok; }); - auto t = Table::New(store_, TableType{ValueType::FuncRef, Limits{0}}); + auto t = + Table::New(store_, TableType{ValueType::FuncRef, Limits{0}}, Ref::Null); auto m = Memory::New(store_, MemoryType{Limits{0}, WABT_DEFAULT_PAGE_SIZE}); auto g = Global::New(store_, GlobalType{ValueType::I32, Mutability::Const}, Value::Make(5)); @@ -709,10 +710,10 @@ TEST_F(InterpGCTest, Collect_DeepRecursion) { // Create a chain of tables, where each contains // a single reference to the next table. - Table::Ptr prev_table = Table::New(store_, tt); + Table::Ptr prev_table = Table::New(store_, tt, Ref::Null); for (size_t i = 1; i < table_count; i++) { - Table::Ptr new_table = Table::New(store_, tt); + Table::Ptr new_table = Table::New(store_, tt, Ref::Null); new_table->Set(store_, 0, prev_table->self()); diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index d859f14823..3b8620224b 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -1307,11 +1307,12 @@ CommandRunner::CommandRunner() : store_(s_features) { }); } - spectest["table"] = - interp::Table::New(store_, TableType{ValueType::FuncRef, Limits{10, 20}}); + spectest["table"] = interp::Table::New( + store_, TableType{ValueType::FuncRef, Limits{10, 20}}, Ref::Null); spectest["table64"] = interp::Table::New( - store_, TableType{ValueType::FuncRef, Limits{10, 20, false, true}}); + store_, TableType{ValueType::FuncRef, Limits{10, 20, false, true}}, + Ref::Null); spectest["memory"] = interp::Memory::New( store_, MemoryType{Limits{1, 2}, WABT_DEFAULT_PAGE_SIZE}); @@ -1920,7 +1921,7 @@ wabt::Result CommandRunner::CheckAssertReturnResult( case Type::FuncRef: // A funcref expectation only requires that the reference be a function, // but it doesn't check the actual index. - ok = (actual.type == Type::FuncRef); + ok = (actual.type == Type::FuncRef || actual.type == Type::RefNull); break; case Type::ExternRef: diff --git a/src/validator.cc b/src/validator.cc index 76b8f31c40..ae405f71b9 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -224,6 +224,12 @@ static Result CheckType(Type actual, Type expected) { } } + if (actual_type == Type::FuncRef && expected_type == Type::RefNull) { + // Specification tests pass expected functions + // directly, their type is not relevant. + return Result::Ok; + } + return Result::Error; } @@ -801,8 +807,8 @@ Result Validator::CheckModule() { case ExternalKind::Table: { auto&& table = cast(f->import.get())->table; - result_ |= - validator_.OnTable(field.loc, table.elem_type, table.elem_limits); + result_ |= validator_.OnTable(field.loc, table.elem_type, + table.elem_limits, true, false); break; } @@ -841,8 +847,18 @@ Result Validator::CheckModule() { // Table section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast(&field)) { + bool has_init_expr = !f->table.init_expr.empty(); result_ |= validator_.OnTable(field.loc, f->table.elem_type, - f->table.elem_limits); + f->table.elem_limits, false, has_init_expr); + + // Init expr. + if (has_init_expr) { + result_ |= validator_.BeginInitExpr(field.loc, f->table.elem_type); + ExprVisitor visitor(this); + result_ |= + visitor.VisitExprList(const_cast(f->table.init_expr)); + result_ |= validator_.EndInitExpr(); + } } } diff --git a/src/wast-parser.cc b/src/wast-parser.cc index ed0b155125..3d97bf3023 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1344,7 +1344,7 @@ Result WastParser::ResolveTargetRefType(const Module& module, assert(type->IsReferenceWithIndex() && !var.is_index()); if (type->GetReferenceIndex() != kInvalidIndex) { - // Resolved earlier. + // Index or resolved earlier. return Result::Ok; } @@ -1538,7 +1538,10 @@ Result WastParser::ParseElemModuleField(Module* module) { VarToType(elem_type, &field->elem_segment.elem_type); ParseElemExprListOpt(&field->elem_segment.elem_exprs); } else { - field->elem_segment.elem_type = Type::FuncRef; + field->elem_segment.elem_type = + Type(Type::FuncRef, options_->features.function_references_enabled() + ? Type::ReferenceNonNull + : Type::ReferenceOrNull); if (PeekMatch(TokenType::Func)) { EXPECT(Func); } @@ -2001,6 +2004,9 @@ Result WastParser::ParseTableModuleField(Module* module) { Var elem_type; CHECK_RESULT(ParseRefType(&elem_type)); VarToType(elem_type, &table.elem_type); + if (PeekMatch(TokenType::Lpar)) { + CHECK_RESULT(ParseTerminatingInstrList(&table.init_expr)); + } module->AppendField(std::move(field)); } } @@ -3112,10 +3118,12 @@ Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { case TokenType::RefNull: { auto token = Consume(); Var type; - CHECK_RESULT(ParseRefKind(&type)); + if (Peek() != TokenType::Rpar) { + CHECK_RESULT(ParseRefKind(&type)); + } ErrorUnlessOpcodeEnabled(token); const_.loc = GetLocation(); - const_.set_null(type.opt_type()); + const_.set_null(type.has_opt_type() ? type.opt_type() : Type::FuncRef); break; } case TokenType::RefFunc: { diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 5da55e8535..04ade45064 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -1596,7 +1596,8 @@ void WatWriter::WriteElemSegment(const ElemSegment& segment) { Writef("(;%u;)", elem_segment_index_); } - uint8_t flags = segment.GetFlags(&module); + uint8_t flags = segment.GetFlags( + &module, options_.features.function_references_enabled()); if ((flags & (SegPassive | SegExplicitIndex)) == SegExplicitIndex) { WriteOpenSpace("table"); diff --git a/test/dump/call_ref.txt b/test/dump/call_ref.txt index 997440c108..a517a45c0e 100644 --- a/test/dump/call_ref.txt +++ b/test/dump/call_ref.txt @@ -11,7 +11,7 @@ (i32.add (local.get $x) (i32.const 19)) ) - (elem declare funcref (ref.func $foo)) + (elem declare func $foo) (type (func (param i32) (result i32))) ) diff --git a/test/dump/relocations-all-features.txt b/test/dump/relocations-all-features.txt index 0b22b64184..8575f6140c 100644 --- a/test/dump/relocations-all-features.txt +++ b/test/dump/relocations-all-features.txt @@ -27,10 +27,11 @@ Sections: Table start=0x00000041 end=0x00000046 (size=0x00000005) count: 1 Global start=0x00000048 end=0x0000004e (size=0x00000006) count: 1 Export start=0x00000050 end=0x00000055 (size=0x00000005) count: 1 - Elem start=0x00000057 end=0x0000005e (size=0x00000007) count: 1 - Code start=0x00000060 end=0x00000086 (size=0x00000026) count: 1 - Custom start=0x00000088 end=0x000000a9 (size=0x00000021) "linking" - Custom start=0x000000ab end=0x000000c7 (size=0x0000001c) "reloc.Code" + Elem start=0x00000057 end=0x00000064 (size=0x0000000d) count: 1 + Code start=0x00000066 end=0x0000008c (size=0x00000026) count: 1 + Custom start=0x0000008e end=0x000000af (size=0x00000021) "linking" + Custom start=0x000000b1 end=0x000000c1 (size=0x00000010) "reloc.Elem" + Custom start=0x000000c3 end=0x000000df (size=0x0000001c) "reloc.Code" Section Details: @@ -50,7 +51,7 @@ Global[1]: Export[1]: - func[2] -> "f" Elem[1]: - - segment[0] flags=0 table=0 count=1 - init i32=0 + - segment[0] flags=4 table=0 count=1 - init i32=0 - elem[0] = ref.func:1 <__extern.bar> Code[1]: - func[2] size=36 @@ -62,29 +63,33 @@ Custom: - 2: F func=2 [ exported no_strip binding=global vis=hidden ] - 3: T <> table=0 [ binding=local vis=hidden ] - 4: G global=0 [ binding=global vis=default ] +Custom: + - name: "reloc.Elem" + - relocations for section: 6 (Elem) [1] + - R_WASM_FUNCTION_INDEX_LEB offset=0x000007(file=0x00005e) symbol=1 <__extern.bar> Custom: - name: "reloc.Code" - relocations for section: 7 (Code) [5] - - R_WASM_GLOBAL_INDEX_LEB offset=0x000004(file=0x000064) symbol=4 - - R_WASM_FUNCTION_INDEX_LEB offset=0x00000a(file=0x00006a) symbol=2 - - R_WASM_FUNCTION_INDEX_LEB offset=0x000010(file=0x000070) symbol=0 <__extern.foo> - - R_WASM_TYPE_INDEX_LEB offset=0x00001b(file=0x00007b) type=2 - - R_WASM_TABLE_NUMBER_LEB offset=0x000020(file=0x000080) symbol=3 <> + - R_WASM_GLOBAL_INDEX_LEB offset=0x000004(file=0x00006a) symbol=4 + - R_WASM_FUNCTION_INDEX_LEB offset=0x00000a(file=0x000070) symbol=2 + - R_WASM_FUNCTION_INDEX_LEB offset=0x000010(file=0x000076) symbol=0 <__extern.foo> + - R_WASM_TYPE_INDEX_LEB offset=0x00001b(file=0x000081) type=2 + - R_WASM_TABLE_NUMBER_LEB offset=0x000020(file=0x000086) symbol=3 <> Code Disassembly: -000062 func[2] : - 000063: 23 80 80 80 80 00 | global.get 0 - 000064: R_WASM_GLOBAL_INDEX_LEB 4 - 000069: 10 82 80 80 80 00 | call 2 - 00006a: R_WASM_FUNCTION_INDEX_LEB 2 - 00006f: 10 80 80 80 80 00 | call 0 <__extern.foo> - 000070: R_WASM_FUNCTION_INDEX_LEB 0 <__extern.foo> - 000075: 41 d2 09 | i32.const 1234 - 000078: 41 00 | i32.const 0 - 00007a: 11 82 80 80 80 00 80 80 80 | call_indirect 0 (type 2) - 000083: 80 00 | - 00007b: R_WASM_TYPE_INDEX_LEB 2 - 000085: 0b | end - 000080: R_WASM_TABLE_NUMBER_LEB 3 <> +000068 func[2] : + 000069: 23 80 80 80 80 00 | global.get 0 + 00006a: R_WASM_GLOBAL_INDEX_LEB 4 + 00006f: 10 82 80 80 80 00 | call 2 + 000070: R_WASM_FUNCTION_INDEX_LEB 2 + 000075: 10 80 80 80 80 00 | call 0 <__extern.foo> + 000076: R_WASM_FUNCTION_INDEX_LEB 0 <__extern.foo> + 00007b: 41 d2 09 | i32.const 1234 + 00007e: 41 00 | i32.const 0 + 000080: 11 82 80 80 80 00 80 80 80 | call_indirect 0 (type 2) + 000089: 80 00 | + 000081: R_WASM_TYPE_INDEX_LEB 2 + 00008b: 0b | end + 000086: R_WASM_TABLE_NUMBER_LEB 3 <> ;;; STDOUT ;;) diff --git a/test/dump/typed_func_refs_params.txt b/test/dump/typed_func_refs_params.txt index 7bbd41f722..d83bd568ec 100644 --- a/test/dump/typed_func_refs_params.txt +++ b/test/dump/typed_func_refs_params.txt @@ -25,7 +25,7 @@ ) ) - (elem declare funcref (ref.func $square)) + (elem declare func $square) ) (;; STDERR ;;; diff --git a/test/dump/typed_func_refs_results.txt b/test/dump/typed_func_refs_results.txt index 81ff524039..2e635ccbf5 100644 --- a/test/dump/typed_func_refs_results.txt +++ b/test/dump/typed_func_refs_results.txt @@ -39,7 +39,7 @@ ) ) - (elem declare funcref (ref.func $square) (ref.func $double)) + (elem declare func $square $double) ) (;; STDERR ;;; diff --git a/test/roundtrip/fold-callref.txt b/test/roundtrip/fold-callref.txt index dbd885b88b..b3a8fe6925 100644 --- a/test/roundtrip/fold-callref.txt +++ b/test/roundtrip/fold-callref.txt @@ -66,5 +66,5 @@ (f32.const 0x1p+2 (;=4;)) (ref.func 1)) (ref.func 2))) - (elem (;0;) declare func 0 1 2)) + (elem (;0;) declare funcref (ref.func 0) (ref.func 1) (ref.func 2))) ;;; STDOUT ;;) diff --git a/test/spec/function-references/binary.txt b/test/spec/function-references/binary.txt new file mode 100644 index 0000000000..69c79857ff --- /dev/null +++ b/test/spec/function-references/binary.txt @@ -0,0 +1,238 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/binary.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/binary.wast:6: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/function-references/binary.wast:7: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/function-references/binary.wast:8: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/function-references/binary.wast:9: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:10: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:11: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:12: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:13: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:14: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:15: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:16: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:17: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:18: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:21: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:24: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:25: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:28: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:31: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:34: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/function-references/binary.wast:37: assert_malformed passed: + 0000004: error: unable to read uint16_t: version +out/test/spec/function-references/binary.wast:38: assert_malformed passed: + 0000004: error: unable to read uint16_t: version +out/test/spec/function-references/binary.wast:39: assert_malformed passed: + 0000006: error: unable to read uint16_t: layer +out/test/spec/function-references/binary.wast:40: assert_malformed passed: + 0000008: error: bad wasm file version: 0 (expected 0x1) +out/test/spec/function-references/binary.wast:41: assert_malformed passed: + 0000008: error: bad wasm file version: 0xd (expected 0x1) +out/test/spec/function-references/binary.wast:42: assert_malformed passed: + 0000008: error: bad wasm file version: 0xe (expected 0x1) +out/test/spec/function-references/binary.wast:43: assert_malformed passed: + 0000008: error: bad wasm file version: 0x100 (expected 0x1) +out/test/spec/function-references/binary.wast:44: assert_malformed passed: + 0000008: error: wasm components are not yet supported in this tool +out/test/spec/function-references/binary.wast:45: assert_malformed passed: + 0000008: error: unsupported wasm layer: 0x100 +out/test/spec/function-references/binary.wast:48: assert_malformed passed: + 000000a: error: invalid section code: 14 +out/test/spec/function-references/binary.wast:49: assert_malformed passed: + 000000a: error: invalid section code: 127 +out/test/spec/function-references/binary.wast:50: assert_malformed passed: + 000000a: error: invalid section code: 128 +out/test/spec/function-references/binary.wast:51: assert_malformed passed: + 000000a: error: invalid section code: 129 +out/test/spec/function-references/binary.wast:52: assert_malformed passed: + 000000a: error: invalid section code: 255 +out/test/spec/function-references/binary.wast:56: assert_malformed passed: + 000001b: error: function body must end with END opcode +out/test/spec/function-references/binary.wast:77: assert_malformed passed: + 000001a: error: function body must end with END opcode +out/test/spec/function-references/binary.wast:93: assert_malformed passed: + 000001a: error: function body must end with END opcode +out/test/spec/function-references/binary.wast:113: assert_malformed passed: + 0000019: error: init expression must end with END opcode +out/test/spec/function-references/binary.wast:126: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/function-references/binary.wast:146: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/function-references/binary.wast:166: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/function-references/binary.wast:185: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/function-references/binary.wast:204: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/function-references/binary.wast:224: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/function-references/binary.wast:243: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/function-references/binary.wast:262: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/function-references/binary.wast:280: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/function-references/binary.wast:298: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/function-references/binary.wast:317: assert_malformed passed: + 0000017: error: unable to read u32 leb128: local type count +out/test/spec/function-references/binary.wast:334: assert_malformed passed: + 0000017: error: unable to read u32 leb128: local type count +out/test/spec/function-references/binary.wast:351: assert_malformed passed: + 000001e: error: local count must be <= 0xffffffff +out/test/spec/function-references/binary.wast:367: assert_malformed passed: + 0000030: error: local count must be <= 0xffffffff +out/test/spec/function-references/binary.wast:401: assert_malformed passed: + 0000013: error: function signature count != function body count +out/test/spec/function-references/binary.wast:411: assert_malformed passed: + 000000b: error: function signature count != function body count +out/test/spec/function-references/binary.wast:420: assert_malformed passed: + 0000016: error: function signature count != function body count +out/test/spec/function-references/binary.wast:431: assert_malformed passed: + 0000015: error: function signature count != function body count +out/test/spec/function-references/binary.wast:454: assert_malformed passed: + 000000e: error: data segment count does not equal count in DataCount section +out/test/spec/function-references/binary.wast:466: assert_malformed passed: + 000000e: error: data segment count does not equal count in DataCount section +out/test/spec/function-references/binary.wast:478: assert_malformed passed: + 0000010: error: Data section missing but DataCount non-zero +out/test/spec/function-references/binary.wast:494: assert_malformed passed: + 0000024: error: memory.init requires data count section +out/test/spec/function-references/binary.wast:517: assert_malformed passed: + 000001e: error: data.drop requires data count section +out/test/spec/function-references/binary.wast:537: assert_malformed passed: + 0000024: error: unexpected opcode: 0xf3 +out/test/spec/function-references/binary.wast:565: assert_malformed passed: + 0000022: error: table elem type must be a reference type +out/test/spec/function-references/binary.wast:650: assert_malformed passed: + 000000a: error: invalid section size: extends past end +out/test/spec/function-references/binary.wast:661: assert_malformed passed: + 000000e: error: unfinished section (expected end: 0x11) +out/test/spec/function-references/binary.wast:680: assert_malformed passed: + 000000e: error: invalid import tag kind: exceptions not allowed +out/test/spec/function-references/binary.wast:690: assert_malformed passed: + 000000e: error: invalid import tag kind: exceptions not allowed +out/test/spec/function-references/binary.wast:701: assert_malformed passed: + 000000e: error: malformed import kind: 5 +out/test/spec/function-references/binary.wast:711: assert_malformed passed: + 000000e: error: malformed import kind: 5 +out/test/spec/function-references/binary.wast:722: assert_malformed passed: + 000000e: error: malformed import kind: 128 +out/test/spec/function-references/binary.wast:732: assert_malformed passed: + 000000e: error: malformed import kind: 128 +out/test/spec/function-references/binary.wast:745: assert_malformed passed: + 0000027: error: unable to read u32 leb128: string length +out/test/spec/function-references/binary.wast:764: assert_malformed passed: + 000002b: error: unfinished section (expected end: 0x40) +out/test/spec/function-references/binary.wast:795: assert_malformed passed: + 000000b: error: invalid table count 1, only 0 bytes left in section +out/test/spec/function-references/binary.wast:805: assert_malformed passed: + 000000d: error: tables may not be shared +out/test/spec/function-references/binary.wast:814: assert_malformed passed: + 000000d: error: tables may not be shared +out/test/spec/function-references/binary.wast:824: assert_malformed passed: + 000000d: error: malformed table limits flag: 129 +out/test/spec/function-references/binary.wast:842: assert_malformed passed: + 000000b: error: invalid memory count 1, only 0 bytes left in section +out/test/spec/function-references/binary.wast:852: assert_malformed passed: + 000000c: error: memory may not be shared: threads not allowed +out/test/spec/function-references/binary.wast:860: assert_malformed passed: + 000000c: error: memory may not be shared: threads not allowed +out/test/spec/function-references/binary.wast:869: assert_malformed passed: + 000000c: error: malformed memory limits flag: 129 +out/test/spec/function-references/binary.wast:878: assert_malformed passed: + 000000c: error: malformed memory limits flag: 129 +out/test/spec/function-references/binary.wast:895: assert_malformed passed: + 0000010: error: unable to read i32 leb128: global type +out/test/spec/function-references/binary.wast:906: assert_malformed passed: + 0000010: error: unfinished section (expected end: 0x15) +out/test/spec/function-references/binary.wast:929: assert_malformed passed: + 000001b: error: unable to read u32 leb128: string length +out/test/spec/function-references/binary.wast:950: assert_malformed passed: + 000001b: error: unfinished section (expected end: 0x20) +out/test/spec/function-references/binary.wast:984: assert_malformed passed: + 0000021: error: unable to read u32 leb128: elem segment flags +out/test/spec/function-references/binary.wast:1000: assert_malformed passed: + 0000024: error: init expression must end with END opcode +out/test/spec/function-references/binary.wast:1017: assert_malformed passed: + 0000021: error: unfinished section (expected end: 0x27) +out/test/spec/function-references/binary.wast:1043: assert_malformed passed: + 0000016: error: unable to read u32 leb128: data segment flags +out/test/spec/function-references/binary.wast:1056: assert_malformed passed: + 0000016: error: unfinished section (expected end: 0x1c) +out/test/spec/function-references/binary.wast:1069: assert_malformed passed: + 0000015: error: unable to read data: data segment data +out/test/spec/function-references/binary.wast:1083: assert_malformed passed: + 000001a: error: unfinished section (expected end: 0x1b) +out/test/spec/function-references/binary.wast:1114: assert_malformed passed: + 0000048: error: function body must end with END opcode +out/test/spec/function-references/binary.wast:1161: assert_malformed passed: + 0000017: error: multiple Start sections +out/test/spec/function-references/binary.wast:1178: assert_malformed passed: + 0000014: error: multiple Function sections +out/test/spec/function-references/binary.wast:1190: assert_malformed passed: + 0000016: error: function signature count != function body count +out/test/spec/function-references/binary.wast:1202: assert_malformed passed: + 000000d: error: multiple DataCount sections +out/test/spec/function-references/binary.wast:1212: assert_malformed passed: + 000000d: error: multiple Data sections +out/test/spec/function-references/binary.wast:1222: assert_malformed passed: + 000000d: error: multiple Global sections +out/test/spec/function-references/binary.wast:1232: assert_malformed passed: + 000000d: error: multiple Export sections +out/test/spec/function-references/binary.wast:1242: assert_malformed passed: + 000000d: error: multiple Table sections +out/test/spec/function-references/binary.wast:1252: assert_malformed passed: + 000000d: error: multiple Elem sections +out/test/spec/function-references/binary.wast:1262: assert_malformed passed: + 000000d: error: multiple Import sections +out/test/spec/function-references/binary.wast:1272: assert_malformed passed: + 000000d: error: multiple Type sections +out/test/spec/function-references/binary.wast:1282: assert_malformed passed: + 000000d: error: multiple Memory sections +out/test/spec/function-references/binary.wast:1292: assert_malformed passed: + 000000d: error: section Type out of order +out/test/spec/function-references/binary.wast:1302: assert_malformed passed: + 000000d: error: section Import out of order +out/test/spec/function-references/binary.wast:1312: assert_malformed passed: + 000000d: error: section Function out of order +out/test/spec/function-references/binary.wast:1322: assert_malformed passed: + 000000d: error: section Table out of order +out/test/spec/function-references/binary.wast:1332: assert_malformed passed: + 000000d: error: section Memory out of order +out/test/spec/function-references/binary.wast:1342: assert_malformed passed: + 000000d: error: section Global out of order +out/test/spec/function-references/binary.wast:1352: assert_malformed passed: + 0000011: error: section Export out of order +out/test/spec/function-references/binary.wast:1363: assert_malformed passed: + 0000011: error: section Start out of order +out/test/spec/function-references/binary.wast:1374: assert_malformed passed: + 000000d: error: section Elem out of order +out/test/spec/function-references/binary.wast:1384: assert_malformed passed: + 000000d: error: section DataCount out of order +out/test/spec/function-references/binary.wast:1394: assert_malformed passed: + 000000d: error: section Code out of order +136/136 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/data.txt b/test/spec/function-references/data.txt new file mode 100644 index 0000000000..6954d9bfe2 --- /dev/null +++ b/test/spec/function-references/data.txt @@ -0,0 +1,66 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/data.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/data.wast:290: assert_invalid passed: + out/test/spec/function-references/data/data.39.wasm:000000c: error: memory variable out of range: 0 (max 0) + 000000c: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:298: assert_invalid passed: + out/test/spec/function-references/data/data.40.wasm:0000012: error: memory variable out of range: 1 (max 1) + 0000012: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:311: assert_invalid passed: + out/test/spec/function-references/data/data.41.wasm:000000c: error: memory variable out of range: 0 (max 0) + 000000c: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:322: assert_invalid passed: + out/test/spec/function-references/data/data.42.wasm:000000d: error: memory variable out of range: 1 (max 0) + 000000d: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:334: assert_invalid passed: + out/test/spec/function-references/data/data.43.wasm:0000012: error: memory variable out of range: 1 (max 1) + 0000012: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:356: assert_invalid passed: + out/test/spec/function-references/data/data.44.wasm:000000d: error: memory variable out of range: 1 (max 0) + 000000d: error: BeginDataSegment callback failed +out/test/spec/function-references/data.wast:375: assert_invalid passed: + out/test/spec/function-references/data/data.45.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [i64] + 0000014: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:383: assert_invalid passed: + out/test/spec/function-references/data/data.46.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [funcref] + 0000014: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:391: assert_invalid passed: + out/test/spec/function-references/data/data.47.wasm:0000011: error: type mismatch in initializer expression, expected [i32] but got [] + 0000012: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:399: assert_invalid passed: + out/test/spec/function-references/data/data.48.wasm:0000015: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000016: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:407: assert_invalid passed: + out/test/spec/function-references/data/data.49.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002c: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:416: assert_invalid passed: + out/test/spec/function-references/data/data.50.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002c: error: EndDataSegmentInitExpr callback failed +out/test/spec/function-references/data.wast:425: assert_invalid passed: + out/test/spec/function-references/data/data.51.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000014: error: OnUnaryExpr callback failed +out/test/spec/function-references/data.wast:433: assert_invalid passed: + out/test/spec/function-references/data/data.52.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop + 0000012: error: OnNopExpr callback failed +out/test/spec/function-references/data.wast:441: assert_invalid passed: + out/test/spec/function-references/data/data.53.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop + 0000012: error: OnNopExpr callback failed +out/test/spec/function-references/data.wast:449: assert_invalid passed: + out/test/spec/function-references/data/data.54.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: nop + 0000014: error: OnNopExpr callback failed +out/test/spec/function-references/data.wast:457: assert_invalid passed: + out/test/spec/function-references/data/data.55.wasm:0000020: error: initializer expression cannot reference a mutable global + 0000020: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/data.wast:466: assert_invalid passed: + out/test/spec/function-references/data/data.56.wasm:0000013: error: global variable out of range: 0 (max 0) + 0000013: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/data.wast:474: assert_invalid passed: + out/test/spec/function-references/data/data.57.wasm:0000029: error: global variable out of range: 1 (max 1) + 0000029: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/data.wast:483: assert_invalid passed: + out/test/spec/function-references/data/data.58.wasm:000002d: error: initializer expression cannot reference a mutable global + 000002d: error: OnGlobalGetExpr callback failed +59/59 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/elem.txt b/test/spec/function-references/elem.txt new file mode 100644 index 0000000000..48e136761a --- /dev/null +++ b/test/spec/function-references/elem.txt @@ -0,0 +1,90 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/elem.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/elem.wast:508: assert_invalid passed: + out/test/spec/function-references/elem/elem.53.wasm:0000025: error: type mismatch at elem segment. got funcref, expected (ref func) + 0000025: error: OnElemSegmentElemType callback failed +out/test/spec/function-references/elem.wast:516: assert_invalid passed: + out/test/spec/function-references/elem/elem.54.wasm:0000025: error: type mismatch at elem segment. got funcref, expected (ref func) + 0000025: error: OnElemSegmentElemType callback failed +out/test/spec/function-references/elem.wast:697: assert_trap passed: out of bounds table access: table.init out of bounds +out/test/spec/function-references/elem.wast:707: assert_trap passed: out of bounds table access: table.init out of bounds +out/test/spec/function-references/elem.wast:713: assert_invalid passed: + out/test/spec/function-references/elem/elem.75.wasm:0000016: error: table variable out of range: 0 (max 0) + 0000016: error: BeginElemSegment callback failed +out/test/spec/function-references/elem.wast:724: assert_invalid passed: + out/test/spec/function-references/elem/elem.76.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [i64] + 0000015: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:732: assert_invalid passed: + out/test/spec/function-references/elem/elem.77.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [funcref] + 0000015: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:740: assert_invalid passed: + out/test/spec/function-references/elem/elem.78.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got [] + 0000013: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:748: assert_invalid passed: + out/test/spec/function-references/elem/elem.79.wasm:0000016: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000017: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:756: assert_invalid passed: + out/test/spec/function-references/elem/elem.80.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002d: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:765: assert_invalid passed: + out/test/spec/function-references/elem/elem.81.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002d: error: EndElemSegmentInitExpr callback failed +out/test/spec/function-references/elem.wast:775: assert_invalid passed: + out/test/spec/function-references/elem/elem.82.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000015: error: OnUnaryExpr callback failed +out/test/spec/function-references/elem.wast:783: assert_invalid passed: + out/test/spec/function-references/elem/elem.83.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop + 0000013: error: OnNopExpr callback failed +out/test/spec/function-references/elem.wast:791: assert_invalid passed: + out/test/spec/function-references/elem/elem.84.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop + 0000013: error: OnNopExpr callback failed +out/test/spec/function-references/elem.wast:799: assert_invalid passed: + out/test/spec/function-references/elem/elem.85.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: nop + 0000015: error: OnNopExpr callback failed +out/test/spec/function-references/elem.wast:807: assert_invalid passed: + out/test/spec/function-references/elem/elem.86.wasm:0000021: error: initializer expression cannot reference a mutable global + 0000021: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/elem.wast:816: assert_invalid passed: + out/test/spec/function-references/elem/elem.87.wasm:0000014: error: global variable out of range: 0 (max 0) + 0000014: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/elem.wast:824: assert_invalid passed: + out/test/spec/function-references/elem/elem.88.wasm:000002a: error: global variable out of range: 1 (max 1) + 000002a: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/elem.wast:833: assert_invalid passed: + out/test/spec/function-references/elem/elem.89.wasm:000002e: error: initializer expression cannot reference a mutable global + 000002e: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/elem.wast:845: assert_invalid passed: + out/test/spec/function-references/elem/elem.90.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [externref] + 0000019: error: EndElemExpr callback failed +out/test/spec/function-references/elem.wast:853: assert_invalid passed: + out/test/spec/function-references/elem/elem.91.wasm:000001a: error: type mismatch at end of initializer expression, expected [] but got [funcref] + 000001b: error: EndElemExpr callback failed +out/test/spec/function-references/elem.wast:861: assert_invalid passed: + out/test/spec/function-references/elem/elem.92.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000019: error: EndElemExpr callback failed +out/test/spec/function-references/elem.wast:869: assert_invalid passed: + out/test/spec/function-references/elem/elem.93.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000019: error: EndElemExpr callback failed +out/test/spec/function-references/elem.wast:877: assert_invalid passed: + out/test/spec/function-references/elem/elem.94.wasm:0000023: error: invalid initializer: instruction not valid in initializer expression: call + 0000023: error: OnCallExpr callback failed +out/test/spec/function-references/elem.wast:886: assert_invalid passed: + out/test/spec/function-references/elem/elem.95.wasm:000001b: error: invalid initializer: instruction not valid in initializer expression: i32.add + 000001b: error: OnBinaryExpr callback failed +out/test/spec/function-references/elem.wast:945: assert_trap passed: uninitialized table element +out/test/spec/function-references/elem.wast:978: assert_invalid passed: + out/test/spec/function-references/elem/elem.101.wasm:000001f: error: type mismatch at elem segment. got (ref func), expected externref + 000001f: error: OnElemSegmentElemType callback failed +out/test/spec/function-references/elem.wast:983: assert_invalid passed: + out/test/spec/function-references/elem/elem.102.wasm:0000017: error: type mismatch at elem segment. got externref, expected funcref + 0000017: error: OnElemSegmentElemType callback failed +out/test/spec/function-references/elem.wast:988: assert_invalid passed: + out/test/spec/function-references/elem/elem.103.wasm:0000034: error: type mismatch at table.init. got funcref, expected externref + 0000034: error: OnTableInitExpr callback failed +out/test/spec/function-references/elem.wast:997: assert_invalid passed: + out/test/spec/function-references/elem/elem.104.wasm:0000030: error: type mismatch at table.init. got externref, expected funcref + 0000030: error: OnTableInitExpr callback failed +135/135 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/global.txt b/test/spec/function-references/global.txt index 2810e9015b..4eeba07b35 100644 --- a/test/spec/function-references/global.txt +++ b/test/spec/function-references/global.txt @@ -123,8 +123,8 @@ out/test/spec/function-references/global.wast:585: assert_invalid passed: out/test/spec/function-references/global/global.45.wasm:0000027: error: type mismatch in global.set, expected [i32] but got [] 0000027: error: OnGlobalSetExpr callback failed out/test/spec/function-references/global.wast:595: assert_invalid passed: - out/test/spec/function-references/global/global.46.wasm:000003e: error: type mismatch in global.set, expected [i32] but got [] - 000003e: error: OnGlobalSetExpr callback failed + out/test/spec/function-references/global/global.46.wasm:0000040: error: type mismatch in global.set, expected [i32] but got [] + 0000040: error: OnGlobalSetExpr callback failed out/test/spec/function-references/global.wast:613: assert_malformed passed: out/test/spec/function-references/global/global.47.wat:1:33: error: redefinition of global "$foo" (global $foo i32 (i32.const 0))(global $foo i32 (i32.const 0)) diff --git a/test/spec/function-references/if.txt b/test/spec/function-references/if.txt new file mode 100644 index 0000000000..4b5c423de0 --- /dev/null +++ b/test/spec/function-references/if.txt @@ -0,0 +1,409 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/if.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/if.wast:593: assert_trap passed: undefined table index +out/test/spec/function-references/if.wast:736: assert_malformed passed: + out/test/spec/function-references/if/if.1.wat:1:95: error: unexpected token "param", expected then block (e.g. (then ...)). + ...i32.const 0) (if (type $sig) (result i32) (param i32) (i32.const 1) (then))) + ^^^^^ + out/test/spec/function-references/if/if.1.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (type $sig) (result i32) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:745: assert_malformed passed: + out/test/spec/function-references/if/if.2.wat:1:82: error: unexpected token "type", expected then block (e.g. (then ...)). + ...nc (i32.const 0) (if (param i32) (type $sig) (result i32) (i32.const 1) (... + ^^^^ + out/test/spec/function-references/if/if.2.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (param i32) (type $sig) (result i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:754: assert_malformed passed: + out/test/spec/function-references/if/if.3.wat:1:95: error: unexpected token "type", expected then block (e.g. (then ...)). + ...i32.const 0) (if (param i32) (result i32) (type $sig) (i32.const 1) (then))) + ^^^^ + out/test/spec/function-references/if/if.3.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (param i32) (result i32) (type $sig) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:763: assert_malformed passed: + out/test/spec/function-references/if/if.4.wat:1:83: error: unexpected token "type", expected then block (e.g. (then ...)). + ...c (i32.const 0) (if (result i32) (type $sig) (param i32) (i32.const 1) (t... + ^^^^ + out/test/spec/function-references/if/if.4.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (result i32) (type $sig) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:772: assert_malformed passed: + out/test/spec/function-references/if/if.5.wat:1:83: error: unexpected token "param", expected then block (e.g. (then ...)). + ...c (i32.const 0) (if (result i32) (param i32) (type $sig) (i32.const 1) (t... + ^^^^^ + out/test/spec/function-references/if/if.5.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (result i32) (param i32) (type $sig) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:781: assert_malformed passed: + out/test/spec/function-references/if/if.6.wat:1:39: error: unexpected token "param", expected then block (e.g. (then ...)). + (func (i32.const 0) (if (result i32) (param i32) (i32.const 1) (then))) + ^^^^^ + out/test/spec/function-references/if/if.6.wat:1:65: error: unexpected token "then", expected an instr. + (func (i32.const 0) (if (result i32) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/function-references/if.wast:788: assert_malformed passed: + out/test/spec/function-references/if/if.7.wat:1:47: error: unexpected token $x, expected ). + ...(i32.const 0) (i32.const 1) (if (param $x i32) (then (drop)) (else (drop)))) + ^^ + out/test/spec/function-references/if/if.7.wat:1:69: error: unexpected token (, expected EOF. + ...(i32.const 0) (i32.const 1) (if (param $x i32) (then (drop)) (else (drop)))) + ^ +out/test/spec/function-references/if.wast:796: assert_malformed passed: + out/test/spec/function-references/if/if.8.wat:1:40: error: expected 0 results, got 1 + (type $sig (func))(func (i32.const 1) (if (type $sig) (result i32) (then (i3... + ^ +out/test/spec/function-references/if.wast:806: assert_malformed passed: + out/test/spec/function-references/if/if.9.wat:1:65: error: expected 1 arguments, got 0 + ...) (result i32)))(func (i32.const 1) (if (type $sig) (result i32) (then (i... + ^ +out/test/spec/function-references/if.wast:816: assert_malformed passed: + out/test/spec/function-references/if/if.10.wat:1:79: error: expected 1 results, got 0 + ...))(func (i32.const 0) (i32.const 1) (if (type $sig) (param i32) (then (dr... + ^ +out/test/spec/function-references/if.wast:826: assert_malformed passed: + out/test/spec/function-references/if/if.11.wat:1:83: error: expected 2 arguments, got 1 + ...))(func (i32.const 0) (i32.const 1) (if (type $sig) (param i32) (result i... + ^ +out/test/spec/function-references/if.wast:836: assert_invalid passed: + out/test/spec/function-references/if/if.12.wasm:000001f: error: type mismatch at end of function, expected [] but got [i32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:844: assert_invalid passed: + out/test/spec/function-references/if/if.13.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:848: assert_invalid passed: + out/test/spec/function-references/if/if.14.wasm:000001e: error: type mismatch in implicit return, expected [i64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:852: assert_invalid passed: + out/test/spec/function-references/if/if.15.wasm:000001e: error: type mismatch in implicit return, expected [f32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:856: assert_invalid passed: + out/test/spec/function-references/if/if.16.wasm:000001e: error: type mismatch in implicit return, expected [f64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:861: assert_invalid passed: + out/test/spec/function-references/if/if.17.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:865: assert_invalid passed: + out/test/spec/function-references/if/if.18.wasm:000001e: error: type mismatch in implicit return, expected [i64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:869: assert_invalid passed: + out/test/spec/function-references/if/if.19.wasm:000001e: error: type mismatch in implicit return, expected [f32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:873: assert_invalid passed: + out/test/spec/function-references/if/if.20.wasm:000001e: error: type mismatch in implicit return, expected [f64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:878: assert_invalid passed: + out/test/spec/function-references/if/if.21.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:884: assert_invalid passed: + out/test/spec/function-references/if/if.22.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:890: assert_invalid passed: + out/test/spec/function-references/if/if.23.wasm:000001f: error: type mismatch at end of `if false` branch, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:896: assert_invalid passed: + out/test/spec/function-references/if/if.24.wasm:000001d: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:903: assert_invalid passed: + out/test/spec/function-references/if/if.25.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:909: assert_invalid passed: + out/test/spec/function-references/if/if.26.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:915: assert_invalid passed: + out/test/spec/function-references/if/if.27.wasm:0000021: error: type mismatch at end of `if false` branch, expected [] but got [i32, i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:921: assert_invalid passed: + out/test/spec/function-references/if/if.28.wasm:000001f: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:928: assert_invalid passed: + out/test/spec/function-references/if/if.29.wasm:000001c: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001d: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:934: assert_invalid passed: + out/test/spec/function-references/if/if.30.wasm:000001f: error: type mismatch in `if false` branch, expected [i32] but got [] + 000001f: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:940: assert_invalid passed: + out/test/spec/function-references/if/if.31.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001d: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:947: assert_invalid passed: + out/test/spec/function-references/if/if.32.wasm:000001d: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:953: assert_invalid passed: + out/test/spec/function-references/if/if.33.wasm:0000022: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:959: assert_invalid passed: + out/test/spec/function-references/if/if.34.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001e: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:966: assert_invalid passed: + out/test/spec/function-references/if/if.35.wasm:000001f: error: type mismatch in `if false` branch, expected [i32] but got [] + 000001f: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:972: assert_invalid passed: + out/test/spec/function-references/if/if.36.wasm:0000022: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:979: assert_invalid passed: + out/test/spec/function-references/if/if.37.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:985: assert_invalid passed: + out/test/spec/function-references/if/if.38.wasm:0000021: error: type mismatch in `if false` branch, expected [i32] but got [] + 0000021: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:991: assert_invalid passed: + out/test/spec/function-references/if/if.39.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:998: assert_invalid passed: + out/test/spec/function-references/if/if.40.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001f: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1004: assert_invalid passed: + out/test/spec/function-references/if/if.41.wasm:0000024: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:1010: assert_invalid passed: + out/test/spec/function-references/if/if.42.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001f: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1017: assert_invalid passed: + out/test/spec/function-references/if/if.43.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1023: assert_invalid passed: + out/test/spec/function-references/if/if.44.wasm:0000022: error: type mismatch in `if false` branch, expected [i32] but got [i64] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:1029: assert_invalid passed: + out/test/spec/function-references/if/if.45.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1036: assert_invalid passed: + out/test/spec/function-references/if/if.46.wasm:000001f: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1042: assert_invalid passed: + out/test/spec/function-references/if/if.47.wasm:0000025: error: type mismatch in `if false` branch, expected [i32, i32] but got [i32] + 0000025: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:1048: assert_invalid passed: + out/test/spec/function-references/if/if.48.wasm:000001f: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1055: assert_invalid passed: + out/test/spec/function-references/if/if.49.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1062: assert_invalid passed: + out/test/spec/function-references/if/if.50.wasm:0000027: error: type mismatch in `if false` branch, expected [i32, i32] but got [i32] + 0000027: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:1069: assert_invalid passed: + out/test/spec/function-references/if/if.51.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1077: assert_invalid passed: + out/test/spec/function-references/if/if.52.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000021: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1083: assert_invalid passed: + out/test/spec/function-references/if/if.53.wasm:0000024: error: type mismatch at end of `if false` branch, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/if.wast:1089: assert_invalid passed: + out/test/spec/function-references/if/if.54.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000021: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1096: assert_invalid passed: + out/test/spec/function-references/if/if.55.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1102: assert_invalid passed: + out/test/spec/function-references/if/if.56.wasm:0000023: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000024: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1109: assert_invalid passed: + out/test/spec/function-references/if/if.57.wasm:0000025: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000025: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:1119: assert_invalid passed: + out/test/spec/function-references/if/if.58.wasm:0000025: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000025: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:1129: assert_invalid passed: + out/test/spec/function-references/if/if.59.wasm:0000027: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000027: error: EndFunctionBody callback failed +out/test/spec/function-references/if.wast:1140: assert_invalid passed: + out/test/spec/function-references/if/if.60.wasm:000001e: error: type mismatch in br, expected [i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1146: assert_invalid passed: + out/test/spec/function-references/if/if.61.wasm:0000021: error: type mismatch in br, expected [i32] but got [] + 0000021: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1152: assert_invalid passed: + out/test/spec/function-references/if/if.62.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1158: assert_invalid passed: + out/test/spec/function-references/if/if.63.wasm:0000024: error: type mismatch in br, expected [i32, i32] but got [] + 0000024: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1165: assert_invalid passed: + out/test/spec/function-references/if/if.64.wasm:000001e: error: type mismatch in br, expected [i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1174: assert_invalid passed: + out/test/spec/function-references/if/if.65.wasm:0000021: error: type mismatch in br, expected [i32] but got [] + 0000021: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1183: assert_invalid passed: + out/test/spec/function-references/if/if.66.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1192: assert_invalid passed: + out/test/spec/function-references/if/if.67.wasm:0000024: error: type mismatch in br, expected [i32, i32] but got [] + 0000024: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1202: assert_invalid passed: + out/test/spec/function-references/if/if.68.wasm:000001f: error: type mismatch in br, expected [i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1211: assert_invalid passed: + out/test/spec/function-references/if/if.69.wasm:0000022: error: type mismatch in br, expected [i32] but got [] + 0000022: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1220: assert_invalid passed: + out/test/spec/function-references/if/if.70.wasm:0000020: error: type mismatch in br, expected [i32, i32] but got [] + 0000020: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1229: assert_invalid passed: + out/test/spec/function-references/if/if.71.wasm:0000025: error: type mismatch in br, expected [i32, i32] but got [] + 0000025: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1239: assert_invalid passed: + out/test/spec/function-references/if/if.72.wasm:0000020: error: type mismatch in br, expected [i32] but got [i64] + 0000020: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1248: assert_invalid passed: + out/test/spec/function-references/if/if.73.wasm:0000023: error: type mismatch in br, expected [i32] but got [i64] + 0000023: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1257: assert_invalid passed: + out/test/spec/function-references/if/if.74.wasm:0000021: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000021: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1266: assert_invalid passed: + out/test/spec/function-references/if/if.75.wasm:0000026: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000026: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1275: assert_invalid passed: + out/test/spec/function-references/if/if.76.wasm:0000023: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000023: error: OnBrExpr callback failed +out/test/spec/function-references/if.wast:1285: assert_invalid passed: + out/test/spec/function-references/if/if.77.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/function-references/if.wast:1296: assert_invalid passed: + out/test/spec/function-references/if/if.78.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1304: assert_invalid passed: + out/test/spec/function-references/if/if.79.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1313: assert_invalid passed: + out/test/spec/function-references/if/if.80.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1322: assert_invalid passed: + out/test/spec/function-references/if/if.81.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1331: assert_invalid passed: + out/test/spec/function-references/if/if.82.wasm:0000022: error: type mismatch in if, expected [i32] but got [] + 0000022: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1341: assert_invalid passed: + out/test/spec/function-references/if/if.83.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1350: assert_invalid passed: + out/test/spec/function-references/if/if.84.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1359: assert_invalid passed: + out/test/spec/function-references/if/if.85.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1368: assert_invalid passed: + out/test/spec/function-references/if/if.86.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1376: assert_invalid passed: + out/test/spec/function-references/if/if.87.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1384: assert_invalid passed: + out/test/spec/function-references/if/if.88.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1393: assert_invalid passed: + out/test/spec/function-references/if/if.89.wasm:0000038: error: type mismatch in if, expected [i32] but got [] + 0000038: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1409: assert_invalid passed: + out/test/spec/function-references/if/if.90.wasm:000001b: error: type mismatch in if, expected [i32] but got [] + 000001b: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1418: assert_invalid passed: + out/test/spec/function-references/if/if.91.wasm:000001b: error: type mismatch in if, expected [i32] but got [] + 000001b: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1427: assert_invalid passed: + out/test/spec/function-references/if/if.92.wasm:0000021: error: type mismatch in if, expected [i32] but got [] + 0000021: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1436: assert_invalid passed: + out/test/spec/function-references/if/if.93.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1445: assert_invalid passed: + out/test/spec/function-references/if/if.94.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1454: assert_invalid passed: + out/test/spec/function-references/if/if.95.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1464: assert_invalid passed: + out/test/spec/function-references/if/if.96.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1470: assert_invalid passed: + out/test/spec/function-references/if/if.97.wasm:0000020: error: type mismatch in if, expected [i32, f64] but got [] + 0000020: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1476: assert_invalid passed: + out/test/spec/function-references/if/if.98.wasm:0000024: error: type mismatch in if, expected [i32] but got [f32] + 0000024: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1482: assert_invalid passed: + out/test/spec/function-references/if/if.99.wasm:0000025: error: type mismatch in if, expected [f32, i32] but got [f32] + 0000025: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1488: assert_invalid passed: + out/test/spec/function-references/if/if.100.wasm:0000021: error: type mismatch in if, expected [i32] but got [] + 0000021: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1494: assert_invalid passed: + out/test/spec/function-references/if/if.101.wasm:0000022: error: type mismatch in if, expected [i32, f64] but got [] + 0000022: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1500: assert_invalid passed: + out/test/spec/function-references/if/if.102.wasm:0000026: error: type mismatch in if, expected [i32] but got [f32] + 0000026: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1506: assert_invalid passed: + out/test/spec/function-references/if/if.103.wasm:0000027: error: type mismatch in if, expected [f32, i32] but got [f32] + 0000027: error: OnIfExpr callback failed +out/test/spec/function-references/if.wast:1513: assert_malformed passed: + out/test/spec/function-references/if/if.104.wat:1:42: error: unexpected token $x, expected ). + (func (param i32) (result i32) if (param $x i32) end) + ^^ +out/test/spec/function-references/if.wast:1517: assert_malformed passed: + out/test/spec/function-references/if/if.105.wat:1:43: error: unexpected token $x, expected ). + (func (param i32) (result i32) (if (param $x i32) (then))) + ^^ +out/test/spec/function-references/if.wast:1522: assert_malformed passed: + out/test/spec/function-references/if/if.106.wat:1:26: error: unexpected label "$l" + (func i32.const 0 if end $l) + ^^ +out/test/spec/function-references/if.wast:1526: assert_malformed passed: + out/test/spec/function-references/if/if.107.wat:1:29: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a end $l) + ^^ +out/test/spec/function-references/if.wast:1530: assert_malformed passed: + out/test/spec/function-references/if/if.108.wat:1:27: error: unexpected label "$l" + (func i32.const 0 if else $l end) + ^^ +out/test/spec/function-references/if.wast:1534: assert_malformed passed: + out/test/spec/function-references/if/if.109.wat:1:30: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end) + ^^ +out/test/spec/function-references/if.wast:1538: assert_malformed passed: + out/test/spec/function-references/if/if.110.wat:1:31: error: unexpected label "$l" + (func i32.const 0 if else end $l) + ^^ +out/test/spec/function-references/if.wast:1542: assert_malformed passed: + out/test/spec/function-references/if/if.111.wat:1:27: error: unexpected label "$l" + (func i32.const 0 if else $l end $l) + ^^ + out/test/spec/function-references/if/if.111.wat:1:34: error: unexpected label "$l" + (func i32.const 0 if else $l end $l) + ^^ +out/test/spec/function-references/if.wast:1546: assert_malformed passed: + out/test/spec/function-references/if/if.112.wat:1:27: error: unexpected label "$l1" + (func i32.const 0 if else $l1 end $l2) + ^^^ + out/test/spec/function-references/if/if.112.wat:1:35: error: unexpected label "$l2" + (func i32.const 0 if else $l1 end $l2) + ^^^ +out/test/spec/function-references/if.wast:1550: assert_malformed passed: + out/test/spec/function-references/if/if.113.wat:1:34: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else end $l) + ^^ +out/test/spec/function-references/if.wast:1554: assert_malformed passed: + out/test/spec/function-references/if/if.114.wat:1:37: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $a end $l) + ^^ +out/test/spec/function-references/if.wast:1558: assert_malformed passed: + out/test/spec/function-references/if/if.115.wat:1:30: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end $l) + ^^ + out/test/spec/function-references/if/if.115.wat:1:37: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end $l) + ^^ +out/test/spec/function-references/if.wast:1562: assert_malformed passed: + out/test/spec/function-references/if/if.116.wat:1:11: error: unexpected token i32.const, expected (. + (func (if i32.const 0 (then) (else))) + ^^^^^^^^^ +241/241 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/linking.txt b/test/spec/function-references/linking.txt new file mode 100644 index 0000000000..01cd478503 --- /dev/null +++ b/test/spec/function-references/linking.txt @@ -0,0 +1,118 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/linking.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/linking.wast:28: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/function-references/linking.wast:32: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/function-references/linking.wast:87: assert_unlinkable passed: + error: mutability mismatch in imported global, expected mutable but got immutable. +out/test/spec/function-references/linking.wast:91: assert_unlinkable passed: + error: mutability mismatch in imported global, expected immutable but got mutable. +out/test/spec/function-references/linking.wast:133: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got externref. +out/test/spec/function-references/linking.wast:138: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got funcref. +out/test/spec/function-references/linking.wast:142: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref null 0). +out/test/spec/function-references/linking.wast:146: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got externref. +out/test/spec/function-references/linking.wast:151: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got funcref. +out/test/spec/function-references/linking.wast:155: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref func). +out/test/spec/function-references/linking.wast:159: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got externref. +out/test/spec/function-references/linking.wast:164: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got funcref. +out/test/spec/function-references/linking.wast:168: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref func). +out/test/spec/function-references/linking.wast:172: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref null 0). +out/test/spec/function-references/linking.wast:176: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got externref. +out/test/spec/function-references/linking.wast:181: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got funcref. +out/test/spec/function-references/linking.wast:185: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref func). +out/test/spec/function-references/linking.wast:189: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref null 0). +out/test/spec/function-references/linking.wast:193: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref 0). +out/test/spec/function-references/linking.wast:199: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref func). +out/test/spec/function-references/linking.wast:203: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref null 0). +out/test/spec/function-references/linking.wast:207: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref 0). +out/test/spec/function-references/linking.wast:211: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got externref. +out/test/spec/function-references/linking.wast:216: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got funcref. +out/test/spec/function-references/linking.wast:220: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref null 0). +out/test/spec/function-references/linking.wast:224: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref 0). +out/test/spec/function-references/linking.wast:228: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got externref. +out/test/spec/function-references/linking.wast:233: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got funcref. +out/test/spec/function-references/linking.wast:237: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref func). +out/test/spec/function-references/linking.wast:241: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref 0). +out/test/spec/function-references/linking.wast:245: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got externref. +out/test/spec/function-references/linking.wast:250: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got funcref. +out/test/spec/function-references/linking.wast:254: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref func). +out/test/spec/function-references/linking.wast:258: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref null 0). +out/test/spec/function-references/linking.wast:262: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got externref. +out/test/spec/function-references/linking.wast:267: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got funcref. +out/test/spec/function-references/linking.wast:271: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref func). +out/test/spec/function-references/linking.wast:275: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref null 0). +out/test/spec/function-references/linking.wast:279: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref 0). +out/test/spec/function-references/linking.wast:325: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:326: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:328: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:330: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:331: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:333: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:335: assert_trap passed: undefined table index +out/test/spec/function-references/linking.wast:336: assert_trap passed: undefined table index +out/test/spec/function-references/linking.wast:337: assert_trap passed: undefined table index +out/test/spec/function-references/linking.wast:338: assert_trap passed: undefined table index +out/test/spec/function-references/linking.wast:341: assert_trap passed: indirect call signature mismatch +out/test/spec/function-references/linking.wast:373: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:374: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:376: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:377: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:379: assert_trap passed: undefined table index +out/test/spec/function-references/linking.wast:405: assert_unlinkable passed: + error: invalid import "Mt.mem" +out/test/spec/function-references/linking.wast:414: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:428: assert_trap passed: uninitialized table element +out/test/spec/function-references/linking.wast:459: assert_unlinkable passed: + error: type mismatch in imported table, expected funcref but got (ref null 0). +out/test/spec/function-references/linking.wast:463: assert_unlinkable passed: + error: type mismatch in imported table, expected funcref but got externref. +out/test/spec/function-references/linking.wast:468: assert_unlinkable passed: + error: type mismatch in imported table, expected (ref null 0) but got funcref. +out/test/spec/function-references/linking.wast:472: assert_unlinkable passed: + error: type mismatch in imported table, expected (ref null 0) but got externref. +out/test/spec/function-references/linking.wast:477: assert_unlinkable passed: + error: type mismatch in imported table, expected externref but got funcref. +out/test/spec/function-references/linking.wast:481: assert_unlinkable passed: + error: type mismatch in imported table, expected externref but got (ref null 0). +out/test/spec/function-references/linking.wast:559: assert_unlinkable passed: + error: invalid import "Mm.tab" +158/158 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/local_get.txt b/test/spec/function-references/local_get.txt new file mode 100644 index 0000000000..580bdaf7a5 --- /dev/null +++ b/test/spec/function-references/local_get.txt @@ -0,0 +1,54 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/local_get.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/local_get.wast:149: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.1.wasm:000001d: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:153: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.2.wasm:000001d: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001d: error: OnConvertExpr callback failed +out/test/spec/function-references/local_get.wast:157: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.3.wasm:000001f: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001f: error: OnUnaryExpr callback failed +out/test/spec/function-references/local_get.wast:165: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.4.wasm:000001c: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:169: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.5.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/local_get.wast:173: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.6.wasm:000001d: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001d: error: OnUnaryExpr callback failed +out/test/spec/function-references/local_get.wast:181: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.7.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:185: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.8.wasm:000001c: error: type mismatch at end of function, expected [] but got [i64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:189: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.9.wasm:000001c: error: type mismatch at end of function, expected [] but got [f32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:193: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.10.wasm:000001c: error: type mismatch at end of function, expected [] but got [f64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/local_get.wast:201: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.11.wasm:000001d: error: local variable out of range (max 2) + 000001d: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_get.wast:205: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.12.wasm:0000020: error: local variable out of range (max 2) + 0000020: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_get.wast:210: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.13.wasm:000001b: error: local variable out of range (max 2) + 000001b: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_get.wast:214: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.14.wasm:000001f: error: local variable out of range (max 2) + 000001f: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_get.wast:219: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.15.wasm:000001e: error: local variable out of range (max 3) + 000001e: error: OnLocalGetExpr callback failed +out/test/spec/function-references/local_get.wast:223: assert_invalid passed: + out/test/spec/function-references/local_get/local_get.16.wasm:0000021: error: local variable out of range (max 3) + 0000021: error: OnLocalGetExpr callback failed +36/36 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/ref.txt b/test/spec/function-references/ref.txt index e178a7799a..e4be27c8d9 100644 --- a/test/spec/function-references/ref.txt +++ b/test/spec/function-references/ref.txt @@ -13,7 +13,7 @@ out/test/spec/function-references/ref.wast:37: assert_invalid passed: 000000e: error: BeginGlobal callback failed out/test/spec/function-references/ref.wast:42: assert_invalid passed: out/test/spec/function-references/ref/ref.4.wasm:000000f: error: reference 1 is out of range in tables - 000000f: error: OnTable callback failed + 000000f: error: BeginTable callback failed out/test/spec/function-references/ref.wast:47: assert_invalid passed: out/test/spec/function-references/ref/ref.5.wasm:000000e: error: reference 1 is out of range 000000e: error: OnElemSegmentElemType callback failed diff --git a/test/spec/function-references/ref_is_null.txt b/test/spec/function-references/ref_is_null.txt new file mode 100644 index 0000000000..7e9b59f5f1 --- /dev/null +++ b/test/spec/function-references/ref_is_null.txt @@ -0,0 +1,14 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/ref_is_null.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +init(externref:1) => +deinit() => +out/test/spec/function-references/ref_is_null.wast:79: assert_invalid passed: + out/test/spec/function-references/ref_is_null/ref_is_null.2.wasm:000001b: error: type mismatch in ref.is_null, expected [reference] but got [i32] + 000001b: error: OnRefIsNullExpr callback failed +out/test/spec/function-references/ref_is_null.wast:83: assert_invalid passed: + out/test/spec/function-references/ref_is_null/ref_is_null.3.wasm:0000018: error: type mismatch in ref.is_null, expected [reference] but got [] + 0000018: error: OnRefIsNullExpr callback failed +22/22 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/ref_null.txt b/test/spec/function-references/ref_null.txt new file mode 100644 index 0000000000..277961e5c0 --- /dev/null +++ b/test/spec/function-references/ref_null.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/ref_null.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +4/4 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/return_call.txt b/test/spec/function-references/return_call.txt new file mode 100644 index 0000000000..1cda3fd427 --- /dev/null +++ b/test/spec/function-references/return_call.txt @@ -0,0 +1,39 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/return_call.wast +;;; ARGS*: --enable-function-references --enable-tail-call +(;; STDOUT ;;; +out/test/spec/function-references/return_call.wast:124: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.1.wasm:000001e: error: return signatures have inconsistent types: expected [i32], got [] + 000001e: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:131: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.2.wasm:000001f: error: return signatures have inconsistent types: expected [i32], got [i64] + 000001f: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:139: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.3.wasm:000001e: error: type mismatch in return_call, expected [i32] but got [] + 000001e: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:146: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.4.wasm:000001f: error: type mismatch in return_call, expected [f64, i32] but got [] + 000001f: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:164: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.7.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32] + 0000022: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:171: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.8.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32] + 0000022: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:178: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.9.wasm:000002a: error: type mismatch in return_call, expected [i32, f64] but got [f64, i32] + 000002a: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:185: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.10.wasm:000002a: error: type mismatch in return_call, expected [f64, i32] but got [i32, f64] + 000002a: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:192: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.11.wasm:0000024: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000024: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:204: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.12.wasm:0000019: error: function variable out of range: 1 (max 1) + 0000019: error: OnReturnCallExpr callback failed +out/test/spec/function-references/return_call.wast:208: assert_invalid passed: + out/test/spec/function-references/return_call/return_call.13.wasm:000001d: error: function variable out of range: 1012321300 (max 1) + 000001d: error: OnReturnCallExpr callback failed +45/45 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/return_call_indirect.txt b/test/spec/function-references/return_call_indirect.txt new file mode 100644 index 0000000000..0d491ef5f5 --- /dev/null +++ b/test/spec/function-references/return_call_indirect.txt @@ -0,0 +1,124 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/return_call_indirect.wast +;;; ARGS*: --enable-function-references --enable-tail-call +(;; STDOUT ;;; +out/test/spec/function-references/return_call_indirect.wast:234: assert_trap passed: indirect call signature mismatch +out/test/spec/function-references/return_call_indirect.wast:235: assert_trap passed: indirect call signature mismatch +out/test/spec/function-references/return_call_indirect.wast:236: assert_trap passed: undefined table index +out/test/spec/function-references/return_call_indirect.wast:237: assert_trap passed: undefined table index +out/test/spec/function-references/return_call_indirect.wast:238: assert_trap passed: undefined table index +out/test/spec/function-references/return_call_indirect.wast:244: assert_trap passed: indirect call signature mismatch +out/test/spec/function-references/return_call_indirect.wast:245: assert_trap passed: indirect call signature mismatch +out/test/spec/function-references/return_call_indirect.wast:273: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.1.wat:1:129: error: unexpected token "param", expected an expr. + ...indirect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const ... + ^^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.1.wat:1:173: error: unexpected token ), expected EOF. + ...irect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:285: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.2.wat:1:116: error: unexpected token "type", expected an expr. + ...(return_call_indirect (param i32) (type $sig) (result i32) (i32.const 0... + ^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.2.wat:1:173: error: unexpected token ), expected EOF. + ...irect (param i32) (type $sig) (result i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:297: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.3.wat:1:129: error: unexpected token "type", expected an expr. + ...indirect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const ... + ^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.3.wat:1:173: error: unexpected token ), expected EOF. + ...irect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:309: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.4.wat:1:117: error: unexpected token "type", expected an expr. + ...return_call_indirect (result i32) (type $sig) (param i32) (i32.const 0)... + ^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.4.wat:1:173: error: unexpected token ), expected EOF. + ...irect (result i32) (type $sig) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:321: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.5.wat:1:117: error: unexpected token "param", expected an expr. + ...return_call_indirect (result i32) (param i32) (type $sig) (i32.const 0)... + ^^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.5.wat:1:173: error: unexpected token ), expected EOF. + ...irect (result i32) (param i32) (type $sig) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:333: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.6.wat:1:74: error: unexpected token "param", expected an expr. + ...return_call_indirect (result i32) (param i32) (i32.const 0) (i32.const ... + ^^^^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.6.wat:1:118: error: unexpected token ), expected EOF. + ...urn_call_indirect (result i32) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/function-references/return_call_indirect.wast:345: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.7.wat:1:53: error: unexpected token $x, expected ). + ...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0))) + ^^ + out/test/spec/function-references/return_call_indirect/return_call_indirect.7.wat:1:89: error: unexpected token ), expected EOF. + ...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0))) + ^ +out/test/spec/function-references/return_call_indirect.wast:352: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.8.wat:1:57: error: expected 0 results, got 1 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/function-references/return_call_indirect.wast:362: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.9.wat:1:82: error: expected 1 arguments, got 0 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/function-references/return_call_indirect.wast:372: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.10.wat:1:69: error: expected 1 results, got 0 + ...))(table 0 funcref)(func (return_call_indirect (type $sig) (param i32) ... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/function-references/return_call_indirect.wast:384: assert_malformed passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.11.wat:1:86: error: expected 2 arguments, got 1 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (param i32) (r... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/function-references/return_call_indirect.wast:399: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.12.wasm:000001c: error: table variable out of range: 0 (max 0) + out/test/spec/function-references/return_call_indirect/return_call_indirect.12.wasm:000001c: error: type mismatch: return_call_indirect must reference table of funcref type + 000001c: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:407: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.13.wasm:0000024: error: type mismatch at end of function, expected [] but got [i32] + 0000024: error: EndFunctionBody callback failed +out/test/spec/function-references/return_call_indirect.wast:415: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.14.wasm:0000026: error: return signatures have inconsistent types: expected [], got [i64] + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:424: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.15.wasm:0000026: error: type mismatch in return_call_indirect, expected [i32] but got [] + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:432: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.16.wasm:0000027: error: type mismatch in return_call_indirect, expected [f64, i32] but got [] + 0000027: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:455: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.19.wasm:0000027: error: type mismatch in return_call_indirect, expected [i32] but got [] + 0000027: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:463: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.20.wasm:0000028: error: type mismatch in return_call_indirect, expected [i32] but got [... i64] + 0000028: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:472: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.21.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32] + 000002a: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:482: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.22.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32] + 000002a: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:492: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.23.wasm:0000032: error: type mismatch in return_call_indirect, expected [i32, f64] but got [f64, i32] + 0000032: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:502: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.24.wasm:0000032: error: type mismatch in return_call_indirect, expected [f64, i32] but got [i32, f64] + 0000032: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:512: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.25.wasm:0000034: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000034: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:526: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.26.wasm:0000022: error: function type variable out of range: 1 (max 1) + 0000022: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:533: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.27.wasm:0000026: error: function type variable out of range: 1012321300 (max 1) + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/function-references/return_call_indirect.wast:544: assert_invalid passed: + out/test/spec/function-references/return_call_indirect/return_call_indirect.28.wasm:0000019: error: function variable out of range: 0 (max 0) + 0000019: error: OnRefFuncExpr callback failed +76/76 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/select.txt b/test/spec/function-references/select.txt new file mode 100644 index 0000000000..77e04f2482 --- /dev/null +++ b/test/spec/function-references/select.txt @@ -0,0 +1,102 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/select.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/select.wast:282: assert_trap passed: unreachable executed +out/test/spec/function-references/select.wast:283: assert_trap passed: unreachable executed +out/test/spec/function-references/select.wast:284: assert_trap passed: unreachable executed +out/test/spec/function-references/select.wast:285: assert_trap passed: unreachable executed +out/test/spec/function-references/select.wast:322: assert_trap passed: undefined table index +out/test/spec/function-references/select.wast:323: assert_trap passed: undefined table index +out/test/spec/function-references/select.wast:364: assert_invalid passed: + out/test/spec/function-references/select/select.1.wasm:000001c: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:368: assert_invalid passed: + out/test/spec/function-references/select/select.2.wasm:000001c: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:372: assert_invalid passed: + out/test/spec/function-references/select/select.3.wasm:0000027: error: invalid arity in select instruction: 2. + 0000027: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:384: assert_invalid passed: + out/test/spec/function-references/select/select.4.wasm:0000023: error: type mismatch in select, expected [any, any, i32] but got [(ref 0), (ref 0), i32] + 0000023: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:392: assert_invalid passed: + out/test/spec/function-references/select/select.5.wasm:000001f: error: type mismatch in select, expected [any, any, i32] but got [funcref, funcref, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:398: assert_invalid passed: + out/test/spec/function-references/select/select.6.wasm:000001f: error: type mismatch in select, expected [any, any, i32] but got [externref, externref, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:408: assert_invalid passed: + out/test/spec/function-references/select/select.8.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:414: assert_invalid passed: + out/test/spec/function-references/select/select.9.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:420: assert_invalid passed: + out/test/spec/function-references/select/select.10.wasm:0000025: error: type mismatch in select, expected [f64, f64, i32] but got [i32, f64, i32] + 0000025: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:427: assert_invalid passed: + out/test/spec/function-references/select/select.11.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:431: assert_invalid passed: + out/test/spec/function-references/select/select.12.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:435: assert_invalid passed: + out/test/spec/function-references/select/select.13.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:439: assert_invalid passed: + out/test/spec/function-references/select/select.14.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:443: assert_invalid passed: + out/test/spec/function-references/select/select.15.wasm:0000025: error: type mismatch in select, expected [f64, f64, i32] but got [i32, f64, i32] + 0000025: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:449: assert_invalid passed: + out/test/spec/function-references/select/select.16.wasm:0000018: error: type mismatch in select, expected [any, any, i32] but got [] + 0000018: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:457: assert_invalid passed: + out/test/spec/function-references/select/select.17.wasm:000001a: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001a: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:465: assert_invalid passed: + out/test/spec/function-references/select/select.18.wasm:000001c: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:473: assert_invalid passed: + out/test/spec/function-references/select/select.19.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:482: assert_invalid passed: + out/test/spec/function-references/select/select.20.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:491: assert_invalid passed: + out/test/spec/function-references/select/select.21.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:500: assert_invalid passed: + out/test/spec/function-references/select/select.22.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:509: assert_invalid passed: + out/test/spec/function-references/select/select.23.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:518: assert_invalid passed: + out/test/spec/function-references/select/select.24.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:527: assert_invalid passed: + out/test/spec/function-references/select/select.25.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:536: assert_invalid passed: + out/test/spec/function-references/select/select.26.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:545: assert_invalid passed: + out/test/spec/function-references/select/select.27.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:557: assert_invalid passed: + out/test/spec/function-references/select/select.28.wasm:000001e: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, i64] + 000001e: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:561: assert_invalid passed: + out/test/spec/function-references/select/select.29.wasm:0000021: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, f32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:565: assert_invalid passed: + out/test/spec/function-references/select/select.30.wasm:0000025: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, f64] + 0000025: error: OnSelectExpr callback failed +out/test/spec/function-references/select.wast:572: assert_invalid passed: + out/test/spec/function-references/select/select.31.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000020: error: EndFunctionBody callback failed +157/157 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/table-sub.txt b/test/spec/function-references/table-sub.txt new file mode 100644 index 0000000000..94e463cbba --- /dev/null +++ b/test/spec/function-references/table-sub.txt @@ -0,0 +1,12 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/table-sub.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/table-sub.wast:13: assert_invalid passed: + out/test/spec/function-references/table-sub/table-sub.1.wasm:000002a: error: type mismatch at table.copy. got externref, expected funcref + 000002a: error: OnTableCopyExpr callback failed +out/test/spec/function-references/table-sub.wast:24: assert_invalid passed: + out/test/spec/function-references/table-sub/table-sub.2.wasm:000002d: error: type mismatch at table.init. got externref, expected funcref + 000002d: error: OnTableInitExpr callback failed +3/3 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/table.txt b/test/spec/function-references/table.txt new file mode 100644 index 0000000000..78f6023cdf --- /dev/null +++ b/test/spec/function-references/table.txt @@ -0,0 +1,75 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/table.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/table.wast:22: assert_invalid passed: + out/test/spec/function-references/table/table.15.wasm:000000c: error: table variable out of range: 0 (max 0) + 000000c: error: BeginElemSegment callback failed +out/test/spec/function-references/table.wast:23: assert_invalid passed: + out/test/spec/function-references/table/table.16.wasm:0000016: error: table variable out of range: 0 (max 0) + 0000016: error: BeginElemSegment callback failed +out/test/spec/function-references/table.wast:27: assert_invalid passed: + out/test/spec/function-references/table/table.17.wasm:000000f: error: max elems (0) must be >= initial elems (1) + 000000f: error: BeginTable callback failed +out/test/spec/function-references/table.wast:31: assert_invalid passed: + out/test/spec/function-references/table/table.18.wasm:0000013: error: max elems (0) must be >= initial elems (4294967295) + 0000013: error: BeginTable callback failed +out/test/spec/function-references/table.wast:36: assert_malformed passed: + out/test/spec/function-references/table/table.19.wat:1:8: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/function-references/table.wast:40: assert_malformed passed: + out/test/spec/function-references/table/table.20.wat:1:8: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ + out/test/spec/function-references/table/table.20.wat:1:22: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/function-references/table.wast:44: assert_malformed passed: + out/test/spec/function-references/table/table.21.wat:1:10: error: invalid int "0x1_0000_0000" + (table 0 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/function-references/table.wast:49: assert_invalid passed: + out/test/spec/function-references/table/table.22.wasm:0000012: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000013: error: EndTableInitExpr callback failed +out/test/spec/function-references/table.wast:53: assert_invalid passed: + out/test/spec/function-references/table/table.23.wasm:0000013: error: type mismatch in initializer expression, expected [(ref func)] but got [externref] + 0000014: error: EndTableInitExpr callback failed +out/test/spec/function-references/table.wast:57: assert_invalid passed: + out/test/spec/function-references/table/table.24.wasm:0000019: error: type mismatch in initializer expression, expected [(ref 0)] but got [funcref] + 000001a: error: EndTableInitExpr callback failed +out/test/spec/function-references/table.wast:61: assert_invalid passed: + out/test/spec/function-references/table/table.25.wasm:0000013: error: type mismatch in initializer expression, expected [(ref func)] but got [funcref] + 0000014: error: EndTableInitExpr callback failed +out/test/spec/function-references/table.wast:65: assert_invalid passed: + out/test/spec/function-references/table/table.26.wasm:000000f: error: missing table initializer + 000000f: error: BeginTable callback failed +out/test/spec/function-references/table.wast:69: assert_invalid passed: + out/test/spec/function-references/table/table.27.wasm:000000f: error: missing table initializer + 000000f: error: BeginTable callback failed +out/test/spec/function-references/table.wast:73: assert_invalid passed: + out/test/spec/function-references/table/table.28.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/function-references/table.wast:114: assert_invalid passed: + out/test/spec/function-references/table/table.31.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/function-references/table.wast:122: assert_invalid passed: + out/test/spec/function-references/table/table.32.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/function-references/table.wast:130: assert_invalid passed: + out/test/spec/function-references/table/table.33.wasm:0000016: error: missing table initializer + 0000016: error: BeginTable callback failed +out/test/spec/function-references/table.wast:141: assert_malformed passed: + out/test/spec/function-references/table/table.34.wat:1:24: error: redefinition of table "$foo" + (table $foo 1 funcref)(table $foo 1 funcref) + ^^^^^ +out/test/spec/function-references/table.wast:148: assert_malformed passed: + out/test/spec/function-references/table/table.35.wat:1:39: error: redefinition of table "$foo" + (import "" "" (table $foo 1 funcref))(table $foo 1 funcref) + ^^^^^ +out/test/spec/function-references/table.wast:155: assert_malformed passed: + out/test/spec/function-references/table/table.36.wat:1:39: error: redefinition of table "$foo" + (import "" "" (table $foo 1 funcref))(import "" "" (table $foo 1 funcref)) + ^^^^^^ +42/42 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/unreached-invalid.txt b/test/spec/function-references/unreached-invalid.txt new file mode 100644 index 0000000000..f24cd1c089 --- /dev/null +++ b/test/spec/function-references/unreached-invalid.txt @@ -0,0 +1,371 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/unreached-invalid.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/unreached-invalid.wast:4: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.0.wasm:000001a: error: local variable out of range (max 0) + 000001a: error: OnLocalGetExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:8: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.1.wasm:000001a: error: global variable out of range: 0 (max 0) + 000001a: error: OnGlobalGetExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:12: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.2.wasm:000001a: error: function variable out of range: 1 (max 1) + 000001a: error: OnCallExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:16: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.3.wasm:0000018: error: invalid depth: 1 (max 0) + 000001a: error: OnBrExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:21: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.4.wasm:000001b: error: type mismatch in i64.eqz, expected [i64] but got [i32] + 000001b: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:27: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.5.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [i64] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:33: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.6.wasm:0000023: error: type mismatch in select, expected [i32, i32, i32] but got [i64, i32, i32] + 0000023: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:42: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.7.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:46: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.8.wasm:000001a: error: type mismatch at end of function, expected [] but got [i32] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:50: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.9.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:56: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.10.wasm:000001a: error: type mismatch at end of function, expected [] but got [any] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:60: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.11.wasm:000001c: error: type mismatch at end of function, expected [] but got [any] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:64: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.12.wasm:000001e: error: type mismatch at end of function, expected [] but got [i32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:71: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.13.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:77: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.14.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:83: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.15.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:89: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.16.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:95: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.17.wasm:000001e: error: type mismatch at end of block, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:101: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.18.wasm:0000024: error: type mismatch in block, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:107: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.19.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:113: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.20.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:119: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.21.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:125: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.22.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000022: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:132: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.23.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:138: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.24.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001e: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:144: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.25.wasm:000001d: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001d: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:150: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.26.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:156: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.27.wasm:000001d: error: type mismatch at end of block, expected [] but got [i32] + 000001d: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:162: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.28.wasm:0000025: error: type mismatch in block, expected [i32] but got [f32] + 0000025: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:168: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.29.wasm:000001f: error: type mismatch at end of loop, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:174: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.30.wasm:0000023: error: type mismatch in loop, expected [i32] but got [f32] + 0000023: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:180: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.31.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:186: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.32.wasm:0000021: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000021: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:193: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.33.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:199: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.34.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:205: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.35.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:211: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.36.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001e: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:217: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.37.wasm:000001d: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001d: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:223: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.38.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:229: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.39.wasm:000001d: error: type mismatch at end of block, expected [] but got [i32] + 000001d: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:235: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.40.wasm:0000023: error: type mismatch in block, expected [i32] but got [f32] + 0000023: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:241: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.41.wasm:000001f: error: type mismatch at end of loop, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:247: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.42.wasm:0000021: error: type mismatch in loop, expected [i32] but got [f32] + 0000021: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:253: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.43.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:259: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.44.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [f32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:265: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.45.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001e: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:271: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.46.wasm:0000020: error: type mismatch in i32.eqz, expected [i32] but got [] + 0000020: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:277: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.47.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:284: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.48.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:290: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.49.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:296: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.50.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:302: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.51.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:308: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.52.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:314: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.53.wasm:0000026: error: type mismatch in block, expected [i32] but got [... f32] + out/test/spec/function-references/unreached-invalid/unreached-invalid.53.wasm:0000026: error: type mismatch at end of block, expected [] but got [i32] + 0000026: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:321: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.54.wasm:0000022: error: type mismatch at end of loop, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:327: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.55.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:334: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.56.wasm:000001e: error: type mismatch at end of function, expected [] but got [i32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:340: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.57.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000022: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:348: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.58.wasm:0000020: error: type mismatch in i32.eqz, expected [i32] but got [] + 0000020: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:354: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.59.wasm:0000022: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000022: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:360: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.60.wasm:0000021: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000021: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:366: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.61.wasm:0000024: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000024: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:372: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.62.wasm:0000021: error: type mismatch at end of block, expected [] but got [i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:378: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.63.wasm:0000027: error: type mismatch in block, expected [i32] but got [... f32] + out/test/spec/function-references/unreached-invalid/unreached-invalid.63.wasm:0000027: error: type mismatch at end of block, expected [] but got [i32] + 0000027: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:384: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.64.wasm:0000023: error: type mismatch at end of loop, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:390: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.65.wasm:0000025: error: type mismatch in loop, expected [i32] but got [f32] + 0000025: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:396: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.66.wasm:000001f: error: type mismatch at end of function, expected [] but got [i32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:402: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.67.wasm:0000023: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000023: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:409: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.68.wasm:000001d: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001d: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:415: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.69.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:421: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.70.wasm:000001e: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001e: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:427: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.71.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:433: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.72.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:439: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.73.wasm:0000022: error: type mismatch in `if true` branch, expected [i32] but got [f32] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:445: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.74.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:451: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.75.wasm:0000024: error: type mismatch in block, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:457: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.76.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:463: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.77.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:470: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.78.wasm:0000025: error: type mismatch in return, expected [i32] but got [f64] + 0000025: error: OnReturnExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:477: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.79.wasm:0000029: error: type mismatch in br, expected [i32] but got [f64] + 0000029: error: OnBrExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:484: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.80.wasm:0000021: error: type mismatch in br_if, expected [i32] but got [f32] + 0000021: error: OnBrIfExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:490: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.81.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:498: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.82.wasm:0000024: error: type mismatch in block, expected [f32] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:507: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.83.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:515: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.84.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [f32] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:521: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.85.wasm:0000025: error: type mismatch in br_table, expected [i32] but got [f32] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:527: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.86.wasm:0000023: error: br_table labels have inconsistent types: expected [f32], got [] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:540: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.87.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:546: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.88.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:552: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.89.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000022: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:558: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.90.wasm:0000023: error: type mismatch at end of block, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:565: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.91.wasm:0000021: error: type mismatch at end of block, expected [] but got [i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:571: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.92.wasm:0000022: error: type mismatch in block, expected [i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:577: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.93.wasm:0000024: error: type mismatch in block, expected [i32] but got [i64] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:584: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.94.wasm:0000023: error: type mismatch at end of block, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:590: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.95.wasm:0000025: error: type mismatch in block, expected [i32] but got [] + 0000025: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:596: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.96.wasm:0000027: error: type mismatch in block, expected [i32] but got [i64] + 0000027: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:604: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.97.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:611: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.98.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:617: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.99.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [] + 0000022: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:623: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.100.wasm:0000024: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000024: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:629: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.101.wasm:0000025: error: type mismatch at end of block, expected [] but got [i32] + 0000025: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:637: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.102.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:643: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.103.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:649: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.104.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000022: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:656: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.105.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:662: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.106.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:669: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.107.wasm:000001d: error: type mismatch at end of function, expected [] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:676: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.108.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:687: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.109.wasm:000001c: error: type mismatch in i64.extend_i32_u, expected [i32] but got [i64] + 000001c: error: OnConvertExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:698: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.110.wasm:000001b: error: type mismatch at end of function, expected [] but got [f32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:710: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.111.wasm:000001f: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:715: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.112.wasm:000001f: error: type mismatch in select, expected [i32, i32, i32] but got [i64, i32, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:721: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.113.wasm:000001f: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, i64] + 000001f: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:726: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.114.wasm:000001d: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i64] + 000001d: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:731: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.115.wasm:000001b: error: type mismatch in select, expected [any, any, i32] but got [i64] + 000001b: error: OnSelectExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:737: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.116.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [i64] + 000001f: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:744: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.117.wasm:000001a: error: type mismatch at end of function, expected [] but got [any] + 000001a: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:749: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.118.wasm:0000026: error: type mismatch in br_table, expected [i32] but got [externref] + 0000026: error: OnBrTableExpr callback failed +out/test/spec/function-references/unreached-invalid.wast:764: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.119.wasm:0000021: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000021: error: EndFunctionBody callback failed +out/test/spec/function-references/unreached-invalid.wast:774: assert_invalid passed: + out/test/spec/function-references/unreached-invalid/unreached-invalid.120.wasm:0000022: error: type mismatch at end of function, expected [] but got [i32] + 0000022: error: EndFunctionBody callback failed +121/121 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/function-references/unreached-valid.txt b/test/spec/function-references/unreached-valid.txt new file mode 100644 index 0000000000..fbf034ed99 --- /dev/null +++ b/test/spec/function-references/unreached-valid.txt @@ -0,0 +1,16 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/function-references/unreached-valid.wast +;;; ARGS*: --enable-function-references +(;; STDOUT ;;; +out/test/spec/function-references/unreached-valid.wast:48: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:49: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:50: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:51: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:53: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:54: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:55: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:56: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:58: assert_trap passed: unreachable executed +out/test/spec/function-references/unreached-valid.wast:77: assert_trap passed: unreachable executed +12/12 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/memory64/table.txt b/test/spec/memory64/table.txt index 1fb959594d..2f04749958 100644 --- a/test/spec/memory64/table.txt +++ b/test/spec/memory64/table.txt @@ -79,10 +79,10 @@ (;; STDOUT ;;; out/test/spec/memory64/table.txt:17: assert_invalid passed: out/test/spec/memory64/table/table.9.wasm:000000f: error: max elems (0) must be >= initial elems (1) - 000000f: error: OnTable callback failed + 000000f: error: BeginTable callback failed out/test/spec/memory64/table.txt:21: assert_invalid passed: out/test/spec/memory64/table/table.10.wasm:0000013: error: max elems (0) must be >= initial elems (4294967295) - 0000013: error: OnTable callback failed + 0000013: error: BeginTable callback failed out/test/spec/memory64/table.txt:26: assert_invalid passed: out/test/spec/memory64/table/table.11.wat:1:8: error: invalid int "0x1_0000_0000" (table 0x1_0000_0000 funcref) @@ -100,10 +100,10 @@ out/test/spec/memory64/table.txt:34: assert_invalid passed: ^^^^^^^^^^^^^ out/test/spec/memory64/table.txt:52: assert_invalid passed: out/test/spec/memory64/table/table.23.wasm:000000f: error: max elems (0) must be >= initial elems (1) - 000000f: error: OnTable callback failed + 000000f: error: BeginTable callback failed out/test/spec/memory64/table.txt:56: assert_invalid passed: out/test/spec/memory64/table/table.24.wasm:0000013: error: max elems (0) must be >= initial elems (4294967295) - 0000013: error: OnTable callback failed + 0000013: error: BeginTable callback failed out/test/spec/memory64/table.txt:62: assert_invalid passed: out/test/spec/memory64/table/table.25.wasm:000000c: error: table variable out of range: 0 (max 0) 000000c: error: BeginElemSegment callback failed diff --git a/test/spec/table.txt b/test/spec/table.txt index 360b4c2562..0654e62353 100644 --- a/test/spec/table.txt +++ b/test/spec/table.txt @@ -9,10 +9,10 @@ out/test/spec/table.wast:15: assert_invalid passed: 0000016: error: BeginElemSegment callback failed out/test/spec/table.wast:19: assert_invalid passed: out/test/spec/table/table.11.wasm:000000f: error: max elems (0) must be >= initial elems (1) - 000000f: error: OnTable callback failed + 000000f: error: BeginTable callback failed out/test/spec/table.wast:23: assert_invalid passed: out/test/spec/table/table.12.wasm:0000013: error: max elems (0) must be >= initial elems (4294967295) - 0000013: error: OnTable callback failed + 0000013: error: BeginTable callback failed out/test/spec/table.wast:28: assert_malformed passed: out/test/spec/table/table.13.wat:1:8: error: invalid int "0x1_0000_0000" (table 0x1_0000_0000 funcref) From ee17d2bdec984561a554b11aae653ba12d7170f4 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 13 May 2025 08:14:02 +0000 Subject: [PATCH 4/6] Implement GC basics --- include/wabt/binary-reader-logging.h | 14 +- include/wabt/binary-reader-nop.h | 15 +- include/wabt/binary-reader.h | 20 +- include/wabt/interp/interp-inl.h | 25 +- include/wabt/interp/interp.h | 23 + include/wabt/ir.h | 51 +- include/wabt/shared-validator.h | 54 +- include/wabt/token.def | 17 +- include/wabt/type-checker.h | 109 +- include/wabt/type.h | 133 +- include/wabt/wast-parser.h | 20 +- src/binary-reader-ir.cc | 44 +- src/binary-reader-logging.cc | 43 +- src/binary-reader-objdump.cc | 50 +- src/binary-reader.cc | 178 +- src/binary-writer.cc | 154 +- src/feature.cc | 5 + src/interp/binary-reader-interp.cc | 110 +- src/interp/interp-util.cc | 22 +- src/interp/interp.cc | 146 +- src/ir.cc | 35 + src/lexer-keywords.txt | 23 +- src/prebuilt/lexer-keywords.cc | 2771 +++++++++-------- src/resolve-names.cc | 11 + src/shared-validator.cc | 251 +- src/type-checker.cc | 383 ++- src/validator.cc | 64 +- src/wast-parser.cc | 296 +- src/wat-writer.cc | 18 + test/binary/bad-reference-indicies.txt | 4 +- test/dump/struct.txt | 4 +- test/gen-wasm.py | 2 +- test/parse/bad-argument-ref.txt | 18 + test/parse/module/bad-array-no-fields.txt | 2 +- test/parse/module/struct-and-func.txt | 2 +- test/parse/module/struct-mut-field.txt | 2 +- test/parse/module/struct.txt | 2 +- test/roundtrip/rec-types.txt | 45 + test/run-roundtrip.py | 3 + test/spec/function-references/ref_is_null.txt | 4 +- .../function-references/unreached-invalid.txt | 4 +- test/spec/gc/table-sub.txt | 12 + test/spec/gc/type-canon.txt | 6 + test/spec/gc/type-equivalence.txt | 9 + test/spec/gc/type-rec.txt | 30 + test/spec/gc/type-subtyping-invalid.txt | 18 + test/spec/gc/unreached-invalid.txt | 371 +++ test/spec/gc/unreached-valid.txt | 16 + test/spec/ref_is_null.txt | 4 +- 49 files changed, 3825 insertions(+), 1818 deletions(-) create mode 100644 test/parse/bad-argument-ref.txt create mode 100644 test/roundtrip/rec-types.txt create mode 100644 test/spec/gc/table-sub.txt create mode 100644 test/spec/gc/type-canon.txt create mode 100644 test/spec/gc/type-equivalence.txt create mode 100644 test/spec/gc/type-rec.txt create mode 100644 test/spec/gc/type-subtyping-invalid.txt create mode 100644 test/spec/gc/unreached-invalid.txt create mode 100644 test/spec/gc/unreached-valid.txt diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 4c9b24eae0..8a47f5d1f1 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -44,13 +44,20 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result BeginTypeSection(Offset size) override; Result OnTypeCount(Index count) override; + Result OnRecursiveType(Index first_type_index, Index type_count) override; Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) override; - Result OnStructType(Index index, Index field_count, TypeMut* fields) override; - Result OnArrayType(Index index, TypeMut field) override; + Type* result_types, + GCTypeExtension* gc_ext) override; + Result OnStructType(Index index, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext) override; + Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) override; Result EndTypeSection() override; Result BeginImportSection(Offset size) override; @@ -432,6 +439,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { void LogType(Type type); void LogTypes(Index type_count, Type* types); void LogTypes(TypeVector& types); + void LogGCInfo(GCTypeExtension* gc_ext); void LogField(TypeMut field); Stream* stream_; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index 02d2958801..70d36e7cc9 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -45,20 +45,29 @@ class BinaryReaderNop : public BinaryReaderDelegate { /* Type section */ Result BeginTypeSection(Offset size) override { return Result::Ok; } + Result OnRecursiveType(Index first_type_index, Index type_count) override { + return Result::Ok; + } Result OnTypeCount(Index count) override { return Result::Ok; } Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) override { + Type* result_types, + GCTypeExtension* gc_ext) override { return Result::Ok; } Result OnStructType(Index index, Index field_count, - TypeMut* fields) override { + TypeMut* fields, + GCTypeExtension* gc_ext) override { + return Result::Ok; + } + Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) override { return Result::Ok; } - Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; } Result EndTypeSection() override { return Result::Ok; } /* Import section */ diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index 3993a45c94..b811cb2ba9 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -52,13 +52,20 @@ struct ReadBinaryOptions { bool skip_function_bodies = false; }; -// TODO: Move somewhere else? +// TODO: Move both TypeMut and GCTypeInformation somewhere else? struct TypeMut { Type type; bool mutable_; }; using TypeMutVector = std::vector; +// Garbage Collector specific type information +struct GCTypeExtension { + bool is_final_sub_type; + Index sub_type_count; + Index* sub_types; +}; + struct CatchClause { CatchKind kind; Index tag; @@ -99,15 +106,20 @@ class BinaryReaderDelegate { /* Type section */ virtual Result BeginTypeSection(Offset size) = 0; virtual Result OnTypeCount(Index count) = 0; + virtual Result OnRecursiveType(Index first_type_index, Index type_count) = 0; virtual Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) = 0; + Type* result_types, + GCTypeExtension* gc_ext) = 0; virtual Result OnStructType(Index index, Index field_count, - TypeMut* fields) = 0; - virtual Result OnArrayType(Index index, TypeMut field) = 0; + TypeMut* fields, + GCTypeExtension* gc_ext) = 0; + virtual Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) = 0; virtual Result EndTypeSection() = 0; /* Import section */ diff --git a/include/wabt/interp/interp-inl.h b/include/wabt/interp/interp-inl.h index 6125999a9b..bc83b93938 100644 --- a/include/wabt/interp/interp-inl.h +++ b/include/wabt/interp/interp-inl.h @@ -42,7 +42,30 @@ inline bool FuncType::classof(const ExternType* type) { } inline FuncType::FuncType(ValueTypes params, ValueTypes results) - : ExternType(ExternKind::Func), params(params), results(results), func_types(nullptr) {} + : ExternType(ExternKind::Func), + kind(FuncType::TypeKind::Func), + canonical_index(kInvalidIndex), + canonical_sub_index(kInvalidIndex), + is_final_sub_type(true), + recursive_start(0), + recursive_count(0), + params(params), + results(results), + func_types(nullptr) {} + +inline FuncType::FuncType(TypeKind kind, ValueTypes params, ValueTypes results) + : ExternType(ExternKind::Func), + kind(kind), + canonical_index(kInvalidIndex), + canonical_sub_index(kInvalidIndex), + is_final_sub_type(true), + recursive_start(0), + recursive_count(0), + params(params), + results(results), + func_types(nullptr) { + assert((kind == TypeKind::Struct || kind == TypeKind::Array) && params.size() == results.size()); +} //// TableType //// // static diff --git a/include/wabt/interp/interp.h b/include/wabt/interp/interp.h index 42e6a6b8bb..71434edc64 100644 --- a/include/wabt/interp/interp.h +++ b/include/wabt/interp/interp.h @@ -178,7 +178,21 @@ struct FuncType : ExternType { static const ExternKind skind = ExternKind::Func; static bool classof(const ExternType* type); + enum class TypeKind { + Func, + Struct, + Array, + }; + + // To simplify the implementation, FuncType may also represent + // Struct and Array types. To do this, the mutability is stored + // in results, which must have the same size as params. + // This implementation might change in the future. + static const Type::Enum Mutable = Type::I32; + static const Type::Enum Immutable = Type::I64; + explicit FuncType(ValueTypes params, ValueTypes results); + explicit FuncType(TypeKind kind, ValueTypes params, ValueTypes results); std::unique_ptr Clone() const override; @@ -186,6 +200,15 @@ struct FuncType : ExternType { const FuncType& actual, std::string* out_msg); + TypeKind kind; + // These two are needed for fast dynamic type comparison. + Index canonical_index; + Index canonical_sub_index; + // These three are needed for type equality comparisons + // across different modules (import/export validation). + bool is_final_sub_type; + Index recursive_start; + Index recursive_count; ValueTypes params; ValueTypes results; // When params or results contain references, the referenced diff --git a/include/wabt/ir.h b/include/wabt/ir.h index c825465034..d220bd3c69 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -297,6 +297,19 @@ enum class TypeEntryKind { Array, }; +struct TypeEntryGCTypeExtension { + TypeEntryGCTypeExtension(bool is_final_sub_type) + : is_final_sub_type(is_final_sub_type) {} + + void InitSubTypes(Index* sub_type_list, Index sub_type_count); + + bool is_final_sub_type; + // The binary/text format allows any number of subtypes, + // so parsers must handle them. The validator rejects + // lists which size is greater than 1. + VarVector sub_types; +}; + class TypeEntry { public: WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry); @@ -307,12 +320,17 @@ class TypeEntry { Location loc; std::string name; + TypeEntryGCTypeExtension gc_ext; protected: explicit TypeEntry(TypeEntryKind kind, + bool is_final_sub_type, std::string_view name = std::string_view(), const Location& loc = Location()) - : loc(loc), name(name), kind_(kind) {} + : loc(loc), + name(name), + gc_ext(is_final_sub_type), + kind_(kind) {} TypeEntryKind kind_; }; @@ -323,8 +341,8 @@ class FuncType : public TypeEntry { return entry->kind() == TypeEntryKind::Func; } - explicit FuncType(std::string_view name = std::string_view()) - : TypeEntry(TypeEntryKind::Func, name) {} + explicit FuncType(bool is_final_sub_type, std::string_view name = std::string_view()) + : TypeEntry(TypeEntryKind::Func, is_final_sub_type, name) {} Index GetNumParams() const { return sig.GetNumParams(); } Index GetNumResults() const { return sig.GetNumResults(); } @@ -353,8 +371,8 @@ class StructType : public TypeEntry { return entry->kind() == TypeEntryKind::Struct; } - explicit StructType(std::string_view name = std::string_view()) - : TypeEntry(TypeEntryKind::Struct) {} + explicit StructType(bool is_final_sub_type, std::string_view name = std::string_view()) + : TypeEntry(TypeEntryKind::Struct, is_final_sub_type, name) {} std::vector fields; }; @@ -365,12 +383,19 @@ class ArrayType : public TypeEntry { return entry->kind() == TypeEntryKind::Array; } - explicit ArrayType(std::string_view name = std::string_view()) - : TypeEntry(TypeEntryKind::Array) {} + explicit ArrayType(bool is_final_sub_type, std::string_view name = std::string_view()) + : TypeEntry(TypeEntryKind::Array, is_final_sub_type, name) {} Field field; }; +struct RecursiveRange { + Index first_type_index; + Index type_count; + + Index EndTypeIndex() const { return first_type_index + type_count; } +}; + struct FuncDeclaration { Index GetNumParams() const { return sig.GetNumParams(); } Index GetNumResults() const { return sig.GetNumResults(); } @@ -1107,7 +1132,8 @@ enum class ModuleFieldType { Memory, DataSegment, Start, - Tag + Tag, + EmptyRec }; class ModuleField : public intrusive_list_base { @@ -1234,6 +1260,12 @@ class TagModuleField : public ModuleFieldMixin { Tag tag; }; +class EmptyRecModuleField : public ModuleFieldMixin { + public: + explicit EmptyRecModuleField(const Location& loc = Location()) + : ModuleFieldMixin(loc) {} +}; + class StartModuleField : public ModuleFieldMixin { public: explicit StartModuleField(Var start = Var(), const Location& loc = Location()) @@ -1293,6 +1325,7 @@ struct Module { void AppendField(std::unique_ptr); void AppendField(std::unique_ptr); void AppendField(std::unique_ptr); + void AppendField(std::unique_ptr); void AppendField(std::unique_ptr); void AppendField(std::unique_ptr); void AppendField(std::unique_ptr); @@ -1319,6 +1352,8 @@ struct Module { std::vector imports; std::vector exports; std::vector types; + // Ordered list of recursive ranges. + std::vector recursive_ranges; std::vector tables; std::vector elem_segments; std::vector memories; diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index 6414ccd753..7bcda66e13 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -29,8 +29,6 @@ #include "wabt/opcode.h" #include "wabt/type-checker.h" -#include "wabt/binary-reader.h" // For TypeMut. - namespace wabt { struct ValidateOptions { @@ -43,7 +41,11 @@ struct ValidateOptions { class SharedValidator { public: WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator); + using TypeEntry = TypeChecker::TypeEntry; using FuncType = TypeChecker::FuncType; + using StructType = TypeChecker::StructType; + using ArrayType = TypeChecker::ArrayType; + using RecursiveRange = TypeChecker::RecursiveRange; SharedValidator(Errors*, const ValidateOptions& options); // TODO: Move into SharedValidator? @@ -63,16 +65,28 @@ class SharedValidator { Index GetLocalCount() const; + // The canonical index of a type is the index of the first type, + // which is equal to the original type. The canonical index is + // always less or equal than type_index. + Index GetCanonicalTypeIndex(Index type_index); + Result EndModule(); + Result OnRecursiveType(Index first_type_index, Index type_count); Result OnFuncType(const Location&, Index param_count, const Type* param_types, Index result_count, const Type* result_types, - Index type_index); - Result OnStructType(const Location&, Index field_count, TypeMut* fields); - Result OnArrayType(const Location&, TypeMut field); + Index type_index, + GCTypeExtension* gc_ext); + Result OnStructType(const Location&, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext); + Result OnArrayType(const Location&, + TypeMut field, + GCTypeExtension* gc_ext); Result OnFunction(const Location&, Var sig_var); Result OnTable(const Location&, Type elem_type, const Limits&, bool, bool); @@ -225,20 +239,6 @@ class SharedValidator { Result OnUnreachable(const Location&); private: - struct StructType { - StructType() = default; - StructType(const TypeMutVector& fields) : fields(fields) {} - - TypeMutVector fields; - }; - - struct ArrayType { - ArrayType() = default; - ArrayType(TypeMut field) : field(field) {} - - TypeMut field; - }; - struct TableType { TableType() = default; TableType(Type element, Limits limits) : element(element), limits(limits) {} @@ -292,7 +292,11 @@ class SharedValidator { Type actual, Type expected, const char* desc); - Result CheckReferenceType(const Location&, Type type, const char* desc); + Result CheckReferenceType(const Location&, + Type type, + Index end_index, + const char* desc); + Result CheckGCTypeExtension(const Location&, GCTypeExtension* gc_ext); Result CheckLimits(const Location&, const Limits&, uint64_t absolute_max, @@ -337,6 +341,8 @@ class SharedValidator { void RestoreLocalRefs(Result result); void IgnoreLocalRefs(); + Index GetEndIndex(); + ValidateOptions options_; Errors* errors_; TypeChecker typechecker_; // TODO: Move into SharedValidator. @@ -344,10 +350,7 @@ class SharedValidator { Location expr_loc_ = Location(kInvalidOffset); bool in_init_expr_ = false; - Index num_types_ = 0; - std::map func_types_; - std::map struct_types_; - std::map array_types_; + TypeChecker::TypeFields type_fields_; std::vector funcs_; // Includes imported and defined. std::vector tables_; // Includes imported and defined. @@ -358,6 +361,9 @@ class SharedValidator { Index starts_ = 0; Index num_imported_globals_ = 0; Index data_segments_ = 0; + Index last_rec_type_end_ = 0; + // Recursive type checks may enter to infinite loop for invalid values. + Result type_validation_result_ = Result::Ok; // Includes parameters, since this is only used for validating // local.{get,set,tee} instructions. diff --git a/include/wabt/token.def b/include/wabt/token.def index 22b333cb73..bebe36a696 100644 --- a/include/wabt/token.def +++ b/include/wabt/token.def @@ -21,7 +21,6 @@ /* Tokens with no additional data (i.e. bare). */ WABT_TOKEN(Invalid, "Invalid") WABT_TOKEN(After, "after") -WABT_TOKEN(Array, "array") WABT_TOKEN(AssertException, "assert_exception") WABT_TOKEN(AssertExhaustion, "assert_exhaustion") WABT_TOKEN(AssertInvalid, "assert_invalid") @@ -42,6 +41,7 @@ WABT_TOKEN(Eof, "EOF") WABT_TOKEN(Tag, "tag") WABT_TOKEN(Export, "export") WABT_TOKEN(Field, "field") +WABT_TOKEN(Final, "final") WABT_TOKEN(Function, "function") WABT_TOKEN(Get, "get") WABT_TOKEN(Global, "global") @@ -62,12 +62,13 @@ WABT_TOKEN(PageSize, "pagesize") WABT_TOKEN(Param, "param") WABT_TOKEN(Ref, "ref") WABT_TOKEN(Quote, "quote") +WABT_TOKEN(Rec, "rec") WABT_TOKEN(Register, "register") WABT_TOKEN(Result, "result") WABT_TOKEN(Rpar, ")") WABT_TOKEN(Shared, "shared") WABT_TOKEN(Start, "start") -WABT_TOKEN(Struct, "struct") +WABT_TOKEN(Sub, "sub") WABT_TOKEN(Table, "table") WABT_TOKEN(Then, "then") WABT_TOKEN(Type, "type") @@ -182,8 +183,16 @@ WABT_TOKEN_FIRST(Type, ValueType) WABT_TOKEN_LAST(Type, ValueType) /* Tokens with Type data, but are reference kinds. */ +WABT_TOKEN(Any, "any") +WABT_TOKEN(Array, "array") WABT_TOKEN(Func, "func") +WABT_TOKEN(Eq, "eq") WABT_TOKEN(Extern, "extern") WABT_TOKEN(Exn, "exn") -WABT_TOKEN_FIRST(RefKind, Func) -WABT_TOKEN_LAST(RefKind, Exn) +WABT_TOKEN(I31, "i31") +WABT_TOKEN(NoExtern, "noextern") +WABT_TOKEN(NoFunc, "nofunc") +WABT_TOKEN(None, "none") +WABT_TOKEN(Struct, "struct") +WABT_TOKEN_FIRST(RefKind, Any) +WABT_TOKEN_LAST(RefKind, Struct) diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h index 3600212a83..3b18ca11ca 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -26,12 +26,33 @@ #include "wabt/feature.h" #include "wabt/opcode.h" +#include "wabt/binary-reader.h" // For TypeMut. + namespace wabt { class TypeChecker { public: using ErrorCallback = std::function; + struct TypeEntry { + explicit TypeEntry(Type::Enum kind, Index map_index, Index canonical_index) + : kind(kind), + map_index(map_index), + canonical_index(canonical_index), + is_final_sub_type(true), + first_sub_type(kInvalidIndex) { + assert(kind == Type::FuncRef || kind == Type::StructRef || + kind == Type::ArrayRef); + } + + Type::Enum kind; + Index map_index; + Index canonical_index; + bool is_final_sub_type; + // Currently the sub type list is limited to maximum 1 value. + Index first_sub_type; + }; + struct FuncType { FuncType() = default; FuncType(const TypeVector& params, @@ -44,6 +65,70 @@ class TypeChecker { Index type_index; }; + struct StructType { + StructType() = default; + StructType(const TypeMutVector& fields) : fields(fields) {} + + TypeMutVector fields; + }; + + struct ArrayType { + ArrayType() = default; + ArrayType(TypeMut field) : field(field) {} + + TypeMut field; + }; + + struct RecursiveRange { + RecursiveRange(Index start_index, Index type_count) + : start_index(start_index), type_count(type_count), hash(0) {} + + Index start_index; + Index type_count; + uint32_t hash; + }; + + struct TypeFields { + Index NumTypes() { + return static_cast(type_entries.size()); + } + + void PushFunc(FuncType&& func_type) { + Index map_index = static_cast(func_types.size()); + type_entries.emplace_back(TypeEntry(Type::FuncRef, map_index, + NumTypes())); + func_types.emplace_back(func_type); + } + + void PushStruct(StructType&& struct_type) { + Index map_index = static_cast(struct_types.size()); + type_entries.emplace_back(TypeEntry(Type::StructRef, map_index, + NumTypes())); + struct_types.emplace_back(struct_type); + } + + void PushArray(ArrayType&& array_type) { + Index map_index = static_cast(array_types.size()); + type_entries.emplace_back(TypeEntry(Type::ArrayRef, map_index, + NumTypes())); + array_types.emplace_back(array_type); + } + + Type GetGenericType(Type type) { + if (type.IsReferenceWithIndex()) { + return Type(type_entries[type.GetReferenceIndex()].kind, + type == Type::RefNull); + } + return type; + } + + std::vector type_entries; + std::vector func_types; + std::vector struct_types; + std::vector array_types; + std::vector recursive_ranges; + }; + struct Label { Label(LabelType, const TypeVector& param_types, @@ -62,8 +147,8 @@ class TypeChecker { std::vector local_ref_is_set_; }; - explicit TypeChecker(const Features& features, std::map& func_types) - : features_(features), func_types_(func_types) {} + explicit TypeChecker(const Features& features, TypeFields& type_fields) + : features_(features), type_fields_(type_fields) {} void set_error_callback(const ErrorCallback& error_callback) { error_callback_ = error_callback; @@ -160,6 +245,12 @@ class TypeChecker { Result BeginInitExpr(Type type); Result EndInitExpr(); + uint32_t UpdateHash(uint32_t hash, Index type_index, Index rec_start); + bool CheckTypeFields(Index actual, + Index actual_rec_start, + Index expected, + Index expected_rec_start, + bool is_equal); Result CheckType(Type actual, Type expected); private: @@ -206,6 +297,18 @@ class TypeChecker { const Limits* limits3 = nullptr); Result OnEnd(Label* label, const char* sig_desc, const char* end_desc); + static uint32_t ComputeHash(uint32_t hash, Index value) { + // Shift-Add-XOR hash + return hash ^ ((hash << 5) + (hash >> 2) + value); + } + + uint32_t ComputeHash(uint32_t hash, Type& type, Index rec_start); + bool CompareType(Type actual, + Index actual_rec_start, + Type expected, + Index expected_rec_start, + bool is_equal); + template void PrintStackIfFailed(Result result, const char* desc, Args... args) { // Assert all args are Type or Type::Enum. If it's a TypeVector then @@ -230,7 +333,7 @@ class TypeChecker { // to represent "any". TypeVector* br_table_sig_ = nullptr; Features features_; - std::map& func_types_; + TypeFields& type_fields_; }; } // namespace wabt diff --git a/include/wabt/type.h b/include/wabt/type.h index 8ef73112db..72a57827b4 100644 --- a/include/wabt/type.h +++ b/include/wabt/type.h @@ -40,17 +40,27 @@ class Type { F32 = -0x03, // 0x7d F64 = -0x04, // 0x7c V128 = -0x05, // 0x7b - I8 = -0x06, // 0x7a : packed-type only, used in gc and as v128 lane - I16 = -0x07, // 0x79 : packed-type only, used in gc and as v128 lane - ExnRef = -0x17, // 0x69 + I8 = -0x08, // 0x78 : packed-type only, used in gc and as v128 lane + I16 = -0x09, // 0x77 : packed-type only, used in gc and as v128 lane + NullFuncRef = -0x0d, // 0x73 + NullExternRef = -0x0e, // 0x72 + NullRef = -0x0f, // 0x71 FuncRef = -0x10, // 0x70 ExternRef = -0x11, // 0x6f - Reference = -0x15, // 0x6b + AnyRef = -0x12, // 0x6e + EqRef = -0x13, // 0x6d + I31Ref = -0x14, // 0x6c + StructRef = -0x15, // 0x6b + ArrayRef = -0x16, // 0x6a + ExnRef = -0x17, // 0x69 Ref = -0x1c, // 0x64 RefNull = -0x1d, // 0x63 Func = -0x20, // 0x60 Struct = -0x21, // 0x5f Array = -0x22, // 0x5e + Sub = -0x30, // 0x50 + SubFinal = -0x31, // 0x4f + Rec = -0x32, // 0x4e Void = -0x40, // 0x40 ___ = Void, // Convenient for the opcode table in opcode.h @@ -78,6 +88,10 @@ class Type { assert(IsReferenceWithIndex() || (IsNonTypedRef() && (type_index_ == ReferenceOrNull || type_index_ == ReferenceNonNull))); } + Type(Enum e, bool is_nullable) + : enum_(e), type_index_(is_nullable ? ReferenceOrNull : ReferenceNonNull) { + assert(IsNonTypedRef()); + } constexpr operator Enum() const { return enum_; } @@ -99,20 +113,23 @@ class Type { } bool IsRef() const { - return enum_ == Type::ExternRef || enum_ == Type::FuncRef || - enum_ == Type::Reference || enum_ == Type::ExnRef || - enum_ == Type::RefNull || enum_ == Type::Ref; + return enum_ == Type::NullFuncRef || enum_ == Type::NullExternRef || + enum_ == Type::NullRef || enum_ == Type::FuncRef || + enum_ == Type::ExternRef || enum_ == Type::AnyRef || + enum_ == Type::EqRef || enum_ == Type::I31Ref || + enum_ == Type::StructRef || enum_ == Type::ArrayRef || + enum_ == Type::ExnRef || enum_ == Type::Ref || + enum_ == Type::RefNull; } bool IsNullableRef() const { - return enum_ == Type::Reference || enum_ == Type::ExnRef || - enum_ == Type::RefNull || - ((enum_ == Type::ExternRef || enum_ == Type::FuncRef) && type_index_ == ReferenceOrNull); + return enum_ == Type::ExnRef || enum_ == Type::RefNull || + (EnumIsNonTypedRef(enum_) && type_index_ == ReferenceOrNull); } bool IsNonNullableRef() const { return enum_ == Type::Ref || - ((enum_ == Type::ExternRef || enum_ == Type::FuncRef) && type_index_ != ReferenceOrNull); + (EnumIsNonTypedRef(enum_) && type_index_ != ReferenceOrNull); } bool IsReferenceWithIndex() const { return EnumIsReferenceWithIndex(enum_); } @@ -137,13 +154,33 @@ class Type { case Type::I16: return "i16"; case Type::ExnRef: return "exnref"; case Type::Func: return "func"; + case Type::Struct: return "struct"; + case Type::Array: return "array"; case Type::Void: return "void"; case Type::Any: return "any"; + case Type::NullFuncRef: + return type_index_ == ReferenceOrNull ? "nullfuncref" : "(ref nofunc)"; + case Type::NullExternRef: + return type_index_ == ReferenceOrNull ? "nullexternref" : "(ref noextern)"; + case Type::NullRef: + if (type_index_ == kBottomRef) { + return "(ref something)"; + } + return type_index_ == ReferenceOrNull ? "nullref" : "(ref none)"; case Type::FuncRef: return type_index_ == ReferenceOrNull ? "funcref" : "(ref func)"; case Type::ExternRef: return type_index_ == ReferenceOrNull ? "externref" : "(ref extern)"; - case Type::Reference: + case Type::AnyRef: + return type_index_ == ReferenceOrNull ? "anyref" : "(ref any)"; + case Type::EqRef: + return type_index_ == ReferenceOrNull ? "eqref" : "(ref eq)"; + case Type::I31Ref: + return type_index_ == ReferenceOrNull ? "i31ref" : "(ref i31)"; + case Type::StructRef: + return type_index_ == ReferenceOrNull ? "structref" : "(ref struct)"; + case Type::ArrayRef: + return type_index_ == ReferenceOrNull ? "arrayref" : "(ref array)"; case Type::Ref: return StringPrintf("(ref %d)", type_index_); case Type::RefNull: @@ -155,12 +192,19 @@ class Type { const char* GetRefKindName() const { switch (enum_) { - case Type::FuncRef: return "func"; - case Type::ExternRef: return "extern"; - case Type::ExnRef: return "exn"; - case Type::Struct: return "struct"; - case Type::Array: return "array"; - default: return ""; + case Type::NullFuncRef: return "nofunc"; + case Type::NullExternRef: return "noextern"; + case Type::NullRef: + return (type_index_ == kBottomRef) ? "something" : "none"; + case Type::FuncRef: return "func"; + case Type::ExternRef: return "extern"; + case Type::ExnRef: return "exn"; + case Type::AnyRef: return "any"; + case Type::EqRef: return "eq"; + case Type::I31Ref: return "i31"; + case Type::Struct: return "struct"; + case Type::Array: return "array"; + default: return ""; } } @@ -188,6 +232,10 @@ class Type { return type_index_; } + bool IsPackedType() const { + return enum_ == Type::I8 || enum_ == Type::I16; + } + TypeVector GetInlineVector() const { assert(!IsIndex()); switch (enum_) { @@ -199,10 +247,17 @@ class Type { case Type::F32: case Type::F64: case Type::V128: + case Type::NullFuncRef: + case Type::NullExternRef: + case Type::NullRef: case Type::FuncRef: - case Type::ExnRef: case Type::ExternRef: - case Type::Reference: + case Type::AnyRef: + case Type::EqRef: + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: + case Type::ExnRef: case Type::Ref: case Type::RefNull: return TypeVector(this, this + 1); @@ -213,15 +268,47 @@ class Type { } static bool EnumIsReferenceWithIndex(Enum value) { - return value == Type::Reference || value == Type::Ref || - value == Type::RefNull; + return value == Type::Ref || value == Type::RefNull; + } + + static bool EnumIsNonTypedGCRef(Enum value) { + return value == Type::NullFuncRef || value == Type::NullExternRef || + value == Type::NullRef || value == Type::AnyRef || + value == Type::EqRef || value == Type::I31Ref || + value == Type::StructRef || value == Type::ArrayRef; } static bool EnumIsNonTypedRef(Enum value) { - return value == Type::ExternRef || value == Type::FuncRef; + return value == Type::ExternRef || value == Type::FuncRef || + value == Type::ExnRef || EnumIsNonTypedGCRef(value); + } + + // Bottom references are only used by the shared + // validator. It represents an unknown reference. + // Nullable property is not defined for this type. + static Type BottomRef() { + Type type(NullRef); + type.type_index_ = kBottomRef; + return type; + } + + bool IsBottomRef() const { + return enum_ == NullRef && type_index_ == kBottomRef; + } + + void ConvertRefNullToRef() { + if (IsReferenceWithIndex()) { + enum_ = Type::Ref; + } else { + assert(IsNonTypedRef()); + type_index_ |= ReferenceNonNull; + } } private: + // Special value representing an unknown reference. + static const uint32_t kBottomRef = 0x2 | ReferenceNonNull; + Enum enum_; // This index is 0 for non-references, so a zeroed // memory area represents a valid Type::Any type. diff --git a/include/wabt/wast-parser.h b/include/wabt/wast-parser.h index ad1c935da3..330a784a10 100644 --- a/include/wabt/wast-parser.h +++ b/include/wabt/wast-parser.h @@ -91,6 +91,14 @@ class WastParser { ReferenceVars vars; }; + struct ResolveField { + ResolveField(StructType* target_struct) + : target_struct(target_struct) {} + + StructType* target_struct; + ReferenceVars vars; + }; + void ErrorUnlessOpcodeEnabled(const Token&); // Print an error message listing the expected tokens, as well as an example @@ -171,7 +179,7 @@ class WastParser { bool ParseElemExprListOpt(ExprListVector* out_list); bool ParseElemExprVarListOpt(ExprListVector* out_list); Result ParseRefDeclaration(Var* out_type); - Result ParseValueType(Var* out_type); + Result ParseValueType(Var* out_type, bool is_field = false); Result ParseValueTypeList( TypeVector* out_type_list, ReferenceVars* type_vars); @@ -190,6 +198,8 @@ class WastParser { static Result ResolveTargetRefType(const Module&, Type*, const Var&, Errors*); static Result ResolveTargetTypeVector(const Module&, TypeVector*, ReferenceVars*, Errors*); + static Result ResolveTargetFieldVector(const Module&, StructType*, + ReferenceVars*, Errors* errors); Result ParseModuleFieldList(Module*); Result ParseModuleField(Module*); Result ParseDataModuleField(Module*); @@ -198,6 +208,7 @@ class WastParser { Result ParseExportModuleField(Module*); Result ParseFuncModuleField(Module*); Result ParseTypeModuleField(Module*); + Result ParseRecTypeModuleField(Module*); Result ParseGlobalModuleField(Module*); Result ParseImportModuleField(Module*); Result ParseMemoryModuleField(Module*); @@ -248,7 +259,7 @@ class WastParser { Result ParseCatchExprList(CatchVector* catches); Result ParseGlobalType(Global*); Result ParseField(Field*); - Result ParseFieldList(std::vector*); + Result ParseFieldList(StructType*); template Result ParsePlainInstrVar(Location, std::unique_ptr*); @@ -322,6 +333,11 @@ class WastParser { // following vector. At least one reference must be present for each vector. std::vector resolve_funcs_; + // Structure fields and their corresponding references are + // stored in the following vector. At least one reference + // must be present for each structure. + std::vector resolve_fields_; + // two-element queue of upcoming tokens class TokenQueue { std::array, 2> tokens{}; diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index c65791fbd8..41ab0a8c1e 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -102,13 +102,20 @@ class BinaryReaderIR : public BinaryReaderNop { bool OnError(const Error&) override; Result OnTypeCount(Index count) override; + Result OnRecursiveType(Index first_type_index, Index type_count) override; Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) override; - Result OnStructType(Index index, Index field_count, TypeMut* fields) override; - Result OnArrayType(Index index, TypeMut field) override; + Type* result_types, + GCTypeExtension* gc_ext) override; + Result OnStructType(Index index, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext) override; + Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) override; Result OnImportCount(Index count) override; Result OnImportFunc(Index import_index, @@ -523,11 +530,24 @@ Result BinaryReaderIR::OnTypeCount(Index count) { return Result::Ok; } +Result BinaryReaderIR::OnRecursiveType(Index first_type_index, + Index type_count) { + if (type_count == 0) { + auto field = std::make_unique(GetLocation()); + module_->AppendField(std::move(field)); + } else if (type_count > 1) { + module_->recursive_ranges.push_back( + RecursiveRange{first_type_index, type_count}); + } + return Result::Ok; +} + Result BinaryReaderIR::OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) { + Type* result_types, + GCTypeExtension* gc_ext) { if (param_count > kMaxFunctionParams) { PrintError("FuncType param count exceeds maximum value"); return Result::Error; @@ -539,7 +559,8 @@ Result BinaryReaderIR::OnFuncType(Index index, } auto field = std::make_unique(GetLocation()); - auto func_type = std::make_unique(); + auto func_type = std::make_unique(gc_ext->is_final_sub_type); + func_type->gc_ext.InitSubTypes(gc_ext->sub_types, gc_ext->sub_type_count); func_type->sig.param_types.assign(param_types, param_types + param_count); func_type->sig.result_types.assign(result_types, result_types + result_count); @@ -565,9 +586,11 @@ Result BinaryReaderIR::OnFuncType(Index index, Result BinaryReaderIR::OnStructType(Index index, Index field_count, - TypeMut* fields) { + TypeMut* fields, + GCTypeExtension* gc_ext) { auto field = std::make_unique(GetLocation()); - auto struct_type = std::make_unique(); + auto struct_type = std::make_unique(gc_ext->is_final_sub_type); + struct_type->gc_ext.InitSubTypes(gc_ext->sub_types, gc_ext->sub_type_count); struct_type->fields.resize(field_count); for (Index i = 0; i < field_count; ++i) { struct_type->fields[i].type = fields[i].type; @@ -580,9 +603,12 @@ Result BinaryReaderIR::OnStructType(Index index, return Result::Ok; } -Result BinaryReaderIR::OnArrayType(Index index, TypeMut type_mut) { +Result BinaryReaderIR::OnArrayType(Index index, + TypeMut type_mut, + GCTypeExtension* gc_ext) { auto field = std::make_unique(GetLocation()); - auto array_type = std::make_unique(); + auto array_type = std::make_unique(gc_ext->is_final_sub_type); + array_type->gc_ext.InitSubTypes(gc_ext->sub_types, gc_ext->sub_type_count); array_type->field.type = type_mut.type; array_type->field.mutable_ = type_mut.mutable_; module_->features_used.simd |= (type_mut.type == Type::V128); diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 5c98c26b0c..3ff6e33e97 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -99,6 +99,19 @@ void BinaryReaderLogging::LogTypes(TypeVector& types) { LogTypes(types.size(), types.data()); } +void BinaryReaderLogging::LogGCInfo(GCTypeExtension* gc_ext) { + if (gc_ext->is_final_sub_type && gc_ext->sub_type_count == 0) { + return; + } + + LOGF_NOINDENT("(sub%s", gc_ext->is_final_sub_type ? " final" : ""); + + for (Index i = 0; i < gc_ext->sub_type_count; i++) { + LOGF_NOINDENT(" %" PRIindex, gc_ext->sub_types[i]); + } + LOGF_NOINDENT("), "); +} + void BinaryReaderLogging::LogField(TypeMut field) { if (field.mutable_) { LOGF_NOINDENT("(mut "); @@ -143,21 +156,26 @@ Result BinaryReaderLogging::OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) { - LOGF("OnFuncType(index: %" PRIindex ", params: ", index); + Type* result_types, + GCTypeExtension* gc_ext) { + LOGF("OnFuncType(index: %" PRIindex ", ", index); + LogGCInfo(gc_ext); + LOGF_NOINDENT("params: "); LogTypes(param_count, param_types); LOGF_NOINDENT(", results: "); LogTypes(result_count, result_types); LOGF_NOINDENT(")\n"); return reader_->OnFuncType(index, param_count, param_types, result_count, - result_types); + result_types, gc_ext); } Result BinaryReaderLogging::OnStructType(Index index, Index field_count, - TypeMut* fields) { - LOGF("OnStructType(index: %" PRIindex ", fields: ", index); - LOGF_NOINDENT("["); + TypeMut* fields, + GCTypeExtension* gc_ext) { + LOGF("OnStructType(index: %" PRIindex ", ", index); + LogGCInfo(gc_ext); + LOGF_NOINDENT("fields: ["); for (Index i = 0; i < field_count; ++i) { LogField(fields[i]); if (i != field_count - 1) { @@ -165,14 +183,18 @@ Result BinaryReaderLogging::OnStructType(Index index, } } LOGF_NOINDENT("])\n"); - return reader_->OnStructType(index, field_count, fields); + return reader_->OnStructType(index, field_count, fields, gc_ext); } -Result BinaryReaderLogging::OnArrayType(Index index, TypeMut field) { - LOGF("OnArrayType(index: %" PRIindex ", field: ", index); +Result BinaryReaderLogging::OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) { + LOGF("OnArrayType(index: %" PRIindex ", ", index); + LogGCInfo(gc_ext); + LOGF_NOINDENT("field: "); LogField(field); LOGF_NOINDENT(")\n"); - return reader_->OnArrayType(index, field); + return reader_->OnArrayType(index, field, gc_ext); } Result BinaryReaderLogging::OnImport(Index index, @@ -804,6 +826,7 @@ DEFINE_END(EndCustomSection) DEFINE_BEGIN(BeginTypeSection) DEFINE_INDEX(OnTypeCount) +DEFINE_INDEX_INDEX(OnRecursiveType, "first_type_index", "type_count") DEFINE_END(EndTypeSection) DEFINE_BEGIN(BeginImportSection) diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 12906dca81..4536dcbdc9 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -265,7 +265,8 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { Index param_count, Type* param_types, Index result_count, - Type* result_types) override { + Type* result_types, + GCTypeExtension* gc_ext) override { objdump_state_->function_param_counts[index] = param_count; return Result::Ok; } @@ -1089,9 +1090,15 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Index param_count, Type* param_types, Index result_count, - Type* result_types) override; - Result OnStructType(Index index, Index field_count, TypeMut* fields) override; - Result OnArrayType(Index index, TypeMut field) override; + Type* result_types, + GCTypeExtension* gc_ext) override; + Result OnStructType(Index index, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext) override; + Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) override; Result OnImportCount(Index count) override; Result OnImportFunc(Index import_index, @@ -1457,15 +1464,31 @@ Result BinaryReaderObjdump::OnTypeCount(Index count) { return OnCount(count); } +void PrintGCTypeExtension(GCTypeExtension* gc_ext) { + if (gc_ext->is_final_sub_type && gc_ext->sub_type_count == 0) { + return; + } + + printf("(sub%s", gc_ext->is_final_sub_type ? " final" : ""); + + for (Index i = 0; i < gc_ext->sub_type_count; i++) { + printf(" %" PRIindex, gc_ext->sub_types[i]); + } + printf(") "); +} + Result BinaryReaderObjdump::OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) { + Type* result_types, + GCTypeExtension* gc_ext) { if (!ShouldPrintDetails()) { return Result::Ok; } - printf(" - type[%" PRIindex "] (", index); + printf(" - type[%" PRIindex "] ", index); + PrintGCTypeExtension(gc_ext); + printf("("); for (Index i = 0; i < param_count; i++) { if (i != 0) { printf(", "); @@ -1497,11 +1520,14 @@ Result BinaryReaderObjdump::OnFuncType(Index index, Result BinaryReaderObjdump::OnStructType(Index index, Index field_count, - TypeMut* fields) { + TypeMut* fields, + GCTypeExtension* gc_ext) { if (!ShouldPrintDetails()) { return Result::Ok; } - printf(" - type[%" PRIindex "] (struct", index); + printf(" - type[%" PRIindex "] ", index); + PrintGCTypeExtension(gc_ext); + printf("(struct"); for (Index i = 0; i < field_count; i++) { if (fields[i].mutable_) { printf(" (mut"); @@ -1515,11 +1541,15 @@ Result BinaryReaderObjdump::OnStructType(Index index, return Result::Ok; } -Result BinaryReaderObjdump::OnArrayType(Index index, TypeMut field) { +Result BinaryReaderObjdump::OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) { if (!ShouldPrintDetails()) { return Result::Ok; } - printf(" - type[%" PRIindex "] (array", index); + printf(" - type[%" PRIindex "] ", index); + PrintGCTypeExtension(gc_ext); + printf("(array"); if (field.mutable_) { printf(" (mut"); } diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 036428c28b..9ec149d26d 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -195,6 +195,7 @@ class BinaryReader { BinaryReaderDelegate::State state_; BinaryReaderLogging logging_delegate_; BinaryReaderDelegate* delegate_ = nullptr; + std::vector sub_types_; TypeVector param_types_; TypeVector result_types_; TypeMutVector fields_; @@ -374,9 +375,11 @@ Result BinaryReader::ReadType(Type* out_value, const char* desc) { if (static_cast(heap_type) < 0 || static_cast(heap_type) >= kInvalidIndex) { Type::Enum heap_type_code = static_cast(heap_type); - ERROR_UNLESS( - heap_type_code == Type::FuncRef || heap_type_code == Type::ExternRef, - "Reference type is limited to func and extern: %s", desc); + ERROR_UNLESS(heap_type_code == Type::FuncRef || + heap_type_code == Type::ExternRef || + (options_.features.gc_enabled() && + Type::EnumIsNonTypedGCRef(heap_type_code)), + "not allowed reference type: %s", desc); type = (static_cast(type) == Type::Ref) ? Type::ReferenceNonNull : Type::ReferenceOrNull; @@ -556,7 +559,8 @@ Result BinaryReader::ReadField(TypeMut* out_value) { // TODO: Reuse for global header too? Type field_type; CHECK_RESULT(ReadType(&field_type, "field type")); - ERROR_UNLESS(IsConcreteType(field_type), + ERROR_UNLESS(IsConcreteType(field_type) || field_type == Type::I8 || + field_type == Type::I16, "expected valid field type (got " PRItypecode ")", WABT_PRINTF_TYPE_CODE(field_type)); @@ -577,6 +581,16 @@ bool BinaryReader::IsConcreteReferenceType(Type::Enum type) { case Type::ExnRef: return options_.features.exceptions_enabled(); + case Type::NullFuncRef: + case Type::NullExternRef: + case Type::NullRef: + case Type::AnyRef: + case Type::EqRef: + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: + return options_.features.gc_enabled(); + default: return false; } @@ -593,7 +607,6 @@ bool BinaryReader::IsConcreteType(Type type) { case Type::V128: return options_.features.simd_enabled(); - case Type::Reference: case Type::Ref: case Type::RefNull: return options_.features.function_references_enabled(); @@ -2603,10 +2616,25 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { CHECK_RESULT(ReadCount(&num_signatures, "type count")); CALLBACK(OnTypeCount, num_signatures); + Index type_index = 0; for (Index i = 0; i < num_signatures; ++i) { Type form; + uint32_t recursive_count = 1; + if (options_.features.gc_enabled()) { - CHECK_RESULT(ReadType(&form, "type form")); + CHECK_RESULT(ReadType(&form, "type form or gc info")); + + if (form == Type::Rec) { + CHECK_RESULT(ReadU32Leb128(&recursive_count, "recursive count")); + + CALLBACK(OnRecursiveType, type_index, recursive_count); + + if (recursive_count == 0) { + continue; + } + + CHECK_RESULT(ReadType(&form, "type form or gc info")); + } } else { uint8_t type; CHECK_RESULT(ReadU8(&type, "type form")); @@ -2614,73 +2642,107 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { form = Type::Func; } - switch (form) { - case Type::Func: { - Index num_params; - CHECK_RESULT(ReadCount(&num_params, "function param count")); - - param_types_.resize(num_params); + while (true) { + GCTypeExtension gc_ext; + gc_ext.is_final_sub_type = true; + gc_ext.sub_type_count = 0; + gc_ext.sub_types = nullptr; + + if (options_.features.gc_enabled() && + (form == Type::Sub || form == Type::SubFinal)) { + gc_ext.is_final_sub_type = (form == Type::SubFinal); + CHECK_RESULT(ReadU32Leb128(&gc_ext.sub_type_count, "sub type count")); + sub_types_.resize(gc_ext.sub_type_count); + + for (Index i = 0; i < gc_ext.sub_type_count; i++) { + Index sub_type; + CHECK_RESULT(ReadU32Leb128(&sub_type, "sub type index")); + sub_types_[i] = sub_type; + } - for (Index j = 0; j < num_params; ++j) { - Type param_type; - CHECK_RESULT(ReadType(¶m_type, "function param type")); - ERROR_UNLESS(IsConcreteType(param_type), - "expected valid param type (got " PRItypecode ")", - WABT_PRINTF_TYPE_CODE(param_type)); - param_types_[j] = param_type; + if (gc_ext.sub_type_count > 0) { + gc_ext.sub_types = sub_types_.data(); } - Index num_results; - CHECK_RESULT(ReadCount(&num_results, "function result count")); + CHECK_RESULT(ReadType(&form, "type form")); + } - result_types_.resize(num_results); + switch (form) { + case Type::Func: { + Index num_params; + CHECK_RESULT(ReadCount(&num_params, "function param count")); - for (Index j = 0; j < num_results; ++j) { - Type result_type; - CHECK_RESULT(ReadType(&result_type, "function result type")); - ERROR_UNLESS(IsConcreteType(result_type), - "expected valid result type (got " PRItypecode ")", - WABT_PRINTF_TYPE_CODE(result_type)); - result_types_[j] = result_type; - } + param_types_.resize(num_params); - Type* param_types = num_params ? param_types_.data() : nullptr; - Type* result_types = num_results ? result_types_.data() : nullptr; + for (Index j = 0; j < num_params; ++j) { + Type param_type; + CHECK_RESULT(ReadType(¶m_type, "function param type")); + ERROR_UNLESS(IsConcreteType(param_type), + "expected valid param type (got " PRItypecode ")", + WABT_PRINTF_TYPE_CODE(param_type)); + param_types_[j] = param_type; + } - CALLBACK(OnFuncType, i, num_params, param_types, num_results, - result_types); - break; - } + Index num_results; + CHECK_RESULT(ReadCount(&num_results, "function result count")); - case Type::Struct: { - ERROR_UNLESS(options_.features.gc_enabled(), - "invalid type form: struct not allowed"); - Index num_fields; - CHECK_RESULT(ReadCount(&num_fields, "field count")); + result_types_.resize(num_results); + + for (Index j = 0; j < num_results; ++j) { + Type result_type; + CHECK_RESULT(ReadType(&result_type, "function result type")); + ERROR_UNLESS(IsConcreteType(result_type), + "expected valid result type (got " PRItypecode ")", + WABT_PRINTF_TYPE_CODE(result_type)); + result_types_[j] = result_type; + } - fields_.resize(num_fields); - for (Index j = 0; j < num_fields; ++j) { - CHECK_RESULT(ReadField(&fields_[j])); + Type* param_types = num_params ? param_types_.data() : nullptr; + Type* result_types = num_results ? result_types_.data() : nullptr; + + CALLBACK(OnFuncType, type_index, num_params, param_types, num_results, + result_types, &gc_ext); + break; } - CALLBACK(OnStructType, i, fields_.size(), fields_.data()); - break; - } + case Type::Struct: { + ERROR_UNLESS(options_.features.gc_enabled(), + "invalid type form: struct not allowed"); + Index num_fields; + CHECK_RESULT(ReadCount(&num_fields, "field count")); + + fields_.resize(num_fields); + for (Index j = 0; j < num_fields; ++j) { + CHECK_RESULT(ReadField(&fields_[j])); + } + + CALLBACK(OnStructType, type_index, fields_.size(), fields_.data(), + &gc_ext); + break; + } - case Type::Array: { - ERROR_UNLESS(options_.features.gc_enabled(), - "invalid type form: array not allowed"); + case Type::Array: { + ERROR_UNLESS(options_.features.gc_enabled(), + "invalid type form: array not allowed"); - TypeMut field; - CHECK_RESULT(ReadField(&field)); - CALLBACK(OnArrayType, i, field); + TypeMut field; + CHECK_RESULT(ReadField(&field)); + CALLBACK(OnArrayType, type_index, field, &gc_ext); + break; + }; + + default: + PrintError("unexpected type form (got " PRItypecode ")", + WABT_PRINTF_TYPE_CODE(form)); + return Result::Error; + } + + type_index++; + if (--recursive_count == 0) { break; - }; + } - default: - PrintError("unexpected type form (got " PRItypecode ")", - WABT_PRINTF_TYPE_CODE(form)); - return Result::Error; + CHECK_RESULT(ReadType(&form, "type form or gc info")); } } CALLBACK0(EndTypeSection); diff --git a/src/binary-writer.cc b/src/binary-writer.cc index fbfaf5690c..b4f41f98d4 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -1408,53 +1408,127 @@ Result BinaryWriter::WriteModule() { CHECK_RESULT(symtab_.Populate(module_)); } - if (module_->types.size()) { + std::vector rec_type_counts; + Index type_index = 0; + Index next_start_index = kInvalidIndex; + Index range_index = 0; + Index range_count = 0; + + if (!module_->recursive_ranges.empty()) { + next_start_index = module_->recursive_ranges[0].first_type_index; + } + + for (const ModuleField& field : module_->fields) { + if (field.type() == ModuleFieldType::Type) { + if (range_count > 0) { + range_count--; + } else if (next_start_index != type_index) { + rec_type_counts.push_back(1); + } else { + range_count = module_->recursive_ranges[range_index].type_count; + rec_type_counts.push_back(range_count--); + range_index++; + next_start_index = kInvalidIndex; + if (range_index < module_->recursive_ranges.size()) { + next_start_index = + module_->recursive_ranges[range_index].first_type_index; + } + } + type_index++; + } else if (field.type() == ModuleFieldType::EmptyRec) { + assert(range_count == 0); + rec_type_counts.push_back(0); + } + } + + if (!rec_type_counts.empty()) { BeginKnownSection(BinarySection::Type); - WriteU32Leb128(stream_, module_->types.size(), "num types"); - for (size_t i = 0; i < module_->types.size(); ++i) { - const TypeEntry* type = module_->types[i]; - switch (type->kind()) { - case TypeEntryKind::Func: { - const FuncType* func_type = cast(type); - const FuncSignature* sig = &func_type->sig; - WriteHeader("func type", i); - WriteType(stream_, Type::Func); - - Index num_params = sig->param_types.size(); - Index num_results = sig->result_types.size(); - WriteU32Leb128(stream_, num_params, "num params"); - for (size_t j = 0; j < num_params; ++j) { - WriteType(stream_, sig->param_types[j]); - } - WriteU32Leb128(stream_, num_results, "num results"); - for (size_t j = 0; j < num_results; ++j) { - WriteType(stream_, sig->result_types[j]); - } - break; + WriteU32Leb128(stream_, rec_type_counts.size(), "num types"); + type_index = 0; + for (auto type_count : rec_type_counts) { + if (type_count != 1) { + WriteS32Leb128(stream_, Type::Rec, "recursive type"); + WriteU32Leb128(stream_, type_count, "recursive type count"); + } + + Index end = type_index + type_count; + // Safety, should never happen for valid modules. + if (end >= module_->types.size()) { + end = module_->types.size(); + } + + while (type_index < end) { + const TypeEntry* type = module_->types[type_index]; + + switch (type->kind()) { + case TypeEntryKind::Func: + WriteHeader("func type", type_index); + break; + case TypeEntryKind::Struct: + WriteHeader("struct type", type_index); + break; + case TypeEntryKind::Array: + WriteHeader("array type", type_index); + break; } - case TypeEntryKind::Struct: { - const StructType* struct_type = cast(type); - WriteHeader("struct type", i); - WriteType(stream_, Type::Struct); - Index num_fields = struct_type->fields.size(); - WriteU32Leb128(stream_, num_fields, "num fields"); - for (size_t j = 0; j < num_fields; ++j) { - const Field& field = struct_type->fields[j]; - WriteType(stream_, field.type); - stream_->WriteU8(field.mutable_, "field mutability"); + type_index++; + + if (!type->gc_ext.is_final_sub_type || + !type->gc_ext.sub_types.empty()) { + WriteS32Leb128( + stream_, + type->gc_ext.is_final_sub_type ? Type::SubFinal : Type::Sub, + "sub type"); + + WriteU32Leb128(stream_, type->gc_ext.sub_types.size(), + "num sub types"); + for (auto it : type->gc_ext.sub_types) { + WriteU32Leb128(stream_, it.index(), "sub type"); } - break; } - case TypeEntryKind::Array: { - const ArrayType* array_type = cast(type); - WriteHeader("array type", i); - WriteType(stream_, Type::Array); - WriteType(stream_, array_type->field.type); - stream_->WriteU8(array_type->field.mutable_, "field mutability"); - break; + switch (type->kind()) { + case TypeEntryKind::Func: { + const FuncType* func_type = cast(type); + const FuncSignature* sig = &func_type->sig; + WriteType(stream_, Type::Func); + + Index num_params = sig->param_types.size(); + Index num_results = sig->result_types.size(); + WriteU32Leb128(stream_, num_params, "num params"); + for (size_t j = 0; j < num_params; ++j) { + WriteType(stream_, sig->param_types[j]); + } + + WriteU32Leb128(stream_, num_results, "num results"); + for (size_t j = 0; j < num_results; ++j) { + WriteType(stream_, sig->result_types[j]); + } + break; + } + + case TypeEntryKind::Struct: { + const StructType* struct_type = cast(type); + WriteType(stream_, Type::Struct); + Index num_fields = struct_type->fields.size(); + WriteU32Leb128(stream_, num_fields, "num fields"); + for (size_t j = 0; j < num_fields; ++j) { + const Field& field = struct_type->fields[j]; + WriteType(stream_, field.type); + stream_->WriteU8(field.mutable_, "field mutability"); + } + break; + } + + case TypeEntryKind::Array: { + const ArrayType* array_type = cast(type); + WriteType(stream_, Type::Array); + WriteType(stream_, array_type->field.type); + stream_->WriteU8(array_type->field.mutable_, "field mutability"); + break; + } } } } diff --git a/src/feature.cc b/src/feature.cc index 88b474c290..21d958c37e 100644 --- a/src/feature.cc +++ b/src/feature.cc @@ -42,6 +42,11 @@ void Features::UpdateDependencies() { reference_types_enabled_ = true; } + // Garbage collector require function references. + if (gc_enabled_) { + function_references_enabled_ = true; + } + // Function references require reference types. if (function_references_enabled_) { reference_types_enabled_ = true; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 57351e531d..3ceb6d262b 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -84,11 +84,21 @@ class BinaryReaderInterp : public BinaryReaderNop { Result EndModule() override; Result OnTypeCount(Index count) override; + Result OnRecursiveType(Index first_type_index, Index type_count) override; Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) override; + Type* result_types, + GCTypeExtension* gc_ext) override; + Result OnStructType(Index index, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext) override; + Result OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) override; + Result EndTypeSection() override; Result OnImportFunc(Index import_index, std::string_view module_name, @@ -338,6 +348,8 @@ class BinaryReaderInterp : public BinaryReaderNop { Index num_func_imports() const; + void UpdateTypeInfo(GCTypeExtension* gc_ext); + Errors* errors_ = nullptr; ModuleDesc& module_; Istream& istream_; @@ -351,6 +363,8 @@ class BinaryReaderInterp : public BinaryReaderNop { u32 local_decl_count_; u32 local_count_; + Index recursive_start_; + Index recursive_end_; std::vector func_types_; // Includes imported and defined. std::vector table_types_; // Includes imported and defined. @@ -526,21 +540,109 @@ Result BinaryReaderInterp::EndModule() { Result BinaryReaderInterp::OnTypeCount(Index count) { module_.func_types.reserve(count); + recursive_end_ = 0; + return Result::Ok; +} + +Result BinaryReaderInterp::OnRecursiveType(Index first_type_index, + Index type_count) { + CHECK_RESULT(validator_.OnRecursiveType(first_type_index, type_count)); + if (type_count > 0) { + // A non-empty recursive group is found. + recursive_start_ = static_cast(module_.func_types.size()); + recursive_end_ = recursive_start_ + type_count; + } return Result::Ok; } +void BinaryReaderInterp::UpdateTypeInfo(GCTypeExtension* gc_ext) { + FuncType& type = module_.func_types.back(); + Index index = static_cast(module_.func_types.size() - 1); + + if (index < recursive_end_) { + type.recursive_start = recursive_start_; + type.recursive_count = recursive_end_ - recursive_start_; + } else { + type.recursive_start = index; + type.recursive_count = 1; + } + + type.is_final_sub_type = gc_ext->is_final_sub_type; + type.canonical_index = index; + if (gc_ext->sub_type_count > 0) { + type.canonical_sub_index = gc_ext->sub_types[0]; + } else { + type.canonical_sub_index = kInvalidIndex; + } +} + Result BinaryReaderInterp::OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, - Type* result_types) { - Result result = validator_.OnFuncType(GetLocation(), param_count, param_types, - result_count, result_types, index); + Type* result_types, + GCTypeExtension* gc_ext) { + Result result = + validator_.OnFuncType(GetLocation(), param_count, param_types, + result_count, result_types, index, gc_ext); module_.func_types.push_back(FuncType(ToInterp(param_count, param_types), ToInterp(result_count, result_types))); + UpdateTypeInfo(gc_ext); + return result; +} + +Result BinaryReaderInterp::OnStructType(Index index, + Index field_count, + TypeMut* fields, + GCTypeExtension* gc_ext) { + Result result = + validator_.OnStructType(GetLocation(), field_count, fields, gc_ext); + + ValueTypes params; + ValueTypes results; + params.reserve(field_count); + results.reserve(field_count); + + for (Index i = 0; i < field_count; i++) { + params.push_back(fields[i].type); + results.push_back(fields[i].mutable_ ? FuncType::Mutable + : FuncType::Immutable); + } + + module_.func_types.push_back( + FuncType(FuncType::TypeKind::Struct, params, results)); + UpdateTypeInfo(gc_ext); return result; } +Result BinaryReaderInterp::OnArrayType(Index index, + TypeMut field, + GCTypeExtension* gc_ext) { + Result result = validator_.OnArrayType(GetLocation(), field, gc_ext); + + ValueTypes params; + ValueTypes results; + params.reserve(1); + results.reserve(1); + + params.push_back(field.type); + results.push_back(field.mutable_ ? FuncType::Mutable : FuncType::Immutable); + + module_.func_types.push_back( + FuncType(FuncType::TypeKind::Array, params, results)); + UpdateTypeInfo(gc_ext); + return result; +} + +Result BinaryReaderInterp::EndTypeSection() { + for (auto& it : module_.func_types) { + it.canonical_index = validator_.GetCanonicalTypeIndex(it.canonical_index); + it.canonical_sub_index = + validator_.GetCanonicalTypeIndex(it.canonical_sub_index); + } + return Result::Ok; +} + Result BinaryReaderInterp::OnImportFunc(Index import_index, std::string_view module_name, std::string_view field_name, diff --git a/src/interp/interp-util.cc b/src/interp/interp-util.cc index 3d21d6d099..6c7d892f4f 100644 --- a/src/interp/interp-util.cc +++ b/src/interp/interp-util.cc @@ -58,12 +58,32 @@ std::string TypedValueToString(const TypedValue& tv) { case Type::ExnRef: return StringPrintf("exnref:%" PRIzd, tv.value.Get().index); - case Type::Reference: + case Type::AnyRef: + return StringPrintf("anyref:%" PRIzd, tv.value.Get().index); + + case Type::EqRef: + return StringPrintf("eqref:%" PRIzd, tv.value.Get().index); + + case Type::I31Ref: + return StringPrintf("i31ref:%" PRIzd, tv.value.Get().index); + + case Type::StructRef: + return StringPrintf("structref:%" PRIzd, tv.value.Get().index); + + case Type::ArrayRef: + return StringPrintf("arrayref:%" PRIzd, tv.value.Get().index); + + case Type::NullFuncRef: + case Type::NullExternRef: + case Type::NullRef: case Type::Ref: case Type::RefNull: case Type::Func: case Type::Struct: case Type::Array: + case Type::Sub: + case Type::SubFinal: + case Type::Rec: case Type::Void: case Type::Any: case Type::I8U: diff --git a/src/interp/interp.cc b/src/interp/interp.cc index 2944d05f06..d5eae194c4 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -94,46 +94,103 @@ std::unique_ptr FuncType::Clone() const { return std::make_unique(*this); } -static bool RecursiveMatch(const ValueTypes& expected, +static bool RecursiveMatch(Type expected, + Index expected_recursive_start, std::vector* expected_func_types, - const ValueTypes& actual, + Type actual, + Index actual_recursive_start, std::vector* actual_func_types) { - if (expected_func_types == nullptr || actual_func_types == nullptr) { + assert(expected_func_types != nullptr && actual_func_types != nullptr); + + if (!expected.IsReferenceWithIndex()) { + return expected == actual; + } else if (!actual.IsReferenceWithIndex()) { return false; } - size_t size = expected.size(); - if (size != actual.size()) { + Index expected_index = expected.GetReferenceIndex(); + Index actual_index = actual.GetReferenceIndex(); + + const FuncType& expected_type = (*expected_func_types)[expected_index]; + const FuncType& actual_type = (*actual_func_types)[actual_index]; + + // Relative reference. + if (expected_index >= expected_recursive_start) { + return (actual_index >= actual_recursive_start && + expected_type.recursive_count == actual_type.recursive_count && + expected_index - expected_recursive_start == + actual_index - actual_recursive_start); + } else if (actual_index >= actual_recursive_start) { return false; } - for (size_t i = 0; i < size; i++) { - if (!expected[i].IsReferenceWithIndex()) { - if (expected[i] != actual[i]) { + // Absolute reference. + expected_recursive_start = expected_type.recursive_start; + actual_recursive_start = actual_type.recursive_start; + Index recursive_count = expected_type.recursive_count; + + if (recursive_count != actual_type.recursive_count || + expected_index - expected_recursive_start != + actual_index - actual_recursive_start) { + return false; + } + + // Recursive match of the whole recursive block. + for (Index i = 0; i < recursive_count; i++) { + const FuncType& expected_rec_type = + (*expected_func_types)[expected_recursive_start + i]; + const FuncType& actual_rec_type = + (*actual_func_types)[actual_recursive_start + i]; + + if (expected_rec_type.kind != actual_rec_type.kind || + expected_rec_type.is_final_sub_type != + actual_rec_type.is_final_sub_type) { + return false; + } + + if (expected_rec_type.canonical_sub_index != kInvalidIndex) { + if (actual_rec_type.canonical_sub_index == kInvalidIndex) { return false; } - continue; - } - if (static_cast(expected[i]) != - static_cast(actual[i])) { + Type expected_sub_type(Type::Ref, expected_rec_type.canonical_sub_index); + Type actual_sub_type(Type::Ref, actual_rec_type.canonical_sub_index); + + if (!RecursiveMatch(expected_sub_type, expected_recursive_start, + expected_func_types, actual_sub_type, + actual_recursive_start, actual_func_types)) { + return false; + } + } else if (actual_rec_type.canonical_sub_index != kInvalidIndex) { return false; } - const FuncType& expected_type = - (*expected_func_types)[expected[i].GetReferenceIndex()]; - const FuncType& actual_type = - (*actual_func_types)[actual[i].GetReferenceIndex()]; + size_t size = expected_rec_type.params.size(); + if (size != actual_rec_type.params.size()) { + return false; + } - assert(expected_type.func_types == expected_func_types); - assert(actual_type.func_types == actual_func_types); + for (size_t j = 0; j < size; j++) { + if (!RecursiveMatch(expected_rec_type.params[j], expected_recursive_start, + expected_func_types, actual_rec_type.params[j], + actual_recursive_start, actual_func_types)) { + return false; + } + } - if (!RecursiveMatch(expected_type.params, expected_func_types, - actual_type.params, actual_func_types) || - !RecursiveMatch(expected_type.results, expected_func_types, - actual_type.results, actual_func_types)) { + size = expected_rec_type.results.size(); + if (size != actual_rec_type.results.size()) { return false; } + + for (size_t j = 0; j < size; j++) { + if (!RecursiveMatch(expected_rec_type.results[j], + expected_recursive_start, expected_func_types, + actual_rec_type.results[j], actual_recursive_start, + actual_func_types)) { + return false; + } + } } return true; @@ -142,36 +199,27 @@ static bool RecursiveMatch(const ValueTypes& expected, Result Match(const FuncType& expected, const FuncType& actual, std::string* out_msg) { - bool has_reference = false; + if (expected.kind == actual.kind) { + if (expected.func_types == nullptr || actual.func_types == nullptr) { + // Simple function, can be a callback without module. + if (expected.params == actual.params && + expected.results == actual.results) { + return Result::Ok; + } + } else { + Type expected_type(Type::Ref, expected.canonical_index); + Index actual_index = actual.canonical_index; - for (auto it : expected.params) { - if (it.IsReferenceWithIndex()) { - has_reference = true; - break; - } - } + do { + Type actual_type(Type::Ref, actual_index); - if (!has_reference) { - for (auto it : expected.results) { - if (it.IsReferenceWithIndex()) { - has_reference = true; - break; - } - } - } + if (RecursiveMatch(expected_type, kInvalidIndex, expected.func_types, + actual_type, kInvalidIndex, actual.func_types)) { + return Result::Ok; + } - if (!has_reference) { - // Simple function, can be a callback without module. - if (expected.params == actual.params && - expected.results == actual.results) { - return Result::Ok; - } - } else { - if (RecursiveMatch(expected.params, expected.func_types, actual.params, - actual.func_types) && - RecursiveMatch(expected.results, expected.func_types, actual.results, - actual.func_types)) { - return Result::Ok; + actual_index = ((*actual.func_types)[actual_index]).canonical_sub_index; + } while (actual_index != kInvalidIndex); } } diff --git a/src/ir.cc b/src/ir.cc index d4ceef5295..346869c751 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -346,7 +346,24 @@ FuncType* Module::GetFuncType(const Var& var) { } Index Module::GetFuncTypeIndex(const FuncSignature& sig) const { + size_t range_index = 0; + size_t range_start = types.size(); + + if (range_index < recursive_ranges.size()) { + range_start = recursive_ranges[range_index].first_type_index; + } + for (size_t i = 0; i < types.size(); ++i) { + if (i == range_start) { + i += recursive_ranges[range_index].type_count - 1; + range_index++; + + if (range_index < recursive_ranges.size()) { + range_start = recursive_ranges[range_index].first_type_index; + } + continue; + } + if (auto* func_type = dyn_cast(types[i])) { if (func_type->sig == sig) { return i; @@ -419,6 +436,10 @@ void Module::AppendField(std::unique_ptr field) { fields.push_back(std::move(field)); } +void Module::AppendField(std::unique_ptr field) { + fields.push_back(std::move(field)); +} + void Module::AppendField(std::unique_ptr field) { Global& global = field->global; if (!global.name.empty()) { @@ -562,6 +583,10 @@ void Module::AppendField(std::unique_ptr field) { case ModuleFieldType::Tag: AppendField(cast(std::move(field))); break; + + case ModuleFieldType::EmptyRec: + AppendField(cast(std::move(field))); + break; } } @@ -703,6 +728,16 @@ void Var::Destroy() { } } +void TypeEntryGCTypeExtension::InitSubTypes(Index* sub_type_list, + Index sub_type_count) { + sub_types.clear(); + sub_types.reserve(sub_type_count); + + for (Index i = 0; i < sub_type_count; i++) { + sub_types.push_back(Var(sub_type_list[i], Location())); + } +} + uint8_t ElemSegment::GetFlags(const Module* module, bool function_references_enabled) const { uint8_t flags = 0; diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt index eda61a3b7e..dfec434b39 100644 --- a/src/lexer-keywords.txt +++ b/src/lexer-keywords.txt @@ -17,7 +17,10 @@ struct TokenInfo { }; }; %% -array, Type::Array, TokenType::Array +any, Type::AnyRef, TokenType::Any +anyref, Type::AnyRef +array, Type::ArrayRef, TokenType::Array +arrayref, Type::ArrayRef after, TokenType::After assert_exception, TokenType::AssertException assert_exhaustion, TokenType::AssertExhaustion @@ -55,6 +58,8 @@ elem, TokenType::Elem else, TokenType::Else, Opcode::Else end, TokenType::End, Opcode::End tag, TokenType::Tag +eq, Type::EqRef, TokenType::Eq +eqref, Type::EqRef extern, Type::ExternRef, TokenType::Extern externref, Type::ExternRef exn, Type::ExnRef, TokenType::Exn @@ -185,6 +190,7 @@ f64x2.convert_low_i32x4_u, TokenType::Unary, Opcode::F64X2ConvertLowI32X4U f64x2.promote_low_f32x4, TokenType::Unary, Opcode::F64X2PromoteLowF32X4 f64x2, TokenType::F64X2 field, TokenType::Field +final, TokenType::Final func, Type::FuncRef, TokenType::Func funcref, Type::FuncRef function, TokenType::Function @@ -192,6 +198,7 @@ get, TokenType::Get global.get, TokenType::GlobalGet, Opcode::GlobalGet global.set, TokenType::GlobalSet, Opcode::GlobalSet global, TokenType::Global +i16, Type::I16 i16x8.abs, TokenType::Unary, Opcode::I16X8Abs i16x8.add_sat_s, TokenType::Binary, Opcode::I16X8AddSatS i16x8.add_sat_u, TokenType::Binary, Opcode::I16X8AddSatU @@ -244,6 +251,8 @@ i16x8.extend_high_i8x16_s, TokenType::Unary, Opcode::I16X8ExtendHighI8X16S i16x8.extend_high_i8x16_u, TokenType::Unary, Opcode::I16X8ExtendHighI8X16U i16x8.extend_low_i8x16_s, TokenType::Unary, Opcode::I16X8ExtendLowI8X16S i16x8.extend_low_i8x16_u, TokenType::Unary, Opcode::I16X8ExtendLowI8X16U +i31, Type::I31Ref, TokenType::I31 +i31ref, Type::I31Ref i32.add, TokenType::Binary, Opcode::I32Add i32.and, TokenType::Binary, Opcode::I32And i32.atomic.load16_u, TokenType::AtomicLoad, Opcode::I32AtomicLoad16U @@ -496,6 +505,7 @@ i64x2.extmul_low_i32x4_u, TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U i64x2.extmul_high_i32x4_u, TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U i64x2, TokenType::I64X2 i64.xor, TokenType::Binary, Opcode::I64Xor +i8, Type::I8 i8x16.abs, TokenType::Unary, Opcode::I8X16Abs i8x16.add_sat_s, TokenType::Binary, Opcode::I8X16AddSatS i8x16.add_sat_u, TokenType::Binary, Opcode::I8X16AddSatU @@ -557,12 +567,19 @@ module, TokenType::Module mut, TokenType::Mut nan:arithmetic, TokenType::NanArithmetic nan:canonical, TokenType::NanCanonical +noextern, Type::NullExternRef, TokenType::NoExtern +nofunc, Type::NullFuncRef, TokenType::NoFunc +none, Type::NullRef, TokenType::None nop, TokenType::Nop, Opcode::Nop null, TokenType::Null +nullfuncref, Type::NullFuncRef +nullexternref, Type::NullExternRef +nullref, Type::NullRef offset, TokenType::Offset output, TokenType::Output pagesize, TokenType::PageSize param, TokenType::Param +rec, TokenType::Rec ref, TokenType::Ref quote, TokenType::Quote ref.as_non_null, TokenType::RefAsNonNull, Opcode::RefAsNonNull @@ -580,7 +597,9 @@ return, TokenType::Return, Opcode::Return select, TokenType::Select, Opcode::Select shared, TokenType::Shared start, TokenType::Start -struct, Type::Struct, TokenType::Struct +struct, Type::StructRef, TokenType::Struct +structref, Type::StructRef +sub, TokenType::Sub table.copy, TokenType::TableCopy, Opcode::TableCopy table.fill, TokenType::TableFill, Opcode::TableFill table.get, TokenType::TableGet, Opcode::TableGet diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc index 8dd541f499..7b20d57738 100644 --- a/src/prebuilt/lexer-keywords.cc +++ b/src/prebuilt/lexer-keywords.cc @@ -48,7 +48,7 @@ struct TokenInfo { Opcode opcode; }; }; -/* maximum key range = 2193, duplicates = 0 */ +/* maximum key range = 2512, duplicates = 0 */ class Perfect_Hash { @@ -63,32 +63,32 @@ Perfect_Hash::hash (const char *str, size_t len) { static unsigned short asso_values[] = { - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 13, 2230, 2230, 426, - 351, 14, 17, 13, 176, 531, 32, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 183, 13, 16, 811, 21, - 68, 16, 326, 13, 347, 223, 20, 13, 15, 140, - 80, 54, 559, 611, 14, 15, 24, 13, 556, 521, - 125, 416, 213, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, - 2230, 2230, 2230, 2230, 2230, 2230, 2230 + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 10, 2532, 2532, 652, + 334, 8, 7, 7, 288, 243, 174, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 133, 20, 8, 753, 10, + 90, 7, 339, 9, 309, 404, 11, 8, 7, 118, + 21, 63, 654, 915, 8, 15, 11, 81, 441, 691, + 75, 256, 315, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2532, 2532, 2532, 2532, 2532, 2532, 2532 }; unsigned int hval = len; @@ -158,1626 +158,1710 @@ Perfect_Hash::InWordSet (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 606, + TOTAL_KEYWORDS = 625, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 35, - MIN_HASH_VALUE = 37, - MAX_HASH_VALUE = 2229 + MIN_HASH_VALUE = 20, + MAX_HASH_VALUE = 2531 }; static struct TokenInfo wordlist[] = { {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 37 "src/lexer-keywords.txt" + {""}, {""}, +#line 40 "src/lexer-keywords.txt" {"br", TokenType::Br, Opcode::Br}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 154 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, +#line 159 "src/lexer-keywords.txt" {"f64", Type::F64}, - {""}, {""}, -#line 47 "src/lexer-keywords.txt" - {"data", TokenType::Data}, - {""}, {""}, {""}, -#line 466 "src/lexer-keywords.txt" + {""}, +#line 475 "src/lexer-keywords.txt" {"i64", Type::I64}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 124 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 129 "src/lexer-keywords.txt" {"f32x4", TokenType::F32X4}, - {""}, {""}, {""}, {""}, -#line 591 "src/lexer-keywords.txt" - {"table", TokenType::Table}, -#line 50 "src/lexer-keywords.txt" - {"do", TokenType::Do}, -#line 366 "src/lexer-keywords.txt" + {""}, +#line 375 "src/lexer-keywords.txt" {"i32x4", TokenType::I32X4}, - {""}, {""}, {""}, -#line 137 "src/lexer-keywords.txt" - {"f64.ge", TokenType::Compare, Opcode::F64Ge}, -#line 76 "src/lexer-keywords.txt" - {"f32.ge", TokenType::Compare, Opcode::F32Ge}, -#line 139 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 144 "src/lexer-keywords.txt" {"f64.le", TokenType::Compare, Opcode::F64Le}, -#line 78 "src/lexer-keywords.txt" +#line 83 "src/lexer-keywords.txt" {"f32.le", TokenType::Compare, Opcode::F32Le}, - {""}, {""}, {""}, {""}, {""}, -#line 30 "src/lexer-keywords.txt" +#line 142 "src/lexer-keywords.txt" + {"f64.ge", TokenType::Compare, Opcode::F64Ge}, +#line 81 "src/lexer-keywords.txt" + {"f32.ge", TokenType::Compare, Opcode::F32Ge}, +#line 33 "src/lexer-keywords.txt" {"before", TokenType::Before}, - {""}, {""}, {""}, {""}, {""}, -#line 188 "src/lexer-keywords.txt" - {"func", Type::FuncRef, TokenType::Func}, -#line 138 "src/lexer-keywords.txt" - {"f64.gt", TokenType::Compare, Opcode::F64Gt}, -#line 77 "src/lexer-keywords.txt" - {"f32.gt", TokenType::Compare, Opcode::F32Gt}, -#line 141 "src/lexer-keywords.txt" + {""}, {""}, {""}, +#line 146 "src/lexer-keywords.txt" {"f64.lt", TokenType::Compare, Opcode::F64Lt}, -#line 80 "src/lexer-keywords.txt" +#line 85 "src/lexer-keywords.txt" {"f32.lt", TokenType::Compare, Opcode::F32Lt}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 45 "src/lexer-keywords.txt" - {"code", TokenType::Code}, - {""}, {""}, {""}, -#line 574 "src/lexer-keywords.txt" - {"result", TokenType::Result}, +#line 143 "src/lexer-keywords.txt" + {"f64.gt", TokenType::Compare, Opcode::F64Gt}, +#line 82 "src/lexer-keywords.txt" + {"f32.gt", TokenType::Compare, Opcode::F32Gt}, +#line 566 "src/lexer-keywords.txt" + {"module", TokenType::Module}, {""}, -#line 102 "src/lexer-keywords.txt" - {"f32x4.ge", TokenType::Compare, Opcode::F32X4Ge}, +#line 152 "src/lexer-keywords.txt" + {"f64.ne", TokenType::Compare, Opcode::F64Ne}, +#line 91 "src/lexer-keywords.txt" + {"f32.ne", TokenType::Compare, Opcode::F32Ne}, +#line 451 "src/lexer-keywords.txt" + {"i64.ne", TokenType::Compare, Opcode::I64Ne}, +#line 308 "src/lexer-keywords.txt" + {"i32.ne", TokenType::Compare, Opcode::I32Ne}, +#line 591 "src/lexer-keywords.txt" + {"result", TokenType::Result}, {""}, -#line 104 "src/lexer-keywords.txt" +#line 109 "src/lexer-keywords.txt" {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, - {""}, -#line 583 "src/lexer-keywords.txt" - {"struct", Type::Struct, TokenType::Struct}, - {""}, {""}, {""}, {""}, {""}, -#line 557 "src/lexer-keywords.txt" - {"mut", TokenType::Mut}, -#line 443 "src/lexer-keywords.txt" - {"i64.or", TokenType::Binary, Opcode::I64Or}, -#line 300 "src/lexer-keywords.txt" - {"i32.or", TokenType::Binary, Opcode::I32Or}, - {""}, {""}, -#line 586 "src/lexer-keywords.txt" - {"table.get", TokenType::TableGet, Opcode::TableGet}, -#line 103 "src/lexer-keywords.txt" - {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, -#line 589 "src/lexer-keywords.txt" - {"table.set", TokenType::TableSet, Opcode::TableSet}, -#line 105 "src/lexer-keywords.txt" +#line 600 "src/lexer-keywords.txt" + {"struct", Type::StructRef, TokenType::Struct}, +#line 107 "src/lexer-keywords.txt" + {"f32x4.ge", TokenType::Compare, Opcode::F32X4Ge}, + {""}, {""}, {""}, +#line 151 "src/lexer-keywords.txt" + {"f64.neg", TokenType::Unary, Opcode::F64Neg}, +#line 90 "src/lexer-keywords.txt" + {"f32.neg", TokenType::Unary, Opcode::F32Neg}, +#line 110 "src/lexer-keywords.txt" {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, -#line 332 "src/lexer-keywords.txt" - {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, - {""}, -#line 336 "src/lexer-keywords.txt" - {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, +#line 53 "src/lexer-keywords.txt" + {"do", TokenType::Do}, +#line 108 "src/lexer-keywords.txt" + {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, {""}, -#line 331 "src/lexer-keywords.txt" - {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, -#line 95 "src/lexer-keywords.txt" +#line 100 "src/lexer-keywords.txt" {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, -#line 335 "src/lexer-keywords.txt" - {"i32x4.le_s", TokenType::Compare, Opcode::I32X4LeS}, {""}, -#line 334 "src/lexer-keywords.txt" - {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, +#line 116 "src/lexer-keywords.txt" + {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, + {""}, +#line 361 "src/lexer-keywords.txt" + {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, +#line 115 "src/lexer-keywords.txt" + {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, {""}, +#line 360 "src/lexer-keywords.txt" + {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, + {""}, {""}, {""}, +#line 194 "src/lexer-keywords.txt" + {"func", Type::FuncRef, TokenType::Func}, + {""}, {""}, {""}, #line 344 "src/lexer-keywords.txt" - {"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU}, + {"i32x4.le_s", TokenType::Compare, Opcode::I32X4LeS}, +#line 193 "src/lexer-keywords.txt" + {"final", TokenType::Final}, +#line 340 "src/lexer-keywords.txt" + {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, {""}, -#line 333 "src/lexer-keywords.txt" +#line 352 "src/lexer-keywords.txt" + {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, +#line 127 "src/lexer-keywords.txt" + {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, +#line 342 "src/lexer-keywords.txt" {"i32x4.gt_s", TokenType::Compare, Opcode::I32X4GtS}, +#line 150 "src/lexer-keywords.txt" + {"f64.nearest", TokenType::Unary, Opcode::F64Nearest}, +#line 89 "src/lexer-keywords.txt" + {"f32.nearest", TokenType::Unary, Opcode::F32Nearest}, {""}, -#line 343 "src/lexer-keywords.txt" - {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, -#line 147 "src/lexer-keywords.txt" - {"f64.ne", TokenType::Compare, Opcode::F64Ne}, -#line 86 "src/lexer-keywords.txt" - {"f32.ne", TokenType::Compare, Opcode::F32Ne}, +#line 50 "src/lexer-keywords.txt" + {"data", TokenType::Data}, + {""}, {""}, +#line 452 "src/lexer-keywords.txt" + {"i64.or", TokenType::Binary, Opcode::I64Or}, +#line 309 "src/lexer-keywords.txt" + {"i32.or", TokenType::Binary, Opcode::I32Or}, {""}, {""}, {""}, -#line 556 "src/lexer-keywords.txt" - {"module", TokenType::Module}, - {""}, -#line 442 "src/lexer-keywords.txt" - {"i64.ne", TokenType::Compare, Opcode::I64Ne}, -#line 299 "src/lexer-keywords.txt" - {"i32.ne", TokenType::Compare, Opcode::I32Ne}, #line 48 "src/lexer-keywords.txt" - {"declare", TokenType::Declare}, + {"code", TokenType::Code}, +#line 114 "src/lexer-keywords.txt" + {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, +#line 610 "src/lexer-keywords.txt" + {"table", TokenType::Table}, + {""}, {""}, {""}, {""}, {""}, +#line 567 "src/lexer-keywords.txt" + {"mut", TokenType::Mut}, {""}, -#line 146 "src/lexer-keywords.txt" - {"f64.neg", TokenType::Unary, Opcode::F64Neg}, -#line 85 "src/lexer-keywords.txt" - {"f32.neg", TokenType::Unary, Opcode::F32Neg}, +#line 582 "src/lexer-keywords.txt" + {"rec", TokenType::Rec}, +#line 571 "src/lexer-keywords.txt" + {"nofunc", Type::NullFuncRef, TokenType::NoFunc}, + {""}, {""}, +#line 457 "src/lexer-keywords.txt" + {"i64.rotl", TokenType::Binary, Opcode::I64Rotl}, +#line 314 "src/lexer-keywords.txt" + {"i32.rotl", TokenType::Binary, Opcode::I32Rotl}, +#line 458 "src/lexer-keywords.txt" + {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, +#line 315 "src/lexer-keywords.txt" + {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, +#line 123 "src/lexer-keywords.txt" + {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, {""}, -#line 151 "src/lexer-keywords.txt" +#line 363 "src/lexer-keywords.txt" + {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, +#line 156 "src/lexer-keywords.txt" {"f64.store", TokenType::Store, Opcode::F64Store}, -#line 89 "src/lexer-keywords.txt" +#line 94 "src/lexer-keywords.txt" {"f32.store", TokenType::Store, Opcode::F32Store}, - {""}, -#line 449 "src/lexer-keywords.txt" - {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, -#line 306 "src/lexer-keywords.txt" - {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, -#line 448 "src/lexer-keywords.txt" - {"i64.rotl", TokenType::Binary, Opcode::I64Rotl}, -#line 305 "src/lexer-keywords.txt" - {"i32.rotl", TokenType::Binary, Opcode::I32Rotl}, -#line 456 "src/lexer-keywords.txt" +#line 465 "src/lexer-keywords.txt" {"i64.store", TokenType::Store, Opcode::I64Store}, -#line 312 "src/lexer-keywords.txt" +#line 321 "src/lexer-keywords.txt" {"i32.store", TokenType::Store, Opcode::I32Store}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 51 "src/lexer-keywords.txt" + {"declare", TokenType::Declare}, + {""}, {""}, #line 572 "src/lexer-keywords.txt" - {"ref.null", TokenType::RefNull, Opcode::RefNull}, -#line 110 "src/lexer-keywords.txt" - {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, + {"none", Type::NullRef, TokenType::None}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 605 "src/lexer-keywords.txt" + {"table.get", TokenType::TableGet, Opcode::TableGet}, +#line 133 "src/lexer-keywords.txt" + {"f64.const", TokenType::Const, Opcode::F64Const}, +#line 71 "src/lexer-keywords.txt" + {"f32.const", TokenType::Const, Opcode::F32Const}, +#line 424 "src/lexer-keywords.txt" + {"i64.const", TokenType::Const, Opcode::I64Const}, +#line 286 "src/lexer-keywords.txt" + {"i32.const", TokenType::Const, Opcode::I32Const}, {""}, -#line 111 "src/lexer-keywords.txt" - {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, - {""}, {""}, {""}, {""}, -#line 351 "src/lexer-keywords.txt" - {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, +#line 608 "src/lexer-keywords.txt" + {"table.set", TokenType::TableSet, Opcode::TableSet}, {""}, -#line 352 "src/lexer-keywords.txt" - {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, +#line 596 "src/lexer-keywords.txt" + {"return", TokenType::Return, Opcode::Return}, {""}, {""}, -#line 153 "src/lexer-keywords.txt" +#line 589 "src/lexer-keywords.txt" + {"ref.null", TokenType::RefNull, Opcode::RefNull}, +#line 158 "src/lexer-keywords.txt" {"f64.trunc", TokenType::Unary, Opcode::F64Trunc}, -#line 91 "src/lexer-keywords.txt" +#line 96 "src/lexer-keywords.txt" {"f32.trunc", TokenType::Unary, Opcode::F32Trunc}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 145 "src/lexer-keywords.txt" - {"f64.nearest", TokenType::Unary, Opcode::F64Nearest}, -#line 84 "src/lexer-keywords.txt" - {"f32.nearest", TokenType::Unary, Opcode::F32Nearest}, {""}, {""}, {""}, -#line 122 "src/lexer-keywords.txt" - {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, -#line 579 "src/lexer-keywords.txt" - {"return", TokenType::Return, Opcode::Return}, +#line 362 "src/lexer-keywords.txt" + {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, + {""}, {""}, {""}, {""}, {""}, +#line 597 "src/lexer-keywords.txt" + {"select", TokenType::Select, Opcode::Select}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 52 "src/lexer-keywords.txt" + {"delegate", TokenType::Delegate}, +#line 586 "src/lexer-keywords.txt" + {"ref.extern", TokenType::RefExtern}, + {""}, {""}, +#line 507 "src/lexer-keywords.txt" + {"i64.xor", TokenType::Binary, Opcode::I64Xor}, +#line 384 "src/lexer-keywords.txt" + {"i32.xor", TokenType::Binary, Opcode::I32Xor}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 508 "src/lexer-keywords.txt" + {"i8", Type::I8}, {""}, {""}, {""}, {""}, -#line 561 "src/lexer-keywords.txt" +#line 574 "src/lexer-keywords.txt" {"null", TokenType::Null}, -#line 455 "src/lexer-keywords.txt" - {"i64.store8", TokenType::Store, Opcode::I64Store8}, -#line 311 "src/lexer-keywords.txt" - {"i32.store8", TokenType::Store, Opcode::I32Store8}, -#line 144 "src/lexer-keywords.txt" + {""}, +#line 105 "src/lexer-keywords.txt" + {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, + {""}, +#line 339 "src/lexer-keywords.txt" + {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 439 "src/lexer-keywords.txt" + {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, +#line 298 "src/lexer-keywords.txt" + {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, +#line 435 "src/lexer-keywords.txt" + {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, +#line 294 "src/lexer-keywords.txt" + {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, +#line 448 "src/lexer-keywords.txt" + {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, +#line 305 "src/lexer-keywords.txt" + {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, +#line 437 "src/lexer-keywords.txt" + {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, +#line 296 "src/lexer-keywords.txt" + {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, + {""}, {""}, +#line 335 "src/lexer-keywords.txt" + {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, + {""}, {""}, {""}, {""}, {""}, +#line 43 "src/lexer-keywords.txt" + {"call", TokenType::Call, Opcode::Call}, + {""}, {""}, +#line 345 "src/lexer-keywords.txt" + {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, + {""}, +#line 341 "src/lexer-keywords.txt" + {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, + {""}, +#line 353 "src/lexer-keywords.txt" + {"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU}, +#line 555 "src/lexer-keywords.txt" + {"local", TokenType::Local}, +#line 343 "src/lexer-keywords.txt" + {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, + {""}, {""}, +#line 99 "src/lexer-keywords.txt" + {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, + {""}, +#line 334 "src/lexer-keywords.txt" + {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, +#line 386 "src/lexer-keywords.txt" + {"i64.and", TokenType::Binary, Opcode::I64And}, +#line 257 "src/lexer-keywords.txt" + {"i32.and", TokenType::Binary, Opcode::I32And}, +#line 149 "src/lexer-keywords.txt" {"f64.mul", TokenType::Binary, Opcode::F64Mul}, -#line 83 "src/lexer-keywords.txt" +#line 88 "src/lexer-keywords.txt" {"f32.mul", TokenType::Binary, Opcode::F32Mul}, -#line 94 "src/lexer-keywords.txt" - {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, -#line 109 "src/lexer-keywords.txt" - {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, - {""}, {""}, {""}, -#line 441 "src/lexer-keywords.txt" +#line 450 "src/lexer-keywords.txt" {"i64.mul", TokenType::Binary, Opcode::I64Mul}, -#line 298 "src/lexer-keywords.txt" +#line 307 "src/lexer-keywords.txt" {"i32.mul", TokenType::Binary, Opcode::I32Mul}, -#line 325 "src/lexer-keywords.txt" - {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, - {""}, -#line 40 "src/lexer-keywords.txt" - {"call", TokenType::Call, Opcode::Call}, {""}, -#line 128 "src/lexer-keywords.txt" - {"f64.const", TokenType::Const, Opcode::F64Const}, -#line 66 "src/lexer-keywords.txt" - {"f32.const", TokenType::Const, Opcode::F32Const}, - {""}, {""}, {""}, -#line 108 "src/lexer-keywords.txt" +#line 121 "src/lexer-keywords.txt" + {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, + {""}, {""}, +#line 111 "src/lexer-keywords.txt" + {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, + {""}, {""}, {""}, {""}, +#line 113 "src/lexer-keywords.txt" {"f32x4.mul", TokenType::Binary, Opcode::F32X4Mul}, {""}, -#line 415 "src/lexer-keywords.txt" - {"i64.const", TokenType::Const, Opcode::I64Const}, -#line 277 "src/lexer-keywords.txt" - {"i32.const", TokenType::Const, Opcode::I32Const}, - {""}, -#line 580 "src/lexer-keywords.txt" - {"select", TokenType::Select, Opcode::Select}, - {""}, -#line 350 "src/lexer-keywords.txt" +#line 359 "src/lexer-keywords.txt" {"i32x4.mul", TokenType::Binary, Opcode::I32X4Mul}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 554 "src/lexer-keywords.txt" + {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, {""}, -#line 545 "src/lexer-keywords.txt" - {"local", TokenType::Local}, - {""}, {""}, {""}, -#line 498 "src/lexer-keywords.txt" - {"i64.xor", TokenType::Binary, Opcode::I64Xor}, -#line 375 "src/lexer-keywords.txt" - {"i32.xor", TokenType::Binary, Opcode::I32Xor}, -#line 49 "src/lexer-keywords.txt" - {"delegate", TokenType::Delegate}, +#line 552 "src/lexer-keywords.txt" + {"local.get", TokenType::LocalGet, Opcode::LocalGet}, + {""}, {""}, {""}, {""}, {""}, +#line 553 "src/lexer-keywords.txt" + {"local.set", TokenType::LocalSet, Opcode::LocalSet}, + {""}, {""}, {""}, {""}, +#line 585 "src/lexer-keywords.txt" + {"ref.as_non_null", TokenType::RefAsNonNull, Opcode::RefAsNonNull}, + {""}, +#line 422 "src/lexer-keywords.txt" + {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, +#line 284 "src/lexer-keywords.txt" + {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, {""}, {""}, {""}, -#line 126 "src/lexer-keywords.txt" - {"f64.add", TokenType::Binary, Opcode::F64Add}, -#line 64 "src/lexer-keywords.txt" - {"f32.add", TokenType::Binary, Opcode::F32Add}, -#line 140 "src/lexer-keywords.txt" +#line 415 "src/lexer-keywords.txt" + {"i64.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I64AtomicRmwOr}, +#line 278 "src/lexer-keywords.txt" + {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, + {""}, +#line 145 "src/lexer-keywords.txt" {"f64.load", TokenType::Load, Opcode::F64Load}, -#line 79 "src/lexer-keywords.txt" +#line 84 "src/lexer-keywords.txt" {"f32.load", TokenType::Load, Opcode::F32Load}, - {""}, {""}, {""}, -#line 376 "src/lexer-keywords.txt" - {"i64.add", TokenType::Binary, Opcode::I64Add}, -#line 247 "src/lexer-keywords.txt" - {"i32.add", TokenType::Binary, Opcode::I32Add}, -#line 438 "src/lexer-keywords.txt" +#line 447 "src/lexer-keywords.txt" {"i64.load", TokenType::Load, Opcode::I64Load}, -#line 295 "src/lexer-keywords.txt" +#line 304 "src/lexer-keywords.txt" {"i32.load", TokenType::Load, Opcode::I32Load}, - {""}, {""}, {""}, {""}, -#line 118 "src/lexer-keywords.txt" - {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, - {""}, {""}, {""}, -#line 377 "src/lexer-keywords.txt" - {"i64.and", TokenType::Binary, Opcode::I64And}, -#line 248 "src/lexer-keywords.txt" - {"i32.and", TokenType::Binary, Opcode::I32And}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 595 "src/lexer-keywords.txt" + {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, + {""}, {""}, {""}, {""}, {""}, +#line 147 "src/lexer-keywords.txt" + {"f64.max", TokenType::Binary, Opcode::F64Max}, +#line 86 "src/lexer-keywords.txt" + {"f32.max", TokenType::Binary, Opcode::F32Max}, +#line 131 "src/lexer-keywords.txt" + {"f64.add", TokenType::Binary, Opcode::F64Add}, +#line 69 "src/lexer-keywords.txt" + {"f32.add", TokenType::Binary, Opcode::F32Add}, +#line 385 "src/lexer-keywords.txt" + {"i64.add", TokenType::Binary, Opcode::I64Add}, +#line 256 "src/lexer-keywords.txt" + {"i32.add", TokenType::Binary, Opcode::I32Add}, + {""}, +#line 348 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, + {""}, +#line 455 "src/lexer-keywords.txt" + {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, +#line 312 "src/lexer-keywords.txt" + {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, +#line 38 "src/lexer-keywords.txt" + {"br_on_null", TokenType::BrOnNull, Opcode::BrOnNull}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 354 "src/lexer-keywords.txt" - {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, + {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, {""}, {""}, {""}, -#line 427 "src/lexer-keywords.txt" - {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, -#line 286 "src/lexer-keywords.txt" - {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, -#line 431 "src/lexer-keywords.txt" +#line 467 "src/lexer-keywords.txt" + {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, +#line 323 "src/lexer-keywords.txt" + {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 440 "src/lexer-keywords.txt" {"i64.le_u", TokenType::Compare, Opcode::I64LeU}, -#line 290 "src/lexer-keywords.txt" +#line 299 "src/lexer-keywords.txt" {"i32.le_u", TokenType::Compare, Opcode::I32LeU}, -#line 426 "src/lexer-keywords.txt" - {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, -#line 285 "src/lexer-keywords.txt" - {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, -#line 430 "src/lexer-keywords.txt" - {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, -#line 289 "src/lexer-keywords.txt" - {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, -#line 429 "src/lexer-keywords.txt" - {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, -#line 288 "src/lexer-keywords.txt" - {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, -#line 440 "src/lexer-keywords.txt" +#line 436 "src/lexer-keywords.txt" + {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, +#line 295 "src/lexer-keywords.txt" + {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, +#line 449 "src/lexer-keywords.txt" {"i64.lt_u", TokenType::Compare, Opcode::I64LtU}, -#line 297 "src/lexer-keywords.txt" +#line 306 "src/lexer-keywords.txt" {"i32.lt_u", TokenType::Compare, Opcode::I32LtU}, -#line 428 "src/lexer-keywords.txt" - {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, -#line 287 "src/lexer-keywords.txt" - {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, -#line 439 "src/lexer-keywords.txt" - {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, -#line 296 "src/lexer-keywords.txt" - {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, - {""}, {""}, {""}, -#line 542 "src/lexer-keywords.txt" - {"local.get", TokenType::LocalGet, Opcode::LocalGet}, - {""}, -#line 543 "src/lexer-keywords.txt" - {"local.set", TokenType::LocalSet, Opcode::LocalSet}, -#line 544 "src/lexer-keywords.txt" - {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 353 "src/lexer-keywords.txt" - {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, -#line 326 "src/lexer-keywords.txt" - {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, - {""}, -#line 127 "src/lexer-keywords.txt" - {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, -#line 65 "src/lexer-keywords.txt" - {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 590 "src/lexer-keywords.txt" - {"table.size", TokenType::TableSize, Opcode::TableSize}, - {""}, {""}, {""}, -#line 106 "src/lexer-keywords.txt" - {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, -#line 537 "src/lexer-keywords.txt" - {"if", TokenType::If, Opcode::If}, -#line 413 "src/lexer-keywords.txt" - {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, -#line 275 "src/lexer-keywords.txt" - {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 566 "src/lexer-keywords.txt" - {"ref", TokenType::Ref}, +#line 438 "src/lexer-keywords.txt" + {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, +#line 297 "src/lexer-keywords.txt" + {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, +#line 418 "src/lexer-keywords.txt" + {"i64.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I64AtomicRmwXor}, +#line 281 "src/lexer-keywords.txt" + {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, +#line 445 "src/lexer-keywords.txt" + {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, +#line 302 "src/lexer-keywords.txt" + {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, {""}, {""}, -#line 406 "src/lexer-keywords.txt" - {"i64.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I64AtomicRmwOr}, -#line 269 "src/lexer-keywords.txt" - {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, - {""}, {""}, {""}, {""}, {""}, -#line 578 "src/lexer-keywords.txt" - {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, +#line 120 "src/lexer-keywords.txt" + {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, {""}, {""}, -#line 55 "src/lexer-keywords.txt" - {"else", TokenType::Else, Opcode::Else}, - {""}, {""}, {""}, {""}, {""}, -#line 57 "src/lexer-keywords.txt" - {"tag", TokenType::Tag}, +#line 547 "src/lexer-keywords.txt" + {"if", TokenType::If, Opcode::If}, {""}, -#line 100 "src/lexer-keywords.txt" - {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, -#line 569 "src/lexer-keywords.txt" - {"ref.extern", TokenType::RefExtern}, -#line 340 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, -#line 92 "src/lexer-keywords.txt" +#line 97 "src/lexer-keywords.txt" {"f32", Type::F32}, -#line 339 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, - {""}, {""}, -#line 330 "src/lexer-keywords.txt" - {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, {""}, -#line 191 "src/lexer-keywords.txt" - {"get", TokenType::Get}, -#line 322 "src/lexer-keywords.txt" +#line 331 "src/lexer-keywords.txt" {"i32", Type::I32}, -#line 52 "src/lexer-keywords.txt" - {"either", TokenType::Either}, - {""}, {""}, -#line 393 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, -#line 437 "src/lexer-keywords.txt" - {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, -#line 294 "src/lexer-keywords.txt" - {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, -#line 436 "src/lexer-keywords.txt" - {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, -#line 293 "src/lexer-keywords.txt" - {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, + {""}, {""}, {""}, {""}, +#line 58 "src/lexer-keywords.txt" + {"else", TokenType::Else, Opcode::Else}, {""}, -#line 412 "src/lexer-keywords.txt" - {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, -#line 274 "src/lexer-keywords.txt" - {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, -#line 433 "src/lexer-keywords.txt" - {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, -#line 292 "src/lexer-keywords.txt" - {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, #line 459 "src/lexer-keywords.txt" - {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, -#line 315 "src/lexer-keywords.txt" - {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, -#line 432 "src/lexer-keywords.txt" - {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, -#line 291 "src/lexer-keywords.txt" - {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, -#line 458 "src/lexer-keywords.txt" - {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, -#line 314 "src/lexer-keywords.txt" - {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, -#line 447 "src/lexer-keywords.txt" - {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, -#line 304 "src/lexer-keywords.txt" - {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, -#line 446 "src/lexer-keywords.txt" - {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, -#line 303 "src/lexer-keywords.txt" - {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, - {""}, -#line 56 "src/lexer-keywords.txt" - {"end", TokenType::End, Opcode::End}, - {""}, -#line 409 "src/lexer-keywords.txt" - {"i64.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I64AtomicRmwXor}, -#line 272 "src/lexer-keywords.txt" - {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 592 "src/lexer-keywords.txt" - {"then", TokenType::Then}, -#line 588 "src/lexer-keywords.txt" - {"table.init", TokenType::TableInit, Opcode::TableInit}, - {""}, {""}, -#line 346 "src/lexer-keywords.txt" - {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, - {""}, -#line 345 "src/lexer-keywords.txt" - {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, -#line 35 "src/lexer-keywords.txt" - {"br_on_null", TokenType::BrOnNull, Opcode::BrOnNull}, -#line 392 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, -#line 450 "src/lexer-keywords.txt" {"i64.shl", TokenType::Binary, Opcode::I64Shl}, -#line 307 "src/lexer-keywords.txt" +#line 316 "src/lexer-keywords.txt" {"i32.shl", TokenType::Binary, Opcode::I32Shl}, - {""}, {""}, -#line 116 "src/lexer-keywords.txt" - {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, {""}, -#line 117 "src/lexer-keywords.txt" - {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, -#line 142 "src/lexer-keywords.txt" - {"f64.max", TokenType::Binary, Opcode::F64Max}, -#line 81 "src/lexer-keywords.txt" - {"f32.max", TokenType::Binary, Opcode::F32Max}, +#line 583 "src/lexer-keywords.txt" + {"ref", TokenType::Ref}, {""}, {""}, -#line 162 "src/lexer-keywords.txt" - {"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge}, +#line 432 "src/lexer-keywords.txt" + {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, +#line 293 "src/lexer-keywords.txt" + {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, {""}, -#line 164 "src/lexer-keywords.txt" - {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, - {""}, {""}, -#line 389 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AddU}, +#line 349 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, {""}, -#line 355 "src/lexer-keywords.txt" +#line 456 "src/lexer-keywords.txt" + {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, +#line 313 "src/lexer-keywords.txt" + {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, +#line 364 "src/lexer-keywords.txt" {"i32x4.shl", TokenType::Binary, Opcode::I32X4Shl}, - {""}, {""}, -#line 573 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 590 "src/lexer-keywords.txt" {"register", TokenType::Register}, -#line 381 "src/lexer-keywords.txt" - {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, -#line 251 "src/lexer-keywords.txt" - {"i32.atomic.load", TokenType::AtomicLoad, Opcode::I32AtomicLoad}, +#line 122 "src/lexer-keywords.txt" + {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, {""}, {""}, {""}, -#line 163 "src/lexer-keywords.txt" - {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, -#line 390 "src/lexer-keywords.txt" +#line 399 "src/lexer-keywords.txt" {"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU}, -#line 165 "src/lexer-keywords.txt" +#line 355 "src/lexer-keywords.txt" + {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, + {""}, +#line 169 "src/lexer-keywords.txt" + {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, + {""}, +#line 167 "src/lexer-keywords.txt" + {"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge}, + {""}, {""}, {""}, {""}, {""}, +#line 170 "src/lexer-keywords.txt" {"f64x2.lt", TokenType::Compare, Opcode::F64X2Lt}, {""}, -#line 60 "src/lexer-keywords.txt" - {"exn", Type::ExnRef, TokenType::Exn}, - {""}, {""}, -#line 477 "src/lexer-keywords.txt" - {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, -#line 157 "src/lexer-keywords.txt" +#line 168 "src/lexer-keywords.txt" + {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, + {""}, +#line 162 "src/lexer-keywords.txt" {"f64x2.ceil", TokenType::Unary, Opcode::F64X2Ceil}, -#line 476 "src/lexer-keywords.txt" +#line 60 "src/lexer-keywords.txt" + {"tag", TokenType::Tag}, +#line 176 "src/lexer-keywords.txt" + {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, +#line 197 "src/lexer-keywords.txt" + {"get", TokenType::Get}, +#line 482 "src/lexer-keywords.txt" + {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, +#line 175 "src/lexer-keywords.txt" + {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, + {""}, +#line 488 "src/lexer-keywords.txt" + {"i64x2.neg", TokenType::Unary, Opcode::I64X2Neg}, + {""}, +#line 601 "src/lexer-keywords.txt" + {"structref", Type::StructRef}, +#line 446 "src/lexer-keywords.txt" + {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, +#line 303 "src/lexer-keywords.txt" + {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, + {""}, {""}, {""}, +#line 485 "src/lexer-keywords.txt" {"i64x2.le_s", TokenType::Binary, Opcode::I64X2LeS}, - {""}, {""}, {""}, {""}, {""}, -#line 475 "src/lexer-keywords.txt" - {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, {""}, -#line 474 "src/lexer-keywords.txt" +#line 486 "src/lexer-keywords.txt" + {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, + {""}, +#line 483 "src/lexer-keywords.txt" {"i64x2.lt_s", TokenType::Binary, Opcode::I64X2LtS}, -#line 101 "src/lexer-keywords.txt" - {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, - {""}, {""}, #line 187 "src/lexer-keywords.txt" - {"field", TokenType::Field}, -#line 114 "src/lexer-keywords.txt" - {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, - {""}, {""}, {""}, {""}, {""}, -#line 421 "src/lexer-keywords.txt" - {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, -#line 283 "src/lexer-keywords.txt" - {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, - {""}, -#line 541 "src/lexer-keywords.txt" - {"item", TokenType::Item}, - {""}, {""}, -#line 423 "src/lexer-keywords.txt" - {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, -#line 284 "src/lexer-keywords.txt" - {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, + {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, +#line 484 "src/lexer-keywords.txt" + {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, + {""}, {""}, {""}, +#line 65 "src/lexer-keywords.txt" + {"exn", Type::ExnRef, TokenType::Exn}, +#line 401 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, {""}, {""}, -#line 570 "src/lexer-keywords.txt" - {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, -#line 136 "src/lexer-keywords.txt" - {"f64.floor", TokenType::Unary, Opcode::F64Floor}, -#line 75 "src/lexer-keywords.txt" - {"f32.floor", TokenType::Unary, Opcode::F32Floor}, +#line 390 "src/lexer-keywords.txt" + {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, +#line 260 "src/lexer-keywords.txt" + {"i32.atomic.load", TokenType::AtomicLoad, Opcode::I32AtomicLoad}, + {""}, {""}, {""}, +#line 174 "src/lexer-keywords.txt" + {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, + {""}, {""}, {""}, +#line 59 "src/lexer-keywords.txt" + {"end", TokenType::End, Opcode::End}, + {""}, {""}, {""}, {""}, {""}, +#line 611 "src/lexer-keywords.txt" + {"then", TokenType::Then}, + {""}, {""}, {""}, +#line 55 "src/lexer-keywords.txt" + {"either", TokenType::Either}, {""}, {""}, -#line 414 "src/lexer-keywords.txt" - {"i64.clz", TokenType::Unary, Opcode::I64Clz}, -#line 276 "src/lexer-keywords.txt" - {"i32.clz", TokenType::Unary, Opcode::I32Clz}, - {""}, {""}, {""}, {""}, -#line 170 "src/lexer-keywords.txt" - {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, -#line 107 "src/lexer-keywords.txt" - {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, -#line 171 "src/lexer-keywords.txt" - {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, -#line 416 "src/lexer-keywords.txt" - {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, -#line 278 "src/lexer-keywords.txt" - {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, +#line 183 "src/lexer-keywords.txt" + {"f64x2.replace_lane", TokenType::SimdLaneOp, Opcode::F64X2ReplaceLane}, +#line 402 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, +#line 496 "src/lexer-keywords.txt" + {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, +#line 398 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AddU}, + {""}, +#line 468 "src/lexer-keywords.txt" + {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, +#line 324 "src/lexer-keywords.txt" + {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, +#line 132 "src/lexer-keywords.txt" + {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, +#line 70 "src/lexer-keywords.txt" + {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, + {""}, +#line 106 "src/lexer-keywords.txt" + {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, {""}, {""}, -#line 479 "src/lexer-keywords.txt" - {"i64x2.neg", TokenType::Unary, Opcode::I64X2Neg}, -#line 454 "src/lexer-keywords.txt" +#line 413 "src/lexer-keywords.txt" + {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, +#line 276 "src/lexer-keywords.txt" + {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, + {""}, +#line 463 "src/lexer-keywords.txt" {"i64.store32", TokenType::Store, Opcode::I64Store32}, -#line 473 "src/lexer-keywords.txt" - {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, {""}, -#line 58 "src/lexer-keywords.txt" +#line 119 "src/lexer-keywords.txt" + {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, + {""}, +#line 551 "src/lexer-keywords.txt" + {"item", TokenType::Item}, +#line 464 "src/lexer-keywords.txt" + {"i64.store8", TokenType::Store, Opcode::I64Store8}, +#line 320 "src/lexer-keywords.txt" + {"i32.store8", TokenType::Store, Opcode::I32Store8}, + {""}, +#line 63 "src/lexer-keywords.txt" {"extern", Type::ExternRef, TokenType::Extern}, -#line 396 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, -#line 259 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, + {""}, +#line 570 "src/lexer-keywords.txt" + {"noextern", Type::NullExternRef, TokenType::NoExtern}, {""}, {""}, -#line 394 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, +#line 232 "src/lexer-keywords.txt" + {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, + {""}, {""}, +#line 230 "src/lexer-keywords.txt" + {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, + {""}, {""}, +#line 495 "src/lexer-keywords.txt" + {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, + {""}, {""}, {""}, {""}, +#line 217 "src/lexer-keywords.txt" + {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, +#line 587 "src/lexer-keywords.txt" + {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, +#line 213 "src/lexer-keywords.txt" + {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, +#line 404 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XorU}, +#line 221 "src/lexer-keywords.txt" + {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, {""}, -#line 115 "src/lexer-keywords.txt" - {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, -#line 568 "src/lexer-keywords.txt" - {"ref.as_non_null", TokenType::RefAsNonNull, Opcode::RefAsNonNull}, +#line 215 "src/lexer-keywords.txt" + {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, {""}, {""}, {""}, {""}, -#line 397 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, -#line 260 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, - {""}, {""}, -#line 190 "src/lexer-keywords.txt" - {"function", TokenType::Function}, +#line 37 "src/lexer-keywords.txt" + {"br_on_non_null", TokenType::BrOnNonNull, Opcode::BrOnNonNull}, + {""}, +#line 141 "src/lexer-keywords.txt" + {"f64.floor", TokenType::Unary, Opcode::F64Floor}, +#line 80 "src/lexer-keywords.txt" + {"f32.floor", TokenType::Unary, Opcode::F32Floor}, +#line 460 "src/lexer-keywords.txt" + {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, +#line 317 "src/lexer-keywords.txt" + {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 441 "src/lexer-keywords.txt" + {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, +#line 300 "src/lexer-keywords.txt" + {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, + {""}, +#line 365 "src/lexer-keywords.txt" + {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, +#line 165 "src/lexer-keywords.txt" + {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, + {""}, +#line 477 "src/lexer-keywords.txt" + {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, + {""}, #line 403 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, +#line 430 "src/lexer-keywords.txt" + {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, +#line 292 "src/lexer-keywords.txt" + {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, + {""}, {""}, {""}, +#line 235 "src/lexer-keywords.txt" + {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, + {""}, {""}, +#line 192 "src/lexer-keywords.txt" + {"field", TokenType::Field}, +#line 412 "src/lexer-keywords.txt" {"i64.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I64AtomicRmwAdd}, -#line 266 "src/lexer-keywords.txt" +#line 275 "src/lexer-keywords.txt" {"i32.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I32AtomicRmwAdd}, - {""}, -#line 182 "src/lexer-keywords.txt" - {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, - {""}, {""}, -#line 395 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XorU}, + {""}, {""}, {""}, +#line 489 "src/lexer-keywords.txt" + {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, + {""}, {""}, {""}, {""}, {""}, +#line 201 "src/lexer-keywords.txt" + {"i16", Type::I16}, + {""}, {""}, {""}, {""}, {""}, +#line 609 "src/lexer-keywords.txt" + {"table.size", TokenType::TableSize, Opcode::TableSize}, {""}, {""}, -#line 559 "src/lexer-keywords.txt" - {"nan:canonical", TokenType::NanCanonical}, +#line 593 "src/lexer-keywords.txt" + {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, {""}, {""}, -#line 404 "src/lexer-keywords.txt" - {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, -#line 267 "src/lexer-keywords.txt" - {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, -#line 156 "src/lexer-keywords.txt" +#line 161 "src/lexer-keywords.txt" {"f64x2.add", TokenType::Binary, Opcode::F64X2Add}, -#line 169 "src/lexer-keywords.txt" - {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, - {""}, {""}, {""}, -#line 143 "src/lexer-keywords.txt" - {"f64.min", TokenType::Binary, Opcode::F64Min}, -#line 82 "src/lexer-keywords.txt" - {"f32.min", TokenType::Binary, Opcode::F32Min}, -#line 467 "src/lexer-keywords.txt" + {""}, +#line 476 "src/lexer-keywords.txt" {"i64x2.add", TokenType::Binary, Opcode::I64X2Add}, {""}, {""}, -#line 402 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, -#line 265 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XorU}, +#line 443 "src/lexer-keywords.txt" + {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, +#line 233 "src/lexer-keywords.txt" + {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, {""}, -#line 461 "src/lexer-keywords.txt" - {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, -#line 317 "src/lexer-keywords.txt" - {"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U}, +#line 607 "src/lexer-keywords.txt" + {"table.init", TokenType::TableInit, Opcode::TableInit}, {""}, -#line 168 "src/lexer-keywords.txt" +#line 181 "src/lexer-keywords.txt" + {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, +#line 565 "src/lexer-keywords.txt" + {"memory", TokenType::Memory}, + {""}, +#line 171 "src/lexer-keywords.txt" + {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, +#line 431 "src/lexer-keywords.txt" + {"i64.extend32_s", TokenType::Unary, Opcode::I64Extend32S}, + {""}, +#line 461 "src/lexer-keywords.txt" + {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, +#line 318 "src/lexer-keywords.txt" + {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, +#line 173 "src/lexer-keywords.txt" {"f64x2.mul", TokenType::Binary, Opcode::F64X2Mul}, -#line 460 "src/lexer-keywords.txt" + {""}, +#line 480 "src/lexer-keywords.txt" + {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, + {""}, {""}, +#line 346 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, + {""}, {""}, {""}, {""}, +#line 366 "src/lexer-keywords.txt" + {"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU}, +#line 112 "src/lexer-keywords.txt" + {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, +#line 148 "src/lexer-keywords.txt" + {"f64.min", TokenType::Binary, Opcode::F64Min}, +#line 87 "src/lexer-keywords.txt" + {"f32.min", TokenType::Binary, Opcode::F32Min}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 34 "src/lexer-keywords.txt" + {"binary", TokenType::Bin}, +#line 196 "src/lexer-keywords.txt" + {"function", TokenType::Function}, + {""}, +#line 417 "src/lexer-keywords.txt" + {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, +#line 280 "src/lexer-keywords.txt" + {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, + {""}, +#line 469 "src/lexer-keywords.txt" {"i64.trunc_f64_s", TokenType::Convert, Opcode::I64TruncF64S}, -#line 316 "src/lexer-keywords.txt" +#line 325 "src/lexer-keywords.txt" {"i32.trunc_f64_s", TokenType::Convert, Opcode::I32TruncF64S}, -#line 571 "src/lexer-keywords.txt" +#line 249 "src/lexer-keywords.txt" + {"i16x8", TokenType::I16X8}, +#line 535 "src/lexer-keywords.txt" + {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, + {""}, {""}, +#line 533 "src/lexer-keywords.txt" + {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, + {""}, {""}, {""}, +#line 206 "src/lexer-keywords.txt" + {"i16x8.all_true", TokenType::Unary, Opcode::I16X8AllTrue}, +#line 421 "src/lexer-keywords.txt" + {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, +#line 283 "src/lexer-keywords.txt" + {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, + {""}, +#line 523 "src/lexer-keywords.txt" + {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, + {""}, +#line 519 "src/lexer-keywords.txt" + {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, +#line 588 "src/lexer-keywords.txt" {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, -#line 610 "src/lexer-keywords.txt" - {"v128", Type::V128}, +#line 525 "src/lexer-keywords.txt" + {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, +#line 218 "src/lexer-keywords.txt" + {"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU}, +#line 521 "src/lexer-keywords.txt" + {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, +#line 214 "src/lexer-keywords.txt" + {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, + {""}, +#line 222 "src/lexer-keywords.txt" + {"i16x8.lt_u", TokenType::Compare, Opcode::I16X8LtU}, + {""}, +#line 216 "src/lexer-keywords.txt" + {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, +#line 406 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, +#line 269 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, + {""}, {""}, +#line 205 "src/lexer-keywords.txt" + {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, + {""}, {""}, +#line 389 "src/lexer-keywords.txt" + {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, +#line 259 "src/lexer-keywords.txt" + {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, + {""}, {""}, {""}, {""}, +#line 45 "src/lexer-keywords.txt" + {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, + {""}, {""}, {""}, +#line 442 "src/lexer-keywords.txt" + {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, +#line 301 "src/lexer-keywords.txt" + {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, + {""}, {""}, {""}, +#line 227 "src/lexer-keywords.txt" + {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, + {""}, +#line 614 "src/lexer-keywords.txt" + {"try", TokenType::Try, Opcode::Try}, + {""}, +#line 538 "src/lexer-keywords.txt" + {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, +#line 411 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, +#line 274 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XorU}, +#line 569 "src/lexer-keywords.txt" + {"nan:canonical", TokenType::NanCanonical}, +#line 576 "src/lexer-keywords.txt" + {"nullexternref", Type::NullExternRef}, +#line 77 "src/lexer-keywords.txt" + {"f32.demote_f64", TokenType::Convert, Opcode::F32DemoteF64}, + {""}, +#line 564 "src/lexer-keywords.txt" + {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 423 "src/lexer-keywords.txt" + {"i64.clz", TokenType::Unary, Opcode::I64Clz}, +#line 285 "src/lexer-keywords.txt" + {"i32.clz", TokenType::Unary, Opcode::I32Clz}, + {""}, +#line 180 "src/lexer-keywords.txt" + {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, +#line 425 "src/lexer-keywords.txt" + {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, +#line 287 "src/lexer-keywords.txt" + {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, + {""}, {""}, +#line 561 "src/lexer-keywords.txt" + {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, +#line 584 "src/lexer-keywords.txt" + {"quote", TokenType::Quote}, + {""}, {""}, {""}, +#line 35 "src/lexer-keywords.txt" + {"block", TokenType::Block, Opcode::Block}, + {""}, {""}, {""}, +#line 191 "src/lexer-keywords.txt" + {"f64x2", TokenType::F64X2}, +#line 537 "src/lexer-keywords.txt" + {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, +#line 506 "src/lexer-keywords.txt" + {"i64x2", TokenType::I64X2}, {""}, {""}, -#line 471 "src/lexer-keywords.txt" - {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, -#line 435 "src/lexer-keywords.txt" +#line 444 "src/lexer-keywords.txt" {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, {""}, {""}, {""}, -#line 434 "src/lexer-keywords.txt" - {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, +#line 578 "src/lexer-keywords.txt" + {"offset", TokenType::Offset}, + {""}, +#line 405 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, +#line 268 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, +#line 497 "src/lexer-keywords.txt" + {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, +#line 603 "src/lexer-keywords.txt" + {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, {""}, {""}, {""}, {""}, -#line 558 "src/lexer-keywords.txt" +#line 182 "src/lexer-keywords.txt" + {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, + {""}, +#line 568 "src/lexer-keywords.txt" {"nan:arithmetic", TokenType::NanArithmetic}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 540 "src/lexer-keywords.txt" - {"invoke", TokenType::Invoke}, - {""}, {""}, {""}, {""}, {""}, -#line 380 "src/lexer-keywords.txt" - {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, -#line 250 "src/lexer-keywords.txt" - {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, {""}, -#line 178 "src/lexer-keywords.txt" - {"f64x2.replace_lane", TokenType::SimdLaneOp, Opcode::F64X2ReplaceLane}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 487 "src/lexer-keywords.txt" - {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, +#line 347 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, +#line 36 "src/lexer-keywords.txt" + {"br_if", TokenType::BrIf, Opcode::BrIf}, {""}, -#line 567 "src/lexer-keywords.txt" - {"quote", TokenType::Quote}, -#line 32 "src/lexer-keywords.txt" - {"block", TokenType::Block, Opcode::Block}, - {""}, {""}, -#line 452 "src/lexer-keywords.txt" - {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, -#line 309 "src/lexer-keywords.txt" - {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, -#line 451 "src/lexer-keywords.txt" - {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, -#line 308 "src/lexer-keywords.txt" - {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, -#line 399 "src/lexer-keywords.txt" +#line 408 "src/lexer-keywords.txt" {"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU}, -#line 262 "src/lexer-keywords.txt" +#line 271 "src/lexer-keywords.txt" {"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU}, -#line 242 "src/lexer-keywords.txt" - {"i16x8", TokenType::I16X8}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 357 "src/lexer-keywords.txt" - {"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU}, -#line 348 "src/lexer-keywords.txt" - {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, #line 356 "src/lexer-keywords.txt" - {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, -#line 347 "src/lexer-keywords.txt" {"i32x4.min_s", TokenType::Binary, Opcode::I32X4MinS}, -#line 605 "src/lexer-keywords.txt" - {"v128.or", TokenType::Binary, Opcode::V128Or}, - {""}, -#line 563 "src/lexer-keywords.txt" - {"output", TokenType::Output}, {""}, {""}, -#line 562 "src/lexer-keywords.txt" - {"offset", TokenType::Offset}, +#line 240 "src/lexer-keywords.txt" + {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, {""}, -#line 597 "src/lexer-keywords.txt" - {"type", TokenType::Type}, -#line 595 "src/lexer-keywords.txt" - {"try", TokenType::Try, Opcode::Try}, +#line 203 "src/lexer-keywords.txt" + {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, +#line 223 "src/lexer-keywords.txt" + {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 585 "src/lexer-keywords.txt" - {"table.fill", TokenType::TableFill, Opcode::TableFill}, - {""}, -#line 486 "src/lexer-keywords.txt" - {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, -#line 480 "src/lexer-keywords.txt" - {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, -#line 34 "src/lexer-keywords.txt" - {"br_on_non_null", TokenType::BrOnNonNull, Opcode::BrOnNonNull}, - {""}, {""}, {""}, {""}, -#line 207 "src/lexer-keywords.txt" - {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, -#line 422 "src/lexer-keywords.txt" - {"i64.extend32_s", TokenType::Unary, Opcode::I64Extend32S}, -#line 211 "src/lexer-keywords.txt" - {"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU}, - {""}, -#line 206 "src/lexer-keywords.txt" - {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, -#line 42 "src/lexer-keywords.txt" - {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, -#line 210 "src/lexer-keywords.txt" - {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, -#line 338 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, -#line 209 "src/lexer-keywords.txt" - {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, - {""}, -#line 215 "src/lexer-keywords.txt" - {"i16x8.lt_u", TokenType::Compare, Opcode::I16X8LtU}, -#line 337 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, -#line 208 "src/lexer-keywords.txt" - {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, - {""}, -#line 214 "src/lexer-keywords.txt" - {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, +#line 550 "src/lexer-keywords.txt" + {"invoke", TokenType::Invoke}, {""}, {""}, -#line 72 "src/lexer-keywords.txt" - {"f32.demote_f64", TokenType::Convert, Opcode::F32DemoteF64}, - {""}, -#line 166 "src/lexer-keywords.txt" - {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, - {""}, -#line 119 "src/lexer-keywords.txt" +#line 124 "src/lexer-keywords.txt" {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, -#line 609 "src/lexer-keywords.txt" - {"v128.store", TokenType::Store, Opcode::V128Store}, -#line 539 "src/lexer-keywords.txt" - {"input", TokenType::Input}, - {""}, {""}, -#line 576 "src/lexer-keywords.txt" - {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, {""}, -#line 358 "src/lexer-keywords.txt" +#line 367 "src/lexer-keywords.txt" {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, -#line 510 "src/lexer-keywords.txt" - {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, -#line 33 "src/lexer-keywords.txt" - {"br_if", TokenType::BrIf, Opcode::BrIf}, -#line 514 "src/lexer-keywords.txt" - {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, - {""}, -#line 509 "src/lexer-keywords.txt" - {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, - {""}, -#line 513 "src/lexer-keywords.txt" - {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, - {""}, -#line 512 "src/lexer-keywords.txt" - {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, -#line 538 "src/lexer-keywords.txt" - {"import", TokenType::Import}, -#line 516 "src/lexer-keywords.txt" - {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, - {""}, -#line 511 "src/lexer-keywords.txt" - {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, - {""}, -#line 515 "src/lexer-keywords.txt" - {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, - {""}, {""}, {""}, {""}, {""}, -#line 603 "src/lexer-keywords.txt" - {"v128.load", TokenType::Load, Opcode::V128Load}, -#line 160 "src/lexer-keywords.txt" - {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, - {""}, {""}, -#line 223 "src/lexer-keywords.txt" - {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, {""}, -#line 225 "src/lexer-keywords.txt" - {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, -#line 425 "src/lexer-keywords.txt" - {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, -#line 468 "src/lexer-keywords.txt" - {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, -#line 424 "src/lexer-keywords.txt" - {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, +#line 470 "src/lexer-keywords.txt" + {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, +#line 326 "src/lexer-keywords.txt" + {"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U}, {""}, {""}, -#line 150 "src/lexer-keywords.txt" - {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, -#line 88 "src/lexer-keywords.txt" - {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, -#line 213 "src/lexer-keywords.txt" - {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, - {""}, -#line 212 "src/lexer-keywords.txt" - {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, -#line 616 "src/lexer-keywords.txt" - {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, -#line 408 "src/lexer-keywords.txt" - {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, -#line 271 "src/lexer-keywords.txt" - {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, +#line 211 "src/lexer-keywords.txt" + {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, +#line 513 "src/lexer-keywords.txt" + {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, {""}, {""}, {""}, -#line 186 "src/lexer-keywords.txt" - {"f64x2", TokenType::F64X2}, - {""}, {""}, -#line 615 "src/lexer-keywords.txt" - {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, - {""}, -#line 604 "src/lexer-keywords.txt" - {"v128.not", TokenType::Unary, Opcode::V128Not}, -#line 623 "src/lexer-keywords.txt" - {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, -#line 497 "src/lexer-keywords.txt" - {"i64x2", TokenType::I64X2}, -#line 120 "src/lexer-keywords.txt" - {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, +#line 136 "src/lexer-keywords.txt" + {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, +#line 74 "src/lexer-keywords.txt" + {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, + {""}, {""}, {""}, +#line 524 "src/lexer-keywords.txt" + {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, {""}, -#line 523 "src/lexer-keywords.txt" - {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, +#line 520 "src/lexer-keywords.txt" + {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, {""}, -#line 525 "src/lexer-keywords.txt" - {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, -#line 46 "src/lexer-keywords.txt" - {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 453 "src/lexer-keywords.txt" - {"i64.store16", TokenType::Store, Opcode::I64Store16}, -#line 310 "src/lexer-keywords.txt" - {"i32.store16", TokenType::Store, Opcode::I32Store16}, +#line 526 "src/lexer-keywords.txt" + {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, {""}, -#line 189 "src/lexer-keywords.txt" +#line 522 "src/lexer-keywords.txt" + {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, + {""}, {""}, {""}, {""}, +#line 512 "src/lexer-keywords.txt" + {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 195 "src/lexer-keywords.txt" {"funcref", Type::FuncRef}, -#line 198 "src/lexer-keywords.txt" - {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, {""}, {""}, {""}, +#line 433 "src/lexer-keywords.txt" + {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, #line 602 "src/lexer-keywords.txt" - {"v128.const", TokenType::Const, Opcode::V128Const}, + {"sub", TokenType::Sub}, +#line 236 "src/lexer-keywords.txt" + {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, + {""}, {""}, {""}, {""}, +#line 357 "src/lexer-keywords.txt" + {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, + {""}, {""}, {""}, {""}, +#line 166 "src/lexer-keywords.txt" + {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, +#line 224 "src/lexer-keywords.txt" + {"i16x8.max_u", TokenType::Binary, Opcode::I16X8MaxU}, {""}, -#line 611 "src/lexer-keywords.txt" - {"v128.xor", TokenType::Binary, Opcode::V128Xor}, - {""}, {""}, {""}, {""}, {""}, -#line 176 "src/lexer-keywords.txt" - {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, +#line 599 "src/lexer-keywords.txt" + {"start", TokenType::Start}, + {""}, {""}, +#line 44 "src/lexer-keywords.txt" + {"catch", TokenType::Catch, Opcode::Catch}, +#line 624 "src/lexer-keywords.txt" + {"v128.or", TokenType::Binary, Opcode::V128Or}, +#line 179 "src/lexer-keywords.txt" + {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, {""}, -#line 177 "src/lexer-keywords.txt" - {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, +#line 400 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, {""}, -#line 220 "src/lexer-keywords.txt" - {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, +#line 57 "src/lexer-keywords.txt" + {"elem", TokenType::Elem}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 212 "src/lexer-keywords.txt" + {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, +#line 473 "src/lexer-keywords.txt" + {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, +#line 329 "src/lexer-keywords.txt" + {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, + {""}, {""}, +#line 64 "src/lexer-keywords.txt" + {"externref", Type::ExternRef}, {""}, -#line 378 "src/lexer-keywords.txt" - {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, -#line 249 "src/lexer-keywords.txt" - {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, - {""}, {""}, {""}, -#line 41 "src/lexer-keywords.txt" - {"catch", TokenType::Catch, Opcode::Catch}, +#line 130 "src/lexer-keywords.txt" + {"f64.abs", TokenType::Unary, Opcode::F64Abs}, +#line 68 "src/lexer-keywords.txt" + {"f32.abs", TokenType::Unary, Opcode::F32Abs}, +#line 617 "src/lexer-keywords.txt" + {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, {""}, {""}, -#line 488 "src/lexer-keywords.txt" - {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, +#line 98 "src/lexer-keywords.txt" + {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, +#line 39 "src/lexer-keywords.txt" + {"br_table", TokenType::BrTable, Opcode::BrTable}, +#line 333 "src/lexer-keywords.txt" + {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, +#line 628 "src/lexer-keywords.txt" + {"v128.store", TokenType::Store, Opcode::V128Store}, +#line 623 "src/lexer-keywords.txt" + {"v128.not", TokenType::Unary, Opcode::V128Not}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 502 "src/lexer-keywords.txt" - {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, +#line 621 "src/lexer-keywords.txt" + {"v128.const", TokenType::Const, Opcode::V128Const}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 434 "src/lexer-keywords.txt" + {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, {""}, -#line 600 "src/lexer-keywords.txt" - {"v128.and", TokenType::Binary, Opcode::V128And}, - {""}, {""}, {""}, {""}, -#line 536 "src/lexer-keywords.txt" - {"i8x16", TokenType::I8X16}, - {""}, {""}, -#line 54 "src/lexer-keywords.txt" - {"elem", TokenType::Elem}, +#line 579 "src/lexer-keywords.txt" + {"output", TokenType::Output}, +#line 498 "src/lexer-keywords.txt" + {"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS}, {""}, -#line 59 "src/lexer-keywords.txt" - {"externref", Type::ExternRef}, - {""}, {""}, -#line 599 "src/lexer-keywords.txt" - {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, - {""}, {""}, -#line 386 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, -#line 256 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, +#line 543 "src/lexer-keywords.txt" + {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, +#line 546 "src/lexer-keywords.txt" + {"i8x16", TokenType::I8X16}, +#line 510 "src/lexer-keywords.txt" + {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, +#line 527 "src/lexer-keywords.txt" + {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, +#line 642 "src/lexer-keywords.txt" + {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, +#line 241 "src/lexer-keywords.txt" + {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, {""}, -#line 228 "src/lexer-keywords.txt" - {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, - {""}, {""}, -#line 161 "src/lexer-keywords.txt" - {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, - {""}, {""}, -#line 470 "src/lexer-keywords.txt" - {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, -#line 174 "src/lexer-keywords.txt" - {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, +#line 204 "src/lexer-keywords.txt" + {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, +#line 24 "src/lexer-keywords.txt" + {"after", TokenType::After}, {""}, {""}, -#line 469 "src/lexer-keywords.txt" - {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, +#line 118 "src/lexer-keywords.txt" + {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 38 "src/lexer-keywords.txt" - {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, - {""}, -#line 528 "src/lexer-keywords.txt" - {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, - {""}, {""}, {""}, {""}, {""}, -#line 167 "src/lexer-keywords.txt" - {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, -#line 385 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, -#line 255 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 226 "src/lexer-keywords.txt" - {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, -#line 199 "src/lexer-keywords.txt" - {"i16x8.all_true", TokenType::Unary, Opcode::I16X8AllTrue}, +#line 517 "src/lexer-keywords.txt" + {"i8x16.extract_lane_s", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneS}, {""}, {""}, -#line 21 "src/lexer-keywords.txt" - {"after", TokenType::After}, -#line 554 "src/lexer-keywords.txt" - {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, -#line 175 "src/lexer-keywords.txt" - {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, -#line 382 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, -#line 252 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, -#line 401 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, -#line 264 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, -#line 234 "src/lexer-keywords.txt" - {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, - {""}, {""}, {""}, -#line 233 "src/lexer-keywords.txt" - {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, +#line 630 "src/lexer-keywords.txt" + {"v128.xor", TokenType::Binary, Opcode::V128Xor}, {""}, {""}, {""}, -#line 383 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, -#line 253 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, -#line 349 "src/lexer-keywords.txt" - {"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S}, +#line 604 "src/lexer-keywords.txt" + {"table.fill", TokenType::TableFill, Opcode::TableFill}, {""}, -#line 391 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, - {""}, {""}, {""}, {""}, {""}, -#line 527 "src/lexer-keywords.txt" - {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, -#line 503 "src/lexer-keywords.txt" - {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, - {""}, {""}, {""}, {""}, -#line 582 "src/lexer-keywords.txt" - {"start", TokenType::Start}, +#line 629 "src/lexer-keywords.txt" + {"v128", Type::V128}, +#line 137 "src/lexer-keywords.txt" + {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, +#line 75 "src/lexer-keywords.txt" + {"f32.convert_i64_u", TokenType::Convert, Opcode::F32ConvertI64U}, {""}, -#line 125 "src/lexer-keywords.txt" - {"f64.abs", TokenType::Unary, Opcode::F64Abs}, -#line 63 "src/lexer-keywords.txt" - {"f32.abs", TokenType::Unary, Opcode::F32Abs}, +#line 577 "src/lexer-keywords.txt" + {"nullref", Type::NullRef}, + {""}, {""}, {""}, {""}, +#line 622 "src/lexer-keywords.txt" + {"v128.load", TokenType::Load, Opcode::V128Load}, + {""}, {""}, {""}, {""}, {""}, +#line 126 "src/lexer-keywords.txt" + {"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub}, {""}, -#line 534 "src/lexer-keywords.txt" - {"i8x16.sub_sat_u", TokenType::Binary, Opcode::I8X16SubSatU}, +#line 368 "src/lexer-keywords.txt" + {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, {""}, {""}, {""}, -#line 533 "src/lexer-keywords.txt" - {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, -#line 621 "src/lexer-keywords.txt" - {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, +#line 41 "src/lexer-keywords.txt" + {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 121 "src/lexer-keywords.txt" - {"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub}, +#line 539 "src/lexer-keywords.txt" + {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, + {""}, +#line 410 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, +#line 273 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, {""}, {""}, -#line 93 "src/lexer-keywords.txt" - {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, +#line 499 "src/lexer-keywords.txt" + {"i64x2.shr_u", TokenType::Binary, Opcode::I64X2ShrU}, +#line 172 "src/lexer-keywords.txt" + {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, +#line 618 "src/lexer-keywords.txt" + {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, {""}, -#line 613 "src/lexer-keywords.txt" - {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, -#line 565 "src/lexer-keywords.txt" - {"param", TokenType::Param}, -#line 359 "src/lexer-keywords.txt" - {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, -#line 98 "src/lexer-keywords.txt" - {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, -#line 607 "src/lexer-keywords.txt" - {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, -#line 324 "src/lexer-keywords.txt" - {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, -#line 36 "src/lexer-keywords.txt" - {"br_table", TokenType::BrTable, Opcode::BrTable}, - {""}, {""}, {""}, -#line 197 "src/lexer-keywords.txt" - {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, +#line 478 "src/lexer-keywords.txt" + {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, +#line 528 "src/lexer-keywords.txt" + {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, + {""}, {""}, {""}, {""}, +#line 237 "src/lexer-keywords.txt" + {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, +#line 49 "src/lexer-keywords.txt" + {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, {""}, {""}, {""}, -#line 196 "src/lexer-keywords.txt" - {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, - {""}, -#line 113 "src/lexer-keywords.txt" - {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, -#line 31 "src/lexer-keywords.txt" - {"binary", TokenType::Bin}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 465 "src/lexer-keywords.txt" +#line 619 "src/lexer-keywords.txt" + {"v128.and", TokenType::Binary, Opcode::V128And}, +#line 387 "src/lexer-keywords.txt" + {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, +#line 258 "src/lexer-keywords.txt" + {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, + {""}, {""}, {""}, {""}, {""}, +#line 518 "src/lexer-keywords.txt" + {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, + {""}, {""}, {""}, {""}, {""}, +#line 474 "src/lexer-keywords.txt" {"i64.trunc_sat_f64_u", TokenType::Convert, Opcode::I64TruncSatF64U}, -#line 321 "src/lexer-keywords.txt" +#line 330 "src/lexer-keywords.txt" {"i32.trunc_sat_f64_u", TokenType::Convert, Opcode::I32TruncSatF64U}, -#line 387 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XchgU}, -#line 257 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU}, -#line 464 "src/lexer-keywords.txt" - {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, -#line 320 "src/lexer-keywords.txt" - {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, + {""}, {""}, {""}, +#line 420 "src/lexer-keywords.txt" + {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 549 "src/lexer-keywords.txt" + {"input", TokenType::Input}, +#line 376 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f32x4_s", TokenType::Unary, Opcode::I32X4TruncSatF32X4S}, {""}, {""}, -#line 618 "src/lexer-keywords.txt" +#line 598 "src/lexer-keywords.txt" + {"shared", TokenType::Shared}, + {""}, {""}, {""}, {""}, +#line 548 "src/lexer-keywords.txt" + {"import", TokenType::Import}, + {""}, {""}, {""}, +#line 117 "src/lexer-keywords.txt" + {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, + {""}, +#line 382 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, + {""}, {""}, {""}, +#line 637 "src/lexer-keywords.txt" {"v128.load32_lane", TokenType::SimdLoadLane, Opcode::V128Load32Lane}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 501 "src/lexer-keywords.txt" - {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, -#line 379 "src/lexer-keywords.txt" +#line 388 "src/lexer-keywords.txt" {"i64.atomic.load32_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad32U}, +#line 632 "src/lexer-keywords.txt" + {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, {""}, -#line 620 "src/lexer-keywords.txt" - {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, -#line 500 "src/lexer-keywords.txt" - {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, +#line 46 "src/lexer-keywords.txt" + {"catch_ref", TokenType::CatchRef}, +#line 29 "src/lexer-keywords.txt" + {"assert_return", TokenType::AssertReturn}, +#line 103 "src/lexer-keywords.txt" + {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, +#line 544 "src/lexer-keywords.txt" + {"i8x16.sub_sat_u", TokenType::Binary, Opcode::I8X16SubSatU}, {""}, -#line 388 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XorU}, -#line 258 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XorU}, +#line 511 "src/lexer-keywords.txt" + {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, +#line 639 "src/lexer-keywords.txt" + {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, {""}, -#line 194 "src/lexer-keywords.txt" - {"global", TokenType::Global}, -#line 217 "src/lexer-keywords.txt" - {"i16x8.max_u", TokenType::Binary, Opcode::I16X8MaxU}, +#line 155 "src/lexer-keywords.txt" + {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, +#line 93 "src/lexer-keywords.txt" + {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, {""}, -#line 216 "src/lexer-keywords.txt" - {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, - {""}, {""}, {""}, {""}, -#line 490 "src/lexer-keywords.txt" - {"i64x2.shr_u", TokenType::Binary, Opcode::I64X2ShrU}, +#line 238 "src/lexer-keywords.txt" + {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, {""}, -#line 489 "src/lexer-keywords.txt" - {"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS}, +#line 575 "src/lexer-keywords.txt" + {"nullfuncref", Type::NullFuncRef}, {""}, -#line 551 "src/lexer-keywords.txt" - {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, +#line 200 "src/lexer-keywords.txt" + {"global", TokenType::Global}, {""}, {""}, {""}, {""}, -#line 328 "src/lexer-keywords.txt" - {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, -#line 43 "src/lexer-keywords.txt" - {"catch_ref", TokenType::CatchRef}, - {""}, {""}, {""}, -#line 584 "src/lexer-keywords.txt" - {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, - {""}, -#line 229 "src/lexer-keywords.txt" - {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, - {""}, {""}, {""}, {""}, {""}, -#line 518 "src/lexer-keywords.txt" - {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, - {""}, -#line 517 "src/lexer-keywords.txt" - {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, +#line 125 "src/lexer-keywords.txt" + {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, +#line 635 "src/lexer-keywords.txt" + {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, {""}, {""}, -#line 581 "src/lexer-keywords.txt" - {"shared", TokenType::Shared}, -#line 132 "src/lexer-keywords.txt" - {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, -#line 70 "src/lexer-keywords.txt" - {"f32.convert_i64_u", TokenType::Convert, Opcode::F32ConvertI64U}, +#line 254 "src/lexer-keywords.txt" + {"i31", Type::I31Ref, TokenType::I31}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 616 "src/lexer-keywords.txt" + {"type", TokenType::Type}, + {""}, {""}, {""}, +#line 634 "src/lexer-keywords.txt" + {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, + {""}, {""}, {""}, +#line 626 "src/lexer-keywords.txt" + {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 198 "src/lexer-keywords.txt" + {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, +#line 392 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, +#line 262 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, {""}, {""}, -#line 131 "src/lexer-keywords.txt" - {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, -#line 69 "src/lexer-keywords.txt" - {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, - {""}, {""}, {""}, {""}, {""}, +#line 383 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, +#line 199 "src/lexer-keywords.txt" + {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, +#line 255 "src/lexer-keywords.txt" + {"i31ref", Type::I31Ref}, #line 62 "src/lexer-keywords.txt" - {"export", TokenType::Export}, - {""}, {""}, {""}, {""}, {""}, -#line 529 "src/lexer-keywords.txt" - {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, -#line 555 "src/lexer-keywords.txt" - {"memory", TokenType::Memory}, -#line 598 "src/lexer-keywords.txt" - {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, + {"eqref", Type::EqRef}, + {""}, {""}, {""}, {""}, +#line 42 "src/lexer-keywords.txt" + {"call_ref", TokenType::CallRef, Opcode::CallRef}, + {""}, {""}, {""}, {""}, +#line 479 "src/lexer-keywords.txt" + {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, +#line 540 "src/lexer-keywords.txt" + {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 179 "src/lexer-keywords.txt" +#line 184 "src/lexer-keywords.txt" {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, -#line 112 "src/lexer-keywords.txt" - {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, -#line 374 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, - {""}, -#line 373 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, {""}, -#line 192 "src/lexer-keywords.txt" - {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, -#line 491 "src/lexer-keywords.txt" +#line 500 "src/lexer-keywords.txt" {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, -#line 193 "src/lexer-keywords.txt" - {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 411 "src/lexer-keywords.txt" - {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, - {""}, {""}, -#line 61 "src/lexer-keywords.txt" - {"exnref", Type::ExnRef}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 614 "src/lexer-keywords.txt" - {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, -#line 622 "src/lexer-keywords.txt" - {"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane}, -#line 180 "src/lexer-keywords.txt" - {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, -#line 593 "src/lexer-keywords.txt" - {"throw", TokenType::Throw, Opcode::Throw}, -#line 608 "src/lexer-keywords.txt" - {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, - {""}, {""}, {""}, {""}, -#line 39 "src/lexer-keywords.txt" - {"call_ref", TokenType::CallRef, Opcode::CallRef}, - {""}, {""}, -#line 553 "src/lexer-keywords.txt" - {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, -#line 418 "src/lexer-keywords.txt" - {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, -#line 280 "src/lexer-keywords.txt" - {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, -#line 417 "src/lexer-keywords.txt" - {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, -#line 279 "src/lexer-keywords.txt" - {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, {""}, {""}, {""}, {""}, -#line 420 "src/lexer-keywords.txt" - {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, -#line 282 "src/lexer-keywords.txt" - {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, - {""}, {""}, -#line 594 "src/lexer-keywords.txt" - {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, +#line 462 "src/lexer-keywords.txt" + {"i64.store16", TokenType::Store, Opcode::I64Store16}, +#line 319 "src/lexer-keywords.txt" + {"i32.store16", TokenType::Store, Opcode::I32Store16}, {""}, -#line 205 "src/lexer-keywords.txt" - {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, +#line 207 "src/lexer-keywords.txt" + {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, {""}, -#line 204 "src/lexer-keywords.txt" - {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, - {""}, {""}, -#line 619 "src/lexer-keywords.txt" - {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, -#line 398 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw8CmpxchgU}, -#line 261 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw8CmpxchgU}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 410 "src/lexer-keywords.txt" - {"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16}, -#line 273 "src/lexer-keywords.txt" - {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, +#line 394 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, +#line 264 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, +#line 134 "src/lexer-keywords.txt" + {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, +#line 72 "src/lexer-keywords.txt" + {"f32.convert_i32_s", TokenType::Convert, Opcode::F32ConvertI32S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 596 "src/lexer-keywords.txt" - {"try_table", TokenType::TryTable, Opcode::TryTable}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 606 "src/lexer-keywords.txt" - {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, - {""}, -#line 508 "src/lexer-keywords.txt" - {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, -#line 368 "src/lexer-keywords.txt" +#line 377 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U}, -#line 507 "src/lexer-keywords.txt" - {"i8x16.extract_lane_s", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneS}, + {""}, {""}, {""}, +#line 562 "src/lexer-keywords.txt" + {"memory.grow", TokenType::MemoryGrow, Opcode::MemoryGrow}, {""}, {""}, -#line 367 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f32x4_s", TokenType::Unary, Opcode::I32X4TruncSatF32X4S}, +#line 66 "src/lexer-keywords.txt" + {"exnref", Type::ExnRef}, + {""}, {""}, {""}, +#line 395 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, +#line 265 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, +#line 391 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, +#line 261 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, +#line 594 "src/lexer-keywords.txt" + {"return_call_ref", TokenType::ReturnCallRef, Opcode::ReturnCallRef}, {""}, {""}, {""}, {""}, -#line 51 "src/lexer-keywords.txt" - {"drop", TokenType::Drop, Opcode::Drop}, +#line 625 "src/lexer-keywords.txt" + {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, {""}, {""}, {""}, -#line 587 "src/lexer-keywords.txt" - {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, +#line 426 "src/lexer-keywords.txt" + {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, +#line 288 "src/lexer-keywords.txt" + {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, {""}, {""}, -#line 575 "src/lexer-keywords.txt" - {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 541 "src/lexer-keywords.txt" + {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, + {""}, {""}, +#line 337 "src/lexer-keywords.txt" + {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, {""}, -#line 231 "src/lexer-keywords.txt" - {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, -#line 219 "src/lexer-keywords.txt" - {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, -#line 230 "src/lexer-keywords.txt" - {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, -#line 218 "src/lexer-keywords.txt" +#line 225 "src/lexer-keywords.txt" {"i16x8.min_s", TokenType::Binary, Opcode::I16X8MinS}, - {""}, {""}, {""}, {""}, {""}, -#line 405 "src/lexer-keywords.txt" +#line 47 "src/lexer-keywords.txt" + {"catch_all_ref", TokenType::CatchAllRef}, + {""}, {""}, {""}, +#line 414 "src/lexer-keywords.txt" {"i64.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmwCmpxchg}, -#line 268 "src/lexer-keywords.txt" +#line 277 "src/lexer-keywords.txt" {"i32.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmwCmpxchg}, - {""}, -#line 123 "src/lexer-keywords.txt" - {"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 640 "src/lexer-keywords.txt" + {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, {""}, {""}, -#line 44 "src/lexer-keywords.txt" - {"catch_all_ref", TokenType::CatchAllRef}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 471 "src/lexer-keywords.txt" + {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, +#line 327 "src/lexer-keywords.txt" + {"i32.trunc_sat_f32_s", TokenType::Convert, Opcode::I32TruncSatF32S}, +#line 239 "src/lexer-keywords.txt" + {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, {""}, -#line 577 "src/lexer-keywords.txt" - {"return_call_ref", TokenType::ReturnCallRef, Opcode::ReturnCallRef}, - {""}, {""}, -#line 531 "src/lexer-keywords.txt" - {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, -#line 520 "src/lexer-keywords.txt" - {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, -#line 530 "src/lexer-keywords.txt" - {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, -#line 519 "src/lexer-keywords.txt" - {"i8x16.min_s", TokenType::Binary, Opcode::I8X16MinS}, - {""}, {""}, {""}, -#line 26 "src/lexer-keywords.txt" - {"assert_return", TokenType::AssertReturn}, -#line 552 "src/lexer-keywords.txt" - {"memory.grow", TokenType::MemoryGrow, Opcode::MemoryGrow}, +#line 397 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XorU}, +#line 267 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XorU}, {""}, {""}, {""}, {""}, -#line 400 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, -#line 263 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8SubU}, +#line 160 "src/lexer-keywords.txt" + {"f64x2.abs", TokenType::Unary, Opcode::F64X2Abs}, +#line 563 "src/lexer-keywords.txt" + {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, +#line 487 "src/lexer-keywords.txt" + {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 200 "src/lexer-keywords.txt" - {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, -#line 232 "src/lexer-keywords.txt" - {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 219 "src/lexer-keywords.txt" + {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, {""}, {""}, {""}, -#line 342 "src/lexer-keywords.txt" - {"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U}, +#line 396 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XchgU}, +#line 266 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU}, {""}, -#line 560 "src/lexer-keywords.txt" - {"nop", TokenType::Nop, Opcode::Nop}, +#line 581 "src/lexer-keywords.txt" + {"param", TokenType::Param}, + {""}, {""}, {""}, {""}, +#line 427 "src/lexer-keywords.txt" + {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, +#line 289 "src/lexer-keywords.txt" + {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, +#line 641 "src/lexer-keywords.txt" + {"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane}, {""}, -#line 341 "src/lexer-keywords.txt" - {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 181 "src/lexer-keywords.txt" - {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, - {""}, {""}, -#line 155 "src/lexer-keywords.txt" - {"f64x2.abs", TokenType::Unary, Opcode::F64X2Abs}, +#line 128 "src/lexer-keywords.txt" + {"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero}, {""}, {""}, {""}, -#line 492 "src/lexer-keywords.txt" - {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, -#line 158 "src/lexer-keywords.txt" - {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, - {""}, -#line 478 "src/lexer-keywords.txt" - {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, -#line 504 "src/lexer-keywords.txt" - {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, -#line 532 "src/lexer-keywords.txt" - {"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 173 "src/lexer-keywords.txt" +#line 178 "src/lexer-keywords.txt" {"f64x2.pmin", TokenType::Binary, Opcode::F64X2PMin}, - {""}, {""}, -#line 546 "src/lexer-keywords.txt" - {"loop", TokenType::Loop, Opcode::Loop}, +#line 226 "src/lexer-keywords.txt" + {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, {""}, {""}, {""}, {""}, {""}, -#line 463 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, -#line 319 "src/lexer-keywords.txt" - {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, -#line 135 "src/lexer-keywords.txt" - {"f64.eq", TokenType::Compare, Opcode::F64Eq}, -#line 74 "src/lexer-keywords.txt" - {"f32.eq", TokenType::Compare, Opcode::F32Eq}, -#line 462 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, -#line 318 "src/lexer-keywords.txt" - {"i32.trunc_sat_f32_s", TokenType::Convert, Opcode::I32TruncSatF32S}, +#line 615 "src/lexer-keywords.txt" + {"try_table", TokenType::TryTable, Opcode::TryTable}, {""}, {""}, {""}, -#line 419 "src/lexer-keywords.txt" - {"i64.eq", TokenType::Compare, Opcode::I64Eq}, -#line 281 "src/lexer-keywords.txt" - {"i32.eq", TokenType::Compare, Opcode::I32Eq}, -#line 327 "src/lexer-keywords.txt" - {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, - {""}, {""}, {""}, {""}, -#line 444 "src/lexer-keywords.txt" - {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, -#line 301 "src/lexer-keywords.txt" - {"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt}, +#line 358 "src/lexer-keywords.txt" + {"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S}, +#line 514 "src/lexer-keywords.txt" + {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 135 "src/lexer-keywords.txt" + {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, +#line 73 "src/lexer-keywords.txt" + {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 28 "src/lexer-keywords.txt" + {"assert_malformed", TokenType::AssertMalformed}, +#line 186 "src/lexer-keywords.txt" + {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, + {""}, +#line 501 "src/lexer-keywords.txt" + {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, {""}, {""}, -#line 384 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, -#line 254 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw16CmpxchgU}, +#line 202 "src/lexer-keywords.txt" + {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 220 "src/lexer-keywords.txt" + {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 99 "src/lexer-keywords.txt" - {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 329 "src/lexer-keywords.txt" - {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, - {""}, {""}, {""}, {""}, {""}, -#line 484 "src/lexer-keywords.txt" - {"i64x2.extend_low_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendLowI32X4U}, +#line 529 "src/lexer-keywords.txt" + {"i8x16.min_s", TokenType::Binary, Opcode::I8X16MinS}, +#line 560 "src/lexer-keywords.txt" + {"memory.copy", TokenType::MemoryCopy, Opcode::MemoryCopy}, + {""}, {""}, {""}, {""}, +#line 638 "src/lexer-keywords.txt" + {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, {""}, -#line 482 "src/lexer-keywords.txt" - {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, -#line 524 "src/lexer-keywords.txt" - {"i8x16.popcnt", TokenType::Unary, Opcode::I8X16Popcnt}, +#line 633 "src/lexer-keywords.txt" + {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, +#line 643 "src/lexer-keywords.txt" + {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, +#line 61 "src/lexer-keywords.txt" + {"eq", Type::EqRef, TokenType::Eq}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 542 "src/lexer-keywords.txt" + {"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat}, {""}, {""}, -#line 612 "src/lexer-keywords.txt" - {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, +#line 472 "src/lexer-keywords.txt" + {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, +#line 328 "src/lexer-keywords.txt" + {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 130 "src/lexer-keywords.txt" - {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, -#line 68 "src/lexer-keywords.txt" - {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, - {""}, {""}, -#line 129 "src/lexer-keywords.txt" - {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, -#line 67 "src/lexer-keywords.txt" - {"f32.convert_i32_s", TokenType::Convert, Opcode::F32ConvertI32S}, +#line 613 "src/lexer-keywords.txt" + {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, {""}, -#line 370 "src/lexer-keywords.txt" - {"i32x4.extend_high_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendHighI16X8U}, +#line 22 "src/lexer-keywords.txt" + {"array", Type::ArrayRef, TokenType::Array}, + {""}, {""}, {""}, {""}, +#line 67 "src/lexer-keywords.txt" + {"export", TokenType::Export}, {""}, -#line 369 "src/lexer-keywords.txt" - {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 172 "src/lexer-keywords.txt" +#line 177 "src/lexer-keywords.txt" {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, - {""}, {""}, {""}, {""}, -#line 617 "src/lexer-keywords.txt" - {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, {""}, -#line 624 "src/lexer-keywords.txt" - {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, +#line 627 "src/lexer-keywords.txt" + {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, +#line 242 "src/lexer-keywords.txt" + {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 163 "src/lexer-keywords.txt" + {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, {""}, {""}, -#line 361 "src/lexer-keywords.txt" - {"i32x4.extadd_pairwise_i16x8_u", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8U}, +#line 407 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw8CmpxchgU}, +#line 270 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw8CmpxchgU}, + {""}, {""}, {""}, +#line 530 "src/lexer-keywords.txt" + {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 54 "src/lexer-keywords.txt" + {"drop", TokenType::Drop, Opcode::Drop}, {""}, -#line 360 "src/lexer-keywords.txt" - {"i32x4.extadd_pairwise_i16x8_s", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8S}, - {""}, {""}, -#line 25 "src/lexer-keywords.txt" - {"assert_malformed", TokenType::AssertMalformed}, +#line 491 "src/lexer-keywords.txt" + {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, +#line 185 "src/lexer-keywords.txt" + {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, {""}, {""}, {""}, -#line 53 "src/lexer-keywords.txt" - {"elem.drop", TokenType::ElemDrop, Opcode::ElemDrop}, +#line 534 "src/lexer-keywords.txt" + {"i8x16.popcnt", TokenType::Unary, Opcode::I8X16Popcnt}, +#line 20 "src/lexer-keywords.txt" + {"any", Type::AnyRef, TokenType::Any}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 495 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, -#line 526 "src/lexer-keywords.txt" - {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, -#line 493 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, - {""}, {""}, {""}, {""}, {""}, -#line 372 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, {""}, -#line 371 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 365 "src/lexer-keywords.txt" - {"i32x4.extmul_high_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8U}, +#line 336 "src/lexer-keywords.txt" + {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, {""}, -#line 363 "src/lexer-keywords.txt" - {"i32x4.extmul_high_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8S}, +#line 502 "src/lexer-keywords.txt" + {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, +#line 509 "src/lexer-keywords.txt" + {"i8x16.abs", TokenType::Unary, Opcode::I8X16Abs}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 149 "src/lexer-keywords.txt" - {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, - {""}, {""}, -#line 323 "src/lexer-keywords.txt" - {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, - {""}, {""}, {""}, {""}, -#line 625 "src/lexer-keywords.txt" - {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, +#line 409 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, +#line 272 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8SubU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 134 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 493 "src/lexer-keywords.txt" + {"i64x2.extend_low_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendLowI32X4U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 139 "src/lexer-keywords.txt" {"f64.div", TokenType::Binary, Opcode::F64Div}, -#line 73 "src/lexer-keywords.txt" +#line 78 "src/lexer-keywords.txt" {"f32.div", TokenType::Binary, Opcode::F32Div}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 235 "src/lexer-keywords.txt" - {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 195 "src/lexer-keywords.txt" - {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, - {""}, -#line 564 "src/lexer-keywords.txt" - {"pagesize", TokenType::PageSize}, +#line 101 "src/lexer-keywords.txt" + {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, {""}, {""}, -#line 97 "src/lexer-keywords.txt" - {"f32x4.convert_i32x4_u", TokenType::Unary, Opcode::F32X4ConvertI32X4U}, +#line 504 "src/lexer-keywords.txt" + {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 545 "src/lexer-keywords.txt" + {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, +#line 228 "src/lexer-keywords.txt" + {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, + {""}, {""}, {""}, {""}, {""}, +#line 556 "src/lexer-keywords.txt" + {"loop", TokenType::Loop, Opcode::Loop}, +#line 453 "src/lexer-keywords.txt" + {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, +#line 310 "src/lexer-keywords.txt" + {"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 393 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, +#line 263 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw16CmpxchgU}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 138 "src/lexer-keywords.txt" + {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, +#line 76 "src/lexer-keywords.txt" + {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 96 "src/lexer-keywords.txt" - {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, +#line 102 "src/lexer-keywords.txt" + {"f32x4.convert_i32x4_u", TokenType::Unary, Opcode::F32X4ConvertI32X4U}, + {""}, {""}, {""}, {""}, +#line 612 "src/lexer-keywords.txt" + {"throw", TokenType::Throw, Opcode::Throw}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 229 "src/lexer-keywords.txt" + {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 419 "src/lexer-keywords.txt" + {"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16}, +#line 282 "src/lexer-keywords.txt" + {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 56 "src/lexer-keywords.txt" + {"elem.drop", TokenType::ElemDrop, Opcode::ElemDrop}, {""}, {""}, -#line 364 "src/lexer-keywords.txt" - {"i32x4.extmul_low_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8U}, +#line 209 "src/lexer-keywords.txt" + {"i16x8.relaxed_dot_i8x16_i7x16_s", TokenType::Binary, Opcode::I16X8DotI8X16I7X16S}, {""}, -#line 362 "src/lexer-keywords.txt" - {"i32x4.extmul_low_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8S}, +#line 606 "src/lexer-keywords.txt" + {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 133 "src/lexer-keywords.txt" - {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, -#line 71 "src/lexer-keywords.txt" - {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, -#line 535 "src/lexer-keywords.txt" - {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, +#line 592 "src/lexer-keywords.txt" + {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, {""}, {""}, -#line 499 "src/lexer-keywords.txt" - {"i8x16.abs", TokenType::Unary, Opcode::I8X16Abs}, +#line 350 "src/lexer-keywords.txt" + {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, + {""}, {""}, {""}, +#line 252 "src/lexer-keywords.txt" + {"i16x8.extend_low_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendLowI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 429 "src/lexer-keywords.txt" + {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, +#line 291 "src/lexer-keywords.txt" + {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 245 "src/lexer-keywords.txt" + {"i16x8.extmul_low_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 30 "src/lexer-keywords.txt" + {"assert_trap", TokenType::AssertTrap}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 644 "src/lexer-keywords.txt" + {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, {""}, {""}, -#line 227 "src/lexer-keywords.txt" +#line 636 "src/lexer-keywords.txt" + {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, + {""}, +#line 631 "src/lexer-keywords.txt" + {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 157 "src/lexer-keywords.txt" + {"f64.sub", TokenType::Binary, Opcode::F64Sub}, +#line 95 "src/lexer-keywords.txt" + {"f32.sub", TokenType::Binary, Opcode::F32Sub}, +#line 466 "src/lexer-keywords.txt" + {"i64.sub", TokenType::Binary, Opcode::I64Sub}, +#line 322 "src/lexer-keywords.txt" + {"i32.sub", TokenType::Binary, Opcode::I32Sub}, +#line 253 "src/lexer-keywords.txt" + {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, + {""}, {""}, {""}, {""}, {""}, +#line 573 "src/lexer-keywords.txt" + {"nop", TokenType::Nop, Opcode::Nop}, + {""}, {""}, {""}, +#line 380 "src/lexer-keywords.txt" + {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, + {""}, {""}, +#line 234 "src/lexer-keywords.txt" {"i16x8.relaxed_q15mulr_s", TokenType::Binary, Opcode::I16X8RelaxedQ15mulrS}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 202 "src/lexer-keywords.txt" - {"i16x8.relaxed_dot_i8x16_i7x16_s", TokenType::Binary, Opcode::I16X8DotI8X16I7X16S}, +#line 247 "src/lexer-keywords.txt" + {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 371 "src/lexer-keywords.txt" + {"i32x4.extmul_low_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8S}, + {""}, {""}, {""}, {""}, +#line 536 "src/lexer-keywords.txt" + {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, +#line 490 "src/lexer-keywords.txt" + {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, + {""}, {""}, {""}, {""}, {""}, +#line 378 "src/lexer-keywords.txt" + {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 153 "src/lexer-keywords.txt" + {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, +#line 25 "src/lexer-keywords.txt" + {"assert_exception", TokenType::AssertException}, + {""}, {""}, {""}, +#line 351 "src/lexer-keywords.txt" + {"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 381 "src/lexer-keywords.txt" + {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, + {""}, +#line 372 "src/lexer-keywords.txt" + {"i32x4.extmul_high_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 23 "src/lexer-keywords.txt" + {"arrayref", Type::ArrayRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 445 "src/lexer-keywords.txt" - {"i64.reinterpret_f64", TokenType::Convert, Opcode::I64ReinterpretF64}, +#line 373 "src/lexer-keywords.txt" + {"i32x4.extmul_low_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 379 "src/lexer-keywords.txt" + {"i32x4.extend_high_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendHighI16X8U}, {""}, {""}, {""}, -#line 246 "src/lexer-keywords.txt" - {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, - {""}, -#line 245 "src/lexer-keywords.txt" - {"i16x8.extend_low_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendLowI8X16S}, +#line 208 "src/lexer-keywords.txt" + {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 21 "src/lexer-keywords.txt" + {"anyref", Type::AnyRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 374 "src/lexer-keywords.txt" + {"i32x4.extmul_high_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8U}, + {""}, {""}, +#line 26 "src/lexer-keywords.txt" + {"assert_exhaustion", TokenType::AssertExhaustion}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 454 "src/lexer-keywords.txt" + {"i64.reinterpret_f64", TokenType::Convert, Opcode::I64ReinterpretF64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 31 "src/lexer-keywords.txt" + {"assert_unlinkable", TokenType::AssertUnlinkable}, +#line 332 "src/lexer-keywords.txt" + {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 222 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, - {""}, -#line 221 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, - {""}, {""}, -#line 240 "src/lexer-keywords.txt" - {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, - {""}, -#line 238 "src/lexer-keywords.txt" - {"i16x8.extmul_low_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 492 "src/lexer-keywords.txt" + {"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S}, {""}, {""}, {""}, -#line 550 "src/lexer-keywords.txt" - {"memory.copy", TokenType::MemoryCopy, Opcode::MemoryCopy}, +#line 557 "src/lexer-keywords.txt" + {"memory.atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 416 "src/lexer-keywords.txt" + {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, +#line 279 "src/lexer-keywords.txt" + {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, +#line 154 "src/lexer-keywords.txt" + {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, + {""}, {""}, {""}, {""}, {""}, +#line 140 "src/lexer-keywords.txt" + {"f64.eq", TokenType::Compare, Opcode::F64Eq}, +#line 79 "src/lexer-keywords.txt" + {"f32.eq", TokenType::Compare, Opcode::F32Eq}, +#line 428 "src/lexer-keywords.txt" + {"i64.eq", TokenType::Compare, Opcode::I64Eq}, +#line 290 "src/lexer-keywords.txt" + {"i32.eq", TokenType::Compare, Opcode::I32Eq}, + {""}, {""}, {""}, +#line 503 "src/lexer-keywords.txt" + {"i64x2.extmul_high_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4S}, + {""}, {""}, {""}, {""}, {""}, +#line 27 "src/lexer-keywords.txt" + {"assert_invalid", TokenType::AssertInvalid}, + {""}, {""}, {""}, +#line 515 "src/lexer-keywords.txt" + {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, + {""}, {""}, +#line 104 "src/lexer-keywords.txt" + {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, {""}, -#line 481 "src/lexer-keywords.txt" - {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 338 "src/lexer-keywords.txt" + {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, -#line 159 "src/lexer-keywords.txt" - {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 472 "src/lexer-keywords.txt" - {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 485 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 494 "src/lexer-keywords.txt" {"i64x2.extend_high_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendHighI32X4U}, - {""}, -#line 483 "src/lexer-keywords.txt" - {"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 20 "src/lexer-keywords.txt" - {"array", Type::Array, TokenType::Array}, - {""}, {""}, -#line 27 "src/lexer-keywords.txt" - {"assert_trap", TokenType::AssertTrap}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 601 "src/lexer-keywords.txt" + {""}, {""}, +#line 620 "src/lexer-keywords.txt" {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 152 "src/lexer-keywords.txt" - {"f64.sub", TokenType::Binary, Opcode::F64Sub}, -#line 90 "src/lexer-keywords.txt" - {"f32.sub", TokenType::Binary, Opcode::F32Sub}, - {""}, {""}, {""}, {""}, {""}, -#line 457 "src/lexer-keywords.txt" - {"i64.sub", TokenType::Binary, Opcode::I64Sub}, -#line 313 "src/lexer-keywords.txt" - {"i32.sub", TokenType::Binary, Opcode::I32Sub}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 148 "src/lexer-keywords.txt" - {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 496 "src/lexer-keywords.txt" +#line 505 "src/lexer-keywords.txt" {"i64x2.extmul_high_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U}, - {""}, -#line 494 "src/lexer-keywords.txt" - {"i64x2.extmul_high_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 369 "src/lexer-keywords.txt" + {"i32x4.extadd_pairwise_i16x8_s", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 580 "src/lexer-keywords.txt" + {"pagesize", TokenType::PageSize}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 370 "src/lexer-keywords.txt" + {"i32x4.extadd_pairwise_i16x8_u", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 22 "src/lexer-keywords.txt" - {"assert_exception", TokenType::AssertException}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 201 "src/lexer-keywords.txt" - {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 23 "src/lexer-keywords.txt" - {"assert_exhaustion", TokenType::AssertExhaustion}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 505 "src/lexer-keywords.txt" - {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, - {""}, -#line 203 "src/lexer-keywords.txt" - {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 506 "src/lexer-keywords.txt" - {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, - {""}, {""}, {""}, {""}, {""}, -#line 549 "src/lexer-keywords.txt" - {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 87 "src/lexer-keywords.txt" - {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, -#line 24 "src/lexer-keywords.txt" - {"assert_invalid", TokenType::AssertInvalid}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 407 "src/lexer-keywords.txt" - {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, -#line 270 "src/lexer-keywords.txt" - {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 547 "src/lexer-keywords.txt" - {"memory.atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 188 "src/lexer-keywords.txt" + {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, +#line 311 "src/lexer-keywords.txt" + {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 244 "src/lexer-keywords.txt" - {"i16x8.extend_high_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendHighI8X16U}, - {""}, -#line 243 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 250 "src/lexer-keywords.txt" {"i16x8.extend_high_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendHighI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 164 "src/lexer-keywords.txt" + {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, {""}, -#line 28 "src/lexer-keywords.txt" - {"assert_unlinkable", TokenType::AssertUnlinkable}, - {""}, {""}, -#line 302 "src/lexer-keywords.txt" - {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, +#line 481 "src/lexer-keywords.txt" + {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, -#line 184 "src/lexer-keywords.txt" - {"f64x2.convert_low_i32x4_u", TokenType::Unary, Opcode::F64X2ConvertLowI32X4U}, - {""}, -#line 183 "src/lexer-keywords.txt" - {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, - {""}, -#line 237 "src/lexer-keywords.txt" - {"i16x8.extadd_pairwise_i8x16_u", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16U}, +#line 559 "src/lexer-keywords.txt" + {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, + {""}, {""}, {""}, {""}, +#line 32 "src/lexer-keywords.txt" + {"atomic.fence", TokenType::AtomicFence, Opcode::AtomicFence}, + {""}, {""}, {""}, {""}, {""}, +#line 246 "src/lexer-keywords.txt" + {"i16x8.extmul_high_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16S}, + {""}, {""}, {""}, {""}, +#line 92 "src/lexer-keywords.txt" + {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, {""}, -#line 236 "src/lexer-keywords.txt" - {"i16x8.extadd_pairwise_i8x16_s", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16S}, +#line 189 "src/lexer-keywords.txt" + {"f64x2.convert_low_i32x4_u", TokenType::Unary, Opcode::F64X2ConvertLowI32X4U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 548 "src/lexer-keywords.txt" +#line 558 "src/lexer-keywords.txt" {"memory.atomic.wait32", TokenType::AtomicWait, Opcode::MemoryAtomicWait32}, - {""}, {""}, {""}, {""}, {""}, -#line 522 "src/lexer-keywords.txt" - {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, - {""}, -#line 521 "src/lexer-keywords.txt" - {"i8x16.narrow_i16x8_s", TokenType::Binary, Opcode::I8X16NarrowI16X8S}, {""}, -#line 224 "src/lexer-keywords.txt" - {"i16x8.q15mulr_sat_s", TokenType::Binary, Opcode::I16X8Q15mulrSatS}, +#line 251 "src/lexer-keywords.txt" + {"i16x8.extend_high_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendHighI8X16U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 29 "src/lexer-keywords.txt" - {"atomic.fence", TokenType::AtomicFence, Opcode::AtomicFence}, - {""}, {""}, {""}, {""}, -#line 241 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 210 "src/lexer-keywords.txt" + {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, + {""}, {""}, {""}, {""}, {""}, +#line 248 "src/lexer-keywords.txt" {"i16x8.extmul_high_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16U}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 231 "src/lexer-keywords.txt" + {"i16x8.q15mulr_sat_s", TokenType::Binary, Opcode::I16X8Q15mulrSatS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 239 "src/lexer-keywords.txt" - {"i16x8.extmul_high_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16S}, +#line 190 "src/lexer-keywords.txt" + {"f64x2.promote_low_f32x4", TokenType::Unary, Opcode::F64X2PromoteLowF32X4}, + {""}, {""}, {""}, +#line 531 "src/lexer-keywords.txt" + {"i8x16.narrow_i16x8_s", TokenType::Binary, Opcode::I8X16NarrowI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 516 "src/lexer-keywords.txt" + {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 532 "src/lexer-keywords.txt" + {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 243 "src/lexer-keywords.txt" + {"i16x8.extadd_pairwise_i8x16_s", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1785,8 +1869,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 185 "src/lexer-keywords.txt" - {"f64x2.promote_low_f32x4", TokenType::Unary, Opcode::F64X2PromoteLowF32X4} + {""}, {""}, +#line 244 "src/lexer-keywords.txt" + {"i16x8.extadd_pairwise_i8x16_u", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16U} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 606bf781c2..18c1955898 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -110,6 +110,7 @@ class NameResolver : public ExprVisitor::DelegateNop { void VisitFunc(Func* func); void VisitExport(Export* export_); void VisitGlobal(Global* global); + void VisitType(TypeEntry* type); void VisitTag(Tag* tag); void VisitTable(Table* table); void VisitElemSegment(ElemSegment* segment); @@ -577,6 +578,14 @@ void NameResolver::VisitGlobal(Global* global) { visitor_.VisitExprList(global->init_expr); } +void NameResolver::VisitType(TypeEntry* type) { + size_t size = type->gc_ext.sub_types.size(); + + for (size_t i = 0; i < size; i++) { + ResolveFuncTypeVar(&type->gc_ext.sub_types[i]); + } +} + void NameResolver::VisitTag(Tag* tag) { if (tag->decl.has_func_type) { ResolveFuncTypeVar(&tag->decl.type_var); @@ -621,6 +630,8 @@ Result NameResolver::VisitModule(Module* module) { VisitExport(export_); for (Global* global : module->globals) VisitGlobal(global); + for (TypeEntry* type : module->types) + VisitType(type); for (Tag* tag : module->tags) VisitTag(tag); for (Table* table : module->tables) diff --git a/src/shared-validator.cc b/src/shared-validator.cc index c1c098db03..ce9043d6c4 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -29,7 +29,7 @@ TypeVector SharedValidator::ToTypeVector(Index count, const Type* types) { SharedValidator::SharedValidator(Errors* errors, const ValidateOptions& options) : options_(options), errors_(errors), - typechecker_(options.features, func_types_) { + typechecker_(options.features, type_fields_) { typechecker_.set_error_callback( [this](const char* msg) { OnTypecheckerError(msg); }); } @@ -46,44 +46,80 @@ void SharedValidator::OnTypecheckerError(const char* msg) { PrintError(expr_loc_, "%s", msg); } +Result SharedValidator::OnRecursiveType(Index first_type_index, + Index type_count) { + if (type_count > 0) { + type_fields_.recursive_ranges.emplace_back( + RecursiveRange(first_type_index, type_count)); + last_rec_type_end_ = first_type_index + type_count; + } + return Result::Ok; +} + Result SharedValidator::OnFuncType(const Location& loc, Index param_count, const Type* param_types, Index result_count, const Type* result_types, - Index type_index) { + Index type_index, + GCTypeExtension* gc_ext) { Result result = Result::Ok; if (!options_.features.multi_value_enabled() && result_count > 1) { result |= PrintError(loc, "multiple result values are not supported without " "multi-value enabled."); } - if (options_.features.reference_types_enabled()) { + + type_fields_.PushFunc(FuncType{ToTypeVector(param_count, param_types), + ToTypeVector(result_count, result_types), + type_index}); + + if (options_.features.function_references_enabled()) { + Index end_index = GetEndIndex(); + for (Index i = 0; i < param_count; i++) { - result |= CheckReferenceType(loc, param_types[i], "params"); + result |= CheckReferenceType(loc, param_types[i], end_index, "params"); } for (Index i = 0; i < result_count; i++) { - result |= CheckReferenceType(loc, result_types[i], "results"); + result |= CheckReferenceType(loc, result_types[i], end_index, "results"); } + + type_validation_result_ |= result; + result |= CheckGCTypeExtension(loc, gc_ext); } - func_types_.emplace( - num_types_++, - FuncType{ToTypeVector(param_count, param_types), - ToTypeVector(result_count, result_types), type_index}); + return result; } -Result SharedValidator::OnStructType(const Location&, +Result SharedValidator::OnStructType(const Location& loc, Index field_count, - TypeMut* fields) { - struct_types_.emplace(num_types_++, StructType{TypeMutVector( - &fields[0], &fields[field_count])}); - return Result::Ok; + TypeMut* fields, + GCTypeExtension* gc_ext) { + type_fields_.PushStruct( + StructType{TypeMutVector(&fields[0], &fields[field_count])}); + + Result result = Result::Ok; + Index end_index = GetEndIndex(); + + for (Index i = 0; i < field_count; i++) { + result |= CheckReferenceType(loc, fields[i].type, end_index, "params"); + } + + type_validation_result_ |= result; + result |= CheckGCTypeExtension(loc, gc_ext); + return result; } -Result SharedValidator::OnArrayType(const Location&, TypeMut field) { - array_types_.emplace(num_types_++, ArrayType{field}); - return Result::Ok; +Result SharedValidator::OnArrayType(const Location& loc, + TypeMut field, + GCTypeExtension* gc_ext) { + type_fields_.PushArray(ArrayType{field}); + + Result result = CheckReferenceType(loc, field.type, GetEndIndex(), "params"); + + type_validation_result_ |= result; + result |= CheckGCTypeExtension(loc, gc_ext); + return result; } Result SharedValidator::OnFunction(const Location& loc, Var sig_var) { @@ -146,7 +182,8 @@ Result SharedValidator::OnTable(const Location& loc, result |= PrintError(loc, "tables must have funcref type"); } - result |= CheckReferenceType(loc, elem_type, "tables"); + result |= + CheckReferenceType(loc, elem_type, type_fields_.NumTypes(), "tables"); tables_.push_back(TableType{elem_type, limits}); return result; @@ -199,7 +236,8 @@ Result SharedValidator::OnGlobalImport(const Location& loc, Result SharedValidator::OnGlobal(const Location& loc, Type type, bool mutable_) { - CHECK_RESULT(CheckReferenceType(loc, type, "globals")); + CHECK_RESULT( + CheckReferenceType(loc, type, type_fields_.NumTypes(), "globals")); globals_.push_back(GlobalType{type, mutable_}); return Result::Ok; } @@ -218,17 +256,116 @@ Result SharedValidator::CheckType(const Location& loc, Result SharedValidator::CheckReferenceType(const Location& loc, Type type, + Index end_index, const char* desc) { - if (type.IsReferenceWithIndex()) { - Index index = type.GetReferenceIndex(); - auto iter = func_types_.find(index); + if (type.IsReferenceWithIndex() && type.GetReferenceIndex() >= end_index) { + return PrintError(loc, "reference %" PRIindex " is out of range in %s", + type.GetReferenceIndex(), desc); + } + + return Result::Ok; +} + +Result SharedValidator::CheckGCTypeExtension(const Location& loc, + GCTypeExtension* gc_ext) { + assert(options_.features.function_references_enabled()); + + TypeEntry& entry = type_fields_.type_entries.back(); + Index current_index = type_fields_.NumTypes() - 1; + Index end_index; + + if (current_index < last_rec_type_end_) { + end_index = last_rec_type_end_; + } else { + type_fields_.recursive_ranges.emplace_back( + RecursiveRange(current_index, 1)); + end_index = current_index + 1; + } + + // Check default. + assert(entry.canonical_index == current_index && entry.is_final_sub_type && + entry.first_sub_type == kInvalidIndex); + entry.is_final_sub_type = gc_ext->is_final_sub_type; + + if (gc_ext->sub_type_count > 1) { + type_validation_result_ = Result::Error; + return PrintError(loc, "sub type count %" PRIindex " is limited to 1", + gc_ext->sub_type_count); + } + + if (gc_ext->sub_type_count == 1) { + entry.first_sub_type = gc_ext->sub_types[0]; - if (iter == func_types_.end()) { - return PrintError(loc, "reference %d is out of range in %s", - static_cast(index), desc); + if (gc_ext->sub_types[0] >= current_index) { + type_validation_result_ = Result::Error; + return PrintError(loc, "invalid sub type %" PRIindex, + gc_ext->sub_types[0]); + } + + if (type_fields_.type_entries[entry.first_sub_type].is_final_sub_type) { + type_validation_result_ = Result::Error; + return PrintError(loc, "sub type %" PRIindex " has final property", + entry.first_sub_type); + } + } + + if (Failed(type_validation_result_) || end_index != current_index + 1) { + return Result::Ok; + } + + Index start_index = type_fields_.recursive_ranges.back().start_index; + + uint32_t hash = 0; + + // Type checking could be done without computing the canonical_index, + // but runtime and validation checks could be very slow without it. + for (Index i = start_index; i < end_index; i++) { + hash = typechecker_.UpdateHash(hash, i, start_index); + } + + type_fields_.recursive_ranges.back().hash = hash; + + size_t size = type_fields_.recursive_ranges.size() - 1; + Index type_count = end_index - start_index; + + for (Index i = 0; i < size; i++) { + if (type_fields_.recursive_ranges[i].hash == hash && + type_fields_.recursive_ranges[i].type_count == type_count) { + Index base_index = type_fields_.recursive_ranges[i].start_index; + bool is_equal = true; + + for (Index j = 0; j < type_count; j++) { + if (!typechecker_.CheckTypeFields(start_index + j, start_index, + base_index + j, base_index, true)) { + is_equal = false; + break; + } + } + + if (is_equal) { + for (Index j = start_index; j < end_index; j++) { + type_fields_.type_entries[j].canonical_index = base_index++; + } + // An equal recurisve type is present in the list, there is + // no need to compare other recursive types to this type. + type_fields_.recursive_ranges.pop_back(); + break; + } } } + for (Index i = start_index; i < end_index; i++) { + Index first_sub_type = type_fields_.type_entries[i].first_sub_type; + if (first_sub_type != kInvalidIndex && + !typechecker_.CheckTypeFields(i, kInvalidIndex, first_sub_type, + kInvalidIndex, false)) { + PrintError(Location(), + "sub type %" PRIindex " does not match super type %" PRIindex, + type_fields_.type_entries[i].first_sub_type, i); + type_validation_result_ = Result::Error; + return Result::Error; + } + } return Result::Ok; } @@ -322,9 +459,8 @@ Result SharedValidator::OnElemSegmentElemType(const Location& loc, if (elem_type.IsReferenceWithIndex()) { Index index = elem_type.GetReferenceIndex(); - auto iter = func_types_.find(index); - if (iter == func_types_.end()) { + if (index >= type_fields_.NumTypes()) { result |= PrintError(loc, "reference %" PRIindex " is out of range", index); } @@ -404,20 +540,21 @@ Result SharedValidator::CheckLocalIndex(Var local_var, Type* out_type) { } Result SharedValidator::CheckFuncTypeIndex(Var sig_var, FuncType* out) { - Result result = CheckIndex(sig_var, num_types_, "function type"); + Result result = CheckIndex(sig_var, type_fields_.NumTypes(), "function type"); if (Failed(result)) { *out = FuncType{}; return Result::Error; } - auto iter = func_types_.find(sig_var.index()); - if (iter == func_types_.end()) { + Index index = sig_var.index(); + assert(index < type_fields_.NumTypes()); + if (type_fields_.type_entries[index].kind != Type::FuncRef) { return PrintError(sig_var.loc, "type %d is not a function", sig_var.index()); } if (out) { - *out = iter->second; + *out = type_fields_.func_types[type_fields_.type_entries[index].map_index]; } return Result::Ok; } @@ -475,9 +612,8 @@ Result SharedValidator::CheckBlockSignature(const Location& loc, } else { if (sig_type.IsReferenceWithIndex()) { Index index = sig_type.GetReferenceIndex(); - auto iter = func_types_.find(index); - if (iter == func_types_.end()) { + if (index >= type_fields_.NumTypes()) { result |= PrintError(loc, "reference %" PRIindex " is out of range", index); } @@ -522,6 +658,16 @@ void SharedValidator::IgnoreLocalRefs() { } } +Index SharedValidator::GetEndIndex() { + assert(options_.features.reference_types_enabled()); + if (options_.features.gc_enabled()) { + return (last_rec_type_end_ != 0) ? last_rec_type_end_ + : type_fields_.NumTypes(); + } + + return type_fields_.NumTypes() - 1; +} + Result SharedValidator::BeginInitExpr(const Location& loc, Type type) { expr_loc_ = loc; in_init_expr_ = true; @@ -563,7 +709,8 @@ Result SharedValidator::OnLocalDecl(const Location& loc, return Result::Error; } - CHECK_RESULT(CheckReferenceType(loc, type, "locals")); + CHECK_RESULT( + CheckReferenceType(loc, type, type_fields_.NumTypes(), "locals")); Index local_count = GetLocalCount(); @@ -583,6 +730,19 @@ Index SharedValidator::GetLocalCount() const { return locals_.empty() ? 0 : locals_.back().end; } +Index SharedValidator::GetCanonicalTypeIndex(Index type_index) { + if (type_index >= type_fields_.NumTypes()) { + return kInvalidIndex; + } + + if (options_.features.function_references_enabled() && + Succeeded(type_validation_result_)) { + return type_fields_.type_entries[type_index].canonical_index; + } + + return type_index; +} + static bool is_power_of_two(uint32_t x) { return x && ((x & (x - 1)) == 0); } @@ -1159,20 +1319,15 @@ Result SharedValidator::OnRefNull(const Location& loc, Var func_type_var) { Type type = func_type_var.to_type(); - switch (type) { - case Type::RefNull: - result |= CheckIndex(func_type_var, num_types_, "function type"); - break; - case Type::FuncRef: - case Type::ExnRef: - case Type::ExternRef: - break; - default: - result |= PrintError( - loc, "Only ref, externref, exnref, funcref are allowed for ref.null"); - break; + if (type == Type::RefNull) { + result |= + CheckIndex(func_type_var, type_fields_.NumTypes(), "function type"); + } else if (!type.IsNonTypedRef()) { + result |= PrintError( + loc, "Only ref, externref, exnref, funcref are allowed for ref.null"); } + assert(!Type::EnumIsNonTypedGCRef(type) || options_.features.gc_enabled()); result |= typechecker_.OnRefNullExpr(type); return result; } @@ -1236,9 +1391,9 @@ Result SharedValidator::OnSelect(const Location& loc, for (Index i = 0; i < result_count; i++) { if (result_types[i].IsReferenceWithIndex()) { Index index = result_types[i].GetReferenceIndex(); - auto iter = func_types_.find(index); - if (iter == func_types_.end()) { + if (index >= type_fields_.NumTypes() || + type_fields_.type_entries[index].kind != Type::FuncRef) { result |= PrintError(loc, "reference %" PRIindex " is out of range", index); } diff --git a/src/type-checker.cc b/src/type-checker.cc index c13e3ad4de..8b5d8662bf 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -228,96 +228,318 @@ Result TypeChecker::CheckTypeStackEnd(const char* desc) { return result; } -static bool CompareTypeVector( - const std::map& func_types, - const TypeVector& left, - const TypeVector& right) { - size_t size = left.size(); +uint32_t TypeChecker::UpdateHash(uint32_t hash, + Index type_index, + Index rec_start) { + TypeEntry& entry = type_fields_.type_entries[type_index]; + + hash = ComputeHash(hash, entry.kind); + + hash = ComputeHash(hash, static_cast(entry.is_final_sub_type)); + if (entry.first_sub_type != kInvalidIndex) { + Index first_sub_type = entry.first_sub_type; + if (first_sub_type >= rec_start) { + first_sub_type = rec_start - first_sub_type - 1; + } else { + first_sub_type = + type_fields_.type_entries[first_sub_type].canonical_index; + } + hash = ComputeHash(hash, first_sub_type); + } + + switch (entry.kind) { + case Type::FuncRef: { + FuncType& type = type_fields_.func_types[entry.map_index]; + + hash = ComputeHash(hash, static_cast(type.params.size())); + for (auto it : type.params) { + hash = ComputeHash(hash, it, rec_start); + } - if (size != right.size()) { + hash = ComputeHash(hash, static_cast(type.results.size())); + for (auto it : type.results) { + hash = ComputeHash(hash, it, rec_start); + } + break; + } + case Type::StructRef: { + StructType& type = type_fields_.struct_types[entry.map_index]; + + hash = ComputeHash(hash, static_cast(type.fields.size())); + for (auto it : type.fields) { + hash = ComputeHash(hash, it.type, rec_start); + hash = ComputeHash(hash, static_cast(it.mutable_)); + } + break; + } + default: { + assert(entry.kind == Type::ArrayRef); + ArrayType& type = type_fields_.array_types[entry.map_index]; + + hash = ComputeHash(hash, type.field.type, rec_start); + hash = ComputeHash(hash, static_cast(type.field.mutable_)); + break; + } + } + + return hash; +} + +bool TypeChecker::CheckTypeFields(Index actual, + Index actual_rec_start, + Index expected, + Index expected_rec_start, + bool is_equal) { + TypeEntry& actual_entry = type_fields_.type_entries[actual]; + TypeEntry& expected_entry = type_fields_.type_entries[expected]; + + if (actual_entry.kind != expected_entry.kind) { return false; } - for (size_t i = 0; i < size; i++) { - const Type& left_type = left[i]; - const Type& right_type = right[i]; + if (is_equal) { + if (actual_entry.is_final_sub_type != expected_entry.is_final_sub_type) { + return false; + } + + if (actual_entry.first_sub_type == kInvalidIndex || + expected_entry.first_sub_type == kInvalidIndex) { + if (actual_entry.first_sub_type != expected_entry.first_sub_type) { + return false; + } + } else { + Type sub_type_actual(Type::Ref, actual_entry.first_sub_type); + Type sub_type_expected(Type::Ref, expected_entry.first_sub_type); + + if (!CompareType(sub_type_actual, actual_rec_start, sub_type_expected, + expected_rec_start, true)) { + return false; + } + } + } + + switch (actual_entry.kind) { + case Type::FuncRef: { + FuncType& actual_type = type_fields_.func_types[actual_entry.map_index]; + FuncType& expected_type = + type_fields_.func_types[expected_entry.map_index]; - if (left_type != right_type) { - if (!left_type.IsReferenceWithIndex() || - left_type != static_cast(right_type)) { + if (actual_type.params.size() != expected_type.params.size() || + actual_type.results.size() != expected_type.results.size()) { return false; } - const TypeChecker::FuncType& left_func_type = - func_types.at(left_type.GetReferenceIndex()); - const TypeChecker::FuncType& right_func_type = - func_types.at(right_type.GetReferenceIndex()); + size_t size = expected_type.params.size(); + for (size_t i = 0; i < size; i++) { + // Arguments are checked in reversed order. + if (!CompareType(expected_type.params[i], expected_rec_start, + actual_type.params[i], actual_rec_start, is_equal)) { + return false; + } + } - // Circular references were checked during validation. - if (!CompareTypeVector(func_types, left_func_type.params, - right_func_type.params) || - !CompareTypeVector(func_types, left_func_type.results, - right_func_type.results)) { + size = expected_type.results.size(); + for (size_t i = 0; i < size; i++) { + if (!CompareType(actual_type.results[i], actual_rec_start, + expected_type.results[i], expected_rec_start, + is_equal)) { + return false; + } + } + return true; + } + case Type::StructRef: { + StructType& actual_type = + type_fields_.struct_types[actual_entry.map_index]; + StructType& expected_type = + type_fields_.struct_types[expected_entry.map_index]; + + size_t actual_type_size = actual_type.fields.size(); + size_t expected_type_size = expected_type.fields.size(); + + if (is_equal ? actual_type_size != expected_type_size + : actual_type_size < expected_type_size) { return false; } + + for (size_t i = 0; i < expected_type_size; i++) { + bool mutable_ = actual_type.fields[i].mutable_; + if (mutable_ != expected_type.fields[i].mutable_ || + !CompareType(actual_type.fields[i].type, actual_rec_start, + expected_type.fields[i].type, expected_rec_start, + is_equal || mutable_)) { + return false; + } + } + return true; + } + default: { + assert(actual_entry.kind == Type::ArrayRef); + ArrayType& actual_type = type_fields_.array_types[actual_entry.map_index]; + ArrayType& expected_type = + type_fields_.array_types[expected_entry.map_index]; + + bool mutable_ = actual_type.field.mutable_; + return mutable_ == expected_type.field.mutable_ && + CompareType(actual_type.field.type, actual_rec_start, + expected_type.field.type, expected_rec_start, + is_equal || mutable_); } } +} - return true; +uint32_t TypeChecker::ComputeHash(uint32_t hash, Type& type, Index rec_start) { + int32_t code = static_cast(type); + if (type.IsNonTypedRef() && !type.IsNullableNonTypedRef()) { + hash ^= 0x80; + } + hash = ComputeHash(hash, static_cast(code)); + if (type.IsReferenceWithIndex()) { + Index index = type.GetReferenceIndex(); + if (index >= rec_start) { + index = rec_start - index - 1; + } else { + index = type_fields_.type_entries[index].canonical_index; + } + hash = ComputeHash(hash, index); + } + return hash; } -Result TypeChecker::CheckType(Type actual, Type expected) { - if (expected == Type::Any || actual == Type::Any) { - return Result::Ok; +bool TypeChecker::CompareType(Type actual, + Index actual_rec_start, + Type expected, + Index expected_rec_start, + bool is_equal) { + if (actual == expected) { + if (actual.IsReferenceWithIndex()) { + Index actual_index = actual.GetReferenceIndex(); + + return (actual_rec_start == expected_rec_start) || + (actual_index < actual_rec_start && + actual_index < expected_rec_start); + } + return true; } - Type::Enum actual_type = actual; - Type::Enum expected_type = expected; - - if (actual_type == expected_type) { - switch (actual_type) { - case Type::ExternRef: - case Type::FuncRef: - return (expected.IsNullableNonTypedRef() || - !actual.IsNullableNonTypedRef()) - ? Result::Ok - : Result::Error; - - case Type::Reference: - case Type::Ref: - case Type::RefNull: - break; - - default: - return Result::Ok; + if (is_equal) { + if (!expected.IsReferenceWithIndex() || + actual != static_cast(expected)) { + return false; + } + } else { + Type gen_actual = type_fields_.GetGenericType(actual); + Type gen_expected = type_fields_.GetGenericType(expected); + + if (gen_actual != static_cast(gen_expected)) { + switch (gen_expected) { + case Type::FuncRef: + if (gen_actual == Type::NullFuncRef) { + break; + } + [[fallthrough]]; + case Type::NullFuncRef: + if (gen_actual.IsBottomRef()) { + break; + } + return false; + case Type::ExternRef: + if (gen_actual == Type::NullExternRef) { + break; + } + [[fallthrough]]; + case Type::NullExternRef: + if (gen_actual.IsBottomRef()) { + break; + } + return false; + case Type::AnyRef: + if (gen_actual == Type::EqRef) { + break; + } + [[fallthrough]]; + case Type::EqRef: + if (gen_actual == Type::I31Ref || gen_actual == Type::StructRef || + gen_actual == Type::ArrayRef) { + break; + } + [[fallthrough]]; + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: + if (gen_actual == Type::NullRef) { + break; + } + return false; + case Type::ExnRef: + // Note: noexn is not implemented. + if (gen_actual.IsBottomRef()) { + break; + } + return false; + default: + return false; + } + } + + if (!gen_expected.IsNullableNonTypedRef() && + gen_actual.IsNullableNonTypedRef()) { + return false; + } + + if (!actual.IsReferenceWithIndex() || !expected.IsReferenceWithIndex()) { + return (!expected.IsReferenceWithIndex() || actual == Type::NullFuncRef || + actual == Type::NullExternRef || actual == Type::NullRef); } } - if (!actual.IsReferenceWithIndex()) { - return Result::Error; + Index expected_index = expected.GetReferenceIndex(); + Index actual_index = actual.GetReferenceIndex(); + + if (expected_index >= expected_rec_start) { + return (actual_index >= actual_rec_start) && + (actual_index - actual_rec_start == + expected_index - expected_rec_start); } - if (expected_type == Type::FuncRef) { - return (actual == Type::Ref || expected.IsNullableNonTypedRef()) - ? Result::Ok - : Result::Error; + expected_index = type_fields_.type_entries[expected_index].canonical_index; + actual_index = type_fields_.type_entries[actual_index].canonical_index; + + if (expected_index == actual_index) { + return true; } - if (!expected.IsReferenceWithIndex()) { - return Result::Error; + if (is_equal) { + return false; } - if (expected_type == Type::Ref && actual_type == Type::RefNull) { - return Result::Error; + while (true) { + actual_index = type_fields_.type_entries[actual_index].first_sub_type; + + if (actual_index == kInvalidIndex) { + return false; + } + + if (expected_index >= expected_rec_start) { + return (actual_index >= actual_rec_start) && + (actual_index - actual_rec_start == + expected_index - expected_rec_start); + } + + actual_index = type_fields_.type_entries[actual_index].canonical_index; + + if (actual_index == expected_index) { + return true; + } } +} - FuncType& actual_func_type = func_types_[actual.GetReferenceIndex()]; - FuncType& expected_func_type = func_types_[expected.GetReferenceIndex()]; +Result TypeChecker::CheckType(Type actual, Type expected) { + if (expected == Type::Any || actual == Type::Any) { + return Result::Ok; + } - if (CompareTypeVector(func_types_, actual_func_type.params, - expected_func_type.params) && - CompareTypeVector(func_types_, actual_func_type.results, - expected_func_type.results)) { + if (CompareType(actual, kInvalidIndex, expected, kInvalidIndex, false)) { return Result::Ok; } @@ -405,13 +627,15 @@ Result TypeChecker::PopAndCheck3Types(Type expected1, } Result TypeChecker::PopAndCheckReference(Type* actual, const char* desc) { - *actual = Type::Any; Result result = PeekType(0, actual); - // Type::Any is a valid value for dead code, and replacing - // it with anything might break the syntax checker. - if (*actual != Type::Any && !actual->IsRef()) { - result = Result::Error; + // Type::Any is a valid value for dead code, and + // it is replaced by an unkown reference. + if (*actual == Type::Any || !actual->IsRef()) { + if (*actual != Type::Any) { + result = Result::Error; + } + *actual = Type::BottomRef(); } PrintStackIfFailed(result, desc, Type::FuncRef); @@ -569,30 +793,19 @@ Result TypeChecker::OnBrIf(Index depth) { return result; } -static Type convertRefNullToRef(Type type) { - if (type == Type::ExternRef || type == Type::FuncRef) { - return Type(type, Type::ReferenceNonNull); - } - - assert(type.IsReferenceWithIndex()); - return Type(Type::Ref, type.GetReferenceIndex()); -} - Result TypeChecker::OnBrOnNonNull(Index depth) { Type actual; CHECK_RESULT(PopAndCheckReference(&actual, "br_on_non_null")); - if (actual != Type::Any) { - PushType(convertRefNullToRef(actual)); - } + actual.ConvertRefNullToRef(); + + PushType(actual); Label* label; CHECK_RESULT(GetLabel(depth, &label)); Result result = PopAndCheckSignature(label->br_types(), "br_on_non_null"); PushTypes(label->br_types()); - if (actual != Type::Any) { - result |= DropTypes(1); - } + result |= DropTypes(1); return result; } @@ -605,9 +818,7 @@ Result TypeChecker::OnBrOnNull(Index depth) { Result result = PopAndCheckSignature(label->br_types(), "br_on_null"); PushTypes(label->br_types()); - if (actual != Type::Any) { - actual = convertRefNullToRef(actual); - } + actual.ConvertRefNullToRef(); PushType(actual); return result; } @@ -926,9 +1137,7 @@ Result TypeChecker::OnTableFill(Type elem_type, const Limits& limits) { Result TypeChecker::OnRefAsNonNullExpr() { Type actual; CHECK_RESULT(PopAndCheckReference(&actual, "ref.as_non_null")); - if (actual != Type::Any) { - actual = convertRefNullToRef(actual); - } + actual.ConvertRefNullToRef(); PushType(actual); return Result::Ok; } @@ -947,7 +1156,7 @@ Result TypeChecker::OnRefIsNullExpr() { Type type; Result result = PeekType(0, &type); if (!type.IsRef()) { - type = Type(Type::Reference, kInvalidIndex); + type = Type::FuncRef; } result |= PopAndCheck1Type(type, "ref.is_null"); PushType(Type::I32); diff --git a/src/validator.cc b/src/validator.cc index ae405f71b9..764fd84349 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -206,12 +206,16 @@ static Result CheckType(Type actual, Type expected) { switch (actual_type) { case Type::ExternRef: case Type::FuncRef: + case Type::AnyRef: + case Type::EqRef: + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: return (expected.IsNullableNonTypedRef() || !actual.IsNullableNonTypedRef()) ? Result::Ok : Result::Error; - case Type::Reference: case Type::Ref: case Type::RefNull: if (actual == expected) { @@ -754,46 +758,96 @@ Validator::Validator(Errors* errors, validator_(errors_, options_), current_module_(module) {} +static void GetGCTypeExtension(const TypeEntryGCTypeExtension& gc_ext_in, + GCTypeExtension* gc_ext_out, + std::vector& sub_types) { + Index sub_type_count = static_cast(gc_ext_in.sub_types.size()); + + gc_ext_out->is_final_sub_type = gc_ext_in.is_final_sub_type; + gc_ext_out->sub_type_count = sub_type_count; + + sub_types.resize(sub_type_count); + for (Index i = 0; i < sub_type_count; i++) { + sub_types[i] = gc_ext_in.sub_types[i].index(); + } + + gc_ext_out->sub_types = sub_types.data(); +} + Result Validator::CheckModule() { const Module* module = current_module_; // Type section. + Index type_index = 0; + Index first_type_index = kInvalidIndex; + Index range_index = 0; + GCTypeExtension gc_ext; + std::vector sub_types; + + if (!module->recursive_ranges.empty()) { + first_type_index = module->recursive_ranges[0].first_type_index; + } + for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast(&field)) { + if (type_index == first_type_index) { + const RecursiveRange& range = module->recursive_ranges[range_index]; + validator_.OnRecursiveType(range.first_type_index, range.type_count); + + first_type_index = kInvalidIndex; + if (++range_index < module->recursive_ranges.size()) { + first_type_index = + module->recursive_ranges[range_index].first_type_index; + } + } + switch (f->type->kind()) { case TypeEntryKind::Func: { FuncType* func_type = cast(f->type.get()); + GetGCTypeExtension(func_type->gc_ext, &gc_ext, sub_types); + result_ |= validator_.OnFuncType( field.loc, func_type->sig.param_types.size(), func_type->sig.param_types.data(), func_type->sig.result_types.size(), - func_type->sig.result_types.data(), - module->GetFuncTypeIndex(func_type->sig)); + func_type->sig.result_types.data(), type_index, &gc_ext); break; } case TypeEntryKind::Struct: { StructType* struct_type = cast(f->type.get()); + GetGCTypeExtension(struct_type->gc_ext, &gc_ext, sub_types); TypeMutVector type_muts; for (auto&& field : struct_type->fields) { type_muts.push_back(TypeMut{field.type, field.mutable_}); } result_ |= validator_.OnStructType(field.loc, type_muts.size(), - type_muts.data()); + type_muts.data(), &gc_ext); break; } case TypeEntryKind::Array: { ArrayType* array_type = cast(f->type.get()); + GetGCTypeExtension(array_type->gc_ext, &gc_ext, sub_types); result_ |= validator_.OnArrayType( field.loc, - TypeMut{array_type->field.type, array_type->field.mutable_}); + TypeMut{array_type->field.type, array_type->field.mutable_}, + &gc_ext); break; } } + + type_index++; } } + while (range_index < module->recursive_ranges.size()) { + // Should be 0 for valid modules. + const RecursiveRange& range = module->recursive_ranges[range_index]; + validator_.OnRecursiveType(range.first_type_index, range.type_count); + ++range_index; + } + // Import section. for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast(&field)) { diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 3d97bf3023..3e94a6d8d5 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -269,6 +269,7 @@ bool IsModuleField(TokenTypePair pair) { case TokenType::Export: case TokenType::Func: case TokenType::Type: + case TokenType::Rec: case TokenType::Global: case TokenType::Import: case TokenType::Memory: @@ -331,7 +332,7 @@ void ResolveImplicitlyDefinedFunctionType(const Location& loc, Index func_type_index = module->GetFuncTypeIndex(decl.sig); if (func_type_index == kInvalidIndex) { auto func_type_field = std::make_unique(loc); - auto func_type = std::make_unique(); + auto func_type = std::make_unique(true); func_type->sig = decl.sig; func_type_field->type = std::move(func_type); module->AppendField(std::move(func_type_field)); @@ -339,6 +340,29 @@ void ResolveImplicitlyDefinedFunctionType(const Location& loc, } } +bool IsTypeEnabled(Type::Enum type, WastParseOptions* options_) { + switch (type) { + case Type::V128: + return options_->features.simd_enabled(); + case Type::FuncRef: + case Type::ExternRef: + return options_->features.reference_types_enabled(); + case Type::ExnRef: + return options_->features.exceptions_enabled(); + case Type::NullFuncRef: + case Type::NullExternRef: + case Type::NullRef: + case Type::AnyRef: + case Type::EqRef: + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: + return options_->features.gc_enabled(); + default: + return true; + } +} + Result CheckTypeIndex(const Location& loc, Type actual, Type expected, @@ -886,20 +910,41 @@ Result WastParser::ParseRefDeclaration(Var* out_type) { EXPECT(Lpar); EXPECT(Ref); - Type::Enum opt_type = Type::Reference; + Type::Enum opt_type = Type::Ref; - if (options_->features.function_references_enabled()) { - opt_type = Type::Ref; + if (options_->features.function_references_enabled() && + Match(TokenType::Null)) { + opt_type = Type::RefNull; + } - if (Match(TokenType::Null)) { - opt_type = Type::RefNull; - } + TokenType token = Peek(0); + bool is_generic_ref = false; + + switch (token) { + case TokenType::Func: + case TokenType::Extern: + is_generic_ref = true; + break; + + case TokenType::Any: + case TokenType::Array: + case TokenType::Eq: + case TokenType::I31: + case TokenType::NoExtern: + case TokenType::NoFunc: + case TokenType::None: + case TokenType::Struct: + if (options_->features.gc_enabled()) { + is_generic_ref = true; + } + break; + + default: + break; } - if (PeekMatch(TokenType::Func) || PeekMatch(TokenType::Extern)) { - TokenType token = Consume().token_type(); - out_type->set_opt_type(token == TokenType::Func ? Type::FuncRef - : Type::ExternRef); + if (is_generic_ref) { + out_type->set_opt_type(Consume().type()); out_type->set_index(opt_type == Type::Ref ? Type::ReferenceNonNull : Type::ReferenceOrNull); } else { @@ -911,7 +956,7 @@ Result WastParser::ParseRefDeclaration(Var* out_type) { return Result::Ok; } -Result WastParser::ParseValueType(Var* out_type) { +Result WastParser::ParseValueType(Var* out_type, bool is_field) { WABT_TRACE(ParseValueType); if (PeekMatchRefType()) { @@ -919,30 +964,20 @@ Result WastParser::ParseValueType(Var* out_type) { } if (!PeekMatch(TokenType::ValueType)) { + if (is_field) { + return ErrorExpected({"i8", "i16", "i32", "i64", "f32", "f64", "v128", + "anyref", "arrayref", "eqref", "externref", + "exnref", "funcref", "i31ref", "nullref", + "nullexternref", "nullfuncref"}); + } return ErrorExpected( {"i32", "i64", "f32", "f64", "v128", "externref", "exnref", "funcref"}); } Token token = Consume(); Type type = token.type(); - bool is_enabled; - switch (type) { - case Type::V128: - is_enabled = options_->features.simd_enabled(); - break; - case Type::FuncRef: - case Type::ExternRef: - is_enabled = options_->features.reference_types_enabled(); - break; - case Type::ExnRef: - is_enabled = options_->features.exceptions_enabled(); - break; - default: - is_enabled = true; - break; - } - if (!is_enabled) { + if ((!is_field || !type.IsPackedType()) && !IsTypeEnabled(type, options_)) { Error(token.loc, "value type not allowed: %s", type.GetName().c_str()); return Result::Error; } @@ -988,16 +1023,17 @@ Result WastParser::ParseRefKind(Var* out_type) { } if (!IsTokenTypeRefKind(Peek())) { + if (options_->features.gc_enabled()) { + return ErrorExpected({"any", "array", "func", "eq", "extern", "exn", + "i31", "noextern", "nofunc", "none", "struct"}); + } return ErrorExpected({"func", "extern", "exn"}); } Token token = Consume(); Type type = token.type(); - if ((type == Type::ExternRef && - !options_->features.reference_types_enabled()) || - ((type == Type::Struct || type == Type::Array) && - !options_->features.gc_enabled())) { + if (!IsTypeEnabled(type, options_)) { Error(token.loc, "value type not allowed: %s", type.GetName().c_str()); return Result::Error; } @@ -1385,6 +1421,30 @@ Result WastParser::ResolveTargetTypeVector(const Module& module, return Result::Ok; } +Result WastParser::ResolveTargetFieldVector(const Module& module, + StructType* target_struct, + ReferenceVars* ref_vars, + Errors* errors) { + Result result = Result::Ok; + + for (auto& ref_var : *ref_vars) { + uint32_t index = ref_var.index; + + // The index of resolved variables is converted to kInvalidIndex. + if (index == kInvalidIndex) { + continue; + } + + ref_var.index = kInvalidIndex; + + assert(index < target_struct->fields.size()); + result |= ResolveTargetRefType(module, &target_struct->fields[index].type, + ref_var.var, errors); + } + + return Result::Ok; +} + Result WastParser::ParseModuleFieldList(Module* module) { WABT_TRACE(ParseModuleFieldList); @@ -1392,6 +1452,7 @@ Result WastParser::ParseModuleFieldList(Module* module) { resolve_ref_types_.clear(); resolve_type_vectors_.clear(); resolve_funcs_.clear(); + resolve_fields_.clear(); while (IsModuleField(PeekPair()) || PeekIsCustom()) { if (PeekIsCustom()) { @@ -1420,6 +1481,11 @@ Result WastParser::ParseModuleFieldList(Module* module) { it.target_func->local_types.Set(it.types); } + for (auto it : resolve_fields_) { + result |= + ResolveTargetFieldVector(*module, it.target_struct, &it.vars, errors_); + } + CHECK_RESULT(result); CHECK_RESULT(ResolveFuncTypes(module, errors_)); CHECK_RESULT(ResolveNamesModule(module, errors_)); @@ -1435,6 +1501,8 @@ Result WastParser::ParseModuleField(Module* module) { case TokenType::Export: return ParseExportModuleField(module); case TokenType::Func: return ParseFuncModuleField(module); case TokenType::Type: return ParseTypeModuleField(module); + case TokenType::Rec: + return ParseRecTypeModuleField(module); case TokenType::Global: return ParseGlobalModuleField(module); case TokenType::Import: return ParseImportModuleField(module); case TokenType::Memory: return ParseMemoryModuleField(module); @@ -1663,78 +1731,173 @@ Result WastParser::ParseTypeModuleField(Module* module) { EXPECT(Type); std::string name; + bool has_sub_type = false; + bool is_final_sub_type = true; + VarVector sub_types; + ParseBindVarOpt(&name); + + if (options_->features.gc_enabled() && MatchLpar(TokenType::Sub)) { + has_sub_type = true; + + if (!Match(TokenType::Final)) { + is_final_sub_type = false; + } + + Var var; + + while (ParseVarOpt(&var)) { + sub_types.emplace_back(var); + } + } + EXPECT(Lpar); Location loc = GetLocation(); if (Match(TokenType::Func)) { - auto func_type = std::make_unique(name); + auto func_type = std::make_unique(is_final_sub_type, name); BindingHash bindings; CHECK_RESULT(ParseFuncSignature(&func_type->sig, &bindings)); CHECK_RESULT(ErrorIfLpar({"param", "result"})); + func_type->gc_ext.sub_types = std::move(sub_types); field->type = std::move(func_type); } else if (Match(TokenType::Struct)) { if (!options_->features.gc_enabled()) { Error(loc, "struct not allowed"); return Result::Error; } - auto struct_type = std::make_unique(name); - CHECK_RESULT(ParseFieldList(&struct_type->fields)); + auto struct_type = std::make_unique(is_final_sub_type, name); + CHECK_RESULT(ParseFieldList(struct_type.get())); + struct_type->gc_ext.sub_types = std::move(sub_types); field->type = std::move(struct_type); } else if (Match(TokenType::Array)) { if (!options_->features.gc_enabled()) { Error(loc, "array type not allowed"); } - auto array_type = std::make_unique(name); + auto array_type = std::make_unique(is_final_sub_type, name); CHECK_RESULT(ParseField(&array_type->field)); + array_type->gc_ext.sub_types = std::move(sub_types); field->type = std::move(array_type); } else { return ErrorExpected({"func", "struct", "array"}); } EXPECT(Rpar); + if (has_sub_type) { + EXPECT(Rpar); + } EXPECT(Rpar); module->AppendField(std::move(field)); return Result::Ok; } +Result WastParser::ParseRecTypeModuleField(Module* module) { + WABT_TRACE(ParseTypeModuleField); + + Location loc = Consume().loc; + + if (!options_->features.gc_enabled()) { + errors_->emplace_back(ErrorLevel::Error, loc, + StringPrintf("garbage collection not enabled")); + return Result::Error; + } + + EXPECT(Rec); + + Index start_index = static_cast(module->types.size()); + + while (PeekMatchLpar(TokenType::Type)) { + CHECK_RESULT(ParseTypeModuleField(module)); + } + + Index type_count = static_cast(module->types.size()) - start_index; + if (type_count == 0) { + auto field = std::make_unique(loc); + module->AppendField(std::move(field)); + } else if (type_count > 1) { + module->recursive_ranges.push_back(RecursiveRange{start_index, type_count}); + } + + EXPECT(Rpar); + return Result::Ok; +} + Result WastParser::ParseField(Field* field) { 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()); - EXPECT(Rpar); - } else { - field->mutable_ = false; - Var type; - CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.opt_type()); - } - return Result::Ok; - }; - if (MatchLpar(TokenType::Field)) { - ParseBindVarOpt(&field->name); - CHECK_RESULT(parse_mut_valuetype()); + field->mutable_ = MatchLpar(TokenType::Mut); + + Var type; + CHECK_RESULT(ParseValueType(&type, true)); + VarToType(type, &field->type); + + if (field->mutable_) { EXPECT(Rpar); - } else { - CHECK_RESULT(parse_mut_valuetype()); } return Result::Ok; } -Result WastParser::ParseFieldList(std::vector* fields) { +Result WastParser::ParseFieldList(StructType* struct_type) { WABT_TRACE(ParseFieldList); - while (PeekMatch(TokenType::ValueType) || PeekMatch(TokenType::Lpar)) { + + std::set known_fields; + ResolveField references(struct_type); + + while (MatchLpar(TokenType::Field)) { + if (Match(TokenType::Rpar)) { + continue; + } + Field field; - CHECK_RESULT(ParseField(&field)); - fields->push_back(field); + bool has_name = false; + Location loc; + + if (PeekMatch(TokenType::Var)) { + Token token = Consume(); + field.name = std::string(token.text()); + + if (!known_fields.insert(field.name).second) { + errors_->emplace_back( + ErrorLevel::Error, loc, + StringPrintf("duplicate field %s", field.name.c_str())); + return Result::Error; + } + + has_name = true; + loc = token.loc; + } + + do { + field.mutable_ = MatchLpar(TokenType::Mut); + + Var type; + CHECK_RESULT(ParseValueType(&type, true)); + + if (field.mutable_) { + EXPECT(Rpar); + } + + if (type.is_index()) { + field.type = type.to_type(); + } else { + assert(type.is_name()); + assert(options_->features.gc_enabled()); + references.vars.push_back( + ReferenceVar(struct_type->fields.size(), type)); + field.type = Type(type.opt_type(), kInvalidIndex); + } + + struct_type->fields.push_back(field); + } while (!has_name && !PeekMatch(TokenType::Rpar)); + + EXPECT(Rpar); } + + if (!references.vars.empty()) { + resolve_fields_.push_back(references); + } + return Result::Ok; } @@ -3979,6 +4142,15 @@ bool WastParser::CheckRefType(Type::Enum type) { return options_->features.reference_types_enabled(); case Type::ExnRef: return options_->features.exceptions_enabled(); + case Type::NullFuncRef: + case Type::NullExternRef: + case Type::NullRef: + case Type::AnyRef: + case Type::EqRef: + case Type::I31Ref: + case Type::StructRef: + case Type::ArrayRef: + return options_->features.gc_enabled(); default: assert(!Type::EnumIsNonTypedRef(type)); return false; diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 04ade45064..80a8948fdc 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -196,6 +196,7 @@ class WatWriter : ModuleContext { Index table_index_ = 0; Index memory_index_ = 0; Index type_index_ = 0; + Index recursive_range_index_ = 0; Index tag_index_ = 0; Index data_segment_index_ = 0; Index elem_segment_index_ = 0; @@ -1715,6 +1716,12 @@ void WatWriter::WriteExport(const Export& export_) { } void WatWriter::WriteTypeEntry(const TypeEntry& type) { + if (recursive_range_index_ < module.recursive_ranges.size() && + module.recursive_ranges[recursive_range_index_].first_type_index == + type_index_) { + WriteOpen("rec", NextChar::Newline); + } + WriteOpenSpace("type"); WriteNameOrIndex(type.name, type_index_++, NextChar::Space); switch (type.kind()) { @@ -1748,6 +1755,14 @@ void WatWriter::WriteTypeEntry(const TypeEntry& type) { } } WriteCloseNewline(); + + // The type_index_ is increased above. + if (recursive_range_index_ < module.recursive_ranges.size() && + module.recursive_ranges[recursive_range_index_].EndTypeIndex() == + type_index_) { + WriteCloseNewline(); + recursive_range_index_++; + } } void WatWriter::WriteField(const Field& field) { @@ -1814,6 +1829,9 @@ Result WatWriter::WriteModule() { case ModuleFieldType::Type: WriteTypeEntry(*cast(&field)->type); break; + case ModuleFieldType::EmptyRec: + WritePuts("(rec)", NextChar::Newline); + break; case ModuleFieldType::Start: WriteStartFunction(cast(&field)->start); break; diff --git a/test/binary/bad-reference-indicies.txt b/test/binary/bad-reference-indicies.txt index fea35b8dfe..123cfe2681 100644 --- a/test/binary/bad-reference-indicies.txt +++ b/test/binary/bad-reference-indicies.txt @@ -5,7 +5,7 @@ magic version section(TYPE) { count[2] - function params[1] reference 10 results[1] reference 20 + function params[1] ref 10 results[1] ref 20 function params[0] results[0] } section(FUNCTION) { count[1] sig[1] } @@ -13,7 +13,7 @@ section(CODE) { count[1] func { local_decls[1] - locals[1] reference 30 + locals[1] ref 30 } } (;; STDERR ;;; diff --git a/test/dump/struct.txt b/test/dump/struct.txt index e5f7d0501b..d95cd93410 100644 --- a/test/dump/struct.txt +++ b/test/dump/struct.txt @@ -2,8 +2,8 @@ ;;; ARGS0: --enable-gc ;;; ARGS1: -x (type (struct)) -(type (struct i32 i64 f32 f64)) -(type (struct i32 (mut i64))) +(type (struct (field i32 i64 f32 f64))) +(type (struct (field i32 (mut i64)))) (;; STDOUT ;;; struct.wasm: file format wasm 0x1 diff --git a/test/gen-wasm.py b/test/gen-wasm.py index ffcaf593c1..e8537278c3 100755 --- a/test/gen-wasm.py +++ b/test/gen-wasm.py @@ -43,7 +43,7 @@ 'f64': 0x7c, # -4 'v128': 0x7b, # -5 'funcref': 0x70, # -0x10 - 'reference': 0x6b, # -0x15 + 'ref': 0x64, # -0x1c 'function': 0x60, # -0x20 'struct': 0x5f, # -0x21 'array': 0x5e, # -0x22 diff --git a/test/parse/bad-argument-ref.txt b/test/parse/bad-argument-ref.txt new file mode 100644 index 0000000000..9237af00dd --- /dev/null +++ b/test/parse/bad-argument-ref.txt @@ -0,0 +1,18 @@ +;;; TOOL: wat2wasm +;;; ARGS: --enable-gc +;;; ERROR: 1 +(module + (func + unreachable + ref.as_non_null + ref.as_non_null + i32.const 5 + i32.add + drop + ) +) +(;; STDERR ;;; +out/test/parse/bad-argument-ref.txt:10:5: error: type mismatch in i32.add, expected [i32, i32] but got [(ref something), i32] + i32.add + ^^^^^^^ +;;; STDERR ;;) diff --git a/test/parse/module/bad-array-no-fields.txt b/test/parse/module/bad-array-no-fields.txt index 8b60fd7bdf..95a059aade 100644 --- a/test/parse/module/bad-array-no-fields.txt +++ b/test/parse/module/bad-array-no-fields.txt @@ -3,7 +3,7 @@ ;;; ERROR: 1 (type (array)) (;; STDERR ;;; -out/test/parse/module/bad-array-no-fields.txt:4:13: error: unexpected token ")", expected i32, i64, f32, f64, v128, externref, exnref or funcref. +out/test/parse/module/bad-array-no-fields.txt:4:13: error: unexpected token ")", expected i8, i16, i32, i64, f32, f64, v128, anyref, arrayref, eqref, externref, exnref, funcref, i31ref, nullref, nullexternref or nullfuncref. (type (array)) ^ ;;; STDERR ;;) diff --git a/test/parse/module/struct-and-func.txt b/test/parse/module/struct-and-func.txt index 93a524e13d..05cd005f55 100644 --- a/test/parse/module/struct-and-func.txt +++ b/test/parse/module/struct-and-func.txt @@ -1,6 +1,6 @@ ;;; TOOL: wat2wasm ;;; ARGS: --enable-gc -(type (struct i32 i32)) +(type (struct (field i32 i32))) (type (func (result i32))) (func (result i32) diff --git a/test/parse/module/struct-mut-field.txt b/test/parse/module/struct-mut-field.txt index 8189179aa7..a0794106e0 100644 --- a/test/parse/module/struct-mut-field.txt +++ b/test/parse/module/struct-mut-field.txt @@ -1,3 +1,3 @@ ;;; TOOL: wat2wasm ;;; ARGS: --enable-gc -(type (struct (mut f32) (field (mut f64)))) +(type (struct (field (mut f32)) (field (mut f64)))) diff --git a/test/parse/module/struct.txt b/test/parse/module/struct.txt index 825e9d6718..cee62d7fd7 100644 --- a/test/parse/module/struct.txt +++ b/test/parse/module/struct.txt @@ -1,3 +1,3 @@ ;;; TOOL: wat2wasm ;;; ARGS: --enable-gc -(type (struct i32 (field i64))) +(type (struct (field i32) (field i64))) diff --git a/test/roundtrip/rec-types.txt b/test/roundtrip/rec-types.txt new file mode 100644 index 0000000000..39a5fea05c --- /dev/null +++ b/test/roundtrip/rec-types.txt @@ -0,0 +1,45 @@ +;;; TOOL: run-roundtrip +;;; ARGS: --stdout --enable-gc +(module + (rec) + (rec) + (type (func (param i32))) + (rec + (type (struct)) + (type (struct (field i32))) + (type (array i64)) + ) + (rec) + (rec) + (rec) + (rec + (type (struct (field f32))) + (type (func (result i64))) + ) + (type (struct (field f64))) + (rec) + (rec) + (rec) + (rec) +) +(;; STDOUT ;;; +(module + (rec) + (rec) + (type (;0;) (func (param i32))) + (rec + (type (;1;) (struct)) + (type (;2;) (struct (field (;0;) i32))) + (type (;3;) (array i64))) + (rec) + (rec) + (rec) + (rec + (type (;4;) (struct (field (;0;) f32))) + (type (;5;) (func (result i64)))) + (type (;6;) (struct (field (;0;) f64))) + (rec) + (rec) + (rec) + (rec)) +;;; 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, diff --git a/test/spec/function-references/ref_is_null.txt b/test/spec/function-references/ref_is_null.txt index 7e9b59f5f1..4b0bb5a7f7 100644 --- a/test/spec/function-references/ref_is_null.txt +++ b/test/spec/function-references/ref_is_null.txt @@ -5,10 +5,10 @@ init(externref:1) => deinit() => out/test/spec/function-references/ref_is_null.wast:79: assert_invalid passed: - out/test/spec/function-references/ref_is_null/ref_is_null.2.wasm:000001b: error: type mismatch in ref.is_null, expected [reference] but got [i32] + out/test/spec/function-references/ref_is_null/ref_is_null.2.wasm:000001b: error: type mismatch in ref.is_null, expected [funcref] but got [i32] 000001b: error: OnRefIsNullExpr callback failed out/test/spec/function-references/ref_is_null.wast:83: assert_invalid passed: - out/test/spec/function-references/ref_is_null/ref_is_null.3.wasm:0000018: error: type mismatch in ref.is_null, expected [reference] but got [] + out/test/spec/function-references/ref_is_null/ref_is_null.3.wasm:0000018: error: type mismatch in ref.is_null, expected [funcref] but got [] 0000018: error: OnRefIsNullExpr callback failed 22/22 tests passed. ;;; STDOUT ;;) diff --git a/test/spec/function-references/unreached-invalid.txt b/test/spec/function-references/unreached-invalid.txt index f24cd1c089..ead31d4f55 100644 --- a/test/spec/function-references/unreached-invalid.txt +++ b/test/spec/function-references/unreached-invalid.txt @@ -335,8 +335,8 @@ out/test/spec/function-references/unreached-invalid.wast:687: assert_invalid pas out/test/spec/function-references/unreached-invalid/unreached-invalid.109.wasm:000001c: error: type mismatch in i64.extend_i32_u, expected [i32] but got [i64] 000001c: error: OnConvertExpr callback failed out/test/spec/function-references/unreached-invalid.wast:698: assert_invalid passed: - out/test/spec/function-references/unreached-invalid/unreached-invalid.110.wasm:000001b: error: type mismatch at end of function, expected [] but got [f32] - 000001b: error: EndFunctionBody callback failed + out/test/spec/function-references/unreached-invalid/unreached-invalid.110.wasm:000001a: error: type mismatch in f32.abs, expected [f32] but got [(ref something)] + 000001a: error: OnUnaryExpr callback failed out/test/spec/function-references/unreached-invalid.wast:710: assert_invalid passed: out/test/spec/function-references/unreached-invalid/unreached-invalid.111.wasm:000001f: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] 000001f: error: OnSelectExpr callback failed diff --git a/test/spec/gc/table-sub.txt b/test/spec/gc/table-sub.txt new file mode 100644 index 0000000000..c20c15b7e5 --- /dev/null +++ b/test/spec/gc/table-sub.txt @@ -0,0 +1,12 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/table-sub.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/table-sub.wast:13: assert_invalid passed: + out/test/spec/gc/table-sub/table-sub.1.wasm:000002a: error: type mismatch at table.copy. got externref, expected funcref + 000002a: error: OnTableCopyExpr callback failed +out/test/spec/gc/table-sub.wast:24: assert_invalid passed: + out/test/spec/gc/table-sub/table-sub.2.wasm:000002d: error: type mismatch at table.init. got externref, expected funcref + 000002d: error: OnTableInitExpr callback failed +3/3 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/type-canon.txt b/test/spec/gc/type-canon.txt new file mode 100644 index 0000000000..c23a2a718a --- /dev/null +++ b/test/spec/gc/type-canon.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/type-canon.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +2/2 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/type-equivalence.txt b/test/spec/gc/type-equivalence.txt new file mode 100644 index 0000000000..2f5085afdd --- /dev/null +++ b/test/spec/gc/type-equivalence.txt @@ -0,0 +1,9 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/type-equivalence.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/type-equivalence.wast:77: assert_invalid passed: + out/test/spec/gc/type-equivalence/type-equivalence.5.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +26/26 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/type-rec.txt b/test/spec/gc/type-rec.txt new file mode 100644 index 0000000000..83bd78e6da --- /dev/null +++ b/test/spec/gc/type-rec.txt @@ -0,0 +1,30 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/type-rec.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/type-rec.wast:26: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.2.wasm:000002b: error: type mismatch in initializer expression, expected [(ref 0)] but got [(ref 2)] + 000002c: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-rec.wast:36: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.3.wasm:0000035: error: type mismatch in initializer expression, expected [(ref 2)] but got [(ref 4)] + 0000036: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-rec.wast:47: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.4.wasm:0000025: error: type mismatch in initializer expression, expected [(ref 0)] but got [(ref 3)] + 0000026: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-rec.wast:57: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.5.wasm:0000028: error: type mismatch in initializer expression, expected [(ref 0)] but got [(ref 2)] + 0000029: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-rec.wast:81: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-rec.wast:89: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-rec.wast:115: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-rec.wast:124: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-rec.wast:137: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.14.wasm:0000025: error: type mismatch in initializer expression, expected [(ref 1)] but got [(ref 2)] + 0000026: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-rec.wast:149: assert_invalid passed: + out/test/spec/gc/type-rec/type-rec.15.wasm:0000021: error: type mismatch in initializer expression, expected [(ref 1)] but got [(ref 2)] + 0000022: error: EndGlobalInitExpr callback failed +19/19 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/type-subtyping-invalid.txt b/test/spec/gc/type-subtyping-invalid.txt new file mode 100644 index 0000000000..0d9eb86ec1 --- /dev/null +++ b/test/spec/gc/type-subtyping-invalid.txt @@ -0,0 +1,18 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/type-subtyping-invalid.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/type-subtyping-invalid.wast:2: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnStructType callback failed +out/test/spec/gc/type-subtyping-invalid.wast:12: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnStructType callback failed +out/test/spec/gc/type-subtyping-invalid.wast:22: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnStructType callback failed +out/test/spec/gc/type-subtyping-invalid.wast:31: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnStructType callback failed +4/4 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/unreached-invalid.txt b/test/spec/gc/unreached-invalid.txt new file mode 100644 index 0000000000..cab97080e0 --- /dev/null +++ b/test/spec/gc/unreached-invalid.txt @@ -0,0 +1,371 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/unreached-invalid.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/unreached-invalid.wast:4: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.0.wasm:000001a: error: local variable out of range (max 0) + 000001a: error: OnLocalGetExpr callback failed +out/test/spec/gc/unreached-invalid.wast:8: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.1.wasm:000001a: error: global variable out of range: 0 (max 0) + 000001a: error: OnGlobalGetExpr callback failed +out/test/spec/gc/unreached-invalid.wast:12: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.2.wasm:000001a: error: function variable out of range: 1 (max 1) + 000001a: error: OnCallExpr callback failed +out/test/spec/gc/unreached-invalid.wast:16: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.3.wasm:0000018: error: invalid depth: 1 (max 0) + 000001a: error: OnBrExpr callback failed +out/test/spec/gc/unreached-invalid.wast:21: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.4.wasm:000001b: error: type mismatch in i64.eqz, expected [i64] but got [i32] + 000001b: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:27: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.5.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [i64] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:33: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.6.wasm:0000023: error: type mismatch in select, expected [i32, i32, i32] but got [i64, i32, i32] + 0000023: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:42: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.7.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:46: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.8.wasm:000001a: error: type mismatch at end of function, expected [] but got [i32] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:50: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.9.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:56: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.10.wasm:000001a: error: type mismatch at end of function, expected [] but got [any] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:60: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.11.wasm:000001c: error: type mismatch at end of function, expected [] but got [any] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:64: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.12.wasm:000001e: error: type mismatch at end of function, expected [] but got [i32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:71: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.13.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:77: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.14.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:83: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.15.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:89: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.16.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:95: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.17.wasm:000001e: error: type mismatch at end of block, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:101: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.18.wasm:0000024: error: type mismatch in block, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:107: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.19.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:113: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.20.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:119: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.21.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:125: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.22.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000022: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:132: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.23.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:138: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.24.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001e: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:144: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.25.wasm:000001d: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001d: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:150: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.26.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:156: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.27.wasm:000001d: error: type mismatch at end of block, expected [] but got [i32] + 000001d: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:162: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.28.wasm:0000025: error: type mismatch in block, expected [i32] but got [f32] + 0000025: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:168: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.29.wasm:000001f: error: type mismatch at end of loop, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:174: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.30.wasm:0000023: error: type mismatch in loop, expected [i32] but got [f32] + 0000023: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:180: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.31.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:186: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.32.wasm:0000021: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000021: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:193: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.33.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:199: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.34.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:205: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.35.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:211: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.36.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001e: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:217: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.37.wasm:000001d: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001d: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:223: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.38.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:229: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.39.wasm:000001d: error: type mismatch at end of block, expected [] but got [i32] + 000001d: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:235: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.40.wasm:0000023: error: type mismatch in block, expected [i32] but got [f32] + 0000023: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:241: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.41.wasm:000001f: error: type mismatch at end of loop, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:247: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.42.wasm:0000021: error: type mismatch in loop, expected [i32] but got [f32] + 0000021: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:253: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.43.wasm:000001b: error: type mismatch at end of function, expected [] but got [i32] + 000001b: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:259: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.44.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [f32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:265: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.45.wasm:000001e: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001e: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:271: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.46.wasm:0000020: error: type mismatch in i32.eqz, expected [i32] but got [] + 0000020: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:277: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.47.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:284: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.48.wasm:000001f: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001f: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:290: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.49.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:296: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.50.wasm:0000020: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000020: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:302: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.51.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:308: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.52.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:314: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.53.wasm:0000026: error: type mismatch in block, expected [i32] but got [... f32] + out/test/spec/gc/unreached-invalid/unreached-invalid.53.wasm:0000026: error: type mismatch at end of block, expected [] but got [i32] + 0000026: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:321: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.54.wasm:0000022: error: type mismatch at end of loop, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:327: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.55.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:334: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.56.wasm:000001e: error: type mismatch at end of function, expected [] but got [i32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:340: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.57.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000022: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:348: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.58.wasm:0000020: error: type mismatch in i32.eqz, expected [i32] but got [] + 0000020: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:354: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.59.wasm:0000022: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000022: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:360: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.60.wasm:0000021: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 0000021: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:366: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.61.wasm:0000024: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000024: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:372: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.62.wasm:0000021: error: type mismatch at end of block, expected [] but got [i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:378: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.63.wasm:0000027: error: type mismatch in block, expected [i32] but got [... f32] + out/test/spec/gc/unreached-invalid/unreached-invalid.63.wasm:0000027: error: type mismatch at end of block, expected [] but got [i32] + 0000027: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:384: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.64.wasm:0000023: error: type mismatch at end of loop, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:390: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.65.wasm:0000025: error: type mismatch in loop, expected [i32] but got [f32] + 0000025: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:396: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.66.wasm:000001f: error: type mismatch at end of function, expected [] but got [i32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:402: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.67.wasm:0000023: error: type mismatch in implicit return, expected [i32] but got [f32] + 0000023: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:409: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.68.wasm:000001d: error: type mismatch in i32.eqz, expected [i32] but got [] + 000001d: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:415: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.69.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:421: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.70.wasm:000001e: error: type mismatch in f32.eq, expected [f32, f32] but got [i32] + 000001e: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:427: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.71.wasm:0000023: error: type mismatch in f32.eq, expected [f32, f32] but got [i32, f32] + 0000023: error: OnCompareExpr callback failed +out/test/spec/gc/unreached-invalid.wast:433: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.72.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:439: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.73.wasm:0000022: error: type mismatch in `if true` branch, expected [i32] but got [f32] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:445: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.74.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:451: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.75.wasm:0000024: error: type mismatch in block, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:457: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.76.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:463: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.77.wasm:0000024: error: type mismatch in loop, expected [i32] but got [f32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:470: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.78.wasm:0000025: error: type mismatch in return, expected [i32] but got [f64] + 0000025: error: OnReturnExpr callback failed +out/test/spec/gc/unreached-invalid.wast:477: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.79.wasm:0000029: error: type mismatch in br, expected [i32] but got [f64] + 0000029: error: OnBrExpr callback failed +out/test/spec/gc/unreached-invalid.wast:484: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.80.wasm:0000021: error: type mismatch in br_if, expected [i32] but got [f32] + 0000021: error: OnBrIfExpr callback failed +out/test/spec/gc/unreached-invalid.wast:490: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.81.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:498: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.82.wasm:0000024: error: type mismatch in block, expected [f32] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:507: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.83.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:515: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.84.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [f32] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/gc/unreached-invalid.wast:521: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.85.wasm:0000025: error: type mismatch in br_table, expected [i32] but got [f32] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/gc/unreached-invalid.wast:527: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.86.wasm:0000023: error: br_table labels have inconsistent types: expected [f32], got [] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/gc/unreached-invalid.wast:540: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.87.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:546: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.88.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:552: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.89.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000022: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:558: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.90.wasm:0000023: error: type mismatch at end of block, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:565: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.91.wasm:0000021: error: type mismatch at end of block, expected [] but got [i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:571: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.92.wasm:0000022: error: type mismatch in block, expected [i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:577: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.93.wasm:0000024: error: type mismatch in block, expected [i32] but got [i64] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:584: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.94.wasm:0000023: error: type mismatch at end of block, expected [] but got [i32] + 0000023: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:590: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.95.wasm:0000025: error: type mismatch in block, expected [i32] but got [] + 0000025: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:596: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.96.wasm:0000027: error: type mismatch in block, expected [i32] but got [i64] + 0000027: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:604: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.97.wasm:0000024: error: type mismatch at end of block, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:611: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.98.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:617: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.99.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [] + 0000022: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:623: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.100.wasm:0000024: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000024: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:629: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.101.wasm:0000025: error: type mismatch at end of block, expected [] but got [i32] + 0000025: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:637: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.102.wasm:0000020: error: type mismatch at end of loop, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:643: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.103.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:649: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.104.wasm:0000022: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000022: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:656: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.105.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:662: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.106.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [] + 0000020: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:669: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.107.wasm:000001d: error: type mismatch at end of function, expected [] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:676: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.108.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/unreached-invalid.wast:687: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.109.wasm:000001c: error: type mismatch in i64.extend_i32_u, expected [i32] but got [i64] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/unreached-invalid.wast:698: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.110.wasm:000001a: error: type mismatch in f32.abs, expected [f32] but got [(ref something)] + 000001a: error: OnUnaryExpr callback failed +out/test/spec/gc/unreached-invalid.wast:710: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.111.wasm:000001f: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:715: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.112.wasm:000001f: error: type mismatch in select, expected [i32, i32, i32] but got [i64, i32, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:721: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.113.wasm:000001f: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, i64] + 000001f: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:726: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.114.wasm:000001d: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i64] + 000001d: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:731: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.115.wasm:000001b: error: type mismatch in select, expected [any, any, i32] but got [i64] + 000001b: error: OnSelectExpr callback failed +out/test/spec/gc/unreached-invalid.wast:737: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.116.wasm:000001f: error: type mismatch in implicit return, expected [i32] but got [i64] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:744: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.117.wasm:000001a: error: type mismatch at end of function, expected [] but got [any] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:749: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.118.wasm:0000026: error: type mismatch in br_table, expected [i32] but got [externref] + 0000026: error: OnBrTableExpr callback failed +out/test/spec/gc/unreached-invalid.wast:764: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.119.wasm:0000021: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000021: error: EndFunctionBody callback failed +out/test/spec/gc/unreached-invalid.wast:774: assert_invalid passed: + out/test/spec/gc/unreached-invalid/unreached-invalid.120.wasm:0000022: error: type mismatch at end of function, expected [] but got [i32] + 0000022: error: EndFunctionBody callback failed +121/121 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/unreached-valid.txt b/test/spec/gc/unreached-valid.txt new file mode 100644 index 0000000000..8859128622 --- /dev/null +++ b/test/spec/gc/unreached-valid.txt @@ -0,0 +1,16 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/unreached-valid.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/unreached-valid.wast:48: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:49: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:50: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:51: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:53: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:54: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:55: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:56: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:58: assert_trap passed: unreachable executed +out/test/spec/gc/unreached-valid.wast:77: assert_trap passed: unreachable executed +13/13 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/ref_is_null.txt b/test/spec/ref_is_null.txt index 45765058d7..4c214a879d 100644 --- a/test/spec/ref_is_null.txt +++ b/test/spec/ref_is_null.txt @@ -4,10 +4,10 @@ init(externref:1) => deinit() => out/test/spec/ref_is_null.wast:52: assert_invalid passed: - out/test/spec/ref_is_null/ref_is_null.1.wasm:000001b: error: type mismatch in ref.is_null, expected [reference] but got [i32] + out/test/spec/ref_is_null/ref_is_null.1.wasm:000001b: error: type mismatch in ref.is_null, expected [funcref] but got [i32] 000001b: error: OnRefIsNullExpr callback failed out/test/spec/ref_is_null.wast:56: assert_invalid passed: - out/test/spec/ref_is_null/ref_is_null.2.wasm:0000018: error: type mismatch in ref.is_null, expected [reference] but got [] + out/test/spec/ref_is_null/ref_is_null.2.wasm:0000018: error: type mismatch in ref.is_null, expected [funcref] but got [] 0000018: error: OnRefIsNullExpr callback failed 16/16 tests passed. ;;; STDOUT ;;) From 1a8e2ac5e24c1b99f9d8efc4cc925df6353808f1 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Thu, 5 Jun 2025 07:12:32 +0000 Subject: [PATCH 5/6] Implement GC opcodes --- include/wabt/binary-reader-logging.h | 24 + include/wabt/binary-reader-nop.h | 46 + include/wabt/binary-reader.h | 24 + include/wabt/expr-visitor.h | 42 + include/wabt/interp/interp-inl.h | 118 +- include/wabt/interp/interp.h | 88 + include/wabt/interp/istream.h | 6 + include/wabt/ir.h | 101 +- include/wabt/opcode.def | 34 + include/wabt/opcode.h | 3 +- include/wabt/shared-validator.h | 26 +- include/wabt/token.def | 30 +- include/wabt/type-checker.h | 46 + include/wabt/wast-parser.h | 2 + src/binary-reader-ir.cc | 123 ++ src/binary-reader-logging.cc | 44 + src/binary-reader.cc | 226 +- src/binary-writer-spec.cc | 62 +- src/binary-writer.cc | 157 +- src/c-writer.cc | 19 + src/expr-visitor.cc | 81 + src/interp/binary-reader-interp.cc | 206 ++ src/interp/interp-util.cc | 45 +- src/interp/interp.cc | 600 +++++- src/interp/istream.cc | 103 + src/ir-util.cc | 40 +- src/ir.cc | 45 +- src/lexer-keywords.txt | 33 + src/opcode.cc | 30 + src/prebuilt/lexer-keywords.cc | 2984 ++++++++++++++------------ src/resolve-names.cc | 149 +- src/shared-validator.cc | 281 ++- src/tools/spectest-interp.cc | 149 +- src/type-checker.cc | 409 +++- src/validator.cc | 192 +- src/wast-parser.cc | 290 ++- src/wat-writer.cc | 172 +- test/spec/gc/array.txt | 37 + test/spec/gc/array_copy.txt | 25 + test/spec/gc/array_fill.txt | 19 + test/spec/gc/array_init_data.txt | 23 + test/spec/gc/array_init_elem.txt | 27 + test/spec/gc/br_on_cast.txt | 27 + test/spec/gc/br_on_cast_fail.txt | 27 + test/spec/gc/extern.txt | 7 + test/spec/gc/i31.txt | 16 + test/spec/gc/ref_cast.txt | 38 + test/spec/gc/ref_eq.txt | 25 + test/spec/gc/ref_null.txt | 6 + test/spec/gc/ref_test.txt | 7 + test/spec/gc/struct.txt | 22 + 51 files changed, 5784 insertions(+), 1552 deletions(-) create mode 100644 test/spec/gc/array.txt create mode 100644 test/spec/gc/array_copy.txt create mode 100644 test/spec/gc/array_fill.txt create mode 100644 test/spec/gc/array_init_data.txt create mode 100644 test/spec/gc/array_init_elem.txt create mode 100644 test/spec/gc/br_on_cast.txt create mode 100644 test/spec/gc/br_on_cast_fail.txt create mode 100644 test/spec/gc/extern.txt create mode 100644 test/spec/gc/i31.txt create mode 100644 test/spec/gc/ref_cast.txt create mode 100644 test/spec/gc/ref_eq.txt create mode 100644 test/spec/gc/ref_null.txt create mode 100644 test/spec/gc/ref_test.txt create mode 100644 test/spec/gc/struct.txt diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 8a47f5d1f1..56eb85eec1 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -165,6 +165,17 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnOpcodeV128(v128 value) override; Result OnOpcodeBlockSig(Type sig_type) override; Result OnOpcodeType(Type type) override; + Result OnArrayCopyExpr(Index dst_type_index, Index src_type_index) override; + Result OnArrayFillExpr(Index type_index) override; + Result OnArrayGetExpr(Opcode opcode, Index type_index) override; + Result OnArrayInitDataExpr(Index type_index, Index data_index) override; + Result OnArrayInitElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewExpr(Index type_index) override; + Result OnArrayNewDataExpr(Index type_index, Index data_index) override; + Result OnArrayNewDefaultExpr(Index type_index) override; + Result OnArrayNewElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewFixedExpr(Index type_index, Index count) override; + Result OnArraySetExpr(Index type_index) override; Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -185,6 +196,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) override; Result OnBrOnNonNullExpr(Index depth) override; Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, @@ -204,6 +219,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; + Result OnGCUnaryExpr(Opcode opcode) override; Result OnGlobalGetExpr(Index global_index) override; Result OnGlobalSetExpr(Index global_index) override; Result OnI32ConstExpr(uint32_t value) override; @@ -232,9 +248,11 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnTableSizeExpr(Index table) override; Result OnTableFillExpr(Index table) override; Result OnRefAsNonNullExpr() override; + Result OnRefCastExpr(Type type) override; Result OnRefFuncExpr(Index index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; + Result OnRefTestExpr(Type type) override; Result OnNopExpr() override; Result OnRethrowExpr(Index depth) override; Result OnReturnCallExpr(Index func_index) override; @@ -246,6 +264,12 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Index memidx, Address alignment_log2, Address offset) override; + Result OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) override; + Result OnStructNewExpr(Index type_index) override; + Result OnStructNewDefaultExpr(Index type_index) override; + Result OnStructSetExpr(Index type_index, Index field_index) override; Result OnThrowExpr(Index tag_index) override; Result OnThrowRefExpr() override; Result OnTryExpr(Type sig_type) override; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index 70d36e7cc9..f57ab3d311 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -219,6 +219,31 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnOpcodeV128(v128 value) override { return Result::Ok; } Result OnOpcodeBlockSig(Type sig_type) override { return Result::Ok; } Result OnOpcodeType(Type type) override { return Result::Ok; } + Result OnArrayCopyExpr(Index dst_type_index, Index src_type_index) override { + return Result::Ok; + } + Result OnArrayFillExpr(Index type_index) override { return Result::Ok; } + Result OnArrayGetExpr(Opcode opcode, Index type_index) override { + return Result::Ok; + } + Result OnArrayInitDataExpr(Index type_index, Index data_index) override { + return Result::Ok; + } + Result OnArrayInitElemExpr(Index type_index, Index elem_index) override { + return Result::Ok; + } + Result OnArrayNewExpr(Index type_index) override { return Result::Ok; } + Result OnArrayNewDataExpr(Index type_index, Index data_index) override { + return Result::Ok; + } + Result OnArrayNewDefaultExpr(Index type_index) override { return Result::Ok; } + Result OnArrayNewElemExpr(Index type_index, Index elem_index) override { + return Result::Ok; + } + Result OnArrayNewFixedExpr(Index type_index, Index count) override { + return Result::Ok; + } + Result OnArraySetExpr(Index type_index) override { return Result::Ok; } Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -254,6 +279,12 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnBlockExpr(Type sig_type) override { return Result::Ok; } Result OnBrExpr(Index depth) override { return Result::Ok; } Result OnBrIfExpr(Index depth) override { return Result::Ok; } + Result OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) override { + return Result::Ok; + } Result OnBrOnNonNullExpr(Index depth) override { return Result::Ok; } Result OnBrOnNullExpr(Index depth) override { return Result::Ok; } Result OnBrTableExpr(Index num_targets, @@ -277,6 +308,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnF32ConstExpr(uint32_t value_bits) override { return Result::Ok; } Result OnF64ConstExpr(uint64_t value_bits) override { return Result::Ok; } Result OnV128ConstExpr(v128 value_bits) override { return Result::Ok; } + Result OnGCUnaryExpr(Opcode opcode) override { return Result::Ok; } Result OnGlobalGetExpr(Index global_index) override { return Result::Ok; } Result OnGlobalSetExpr(Index global_index) override { return Result::Ok; } Result OnI32ConstExpr(uint32_t value) override { return Result::Ok; } @@ -315,9 +347,11 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnTableSizeExpr(Index table_index) override { return Result::Ok; } Result OnTableFillExpr(Index table_index) override { return Result::Ok; } Result OnRefAsNonNullExpr() override { return Result::Ok; } + Result OnRefCastExpr(Type type) override { return Result::Ok; } Result OnRefFuncExpr(Index func_index) override { return Result::Ok; } Result OnRefNullExpr(Type type) override { return Result::Ok; } Result OnRefIsNullExpr() override { return Result::Ok; } + Result OnRefTestExpr(Type type) override { return Result::Ok; } Result OnNopExpr() override { return Result::Ok; } Result OnRethrowExpr(Index depth) override { return Result::Ok; } Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; } @@ -335,6 +369,18 @@ class BinaryReaderNop : public BinaryReaderDelegate { Address offset) override { return Result::Ok; } + Result OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) override { + return Result::Ok; + } + Result OnStructNewExpr(Index type_index) override { return Result::Ok; } + Result OnStructNewDefaultExpr(Index type_index) override { + return Result::Ok; + } + Result OnStructSetExpr(Index type_index, Index field_index) override { + return Result::Ok; + } Result OnThrowExpr(Index depth) override { return Result::Ok; } Result OnThrowRefExpr() override { return Result::Ok; } Result OnTryExpr(Type sig_type) override { return Result::Ok; } diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index b811cb2ba9..89b2e31b96 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -237,6 +237,17 @@ class BinaryReaderDelegate { virtual Result OnOpcodeV128(v128 value) = 0; virtual Result OnOpcodeBlockSig(Type sig_type) = 0; virtual Result OnOpcodeType(Type type) = 0; + virtual Result OnArrayCopyExpr(Index dst_type_index, Index src_type_index) = 0; + virtual Result OnArrayFillExpr(Index type_index) = 0; + virtual Result OnArrayGetExpr(Opcode opcode, Index type_index) = 0; + virtual Result OnArrayInitDataExpr(Index type_index, Index data_index) = 0; + virtual Result OnArrayInitElemExpr(Index type_index, Index elem_index) = 0; + virtual Result OnArrayNewExpr(Index type_index) = 0; + virtual Result OnArrayNewDataExpr(Index type_index, Index data_index) = 0; + virtual Result OnArrayNewDefaultExpr(Index type_index) = 0; + virtual Result OnArrayNewElemExpr(Index type_index, Index elem_index) = 0; + virtual Result OnArrayNewFixedExpr(Index type_index, Index count) = 0; + virtual Result OnArraySetExpr(Index type_index) = 0; virtual Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -266,6 +277,10 @@ class BinaryReaderDelegate { virtual Result OnBlockExpr(Type sig_type) = 0; virtual Result OnBrExpr(Index depth) = 0; virtual Result OnBrIfExpr(Index depth) = 0; + virtual Result OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) = 0; virtual Result OnBrOnNonNullExpr(Index depth) = 0; virtual Result OnBrOnNullExpr(Index depth) = 0; virtual Result OnBrTableExpr(Index num_targets, @@ -285,6 +300,7 @@ class BinaryReaderDelegate { virtual Result OnF32ConstExpr(uint32_t value_bits) = 0; virtual Result OnF64ConstExpr(uint64_t value_bits) = 0; virtual Result OnV128ConstExpr(v128 value_bits) = 0; + virtual Result OnGCUnaryExpr(Opcode opcode) = 0; virtual Result OnGlobalGetExpr(Index global_index) = 0; virtual Result OnGlobalSetExpr(Index global_index) = 0; virtual Result OnI32ConstExpr(uint32_t value) = 0; @@ -313,9 +329,11 @@ class BinaryReaderDelegate { virtual Result OnTableSizeExpr(Index table_index) = 0; virtual Result OnTableFillExpr(Index table_index) = 0; virtual Result OnRefAsNonNullExpr() = 0; + virtual Result OnRefCastExpr(Type type) = 0; virtual Result OnRefFuncExpr(Index func_index) = 0; virtual Result OnRefNullExpr(Type type) = 0; virtual Result OnRefIsNullExpr() = 0; + virtual Result OnRefTestExpr(Type type) = 0; virtual Result OnNopExpr() = 0; virtual Result OnRethrowExpr(Index depth) = 0; virtual Result OnReturnExpr() = 0; @@ -328,6 +346,12 @@ class BinaryReaderDelegate { Index memidx, Address alignment_log2, Address offset) = 0; + virtual Result OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) = 0; + virtual Result OnStructNewExpr(Index type_index) = 0; + virtual Result OnStructNewDefaultExpr(Index type_index) = 0; + virtual Result OnStructSetExpr(Index type_index, Index field_index) = 0; virtual Result OnThrowExpr(Index tag_index) = 0; virtual Result OnThrowRefExpr() = 0; virtual Result OnTryExpr(Type sig_type) = 0; diff --git a/include/wabt/expr-visitor.h b/include/wabt/expr-visitor.h index cef8025baa..50a8155562 100644 --- a/include/wabt/expr-visitor.h +++ b/include/wabt/expr-visitor.h @@ -73,6 +73,7 @@ class ExprVisitor::Delegate { virtual Result EndBlockExpr(BlockExpr*) = 0; virtual Result OnBrExpr(BrExpr*) = 0; virtual Result OnBrIfExpr(BrIfExpr*) = 0; + virtual Result OnBrOnCastExpr(BrOnCastExpr*) = 0; virtual Result OnBrOnNonNullExpr(BrOnNonNullExpr*) = 0; virtual Result OnBrOnNullExpr(BrOnNullExpr*) = 0; virtual Result OnBrTableExpr(BrTableExpr*) = 0; @@ -145,6 +146,24 @@ class ExprVisitor::Delegate { virtual Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) = 0; virtual Result OnLoadSplatExpr(LoadSplatExpr*) = 0; virtual Result OnLoadZeroExpr(LoadZeroExpr*) = 0; + virtual Result OnArrayCopyExpr(ArrayCopyExpr*) = 0; + virtual Result OnArrayFillExpr(ArrayFillExpr*) = 0; + virtual Result OnArrayGetExpr(ArrayGetExpr*) = 0; + virtual Result OnArrayInitDataExpr(ArrayInitDataExpr*) = 0; + virtual Result OnArrayInitElemExpr(ArrayInitElemExpr*) = 0; + virtual Result OnArrayNewExpr(ArrayNewExpr*) = 0; + virtual Result OnArrayNewDataExpr(ArrayNewDataExpr*) = 0; + virtual Result OnArrayNewDefaultExpr(ArrayNewDefaultExpr*) = 0; + virtual Result OnArrayNewElemExpr(ArrayNewElemExpr*) = 0; + virtual Result OnArrayNewFixedExpr(ArrayNewFixedExpr*) = 0; + virtual Result OnArraySetExpr(ArraySetExpr*) = 0; + virtual Result OnGCUnaryExpr(GCUnaryExpr*) = 0; + virtual Result OnRefCastExpr(RefCastExpr*) = 0; + virtual Result OnRefTestExpr(RefTestExpr*) = 0; + virtual Result OnStructGetExpr(StructGetExpr*) = 0; + virtual Result OnStructNewExpr(StructNewExpr*) = 0; + virtual Result OnStructNewDefaultExpr(StructNewDefaultExpr*) = 0; + virtual Result OnStructSetExpr(StructSetExpr*) = 0; }; class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { @@ -154,6 +173,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override { return Result::Ok; } Result OnBrExpr(BrExpr*) override { return Result::Ok; } Result OnBrIfExpr(BrIfExpr*) override { return Result::Ok; } + Result OnBrOnCastExpr(BrOnCastExpr*) override { return Result::Ok; }; Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override { return Result::Ok; }; Result OnBrOnNullExpr(BrOnNullExpr*) override { return Result::Ok; }; Result OnBrTableExpr(BrTableExpr*) override { return Result::Ok; } @@ -230,6 +250,28 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override { return Result::Ok; } Result OnLoadSplatExpr(LoadSplatExpr*) override { return Result::Ok; } Result OnLoadZeroExpr(LoadZeroExpr*) override { return Result::Ok; } + Result OnArrayCopyExpr(ArrayCopyExpr*) override { return Result::Ok; } + Result OnArrayFillExpr(ArrayFillExpr*) override { return Result::Ok; } + Result OnArrayGetExpr(ArrayGetExpr*) override { return Result::Ok; } + Result OnArrayInitDataExpr(ArrayInitDataExpr*) override { return Result::Ok; } + Result OnArrayInitElemExpr(ArrayInitElemExpr*) override { return Result::Ok; } + Result OnArrayNewExpr(ArrayNewExpr*) override { return Result::Ok; } + Result OnArrayNewDataExpr(ArrayNewDataExpr*) override { return Result::Ok; } + Result OnArrayNewDefaultExpr(ArrayNewDefaultExpr*) override { + return Result::Ok; + } + Result OnArrayNewElemExpr(ArrayNewElemExpr*) override { return Result::Ok; } + Result OnArrayNewFixedExpr(ArrayNewFixedExpr*) override { return Result::Ok; } + Result OnArraySetExpr(ArraySetExpr*) override { return Result::Ok; } + Result OnGCUnaryExpr(GCUnaryExpr*) override { return Result::Ok; } + Result OnRefCastExpr(RefCastExpr*) override { return Result::Ok; } + Result OnRefTestExpr(RefTestExpr*) override { return Result::Ok; } + Result OnStructGetExpr(StructGetExpr*) override { return Result::Ok; } + Result OnStructNewExpr(StructNewExpr*) override { return Result::Ok; } + Result OnStructNewDefaultExpr(StructNewDefaultExpr*) override { + return Result::Ok; + } + Result OnStructSetExpr(StructSetExpr*) override { return Result::Ok; } }; } // namespace wabt diff --git a/include/wabt/interp/interp-inl.h b/include/wabt/interp/interp-inl.h index bc83b93938..d69cd21f58 100644 --- a/include/wabt/interp/interp-inl.h +++ b/include/wabt/interp/interp-inl.h @@ -32,6 +32,50 @@ inline bool operator!=(Ref lhs, Ref rhs) { return lhs.index != rhs.index; } +// static +inline Ref Ref::CreateI31Val(size_t value) { + assert((value & 0x7fffffff) < kI31Value); + return Ref((value & 0x7fffffff) | kI31Value); +} + +// static +inline Ref Ref::CreateHostVal(size_t value) { + assert(value < kHostValue); + return Ref(value | kHostValue); +} + +inline bool Ref::IsI31Val() const { + return (index & kI31Value) != 0; +} + +inline bool Ref::IsHostVal() const { + return (index & (kI31Value | kHostValue)) == kHostValue; +} + +inline bool Ref::IsI31OrHostVal() const { + return (index & (kI31Value | kHostValue)) != 0; +} + +inline u32 Ref::GetS32Val() const { + assert(IsI31Val()); + return static_cast(static_cast(index) << 1) >> 1; +} + +inline u32 Ref::GetU32Val() const { + assert(IsI31Val()); + return static_cast(index & 0x7fffffff); +} + +inline size_t Ref::GetHostVal() const { + assert(IsHostVal()); + return index ^ kHostValue; +} + +inline size_t Ref::IsAnyHostVal() const { + assert(IsHostVal()); + return index == (kHostValue | kAnyHostValue); +} + //// ExternType //// inline ExternType::ExternType(ExternKind kind) : kind(kind) {} @@ -165,6 +209,7 @@ inline Frame::Frame(Ref func, //// FreeList //// template <> inline bool FreeList::IsUsed(Index index) const { + assert(index < list_.size()); return (list_[index].index & refFreeBit) == 0; } @@ -201,6 +246,7 @@ inline void FreeList::Delete(Index index) { template bool FreeList::IsUsed(Index index) const { + assert(index < list_.size()); return (reinterpret_cast(list_[index]) & ptrFreeBit) == 0; } @@ -497,12 +543,13 @@ template <> inline void WABT_VECTORCALL Value::Set(Ref val) { ref_ = val; S //// Store //// inline bool Store::IsValid(Ref ref) const { - return objects_.IsUsed(ref.index) && objects_.Get(ref.index); + return ref.index >= Ref::kHostValue || objects_.IsUsed(ref.index); } template bool Store::Is(Ref ref) const { - return objects_.IsUsed(ref.index) && isa(objects_.Get(ref.index)); + return ref.index < Ref::kHostValue && objects_.IsUsed(ref.index) && + isa(objects_.Get(ref.index)); } template @@ -902,6 +949,73 @@ inline const TagType& Tag::type() const { return type_; } +//// Array //// +// static +inline bool Array::classof(const Object* obj) { + return obj->kind() == skind; +} + +inline Array::Ptr Array::New(Store& store, + u32 size, + Index type_index, + Module* mod) { + return store.Alloc(store, size, type_index, mod); +} + +inline Index Array::Size() const { + return static_cast(items_.size()); +} + +inline Value Array::GetItem(Index idx) const { + return items_[idx]; +} + +inline void Array::SetItem(Index idx, Value value) { + items_[idx] = value; +} + +inline Values& Array::GetItems() { + return items_; +} + +inline Index Array::GetTypeIndex() const { + return type_index_; +} + +inline Ref Array::GetModule() const { + return module_; +} + +//// Struct //// +// static +inline bool Struct::classof(const Object* obj) { + return obj->kind() == skind; +} + +inline Struct::Ptr Struct::New(Store& store, Index type_index, Module* mod) { + return store.Alloc(store, type_index, mod); +} + +inline Index Struct::Size() const { + return static_cast(fields_.size()); +} + +inline Value Struct::GetField(Index idx) const { + return fields_[idx]; +} + +inline void Struct::SetField(Index idx, Value value) { + fields_[idx] = value; +} + +inline Index Struct::GetTypeIndex() const { + return type_index_; +} + +inline Ref Struct::GetModule() const { + return module_; +} + //// ElemSegment //// inline void ElemSegment::Drop() { elements_.clear(); diff --git a/include/wabt/interp/interp.h b/include/wabt/interp/interp.h index 71434edc64..7828969cd9 100644 --- a/include/wabt/interp/interp.h +++ b/include/wabt/interp/interp.h @@ -89,6 +89,8 @@ enum class ObjectKind { Memory, Global, Tag, + Array, + Struct, Module, Instance, @@ -105,10 +107,24 @@ const char* GetName(ObjectKind); struct Ref { static const Ref Null; + // The highest two bits represent special values. + static const size_t kI31Value = static_cast(1) << (sizeof(size_t) * 8 - 1); + static const size_t kHostValue = static_cast(1) << (sizeof(size_t) * 8 - 2); + static const size_t kAnyHostValue = ~static_cast(0) >> 2; Ref() = default; explicit Ref(size_t index); + static Ref CreateI31Val(size_t value); + static Ref CreateHostVal(size_t value); + bool IsI31Val() const; + bool IsHostVal() const; + bool IsI31OrHostVal() const; + u32 GetS32Val() const; + u32 GetU32Val() const; + size_t GetHostVal() const; + size_t IsAnyHostVal() const; + friend bool operator==(Ref, Ref); friend bool operator!=(Ref, Ref); @@ -999,6 +1015,59 @@ class Tag : public Extern { TagType type_; }; +class Array : public Object { + public: + static bool classof(const Object* obj); + static const ObjectKind skind = ObjectKind::Array; + static const char* GetTypeName() { return "Array"; } + using Ptr = RefPtr; + + static Array::Ptr New(Store&, u32 size, Index type_index, Module* mod); + + bool IsValidRange(u64 offset, u64 size) const; + + Index Size() const; + Value GetItem(Index idx) const; + void SetItem(Index idx, Value value); + Values& GetItems(); + Index GetTypeIndex() const; + Ref GetModule() const; + + private: + friend Store; + explicit Array(Store&, u32 size, Index type_index, Module* mod); + void Mark(Store&) override; + + Ref module_; + Index type_index_; + Values items_; +}; + +class Struct : public Object { + public: + static bool classof(const Object* obj); + static const ObjectKind skind = ObjectKind::Struct; + static const char* GetTypeName() { return "Struct"; } + using Ptr = RefPtr; + + static Struct::Ptr New(Store&, Index type_index, Module* mod); + + Index Size() const; + Value GetField(Index idx) const; + void SetField(Index idx, Value value); + Index GetTypeIndex() const; + Ref GetModule() const; + + private: + friend Store; + explicit Struct(Store&, Index type_index, Module* mod); + void Mark(Store&) override; + + Ref module_; + Index type_index_; + Values fields_; +}; + class ElemSegment { public: explicit ElemSegment(Store& store, const ElemDesc*, RefPtr&); @@ -1167,6 +1236,8 @@ class Thread { void Push(Value); void Push(Ref); + bool CheckRefCast(Ref ref, Type expected); + template using UnopFunc = R WABT_VECTORCALL(T); template @@ -1270,6 +1341,23 @@ class Thread { template RunResult DoAtomicRmwCmpxchg(Instr, Trap::Ptr* out_trap); + RunResult DoArrayCopy(Trap::Ptr* out_trap); + RunResult DoArrayFill(Trap::Ptr* out_trap); + RunResult DoArrayGet(Trap::Ptr* out_trap); + RunResult DoArrayInitElem(Instr, Trap::Ptr* out_trap); + RunResult DoArrayInitData(Instr, Trap::Ptr* out_trap); + RunResult DoArrayGetPacked(Instr, Trap::Ptr* out_trap); + RunResult DoArrayNew(Instr); + RunResult DoArrayNewData(Instr, Trap::Ptr* out_trap); + RunResult DoArrayNewElem(Instr, Trap::Ptr* out_trap); + RunResult DoArrayNewFixed(Instr); + RunResult DoArraySet(Trap::Ptr* out_trap); + RunResult DoBrOnCast(Instr); + RunResult DoRefCast(Instr, Trap::Ptr* out_trap); + RunResult DoRefTest(Instr); + RunResult DoStructGetPacked(Instr, Trap::Ptr* out_trap); + RunResult DoStructNew(Instr); + RunResult DoThrow(Exception::Ptr exn_ref); RunResult StepInternal(Trap::Ptr* out_trap); diff --git a/include/wabt/interp/istream.h b/include/wabt/interp/istream.h index f8eb6a2679..779a750685 100644 --- a/include/wabt/interp/istream.h +++ b/include/wabt/interp/istream.h @@ -47,14 +47,20 @@ enum class InstrKind { Imm_0_Op_1, // i32.eqz Imm_0_Op_2, // i32.add Imm_0_Op_3, // select + Imm_0_Op_4, // array.fill + Imm_0_Op_5, // array.copy Imm_Jump_Op_0, // br Imm_Jump_Op_1, // br_if Imm_Index_Op_0, // global.get Imm_Index_Op_1, // global.set Imm_Index_Op_2, // table.set Imm_Index_Op_3, // memory.fill + Imm_Index_Op_4, // array.init_elem Imm_Index_Op_N, // call + Imm_Index_Index_Op_1, // struct.get_s + Imm_Index_Index_Op_2, // array.new_data Imm_Index_Index_Op_3, // memory.init + Imm_Index_Index_Op_4, // array.init_data Imm_Index_Index_Op_N, // call_indirect Imm_Index_Offset_Op_1, // i32.load Imm_Index_Offset_Op_2, // i32.store diff --git a/include/wabt/ir.h b/include/wabt/ir.h index d220bd3c69..aa74ef167e 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -110,6 +110,7 @@ using VarVector = std::vector; struct Const { static constexpr uintptr_t kRefNullBits = ~uintptr_t(0); + static constexpr uintptr_t kRefAnyValueBits = ~uintptr_t(1); Const() : Const(Type::I32, uint32_t(0)) {} @@ -180,9 +181,16 @@ struct Const { set_f64(0); set_expected_nan(0, nan); } - void set_funcref() { From(Type::FuncRef, 0); } + void set_arrayref() { From(Type(Type::ArrayRef, Type::ReferenceNonNull), 0); } + // AnyRef represents ref.host. + void set_anyref(uintptr_t x) { From(Type::AnyRef, x); } + void set_any(uintptr_t x) { From(Type(Type::AnyRef, Type::ReferenceNonNull), x); } + void set_eqref() { From(Type(Type::EqRef, Type::ReferenceNonNull), 0); } void set_externref(uintptr_t x) { From(Type::ExternRef, x); } void set_extern(uintptr_t x) { From(Type(Type::ExternRef, Type::ReferenceNonNull), x); } + void set_funcref() { From(Type::FuncRef, 0); } + void set_i31ref() { From(Type(Type::I31Ref, Type::ReferenceNonNull), 0); } + void set_structref() { From(Type(Type::StructRef, Type::ReferenceNonNull), 0); } void set_null(Type type) { From(type, kRefNullBits); } bool is_expected_nan(int lane = 0) const { @@ -408,6 +416,17 @@ struct FuncDeclaration { }; enum class ExprType { + ArrayCopy, + ArrayFill, + ArrayGet, + ArrayInitData, + ArrayInitElem, + ArrayNew, + ArrayNewData, + ArrayNewDefault, + ArrayNewElem, + ArrayNewFixed, + ArraySet, AtomicLoad, AtomicRmw, AtomicRmwCmpxchg, @@ -419,6 +438,7 @@ enum class ExprType { Block, Br, BrIf, + BrOnCast, BrOnNonNull, BrOnNull, BrTable, @@ -430,6 +450,7 @@ enum class ExprType { Const, Convert, Drop, + GCUnary, GlobalGet, GlobalSet, If, @@ -446,9 +467,11 @@ enum class ExprType { MemorySize, Nop, RefAsNonNull, + RefCast, RefIsNull, RefFunc, RefNull, + RefTest, Rethrow, Return, ReturnCall, @@ -459,6 +482,10 @@ enum class ExprType { SimdLoadLane, SimdStoreLane, SimdShuffleOp, + StructGet, + StructNew, + StructNewDefault, + StructSet, LoadSplat, LoadZero, Store, @@ -478,7 +505,7 @@ enum class ExprType { Unary, Unreachable, - First = AtomicLoad, + First = ArrayCopy, Last = Unreachable }; @@ -615,6 +642,7 @@ class OpcodeExpr : public ExprMixin { using BinaryExpr = OpcodeExpr; using CompareExpr = OpcodeExpr; using ConvertExpr = OpcodeExpr; +using GCUnaryExpr = OpcodeExpr; using UnaryExpr = OpcodeExpr; using TernaryExpr = OpcodeExpr; using RefAsNonNullExpr = OpcodeExpr; @@ -720,6 +748,15 @@ using TableFillExpr = VarExpr; using MemoryInitExpr = MemoryVarExpr; +using ArrayFillExpr = VarExpr; +using ArrayNewExpr = VarExpr; +using ArrayNewDefaultExpr = VarExpr; +using ArraySetExpr = VarExpr; +using RefCastExpr = VarExpr; +using RefTestExpr = VarExpr; +using StructNewExpr = VarExpr; +using StructNewDefaultExpr = VarExpr; + class SelectExpr : public ExprMixin { public: SelectExpr(const Location& loc = Location()) @@ -898,6 +935,62 @@ class AtomicFenceExpr : public ExprMixin { uint32_t consistency_model; }; +class ArrayGetExpr : public ExprMixin { + public: + ArrayGetExpr(Opcode opcode, const Var& type_var, const Location& loc = Location()) + : ExprMixin(loc), opcode(opcode), type_var(type_var) {} + + Opcode opcode; + Var type_var; +}; + +template +class TypeVarExpr : public ExprMixin { + public: + TypeVarExpr(const Var& type_var, const Var& var, const Location& loc = Location()) + : ExprMixin(loc), type_var(type_var), var(var) {} + + Var type_var; + Var var; +}; + +using ArrayCopyExpr = TypeVarExpr; +using ArrayInitDataExpr = TypeVarExpr; +using ArrayInitElemExpr = TypeVarExpr; +using ArrayNewDataExpr = TypeVarExpr; +using ArrayNewElemExpr = TypeVarExpr; +using StructSetExpr = TypeVarExpr; + +class ArrayNewFixedExpr : public ExprMixin { + public: + ArrayNewFixedExpr(const Var& type_var, Index count, const Location& loc = Location()) + : ExprMixin(loc), type_var(type_var), count(count) {} + + Var type_var; + Index count; +}; + +class StructGetExpr : public ExprMixin { + public: + StructGetExpr(Opcode opcode, const Var& type_var, const Var& var, const Location& loc = Location()) + : ExprMixin(loc), opcode(opcode), type_var(type_var), var(var) {} + + Opcode opcode; + Var type_var; + Var var; +}; + +class BrOnCastExpr : public ExprMixin { + public: + BrOnCastExpr(Opcode opcode, const Var& label_var, const Var& type1_var, const Var& type2_var, const Location& loc = Location()) + : ExprMixin(loc), opcode(opcode), label_var(label_var), type1_var(type1_var), type2_var(type2_var) {} + + Opcode opcode; + Var label_var; + Var type1_var; + Var type2_var; +}; + struct Tag { explicit Tag(std::string_view name) : name(name) {} @@ -1291,6 +1384,10 @@ struct Module { Index GetFuncTypeIndex(const FuncSignature&) const; const FuncType* GetFuncType(const Var&) const; FuncType* GetFuncType(const Var&); + const StructType* GetStructType(const Var&) const; + StructType* GetStructType(const Var&); + const ArrayType* GetArrayType(const Var&) const; + ArrayType* GetArrayType(const Var&); Index GetFuncIndex(const Var&) const; const Func* GetFunc(const Var&) const; Func* GetFunc(const Var&); diff --git a/include/wabt/opcode.def b/include/wabt/opcode.def index 901c0359a8..78201cfcbe 100644 --- a/include/wabt/opcode.def +++ b/include/wabt/opcode.def @@ -268,10 +268,44 @@ WABT_OPCODE(___, I32, ___, I32, 0, 0xfc, 0x11, TableFill, "table.fill", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd0, RefNull, "ref.null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd1, RefIsNull, "ref.is_null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd2, RefFunc, "ref.func", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd3, RefEq, "ref.eq", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd4, RefAsNonNull, "ref.as_non_null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd5, BrOnNull, "br_on_null", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd6, BrOnNonNull, "br_on_non_null", "") +/* Garbage collection opcodes */ +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x00, StructNew, "struct.new", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x01, StructNewDefault, "struct.new_default", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x02, StructGet, "struct.get", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x03, StructGetS, "struct.get_s", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x04, StructGetU, "struct.get_u", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x05, StructSet, "struct.set", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x06, ArrayNew, "array.new", "") +WABT_OPCODE(___, I32, ___, ___, 0, 0xfb, 0x07, ArrayNewDefault, "array.new_default", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x08, ArrayNewFixed, "array.new_fixed", "") +WABT_OPCODE(___, I32, I32, ___, 0, 0xfb, 0x09, ArrayNewData, "array.new_data", "") +WABT_OPCODE(___, I32, I32, ___, 0, 0xfb, 0x0a, ArrayNewElem, "array.new_elem", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x0b, ArrayGet, "array.get", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x0c, ArrayGetS, "array.get_s", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x0d, ArrayGetU, "array.get_u", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x0e, ArraySet, "array.set", "") +WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x0f, ArrayLen, "array.len", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x10, ArrayFill, "array.fill", "") +WABT_OPCODE(___, ___, I32, ___, 0, 0xfb, 0x11, ArrayCopy, "array.copy", "") +WABT_OPCODE(___, ___, I32, I32, 0, 0xfb, 0x12, ArrayInitData, "array.init_data", "") +WABT_OPCODE(___, ___, I32, I32, 0, 0xfb, 0x13, ArrayInitElem, "array.init_elem", "") +WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x14, RefTest, "ref.test", "") +WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x15, RefTestNull, "ref.test", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x16, RefCast, "ref.cast", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x17, RefCastNull, "ref.cast", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x18, BrOnCast, "br_on_cast", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x19, BrOnCastFail, "br_on_cast_fail", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x1a, AnyConvertExtern, "any.convert_extern", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0xfb, 0x1b, ExternConvertAny, "extern.convert_any", "") +WABT_OPCODE(___, I32, ___, ___, 0, 0xfb, 0x1c, RefI31, "ref.i31", "") +WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x1d, I31GetS, "i31.get_s", "") +WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x1e, I31GetU, "i31.get_u", "") + /* Simd opcodes */ WABT_OPCODE(V128, I32, ___, ___, 16, 0xfd, 0x00, V128Load, "v128.load", "") WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x01, V128Load8X8S, "v128.load8x8_s", "") diff --git a/include/wabt/opcode.h b/include/wabt/opcode.h index a7c7b2495a..e63658852a 100644 --- a/include/wabt/opcode.h +++ b/include/wabt/opcode.h @@ -84,7 +84,7 @@ struct Opcode { Address GetAlignment(Address alignment) const; static bool IsPrefixByte(uint8_t byte) { - return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix; + return byte == kMathPrefix || byte == kThreadsPrefix || byte == kGarbageCollectionPrefix || byte == kSimdPrefix; } bool IsEnabled(const Features& features) const; @@ -93,6 +93,7 @@ struct Opcode { private: static constexpr uint32_t kMathPrefix = 0xfc; static constexpr uint32_t kThreadsPrefix = 0xfe; + static constexpr uint32_t kGarbageCollectionPrefix = 0xfb; static constexpr uint32_t kSimdPrefix = 0xfd; struct Info { diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index 7bcda66e13..c4ad8ac7e4 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -115,6 +115,17 @@ class SharedValidator { Result EndFunctionBody(const Location&); Result OnLocalDecl(const Location&, Index count, Type type); + Result OnArrayCopy(const Location&, Var dst_type, Var src_type); + Result OnArrayFill(const Location&, Var type); + Result OnArrayGet(const Location&, Opcode, Var type); + Result OnArrayInitData(const Location&, Var type, Var segment_var); + Result OnArrayInitElem(const Location&, Var type, Var segment_var); + Result OnArrayNew(const Location&, Var type); + Result OnArrayNewData(const Location&, Var type, Var segment_var); + Result OnArrayNewDefault(const Location&, Var type); + Result OnArrayNewElem(const Location&, Var type, Var segment_var); + Result OnArrayNewFixed(const Location&, Var type, Index count); + Result OnArraySet(const Location&, Var type); Result OnAtomicFence(const Location&, uint32_t consistency_model); Result OnAtomicLoad(const Location&, Opcode, @@ -150,6 +161,10 @@ class SharedValidator { Result OnBlock(const Location&, Type sig_type); Result OnBr(const Location&, Var depth); Result OnBrIf(const Location&, Var depth); + Result OnBrOnCast(const Location&, + Opcode, Var depth, + Var type1_var, + Var type2_var); Result OnBrOnNonNull(const Location&, Var depth); Result OnBrOnNull(const Location&, Var depth); Result BeginBrTable(const Location&); @@ -168,6 +183,7 @@ class SharedValidator { Result OnElemDrop(const Location&, Var segment_var); Result OnElse(const Location&); Result OnEnd(const Location&); + Result OnGCUnary(const Location&, Opcode); Result OnGlobalGet(const Location&, Var); Result OnGlobalSet(const Location&, Var); Result OnIf(const Location&, Type sig_type); @@ -193,9 +209,11 @@ class SharedValidator { Result OnMemorySize(const Location&, Var memidx); Result OnNop(const Location&); Result OnRefAsNonNull(const Location&); + Result OnRefCast(const Location&, Var type_var); Result OnRefFunc(const Location&, Var func_var); Result OnRefIsNull(const Location&); Result OnRefNull(const Location&, Var func_type_var); + Result OnRefTest(const Location&, Var type_var); Result OnRethrow(const Location&, Var depth); Result OnReturnCall(const Location&, Var func_var); Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var); @@ -221,6 +239,10 @@ class SharedValidator { Var memidx, Address align, Address offset); + Result OnStructGet(const Location&, Opcode, Var type, Var field); + Result OnStructNew(const Location&, Var type); + Result OnStructNewDefault(const Location&, Var type); + Result OnStructSet(const Location&, Var type, Var field); Result OnTableCopy(const Location&, Var dst_var, Var src_var); Result OnTableFill(const Location&, Var table_var); Result OnTableGet(const Location&, Var table_var); @@ -312,7 +334,9 @@ class SharedValidator { const std::vector& values, T* out, const char* desc); - Result CheckFuncTypeIndex(Var sig_var, FuncType* out = nullptr); + Result CheckFuncTypeIndex(Var sig_var, FuncType* out); + Result CheckStructTypeIndex(Var type_var, Type* out_ref, StructType* out); + Result CheckArrayTypeIndex(Var type_var, Type* out_ref, TypeMut* out); Result CheckFuncIndex(Var func_var, FuncType* out = nullptr); Result CheckTableIndex(Var table_var, TableType* out = nullptr); Result CheckMemoryIndex(Var memory_var, MemoryType* out = nullptr); diff --git a/include/wabt/token.def b/include/wabt/token.def index bebe36a696..f22cdb9c77 100644 --- a/include/wabt/token.def +++ b/include/wabt/token.def @@ -61,6 +61,9 @@ WABT_TOKEN(Output, "output") WABT_TOKEN(PageSize, "pagesize") WABT_TOKEN(Param, "param") WABT_TOKEN(Ref, "ref") +WABT_TOKEN(RefArray, "ref.array") +WABT_TOKEN(RefHost, "ref.host") +WABT_TOKEN(RefStruct, "ref.struct") WABT_TOKEN(Quote, "quote") WABT_TOKEN(Rec, "rec") WABT_TOKEN(Register, "register") @@ -89,6 +92,19 @@ WABT_TOKEN_FIRST(Literal, Float) WABT_TOKEN_LAST(Literal, Nat) /* Tokens with Opcode data. */ +WABT_TOKEN(ArrayCopy, "array.copy") +WABT_TOKEN(ArrayFill, "array.fill") +WABT_TOKEN(ArrayGet, "array.get") +WABT_TOKEN(ArrayGetS, "array.get_s") +WABT_TOKEN(ArrayGetU, "array.get_u") +WABT_TOKEN(ArrayInitData, "array.init_data") +WABT_TOKEN(ArrayInitElem, "array.init_elem") +WABT_TOKEN(ArrayNew, "array.new") +WABT_TOKEN(ArrayNewData, "array.new_data") +WABT_TOKEN(ArrayNewDefault, "array.new_default") +WABT_TOKEN(ArrayNewFixed, "array.new_fixed") +WABT_TOKEN(ArrayNewElem, "array.new_elem") +WABT_TOKEN(ArraySet, "array.set") WABT_TOKEN(AtomicFence, "atomic.fence") WABT_TOKEN(AtomicLoad, "ATOMIC_LOAD") WABT_TOKEN(AtomicNotify, "ATOMIC_NOTIFY") @@ -100,6 +116,7 @@ WABT_TOKEN(Binary, "BINARY") WABT_TOKEN(Block, "block") WABT_TOKEN(Br, "br") WABT_TOKEN(BrIf, "br_if") +WABT_TOKEN(BrOnCast, "br_on_cast") WABT_TOKEN(BrOnNonNull, "br_on_non_null") WABT_TOKEN(BrOnNull, "br_on_null") WABT_TOKEN(BrTable, "br_table") @@ -120,6 +137,7 @@ WABT_TOKEN(Drop, "drop") WABT_TOKEN(ElemDrop, "elem.drop") WABT_TOKEN(Else, "else") WABT_TOKEN(End, "end") +WABT_TOKEN(GCUnary, "GC_UNARY") WABT_TOKEN(GlobalGet, "global.get") WABT_TOKEN(GlobalSet, "global.set") WABT_TOKEN(If, "if") @@ -135,10 +153,14 @@ WABT_TOKEN(MemoryInit, "memory.init") WABT_TOKEN(MemorySize, "memory.size") WABT_TOKEN(Nop, "nop") WABT_TOKEN(RefAsNonNull, "ref.as_non_null") +WABT_TOKEN(RefCast, "ref.cast") +WABT_TOKEN(RefEq, "ref.eq") WABT_TOKEN(RefExtern, "ref.extern") WABT_TOKEN(RefFunc, "ref.func") +WABT_TOKEN(RefI31, "ref.i31") WABT_TOKEN(RefIsNull, "ref.is_null") WABT_TOKEN(RefNull, "ref.null") +WABT_TOKEN(RefTest, "ref.test") WABT_TOKEN(Rethrow, "rethrow") WABT_TOKEN(ReturnCallIndirect, "return_call_indirect") WABT_TOKEN(ReturnCall, "return_call") @@ -150,6 +172,12 @@ WABT_TOKEN(SimdLoadLane, "SIMDLOADLANE") WABT_TOKEN(SimdStoreLane, "SIMDSTORELANE") WABT_TOKEN(SimdShuffleOp, "i8x16.shuffle") WABT_TOKEN(Store, "STORE") +WABT_TOKEN(StructGet, "struct.get") +WABT_TOKEN(StructGetS, "struct.get_s") +WABT_TOKEN(StructGetU, "struct.get_u") +WABT_TOKEN(StructNew, "struct.new") +WABT_TOKEN(StructNewDefault, "struct.new_default") +WABT_TOKEN(StructSet, "struct.set") WABT_TOKEN(TableCopy, "table.copy") WABT_TOKEN(TableFill, "table.fill") WABT_TOKEN(TableGet, "table.get") @@ -164,7 +192,7 @@ WABT_TOKEN(Try, "try") WABT_TOKEN(TryTable, "try_table") WABT_TOKEN(Unary, "UNARY") WABT_TOKEN(Unreachable, "unreachable") -WABT_TOKEN_FIRST(Opcode, AtomicFence) +WABT_TOKEN_FIRST(Opcode, ArrayCopy) WABT_TOKEN_LAST(Opcode, Unreachable) /* Tokens with string data. */ diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h index 3b18ca11ca..b8d609c98f 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -122,6 +122,8 @@ class TypeChecker { return type; } + Type GetGroupType(Type type); + std::vector type_entries; std::vector func_types; std::vector struct_types; @@ -162,6 +164,24 @@ class TypeChecker { Result GetCatchCount(Index depth, Index* out_depth); Result BeginFunction(const TypeVector& sig); + Result OnArrayCopy(Type dst_ref_type, + TypeMut& dst_array_type, + Type src_ref_type, + Type src_array_type); + Result OnArrayFill(Type ref_type, TypeMut& array_type); + Result OnArrayGet(Opcode, Type ref_type, Type array_type); + Result OnArrayInitData(Type ref_type, TypeMut& array_type); + Result OnArrayInitElem(Type ref_type, TypeMut& array_type, Type elem_type); + Result OnArrayNew(Type ref_type, Type array_type); + Result OnArrayNewData(Type ref_type, Type array_type); + Result OnArrayNewDefault(Type ref_type); + Result OnArrayNewElem(Type ref_type, + Type array_type, + Type elem_type); + Result OnArrayNewFixed(Type ref_type, + Type array_type, + Index count); + Result OnArraySet(Type ref_type, const TypeMut& field); Result OnAtomicFence(uint32_t consistency_model); Result OnAtomicLoad(Opcode, const Limits& limits); Result OnAtomicNotify(Opcode, const Limits& limits); @@ -173,6 +193,7 @@ class TypeChecker { Result OnBlock(const TypeVector& param_types, const TypeVector& result_types); Result OnBr(Index depth); Result OnBrIf(Index depth); + Result OnBrOnCast(Opcode opcode, Index depth, Type type1, Type type2); Result OnBrOnNonNull(Index depth); Result OnBrOnNull(Index depth); Result BeginBrTable(); @@ -196,6 +217,7 @@ class TypeChecker { Result OnDrop(); Result OnElse(); Result OnEnd(); + Result OnGCUnary(Opcode); Result OnGlobalGet(Type); Result OnGlobalSet(Type); Result OnIf(const TypeVector& param_types, const TypeVector& result_types); @@ -220,8 +242,10 @@ class TypeChecker { Result OnTableFill(Type elem_type, const Limits& limits); Result OnRefFuncExpr(Index func_type); Result OnRefAsNonNullExpr(); + Result OnRefCast(Type type); Result OnRefNullExpr(Type type); Result OnRefIsNullExpr(); + Result OnRefTest(Type type); Result OnRethrow(Index depth); Result OnReturn(); Result OnSelect(const TypeVector& result_types); @@ -230,6 +254,10 @@ class TypeChecker { Result OnSimdStoreLane(Opcode, const Limits& limits, uint64_t); Result OnSimdShuffleOp(Opcode, v128); Result OnStore(Opcode, const Limits& limits); + Result OnStructGet(Opcode, Type ref_type, const StructType&, Index field); + Result OnStructNew(Type ref_type, const StructType&); + Result OnStructNewDefault(Type ref_type); + Result OnStructSet(Type ref_type, const StructType&, Index field); Result OnTernary(Opcode); Result OnThrow(const TypeVector& sig); Result OnThrowRef(); @@ -288,6 +316,17 @@ class TypeChecker { Type expected2, Type expected3, const char* desc); + Result PopAndCheck4Types(Type expected1, + Type expected2, + Type expected3, + Type expected4, + const char* desc); + Result PopAndCheck5Types(Type expected1, + Type expected2, + Type expected3, + Type expected4, + Type expected5, + const char* desc); Result PopAndCheckReference(Type* actual, const char* desc); Result CheckOpcode1(Opcode opcode, const Limits* limits = nullptr); Result CheckOpcode2(Opcode opcode, const Limits* limits = nullptr); @@ -302,6 +341,13 @@ class TypeChecker { return hash ^ ((hash << 5) + (hash >> 2) + value); } + static Type ToUnpackedType(Type type) { + if (type.IsPackedType()) { + return Type::I32; + } + return type; + } + uint32_t ComputeHash(uint32_t hash, Type& type, Index rec_start); bool CompareType(Type actual, Index actual_rec_start, diff --git a/include/wabt/wast-parser.h b/include/wabt/wast-parser.h index 330a784a10..359b25b609 100644 --- a/include/wabt/wast-parser.h +++ b/include/wabt/wast-parser.h @@ -264,6 +264,8 @@ class WastParser { template Result ParsePlainInstrVar(Location, std::unique_ptr*); template + Result ParsePlainInstrVarVar(Location, std::unique_ptr*); + template Result ParseMemoryInstrVar(Location, std::unique_ptr*); template Result ParseLoadStoreInstr(Location, Token, std::unique_ptr*); diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 41ab0a8c1e..eff32b93a0 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -181,6 +181,17 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnLocalDecl(Index decl_index, Index count, Type type) override; Result OnOpcode(Opcode opcode) override; + Result OnArrayCopyExpr(Index dst_type_index, Index src_type_index) override; + Result OnArrayFillExpr(Index type_index) override; + Result OnArrayGetExpr(Opcode opcode, Index type_index) override; + Result OnArrayInitDataExpr(Index type_index, Index data_index) override; + Result OnArrayInitElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewExpr(Index type_index) override; + Result OnArrayNewDataExpr(Index type_index, Index data_index) override; + Result OnArrayNewDefaultExpr(Index type_index) override; + Result OnArrayNewElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewFixedExpr(Index type_index, Index count) override; + Result OnArraySetExpr(Index type_index) override; Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -210,6 +221,10 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) override; Result OnBrOnNonNullExpr(Index depth) override; Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, @@ -232,6 +247,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; + Result OnGCUnaryExpr(Opcode opcode) override; Result OnGlobalGetExpr(Index global_index) override; Result OnGlobalSetExpr(Index global_index) override; Result OnI32ConstExpr(uint32_t value) override; @@ -260,9 +276,11 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnTableSizeExpr(Index table_index) override; Result OnTableFillExpr(Index table_index) override; Result OnRefAsNonNullExpr() override; + Result OnRefCastExpr(Type type) override; Result OnRefFuncExpr(Index func_index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; + Result OnRefTestExpr(Type type) override; Result OnNopExpr() override; Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; @@ -271,6 +289,12 @@ class BinaryReaderIR : public BinaryReaderNop { Index memidx, Address alignment_log2, Address offset) override; + Result OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) override; + Result OnStructNewExpr(Index type_index) override; + Result OnStructNewDefaultExpr(Index type_index) override; + Result OnStructSetExpr(Index type_index, Index field_index) override; Result OnThrowExpr(Index tag_index) override; Result OnThrowRefExpr() override; Result OnTryExpr(Type sig_type) override; @@ -869,6 +893,62 @@ Result BinaryReaderIR::OnOpcode(Opcode opcode) { return Result::Ok; } +Result BinaryReaderIR::OnArrayCopyExpr(Index dst_type_index, + Index src_type_index) { + return AppendExpr(std::make_unique( + Var(dst_type_index, GetLocation()), Var(src_type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayFillExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayGetExpr(Opcode opcode, Index type_index) { + return AppendExpr( + std::make_unique(opcode, Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayInitDataExpr(Index type_index, Index data_index) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), Var(data_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayInitElemExpr(Index type_index, Index elem_index) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), Var(elem_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayNewExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayNewDataExpr(Index type_index, Index data_index) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), Var(data_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayNewDefaultExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayNewElemExpr(Index type_index, Index elem_index) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), Var(elem_index, GetLocation()))); +} + +Result BinaryReaderIR::OnArrayNewFixedExpr(Index type_index, Index count) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), count)); +} + +Result BinaryReaderIR::OnArraySetExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -941,6 +1021,15 @@ Result BinaryReaderIR::OnBrIfExpr(Index depth) { return AppendExpr(std::make_unique(Var(depth, GetLocation()))); } +Result BinaryReaderIR::OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) { + return AppendExpr(std::make_unique( + opcode, Var(depth, GetLocation()), Var(type1, GetLocation()), + Var(type2, GetLocation()))); +} + Result BinaryReaderIR::OnBrOnNonNullExpr(Index depth) { return AppendExpr( std::make_unique(Var(depth, GetLocation()))); @@ -1092,6 +1181,10 @@ Result BinaryReaderIR::OnV128ConstExpr(v128 value_bits) { std::make_unique(Const::V128(value_bits, GetLocation()))); } +Result BinaryReaderIR::OnGCUnaryExpr(Opcode opcode) { + return AppendExpr(std::make_unique(opcode)); +} + Result BinaryReaderIR::OnGlobalGetExpr(Index global_index) { return AppendExpr( std::make_unique(Var(global_index, GetLocation()))); @@ -1211,6 +1304,10 @@ Result BinaryReaderIR::OnRefAsNonNullExpr() { std::make_unique(Opcode::RefAsNonNull, GetLocation())); } +Result BinaryReaderIR::OnRefCastExpr(Type type) { + return AppendExpr(std::make_unique(Var(type, GetLocation()))); +} + Result BinaryReaderIR::OnRefFuncExpr(Index func_index) { module_->used_func_refs.insert(func_index); return AppendExpr( @@ -1226,6 +1323,10 @@ Result BinaryReaderIR::OnRefIsNullExpr() { return AppendExpr(std::make_unique()); } +Result BinaryReaderIR::OnRefTestExpr(Type type) { + return AppendExpr(std::make_unique(Var(type, GetLocation()))); +} + Result BinaryReaderIR::OnNopExpr() { return AppendExpr(std::make_unique()); } @@ -1262,6 +1363,28 @@ Result BinaryReaderIR::OnStoreExpr(Opcode opcode, opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } +Result BinaryReaderIR::OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) { + return AppendExpr(std::make_unique( + opcode, Var(type_index, GetLocation()), Var(field_index, GetLocation()))); +} + +Result BinaryReaderIR::OnStructNewExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnStructNewDefaultExpr(Index type_index) { + return AppendExpr( + std::make_unique(Var(type_index, GetLocation()))); +} + +Result BinaryReaderIR::OnStructSetExpr(Index type_index, Index field_index) { + return AppendExpr(std::make_unique( + Var(type_index, GetLocation()), Var(field_index, GetLocation()))); +} + Result BinaryReaderIR::OnThrowExpr(Index tag_index) { module_->features_used.exceptions = true; return AppendExpr(std::make_unique(Var(tag_index, GetLocation()))); diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 3ff6e33e97..b9cb62c57b 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -343,6 +343,17 @@ Result BinaryReaderLogging::OnBrIfExpr(Index depth) { return reader_->OnBrIfExpr(depth); } +Result BinaryReaderLogging::OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) { + LOGF("OnBrOnCastExpr(opcode: \"%s\" (%u), depth: %" PRIindex + ", type1: %s, type2: %s)\n", + opcode.GetName(), opcode.GetCode(), depth, type1.GetName().c_str(), + type2.GetName().c_str()); + return reader_->OnBrOnCastExpr(opcode, depth, type1, type2); +} + Result BinaryReaderLogging::OnBrOnNonNullExpr(Index depth) { LOGF("OnBrOnNonNullExpr(depth: %" PRIindex ")\n", depth); return reader_->OnBrOnNonNullExpr(depth); @@ -420,6 +431,15 @@ Result BinaryReaderLogging::OnSelectExpr(Index result_count, return reader_->OnSelectExpr(result_count, result_types); } +Result BinaryReaderLogging::OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) { + LOGF("OnStructGetExpr(opcode: \"%s\" (%u), type_index: %" PRIindex + ", field_index: %" PRIindex ")\n", + opcode.GetName(), opcode.GetCode(), type_index, field_index); + return reader_->OnStructGetExpr(opcode, type_index, field_index); +} + Result BinaryReaderLogging::OnTryExpr(Type sig_type) { LOGF("OnTryExpr(sig: "); LogType(sig_type); @@ -793,6 +813,13 @@ Result BinaryReaderLogging::OnGenericCustomSection(std::string_view name, return reader_->name(opcode); \ } +#define DEFINE_OPCODE_INDEX(name, desc) \ + Result BinaryReaderLogging::name(Opcode opcode, Index index) { \ + LOGF(#name "(opcode: \"%s\" (%u), " desc ": %" PRIindex ")\n", \ + opcode.GetName(), opcode.GetCode(), index); \ + return reader_->name(opcode, index); \ + } + #define DEFINE_LOAD_STORE_OPCODE(name) \ Result BinaryReaderLogging::name(Opcode opcode, Index memidx, \ Address alignment_log2, Address offset) { \ @@ -869,6 +896,17 @@ DEFINE_INDEX(OnFunctionBodyCount) DEFINE_INDEX(EndFunctionBody) DEFINE_INDEX(OnLocalDeclCount) DEFINE0(EndLocalDecls) +DEFINE_INDEX_INDEX(OnArrayCopyExpr, "dst_type_index", "src_type_index") +DEFINE_INDEX_DESC(OnArrayFillExpr, "type_index") +DEFINE_OPCODE_INDEX(OnArrayGetExpr, "type_index") +DEFINE_INDEX_INDEX(OnArrayInitDataExpr, "type_index", "data_index") +DEFINE_INDEX_INDEX(OnArrayInitElemExpr, "type_index", "elem_index") +DEFINE_INDEX_DESC(OnArrayNewExpr, "type_index") +DEFINE_INDEX_INDEX(OnArrayNewDataExpr, "type_index", "data_index") +DEFINE_INDEX_DESC(OnArrayNewDefaultExpr, "type_index") +DEFINE_INDEX_INDEX(OnArrayNewElemExpr, "type_index", "elem_index") +DEFINE_INDEX_INDEX(OnArrayNewFixedExpr, "type_index", "count") +DEFINE_INDEX_DESC(OnArraySetExpr, "type_index") DEFINE_LOAD_STORE_OPCODE(OnAtomicLoadExpr); DEFINE_LOAD_STORE_OPCODE(OnAtomicRmwExpr); DEFINE_LOAD_STORE_OPCODE(OnAtomicRmwCmpxchgExpr); @@ -888,6 +926,7 @@ DEFINE_INDEX_DESC(OnDelegateExpr, "depth"); DEFINE0(OnDropExpr) DEFINE0(OnElseExpr) DEFINE0(OnEndExpr) +DEFINE_OPCODE(OnGCUnaryExpr) DEFINE_INDEX_DESC(OnGlobalGetExpr, "index") DEFINE_INDEX_DESC(OnGlobalSetExpr, "index") DEFINE_LOAD_STORE_OPCODE(OnLoadExpr); @@ -909,8 +948,10 @@ DEFINE_INDEX(OnTableGrowExpr) DEFINE_INDEX(OnTableSizeExpr) DEFINE_INDEX_DESC(OnTableFillExpr, "table index") DEFINE0(OnRefAsNonNullExpr) +DEFINE_TYPE(OnRefCastExpr) DEFINE_INDEX(OnRefFuncExpr) DEFINE_TYPE(OnRefNullExpr) +DEFINE_TYPE(OnRefTestExpr) DEFINE0(OnRefIsNullExpr) DEFINE0(OnNopExpr) DEFINE_INDEX_DESC(OnRethrowExpr, "depth"); @@ -922,6 +963,9 @@ DEFINE0(OnReturnExpr) DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr); DEFINE_LOAD_STORE_OPCODE(OnLoadZeroExpr); DEFINE_LOAD_STORE_OPCODE(OnStoreExpr); +DEFINE_INDEX_DESC(OnStructNewExpr, "type_index") +DEFINE_INDEX_DESC(OnStructNewDefaultExpr, "type_index") +DEFINE_INDEX_INDEX(OnStructSetExpr, "type_index", "field_index") DEFINE_INDEX_DESC(OnThrowExpr, "tag_index") DEFINE0(OnUnreachableExpr) DEFINE0(OnThrowRefExpr) diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 9ec149d26d..cb1245bb55 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -116,6 +116,9 @@ class BinaryReader { [[nodiscard]] Result ReadS64Leb128(uint64_t* out_value, const char* desc); [[nodiscard]] Result ReadType(Type* out_value, const char* desc); [[nodiscard]] Result ReadRefType(Type* out_value, const char* desc); + [[nodiscard]] Result ReadHeapType(Type* out_value, + bool is_nullable, + const char* desc); [[nodiscard]] Result ReadExternalKind(ExternalKind* out_value, const char* desc); [[nodiscard]] Result ReadStr(std::string_view* out_str, const char* desc); @@ -380,10 +383,8 @@ Result BinaryReader::ReadType(Type* out_value, const char* desc) { (options_.features.gc_enabled() && Type::EnumIsNonTypedGCRef(heap_type_code)), "not allowed reference type: %s", desc); - type = (static_cast(type) == Type::Ref) - ? Type::ReferenceNonNull - : Type::ReferenceOrNull; - *out_value = Type(heap_type_code, type); + *out_value = + Type(heap_type_code, static_cast(type) == Type::RefNull); } else { *out_value = Type(static_cast(type), static_cast(heap_type)); @@ -400,6 +401,28 @@ Result BinaryReader::ReadRefType(Type* out_value, const char* desc) { return Result::Ok; } +Result BinaryReader::ReadHeapType(Type* out_value, + bool is_nullable, + const char* desc) { + uint64_t heap_type; + CHECK_RESULT(ReadS64Leb128(&heap_type, "heap type")); + + if (static_cast(heap_type) < 0 || + static_cast(heap_type) >= kInvalidIndex) { + Type::Enum type_code = static_cast(heap_type); + ERROR_UNLESS(IsConcreteReferenceType(type_code), + "expected valid %s type (got " PRItypecode ")", desc, + WABT_PRINTF_TYPE_CODE(type_code)); + *out_value = Type(type_code, is_nullable); + } else { + ERROR_UNLESS(options_.features.function_references_enabled(), + "type references are not enabled for %s", desc); + *out_value = Type(is_nullable ? Type::RefNull : Type::Ref, + static_cast(heap_type)); + } + return Result::Ok; +} + Result BinaryReader::ReadExternalKind(ExternalKind* out_value, const char* desc) { uint8_t value = 0; @@ -1970,23 +1993,8 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { } case Opcode::RefNull: { - uint64_t heap_type; Type type; - CHECK_RESULT(ReadS64Leb128(&heap_type, "ref.null type")); - - if (static_cast(heap_type) < 0 || - static_cast(heap_type) >= kInvalidIndex) { - Type::Enum type_code = static_cast(heap_type); - ERROR_UNLESS(IsConcreteReferenceType(type_code), - "expected valid ref.null type (got " PRItypecode ")", - WABT_PRINTF_TYPE_CODE(type_code)); - type = Type(type_code); - } else { - ERROR_UNLESS(options_.features.function_references_enabled(), - "function references are not enabled for ref.null"); - type = Type(Type::RefNull, static_cast(heap_type)); - } - + CHECK_RESULT(ReadHeapType(&type, true, "ref.null")); CALLBACK(OnRefNullExpr, type); CALLBACK(OnOpcodeType, type); break; @@ -2017,6 +2025,184 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { break; } + case Opcode::ArrayCopy: { + uint32_t dst_type_index, src_type_index; + CHECK_RESULT(ReadIndex(&dst_type_index, "dst type index")); + CHECK_RESULT(ReadIndex(&src_type_index, "src type index")); + CALLBACK(OnArrayCopyExpr, dst_type_index, src_type_index); + CALLBACK(OnOpcodeIndexIndex, dst_type_index, src_type_index); + break; + } + + case Opcode::ArrayFill: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnArrayFillExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::ArrayGet: + case Opcode::ArrayGetS: + case Opcode::ArrayGetU: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnArrayGetExpr, opcode, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::ArrayInitData: { + uint32_t type_index, data_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&data_index, "data index")); + CALLBACK(OnArrayInitDataExpr, type_index, data_index); + CALLBACK(OnOpcodeIndexIndex, type_index, data_index); + break; + } + + case Opcode::ArrayInitElem: { + uint32_t type_index, elem_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&elem_index, "elem index")); + CALLBACK(OnArrayInitElemExpr, type_index, elem_index); + CALLBACK(OnOpcodeIndexIndex, type_index, elem_index); + break; + } + + case Opcode::ArrayNew: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnArrayNewExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::ArrayNewData: { + uint32_t type_index, data_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&data_index, "data index")); + CALLBACK(OnArrayNewDataExpr, type_index, data_index); + CALLBACK(OnOpcodeIndexIndex, type_index, data_index); + break; + } + + case Opcode::ArrayNewDefault: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnArrayNewDefaultExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::ArrayNewElem: { + uint32_t type_index, elem_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&elem_index, "elem index")); + CALLBACK(OnArrayNewElemExpr, type_index, elem_index); + CALLBACK(OnOpcodeIndexIndex, type_index, elem_index); + break; + } + + case Opcode::ArrayNewFixed: { + uint32_t type_index, count; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&count, "count")); + CALLBACK(OnArrayNewFixedExpr, type_index, count); + CALLBACK(OnOpcodeUint32Uint32, type_index, count); + break; + } + + case Opcode::ArraySet: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnArraySetExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::ArrayLen: + case Opcode::AnyConvertExtern: + case Opcode::ExternConvertAny: + case Opcode::RefI31: + case Opcode::RefEq: + case Opcode::I31GetS: + case Opcode::I31GetU: + CALLBACK(OnGCUnaryExpr, opcode); + CALLBACK0(OnOpcodeBare); + break; + + case Opcode::RefCast: + case Opcode::RefCastNull: { + Type type; + CHECK_RESULT( + ReadHeapType(&type, opcode == Opcode::RefCastNull, "ref.cast")); + CALLBACK(OnRefCastExpr, type); + CALLBACK(OnOpcodeType, type); + break; + } + + case Opcode::RefTest: + case Opcode::RefTestNull: { + Type type; + CHECK_RESULT( + ReadHeapType(&type, opcode == Opcode::RefTestNull, "ref.test")); + CALLBACK(OnRefTestExpr, type); + CALLBACK(OnOpcodeType, type); + break; + } + + case Opcode::BrOnCast: + case Opcode::BrOnCastFail: { + Index depth; + uint8_t flags; + Type type1, type2; + CHECK_RESULT(ReadU8(&flags, "br_on_cast flags")); + CHECK_RESULT(ReadIndex(&depth, "br_on_cast depth")); + CHECK_RESULT( + ReadHeapType(&type1, (flags & 0x1) != 0, "br_on_cast type1")); + CHECK_RESULT( + ReadHeapType(&type2, (flags & 0x2) != 0, "br_on_cast type2")); + CALLBACK(OnBrOnCastExpr, opcode, depth, type1, type2); + break; + } + + case Opcode::StructGet: + case Opcode::StructGetS: + case Opcode::StructGetU: { + uint32_t type_index, field_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&field_index, "field index")); + CALLBACK(OnStructGetExpr, opcode, type_index, field_index); + CALLBACK(OnOpcodeIndexIndex, type_index, field_index); + break; + } + + case Opcode::StructNew: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnStructNewExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::StructNewDefault: { + uint32_t type_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CALLBACK(OnStructNewDefaultExpr, type_index); + CALLBACK(OnOpcodeIndex, type_index); + break; + } + + case Opcode::StructSet: { + uint32_t type_index, field_index; + CHECK_RESULT(ReadIndex(&type_index, "type index")); + CHECK_RESULT(ReadIndex(&field_index, "field index")); + CALLBACK(OnStructSetExpr, type_index, field_index); + CALLBACK(OnOpcodeIndexIndex, type_index, field_index); + break; + } + default: return ReportUnexpectedOpcode(opcode); } diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc index edcf0ba58f..0cb9aadc65 100644 --- a/src/binary-writer-spec.cc +++ b/src/binary-writer-spec.cc @@ -200,6 +200,8 @@ void BinaryWriterSpec::WriteF64(uint64_t f64_bits, ExpectedNan expected) { void BinaryWriterSpec::WriteRefBits(uintptr_t ref_bits) { if (ref_bits == Const::kRefNullBits) { json_stream_->Writef("\"null\""); + } else if (ref_bits == Const::kRefAnyValueBits) { + json_stream_->Writef("\"\""); } else { json_stream_->Writef("\"%" PRIuPTR "\"", ref_bits); } @@ -240,16 +242,26 @@ void BinaryWriterSpec::WriteConst(const Const& const_) { WriteF64(const_.f64_bits(), const_.expected_nan()); break; - case Type::FuncRef: { - WriteString("funcref"); + case Type::AnyRef: { + // If ref_bits() is not equal to kRefNullBits or + // kRefAnyValueBits, it represents a host value. + WriteString("anyref"); WriteSeparator(); WriteKey("value"); WriteRefBits(const_.ref_bits()); break; } - case Type::ExternRef: { - WriteString("externref"); + case Type::ArrayRef: { + WriteString("arrayref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + + case Type::EqRef: { + WriteString("eqref"); WriteSeparator(); WriteKey("value"); WriteRefBits(const_.ref_bits()); @@ -264,6 +276,48 @@ void BinaryWriterSpec::WriteConst(const Const& const_) { break; } + case Type::ExternRef: { + WriteString("externref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + + case Type::FuncRef: { + WriteString("funcref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + + case Type::I31Ref: { + WriteString("i31ref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + + case Type::NullRef: { + assert(const_.type().IsBottomRef() && + const_.ref_bits() == Const::kRefNullBits); + WriteString("botref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + + case Type::StructRef: { + WriteString("structref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + case Type::V128: { WriteString("v128"); WriteSeparator(); diff --git a/src/binary-writer.cc b/src/binary-writer.cc index b4f41f98d4..a3a9308b25 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -67,6 +67,14 @@ void WriteType(Stream* stream, Type type, const char* desc) { } } +void WriteHeapType(Stream* stream, Type type, const char* desc) { + if (type.IsReferenceWithIndex()) { + WriteU32Leb128(stream, type.GetReferenceIndex(), desc); + } else { + WriteS32Leb128(stream, type, desc); + } +} + void WriteLimitsFlags(Stream* stream, uint32_t flags) { WriteU32Leb128(stream, flags, "limits: flags"); } @@ -424,6 +432,11 @@ class BinaryWriter { void WriteSimdLoadStoreLaneExpr(const Func* func, const Expr* expr, const char* desc); + void WriteTypeIndex(Opcode opcode, const Var& type); + void WriteTypeIndexIndex(Opcode opcode, + const Var& type, + const Var& var, + const char* desc); void WriteExpr(const Func* func, const Expr* expr); void WriteExprList(const Func* func, const ExprList& exprs); void WriteInitExpr(const ExprList& expr); @@ -716,8 +729,77 @@ void BinaryWriter::WriteSimdLoadStoreLaneExpr(const Func* func, stream_->WriteU8(static_cast(typed_expr->val), "Simd Lane literal"); } +void BinaryWriter::WriteTypeIndex(Opcode opcode, const Var& type) { + WriteOpcode(stream_, opcode); + Index index = module_->GetFuncTypeIndex(type); + WriteU32Leb128WithReloc(index, "type index", RelocType::TypeIndexLEB); +} + +void BinaryWriter::WriteTypeIndexIndex(Opcode opcode, + const Var& type, + const Var& var, + const char* desc) { + WriteTypeIndex(opcode, type); + WriteU32Leb128(stream_, var.index(), desc); +} + void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { switch (expr->type()) { + case ExprType::ArrayCopy: { + auto* array_copy_expr = cast(expr); + WriteTypeIndexIndex(Opcode::ArrayCopy, array_copy_expr->type_var, + array_copy_expr->var, "type index"); + break; + } + case ExprType::ArrayFill: + WriteTypeIndex(Opcode::ArrayFill, cast(expr)->var); + break; + case ExprType::ArrayGet: { + auto* array_get_expr = cast(expr); + WriteTypeIndex(array_get_expr->opcode, array_get_expr->type_var); + break; + } + case ExprType::ArrayInitData: { + auto* array_init_data_expr = cast(expr); + WriteTypeIndexIndex(Opcode::ArrayInitData, array_init_data_expr->type_var, + array_init_data_expr->var, "data index"); + break; + } + case ExprType::ArrayInitElem: { + auto* array_init_elem_expr = cast(expr); + WriteTypeIndexIndex(Opcode::ArrayInitElem, array_init_elem_expr->type_var, + array_init_elem_expr->var, "elem index"); + break; + } + case ExprType::ArrayNew: + WriteTypeIndex(Opcode::ArrayNew, cast(expr)->var); + break; + case ExprType::ArrayNewData: { + auto* array_new_data_expr = cast(expr); + WriteTypeIndexIndex(Opcode::ArrayNewData, array_new_data_expr->type_var, + array_new_data_expr->var, "data index"); + has_data_segment_instruction_ = true; + break; + } + case ExprType::ArrayNewDefault: + WriteTypeIndex(Opcode::ArrayNewDefault, + cast(expr)->var); + break; + case ExprType::ArrayNewElem: { + auto* array_new_elem_expr = cast(expr); + WriteTypeIndexIndex(Opcode::ArrayNewElem, array_new_elem_expr->type_var, + array_new_elem_expr->var, "elem index"); + break; + } + case ExprType::ArrayNewFixed: { + auto* array_new_fixed_expr = cast(expr); + WriteTypeIndex(Opcode::ArrayNewFixed, array_new_fixed_expr->type_var); + WriteU32Leb128(stream_, array_new_fixed_expr->count, "count"); + break; + } + case ExprType::ArraySet: + WriteTypeIndex(Opcode::ArraySet, cast(expr)->var); + break; case ExprType::AtomicLoad: WriteLoadStoreExpr(func, expr, "memory offset"); break; @@ -762,6 +844,25 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteU32Leb128(stream_, GetLabelVarDepth(&cast(expr)->var), "break depth"); break; + case ExprType::BrOnCast: { + auto* br_on_cast_expr = cast(expr); + Type type1 = br_on_cast_expr->type1_var.to_type(); + Type type2 = br_on_cast_expr->type2_var.to_type(); + uint8_t flags = 0; + if (type1.IsNullableRef()) { + flags |= 0x1; + } + if (type2.IsNullableRef()) { + flags |= 0x2; + } + WriteOpcode(stream_, br_on_cast_expr->opcode); + stream_->WriteU8(flags, "flags"); + WriteU32Leb128(stream_, GetLabelVarDepth(&br_on_cast_expr->label_var), + "break depth"); + WriteHeapType(stream_, type1, "br_on_cast type1"); + WriteHeapType(stream_, type2, "br_on_cast type2"); + break; + } case ExprType::BrOnNonNull: WriteOpcode(stream_, Opcode::BrOnNonNull); WriteU32Leb128(stream_, @@ -875,6 +976,9 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { case ExprType::Drop: WriteOpcode(stream_, Opcode::Drop); break; + case ExprType::GCUnary: + WriteOpcode(stream_, cast(expr)->opcode); + break; case ExprType::GlobalGet: { Index index = module_->GetGlobalIndex(cast(expr)->var); WriteOpcode(stream_, Opcode::GlobalGet); @@ -1034,6 +1138,14 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteOpcode(stream_, Opcode::RefAsNonNull); break; } + case ExprType::RefCast: { + const RefCastExpr* ref_cast_expr = cast(expr); + Type type = ref_cast_expr->var.to_type(); + WriteOpcode(stream_, + type.IsNullableRef() ? Opcode::RefCastNull : Opcode::RefCast); + WriteHeapType(stream_, type, "ref.cast type"); + break; + } case ExprType::RefFunc: { WriteOpcode(stream_, Opcode::RefFunc); Index index = module_->GetFuncIndex(cast(expr)->var); @@ -1043,21 +1155,21 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { case ExprType::RefNull: { WriteOpcode(stream_, Opcode::RefNull); const RefNullExpr* ref_null_expr = cast(expr); - Type::Enum type = ref_null_expr->type.opt_type(); - - if (type != Type::RefNull) { - WriteType(stream_, type, "ref.null type"); - break; - } - - Index index = module_->GetFuncTypeIndex(ref_null_expr->type); - WriteU32Leb128WithReloc(index, "heap type index", - RelocType::FuncIndexLEB); + Type type = ref_null_expr->type.to_type(); + WriteHeapType(stream_, type, "ref.null type"); break; } case ExprType::RefIsNull: WriteOpcode(stream_, Opcode::RefIsNull); break; + case ExprType::RefTest: { + const RefTestExpr* ref_test_expr = cast(expr); + Type type = ref_test_expr->var.to_type(); + WriteOpcode(stream_, + type.IsNullableRef() ? Opcode::RefTestNull : Opcode::RefTest); + WriteHeapType(stream_, type, "ref.test type"); + break; + } case ExprType::Nop: WriteOpcode(stream_, Opcode::Nop); break; @@ -1086,6 +1198,25 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { case ExprType::Store: WriteLoadStoreExpr(func, expr, "store offset"); break; + case ExprType::StructGet: { + auto* struct_get_expr = cast(expr); + WriteTypeIndexIndex(struct_get_expr->opcode, struct_get_expr->type_var, + struct_get_expr->var, "field"); + break; + } + case ExprType::StructNew: + WriteTypeIndex(Opcode::StructNew, cast(expr)->var); + break; + case ExprType::StructNewDefault: + WriteTypeIndex(Opcode::StructNewDefault, + cast(expr)->var); + break; + case ExprType::StructSet: { + auto* struct_set_expr = cast(expr); + WriteTypeIndexIndex(Opcode::StructSet, struct_set_expr->type_var, + struct_set_expr->var, "field"); + break; + } case ExprType::Throw: WriteOpcode(stream_, Opcode::Throw); WriteU32Leb128(stream_, GetTagVarDepth(&cast(expr)->var), @@ -1739,7 +1870,8 @@ Result BinaryWriter::WriteModule() { EndSection(); } - if (options_.features.bulk_memory_enabled() && + if ((options_.features.bulk_memory_enabled() || + options_.features.gc_enabled()) && module_->data_segments.size()) { // Keep track of the data count section offset so it can be removed if // it isn't needed. @@ -1783,7 +1915,8 @@ Result BinaryWriter::WriteModule() { } // Remove the DataCount section if there are no instructions that require it. - if (options_.features.bulk_memory_enabled() && + if ((options_.features.bulk_memory_enabled() || + options_.features.gc_enabled()) && module_->data_segments.size() && !has_data_segment_instruction_) { Offset size = stream_->offset() - data_count_end_; if (size) { diff --git a/src/c-writer.cc b/src/c-writer.cc index 8fc565ae7e..261e33a614 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -4299,10 +4299,29 @@ void CWriter::Write(const ExprList& exprs) { return; } + case ExprType::ArrayCopy: + case ExprType::ArrayFill: + case ExprType::ArrayGet: + case ExprType::ArrayInitData: + case ExprType::ArrayInitElem: + case ExprType::ArrayNew: + case ExprType::ArrayNewData: + case ExprType::ArrayNewDefault: + case ExprType::ArrayNewElem: + case ExprType::ArrayNewFixed: + case ExprType::ArraySet: case ExprType::AtomicWait: case ExprType::AtomicNotify: + case ExprType::BrOnCast: case ExprType::CallRef: + case ExprType::GCUnary: + case ExprType::RefCast: + case ExprType::RefTest: case ExprType::ReturnCallRef: + case ExprType::StructGet: + case ExprType::StructNew: + case ExprType::StructNewDefault: + case ExprType::StructSet: UNIMPLEMENTED("..."); break; } diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc index b1e8b8c37d..19e995cc80 100644 --- a/src/expr-visitor.cc +++ b/src/expr-visitor.cc @@ -167,6 +167,54 @@ Result ExprVisitor::VisitFunc(Func* func) { Result ExprVisitor::HandleDefaultState(Expr* expr) { switch (expr->type()) { + case ExprType::ArrayCopy: + CHECK_RESULT(delegate_->OnArrayCopyExpr(cast(expr))); + break; + + case ExprType::ArrayFill: + CHECK_RESULT(delegate_->OnArrayFillExpr(cast(expr))); + break; + + case ExprType::ArrayGet: + CHECK_RESULT(delegate_->OnArrayGetExpr(cast(expr))); + break; + + case ExprType::ArrayInitData: + CHECK_RESULT( + delegate_->OnArrayInitDataExpr(cast(expr))); + break; + + case ExprType::ArrayInitElem: + CHECK_RESULT( + delegate_->OnArrayInitElemExpr(cast(expr))); + break; + + case ExprType::ArrayNew: + CHECK_RESULT(delegate_->OnArrayNewExpr(cast(expr))); + break; + + case ExprType::ArrayNewData: + CHECK_RESULT(delegate_->OnArrayNewDataExpr(cast(expr))); + break; + + case ExprType::ArrayNewDefault: + CHECK_RESULT( + delegate_->OnArrayNewDefaultExpr(cast(expr))); + break; + + case ExprType::ArrayNewElem: + CHECK_RESULT(delegate_->OnArrayNewElemExpr(cast(expr))); + break; + + case ExprType::ArrayNewFixed: + CHECK_RESULT( + delegate_->OnArrayNewFixedExpr(cast(expr))); + break; + + case ExprType::ArraySet: + CHECK_RESULT(delegate_->OnArraySetExpr(cast(expr))); + break; + case ExprType::AtomicLoad: CHECK_RESULT(delegate_->OnAtomicLoadExpr(cast(expr))); break; @@ -215,6 +263,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnBrIfExpr(cast(expr))); break; + case ExprType::BrOnCast: + CHECK_RESULT(delegate_->OnBrOnCastExpr(cast(expr))); + break; + case ExprType::BrOnNonNull: CHECK_RESULT(delegate_->OnBrOnNonNullExpr(cast(expr))); break; @@ -259,6 +311,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnDropExpr(cast(expr))); break; + case ExprType::GCUnary: + CHECK_RESULT(delegate_->OnGCUnaryExpr(cast(expr))); + break; + case ExprType::GlobalGet: CHECK_RESULT(delegate_->OnGlobalGetExpr(cast(expr))); break; @@ -365,6 +421,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnRefAsNonNullExpr(cast(expr))); break; + case ExprType::RefCast: + CHECK_RESULT(delegate_->OnRefCastExpr(cast(expr))); + break; + case ExprType::RefFunc: CHECK_RESULT(delegate_->OnRefFuncExpr(cast(expr))); break; @@ -377,6 +437,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnRefIsNullExpr(cast(expr))); break; + case ExprType::RefTest: + CHECK_RESULT(delegate_->OnRefTestExpr(cast(expr))); + break; + case ExprType::Nop: CHECK_RESULT(delegate_->OnNopExpr(cast(expr))); break; @@ -411,6 +475,23 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { CHECK_RESULT(delegate_->OnStoreExpr(cast(expr))); break; + case ExprType::StructGet: + CHECK_RESULT(delegate_->OnStructGetExpr(cast(expr))); + break; + + case ExprType::StructNew: + CHECK_RESULT(delegate_->OnStructNewExpr(cast(expr))); + break; + + case ExprType::StructNewDefault: + CHECK_RESULT( + delegate_->OnStructNewDefaultExpr(cast(expr))); + break; + + case ExprType::StructSet: + CHECK_RESULT(delegate_->OnStructSetExpr(cast(expr))); + break; + case ExprType::Throw: CHECK_RESULT(delegate_->OnThrowExpr(cast(expr))); break; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 3ceb6d262b..764faca22c 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -166,6 +166,17 @@ class BinaryReaderInterp : public BinaryReaderNop { Result EndLocalDecls() override; Result OnOpcode(Opcode Opcode) override; + Result OnArrayCopyExpr(Index dst_type_index, Index src_type_index) override; + Result OnArrayFillExpr(Index type_index) override; + Result OnArrayGetExpr(Opcode opcode, Index type_index) override; + Result OnArrayInitDataExpr(Index type_index, Index data_index) override; + Result OnArrayInitElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewExpr(Index type_index) override; + Result OnArrayNewDataExpr(Index type_index, Index data_index) override; + Result OnArrayNewDefaultExpr(Index type_index) override; + Result OnArrayNewElemExpr(Index type_index, Index elem_index) override; + Result OnArrayNewFixedExpr(Index type_index, Index count) override; + Result OnArraySetExpr(Index type_index) override; Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, @@ -195,6 +206,10 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; + Result OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) override; Result OnBrOnNonNullExpr(Index depth) override; Result OnBrOnNullExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, @@ -217,6 +232,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; + Result OnGCUnaryExpr(Opcode opcode) override; Result OnGlobalGetExpr(Index global_index) override; Result OnGlobalSetExpr(Index global_index) override; Result OnI32ConstExpr(uint32_t value) override; @@ -237,9 +253,11 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnMemoryInitExpr(Index segment_index, Index memidx) override; Result OnMemorySizeExpr(Index memidx) override; Result OnRefAsNonNullExpr() override; + Result OnRefCastExpr(Type type) override; Result OnRefFuncExpr(Index func_index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; + Result OnRefTestExpr(Type type) override; Result OnNopExpr() override; Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; @@ -258,6 +276,12 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnElemDropExpr(Index segment_index) override; Result OnTableInitExpr(Index segment_index, Index table_index) override; Result OnTernaryExpr(Opcode opcode) override; + Result OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) override; + Result OnStructNewExpr(Index type_index) override; + Result OnStructNewDefaultExpr(Index type_index) override; + Result OnStructSetExpr(Index type_index, Index field_index) override; Result OnThrowExpr(Index tag_index) override; Result OnThrowRefExpr() override; Result OnTryExpr(Type sig_type) override; @@ -1136,6 +1160,99 @@ Result BinaryReaderInterp::OnLoadZeroExpr(Opcode opcode, return Result::Ok; } +Result BinaryReaderInterp::OnArrayCopyExpr(Index dst_type_index, + Index src_type_index) { + CHECK_RESULT(validator_.OnArrayCopy(GetLocation(), + Var(dst_type_index, GetLocation()), + Var(src_type_index, GetLocation()))); + istream_.Emit(Opcode::ArrayCopy); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayFillExpr(Index type_index) { + CHECK_RESULT( + validator_.OnArrayFill(GetLocation(), Var(type_index, GetLocation()))); + istream_.Emit(Opcode::ArrayFill); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayGetExpr(Opcode opcode, Index type_index) { + CHECK_RESULT(validator_.OnArrayGet(GetLocation(), opcode, + Var(type_index, GetLocation()))); + if (opcode == Opcode::ArrayGet) { + istream_.Emit(opcode); + } else { + Index is_16 = (module_.func_types[type_index].params[0] == Type::I16); + istream_.Emit(opcode, is_16); + } + + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayInitDataExpr(Index type_index, + Index data_index) { + CHECK_RESULT(validator_.OnArrayInitData(GetLocation(), + Var(type_index, GetLocation()), + Var(data_index, GetLocation()))); + istream_.Emit(Opcode::ArrayInitData, type_index, data_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayInitElemExpr(Index type_index, + Index elem_index) { + CHECK_RESULT(validator_.OnArrayInitElem(GetLocation(), + Var(type_index, GetLocation()), + Var(elem_index, GetLocation()))); + istream_.Emit(Opcode::ArrayInitElem, elem_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayNewExpr(Index type_index) { + CHECK_RESULT( + validator_.OnArrayNew(GetLocation(), Var(type_index, GetLocation()))); + istream_.Emit(Opcode::ArrayNew, type_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayNewDataExpr(Index type_index, + Index data_index) { + CHECK_RESULT(validator_.OnArrayNewData(GetLocation(), + Var(type_index, GetLocation()), + Var(data_index, GetLocation()))); + istream_.Emit(Opcode::ArrayNewData, type_index, data_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayNewDefaultExpr(Index type_index) { + CHECK_RESULT(validator_.OnArrayNewDefault(GetLocation(), + Var(type_index, GetLocation()))); + istream_.Emit(Opcode::ArrayNewDefault, type_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayNewElemExpr(Index type_index, + Index elem_index) { + CHECK_RESULT(validator_.OnArrayNewElem(GetLocation(), + Var(type_index, GetLocation()), + Var(elem_index, GetLocation()))); + istream_.Emit(Opcode::ArrayNewElem, type_index, elem_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArrayNewFixedExpr(Index type_index, Index count) { + CHECK_RESULT(validator_.OnArrayNewFixed( + GetLocation(), Var(type_index, GetLocation()), count)); + istream_.Emit(Opcode::ArrayNewFixed, type_index, count); + return Result::Ok; +} + +Result BinaryReaderInterp::OnArraySetExpr(Index type_index) { + CHECK_RESULT( + validator_.OnArraySet(GetLocation(), Var(type_index, GetLocation()))); + istream_.Emit(Opcode::ArraySet); + return Result::Ok; +} + Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode, Index memidx, Address align_log2, @@ -1261,6 +1378,27 @@ Result BinaryReaderInterp::OnBrIfExpr(Index depth) { return EmitBrCond(Opcode::InterpBrUnless, depth); } +Result BinaryReaderInterp::OnBrOnCastExpr(Opcode opcode, + Index depth, + Type type1, + Type type2) { + CHECK_RESULT(validator_.OnBrOnCast( + GetLocation(), opcode, Var(depth, GetLocation()), + Var(type1, GetLocation()), Var(type2, GetLocation()))); + // For simplicity, the reftest result is pushed onto + // the stack, and it is processed by a br_if/br_unless. + Opcode test_opcode = + type2.IsNullableRef() ? Opcode::BrOnCast : Opcode::BrOnCastFail; + uint32_t code = static_cast(type2); + uint32_t value = type2.IsReferenceWithIndex() ? type2.GetReferenceIndex() + : Type::ReferenceNonNull; + istream_.Emit(test_opcode, code, value); + // Opcode is flipped. + return EmitBrCond( + opcode == Opcode::BrOnCast ? Opcode::InterpBrUnless : Opcode::BrIf, + depth); +} + Result BinaryReaderInterp::OnBrOnNonNullExpr(Index depth) { CHECK_RESULT( validator_.OnBrOnNonNull(GetLocation(), Var(depth, GetLocation()))); @@ -1451,6 +1589,15 @@ Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) { return Result::Ok; } +Result BinaryReaderInterp::OnGCUnaryExpr(Opcode opcode) { + CHECK_RESULT(validator_.OnGCUnary(GetLocation(), opcode)); + if (opcode != Opcode::AnyConvertExtern && + opcode != Opcode::ExternConvertAny) { + istream_.Emit(opcode); + } + return Result::Ok; +} + Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) { CHECK_RESULT( validator_.OnGlobalGet(GetLocation(), Var(global_index, GetLocation()))); @@ -1574,6 +1721,16 @@ Result BinaryReaderInterp::OnRefAsNonNullExpr() { return Result::Ok; } +Result BinaryReaderInterp::OnRefCastExpr(Type type) { + CHECK_RESULT(validator_.OnRefCast(GetLocation(), Var(type, GetLocation()))); + Opcode opcode = type.IsNullableRef() ? Opcode::RefCastNull : Opcode::RefCast; + uint32_t code = static_cast(type); + uint32_t value = type.IsReferenceWithIndex() ? type.GetReferenceIndex() + : Type::ReferenceNonNull; + istream_.Emit(opcode, code, value); + return Result::Ok; +} + Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) { CHECK_RESULT( validator_.OnRefFunc(GetLocation(), Var(func_index, GetLocation()))); @@ -1593,6 +1750,16 @@ Result BinaryReaderInterp::OnRefIsNullExpr() { return Result::Ok; } +Result BinaryReaderInterp::OnRefTestExpr(Type type) { + CHECK_RESULT(validator_.OnRefTest(GetLocation(), Var(type, GetLocation()))); + Opcode opcode = type.IsNullableRef() ? Opcode::RefTestNull : Opcode::RefTest; + uint32_t code = static_cast(type); + uint32_t value = type.IsReferenceWithIndex() ? type.GetReferenceIndex() + : Type::ReferenceNonNull; + istream_.Emit(opcode, code, value); + return Result::Ok; +} + Result BinaryReaderInterp::OnNopExpr() { CHECK_RESULT(validator_.OnNop(GetLocation())); return Result::Ok; @@ -1719,6 +1886,45 @@ Result BinaryReaderInterp::OnTableInitExpr(Index segment_index, return Result::Ok; } +Result BinaryReaderInterp::OnStructGetExpr(Opcode opcode, + Index type_index, + Index field_index) { + CHECK_RESULT(validator_.OnStructGet(GetLocation(), opcode, + Var(type_index, GetLocation()), + Var(field_index, GetLocation()))); + if (opcode == Opcode::StructGet) { + istream_.Emit(opcode, field_index); + } else { + Index is_16 = + (module_.func_types[type_index].params[field_index] == Type::I16); + istream_.Emit(opcode, field_index, is_16); + } + return Result::Ok; +} + +Result BinaryReaderInterp::OnStructNewExpr(Index type_index) { + CHECK_RESULT( + validator_.OnStructNew(GetLocation(), Var(type_index, GetLocation()))); + istream_.Emit(Opcode::StructNew, type_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnStructNewDefaultExpr(Index type_index) { + CHECK_RESULT(validator_.OnStructNewDefault(GetLocation(), + Var(type_index, GetLocation()))); + istream_.Emit(Opcode::StructNewDefault, type_index); + return Result::Ok; +} + +Result BinaryReaderInterp::OnStructSetExpr(Index type_index, + Index field_index) { + CHECK_RESULT(validator_.OnStructSet(GetLocation(), + Var(type_index, GetLocation()), + Var(field_index, GetLocation()))); + istream_.Emit(Opcode::StructSet, field_index); + return Result::Ok; +} + Result BinaryReaderInterp::OnThrowExpr(Index tag_index) { CHECK_RESULT( validator_.OnThrow(GetLocation(), Var(tag_index, GetLocation()))); diff --git a/src/interp/interp-util.cc b/src/interp/interp-util.cc index 6c7d892f4f..99b5a098eb 100644 --- a/src/interp/interp-util.cc +++ b/src/interp/interp-util.cc @@ -52,8 +52,14 @@ std::string TypedValueToString(const TypedValue& tv) { case Type::FuncRef: return StringPrintf("funcref:%" PRIzd, tv.value.Get().index); - case Type::ExternRef: - return StringPrintf("externref:%" PRIzd, tv.value.Get().index); + case Type::ExternRef: { + // Backward compatible print. + if (tv.value.Get() == Ref::Null) { + return "externref:0"; + } + return StringPrintf("externref:%" PRIzd, + tv.value.Get().GetHostVal() + 1); + } case Type::ExnRef: return StringPrintf("exnref:%" PRIzd, tv.value.Get().index); @@ -61,23 +67,38 @@ std::string TypedValueToString(const TypedValue& tv) { case Type::AnyRef: return StringPrintf("anyref:%" PRIzd, tv.value.Get().index); + case Type::ArrayRef: + return StringPrintf("arrayref:%" PRIzd, tv.value.Get().index); + + case Type::NullRef: + return StringPrintf("botref:0"); + + case Type::NullExternRef: + return StringPrintf("externref:0"); + + case Type::NullFuncRef: + return StringPrintf("funcref:0"); + case Type::EqRef: return StringPrintf("eqref:%" PRIzd, tv.value.Get().index); - case Type::I31Ref: - return StringPrintf("i31ref:%" PRIzd, tv.value.Get().index); + case Type::I31Ref: { + if (tv.value.Get() == Ref::Null) { + return "i31ref:null"; + } + return StringPrintf("i31ref:%d", + static_cast(tv.value.Get().GetU32Val())); + } + + case Type::Ref: + return StringPrintf("ref:%" PRIindex, tv.type.GetReferenceIndex()); + + case Type::RefNull: + return StringPrintf("refnull:%" PRIindex, tv.type.GetReferenceIndex()); case Type::StructRef: return StringPrintf("structref:%" PRIzd, tv.value.Get().index); - case Type::ArrayRef: - return StringPrintf("arrayref:%" PRIzd, tv.value.Get().index); - - case Type::NullFuncRef: - case Type::NullExternRef: - case Type::NullRef: - case Type::Ref: - case Type::RefNull: case Type::Func: case Type::Struct: case Type::Array: diff --git a/src/interp/interp.cc b/src/interp/interp.cc index d5eae194c4..7c6e5e0533 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -40,8 +40,9 @@ const char* GetName(ExternKind kind) { const char* GetName(ObjectKind kind) { static const char* kNames[] = { - "Null", "Foreign", "Trap", "Exception", "DefinedFunc", "HostFunc", - "Table", "Memory", "Global", "Tag", "Module", "Instance", + "Null", "Foreign", "Trap", "Exception", "DefinedFunc", + "HostFunc", "Table", "Memory", "Global", "Tag", + "Array", "Struct", "Module", "Instance", }; WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(kNames) == kCommandTypeCount); @@ -49,6 +50,79 @@ const char* GetName(ObjectKind kind) { return kNames[int(kind)]; } +static u32 GetTypeLog2Size(Type type) { + switch (type) { + case Type::I8: + return 0; + case Type::I16: + return 1; + case Type::I32: + case Type::F32: + return 2; + case Type::I64: + case Type::F64: + return 3; + case Type::V128: + return 4; + default: + WABT_UNREACHABLE; + } +} + +static void ArrayInitFromDataSegment(u32 log2_size, + Array* dst, + u32 dst_offset, + u32 size, + const u8* src) { + // Supports both unaligned access and big endian mode. + switch (log2_size) { + case 0: { + for (u32 i = 0; i < size; i++) { + u32 value = *src++; + dst->SetItem(dst_offset + i, Value::Make(value)); + } + return; + } + case 1: { + for (u32 i = 0; i < size; i++, src += 2) { + u32 value = src[0] | (static_cast(src[1]) << 8); + dst->SetItem(dst_offset + i, Value::Make(value)); + } + return; + } + case 2: { + for (u32 i = 0; i < size; i++, src += 4) { + u32 value = src[0]; + for (u32 j = 1; j < 4; j++) { + value |= static_cast(src[j]) << (j << 3); + } + dst->SetItem(dst_offset + i, Value::Make(value)); + } + return; + } + case 3: { + for (u32 i = 0; i < size; i++, src += 8) { + u64 value = src[0]; + for (u32 j = 1; j < 8; j++) { + value |= static_cast(src[j]) << (j << 3); + } + dst->SetItem(dst_offset + i, Value::Make(value)); + } + return; + } + case 4: { + for (u32 i = 0; i < size; i++, src += 16) { + v128 value; + memcpy(value.v, src, 16); + dst->SetItem(dst_offset + i, Value::Make(value)); + } + return; + } + default: + WABT_UNREACHABLE; + } +} + //// Refs //// // static const Ref Ref::Null{0}; @@ -321,18 +395,34 @@ bool TypesMatch(ValueType expected, ValueType actual) { return true; } - if (expected == Type::FuncRef && - (actual == Type::Ref || - (expected.IsNullableNonTypedRef() && - (actual == Type::FuncRef || actual == Type::RefNull)))) { - return true; + switch (expected) { + case Type::FuncRef: + return actual == Type::Ref || + (expected.IsNullableNonTypedRef() && + (actual == Type::FuncRef || actual == Type::RefNull)); + case Type::RefNull: + return actual == Type::Ref && + actual.GetReferenceIndex() == expected.GetReferenceIndex(); + case Type::AnyRef: + if (actual == Type::AnyRef || actual == Type::EqRef || + actual == Type::I31Ref || actual == Type::StructRef || + actual == Type::ArrayRef) { + break; + } + return false; + case Type::EqRef: + if (actual == Type::EqRef || actual == Type::I31Ref || + actual == Type::StructRef || actual == Type::ArrayRef) { + break; + } + return false; + default: + return false; } - if (actual == Type::Ref && expected == Type::RefNull && - actual.GetReferenceIndex() == expected.GetReferenceIndex()) { + if (expected.IsNullableRef() || actual.IsNonNullableRef()) { return true; } - return false; } @@ -374,22 +464,36 @@ bool Store::HasValueType(Ref ref, ValueType type) const { if (!IsValid(ref)) { return false; } - if (type == ValueType::ExternRef) { + if (ref == Ref::Null || type == ValueType::ExternRef) { return true; } - if (ref == Ref::Null) { - return true; + if (ref.IsI31OrHostVal()) { + if (ref.IsI31Val()) { + return type == ValueType::AnyRef || type == ValueType::EqRef || + type == ValueType::I31Ref || type == ValueType::ExternRef; + } + return type == ValueType::AnyRef; } Object* obj = objects_.Get(ref.index); switch (type) { + case ValueType::AnyRef: + return obj->kind() == ObjectKind::Array || + obj->kind() == ObjectKind::Struct; + case ValueType::EqRef: + return obj->kind() == ObjectKind::Array || + obj->kind() == ObjectKind::Struct; case ValueType::FuncRef: case ValueType::Ref: case ValueType::RefNull: return obj->kind() == ObjectKind::DefinedFunc || obj->kind() == ObjectKind::HostFunc; + case ValueType::ArrayRef: + return obj->kind() == ObjectKind::Array; case ValueType::ExnRef: return obj->kind() == ObjectKind::Exception; + case ValueType::StructRef: + return obj->kind() == ObjectKind::Struct; default: return false; } @@ -873,6 +977,52 @@ Result Tag::Match(Store& store, return MatchImpl(store, import_type, type_, out_trap); } +//// Array //// +Array::Array(Store& store, u32 size, Index type_index, Module* mod) + : Object(ObjectKind::Array), module_(mod->self()), type_index_(type_index) { + items_.resize(size); +} + +bool Array::IsValidRange(u64 offset, u64 size) const { + size_t array_size = items_.size(); + return size <= array_size && offset <= array_size - size; +} + +void Array::Mark(Store& store) { + store.Mark(module_); + + RefPtr mod = store.UnsafeGet(module_); + Type array_type = mod->desc().func_types[type_index_].params[0]; + + if (array_type.IsRef()) { + for (auto it : items_) { + store.Mark(it.Get()); + } + } +} + +//// Struct //// +Struct::Struct(Store& store, Index type_index, Module* mod) + : Object(ObjectKind::Struct), + module_(mod->self()), + type_index_(type_index) { + fields_.resize(mod->desc().func_types[type_index].params.size()); +} + +void Struct::Mark(Store& store) { + store.Mark(module_); + + RefPtr mod = store.UnsafeGet(module_); + const ValueTypes& field_types = mod->desc().func_types[type_index_].params; + size_t size = fields_.size(); + + for (size_t i = 0; i < size; i++) { + if (field_types[i].IsRef()) { + store.Mark(fields_[i].Get()); + } + } +} + //// ElemSegment //// ElemSegment::ElemSegment(Store& store, const ElemDesc* desc, @@ -1360,6 +1510,94 @@ void Thread::Push(Ref ref) { values_.push_back(Value::Make(ref)); } +bool Thread::CheckRefCast(Ref ref, Type expected) { + assert(expected.IsRef()); + + // Note: "any" and "extern" types represent the same value + // sets in the current implementation, so any.convert_extern + // and extern.convert_any are no operations. + if (ref.IsI31OrHostVal()) { + if (ref.IsI31Val()) { + return expected == Type::AnyRef || expected == Type::EqRef || + expected == Type::I31Ref || expected == Type::ExternRef; + } + return expected == Type::AnyRef || expected == Type::ExternRef; + } + + Object* object = store_.UnsafeGet(ref).get(); + + if (!expected.IsReferenceWithIndex()) { + if (Func::classof(object)) { + return expected == Type::FuncRef; + } + if (Array::classof(object)) { + return expected == Type::ArrayRef || expected == Type::EqRef || + expected == Type::AnyRef || expected == Type::ExternRef; + } + if (Struct::classof(object)) { + return expected == Type::StructRef || expected == Type::EqRef || + expected == Type::AnyRef || expected == Type::ExternRef; + } + return false; + } + + const FuncType& expected_type = + mod_->desc().func_types[expected.GetReferenceIndex()]; + Index expected_type_index = expected_type.canonical_index; + Index actual_type_index; + + switch (expected_type.kind) { + case FuncType::TypeKind::Func: { + if (!Func::classof(object)) { + return false; + } + const FuncType& type = cast(object)->type(); + if (type.func_types != &mod_->desc().func_types) { + return false; + } + actual_type_index = type.canonical_index; + break; + } + case FuncType::TypeKind::Array: { + if (!Array::classof(object)) { + return false; + } + Array* array = cast(object); + if (array->GetModule() != mod_->self()) { + return false; + } + actual_type_index = + mod_->desc().func_types[array->GetTypeIndex()].canonical_index; + break; + } + case FuncType::TypeKind::Struct: { + if (!Struct::classof(object)) { + return false; + } + Struct* struct_ = cast(object); + if (struct_->GetModule() != mod_->self()) { + return false; + } + actual_type_index = + mod_->desc().func_types[struct_->GetTypeIndex()].canonical_index; + break; + } + default: + WABT_UNREACHABLE; + } + + do { + if (expected_type_index == actual_type_index) { + return true; + } + + actual_type_index = + mod_->desc().func_types[actual_type_index].canonical_sub_index; + } while (actual_type_index != kInvalidIndex); + + return false; +} + RunResult Thread::StepInternal(Trap::Ptr* out_trap) { using O = Opcode; @@ -2180,6 +2418,91 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { case O::I64AtomicRmw16CmpxchgU: return DoAtomicRmwCmpxchg(instr, out_trap); case O::I64AtomicRmw32CmpxchgU: return DoAtomicRmwCmpxchg(instr, out_trap); + case O::ArrayCopy: return DoArrayCopy(out_trap); + case O::ArrayFill: return DoArrayFill(out_trap); + case O::ArrayGet: return DoArrayGet(out_trap); + case O::ArrayInitElem: return DoArrayInitElem(instr, out_trap); + case O::ArrayInitData: return DoArrayInitData(instr, out_trap); + case O::ArrayGetS: + case O::ArrayGetU: return DoArrayGetPacked(instr, out_trap); + case O::ArrayNew: return DoArrayNew(instr); + case O::ArrayNewData: return DoArrayNewData(instr, out_trap); + case O::ArrayNewElem: return DoArrayNewElem(instr, out_trap); + case O::ArrayNewFixed: return DoArrayNewFixed(instr); + case O::ArraySet: return DoArraySet(out_trap); + + case O::ArrayLen: { + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null array ref"); + Push(store_.UnsafeGet(ref)->Size()); + break; + } + + case O::ArrayNewDefault: { + Array::Ptr array = Array::New(store_, Pop(), instr.imm_u32, mod_); + Push(array->self()); + break; + } + + case O::BrOnCast: + case O::BrOnCastFail: return DoBrOnCast(instr); + + case O::I31GetS: { + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null i31 ref"); + Push(ref.GetS32Val()); + break; + } + + case O::I31GetU: { + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null i31 ref"); + Push(ref.GetU32Val()); + break; + } + + case O::RefI31: { + Push(Ref::CreateI31Val(Pop())); + break; + } + + case O::RefCast: + case O::RefCastNull: return DoRefCast(instr, out_trap); + case O::RefTest: + case O::RefTestNull: return DoRefTest(instr); + + case O::RefEq: { + Ref ref1 = Pop(); + Ref ref2 = Pop(); + Push(ref1.index == ref2.index); + break; + } + + case O::StructGetS: + case O::StructGetU: return DoStructGetPacked(instr, out_trap); + case O::StructNew: return DoStructNew(instr); + + case O::StructGet: { + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null struct ref"); + Push(store_.UnsafeGet(ref)->GetField(instr.imm_u32)); + break; + } + + case O::StructNewDefault: { + Struct::Ptr struct_ = Struct::New(store_, instr.imm_u32, mod_); + Push(struct_->self()); + break; + } + + case O::StructSet: { + Value value = Pop(); + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null struct ref"); + store_.UnsafeGet(ref)->SetField(instr.imm_u32, value); + break; + } + case O::Throw: { u32 tag_index = instr.imm_u32; Values params; @@ -2206,8 +2529,10 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { // The following opcodes are either never generated or should never be // executed. + case O::AnyConvertExtern: case O::Nop: case O::Block: + case O::ExternConvertAny: case O::Loop: case O::If: case O::Else: @@ -2852,6 +3177,255 @@ RunResult Thread::DoAtomicRmwCmpxchg(Instr instr, Trap::Ptr* out_trap) { return RunResult::Ok; } +RunResult Thread::DoArrayCopy(Trap::Ptr* out_trap) { + u32 size = Pop(); + u32 src_offset = Pop(); + Ref src_ref = Pop(); + u32 dst_offset = Pop(); + Ref dst_ref = Pop(); + + TRAP_IF(src_ref == Ref::Null || dst_ref == Ref::Null, "null array ref"); + RefPtr src_array = store_.UnsafeGet(src_ref); + TRAP_IF(!src_array->IsValidRange(src_offset, size), "invalid range"); + RefPtr dst_array = store_.UnsafeGet(dst_ref); + TRAP_IF(!dst_array->IsValidRange(dst_offset, size), "invalid range"); + + if (src_array.get() == dst_array.get() && src_offset < dst_offset) { + std::copy_backward(src_array->GetItems().begin() + src_offset, + src_array->GetItems().begin() + src_offset + size, + dst_array->GetItems().begin() + dst_offset + size); + } else { + std::copy(src_array->GetItems().begin() + src_offset, + src_array->GetItems().begin() + src_offset + size, + dst_array->GetItems().begin() + dst_offset); + } + return RunResult::Ok; +} + +RunResult Thread::DoArrayFill(Trap::Ptr* out_trap) { + u32 size = Pop(); + Value value = Pop(); + u32 offset = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(!array->IsValidRange(offset, size), "invalid range"); + std::fill(array->GetItems().begin() + offset, + array->GetItems().begin() + offset + size, value); + return RunResult::Ok; +} + +RunResult Thread::DoArrayGet(Trap::Ptr* out_trap) { + u32 index = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(index >= array->Size(), "invalid index"); + Push(array->GetItem(index)); + return RunResult::Ok; +} + +RunResult Thread::DoArrayInitElem(Instr instr, Trap::Ptr* out_trap) { + ElemSegment& segment = inst_->elems()[instr.imm_u32]; + u32 size = Pop(); + u32 src_offset = Pop(); + u32 dst_offset = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(!array->IsValidRange(dst_offset, size), "invalid range"); + TRAP_IF(!segment.IsValidRange(src_offset, size), "invalid range"); + for (size_t i = 0; i < size; i++) { + array->SetItem(dst_offset + i, + Value::Make(segment.elements()[src_offset + i])); + } + return RunResult::Ok; +} + +RunResult Thread::DoArrayInitData(Instr instr, Trap::Ptr* out_trap) { + DataSegment& data = inst_->datas()[instr.imm_u32x2.snd]; + u32 size = Pop(); + u32 src_offset = Pop(); + u32 dst_offset = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(!array->IsValidRange(dst_offset, size), "invalid range"); + Type array_type = mod_->desc().func_types[instr.imm_u32x2.fst].params[0]; + u32 log2_size = GetTypeLog2Size(array_type); + TRAP_IF(size >= (~static_cast(0)) >> log2_size, "invalid range"); + TRAP_IF(!data.IsValidRange(src_offset, size << log2_size), "invalid range"); + ArrayInitFromDataSegment(log2_size, array.get(), dst_offset, size, + data.desc().data.data() + src_offset); + return RunResult::Ok; +} + +RunResult Thread::DoArrayGetPacked(Instr instr, Trap::Ptr* out_trap) { + u32 index = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(index >= array->Size(), "invalid index"); + Value value = array->GetItem(index); + + if (instr.op == Opcode::ArrayGetS) { + if (instr.imm_u32) { + value.Set(static_cast(value.Get())); + } else { + value.Set(static_cast(value.Get())); + } + } else if (instr.imm_u32) { + value.Set(static_cast(value.Get())); + } else { + value.Set(static_cast(value.Get())); + } + Push(value); + return RunResult::Ok; +} + +RunResult Thread::DoArrayNew(Instr instr) { + u32 size = Pop(); + Value value = Pop(); + Array::Ptr array = Array::New(store_, size, instr.imm_u32, mod_); + + for (size_t i = array->Size(); i > 0; i--) { + array->SetItem(i - 1, value); + } + Push(array->self()); + return RunResult::Ok; +} + +RunResult Thread::DoArrayNewData(Instr instr, Trap::Ptr* out_trap) { + DataSegment& data = inst_->datas()[instr.imm_u32x2.snd]; + u32 size = Pop(); + u32 offset = Pop(); + Type array_type = mod_->desc().func_types[instr.imm_u32x2.fst].params[0]; + u32 log2_size = GetTypeLog2Size(array_type); + + TRAP_IF(size >= (~static_cast(0)) >> log2_size, "invalid range"); + TRAP_IF(!data.IsValidRange(offset, size << log2_size), "invalid range"); + Array::Ptr array = Array::New(store_, size, instr.imm_u32x2.fst, mod_); + ArrayInitFromDataSegment(log2_size, array.get(), 0, size, + data.desc().data.data() + offset); + Push(array->self()); + return RunResult::Ok; +} + +RunResult Thread::DoArrayNewElem(Instr instr, Trap::Ptr* out_trap) { + ElemSegment& segment = inst_->elems()[instr.imm_u32x2.snd]; + u32 size = Pop(); + u32 offset = Pop(); + + TRAP_IF(!segment.IsValidRange(offset, size), "invalid range"); + Array::Ptr array = Array::New(store_, size, instr.imm_u32x2.fst, mod_); + for (size_t i = 0; i < size; i++) { + array->SetItem(i, Value::Make(segment.elements()[offset + i])); + } + Push(array->self()); + return RunResult::Ok; +} + +RunResult Thread::DoArrayNewFixed(Instr instr) { + u32 size = instr.imm_u32x2.snd; + Array::Ptr array = Array::New(store_, size, instr.imm_u32x2.fst, mod_); + + for (size_t i = size; i > 0; i--) { + array->SetItem(i - 1, Pop()); + } + Push(array->self()); + return RunResult::Ok; +} + +RunResult Thread::DoArraySet(Trap::Ptr* out_trap) { + Value value = Pop(); + u32 index = Pop(); + Ref ref = Pop(); + + TRAP_IF(ref == Ref::Null, "null array ref"); + RefPtr array = store_.UnsafeGet(ref); + TRAP_IF(index >= array->Size(), "invalid index"); + array->SetItem(index, value); + return RunResult::Ok; +} + +RunResult Thread::DoBrOnCast(Instr instr) { + Ref ref = Pick(1).Get(); + u32 result = 0; + + if (ref == Ref::Null) { + result = (instr.op == Opcode::BrOnCast); + } else { + Type type(static_cast(instr.imm_u32x2.fst), + instr.imm_u32x2.snd); + result = CheckRefCast(ref, type); + } + Push(result); + return RunResult::Ok; +} + +RunResult Thread::DoRefCast(Instr instr, Trap::Ptr* out_trap) { + Ref ref = Pick(1).Get(); + if (ref == Ref::Null) { + TRAP_IF(instr.op == Opcode::RefCast, "null reference"); + return RunResult::Ok; + } + + Type type(static_cast(instr.imm_u32x2.fst), instr.imm_u32x2.snd); + TRAP_IF(!CheckRefCast(ref, type), "type error: invalid type cast"); + return RunResult::Ok; +} + +RunResult Thread::DoRefTest(Instr instr) { + Ref ref = Pop(); + u32 result = 0; + + if (ref == Ref::Null) { + result = (instr.op == Opcode::RefTestNull); + } else { + Type type(static_cast(instr.imm_u32x2.fst), + instr.imm_u32x2.snd); + result = CheckRefCast(ref, type); + } + Push(result); + return RunResult::Ok; +} + +RunResult Thread::DoStructGetPacked(Instr instr, Trap::Ptr* out_trap) { + Ref ref = Pop(); + TRAP_IF(ref == Ref::Null, "null struct ref"); + Value value = store_.UnsafeGet(ref)->GetField(instr.imm_u32x2.fst); + + if (instr.op == Opcode::StructGetS) { + if (instr.imm_u32x2.snd) { + value.Set(static_cast(value.Get())); + } else { + value.Set(static_cast(value.Get())); + } + } else if (instr.imm_u32x2.snd) { + value.Set(static_cast(value.Get())); + } else { + value.Set(static_cast(value.Get())); + } + Push(value); + return RunResult::Ok; +} + +RunResult Thread::DoStructNew(Instr instr) { + Struct::Ptr struct_ = Struct::New(store_, instr.imm_u32, mod_); + Struct* struct_ptr = struct_.get(); + + for (size_t i = struct_ptr->Size(); i > 0; i--) { + struct_ptr->SetField(i - 1, Pop()); + } + Push(struct_->self()); + return RunResult::Ok; +} + RunResult Thread::DoThrow(Exception::Ptr exn) { Istream::Offset target_offset = Istream::kInvalidOffset; u32 target_values, target_exceptions; diff --git a/src/interp/istream.cc b/src/interp/istream.cc index 827d1b7c30..cd09bed924 100644 --- a/src/interp/istream.cc +++ b/src/interp/istream.cc @@ -130,6 +130,9 @@ Instr Istream::Read(Offset* offset) const { instr.kind = InstrKind::Imm_0_Op_0; break; + case Opcode::ArrayLen: + case Opcode::AnyConvertExtern: + case Opcode::ExternConvertAny: case Opcode::F32Abs: case Opcode::F32Ceil: case Opcode::F32ConvertI32S: @@ -182,6 +185,8 @@ Instr Istream::Read(Offset* offset) const { case Opcode::I16X8ExtendHighI8X16U: case Opcode::I16X8ExtendLowI8X16S: case Opcode::I16X8ExtendLowI8X16U: + case Opcode::I31GetS: + case Opcode::I31GetU: case Opcode::I32Clz: case Opcode::I32Ctz: case Opcode::I32Eqz: @@ -245,6 +250,7 @@ Instr Istream::Read(Offset* offset) const { case Opcode::F64X2ConvertLowI32X4S: case Opcode::F64X2ConvertLowI32X4U: case Opcode::I8X16Splat: + case Opcode::RefI31: case Opcode::RefIsNull: case Opcode::RefAsNonNull: case Opcode::V128Not: @@ -261,10 +267,12 @@ Instr Istream::Read(Offset* offset) const { case Opcode::I32X4RelaxedTruncF32X4U: case Opcode::I32X4RelaxedTruncF64X2SZero: case Opcode::I32X4RelaxedTruncF64X2UZero: + case Opcode::RefEq: // 0 immediates, 1 operand. instr.kind = InstrKind::Imm_0_Op_1; break; + case Opcode::ArrayGet: case Opcode::F32Add: case Opcode::F32Copysign: case Opcode::F32Div: @@ -485,6 +493,7 @@ Instr Istream::Read(Offset* offset) const { instr.kind = InstrKind::Imm_0_Op_2; break; + case Opcode::ArraySet: case Opcode::Select: case Opcode::SelectT: case Opcode::F32X4RelaxedMadd: @@ -500,6 +509,16 @@ Instr Istream::Read(Offset* offset) const { instr.kind = InstrKind::Imm_0_Op_3; break; + case Opcode::ArrayFill: + // 0 immediates, 4 operands + instr.kind = InstrKind::Imm_0_Op_4; + break; + + case Opcode::ArrayCopy: + // 0 immediates, 5 operands + instr.kind = InstrKind::Imm_0_Op_5; + break; + case Opcode::Br: // Jump target immediate, 0 operands. instr.kind = InstrKind::Imm_Jump_Op_0; @@ -526,6 +545,7 @@ Instr Istream::Read(Offset* offset) const { case Opcode::DataDrop: case Opcode::ElemDrop: case Opcode::RefFunc: + case Opcode::StructNewDefault: case Opcode::Throw: case Opcode::Rethrow: // Index immediate, 0 operands. @@ -533,16 +553,22 @@ Instr Istream::Read(Offset* offset) const { instr.imm_u32 = ReadAt(offset); break; + case Opcode::ArrayNewDefault: case Opcode::GlobalSet: case Opcode::LocalSet: case Opcode::LocalTee: case Opcode::MemoryGrow: + case Opcode::StructGet: case Opcode::TableGet: // Index immediate, 1 operand. instr.kind = InstrKind::Imm_Index_Op_1; instr.imm_u32 = ReadAt(offset); break; + case Opcode::ArrayNew: + case Opcode::ArrayGetS: + case Opcode::ArrayGetU: + case Opcode::StructSet: case Opcode::TableSet: case Opcode::TableGrow: // Index immediate, 2 operands. @@ -557,8 +583,15 @@ Instr Istream::Read(Offset* offset) const { instr.imm_u32 = ReadAt(offset); break; + case Opcode::ArrayInitElem: + // Index immediate, 3 operands. + instr.kind = InstrKind::Imm_Index_Op_4; + instr.imm_u32 = ReadAt(offset); + break; + case Opcode::Call: case Opcode::InterpCallImport: + case Opcode::StructNew: instr.kind = InstrKind::Imm_Index_Op_N; instr.imm_u32 = ReadAt(offset); break; @@ -571,6 +604,29 @@ Instr Istream::Read(Offset* offset) const { instr.imm_u32x2.snd = ReadAt(offset); break; + case Opcode::ArrayNewFixed: + case Opcode::BrOnCast: + case Opcode::BrOnCastFail: + case Opcode::RefCast: + case Opcode::RefCastNull: + case Opcode::RefTest: + case Opcode::RefTestNull: + case Opcode::StructGetS: + case Opcode::StructGetU: + // Index + index immediates, 1 operand. + instr.kind = InstrKind::Imm_Index_Index_Op_1; + instr.imm_u32x2.fst = ReadAt(offset); + instr.imm_u32x2.snd = ReadAt(offset); + break; + + case Opcode::ArrayNewData: + case Opcode::ArrayNewElem: + // Index + index immediates, 2 operands. + instr.kind = InstrKind::Imm_Index_Index_Op_2; + instr.imm_u32x2.fst = ReadAt(offset); + instr.imm_u32x2.snd = ReadAt(offset); + break; + case Opcode::MemoryInit: case Opcode::TableInit: case Opcode::MemoryCopy: @@ -581,6 +637,13 @@ Instr Istream::Read(Offset* offset) const { instr.imm_u32x2.snd = ReadAt(offset); break; + case Opcode::ArrayInitData: + // Index + index immediates, 4 operands. + instr.kind = InstrKind::Imm_Index_Index_Op_3; + instr.imm_u32x2.fst = ReadAt(offset); + instr.imm_u32x2.snd = ReadAt(offset); + break; + case Opcode::F32Load: case Opcode::F64Load: case Opcode::V128Load8X8S: @@ -863,6 +926,20 @@ Istream::Offset Istream::Trace(Stream* stream, source->Pick(1, instr).c_str()); break; + case InstrKind::Imm_0_Op_4: + stream->Writef(" %s, %s, %s, %s\n", source->Pick(4, instr).c_str(), + source->Pick(3, instr).c_str(), + source->Pick(2, instr).c_str(), + source->Pick(1, instr).c_str()); + break; + + case InstrKind::Imm_0_Op_5: + stream->Writef( + " %s, %s, %s, %s, %s\n", source->Pick(5, instr).c_str(), + source->Pick(4, instr).c_str(), source->Pick(3, instr).c_str(), + source->Pick(2, instr).c_str(), source->Pick(1, instr).c_str()); + break; + case InstrKind::Imm_Jump_Op_0: stream->Writef(" @%u\n", instr.imm_u32); break; @@ -893,10 +970,28 @@ Istream::Offset Istream::Trace(Stream* stream, source->Pick(2, instr).c_str(), source->Pick(1, instr).c_str()); break; + case InstrKind::Imm_Index_Op_4: + stream->Writef( + " $%u, %s, %s, %s, %s\n", instr.imm_u32, + source->Pick(4, instr).c_str(), source->Pick(3, instr).c_str(), + source->Pick(2, instr).c_str(), source->Pick(1, instr).c_str()); + break; + case InstrKind::Imm_Index_Op_N: stream->Writef(" $%u\n", instr.imm_u32); // TODO param/result count? break; + case InstrKind::Imm_Index_Index_Op_1: + stream->Writef(" $%u, $%u, %s\n", instr.imm_u32x2.fst, + instr.imm_u32x2.snd, source->Pick(1, instr).c_str()); + break; + + case InstrKind::Imm_Index_Index_Op_2: + stream->Writef(" $%u, $%u, %s, %s\n", instr.imm_u32x2.fst, + instr.imm_u32x2.snd, source->Pick(2, instr).c_str(), + source->Pick(1, instr).c_str()); + break; + case InstrKind::Imm_Index_Index_Op_3: stream->Writef(" $%u, $%u, %s, %s, %s\n", instr.imm_u32x2.fst, instr.imm_u32x2.snd, source->Pick(3, instr).c_str(), @@ -904,6 +999,14 @@ Istream::Offset Istream::Trace(Stream* stream, source->Pick(1, instr).c_str()); break; + case InstrKind::Imm_Index_Index_Op_4: + stream->Writef(" $%u, $%u, %s, %s, %s, %s\n", instr.imm_u32x2.fst, + instr.imm_u32x2.snd, source->Pick(4, instr).c_str(), + source->Pick(3, instr).c_str(), + source->Pick(2, instr).c_str(), + source->Pick(1, instr).c_str()); + break; + case InstrKind::Imm_Index_Index_Op_N: stream->Writef(" $%u, $%u\n", instr.imm_u32x2.fst, instr.imm_u32x2.snd); // TODO param/result count? diff --git a/src/ir-util.cc b/src/ir-util.cc index 16a85cd220..eef81aedd0 100644 --- a/src/ir-util.cc +++ b/src/ir-util.cc @@ -97,6 +97,10 @@ void ModuleContext::EndFunc() { ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { switch (expr.type()) { + case ExprType::ArrayGet: + case ExprType::ArrayNew: + case ExprType::ArrayNewData: + case ExprType::ArrayNewElem: case ExprType::AtomicNotify: case ExprType::AtomicRmw: case ExprType::Binary: @@ -107,6 +111,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::AtomicStore: case ExprType::Store: case ExprType::TableSet: + case ExprType::StructSet: return {2, 0}; case ExprType::Block: @@ -120,6 +125,11 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { return {arity + 1, arity}; } + case ExprType::BrOnCast: { + Index arity = GetLabelArity(cast(&expr)->label_var); + return {arity + 1, arity + 1}; + } + case ExprType::BrOnNonNull: { Index arity = GetLabelArity(cast(&expr)->var); return {arity + 1, arity}; @@ -172,6 +182,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::TableSize: case ExprType::RefNull: case ExprType::RefFunc: + case ExprType::StructNewDefault: return {0, 1}; case ExprType::Unreachable: @@ -183,6 +194,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::CodeMetadata: return {0, 0}; + case ExprType::ArraySet: case ExprType::MemoryInit: case ExprType::TableInit: case ExprType::MemoryFill: @@ -191,17 +203,22 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::TableFill: return {3, 0}; + case ExprType::ArrayNewDefault: case ExprType::AtomicLoad: case ExprType::Convert: + case ExprType::GCUnary: case ExprType::Load: case ExprType::LocalTee: case ExprType::MemoryGrow: case ExprType::Unary: case ExprType::TableGet: + case ExprType::RefAsNonNull: + case ExprType::RefCast: case ExprType::RefIsNull: + case ExprType::RefTest: case ExprType::LoadSplat: case ExprType::LoadZero: - case ExprType::RefAsNonNull: + case ExprType::StructGet: return {1, 1}; case ExprType::Drop: @@ -288,6 +305,27 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::SimdShuffleOp: return {2, 1}; + + case ExprType::ArrayCopy: + return {5, 0}; + + case ExprType::ArrayFill: + case ExprType::ArrayInitData: + case ExprType::ArrayInitElem: + return {4, 0}; + + case ExprType::ArrayNewFixed: { + return {cast(&expr)->count, 1}; + } + + case ExprType::StructNew: { + auto struct_new = cast(&expr); + Index operand_count = 0; + if (const StructType* struct_ = module.GetStructType(struct_new->var)) { + operand_count = struct_->fields.size(); + } + return {operand_count, 0}; + } } WABT_UNREACHABLE; diff --git a/src/ir.cc b/src/ir.cc index 346869c751..279a3462b5 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -25,17 +25,29 @@ namespace { const char* ExprTypeName[] = { - "AtomicFence", + "ArrayCopy", + "ArrayFill", + "ArrayGet", + "ArrayInitData", + "ArrayInitElem", + "ArrayNew", + "ArrayNewData", + "ArrayNewDefault", + "ArrayNewElem", + "ArrayNewFixed", + "ArraySet", "AtomicLoad", "AtomicRmw", "AtomicRmwCmpxchg", "AtomicStore", "AtomicNotify", + "AtomicFence", "AtomicWait", "Binary", "Block", "Br", "BrIf", + "BrOnCast", "BrOnNonNull", "BrOnNull", "BrTable", @@ -47,6 +59,7 @@ const char* ExprTypeName[] = { "Const", "Convert", "Drop", + "GCUnary", "GlobalGet", "GlobalSet", "If", @@ -63,9 +76,11 @@ const char* ExprTypeName[] = { "MemorySize", "Nop", "RefAsNonNull", + "RefCast", "RefIsNull", "RefFunc", "RefNull", + "RefTest", "Rethrow", "Return", "ReturnCall", @@ -76,6 +91,10 @@ const char* ExprTypeName[] = { "SimdLoadLane", "SimdStoreLane", "SimdShuffleOp", + "StructGet", + "StructNew", + "StructNewDefault", + "StructSet", "LoadSplat", "LoadZero", "Store", @@ -345,6 +364,30 @@ FuncType* Module::GetFuncType(const Var& var) { return dyn_cast(types[index]); } +const StructType* Module::GetStructType(const Var& var) const { + return const_cast(this)->GetStructType(var); +} + +StructType* Module::GetStructType(const Var& var) { + Index index = type_bindings.FindIndex(var); + if (index >= types.size()) { + return nullptr; + } + return dyn_cast(types[index]); +} + +const ArrayType* Module::GetArrayType(const Var& var) const { + return const_cast(this)->GetArrayType(var); +} + +ArrayType* Module::GetArrayType(const Var& var) { + Index index = type_bindings.FindIndex(var); + if (index >= types.size()) { + return nullptr; + } + return dyn_cast(types[index]); +} + Index Module::GetFuncTypeIndex(const FuncSignature& sig) const { size_t range_index = 0; size_t range_start = types.size(); diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt index dfec434b39..2ce6000909 100644 --- a/src/lexer-keywords.txt +++ b/src/lexer-keywords.txt @@ -19,8 +19,23 @@ struct TokenInfo { %% any, Type::AnyRef, TokenType::Any anyref, Type::AnyRef +any.convert_extern, TokenType::GCUnary, Opcode::AnyConvertExtern array, Type::ArrayRef, TokenType::Array arrayref, Type::ArrayRef +array.copy, TokenType::ArrayCopy, Opcode::ArrayCopy +array.fill, TokenType::ArrayFill, Opcode::ArrayFill +array.get, TokenType::ArrayGet, Opcode::ArrayGet +array.get_s, TokenType::ArrayGetS, Opcode::ArrayGetS +array.get_u, TokenType::ArrayGetU, Opcode::ArrayGetU +array.init_data, TokenType::ArrayInitData, Opcode::ArrayInitData +array.init_elem, TokenType::ArrayInitElem, Opcode::ArrayInitElem +array.len, TokenType::GCUnary, Opcode::ArrayLen +array.new, TokenType::ArrayNew, Opcode::ArrayNew +array.new_data, TokenType::ArrayNewData, Opcode::ArrayNewData +array.new_default, TokenType::ArrayNewDefault, Opcode::ArrayNewDefault +array.new_elem, TokenType::ArrayNewElem, Opcode::ArrayNewElem +array.new_fixed, TokenType::ArrayNewFixed, Opcode::ArrayNewFixed +array.set, TokenType::ArraySet, Opcode::ArraySet after, TokenType::After assert_exception, TokenType::AssertException assert_exhaustion, TokenType::AssertExhaustion @@ -34,6 +49,8 @@ before, TokenType::Before binary, TokenType::Bin block, TokenType::Block, Opcode::Block br_if, TokenType::BrIf, Opcode::BrIf +br_on_cast, TokenType::BrOnCast, Opcode::BrOnCast +br_on_cast_fail, TokenType::BrOnCast, Opcode::BrOnCastFail br_on_non_null, TokenType::BrOnNonNull, Opcode::BrOnNonNull br_on_null, TokenType::BrOnNull, Opcode::BrOnNull br_table, TokenType::BrTable, Opcode::BrTable @@ -62,6 +79,7 @@ eq, Type::EqRef, TokenType::Eq eqref, Type::EqRef extern, Type::ExternRef, TokenType::Extern externref, Type::ExternRef +extern.convert_any, TokenType::GCUnary, Opcode::ExternConvertAny exn, Type::ExnRef, TokenType::Exn exnref, Type::ExnRef export, TokenType::Export @@ -253,6 +271,8 @@ i16x8.extend_low_i8x16_s, TokenType::Unary, Opcode::I16X8ExtendLowI8X16S i16x8.extend_low_i8x16_u, TokenType::Unary, Opcode::I16X8ExtendLowI8X16U i31, Type::I31Ref, TokenType::I31 i31ref, Type::I31Ref +i31.get_s, TokenType::GCUnary, Opcode::I31GetS +i31.get_u, TokenType::GCUnary, Opcode::I31GetU i32.add, TokenType::Binary, Opcode::I32Add i32.and, TokenType::Binary, Opcode::I32And i32.atomic.load16_u, TokenType::AtomicLoad, Opcode::I32AtomicLoad16U @@ -582,11 +602,18 @@ param, TokenType::Param rec, TokenType::Rec ref, TokenType::Ref quote, TokenType::Quote +ref.array, TokenType::RefArray ref.as_non_null, TokenType::RefAsNonNull, Opcode::RefAsNonNull +ref.cast, TokenType::RefCast, Opcode::RefCast +ref.eq, TokenType::RefEq, Opcode::RefEq ref.extern, TokenType::RefExtern ref.func, TokenType::RefFunc, Opcode::RefFunc +ref.host, TokenType::RefHost +ref.i31, TokenType::RefI31, Opcode::RefI31 ref.is_null, TokenType::RefIsNull, Opcode::RefIsNull ref.null, TokenType::RefNull, Opcode::RefNull +ref.struct, TokenType::RefStruct +ref.test, TokenType::RefTest, Opcode::RefTest register, TokenType::Register result, TokenType::Result rethrow, TokenType::Rethrow, Opcode::Rethrow @@ -599,6 +626,12 @@ shared, TokenType::Shared start, TokenType::Start struct, Type::StructRef, TokenType::Struct structref, Type::StructRef +struct.get, TokenType::StructGet, Opcode::StructGet +struct.get_s, TokenType::StructGetS, Opcode::StructGetS +struct.get_u, TokenType::StructGetU, Opcode::StructGetU +struct.new, TokenType::StructNew, Opcode::StructNew +struct.new_default, TokenType::StructNewDefault, Opcode::StructNewDefault +struct.set, TokenType::StructSet, Opcode::StructSet sub, TokenType::Sub table.copy, TokenType::TableCopy, Opcode::TableCopy table.fill, TokenType::TableFill, Opcode::TableFill diff --git a/src/opcode.cc b/src/opcode.cc index b01e615de5..51ce5de6fa 100644 --- a/src/opcode.cc +++ b/src/opcode.cc @@ -366,6 +366,36 @@ bool Opcode::IsEnabled(const Features& features) const { case Opcode::RefAsNonNull: return features.function_references_enabled(); + case Opcode::RefEq: + case Opcode::StructNew: + case Opcode::StructNewDefault: + case Opcode::StructGet: + case Opcode::StructGetS: + case Opcode::StructGetU: + case Opcode::StructSet: + case Opcode::ArrayNew: + case Opcode::ArrayNewDefault: + case Opcode::ArrayNewFixed: + case Opcode::ArrayNewData: + case Opcode::ArrayNewElem: + case Opcode::ArrayGet: + case Opcode::ArrayGetS: + case Opcode::ArrayGetU: + case Opcode::ArraySet: + case Opcode::ArrayLen: + case Opcode::ArrayFill: + case Opcode::ArrayCopy: + case Opcode::ArrayInitData: + case Opcode::ArrayInitElem: + case Opcode::AnyConvertExtern: + case Opcode::ExternConvertAny: + case Opcode::RefCast: + case Opcode::RefI31: + case Opcode::RefTest: + case Opcode::I31GetS: + case Opcode::I31GetU: + return features.gc_enabled(); + // Interpreter opcodes are never "enabled". case Opcode::InterpAlloca: case Opcode::InterpBrUnless: diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc index 7b20d57738..dbf941ee2e 100644 --- a/src/prebuilt/lexer-keywords.cc +++ b/src/prebuilt/lexer-keywords.cc @@ -48,7 +48,7 @@ struct TokenInfo { Opcode opcode; }; }; -/* maximum key range = 2512, duplicates = 0 */ +/* maximum key range = 3324, duplicates = 0 */ class Perfect_Hash { @@ -63,32 +63,32 @@ Perfect_Hash::hash (const char *str, size_t len) { static unsigned short asso_values[] = { - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 10, 2532, 2532, 652, - 334, 8, 7, 7, 288, 243, 174, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 133, 20, 8, 753, 10, - 90, 7, 339, 9, 309, 404, 11, 8, 7, 118, - 21, 63, 654, 915, 8, 15, 11, 81, 441, 691, - 75, 256, 315, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, - 2532, 2532, 2532, 2532, 2532, 2532, 2532 + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 85, 3337, 3337, 490, + 351, 1, 145, 0, 545, 469, 322, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 11, 3, 3, 300, 125, + 42, 6, 432, 4, 598, 204, 21, 2, 20, 131, + 13, 51, 726, 709, 29, 2, 0, 0, 742, 968, + 404, 158, 33, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, 3337, + 3337, 3337, 3337, 3337, 3337, 3337, 3337 }; unsigned int hval = len; @@ -158,1611 +158,1770 @@ Perfect_Hash::InWordSet (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 625, + TOTAL_KEYWORDS = 658, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 35, - MIN_HASH_VALUE = 20, - MAX_HASH_VALUE = 2531 + MIN_HASH_VALUE = 13, + MAX_HASH_VALUE = 3336 }; static struct TokenInfo wordlist[] = { {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 40 "src/lexer-keywords.txt" - {"br", TokenType::Br, Opcode::Br}, - {""}, {""}, {""}, {""}, {""}, -#line 159 "src/lexer-keywords.txt" - {"f64", Type::F64}, - {""}, -#line 475 "src/lexer-keywords.txt" - {"i64", Type::I64}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 129 "src/lexer-keywords.txt" - {"f32x4", TokenType::F32X4}, - {""}, -#line 375 "src/lexer-keywords.txt" - {"i32x4", TokenType::I32X4}, {""}, {""}, {""}, {""}, -#line 144 "src/lexer-keywords.txt" - {"f64.le", TokenType::Compare, Opcode::F64Le}, -#line 83 "src/lexer-keywords.txt" - {"f32.le", TokenType::Compare, Opcode::F32Le}, -#line 142 "src/lexer-keywords.txt" +#line 67 "src/lexer-keywords.txt" + {"data", TokenType::Data}, +#line 161 "src/lexer-keywords.txt" + {"f64.gt", TokenType::Compare, Opcode::F64Gt}, +#line 100 "src/lexer-keywords.txt" + {"f32.gt", TokenType::Compare, Opcode::F32Gt}, +#line 587 "src/lexer-keywords.txt" + {"mut", TokenType::Mut}, + {""}, {""}, {""}, {""}, {""}, +#line 616 "src/lexer-keywords.txt" + {"ref.test", TokenType::RefTest, Opcode::RefTest}, + {""}, {""}, {""}, +#line 160 "src/lexer-keywords.txt" {"f64.ge", TokenType::Compare, Opcode::F64Ge}, -#line 81 "src/lexer-keywords.txt" +#line 99 "src/lexer-keywords.txt" {"f32.ge", TokenType::Compare, Opcode::F32Ge}, -#line 33 "src/lexer-keywords.txt" - {"before", TokenType::Before}, - {""}, {""}, {""}, -#line 146 "src/lexer-keywords.txt" +#line 618 "src/lexer-keywords.txt" + {"result", TokenType::Result}, + {""}, +#line 164 "src/lexer-keywords.txt" {"f64.lt", TokenType::Compare, Opcode::F64Lt}, -#line 85 "src/lexer-keywords.txt" +#line 103 "src/lexer-keywords.txt" {"f32.lt", TokenType::Compare, Opcode::F32Lt}, -#line 143 "src/lexer-keywords.txt" - {"f64.gt", TokenType::Compare, Opcode::F64Gt}, -#line 82 "src/lexer-keywords.txt" - {"f32.gt", TokenType::Compare, Opcode::F32Gt}, -#line 566 "src/lexer-keywords.txt" - {"module", TokenType::Module}, - {""}, -#line 152 "src/lexer-keywords.txt" + {""}, {""}, {""}, +#line 170 "src/lexer-keywords.txt" {"f64.ne", TokenType::Compare, Opcode::F64Ne}, -#line 91 "src/lexer-keywords.txt" +#line 109 "src/lexer-keywords.txt" {"f32.ne", TokenType::Compare, Opcode::F32Ne}, -#line 451 "src/lexer-keywords.txt" - {"i64.ne", TokenType::Compare, Opcode::I64Ne}, -#line 308 "src/lexer-keywords.txt" - {"i32.ne", TokenType::Compare, Opcode::I32Ne}, -#line 591 "src/lexer-keywords.txt" - {"result", TokenType::Result}, {""}, -#line 109 "src/lexer-keywords.txt" - {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, -#line 600 "src/lexer-keywords.txt" - {"struct", Type::StructRef, TokenType::Struct}, -#line 107 "src/lexer-keywords.txt" - {"f32x4.ge", TokenType::Compare, Opcode::F32X4Ge}, - {""}, {""}, {""}, -#line 151 "src/lexer-keywords.txt" +#line 169 "src/lexer-keywords.txt" {"f64.neg", TokenType::Unary, Opcode::F64Neg}, -#line 90 "src/lexer-keywords.txt" - {"f32.neg", TokenType::Unary, Opcode::F32Neg}, -#line 110 "src/lexer-keywords.txt" - {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, -#line 53 "src/lexer-keywords.txt" - {"do", TokenType::Do}, #line 108 "src/lexer-keywords.txt" - {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, - {""}, -#line 100 "src/lexer-keywords.txt" - {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, - {""}, -#line 116 "src/lexer-keywords.txt" - {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, + {"f32.neg", TokenType::Unary, Opcode::F32Neg}, + {""}, {""}, +#line 162 "src/lexer-keywords.txt" + {"f64.le", TokenType::Compare, Opcode::F64Le}, +#line 101 "src/lexer-keywords.txt" + {"f32.le", TokenType::Compare, Opcode::F32Le}, +#line 458 "src/lexer-keywords.txt" + {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, +#line 317 "src/lexer-keywords.txt" + {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, {""}, -#line 361 "src/lexer-keywords.txt" - {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, -#line 115 "src/lexer-keywords.txt" - {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, +#line 615 "src/lexer-keywords.txt" + {"ref.struct", TokenType::RefStruct}, +#line 457 "src/lexer-keywords.txt" + {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, +#line 316 "src/lexer-keywords.txt" + {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, +#line 456 "src/lexer-keywords.txt" + {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, +#line 315 "src/lexer-keywords.txt" + {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, +#line 471 "src/lexer-keywords.txt" + {"i64.ne", TokenType::Compare, Opcode::I64Ne}, +#line 328 "src/lexer-keywords.txt" + {"i32.ne", TokenType::Compare, Opcode::I32Ne}, +#line 455 "src/lexer-keywords.txt" + {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, +#line 314 "src/lexer-keywords.txt" + {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, {""}, -#line 360 "src/lexer-keywords.txt" - {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, - {""}, {""}, {""}, -#line 194 "src/lexer-keywords.txt" - {"func", Type::FuncRef, TokenType::Func}, - {""}, {""}, {""}, -#line 344 "src/lexer-keywords.txt" - {"i32x4.le_s", TokenType::Compare, Opcode::I32X4LeS}, -#line 193 "src/lexer-keywords.txt" - {"final", TokenType::Final}, -#line 340 "src/lexer-keywords.txt" - {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, +#line 586 "src/lexer-keywords.txt" + {"module", TokenType::Module}, +#line 65 "src/lexer-keywords.txt" + {"code", TokenType::Code}, +#line 70 "src/lexer-keywords.txt" + {"do", TokenType::Do}, +#line 469 "src/lexer-keywords.txt" + {"i64.lt_u", TokenType::Compare, Opcode::I64LtU}, +#line 326 "src/lexer-keywords.txt" + {"i32.lt_u", TokenType::Compare, Opcode::I32LtU}, {""}, -#line 352 "src/lexer-keywords.txt" - {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, -#line 127 "src/lexer-keywords.txt" - {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, -#line 342 "src/lexer-keywords.txt" - {"i32x4.gt_s", TokenType::Compare, Opcode::I32X4GtS}, -#line 150 "src/lexer-keywords.txt" +#line 623 "src/lexer-keywords.txt" + {"return", TokenType::Return, Opcode::Return}, +#line 468 "src/lexer-keywords.txt" + {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, +#line 325 "src/lexer-keywords.txt" + {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, +#line 460 "src/lexer-keywords.txt" + {"i64.le_u", TokenType::Compare, Opcode::I64LeU}, +#line 319 "src/lexer-keywords.txt" + {"i32.le_u", TokenType::Compare, Opcode::I32LeU}, +#line 168 "src/lexer-keywords.txt" {"f64.nearest", TokenType::Unary, Opcode::F64Nearest}, -#line 89 "src/lexer-keywords.txt" +#line 107 "src/lexer-keywords.txt" {"f32.nearest", TokenType::Unary, Opcode::F32Nearest}, +#line 459 "src/lexer-keywords.txt" + {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, +#line 318 "src/lexer-keywords.txt" + {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 614 "src/lexer-keywords.txt" + {"ref.null", TokenType::RefNull, Opcode::RefNull}, + {""}, {""}, +#line 488 "src/lexer-keywords.txt" + {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, +#line 344 "src/lexer-keywords.txt" + {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, + {""}, {""}, +#line 487 "src/lexer-keywords.txt" + {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, +#line 343 "src/lexer-keywords.txt" + {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, + {""}, {""}, {""}, +#line 68 "src/lexer-keywords.txt" + {"declare", TokenType::Declare}, +#line 211 "src/lexer-keywords.txt" + {"final", TokenType::Final}, +#line 174 "src/lexer-keywords.txt" + {"f64.store", TokenType::Store, Opcode::F64Store}, +#line 112 "src/lexer-keywords.txt" + {"f32.store", TokenType::Store, Opcode::F32Store}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 592 "src/lexer-keywords.txt" + {"none", Type::NullRef, TokenType::None}, + {""}, {""}, {""}, +#line 606 "src/lexer-keywords.txt" + {"ref.as_non_null", TokenType::RefAsNonNull, Opcode::RefAsNonNull}, {""}, -#line 50 "src/lexer-keywords.txt" - {"data", TokenType::Data}, +#line 485 "src/lexer-keywords.txt" + {"i64.store", TokenType::Store, Opcode::I64Store}, +#line 341 "src/lexer-keywords.txt" + {"i32.store", TokenType::Store, Opcode::I32Store}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 406 "src/lexer-keywords.txt" + {"i64.and", TokenType::Binary, Opcode::I64And}, +#line 277 "src/lexer-keywords.txt" + {"i32.and", TokenType::Binary, Opcode::I32And}, + {""}, {""}, {""}, +#line 627 "src/lexer-keywords.txt" + {"struct", Type::StructRef, TokenType::Struct}, {""}, {""}, -#line 452 "src/lexer-keywords.txt" +#line 472 "src/lexer-keywords.txt" {"i64.or", TokenType::Binary, Opcode::I64Or}, -#line 309 "src/lexer-keywords.txt" +#line 329 "src/lexer-keywords.txt" {"i32.or", TokenType::Binary, Opcode::I32Or}, - {""}, {""}, {""}, -#line 48 "src/lexer-keywords.txt" - {"code", TokenType::Code}, -#line 114 "src/lexer-keywords.txt" - {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, -#line 610 "src/lexer-keywords.txt" + {""}, {""}, +#line 149 "src/lexer-keywords.txt" + {"f64.add", TokenType::Binary, Opcode::F64Add}, +#line 87 "src/lexer-keywords.txt" + {"f32.add", TokenType::Binary, Opcode::F32Add}, +#line 643 "src/lexer-keywords.txt" {"table", TokenType::Table}, - {""}, {""}, {""}, {""}, {""}, -#line 567 "src/lexer-keywords.txt" - {"mut", TokenType::Mut}, {""}, -#line 582 "src/lexer-keywords.txt" - {"rec", TokenType::Rec}, -#line 571 "src/lexer-keywords.txt" - {"nofunc", Type::NullFuncRef, TokenType::NoFunc}, - {""}, {""}, -#line 457 "src/lexer-keywords.txt" +#line 607 "src/lexer-keywords.txt" + {"ref.cast", TokenType::RefCast, Opcode::RefCast}, + {""}, {""}, {""}, {""}, +#line 477 "src/lexer-keywords.txt" {"i64.rotl", TokenType::Binary, Opcode::I64Rotl}, -#line 314 "src/lexer-keywords.txt" +#line 334 "src/lexer-keywords.txt" {"i32.rotl", TokenType::Binary, Opcode::I32Rotl}, -#line 458 "src/lexer-keywords.txt" - {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, -#line 315 "src/lexer-keywords.txt" - {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, -#line 123 "src/lexer-keywords.txt" - {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, - {""}, -#line 363 "src/lexer-keywords.txt" - {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, -#line 156 "src/lexer-keywords.txt" - {"f64.store", TokenType::Store, Opcode::F64Store}, -#line 94 "src/lexer-keywords.txt" - {"f32.store", TokenType::Store, Opcode::F32Store}, -#line 465 "src/lexer-keywords.txt" - {"i64.store", TokenType::Store, Opcode::I64Store}, -#line 321 "src/lexer-keywords.txt" - {"i32.store", TokenType::Store, Opcode::I32Store}, {""}, -#line 51 "src/lexer-keywords.txt" - {"declare", TokenType::Declare}, - {""}, {""}, -#line 572 "src/lexer-keywords.txt" - {"none", Type::NullRef, TokenType::None}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 605 "src/lexer-keywords.txt" - {"table.get", TokenType::TableGet, Opcode::TableGet}, -#line 133 "src/lexer-keywords.txt" +#line 177 "src/lexer-keywords.txt" + {"f64", Type::F64}, + {""}, {""}, {""}, +#line 57 "src/lexer-keywords.txt" + {"br", TokenType::Br, Opcode::Br}, +#line 405 "src/lexer-keywords.txt" + {"i64.add", TokenType::Binary, Opcode::I64Add}, +#line 276 "src/lexer-keywords.txt" + {"i32.add", TokenType::Binary, Opcode::I32Add}, +#line 466 "src/lexer-keywords.txt" + {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, +#line 323 "src/lexer-keywords.txt" + {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, +#line 465 "src/lexer-keywords.txt" + {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, +#line 322 "src/lexer-keywords.txt" + {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, + {""}, +#line 69 "src/lexer-keywords.txt" + {"delegate", TokenType::Delegate}, + {""}, {""}, +#line 478 "src/lexer-keywords.txt" + {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, +#line 335 "src/lexer-keywords.txt" + {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, +#line 495 "src/lexer-keywords.txt" + {"i64", Type::I64}, +#line 163 "src/lexer-keywords.txt" + {"f64.load", TokenType::Load, Opcode::F64Load}, +#line 102 "src/lexer-keywords.txt" + {"f32.load", TokenType::Load, Opcode::F32Load}, +#line 602 "src/lexer-keywords.txt" + {"rec", TokenType::Rec}, + {""}, {""}, {""}, +#line 48 "src/lexer-keywords.txt" + {"before", TokenType::Before}, + {""}, {""}, {""}, +#line 176 "src/lexer-keywords.txt" + {"f64.trunc", TokenType::Unary, Opcode::F64Trunc}, +#line 114 "src/lexer-keywords.txt" + {"f32.trunc", TokenType::Unary, Opcode::F32Trunc}, +#line 167 "src/lexer-keywords.txt" + {"f64.mul", TokenType::Binary, Opcode::F64Mul}, +#line 106 "src/lexer-keywords.txt" + {"f32.mul", TokenType::Binary, Opcode::F32Mul}, +#line 212 "src/lexer-keywords.txt" + {"func", Type::FuncRef, TokenType::Func}, + {""}, {""}, +#line 467 "src/lexer-keywords.txt" + {"i64.load", TokenType::Load, Opcode::I64Load}, +#line 324 "src/lexer-keywords.txt" + {"i32.load", TokenType::Load, Opcode::I32Load}, + {""}, {""}, {""}, {""}, {""}, +#line 647 "src/lexer-keywords.txt" + {"try", TokenType::Try, Opcode::Try}, + {""}, {""}, +#line 60 "src/lexer-keywords.txt" + {"call", TokenType::Call, Opcode::Call}, + {""}, +#line 470 "src/lexer-keywords.txt" + {"i64.mul", TokenType::Binary, Opcode::I64Mul}, +#line 327 "src/lexer-keywords.txt" + {"i32.mul", TokenType::Binary, Opcode::I32Mul}, + {""}, {""}, {""}, +#line 151 "src/lexer-keywords.txt" {"f64.const", TokenType::Const, Opcode::F64Const}, -#line 71 "src/lexer-keywords.txt" +#line 89 "src/lexer-keywords.txt" {"f32.const", TokenType::Const, Opcode::F32Const}, -#line 424 "src/lexer-keywords.txt" +#line 594 "src/lexer-keywords.txt" + {"null", TokenType::Null}, +#line 476 "src/lexer-keywords.txt" + {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, +#line 333 "src/lexer-keywords.txt" + {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, +#line 475 "src/lexer-keywords.txt" + {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, +#line 332 "src/lexer-keywords.txt" + {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, + {""}, {""}, {""}, {""}, +#line 55 "src/lexer-keywords.txt" + {"br_on_null", TokenType::BrOnNull, Opcode::BrOnNull}, + {""}, {""}, +#line 575 "src/lexer-keywords.txt" + {"local", TokenType::Local}, +#line 445 "src/lexer-keywords.txt" + {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, +#line 307 "src/lexer-keywords.txt" + {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, +#line 444 "src/lexer-keywords.txt" {"i64.const", TokenType::Const, Opcode::I64Const}, -#line 286 "src/lexer-keywords.txt" +#line 306 "src/lexer-keywords.txt" {"i32.const", TokenType::Const, Opcode::I32Const}, {""}, -#line 608 "src/lexer-keywords.txt" +#line 634 "src/lexer-keywords.txt" + {"struct.set", TokenType::StructSet, Opcode::StructSet}, + {""}, +#line 629 "src/lexer-keywords.txt" + {"struct.get", TokenType::StructGet, Opcode::StructGet}, + {""}, +#line 631 "src/lexer-keywords.txt" + {"struct.get_u", TokenType::StructGetU, Opcode::StructGetU}, + {""}, {""}, +#line 622 "src/lexer-keywords.txt" + {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, +#line 630 "src/lexer-keywords.txt" + {"struct.get_s", TokenType::StructGetS, Opcode::StructGetS}, +#line 641 "src/lexer-keywords.txt" {"table.set", TokenType::TableSet, Opcode::TableSet}, {""}, -#line 596 "src/lexer-keywords.txt" - {"return", TokenType::Return, Opcode::Return}, +#line 638 "src/lexer-keywords.txt" + {"table.get", TokenType::TableGet, Opcode::TableGet}, + {""}, +#line 605 "src/lexer-keywords.txt" + {"ref.array", TokenType::RefArray}, + {""}, +#line 443 "src/lexer-keywords.txt" + {"i64.clz", TokenType::Unary, Opcode::I64Clz}, +#line 305 "src/lexer-keywords.txt" + {"i32.clz", TokenType::Unary, Opcode::I32Clz}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 126 "src/lexer-keywords.txt" + {"f32x4.gt", TokenType::Compare, Opcode::F32X4Gt}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 589 "src/lexer-keywords.txt" - {"ref.null", TokenType::RefNull, Opcode::RefNull}, -#line 158 "src/lexer-keywords.txt" - {"f64.trunc", TokenType::Unary, Opcode::F64Trunc}, -#line 96 "src/lexer-keywords.txt" - {"f32.trunc", TokenType::Unary, Opcode::F32Trunc}, - {""}, {""}, {""}, +#line 125 "src/lexer-keywords.txt" + {"f32x4.ge", TokenType::Compare, Opcode::F32X4Ge}, + {""}, +#line 54 "src/lexer-keywords.txt" + {"br_on_non_null", TokenType::BrOnNonNull, Opcode::BrOnNonNull}, +#line 624 "src/lexer-keywords.txt" + {"select", TokenType::Select, Opcode::Select}, +#line 128 "src/lexer-keywords.txt" + {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, + {""}, {""}, +#line 363 "src/lexer-keywords.txt" + {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, +#line 133 "src/lexer-keywords.txt" + {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, +#line 134 "src/lexer-keywords.txt" + {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, + {""}, #line 362 "src/lexer-keywords.txt" - {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, + {"i32x4.gt_s", TokenType::Compare, Opcode::I32X4GtS}, + {""}, +#line 361 "src/lexer-keywords.txt" + {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, + {""}, {""}, +#line 127 "src/lexer-keywords.txt" + {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, +#line 360 "src/lexer-keywords.txt" + {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, {""}, {""}, {""}, {""}, {""}, -#line 597 "src/lexer-keywords.txt" - {"select", TokenType::Select, Opcode::Select}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 373 "src/lexer-keywords.txt" + {"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU}, + {""}, +#line 380 "src/lexer-keywords.txt" + {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, +#line 381 "src/lexer-keywords.txt" + {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, +#line 372 "src/lexer-keywords.txt" + {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, +#line 613 "src/lexer-keywords.txt" + {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, +#line 365 "src/lexer-keywords.txt" + {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, + {""}, #line 52 "src/lexer-keywords.txt" - {"delegate", TokenType::Delegate}, -#line 586 "src/lexer-keywords.txt" - {"ref.extern", TokenType::RefExtern}, + {"br_on_cast", TokenType::BrOnCast, Opcode::BrOnCast}, + {""}, +#line 364 "src/lexer-keywords.txt" + {"i32x4.le_s", TokenType::Compare, Opcode::I32X4LeS}, {""}, {""}, -#line 507 "src/lexer-keywords.txt" - {"i64.xor", TokenType::Binary, Opcode::I64Xor}, -#line 384 "src/lexer-keywords.txt" - {"i32.xor", TokenType::Binary, Opcode::I32Xor}, +#line 573 "src/lexer-keywords.txt" + {"local.set", TokenType::LocalSet, Opcode::LocalSet}, + {""}, +#line 572 "src/lexer-keywords.txt" + {"local.get", TokenType::LocalGet, Opcode::LocalGet}, +#line 132 "src/lexer-keywords.txt" + {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, +#line 574 "src/lexer-keywords.txt" + {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, +#line 147 "src/lexer-keywords.txt" + {"f32x4", TokenType::F32X4}, + {""}, {""}, {""}, {""}, +#line 626 "src/lexer-keywords.txt" + {"start", TokenType::Start}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 395 "src/lexer-keywords.txt" + {"i32x4", TokenType::I32X4}, +#line 148 "src/lexer-keywords.txt" + {"f64.abs", TokenType::Unary, Opcode::F64Abs}, +#line 86 "src/lexer-keywords.txt" + {"f32.abs", TokenType::Unary, Opcode::F32Abs}, + {""}, {""}, {""}, {""}, +#line 591 "src/lexer-keywords.txt" + {"nofunc", Type::NullFuncRef, TokenType::NoFunc}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 508 "src/lexer-keywords.txt" +#line 117 "src/lexer-keywords.txt" + {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, + {""}, {""}, {""}, +#line 355 "src/lexer-keywords.txt" + {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 214 "src/lexer-keywords.txt" + {"function", TokenType::Function}, +#line 528 "src/lexer-keywords.txt" {"i8", Type::I8}, + {""}, {""}, +#line 354 "src/lexer-keywords.txt" + {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, + {""}, +#line 584 "src/lexer-keywords.txt" + {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 115 "src/lexer-keywords.txt" + {"f32", Type::F32}, + {""}, {""}, {""}, +#line 39 "src/lexer-keywords.txt" + {"after", TokenType::After}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 648 "src/lexer-keywords.txt" + {"try_table", TokenType::TryTable, Opcode::TryTable}, +#line 166 "src/lexer-keywords.txt" + {"f64.min", TokenType::Binary, Opcode::F64Min}, +#line 105 "src/lexer-keywords.txt" + {"f32.min", TokenType::Binary, Opcode::F32Min}, + {""}, {""}, +#line 351 "src/lexer-keywords.txt" + {"i32", Type::I32}, +#line 585 "src/lexer-keywords.txt" + {"memory", TokenType::Memory}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 442 "src/lexer-keywords.txt" + {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, +#line 304 "src/lexer-keywords.txt" + {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, + {""}, +#line 150 "src/lexer-keywords.txt" + {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, +#line 88 "src/lexer-keywords.txt" + {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 131 "src/lexer-keywords.txt" + {"f32x4.mul", TokenType::Binary, Opcode::F32X4Mul}, +#line 625 "src/lexer-keywords.txt" + {"shared", TokenType::Shared}, + {""}, {""}, {""}, {""}, {""}, +#line 275 "src/lexer-keywords.txt" + {"i31.get_u", TokenType::GCUnary, Opcode::I31GetU}, + {""}, +#line 274 "src/lexer-keywords.txt" + {"i31.get_s", TokenType::GCUnary, Opcode::I31GetS}, + {""}, {""}, {""}, +#line 375 "src/lexer-keywords.txt" + {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, + {""}, +#line 374 "src/lexer-keywords.txt" + {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, + {""}, +#line 379 "src/lexer-keywords.txt" + {"i32x4.mul", TokenType::Binary, Opcode::I32X4Mul}, +#line 145 "src/lexer-keywords.txt" + {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, + {""}, {""}, +#line 118 "src/lexer-keywords.txt" + {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, + {""}, {""}, {""}, {""}, {""}, +#line 409 "src/lexer-keywords.txt" + {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, +#line 279 "src/lexer-keywords.txt" + {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, +#line 44 "src/lexer-keywords.txt" + {"assert_return", TokenType::AssertReturn}, + {""}, {""}, {""}, +#line 635 "src/lexer-keywords.txt" + {"sub", TokenType::Sub}, + {""}, {""}, {""}, {""}, +#line 620 "src/lexer-keywords.txt" + {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 140 "src/lexer-keywords.txt" + {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, +#line 603 "src/lexer-keywords.txt" + {"ref", TokenType::Ref}, +#line 75 "src/lexer-keywords.txt" + {"else", TokenType::Else, Opcode::Else}, +#line 640 "src/lexer-keywords.txt" + {"table.init", TokenType::TableInit, Opcode::TableInit}, +#line 642 "src/lexer-keywords.txt" + {"table.size", TokenType::TableSize, Opcode::TableSize}, {""}, {""}, {""}, {""}, -#line 574 "src/lexer-keywords.txt" - {"null", TokenType::Null}, - {""}, -#line 105 "src/lexer-keywords.txt" - {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, +#line 644 "src/lexer-keywords.txt" + {"then", TokenType::Then}, +#line 410 "src/lexer-keywords.txt" + {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, +#line 280 "src/lexer-keywords.txt" + {"i32.atomic.load", TokenType::AtomicLoad, Opcode::I32AtomicLoad}, +#line 186 "src/lexer-keywords.txt" + {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, +#line 139 "src/lexer-keywords.txt" + {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, {""}, -#line 339 "src/lexer-keywords.txt" - {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 439 "src/lexer-keywords.txt" - {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, -#line 298 "src/lexer-keywords.txt" - {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, -#line 435 "src/lexer-keywords.txt" - {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, -#line 294 "src/lexer-keywords.txt" - {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, -#line 448 "src/lexer-keywords.txt" - {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, -#line 305 "src/lexer-keywords.txt" - {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, -#line 437 "src/lexer-keywords.txt" - {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, -#line 296 "src/lexer-keywords.txt" - {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, +#line 567 "src/lexer-keywords.txt" + {"if", TokenType::If, Opcode::If}, {""}, {""}, -#line 335 "src/lexer-keywords.txt" - {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, +#line 609 "src/lexer-keywords.txt" + {"ref.extern", TokenType::RefExtern}, {""}, {""}, {""}, {""}, {""}, -#line 43 "src/lexer-keywords.txt" - {"call", TokenType::Call, Opcode::Call}, - {""}, {""}, -#line 345 "src/lexer-keywords.txt" - {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, +#line 185 "src/lexer-keywords.txt" + {"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge}, {""}, -#line 341 "src/lexer-keywords.txt" - {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, +#line 483 "src/lexer-keywords.txt" + {"i64.store32", TokenType::Store, Opcode::I64Store32}, {""}, -#line 353 "src/lexer-keywords.txt" - {"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU}, -#line 555 "src/lexer-keywords.txt" - {"local", TokenType::Local}, -#line 343 "src/lexer-keywords.txt" - {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, +#line 188 "src/lexer-keywords.txt" + {"f64x2.lt", TokenType::Compare, Opcode::F64X2Lt}, + {""}, +#line 422 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, +#line 56 "src/lexer-keywords.txt" + {"br_table", TokenType::BrTable, Opcode::BrTable}, +#line 193 "src/lexer-keywords.txt" + {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, +#line 194 "src/lexer-keywords.txt" + {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, + {""}, +#line 504 "src/lexer-keywords.txt" + {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, {""}, {""}, -#line 99 "src/lexer-keywords.txt" - {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, +#line 141 "src/lexer-keywords.txt" + {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, {""}, -#line 334 "src/lexer-keywords.txt" - {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, -#line 386 "src/lexer-keywords.txt" - {"i64.and", TokenType::Binary, Opcode::I64And}, -#line 257 "src/lexer-keywords.txt" - {"i32.and", TokenType::Binary, Opcode::I32And}, -#line 149 "src/lexer-keywords.txt" - {"f64.mul", TokenType::Binary, Opcode::F64Mul}, -#line 88 "src/lexer-keywords.txt" - {"f32.mul", TokenType::Binary, Opcode::F32Mul}, -#line 450 "src/lexer-keywords.txt" - {"i64.mul", TokenType::Binary, Opcode::I64Mul}, -#line 307 "src/lexer-keywords.txt" - {"i32.mul", TokenType::Binary, Opcode::I32Mul}, +#line 187 "src/lexer-keywords.txt" + {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, +#line 506 "src/lexer-keywords.txt" + {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, {""}, -#line 121 "src/lexer-keywords.txt" - {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, +#line 76 "src/lexer-keywords.txt" + {"end", TokenType::End, Opcode::End}, +#line 419 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU}, + {""}, +#line 382 "src/lexer-keywords.txt" + {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, {""}, {""}, -#line 111 "src/lexer-keywords.txt" - {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, - {""}, {""}, {""}, {""}, -#line 113 "src/lexer-keywords.txt" - {"f32x4.mul", TokenType::Binary, Opcode::F32X4Mul}, +#line 508 "src/lexer-keywords.txt" + {"i64x2.neg", TokenType::Unary, Opcode::I64X2Neg}, +#line 502 "src/lexer-keywords.txt" + {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, +#line 503 "src/lexer-keywords.txt" + {"i64x2.lt_s", TokenType::Binary, Opcode::I64X2LtS}, {""}, -#line 359 "src/lexer-keywords.txt" - {"i32x4.mul", TokenType::Binary, Opcode::I32X4Mul}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 554 "src/lexer-keywords.txt" - {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, +#line 80 "src/lexer-keywords.txt" + {"extern", Type::ExternRef, TokenType::Extern}, +#line 20 "src/lexer-keywords.txt" + {"any", Type::AnyRef, TokenType::Any}, +#line 383 "src/lexer-keywords.txt" + {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, {""}, -#line 552 "src/lexer-keywords.txt" - {"local.get", TokenType::LocalGet, Opcode::LocalGet}, - {""}, {""}, {""}, {""}, {""}, -#line 553 "src/lexer-keywords.txt" - {"local.set", TokenType::LocalSet, Opcode::LocalSet}, - {""}, {""}, {""}, {""}, -#line 585 "src/lexer-keywords.txt" - {"ref.as_non_null", TokenType::RefAsNonNull, Opcode::RefAsNonNull}, +#line 505 "src/lexer-keywords.txt" + {"i64x2.le_s", TokenType::Binary, Opcode::I64X2LeS}, {""}, -#line 422 "src/lexer-keywords.txt" - {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, -#line 284 "src/lexer-keywords.txt" - {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, - {""}, {""}, {""}, -#line 415 "src/lexer-keywords.txt" +#line 83 "src/lexer-keywords.txt" + {"exn", Type::ExnRef, TokenType::Exn}, +#line 464 "src/lexer-keywords.txt" + {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, + {""}, +#line 72 "src/lexer-keywords.txt" + {"either", TokenType::Either}, +#line 192 "src/lexer-keywords.txt" + {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, +#line 463 "src/lexer-keywords.txt" + {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, +#line 452 "src/lexer-keywords.txt" + {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, +#line 313 "src/lexer-keywords.txt" + {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 418 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AddU}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 435 "src/lexer-keywords.txt" {"i64.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I64AtomicRmwOr}, -#line 278 "src/lexer-keywords.txt" +#line 298 "src/lexer-keywords.txt" {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, + {""}, {""}, {""}, +#line 210 "src/lexer-keywords.txt" + {"field", TokenType::Field}, {""}, -#line 145 "src/lexer-keywords.txt" - {"f64.load", TokenType::Load, Opcode::F64Load}, -#line 84 "src/lexer-keywords.txt" - {"f32.load", TokenType::Load, Opcode::F32Load}, -#line 447 "src/lexer-keywords.txt" - {"i64.load", TokenType::Load, Opcode::I64Load}, -#line 304 "src/lexer-keywords.txt" - {"i32.load", TokenType::Load, Opcode::I32Load}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 595 "src/lexer-keywords.txt" - {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, - {""}, {""}, {""}, {""}, {""}, -#line 147 "src/lexer-keywords.txt" - {"f64.max", TokenType::Binary, Opcode::F64Max}, -#line 86 "src/lexer-keywords.txt" - {"f32.max", TokenType::Binary, Opcode::F32Max}, -#line 131 "src/lexer-keywords.txt" - {"f64.add", TokenType::Binary, Opcode::F64Add}, -#line 69 "src/lexer-keywords.txt" - {"f32.add", TokenType::Binary, Opcode::F32Add}, -#line 385 "src/lexer-keywords.txt" - {"i64.add", TokenType::Binary, Opcode::I64Add}, -#line 256 "src/lexer-keywords.txt" - {"i32.add", TokenType::Binary, Opcode::I32Add}, +#line 49 "src/lexer-keywords.txt" + {"binary", TokenType::Bin}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 589 "src/lexer-keywords.txt" + {"nan:canonical", TokenType::NanCanonical}, {""}, -#line 348 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, +#line 179 "src/lexer-keywords.txt" + {"f64x2.add", TokenType::Binary, Opcode::F64X2Add}, + {""}, {""}, {""}, +#line 509 "src/lexer-keywords.txt" + {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, +#line 527 "src/lexer-keywords.txt" + {"i64.xor", TokenType::Binary, Opcode::I64Xor}, +#line 404 "src/lexer-keywords.txt" + {"i32.xor", TokenType::Binary, Opcode::I32Xor}, + {""}, {""}, {""}, +#line 144 "src/lexer-keywords.txt" + {"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub}, +#line 421 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, {""}, -#line 455 "src/lexer-keywords.txt" - {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, -#line 312 "src/lexer-keywords.txt" - {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, +#line 116 "src/lexer-keywords.txt" + {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, + {""}, {""}, +#line 590 "src/lexer-keywords.txt" + {"noextern", Type::NullExternRef, TokenType::NoExtern}, +#line 496 "src/lexer-keywords.txt" + {"i64x2.add", TokenType::Binary, Opcode::I64X2Add}, +#line 137 "src/lexer-keywords.txt" + {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, + {""}, {""}, {""}, {""}, {""}, +#line 433 "src/lexer-keywords.txt" + {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, +#line 296 "src/lexer-keywords.txt" + {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, #line 38 "src/lexer-keywords.txt" - {"br_on_null", TokenType::BrOnNull, Opcode::BrOnNull}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {"array.set", TokenType::ArraySet, Opcode::ArraySet}, +#line 388 "src/lexer-keywords.txt" + {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, +#line 27 "src/lexer-keywords.txt" + {"array.get", TokenType::ArrayGet, Opcode::ArrayGet}, {""}, -#line 354 "src/lexer-keywords.txt" - {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, - {""}, {""}, {""}, -#line 467 "src/lexer-keywords.txt" - {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, -#line 323 "src/lexer-keywords.txt" - {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 440 "src/lexer-keywords.txt" - {"i64.le_u", TokenType::Compare, Opcode::I64LeU}, -#line 299 "src/lexer-keywords.txt" - {"i32.le_u", TokenType::Compare, Opcode::I32LeU}, -#line 436 "src/lexer-keywords.txt" - {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, -#line 295 "src/lexer-keywords.txt" - {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, -#line 449 "src/lexer-keywords.txt" - {"i64.lt_u", TokenType::Compare, Opcode::I64LtU}, -#line 306 "src/lexer-keywords.txt" - {"i32.lt_u", TokenType::Compare, Opcode::I32LtU}, +#line 353 "src/lexer-keywords.txt" + {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, + {""}, {""}, {""}, {""}, {""}, #line 438 "src/lexer-keywords.txt" - {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, -#line 297 "src/lexer-keywords.txt" - {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, -#line 418 "src/lexer-keywords.txt" {"i64.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I64AtomicRmwXor}, -#line 281 "src/lexer-keywords.txt" +#line 301 "src/lexer-keywords.txt" {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, -#line 445 "src/lexer-keywords.txt" - {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, -#line 302 "src/lexer-keywords.txt" - {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, - {""}, {""}, -#line 120 "src/lexer-keywords.txt" - {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, - {""}, {""}, -#line 547 "src/lexer-keywords.txt" - {"if", TokenType::If, Opcode::If}, - {""}, -#line 97 "src/lexer-keywords.txt" - {"f32", Type::F32}, - {""}, -#line 331 "src/lexer-keywords.txt" - {"i32", Type::I32}, - {""}, {""}, {""}, {""}, -#line 58 "src/lexer-keywords.txt" - {"else", TokenType::Else, Opcode::Else}, - {""}, -#line 459 "src/lexer-keywords.txt" - {"i64.shl", TokenType::Binary, Opcode::I64Shl}, -#line 316 "src/lexer-keywords.txt" - {"i32.shl", TokenType::Binary, Opcode::I32Shl}, + {""}, {""}, {""}, +#line 29 "src/lexer-keywords.txt" + {"array.get_u", TokenType::ArrayGetU, Opcode::ArrayGetU}, {""}, -#line 583 "src/lexer-keywords.txt" - {"ref", TokenType::Ref}, - {""}, {""}, +#line 28 "src/lexer-keywords.txt" + {"array.get_s", TokenType::ArrayGetS, Opcode::ArrayGetS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 571 "src/lexer-keywords.txt" + {"item", TokenType::Item}, #line 432 "src/lexer-keywords.txt" - {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, -#line 293 "src/lexer-keywords.txt" - {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, - {""}, -#line 349 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, + {"i64.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I64AtomicRmwAdd}, +#line 295 "src/lexer-keywords.txt" + {"i32.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I32AtomicRmwAdd}, {""}, -#line 456 "src/lexer-keywords.txt" - {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, -#line 313 "src/lexer-keywords.txt" - {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, -#line 364 "src/lexer-keywords.txt" - {"i32x4.shl", TokenType::Binary, Opcode::I32X4Shl}, - {""}, {""}, {""}, {""}, -#line 590 "src/lexer-keywords.txt" - {"register", TokenType::Register}, -#line 122 "src/lexer-keywords.txt" - {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, - {""}, {""}, {""}, -#line 399 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU}, -#line 355 "src/lexer-keywords.txt" - {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, +#line 130 "src/lexer-keywords.txt" + {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, +#line 32 "src/lexer-keywords.txt" + {"array.len", TokenType::GCUnary, Opcode::ArrayLen}, {""}, -#line 169 "src/lexer-keywords.txt" - {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, +#line 34 "src/lexer-keywords.txt" + {"array.new_data", TokenType::ArrayNewData, Opcode::ArrayNewData}, +#line 159 "src/lexer-keywords.txt" + {"f64.floor", TokenType::Unary, Opcode::F64Floor}, +#line 98 "src/lexer-keywords.txt" + {"f32.floor", TokenType::Unary, Opcode::F32Floor}, +#line 35 "src/lexer-keywords.txt" + {"array.new_default", TokenType::ArrayNewDefault, Opcode::ArrayNewDefault}, {""}, -#line 167 "src/lexer-keywords.txt" - {"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge}, - {""}, {""}, {""}, {""}, {""}, -#line 170 "src/lexer-keywords.txt" - {"f64x2.lt", TokenType::Compare, Opcode::F64X2Lt}, +#line 191 "src/lexer-keywords.txt" + {"f64x2.mul", TokenType::Binary, Opcode::F64X2Mul}, +#line 215 "src/lexer-keywords.txt" + {"get", TokenType::Get}, {""}, -#line 168 "src/lexer-keywords.txt" - {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, +#line 628 "src/lexer-keywords.txt" + {"structref", Type::StructRef}, {""}, -#line 162 "src/lexer-keywords.txt" - {"f64x2.ceil", TokenType::Unary, Opcode::F64X2Ceil}, -#line 60 "src/lexer-keywords.txt" +#line 77 "src/lexer-keywords.txt" {"tag", TokenType::Tag}, -#line 176 "src/lexer-keywords.txt" - {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, -#line 197 "src/lexer-keywords.txt" - {"get", TokenType::Get}, -#line 482 "src/lexer-keywords.txt" - {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, -#line 175 "src/lexer-keywords.txt" - {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, +#line 43 "src/lexer-keywords.txt" + {"assert_malformed", TokenType::AssertMalformed}, {""}, -#line 488 "src/lexer-keywords.txt" - {"i64x2.neg", TokenType::Unary, Opcode::I64X2Neg}, +#line 588 "src/lexer-keywords.txt" + {"nan:arithmetic", TokenType::NanArithmetic}, +#line 377 "src/lexer-keywords.txt" + {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, +#line 58 "src/lexer-keywords.txt" + {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, +#line 376 "src/lexer-keywords.txt" + {"i32x4.min_s", TokenType::Binary, Opcode::I32X4MinS}, {""}, -#line 601 "src/lexer-keywords.txt" - {"structref", Type::StructRef}, -#line 446 "src/lexer-keywords.txt" - {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, -#line 303 "src/lexer-keywords.txt" - {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, - {""}, {""}, {""}, -#line 485 "src/lexer-keywords.txt" - {"i64x2.le_s", TokenType::Binary, Opcode::I64X2LeS}, +#line 175 "src/lexer-keywords.txt" + {"f64.sub", TokenType::Binary, Opcode::F64Sub}, +#line 113 "src/lexer-keywords.txt" + {"f32.sub", TokenType::Binary, Opcode::F32Sub}, + {""}, {""}, +#line 500 "src/lexer-keywords.txt" + {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, +#line 205 "src/lexer-keywords.txt" + {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, + {""}, {""}, +#line 180 "src/lexer-keywords.txt" + {"f64x2.ceil", TokenType::Unary, Opcode::F64X2Ceil}, {""}, +#line 23 "src/lexer-keywords.txt" + {"array", Type::ArrayRef, TokenType::Array}, + {""}, {""}, {""}, {""}, {""}, {""}, #line 486 "src/lexer-keywords.txt" - {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, - {""}, -#line 483 "src/lexer-keywords.txt" - {"i64x2.lt_s", TokenType::Binary, Opcode::I64X2LtS}, -#line 187 "src/lexer-keywords.txt" - {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, -#line 484 "src/lexer-keywords.txt" - {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, - {""}, {""}, {""}, -#line 65 "src/lexer-keywords.txt" - {"exn", Type::ExnRef, TokenType::Exn}, -#line 401 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, + {"i64.sub", TokenType::Binary, Opcode::I64Sub}, +#line 342 "src/lexer-keywords.txt" + {"i32.sub", TokenType::Binary, Opcode::I32Sub}, {""}, {""}, -#line 390 "src/lexer-keywords.txt" - {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, -#line 260 "src/lexer-keywords.txt" - {"i32.atomic.load", TokenType::AtomicLoad, Opcode::I32AtomicLoad}, +#line 490 "src/lexer-keywords.txt" + {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, +#line 346 "src/lexer-keywords.txt" + {"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U}, + {""}, {""}, +#line 489 "src/lexer-keywords.txt" + {"i64.trunc_f64_s", TokenType::Convert, Opcode::I64TruncF64S}, +#line 345 "src/lexer-keywords.txt" + {"i32.trunc_f64_s", TokenType::Convert, Opcode::I32TruncF64S}, + {""}, {""}, {""}, {""}, {""}, +#line 200 "src/lexer-keywords.txt" + {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 174 "src/lexer-keywords.txt" - {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, +#line 199 "src/lexer-keywords.txt" + {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, {""}, {""}, {""}, -#line 59 "src/lexer-keywords.txt" - {"end", TokenType::End, Opcode::End}, - {""}, {""}, {""}, {""}, {""}, +#line 369 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, + {""}, +#line 368 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, #line 611 "src/lexer-keywords.txt" - {"then", TokenType::Then}, - {""}, {""}, {""}, -#line 55 "src/lexer-keywords.txt" - {"either", TokenType::Either}, + {"ref.host", TokenType::RefHost}, {""}, {""}, -#line 183 "src/lexer-keywords.txt" +#line 479 "src/lexer-keywords.txt" + {"i64.shl", TokenType::Binary, Opcode::I64Shl}, +#line 336 "src/lexer-keywords.txt" + {"i32.shl", TokenType::Binary, Opcode::I32Shl}, +#line 481 "src/lexer-keywords.txt" + {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, +#line 338 "src/lexer-keywords.txt" + {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, +#line 480 "src/lexer-keywords.txt" + {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, +#line 337 "src/lexer-keywords.txt" + {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, +#line 617 "src/lexer-keywords.txt" + {"register", TokenType::Register}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 201 "src/lexer-keywords.txt" {"f64x2.replace_lane", TokenType::SimdLaneOp, Opcode::F64X2ReplaceLane}, -#line 402 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, -#line 496 "src/lexer-keywords.txt" - {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, -#line 398 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AddU}, - {""}, -#line 468 "src/lexer-keywords.txt" - {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, -#line 324 "src/lexer-keywords.txt" - {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, -#line 132 "src/lexer-keywords.txt" - {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, -#line 70 "src/lexer-keywords.txt" - {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, - {""}, -#line 106 "src/lexer-keywords.txt" - {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, +#line 494 "src/lexer-keywords.txt" + {"i64.trunc_sat_f64_u", TokenType::Convert, Opcode::I64TruncSatF64U}, +#line 350 "src/lexer-keywords.txt" + {"i32.trunc_sat_f64_u", TokenType::Convert, Opcode::I32TruncSatF64U}, {""}, {""}, -#line 413 "src/lexer-keywords.txt" - {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, -#line 276 "src/lexer-keywords.txt" - {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, - {""}, -#line 463 "src/lexer-keywords.txt" - {"i64.store32", TokenType::Store, Opcode::I64Store32}, - {""}, -#line 119 "src/lexer-keywords.txt" - {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, - {""}, -#line 551 "src/lexer-keywords.txt" - {"item", TokenType::Item}, -#line 464 "src/lexer-keywords.txt" - {"i64.store8", TokenType::Store, Opcode::I64Store8}, -#line 320 "src/lexer-keywords.txt" - {"i32.store8", TokenType::Store, Opcode::I32Store8}, - {""}, -#line 63 "src/lexer-keywords.txt" - {"extern", Type::ExternRef, TokenType::Extern}, +#line 493 "src/lexer-keywords.txt" + {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, +#line 349 "src/lexer-keywords.txt" + {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, {""}, -#line 570 "src/lexer-keywords.txt" - {"noextern", Type::NullExternRef, TokenType::NoExtern}, - {""}, {""}, -#line 232 "src/lexer-keywords.txt" - {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, +#line 515 "src/lexer-keywords.txt" + {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, {""}, {""}, -#line 230 "src/lexer-keywords.txt" - {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, +#line 462 "src/lexer-keywords.txt" + {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, +#line 321 "src/lexer-keywords.txt" + {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, {""}, {""}, -#line 495 "src/lexer-keywords.txt" - {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, - {""}, {""}, {""}, {""}, -#line 217 "src/lexer-keywords.txt" - {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, -#line 587 "src/lexer-keywords.txt" - {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, -#line 213 "src/lexer-keywords.txt" - {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, -#line 404 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XorU}, -#line 221 "src/lexer-keywords.txt" - {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, +#line 461 "src/lexer-keywords.txt" + {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, +#line 320 "src/lexer-keywords.txt" + {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, +#line 516 "src/lexer-keywords.txt" + {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, {""}, -#line 215 "src/lexer-keywords.txt" - {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, +#line 46 "src/lexer-keywords.txt" + {"assert_unlinkable", TokenType::AssertUnlinkable}, +#line 62 "src/lexer-keywords.txt" + {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, + {""}, {""}, {""}, {""}, {""}, +#line 610 "src/lexer-keywords.txt" + {"ref.func", TokenType::RefFunc, Opcode::RefFunc}, +#line 454 "src/lexer-keywords.txt" + {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, +#line 209 "src/lexer-keywords.txt" + {"f64x2", TokenType::F64X2}, +#line 453 "src/lexer-keywords.txt" + {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, {""}, {""}, {""}, {""}, -#line 37 "src/lexer-keywords.txt" - {"br_on_non_null", TokenType::BrOnNonNull, Opcode::BrOnNonNull}, +#line 583 "src/lexer-keywords.txt" + {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, +#line 636 "src/lexer-keywords.txt" + {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, +#line 649 "src/lexer-keywords.txt" + {"type", TokenType::Type}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 526 "src/lexer-keywords.txt" + {"i64x2", TokenType::I64X2}, + {""}, {""}, {""}, +#line 599 "src/lexer-keywords.txt" + {"output", TokenType::Output}, + {""}, {""}, +#line 569 "src/lexer-keywords.txt" + {"input", TokenType::Input}, + {""}, {""}, {""}, {""}, +#line 36 "src/lexer-keywords.txt" + {"array.new_elem", TokenType::ArrayNewElem, Opcode::ArrayNewElem}, {""}, -#line 141 "src/lexer-keywords.txt" - {"f64.floor", TokenType::Unary, Opcode::F64Floor}, -#line 80 "src/lexer-keywords.txt" - {"f32.floor", TokenType::Unary, Opcode::F32Floor}, -#line 460 "src/lexer-keywords.txt" - {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, -#line 317 "src/lexer-keywords.txt" - {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 441 "src/lexer-keywords.txt" - {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, -#line 300 "src/lexer-keywords.txt" - {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, +#line 598 "src/lexer-keywords.txt" + {"offset", TokenType::Offset}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 204 "src/lexer-keywords.txt" + {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, +#line 173 "src/lexer-keywords.txt" + {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, +#line 111 "src/lexer-keywords.txt" + {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, +#line 178 "src/lexer-keywords.txt" + {"f64x2.abs", TokenType::Unary, Opcode::F64X2Abs}, + {""}, {""}, +#line 484 "src/lexer-keywords.txt" + {"i64.store8", TokenType::Store, Opcode::I64Store8}, +#line 340 "src/lexer-keywords.txt" + {"i32.store8", TokenType::Store, Opcode::I32Store8}, +#line 197 "src/lexer-keywords.txt" + {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, {""}, -#line 365 "src/lexer-keywords.txt" - {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, -#line 165 "src/lexer-keywords.txt" - {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, +#line 426 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, +#line 289 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, + {""}, {""}, +#line 568 "src/lexer-keywords.txt" + {"import", TokenType::Import}, {""}, -#line 477 "src/lexer-keywords.txt" - {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, +#line 53 "src/lexer-keywords.txt" + {"br_on_cast_fail", TokenType::BrOnCast, Opcode::BrOnCastFail}, +#line 521 "src/lexer-keywords.txt" + {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, + {""}, {""}, +#line 507 "src/lexer-keywords.txt" + {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, +#line 604 "src/lexer-keywords.txt" + {"quote", TokenType::Quote}, {""}, -#line 403 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, -#line 430 "src/lexer-keywords.txt" - {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, -#line 292 "src/lexer-keywords.txt" - {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, +#line 408 "src/lexer-keywords.txt" + {"i64.atomic.load32_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad32U}, {""}, {""}, {""}, -#line 235 "src/lexer-keywords.txt" - {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, +#line 124 "src/lexer-keywords.txt" + {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, {""}, {""}, -#line 192 "src/lexer-keywords.txt" - {"field", TokenType::Field}, -#line 412 "src/lexer-keywords.txt" - {"i64.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I64AtomicRmwAdd}, -#line 275 "src/lexer-keywords.txt" - {"i32.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I32AtomicRmwAdd}, - {""}, {""}, {""}, -#line 489 "src/lexer-keywords.txt" - {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, - {""}, {""}, {""}, {""}, {""}, -#line 201 "src/lexer-keywords.txt" - {"i16", Type::I16}, - {""}, {""}, {""}, {""}, {""}, -#line 609 "src/lexer-keywords.txt" - {"table.size", TokenType::TableSize, Opcode::TableSize}, +#line 581 "src/lexer-keywords.txt" + {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, +#line 129 "src/lexer-keywords.txt" + {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 425 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, +#line 288 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, + {""}, +#line 428 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU}, +#line 291 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU}, {""}, {""}, -#line 593 "src/lexer-keywords.txt" - {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, +#line 190 "src/lexer-keywords.txt" + {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 161 "src/lexer-keywords.txt" - {"f64x2.add", TokenType::Binary, Opcode::F64X2Add}, +#line 449 "src/lexer-keywords.txt" + {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, +#line 311 "src/lexer-keywords.txt" + {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, {""}, -#line 476 "src/lexer-keywords.txt" - {"i64x2.add", TokenType::Binary, Opcode::I64X2Add}, - {""}, {""}, -#line 443 "src/lexer-keywords.txt" - {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, -#line 233 "src/lexer-keywords.txt" - {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, +#line 367 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, + {""}, {""}, {""}, +#line 366 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 542 "src/lexer-keywords.txt" + {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, {""}, -#line 607 "src/lexer-keywords.txt" - {"table.init", TokenType::TableInit, Opcode::TableInit}, +#line 30 "src/lexer-keywords.txt" + {"array.init_data", TokenType::ArrayInitData, Opcode::ArrayInitData}, {""}, -#line 181 "src/lexer-keywords.txt" - {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, -#line 565 "src/lexer-keywords.txt" - {"memory", TokenType::Memory}, +#line 541 "src/lexer-keywords.txt" + {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, {""}, -#line 171 "src/lexer-keywords.txt" - {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, -#line 431 "src/lexer-keywords.txt" +#line 540 "src/lexer-keywords.txt" + {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, + {""}, {""}, +#line 95 "src/lexer-keywords.txt" + {"f32.demote_f64", TokenType::Convert, Opcode::F32DemoteF64}, +#line 539 "src/lexer-keywords.txt" + {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, + {""}, {""}, {""}, {""}, {""}, +#line 546 "src/lexer-keywords.txt" + {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, +#line 564 "src/lexer-keywords.txt" + {"i8x16.sub_sat_u", TokenType::Binary, Opcode::I8X16SubSatU}, +#line 553 "src/lexer-keywords.txt" + {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, +#line 555 "src/lexer-keywords.txt" + {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, +#line 545 "src/lexer-keywords.txt" + {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, +#line 563 "src/lexer-keywords.txt" + {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, +#line 544 "src/lexer-keywords.txt" + {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, +#line 451 "src/lexer-keywords.txt" {"i64.extend32_s", TokenType::Unary, Opcode::I64Extend32S}, + {""}, {""}, +#line 543 "src/lexer-keywords.txt" + {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 461 "src/lexer-keywords.txt" - {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, -#line 318 "src/lexer-keywords.txt" - {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, -#line 173 "src/lexer-keywords.txt" - {"f64x2.mul", TokenType::Binary, Opcode::F64X2Mul}, +#line 50 "src/lexer-keywords.txt" + {"block", TokenType::Block, Opcode::Block}, {""}, -#line 480 "src/lexer-keywords.txt" - {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, +#line 123 "src/lexer-keywords.txt" + {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, {""}, {""}, -#line 346 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, - {""}, {""}, {""}, {""}, -#line 366 "src/lexer-keywords.txt" +#line 272 "src/lexer-keywords.txt" + {"i31", Type::I31Ref, TokenType::I31}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 386 "src/lexer-keywords.txt" {"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU}, -#line 112 "src/lexer-keywords.txt" - {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, -#line 148 "src/lexer-keywords.txt" - {"f64.min", TokenType::Binary, Opcode::F64Min}, -#line 87 "src/lexer-keywords.txt" - {"f32.min", TokenType::Binary, Opcode::F32Min}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 34 "src/lexer-keywords.txt" - {"binary", TokenType::Bin}, -#line 196 "src/lexer-keywords.txt" - {"function", TokenType::Function}, +#line 385 "src/lexer-keywords.txt" + {"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS}, {""}, -#line 417 "src/lexer-keywords.txt" - {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, -#line 280 "src/lexer-keywords.txt" - {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, +#line 37 "src/lexer-keywords.txt" + {"array.new_fixed", TokenType::ArrayNewFixed, Opcode::ArrayNewFixed}, +#line 359 "src/lexer-keywords.txt" + {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, {""}, -#line 469 "src/lexer-keywords.txt" - {"i64.trunc_f64_s", TokenType::Convert, Opcode::I64TruncF64S}, -#line 325 "src/lexer-keywords.txt" - {"i32.trunc_f64_s", TokenType::Convert, Opcode::I32TruncF64S}, -#line 249 "src/lexer-keywords.txt" - {"i16x8", TokenType::I16X8}, -#line 535 "src/lexer-keywords.txt" - {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, +#line 384 "src/lexer-keywords.txt" + {"i32x4.shl", TokenType::Binary, Opcode::I32X4Shl}, + {""}, +#line 531 "src/lexer-keywords.txt" + {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, + {""}, {""}, {""}, +#line 530 "src/lexer-keywords.txt" + {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, {""}, {""}, +#line 492 "src/lexer-keywords.txt" + {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, +#line 348 "src/lexer-keywords.txt" + {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, #line 533 "src/lexer-keywords.txt" - {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, - {""}, {""}, {""}, -#line 206 "src/lexer-keywords.txt" - {"i16x8.all_true", TokenType::Unary, Opcode::I16X8AllTrue}, -#line 421 "src/lexer-keywords.txt" - {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, -#line 283 "src/lexer-keywords.txt" - {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, + {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, {""}, -#line 523 "src/lexer-keywords.txt" - {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, +#line 491 "src/lexer-keywords.txt" + {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, +#line 347 "src/lexer-keywords.txt" + {"i32.trunc_sat_f32_s", TokenType::Convert, Opcode::I32TruncSatF32S}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 637 "src/lexer-keywords.txt" + {"table.fill", TokenType::TableFill, Opcode::TableFill}, {""}, -#line 519 "src/lexer-keywords.txt" - {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, -#line 588 "src/lexer-keywords.txt" - {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, -#line 525 "src/lexer-keywords.txt" - {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, -#line 218 "src/lexer-keywords.txt" - {"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU}, -#line 521 "src/lexer-keywords.txt" - {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, -#line 214 "src/lexer-keywords.txt" +#line 356 "src/lexer-keywords.txt" + {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, +#line 532 "src/lexer-keywords.txt" + {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, + {""}, {""}, {""}, {""}, {""}, +#line 234 "src/lexer-keywords.txt" + {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, + {""}, {""}, {""}, +#line 233 "src/lexer-keywords.txt" + {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, + {""}, +#line 232 "src/lexer-keywords.txt" {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, + {""}, {""}, {""}, +#line 231 "src/lexer-keywords.txt" + {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, {""}, -#line 222 "src/lexer-keywords.txt" +#line 424 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XorU}, + {""}, {""}, {""}, +#line 240 "src/lexer-keywords.txt" {"i16x8.lt_u", TokenType::Compare, Opcode::I16X8LtU}, - {""}, -#line 216 "src/lexer-keywords.txt" - {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, -#line 406 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, -#line 269 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, - {""}, {""}, -#line 205 "src/lexer-keywords.txt" - {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, - {""}, {""}, -#line 389 "src/lexer-keywords.txt" - {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, #line 259 "src/lexer-keywords.txt" - {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, - {""}, {""}, {""}, {""}, -#line 45 "src/lexer-keywords.txt" - {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, - {""}, {""}, {""}, -#line 442 "src/lexer-keywords.txt" - {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, -#line 301 "src/lexer-keywords.txt" - {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, + {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, +#line 248 "src/lexer-keywords.txt" + {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, +#line 250 "src/lexer-keywords.txt" + {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, +#line 239 "src/lexer-keywords.txt" + {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, +#line 258 "src/lexer-keywords.txt" + {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, +#line 236 "src/lexer-keywords.txt" + {"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU}, {""}, {""}, {""}, -#line 227 "src/lexer-keywords.txt" - {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, - {""}, -#line 614 "src/lexer-keywords.txt" - {"try", TokenType::Try, Opcode::Try}, - {""}, -#line 538 "src/lexer-keywords.txt" - {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, -#line 411 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, -#line 274 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XorU}, -#line 569 "src/lexer-keywords.txt" - {"nan:canonical", TokenType::NanCanonical}, -#line 576 "src/lexer-keywords.txt" - {"nullexternref", Type::NullExternRef}, -#line 77 "src/lexer-keywords.txt" - {"f32.demote_f64", TokenType::Convert, Opcode::F32DemoteF64}, +#line 235 "src/lexer-keywords.txt" + {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 564 "src/lexer-keywords.txt" - {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 423 "src/lexer-keywords.txt" - {"i64.clz", TokenType::Unary, Opcode::I64Clz}, -#line 285 "src/lexer-keywords.txt" - {"i32.clz", TokenType::Unary, Opcode::I32Clz}, +#line 66 "src/lexer-keywords.txt" + {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, {""}, -#line 180 "src/lexer-keywords.txt" - {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, -#line 425 "src/lexer-keywords.txt" - {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, -#line 287 "src/lexer-keywords.txt" - {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, +#line 81 "src/lexer-keywords.txt" + {"externref", Type::ExternRef}, {""}, {""}, -#line 561 "src/lexer-keywords.txt" - {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, -#line 584 "src/lexer-keywords.txt" - {"quote", TokenType::Quote}, - {""}, {""}, {""}, -#line 35 "src/lexer-keywords.txt" - {"block", TokenType::Block, Opcode::Block}, - {""}, {""}, {""}, -#line 191 "src/lexer-keywords.txt" - {"f64x2", TokenType::F64X2}, -#line 537 "src/lexer-keywords.txt" - {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, -#line 506 "src/lexer-keywords.txt" - {"i64x2", TokenType::I64X2}, +#line 165 "src/lexer-keywords.txt" + {"f64.max", TokenType::Binary, Opcode::F64Max}, +#line 104 "src/lexer-keywords.txt" + {"f32.max", TokenType::Binary, Opcode::F32Max}, + {""}, +#line 143 "src/lexer-keywords.txt" + {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, {""}, {""}, -#line 444 "src/lexer-keywords.txt" - {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, +#line 415 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, +#line 285 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, +#line 213 "src/lexer-keywords.txt" + {"funcref", Type::FuncRef}, {""}, {""}, {""}, -#line 578 "src/lexer-keywords.txt" - {"offset", TokenType::Offset}, - {""}, -#line 405 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, -#line 268 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, -#line 497 "src/lexer-keywords.txt" - {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, -#line 603 "src/lexer-keywords.txt" - {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, - {""}, {""}, {""}, {""}, -#line 182 "src/lexer-keywords.txt" - {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, - {""}, -#line 568 "src/lexer-keywords.txt" - {"nan:arithmetic", TokenType::NanArithmetic}, +#line 548 "src/lexer-keywords.txt" + {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, {""}, -#line 347 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, -#line 36 "src/lexer-keywords.txt" - {"br_if", TokenType::BrIf, Opcode::BrIf}, +#line 547 "src/lexer-keywords.txt" + {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, +#line 407 "src/lexer-keywords.txt" + {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, +#line 278 "src/lexer-keywords.txt" + {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, {""}, -#line 408 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU}, -#line 271 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU}, -#line 356 "src/lexer-keywords.txt" - {"i32x4.min_s", TokenType::Binary, Opcode::I32X4MinS}, - {""}, {""}, -#line 240 "src/lexer-keywords.txt" - {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, +#line 222 "src/lexer-keywords.txt" + {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, {""}, -#line 203 "src/lexer-keywords.txt" +#line 412 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, +#line 282 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, +#line 221 "src/lexer-keywords.txt" {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, -#line 223 "src/lexer-keywords.txt" - {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 550 "src/lexer-keywords.txt" - {"invoke", TokenType::Invoke}, - {""}, {""}, -#line 124 "src/lexer-keywords.txt" - {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, {""}, -#line 367 "src/lexer-keywords.txt" - {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, +#line 142 "src/lexer-keywords.txt" + {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, +#line 601 "src/lexer-keywords.txt" + {"param", TokenType::Param}, {""}, -#line 470 "src/lexer-keywords.txt" - {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, -#line 326 "src/lexer-keywords.txt" - {"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U}, +#line 224 "src/lexer-keywords.txt" + {"i16x8.all_true", TokenType::Unary, Opcode::I16X8AllTrue}, {""}, {""}, -#line 211 "src/lexer-keywords.txt" - {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, -#line 513 "src/lexer-keywords.txt" - {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, +#line 184 "src/lexer-keywords.txt" + {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, {""}, {""}, {""}, -#line 136 "src/lexer-keywords.txt" - {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, +#line 189 "src/lexer-keywords.txt" + {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, + {""}, {""}, {""}, {""}, {""}, +#line 223 "src/lexer-keywords.txt" + {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, +#line 387 "src/lexer-keywords.txt" + {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, + {""}, {""}, +#line 51 "src/lexer-keywords.txt" + {"br_if", TokenType::BrIf, Opcode::BrIf}, +#line 423 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, #line 74 "src/lexer-keywords.txt" - {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, - {""}, {""}, {""}, -#line 524 "src/lexer-keywords.txt" - {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, - {""}, -#line 520 "src/lexer-keywords.txt" - {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, - {""}, -#line 526 "src/lexer-keywords.txt" - {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, + {"elem", TokenType::Elem}, + {""}, {""}, +#line 411 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, +#line 281 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, {""}, -#line 522 "src/lexer-keywords.txt" - {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, - {""}, {""}, {""}, {""}, -#line 512 "src/lexer-keywords.txt" - {"i8x16.add", TokenType::Binary, Opcode::I8X16Add}, +#line 429 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, +#line 292 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8SubU}, + {""}, {""}, +#line 570 "src/lexer-keywords.txt" + {"invoke", TokenType::Invoke}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 195 "src/lexer-keywords.txt" - {"funcref", Type::FuncRef}, - {""}, {""}, {""}, -#line 433 "src/lexer-keywords.txt" - {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, -#line 602 "src/lexer-keywords.txt" - {"sub", TokenType::Sub}, -#line 236 "src/lexer-keywords.txt" - {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, {""}, {""}, {""}, {""}, -#line 357 "src/lexer-keywords.txt" - {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, +#line 441 "src/lexer-keywords.txt" + {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, +#line 303 "src/lexer-keywords.txt" + {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, {""}, {""}, {""}, {""}, -#line 166 "src/lexer-keywords.txt" - {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, -#line 224 "src/lexer-keywords.txt" - {"i16x8.max_u", TokenType::Binary, Opcode::I16X8MaxU}, +#line 447 "src/lexer-keywords.txt" + {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, +#line 309 "src/lexer-keywords.txt" + {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, +#line 446 "src/lexer-keywords.txt" + {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, +#line 308 "src/lexer-keywords.txt" + {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, + {""}, {""}, {""}, +#line 414 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, +#line 284 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, +#line 219 "src/lexer-keywords.txt" + {"i16", Type::I16}, {""}, -#line 599 "src/lexer-keywords.txt" - {"start", TokenType::Start}, - {""}, {""}, -#line 44 "src/lexer-keywords.txt" - {"catch", TokenType::Catch, Opcode::Catch}, -#line 624 "src/lexer-keywords.txt" - {"v128.or", TokenType::Binary, Opcode::V128Or}, -#line 179 "src/lexer-keywords.txt" - {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, +#line 450 "src/lexer-keywords.txt" + {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, +#line 312 "src/lexer-keywords.txt" + {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, {""}, -#line 400 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, +#line 557 "src/lexer-keywords.txt" + {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, {""}, -#line 57 "src/lexer-keywords.txt" - {"elem", TokenType::Elem}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 212 "src/lexer-keywords.txt" - {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, -#line 473 "src/lexer-keywords.txt" - {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, -#line 329 "src/lexer-keywords.txt" - {"i32.trunc_sat_f64_s", TokenType::Convert, Opcode::I32TruncSatF64S}, - {""}, {""}, -#line 64 "src/lexer-keywords.txt" - {"externref", Type::ExternRef}, +#line 31 "src/lexer-keywords.txt" + {"array.init_elem", TokenType::ArrayInitElem, Opcode::ArrayInitElem}, {""}, -#line 130 "src/lexer-keywords.txt" - {"f64.abs", TokenType::Unary, Opcode::F64Abs}, -#line 68 "src/lexer-keywords.txt" - {"f32.abs", TokenType::Unary, Opcode::F32Abs}, -#line 617 "src/lexer-keywords.txt" - {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, +#line 25 "src/lexer-keywords.txt" + {"array.copy", TokenType::ArrayCopy, Opcode::ArrayCopy}, + {""}, {""}, {""}, {""}, +#line 558 "src/lexer-keywords.txt" + {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, +#line 242 "src/lexer-keywords.txt" + {"i16x8.max_u", TokenType::Binary, Opcode::I16X8MaxU}, + {""}, +#line 241 "src/lexer-keywords.txt" + {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, + {""}, +#line 245 "src/lexer-keywords.txt" + {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, + {""}, {""}, {""}, +#line 82 "src/lexer-keywords.txt" + {"extern.convert_any", TokenType::GCUnary, Opcode::ExternConvertAny}, +#line 596 "src/lexer-keywords.txt" + {"nullexternref", Type::NullExternRef}, +#line 436 "src/lexer-keywords.txt" + {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, +#line 299 "src/lexer-keywords.txt" + {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, {""}, {""}, -#line 98 "src/lexer-keywords.txt" - {"f32x4.abs", TokenType::Unary, Opcode::F32X4Abs}, -#line 39 "src/lexer-keywords.txt" - {"br_table", TokenType::BrTable, Opcode::BrTable}, -#line 333 "src/lexer-keywords.txt" - {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, -#line 628 "src/lexer-keywords.txt" - {"v128.store", TokenType::Store, Opcode::V128Store}, -#line 623 "src/lexer-keywords.txt" - {"v128.not", TokenType::Unary, Opcode::V128Not}, +#line 183 "src/lexer-keywords.txt" + {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 621 "src/lexer-keywords.txt" - {"v128.const", TokenType::Const, Opcode::V128Const}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 434 "src/lexer-keywords.txt" - {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, - {""}, -#line 579 "src/lexer-keywords.txt" - {"output", TokenType::Output}, -#line 498 "src/lexer-keywords.txt" +#line 519 "src/lexer-keywords.txt" + {"i64x2.shr_u", TokenType::Binary, Opcode::I64X2ShrU}, +#line 45 "src/lexer-keywords.txt" + {"assert_trap", TokenType::AssertTrap}, +#line 518 "src/lexer-keywords.txt" {"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS}, {""}, -#line 543 "src/lexer-keywords.txt" - {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, -#line 546 "src/lexer-keywords.txt" - {"i8x16", TokenType::I8X16}, -#line 510 "src/lexer-keywords.txt" - {"i8x16.add_sat_s", TokenType::Binary, Opcode::I8X16AddSatS}, -#line 527 "src/lexer-keywords.txt" - {"i8x16.max_s", TokenType::Binary, Opcode::I8X16MaxS}, -#line 642 "src/lexer-keywords.txt" - {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, -#line 241 "src/lexer-keywords.txt" - {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, +#line 440 "src/lexer-keywords.txt" + {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, +#line 497 "src/lexer-keywords.txt" + {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, {""}, -#line 204 "src/lexer-keywords.txt" - {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, -#line 24 "src/lexer-keywords.txt" - {"after", TokenType::After}, - {""}, {""}, -#line 118 "src/lexer-keywords.txt" - {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 517 "src/lexer-keywords.txt" - {"i8x16.extract_lane_s", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneS}, + {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, + {""}, +#line 597 "src/lexer-keywords.txt" + {"nullref", Type::NullRef}, + {""}, +#line 621 "src/lexer-keywords.txt" + {"return_call_ref", TokenType::ReturnCallRef, Opcode::ReturnCallRef}, +#line 59 "src/lexer-keywords.txt" + {"call_ref", TokenType::CallRef, Opcode::CallRef}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 510 "src/lexer-keywords.txt" + {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, {""}, {""}, -#line 630 "src/lexer-keywords.txt" - {"v128.xor", TokenType::Binary, Opcode::V128Xor}, +#line 397 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U}, {""}, {""}, {""}, -#line 604 "src/lexer-keywords.txt" - {"table.fill", TokenType::TableFill, Opcode::TableFill}, +#line 396 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f32x4_s", TokenType::Unary, Opcode::I32X4TruncSatF32X4S}, + {""}, {""}, {""}, +#line 565 "src/lexer-keywords.txt" + {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, + {""}, {""}, +#line 529 "src/lexer-keywords.txt" + {"i8x16.abs", TokenType::Unary, Opcode::I8X16Abs}, + {""}, {""}, +#line 656 "src/lexer-keywords.txt" + {"v128.not", TokenType::Unary, Opcode::V128Not}, +#line 63 "src/lexer-keywords.txt" + {"catch_ref", TokenType::CatchRef}, +#line 136 "src/lexer-keywords.txt" + {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, +#line 661 "src/lexer-keywords.txt" + {"v128.store", TokenType::Store, Opcode::V128Store}, {""}, -#line 629 "src/lexer-keywords.txt" - {"v128", Type::V128}, -#line 137 "src/lexer-keywords.txt" +#line 251 "src/lexer-keywords.txt" + {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, + {""}, {""}, {""}, {""}, +#line 64 "src/lexer-keywords.txt" + {"catch_all_ref", TokenType::CatchAllRef}, +#line 155 "src/lexer-keywords.txt" {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, -#line 75 "src/lexer-keywords.txt" +#line 93 "src/lexer-keywords.txt" {"f32.convert_i64_u", TokenType::Convert, Opcode::F32ConvertI64U}, - {""}, -#line 577 "src/lexer-keywords.txt" - {"nullref", Type::NullRef}, - {""}, {""}, {""}, {""}, -#line 622 "src/lexer-keywords.txt" - {"v128.load", TokenType::Load, Opcode::V128Load}, +#line 267 "src/lexer-keywords.txt" + {"i16x8", TokenType::I16X8}, +#line 253 "src/lexer-keywords.txt" + {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, +#line 154 "src/lexer-keywords.txt" + {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, +#line 92 "src/lexer-keywords.txt" + {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, +#line 78 "src/lexer-keywords.txt" + {"eq", Type::EqRef, TokenType::Eq}, {""}, {""}, {""}, {""}, {""}, -#line 126 "src/lexer-keywords.txt" - {"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub}, - {""}, -#line 368 "src/lexer-keywords.txt" - {"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub}, - {""}, {""}, {""}, -#line 41 "src/lexer-keywords.txt" - {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 539 "src/lexer-keywords.txt" - {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, - {""}, -#line 410 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, -#line 273 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, - {""}, {""}, -#line 499 "src/lexer-keywords.txt" - {"i64x2.shr_u", TokenType::Binary, Opcode::I64X2ShrU}, -#line 172 "src/lexer-keywords.txt" - {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, -#line 618 "src/lexer-keywords.txt" - {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, +#line 482 "src/lexer-keywords.txt" + {"i64.store16", TokenType::Store, Opcode::I64Store16}, +#line 339 "src/lexer-keywords.txt" + {"i32.store16", TokenType::Store, Opcode::I32Store16}, {""}, -#line 478 "src/lexer-keywords.txt" - {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, -#line 528 "src/lexer-keywords.txt" - {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, - {""}, {""}, {""}, {""}, -#line 237 "src/lexer-keywords.txt" - {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, -#line 49 "src/lexer-keywords.txt" - {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, - {""}, {""}, {""}, -#line 619 "src/lexer-keywords.txt" +#line 556 "src/lexer-keywords.txt" + {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 672 "src/lexer-keywords.txt" + {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, + {""}, +#line 203 "src/lexer-keywords.txt" + {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, +#line 652 "src/lexer-keywords.txt" {"v128.and", TokenType::Binary, Opcode::V128And}, -#line 387 "src/lexer-keywords.txt" - {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, -#line 258 "src/lexer-keywords.txt" - {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, - {""}, {""}, {""}, {""}, {""}, -#line 518 "src/lexer-keywords.txt" - {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, - {""}, {""}, {""}, {""}, {""}, -#line 474 "src/lexer-keywords.txt" - {"i64.trunc_sat_f64_u", TokenType::Convert, Opcode::I64TruncSatF64U}, -#line 330 "src/lexer-keywords.txt" - {"i32.trunc_sat_f64_u", TokenType::Convert, Opcode::I32TruncSatF64U}, {""}, {""}, {""}, -#line 420 "src/lexer-keywords.txt" - {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 550 "src/lexer-keywords.txt" + {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, + {""}, #line 549 "src/lexer-keywords.txt" - {"input", TokenType::Input}, -#line 376 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f32x4_s", TokenType::Unary, Opcode::I32X4TruncSatF32X4S}, - {""}, {""}, -#line 598 "src/lexer-keywords.txt" - {"shared", TokenType::Shared}, - {""}, {""}, {""}, {""}, -#line 548 "src/lexer-keywords.txt" - {"import", TokenType::Import}, - {""}, {""}, {""}, -#line 117 "src/lexer-keywords.txt" - {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, + {"i8x16.min_s", TokenType::Binary, Opcode::I8X16MinS}, {""}, -#line 382 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, +#line 657 "src/lexer-keywords.txt" + {"v128.or", TokenType::Binary, Opcode::V128Or}, {""}, {""}, {""}, -#line 637 "src/lexer-keywords.txt" +#line 651 "src/lexer-keywords.txt" + {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, +#line 670 "src/lexer-keywords.txt" {"v128.load32_lane", TokenType::SimdLoadLane, Opcode::V128Load32Lane}, -#line 388 "src/lexer-keywords.txt" - {"i64.atomic.load32_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad32U}, -#line 632 "src/lexer-keywords.txt" +#line 85 "src/lexer-keywords.txt" + {"export", TokenType::Export}, +#line 665 "src/lexer-keywords.txt" {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, {""}, -#line 46 "src/lexer-keywords.txt" - {"catch_ref", TokenType::CatchRef}, -#line 29 "src/lexer-keywords.txt" - {"assert_return", TokenType::AssertReturn}, -#line 103 "src/lexer-keywords.txt" - {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, -#line 544 "src/lexer-keywords.txt" - {"i8x16.sub_sat_u", TokenType::Binary, Opcode::I8X16SubSatU}, - {""}, -#line 511 "src/lexer-keywords.txt" - {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, -#line 639 "src/lexer-keywords.txt" - {"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane}, +#line 655 "src/lexer-keywords.txt" + {"v128.load", TokenType::Load, Opcode::V128Load}, + {""}, {""}, +#line 202 "src/lexer-keywords.txt" + {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, + {""}, {""}, {""}, {""}, +#line 431 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, +#line 294 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XorU}, +#line 378 "src/lexer-keywords.txt" + {"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S}, {""}, -#line 155 "src/lexer-keywords.txt" - {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, -#line 93 "src/lexer-keywords.txt" - {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, +#line 41 "src/lexer-keywords.txt" + {"assert_exhaustion", TokenType::AssertExhaustion}, + {""}, {""}, {""}, +#line 437 "src/lexer-keywords.txt" + {"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg}, +#line 300 "src/lexer-keywords.txt" + {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, {""}, -#line 238 "src/lexer-keywords.txt" - {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, +#line 612 "src/lexer-keywords.txt" + {"ref.i31", TokenType::RefI31, Opcode::RefI31}, +#line 520 "src/lexer-keywords.txt" + {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, {""}, -#line 575 "src/lexer-keywords.txt" +#line 595 "src/lexer-keywords.txt" {"nullfuncref", Type::NullFuncRef}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 260 "src/lexer-keywords.txt" + {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, +#line 21 "src/lexer-keywords.txt" + {"anyref", Type::AnyRef}, {""}, -#line 200 "src/lexer-keywords.txt" - {"global", TokenType::Global}, - {""}, {""}, {""}, {""}, -#line 125 "src/lexer-keywords.txt" - {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, -#line 635 "src/lexer-keywords.txt" - {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, +#line 220 "src/lexer-keywords.txt" + {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, + {""}, {""}, {""}, {""}, {""}, +#line 513 "src/lexer-keywords.txt" + {"i64x2.extend_low_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendLowI32X4U}, + {""}, +#line 511 "src/lexer-keywords.txt" + {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 254 "src/lexer-keywords.txt" - {"i31", Type::I31Ref, TokenType::I31}, +#line 26 "src/lexer-keywords.txt" + {"array.fill", TokenType::ArrayFill, Opcode::ArrayFill}, +#line 121 "src/lexer-keywords.txt" + {"f32x4.div", TokenType::Binary, Opcode::F32X4Div}, + {""}, {""}, +#line 138 "src/lexer-keywords.txt" + {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, +#line 659 "src/lexer-keywords.txt" + {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 616 "src/lexer-keywords.txt" - {"type", TokenType::Type}, - {""}, {""}, {""}, -#line 634 "src/lexer-keywords.txt" - {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, +#line 61 "src/lexer-keywords.txt" + {"catch", TokenType::Catch, Opcode::Catch}, {""}, {""}, {""}, -#line 626 "src/lexer-keywords.txt" - {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 198 "src/lexer-keywords.txt" - {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, -#line 392 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, -#line 262 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, - {""}, {""}, -#line 383 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, -#line 199 "src/lexer-keywords.txt" - {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, -#line 255 "src/lexer-keywords.txt" +#line 658 "src/lexer-keywords.txt" + {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, +#line 273 "src/lexer-keywords.txt" {"i31ref", Type::I31Ref}, -#line 62 "src/lexer-keywords.txt" - {"eqref", Type::EqRef}, {""}, {""}, {""}, {""}, -#line 42 "src/lexer-keywords.txt" - {"call_ref", TokenType::CallRef, Opcode::CallRef}, - {""}, {""}, {""}, {""}, -#line 479 "src/lexer-keywords.txt" - {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, -#line 540 "src/lexer-keywords.txt" - {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 654 "src/lexer-keywords.txt" + {"v128.const", TokenType::Const, Opcode::V128Const}, +#line 244 "src/lexer-keywords.txt" + {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, {""}, -#line 184 "src/lexer-keywords.txt" - {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, +#line 243 "src/lexer-keywords.txt" + {"i16x8.min_s", TokenType::Binary, Opcode::I16X8MinS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 566 "src/lexer-keywords.txt" + {"i8x16", TokenType::I8X16}, {""}, -#line 500 "src/lexer-keywords.txt" - {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, +#line 633 "src/lexer-keywords.txt" + {"struct.new_default", TokenType::StructNewDefault, Opcode::StructNewDefault}, +#line 40 "src/lexer-keywords.txt" + {"assert_exception", TokenType::AssertException}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 675 "src/lexer-keywords.txt" + {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, {""}, {""}, {""}, {""}, -#line 462 "src/lexer-keywords.txt" - {"i64.store16", TokenType::Store, Opcode::I64Store16}, -#line 319 "src/lexer-keywords.txt" - {"i32.store16", TokenType::Store, Opcode::I32Store16}, +#line 662 "src/lexer-keywords.txt" + {"v128", Type::V128}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 79 "src/lexer-keywords.txt" + {"eqref", Type::EqRef}, + {""}, {""}, +#line 156 "src/lexer-keywords.txt" + {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, +#line 94 "src/lexer-keywords.txt" + {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 207 "src/lexer-keywords.txt" - {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, +#line 580 "src/lexer-keywords.txt" + {"memory.copy", TokenType::MemoryCopy, Opcode::MemoryCopy}, {""}, -#line 394 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, -#line 264 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, -#line 134 "src/lexer-keywords.txt" - {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, -#line 72 "src/lexer-keywords.txt" - {"f32.convert_i32_s", TokenType::Convert, Opcode::F32ConvertI32S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 377 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U}, +#line 524 "src/lexer-keywords.txt" + {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, + {""}, +#line 522 "src/lexer-keywords.txt" + {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, {""}, {""}, {""}, -#line 562 "src/lexer-keywords.txt" +#line 420 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, + {""}, {""}, {""}, {""}, {""}, +#line 582 "src/lexer-keywords.txt" {"memory.grow", TokenType::MemoryGrow, Opcode::MemoryGrow}, +#line 196 "src/lexer-keywords.txt" + {"f64x2.pmin", TokenType::Binary, Opcode::F64X2PMin}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 153 "src/lexer-keywords.txt" + {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, +#line 91 "src/lexer-keywords.txt" + {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, {""}, {""}, -#line 66 "src/lexer-keywords.txt" - {"exnref", Type::ExnRef}, - {""}, {""}, {""}, -#line 395 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, -#line 265 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, -#line 391 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, -#line 261 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, -#line 594 "src/lexer-keywords.txt" - {"return_call_ref", TokenType::ReturnCallRef, Opcode::ReturnCallRef}, - {""}, {""}, {""}, {""}, -#line 625 "src/lexer-keywords.txt" - {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, - {""}, {""}, {""}, -#line 426 "src/lexer-keywords.txt" - {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, -#line 288 "src/lexer-keywords.txt" - {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, - {""}, {""}, -#line 541 "src/lexer-keywords.txt" - {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, - {""}, {""}, -#line 337 "src/lexer-keywords.txt" - {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, +#line 152 "src/lexer-keywords.txt" + {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, +#line 90 "src/lexer-keywords.txt" + {"f32.convert_i32_s", TokenType::Convert, Opcode::F32ConvertI32S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 225 "src/lexer-keywords.txt" - {"i16x8.min_s", TokenType::Binary, Opcode::I16X8MinS}, -#line 47 "src/lexer-keywords.txt" - {"catch_all_ref", TokenType::CatchAllRef}, - {""}, {""}, {""}, -#line 414 "src/lexer-keywords.txt" - {"i64.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmwCmpxchg}, -#line 277 "src/lexer-keywords.txt" - {"i32.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmwCmpxchg}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 640 "src/lexer-keywords.txt" - {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, +#line 84 "src/lexer-keywords.txt" + {"exnref", Type::ExnRef}, {""}, {""}, -#line 471 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, -#line 327 "src/lexer-keywords.txt" - {"i32.trunc_sat_f32_s", TokenType::Convert, Opcode::I32TruncSatF32S}, -#line 239 "src/lexer-keywords.txt" - {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, +#line 42 "src/lexer-keywords.txt" + {"assert_invalid", TokenType::AssertInvalid}, + {""}, {""}, {""}, {""}, +#line 24 "src/lexer-keywords.txt" + {"arrayref", Type::ArrayRef}, + {""}, {""}, {""}, {""}, {""}, +#line 218 "src/lexer-keywords.txt" + {"global", TokenType::Global}, + {""}, {""}, {""}, +#line 22 "src/lexer-keywords.txt" + {"any.convert_extern", TokenType::GCUnary, Opcode::AnyConvertExtern}, + {""}, {""}, {""}, {""}, {""}, +#line 577 "src/lexer-keywords.txt" + {"memory.atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 397 "src/lexer-keywords.txt" +#line 417 "src/lexer-keywords.txt" {"i64.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XorU}, -#line 267 "src/lexer-keywords.txt" +#line 287 "src/lexer-keywords.txt" {"i32.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XorU}, - {""}, {""}, {""}, {""}, -#line 160 "src/lexer-keywords.txt" - {"f64x2.abs", TokenType::Unary, Opcode::F64X2Abs}, -#line 563 "src/lexer-keywords.txt" - {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, -#line 487 "src/lexer-keywords.txt" - {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 219 "src/lexer-keywords.txt" - {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 561 "src/lexer-keywords.txt" + {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, + {""}, +#line 560 "src/lexer-keywords.txt" + {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, +#line 158 "src/lexer-keywords.txt" + {"f64.eq", TokenType::Compare, Opcode::F64Eq}, +#line 97 "src/lexer-keywords.txt" + {"f32.eq", TokenType::Compare, Opcode::F32Eq}, +#line 608 "src/lexer-keywords.txt" + {"ref.eq", TokenType::RefEq, Opcode::RefEq}, +#line 181 "src/lexer-keywords.txt" + {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, +#line 559 "src/lexer-keywords.txt" + {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, + {""}, +#line 198 "src/lexer-keywords.txt" + {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, + {""}, {""}, +#line 538 "src/lexer-keywords.txt" + {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, +#line 217 "src/lexer-keywords.txt" + {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, +#line 537 "src/lexer-keywords.txt" + {"i8x16.extract_lane_s", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneS}, +#line 216 "src/lexer-keywords.txt" + {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, + {""}, {""}, {""}, {""}, +#line 448 "src/lexer-keywords.txt" + {"i64.eq", TokenType::Compare, Opcode::I64Eq}, +#line 310 "src/lexer-keywords.txt" + {"i32.eq", TokenType::Compare, Opcode::I32Eq}, + {""}, {""}, {""}, {""}, +#line 646 "src/lexer-keywords.txt" + {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, {""}, {""}, {""}, -#line 396 "src/lexer-keywords.txt" +#line 535 "src/lexer-keywords.txt" + {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, +#line 71 "src/lexer-keywords.txt" + {"drop", TokenType::Drop, Opcode::Drop}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 667 "src/lexer-keywords.txt" + {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 416 "src/lexer-keywords.txt" {"i64.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XchgU}, -#line 266 "src/lexer-keywords.txt" +#line 286 "src/lexer-keywords.txt" {"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU}, - {""}, -#line 581 "src/lexer-keywords.txt" - {"param", TokenType::Param}, - {""}, {""}, {""}, {""}, -#line 427 "src/lexer-keywords.txt" - {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, -#line 289 "src/lexer-keywords.txt" - {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, -#line 641 "src/lexer-keywords.txt" +#line 593 "src/lexer-keywords.txt" + {"nop", TokenType::Nop, Opcode::Nop}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 674 "src/lexer-keywords.txt" {"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane}, - {""}, -#line 128 "src/lexer-keywords.txt" - {"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero}, - {""}, {""}, {""}, -#line 178 "src/lexer-keywords.txt" - {"f64x2.pmin", TokenType::Binary, Opcode::F64X2PMin}, -#line 226 "src/lexer-keywords.txt" - {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, - {""}, {""}, {""}, {""}, {""}, -#line 615 "src/lexer-keywords.txt" - {"try_table", TokenType::TryTable, Opcode::TryTable}, +#line 668 "src/lexer-keywords.txt" + {"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane}, {""}, {""}, {""}, -#line 358 "src/lexer-keywords.txt" - {"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S}, -#line 514 "src/lexer-keywords.txt" - {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, +#line 401 "src/lexer-keywords.txt" + {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, + {""}, +#line 400 "src/lexer-keywords.txt" + {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 650 "src/lexer-keywords.txt" + {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 135 "src/lexer-keywords.txt" - {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, -#line 73 "src/lexer-keywords.txt" - {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 256 "src/lexer-keywords.txt" + {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, {""}, -#line 28 "src/lexer-keywords.txt" - {"assert_malformed", TokenType::AssertMalformed}, -#line 186 "src/lexer-keywords.txt" - {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, +#line 255 "src/lexer-keywords.txt" + {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, + {""}, {""}, {""}, {""}, +#line 254 "src/lexer-keywords.txt" + {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, + {""}, {""}, {""}, {""}, +#line 230 "src/lexer-keywords.txt" + {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, {""}, -#line 501 "src/lexer-keywords.txt" - {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, - {""}, {""}, -#line 202 "src/lexer-keywords.txt" - {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 220 "src/lexer-keywords.txt" - {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 229 "src/lexer-keywords.txt" + {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, + {""}, +#line 403 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, + {""}, +#line 402 "src/lexer-keywords.txt" + {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, + {""}, +#line 357 "src/lexer-keywords.txt" + {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, + {""}, +#line 33 "src/lexer-keywords.txt" + {"array.new", TokenType::ArrayNew, Opcode::ArrayNew}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 529 "src/lexer-keywords.txt" - {"i8x16.min_s", TokenType::Binary, Opcode::I8X16MinS}, -#line 560 "src/lexer-keywords.txt" - {"memory.copy", TokenType::MemoryCopy, Opcode::MemoryCopy}, - {""}, {""}, {""}, {""}, -#line 638 "src/lexer-keywords.txt" - {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, +#line 499 "src/lexer-keywords.txt" + {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, +#line 226 "src/lexer-keywords.txt" + {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, {""}, -#line 633 "src/lexer-keywords.txt" - {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, -#line 643 "src/lexer-keywords.txt" - {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, -#line 61 "src/lexer-keywords.txt" - {"eq", Type::EqRef, TokenType::Eq}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 542 "src/lexer-keywords.txt" +#line 562 "src/lexer-keywords.txt" {"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat}, +#line 498 "src/lexer-keywords.txt" + {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 600 "src/lexer-keywords.txt" + {"pagesize", TokenType::PageSize}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 663 "src/lexer-keywords.txt" + {"v128.xor", TokenType::Binary, Opcode::V128Xor}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 653 "src/lexer-keywords.txt" + {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, {""}, {""}, -#line 472 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, -#line 328 "src/lexer-keywords.txt" - {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, +#line 576 "src/lexer-keywords.txt" + {"loop", TokenType::Loop, Opcode::Loop}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 534 "src/lexer-keywords.txt" + {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 393 "src/lexer-keywords.txt" + {"i32x4.extmul_low_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8U}, + {""}, +#line 391 "src/lexer-keywords.txt" + {"i32x4.extmul_low_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 613 "src/lexer-keywords.txt" - {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, +#line 257 "src/lexer-keywords.txt" + {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 22 "src/lexer-keywords.txt" - {"array", Type::ArrayRef, TokenType::Array}, - {""}, {""}, {""}, {""}, -#line 67 "src/lexer-keywords.txt" - {"export", TokenType::Export}, +#line 473 "src/lexer-keywords.txt" + {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, +#line 330 "src/lexer-keywords.txt" + {"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt}, + {""}, {""}, {""}, +#line 669 "src/lexer-keywords.txt" + {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, -#line 177 "src/lexer-keywords.txt" - {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, - {""}, {""}, -#line 627 "src/lexer-keywords.txt" - {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, -#line 242 "src/lexer-keywords.txt" - {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 163 "src/lexer-keywords.txt" - {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, +#line 664 "src/lexer-keywords.txt" + {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, +#line 122 "src/lexer-keywords.txt" + {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, + {""}, +#line 171 "src/lexer-keywords.txt" + {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 225 "src/lexer-keywords.txt" + {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, +#line 358 "src/lexer-keywords.txt" + {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, + {""}, {""}, {""}, {""}, {""}, +#line 673 "src/lexer-keywords.txt" + {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, {""}, {""}, -#line 407 "src/lexer-keywords.txt" +#line 427 "src/lexer-keywords.txt" {"i64.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw8CmpxchgU}, -#line 270 "src/lexer-keywords.txt" +#line 290 "src/lexer-keywords.txt" {"i32.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw8CmpxchgU}, - {""}, {""}, {""}, -#line 530 "src/lexer-keywords.txt" - {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 54 "src/lexer-keywords.txt" - {"drop", TokenType::Drop, Opcode::Drop}, +#line 671 "src/lexer-keywords.txt" + {"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane}, {""}, -#line 491 "src/lexer-keywords.txt" - {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, -#line 185 "src/lexer-keywords.txt" - {"f64x2.sqrt", TokenType::Unary, Opcode::F64X2Sqrt}, - {""}, {""}, {""}, -#line 534 "src/lexer-keywords.txt" +#line 666 "src/lexer-keywords.txt" + {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, + {""}, +#line 554 "src/lexer-keywords.txt" {"i8x16.popcnt", TokenType::Unary, Opcode::I8X16Popcnt}, -#line 20 "src/lexer-keywords.txt" - {"any", Type::AnyRef, TokenType::Any}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 434 "src/lexer-keywords.txt" + {"i64.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmwCmpxchg}, +#line 297 "src/lexer-keywords.txt" + {"i32.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmwCmpxchg}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 157 "src/lexer-keywords.txt" + {"f64.div", TokenType::Binary, Opcode::F64Div}, +#line 96 "src/lexer-keywords.txt" + {"f32.div", TokenType::Binary, Opcode::F32Div}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 146 "src/lexer-keywords.txt" + {"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero}, + {""}, {""}, {""}, +#line 660 "src/lexer-keywords.txt" + {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, + {""}, {""}, {""}, {""}, {""}, +#line 238 "src/lexer-keywords.txt" + {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, {""}, -#line 336 "src/lexer-keywords.txt" - {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, - {""}, -#line 502 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, -#line 509 "src/lexer-keywords.txt" - {"i8x16.abs", TokenType::Unary, Opcode::I8X16Abs}, +#line 237 "src/lexer-keywords.txt" + {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 73 "src/lexer-keywords.txt" + {"elem.drop", TokenType::ElemDrop, Opcode::ElemDrop}, {""}, -#line 409 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, -#line 272 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8SubU}, +#line 252 "src/lexer-keywords.txt" + {"i16x8.relaxed_q15mulr_s", TokenType::Binary, Opcode::I16X8RelaxedQ15mulrS}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 413 "src/lexer-keywords.txt" + {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, +#line 283 "src/lexer-keywords.txt" + {"i32.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw16CmpxchgU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, +#line 430 "src/lexer-keywords.txt" + {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, +#line 293 "src/lexer-keywords.txt" + {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 493 "src/lexer-keywords.txt" - {"i64x2.extend_low_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendLowI32X4U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 139 "src/lexer-keywords.txt" - {"f64.div", TokenType::Binary, Opcode::F64Div}, -#line 78 "src/lexer-keywords.txt" - {"f32.div", TokenType::Binary, Opcode::F32Div}, +#line 677 "src/lexer-keywords.txt" + {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 101 "src/lexer-keywords.txt" - {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, - {""}, {""}, -#line 504 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, +#line 182 "src/lexer-keywords.txt" + {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 545 "src/lexer-keywords.txt" - {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, -#line 228 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, - {""}, {""}, {""}, {""}, {""}, -#line 556 "src/lexer-keywords.txt" - {"loop", TokenType::Loop, Opcode::Loop}, -#line 453 "src/lexer-keywords.txt" - {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, -#line 310 "src/lexer-keywords.txt" - {"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt}, +#line 676 "src/lexer-keywords.txt" + {"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 501 "src/lexer-keywords.txt" + {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 393 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, -#line 263 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw16CmpxchgU}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 47 "src/lexer-keywords.txt" + {"atomic.fence", TokenType::AtomicFence, Opcode::AtomicFence}, +#line 135 "src/lexer-keywords.txt" + {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, {""}, {""}, {""}, {""}, -#line 138 "src/lexer-keywords.txt" - {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, -#line 76 "src/lexer-keywords.txt" - {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, +#line 110 "src/lexer-keywords.txt" + {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 102 "src/lexer-keywords.txt" - {"f32x4.convert_i32x4_u", TokenType::Unary, Opcode::F32X4ConvertI32X4U}, - {""}, {""}, {""}, {""}, -#line 612 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 645 "src/lexer-keywords.txt" {"throw", TokenType::Throw, Opcode::Throw}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 229 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 419 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 439 "src/lexer-keywords.txt" {"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16}, -#line 282 "src/lexer-keywords.txt" +#line 302 "src/lexer-keywords.txt" {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 56 "src/lexer-keywords.txt" - {"elem.drop", TokenType::ElemDrop, Opcode::ElemDrop}, - {""}, {""}, -#line 209 "src/lexer-keywords.txt" - {"i16x8.relaxed_dot_i8x16_i7x16_s", TokenType::Binary, Opcode::I16X8DotI8X16I7X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 271 "src/lexer-keywords.txt" + {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, {""}, -#line 606 "src/lexer-keywords.txt" - {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, +#line 270 "src/lexer-keywords.txt" + {"i16x8.extend_low_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendLowI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 592 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 619 "src/lexer-keywords.txt" {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 350 "src/lexer-keywords.txt" - {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, +#line 371 "src/lexer-keywords.txt" + {"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U}, {""}, {""}, {""}, -#line 252 "src/lexer-keywords.txt" - {"i16x8.extend_low_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendLowI8X16S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 370 "src/lexer-keywords.txt" + {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, {""}, {""}, {""}, {""}, -#line 429 "src/lexer-keywords.txt" - {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, -#line 291 "src/lexer-keywords.txt" - {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, +#line 172 "src/lexer-keywords.txt" + {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 245 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 399 "src/lexer-keywords.txt" + {"i32x4.extend_high_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendHighI16X8U}, + {""}, +#line 398 "src/lexer-keywords.txt" + {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, + {""}, {""}, {""}, {""}, +#line 265 "src/lexer-keywords.txt" + {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, + {""}, +#line 263 "src/lexer-keywords.txt" {"i16x8.extmul_low_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 578 "src/lexer-keywords.txt" + {"memory.atomic.wait32", TokenType::AtomicWait, Opcode::MemoryAtomicWait32}, + {""}, +#line 514 "src/lexer-keywords.txt" + {"i64x2.extend_high_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendHighI32X4U}, + {""}, +#line 512 "src/lexer-keywords.txt" + {"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 195 "src/lexer-keywords.txt" + {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 30 "src/lexer-keywords.txt" - {"assert_trap", TokenType::AssertTrap}, +#line 331 "src/lexer-keywords.txt" + {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 644 "src/lexer-keywords.txt" - {"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle}, - {""}, {""}, -#line 636 "src/lexer-keywords.txt" - {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, -#line 631 "src/lexer-keywords.txt" - {"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 157 "src/lexer-keywords.txt" - {"f64.sub", TokenType::Binary, Opcode::F64Sub}, -#line 95 "src/lexer-keywords.txt" - {"f32.sub", TokenType::Binary, Opcode::F32Sub}, -#line 466 "src/lexer-keywords.txt" - {"i64.sub", TokenType::Binary, Opcode::I64Sub}, -#line 322 "src/lexer-keywords.txt" - {"i32.sub", TokenType::Binary, Opcode::I32Sub}, -#line 253 "src/lexer-keywords.txt" - {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, +#line 632 "src/lexer-keywords.txt" + {"struct.new", TokenType::StructNew, Opcode::StructNew}, {""}, {""}, {""}, {""}, {""}, -#line 573 "src/lexer-keywords.txt" - {"nop", TokenType::Nop, Opcode::Nop}, - {""}, {""}, {""}, -#line 380 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, - {""}, {""}, -#line 234 "src/lexer-keywords.txt" - {"i16x8.relaxed_q15mulr_s", TokenType::Binary, Opcode::I16X8RelaxedQ15mulrS}, +#line 394 "src/lexer-keywords.txt" + {"i32x4.extmul_high_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8U}, + {""}, +#line 392 "src/lexer-keywords.txt" + {"i32x4.extmul_high_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8S}, +#line 227 "src/lexer-keywords.txt" + {"i16x8.relaxed_dot_i8x16_i7x16_s", TokenType::Binary, Opcode::I16X8DotI8X16I7X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, +#line 639 "src/lexer-keywords.txt" + {"table.grow", TokenType::TableGrow, Opcode::TableGrow}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 525 "src/lexer-keywords.txt" + {"i64x2.extmul_high_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U}, + {""}, +#line 523 "src/lexer-keywords.txt" + {"i64x2.extmul_high_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, -#line 247 "src/lexer-keywords.txt" - {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 371 "src/lexer-keywords.txt" - {"i32x4.extmul_low_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8S}, - {""}, {""}, {""}, {""}, -#line 536 "src/lexer-keywords.txt" - {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, -#line 490 "src/lexer-keywords.txt" - {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, - {""}, {""}, {""}, {""}, {""}, -#line 378 "src/lexer-keywords.txt" - {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 153 "src/lexer-keywords.txt" - {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, -#line 25 "src/lexer-keywords.txt" - {"assert_exception", TokenType::AssertException}, +#line 536 "src/lexer-keywords.txt" + {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 351 "src/lexer-keywords.txt" - {"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U}, +#line 352 "src/lexer-keywords.txt" + {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 381 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, - {""}, -#line 372 "src/lexer-keywords.txt" - {"i32x4.extmul_high_i16x8_s", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 23 "src/lexer-keywords.txt" - {"arrayref", Type::ArrayRef}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 249 "src/lexer-keywords.txt" + {"i16x8.q15mulr_sat_s", TokenType::Binary, Opcode::I16X8Q15mulrSatS}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 373 "src/lexer-keywords.txt" - {"i32x4.extmul_low_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulLowI16X8U}, +#line 474 "src/lexer-keywords.txt" + {"i64.reinterpret_f64", TokenType::Convert, Opcode::I64ReinterpretF64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 379 "src/lexer-keywords.txt" - {"i32x4.extend_high_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendHighI16X8U}, - {""}, {""}, {""}, -#line 208 "src/lexer-keywords.txt" - {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 120 "src/lexer-keywords.txt" + {"f32x4.convert_i32x4_u", TokenType::Unary, Opcode::F32X4ConvertI32X4U}, + {""}, +#line 119 "src/lexer-keywords.txt" + {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 21 "src/lexer-keywords.txt" - {"anyref", Type::AnyRef}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 374 "src/lexer-keywords.txt" - {"i32x4.extmul_high_i16x8_u", TokenType::Binary, Opcode::I32X4ExtmulHighI16X8U}, - {""}, {""}, -#line 26 "src/lexer-keywords.txt" - {"assert_exhaustion", TokenType::AssertExhaustion}, + {""}, +#line 228 "src/lexer-keywords.txt" + {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 454 "src/lexer-keywords.txt" - {"i64.reinterpret_f64", TokenType::Convert, Opcode::I64ReinterpretF64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 31 "src/lexer-keywords.txt" - {"assert_unlinkable", TokenType::AssertUnlinkable}, -#line 332 "src/lexer-keywords.txt" - {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 492 "src/lexer-keywords.txt" - {"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S}, - {""}, {""}, {""}, -#line 557 "src/lexer-keywords.txt" - {"memory.atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 416 "src/lexer-keywords.txt" - {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, -#line 279 "src/lexer-keywords.txt" - {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, -#line 154 "src/lexer-keywords.txt" - {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, - {""}, {""}, {""}, {""}, {""}, -#line 140 "src/lexer-keywords.txt" - {"f64.eq", TokenType::Compare, Opcode::F64Eq}, -#line 79 "src/lexer-keywords.txt" - {"f32.eq", TokenType::Compare, Opcode::F32Eq}, -#line 428 "src/lexer-keywords.txt" - {"i64.eq", TokenType::Compare, Opcode::I64Eq}, -#line 290 "src/lexer-keywords.txt" - {"i32.eq", TokenType::Compare, Opcode::I32Eq}, - {""}, {""}, {""}, -#line 503 "src/lexer-keywords.txt" - {"i64x2.extmul_high_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4S}, - {""}, {""}, {""}, {""}, {""}, -#line 27 "src/lexer-keywords.txt" - {"assert_invalid", TokenType::AssertInvalid}, - {""}, {""}, {""}, -#line 515 "src/lexer-keywords.txt" - {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, - {""}, {""}, -#line 104 "src/lexer-keywords.txt" - {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 579 "src/lexer-keywords.txt" + {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 390 "src/lexer-keywords.txt" + {"i32x4.extadd_pairwise_i16x8_u", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8U}, {""}, -#line 338 "src/lexer-keywords.txt" - {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, +#line 389 "src/lexer-keywords.txt" + {"i32x4.extadd_pairwise_i16x8_s", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 494 "src/lexer-keywords.txt" - {"i64x2.extend_high_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendHighI32X4U}, +#line 247 "src/lexer-keywords.txt" + {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, + {""}, +#line 246 "src/lexer-keywords.txt" + {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 620 "src/lexer-keywords.txt" - {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 505 "src/lexer-keywords.txt" - {"i64x2.extmul_high_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 369 "src/lexer-keywords.txt" - {"i32x4.extadd_pairwise_i16x8_s", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 580 "src/lexer-keywords.txt" - {"pagesize", TokenType::PageSize}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 370 "src/lexer-keywords.txt" - {"i32x4.extadd_pairwise_i16x8_u", TokenType::Unary, Opcode::I32X4ExtaddPairwiseI16X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1779,89 +1938,77 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 188 "src/lexer-keywords.txt" - {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, -#line 311 "src/lexer-keywords.txt" - {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 250 "src/lexer-keywords.txt" - {"i16x8.extend_high_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendHighI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 164 "src/lexer-keywords.txt" - {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, - {""}, -#line 481 "src/lexer-keywords.txt" - {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, - {""}, {""}, {""}, {""}, -#line 559 "src/lexer-keywords.txt" - {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, - {""}, {""}, {""}, {""}, -#line 32 "src/lexer-keywords.txt" - {"atomic.fence", TokenType::AtomicFence, Opcode::AtomicFence}, {""}, {""}, {""}, {""}, {""}, -#line 246 "src/lexer-keywords.txt" - {"i16x8.extmul_high_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16S}, - {""}, {""}, {""}, {""}, -#line 92 "src/lexer-keywords.txt" - {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, - {""}, -#line 189 "src/lexer-keywords.txt" +#line 207 "src/lexer-keywords.txt" {"f64x2.convert_low_i32x4_u", TokenType::Unary, Opcode::F64X2ConvertLowI32X4U}, + {""}, +#line 206 "src/lexer-keywords.txt" + {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 558 "src/lexer-keywords.txt" - {"memory.atomic.wait32", TokenType::AtomicWait, Opcode::MemoryAtomicWait32}, - {""}, -#line 251 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 269 "src/lexer-keywords.txt" {"i16x8.extend_high_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendHighI8X16U}, + {""}, +#line 268 "src/lexer-keywords.txt" + {"i16x8.extend_high_i8x16_s", TokenType::Unary, Opcode::I16X8ExtendHighI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 210 "src/lexer-keywords.txt" - {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, - {""}, {""}, {""}, {""}, {""}, -#line 248 "src/lexer-keywords.txt" - {"i16x8.extmul_high_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 231 "src/lexer-keywords.txt" - {"i16x8.q15mulr_sat_s", TokenType::Binary, Opcode::I16X8Q15mulrSatS}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 190 "src/lexer-keywords.txt" - {"f64x2.promote_low_f32x4", TokenType::Unary, Opcode::F64X2PromoteLowF32X4}, +#line 266 "src/lexer-keywords.txt" + {"i16x8.extmul_high_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16U}, + {""}, +#line 264 "src/lexer-keywords.txt" + {"i16x8.extmul_high_i8x16_s", TokenType::Binary, Opcode::I16X8ExtmulHighI8X16S}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 531 "src/lexer-keywords.txt" +#line 552 "src/lexer-keywords.txt" + {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, +#line 208 "src/lexer-keywords.txt" + {"f64x2.promote_low_f32x4", TokenType::Unary, Opcode::F64X2PromoteLowF32X4}, +#line 551 "src/lexer-keywords.txt" {"i8x16.narrow_i16x8_s", TokenType::Binary, Opcode::I8X16NarrowI16X8S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 516 "src/lexer-keywords.txt" - {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 532 "src/lexer-keywords.txt" - {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 243 "src/lexer-keywords.txt" - {"i16x8.extadd_pairwise_i8x16_s", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16S}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1869,9 +2016,24 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 244 "src/lexer-keywords.txt" - {"i16x8.extadd_pairwise_i8x16_u", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16U} + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 262 "src/lexer-keywords.txt" + {"i16x8.extadd_pairwise_i8x16_u", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16U}, + {""}, +#line 261 "src/lexer-keywords.txt" + {"i16x8.extadd_pairwise_i8x16_s", TokenType::Unary, Opcode::I16X8ExtaddPairwiseI8X16S} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 18c1955898..abdcbb3bd1 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -40,6 +40,7 @@ class NameResolver : public ExprVisitor::DelegateNop { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnCastExpr(BrOnCastExpr*) override; Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; @@ -86,6 +87,23 @@ class NameResolver : public ExprVisitor::DelegateNop { Result OnRethrowExpr(RethrowExpr*) override; Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override; Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override; + Result OnArrayCopyExpr(ArrayCopyExpr*) override; + Result OnArrayFillExpr(ArrayFillExpr*) override; + Result OnArrayGetExpr(ArrayGetExpr*) override; + Result OnArrayInitDataExpr(ArrayInitDataExpr*) override; + Result OnArrayInitElemExpr(ArrayInitElemExpr*) override; + Result OnArrayNewExpr(ArrayNewExpr*) override; + Result OnArrayNewDataExpr(ArrayNewDataExpr*) override; + Result OnArrayNewDefaultExpr(ArrayNewDefaultExpr*) override; + Result OnArrayNewElemExpr(ArrayNewElemExpr*) override; + Result OnArrayNewFixedExpr(ArrayNewFixedExpr*) override; + Result OnArraySetExpr(ArraySetExpr*) override; + Result OnRefCastExpr(RefCastExpr*) override; + Result OnRefTestExpr(RefTestExpr*) override; + Result OnStructGetExpr(StructGetExpr*) override; + Result OnStructNewExpr(StructNewExpr*) override; + Result OnStructNewDefaultExpr(StructNewDefaultExpr*) override; + Result OnStructSetExpr(StructSetExpr*) override; private: void PrintError(const Location* loc, const char* fmt, ...); @@ -107,6 +125,7 @@ class NameResolver : public ExprVisitor::DelegateNop { void ResolveElemSegmentVar(Var* var); void ResolveLocalVar(Var* var); void ResolveBlockDeclarationVar(BlockDeclaration* decl); + void ResolveStructFieldVar(Var* type, Var* var); void VisitFunc(Func* func); void VisitExport(Export* export_); void VisitGlobal(Global* global); @@ -250,6 +269,34 @@ void NameResolver::ResolveBlockDeclarationVar(BlockDeclaration* decl) { } } +void NameResolver::ResolveStructFieldVar(Var* type, Var* var) { + ResolveFuncTypeVar(type); + + if (type->is_index() && var->is_name()) { + // If type is still a name, it cannot be resolved. + Index index = type->index(); + + if (index < current_module_->types.size() && + current_module_->types[index]->kind() == TypeEntryKind::Struct) { + StructType* struct_type = cast(current_module_->types[index]); + + Index size = static_cast(struct_type->fields.size()); + + for (Index i = 0; i < size; i++) { + if (struct_type->fields[i].name == var->name()) { + var->set_index(i); + break; + } + } + } + + if (var->is_name()) { + PrintError(&var->loc, "undefined struct field \"%s\"", + var->name().c_str()); + } + } +} + Result NameResolver::BeginBlockExpr(BlockExpr* expr) { PushLabel(expr->block.label); ResolveBlockDeclarationVar(&expr->block.decl); @@ -282,6 +329,13 @@ Result NameResolver::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result NameResolver::OnBrOnCastExpr(BrOnCastExpr* expr) { + ResolveLabelVar(&expr->label_var); + ResolveFuncTypeVar(&expr->type1_var); + ResolveFuncTypeVar(&expr->type2_var); + return Result::Ok; +} + Result NameResolver::OnBrOnNonNullExpr(BrOnNonNullExpr* expr) { ResolveLabelVar(&expr->var); return Result::Ok; @@ -533,6 +587,96 @@ Result NameResolver::OnSimdStoreLaneExpr(SimdStoreLaneExpr* expr) { return Result::Ok; } +Result NameResolver::OnArrayCopyExpr(ArrayCopyExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayFillExpr(ArrayFillExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayGetExpr(ArrayGetExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + return Result::Ok; +} + +Result NameResolver::OnArrayInitDataExpr(ArrayInitDataExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + ResolveDataSegmentVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayInitElemExpr(ArrayInitElemExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + ResolveElemSegmentVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayNewExpr(ArrayNewExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayNewDataExpr(ArrayNewDataExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + ResolveDataSegmentVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayNewDefaultExpr(ArrayNewDefaultExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayNewElemExpr(ArrayNewElemExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + ResolveElemSegmentVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnArrayNewFixedExpr(ArrayNewFixedExpr* expr) { + ResolveFuncTypeVar(&expr->type_var); + return Result::Ok; +} + +Result NameResolver::OnArraySetExpr(ArraySetExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnRefCastExpr(RefCastExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnRefTestExpr(RefTestExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnStructGetExpr(StructGetExpr* expr) { + ResolveStructFieldVar(&expr->type_var, &expr->var); + return Result::Ok; +} + +Result NameResolver::OnStructNewExpr(StructNewExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnStructNewDefaultExpr(StructNewDefaultExpr* expr) { + ResolveFuncTypeVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnStructSetExpr(StructSetExpr* expr) { + ResolveStructFieldVar(&expr->type_var, &expr->var); + return Result::Ok; +} + void NameResolver::VisitFunc(Func* func) { current_func_ = func; if (func->decl.has_func_type) { @@ -602,10 +746,7 @@ void NameResolver::VisitElemSegment(ElemSegment* segment) { ResolveTableVar(&segment->table_var); visitor_.VisitExprList(segment->offset); for (ExprList& elem_expr : segment->elem_exprs) { - if (elem_expr.size() == 1 && - elem_expr.front().type() == ExprType::RefFunc) { - ResolveFuncVar(&cast(&elem_expr.front())->var); - } + visitor_.VisitExprList(elem_expr); } } diff --git a/src/shared-validator.cc b/src/shared-validator.cc index ce9043d6c4..efba7c9be6 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -542,7 +542,7 @@ Result SharedValidator::CheckLocalIndex(Var local_var, Type* out_type) { Result SharedValidator::CheckFuncTypeIndex(Var sig_var, FuncType* out) { Result result = CheckIndex(sig_var, type_fields_.NumTypes(), "function type"); if (Failed(result)) { - *out = FuncType{}; + out->type_index = kInvalidIndex; return Result::Error; } @@ -553,9 +553,51 @@ Result SharedValidator::CheckFuncTypeIndex(Var sig_var, FuncType* out) { sig_var.index()); } - if (out) { - *out = type_fields_.func_types[type_fields_.type_entries[index].map_index]; + *out = type_fields_.func_types[type_fields_.type_entries[index].map_index]; + return Result::Ok; +} + +Result SharedValidator::CheckStructTypeIndex(Var type_var, + Type* out_ref, + StructType* out) { + Result result = CheckIndex(type_var, type_fields_.NumTypes(), "struct type"); + if (Failed(result)) { + return Result::Error; + } + + Index index = type_var.index(); + assert(index < type_fields_.NumTypes()); + if (type_fields_.type_entries[index].kind != Type::StructRef) { + return PrintError(type_var.loc, "type %d is not a struct type", + type_var.index()); + } + + *out_ref = + Type(out_ref->IsNullableNonTypedRef() ? Type::RefNull : Type::Ref, index); + index = type_fields_.type_entries[index].map_index; + *out = type_fields_.struct_types[index]; + return Result::Ok; +} + +Result SharedValidator::CheckArrayTypeIndex(Var type_var, + Type* out_ref, + TypeMut* out) { + Result result = CheckIndex(type_var, type_fields_.NumTypes(), "array type"); + if (Failed(result)) { + return Result::Error; } + + Index index = type_var.index(); + assert(index < type_fields_.NumTypes()); + if (type_fields_.type_entries[index].kind != Type::ArrayRef) { + return PrintError(type_var.loc, "type %d is not an array type", + type_var.index()); + } + + *out_ref = + Type(out_ref->IsNullableNonTypedRef() ? Type::RefNull : Type::Ref, index); + index = type_fields_.type_entries[index].map_index; + *out = type_fields_.array_types[index].field; return Result::Ok; } @@ -660,12 +702,13 @@ void SharedValidator::IgnoreLocalRefs() { Index SharedValidator::GetEndIndex() { assert(options_.features.reference_types_enabled()); + Index num_types = type_fields_.NumTypes(); + if (options_.features.gc_enabled()) { - return (last_rec_type_end_ != 0) ? last_rec_type_end_ - : type_fields_.NumTypes(); + return (last_rec_type_end_ > num_types) ? last_rec_type_end_ : num_types; } - return type_fields_.NumTypes() - 1; + return num_types - 1; } Result SharedValidator::BeginInitExpr(const Location& loc, Type type) { @@ -807,6 +850,14 @@ bool SharedValidator::ValidInitOpcode(Opcode opcode) const { return true; } } + if (options_.features.gc_enabled()) { + if (opcode == Opcode::AnyConvertExtern || opcode == Opcode::ArrayNew || + opcode == Opcode::ArrayNewDefault || opcode == Opcode::ArrayNewFixed || + opcode == Opcode::ExternConvertAny || opcode == Opcode::RefI31 || + opcode == Opcode::StructNew || opcode == Opcode::StructNewDefault) { + return true; + } + } return false; } @@ -822,6 +873,139 @@ Result SharedValidator::CheckInstr(Opcode opcode, const Location& loc) { return Result::Ok; } +Result SharedValidator::OnArrayCopy(const Location& loc, + Var dst_type, + Var src_type) { + Result result = CheckInstr(Opcode::ArrayCopy, loc); + Type dst_ref_type(Type::ArrayRef, Type::ReferenceOrNull); + Type src_ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut dst_array_type, src_array_type; + result |= CheckArrayTypeIndex(dst_type, &dst_ref_type, &dst_array_type); + result |= CheckArrayTypeIndex(src_type, &src_ref_type, &src_array_type); + result |= typechecker_.OnArrayCopy(dst_ref_type, dst_array_type, src_ref_type, + src_array_type.type); + return result; +} + +Result SharedValidator::OnArrayFill(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::ArrayFill, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= typechecker_.OnArrayFill(ref_type, array_type); + return result; +} + +Result SharedValidator::OnArrayGet(const Location& loc, + Opcode opcode, + Var type) { + Result result = CheckInstr(opcode, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= typechecker_.OnArrayGet(opcode, ref_type, array_type.type); + return result; +} + +Result SharedValidator::OnArrayInitData(const Location& loc, + Var type, + Var segment_var) { + Result result = CheckInstr(Opcode::ArrayInitData, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= CheckDataSegmentIndex(segment_var); + result |= typechecker_.OnArrayInitData(ref_type, array_type); + return result; +} + +Result SharedValidator::OnArrayInitElem(const Location& loc, + Var type, + Var segment_var) { + Result result = CheckInstr(Opcode::ArrayInitElem, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut array_type; + ElemType elem_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= CheckElemSegmentIndex(segment_var, &elem_type); + result |= + typechecker_.OnArrayInitElem(ref_type, array_type, elem_type.element); + return result; +} + +Result SharedValidator::OnArrayNew(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::ArrayNew, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceNonNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= typechecker_.OnArrayNew(ref_type, array_type.type); + return result; +} + +Result SharedValidator::OnArrayNewData(const Location& loc, + Var type, + Var segment_var) { + Result result = CheckInstr(Opcode::ArrayNewData, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceNonNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= CheckDataSegmentIndex(segment_var); + result |= typechecker_.OnArrayNewData(ref_type, array_type.type); + return result; +} + +Result SharedValidator::OnArrayNewDefault(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::ArrayNewDefault, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceNonNull); + TypeMut array_type; + + if (Succeeded(CheckArrayTypeIndex(type, &ref_type, &array_type))) { + if (array_type.type.IsNonNullableRef()) { + result = PrintError(loc, "array type has no default value: %" PRIindex, + type.index()); + } + } else { + result = Result::Error; + } + + result |= typechecker_.OnArrayNewDefault(ref_type); + return result; +} + +Result SharedValidator::OnArrayNewElem(const Location& loc, + Var type, + Var segment_var) { + Result result = CheckInstr(Opcode::ArrayNewElem, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceNonNull); + TypeMut array_type; + ElemType elem_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= CheckElemSegmentIndex(segment_var, &elem_type); + result |= + typechecker_.OnArrayNewElem(ref_type, array_type.type, elem_type.element); + return result; +} + +Result SharedValidator::OnArrayNewFixed(const Location& loc, + Var type, + Index count) { + Result result = CheckInstr(Opcode::ArrayNewFixed, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceNonNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= typechecker_.OnArrayNewFixed(ref_type, array_type.type, count); + return result; +} + +Result SharedValidator::OnArraySet(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::ArraySet, loc); + Type ref_type(Type::ArrayRef, Type::ReferenceOrNull); + TypeMut array_type; + result |= CheckArrayTypeIndex(type, &ref_type, &array_type); + result |= typechecker_.OnArraySet(ref_type, array_type); + return result; +} + Result SharedValidator::OnAtomicFence(const Location& loc, uint32_t consistency_model) { Result result = CheckInstr(Opcode::AtomicFence, loc); @@ -947,6 +1131,17 @@ Result SharedValidator::OnBrIf(const Location& loc, Var depth) { return result; } +Result SharedValidator::OnBrOnCast(const Location& loc, + Opcode opcode, + Var depth, + Var type1_var, + Var type2_var) { + Result result = CheckInstr(Opcode::BrOnCast, loc); + result |= typechecker_.OnBrOnCast(opcode, depth.index(), type1_var.to_type(), + type2_var.to_type()); + return result; +} + Result SharedValidator::OnBrOnNonNull(const Location& loc, Var depth) { Result result = CheckInstr(Opcode::BrOnNonNull, loc); result |= typechecker_.OnBrOnNonNull(depth.index()); @@ -1092,6 +1287,12 @@ Result SharedValidator::OnEnd(const Location& loc) { return result; } +Result SharedValidator::OnGCUnary(const Location& loc, Opcode opcode) { + Result result = CheckInstr(opcode, loc); + result |= typechecker_.OnGCUnary(opcode); + return result; +} + Result SharedValidator::OnGlobalGet(const Location& loc, Var global_var) { Result result = CheckInstr(Opcode::GlobalGet, loc); GlobalType global_type; @@ -1291,6 +1492,12 @@ Result SharedValidator::OnRefAsNonNull(const Location& loc) { return result; } +Result SharedValidator::OnRefCast(const Location& loc, Var type_var) { + Result result = CheckInstr(Opcode::RefCast, loc); + result |= typechecker_.OnRefCast(type_var.to_type()); + return result; +} + Result SharedValidator::OnRefFunc(const Location& loc, Var func_var) { Result result = CheckInstr(Opcode::RefFunc, loc); result |= CheckFuncIndex(func_var); @@ -1323,8 +1530,7 @@ Result SharedValidator::OnRefNull(const Location& loc, Var func_type_var) { result |= CheckIndex(func_type_var, type_fields_.NumTypes(), "function type"); } else if (!type.IsNonTypedRef()) { - result |= PrintError( - loc, "Only ref, externref, exnref, funcref are allowed for ref.null"); + result |= PrintError(loc, "Only nullable reference types are allowed"); } assert(!Type::EnumIsNonTypedGCRef(type) || options_.features.gc_enabled()); @@ -1332,6 +1538,12 @@ Result SharedValidator::OnRefNull(const Location& loc, Var func_type_var) { return result; } +Result SharedValidator::OnRefTest(const Location& loc, Var type_var) { + Result result = CheckInstr(Opcode::RefTest, loc); + result |= typechecker_.OnRefTest(type_var.to_type()); + return result; +} + Result SharedValidator::OnRethrow(const Location& loc, Var depth) { Result result = CheckInstr(Opcode::Rethrow, loc); result |= typechecker_.OnRethrow(depth.index()); @@ -1470,6 +1682,59 @@ Result SharedValidator::OnStore(const Location& loc, return result; } +Result SharedValidator::OnStructGet(const Location& loc, + Opcode opcode, + Var type, + Var field) { + Result result = CheckInstr(opcode, loc); + Type ref_type(Type::StructRef, Type::ReferenceOrNull); + StructType struct_type; + result |= CheckStructTypeIndex(type, &ref_type, &struct_type); + result |= + typechecker_.OnStructGet(opcode, ref_type, struct_type, field.index()); + return result; +} + +Result SharedValidator::OnStructNew(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::StructNew, loc); + Type ref_type(Type::StructRef, Type::ReferenceNonNull); + StructType struct_type; + result |= CheckStructTypeIndex(type, &ref_type, &struct_type); + result |= typechecker_.OnStructNew(ref_type, struct_type); + return result; +} + +Result SharedValidator::OnStructNewDefault(const Location& loc, Var type) { + Result result = CheckInstr(Opcode::StructNewDefault, loc); + Type ref_type(Type::StructRef, Type::ReferenceNonNull); + StructType struct_type; + + if (Succeeded(CheckStructTypeIndex(type, &ref_type, &struct_type))) { + for (auto it : struct_type.fields) { + if (it.type.IsNonNullableRef()) { + result = + PrintError(loc, "type has field without default value: %" PRIindex, + type.index()); + break; + } + } + } else { + result = Result::Error; + } + + result |= typechecker_.OnStructNewDefault(ref_type); + return result; +} + +Result SharedValidator::OnStructSet(const Location& loc, Var type, Var field) { + Result result = CheckInstr(Opcode::StructSet, loc); + Type ref_type(Type::StructRef, Type::ReferenceOrNull); + StructType struct_type; + result |= CheckStructTypeIndex(type, &ref_type, &struct_type); + result |= typechecker_.OnStructSet(ref_type, struct_type, field.index()); + return result; +} + Result SharedValidator::OnTableCopy(const Location& loc, Var dst_var, Var src_var) { diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index 3b8620224b..a4a4b7e405 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -629,12 +629,24 @@ wabt::Result JSONParser::ParseType(Type* out_type) { *out_type = Type::I8; } else if (type_str == "i16") { *out_type = Type::I16; - } else if (type_str == "funcref") { - *out_type = Type::FuncRef; - } else if (type_str == "externref") { - *out_type = Type::ExternRef; + } else if (type_str == "anyref") { + *out_type = Type::AnyRef; + } else if (type_str == "arrayref") { + *out_type = Type::ArrayRef; + } else if (type_str == "botref") { + *out_type = Type::BottomRef(); + } else if (type_str == "eqref") { + *out_type = Type::EqRef; } else if (type_str == "exnref") { *out_type = Type::ExnRef; + } else if (type_str == "externref") { + *out_type = Type::ExternRef; + } else if (type_str == "funcref") { + *out_type = Type::FuncRef; + } else if (type_str == "i31ref") { + *out_type = Type::I31Ref; + } else if (type_str == "structref") { + *out_type = Type::StructRef; } else { PrintError("unknown type: \"%s\"", type_str.c_str()); return wabt::Result::Error; @@ -853,18 +865,47 @@ wabt::Result JSONParser::ParseConstValue(Type type, } break; + case Type::AnyRef: case Type::ExternRef: if (value_str == "null") { out_value->Set(Ref::Null); + } else if (value_str == "") { + out_value->Set(Ref::CreateHostVal(Ref::kAnyHostValue)); } else { uint32_t value; CHECK_RESULT(ParseI32Value(&value, value_str)); - // TODO: hack, just whatever ref is at this index; but skip null (which - // is always 0). + out_value->Set(Ref::CreateHostVal(value)); + } + break; + + case Type::ArrayRef: + case Type::EqRef: + case Type::StructRef: + if (value_str == "null") { + out_value->Set(Ref::Null); + } else { + uint32_t value; + CHECK_RESULT(ParseI32Value(&value, value_str)); + // TODO: these cannot be constructed without a type reference. out_value->Set(Ref{value + 1}); } break; + case Type::NullRef: + assert(type.IsBottomRef()); + out_value->Set(Ref::Null); + break; + + case Type::I31Ref: + if (value_str == "null") { + out_value->Set(Ref::Null); + } else { + uint32_t value; + CHECK_RESULT(ParseI32Value(&value, value_str)); + out_value->Set(Ref::CreateI31Val(value)); + } + break; + case Type::ExnRef: if (value_str == "null") { out_value->Set(Ref::Null); @@ -1918,14 +1959,100 @@ wabt::Result CommandRunner::CheckAssertReturnResult( break; } - case Type::FuncRef: - // A funcref expectation only requires that the reference be a function, - // but it doesn't check the actual index. - ok = (actual.type == Type::FuncRef || actual.type == Type::RefNull); + case Type::AnyRef: + ok = false; + if (actual.type == Type::AnyRef || actual.type == Type::NullRef) { + Ref actual_ref = actual.value.Get(); + Ref expected_ref = expected.value.value.Get(); + if (expected_ref == Ref::Null) { + ok = (actual_ref == Ref::Null); + } else if (actual_ref != Ref::Null) { + ok = expected_ref.IsAnyHostVal() || + actual_ref.GetHostVal() == expected_ref.GetHostVal(); + } + } + break; + + case Type::ArrayRef: + ok = false; + if (actual.type == Type::ArrayRef) { + ok = actual.value.Get() != Ref::Null; + } else if ((actual.type == Type::AnyRef || actual.type == Type::Ref) && + actual.value.Get() != Ref::Null) { + RefPtr obj = store_.UnsafeGet(actual.value.Get()); + ok = obj->kind() == ObjectKind::Array; + } + break; + + case Type::NullRef: + assert(expected.value.type.IsBottomRef()); + ok = actual.value.Get() == Ref::Null; break; + case Type::EqRef: { + ok = false; + Ref ref = actual.value.Get(); + if (ref == Ref::Null || ref.IsI31Val()) { + ok = true; + } else if (!ref.IsHostVal()) { + if (actual.type == Type::EqRef || actual.type == Type::StructRef || + actual.type == Type::ArrayRef) { + ok = true; + } else if (actual.type == Type::AnyRef || actual.type == Type::Ref) { + RefPtr obj = store_.UnsafeGet(ref); + ok = obj->kind() == ObjectKind::Array || + obj->kind() == ObjectKind::Struct; + } + } + break; + } + case Type::ExternRef: - ok = expected.value.value.Get() == actual.value.Get(); + ok = false; + if (actual.type == Type::ExternRef || + actual.type == Type::NullExternRef) { + Ref actual_ref = actual.value.Get(); + Ref expected_ref = expected.value.value.Get(); + if (expected_ref == Ref::Null) { + ok = (actual_ref == Ref::Null); + } else if (actual_ref != Ref::Null) { + ok = expected_ref.IsAnyHostVal() || + actual_ref.GetHostVal() == expected_ref.GetHostVal(); + } + } + break; + + case Type::FuncRef: + if (actual.type == Type::NullFuncRef) { + ok = actual.value.Get() == Ref::Null; + } else { + // A funcref expectation only requires that the reference be a function, + // but it doesn't check the actual index. + ok = (actual.type == Type::FuncRef || actual.type == Type::RefNull); + } + break; + + case Type::I31Ref: { + ok = false; + Ref ref = actual.value.Get(); + if (actual.type == Type::I31Ref) { + ok = ref != Ref::Null; + } else if ((actual.type == Type::AnyRef || actual.type == Type::Ref) && + ref != Ref::Null) { + ok = ref.IsI31Val(); + } + break; + } + + case Type::StructRef: + ok = false; + if (actual.type == Type::StructRef) { + ok = actual.value.Get() != Ref::Null; + } else if ((actual.type == Type::AnyRef || actual.type == Type::Ref) && + actual.value.Get() != Ref::Null) { + RefPtr obj = store_.UnsafeGet(actual.value.Get()); + ok = obj->kind() == ObjectKind::Struct; + } break; case Type::ExnRef: diff --git a/src/type-checker.cc b/src/type-checker.cc index 8b5d8662bf..dbefde96c6 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -48,6 +48,24 @@ std::string TypesToString(const TypeVector& types, } // end anonymous namespace +Type TypeChecker::TypeFields::GetGroupType(Type type) { + assert(type.IsRef()); + type = GetGenericType(type); + + switch (type) { + case Type::NullFuncRef: + case Type::FuncRef: + return Type::FuncRef; + + case Type::NullExternRef: + case Type::ExternRef: + return Type::ExternRef; + + default: + return Type::Any; + } +} + TypeChecker::Label::Label(LabelType label_type, const TypeVector& param_types, const TypeVector& result_types, @@ -626,6 +644,39 @@ Result TypeChecker::PopAndCheck3Types(Type expected1, return result; } +Result TypeChecker::PopAndCheck4Types(Type expected1, + Type expected2, + Type expected3, + Type expected4, + const char* desc) { + Result result = Result::Ok; + result |= PeekAndCheckType(0, expected4); + result |= PeekAndCheckType(1, expected3); + result |= PeekAndCheckType(2, expected2); + result |= PeekAndCheckType(3, expected1); + PrintStackIfFailed(result, desc, expected1, expected2, expected3, expected4); + result |= DropTypes(4); + return result; +} + +Result TypeChecker::PopAndCheck5Types(Type expected1, + Type expected2, + Type expected3, + Type expected4, + Type expected5, + const char* desc) { + Result result = Result::Ok; + result |= PeekAndCheckType(0, expected5); + result |= PeekAndCheckType(1, expected4); + result |= PeekAndCheckType(2, expected3); + result |= PeekAndCheckType(3, expected2); + result |= PeekAndCheckType(4, expected1); + PrintStackIfFailed(result, desc, expected1, expected2, expected3, expected4, + expected5); + result |= DropTypes(5); + return result; +} + Result TypeChecker::PopAndCheckReference(Type* actual, const char* desc) { Result result = PeekType(0, actual); @@ -735,6 +786,148 @@ Result TypeChecker::BeginFunction(const TypeVector& sig) { return Result::Ok; } +Result TypeChecker::OnArrayCopy(Type dst_ref_type, + TypeMut& dst_array_type, + Type src_ref_type, + Type src_array_type) { + Result result = PopAndCheck5Types(dst_ref_type, Type::I32, src_ref_type, + Type::I32, Type::I32, "array.copy"); + if (!dst_array_type.mutable_) { + PrintError("array is immutable"); + result = Result::Error; + } + if (Failed(CheckType(src_array_type, dst_array_type.type))) { + PrintError("type mismatch: array types do not match"); + result = Result::Error; + } + return result; +} + +Result TypeChecker::OnArrayFill(Type ref_type, TypeMut& array_type) { + Result result = + PopAndCheck4Types(ref_type, Type::I32, ToUnpackedType(array_type.type), + Type::I32, "array.fill"); + if (!array_type.mutable_) { + PrintError("array is immutable"); + result = Result::Error; + } + return result; +} + +Result TypeChecker::OnArrayGet(Opcode opcode, Type ref_type, Type array_type) { + Result result = PopAndCheck2Types(ref_type, Type::I32, "array.get"); + bool is_packed_get = (opcode != Opcode::ArrayGet); + + if (array_type.IsPackedType() != is_packed_get) { + PrintError("array is %spacked", is_packed_get ? "not " : ""); + result = Result::Error; + } + + PushType(ToUnpackedType(array_type)); + return result; +} + +Result TypeChecker::OnArrayInitData(Type ref_type, TypeMut& array_type) { + Result result = PopAndCheck4Types(ref_type, Type::I32, Type::I32, Type::I32, + "array.init_data"); + if (!array_type.mutable_) { + PrintError("array is immutable"); + result = Result::Error; + } + if (array_type.type.IsRef()) { + PrintError("type mismatch: array type must be number or vector type"); + result = Result::Error; + } + return result; +} + +Result TypeChecker::OnArrayInitElem(Type ref_type, + TypeMut& array_type, + Type elem_type) { + Result result = PopAndCheck4Types(ref_type, Type::I32, Type::I32, Type::I32, + "array.init_elem"); + if (!array_type.mutable_) { + PrintError("array is immutable"); + result = Result::Error; + } + if (Failed(CheckType(elem_type, array_type.type))) { + PrintError("type mismatch: array type does not match to elem type"); + result = Result::Error; + } + return result; +} + +Result TypeChecker::OnArrayNew(Type ref_type, Type array_type) { + Result result = + PopAndCheck2Types(ToUnpackedType(array_type), Type::I32, "array.new"); + PushType(ToUnpackedType(ref_type)); + return result; +} + +Result TypeChecker::OnArrayNewData(Type ref_type, Type array_type) { + Result result = PopAndCheck2Types(Type::I32, Type::I32, "array.new_elem"); + if (array_type.IsRef()) { + PrintError("type mismatch: array type must be number or vector type"); + result = Result::Error; + } + PushType(ToUnpackedType(ref_type)); + return result; +} + +Result TypeChecker::OnArrayNewDefault(Type ref_type) { + Result result = PopAndCheck1Type(Type::I32, "array.new_default"); + PushType(ToUnpackedType(ref_type)); + return result; +} + +Result TypeChecker::OnArrayNewElem(Type ref_type, + Type array_type, + Type elem_type) { + Result result = PopAndCheck2Types(Type::I32, Type::I32, "array.new_elem"); + if (Failed(CheckType(elem_type, array_type))) { + PrintError("type mismatch: array type does not match to elem type"); + result |= Result::Error; + } + PushType(ToUnpackedType(ref_type)); + return result; +} + +Result TypeChecker::OnArrayNewFixed(Type ref_type, + Type array_type, + Index count) { + Result result = Result::Ok; + array_type = ToUnpackedType(array_type); + for (Index i = 0; i < count; ++i) { + result |= PeekAndCheckType(count - i - 1, array_type); + } + + if (Failed(result)) { + // To improve performance, type vector + // conversion is only done on error. + TypeVector types; + types.reserve(count); + + for (size_t i = 0; i < count; ++i) { + types.push_back(array_type); + } + PrintStackIfFailedV(result, "array.new_fixed", types, /*is_end=*/false); + } + + result |= DropTypes(count); + PushType(ref_type); + return result; +} + +Result TypeChecker::OnArraySet(Type ref_type, const TypeMut& field) { + Result result = PopAndCheck3Types(ref_type, Type::I32, + ToUnpackedType(field.type), "array.set"); + if (!field.mutable_) { + PrintError("array is immutable"); + result = Result::Error; + } + return result; +} + Result TypeChecker::OnAtomicLoad(Opcode opcode, const Limits& limits) { return CheckOpcode1(opcode, &limits); } @@ -793,6 +986,43 @@ Result TypeChecker::OnBrIf(Index depth) { return result; } +Result TypeChecker::OnBrOnCast(Opcode opcode, + Index depth, + Type type1, + Type type2) { + Type actual; + Result result = PopAndCheckReference(&actual, opcode.GetName()); + if (Failed(TypeChecker::CheckType(actual, type1))) { + PrintError("type mismatch: %s is not a subtype of %s", + actual.GetName().c_str(), type1.GetName().c_str()); + result = Result::Error; + } + + if (Failed(TypeChecker::CheckType(type2, type1))) { + PrintError("type mismatch: %s is not a subtype of %s", + type2.GetName().c_str(), type1.GetName().c_str()); + result = Result::Error; + } + + // The spec expects a type1 \ type2 subtraction operation. + // Currently this operation is applied only to the Null value. + if (type2.IsNullableRef()) { + type1.ConvertRefNullToRef(); + } + + PushType(opcode == Opcode::BrOnCast ? type2 : type1); + Label* label; + if (Succeeded(GetLabel(depth, &label))) { + result |= PopAndCheckSignature(label->br_types(), opcode.GetName()); + PushTypes(label->br_types()); + } else { + result = Result::Error; + } + result |= DropTypes(1); + PushType(opcode == Opcode::BrOnCast ? type1 : type2); + return result; +} + Result TypeChecker::OnBrOnNonNull(Index depth) { Type actual; CHECK_RESULT(PopAndCheckReference(&actual, "br_on_non_null")); @@ -1015,6 +1245,51 @@ Result TypeChecker::OnIf(const TypeVector& param_types, return result; } +Result TypeChecker::OnGCUnary(Opcode opcode) { + Result result; + switch (opcode) { + case Opcode::RefEq: { + result = PopAndCheck2Types(Type::EqRef, Type::EqRef, "ref.eq"); + PushType(Type::I32); + return result; + } + case Opcode::ArrayLen: + result = PopAndCheck1Type(Type::ArrayRef, "array.len"); + PushType(Type::I32); + return result; + case Opcode::AnyConvertExtern: { + Type type; + // Nullability must be copied. + PeekType(0, &type); + result = PopAndCheck1Type(Type::ExternRef, "any.convert_extern"); + PushType(Type(Type::AnyRef, !type.IsNonNullableRef())); + return result; + } + case Opcode::ExternConvertAny: { + Type type; + // Nullability must be copied. + PeekType(0, &type); + result = PopAndCheck1Type(Type::AnyRef, "any.convert_extern"); + PushType(Type(Type::ExternRef, !type.IsNonNullableRef())); + return result; + } + case Opcode::RefI31: { + result = PopAndCheck1Type(Type::I32, "ref.i31"); + PushType(Type(Type::I31Ref, Type::ReferenceNonNull)); + return result; + } + case Opcode::I31GetS: + case Opcode::I31GetU: { + result = PopAndCheck1Type( + Type::I31Ref, opcode == Opcode::I31GetS ? "i31.get_s" : "i31.get_u"); + PushType(Type::I32); + return result; + } + default: + WABT_UNREACHABLE; + } +} + Result TypeChecker::OnGlobalGet(Type type) { PushType(type); return Result::Ok; @@ -1142,8 +1417,39 @@ Result TypeChecker::OnRefAsNonNullExpr() { return Result::Ok; } +Result TypeChecker::OnRefCast(Type type) { + Result result = Result::Ok; + if (!type.IsRef()) { + PrintError("type mismatch: reference type expected"); + result = Result::Error; + } else { + Type expected = Type::Any; + result |= PeekType(0, &expected); + if (Succeeded(result)) { + if (!expected.IsRef()) { + PrintError("type mismatch: reference type expected, but got %s", + expected.GetName().c_str()); + result = Result::Error; + } else if (type != Type::NullRef && expected != Type::NullRef && + type_fields_.GetGroupType(type) != + type_fields_.GetGroupType(expected)) { + PrintError("type mismatch: %s is not a subtype of %s", + type.GetName().c_str(), expected.GetName().c_str()); + result = Result::Error; + } + } + } + DropTypes(1); + PushType(type); + return Result::Ok; +} + Result TypeChecker::OnRefFuncExpr(Index func_type) { - PushType(Type(Type::Ref, func_type)); + if (func_type == kInvalidIndex) { + PushType(Type(Type::FuncRef, Type::ReferenceNonNull)); + } else { + PushType(Type(Type::Ref, func_type)); + } return Result::Ok; } @@ -1163,6 +1469,33 @@ Result TypeChecker::OnRefIsNullExpr() { return result; } +Result TypeChecker::OnRefTest(Type type) { + Result result = Result::Ok; + if (!type.IsRef()) { + PrintError("type mismatch: reference type expected"); + result = Result::Error; + } else { + Type expected = Type::Any; + result |= PeekType(0, &expected); + if (Succeeded(result)) { + if (!expected.IsRef()) { + PrintError("type mismatch: reference type expected, but got %s", + expected.GetName().c_str()); + result = Result::Error; + } else if (type != Type::NullRef && expected != Type::NullRef && + type_fields_.GetGroupType(type) != + type_fields_.GetGroupType(expected)) { + PrintError("type mismatch: %s is not a subtype of %s", + type.GetName().c_str(), expected.GetName().c_str()); + result = Result::Error; + } + } + } + DropTypes(1); + PushType(Type::I32); + return Result::Ok; +} + Result TypeChecker::OnRethrow(Index depth) { Result result = Result::Ok; Label* label; @@ -1224,6 +1557,80 @@ Result TypeChecker::OnStore(Opcode opcode, const Limits& limits) { return CheckOpcode2(opcode, &limits); } +Result TypeChecker::OnStructGet(Opcode opcode, + Type ref_type, + const StructType& struct_type, + Index field) { + Result result = PopAndCheck1Type(ref_type, "struct.get"); + if (field >= struct_type.fields.size()) { + PrintError("unknown field: %" PRIindex, field); + result = Result::Error; + } else { + Type type = struct_type.fields[field].type; + bool is_packed_get = (opcode != Opcode::StructGet); + + if (type.IsPackedType() != is_packed_get) { + PrintError("field %" PRIindex " is %spacked", field, + is_packed_get ? "not " : ""); + result = Result::Error; + } + + PushType(ToUnpackedType(type)); + } + return result; +} + +Result TypeChecker::OnStructNew(Type ref_type, const StructType& struct_type) { + Result result = Result::Ok; + size_t size = struct_type.fields.size(); + + for (size_t i = 0; i < size; ++i) { + result |= PeekAndCheckType(size - i - 1, + ToUnpackedType(struct_type.fields[i].type)); + } + + if (Failed(result)) { + // To improve performance, type vector + // conversion is only done on error. + TypeVector types; + types.reserve(size); + + for (size_t i = 0; i < size; ++i) { + types.push_back(ToUnpackedType(struct_type.fields[i].type)); + } + PrintStackIfFailedV(result, "struct.new", types, /*is_end=*/false); + } + result |= DropTypes(size); + PushType(ref_type); + return result; +} + +Result TypeChecker::OnStructNewDefault(Type ref_type) { + PushType(ref_type); + return Result::Ok; +} + +Result TypeChecker::OnStructSet(Type ref_type, + const StructType& struct_type, + Index field) { + Result result = Result::Ok; + + if (field >= struct_type.fields.size() || + !struct_type.fields[field].mutable_) { + const char* message = field >= struct_type.fields.size() + ? "unknown field: %" PRIindex + : "field %" PRIindex " is immutable"; + PrintError(message, field); + DropTypes(1); + PopAndCheck1Type(ref_type, "struct.set"); + result = Result::Error; + } else { + Type expected_type = ToUnpackedType(struct_type.fields[field].type); + result |= PopAndCheck2Types(ref_type, expected_type, "struct.set"); + } + return result; +} + Result TypeChecker::OnTry(const TypeVector& param_types, const TypeVector& result_types) { Result result = PopAndCheckSignature(param_types, "try"); diff --git a/src/validator.cc b/src/validator.cc index 764fd84349..bf324a078e 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -98,6 +98,7 @@ class Validator : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnCastExpr(BrOnCastExpr*) override; Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; @@ -170,6 +171,24 @@ class Validator : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override; Result OnLoadSplatExpr(LoadSplatExpr*) override; Result OnLoadZeroExpr(LoadZeroExpr*) override; + Result OnArrayCopyExpr(ArrayCopyExpr*) override; + Result OnArrayFillExpr(ArrayFillExpr*) override; + Result OnArrayGetExpr(ArrayGetExpr*) override; + Result OnArrayInitDataExpr(ArrayInitDataExpr*) override; + Result OnArrayInitElemExpr(ArrayInitElemExpr*) override; + Result OnArrayNewExpr(ArrayNewExpr*) override; + Result OnArrayNewDataExpr(ArrayNewDataExpr*) override; + Result OnArrayNewDefaultExpr(ArrayNewDefaultExpr*) override; + Result OnArrayNewElemExpr(ArrayNewElemExpr*) override; + Result OnArrayNewFixedExpr(ArrayNewFixedExpr*) override; + Result OnArraySetExpr(ArraySetExpr*) override; + Result OnGCUnaryExpr(GCUnaryExpr*) override; + Result OnRefCastExpr(RefCastExpr*) override; + Result OnRefTestExpr(RefTestExpr*) override; + Result OnStructGetExpr(StructGetExpr*) override; + Result OnStructNewExpr(StructNewExpr*) override; + Result OnStructNewDefaultExpr(StructNewDefaultExpr*) override; + Result OnStructSetExpr(StructSetExpr*) override; private: Type GetDeclarationType(const FuncDeclaration&); @@ -203,38 +222,62 @@ static Result CheckType(Type actual, Type expected) { Type::Enum expected_type = expected; if (actual_type == expected_type) { - switch (actual_type) { - case Type::ExternRef: - case Type::FuncRef: - case Type::AnyRef: - case Type::EqRef: - case Type::I31Ref: - case Type::StructRef: - case Type::ArrayRef: - return (expected.IsNullableNonTypedRef() || - !actual.IsNullableNonTypedRef()) - ? Result::Ok - : Result::Error; - - case Type::Ref: - case Type::RefNull: - if (actual == expected) { - return Result::Ok; - } - break; + return Result::Ok; + } - default: - return Result::Ok; - } + if (!expected.IsRef() || !actual.IsRef()) { + return Result::Error; } - if (actual_type == Type::FuncRef && expected_type == Type::RefNull) { - // Specification tests pass expected functions - // directly, their type is not relevant. + if (actual.IsBottomRef()) { return Result::Ok; } - return Result::Error; + switch (expected_type) { + case Type::RefNull: + if (actual_type == Type::FuncRef) { + // Specification tests pass expected functions + // directly, their type is not relevant. + return Result::Ok; + } + return Result::Error; + case Type::Ref: + if (actual_type == Type::ArrayRef || actual_type == Type::EqRef || + actual_type == Type::StructRef) { + return Result::Ok; + } + return Result::Error; + case Type::NullFuncRef: + case Type::FuncRef: + if (actual_type == Type::FuncRef) { + break; + } + return Result::Error; + case Type::NullExternRef: + case Type::ExternRef: + if (actual_type == Type::ExternRef) { + break; + } + return Result::Error; + case Type::NullRef: + case Type::AnyRef: + if (actual_type == Type::EqRef) { + break; + } + [[fallthrough]]; + case Type::EqRef: + if (actual_type == Type::I31Ref || actual_type == Type::StructRef || + actual_type == Type::ArrayRef) { + break; + } + break; + default: + return Result::Error; + } + + return (expected.IsNullableNonTypedRef() || !actual.IsNullableNonTypedRef()) + ? Result::Ok + : Result::Error; } void ScriptValidator::CheckTypeIndex(const Location* loc, @@ -347,6 +390,12 @@ Result Validator::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result Validator::OnBrOnCastExpr(BrOnCastExpr* expr) { + result_ |= validator_.OnBrOnCast(expr->loc, expr->opcode, expr->label_var, + expr->type1_var, expr->type2_var); + return Result::Ok; +} + Result Validator::OnBrOnNonNullExpr(BrOnNonNullExpr* expr) { result_ |= validator_.OnBrOnNonNull(expr->loc, expr->var); return Result::Ok; @@ -750,6 +799,97 @@ Result Validator::OnLoadZeroExpr(LoadZeroExpr* expr) { return Result::Ok; } +Result Validator::OnArrayCopyExpr(ArrayCopyExpr* expr) { + result_ |= validator_.OnArrayCopy(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayFillExpr(ArrayFillExpr* expr) { + result_ |= validator_.OnArrayFill(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayGetExpr(ArrayGetExpr* expr) { + result_ |= validator_.OnArrayGet(expr->loc, expr->opcode, expr->type_var); + return Result::Ok; +} + +Result Validator::OnArrayInitDataExpr(ArrayInitDataExpr* expr) { + result_ |= validator_.OnArrayInitData(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayInitElemExpr(ArrayInitElemExpr* expr) { + result_ |= validator_.OnArrayInitElem(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayNewExpr(ArrayNewExpr* expr) { + result_ |= validator_.OnArrayNew(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayNewDataExpr(ArrayNewDataExpr* expr) { + result_ |= validator_.OnArrayNewData(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayNewDefaultExpr(ArrayNewDefaultExpr* expr) { + result_ |= validator_.OnArrayNewDefault(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayNewElemExpr(ArrayNewElemExpr* expr) { + result_ |= validator_.OnArrayNewElem(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + +Result Validator::OnArrayNewFixedExpr(ArrayNewFixedExpr* expr) { + result_ |= validator_.OnArrayNewFixed(expr->loc, expr->type_var, expr->count); + return Result::Ok; +} + +Result Validator::OnArraySetExpr(ArraySetExpr* expr) { + result_ |= validator_.OnArraySet(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnGCUnaryExpr(GCUnaryExpr* expr) { + result_ |= validator_.OnGCUnary(expr->loc, expr->opcode); + return Result::Ok; +} + +Result Validator::OnRefCastExpr(RefCastExpr* expr) { + result_ |= validator_.OnRefCast(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnRefTestExpr(RefTestExpr* expr) { + result_ |= validator_.OnRefTest(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnStructGetExpr(StructGetExpr* expr) { + result_ |= validator_.OnStructGet(expr->loc, expr->opcode, expr->type_var, + expr->var); + return Result::Ok; +} + +Result Validator::OnStructNewExpr(StructNewExpr* expr) { + result_ |= validator_.OnStructNew(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnStructNewDefaultExpr(StructNewDefaultExpr* expr) { + result_ |= validator_.OnStructNewDefault(expr->loc, expr->var); + return Result::Ok; +} + +Result Validator::OnStructSetExpr(StructSetExpr* expr) { + result_ |= validator_.OnStructSet(expr->loc, expr->type_var, expr->var); + return Result::Ok; +} + Validator::Validator(Errors* errors, const Module* module, const ValidateOptions& options) diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 3e94a6d8d5..d4d18b4e34 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -157,6 +157,7 @@ bool IsPlainInstr(TokenType token_type) { case TokenType::Select: case TokenType::Br: case TokenType::BrIf: + case TokenType::BrOnCast: case TokenType::BrOnNonNull: case TokenType::BrOnNull: case TokenType::BrTable: @@ -212,6 +213,30 @@ bool IsPlainInstr(TokenType token_type) { case TokenType::SimdLoadLane: case TokenType::SimdStoreLane: case TokenType::SimdShuffleOp: + case TokenType::ArrayCopy: + case TokenType::ArrayFill: + case TokenType::ArrayGet: + case TokenType::ArrayGetS: + case TokenType::ArrayGetU: + case TokenType::ArrayInitData: + case TokenType::ArrayInitElem: + case TokenType::ArrayNew: + case TokenType::ArrayNewData: + case TokenType::ArrayNewDefault: + case TokenType::ArrayNewFixed: + case TokenType::ArrayNewElem: + case TokenType::ArraySet: + case TokenType::GCUnary: + case TokenType::RefCast: + case TokenType::RefEq: + case TokenType::RefI31: + case TokenType::RefTest: + case TokenType::StructGet: + case TokenType::StructGetS: + case TokenType::StructGetU: + case TokenType::StructNew: + case TokenType::StructNewDefault: + case TokenType::StructSet: return true; default: return false; @@ -2402,6 +2427,16 @@ Result WastParser::ParsePlainInstrVar(Location loc, return Result::Ok; } +template +Result WastParser::ParsePlainInstrVarVar(Location loc, + std::unique_ptr* out_expr) { + Var first_var, second_var; + CHECK_RESULT(ParseVar(&first_var)); + CHECK_RESULT(ParseVar(&second_var)); + out_expr->reset(new T(first_var, second_var, loc)); + return Result::Ok; +} + template Result WastParser::ParseMemoryInstrVar(Location loc, std::unique_ptr* out_expr) { @@ -2575,6 +2610,18 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); break; + case TokenType::BrOnCast: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var label, type1, type2; + CHECK_RESULT(ParseVar(&label)); + CHECK_RESULT(ParseRefType(&type1)); + CHECK_RESULT(ParseRefType(&type2)); + out_expr->reset( + new BrOnCastExpr(token.opcode(), label, type1, type2, loc)); + break; + } + case TokenType::BrOnNonNull: Consume(); CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); @@ -2914,6 +2961,152 @@ Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { break; } + case TokenType::ArrayCopy: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + + case TokenType::ArrayFill: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::ArrayInitData: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + + case TokenType::ArrayInitElem: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + + case TokenType::ArrayGet: + case TokenType::ArrayGetS: + case TokenType::ArrayGetU: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var type; + CHECK_RESULT(ParseVar(&type)); + out_expr->reset(new ArrayGetExpr(token.opcode(), type, loc)); + break; + } + + case TokenType::ArrayNew: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::ArrayNewData: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + + case TokenType::ArrayNewDefault: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::ArrayNewFixed: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var type; + uint64_t count; + CHECK_RESULT(ParseVar(&type)); + CHECK_RESULT(ParseNat(&count, false)); + out_expr->reset( + new ArrayNewFixedExpr(type, static_cast(count), loc)); + break; + } + + case TokenType::ArrayNewElem: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + + case TokenType::ArraySet: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::GCUnary: + case TokenType::RefEq: + case TokenType::RefI31: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + out_expr->reset(new GCUnaryExpr(token.opcode(), loc)); + break; + } + + case TokenType::RefCast: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var type; + CHECK_RESULT(ParseRefType(&type)); + out_expr->reset(new RefCastExpr(type, loc)); + break; + } + + case TokenType::RefTest: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var type; + CHECK_RESULT(ParseRefType(&type)); + out_expr->reset(new RefTestExpr(type, loc)); + break; + } + + case TokenType::StructGet: + case TokenType::StructGetS: + case TokenType::StructGetU: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + Var type, field; + CHECK_RESULT(ParseVar(&type)); + CHECK_RESULT(ParseVar(&field)); + out_expr->reset(new StructGetExpr(token.opcode(), type, field, loc)); + break; + } + + case TokenType::StructNew: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::StructNewDefault: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + } + + case TokenType::StructSet: { + Token token = Consume(); + ErrorUnlessOpcodeEnabled(token); + CHECK_RESULT(ParsePlainInstrVarVar(loc, out_expr)); + break; + } + case TokenType::SimdLaneOp: { Token token = Consume(); ErrorUnlessOpcodeEnabled(token); @@ -3228,7 +3421,7 @@ Result WastParser::ParseExternref(Const* const_) { WABT_TRACE(ParseExternref); Token token = Consume(); if (!options_->features.reference_types_enabled()) { - Error(token.loc, "externref not allowed"); + Error(token.loc, "externref/hostref not allowed"); return Result::Error; } @@ -3237,24 +3430,35 @@ Result WastParser::ParseExternref(Const* const_) { const_->loc = GetLocation(); TokenType token_type = Peek(); + uint64_t ref_bits = Const::kRefAnyValueBits; + Result result = Result::Ok; + switch (token_type) { case TokenType::Nat: case TokenType::Int: { literal = Consume().literal(); sv = literal.text; + result = ParseInt64(sv, &ref_bits, ParseIntType::UnsignedOnly); break; } + case TokenType::Rpar: + break; default: return ErrorExpected({"a numeric literal"}, "123"); } - uint64_t ref_bits; - Result result = ParseInt64(sv, &ref_bits, ParseIntType::UnsignedOnly); - - if (ref_bits != 0 && options_->features.function_references_enabled()) { - const_->set_extern(static_cast(ref_bits)); + if (options_->features.function_references_enabled()) { + if (token.token_type() == TokenType::RefExtern) { + const_->set_extern(static_cast(ref_bits)); + } else { + const_->set_any(static_cast(ref_bits)); + } } else { - const_->set_externref(static_cast(ref_bits)); + if (token.token_type() == TokenType::RefExtern) { + const_->set_externref(static_cast(ref_bits)); + } else { + const_->set_anyref(static_cast(ref_bits)); + } } if (Failed(result)) { @@ -3269,9 +3473,13 @@ Result WastParser::ParseExternref(Const* const_) { Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { WABT_TRACE(ParseConstList); - while (PeekMatchLpar(TokenType::Const) || PeekMatchLpar(TokenType::RefNull) || - PeekMatchLpar(TokenType::RefExtern) || - PeekMatchLpar(TokenType::RefFunc)) { + while ( + PeekMatchLpar(TokenType::Const) || PeekMatchLpar(TokenType::RefNull) || + PeekMatchLpar(TokenType::RefArray) || PeekMatchLpar(TokenType::RefEq) || + PeekMatchLpar(TokenType::RefExtern) || + PeekMatchLpar(TokenType::RefHost) || PeekMatchLpar(TokenType::RefI31) || + PeekMatchLpar(TokenType::RefFunc) || + PeekMatchLpar(TokenType::RefStruct)) { Consume(); Const const_; switch (Peek()) { @@ -3280,13 +3488,58 @@ Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { break; case TokenType::RefNull: { auto token = Consume(); - Var type; + Type type = Type::BottomRef(); + if (Peek() != TokenType::Rpar) { - CHECK_RESULT(ParseRefKind(&type)); + Var var; + CHECK_RESULT(ParseRefKind(&var)); + type = var.opt_type(); + // Nulls are represented by "null" string. + if (type == Type::NullRef) { + type = Type::AnyRef; + } else if (type == Type::NullExternRef) { + type = Type::ExternRef; + } else if (type == Type::NullFuncRef) { + type = Type::FuncRef; + } } ErrorUnlessOpcodeEnabled(token); const_.loc = GetLocation(); - const_.set_null(type.has_opt_type() ? type.opt_type() : Type::FuncRef); + const_.set_null(type); + break; + } + case TokenType::RefArray: { + auto token = Consume(); + if (!options_->features.gc_enabled()) { + Error(token.loc, "ref.array not allowed"); + return Result::Error; + } + const_.loc = GetLocation(); + const_.set_arrayref(); + break; + } + case TokenType::RefEq: { + auto token = Consume(); + if (!options_->features.gc_enabled()) { + Error(token.loc, "ref.eq not allowed"); + return Result::Error; + } + const_.loc = GetLocation(); + const_.set_eqref(); + break; + } + case TokenType::RefExtern: + case TokenType::RefHost: + CHECK_RESULT(ParseExternref(&const_)); + break; + case TokenType::RefI31: { + auto token = Consume(); + if (!options_->features.gc_enabled()) { + Error(token.loc, "ref.i31 not allowed"); + return Result::Error; + } + const_.loc = GetLocation(); + const_.set_i31ref(); break; } case TokenType::RefFunc: { @@ -3296,9 +3549,16 @@ Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { const_.set_funcref(); break; } - case TokenType::RefExtern: - CHECK_RESULT(ParseExternref(&const_)); + case TokenType::RefStruct: { + auto token = Consume(); + if (!options_->features.gc_enabled()) { + Error(token.loc, "ref.struct not allowed"); + return Result::Error; + } + const_.loc = GetLocation(); + const_.set_structref(); break; + } default: assert(!"unreachable"); return Result::Error; diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 80a8948fdc..fc4b370c20 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -128,7 +128,7 @@ class WatWriter : ModuleContext { const Var& destmemidx, NextChar next_char); void WriteBrVar(const Var& var, NextChar next_char); - void WriteRefKind(Type type, NextChar next_char); + void WriteRef(const Var& var, NextChar next_char); void WriteType(Type type, NextChar next_char); void WriteTypes(const TypeVector& types, const char* name); void WriteFuncSigSpace(const FuncSignature& func_sig); @@ -419,8 +419,17 @@ void WatWriter::WriteBrVar(const Var& var, NextChar next_char) { } } -void WatWriter::WriteRefKind(Type type, NextChar next_char) { - WritePuts(type.GetRefKindName(), next_char); +void WatWriter::WriteRef(const Var& var, NextChar next_char) { + Type type = var.to_type(); + + if (!type.IsReferenceWithIndex()) { + WritePuts(type.GetName().c_str(), next_char); + return; + } + + WritePuts(type == Type::Ref ? "(ref" : "(ref null", NextChar::Space); + WriteVar(var, NextChar::None); + WritePuts(")", next_char); } void WatWriter::WriteType(Type type, NextChar next_char) { @@ -555,6 +564,7 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result EndBlockExpr(BlockExpr*) override; Result OnBrExpr(BrExpr*) override; Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrOnCastExpr(BrOnCastExpr*) override; Result OnBrOnNonNullExpr(BrOnNonNullExpr*) override; Result OnBrOnNullExpr(BrOnNullExpr*) override; Result OnBrTableExpr(BrTableExpr*) override; @@ -627,6 +637,24 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override; Result OnLoadSplatExpr(LoadSplatExpr*) override; Result OnLoadZeroExpr(LoadZeroExpr*) override; + Result OnArrayCopyExpr(ArrayCopyExpr*) override; + Result OnArrayFillExpr(ArrayFillExpr*) override; + Result OnArrayGetExpr(ArrayGetExpr*) override; + Result OnArrayInitDataExpr(ArrayInitDataExpr*) override; + Result OnArrayInitElemExpr(ArrayInitElemExpr*) override; + Result OnArrayNewExpr(ArrayNewExpr*) override; + Result OnArrayNewDataExpr(ArrayNewDataExpr*) override; + Result OnArrayNewDefaultExpr(ArrayNewDefaultExpr*) override; + Result OnArrayNewElemExpr(ArrayNewElemExpr*) override; + Result OnArrayNewFixedExpr(ArrayNewFixedExpr*) override; + Result OnArraySetExpr(ArraySetExpr*) override; + Result OnGCUnaryExpr(GCUnaryExpr*) override; + Result OnRefCastExpr(RefCastExpr*) override; + Result OnRefTestExpr(RefTestExpr*) override; + Result OnStructGetExpr(StructGetExpr*) override; + Result OnStructNewExpr(StructNewExpr*) override; + Result OnStructNewDefaultExpr(StructNewDefaultExpr*) override; + Result OnStructSetExpr(StructSetExpr*) override; private: WatWriter* writer_; @@ -660,6 +688,14 @@ Result WatWriter::ExprVisitorDelegate::OnBrIfExpr(BrIfExpr* expr) { return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnBrOnCastExpr(BrOnCastExpr* expr) { + writer_->WritePutsSpace(expr->opcode.GetName()); + writer_->WriteBrVar(expr->label_var, NextChar::Space); + writer_->WriteRef(expr->type1_var, NextChar::Space); + writer_->WriteRef(expr->type2_var, NextChar::Newline); + return Result::Ok; +} + Result WatWriter::ExprVisitorDelegate::OnBrOnNonNullExpr( BrOnNonNullExpr* expr) { writer_->WritePutsSpace(Opcode::BrOnNonNull_Opcode.GetName()); @@ -915,9 +951,11 @@ Result WatWriter::ExprVisitorDelegate::OnRefFuncExpr(RefFuncExpr* expr) { Result WatWriter::ExprVisitorDelegate::OnRefNullExpr(RefNullExpr* expr) { writer_->WritePutsSpace(Opcode::RefNull_Opcode.GetName()); - if (expr->type.opt_type() != Type::RefNull) { - assert(!Type(expr->type.opt_type()).IsReferenceWithIndex()); - writer_->WriteRefKind(expr->type.opt_type(), NextChar::Newline); + Type type = expr->type.to_type(); + + if (type != Type::RefNull) { + assert(!type.IsReferenceWithIndex()); + writer_->WritePuts(type.GetRefKindName(), NextChar::Newline); } else { writer_->WriteVar(expr->type, NextChar::Newline); } @@ -1193,6 +1231,128 @@ Result WatWriter::ExprVisitorDelegate::OnLoadZeroExpr(LoadZeroExpr* expr) { return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnArrayCopyExpr(ArrayCopyExpr* expr) { + writer_->WritePuts("array.copy", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayFillExpr(ArrayFillExpr* expr) { + writer_->WritePuts("array.fill", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayGetExpr(ArrayGetExpr* expr) { + writer_->WritePuts(expr->opcode.GetName(), NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayInitDataExpr( + ArrayInitDataExpr* expr) { + writer_->WritePuts("array.init_data", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayInitElemExpr( + ArrayInitElemExpr* expr) { + writer_->WritePuts("array.init_elem", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayNewExpr(ArrayNewExpr* expr) { + writer_->WritePuts("array.new", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayNewDataExpr( + ArrayNewDataExpr* expr) { + writer_->WritePuts("array.new_data", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayNewDefaultExpr( + ArrayNewDefaultExpr* expr) { + writer_->WritePuts("array.new_default", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayNewElemExpr( + ArrayNewElemExpr* expr) { + writer_->WritePuts("array.new_elem", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArrayNewFixedExpr( + ArrayNewFixedExpr* expr) { + writer_->WritePuts("array.new_fixed", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(Var(expr->count, Location()), NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnArraySetExpr(ArraySetExpr* expr) { + writer_->WritePuts("array.set", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnGCUnaryExpr(GCUnaryExpr* expr) { + writer_->WritePuts(expr->opcode.GetName(), NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnRefCastExpr(RefCastExpr* expr) { + writer_->WritePutsSpace("ref.cast"); + writer_->WriteRef(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnRefTestExpr(RefTestExpr* expr) { + writer_->WritePutsSpace("ref.test"); + writer_->WriteRef(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnStructGetExpr(StructGetExpr* expr) { + writer_->WritePuts(expr->opcode.GetName(), NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnStructNewExpr(StructNewExpr* expr) { + writer_->WritePuts("struct.new", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnStructNewDefaultExpr( + StructNewDefaultExpr* expr) { + writer_->WritePuts("struct.new_default", NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + +Result WatWriter::ExprVisitorDelegate::OnStructSetExpr(StructSetExpr* expr) { + writer_->WritePuts("struct.set", NextChar::Space); + writer_->WriteVar(expr->type_var, NextChar::Space); + writer_->WriteVar(expr->var, NextChar::Newline); + return Result::Ok; +} + void WatWriter::WriteExpr(const Expr* expr) { WABT_TRACE(WriteExprList); ExprVisitorDelegate delegate(this); diff --git a/test/spec/gc/array.txt b/test/spec/gc/array.txt new file mode 100644 index 0000000000..36018400d1 --- /dev/null +++ b/test/spec/gc/array.txt @@ -0,0 +1,37 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array.wast:28: assert_invalid passed: + out/test/spec/gc/array/array.1.wasm:000000f: error: reference 10 is out of range in params + 000000f: error: OnArrayType callback failed +out/test/spec/gc/array.wast:49: assert_invalid passed: + out/test/spec/gc/array/array.3.wasm:000000f: error: reference 1 is out of range in params + 000000f: error: OnArrayType callback failed +out/test/spec/gc/array.wast:53: assert_invalid passed: + out/test/spec/gc/array/array.4.wasm:000000f: error: reference 1 is out of range in params + 000000f: error: OnArrayType callback failed +out/test/spec/gc/array.wast:103: assert_trap passed: invalid index +out/test/spec/gc/array.wast:104: assert_trap passed: invalid index +out/test/spec/gc/array.wast:148: assert_trap passed: invalid index +out/test/spec/gc/array.wast:149: assert_trap passed: invalid index +out/test/spec/gc/array.wast:201: assert_trap passed: invalid index +out/test/spec/gc/array.wast:202: assert_trap passed: invalid index +out/test/spec/gc/array.wast:203: assert_trap passed: invalid index +out/test/spec/gc/array.wast:261: assert_trap passed: invalid index +out/test/spec/gc/array.wast:262: assert_trap passed: invalid index +out/test/spec/gc/array.wast:265: assert_invalid passed: + out/test/spec/gc/array/array.9.wasm:000003e: error: array is immutable + 000003e: error: OnArraySetExpr callback failed +out/test/spec/gc/array.wast:275: assert_invalid passed: + out/test/spec/gc/array/array.10.wasm:000001c: error: invalid initializer: instruction not valid in initializer expression: array.new_data + out/test/spec/gc/array/array.10.wasm:000001c: error: data_segment variable out of range: 0 (max 0) + 000001c: error: OnArrayNewDataExpr callback failed +out/test/spec/gc/array.wast:288: assert_invalid passed: + out/test/spec/gc/array/array.11.wasm:0000020: error: invalid initializer: instruction not valid in initializer expression: array.new_elem + out/test/spec/gc/array/array.11.wasm:0000020: error: elem_segment variable out of range: 0 (max 0) + 0000020: error: OnArrayNewElemExpr callback failed +out/test/spec/gc/array.wast:314: assert_trap passed: null array ref +out/test/spec/gc/array.wast:315: assert_trap passed: null array ref +46/46 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/array_copy.txt b/test/spec/gc/array_copy.txt new file mode 100644 index 0000000000..78031d25bd --- /dev/null +++ b/test/spec/gc/array_copy.txt @@ -0,0 +1,25 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_copy.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_copy.wast:6: assert_invalid passed: + out/test/spec/gc/array_copy/array_copy.0.wasm:0000049: error: array is immutable + 0000049: error: OnArrayCopyExpr callback failed +out/test/spec/gc/array_copy.wast:18: assert_invalid passed: + out/test/spec/gc/array_copy/array_copy.1.wasm:000004e: error: type mismatch: array types do not match + 000004e: error: OnArrayCopyExpr callback failed +out/test/spec/gc/array_copy.wast:30: assert_invalid passed: + out/test/spec/gc/array_copy/array_copy.2.wasm:000004e: error: type mismatch: array types do not match + 000004e: error: OnArrayCopyExpr callback failed +out/test/spec/gc/array_copy.wast:42: assert_invalid passed: + out/test/spec/gc/array_copy/array_copy.3.wasm:0000052: error: type mismatch: array types do not match + 0000052: error: OnArrayCopyExpr callback failed +out/test/spec/gc/array_copy.wast:97: assert_trap passed: null array ref +out/test/spec/gc/array_copy.wast:98: assert_trap passed: null array ref +out/test/spec/gc/array_copy.wast:101: assert_trap passed: invalid range +out/test/spec/gc/array_copy.wast:102: assert_trap passed: invalid range +out/test/spec/gc/array_copy.wast:105: assert_trap passed: invalid range +out/test/spec/gc/array_copy.wast:106: assert_trap passed: invalid range +out/test/spec/gc/array_copy.wast:116: assert_trap passed: invalid index +35/35 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/array_fill.txt b/test/spec/gc/array_fill.txt new file mode 100644 index 0000000000..04e7b69a26 --- /dev/null +++ b/test/spec/gc/array_fill.txt @@ -0,0 +1,19 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_fill.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_fill.wast:6: assert_invalid passed: + out/test/spec/gc/array_fill/array_fill.0.wasm:0000042: error: array is immutable + 0000042: error: OnArrayFillExpr callback failed +out/test/spec/gc/array_fill.wast:17: assert_invalid passed: + out/test/spec/gc/array_fill/array_fill.1.wasm:0000042: error: type mismatch in array.fill, expected [(ref null 0), i32, i32, i32] but got [(ref 0), i32, funcref, i32] + 0000042: error: OnArrayFillExpr callback failed +out/test/spec/gc/array_fill.wast:28: assert_invalid passed: + out/test/spec/gc/array_fill/array_fill.2.wasm:0000042: error: type mismatch in array.fill, expected [(ref null 0), i32, funcref, i32] but got [(ref 0), i32, i32, i32] + 0000042: error: OnArrayFillExpr callback failed +out/test/spec/gc/array_fill.wast:59: assert_trap passed: null array ref +out/test/spec/gc/array_fill.wast:62: assert_trap passed: invalid range +out/test/spec/gc/array_fill.wast:65: assert_trap passed: invalid range +out/test/spec/gc/array_fill.wast:74: assert_trap passed: invalid index +17/17 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/array_init_data.txt b/test/spec/gc/array_init_data.txt new file mode 100644 index 0000000000..f77c70d3f8 --- /dev/null +++ b/test/spec/gc/array_init_data.txt @@ -0,0 +1,23 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_init_data.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_init_data.wast:6: assert_invalid passed: + out/test/spec/gc/array_init_data/array_init_data.0.wasm:0000047: error: data_segment variable out of range: 0 (max 0) + out/test/spec/gc/array_init_data/array_init_data.0.wasm:0000047: error: array is immutable + 0000047: error: OnArrayInitDataExpr callback failed +out/test/spec/gc/array_init_data.wast:19: assert_invalid passed: + out/test/spec/gc/array_init_data/array_init_data.1.wasm:0000047: error: data_segment variable out of range: 0 (max 0) + out/test/spec/gc/array_init_data/array_init_data.1.wasm:0000047: error: type mismatch: array type must be number or vector type + 0000047: error: OnArrayInitDataExpr callback failed +out/test/spec/gc/array_init_data.wast:68: assert_trap passed: null array ref +out/test/spec/gc/array_init_data.wast:71: assert_trap passed: invalid range +out/test/spec/gc/array_init_data.wast:72: assert_trap passed: invalid range +out/test/spec/gc/array_init_data.wast:75: assert_trap passed: invalid range +out/test/spec/gc/array_init_data.wast:76: assert_trap passed: invalid range +out/test/spec/gc/array_init_data.wast:77: assert_trap passed: invalid range +out/test/spec/gc/array_init_data.wast:88: assert_trap passed: invalid index +out/test/spec/gc/array_init_data.wast:92: assert_trap passed: invalid index +out/test/spec/gc/array_init_data.wast:110: assert_trap passed: invalid range +33/33 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/array_init_elem.txt b/test/spec/gc/array_init_elem.txt new file mode 100644 index 0000000000..009a2efc9f --- /dev/null +++ b/test/spec/gc/array_init_elem.txt @@ -0,0 +1,27 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_init_elem.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_init_elem.wast:6: assert_invalid passed: + out/test/spec/gc/array_init_elem/array_init_elem.0.wasm:000004d: error: array is immutable + 000004d: error: OnArrayInitElemExpr callback failed +out/test/spec/gc/array_init_elem.wast:19: assert_invalid passed: + out/test/spec/gc/array_init_elem/array_init_elem.1.wasm:000004d: error: type mismatch: array type does not match to elem type + 000004d: error: OnArrayInitElemExpr callback failed +out/test/spec/gc/array_init_elem.wast:32: assert_invalid passed: + out/test/spec/gc/array_init_elem/array_init_elem.2.wasm:000004d: error: type mismatch: array type does not match to elem type + 000004d: error: OnArrayInitElemExpr callback failed +out/test/spec/gc/array_init_elem.wast:78: assert_trap passed: null array ref +out/test/spec/gc/array_init_elem.wast:81: assert_trap passed: invalid range +out/test/spec/gc/array_init_elem.wast:82: assert_trap passed: invalid range +out/test/spec/gc/array_init_elem.wast:85: assert_trap passed: invalid range +out/test/spec/gc/array_init_elem.wast:86: assert_trap passed: invalid range +out/test/spec/gc/array_init_elem.wast:93: assert_trap passed: uninitialized table element +out/test/spec/gc/array_init_elem.wast:94: assert_trap passed: uninitialized table element +out/test/spec/gc/array_init_elem.wast:95: assert_trap passed: uninitialized table element +out/test/spec/gc/array_init_elem.wast:96: assert_trap passed: invalid index +out/test/spec/gc/array_init_elem.wast:100: assert_trap passed: uninitialized table element +out/test/spec/gc/array_init_elem.wast:103: assert_trap passed: uninitialized table element +out/test/spec/gc/array_init_elem.wast:108: assert_trap passed: invalid range +23/23 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_on_cast.txt b/test/spec/gc/br_on_cast.txt new file mode 100644 index 0000000000..458bdbcc8b --- /dev/null +++ b/test/spec/gc/br_on_cast.txt @@ -0,0 +1,27 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_on_cast.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +test-sub() => +test-canon() => +out/test/spec/gc/br_on_cast.wast:226: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.3.wasm:0000028: error: type mismatch in br_on_cast, expected [(ref 0)] but got [(ref null 0)] + 0000028: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast.wast:235: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.4.wasm:0000028: error: type mismatch: (ref null 0) is not a subtype of (ref any) + 0000028: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast.wast:244: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.5.wasm:0000028: error: type mismatch in block, expected [(ref any)] but got [anyref] + 0000028: error: OnEndExpr callback failed +out/test/spec/gc/br_on_cast.wast:253: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.6.wasm:000001f: error: type mismatch: anyref is not a subtype of eqref + 000001f: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast.wast:261: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.7.wasm:000001f: error: type mismatch: arrayref is not a subtype of structref + 000001f: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast.wast:272: assert_invalid passed: + out/test/spec/gc/br_on_cast/br_on_cast.8.wasm:0000036: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 0000036: error: OnCallExpr callback failed +37/37 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_on_cast_fail.txt b/test/spec/gc/br_on_cast_fail.txt new file mode 100644 index 0000000000..dc274cac2c --- /dev/null +++ b/test/spec/gc/br_on_cast_fail.txt @@ -0,0 +1,27 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_on_cast_fail.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +test-sub() => +test-canon() => +out/test/spec/gc/br_on_cast_fail.wast:241: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.3.wasm:0000029: error: type mismatch in block, expected [(ref 0)] but got [(ref null 0)] + 0000029: error: OnEndExpr callback failed +out/test/spec/gc/br_on_cast_fail.wast:250: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.4.wasm:0000028: error: type mismatch: (ref null 0) is not a subtype of (ref any) + 0000028: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast_fail.wast:259: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.5.wasm:0000027: error: type mismatch in br_on_cast_fail, expected [(ref any)] but got [anyref] + 0000027: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast_fail.wast:268: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.6.wasm:000001f: error: type mismatch: anyref is not a subtype of eqref + 000001f: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast_fail.wast:276: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.7.wasm:000001f: error: type mismatch: arrayref is not a subtype of structref + 000001f: error: OnBrOnCastExpr callback failed +out/test/spec/gc/br_on_cast_fail.wast:287: assert_invalid passed: + out/test/spec/gc/br_on_cast_fail/br_on_cast_fail.8.wasm:0000036: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 0000036: error: OnCallExpr callback failed +37/37 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/extern.txt b/test/spec/gc/extern.txt new file mode 100644 index 0000000000..ab5a82aba9 --- /dev/null +++ b/test/spec/gc/extern.txt @@ -0,0 +1,7 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/extern.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +18/18 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/i31.txt b/test/spec/gc/i31.txt new file mode 100644 index 0000000000..2d54197549 --- /dev/null +++ b/test/spec/gc/i31.txt @@ -0,0 +1,16 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/i31.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/i31.wast:53: assert_trap passed: null i31 ref +out/test/spec/gc/i31.wast:54: assert_trap passed: null i31 ref +set_global(i32:1234) => +fill(i32:2, i32:111, i32:2) => +copy(i32:3, i32:0, i32:2) => +init(i32:1, i32:0, i32:3) => +set_global(i32:0) => +fill(i32:2, i32:111, i32:2) => +copy(i32:3, i32:0, i32:2) => +init(i32:1, i32:0, i32:3) => +72/72 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_cast.txt b/test/spec/gc/ref_cast.txt new file mode 100644 index 0000000000..a072895e28 --- /dev/null +++ b/test/spec/gc/ref_cast.txt @@ -0,0 +1,38 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_cast.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +out/test/spec/gc/ref_cast.wast:51: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:56: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:57: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:58: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:61: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:62: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:63: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:64: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:69: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:71: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:72: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:73: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:74: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:75: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:76: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:78: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:79: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:81: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:82: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:83: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:84: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:85: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:87: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:88: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:89: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:91: assert_trap passed: type error: invalid type cast +out/test/spec/gc/ref_cast.wast:92: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:93: assert_trap passed: null reference +out/test/spec/gc/ref_cast.wast:94: assert_trap passed: null reference +test-sub() => +test-canon() => +45/45 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_eq.txt b/test/spec/gc/ref_eq.txt new file mode 100644 index 0000000000..40ad7b0c2c --- /dev/null +++ b/test/spec/gc/ref_eq.txt @@ -0,0 +1,25 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_eq.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init() => +out/test/spec/gc/ref_eq.wast:122: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.1.wasm:0000027: error: type mismatch in ref.eq, expected [eqref, eqref] but got [(ref any), (ref any)] + 0000027: error: OnGCUnaryExpr callback failed +out/test/spec/gc/ref_eq.wast:130: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.2.wasm:0000026: error: type mismatch in ref.eq, expected [eqref, eqref] but got [anyref, anyref] + 0000026: error: OnGCUnaryExpr callback failed +out/test/spec/gc/ref_eq.wast:138: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.3.wasm:0000027: error: type mismatch in ref.eq, expected [eqref, eqref] but got [(ref func), (ref func)] + 0000027: error: OnGCUnaryExpr callback failed +out/test/spec/gc/ref_eq.wast:146: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.4.wasm:0000026: error: type mismatch in ref.eq, expected [eqref, eqref] but got [funcref, funcref] + 0000026: error: OnGCUnaryExpr callback failed +out/test/spec/gc/ref_eq.wast:154: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.5.wasm:0000027: error: type mismatch in ref.eq, expected [eqref, eqref] but got [(ref extern), (ref extern)] + 0000027: error: OnGCUnaryExpr callback failed +out/test/spec/gc/ref_eq.wast:162: assert_invalid passed: + out/test/spec/gc/ref_eq/ref_eq.6.wasm:0000026: error: type mismatch in ref.eq, expected [eqref, eqref] but got [externref, externref] + 0000026: error: OnGCUnaryExpr callback failed +89/89 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_null.txt b/test/spec/gc/ref_null.txt new file mode 100644 index 0000000000..f6f8c66206 --- /dev/null +++ b/test/spec/gc/ref_null.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_null.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +26/26 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_test.txt b/test/spec/gc/ref_test.txt new file mode 100644 index 0000000000..4e5cf25cff --- /dev/null +++ b/test/spec/gc/ref_test.txt @@ -0,0 +1,7 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_test.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +71/71 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/struct.txt b/test/spec/gc/struct.txt new file mode 100644 index 0000000000..ace65db194 --- /dev/null +++ b/test/spec/gc/struct.txt @@ -0,0 +1,22 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/struct.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/struct.wast:16: assert_malformed passed: + 0:0: error: duplicate field $x +out/test/spec/gc/struct.wast:37: assert_invalid passed: + out/test/spec/gc/struct/struct.3.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnStructType callback failed +out/test/spec/gc/struct.wast:41: assert_invalid passed: + out/test/spec/gc/struct/struct.4.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnStructType callback failed +out/test/spec/gc/struct.wast:59: assert_invalid passed: + out/test/spec/gc/struct/struct.6.wasm:0000029: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000029: error: EndFunctionBody callback failed +out/test/spec/gc/struct.wast:133: assert_invalid passed: + out/test/spec/gc/struct/struct.8.wasm:000003f: error: field 0 is immutable + 000003f: error: OnStructSetExpr callback failed +out/test/spec/gc/struct.wast:155: assert_trap passed: null struct ref +out/test/spec/gc/struct.wast:156: assert_trap passed: null struct ref +30/30 tests passed. +;;; STDOUT ;;) From 1917fb3531f06f8d74e95250d784bf4a1379982f Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Wed, 25 Jun 2025 03:53:22 +0000 Subject: [PATCH 6/6] Support all gc tests --- include/wabt/interp/interp.h | 1 + include/wabt/shared-validator.h | 5 +- src/binary-writer-spec.cc | 5 + src/interp/binary-reader-interp.cc | 9 +- src/interp/interp.cc | 32 +- src/shared-validator.cc | 26 +- src/tools/spectest-interp.cc | 2 + src/validator.cc | 3 +- test/spec/call_indirect.txt | 1 - test/spec/gc/array_new_data.txt | 10 + test/spec/gc/array_new_elem.txt | 14 + test/spec/gc/binary-gc.txt | 8 + test/spec/gc/binary.txt | 238 +++++++++++++++ test/spec/gc/br_if.txt | 98 ++++++ test/spec/gc/br_on_non_null.txt | 10 + test/spec/gc/br_on_null.txt | 10 + test/spec/gc/br_table.txt | 78 +++++ test/spec/gc/call_ref.txt | 22 ++ test/spec/gc/data.txt | 66 +++++ test/spec/gc/elem.txt | 90 ++++++ test/spec/gc/func.txt | 257 ++++++++++++++++ test/spec/gc/global.txt | 147 +++++++++ test/spec/gc/if.txt | 409 ++++++++++++++++++++++++++ test/spec/gc/linking.txt | 110 +++++++ test/spec/gc/local_get.txt | 54 ++++ test/spec/gc/local_init.txt | 18 ++ test/spec/gc/local_tee.txt | 132 +++++++++ test/spec/gc/ref.txt | 43 +++ test/spec/gc/ref_as_non_null.txt | 11 + test/spec/gc/ref_is_null.txt | 14 + test/spec/gc/return_call.txt | 39 +++ test/spec/gc/return_call_indirect.txt | 124 ++++++++ test/spec/gc/return_call_ref.txt | 44 +++ test/spec/gc/select.txt | 102 +++++++ test/spec/gc/table.txt | 75 +++++ test/spec/gc/type-subtyping.txt | 82 ++++++ test/spec/memory64/call_indirect.txt | 1 - 37 files changed, 2367 insertions(+), 23 deletions(-) create mode 100644 test/spec/gc/array_new_data.txt create mode 100644 test/spec/gc/array_new_elem.txt create mode 100644 test/spec/gc/binary-gc.txt create mode 100644 test/spec/gc/binary.txt create mode 100644 test/spec/gc/br_if.txt create mode 100644 test/spec/gc/br_on_non_null.txt create mode 100644 test/spec/gc/br_on_null.txt create mode 100644 test/spec/gc/br_table.txt create mode 100644 test/spec/gc/call_ref.txt create mode 100644 test/spec/gc/data.txt create mode 100644 test/spec/gc/elem.txt create mode 100644 test/spec/gc/func.txt create mode 100644 test/spec/gc/global.txt create mode 100644 test/spec/gc/if.txt create mode 100644 test/spec/gc/linking.txt create mode 100644 test/spec/gc/local_get.txt create mode 100644 test/spec/gc/local_init.txt create mode 100644 test/spec/gc/local_tee.txt create mode 100644 test/spec/gc/ref.txt create mode 100644 test/spec/gc/ref_as_non_null.txt create mode 100644 test/spec/gc/ref_is_null.txt create mode 100644 test/spec/gc/return_call.txt create mode 100644 test/spec/gc/return_call_indirect.txt create mode 100644 test/spec/gc/return_call_ref.txt create mode 100644 test/spec/gc/select.txt create mode 100644 test/spec/gc/table.txt create mode 100644 test/spec/gc/type-subtyping.txt diff --git a/include/wabt/interp/interp.h b/include/wabt/interp/interp.h index 7828969cd9..fbcffe3e90 100644 --- a/include/wabt/interp/interp.h +++ b/include/wabt/interp/interp.h @@ -1237,6 +1237,7 @@ class Thread { void Push(Ref); bool CheckRefCast(Ref ref, Type expected); + bool CheckRefFunc(Ref ref, Index expected_index, Func* new_func); template using UnopFunc = R WABT_VECTORCALL(T); diff --git a/include/wabt/shared-validator.h b/include/wabt/shared-validator.h index c4ad8ac7e4..8b60fc531e 100644 --- a/include/wabt/shared-validator.h +++ b/include/wabt/shared-validator.h @@ -92,7 +92,8 @@ class SharedValidator { Result OnTable(const Location&, Type elem_type, const Limits&, bool, bool); Result OnMemory(const Location&, const Limits&, uint32_t page_size); Result OnGlobalImport(const Location&, Type type, bool mutable_); - Result OnGlobal(const Location&, Type type, bool mutable_); + Result BeginGlobal(const Location&, Type type, bool mutable_); + Result EndGlobal(const Location&); Result OnTag(const Location&, Var sig_var); Result OnExport(const Location&, @@ -383,7 +384,7 @@ class SharedValidator { std::vector tags_; // Includes imported and defined. std::vector elems_; Index starts_ = 0; - Index num_imported_globals_ = 0; + Index last_initialized_global_ = 0; Index data_segments_ = 0; Index last_rec_type_end_ = 0; // Recursive type checks may enter to infinite loop for invalid values. diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc index 0cb9aadc65..9f9607e5de 100644 --- a/src/binary-writer-spec.cc +++ b/src/binary-writer-spec.cc @@ -161,6 +161,10 @@ void BinaryWriterSpec::WriteVar(const Var& var) { void BinaryWriterSpec::WriteTypeObject(Type type) { json_stream_->Writef("{"); WriteKey("type"); + if (type.IsReferenceWithIndex()) { + // This should happen only for invalid modules. + type = Type::AnyRef; + } WriteString(type.GetName().c_str()); json_stream_->Writef("}"); } @@ -284,6 +288,7 @@ void BinaryWriterSpec::WriteConst(const Const& const_) { break; } + case Type::NullFuncRef: case Type::FuncRef: { WriteString("funcref"); WriteSeparator(); diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 764faca22c..69afd6d787 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -805,7 +805,7 @@ Result BinaryReaderInterp::OnGlobalCount(Index count) { } Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) { - CHECK_RESULT(validator_.OnGlobal(GetLocation(), type, mutable_)); + CHECK_RESULT(validator_.BeginGlobal(GetLocation(), type, mutable_)); GlobalType global_type{type, ToMutability(mutable_)}; FuncDesc init_func{FuncType{{}, {type}}, {}, Istream::kInvalidOffset, {}}; module_.globals.push_back(GlobalDesc{global_type, init_func}); @@ -838,6 +838,7 @@ Result BinaryReaderInterp::BeginInitExpr(FuncDesc* func) { } Result BinaryReaderInterp::EndGlobalInitExpr(Index index) { + CHECK_RESULT(validator_.EndGlobal(GetLocation())); return EndInitExpr(); } @@ -1464,7 +1465,8 @@ Result BinaryReaderInterp::OnCallIndirectExpr(Index sig_index, CHECK_RESULT(validator_.OnCallIndirect(GetLocation(), Var(sig_index, GetLocation()), Var(table_index, GetLocation()))); - istream_.Emit(Opcode::CallIndirect, table_index, sig_index); + istream_.Emit(Opcode::CallIndirect, table_index, + module_.func_types[sig_index].canonical_index); return Result::Ok; } @@ -1529,7 +1531,8 @@ Result BinaryReaderInterp::OnReturnCallIndirectExpr(Index sig_index, Var(table_index, GetLocation()))); istream_.EmitDropKeep(drop_count, keep_count); istream_.EmitCatchDrop(catch_drop_count); - istream_.Emit(Opcode::ReturnCallIndirect, table_index, sig_index); + istream_.Emit(Opcode::ReturnCallIndirect, table_index, + module_.func_types[sig_index].canonical_index); return Result::Ok; } diff --git a/src/interp/interp.cc b/src/interp/interp.cc index 7c6e5e0533..e251480aef 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -1598,6 +1598,31 @@ bool Thread::CheckRefCast(Ref ref, Type expected) { return false; } +bool Thread::CheckRefFunc(Ref ref, Index expected_type_index, Func* new_func) { + // Validator checks that the table contains funcrefs. + assert(!ref.IsI31OrHostVal()); + Object* object = store_.UnsafeGet(ref).get(); + assert(Func::classof(object)); + + const FuncType& type = cast(object)->type(); + if (type.func_types != &mod_->desc().func_types) { + auto&& func_type = mod_->desc().func_types[expected_type_index]; + return Succeeded(Match(new_func->type(), func_type, nullptr)); + } + Index actual_type_index = type.canonical_index; + + do { + if (expected_type_index == actual_type_index) { + return true; + } + + actual_type_index = + mod_->desc().func_types[actual_type_index].canonical_sub_index; + } while (actual_type_index != kInvalidIndex); + + return false; +} + RunResult Thread::StepInternal(Trap::Ptr* out_trap) { using O = Opcode; @@ -1668,15 +1693,14 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { case O::CallIndirect: case O::ReturnCallIndirect: { Table::Ptr table{store_, inst_->tables()[instr.imm_u32x2.fst]}; - auto&& func_type = mod_->desc().func_types[instr.imm_u32x2.snd]; u64 entry = PopPtr(table); TRAP_IF(entry >= table->elements().size(), "undefined table index"); auto new_func_ref = table->elements()[entry]; TRAP_IF(new_func_ref == Ref::Null, "uninitialized table element"); Func::Ptr new_func{store_, new_func_ref}; - TRAP_IF( - Failed(Match(new_func->type(), func_type, nullptr)), - "indirect call signature mismatch"); // TODO: don't use "signature" + // TODO: don't use "signature" + TRAP_IF(!CheckRefFunc(new_func_ref, instr.imm_u32x2.snd, new_func.get()), + "indirect call signature mismatch"); if (instr.op == O::ReturnCallIndirect) { return DoReturnCall(new_func, out_trap); } else { diff --git a/src/shared-validator.cc b/src/shared-validator.cc index efba7c9be6..a9f68fd64d 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -85,8 +85,8 @@ Result SharedValidator::OnFuncType(const Location& loc, } type_validation_result_ |= result; - result |= CheckGCTypeExtension(loc, gc_ext); } + result |= CheckGCTypeExtension(loc, gc_ext); return result; } @@ -229,19 +229,26 @@ Result SharedValidator::OnGlobalImport(const Location& loc, result |= PrintError(loc, "mutable globals cannot be imported"); } globals_.push_back(GlobalType{type, mutable_}); - ++num_imported_globals_; + ++last_initialized_global_; return result; } -Result SharedValidator::OnGlobal(const Location& loc, - Type type, - bool mutable_) { +Result SharedValidator::BeginGlobal(const Location& loc, + Type type, + bool mutable_) { CHECK_RESULT( CheckReferenceType(loc, type, type_fields_.NumTypes(), "globals")); globals_.push_back(GlobalType{type, mutable_}); return Result::Ok; } +Result SharedValidator::EndGlobal(const Location&) { + if (options_.features.gc_enabled()) { + last_initialized_global_++; + } + return Result::Ok; +} + Result SharedValidator::CheckType(const Location& loc, Type actual, Type expected, @@ -268,8 +275,6 @@ Result SharedValidator::CheckReferenceType(const Location& loc, Result SharedValidator::CheckGCTypeExtension(const Location& loc, GCTypeExtension* gc_ext) { - assert(options_.features.function_references_enabled()); - TypeEntry& entry = type_fields_.type_entries.back(); Index current_index = type_fields_.NumTypes() - 1; Index end_index; @@ -778,8 +783,7 @@ Index SharedValidator::GetCanonicalTypeIndex(Index type_index) { return kInvalidIndex; } - if (options_.features.function_references_enabled() && - Succeeded(type_validation_result_)) { + if (Succeeded(type_validation_result_)) { return type_fields_.type_entries[type_index].canonical_index; } @@ -1190,7 +1194,7 @@ Result SharedValidator::OnCallIndirect(const Location& loc, TableType table_type; result |= CheckFuncTypeIndex(sig_var, &func_type); result |= CheckTableIndex(table_var, &table_type); - if (table_type.element != Type::FuncRef) { + if (Failed(typechecker_.CheckType(table_type.element, Type::FuncRef))) { result |= PrintError( loc, "type mismatch: call_indirect must reference table of funcref type"); @@ -1299,7 +1303,7 @@ Result SharedValidator::OnGlobalGet(const Location& loc, Var global_var) { result |= CheckGlobalIndex(global_var, &global_type); result |= typechecker_.OnGlobalGet(global_type.type); if (Succeeded(result) && in_init_expr_) { - if (global_var.index() >= num_imported_globals_) { + if (global_var.index() >= last_initialized_global_) { result |= PrintError( global_var.loc, "initializer expression can only reference an imported global"); diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index a4a4b7e405..6989501f6d 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -2003,6 +2003,8 @@ wabt::Result CommandRunner::CheckAssertReturnResult( ok = obj->kind() == ObjectKind::Array || obj->kind() == ObjectKind::Struct; } + } else { + ok = expected.value.type == Type::AnyRef; } break; } diff --git a/src/validator.cc b/src/validator.cc index bf324a078e..758213e2c2 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -1068,7 +1068,7 @@ Result Validator::CheckModule() { for (const ModuleField& field : module->fields) { if (auto* f = dyn_cast(&field)) { result_ |= - validator_.OnGlobal(field.loc, f->global.type, f->global.mutable_); + validator_.BeginGlobal(field.loc, f->global.type, f->global.mutable_); // Init expr. result_ |= validator_.BeginInitExpr(field.loc, f->global.type); @@ -1076,6 +1076,7 @@ Result Validator::CheckModule() { result_ |= visitor.VisitExprList(const_cast(f->global.init_expr)); result_ |= validator_.EndInitExpr(); + result_ |= validator_.EndGlobal(field.loc); } } diff --git a/test/spec/call_indirect.txt b/test/spec/call_indirect.txt index b4b2d55f28..ca1f3940d8 100644 --- a/test/spec/call_indirect.txt +++ b/test/spec/call_indirect.txt @@ -86,7 +86,6 @@ out/test/spec/call_indirect.wast:776: assert_malformed passed: ^^^^^^^^^^^^^ out/test/spec/call_indirect.wast:791: assert_invalid passed: out/test/spec/call_indirect/call_indirect.13.wasm:000001c: error: table variable out of range: 0 (max 0) - out/test/spec/call_indirect/call_indirect.13.wasm:000001c: error: type mismatch: call_indirect must reference table of funcref type 000001c: error: OnCallIndirectExpr callback failed out/test/spec/call_indirect.wast:799: assert_invalid passed: out/test/spec/call_indirect/call_indirect.14.wasm:0000023: error: type mismatch in i32.eqz, expected [i32] but got [] diff --git a/test/spec/gc/array_new_data.txt b/test/spec/gc/array_new_data.txt new file mode 100644 index 0000000000..8f20e52f36 --- /dev/null +++ b/test/spec/gc/array_new_data.txt @@ -0,0 +1,10 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_new_data.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_new_data.wast:18: assert_trap passed: invalid range +out/test/spec/gc/array_new_data.wast:19: assert_trap passed: invalid range +out/test/spec/gc/array_new_data.wast:20: assert_trap passed: invalid range +out/test/spec/gc/array_new_data.wast:21: assert_trap passed: invalid range +15/15 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/array_new_elem.txt b/test/spec/gc/array_new_elem.txt new file mode 100644 index 0000000000..ed0e4b64bd --- /dev/null +++ b/test/spec/gc/array_new_elem.txt @@ -0,0 +1,14 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/array_new_elem.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/array_new_elem.wast:24: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:25: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:26: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:27: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:72: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:73: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:74: assert_trap passed: invalid range +out/test/spec/gc/array_new_elem.wast:75: assert_trap passed: invalid range +22/22 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/binary-gc.txt b/test/spec/gc/binary-gc.txt new file mode 100644 index 0000000000..09957c3247 --- /dev/null +++ b/test/spec/gc/binary-gc.txt @@ -0,0 +1,8 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/binary-gc.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/binary-gc.wast:2: assert_malformed passed: + 000000e: error: field mutability must be 0 or 1 +1/1 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/binary.txt b/test/spec/gc/binary.txt new file mode 100644 index 0000000000..ca4c175b45 --- /dev/null +++ b/test/spec/gc/binary.txt @@ -0,0 +1,238 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/binary.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/binary.wast:6: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/gc/binary.wast:7: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/gc/binary.wast:8: assert_malformed passed: + 0000000: error: unable to read uint32_t: magic +out/test/spec/gc/binary.wast:9: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:10: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:11: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:12: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:13: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:14: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:15: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:16: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:17: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:18: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:21: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:24: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:25: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:28: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:31: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:34: assert_malformed passed: + 0000004: error: bad magic value +out/test/spec/gc/binary.wast:37: assert_malformed passed: + 0000004: error: unable to read uint16_t: version +out/test/spec/gc/binary.wast:38: assert_malformed passed: + 0000004: error: unable to read uint16_t: version +out/test/spec/gc/binary.wast:39: assert_malformed passed: + 0000006: error: unable to read uint16_t: layer +out/test/spec/gc/binary.wast:40: assert_malformed passed: + 0000008: error: bad wasm file version: 0 (expected 0x1) +out/test/spec/gc/binary.wast:41: assert_malformed passed: + 0000008: error: bad wasm file version: 0xd (expected 0x1) +out/test/spec/gc/binary.wast:42: assert_malformed passed: + 0000008: error: bad wasm file version: 0xe (expected 0x1) +out/test/spec/gc/binary.wast:43: assert_malformed passed: + 0000008: error: bad wasm file version: 0x100 (expected 0x1) +out/test/spec/gc/binary.wast:44: assert_malformed passed: + 0000008: error: wasm components are not yet supported in this tool +out/test/spec/gc/binary.wast:45: assert_malformed passed: + 0000008: error: unsupported wasm layer: 0x100 +out/test/spec/gc/binary.wast:48: assert_malformed passed: + 000000a: error: invalid section code: 14 +out/test/spec/gc/binary.wast:49: assert_malformed passed: + 000000a: error: invalid section code: 127 +out/test/spec/gc/binary.wast:50: assert_malformed passed: + 000000a: error: invalid section code: 128 +out/test/spec/gc/binary.wast:51: assert_malformed passed: + 000000a: error: invalid section code: 129 +out/test/spec/gc/binary.wast:52: assert_malformed passed: + 000000a: error: invalid section code: 255 +out/test/spec/gc/binary.wast:56: assert_malformed passed: + 000001b: error: function body must end with END opcode +out/test/spec/gc/binary.wast:77: assert_malformed passed: + 000001a: error: function body must end with END opcode +out/test/spec/gc/binary.wast:93: assert_malformed passed: + 000001a: error: function body must end with END opcode +out/test/spec/gc/binary.wast:113: assert_malformed passed: + 0000019: error: init expression must end with END opcode +out/test/spec/gc/binary.wast:126: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/gc/binary.wast:146: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/gc/binary.wast:166: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/gc/binary.wast:185: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/gc/binary.wast:204: assert_malformed passed: + 0000020: error: memory.grow reserved value must be 0 +out/test/spec/gc/binary.wast:224: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/gc/binary.wast:243: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/gc/binary.wast:262: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/gc/binary.wast:280: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/gc/binary.wast:298: assert_malformed passed: + 000001e: error: memory.size reserved value must be 0 +out/test/spec/gc/binary.wast:317: assert_malformed passed: + 0000017: error: unable to read u32 leb128: local type count +out/test/spec/gc/binary.wast:334: assert_malformed passed: + 0000017: error: unable to read u32 leb128: local type count +out/test/spec/gc/binary.wast:351: assert_malformed passed: + 000001e: error: local count must be <= 0xffffffff +out/test/spec/gc/binary.wast:367: assert_malformed passed: + 0000030: error: local count must be <= 0xffffffff +out/test/spec/gc/binary.wast:401: assert_malformed passed: + 0000013: error: function signature count != function body count +out/test/spec/gc/binary.wast:411: assert_malformed passed: + 000000b: error: function signature count != function body count +out/test/spec/gc/binary.wast:420: assert_malformed passed: + 0000016: error: function signature count != function body count +out/test/spec/gc/binary.wast:431: assert_malformed passed: + 0000015: error: function signature count != function body count +out/test/spec/gc/binary.wast:454: assert_malformed passed: + 000000e: error: data segment count does not equal count in DataCount section +out/test/spec/gc/binary.wast:466: assert_malformed passed: + 000000e: error: data segment count does not equal count in DataCount section +out/test/spec/gc/binary.wast:478: assert_malformed passed: + 0000010: error: Data section missing but DataCount non-zero +out/test/spec/gc/binary.wast:494: assert_malformed passed: + 0000024: error: memory.init requires data count section +out/test/spec/gc/binary.wast:517: assert_malformed passed: + 000001e: error: data.drop requires data count section +out/test/spec/gc/binary.wast:537: assert_malformed passed: + 0000024: error: unexpected opcode: 0xf3 +out/test/spec/gc/binary.wast:565: assert_malformed passed: + 0000022: error: table elem type must be a reference type +out/test/spec/gc/binary.wast:650: assert_malformed passed: + 000000a: error: invalid section size: extends past end +out/test/spec/gc/binary.wast:661: assert_malformed passed: + 000000e: error: unfinished section (expected end: 0x11) +out/test/spec/gc/binary.wast:680: assert_malformed passed: + 000000e: error: invalid import tag kind: exceptions not allowed +out/test/spec/gc/binary.wast:690: assert_malformed passed: + 000000e: error: invalid import tag kind: exceptions not allowed +out/test/spec/gc/binary.wast:701: assert_malformed passed: + 000000e: error: malformed import kind: 5 +out/test/spec/gc/binary.wast:711: assert_malformed passed: + 000000e: error: malformed import kind: 5 +out/test/spec/gc/binary.wast:722: assert_malformed passed: + 000000e: error: malformed import kind: 128 +out/test/spec/gc/binary.wast:732: assert_malformed passed: + 000000e: error: malformed import kind: 128 +out/test/spec/gc/binary.wast:745: assert_malformed passed: + 0000027: error: unable to read u32 leb128: string length +out/test/spec/gc/binary.wast:764: assert_malformed passed: + 000002b: error: unfinished section (expected end: 0x40) +out/test/spec/gc/binary.wast:795: assert_malformed passed: + 000000b: error: invalid table count 1, only 0 bytes left in section +out/test/spec/gc/binary.wast:805: assert_malformed passed: + 000000d: error: tables may not be shared +out/test/spec/gc/binary.wast:814: assert_malformed passed: + 000000d: error: tables may not be shared +out/test/spec/gc/binary.wast:824: assert_malformed passed: + 000000d: error: malformed table limits flag: 129 +out/test/spec/gc/binary.wast:842: assert_malformed passed: + 000000b: error: invalid memory count 1, only 0 bytes left in section +out/test/spec/gc/binary.wast:852: assert_malformed passed: + 000000c: error: memory may not be shared: threads not allowed +out/test/spec/gc/binary.wast:860: assert_malformed passed: + 000000c: error: memory may not be shared: threads not allowed +out/test/spec/gc/binary.wast:869: assert_malformed passed: + 000000c: error: malformed memory limits flag: 129 +out/test/spec/gc/binary.wast:878: assert_malformed passed: + 000000c: error: malformed memory limits flag: 129 +out/test/spec/gc/binary.wast:895: assert_malformed passed: + 0000010: error: unable to read i32 leb128: global type +out/test/spec/gc/binary.wast:906: assert_malformed passed: + 0000010: error: unfinished section (expected end: 0x15) +out/test/spec/gc/binary.wast:929: assert_malformed passed: + 000001b: error: unable to read u32 leb128: string length +out/test/spec/gc/binary.wast:950: assert_malformed passed: + 000001b: error: unfinished section (expected end: 0x20) +out/test/spec/gc/binary.wast:984: assert_malformed passed: + 0000021: error: unable to read u32 leb128: elem segment flags +out/test/spec/gc/binary.wast:1000: assert_malformed passed: + 0000024: error: init expression must end with END opcode +out/test/spec/gc/binary.wast:1017: assert_malformed passed: + 0000021: error: unfinished section (expected end: 0x27) +out/test/spec/gc/binary.wast:1043: assert_malformed passed: + 0000016: error: unable to read u32 leb128: data segment flags +out/test/spec/gc/binary.wast:1056: assert_malformed passed: + 0000016: error: unfinished section (expected end: 0x1c) +out/test/spec/gc/binary.wast:1069: assert_malformed passed: + 0000015: error: unable to read data: data segment data +out/test/spec/gc/binary.wast:1083: assert_malformed passed: + 000001a: error: unfinished section (expected end: 0x1b) +out/test/spec/gc/binary.wast:1114: assert_malformed passed: + 0000048: error: function body must end with END opcode +out/test/spec/gc/binary.wast:1161: assert_malformed passed: + 0000017: error: multiple Start sections +out/test/spec/gc/binary.wast:1178: assert_malformed passed: + 0000014: error: multiple Function sections +out/test/spec/gc/binary.wast:1190: assert_malformed passed: + 0000016: error: function signature count != function body count +out/test/spec/gc/binary.wast:1202: assert_malformed passed: + 000000d: error: multiple DataCount sections +out/test/spec/gc/binary.wast:1212: assert_malformed passed: + 000000d: error: multiple Data sections +out/test/spec/gc/binary.wast:1222: assert_malformed passed: + 000000d: error: multiple Global sections +out/test/spec/gc/binary.wast:1232: assert_malformed passed: + 000000d: error: multiple Export sections +out/test/spec/gc/binary.wast:1242: assert_malformed passed: + 000000d: error: multiple Table sections +out/test/spec/gc/binary.wast:1252: assert_malformed passed: + 000000d: error: multiple Elem sections +out/test/spec/gc/binary.wast:1262: assert_malformed passed: + 000000d: error: multiple Import sections +out/test/spec/gc/binary.wast:1272: assert_malformed passed: + 000000d: error: multiple Type sections +out/test/spec/gc/binary.wast:1282: assert_malformed passed: + 000000d: error: multiple Memory sections +out/test/spec/gc/binary.wast:1292: assert_malformed passed: + 000000d: error: section Type out of order +out/test/spec/gc/binary.wast:1302: assert_malformed passed: + 000000d: error: section Import out of order +out/test/spec/gc/binary.wast:1312: assert_malformed passed: + 000000d: error: section Function out of order +out/test/spec/gc/binary.wast:1322: assert_malformed passed: + 000000d: error: section Table out of order +out/test/spec/gc/binary.wast:1332: assert_malformed passed: + 000000d: error: section Memory out of order +out/test/spec/gc/binary.wast:1342: assert_malformed passed: + 000000d: error: section Global out of order +out/test/spec/gc/binary.wast:1352: assert_malformed passed: + 0000011: error: section Export out of order +out/test/spec/gc/binary.wast:1363: assert_malformed passed: + 0000011: error: section Start out of order +out/test/spec/gc/binary.wast:1374: assert_malformed passed: + 000000d: error: section Elem out of order +out/test/spec/gc/binary.wast:1384: assert_malformed passed: + 000000d: error: section DataCount out of order +out/test/spec/gc/binary.wast:1394: assert_malformed passed: + 000000d: error: section Code out of order +136/136 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_if.txt b/test/spec/gc/br_if.txt new file mode 100644 index 0000000000..6677462665 --- /dev/null +++ b/test/spec/gc/br_if.txt @@ -0,0 +1,98 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_if.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/br_if.wast:481: assert_invalid passed: + out/test/spec/gc/br_if/br_if.1.wasm:000001e: error: type mismatch in i32.ctz, expected [i32] but got [] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/br_if.wast:485: assert_invalid passed: + out/test/spec/gc/br_if/br_if.2.wasm:000001e: error: type mismatch in i64.ctz, expected [i64] but got [] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/br_if.wast:489: assert_invalid passed: + out/test/spec/gc/br_if/br_if.3.wasm:000001e: error: type mismatch in f32.neg, expected [f32] but got [] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/br_if.wast:493: assert_invalid passed: + out/test/spec/gc/br_if/br_if.4.wasm:000001e: error: type mismatch in f64.neg, expected [f64] but got [] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/br_if.wast:498: assert_invalid passed: + out/test/spec/gc/br_if/br_if.5.wasm:000001e: error: type mismatch in i32.ctz, expected [i32] but got [] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/br_if.wast:502: assert_invalid passed: + out/test/spec/gc/br_if/br_if.6.wasm:000001d: error: type mismatch in br_if, expected [i32] but got [i64] + 000001d: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:506: assert_invalid passed: + out/test/spec/gc/br_if/br_if.7.wasm:0000020: error: type mismatch in br_if, expected [i32] but got [f32] + 0000020: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:510: assert_invalid passed: + out/test/spec/gc/br_if/br_if.8.wasm:000001d: error: type mismatch in br_if, expected [i32] but got [i64] + 000001d: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:515: assert_invalid passed: + out/test/spec/gc/br_if/br_if.9.wasm:000001e: error: type mismatch in br_if, expected [i32] but got [] + 000001e: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:521: assert_invalid passed: + out/test/spec/gc/br_if/br_if.10.wasm:000001e: error: type mismatch in br_if, expected [i32] but got [] + 000001e: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:527: assert_invalid passed: + out/test/spec/gc/br_if/br_if.11.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/br_if.wast:533: assert_invalid passed: + out/test/spec/gc/br_if/br_if.12.wasm:0000020: error: type mismatch at end of block, expected [] but got [i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/br_if.wast:540: assert_invalid passed: + out/test/spec/gc/br_if/br_if.13.wasm:000001f: error: type mismatch in br_if, expected [i32] but got [] + 000001f: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:546: assert_invalid passed: + out/test/spec/gc/br_if/br_if.14.wasm:000001f: error: type mismatch in br_if, expected [i32] but got [] + 000001f: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:552: assert_invalid passed: + out/test/spec/gc/br_if/br_if.15.wasm:0000020: error: type mismatch in br_if, expected [i32] but got [i64] + 0000020: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:560: assert_invalid passed: + out/test/spec/gc/br_if/br_if.16.wasm:0000020: error: type mismatch in br_if, expected [i32] but got [i64] + 0000020: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:569: assert_invalid passed: + out/test/spec/gc/br_if/br_if.17.wasm:000001b: error: type mismatch in br_if, expected [i32] but got [] + 000001b: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:575: assert_invalid passed: + out/test/spec/gc/br_if/br_if.18.wasm:000001c: error: type mismatch in br_if, expected [i32] but got [] + 000001c: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:581: assert_invalid passed: + out/test/spec/gc/br_if/br_if.19.wasm:000001d: error: type mismatch in br_if, expected [i32] but got [i64] + 000001d: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:587: assert_invalid passed: + out/test/spec/gc/br_if/br_if.20.wasm:000001f: error: type mismatch in br_if, expected [i32] but got [] + 000001f: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:593: assert_invalid passed: + out/test/spec/gc/br_if/br_if.21.wasm:0000022: error: type mismatch in br_if, expected [i32] but got [] + 0000022: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:599: assert_invalid passed: + out/test/spec/gc/br_if/br_if.22.wasm:0000020: error: type mismatch in br_if, expected [i32] but got [... i64] + 0000020: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:606: assert_invalid passed: + out/test/spec/gc/br_if/br_if.23.wasm:0000021: error: type mismatch in br_if, expected [i32] but got [] + out/test/spec/gc/br_if/br_if.23.wasm:0000021: error: type mismatch in br_if, expected [i32] but got [] + 0000021: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:618: assert_invalid passed: + out/test/spec/gc/br_if/br_if.24.wasm:0000023: error: type mismatch in br_if, expected [i32] but got [] + 0000023: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:630: assert_invalid passed: + out/test/spec/gc/br_if/br_if.25.wasm:000001b: error: type mismatch in br_if, expected [i32] but got [] + out/test/spec/gc/br_if/br_if.25.wasm:000001b: error: type mismatch in br_if, expected [i32] but got [] + 000001b: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:641: assert_invalid passed: + out/test/spec/gc/br_if/br_if.26.wasm:000001d: error: type mismatch in br_if, expected [i32] but got [] + 000001d: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:654: assert_invalid passed: + out/test/spec/gc/br_if/br_if.27.wasm:000001b: error: invalid depth: 1 (max 0) + 000001b: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:658: assert_invalid passed: + out/test/spec/gc/br_if/br_if.28.wasm:000001f: error: invalid depth: 5 (max 2) + 000001f: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:662: assert_invalid passed: + out/test/spec/gc/br_if/br_if.29.wasm:000001f: error: invalid depth: 268435457 (max 0) + 000001f: error: OnBrIfExpr callback failed +out/test/spec/gc/br_if.wast:668: assert_invalid passed: + out/test/spec/gc/br_if/br_if.30.wasm:000002f: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 000002f: error: OnCallExpr callback failed +119/119 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_on_non_null.txt b/test/spec/gc/br_on_non_null.txt new file mode 100644 index 0000000000..d277ad25a6 --- /dev/null +++ b/test/spec/gc/br_on_non_null.txt @@ -0,0 +1,10 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_on_non_null.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/br_on_non_null.wast:37: assert_trap passed: unreachable executed +out/test/spec/gc/br_on_non_null.wast:78: assert_invalid passed: + out/test/spec/gc/br_on_non_null/br_on_non_null.3.wasm:0000031: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 0000031: error: OnCallExpr callback failed +10/10 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_on_null.txt b/test/spec/gc/br_on_null.txt new file mode 100644 index 0000000000..067911c15e --- /dev/null +++ b/test/spec/gc/br_on_null.txt @@ -0,0 +1,10 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_on_null.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/br_on_null.wast:32: assert_trap passed: unreachable executed +out/test/spec/gc/br_on_null.wast:82: assert_invalid passed: + out/test/spec/gc/br_on_null/br_on_null.3.wasm:0000031: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 0000031: error: OnCallExpr callback failed +10/10 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/br_table.txt b/test/spec/gc/br_table.txt new file mode 100644 index 0000000000..12425961da --- /dev/null +++ b/test/spec/gc/br_table.txt @@ -0,0 +1,78 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/br_table.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/br_table.wast:1267: assert_invalid passed: + out/test/spec/gc/br_table/br_table.1.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/br_table.wast:1274: assert_invalid passed: + out/test/spec/gc/br_table/br_table.2.wasm:000001d: error: type mismatch in br_table, expected [i32] but got [] + 000001d: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1281: assert_invalid passed: + out/test/spec/gc/br_table/br_table.3.wasm:0000020: error: type mismatch in br_table, expected [i32] but got [] + 0000020: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1287: assert_invalid passed: + out/test/spec/gc/br_table/br_table.4.wasm:0000023: error: type mismatch in br_table, expected [i32] but got [i64] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1295: assert_invalid passed: + out/test/spec/gc/br_table/br_table.5.wasm:0000026: error: br_table labels have inconsistent types: expected [f32], got [] + 0000026: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1306: assert_invalid passed: + out/test/spec/gc/br_table/br_table.6.wasm:0000023: error: type mismatch in br_table, expected [i64] but got [i32] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1317: assert_invalid passed: + out/test/spec/gc/br_table/br_table.7.wasm:000001f: error: type mismatch in br_table, expected [i32] but got [] + 000001f: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1323: assert_invalid passed: + out/test/spec/gc/br_table/br_table.8.wasm:000001e: error: type mismatch in br_table, expected [i32] but got [i64] + 000001e: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1329: assert_invalid passed: + out/test/spec/gc/br_table/br_table.9.wasm:0000021: error: type mismatch in br_table, expected [i32] but got [] + 0000021: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1335: assert_invalid passed: + out/test/spec/gc/br_table/br_table.10.wasm:0000023: error: type mismatch in br_table, expected [i32] but got [] + 0000023: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1341: assert_invalid passed: + out/test/spec/gc/br_table/br_table.11.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [... i64] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1350: assert_invalid passed: + out/test/spec/gc/br_table/br_table.12.wasm:0000022: error: type mismatch at end of block, expected [] but got [i32] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/br_table.wast:1357: assert_invalid passed: + out/test/spec/gc/br_table/br_table.13.wasm:0000022: error: type mismatch in br_table, expected [i32] but got [] + 0000022: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1369: assert_invalid passed: + out/test/spec/gc/br_table/br_table.14.wasm:0000024: error: type mismatch in br_table, expected [i32] but got [] + 0000024: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1381: assert_invalid passed: + out/test/spec/gc/br_table/br_table.15.wasm:000001c: error: type mismatch in br_table, expected [i32] but got [] + 000001c: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1392: assert_invalid passed: + out/test/spec/gc/br_table/br_table.16.wasm:000001e: error: type mismatch in br_table, expected [i32] but got [] + 000001e: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1404: assert_invalid passed: + out/test/spec/gc/br_table/br_table.17.wasm:0000025: error: br_table labels have inconsistent types: expected [i32], got [] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1416: assert_invalid passed: + out/test/spec/gc/br_table/br_table.18.wasm:0000025: error: br_table labels have inconsistent types: expected [], got [i32] + 0000025: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1430: assert_invalid passed: + out/test/spec/gc/br_table/br_table.19.wasm:000001f: error: invalid depth: 2 (max 1) + 000001f: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1436: assert_invalid passed: + out/test/spec/gc/br_table/br_table.20.wasm:0000021: error: invalid depth: 5 (max 2) + 0000021: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1442: assert_invalid passed: + out/test/spec/gc/br_table/br_table.21.wasm:0000024: error: invalid depth: 268435457 (max 1) + 0000024: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1449: assert_invalid passed: + out/test/spec/gc/br_table/br_table.22.wasm:000001f: error: invalid depth: 2 (max 1) + 000001f: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1455: assert_invalid passed: + out/test/spec/gc/br_table/br_table.23.wasm:0000021: error: invalid depth: 5 (max 2) + 0000021: error: OnBrTableExpr callback failed +out/test/spec/gc/br_table.wast:1461: assert_invalid passed: + out/test/spec/gc/br_table/br_table.24.wasm:0000024: error: invalid depth: 268435457 (max 1) + 0000024: error: OnBrTableExpr callback failed +186/186 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/call_ref.txt b/test/spec/gc/call_ref.txt new file mode 100644 index 0000000000..dda63dfdf4 --- /dev/null +++ b/test/spec/gc/call_ref.txt @@ -0,0 +1,22 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/call_ref.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/call_ref.wast:97: assert_trap passed: null function reference +out/test/spec/gc/call_ref.wast:136: assert_trap passed: unreachable executed +out/test/spec/gc/call_ref.wast:149: assert_trap passed: unreachable executed +out/test/spec/gc/call_ref.wast:165: assert_trap passed: unreachable executed +out/test/spec/gc/call_ref.wast:168: assert_invalid passed: + out/test/spec/gc/call_ref/call_ref.4.wasm:0000042: error: type mismatch in call, expected [i32] but got [i64] + 0000042: error: OnCallRefExpr callback failed +out/test/spec/gc/call_ref.wast:184: assert_invalid passed: + out/test/spec/gc/call_ref/call_ref.5.wasm:0000044: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000044: error: EndFunctionBody callback failed +out/test/spec/gc/call_ref.wast:201: assert_invalid passed: + out/test/spec/gc/call_ref/call_ref.6.wasm:000001f: error: type mismatch in call_ref, expected [(ref null 0)] but got [externref] + 000001f: error: OnCallRefExpr callback failed +out/test/spec/gc/call_ref.wast:211: assert_invalid passed: + out/test/spec/gc/call_ref/call_ref.7.wasm:000001f: error: type mismatch in call_ref, expected [(ref null 0)] but got [funcref] + 000001f: error: OnCallRefExpr callback failed +35/35 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/data.txt b/test/spec/gc/data.txt new file mode 100644 index 0000000000..1b2441a1db --- /dev/null +++ b/test/spec/gc/data.txt @@ -0,0 +1,66 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/data.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/data.wast:293: assert_invalid passed: + out/test/spec/gc/data/data.41.wasm:000000c: error: memory variable out of range: 0 (max 0) + 000000c: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:301: assert_invalid passed: + out/test/spec/gc/data/data.42.wasm:0000012: error: memory variable out of range: 1 (max 1) + 0000012: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:314: assert_invalid passed: + out/test/spec/gc/data/data.43.wasm:000000c: error: memory variable out of range: 0 (max 0) + 000000c: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:325: assert_invalid passed: + out/test/spec/gc/data/data.44.wasm:000000d: error: memory variable out of range: 1 (max 0) + 000000d: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:337: assert_invalid passed: + out/test/spec/gc/data/data.45.wasm:0000012: error: memory variable out of range: 1 (max 1) + 0000012: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:359: assert_invalid passed: + out/test/spec/gc/data/data.46.wasm:000000d: error: memory variable out of range: 1 (max 0) + 000000d: error: BeginDataSegment callback failed +out/test/spec/gc/data.wast:378: assert_invalid passed: + out/test/spec/gc/data/data.47.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [i64] + 0000014: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:386: assert_invalid passed: + out/test/spec/gc/data/data.48.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [funcref] + 0000014: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:394: assert_invalid passed: + out/test/spec/gc/data/data.49.wasm:0000011: error: type mismatch in initializer expression, expected [i32] but got [] + 0000012: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:402: assert_invalid passed: + out/test/spec/gc/data/data.50.wasm:0000015: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000016: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:410: assert_invalid passed: + out/test/spec/gc/data/data.51.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002c: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:419: assert_invalid passed: + out/test/spec/gc/data/data.52.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002c: error: EndDataSegmentInitExpr callback failed +out/test/spec/gc/data.wast:428: assert_invalid passed: + out/test/spec/gc/data/data.53.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000014: error: OnUnaryExpr callback failed +out/test/spec/gc/data.wast:436: assert_invalid passed: + out/test/spec/gc/data/data.54.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop + 0000012: error: OnNopExpr callback failed +out/test/spec/gc/data.wast:444: assert_invalid passed: + out/test/spec/gc/data/data.55.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop + 0000012: error: OnNopExpr callback failed +out/test/spec/gc/data.wast:452: assert_invalid passed: + out/test/spec/gc/data/data.56.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: nop + 0000014: error: OnNopExpr callback failed +out/test/spec/gc/data.wast:460: assert_invalid passed: + out/test/spec/gc/data/data.57.wasm:0000020: error: initializer expression cannot reference a mutable global + 0000020: error: OnGlobalGetExpr callback failed +out/test/spec/gc/data.wast:469: assert_invalid passed: + out/test/spec/gc/data/data.58.wasm:0000013: error: global variable out of range: 0 (max 0) + 0000013: error: OnGlobalGetExpr callback failed +out/test/spec/gc/data.wast:477: assert_invalid passed: + out/test/spec/gc/data/data.59.wasm:0000029: error: global variable out of range: 1 (max 1) + 0000029: error: OnGlobalGetExpr callback failed +out/test/spec/gc/data.wast:486: assert_invalid passed: + out/test/spec/gc/data/data.60.wasm:000002d: error: initializer expression cannot reference a mutable global + 000002d: error: OnGlobalGetExpr callback failed +61/61 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/elem.txt b/test/spec/gc/elem.txt new file mode 100644 index 0000000000..94f9f7498d --- /dev/null +++ b/test/spec/gc/elem.txt @@ -0,0 +1,90 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/elem.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/elem.wast:517: assert_invalid passed: + out/test/spec/gc/elem/elem.55.wasm:0000025: error: type mismatch at elem segment. got funcref, expected (ref func) + 0000025: error: OnElemSegmentElemType callback failed +out/test/spec/gc/elem.wast:525: assert_invalid passed: + out/test/spec/gc/elem/elem.56.wasm:0000025: error: type mismatch at elem segment. got funcref, expected (ref func) + 0000025: error: OnElemSegmentElemType callback failed +out/test/spec/gc/elem.wast:706: assert_trap passed: out of bounds table access: table.init out of bounds +out/test/spec/gc/elem.wast:716: assert_trap passed: out of bounds table access: table.init out of bounds +out/test/spec/gc/elem.wast:722: assert_invalid passed: + out/test/spec/gc/elem/elem.77.wasm:0000016: error: table variable out of range: 0 (max 0) + 0000016: error: BeginElemSegment callback failed +out/test/spec/gc/elem.wast:733: assert_invalid passed: + out/test/spec/gc/elem/elem.78.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [i64] + 0000015: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:741: assert_invalid passed: + out/test/spec/gc/elem/elem.79.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [funcref] + 0000015: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:749: assert_invalid passed: + out/test/spec/gc/elem/elem.80.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got [] + 0000013: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:757: assert_invalid passed: + out/test/spec/gc/elem/elem.81.wasm:0000016: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000017: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:765: assert_invalid passed: + out/test/spec/gc/elem/elem.82.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002d: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:774: assert_invalid passed: + out/test/spec/gc/elem/elem.83.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32] + 000002d: error: EndElemSegmentInitExpr callback failed +out/test/spec/gc/elem.wast:784: assert_invalid passed: + out/test/spec/gc/elem/elem.84.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000015: error: OnUnaryExpr callback failed +out/test/spec/gc/elem.wast:792: assert_invalid passed: + out/test/spec/gc/elem/elem.85.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop + 0000013: error: OnNopExpr callback failed +out/test/spec/gc/elem.wast:800: assert_invalid passed: + out/test/spec/gc/elem/elem.86.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop + 0000013: error: OnNopExpr callback failed +out/test/spec/gc/elem.wast:808: assert_invalid passed: + out/test/spec/gc/elem/elem.87.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: nop + 0000015: error: OnNopExpr callback failed +out/test/spec/gc/elem.wast:816: assert_invalid passed: + out/test/spec/gc/elem/elem.88.wasm:0000021: error: initializer expression cannot reference a mutable global + 0000021: error: OnGlobalGetExpr callback failed +out/test/spec/gc/elem.wast:825: assert_invalid passed: + out/test/spec/gc/elem/elem.89.wasm:0000014: error: global variable out of range: 0 (max 0) + 0000014: error: OnGlobalGetExpr callback failed +out/test/spec/gc/elem.wast:833: assert_invalid passed: + out/test/spec/gc/elem/elem.90.wasm:000002a: error: global variable out of range: 1 (max 1) + 000002a: error: OnGlobalGetExpr callback failed +out/test/spec/gc/elem.wast:842: assert_invalid passed: + out/test/spec/gc/elem/elem.91.wasm:000002e: error: initializer expression cannot reference a mutable global + 000002e: error: OnGlobalGetExpr callback failed +out/test/spec/gc/elem.wast:854: assert_invalid passed: + out/test/spec/gc/elem/elem.92.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [externref] + 0000019: error: EndElemExpr callback failed +out/test/spec/gc/elem.wast:862: assert_invalid passed: + out/test/spec/gc/elem/elem.93.wasm:000001a: error: type mismatch at end of initializer expression, expected [] but got [funcref] + 000001b: error: EndElemExpr callback failed +out/test/spec/gc/elem.wast:870: assert_invalid passed: + out/test/spec/gc/elem/elem.94.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000019: error: EndElemExpr callback failed +out/test/spec/gc/elem.wast:878: assert_invalid passed: + out/test/spec/gc/elem/elem.95.wasm:0000018: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000019: error: EndElemExpr callback failed +out/test/spec/gc/elem.wast:886: assert_invalid passed: + out/test/spec/gc/elem/elem.96.wasm:0000023: error: invalid initializer: instruction not valid in initializer expression: call + 0000023: error: OnCallExpr callback failed +out/test/spec/gc/elem.wast:895: assert_invalid passed: + out/test/spec/gc/elem/elem.97.wasm:000001b: error: invalid initializer: instruction not valid in initializer expression: i32.add + 000001b: error: OnBinaryExpr callback failed +out/test/spec/gc/elem.wast:954: assert_trap passed: uninitialized table element +out/test/spec/gc/elem.wast:987: assert_invalid passed: + out/test/spec/gc/elem/elem.103.wasm:000001f: error: type mismatch at elem segment. got (ref func), expected externref + 000001f: error: OnElemSegmentElemType callback failed +out/test/spec/gc/elem.wast:992: assert_invalid passed: + out/test/spec/gc/elem/elem.104.wasm:0000017: error: type mismatch at elem segment. got externref, expected funcref + 0000017: error: OnElemSegmentElemType callback failed +out/test/spec/gc/elem.wast:997: assert_invalid passed: + out/test/spec/gc/elem/elem.105.wasm:0000034: error: type mismatch at table.init. got funcref, expected externref + 0000034: error: OnTableInitExpr callback failed +out/test/spec/gc/elem.wast:1006: assert_invalid passed: + out/test/spec/gc/elem/elem.106.wasm:0000030: error: type mismatch at table.init. got externref, expected funcref + 0000030: error: OnTableInitExpr callback failed +137/137 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/func.txt b/test/spec/gc/func.txt new file mode 100644 index 0000000000..625fb519d3 --- /dev/null +++ b/test/spec/gc/func.txt @@ -0,0 +1,257 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/func.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/func.wast:436: assert_invalid passed: + out/test/spec/gc/func/func.2.wasm:000001a: error: function type variable out of range: 2 (max 2) + 000001a: error: OnFunction callback failed +out/test/spec/gc/func.wast:448: assert_malformed passed: + out/test/spec/gc/func/func.3.wat:1:123: error: invalid func type index 2 + ...lt f64) (f64.const 1))(type $t (func (param i32)))(func (type 2) (param i32)) + ^^^^ +out/test/spec/gc/func.wast:560: assert_malformed passed: + out/test/spec/gc/func/func.6.wat:1:76: error: unexpected token "param", expected an instr. + ... i32) (result i32)))(func (type $sig) (result i32) (param i32) (i32.const 0)) + ^^^^^ +out/test/spec/gc/func.wast:567: assert_malformed passed: + out/test/spec/gc/func/func.7.wat:1:63: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (param i32) (type $sig) (result i32) (i32.const 0)) + ^^^^ +out/test/spec/gc/func.wast:574: assert_malformed passed: + out/test/spec/gc/func/func.8.wat:1:76: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (param i32) (result i32) (type $sig) (i32.const 0)) + ^^^^ +out/test/spec/gc/func.wast:581: assert_malformed passed: + out/test/spec/gc/func/func.9.wat:1:64: error: unexpected token "type", expected an instr. + ... i32) (result i32)))(func (result i32) (type $sig) (param i32) (i32.const 0)) + ^^^^ +out/test/spec/gc/func.wast:588: assert_malformed passed: + out/test/spec/gc/func/func.10.wat:1:64: error: unexpected token "param", expected an instr. + ... i32) (result i32)))(func (result i32) (param i32) (type $sig) (i32.const 0)) + ^^^^^ + out/test/spec/gc/func/func.10.wat:1:85: error: unexpected token ), expected (. + ... i32) (result i32)))(func (result i32) (param i32) (type $sig) (i32.const 0)) + ^ +out/test/spec/gc/func.wast:595: assert_malformed passed: + out/test/spec/gc/func/func.11.wat:1:21: error: unexpected token "param", expected an instr. + (func (result i32) (param i32) (i32.const 0)) + ^^^^^ +out/test/spec/gc/func.wast:602: assert_malformed passed: + out/test/spec/gc/func/func.12.wat:1:20: error: expected 0 results, got 1 + (type $sig (func))(func (type $sig) (result i32) (i32.const 0)) + ^^^^ +out/test/spec/gc/func.wast:609: assert_malformed passed: + out/test/spec/gc/func/func.13.wat:1:45: error: expected 1 arguments, got 0 + ...g (func (param i32) (result i32)))(func (type $sig) (result i32) (i32.cons... + ^^^^ +out/test/spec/gc/func.wast:616: assert_malformed passed: + out/test/spec/gc/func/func.14.wat:1:45: error: expected 1 results, got 0 + ...g (func (param i32) (result i32)))(func (type $sig) (param i32) (i32.const... + ^^^^ +out/test/spec/gc/func.wast:623: assert_malformed passed: + out/test/spec/gc/func/func.15.wat:1:49: error: expected 2 arguments, got 1 + ...unc (param i32 i32) (result i32)))(func (type $sig) (param i32) (result i3... + ^^^^ +out/test/spec/gc/func.wast:631: assert_invalid passed: + out/test/spec/gc/func/func.16.wasm:000000c: error: function type variable out of range: 4 (max 0) + 000000c: error: OnFunction callback failed +out/test/spec/gc/func.wast:635: assert_invalid passed: + out/test/spec/gc/func/func.17.wasm:0000013: error: function type variable out of range: 4 (max 1) + 0000013: error: OnFunction callback failed +out/test/spec/gc/func.wast:647: assert_invalid passed: + out/test/spec/gc/func/func.18.wasm:000001d: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:651: assert_invalid passed: + out/test/spec/gc/func/func.19.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/func.wast:655: assert_invalid passed: + out/test/spec/gc/func/func.20.wasm:000001e: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001e: error: OnUnaryExpr callback failed +out/test/spec/gc/func.wast:660: assert_invalid passed: + out/test/spec/gc/func/func.21.wasm:000001c: error: uninitialized local reference + 000001c: error: OnLocalGetExpr callback failed +out/test/spec/gc/func.wast:671: assert_invalid passed: + out/test/spec/gc/func/func.22.wasm:000001c: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:675: assert_invalid passed: + out/test/spec/gc/func/func.23.wasm:000001b: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001b: error: OnConvertExpr callback failed +out/test/spec/gc/func.wast:679: assert_invalid passed: + out/test/spec/gc/func/func.24.wasm:000001c: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001c: error: OnUnaryExpr callback failed +out/test/spec/gc/func.wast:687: assert_invalid passed: + out/test/spec/gc/func/func.25.wasm:0000019: error: type mismatch in implicit return, expected [i32] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:691: assert_invalid passed: + out/test/spec/gc/func/func.26.wasm:0000019: error: type mismatch in implicit return, expected [i64] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:695: assert_invalid passed: + out/test/spec/gc/func/func.27.wasm:0000019: error: type mismatch in implicit return, expected [f32] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:699: assert_invalid passed: + out/test/spec/gc/func/func.28.wasm:0000019: error: type mismatch in implicit return, expected [f64] but got [] + 0000019: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:703: assert_invalid passed: + out/test/spec/gc/func/func.29.wasm:000001a: error: type mismatch in implicit return, expected [f64, i32] but got [] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:708: assert_invalid passed: + out/test/spec/gc/func/func.30.wasm:000001a: error: type mismatch in implicit return, expected [i32] but got [] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:714: assert_invalid passed: + out/test/spec/gc/func/func.31.wasm:000001b: error: type mismatch in implicit return, expected [i32, i32] but got [] + 000001b: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:720: assert_invalid passed: + out/test/spec/gc/func/func.32.wasm:000001a: error: type mismatch at end of function, expected [] but got [i32] + 000001a: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:726: assert_invalid passed: + out/test/spec/gc/func/func.33.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32, i64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:732: assert_invalid passed: + out/test/spec/gc/func/func.34.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [f32] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:738: assert_invalid passed: + out/test/spec/gc/func/func.35.wasm:000001f: error: type mismatch in implicit return, expected [f32, f32] but got [f32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:744: assert_invalid passed: + out/test/spec/gc/func/func.36.wasm:0000023: error: type mismatch at end of function, expected [] but got [f32] + 0000023: error: EndFunctionBody callback failed +out/test/spec/gc/func.wast:751: assert_invalid passed: + out/test/spec/gc/func/func.37.wasm:0000019: error: type mismatch in return, expected [i32] but got [] + 0000019: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:757: assert_invalid passed: + out/test/spec/gc/func/func.38.wasm:000001a: error: type mismatch in return, expected [i32, i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:763: assert_invalid passed: + out/test/spec/gc/func/func.39.wasm:000001a: error: type mismatch in return, expected [i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:769: assert_invalid passed: + out/test/spec/gc/func/func.40.wasm:000001b: error: type mismatch in return, expected [i32, i64] but got [] + 000001b: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:775: assert_invalid passed: + out/test/spec/gc/func/func.41.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:781: assert_invalid passed: + out/test/spec/gc/func/func.42.wasm:000001c: error: type mismatch in return, expected [i64, i64] but got [i64] + 000001c: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:788: assert_invalid passed: + out/test/spec/gc/func/func.43.wasm:0000019: error: type mismatch in return, expected [i32] but got [] + 0000019: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:794: assert_invalid passed: + out/test/spec/gc/func/func.44.wasm:000001a: error: type mismatch in return, expected [i32, i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:800: assert_invalid passed: + out/test/spec/gc/func/func.45.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i32] + 000001c: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:806: assert_invalid passed: + out/test/spec/gc/func/func.46.wasm:000001a: error: type mismatch in return, expected [i32] but got [] + 000001a: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:812: assert_invalid passed: + out/test/spec/gc/func/func.47.wasm:000001b: error: type mismatch in return, expected [i32, i32] but got [] + 000001b: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:818: assert_invalid passed: + out/test/spec/gc/func/func.48.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:824: assert_invalid passed: + out/test/spec/gc/func/func.49.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i64] + 000001c: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:830: assert_invalid passed: + out/test/spec/gc/func/func.50.wasm:000001b: error: type mismatch in return, expected [i32] but got [i64] + 000001b: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:836: assert_invalid passed: + out/test/spec/gc/func/func.51.wasm:000001c: error: type mismatch in return, expected [i32, i32] but got [i32] + 000001c: error: OnReturnExpr callback failed +out/test/spec/gc/func.wast:843: assert_invalid passed: + out/test/spec/gc/func/func.52.wasm:000001a: error: type mismatch in br, expected [i32] but got [] + 000001a: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:849: assert_invalid passed: + out/test/spec/gc/func/func.53.wasm:000001b: error: type mismatch in br, expected [i32, i32] but got [] + 000001b: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:855: assert_invalid passed: + out/test/spec/gc/func/func.54.wasm:000001f: error: type mismatch in br, expected [i32] but got [f32] + 000001f: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:861: assert_invalid passed: + out/test/spec/gc/func/func.55.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001d: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:867: assert_invalid passed: + out/test/spec/gc/func/func.56.wasm:000001a: error: type mismatch in br, expected [i32] but got [] + 000001a: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:873: assert_invalid passed: + out/test/spec/gc/func/func.57.wasm:000001b: error: type mismatch in br, expected [i32, i32] but got [] + 000001b: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:879: assert_invalid passed: + out/test/spec/gc/func/func.58.wasm:000001c: error: type mismatch in br, expected [i32] but got [i64] + 000001c: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:885: assert_invalid passed: + out/test/spec/gc/func/func.59.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001d: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:891: assert_invalid passed: + out/test/spec/gc/func/func.60.wasm:000001c: error: type mismatch in br, expected [i32] but got [i64] + 000001c: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:898: assert_invalid passed: + out/test/spec/gc/func/func.61.wasm:000001c: error: type mismatch in br, expected [i32] but got [] + 000001c: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:904: assert_invalid passed: + out/test/spec/gc/func/func.62.wasm:000001d: error: type mismatch in br, expected [i32, i32] but got [] + 000001d: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:910: assert_invalid passed: + out/test/spec/gc/func/func.63.wasm:000001d: error: type mismatch in br, expected [i32] but got [] + 000001d: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:916: assert_invalid passed: + out/test/spec/gc/func/func.64.wasm:000001e: error: type mismatch in br, expected [i32, i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:922: assert_invalid passed: + out/test/spec/gc/func/func.65.wasm:000001e: error: type mismatch in br, expected [i32] but got [i64] + 000001e: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:928: assert_invalid passed: + out/test/spec/gc/func/func.66.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [i32] + 000001f: error: OnBrExpr callback failed +out/test/spec/gc/func.wast:938: assert_malformed passed: + out/test/spec/gc/func/func.67.wat:1:14: error: unexpected token "local", expected an instr. + (func (nop) (local i32)) + ^^^^^ +out/test/spec/gc/func.wast:942: assert_malformed passed: + out/test/spec/gc/func/func.68.wat:1:14: error: unexpected token "param", expected an instr. + (func (nop) (param i32)) + ^^^^^ +out/test/spec/gc/func.wast:946: assert_malformed passed: + out/test/spec/gc/func/func.69.wat:1:14: error: unexpected token "result", expected an instr. + (func (nop) (result i32)) + ^^^^^^ +out/test/spec/gc/func.wast:950: assert_malformed passed: + out/test/spec/gc/func/func.70.wat:1:20: error: unexpected token "param", expected an instr. + (func (local i32) (param i32)) + ^^^^^ +out/test/spec/gc/func.wast:954: assert_malformed passed: + out/test/spec/gc/func/func.71.wat:1:20: error: unexpected token "result", expected an instr. + (func (local i32) (result i32) (local.get 0)) + ^^^^^^ +out/test/spec/gc/func.wast:958: assert_malformed passed: + out/test/spec/gc/func/func.72.wat:1:21: error: unexpected token "param", expected an instr. + (func (result i32) (param i32) (local.get 0)) + ^^^^^ +out/test/spec/gc/func.wast:965: assert_malformed passed: + out/test/spec/gc/func/func.73.wat:1:13: error: redefinition of function "$foo" + (func $foo)(func $foo) + ^^^^ +out/test/spec/gc/func.wast:969: assert_malformed passed: + out/test/spec/gc/func/func.74.wat:1:28: error: redefinition of function "$foo" + (import "" "" (func $foo))(func $foo) + ^^^^ +out/test/spec/gc/func.wast:973: assert_malformed passed: + out/test/spec/gc/func/func.75.wat:1:28: error: redefinition of function "$foo" + (import "" "" (func $foo))(import "" "" (func $foo)) + ^^^^^^ +out/test/spec/gc/func.wast:978: assert_malformed passed: + out/test/spec/gc/func/func.76.wat:1:31: error: redefinition of parameter "$foo" + (func (param $foo i32) (param $foo i32)) + ^^^^ +out/test/spec/gc/func.wast:982: assert_malformed passed: + out/test/spec/gc/func/func.77.wat:1:31: error: redefinition of parameter "$foo" + (func (param $foo i32) (local $foo i32)) + ^^^^ +out/test/spec/gc/func.wast:986: assert_malformed passed: + out/test/spec/gc/func/func.78.wat:1:31: error: redefinition of local "$foo" + (func (local $foo i32) (local $foo i32)) + ^^^^ +175/175 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/global.txt b/test/spec/gc/global.txt new file mode 100644 index 0000000000..f2fe53f1a2 --- /dev/null +++ b/test/spec/gc/global.txt @@ -0,0 +1,147 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/global.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/global.wast:251: assert_trap passed: undefined table index +out/test/spec/gc/global.wast:273: assert_invalid passed: + out/test/spec/gc/global/global.1.wasm:0000029: error: can't global.set on immutable global at index 0. + 0000029: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:278: assert_invalid passed: + out/test/spec/gc/global/global.2.wasm:0000035: error: can't global.set on immutable global at index 0. + 0000035: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:287: assert_invalid passed: + out/test/spec/gc/global/global.5.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg + 0000013: error: OnUnaryExpr callback failed +out/test/spec/gc/global.wast:292: assert_invalid passed: + out/test/spec/gc/global/global.6.wasm:000000f: error: invalid initializer: instruction not valid in initializer expression: local.get + 000000f: error: OnLocalGetExpr callback failed +out/test/spec/gc/global.wast:297: assert_invalid passed: + out/test/spec/gc/global/global.7.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg + 0000013: error: OnUnaryExpr callback failed +out/test/spec/gc/global.wast:302: assert_invalid passed: + out/test/spec/gc/global/global.8.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: nop + 0000010: error: OnNopExpr callback failed +out/test/spec/gc/global.wast:307: assert_invalid passed: + out/test/spec/gc/global/global.9.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: i32.ctz + 0000010: error: OnUnaryExpr callback failed +out/test/spec/gc/global.wast:312: assert_invalid passed: + out/test/spec/gc/global/global.10.wasm:000000e: error: invalid initializer: instruction not valid in initializer expression: nop + 000000e: error: OnNopExpr callback failed +out/test/spec/gc/global.wast:317: assert_invalid passed: + out/test/spec/gc/global/global.11.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got [f32] + 0000013: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:322: assert_invalid passed: + out/test/spec/gc/global/global.12.wasm:0000011: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000012: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:327: assert_invalid passed: + out/test/spec/gc/global/global.13.wasm:000000d: error: type mismatch in initializer expression, expected [i32] but got [] + 000000e: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:332: assert_invalid passed: + out/test/spec/gc/global/global.14.wasm:0000017: error: type mismatch in initializer expression, expected [funcref] but got [externref] + 0000018: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:337: assert_invalid passed: + out/test/spec/gc/global/global.15.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000028: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:342: assert_invalid passed: + out/test/spec/gc/global/global.16.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32] + 0000028: error: EndGlobalInitExpr callback failed +out/test/spec/gc/global.wast:347: assert_invalid passed: + out/test/spec/gc/global/global.17.wasm:000000f: error: initializer expression can only reference an imported global + 000000f: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:352: assert_invalid passed: + out/test/spec/gc/global/global.18.wasm:000000f: error: global variable out of range: 1 (max 1) + 000000f: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:357: assert_invalid passed: + out/test/spec/gc/global/global.19.wasm:0000025: error: global variable out of range: 2 (max 2) + 0000025: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:365: assert_invalid passed: + out/test/spec/gc/global/global.22.wasm:0000029: error: initializer expression cannot reference a mutable global + 0000029: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:373: assert_malformed passed: + 0000026: error: global mutability must be 0 or 1 +out/test/spec/gc/global.wast:386: assert_malformed passed: + 0000026: error: global mutability must be 0 or 1 +out/test/spec/gc/global.wast:403: assert_malformed passed: + 0000011: error: global mutability must be 0 or 1 +out/test/spec/gc/global.wast:415: assert_malformed passed: + 0000011: error: global mutability must be 0 or 1 +out/test/spec/gc/global.wast:429: assert_invalid passed: + out/test/spec/gc/global/global.29.wasm:000001a: error: global variable out of range: 0 (max 0) + 000001a: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:434: assert_invalid passed: + out/test/spec/gc/global/global.30.wasm:0000022: error: global variable out of range: 1 (max 1) + 0000022: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:442: assert_invalid passed: + out/test/spec/gc/global/global.31.wasm:0000034: error: global variable out of range: 1 (max 1) + 0000034: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:450: assert_invalid passed: + out/test/spec/gc/global/global.32.wasm:000003c: error: global variable out of range: 2 (max 2) + 000003c: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:460: assert_invalid passed: + out/test/spec/gc/global/global.33.wasm:000001b: error: global variable out of range: 0 (max 0) + 000001b: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:465: assert_invalid passed: + out/test/spec/gc/global/global.34.wasm:0000023: error: global variable out of range: 1 (max 1) + 0000023: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:473: assert_invalid passed: + out/test/spec/gc/global/global.35.wasm:0000035: error: global variable out of range: 1 (max 1) + 0000035: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:481: assert_invalid passed: + out/test/spec/gc/global/global.36.wasm:000003d: error: global variable out of range: 2 (max 2) + 000003d: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:491: assert_invalid passed: + out/test/spec/gc/global/global.37.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:500: assert_invalid passed: + out/test/spec/gc/global/global.38.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:510: assert_invalid passed: + out/test/spec/gc/global/global.39.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:520: assert_invalid passed: + out/test/spec/gc/global/global.40.wasm:0000027: error: type mismatch in global.set, expected [i32] but got [] + 0000027: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:530: assert_invalid passed: + out/test/spec/gc/global/global.41.wasm:000002a: error: type mismatch in global.set, expected [i32] but got [] + 000002a: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:540: assert_invalid passed: + out/test/spec/gc/global/global.42.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:550: assert_invalid passed: + out/test/spec/gc/global/global.43.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:560: assert_invalid passed: + out/test/spec/gc/global/global.44.wasm:0000025: error: type mismatch in global.set, expected [i32] but got [] + 0000025: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:570: assert_invalid passed: + out/test/spec/gc/global/global.45.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:579: assert_invalid passed: + out/test/spec/gc/global/global.46.wasm:0000021: error: type mismatch in global.set, expected [i32] but got [] + 0000021: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:588: assert_invalid passed: + out/test/spec/gc/global/global.47.wasm:0000027: error: type mismatch in global.set, expected [i32] but got [] + 0000027: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:598: assert_invalid passed: + out/test/spec/gc/global/global.48.wasm:0000040: error: type mismatch in global.set, expected [i32] but got [] + 0000040: error: OnGlobalSetExpr callback failed +out/test/spec/gc/global.wast:655: assert_invalid passed: + out/test/spec/gc/global/global.51.wasm:000000f: error: global variable out of range: 1 (max 1) + 000000f: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:663: assert_invalid passed: + out/test/spec/gc/global/global.52.wasm:0000012: error: global variable out of range: 0 (max 0) + 0000012: error: OnGlobalGetExpr callback failed +out/test/spec/gc/global.wast:674: assert_malformed passed: + out/test/spec/gc/global/global.53.wat:1:33: error: redefinition of global "$foo" + (global $foo i32 (i32.const 0))(global $foo i32 (i32.const 0)) + ^^^^^^ +out/test/spec/gc/global.wast:681: assert_malformed passed: + out/test/spec/gc/global/global.54.wat:1:34: error: redefinition of global "$foo" + (import "" "" (global $foo i32))(global $foo i32 (i32.const 0)) + ^^^^^^ +out/test/spec/gc/global.wast:688: assert_malformed passed: + out/test/spec/gc/global/global.55.wat:1:34: error: redefinition of global "$foo" + (import "" "" (global $foo i32))(import "" "" (global $foo i32)) + ^^^^^^ +119/119 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/if.txt b/test/spec/gc/if.txt new file mode 100644 index 0000000000..911dac3e5d --- /dev/null +++ b/test/spec/gc/if.txt @@ -0,0 +1,409 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/if.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/if.wast:593: assert_trap passed: undefined table index +out/test/spec/gc/if.wast:736: assert_malformed passed: + out/test/spec/gc/if/if.1.wat:1:95: error: unexpected token "param", expected then block (e.g. (then ...)). + ...i32.const 0) (if (type $sig) (result i32) (param i32) (i32.const 1) (then))) + ^^^^^ + out/test/spec/gc/if/if.1.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (type $sig) (result i32) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:745: assert_malformed passed: + out/test/spec/gc/if/if.2.wat:1:82: error: unexpected token "type", expected then block (e.g. (then ...)). + ...nc (i32.const 0) (if (param i32) (type $sig) (result i32) (i32.const 1) (... + ^^^^ + out/test/spec/gc/if/if.2.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (param i32) (type $sig) (result i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:754: assert_malformed passed: + out/test/spec/gc/if/if.3.wat:1:95: error: unexpected token "type", expected then block (e.g. (then ...)). + ...i32.const 0) (if (param i32) (result i32) (type $sig) (i32.const 1) (then))) + ^^^^ + out/test/spec/gc/if/if.3.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (param i32) (result i32) (type $sig) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:763: assert_malformed passed: + out/test/spec/gc/if/if.4.wat:1:83: error: unexpected token "type", expected then block (e.g. (then ...)). + ...c (i32.const 0) (if (result i32) (type $sig) (param i32) (i32.const 1) (t... + ^^^^ + out/test/spec/gc/if/if.4.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (result i32) (type $sig) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:772: assert_malformed passed: + out/test/spec/gc/if/if.5.wat:1:83: error: unexpected token "param", expected then block (e.g. (then ...)). + ...c (i32.const 0) (if (result i32) (param i32) (type $sig) (i32.const 1) (t... + ^^^^^ + out/test/spec/gc/if/if.5.wat:1:121: error: unexpected token "then", expected an instr. + ...i32.const 0) (if (result i32) (param i32) (type $sig) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:781: assert_malformed passed: + out/test/spec/gc/if/if.6.wat:1:39: error: unexpected token "param", expected then block (e.g. (then ...)). + (func (i32.const 0) (if (result i32) (param i32) (i32.const 1) (then))) + ^^^^^ + out/test/spec/gc/if/if.6.wat:1:65: error: unexpected token "then", expected an instr. + (func (i32.const 0) (if (result i32) (param i32) (i32.const 1) (then))) + ^^^^ +out/test/spec/gc/if.wast:788: assert_malformed passed: + out/test/spec/gc/if/if.7.wat:1:47: error: unexpected token $x, expected ). + ...(i32.const 0) (i32.const 1) (if (param $x i32) (then (drop)) (else (drop)))) + ^^ + out/test/spec/gc/if/if.7.wat:1:69: error: unexpected token (, expected EOF. + ...(i32.const 0) (i32.const 1) (if (param $x i32) (then (drop)) (else (drop)))) + ^ +out/test/spec/gc/if.wast:796: assert_malformed passed: + out/test/spec/gc/if/if.8.wat:1:40: error: expected 0 results, got 1 + (type $sig (func))(func (i32.const 1) (if (type $sig) (result i32) (then (i3... + ^ +out/test/spec/gc/if.wast:806: assert_malformed passed: + out/test/spec/gc/if/if.9.wat:1:65: error: expected 1 arguments, got 0 + ...) (result i32)))(func (i32.const 1) (if (type $sig) (result i32) (then (i... + ^ +out/test/spec/gc/if.wast:816: assert_malformed passed: + out/test/spec/gc/if/if.10.wat:1:79: error: expected 1 results, got 0 + ...))(func (i32.const 0) (i32.const 1) (if (type $sig) (param i32) (then (dr... + ^ +out/test/spec/gc/if.wast:826: assert_malformed passed: + out/test/spec/gc/if/if.11.wat:1:83: error: expected 2 arguments, got 1 + ...))(func (i32.const 0) (i32.const 1) (if (type $sig) (param i32) (result i... + ^ +out/test/spec/gc/if.wast:836: assert_invalid passed: + out/test/spec/gc/if/if.12.wasm:000001f: error: type mismatch at end of function, expected [] but got [i32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:844: assert_invalid passed: + out/test/spec/gc/if/if.13.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:848: assert_invalid passed: + out/test/spec/gc/if/if.14.wasm:000001e: error: type mismatch in implicit return, expected [i64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:852: assert_invalid passed: + out/test/spec/gc/if/if.15.wasm:000001e: error: type mismatch in implicit return, expected [f32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:856: assert_invalid passed: + out/test/spec/gc/if/if.16.wasm:000001e: error: type mismatch in implicit return, expected [f64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:861: assert_invalid passed: + out/test/spec/gc/if/if.17.wasm:000001e: error: type mismatch in implicit return, expected [i32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:865: assert_invalid passed: + out/test/spec/gc/if/if.18.wasm:000001e: error: type mismatch in implicit return, expected [i64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:869: assert_invalid passed: + out/test/spec/gc/if/if.19.wasm:000001e: error: type mismatch in implicit return, expected [f32] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:873: assert_invalid passed: + out/test/spec/gc/if/if.20.wasm:000001e: error: type mismatch in implicit return, expected [f64] but got [] + 000001e: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:878: assert_invalid passed: + out/test/spec/gc/if/if.21.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:884: assert_invalid passed: + out/test/spec/gc/if/if.22.wasm:000001e: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:890: assert_invalid passed: + out/test/spec/gc/if/if.23.wasm:000001f: error: type mismatch at end of `if false` branch, expected [] but got [i32] + 000001f: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:896: assert_invalid passed: + out/test/spec/gc/if/if.24.wasm:000001d: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 000001e: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:903: assert_invalid passed: + out/test/spec/gc/if/if.25.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:909: assert_invalid passed: + out/test/spec/gc/if/if.26.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:915: assert_invalid passed: + out/test/spec/gc/if/if.27.wasm:0000021: error: type mismatch at end of `if false` branch, expected [] but got [i32, i32] + 0000021: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:921: assert_invalid passed: + out/test/spec/gc/if/if.28.wasm:000001f: error: type mismatch at end of `if true` branch, expected [] but got [i32, i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:928: assert_invalid passed: + out/test/spec/gc/if/if.29.wasm:000001c: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001d: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:934: assert_invalid passed: + out/test/spec/gc/if/if.30.wasm:000001f: error: type mismatch in `if false` branch, expected [i32] but got [] + 000001f: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:940: assert_invalid passed: + out/test/spec/gc/if/if.31.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001d: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:947: assert_invalid passed: + out/test/spec/gc/if/if.32.wasm:000001d: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:953: assert_invalid passed: + out/test/spec/gc/if/if.33.wasm:0000022: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:959: assert_invalid passed: + out/test/spec/gc/if/if.34.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001e: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:966: assert_invalid passed: + out/test/spec/gc/if/if.35.wasm:000001f: error: type mismatch in `if false` branch, expected [i32] but got [] + 000001f: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:972: assert_invalid passed: + out/test/spec/gc/if/if.36.wasm:0000022: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:979: assert_invalid passed: + out/test/spec/gc/if/if.37.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:985: assert_invalid passed: + out/test/spec/gc/if/if.38.wasm:0000021: error: type mismatch in `if false` branch, expected [i32] but got [] + 0000021: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:991: assert_invalid passed: + out/test/spec/gc/if/if.39.wasm:000001d: error: type mismatch in `if true` branch, expected [i32] but got [] + 000001e: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:998: assert_invalid passed: + out/test/spec/gc/if/if.40.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001f: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1004: assert_invalid passed: + out/test/spec/gc/if/if.41.wasm:0000024: error: type mismatch in `if false` branch, expected [i32, i32] but got [] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:1010: assert_invalid passed: + out/test/spec/gc/if/if.42.wasm:000001e: error: type mismatch in `if true` branch, expected [i32, i32] but got [] + 000001f: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1017: assert_invalid passed: + out/test/spec/gc/if/if.43.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1023: assert_invalid passed: + out/test/spec/gc/if/if.44.wasm:0000022: error: type mismatch in `if false` branch, expected [i32] but got [i64] + 0000022: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:1029: assert_invalid passed: + out/test/spec/gc/if/if.45.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1036: assert_invalid passed: + out/test/spec/gc/if/if.46.wasm:000001f: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1042: assert_invalid passed: + out/test/spec/gc/if/if.47.wasm:0000025: error: type mismatch in `if false` branch, expected [i32, i32] but got [i32] + 0000025: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:1048: assert_invalid passed: + out/test/spec/gc/if/if.48.wasm:000001f: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000020: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1055: assert_invalid passed: + out/test/spec/gc/if/if.49.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1062: assert_invalid passed: + out/test/spec/gc/if/if.50.wasm:0000027: error: type mismatch in `if false` branch, expected [i32, i32] but got [i32] + 0000027: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:1069: assert_invalid passed: + out/test/spec/gc/if/if.51.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1077: assert_invalid passed: + out/test/spec/gc/if/if.52.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000021: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1083: assert_invalid passed: + out/test/spec/gc/if/if.53.wasm:0000024: error: type mismatch at end of `if false` branch, expected [] but got [i32] + 0000024: error: OnEndExpr callback failed +out/test/spec/gc/if.wast:1089: assert_invalid passed: + out/test/spec/gc/if/if.54.wasm:0000020: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000021: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1096: assert_invalid passed: + out/test/spec/gc/if/if.55.wasm:000001e: error: type mismatch in `if true` branch, expected [i32] but got [i64] + 000001f: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1102: assert_invalid passed: + out/test/spec/gc/if/if.56.wasm:0000023: error: type mismatch at end of `if true` branch, expected [] but got [i32] + 0000024: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1109: assert_invalid passed: + out/test/spec/gc/if/if.57.wasm:0000025: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000025: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:1119: assert_invalid passed: + out/test/spec/gc/if/if.58.wasm:0000025: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000025: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:1129: assert_invalid passed: + out/test/spec/gc/if/if.59.wasm:0000027: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000027: error: EndFunctionBody callback failed +out/test/spec/gc/if.wast:1140: assert_invalid passed: + out/test/spec/gc/if/if.60.wasm:000001e: error: type mismatch in br, expected [i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1146: assert_invalid passed: + out/test/spec/gc/if/if.61.wasm:0000021: error: type mismatch in br, expected [i32] but got [] + 0000021: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1152: assert_invalid passed: + out/test/spec/gc/if/if.62.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1158: assert_invalid passed: + out/test/spec/gc/if/if.63.wasm:0000024: error: type mismatch in br, expected [i32, i32] but got [] + 0000024: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1165: assert_invalid passed: + out/test/spec/gc/if/if.64.wasm:000001e: error: type mismatch in br, expected [i32] but got [] + 000001e: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1174: assert_invalid passed: + out/test/spec/gc/if/if.65.wasm:0000021: error: type mismatch in br, expected [i32] but got [] + 0000021: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1183: assert_invalid passed: + out/test/spec/gc/if/if.66.wasm:000001f: error: type mismatch in br, expected [i32, i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1192: assert_invalid passed: + out/test/spec/gc/if/if.67.wasm:0000024: error: type mismatch in br, expected [i32, i32] but got [] + 0000024: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1202: assert_invalid passed: + out/test/spec/gc/if/if.68.wasm:000001f: error: type mismatch in br, expected [i32] but got [] + 000001f: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1211: assert_invalid passed: + out/test/spec/gc/if/if.69.wasm:0000022: error: type mismatch in br, expected [i32] but got [] + 0000022: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1220: assert_invalid passed: + out/test/spec/gc/if/if.70.wasm:0000020: error: type mismatch in br, expected [i32, i32] but got [] + 0000020: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1229: assert_invalid passed: + out/test/spec/gc/if/if.71.wasm:0000025: error: type mismatch in br, expected [i32, i32] but got [] + 0000025: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1239: assert_invalid passed: + out/test/spec/gc/if/if.72.wasm:0000020: error: type mismatch in br, expected [i32] but got [i64] + 0000020: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1248: assert_invalid passed: + out/test/spec/gc/if/if.73.wasm:0000023: error: type mismatch in br, expected [i32] but got [i64] + 0000023: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1257: assert_invalid passed: + out/test/spec/gc/if/if.74.wasm:0000021: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000021: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1266: assert_invalid passed: + out/test/spec/gc/if/if.75.wasm:0000026: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000026: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1275: assert_invalid passed: + out/test/spec/gc/if/if.76.wasm:0000023: error: type mismatch in br, expected [i32, i32] but got [i64] + 0000023: error: OnBrExpr callback failed +out/test/spec/gc/if.wast:1285: assert_invalid passed: + out/test/spec/gc/if/if.77.wasm:0000021: error: type mismatch in `if true` branch, expected [i32, i32] but got [i32] + 0000022: error: OnElseExpr callback failed +out/test/spec/gc/if.wast:1296: assert_invalid passed: + out/test/spec/gc/if/if.78.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1304: assert_invalid passed: + out/test/spec/gc/if/if.79.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1313: assert_invalid passed: + out/test/spec/gc/if/if.80.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1322: assert_invalid passed: + out/test/spec/gc/if/if.81.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1331: assert_invalid passed: + out/test/spec/gc/if/if.82.wasm:0000022: error: type mismatch in if, expected [i32] but got [] + 0000022: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1341: assert_invalid passed: + out/test/spec/gc/if/if.83.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1350: assert_invalid passed: + out/test/spec/gc/if/if.84.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1359: assert_invalid passed: + out/test/spec/gc/if/if.85.wasm:000001d: error: type mismatch in if, expected [i32] but got [] + 000001d: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1368: assert_invalid passed: + out/test/spec/gc/if/if.86.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1376: assert_invalid passed: + out/test/spec/gc/if/if.87.wasm:0000019: error: type mismatch in if, expected [i32] but got [] + 0000019: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1384: assert_invalid passed: + out/test/spec/gc/if/if.88.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1393: assert_invalid passed: + out/test/spec/gc/if/if.89.wasm:0000038: error: type mismatch in if, expected [i32] but got [] + 0000038: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1409: assert_invalid passed: + out/test/spec/gc/if/if.90.wasm:000001b: error: type mismatch in if, expected [i32] but got [] + 000001b: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1418: assert_invalid passed: + out/test/spec/gc/if/if.91.wasm:000001b: error: type mismatch in if, expected [i32] but got [] + 000001b: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1427: assert_invalid passed: + out/test/spec/gc/if/if.92.wasm:0000021: error: type mismatch in if, expected [i32] but got [] + 0000021: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1436: assert_invalid passed: + out/test/spec/gc/if/if.93.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1445: assert_invalid passed: + out/test/spec/gc/if/if.94.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1454: assert_invalid passed: + out/test/spec/gc/if/if.95.wasm:000001e: error: type mismatch in if, expected [i32] but got [] + 000001e: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1464: assert_invalid passed: + out/test/spec/gc/if/if.96.wasm:000001f: error: type mismatch in if, expected [i32] but got [] + 000001f: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1470: assert_invalid passed: + out/test/spec/gc/if/if.97.wasm:0000020: error: type mismatch in if, expected [i32, f64] but got [] + 0000020: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1476: assert_invalid passed: + out/test/spec/gc/if/if.98.wasm:0000024: error: type mismatch in if, expected [i32] but got [f32] + 0000024: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1482: assert_invalid passed: + out/test/spec/gc/if/if.99.wasm:0000025: error: type mismatch in if, expected [f32, i32] but got [f32] + 0000025: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1488: assert_invalid passed: + out/test/spec/gc/if/if.100.wasm:0000021: error: type mismatch in if, expected [i32] but got [] + 0000021: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1494: assert_invalid passed: + out/test/spec/gc/if/if.101.wasm:0000022: error: type mismatch in if, expected [i32, f64] but got [] + 0000022: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1500: assert_invalid passed: + out/test/spec/gc/if/if.102.wasm:0000026: error: type mismatch in if, expected [i32] but got [f32] + 0000026: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1506: assert_invalid passed: + out/test/spec/gc/if/if.103.wasm:0000027: error: type mismatch in if, expected [f32, i32] but got [f32] + 0000027: error: OnIfExpr callback failed +out/test/spec/gc/if.wast:1513: assert_malformed passed: + out/test/spec/gc/if/if.104.wat:1:42: error: unexpected token $x, expected ). + (func (param i32) (result i32) if (param $x i32) end) + ^^ +out/test/spec/gc/if.wast:1517: assert_malformed passed: + out/test/spec/gc/if/if.105.wat:1:43: error: unexpected token $x, expected ). + (func (param i32) (result i32) (if (param $x i32) (then))) + ^^ +out/test/spec/gc/if.wast:1522: assert_malformed passed: + out/test/spec/gc/if/if.106.wat:1:26: error: unexpected label "$l" + (func i32.const 0 if end $l) + ^^ +out/test/spec/gc/if.wast:1526: assert_malformed passed: + out/test/spec/gc/if/if.107.wat:1:29: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a end $l) + ^^ +out/test/spec/gc/if.wast:1530: assert_malformed passed: + out/test/spec/gc/if/if.108.wat:1:27: error: unexpected label "$l" + (func i32.const 0 if else $l end) + ^^ +out/test/spec/gc/if.wast:1534: assert_malformed passed: + out/test/spec/gc/if/if.109.wat:1:30: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end) + ^^ +out/test/spec/gc/if.wast:1538: assert_malformed passed: + out/test/spec/gc/if/if.110.wat:1:31: error: unexpected label "$l" + (func i32.const 0 if else end $l) + ^^ +out/test/spec/gc/if.wast:1542: assert_malformed passed: + out/test/spec/gc/if/if.111.wat:1:27: error: unexpected label "$l" + (func i32.const 0 if else $l end $l) + ^^ + out/test/spec/gc/if/if.111.wat:1:34: error: unexpected label "$l" + (func i32.const 0 if else $l end $l) + ^^ +out/test/spec/gc/if.wast:1546: assert_malformed passed: + out/test/spec/gc/if/if.112.wat:1:27: error: unexpected label "$l1" + (func i32.const 0 if else $l1 end $l2) + ^^^ + out/test/spec/gc/if/if.112.wat:1:35: error: unexpected label "$l2" + (func i32.const 0 if else $l1 end $l2) + ^^^ +out/test/spec/gc/if.wast:1550: assert_malformed passed: + out/test/spec/gc/if/if.113.wat:1:34: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else end $l) + ^^ +out/test/spec/gc/if.wast:1554: assert_malformed passed: + out/test/spec/gc/if/if.114.wat:1:37: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $a end $l) + ^^ +out/test/spec/gc/if.wast:1558: assert_malformed passed: + out/test/spec/gc/if/if.115.wat:1:30: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end $l) + ^^ + out/test/spec/gc/if/if.115.wat:1:37: error: mismatching label "$a" != "$l" + (func i32.const 0 if $a else $l end $l) + ^^ +out/test/spec/gc/if.wast:1562: assert_malformed passed: + out/test/spec/gc/if/if.116.wat:1:11: error: unexpected token i32.const, expected (. + (func (if i32.const 0 (then) (else))) + ^^^^^^^^^ +241/241 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/linking.txt b/test/spec/gc/linking.txt new file mode 100644 index 0000000000..328d61a442 --- /dev/null +++ b/test/spec/gc/linking.txt @@ -0,0 +1,110 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/linking.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/linking.wast:28: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/linking.wast:32: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/linking.wast:87: assert_unlinkable passed: + error: mutability mismatch in imported global, expected mutable but got immutable. +out/test/spec/gc/linking.wast:91: assert_unlinkable passed: + error: mutability mismatch in imported global, expected immutable but got mutable. +out/test/spec/gc/linking.wast:133: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got externref. +out/test/spec/gc/linking.wast:138: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got funcref. +out/test/spec/gc/linking.wast:142: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref null 0). +out/test/spec/gc/linking.wast:146: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got externref. +out/test/spec/gc/linking.wast:151: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got funcref. +out/test/spec/gc/linking.wast:155: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref func). +out/test/spec/gc/linking.wast:159: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got externref. +out/test/spec/gc/linking.wast:164: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got funcref. +out/test/spec/gc/linking.wast:168: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref func). +out/test/spec/gc/linking.wast:172: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref null 0). +out/test/spec/gc/linking.wast:176: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got externref. +out/test/spec/gc/linking.wast:182: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref func). +out/test/spec/gc/linking.wast:186: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref null 0). +out/test/spec/gc/linking.wast:190: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got (ref 0). +out/test/spec/gc/linking.wast:194: assert_unlinkable passed: + error: type mismatch in imported global, expected funcref but got externref. +out/test/spec/gc/linking.wast:199: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got funcref. +out/test/spec/gc/linking.wast:203: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref null 0). +out/test/spec/gc/linking.wast:207: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got (ref 0). +out/test/spec/gc/linking.wast:211: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref func) but got externref. +out/test/spec/gc/linking.wast:216: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got funcref. +out/test/spec/gc/linking.wast:220: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref func). +out/test/spec/gc/linking.wast:224: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got (ref 0). +out/test/spec/gc/linking.wast:228: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref null 0) but got externref. +out/test/spec/gc/linking.wast:233: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got funcref. +out/test/spec/gc/linking.wast:237: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref func). +out/test/spec/gc/linking.wast:241: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got (ref null 0). +out/test/spec/gc/linking.wast:245: assert_unlinkable passed: + error: type mismatch in imported global, expected (ref 0) but got externref. +out/test/spec/gc/linking.wast:250: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got funcref. +out/test/spec/gc/linking.wast:254: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref func). +out/test/spec/gc/linking.wast:258: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref null 0). +out/test/spec/gc/linking.wast:262: assert_unlinkable passed: + error: type mismatch in imported global, expected externref but got (ref 0). +out/test/spec/gc/linking.wast:308: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:309: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:311: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:313: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:314: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:316: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:318: assert_trap passed: undefined table index +out/test/spec/gc/linking.wast:319: assert_trap passed: undefined table index +out/test/spec/gc/linking.wast:320: assert_trap passed: undefined table index +out/test/spec/gc/linking.wast:321: assert_trap passed: undefined table index +out/test/spec/gc/linking.wast:324: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/linking.wast:356: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:357: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:359: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:360: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:362: assert_trap passed: undefined table index +out/test/spec/gc/linking.wast:388: assert_unlinkable passed: + error: invalid import "Mt.mem" +out/test/spec/gc/linking.wast:397: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:411: assert_trap passed: uninitialized table element +out/test/spec/gc/linking.wast:442: assert_unlinkable passed: + error: type mismatch in imported table, expected funcref but got (ref null 0). +out/test/spec/gc/linking.wast:446: assert_unlinkable passed: + error: type mismatch in imported table, expected funcref but got externref. +out/test/spec/gc/linking.wast:451: assert_unlinkable passed: + error: type mismatch in imported table, expected (ref null 0) but got funcref. +out/test/spec/gc/linking.wast:455: assert_unlinkable passed: + error: type mismatch in imported table, expected (ref null 0) but got externref. +out/test/spec/gc/linking.wast:460: assert_unlinkable passed: + error: type mismatch in imported table, expected externref but got funcref. +out/test/spec/gc/linking.wast:464: assert_unlinkable passed: + error: type mismatch in imported table, expected externref but got (ref null 0). +out/test/spec/gc/linking.wast:542: assert_unlinkable passed: + error: invalid import "Mm.tab" +154/154 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/local_get.txt b/test/spec/gc/local_get.txt new file mode 100644 index 0000000000..a95a10e313 --- /dev/null +++ b/test/spec/gc/local_get.txt @@ -0,0 +1,54 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/local_get.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/local_get.wast:149: assert_invalid passed: + out/test/spec/gc/local_get/local_get.1.wasm:000001d: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001d: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:153: assert_invalid passed: + out/test/spec/gc/local_get/local_get.2.wasm:000001d: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001d: error: OnConvertExpr callback failed +out/test/spec/gc/local_get.wast:157: assert_invalid passed: + out/test/spec/gc/local_get/local_get.3.wasm:000001f: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001f: error: OnUnaryExpr callback failed +out/test/spec/gc/local_get.wast:165: assert_invalid passed: + out/test/spec/gc/local_get/local_get.4.wasm:000001c: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:169: assert_invalid passed: + out/test/spec/gc/local_get/local_get.5.wasm:000001c: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001c: error: OnConvertExpr callback failed +out/test/spec/gc/local_get.wast:173: assert_invalid passed: + out/test/spec/gc/local_get/local_get.6.wasm:000001d: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001d: error: OnUnaryExpr callback failed +out/test/spec/gc/local_get.wast:181: assert_invalid passed: + out/test/spec/gc/local_get/local_get.7.wasm:000001c: error: type mismatch at end of function, expected [] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:185: assert_invalid passed: + out/test/spec/gc/local_get/local_get.8.wasm:000001c: error: type mismatch at end of function, expected [] but got [i64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:189: assert_invalid passed: + out/test/spec/gc/local_get/local_get.9.wasm:000001c: error: type mismatch at end of function, expected [] but got [f32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:193: assert_invalid passed: + out/test/spec/gc/local_get/local_get.10.wasm:000001c: error: type mismatch at end of function, expected [] but got [f64] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_get.wast:201: assert_invalid passed: + out/test/spec/gc/local_get/local_get.11.wasm:000001d: error: local variable out of range (max 2) + 000001d: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_get.wast:205: assert_invalid passed: + out/test/spec/gc/local_get/local_get.12.wasm:0000020: error: local variable out of range (max 2) + 0000020: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_get.wast:210: assert_invalid passed: + out/test/spec/gc/local_get/local_get.13.wasm:000001b: error: local variable out of range (max 2) + 000001b: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_get.wast:214: assert_invalid passed: + out/test/spec/gc/local_get/local_get.14.wasm:000001f: error: local variable out of range (max 2) + 000001f: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_get.wast:219: assert_invalid passed: + out/test/spec/gc/local_get/local_get.15.wasm:000001e: error: local variable out of range (max 3) + 000001e: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_get.wast:223: assert_invalid passed: + out/test/spec/gc/local_get/local_get.16.wasm:0000021: error: local variable out of range (max 3) + 0000021: error: OnLocalGetExpr callback failed +36/36 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/local_init.txt b/test/spec/gc/local_init.txt new file mode 100644 index 0000000000..00d5dadd68 --- /dev/null +++ b/test/spec/gc/local_init.txt @@ -0,0 +1,18 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/local_init.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/local_init.wast:26: assert_invalid passed: + out/test/spec/gc/local_init/local_init.1.wasm:000001c: error: uninitialized local reference + 000001c: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_init.wast:30: assert_invalid passed: + out/test/spec/gc/local_init/local_init.2.wasm:000002a: error: uninitialized local reference + 000002a: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_init.wast:40: assert_invalid passed: + out/test/spec/gc/local_init/local_init.3.wasm:0000027: error: uninitialized local reference + 0000027: error: OnLocalGetExpr callback failed +out/test/spec/gc/local_init.wast:53: assert_invalid passed: + out/test/spec/gc/local_init/local_init.4.wasm:000002c: error: uninitialized local reference + 000002c: error: OnLocalGetExpr callback failed +10/10 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/local_tee.txt b/test/spec/gc/local_tee.txt new file mode 100644 index 0000000000..58b9ee859a --- /dev/null +++ b/test/spec/gc/local_tee.txt @@ -0,0 +1,132 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/local_tee.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/local_tee.wast:371: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.1.wasm:000001f: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001f: error: EndFunctionBody callback failed +out/test/spec/gc/local_tee.wast:375: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.2.wasm:0000021: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 0000021: error: OnConvertExpr callback failed +out/test/spec/gc/local_tee.wast:379: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.3.wasm:0000020: error: type mismatch in f64.neg, expected [f64] but got [i64] + 0000020: error: OnUnaryExpr callback failed +out/test/spec/gc/local_tee.wast:384: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.4.wasm:000001c: error: type mismatch in local.tee, expected [i32] but got [] + 000001c: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:388: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.5.wasm:0000020: error: type mismatch in local.tee, expected [i32] but got [f32] + 0000020: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:392: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.6.wasm:0000024: error: type mismatch in local.tee, expected [f32] but got [f64] + 0000024: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:396: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.7.wasm:0000026: error: type mismatch in local.tee, expected [i64] but got [f64] + 0000026: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:404: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.8.wasm:000001c: error: type mismatch in implicit return, expected [i64] but got [i32] + 000001c: error: EndFunctionBody callback failed +out/test/spec/gc/local_tee.wast:408: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.9.wasm:000001b: error: type mismatch in i32.eqz, expected [i32] but got [f32] + 000001b: error: OnConvertExpr callback failed +out/test/spec/gc/local_tee.wast:412: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.10.wasm:000001c: error: type mismatch in f64.neg, expected [f64] but got [i64] + 000001c: error: OnUnaryExpr callback failed +out/test/spec/gc/local_tee.wast:417: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.11.wasm:000001b: error: type mismatch in local.tee, expected [i32] but got [] + 000001b: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:421: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.12.wasm:000001f: error: type mismatch in local.tee, expected [i32] but got [f32] + 000001f: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:425: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.13.wasm:0000023: error: type mismatch in local.tee, expected [f32] but got [f64] + 0000023: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:429: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.14.wasm:0000024: error: type mismatch in local.tee, expected [i64] but got [f64] + 0000024: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:434: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.15.wasm:000001a: error: type mismatch in local.tee, expected [i32] but got [] + 000001a: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:442: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.16.wasm:000001e: error: type mismatch in local.tee, expected [i32] but got [] + 000001e: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:451: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.17.wasm:000001e: error: type mismatch in local.tee, expected [i32] but got [] + 000001e: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:460: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.18.wasm:0000020: error: type mismatch in local.tee, expected [i32] but got [] + 0000020: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:469: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.19.wasm:0000023: error: type mismatch in local.tee, expected [i32] but got [] + 0000023: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:478: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.20.wasm:000001e: error: type mismatch in local.tee, expected [i32] but got [] + 000001e: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:487: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.21.wasm:000001e: error: type mismatch in local.tee, expected [i32] but got [] + 000001e: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:496: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.22.wasm:000001e: error: type mismatch in local.tee, expected [i32] but got [] + 000001e: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:505: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.23.wasm:000001a: error: type mismatch in local.tee, expected [i32] but got [] + 000001a: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:513: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.24.wasm:000001a: error: type mismatch in local.tee, expected [i32] but got [] + 000001a: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:521: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.25.wasm:0000020: error: type mismatch in local.tee, expected [i32] but got [] + 0000020: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:530: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.26.wasm:0000039: error: type mismatch in local.tee, expected [i32] but got [] + 0000039: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:546: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.27.wasm:000001a: error: type mismatch in local.tee, expected [i32] but got [] + 000001a: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:554: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.28.wasm:000001a: error: type mismatch in local.tee, expected [i32] but got [] + 000001a: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:562: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.29.wasm:0000022: error: type mismatch in local.tee, expected [i32] but got [] + 0000022: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:571: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.30.wasm:000001f: error: type mismatch in local.tee, expected [i32] but got [] + 000001f: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:580: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.31.wasm:000001f: error: type mismatch in local.tee, expected [i32] but got [] + 000001f: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:589: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.32.wasm:000001f: error: type mismatch in local.tee, expected [i32] but got [] + 000001f: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:599: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.33.wasm:0000021: error: type mismatch in local.tee, expected [i32] but got [f32] + 0000021: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:603: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.34.wasm:0000022: error: type mismatch in local.tee, expected [i32] but got [f32] + 0000022: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:607: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.35.wasm:0000020: error: type mismatch in local.tee, expected [f64] but got [i64] + 0000020: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:613: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.36.wasm:0000028: error: type mismatch in call, expected [(ref null 0)] but got [funcref] + 0000028: error: OnCallExpr callback failed +out/test/spec/gc/local_tee.wast:630: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.37.wasm:000001f: error: local variable out of range (max 2) + 000001f: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:634: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.38.wasm:0000022: error: local variable out of range (max 2) + 0000022: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:639: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.39.wasm:000001d: error: local variable out of range (max 2) + 000001d: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:643: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.40.wasm:0000021: error: local variable out of range (max 2) + 0000021: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:648: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.41.wasm:0000020: error: local variable out of range (max 3) + 0000020: error: OnLocalTeeExpr callback failed +out/test/spec/gc/local_tee.wast:652: assert_invalid passed: + out/test/spec/gc/local_tee/local_tee.42.wasm:0000023: error: local variable out of range (max 3) + 0000023: error: OnLocalTeeExpr callback failed +98/98 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref.txt b/test/spec/gc/ref.txt new file mode 100644 index 0000000000..a90204e6b8 --- /dev/null +++ b/test/spec/gc/ref.txt @@ -0,0 +1,43 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/ref.wast:28: assert_invalid passed: + out/test/spec/gc/ref/ref.1.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +out/test/spec/gc/ref.wast:32: assert_invalid passed: + out/test/spec/gc/ref/ref.2.wasm:0000010: error: reference 1 is out of range in results + 0000010: error: OnFuncType callback failed +out/test/spec/gc/ref.wast:37: assert_invalid passed: + out/test/spec/gc/ref/ref.3.wasm:000000e: error: reference 1 is out of range in globals + 000000e: error: BeginGlobal callback failed +out/test/spec/gc/ref.wast:42: assert_invalid passed: + out/test/spec/gc/ref/ref.4.wasm:000000f: error: reference 1 is out of range in tables + 000000f: error: BeginTable callback failed +out/test/spec/gc/ref.wast:47: assert_invalid passed: + out/test/spec/gc/ref/ref.5.wasm:000000e: error: reference 1 is out of range + 000000e: error: OnElemSegmentElemType callback failed +out/test/spec/gc/ref.wast:52: assert_invalid passed: + out/test/spec/gc/ref/ref.6.wasm:0000010: error: reference 1 is out of range in params + 0000010: error: OnFuncType callback failed +out/test/spec/gc/ref.wast:56: assert_invalid passed: + out/test/spec/gc/ref/ref.7.wasm:0000010: error: reference 1 is out of range in results + 0000010: error: OnFuncType callback failed +out/test/spec/gc/ref.wast:60: assert_invalid passed: + out/test/spec/gc/ref/ref.8.wasm:000001a: error: reference 1 is out of range in locals + 000001a: error: OnLocalDecl callback failed +out/test/spec/gc/ref.wast:65: assert_invalid passed: + out/test/spec/gc/ref/ref.9.wasm:000001a: error: reference 1 is out of range + 000001a: error: OnBlockExpr callback failed +out/test/spec/gc/ref.wast:69: assert_invalid passed: + out/test/spec/gc/ref/ref.10.wasm:000001a: error: reference 1 is out of range + 000001a: error: OnLoopExpr callback failed +out/test/spec/gc/ref.wast:73: assert_invalid passed: + out/test/spec/gc/ref/ref.11.wasm:000001a: error: reference 1 is out of range + out/test/spec/gc/ref/ref.11.wasm:000001a: error: type mismatch in if, expected [i32] but got [] + 000001a: error: OnIfExpr callback failed +out/test/spec/gc/ref.wast:78: assert_invalid passed: + out/test/spec/gc/ref/ref.12.wasm:000001c: error: reference 1 is out of range + 000001c: error: OnSelectExpr callback failed +13/13 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_as_non_null.txt b/test/spec/gc/ref_as_non_null.txt new file mode 100644 index 0000000000..2778891508 --- /dev/null +++ b/test/spec/gc/ref_as_non_null.txt @@ -0,0 +1,11 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_as_non_null.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/ref_as_non_null.wast:25: assert_trap passed: unreachable executed +out/test/spec/gc/ref_as_non_null.wast:27: assert_trap passed: null reference +out/test/spec/gc/ref_as_non_null.wast:32: assert_invalid passed: + out/test/spec/gc/ref_as_non_null/ref_as_non_null.1.wasm:000002c: error: type mismatch in call, expected [(ref 0)] but got [(ref null 0)] + 000002c: error: OnCallExpr callback failed +7/7 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/ref_is_null.txt b/test/spec/gc/ref_is_null.txt new file mode 100644 index 0000000000..7d5f9cd012 --- /dev/null +++ b/test/spec/gc/ref_is_null.txt @@ -0,0 +1,14 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/ref_is_null.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +init(externref:1) => +deinit() => +out/test/spec/gc/ref_is_null.wast:79: assert_invalid passed: + out/test/spec/gc/ref_is_null/ref_is_null.2.wasm:000001b: error: type mismatch in ref.is_null, expected [funcref] but got [i32] + 000001b: error: OnRefIsNullExpr callback failed +out/test/spec/gc/ref_is_null.wast:83: assert_invalid passed: + out/test/spec/gc/ref_is_null/ref_is_null.3.wasm:0000018: error: type mismatch in ref.is_null, expected [funcref] but got [] + 0000018: error: OnRefIsNullExpr callback failed +22/22 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/return_call.txt b/test/spec/gc/return_call.txt new file mode 100644 index 0000000000..dc29132498 --- /dev/null +++ b/test/spec/gc/return_call.txt @@ -0,0 +1,39 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/return_call.wast +;;; ARGS*: --enable-gc --enable-tail-call +(;; STDOUT ;;; +out/test/spec/gc/return_call.wast:124: assert_invalid passed: + out/test/spec/gc/return_call/return_call.1.wasm:000001e: error: return signatures have inconsistent types: expected [i32], got [] + 000001e: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:131: assert_invalid passed: + out/test/spec/gc/return_call/return_call.2.wasm:000001f: error: return signatures have inconsistent types: expected [i32], got [i64] + 000001f: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:139: assert_invalid passed: + out/test/spec/gc/return_call/return_call.3.wasm:000001e: error: type mismatch in return_call, expected [i32] but got [] + 000001e: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:146: assert_invalid passed: + out/test/spec/gc/return_call/return_call.4.wasm:000001f: error: type mismatch in return_call, expected [f64, i32] but got [] + 000001f: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:164: assert_invalid passed: + out/test/spec/gc/return_call/return_call.7.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32] + 0000022: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:171: assert_invalid passed: + out/test/spec/gc/return_call/return_call.8.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32] + 0000022: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:178: assert_invalid passed: + out/test/spec/gc/return_call/return_call.9.wasm:000002a: error: type mismatch in return_call, expected [i32, f64] but got [f64, i32] + 000002a: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:185: assert_invalid passed: + out/test/spec/gc/return_call/return_call.10.wasm:000002a: error: type mismatch in return_call, expected [f64, i32] but got [i32, f64] + 000002a: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:192: assert_invalid passed: + out/test/spec/gc/return_call/return_call.11.wasm:0000024: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000024: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:204: assert_invalid passed: + out/test/spec/gc/return_call/return_call.12.wasm:0000019: error: function variable out of range: 1 (max 1) + 0000019: error: OnReturnCallExpr callback failed +out/test/spec/gc/return_call.wast:208: assert_invalid passed: + out/test/spec/gc/return_call/return_call.13.wasm:000001d: error: function variable out of range: 1012321300 (max 1) + 000001d: error: OnReturnCallExpr callback failed +45/45 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/return_call_indirect.txt b/test/spec/gc/return_call_indirect.txt new file mode 100644 index 0000000000..59b7f87f35 --- /dev/null +++ b/test/spec/gc/return_call_indirect.txt @@ -0,0 +1,124 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/return_call_indirect.wast +;;; ARGS*: --enable-gc --enable-tail-call +(;; STDOUT ;;; +out/test/spec/gc/return_call_indirect.wast:234: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/return_call_indirect.wast:235: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/return_call_indirect.wast:236: assert_trap passed: undefined table index +out/test/spec/gc/return_call_indirect.wast:237: assert_trap passed: undefined table index +out/test/spec/gc/return_call_indirect.wast:238: assert_trap passed: undefined table index +out/test/spec/gc/return_call_indirect.wast:244: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/return_call_indirect.wast:245: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/return_call_indirect.wast:273: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.1.wat:1:129: error: unexpected token "param", expected an expr. + ...indirect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const ... + ^^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.1.wat:1:173: error: unexpected token ), expected EOF. + ...irect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:285: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.2.wat:1:116: error: unexpected token "type", expected an expr. + ...(return_call_indirect (param i32) (type $sig) (result i32) (i32.const 0... + ^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.2.wat:1:173: error: unexpected token ), expected EOF. + ...irect (param i32) (type $sig) (result i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:297: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.3.wat:1:129: error: unexpected token "type", expected an expr. + ...indirect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const ... + ^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.3.wat:1:173: error: unexpected token ), expected EOF. + ...irect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:309: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.4.wat:1:117: error: unexpected token "type", expected an expr. + ...return_call_indirect (result i32) (type $sig) (param i32) (i32.const 0)... + ^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.4.wat:1:173: error: unexpected token ), expected EOF. + ...irect (result i32) (type $sig) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:321: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.5.wat:1:117: error: unexpected token "param", expected an expr. + ...return_call_indirect (result i32) (param i32) (type $sig) (i32.const 0)... + ^^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.5.wat:1:173: error: unexpected token ), expected EOF. + ...irect (result i32) (param i32) (type $sig) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:333: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.6.wat:1:74: error: unexpected token "param", expected an expr. + ...return_call_indirect (result i32) (param i32) (i32.const 0) (i32.const ... + ^^^^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.6.wat:1:118: error: unexpected token ), expected EOF. + ...urn_call_indirect (result i32) (param i32) (i32.const 0) (i32.const 0) )) + ^ +out/test/spec/gc/return_call_indirect.wast:345: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.7.wat:1:53: error: unexpected token $x, expected ). + ...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0))) + ^^ + out/test/spec/gc/return_call_indirect/return_call_indirect.7.wat:1:89: error: unexpected token ), expected EOF. + ...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0))) + ^ +out/test/spec/gc/return_call_indirect.wast:352: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.8.wat:1:57: error: expected 0 results, got 1 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/gc/return_call_indirect.wast:362: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.9.wat:1:82: error: expected 1 arguments, got 0 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/gc/return_call_indirect.wast:372: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.10.wat:1:69: error: expected 1 results, got 0 + ...))(table 0 funcref)(func (return_call_indirect (type $sig) (param i32) ... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/gc/return_call_indirect.wast:384: assert_malformed passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.11.wat:1:86: error: expected 2 arguments, got 1 + ...ncref)(func (result i32) (return_call_indirect (type $sig) (param i32) (r... + ^^^^^^^^^^^^^^^^^^^^ +out/test/spec/gc/return_call_indirect.wast:399: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.12.wasm:000001c: error: table variable out of range: 0 (max 0) + out/test/spec/gc/return_call_indirect/return_call_indirect.12.wasm:000001c: error: type mismatch: return_call_indirect must reference table of funcref type + 000001c: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:407: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.13.wasm:0000024: error: type mismatch at end of function, expected [] but got [i32] + 0000024: error: EndFunctionBody callback failed +out/test/spec/gc/return_call_indirect.wast:415: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.14.wasm:0000026: error: return signatures have inconsistent types: expected [], got [i64] + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:424: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.15.wasm:0000026: error: type mismatch in return_call_indirect, expected [i32] but got [] + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:432: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.16.wasm:0000027: error: type mismatch in return_call_indirect, expected [f64, i32] but got [] + 0000027: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:455: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.19.wasm:0000027: error: type mismatch in return_call_indirect, expected [i32] but got [] + 0000027: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:463: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.20.wasm:0000028: error: type mismatch in return_call_indirect, expected [i32] but got [... i64] + 0000028: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:472: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.21.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32] + 000002a: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:482: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.22.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32] + 000002a: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:492: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.23.wasm:0000032: error: type mismatch in return_call_indirect, expected [i32, f64] but got [f64, i32] + 0000032: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:502: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.24.wasm:0000032: error: type mismatch in return_call_indirect, expected [f64, i32] but got [i32, f64] + 0000032: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:512: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.25.wasm:0000034: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000034: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:526: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.26.wasm:0000022: error: function type variable out of range: 1 (max 1) + 0000022: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:533: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.27.wasm:0000026: error: function type variable out of range: 1012321300 (max 1) + 0000026: error: OnReturnCallIndirectExpr callback failed +out/test/spec/gc/return_call_indirect.wast:544: assert_invalid passed: + out/test/spec/gc/return_call_indirect/return_call_indirect.28.wasm:0000019: error: function variable out of range: 0 (max 0) + 0000019: error: OnRefFuncExpr callback failed +76/76 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/return_call_ref.txt b/test/spec/gc/return_call_ref.txt new file mode 100644 index 0000000000..63049467c6 --- /dev/null +++ b/test/spec/gc/return_call_ref.txt @@ -0,0 +1,44 @@ +;;; SLOW: +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/return_call_ref.wast +;;; ARGS*: --enable-gc --enable-tail-call +(;; STDOUT ;;; +out/test/spec/gc/return_call_ref.wast:183: assert_trap passed: null function reference +out/test/spec/gc/return_call_ref.wast:232: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.2.wasm:000002d: error: return signatures have inconsistent types: expected [(ref 0)], got [(ref null 0)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:243: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.3.wasm:000002d: error: return signatures have inconsistent types: expected [(ref 0)], got [(ref func)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:254: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.4.wasm:000002c: error: return signatures have inconsistent types: expected [(ref 0)], got [funcref] + 000002c: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:265: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.5.wasm:000002d: error: return signatures have inconsistent types: expected [(ref null 0)], got [(ref func)] + 000002d: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:276: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.6.wasm:000002c: error: return signatures have inconsistent types: expected [(ref null 0)], got [funcref] + 000002c: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:287: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.7.wasm:0000029: error: return signatures have inconsistent types: expected [(ref func)], got [funcref] + 0000029: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:306: assert_trap passed: unreachable executed +out/test/spec/gc/return_call_ref.wast:319: assert_trap passed: unreachable executed +out/test/spec/gc/return_call_ref.wast:334: assert_trap passed: unreachable executed +out/test/spec/gc/return_call_ref.wast:337: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.11.wasm:0000042: error: type mismatch in return_call, expected [i32] but got [i64] + 0000042: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:353: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.12.wasm:0000043: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000043: error: EndFunctionBody callback failed +out/test/spec/gc/return_call_ref.wast:369: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.13.wasm:000001f: error: type mismatch in return_call_ref, expected [(ref null 0)] but got [externref] + 000001f: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:379: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.14.wasm:000001f: error: type mismatch in return_call_ref, expected [(ref null 0)] but got [funcref] + 000001f: error: OnReturnCallRefExpr callback failed +out/test/spec/gc/return_call_ref.wast:389: assert_invalid passed: + out/test/spec/gc/return_call_ref/return_call_ref.15.wasm:0000023: error: return signatures have inconsistent types: expected [i32], got [i32, i32] + 0000023: error: OnReturnCallRefExpr callback failed +51/51 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/select.txt b/test/spec/gc/select.txt new file mode 100644 index 0000000000..e53fe1677f --- /dev/null +++ b/test/spec/gc/select.txt @@ -0,0 +1,102 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/select.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/select.wast:282: assert_trap passed: unreachable executed +out/test/spec/gc/select.wast:283: assert_trap passed: unreachable executed +out/test/spec/gc/select.wast:284: assert_trap passed: unreachable executed +out/test/spec/gc/select.wast:285: assert_trap passed: unreachable executed +out/test/spec/gc/select.wast:322: assert_trap passed: undefined table index +out/test/spec/gc/select.wast:323: assert_trap passed: undefined table index +out/test/spec/gc/select.wast:364: assert_invalid passed: + out/test/spec/gc/select/select.1.wasm:000001c: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:368: assert_invalid passed: + out/test/spec/gc/select/select.2.wasm:000001c: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:372: assert_invalid passed: + out/test/spec/gc/select/select.3.wasm:0000027: error: invalid arity in select instruction: 2. + 0000027: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:384: assert_invalid passed: + out/test/spec/gc/select/select.4.wasm:0000023: error: type mismatch in select, expected [any, any, i32] but got [(ref 0), (ref 0), i32] + 0000023: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:392: assert_invalid passed: + out/test/spec/gc/select/select.5.wasm:000001f: error: type mismatch in select, expected [any, any, i32] but got [funcref, funcref, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:398: assert_invalid passed: + out/test/spec/gc/select/select.6.wasm:000001f: error: type mismatch in select, expected [any, any, i32] but got [externref, externref, i32] + 000001f: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:408: assert_invalid passed: + out/test/spec/gc/select/select.8.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:414: assert_invalid passed: + out/test/spec/gc/select/select.9.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:420: assert_invalid passed: + out/test/spec/gc/select/select.10.wasm:0000025: error: type mismatch in select, expected [f64, f64, i32] but got [i32, f64, i32] + 0000025: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:427: assert_invalid passed: + out/test/spec/gc/select/select.11.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:431: assert_invalid passed: + out/test/spec/gc/select/select.12.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:435: assert_invalid passed: + out/test/spec/gc/select/select.13.wasm:000001e: error: type mismatch in select, expected [i64, i64, i32] but got [i32, i64, i32] + 000001e: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:439: assert_invalid passed: + out/test/spec/gc/select/select.14.wasm:0000021: error: type mismatch in select, expected [f32, f32, i32] but got [i32, f32, i32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:443: assert_invalid passed: + out/test/spec/gc/select/select.15.wasm:0000025: error: type mismatch in select, expected [f64, f64, i32] but got [i32, f64, i32] + 0000025: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:449: assert_invalid passed: + out/test/spec/gc/select/select.16.wasm:0000018: error: type mismatch in select, expected [any, any, i32] but got [] + 0000018: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:457: assert_invalid passed: + out/test/spec/gc/select/select.17.wasm:000001a: error: type mismatch in select, expected [any, any, i32] but got [i32] + 000001a: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:465: assert_invalid passed: + out/test/spec/gc/select/select.18.wasm:000001c: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 000001c: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:473: assert_invalid passed: + out/test/spec/gc/select/select.19.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:482: assert_invalid passed: + out/test/spec/gc/select/select.20.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:491: assert_invalid passed: + out/test/spec/gc/select/select.21.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:500: assert_invalid passed: + out/test/spec/gc/select/select.22.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:509: assert_invalid passed: + out/test/spec/gc/select/select.23.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:518: assert_invalid passed: + out/test/spec/gc/select/select.24.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:527: assert_invalid passed: + out/test/spec/gc/select/select.25.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:536: assert_invalid passed: + out/test/spec/gc/select/select.26.wasm:0000020: error: type mismatch in select, expected [any, any, i32] but got [i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:545: assert_invalid passed: + out/test/spec/gc/select/select.27.wasm:0000020: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32] + 0000020: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:557: assert_invalid passed: + out/test/spec/gc/select/select.28.wasm:000001e: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, i64] + 000001e: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:561: assert_invalid passed: + out/test/spec/gc/select/select.29.wasm:0000021: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, f32] + 0000021: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:565: assert_invalid passed: + out/test/spec/gc/select/select.30.wasm:0000025: error: type mismatch in select, expected [i32, i32, i32] but got [i32, i32, f64] + 0000025: error: OnSelectExpr callback failed +out/test/spec/gc/select.wast:572: assert_invalid passed: + out/test/spec/gc/select/select.31.wasm:0000020: error: type mismatch in implicit return, expected [i32] but got [i64] + 0000020: error: EndFunctionBody callback failed +157/157 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/table.txt b/test/spec/gc/table.txt new file mode 100644 index 0000000000..e54ab19bf3 --- /dev/null +++ b/test/spec/gc/table.txt @@ -0,0 +1,75 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/table.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/table.wast:22: assert_invalid passed: + out/test/spec/gc/table/table.15.wasm:000000c: error: table variable out of range: 0 (max 0) + 000000c: error: BeginElemSegment callback failed +out/test/spec/gc/table.wast:23: assert_invalid passed: + out/test/spec/gc/table/table.16.wasm:0000016: error: table variable out of range: 0 (max 0) + 0000016: error: BeginElemSegment callback failed +out/test/spec/gc/table.wast:27: assert_invalid passed: + out/test/spec/gc/table/table.17.wasm:000000f: error: max elems (0) must be >= initial elems (1) + 000000f: error: BeginTable callback failed +out/test/spec/gc/table.wast:31: assert_invalid passed: + out/test/spec/gc/table/table.18.wasm:0000013: error: max elems (0) must be >= initial elems (4294967295) + 0000013: error: BeginTable callback failed +out/test/spec/gc/table.wast:36: assert_malformed passed: + out/test/spec/gc/table/table.19.wat:1:8: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/gc/table.wast:40: assert_malformed passed: + out/test/spec/gc/table/table.20.wat:1:8: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ + out/test/spec/gc/table/table.20.wat:1:22: error: invalid int "0x1_0000_0000" + (table 0x1_0000_0000 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/gc/table.wast:44: assert_malformed passed: + out/test/spec/gc/table/table.21.wat:1:10: error: invalid int "0x1_0000_0000" + (table 0 0x1_0000_0000 funcref) + ^^^^^^^^^^^^^ +out/test/spec/gc/table.wast:49: assert_invalid passed: + out/test/spec/gc/table/table.22.wasm:0000012: error: type mismatch in initializer expression, expected [funcref] but got [i32] + 0000013: error: EndTableInitExpr callback failed +out/test/spec/gc/table.wast:53: assert_invalid passed: + out/test/spec/gc/table/table.23.wasm:0000013: error: type mismatch in initializer expression, expected [(ref func)] but got [externref] + 0000014: error: EndTableInitExpr callback failed +out/test/spec/gc/table.wast:57: assert_invalid passed: + out/test/spec/gc/table/table.24.wasm:0000019: error: type mismatch in initializer expression, expected [(ref 0)] but got [funcref] + 000001a: error: EndTableInitExpr callback failed +out/test/spec/gc/table.wast:61: assert_invalid passed: + out/test/spec/gc/table/table.25.wasm:0000013: error: type mismatch in initializer expression, expected [(ref func)] but got [funcref] + 0000014: error: EndTableInitExpr callback failed +out/test/spec/gc/table.wast:65: assert_invalid passed: + out/test/spec/gc/table/table.26.wasm:000000f: error: missing table initializer + 000000f: error: BeginTable callback failed +out/test/spec/gc/table.wast:69: assert_invalid passed: + out/test/spec/gc/table/table.27.wasm:000000f: error: missing table initializer + 000000f: error: BeginTable callback failed +out/test/spec/gc/table.wast:73: assert_invalid passed: + out/test/spec/gc/table/table.28.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/gc/table.wast:114: assert_invalid passed: + out/test/spec/gc/table/table.31.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/gc/table.wast:122: assert_invalid passed: + out/test/spec/gc/table/table.32.wasm:0000015: error: missing table initializer + 0000015: error: BeginTable callback failed +out/test/spec/gc/table.wast:130: assert_invalid passed: + out/test/spec/gc/table/table.33.wasm:0000016: error: missing table initializer + 0000016: error: BeginTable callback failed +out/test/spec/gc/table.wast:141: assert_malformed passed: + out/test/spec/gc/table/table.34.wat:1:24: error: redefinition of table "$foo" + (table $foo 1 funcref)(table $foo 1 funcref) + ^^^^^ +out/test/spec/gc/table.wast:148: assert_malformed passed: + out/test/spec/gc/table/table.35.wat:1:39: error: redefinition of table "$foo" + (import "" "" (table $foo 1 funcref))(table $foo 1 funcref) + ^^^^^ +out/test/spec/gc/table.wast:155: assert_malformed passed: + out/test/spec/gc/table/table.36.wat:1:39: error: redefinition of table "$foo" + (import "" "" (table $foo 1 funcref))(import "" "" (table $foo 1 funcref)) + ^^^^^^ +42/42 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/gc/type-subtyping.txt b/test/spec/gc/type-subtyping.txt new file mode 100644 index 0000000000..3bc53d53ce --- /dev/null +++ b/test/spec/gc/type-subtyping.txt @@ -0,0 +1,82 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/gc/type-subtyping.wast +;;; ARGS*: --enable-gc +(;; STDOUT ;;; +out/test/spec/gc/type-subtyping.wast:140: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.10.wasm:0000043: error: type mismatch in initializer expression, expected [(ref 4)] but got [(ref 6)] + 0000044: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-subtyping.wast:206: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.15.wasm:0000031: error: type mismatch in initializer expression, expected [(ref 0)] but got [(ref 2)] + 0000032: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-subtyping.wast:216: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.16.wasm:000003e: error: type mismatch in initializer expression, expected [(ref 2)] but got [(ref 4)] + 000003f: error: EndGlobalInitExpr callback failed +out/test/spec/gc/type-subtyping.wast:283: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:284: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:285: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:286: assert_trap passed: type error: invalid type cast +out/test/spec/gc/type-subtyping.wast:287: assert_trap passed: type error: invalid type cast +out/test/spec/gc/type-subtyping.wast:288: assert_trap passed: type error: invalid type cast +out/test/spec/gc/type-subtyping.wast:314: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:315: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:316: assert_trap passed: type error: invalid type cast +out/test/spec/gc/type-subtyping.wast:317: assert_trap passed: type error: invalid type cast +out/test/spec/gc/type-subtyping.wast:345: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:346: assert_trap passed: indirect call signature mismatch +out/test/spec/gc/type-subtyping.wast:511: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:521: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:531: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:549: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:557: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:606: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:699: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:714: assert_unlinkable passed: + error: import signature mismatch +out/test/spec/gc/type-subtyping.wast:727: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.55.wasm:0000014: error: sub type 0 has final property + 0000014: error: OnFuncType callback failed +out/test/spec/gc/type-subtyping.wast:735: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.56.wasm:0000012: error: sub type 0 has final property + 0000012: error: OnStructType callback failed +out/test/spec/gc/type-subtyping.wast:743: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.57.wasm:0000014: error: sub type 0 has final property + 0000014: error: OnFuncType callback failed +out/test/spec/gc/type-subtyping.wast:751: assert_invalid passed: + out/test/spec/gc/type-subtyping/type-subtyping.58.wasm:000001c: error: sub type 1 has final property + 000001c: error: OnFuncType callback failed +out/test/spec/gc/type-subtyping.wast:764: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000015: error: OnStructType callback failed +out/test/spec/gc/type-subtyping.wast:772: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000017: error: OnStructType callback failed +out/test/spec/gc/type-subtyping.wast:780: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000015: error: OnArrayType callback failed +out/test/spec/gc/type-subtyping.wast:788: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnArrayType callback failed +out/test/spec/gc/type-subtyping.wast:796: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000017: error: OnFuncType callback failed +out/test/spec/gc/type-subtyping.wast:804: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnFuncType callback failed +out/test/spec/gc/type-subtyping.wast:812: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000016: error: OnArrayType callback failed +out/test/spec/gc/type-subtyping.wast:820: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000018: error: OnStructType callback failed +out/test/spec/gc/type-subtyping.wast:828: assert_invalid passed: + 0000000: error: sub type 0 does not match super type 1 + 0000017: error: OnFuncType callback failed +91/91 tests passed. +;;; STDOUT ;;) diff --git a/test/spec/memory64/call_indirect.txt b/test/spec/memory64/call_indirect.txt index 704d7ca2ee..95bd436867 100644 --- a/test/spec/memory64/call_indirect.txt +++ b/test/spec/memory64/call_indirect.txt @@ -87,7 +87,6 @@ out/test/spec/memory64/call_indirect.wast:786: assert_malformed passed: ^^^^^^^^^^^^^ out/test/spec/memory64/call_indirect.wast:801: assert_invalid passed: out/test/spec/memory64/call_indirect/call_indirect.13.wasm:000001c: error: table variable out of range: 0 (max 0) - out/test/spec/memory64/call_indirect/call_indirect.13.wasm:000001c: error: type mismatch: call_indirect must reference table of funcref type 000001c: error: OnCallIndirectExpr callback failed out/test/spec/memory64/call_indirect.wast:809: assert_invalid passed: out/test/spec/memory64/call_indirect/call_indirect.14.wasm:0000023: error: type mismatch in i32.eqz, expected [i32] but got []