diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 4a031f74bb..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; @@ -96,9 +103,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; @@ -174,6 +185,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; @@ -181,7 +194,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; @@ -218,12 +231,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; @@ -424,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 fdb7d14a41..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 */ @@ -121,11 +130,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 */ @@ -241,6 +254,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 { @@ -250,7 +265,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; } @@ -299,6 +314,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 +324,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 94b19c1100..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 */ @@ -156,9 +168,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 */ @@ -250,12 +266,14 @@ 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; 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; @@ -294,6 +312,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 +322,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/interp/interp-inl.h b/include/wabt/interp/interp-inl.h index a9ac4a3488..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) {} + : 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 @@ -422,12 +445,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 +699,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 9ce7b1815e..71434edc64 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, @@ -174,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; @@ -182,8 +200,21 @@ 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 + // types are also needed for type equality comparisons. + // An example for these comparisons is import validation. + std::vector* func_types; }; struct TableType : ExternType { @@ -330,6 +361,7 @@ struct FuncDesc { struct TableDesc { TableType type; + FuncDesc init_func; }; struct MemoryDesc { @@ -814,7 +846,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; @@ -846,7 +878,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 5fa4439a0c..d220bd3c69 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 { @@ -269,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); @@ -279,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_; }; @@ -295,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(); } @@ -325,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; }; @@ -337,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(); } @@ -366,6 +419,8 @@ enum class ExprType { Block, Br, BrIf, + BrOnNonNull, + BrOnNull, BrTable, Call, CallIndirect, @@ -390,6 +445,7 @@ enum class ExprType { MemoryInit, MemorySize, Nop, + RefAsNonNull, RefIsNull, RefFunc, RefNull, @@ -397,6 +453,7 @@ enum class ExprType { Return, ReturnCall, ReturnCallIndirect, + ReturnCallRef, Select, SimdLaneOp, SimdLoadLane, @@ -537,10 +594,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; @@ -560,6 +617,7 @@ using CompareExpr = OpcodeExpr; using ConvertExpr = OpcodeExpr; using UnaryExpr = OpcodeExpr; using TernaryExpr = OpcodeExpr; +using RefAsNonNullExpr = OpcodeExpr; class SimdLaneOpExpr : public ExprMixin { public: @@ -639,6 +697,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; @@ -662,8 +722,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 +787,15 @@ 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; +}; + +class ReturnCallRefExpr : public ExprMixin { + public: + explicit ReturnCallRefExpr(const Location& loc = Location()) + : ExprMixin(loc) {} + + Var sig_type; }; template @@ -946,13 +1012,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; @@ -1065,7 +1132,8 @@ enum class ModuleFieldType { Memory, DataSegment, Start, - Tag + Tag, + EmptyRec }; class ModuleField : public intrusive_list_base { @@ -1192,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()) @@ -1251,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); @@ -1277,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/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 267a77b276..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,6 +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? @@ -62,20 +65,31 @@ 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); - Result EndTypeSection(); + 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&); + 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_); @@ -136,12 +150,14 @@ 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&); 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); @@ -176,12 +192,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&, 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); + 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); @@ -221,32 +239,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) {} - - 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) {} @@ -289,13 +281,22 @@ 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&, 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, @@ -336,6 +337,12 @@ class SharedValidator { TypeVector ToTypeVector(Index count, const Type* types); + void SaveLocalRefs(); + void RestoreLocalRefs(Result result); + void IgnoreLocalRefs(); + + Index GetEndIndex(); + ValidateOptions options_; Errors* errors_; TypeChecker typechecker_; // TODO: Move into SharedValidator. @@ -343,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. @@ -357,10 +361,15 @@ 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. 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..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") @@ -55,18 +55,20 @@ 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") 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") @@ -98,11 +100,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") @@ -129,6 +134,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") @@ -177,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 85575c3c8b..c2b4e5ef4d 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -20,17 +20,115 @@ #include #include #include +#include #include "wabt/common.h" #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, + 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) {} + + 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, @@ -46,9 +144,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, TypeFields& type_fields) + : features_(features), type_fields_(type_fields) {} void set_error_callback(const ErrorCallback& error_callback) { error_callback_ = error_callback; @@ -73,6 +173,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(); @@ -80,11 +182,12 @@ 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, const TypeVector& result_types); + Result OnReturnCallRef(Type); Result OnCatch(const TypeVector& sig); Result OnCompare(Opcode); Result OnConst(Type); @@ -115,7 +218,8 @@ 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 OnRefAsNonNullExpr(); Result OnRefNullExpr(Type type); Result OnRefIsNullExpr(); Result OnRethrow(Index depth); @@ -141,7 +245,13 @@ class TypeChecker { Result BeginInitExpr(Type type); Result EndInitExpr(); - static Result CheckType(Type actual, Type expected); + 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: void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* fmt, ...); @@ -178,6 +288,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, @@ -186,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 << 6) + (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 @@ -210,6 +333,7 @@ class TypeChecker { // to represent "any". TypeVector* br_table_sig_ = nullptr; Features features_; + TypeFields& type_fields_; }; } // namespace wabt diff --git a/include/wabt/type.h b/include/wabt/type.h index 30234166b3..72a57827b4 100644 --- a/include/wabt/type.h +++ b/include/wabt/type.h @@ -40,15 +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 @@ -58,17 +70,29 @@ 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))); + } + Type(Enum e, bool is_nullable) + : enum_(e), type_index_(is_nullable ? ReferenceOrNull : ReferenceNonNull) { + assert(IsNonTypedRef()); } + constexpr operator Enum() const { return enum_; } friend constexpr bool operator==(const Type a, const Type b) { @@ -89,15 +113,34 @@ class Type { } bool IsRef() const { - return enum_ == Type::ExternRef || enum_ == Type::FuncRef || - enum_ == Type::Reference || enum_ == Type::ExnRef; + 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::ExnRef || enum_ == Type::RefNull || + (EnumIsNonTypedRef(enum_) && type_index_ == ReferenceOrNull); + } + + bool IsNonNullableRef() const { + return enum_ == Type::Ref || + (EnumIsNonTypedRef(enum_) && 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 +153,38 @@ 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::Struct: return "struct"; + case Type::Array: return "array"; case Type::Void: return "void"; case Type::Any: return "any"; - case Type::ExternRef: return "externref"; - case Type::Reference: + 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::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: + return StringPrintf("(ref null %d)", type_index_); default: return StringPrintf("", enum_); } @@ -124,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 ""; } } @@ -153,10 +228,14 @@ class Type { } Index GetReferenceIndex() const { - assert(enum_ == Enum::Reference); + assert(IsReferenceWithIndex()); return type_index_; } + bool IsPackedType() const { + return enum_ == Type::I8 || enum_ == Type::I16; + } + TypeVector GetInlineVector() const { assert(!IsIndex()); switch (enum_) { @@ -168,10 +247,19 @@ 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); default: @@ -179,11 +267,48 @@ class Type { } } - private: static bool EnumIsReferenceWithIndex(Enum value) { - return value == Type::Reference; + 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 || + 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 7a60af23b5..330a784a10 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; @@ -83,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 @@ -162,13 +178,14 @@ class WastParser { bool ParseElemExprOpt(ExprList* out_elem_expr); bool ParseElemExprListOpt(ExprListVector* out_list); bool ParseElemExprVarListOpt(ExprListVector* out_list); - Result ParseValueType(Var* out_type); + Result ParseRefDeclaration(Var* out_type); + Result ParseValueType(Var* out_type, bool is_field = false); 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 +195,11 @@ 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*); + static Result ResolveTargetFieldVector(const Module&, StructType*, + ReferenceVars*, Errors* errors); Result ParseModuleFieldList(Module*); Result ParseModuleField(Module*); Result ParseDataModuleField(Module*); @@ -188,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*); @@ -238,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*); @@ -288,25 +309,34 @@ 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_; + + // 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 { diff --git a/src/apply-names.cc b/src/apply-names.cc index c8516c8cd9..ab91fa42a4 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; @@ -100,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); @@ -350,6 +353,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); @@ -545,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)); @@ -580,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 2029b0f7c4..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, @@ -144,9 +151,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, @@ -200,6 +210,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; @@ -207,9 +219,10 @@ 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 OnReturnCallRefExpr(Type sig_type) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; Result OnDelegateExpr(Index depth) override; @@ -246,6 +259,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; @@ -516,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; @@ -532,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); @@ -558,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; @@ -573,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); @@ -696,9 +729,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; @@ -708,6 +742,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); @@ -897,6 +941,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) { @@ -920,8 +973,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) { @@ -951,6 +1006,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)); } @@ -1145,6 +1206,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( @@ -1153,7 +1219,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 +1239,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..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, @@ -255,14 +277,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, @@ -320,6 +343,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) { @@ -793,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) @@ -806,6 +840,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) @@ -842,7 +879,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) @@ -871,6 +908,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 +917,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-objdump.cc b/src/binary-reader-objdump.cc index 34ba068708..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; } @@ -901,7 +902,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()); @@ -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, @@ -1127,9 +1134,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 +1184,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 +1321,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 +1334,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_; } }; @@ -1446,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(", "); @@ -1486,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"); @@ -1504,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"); } @@ -1697,9 +1738,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 +1964,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 6828435385..9ec149d26d 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); @@ -194,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_; @@ -365,10 +367,27 @@ 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 || + (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); + } else { + *out_value = + Type(static_cast(type), static_cast(heap_type)); + } } else { *out_value = static_cast(type); } @@ -540,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)); @@ -552,6 +572,30 @@ 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(); + + 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; + } +} + bool BinaryReader::IsConcreteType(Type type) { switch (type) { case Type::I32: @@ -563,18 +607,12 @@ 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); } } @@ -815,6 +853,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")); @@ -1902,6 +1956,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")); @@ -1911,8 +1970,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 +1997,25 @@ 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; + } + + 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); @@ -2527,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")); @@ -2538,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")); - case Type::Array: { - ERROR_UNLESS(options_.features.gc_enabled(), - "invalid type form: array not allowed"); + 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; + } - TypeMut field; - CHECK_RESULT(ReadField(&field)); - CALLBACK(OnArrayType, i, field); + case Type::Array: { + ERROR_UNLESS(options_.features.gc_enabled(), + "invalid type form: array not allowed"); + + 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); @@ -2711,8 +2849,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; @@ -2803,6 +2965,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)) { @@ -2821,7 +2988,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 600154b941..b4f41f98d4 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()); } } @@ -759,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); @@ -795,10 +809,6 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteTableNumberWithReloc(table_index, "table index"); break; } - case ExprType::CallRef: { - WriteOpcode(stream_, Opcode::CallRef); - break; - } case ExprType::ReturnCallIndirect: { Index sig_index = module_->GetFuncTypeIndex(cast(expr)->decl); @@ -810,6 +820,23 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { WriteTableNumberWithReloc(table_index, "table index"); break; } + 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::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); + break; + } case ExprType::Compare: WriteOpcode(stream_, cast(expr)->opcode); break; @@ -1003,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); @@ -1011,7 +1042,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: @@ -1186,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) { @@ -1359,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; + } } } } @@ -1575,7 +1698,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/c-writer.cc b/src/c-writer.cc index da58d1c951..8fc565ae7e 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"); } @@ -3610,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()); @@ -3944,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); @@ -3973,10 +3993,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: @@ -4282,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/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 9eb54d45da..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, @@ -123,9 +133,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, @@ -182,16 +195,20 @@ 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; 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; 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; @@ -219,6 +236,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; @@ -320,6 +338,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); @@ -327,6 +348,8 @@ class BinaryReaderInterp : public BinaryReaderNop { Index num_func_imports() const; + void UpdateTypeInfo(GCTypeExtension* gc_ext); + Errors* errors_ = nullptr; ModuleDesc& module_; Istream& istream_; @@ -340,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. @@ -471,6 +496,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); } @@ -496,18 +540,106 @@ 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) { - CHECK_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; } @@ -531,7 +663,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())}); @@ -600,16 +733,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; @@ -1106,16 +1256,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, @@ -1174,6 +1330,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()))); @@ -1231,6 +1395,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); @@ -1396,6 +1568,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()))); @@ -1404,7 +1582,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..6c7d892f4f 100644 --- a/src/interp/interp-util.cc +++ b/src/interp/interp-util.cc @@ -58,10 +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-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 cc4415fb9f..d5eae194c4 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -94,16 +94,139 @@ std::unique_ptr FuncType::Clone() const { return std::make_unique(*this); } +static bool RecursiveMatch(Type expected, + Index expected_recursive_start, + std::vector* expected_func_types, + Type actual, + Index actual_recursive_start, + std::vector* actual_func_types) { + assert(expected_func_types != nullptr && actual_func_types != nullptr); + + if (!expected.IsReferenceWithIndex()) { + return expected == actual; + } else if (!actual.IsReferenceWithIndex()) { + return false; + } + + 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; + } + + // 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; + } + + 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; + } + + size_t size = expected_rec_type.params.size(); + if (size != actual_rec_type.params.size()) { + return false; + } + + 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; + } + } + + 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; +} + 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"; + 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; + + do { + Type actual_type(Type::Ref, actual_index); + + if (RecursiveMatch(expected_type, kInvalidIndex, expected.func_types, + actual_type, kInvalidIndex, actual.func_types)) { + return Result::Ok; + } + + actual_index = ((*actual.func_types)[actual_index]).canonical_sub_index; + } while (actual_index != kInvalidIndex); } - return Result::Error; } - return Result::Ok; + + if (out_msg) { + *out_msg = "import signature mismatch"; + } + return Result::Error; } //// TableType //// @@ -189,6 +312,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) { @@ -237,6 +384,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: @@ -474,8 +623,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) { @@ -756,10 +909,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; } } @@ -823,7 +992,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. @@ -1208,6 +1386,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) { @@ -1249,6 +1446,19 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) { } } + 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}; + + if (instr.op == O::ReturnCallRef) { + return DoReturnCall(new_func, out_trap); + } else { + return DoCall(new_func, out_trap); + } + } + case O::Drop: Pop(); break; @@ -1583,6 +1793,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; @@ -2001,7 +2215,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/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 5266a26457..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}; @@ -140,7 +150,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)}; } @@ -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 a2f9c48e0c..346869c751 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", @@ -107,7 +111,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 { @@ -325,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; @@ -398,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()) { @@ -541,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; } } @@ -591,10 +637,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 +666,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 +677,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,13 +706,40 @@ 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_); } } -uint8_t ElemSegment::GetFlags(const Module* module) const { +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; switch (kind) { @@ -671,15 +760,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/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..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 @@ -31,6 +34,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 @@ -53,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 @@ -183,13 +190,15 @@ 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 +final, TokenType::Final func, Type::FuncRef, TokenType::Func +funcref, Type::FuncRef function, TokenType::Function 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 @@ -242,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 @@ -494,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 @@ -555,13 +567,22 @@ 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 ref.extern, TokenType::RefExtern ref.func, TokenType::RefFunc, Opcode::RefFunc ref.is_null, TokenType::RefIsNull, Opcode::RefIsNull @@ -570,12 +591,15 @@ 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 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/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 89f14dbaca..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,1616 +158,1710 @@ Perfect_Hash::InWordSet (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 601, + 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 35 "src/lexer-keywords.txt" + {""}, {""}, +#line 40 "src/lexer-keywords.txt" {"br", TokenType::Br, Opcode::Br}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 152 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, +#line 159 "src/lexer-keywords.txt" {"f64", Type::F64}, - {""}, {""}, -#line 45 "src/lexer-keywords.txt" - {"data", TokenType::Data}, - {""}, {""}, {""}, -#line 464 "src/lexer-keywords.txt" + {""}, +#line 475 "src/lexer-keywords.txt" {"i64", Type::I64}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 122 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 129 "src/lexer-keywords.txt" {"f32x4", TokenType::F32X4}, - {""}, {""}, {""}, {""}, -#line 586 "src/lexer-keywords.txt" - {"table", TokenType::Table}, -#line 48 "src/lexer-keywords.txt" - {"do", TokenType::Do}, -#line 364 "src/lexer-keywords.txt" + {""}, +#line 375 "src/lexer-keywords.txt" {"i32x4", TokenType::I32X4}, - {""}, {""}, {""}, -#line 135 "src/lexer-keywords.txt" - {"f64.ge", TokenType::Compare, Opcode::F64Ge}, -#line 74 "src/lexer-keywords.txt" - {"f32.ge", TokenType::Compare, Opcode::F32Ge}, -#line 137 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 144 "src/lexer-keywords.txt" {"f64.le", TokenType::Compare, Opcode::F64Le}, -#line 76 "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 187 "src/lexer-keywords.txt" - {"func", Type::FuncRef, TokenType::Func}, -#line 136 "src/lexer-keywords.txt" - {"f64.gt", TokenType::Compare, Opcode::F64Gt}, -#line 75 "src/lexer-keywords.txt" - {"f32.gt", TokenType::Compare, Opcode::F32Gt}, -#line 139 "src/lexer-keywords.txt" + {""}, {""}, {""}, +#line 146 "src/lexer-keywords.txt" {"f64.lt", TokenType::Compare, Opcode::F64Lt}, -#line 78 "src/lexer-keywords.txt" +#line 85 "src/lexer-keywords.txt" {"f32.lt", TokenType::Compare, Opcode::F32Lt}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 43 "src/lexer-keywords.txt" - {"code", TokenType::Code}, - {""}, {""}, {""}, -#line 570 "src/lexer-keywords.txt" +#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" + {"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 100 "src/lexer-keywords.txt" +#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" + {"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 102 "src/lexer-keywords.txt" - {"f32x4.le", TokenType::Compare, Opcode::F32X4Le}, +#line 100 "src/lexer-keywords.txt" + {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, {""}, -#line 578 "src/lexer-keywords.txt" - {"struct", Type::Struct, TokenType::Struct}, - {""}, {""}, {""}, {""}, {""}, -#line 555 "src/lexer-keywords.txt" - {"mut", TokenType::Mut}, -#line 441 "src/lexer-keywords.txt" - {"i64.or", TokenType::Binary, Opcode::I64Or}, -#line 298 "src/lexer-keywords.txt" - {"i32.or", TokenType::Binary, Opcode::I32Or}, - {""}, {""}, -#line 581 "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" - {"table.set", TokenType::TableSet, Opcode::TableSet}, -#line 103 "src/lexer-keywords.txt" - {"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt}, -#line 330 "src/lexer-keywords.txt" - {"i32x4.ge_u", TokenType::Compare, Opcode::I32X4GeU}, +#line 116 "src/lexer-keywords.txt" + {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, {""}, -#line 334 "src/lexer-keywords.txt" - {"i32x4.le_u", TokenType::Compare, Opcode::I32X4LeU}, +#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 329 "src/lexer-keywords.txt" - {"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS}, -#line 93 "src/lexer-keywords.txt" - {"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil}, -#line 333 "src/lexer-keywords.txt" +#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 332 "src/lexer-keywords.txt" - {"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU}, - {""}, +#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.lt_u", TokenType::Compare, Opcode::I32X4LtU}, - {""}, -#line 331 "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 341 "src/lexer-keywords.txt" - {"i32x4.lt_s", TokenType::Compare, Opcode::I32X4LtS}, -#line 145 "src/lexer-keywords.txt" - {"f64.ne", TokenType::Compare, Opcode::F64Ne}, -#line 84 "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 554 "src/lexer-keywords.txt" - {"module", TokenType::Module}, - {""}, -#line 440 "src/lexer-keywords.txt" - {"i64.ne", TokenType::Compare, Opcode::I64Ne}, -#line 297 "src/lexer-keywords.txt" - {"i32.ne", TokenType::Compare, Opcode::I32Ne}, -#line 46 "src/lexer-keywords.txt" - {"declare", TokenType::Declare}, +#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" + {"table", TokenType::Table}, + {""}, {""}, {""}, {""}, {""}, +#line 567 "src/lexer-keywords.txt" + {"mut", TokenType::Mut}, {""}, -#line 144 "src/lexer-keywords.txt" - {"f64.neg", TokenType::Unary, Opcode::F64Neg}, -#line 83 "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 149 "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 87 "src/lexer-keywords.txt" +#line 94 "src/lexer-keywords.txt" {"f32.store", TokenType::Store, Opcode::F32Store}, - {""}, -#line 447 "src/lexer-keywords.txt" - {"i64.rotr", TokenType::Binary, Opcode::I64Rotr}, -#line 304 "src/lexer-keywords.txt" - {"i32.rotr", TokenType::Binary, Opcode::I32Rotr}, -#line 446 "src/lexer-keywords.txt" - {"i64.rotl", TokenType::Binary, Opcode::I64Rotl}, -#line 303 "src/lexer-keywords.txt" - {"i32.rotl", TokenType::Binary, Opcode::I32Rotl}, -#line 454 "src/lexer-keywords.txt" +#line 465 "src/lexer-keywords.txt" {"i64.store", TokenType::Store, Opcode::I64Store}, -#line 310 "src/lexer-keywords.txt" +#line 321 "src/lexer-keywords.txt" {"i32.store", TokenType::Store, Opcode::I32Store}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 568 "src/lexer-keywords.txt" - {"ref.null", TokenType::RefNull, Opcode::RefNull}, -#line 108 "src/lexer-keywords.txt" - {"f32x4.neg", TokenType::Unary, Opcode::F32X4Neg}, {""}, -#line 109 "src/lexer-keywords.txt" - {"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne}, - {""}, {""}, {""}, {""}, -#line 349 "src/lexer-keywords.txt" - {"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg}, +#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" + {"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 350 "src/lexer-keywords.txt" - {"i32x4.ne", TokenType::Compare, Opcode::I32X4Ne}, +#line 608 "src/lexer-keywords.txt" + {"table.set", TokenType::TableSet, Opcode::TableSet}, + {""}, +#line 596 "src/lexer-keywords.txt" + {"return", TokenType::Return, Opcode::Return}, {""}, {""}, -#line 151 "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 89 "src/lexer-keywords.txt" +#line 96 "src/lexer-keywords.txt" {"f32.trunc", TokenType::Unary, Opcode::F32Trunc}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 143 "src/lexer-keywords.txt" - {"f64.nearest", TokenType::Unary, Opcode::F64Nearest}, -#line 82 "src/lexer-keywords.txt" - {"f32.nearest", TokenType::Unary, Opcode::F32Nearest}, {""}, {""}, {""}, -#line 120 "src/lexer-keywords.txt" - {"f32x4.trunc", TokenType::Unary, Opcode::F32X4Trunc}, +#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 574 "src/lexer-keywords.txt" - {"return", TokenType::Return, Opcode::Return}, + {"null", TokenType::Null}, + {""}, +#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 453 "src/lexer-keywords.txt" - {"i64.store8", TokenType::Store, Opcode::I64Store8}, -#line 309 "src/lexer-keywords.txt" - {"i32.store8", TokenType::Store, Opcode::I32Store8}, -#line 142 "src/lexer-keywords.txt" +#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 81 "src/lexer-keywords.txt" +#line 88 "src/lexer-keywords.txt" {"f32.mul", TokenType::Binary, Opcode::F32Mul}, -#line 92 "src/lexer-keywords.txt" - {"f32x4.add", TokenType::Binary, Opcode::F32X4Add}, -#line 107 "src/lexer-keywords.txt" - {"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest}, - {""}, {""}, {""}, -#line 439 "src/lexer-keywords.txt" +#line 450 "src/lexer-keywords.txt" {"i64.mul", TokenType::Binary, Opcode::I64Mul}, -#line 296 "src/lexer-keywords.txt" +#line 307 "src/lexer-keywords.txt" {"i32.mul", TokenType::Binary, Opcode::I32Mul}, -#line 323 "src/lexer-keywords.txt" - {"i32x4.add", TokenType::Binary, Opcode::I32X4Add}, - {""}, -#line 38 "src/lexer-keywords.txt" - {"call", TokenType::Call, Opcode::Call}, {""}, -#line 126 "src/lexer-keywords.txt" - {"f64.const", TokenType::Const, Opcode::F64Const}, -#line 64 "src/lexer-keywords.txt" - {"f32.const", TokenType::Const, Opcode::F32Const}, - {""}, {""}, {""}, -#line 106 "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 413 "src/lexer-keywords.txt" - {"i64.const", TokenType::Const, Opcode::I64Const}, -#line 275 "src/lexer-keywords.txt" - {"i32.const", TokenType::Const, Opcode::I32Const}, - {""}, -#line 575 "src/lexer-keywords.txt" - {"select", TokenType::Select, Opcode::Select}, - {""}, -#line 348 "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 543 "src/lexer-keywords.txt" - {"local", TokenType::Local}, - {""}, {""}, {""}, -#line 496 "src/lexer-keywords.txt" - {"i64.xor", TokenType::Binary, Opcode::I64Xor}, -#line 373 "src/lexer-keywords.txt" - {"i32.xor", TokenType::Binary, Opcode::I32Xor}, -#line 47 "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 124 "src/lexer-keywords.txt" - {"f64.add", TokenType::Binary, Opcode::F64Add}, -#line 62 "src/lexer-keywords.txt" - {"f32.add", TokenType::Binary, Opcode::F32Add}, -#line 138 "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 77 "src/lexer-keywords.txt" +#line 84 "src/lexer-keywords.txt" {"f32.load", TokenType::Load, Opcode::F32Load}, - {""}, {""}, {""}, -#line 374 "src/lexer-keywords.txt" - {"i64.add", TokenType::Binary, Opcode::I64Add}, -#line 245 "src/lexer-keywords.txt" - {"i32.add", TokenType::Binary, Opcode::I32Add}, -#line 436 "src/lexer-keywords.txt" +#line 447 "src/lexer-keywords.txt" {"i64.load", TokenType::Load, Opcode::I64Load}, -#line 293 "src/lexer-keywords.txt" +#line 304 "src/lexer-keywords.txt" {"i32.load", TokenType::Load, Opcode::I32Load}, - {""}, {""}, {""}, {""}, -#line 116 "src/lexer-keywords.txt" - {"f32x4.replace_lane", TokenType::SimdLaneOp, Opcode::F32X4ReplaceLane}, - {""}, {""}, {""}, -#line 375 "src/lexer-keywords.txt" - {"i64.and", TokenType::Binary, Opcode::I64And}, -#line 246 "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 352 "src/lexer-keywords.txt" - {"i32x4.replace_lane", TokenType::SimdLaneOp, Opcode::I32X4ReplaceLane}, +#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.max_s", TokenType::Binary, Opcode::I32X4MaxS}, {""}, {""}, {""}, -#line 425 "src/lexer-keywords.txt" - {"i64.ge_u", TokenType::Compare, Opcode::I64GeU}, -#line 284 "src/lexer-keywords.txt" - {"i32.ge_u", TokenType::Compare, Opcode::I32GeU}, -#line 429 "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 288 "src/lexer-keywords.txt" +#line 299 "src/lexer-keywords.txt" {"i32.le_u", TokenType::Compare, Opcode::I32LeU}, -#line 424 "src/lexer-keywords.txt" - {"i64.ge_s", TokenType::Compare, Opcode::I64GeS}, -#line 283 "src/lexer-keywords.txt" - {"i32.ge_s", TokenType::Compare, Opcode::I32GeS}, -#line 428 "src/lexer-keywords.txt" - {"i64.le_s", TokenType::Compare, Opcode::I64LeS}, -#line 287 "src/lexer-keywords.txt" - {"i32.le_s", TokenType::Compare, Opcode::I32LeS}, -#line 427 "src/lexer-keywords.txt" - {"i64.gt_u", TokenType::Compare, Opcode::I64GtU}, -#line 286 "src/lexer-keywords.txt" - {"i32.gt_u", TokenType::Compare, Opcode::I32GtU}, -#line 438 "src/lexer-keywords.txt" - {"i64.lt_u", TokenType::Compare, Opcode::I64LtU}, +#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 426 "src/lexer-keywords.txt" - {"i64.gt_s", TokenType::Compare, Opcode::I64GtS}, -#line 285 "src/lexer-keywords.txt" - {"i32.gt_s", TokenType::Compare, Opcode::I32GtS}, -#line 437 "src/lexer-keywords.txt" - {"i64.lt_s", TokenType::Compare, Opcode::I64LtS}, -#line 294 "src/lexer-keywords.txt" - {"i32.lt_s", TokenType::Compare, Opcode::I32LtS}, - {""}, {""}, {""}, -#line 540 "src/lexer-keywords.txt" - {"local.get", TokenType::LocalGet, Opcode::LocalGet}, - {""}, -#line 541 "src/lexer-keywords.txt" - {"local.set", TokenType::LocalSet, Opcode::LocalSet}, -#line 542 "src/lexer-keywords.txt" - {"local.tee", TokenType::LocalTee, Opcode::LocalTee}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 351 "src/lexer-keywords.txt" - {"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect}, -#line 324 "src/lexer-keywords.txt" - {"i32x4.all_true", TokenType::Unary, Opcode::I32X4AllTrue}, - {""}, -#line 125 "src/lexer-keywords.txt" - {"f64.ceil", TokenType::Unary, Opcode::F64Ceil}, -#line 63 "src/lexer-keywords.txt" - {"f32.ceil", TokenType::Unary, Opcode::F32Ceil}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 585 "src/lexer-keywords.txt" - {"table.size", TokenType::TableSize, Opcode::TableSize}, - {""}, {""}, {""}, -#line 104 "src/lexer-keywords.txt" - {"f32x4.max", TokenType::Binary, Opcode::F32X4Max}, -#line 535 "src/lexer-keywords.txt" - {"if", TokenType::If, Opcode::If}, -#line 411 "src/lexer-keywords.txt" - {"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore}, -#line 273 "src/lexer-keywords.txt" - {"i32.atomic.store", TokenType::AtomicStore, Opcode::I32AtomicStore}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 563 "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 404 "src/lexer-keywords.txt" - {"i64.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I64AtomicRmwOr}, -#line 267 "src/lexer-keywords.txt" - {"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr}, - {""}, {""}, {""}, {""}, {""}, -#line 573 "src/lexer-keywords.txt" - {"return_call", TokenType::ReturnCall, Opcode::ReturnCall}, +#line 120 "src/lexer-keywords.txt" + {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, {""}, {""}, -#line 53 "src/lexer-keywords.txt" - {"else", TokenType::Else, Opcode::Else}, - {""}, {""}, {""}, {""}, {""}, -#line 55 "src/lexer-keywords.txt" - {"tag", TokenType::Tag}, +#line 547 "src/lexer-keywords.txt" + {"if", TokenType::If, Opcode::If}, {""}, -#line 98 "src/lexer-keywords.txt" - {"f32x4.extract_lane", TokenType::SimdLaneOp, Opcode::F32X4ExtractLane}, -#line 565 "src/lexer-keywords.txt" - {"ref.extern", TokenType::RefExtern}, -#line 338 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_u_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2UZero}, -#line 90 "src/lexer-keywords.txt" +#line 97 "src/lexer-keywords.txt" {"f32", Type::F32}, -#line 337 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f64x2_s_zero", TokenType::Unary, Opcode::I32X4RelaxedTruncF64X2SZero}, - {""}, {""}, -#line 328 "src/lexer-keywords.txt" - {"i32x4.extract_lane", TokenType::SimdLaneOp, Opcode::I32X4ExtractLane}, {""}, -#line 189 "src/lexer-keywords.txt" - {"get", TokenType::Get}, -#line 320 "src/lexer-keywords.txt" +#line 331 "src/lexer-keywords.txt" {"i32", Type::I32}, -#line 50 "src/lexer-keywords.txt" - {"either", TokenType::Either}, - {""}, {""}, -#line 391 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32SubU}, -#line 435 "src/lexer-keywords.txt" - {"i64.load8_u", TokenType::Load, Opcode::I64Load8U}, -#line 292 "src/lexer-keywords.txt" - {"i32.load8_u", TokenType::Load, Opcode::I32Load8U}, -#line 434 "src/lexer-keywords.txt" - {"i64.load8_s", TokenType::Load, Opcode::I64Load8S}, -#line 291 "src/lexer-keywords.txt" - {"i32.load8_s", TokenType::Load, Opcode::I32Load8S}, - {""}, -#line 410 "src/lexer-keywords.txt" - {"i64.atomic.store8", TokenType::AtomicStore, Opcode::I64AtomicStore8}, -#line 272 "src/lexer-keywords.txt" - {"i32.atomic.store8", TokenType::AtomicStore, Opcode::I32AtomicStore8}, -#line 431 "src/lexer-keywords.txt" - {"i64.load16_u", TokenType::Load, Opcode::I64Load16U}, -#line 290 "src/lexer-keywords.txt" - {"i32.load16_u", TokenType::Load, Opcode::I32Load16U}, -#line 457 "src/lexer-keywords.txt" - {"i64.trunc_f32_u", TokenType::Convert, Opcode::I64TruncF32U}, -#line 313 "src/lexer-keywords.txt" - {"i32.trunc_f32_u", TokenType::Convert, Opcode::I32TruncF32U}, -#line 430 "src/lexer-keywords.txt" - {"i64.load16_s", TokenType::Load, Opcode::I64Load16S}, -#line 289 "src/lexer-keywords.txt" - {"i32.load16_s", TokenType::Load, Opcode::I32Load16S}, -#line 456 "src/lexer-keywords.txt" - {"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S}, -#line 312 "src/lexer-keywords.txt" - {"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S}, -#line 445 "src/lexer-keywords.txt" - {"i64.rem_u", TokenType::Binary, Opcode::I64RemU}, -#line 302 "src/lexer-keywords.txt" - {"i32.rem_u", TokenType::Binary, Opcode::I32RemU}, -#line 444 "src/lexer-keywords.txt" - {"i64.rem_s", TokenType::Binary, Opcode::I64RemS}, -#line 301 "src/lexer-keywords.txt" - {"i32.rem_s", TokenType::Binary, Opcode::I32RemS}, - {""}, -#line 54 "src/lexer-keywords.txt" - {"end", TokenType::End, Opcode::End}, - {""}, -#line 407 "src/lexer-keywords.txt" - {"i64.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I64AtomicRmwXor}, -#line 270 "src/lexer-keywords.txt" - {"i32.atomic.rmw.xor", TokenType::AtomicRmw, Opcode::I32AtomicRmwXor}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 587 "src/lexer-keywords.txt" - {"then", TokenType::Then}, -#line 583 "src/lexer-keywords.txt" - {"table.init", TokenType::TableInit, Opcode::TableInit}, - {""}, {""}, -#line 344 "src/lexer-keywords.txt" - {"i32x4.max_u", TokenType::Binary, Opcode::I32X4MaxU}, - {""}, -#line 343 "src/lexer-keywords.txt" - {"i32x4.max_s", TokenType::Binary, Opcode::I32X4MaxS}, + {""}, {""}, {""}, {""}, +#line 58 "src/lexer-keywords.txt" + {"else", TokenType::Else, Opcode::Else}, {""}, -#line 390 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32OrU}, -#line 448 "src/lexer-keywords.txt" +#line 459 "src/lexer-keywords.txt" {"i64.shl", TokenType::Binary, Opcode::I64Shl}, -#line 305 "src/lexer-keywords.txt" +#line 316 "src/lexer-keywords.txt" {"i32.shl", TokenType::Binary, Opcode::I32Shl}, - {""}, {""}, -#line 114 "src/lexer-keywords.txt" - {"f32x4.relaxed_min", TokenType::Binary, Opcode::F32X4RelaxedMin}, {""}, -#line 115 "src/lexer-keywords.txt" - {"f32x4.relaxed_nmadd", TokenType::Ternary, Opcode::F32X4RelaxedNmadd}, -#line 140 "src/lexer-keywords.txt" - {"f64.max", TokenType::Binary, Opcode::F64Max}, -#line 79 "src/lexer-keywords.txt" - {"f32.max", TokenType::Binary, Opcode::F32Max}, +#line 583 "src/lexer-keywords.txt" + {"ref", TokenType::Ref}, {""}, {""}, -#line 160 "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 162 "src/lexer-keywords.txt" - {"f64x2.le", TokenType::Compare, Opcode::F64X2Le}, - {""}, {""}, -#line 387 "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 353 "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 569 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 590 "src/lexer-keywords.txt" {"register", TokenType::Register}, -#line 379 "src/lexer-keywords.txt" - {"i64.atomic.load", TokenType::AtomicLoad, Opcode::I64AtomicLoad}, -#line 249 "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 161 "src/lexer-keywords.txt" - {"f64x2.gt", TokenType::Compare, Opcode::F64X2Gt}, -#line 388 "src/lexer-keywords.txt" +#line 399 "src/lexer-keywords.txt" {"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU}, -#line 163 "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 58 "src/lexer-keywords.txt" - {"exn", Type::ExnRef, TokenType::Exn}, - {""}, {""}, -#line 475 "src/lexer-keywords.txt" - {"i64x2.ge_s", TokenType::Binary, Opcode::I64X2GeS}, -#line 155 "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 474 "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 473 "src/lexer-keywords.txt" - {"i64x2.gt_s", TokenType::Binary, Opcode::I64X2GtS}, {""}, -#line 472 "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 99 "src/lexer-keywords.txt" - {"f32x4.floor", TokenType::Unary, Opcode::F32X4Floor}, +#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}, {""}, {""}, -#line 185 "src/lexer-keywords.txt" - {"field", TokenType::Field}, -#line 112 "src/lexer-keywords.txt" - {"f32x4.relaxed_madd", TokenType::Ternary, Opcode::F32X4RelaxedMadd}, +#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 419 "src/lexer-keywords.txt" - {"i64.extend16_s", TokenType::Unary, Opcode::I64Extend16S}, -#line 281 "src/lexer-keywords.txt" - {"i32.extend16_s", TokenType::Unary, Opcode::I32Extend16S}, +#line 611 "src/lexer-keywords.txt" + {"then", TokenType::Then}, + {""}, {""}, {""}, +#line 55 "src/lexer-keywords.txt" + {"either", TokenType::Either}, + {""}, {""}, +#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 539 "src/lexer-keywords.txt" +#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 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 570 "src/lexer-keywords.txt" + {"noextern", Type::NullExternRef, TokenType::NoExtern}, {""}, {""}, -#line 421 "src/lexer-keywords.txt" - {"i64.extend8_s", TokenType::Unary, Opcode::I64Extend8S}, -#line 282 "src/lexer-keywords.txt" - {"i32.extend8_s", TokenType::Unary, Opcode::I32Extend8S}, +#line 232 "src/lexer-keywords.txt" + {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, {""}, {""}, -#line 566 "src/lexer-keywords.txt" +#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 134 "src/lexer-keywords.txt" +#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 215 "src/lexer-keywords.txt" + {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, + {""}, {""}, {""}, {""}, +#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 73 "src/lexer-keywords.txt" +#line 80 "src/lexer-keywords.txt" {"f32.floor", TokenType::Unary, Opcode::F32Floor}, - {""}, {""}, -#line 412 "src/lexer-keywords.txt" - {"i64.clz", TokenType::Unary, Opcode::I64Clz}, -#line 274 "src/lexer-keywords.txt" - {"i32.clz", TokenType::Unary, Opcode::I32Clz}, - {""}, {""}, {""}, {""}, -#line 168 "src/lexer-keywords.txt" - {"f64x2.neg", TokenType::Unary, Opcode::F64X2Neg}, -#line 105 "src/lexer-keywords.txt" - {"f32x4.min", TokenType::Binary, Opcode::F32X4Min}, -#line 169 "src/lexer-keywords.txt" - {"f64x2.ne", TokenType::Compare, Opcode::F64X2Ne}, -#line 414 "src/lexer-keywords.txt" - {"i64.ctz", TokenType::Unary, Opcode::I64Ctz}, -#line 276 "src/lexer-keywords.txt" - {"i32.ctz", TokenType::Unary, Opcode::I32Ctz}, - {""}, {""}, +#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.neg", TokenType::Unary, Opcode::I64X2Neg}, -#line 452 "src/lexer-keywords.txt" - {"i64.store32", TokenType::Store, Opcode::I64Store32}, -#line 471 "src/lexer-keywords.txt" - {"i64x2.ne", TokenType::Binary, Opcode::I64X2Ne}, + {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, {""}, -#line 56 "src/lexer-keywords.txt" - {"extern", Type::ExternRef, TokenType::Extern}, -#line 394 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AddU}, -#line 257 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AddU}, - {""}, {""}, -#line 392 "src/lexer-keywords.txt" +#line 403 "src/lexer-keywords.txt" {"i64.atomic.rmw32.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32XchgU}, - {""}, -#line 113 "src/lexer-keywords.txt" - {"f32x4.relaxed_max", TokenType::Binary, Opcode::F32X4RelaxedMax}, - {""}, {""}, {""}, {""}, {""}, -#line 395 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8AndU}, -#line 258 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8AndU}, +#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 188 "src/lexer-keywords.txt" - {"function", TokenType::Function}, -#line 401 "src/lexer-keywords.txt" +#line 192 "src/lexer-keywords.txt" + {"field", TokenType::Field}, +#line 412 "src/lexer-keywords.txt" {"i64.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I64AtomicRmwAdd}, -#line 264 "src/lexer-keywords.txt" +#line 275 "src/lexer-keywords.txt" {"i32.atomic.rmw.add", TokenType::AtomicRmw, Opcode::I32AtomicRmwAdd}, - {""}, -#line 180 "src/lexer-keywords.txt" - {"f64x2.trunc", TokenType::Unary, Opcode::F64X2Trunc}, - {""}, {""}, -#line 393 "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 557 "src/lexer-keywords.txt" - {"nan:canonical", TokenType::NanCanonical}, +#line 593 "src/lexer-keywords.txt" + {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, {""}, {""}, -#line 402 "src/lexer-keywords.txt" - {"i64.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I64AtomicRmwAnd}, -#line 265 "src/lexer-keywords.txt" - {"i32.atomic.rmw.and", TokenType::AtomicRmw, Opcode::I32AtomicRmwAnd}, -#line 154 "src/lexer-keywords.txt" +#line 161 "src/lexer-keywords.txt" {"f64x2.add", TokenType::Binary, Opcode::F64X2Add}, -#line 167 "src/lexer-keywords.txt" - {"f64x2.nearest", TokenType::Unary, Opcode::F64X2Nearest}, - {""}, {""}, {""}, -#line 141 "src/lexer-keywords.txt" - {"f64.min", TokenType::Binary, Opcode::F64Min}, -#line 80 "src/lexer-keywords.txt" - {"f32.min", TokenType::Binary, Opcode::F32Min}, -#line 465 "src/lexer-keywords.txt" + {""}, +#line 476 "src/lexer-keywords.txt" {"i64x2.add", TokenType::Binary, Opcode::I64X2Add}, {""}, {""}, -#line 400 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XorU}, -#line 263 "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 459 "src/lexer-keywords.txt" - {"i64.trunc_f64_u", TokenType::Convert, Opcode::I64TruncF64U}, -#line 315 "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 166 "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 458 "src/lexer-keywords.txt" - {"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" - {"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull}, -#line 605 "src/lexer-keywords.txt" - {"v128", Type::V128}, - {""}, {""}, -#line 469 "src/lexer-keywords.txt" + {""}, +#line 480 "src/lexer-keywords.txt" {"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul}, -#line 433 "src/lexer-keywords.txt" - {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, - {""}, {""}, {""}, -#line 432 "src/lexer-keywords.txt" - {"i64.load32_s", TokenType::Load, Opcode::I64Load32S}, + {""}, {""}, +#line 346 "src/lexer-keywords.txt" + {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, {""}, {""}, {""}, {""}, -#line 556 "src/lexer-keywords.txt" - {"nan:arithmetic", TokenType::NanArithmetic}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 538 "src/lexer-keywords.txt" - {"invoke", TokenType::Invoke}, - {""}, {""}, {""}, {""}, {""}, -#line 378 "src/lexer-keywords.txt" - {"i64.atomic.load8_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad8U}, -#line 248 "src/lexer-keywords.txt" - {"i32.atomic.load8_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad8U}, +#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 176 "src/lexer-keywords.txt" - {"f64x2.replace_lane", TokenType::SimdLaneOp, Opcode::F64X2ReplaceLane}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 485 "src/lexer-keywords.txt" - {"i64x2.replace_lane", TokenType::SimdLaneOp, Opcode::I64X2ReplaceLane}, +#line 34 "src/lexer-keywords.txt" + {"binary", TokenType::Bin}, +#line 196 "src/lexer-keywords.txt" + {"function", TokenType::Function}, {""}, -#line 564 "src/lexer-keywords.txt" - {"quote", TokenType::Quote}, -#line 32 "src/lexer-keywords.txt" - {"block", TokenType::Block, Opcode::Block}, - {""}, {""}, -#line 450 "src/lexer-keywords.txt" - {"i64.shr_u", TokenType::Binary, Opcode::I64ShrU}, -#line 307 "src/lexer-keywords.txt" - {"i32.shr_u", TokenType::Binary, Opcode::I32ShrU}, -#line 449 "src/lexer-keywords.txt" - {"i64.shr_s", TokenType::Binary, Opcode::I64ShrS}, -#line 306 "src/lexer-keywords.txt" - {"i32.shr_s", TokenType::Binary, Opcode::I32ShrS}, -#line 397 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU}, -#line 260 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU}, -#line 240 "src/lexer-keywords.txt" - {"i16x8", TokenType::I16X8}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 355 "src/lexer-keywords.txt" - {"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU}, -#line 346 "src/lexer-keywords.txt" - {"i32x4.min_u", TokenType::Binary, Opcode::I32X4MinU}, -#line 354 "src/lexer-keywords.txt" - {"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" - {"v128.or", TokenType::Binary, Opcode::V128Or}, +#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 560 "src/lexer-keywords.txt" - {"output", TokenType::Output}, +#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 559 "src/lexer-keywords.txt" - {"offset", TokenType::Offset}, +#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 592 "src/lexer-keywords.txt" - {"type", TokenType::Type}, -#line 590 "src/lexer-keywords.txt" - {"try", TokenType::Try, Opcode::Try}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 580 "src/lexer-keywords.txt" - {"table.fill", TokenType::TableFill, Opcode::TableFill}, +#line 523 "src/lexer-keywords.txt" + {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, {""}, -#line 484 "src/lexer-keywords.txt" - {"i64x2.relaxed_laneselect", TokenType::Ternary, Opcode::I64X2RelaxedLaneSelect}, -#line 478 "src/lexer-keywords.txt" - {"i64x2.all_true", TokenType::Unary, Opcode::I64X2AllTrue}, - {""}, {""}, {""}, {""}, {""}, -#line 205 "src/lexer-keywords.txt" - {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, -#line 420 "src/lexer-keywords.txt" - {"i64.extend32_s", TokenType::Unary, Opcode::I64Extend32S}, -#line 209 "src/lexer-keywords.txt" +#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" + {"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU}, {""}, -#line 204 "src/lexer-keywords.txt" - {"i16x8.ge_s", TokenType::Compare, Opcode::I16X8GeS}, -#line 40 "src/lexer-keywords.txt" - {"catch_all", TokenType::CatchAll, Opcode::CatchAll}, -#line 208 "src/lexer-keywords.txt" - {"i16x8.le_s", TokenType::Compare, Opcode::I16X8LeS}, -#line 336 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_u", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4U}, -#line 207 "src/lexer-keywords.txt" - {"i16x8.gt_u", TokenType::Compare, Opcode::I16X8GtU}, - {""}, -#line 213 "src/lexer-keywords.txt" +#line 222 "src/lexer-keywords.txt" {"i16x8.lt_u", TokenType::Compare, Opcode::I16X8LtU}, -#line 335 "src/lexer-keywords.txt" - {"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S}, -#line 206 "src/lexer-keywords.txt" - {"i16x8.gt_s", TokenType::Compare, Opcode::I16X8GtS}, {""}, -#line 212 "src/lexer-keywords.txt" - {"i16x8.lt_s", TokenType::Compare, Opcode::I16X8LtS}, +#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 70 "src/lexer-keywords.txt" +#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 164 "src/lexer-keywords.txt" - {"f64x2.max", TokenType::Binary, Opcode::F64X2Max}, +#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 117 "src/lexer-keywords.txt" - {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, -#line 604 "src/lexer-keywords.txt" - {"v128.store", TokenType::Store, Opcode::V128Store}, +#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" - {"input", TokenType::Input}, + {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, +#line 506 "src/lexer-keywords.txt" + {"i64x2", TokenType::I64X2}, {""}, {""}, -#line 572 "src/lexer-keywords.txt" - {"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect}, - {""}, -#line 356 "src/lexer-keywords.txt" - {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, -#line 508 "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" - {"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU}, - {""}, -#line 507 "src/lexer-keywords.txt" - {"i8x16.ge_s", TokenType::Compare, Opcode::I8X16GeS}, +#line 444 "src/lexer-keywords.txt" + {"i64.load32_u", TokenType::Load, Opcode::I64Load32U}, + {""}, {""}, {""}, +#line 578 "src/lexer-keywords.txt" + {"offset", TokenType::Offset}, {""}, -#line 511 "src/lexer-keywords.txt" - {"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS}, +#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 510 "src/lexer-keywords.txt" - {"i8x16.gt_u", TokenType::Compare, Opcode::I8X16GtU}, -#line 536 "src/lexer-keywords.txt" - {"import", TokenType::Import}, -#line 514 "src/lexer-keywords.txt" - {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, +#line 568 "src/lexer-keywords.txt" + {"nan:arithmetic", TokenType::NanArithmetic}, {""}, -#line 509 "src/lexer-keywords.txt" - {"i8x16.gt_s", TokenType::Compare, Opcode::I8X16GtS}, +#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 513 "src/lexer-keywords.txt" - {"i8x16.lt_s", TokenType::Compare, Opcode::I8X16LtS}, - {""}, {""}, {""}, {""}, {""}, -#line 598 "src/lexer-keywords.txt" - {"v128.load", TokenType::Load, Opcode::V128Load}, -#line 158 "src/lexer-keywords.txt" - {"f64x2.extract_lane", TokenType::SimdLaneOp, Opcode::F64X2ExtractLane}, +#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 221 "src/lexer-keywords.txt" - {"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg}, +#line 240 "src/lexer-keywords.txt" + {"i16x8.sub_sat_s", TokenType::Binary, Opcode::I16X8SubSatS}, {""}, +#line 203 "src/lexer-keywords.txt" + {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, #line 223 "src/lexer-keywords.txt" - {"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne}, -#line 423 "src/lexer-keywords.txt" - {"i64.extend_i32_u", TokenType::Convert, Opcode::I64ExtendI32U}, -#line 466 "src/lexer-keywords.txt" - {"i64x2.extract_lane", TokenType::SimdLaneOp, Opcode::I64X2ExtractLane}, -#line 422 "src/lexer-keywords.txt" - {"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S}, - {""}, {""}, -#line 148 "src/lexer-keywords.txt" - {"f64.sqrt", TokenType::Unary, Opcode::F64Sqrt}, -#line 86 "src/lexer-keywords.txt" - {"f32.sqrt", TokenType::Unary, Opcode::F32Sqrt}, -#line 211 "src/lexer-keywords.txt" - {"v128.load8x8_u", TokenType::Load, Opcode::V128Load8X8U}, - {""}, -#line 210 "src/lexer-keywords.txt" - {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, -#line 611 "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}, -#line 269 "src/lexer-keywords.txt" - {"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg}, - {""}, {""}, {""}, -#line 184 "src/lexer-keywords.txt" - {"f64x2", TokenType::F64X2}, + {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 550 "src/lexer-keywords.txt" + {"invoke", TokenType::Invoke}, {""}, {""}, -#line 610 "src/lexer-keywords.txt" - {"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat}, - {""}, -#line 599 "src/lexer-keywords.txt" - {"v128.not", TokenType::Unary, Opcode::V128Not}, -#line 618 "src/lexer-keywords.txt" - {"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane}, -#line 495 "src/lexer-keywords.txt" - {"i64x2", TokenType::I64X2}, -#line 118 "src/lexer-keywords.txt" - {"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt}, - {""}, -#line 521 "src/lexer-keywords.txt" - {"i8x16.neg", TokenType::Unary, Opcode::I8X16Neg}, +#line 124 "src/lexer-keywords.txt" + {"f32x4.splat", TokenType::Unary, Opcode::F32X4Splat}, {""}, -#line 523 "src/lexer-keywords.txt" - {"i8x16.ne", TokenType::Compare, Opcode::I8X16Ne}, -#line 44 "src/lexer-keywords.txt" - {"data.drop", TokenType::DataDrop, Opcode::DataDrop}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 451 "src/lexer-keywords.txt" - {"i64.store16", TokenType::Store, Opcode::I64Store16}, -#line 308 "src/lexer-keywords.txt" - {"i32.store16", TokenType::Store, Opcode::I32Store16}, +#line 367 "src/lexer-keywords.txt" + {"i32x4.splat", TokenType::Unary, Opcode::I32X4Splat}, {""}, -#line 186 "src/lexer-keywords.txt" - {"funcref", Type::FuncRef}, -#line 196 "src/lexer-keywords.txt" - {"i16x8.add", TokenType::Binary, Opcode::I16X8Add}, +#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 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 597 "src/lexer-keywords.txt" - {"v128.const", TokenType::Const, Opcode::V128Const}, - {""}, -#line 606 "src/lexer-keywords.txt" - {"v128.xor", TokenType::Binary, Opcode::V128Xor}, - {""}, {""}, {""}, {""}, {""}, -#line 174 "src/lexer-keywords.txt" - {"f64x2.relaxed_min", TokenType::Binary, Opcode::F64X2RelaxedMin}, +#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 175 "src/lexer-keywords.txt" - {"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd}, +#line 520 "src/lexer-keywords.txt" + {"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU}, {""}, -#line 218 "src/lexer-keywords.txt" - {"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul}, +#line 526 "src/lexer-keywords.txt" + {"i8x16.lt_u", TokenType::Compare, Opcode::I8X16LtU}, {""}, -#line 376 "src/lexer-keywords.txt" - {"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U}, -#line 247 "src/lexer-keywords.txt" - {"i32.atomic.load16_u", TokenType::AtomicLoad, Opcode::I32AtomicLoad16U}, - {""}, {""}, {""}, -#line 39 "src/lexer-keywords.txt" - {"catch", TokenType::Catch, Opcode::Catch}, - {""}, {""}, -#line 486 "src/lexer-keywords.txt" - {"i64x2.shl", TokenType::Binary, Opcode::I64X2Shl}, - {""}, {""}, -#line 500 "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 595 "src/lexer-keywords.txt" - {"v128.and", TokenType::Binary, Opcode::V128And}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#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 534 "src/lexer-keywords.txt" - {"i8x16", TokenType::I8X16}, +#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 599 "src/lexer-keywords.txt" + {"start", TokenType::Start}, {""}, {""}, -#line 52 "src/lexer-keywords.txt" - {"elem", TokenType::Elem}, +#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 400 "src/lexer-keywords.txt" + {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, {""}, #line 57 "src/lexer-keywords.txt" - {"externref", Type::ExternRef}, - {""}, {""}, -#line 594 "src/lexer-keywords.txt" - {"v128.andnot", TokenType::Binary, Opcode::V128Andnot}, + {"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 384 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16SubU}, -#line 254 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.sub_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16SubU}, +#line 64 "src/lexer-keywords.txt" + {"externref", Type::ExternRef}, {""}, -#line 226 "src/lexer-keywords.txt" - {"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane}, +#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 159 "src/lexer-keywords.txt" - {"f64x2.floor", TokenType::Unary, Opcode::F64X2Floor}, +#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 468 "src/lexer-keywords.txt" - {"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U}, -#line 172 "src/lexer-keywords.txt" - {"f64x2.relaxed_madd", TokenType::Ternary, Opcode::F64X2RelaxedMadd}, +#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" + {"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 204 "src/lexer-keywords.txt" + {"i16x8.add_sat_u", TokenType::Binary, Opcode::I16X8AddSatU}, +#line 24 "src/lexer-keywords.txt" + {"after", TokenType::After}, {""}, {""}, -#line 467 "src/lexer-keywords.txt" - {"v128.load32x2_s", TokenType::Load, Opcode::V128Load32X2S}, +#line 118 "src/lexer-keywords.txt" + {"f32x4.pmin", TokenType::Binary, Opcode::F32X4PMin}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 36 "src/lexer-keywords.txt" - {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, - {""}, -#line 526 "src/lexer-keywords.txt" - {"i8x16.replace_lane", TokenType::SimdLaneOp, Opcode::I8X16ReplaceLane}, - {""}, {""}, {""}, {""}, {""}, -#line 165 "src/lexer-keywords.txt" - {"f64x2.min", TokenType::Binary, Opcode::F64X2Min}, -#line 383 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16OrU}, -#line 253 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 224 "src/lexer-keywords.txt" - {"i16x8.relaxed_laneselect", TokenType::Ternary, Opcode::I16X8RelaxedLaneSelect}, -#line 197 "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 552 "src/lexer-keywords.txt" - {"memory.size", TokenType::MemorySize, Opcode::MemorySize}, -#line 173 "src/lexer-keywords.txt" - {"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax}, -#line 380 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AddU}, -#line 250 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.add_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AddU}, -#line 399 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8XchgU}, -#line 262 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8XchgU}, -#line 232 "src/lexer-keywords.txt" - {"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU}, - {""}, {""}, {""}, -#line 231 "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 381 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16AndU}, -#line 251 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.and_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16AndU}, -#line 347 "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 389 "src/lexer-keywords.txt" - {"i64.atomic.rmw32.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw32CmpxchgU}, - {""}, {""}, {""}, {""}, {""}, -#line 525 "src/lexer-keywords.txt" - {"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect}, -#line 501 "src/lexer-keywords.txt" - {"i8x16.all_true", TokenType::Unary, Opcode::I8X16AllTrue}, - {""}, {""}, {""}, {""}, -#line 577 "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 123 "src/lexer-keywords.txt" - {"f64.abs", TokenType::Unary, Opcode::F64Abs}, -#line 61 "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 532 "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 531 "src/lexer-keywords.txt" - {"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS}, -#line 616 "src/lexer-keywords.txt" - {"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane}, +#line 41 "src/lexer-keywords.txt" + {"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 119 "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 91 "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 608 "src/lexer-keywords.txt" - {"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat}, -#line 562 "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" - {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero}, -#line 322 "src/lexer-keywords.txt" - {"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs}, -#line 34 "src/lexer-keywords.txt" - {"br_table", TokenType::BrTable, Opcode::BrTable}, - {""}, {""}, {""}, -#line 195 "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 194 "src/lexer-keywords.txt" - {"i16x8.add_sat_s", TokenType::Binary, Opcode::I16X8AddSatS}, - {""}, -#line 111 "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 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 319 "src/lexer-keywords.txt" +#line 330 "src/lexer-keywords.txt" {"i32.trunc_sat_f64_u", TokenType::Convert, Opcode::I32TruncSatF64U}, -#line 385 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XchgU}, -#line 255 "src/lexer-keywords.txt" - {"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU}, -#line 462 "src/lexer-keywords.txt" - {"i64.trunc_sat_f64_s", TokenType::Convert, Opcode::I64TruncSatF64S}, -#line 318 "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 613 "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 499 "src/lexer-keywords.txt" - {"i8x16.add_sat_u", TokenType::Binary, Opcode::I8X16AddSatU}, -#line 377 "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 615 "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}, +#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 386 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.xor_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw16XorU}, -#line 256 "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 192 "src/lexer-keywords.txt" - {"global", TokenType::Global}, -#line 215 "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 214 "src/lexer-keywords.txt" - {"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS}, - {""}, {""}, {""}, {""}, -#line 488 "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 487 "src/lexer-keywords.txt" - {"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS}, +#line 575 "src/lexer-keywords.txt" + {"nullfuncref", Type::NullFuncRef}, {""}, -#line 549 "src/lexer-keywords.txt" - {"memory.fill", TokenType::MemoryFill, Opcode::MemoryFill}, +#line 200 "src/lexer-keywords.txt" + {"global", TokenType::Global}, {""}, {""}, {""}, {""}, -#line 326 "src/lexer-keywords.txt" - {"i32x4.relaxed_dot_i8x16_i7x16_add_s", TokenType::Ternary, Opcode::I32X4DotI8X16I7X16AddS}, -#line 41 "src/lexer-keywords.txt" - {"catch_ref", TokenType::CatchRef}, - {""}, {""}, {""}, -#line 579 "src/lexer-keywords.txt" - {"table.copy", TokenType::TableCopy, Opcode::TableCopy}, - {""}, -#line 227 "src/lexer-keywords.txt" - {"i16x8.shl", TokenType::Binary, Opcode::I16X8Shl}, - {""}, {""}, {""}, {""}, {""}, -#line 516 "src/lexer-keywords.txt" - {"i8x16.max_u", TokenType::Binary, Opcode::I8X16MaxU}, - {""}, -#line 515 "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 576 "src/lexer-keywords.txt" - {"shared", TokenType::Shared}, -#line 130 "src/lexer-keywords.txt" - {"f64.convert_i64_u", TokenType::Convert, Opcode::F64ConvertI64U}, -#line 68 "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 129 "src/lexer-keywords.txt" - {"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S}, -#line 67 "src/lexer-keywords.txt" - {"f32.convert_i64_s", TokenType::Convert, Opcode::F32ConvertI64S}, - {""}, {""}, {""}, {""}, {""}, -#line 60 "src/lexer-keywords.txt" - {"export", TokenType::Export}, - {""}, {""}, {""}, {""}, {""}, -#line 527 "src/lexer-keywords.txt" - {"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl}, -#line 553 "src/lexer-keywords.txt" - {"memory", TokenType::Memory}, -#line 593 "src/lexer-keywords.txt" - {"unreachable", TokenType::Unreachable, Opcode::Unreachable}, - {""}, -#line 177 "src/lexer-keywords.txt" - {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, -#line 110 "src/lexer-keywords.txt" - {"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax}, -#line 372 "src/lexer-keywords.txt" +#line 383 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f64x2_u_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2UZero}, - {""}, -#line 371 "src/lexer-keywords.txt" - {"i32x4.trunc_sat_f64x2_s_zero", TokenType::Unary, Opcode::I32X4TruncSatF64X2SZero}, - {""}, -#line 190 "src/lexer-keywords.txt" - {"global.get", TokenType::GlobalGet, Opcode::GlobalGet}, -#line 489 "src/lexer-keywords.txt" - {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, -#line 191 "src/lexer-keywords.txt" +#line 199 "src/lexer-keywords.txt" {"global.set", TokenType::GlobalSet, Opcode::GlobalSet}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 409 "src/lexer-keywords.txt" - {"i64.atomic.store32", TokenType::AtomicStore, Opcode::I64AtomicStore32}, - {""}, {""}, -#line 59 "src/lexer-keywords.txt" - {"exnref", Type::ExnRef}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 609 "src/lexer-keywords.txt" - {"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat}, -#line 617 "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" - {"throw", TokenType::Throw, Opcode::Throw}, -#line 603 "src/lexer-keywords.txt" - {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero}, +#line 255 "src/lexer-keywords.txt" + {"i31ref", Type::I31Ref}, +#line 62 "src/lexer-keywords.txt" + {"eqref", Type::EqRef}, {""}, {""}, {""}, {""}, -#line 37 "src/lexer-keywords.txt" +#line 42 "src/lexer-keywords.txt" {"call_ref", TokenType::CallRef, Opcode::CallRef}, - {""}, {""}, -#line 551 "src/lexer-keywords.txt" - {"memory.init", TokenType::MemoryInit, Opcode::MemoryInit}, -#line 416 "src/lexer-keywords.txt" - {"i64.div_u", TokenType::Binary, Opcode::I64DivU}, -#line 278 "src/lexer-keywords.txt" - {"i32.div_u", TokenType::Binary, Opcode::I32DivU}, -#line 415 "src/lexer-keywords.txt" - {"i64.div_s", TokenType::Binary, Opcode::I64DivS}, -#line 277 "src/lexer-keywords.txt" - {"i32.div_s", TokenType::Binary, Opcode::I32DivS}, {""}, {""}, {""}, {""}, -#line 418 "src/lexer-keywords.txt" - {"i64.eqz", TokenType::Convert, Opcode::I64Eqz}, -#line 280 "src/lexer-keywords.txt" - {"i32.eqz", TokenType::Convert, Opcode::I32Eqz}, - {""}, {""}, -#line 589 "src/lexer-keywords.txt" - {"throw_ref", TokenType::ThrowRef, Opcode::ThrowRef}, +#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 203 "src/lexer-keywords.txt" - {"i16x8.extract_lane_u", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneU}, +#line 184 "src/lexer-keywords.txt" + {"f64x2.splat", TokenType::Unary, Opcode::F64X2Splat}, {""}, -#line 202 "src/lexer-keywords.txt" - {"i16x8.extract_lane_s", TokenType::SimdLaneOp, Opcode::I16X8ExtractLaneS}, - {""}, {""}, -#line 614 "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}, -#line 259 "src/lexer-keywords.txt" - {"i32.atomic.rmw8.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmw8CmpxchgU}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 408 "src/lexer-keywords.txt" - {"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16}, -#line 271 "src/lexer-keywords.txt" - {"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16}, +#line 500 "src/lexer-keywords.txt" + {"i64x2.splat", TokenType::Unary, Opcode::I64X2Splat}, + {""}, {""}, {""}, {""}, +#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 207 "src/lexer-keywords.txt" + {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, + {""}, +#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 591 "src/lexer-keywords.txt" - {"try_table", TokenType::TryTable, Opcode::TryTable}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 601 "src/lexer-keywords.txt" - {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, - {""}, -#line 506 "src/lexer-keywords.txt" - {"i8x16.extract_lane_u", TokenType::SimdLaneOp, Opcode::I8X16ExtractLaneU}, -#line 366 "src/lexer-keywords.txt" +#line 377 "src/lexer-keywords.txt" {"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U}, -#line 505 "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 365 "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 49 "src/lexer-keywords.txt" - {"drop", TokenType::Drop, Opcode::Drop}, +#line 625 "src/lexer-keywords.txt" + {"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue}, {""}, {""}, {""}, -#line 582 "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 571 "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 229 "src/lexer-keywords.txt" - {"i16x8.shr_u", TokenType::Binary, Opcode::I16X8ShrU}, -#line 217 "src/lexer-keywords.txt" - {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, -#line 228 "src/lexer-keywords.txt" - {"i16x8.shr_s", TokenType::Binary, Opcode::I16X8ShrS}, -#line 216 "src/lexer-keywords.txt" +#line 225 "src/lexer-keywords.txt" {"i16x8.min_s", TokenType::Binary, Opcode::I16X8MinS}, - {""}, {""}, {""}, {""}, {""}, -#line 403 "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 266 "src/lexer-keywords.txt" +#line 277 "src/lexer-keywords.txt" {"i32.atomic.rmw.cmpxchg", TokenType::AtomicRmwCmpxchg, Opcode::I32AtomicRmwCmpxchg}, - {""}, -#line 121 "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 42 "src/lexer-keywords.txt" - {"catch_all_ref", TokenType::CatchAllRef}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, -#line 529 "src/lexer-keywords.txt" - {"i8x16.shr_u", TokenType::Binary, Opcode::I8X16ShrU}, -#line 518 "src/lexer-keywords.txt" - {"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU}, -#line 528 "src/lexer-keywords.txt" - {"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS}, -#line 517 "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" - {"memory.grow", TokenType::MemoryGrow, Opcode::MemoryGrow}, +#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 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 398 "src/lexer-keywords.txt" - {"i64.atomic.rmw8.sub_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8SubU}, -#line 261 "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 198 "src/lexer-keywords.txt" - {"i16x8.avgr_u", TokenType::Binary, Opcode::I16X8AvgrU}, -#line 230 "src/lexer-keywords.txt" - {"i16x8.splat", TokenType::Unary, Opcode::I16X8Splat}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 219 "src/lexer-keywords.txt" + {"v128.load8x8_s", TokenType::Load, Opcode::V128Load8X8S}, {""}, {""}, {""}, -#line 340 "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 558 "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 339 "src/lexer-keywords.txt" - {"v128.load16x4_s", TokenType::Load, Opcode::V128Load16X4S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 179 "src/lexer-keywords.txt" - {"f64x2.sub", TokenType::Binary, Opcode::F64X2Sub}, - {""}, {""}, -#line 153 "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 490 "src/lexer-keywords.txt" - {"i64x2.sub", TokenType::Binary, Opcode::I64X2Sub}, -#line 156 "src/lexer-keywords.txt" - {"f64x2.div", TokenType::Binary, Opcode::F64X2Div}, - {""}, -#line 476 "src/lexer-keywords.txt" - {"i64x2.abs", TokenType::Unary, Opcode::I64X2Abs}, -#line 502 "src/lexer-keywords.txt" - {"i8x16.avgr_u", TokenType::Binary, Opcode::I8X16AvgrU}, -#line 530 "src/lexer-keywords.txt" - {"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 171 "src/lexer-keywords.txt" +#line 178 "src/lexer-keywords.txt" {"f64x2.pmin", TokenType::Binary, Opcode::F64X2PMin}, - {""}, {""}, -#line 544 "src/lexer-keywords.txt" - {"loop", TokenType::Loop, Opcode::Loop}, +#line 226 "src/lexer-keywords.txt" + {"i16x8.min_u", TokenType::Binary, Opcode::I16X8MinU}, {""}, {""}, {""}, {""}, {""}, -#line 461 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_u", TokenType::Convert, Opcode::I64TruncSatF32U}, -#line 317 "src/lexer-keywords.txt" - {"i32.trunc_sat_f32_u", TokenType::Convert, Opcode::I32TruncSatF32U}, -#line 133 "src/lexer-keywords.txt" - {"f64.eq", TokenType::Compare, Opcode::F64Eq}, -#line 72 "src/lexer-keywords.txt" - {"f32.eq", TokenType::Compare, Opcode::F32Eq}, -#line 460 "src/lexer-keywords.txt" - {"i64.trunc_sat_f32_s", TokenType::Convert, Opcode::I64TruncSatF32S}, -#line 316 "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 417 "src/lexer-keywords.txt" - {"i64.eq", TokenType::Compare, Opcode::I64Eq}, -#line 279 "src/lexer-keywords.txt" - {"i32.eq", TokenType::Compare, Opcode::I32Eq}, -#line 325 "src/lexer-keywords.txt" - {"i32x4.bitmask", TokenType::Unary, Opcode::I32X4Bitmask}, - {""}, {""}, {""}, {""}, -#line 442 "src/lexer-keywords.txt" - {"i64.popcnt", TokenType::Unary, Opcode::I64Popcnt}, -#line 299 "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 382 "src/lexer-keywords.txt" - {"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU}, -#line 252 "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 97 "src/lexer-keywords.txt" - {"f32x4.eq", TokenType::Compare, Opcode::F32X4Eq}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 327 "src/lexer-keywords.txt" - {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, - {""}, {""}, {""}, {""}, {""}, -#line 482 "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 480 "src/lexer-keywords.txt" - {"i64x2.extend_low_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendLowI32X4S}, -#line 522 "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 607 "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 128 "src/lexer-keywords.txt" - {"f64.convert_i32_u", TokenType::Convert, Opcode::F64ConvertI32U}, -#line 66 "src/lexer-keywords.txt" - {"f32.convert_i32_u", TokenType::Convert, Opcode::F32ConvertI32U}, - {""}, {""}, -#line 127 "src/lexer-keywords.txt" - {"f64.convert_i32_s", TokenType::Convert, Opcode::F64ConvertI32S}, -#line 65 "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 368 "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 367 "src/lexer-keywords.txt" - {"i32x4.extend_high_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendHighI16X8S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 170 "src/lexer-keywords.txt" +#line 177 "src/lexer-keywords.txt" {"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax}, - {""}, {""}, {""}, {""}, -#line 612 "src/lexer-keywords.txt" - {"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane}, {""}, {""}, -#line 619 "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 359 "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 358 "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 51 "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 493 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4U}, -#line 524 "src/lexer-keywords.txt" - {"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle}, -#line 491 "src/lexer-keywords.txt" - {"i64x2.extmul_low_i32x4_s", TokenType::Binary, Opcode::I64X2ExtmulLowI32X4S}, - {""}, {""}, {""}, {""}, {""}, -#line 370 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_u", TokenType::Unary, Opcode::I32X4ExtendLowI16X8U}, {""}, -#line 369 "src/lexer-keywords.txt" - {"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 363 "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 361 "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 147 "src/lexer-keywords.txt" - {"f64.reinterpret_i64", TokenType::Convert, Opcode::F64ReinterpretI64}, - {""}, {""}, -#line 321 "src/lexer-keywords.txt" - {"i32.wrap_i64", TokenType::Convert, Opcode::I32WrapI64}, - {""}, {""}, {""}, {""}, -#line 620 "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 132 "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 71 "src/lexer-keywords.txt" +#line 78 "src/lexer-keywords.txt" {"f32.div", TokenType::Binary, Opcode::F32Div}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 233 "src/lexer-keywords.txt" - {"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 193 "src/lexer-keywords.txt" - {"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs}, - {""}, -#line 561 "src/lexer-keywords.txt" - {"pagesize", TokenType::PageSize}, +#line 101 "src/lexer-keywords.txt" + {"f32x4.convert_i32x4_s", TokenType::Unary, Opcode::F32X4ConvertI32X4S}, {""}, {""}, -#line 95 "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 94 "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 362 "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 360 "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 131 "src/lexer-keywords.txt" - {"f64.copysign", TokenType::Binary, Opcode::F64Copysign}, -#line 69 "src/lexer-keywords.txt" - {"f32.copysign", TokenType::Binary, Opcode::F32Copysign}, -#line 533 "src/lexer-keywords.txt" - {"i8x16.sub", TokenType::Binary, Opcode::I8X16Sub}, +#line 592 "src/lexer-keywords.txt" + {"rethrow", TokenType::Rethrow, Opcode::Rethrow}, {""}, {""}, -#line 497 "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 225 "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 200 "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 443 "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 244 "src/lexer-keywords.txt" - {"i16x8.extend_low_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendLowI8X16U}, - {""}, -#line 243 "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 220 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_u", TokenType::Binary, Opcode::I16X8NarrowI32X4U}, - {""}, -#line 219 "src/lexer-keywords.txt" - {"i16x8.narrow_i32x4_s", TokenType::Binary, Opcode::I16X8NarrowI32X4S}, - {""}, {""}, -#line 238 "src/lexer-keywords.txt" - {"i16x8.extmul_low_i8x16_u", TokenType::Binary, Opcode::I16X8ExtmulLowI8X16U}, - {""}, -#line 236 "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 548 "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 479 "src/lexer-keywords.txt" - {"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 338 "src/lexer-keywords.txt" + {"i32x4.eq", TokenType::Compare, Opcode::I32X4Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, -#line 157 "src/lexer-keywords.txt" - {"f64x2.eq", TokenType::Compare, Opcode::F64X2Eq}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 470 "src/lexer-keywords.txt" - {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 483 "src/lexer-keywords.txt" + {""}, {""}, {""}, {""}, +#line 494 "src/lexer-keywords.txt" {"i64x2.extend_high_i32x4_u", TokenType::Unary, Opcode::I64X2ExtendHighI32X4U}, - {""}, -#line 481 "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 596 "src/lexer-keywords.txt" + {""}, {""}, +#line 620 "src/lexer-keywords.txt" {"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 150 "src/lexer-keywords.txt" - {"f64.sub", TokenType::Binary, Opcode::F64Sub}, -#line 88 "src/lexer-keywords.txt" - {"f32.sub", TokenType::Binary, Opcode::F32Sub}, - {""}, {""}, {""}, {""}, {""}, -#line 455 "src/lexer-keywords.txt" - {"i64.sub", TokenType::Binary, Opcode::I64Sub}, -#line 311 "src/lexer-keywords.txt" - {"i32.sub", TokenType::Binary, Opcode::I32Sub}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 146 "src/lexer-keywords.txt" - {"f64.promote_f32", TokenType::Convert, Opcode::F64PromoteF32}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 494 "src/lexer-keywords.txt" +#line 505 "src/lexer-keywords.txt" {"i64x2.extmul_high_i32x4_u", TokenType::Binary, Opcode::I64X2ExtmulHighI32X4U}, - {""}, -#line 492 "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 199 "src/lexer-keywords.txt" - {"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, -#line 23 "src/lexer-keywords.txt" - {"assert_exhaustion", TokenType::AssertExhaustion}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 503 "src/lexer-keywords.txt" - {"i8x16.bitmask", TokenType::Unary, Opcode::I8X16Bitmask}, - {""}, -#line 201 "src/lexer-keywords.txt" - {"i16x8.eq", TokenType::Compare, Opcode::I16X8Eq}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, -#line 504 "src/lexer-keywords.txt" - {"i8x16.eq", TokenType::Compare, Opcode::I8X16Eq}, - {""}, {""}, {""}, {""}, {""}, -#line 547 "src/lexer-keywords.txt" - {"memory.atomic.wait64", TokenType::AtomicWait, Opcode::MemoryAtomicWait64}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, -#line 85 "src/lexer-keywords.txt" - {"f32.reinterpret_i32", TokenType::Convert, Opcode::F32ReinterpretI32}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, -#line 24 "src/lexer-keywords.txt" - {"assert_invalid", TokenType::AssertInvalid}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 405 "src/lexer-keywords.txt" - {"i64.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I64AtomicRmwSub}, -#line 268 "src/lexer-keywords.txt" - {"i32.atomic.rmw.sub", TokenType::AtomicRmw, Opcode::I32AtomicRmwSub}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, -#line 545 "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 242 "src/lexer-keywords.txt" - {"i16x8.extend_high_i8x16_u", TokenType::Unary, Opcode::I16X8ExtendHighI8X16U}, - {""}, -#line 241 "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 300 "src/lexer-keywords.txt" - {"i32.reinterpret_f32", TokenType::Convert, Opcode::I32ReinterpretF32}, +#line 481 "src/lexer-keywords.txt" + {"i64x2.eq", TokenType::Binary, Opcode::I64X2Eq}, {""}, {""}, {""}, {""}, -#line 182 "src/lexer-keywords.txt" - {"f64x2.convert_low_i32x4_u", TokenType::Unary, Opcode::F64X2ConvertLowI32X4U}, - {""}, -#line 181 "src/lexer-keywords.txt" - {"f64x2.convert_low_i32x4_s", TokenType::Unary, Opcode::F64X2ConvertLowI32X4S}, - {""}, -#line 235 "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 234 "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 546 "src/lexer-keywords.txt" +#line 558 "src/lexer-keywords.txt" {"memory.atomic.wait32", TokenType::AtomicWait, Opcode::MemoryAtomicWait32}, - {""}, {""}, {""}, {""}, {""}, -#line 520 "src/lexer-keywords.txt" - {"i8x16.narrow_i16x8_u", TokenType::Binary, Opcode::I8X16NarrowI16X8U}, - {""}, -#line 519 "src/lexer-keywords.txt" - {"i8x16.narrow_i16x8_s", TokenType::Binary, Opcode::I8X16NarrowI16X8S}, {""}, -#line 222 "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 239 "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 237 "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}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -1775,8 +1869,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len) {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 183 "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 67fc44e923..18c1955898 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -40,13 +40,17 @@ 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; + Result OnCallRefExpr(CallRefExpr*) override; Result OnCatchExpr(TryExpr*, Catch*) override; 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; @@ -72,6 +76,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; @@ -105,7 +110,9 @@ 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); void VisitDataSegment(DataSegment* segment); void VisitScriptModule(ScriptModule* script_module); @@ -275,6 +282,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); @@ -295,6 +312,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; @@ -308,6 +330,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; @@ -428,6 +455,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; @@ -546,12 +578,26 @@ 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); } } +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); @@ -584,8 +630,12 @@ 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) + 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 ad3a85393b..ce9043d6c4 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, type_fields_) { typechecker_.set_error_callback( [this](const char* msg) { OnTypecheckerError(msg); }); } @@ -44,50 +46,79 @@ 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."); } - func_types_.emplace( - num_types_++, - FuncType{ToTypeVector(param_count, param_types), - ToTypeVector(result_count, result_types), type_index}); + + 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], end_index, "params"); + } + for (Index i = 0; i < result_count; i++) { + result |= CheckReferenceType(loc, result_types[i], end_index, "results"); + } + + type_validation_result_ |= result; + result |= CheckGCTypeExtension(loc, gc_ext); + } + 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 SharedValidator::OnArrayType(const Location&, TypeMut field) { - array_types_.emplace(num_types_++, ArrayType{field}); - return Result::Ok; + 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::EndTypeSection() { - Result result = Result::Ok; +Result SharedValidator::OnArrayType(const Location& loc, + TypeMut field, + GCTypeExtension* gc_ext) { + type_fields_.PushArray(ArrayType{field}); - for (auto func_type : func_types_) { - for (auto type : func_type.second.params) { - result |= CheckReferenceType(Location(), type, "params"); - } + Result result = CheckReferenceType(loc, field.type, GetEndIndex(), "params"); - for (auto type : func_type.second.results) { - result |= CheckReferenceType(Location(), type, "results"); - } - } + type_validation_result_ |= result; + result |= CheckGCTypeExtension(loc, gc_ext); return result; } @@ -127,8 +158,12 @@ 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()); if (tables_.size() > 0 && !options_.features.reference_types_enabled()) { result |= PrintError(loc, "only one table allowed"); } @@ -137,13 +172,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"); } - if (!elem_type.IsRef()) { - result |= PrintError(loc, "tables must have reference types"); - } + + result |= + CheckReferenceType(loc, elem_type, type_fields_.NumTypes(), "tables"); tables_.push_back(TableType{elem_type, limits}); return result; @@ -196,6 +236,8 @@ Result SharedValidator::OnGlobalImport(const Location& loc, Result SharedValidator::OnGlobal(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; } @@ -204,7 +246,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; @@ -214,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 (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 (iter == func_types_.end()) { - return PrintError(loc, "reference %d is out of range in %s", - static_cast(index), desc); + 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; } @@ -315,6 +456,16 @@ 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(); + + if (index >= type_fields_.NumTypes()) { + result |= + PrintError(loc, "reference %" PRIindex " is out of range", index); + } + } + elem.element = elem_type; return result; } @@ -389,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; } @@ -458,6 +610,15 @@ 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(); + + if (index >= type_fields_.NumTypes()) { + result |= + PrintError(loc, "reference %" PRIindex " is out of range", index); + } + } + out_param_types->clear(); *out_result_types = sig_type.GetInlineVector(); } @@ -470,6 +631,43 @@ 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); + } +} + +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; @@ -511,9 +709,20 @@ 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(); - locals_.push_back(LocalDecl{type, GetLocalCount() + count}); + 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; } @@ -521,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); } @@ -708,12 +930,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; } @@ -723,6 +947,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(); @@ -739,6 +975,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 +1005,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 +1026,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 +1081,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 +1131,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 +1183,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 +1199,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 +1214,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 +1229,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; } @@ -1032,6 +1285,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); @@ -1044,7 +1303,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 +1314,20 @@ 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(); + + 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; } @@ -1072,6 +1343,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 +1362,24 @@ Result SharedValidator::OnReturnCallIndirect(const Location& loc, } result |= typechecker_.OnReturnCallIndirect(func_type.params, func_type.results); + IgnoreLocalRefs(); + 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(); + IgnoreLocalRefs(); return result; } @@ -1103,6 +1387,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(); + + if (index >= type_fields_.NumTypes() || + type_fields_.type_entries[index].kind != Type::FuncRef) { + 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 +1562,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 +1609,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/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/type-checker.cc b/src/type-checker.cc index 90dda71e42..906fa18d0f 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,316 @@ Result TypeChecker::CheckTypeStackEnd(const char* desc) { return result; } +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; + } 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]; + + for (auto it : type.params) { + hash = ComputeHash(hash, it, rec_start); + } + + for (auto it : type.results) { + hash = ComputeHash(hash, it, rec_start); + } + break; + } + case Type::StructRef: { + StructType& type = type_fields_.struct_types[entry.map_index]; + + 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; + } + + 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 (actual_type.params.size() != expected_type.params.size() || + actual_type.results.size() != expected_type.results.size()) { + return false; + } + + 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; + } + } + + 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_); + } + } +} + +uint32_t TypeChecker::ComputeHash(uint32_t hash, Type& type, Index rec_start) { + Type::Enum code = type; + hash = ComputeHash(hash, static_cast(code)); + if (type.IsReferenceWithIndex()) { + Index index = type.GetReferenceIndex(); + if (index >= rec_start) { + index -= rec_start; + } else { + index = type_fields_.type_entries[index].canonical_index; + } + hash = ComputeHash(hash, index); + } + return hash; +} + +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; + } + + 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); + } + } + + 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); + } + + 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 (is_equal) { + return false; + } + + 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; + } + } +} + Result TypeChecker::CheckType(Type actual, Type expected) { if (expected == Type::Any || actual == Type::Any) { return Result::Ok; } - if (actual != expected) { - return Result::Error; + if (CompareType(actual, kInvalidIndex, expected, kInvalidIndex, false)) { + return Result::Ok; } - return Result::Ok; + + return Result::Error; } Result TypeChecker::CheckTypes(const TypeVector& actual, @@ -319,6 +620,23 @@ Result TypeChecker::PopAndCheck3Types(Type expected1, return result; } +Result TypeChecker::PopAndCheckReference(Type* actual, const char* desc) { + Result result = PeekType(0, actual); + + // 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); + 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) { @@ -469,6 +787,36 @@ Result TypeChecker::OnBrIf(Index depth) { return result; } +Result TypeChecker::OnBrOnNonNull(Index depth) { + Type actual; + CHECK_RESULT(PopAndCheckReference(&actual, "br_on_non_null")); + 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()); + + 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()); + + actual.ConvertRefNullToRef(); + PushType(actual); + return result; +} + Result TypeChecker::BeginBrTable() { br_table_sig_ = nullptr; return PopAndCheck1Type(Type::I32, "br_table"); @@ -515,17 +863,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, @@ -554,6 +893,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); } @@ -785,18 +1128,16 @@ 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::OnRefAsNonNullExpr() { + Type actual; + CHECK_RESULT(PopAndCheckReference(&actual, "ref.as_non_null")); + actual.ConvertRefNullToRef(); + PushType(actual); + return Result::Ok; +} + +Result TypeChecker::OnRefFuncExpr(Index func_type) { + PushType(Type(Type::Ref, func_type)); return Result::Ok; } @@ -809,7 +1150,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 fcb4e69be1..764fd84349 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; @@ -189,13 +193,57 @@ 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: + 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; + + default: + return Result::Ok; + } + } + + 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; +} + 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(), @@ -299,6 +347,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) { @@ -321,14 +379,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) { @@ -488,6 +540,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; @@ -524,6 +581,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()); @@ -696,47 +758,95 @@ 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++; } } - result_ |= validator_.EndTypeSection(); + 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) { @@ -751,8 +861,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; } @@ -791,8 +901,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 b452697bfa..3e94a6d8d5 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: @@ -265,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: @@ -327,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)); @@ -335,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, @@ -542,11 +570,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,50 +906,84 @@ bool WastParser::ParseElemExprVarListOpt(ExprListVector* out_list) { return !out_list->empty(); } -Result WastParser::ParseValueType(Var* out_type) { - WABT_TRACE(ParseValueType); +Result WastParser::ParseRefDeclaration(Var* out_type) { + EXPECT(Lpar); + EXPECT(Ref); - const bool is_ref_type = PeekMatchRefType(); - const bool is_value_type = PeekMatch(TokenType::ValueType); + Type::Enum opt_type = Type::Ref; - if (!is_value_type && !is_ref_type) { - return ErrorExpected( - {"i32", "i64", "f32", "f64", "v128", "externref", "exnref", "funcref"}); + if (options_->features.function_references_enabled() && + Match(TokenType::Null)) { + opt_type = Type::RefNull; } - if (is_ref_type) { - EXPECT(Lpar); - EXPECT(Ref); - CHECK_RESULT(ParseVar(out_type)); - EXPECT(Rpar); - return Result::Ok; - } + TokenType token = Peek(0); + bool is_generic_ref = false; - 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(); + switch (token) { + case TokenType::Func: + case TokenType::Extern: + is_generic_ref = true; break; - case Type::ExnRef: - is_enabled = options_->features.exceptions_enabled(); + + 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: - is_enabled = true; break; } - if (!is_enabled) { + if (is_generic_ref) { + out_type->set_opt_type(Consume().type()); + 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, bool is_field) { + WABT_TRACE(ParseValueType); + + if (PeekMatchRefType()) { + return ParseRefDeclaration(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(); + + if ((!is_field || !type.IsPackedType()) && !IsTypeEnabled(type, options_)) { Error(token.loc, "value type not allowed: %s", type.GetName().c_str()); return Result::Error; } - *out_type = Var(type, GetLocation()); + *out_type = Var(0, GetLocation()); + out_type->set_opt_type(type); return Result::Ok; } @@ -942,76 +999,94 @@ 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())) { + 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; } - *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 +1373,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) { + // Index or 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 +1411,35 @@ Result WastParser::ResolveRefTypes(const Module& module, continue; } - assert(index < types->size()); - Type type = (*types)[index]; ref_var.index = kInvalidIndex; - assert(type.IsReferenceWithIndex()); + assert(index < types->size()); + result |= ResolveTargetRefType(module, types->data() + index, ref_var.var, + errors); + } - 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; - } + return Result::Ok; +} - if (type.GetReferenceIndex() != kInvalidIndex) { - // Resolved earlier. - continue; - } +Result WastParser::ResolveTargetFieldVector(const Module& module, + StructType* target_struct, + ReferenceVars* ref_vars, + Errors* errors) { + Result result = Result::Ok; - Index type_index = module.type_bindings.FindIndex(ref_var.var.name()); + for (auto& ref_var : *ref_vars) { + uint32_t index = ref_var.index; - 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; + // The index of resolved variables is converted to kInvalidIndex. + if (index == kInvalidIndex) { continue; } - (*types)[index] = Type(static_cast(type), type_index); + 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; @@ -1355,8 +1449,10 @@ 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(); + resolve_fields_.clear(); while (IsModuleField(PeekPair()) || PeekIsCustom()) { if (PeekIsCustom()) { @@ -1371,15 +1467,25 @@ 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); } + 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_)); @@ -1395,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); @@ -1491,10 +1599,17 @@ 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; + field->elem_segment.elem_type = + Type(Type::FuncRef, options_->features.function_references_enabled() + ? Type::ReferenceNonNull + : Type::ReferenceOrNull); if (PeekMatch(TokenType::Func)) { EXPECT(Func); } @@ -1586,7 +1701,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, @@ -1616,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.index()); - EXPECT(Rpar); - } else { - field->mutable_ = false; - Var type; - CHECK_RESULT(ParseValueType(&type)); - field->type = Type(type.index()); - } - 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; } @@ -1758,7 +1968,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 +2120,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 +2130,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 +2143,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 +2159,17 @@ 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); + if (PeekMatch(TokenType::Lpar)) { + CHECK_RESULT(ParseTerminatingInstrList(&table.init_expr)); + } module->AppendField(std::move(field)); } } @@ -2020,19 +2239,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 +2260,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 +2294,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 +2555,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; } @@ -2360,6 +2575,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); @@ -2392,7 +2617,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; } @@ -2411,6 +2639,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)); @@ -2581,6 +2818,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)); @@ -2588,7 +2830,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 +3251,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 +3280,13 @@ Result WastParser::ParseConstList(ConstVector* consts, ConstType type) { break; case TokenType::RefNull: { auto token = Consume(); - Type type; - CHECK_RESULT(ParseRefKind(&type)); + Var type; + if (Peek() != TokenType::Rpar) { + CHECK_RESULT(ParseRefKind(&type)); + } ErrorUnlessOpcodeEnabled(token); const_.loc = GetLocation(); - const_.set_null(type); + const_.set_null(type.has_opt_type() ? type.opt_type() : Type::FuncRef); break; } case TokenType::RefFunc: { @@ -3437,13 +3685,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 +4134,39 @@ 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(); + 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; + } +} + +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..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; @@ -554,6 +555,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 +591,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 +599,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 +660,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) { @@ -686,6 +704,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; } @@ -882,6 +901,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); @@ -890,7 +915,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; } @@ -928,6 +958,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()) { @@ -1560,7 +1597,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"); @@ -1678,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()) { @@ -1711,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) { @@ -1777,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 06d21a7c8d..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,14 +13,14 @@ section(CODE) { count[1] func { local_decls[1] - locals[1] reference 30 + locals[1] ref 30 } } (;; 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..a517a45c0e 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)) + (elem declare 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/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/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/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..d83bd568ec 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) ) @@ -25,7 +25,7 @@ ) ) - (elem declare funcref (ref.func $square)) + (elem declare func $square) ) (;; STDERR ;;; @@ -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..2e635ccbf5 100644 --- a/test/dump/typed_func_refs_results.txt +++ b/test/dump/typed_func_refs_results.txt @@ -33,13 +33,13 @@ ) (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)) ) ) - (elem declare funcref (ref.func $square) (ref.func $double)) + (elem declare func $square $double) ) (;; STDERR ;;; @@ -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/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/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-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/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/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/fold-callref.txt b/test/roundtrip/fold-callref.txt index fdfbcae052..b3a8fe6925 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,17 +50,21 @@ (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))) - (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/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/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/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/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/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/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/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/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..4eeba07b35 --- /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: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)) + ^^^^^^ +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/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/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..e4be27c8d9 --- /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: 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 +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/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/ref_is_null.txt b/test/spec/function-references/ref_is_null.txt new file mode 100644 index 0000000000..4b0bb5a7f7 --- /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 [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 [funcref] 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/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 ;;) 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/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/spec/function-references/unreached-invalid.txt b/test/spec/function-references/unreached-invalid.txt new file mode 100644 index 0000000000..ead31d4f55 --- /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: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 +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/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/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/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 ;;) 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) 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 ;;)