diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2022-07-20 20:13:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-20 20:13:18 -0700 |
commit | da5035f893ce9e046f99cf3ede92b576024aa9da (patch) | |
tree | 9db48e77502a646d74ef1a9d11f9b8f0967ff856 | |
parent | 1c53f7dd29e79bc1894959cad817b22f087689f7 (diff) | |
download | binaryen-da5035f893ce9e046f99cf3ede92b576024aa9da.tar.gz binaryen-da5035f893ce9e046f99cf3ede92b576024aa9da.tar.bz2 binaryen-da5035f893ce9e046f99cf3ede92b576024aa9da.zip |
Remove basic reference types (#4802)
Basic reference types like `Type::funcref`, `Type::anyref`, etc. made it easy to
accidentally forget to handle reference types with the same basic HeapTypes but
the opposite nullability. In principle there is nothing special about the types
with shorthands except in the binary and text formats. Removing these shorthands
from the internal type representation by removing all basic reference types
makes some code more complicated locally, but simplifies code globally and
encourages properly handling both nullable and non-nullable reference types.
46 files changed, 591 insertions, 871 deletions
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index 38eb029f4..314c2494f 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -33,12 +33,6 @@ JsType wasmToJsType(Type type) { return JS_INT64; case Type::v128: WASM_UNREACHABLE("v128 not implemented yet"); - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("reference types are not supported by wasm2js"); case Type::none: return JS_NONE; case Type::unreachable: @@ -60,16 +54,6 @@ char getSig(Type type) { return 'd'; case Type::v128: return 'V'; - case Type::funcref: - return 'F'; - case Type::anyref: - return 'A'; - case Type::eqref: - return 'Q'; - case Type::i31ref: - return 'I'; - case Type::dataref: - return 'D'; case Type::none: return 'v'; case Type::unreachable: diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index e2afe66dc..d0e99ac0b 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -51,6 +51,29 @@ static_assert(sizeof(BinaryenLiteral) == sizeof(Literal), BinaryenLiteral toBinaryenLiteral(Literal x) { BinaryenLiteral ret; ret.type = x.type.getID(); + if (x.type.isRef()) { + auto heapType = x.type.getHeapType(); + if (heapType.isBasic()) { + switch (heapType.getBasic()) { + case HeapType::func: + ret.func = x.isNull() ? nullptr : x.getFunc().c_str(); + break; + case HeapType::any: + case HeapType::eq: + assert(x.isNull() && "unexpected non-null reference type literal"); + break; + case HeapType::i31: + case HeapType::data: + case HeapType::string: + case HeapType::stringview_wtf8: + case HeapType::stringview_wtf16: + case HeapType::stringview_iter: + WASM_UNREACHABLE("TODO: reftypes"); + } + return ret; + } + WASM_UNREACHABLE("TODO: reftypes"); + } TODO_SINGLE_COMPOUND(x.type); switch (x.type.getBasic()) { case Type::i32: @@ -68,16 +91,6 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { case Type::v128: memcpy(&ret.v128, x.getv128Ptr(), 16); break; - case Type::funcref: - ret.func = x.isNull() ? nullptr : x.getFunc().c_str(); - break; - case Type::anyref: - case Type::eqref: - assert(x.isNull() && "unexpected non-null reference type literal"); - break; - case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("TODO: reftypes"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -86,7 +99,30 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { } Literal fromBinaryenLiteral(BinaryenLiteral x) { - switch (x.type) { + auto type = Type(x.type); + if (type.isRef()) { + auto heapType = type.getHeapType(); + if (type.isNullable()) { + return Literal::makeNull(heapType); + } + if (heapType.isBasic()) { + switch (heapType.getBasic()) { + case HeapType::func: + return Literal::makeFunc(x.func); + case HeapType::any: + case HeapType::eq: + case HeapType::i31: + case HeapType::data: + case HeapType::string: + case HeapType::stringview_wtf8: + case HeapType::stringview_wtf16: + case HeapType::stringview_iter: + WASM_UNREACHABLE("TODO: reftypes"); + } + } + } + assert(type.isBasic()); + switch (type.getBasic()) { case Type::i32: return Literal(x.i32); case Type::i64: @@ -97,14 +133,6 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { return Literal(x.i64).castToF64(); case Type::v128: return Literal(x.v128); - case Type::funcref: - return Literal::makeFunc(x.func); - case Type::anyref: - case Type::eqref: - return Literal::makeNull(Type(x.type).getHeapType()); - case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("TODO: reftypes"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -137,12 +165,24 @@ BinaryenType BinaryenTypeInt64(void) { return Type::i64; } BinaryenType BinaryenTypeFloat32(void) { return Type::f32; } BinaryenType BinaryenTypeFloat64(void) { return Type::f64; } BinaryenType BinaryenTypeVec128(void) { return Type::v128; } -BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; } -BinaryenType BinaryenTypeExternref(void) { return Type::anyref; } -BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; } -BinaryenType BinaryenTypeEqref(void) { return Type::eqref; } -BinaryenType BinaryenTypeI31ref(void) { return Type::i31ref; } -BinaryenType BinaryenTypeDataref(void) { return Type::dataref; } +BinaryenType BinaryenTypeFuncref(void) { + return Type(HeapType::func, Nullable).getID(); +} +BinaryenType BinaryenTypeExternref(void) { + return Type(HeapType::any, Nullable).getID(); +} +BinaryenType BinaryenTypeAnyref(void) { + return Type(HeapType::any, Nullable).getID(); +} +BinaryenType BinaryenTypeEqref(void) { + return Type(HeapType::eq, Nullable).getID(); +} +BinaryenType BinaryenTypeI31ref(void) { + return Type(HeapType::i31, NonNullable).getID(); +} +BinaryenType BinaryenTypeDataref(void) { + return Type(HeapType::data, NonNullable).getID(); +} BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; } BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); } diff --git a/src/ir/abstract.h b/src/ir/abstract.h index 63057a975..feac9b50d 100644 --- a/src/ir/abstract.h +++ b/src/ir/abstract.h @@ -121,11 +121,6 @@ inline UnaryOp getUnary(Type type, Op op) { break; } case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: { return InvalidUnary; @@ -293,11 +288,6 @@ inline BinaryOp getBinary(Type type, Op op) { break; } case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: { return InvalidBinary; diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index dc04cdba2..e24dd6452 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -143,11 +143,11 @@ void TableSlotManager::addSlot(Name func, Slot slot) { TableSlotManager::TableSlotManager(Module& module) : module(module) { // TODO: Reject or handle passive element segments - auto it = std::find_if(module.tables.begin(), - module.tables.end(), - [&](std::unique_ptr<Table>& table) { - return table->type == Type::funcref; - }); + auto funcref = Type(HeapType::func, Nullable); + auto it = std::find_if( + module.tables.begin(), + module.tables.end(), + [&](std::unique_ptr<Table>& table) { return table->type == funcref; }); if (it == module.tables.end()) { return; } @@ -163,7 +163,7 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) { // append new items at constant offsets after all existing items at constant // offsets. if (activeTableSegments.size() == 1 && - activeTableSegments[0]->type == Type::funcref && + activeTableSegments[0]->type == funcref && !activeTableSegments[0]->offset->is<Const>()) { assert(activeTableSegments[0]->offset->is<GlobalGet>() && "Unexpected initializer instruction"); diff --git a/src/ir/table-utils.cpp b/src/ir/table-utils.cpp index 0d47f155b..fb9285319 100644 --- a/src/ir/table-utils.cpp +++ b/src/ir/table-utils.cpp @@ -76,7 +76,8 @@ bool usesExpressions(ElementSegment* curr, Module* module) { // declare a type that is a subtype of that, so it must use the post-MVP form // of using expressions. bool hasTableOfSpecializedType = - curr->table.is() && module->getTable(curr->table)->type != Type::funcref; + curr->table.is() && + module->getTable(curr->table)->type != Type(HeapType::func, Nullable); return !allElementsRefFunc || hasTableOfSpecializedType; } diff --git a/src/literal.h b/src/literal.h index 4caeab9d4..c37f74499 100644 --- a/src/literal.h +++ b/src/literal.h @@ -251,11 +251,12 @@ public: static Literal makeNull(HeapType type) { return Literal(Type(type, Nullable)); } - static Literal makeFunc(Name func, Type type = Type::funcref) { + static Literal makeFunc(Name func, + Type type = Type(HeapType::func, Nullable)) { return Literal(func, type); } static Literal makeI31(int32_t value) { - auto lit = Literal(Type::i31ref); + auto lit = Literal(Type(HeapType::i31, NonNullable)); lit.i32 = value & 0x7fffffff; return lit; } @@ -753,20 +754,7 @@ struct RttSupers : std::vector<RttSuper> {}; namespace std { template<> struct hash<wasm::Literal> { size_t operator()(const wasm::Literal& a) const { - auto digest = wasm::hash(a.type.getID()); - auto hashRef = [&]() { - assert(a.type.isRef()); - if (a.isNull()) { - return digest; - } - if (a.type.isFunction()) { - wasm::rehash(digest, a.getFunc()); - return digest; - } - // other non-null reference type literals cannot represent concrete - // values, i.e. there is no concrete anyref or eqref other than null. - WASM_UNREACHABLE("unexpected type"); - }; + auto digest = wasm::hash(a.type); if (a.type.isBasic()) { switch (a.type.getBasic()) { case wasm::Type::i32: @@ -787,20 +775,25 @@ template<> struct hash<wasm::Literal> { wasm::rehash(digest, chunks[0]); wasm::rehash(digest, chunks[1]); return digest; - case wasm::Type::funcref: - case wasm::Type::anyref: - case wasm::Type::eqref: - case wasm::Type::dataref: - return hashRef(); - case wasm::Type::i31ref: - wasm::rehash(digest, a.geti31(true)); - return digest; case wasm::Type::none: case wasm::Type::unreachable: break; } } else if (a.type.isRef()) { - return hashRef(); + if (a.isNull()) { + return digest; + } + if (a.type.isFunction()) { + wasm::rehash(digest, a.getFunc()); + return digest; + } + if (a.type.getHeapType() == wasm::HeapType::i31) { + wasm::rehash(digest, a.geti31(true)); + return digest; + } + // other non-null reference type literals cannot represent concrete + // values, i.e. there is no concrete anyref or eqref other than null. + WASM_UNREACHABLE("unexpected type"); } else if (a.type.isRtt()) { const auto& supers = a.getRttSupers(); wasm::rehash(digest, supers.size()); diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index 3320c129b..3d9ac5e90 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -89,15 +89,9 @@ private: size = value.type.getByteSize(); break; } - // not implemented yet + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: { return false; - } case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 704f44e03..5e62ec9fc 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -62,13 +62,6 @@ static Expression* toABI(Expression* value, Module* module) { case Type::v128: { WASM_UNREACHABLE("v128 not implemented yet"); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: { - WASM_UNREACHABLE("reference types cannot be converted to i64"); - } case Type::none: { // the value is none, but we need a value here value = @@ -107,13 +100,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) { case Type::v128: { WASM_UNREACHABLE("v128 not implemented yet"); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: { - WASM_UNREACHABLE("reference types cannot be converted from i64"); - } case Type::none: { value = builder.makeDrop(value); break; diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index 3bf23b61c..761aac2a9 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -58,9 +58,6 @@ Name get_f64("get_f64"); Name get_v128("get_v128"); Name get_funcref("get_funcref"); Name get_anyref("get_anyref"); -Name get_eqref("get_eqref"); -Name get_i31ref("get_i31ref"); -Name get_dataref("get_dataref"); Name set_i32("set_i32"); Name set_i64("set_i64"); @@ -69,48 +66,41 @@ Name set_f64("set_f64"); Name set_v128("set_v128"); Name set_funcref("set_funcref"); Name set_anyref("set_anyref"); -Name set_eqref("set_eqref"); -Name set_i31ref("set_i31ref"); -Name set_dataref("set_dataref"); struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { void visitLocalGet(LocalGet* curr) { Builder builder(*getModule()); Name import; - TODO_SINGLE_COMPOUND(curr->type); - switch (curr->type.getBasic()) { - case Type::i32: - import = get_i32; - break; - case Type::i64: - return; // TODO - case Type::f32: - import = get_f32; - break; - case Type::f64: - import = get_f64; - break; - case Type::v128: - import = get_v128; - break; - case Type::funcref: + if (curr->type.isRef()) { + auto heapType = curr->type.getHeapType(); + if (heapType == HeapType::func && curr->type.isNullable()) { import = get_funcref; - break; - case Type::anyref: + } else if (heapType == HeapType::any && curr->type.isNullable()) { import = get_anyref; - break; - case Type::eqref: - import = get_eqref; - break; - case Type::i31ref: - import = get_i31ref; - break; - case Type::dataref: - import = get_dataref; - break; - case Type::none: - case Type::unreachable: - WASM_UNREACHABLE("unexpected type"); + } else { + WASM_UNREACHABLE("TODO: general reference types"); + } + } else { + TODO_SINGLE_COMPOUND(curr->type); + switch (curr->type.getBasic()) { + case Type::i32: + import = get_i32; + break; + case Type::i64: + return; // TODO + case Type::f32: + import = get_f32; + break; + case Type::f64: + import = get_f64; + break; + case Type::v128: + import = get_v128; + break; + case Type::none: + case Type::unreachable: + WASM_UNREACHABLE("unexpected type"); + } } replaceCurrent(builder.makeCall(import, {builder.makeConst(int32_t(id++)), @@ -130,45 +120,41 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { Builder builder(*getModule()); Name import; auto type = curr->value->type; - if (type.isFunction() && type != Type::funcref) { + if (type.isFunction() && type.getHeapType() != HeapType::func) { // FIXME: support typed function references return; } - TODO_SINGLE_COMPOUND(curr->value->type); - switch (type.getBasic()) { - case Type::i32: - import = set_i32; - break; - case Type::i64: - return; // TODO - case Type::f32: - import = set_f32; - break; - case Type::f64: - import = set_f64; - break; - case Type::v128: - import = set_v128; - break; - case Type::funcref: + if (type.isRef()) { + auto heapType = type.getHeapType(); + if (heapType == HeapType::func && type.isNullable()) { import = set_funcref; - break; - case Type::anyref: + } else if (heapType == HeapType::any && type.isNullable()) { import = set_anyref; - break; - case Type::eqref: - import = set_eqref; - break; - case Type::i31ref: - import = set_i31ref; - break; - case Type::dataref: - import = set_dataref; - break; - case Type::unreachable: - return; // nothing to do here - default: - WASM_UNREACHABLE("unexpected type"); + } else { + WASM_UNREACHABLE("TODO: general reference types"); + } + } else { + TODO_SINGLE_COMPOUND(curr->value->type); + switch (type.getBasic()) { + case Type::i32: + import = set_i32; + break; + case Type::i64: + return; // TODO + case Type::f32: + import = set_f32; + break; + case Type::f64: + import = set_f64; + break; + case Type::v128: + import = set_v128; + break; + case Type::unreachable: + return; // nothing to do here + case Type::none: + WASM_UNREACHABLE("unexpected type"); + } } curr->value = builder.makeCall(import, {builder.makeConst(int32_t(id++)), @@ -188,36 +174,13 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { addImport(curr, set_f64, {Type::i32, Type::i32, Type::f64}, Type::f64); if (curr->features.hasReferenceTypes()) { - addImport(curr, - get_funcref, - {Type::i32, Type::i32, Type::funcref}, - Type::funcref); - addImport(curr, - set_funcref, - {Type::i32, Type::i32, Type::funcref}, - Type::funcref); - addImport( - curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); - addImport( - curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); - if (curr->features.hasGC()) { - addImport( - curr, get_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref); - addImport( - curr, set_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref); - addImport( - curr, get_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref); - addImport( - curr, set_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref); - addImport(curr, - get_dataref, - {Type::i32, Type::i32, Type::dataref}, - Type::dataref); - addImport(curr, - set_dataref, - {Type::i32, Type::i32, Type::dataref}, - Type::dataref); - } + Type func = Type(HeapType::func, Nullable); + Type any = Type(HeapType::any, Nullable); + + addImport(curr, get_funcref, {Type::i32, Type::i32, func}, func); + addImport(curr, set_funcref, {Type::i32, Type::i32, func}, func); + addImport(curr, get_anyref, {Type::i32, Type::i32, any}, any); + addImport(curr, set_anyref, {Type::i32, Type::i32, any}, any); } if (curr->features.hasSIMD()) { addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 9d50275b9..9ab8e20d9 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1472,7 +1472,8 @@ struct OptimizeInstructions // there. // // See "notes on removing casts", above, for when this is safe to do. - void skipCast(Expression*& input, Type requiredType = Type::anyref) { + void skipCast(Expression*& input, + Type requiredType = Type(HeapType::any, Nullable)) { // Traps-never-happen mode is a requirement for us to optimize here. if (!getPassOptions().trapsNeverHappen) { return; @@ -1523,8 +1524,9 @@ struct OptimizeInstructions // This is safe to do first because nothing farther down cares about the // type, and we consume the two input references, so removing a cast could // not help our parents (see "notes on removing casts"). - skipCast(curr->left, Type::eqref); - skipCast(curr->right, Type::eqref); + Type nullableEq = Type(HeapType::eq, Nullable); + skipCast(curr->left, nullableEq); + skipCast(curr->right, nullableEq); // Identical references compare equal. // (Technically we do not need to check if the inputs are also foldable into diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index f599990a0..156c33c3f 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -249,7 +249,8 @@ struct Precompute curr->finalize(); return; } - } else if (singleValue.type == Type::funcref) { + } else if (singleValue.type.isRef() && + singleValue.type.getHeapType() == HeapType::func) { if (auto* r = curr->value->template dynCast<RefFunc>()) { r->func = singleValue.getFunc(); r->finalize(); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index ca2985240..440ff114f 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -72,6 +72,62 @@ static std::ostream& printLocal(Index index, Function* func, std::ostream& o) { namespace { +static bool maybePrintRefShorthand(std::ostream& o, Type type) { + if (!type.isRef()) { + return false; + } + auto heapType = type.getHeapType(); + if (heapType.isBasic()) { + if (type.isNullable()) { + switch (heapType.getBasic()) { + case HeapType::func: + o << "funcref"; + return true; + case HeapType::any: + o << "anyref"; + return true; + case HeapType::eq: + o << "eqref"; + return true; + case HeapType::i31: + case HeapType::data: + break; + case HeapType::string: + o << "stringref"; + return true; + case HeapType::stringview_wtf8: + o << "stringview_wtf8"; + return true; + case HeapType::stringview_wtf16: + o << "stringview_wtf16"; + return true; + case HeapType::stringview_iter: + o << "stringview_iter"; + return true; + } + } else { + switch (heapType.getBasic()) { + case HeapType::func: + case HeapType::any: + case HeapType::eq: + break; + case HeapType::i31: + o << "i31ref"; + return true; + case HeapType::data: + o << "dataref"; + return true; + case HeapType::string: + case HeapType::stringview_wtf8: + case HeapType::stringview_wtf16: + case HeapType::stringview_iter: + break; + } + } + } + return false; +} + // Helper for printing the name of a type. This output is guaranteed to not // contain spaces. struct TypeNamePrinter { @@ -126,13 +182,15 @@ void TypeNamePrinter::print(Type type) { } else if (type.isRtt()) { print(type.getRtt()); } else if (type.isRef()) { - os << "ref"; - if (type.isNullable()) { - os << "?"; + if (!maybePrintRefShorthand(os, type)) { + os << "ref"; + if (type.isNullable()) { + os << "?"; + } + os << '|'; + print(type.getHeapType()); + os << '|'; } - os << '|'; - print(type.getHeapType()); - os << '|'; } else { WASM_UNREACHABLE("unexpected type"); } @@ -273,29 +331,15 @@ static std::ostream& printType(std::ostream& o, Type type, Module* wasm) { } TypeNamePrinter(o, wasm).print(rtt.heapType); o << ')'; - } else if (type.isRef() && !type.isBasic()) { - auto heapType = type.getHeapType(); - if (type.isNullable() && heapType.isBasic()) { - // Print shorthands for certain nullable basic heap types. - switch (heapType.getBasic()) { - case HeapType::string: - return o << "stringref"; - case HeapType::stringview_wtf8: - return o << "stringview_wtf8"; - case HeapType::stringview_wtf16: - return o << "stringview_wtf16"; - case HeapType::stringview_iter: - return o << "stringview_iter"; - default: - break; + } else if (type.isRef()) { + if (!maybePrintRefShorthand(o, type)) { + o << "(ref "; + if (type.isNullable()) { + o << "null "; } + TypeNamePrinter(o, wasm).print(type.getHeapType()); + o << ')'; } - o << "(ref "; - if (type.isNullable()) { - o << "null "; - } - TypeNamePrinter(o, wasm).print(type.getHeapType()); - o << ')'; } else { WASM_UNREACHABLE("unexpected type"); } diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 5489e7638..59c9dca45 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -260,15 +260,15 @@ void TranslateToFuzzReader::setupTables() { // Ensure a funcref element segment and table exist. Segments with more // specific function types may have a smaller chance of getting functions. Table* table = nullptr; - auto iter = - std::find_if(wasm.tables.begin(), wasm.tables.end(), [&](auto& table) { - return table->type == Type::funcref; - }); + Type funcref = Type(HeapType::func, Nullable); + auto iter = std::find_if(wasm.tables.begin(), + wasm.tables.end(), + [&](auto& table) { return table->type == funcref; }); if (iter != wasm.tables.end()) { table = iter->get(); } else { auto tablePtr = builder.makeTable( - Names::getValidTableName(wasm, "fuzzing_table"), Type::funcref, 0, 0); + Names::getValidTableName(wasm, "fuzzing_table"), funcref, 0, 0); tablePtr->hasExplicitName = true; table = wasm.addTable(std::move(tablePtr)); } @@ -277,7 +277,7 @@ void TranslateToFuzzReader::setupTables() { std::any_of(wasm.elementSegments.begin(), wasm.elementSegments.end(), [&](auto& segment) { - return segment->table.is() && segment->type == Type::funcref; + return segment->table.is() && segment->type == funcref; }); if (!hasFuncrefElemSegment) { // TODO: use a random table @@ -934,7 +934,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) { if (type.isTuple()) { options.add(FeatureSet::Multivalue, &Self::makeTupleMake); } - if (type == Type::i31ref) { + if (type.isRef() && type.getHeapType() == HeapType::i31) { options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeI31New); } // TODO: struct.get and other GC things @@ -1463,11 +1463,6 @@ Expression* TranslateToFuzzReader::makeNonAtomicLoad(Type type) { return builder.makeLoad( 16, false, offset, pick(1, 2, 4, 8, 16), ptr, type); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1566,11 +1561,6 @@ Expression* TranslateToFuzzReader::makeNonAtomicStore(Type type) { return builder.makeStore( 16, offset, pick(1, 2, 4, 8, 16), ptr, value, type); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1701,11 +1691,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) { case Type::f64: return Literal(getDouble()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1747,11 +1732,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) { case Type::f64: return Literal(double(small)); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1816,11 +1796,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) { std::numeric_limits<uint64_t>::max())); break; case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1844,11 +1819,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) { value = Literal(double(int64_t(1) << upTo(64))); break; case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2115,11 +2085,6 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) { AllTrueVecI32x4), make(Type::v128)}); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2255,11 +2220,6 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) { } WASM_UNREACHABLE("invalid value"); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2493,11 +2453,6 @@ Expression* TranslateToFuzzReader::makeBinary(Type type) { make(Type::v128), make(Type::v128)}); } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2700,11 +2655,6 @@ Expression* TranslateToFuzzReader::makeSIMDExtract(Type type) { op = ExtractLaneVecF64x2; break; case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2892,7 +2842,7 @@ Expression* TranslateToFuzzReader::makeRefEq(Type type) { } Expression* TranslateToFuzzReader::makeI31New(Type type) { - assert(type == Type::i31ref); + assert(type.isRef() && type.getHeapType() == HeapType::i31); assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC()); auto* value = make(Type::i32); return builder.makeI31New(value); @@ -2901,7 +2851,9 @@ Expression* TranslateToFuzzReader::makeI31New(Type type) { Expression* TranslateToFuzzReader::makeI31Get(Type type) { assert(type == Type::i32); assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC()); - auto* i31 = make(Type::i31ref); + // TODO: Maybe this should be nullable? + // https://github.com/WebAssembly/gc/issues/312 + auto* i31 = make(Type(HeapType::i31, NonNullable)); return builder.makeI31Get(i31, bool(oneIn(2))); } @@ -2958,7 +2910,9 @@ Type TranslateToFuzzReader::getSingleConcreteType() { WeightedOption{Type::f32, VeryImportant}, WeightedOption{Type::f64, VeryImportant}) .add(FeatureSet::SIMD, WeightedOption{Type::v128, Important}) - .add(FeatureSet::ReferenceTypes, Type::funcref, Type::anyref) + .add(FeatureSet::ReferenceTypes, + Type(HeapType::func, Nullable), + Type(HeapType::any, Nullable)) .add(FeatureSet::ReferenceTypes | FeatureSet::GC, // Type(HeapType::func, NonNullable), // Type(HeapType::any, NonNullable), @@ -2974,7 +2928,7 @@ Type TranslateToFuzzReader::getReferenceType() { return pick(FeatureOptions<Type>() // Avoid Type::anyref without GC enabled, see // TranslateToFuzzReader::getSingleConcreteType. - .add(FeatureSet::ReferenceTypes, Type::funcref) + .add(FeatureSet::ReferenceTypes, Type(HeapType::func, Nullable)) .add(FeatureSet::ReferenceTypes | FeatureSet::GC, Type(HeapType::func, NonNullable), Type(HeapType::any, NonNullable), diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index 77891ce53..edb96977d 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -163,13 +163,7 @@ struct HeapTypeGeneratorImpl { return rand.pick( Random::FeatureOptions<Type::BasicType>{} .add(FeatureSet::MVP, Type::i32, Type::i64, Type::f32, Type::f64) - .add(FeatureSet::SIMD, Type::v128) - .add(FeatureSet::ReferenceTypes | FeatureSet::GC, - Type::funcref, - Type::anyref, - Type::eqref, - Type::i31ref, - Type::dataref)); + .add(FeatureSet::SIMD, Type::v128)); } HeapType generateHeapType() { diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index c2a49c598..366e8d4fc 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -52,18 +52,6 @@ inline std::string generateSpecWrapper(Module& wasm) { case Type::v128: ret += "(v128.const i32x4 0 0 0 0)"; break; - case Type::funcref: - ret += "(ref.null func)"; - break; - case Type::anyref: - ret += "(ref.null any)"; - break; - case Type::eqref: - ret += "(ref.null eq)"; - break; - case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("TODO: reftypes"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index a4d326426..28cc77e95 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -626,13 +626,9 @@ struct Reducer case Type::f64: fixed = builder->makeUnary(TruncSFloat64ToInt32, child); break; + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - continue; // not implemented yet + continue; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -653,13 +649,9 @@ struct Reducer case Type::f64: fixed = builder->makeUnary(TruncSFloat64ToInt64, child); break; + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - continue; // not implemented yet + continue; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -680,13 +672,9 @@ struct Reducer case Type::f64: fixed = builder->makeUnary(DemoteFloat64, child); break; + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - continue; // not implemented yet + continue; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -707,26 +695,18 @@ struct Reducer break; case Type::f64: WASM_UNREACHABLE("unexpected type"); + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - continue; // not implemented yet + continue; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); } break; } + // not implemented yet case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - continue; // not implemented yet + continue; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 617d56313..51eafb652 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -347,8 +347,8 @@ protected: spectest->addExport( builder.makeExport("global_f64", Name::fromInt(3), ExternalKind::Global)); - spectest->addTable( - builder.makeTable(Name::fromInt(0), Type::funcref, 10, 20)); + spectest->addTable(builder.makeTable( + Name::fromInt(0), Type(HeapType::func, Nullable), 10, 20)); spectest->addExport( builder.makeExport("table", Name::fromInt(0), ExternalKind::Table)); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index eec86bc50..d76d24b21 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -82,7 +82,8 @@ public: } static std::unique_ptr<Table> makeTable(Name name, - Type type = Type::funcref, + Type type = Type(HeapType::func, + Nullable), Address initial = 0, Address max = Table::kMaxSize) { auto table = std::make_unique<Table>(); @@ -97,7 +98,7 @@ public: makeElementSegment(Name name, Name table, Expression* offset = nullptr, - Type type = Type::funcref) { + Type type = Type(HeapType::func, Nullable)) { auto seg = std::make_unique<ElementSegment>(); seg->name = name; seg->table = table; @@ -1114,20 +1115,14 @@ public: if (type.isFunction()) { return makeRefFunc(value.getFunc(), type.getHeapType()); } + if (type.isRef() && type.getHeapType() == HeapType::i31) { + return makeI31New(makeConst(value.geti31())); + } if (type.isRtt()) { return makeRtt(value.type); } TODO_SINGLE_COMPOUND(type); - switch (type.getBasic()) { - case Type::anyref: - case Type::eqref: - assert(value.isNull() && "unexpected non-null reference type literal"); - return makeRefNull(type); - case Type::i31ref: - return makeI31New(makeConst(value.geti31())); - default: - WASM_UNREACHABLE("invalid constant expression"); - } + WASM_UNREACHABLE("unsupported constant expression"); } Expression* makeConstantExpression(Literals values) { @@ -1273,7 +1268,10 @@ public: if (curr->type.isNullable()) { return ExpressionManipulator::refNull(curr, curr->type); } - if (curr->type.isFunction() || !curr->type.isBasic()) { + if (curr->type.isRef() && curr->type.getHeapType() == HeapType::i31) { + return makeI31New(makeConst(0)); + } + if (!curr->type.isBasic()) { // We can't do any better, keep the original. return curr; } @@ -1298,15 +1296,6 @@ public: value = Literal(bytes.data()); break; } - case Type::funcref: - WASM_UNREACHABLE("handled above"); - case Type::anyref: - case Type::eqref: - return ExpressionManipulator::refNull(curr, curr->type); - case Type::i31ref: - return makeI31New(makeConst(0)); - case Type::dataref: - return curr; case Type::none: return ExpressionManipulator::nop(curr); case Type::unreachable: diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 478b33bc4..eb5dcd5a7 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2396,11 +2396,6 @@ public: return Literal(load64u(addr)).castToF64(); case Type::v128: return Literal(load128(addr).data()); - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2454,11 +2449,6 @@ public: case Type::v128: store128(addr, value.getv128()); break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm-type.h b/src/wasm-type.h index 23e559aad..4d87ac68d 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -106,14 +106,8 @@ public: f32, f64, v128, - funcref, - anyref, - eqref, - // From here types are non-nullable. - i31ref, - dataref, }; - static constexpr BasicType _last_basic_type = dataref; + static constexpr BasicType _last_basic_type = v128; Type() : id(none) {} diff --git a/src/wasm.h b/src/wasm.h index b5d51b84b..99a2d9f94 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -2036,11 +2036,13 @@ class ElementSegment : public Named { public: Name table; Expression* offset; - Type type = Type::funcref; + Type type = Type(HeapType::func, Nullable); std::vector<Expression*> data; ElementSegment() = default; - ElementSegment(Name table, Expression* offset, Type type = Type::funcref) + ElementSegment(Name table, + Expression* offset, + Type type = Type(HeapType::func, Nullable)) : table(table), offset(offset), type(type) {} ElementSegment(Name table, Expression* offset, @@ -2060,7 +2062,7 @@ public: Address initial = 0; Address max = kMaxSize; - Type type = Type::funcref; + Type type = Type(HeapType::func, Nullable); bool hasMax() { return max != kUnlimitedSize; } void clear() { diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 6c7689990..85e93f912 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -46,11 +46,6 @@ Literal::Literal(Type type) : type(type) { case Type::none: return; case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } } @@ -100,11 +95,6 @@ Literal::Literal(const Literal& other) : type(other.type) { case Type::none: return; case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } } @@ -239,7 +229,7 @@ Literals Literal::makeNegOnes(Type type) { Literal Literal::makeZero(Type type) { assert(type.isSingle()); if (type.isRef()) { - if (type == Type::i31ref) { + if (type.getHeapType() == HeapType::i31) { return makeI31(0); } else { return makeNull(type.getHeapType()); @@ -355,11 +345,6 @@ void Literal::getBits(uint8_t (&buf)[16]) const { break; case Type::none: case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: WASM_UNREACHABLE("invalid type"); } } @@ -373,43 +358,37 @@ bool Literal::operator==(const Literal& other) const { if (type != other.type) { return false; } - auto compareRef = [&]() { - assert(type.isRef()); - // Note that we've already handled nulls earlier. - if (type.isFunction()) { - assert(func.is() && other.func.is()); - return func == other.func; - } - if (type.isData()) { - return gcData == other.gcData; - } - // other non-null reference type literals cannot represent concrete values, - // i.e. there is no concrete anyref or eqref other than null. - WASM_UNREACHABLE("unexpected type"); - }; if (type.isBasic()) { switch (type.getBasic()) { case Type::none: return true; // special voided literal case Type::i32: case Type::f32: - case Type::i31ref: return i32 == other.i32; case Type::i64: case Type::f64: return i64 == other.i64; case Type::v128: return memcmp(v128, other.v128, 16) == 0; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::dataref: - return compareRef(); case Type::unreachable: break; } } else if (type.isRef()) { - return compareRef(); + assert(type.isRef()); + // Note that we've already handled nulls earlier. + if (type.isFunction()) { + assert(func.is() && other.func.is()); + return func == other.func; + } + if (type.isData()) { + return gcData == other.gcData; + } + if (type.getHeapType() == HeapType::i31) { + return i32 == other.i32; + } + // other non-null reference type literals cannot represent concrete values, + // i.e. there is no concrete anyref or eqref other than null. + WASM_UNREACHABLE("unexpected type"); } else if (type.isRtt()) { return *rttSupers == *other.rttSupers; } @@ -578,11 +557,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { o << "i32x4 "; literal.printVec128(o, literal.getv128()); break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); } @@ -801,11 +775,6 @@ Literal Literal::eqz() const { case Type::f64: return eq(Literal(double(0))); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -824,11 +793,6 @@ Literal Literal::neg() const { case Type::f64: return Literal(int64_t(i64 ^ 0x8000000000000000ULL)).castToF64(); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -847,11 +811,6 @@ Literal Literal::abs() const { case Type::f64: return Literal(int64_t(i64 & 0x7fffffffffffffffULL)).castToF64(); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -987,11 +946,6 @@ Literal Literal::add(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() + other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1010,11 +964,6 @@ Literal Literal::sub(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() - other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1112,11 +1061,6 @@ Literal Literal::mul(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() * other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1347,11 +1291,6 @@ Literal Literal::eq(const Literal& other) const { case Type::f64: return Literal(getf64() == other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1370,11 +1309,6 @@ Literal Literal::ne(const Literal& other) const { case Type::f64: return Literal(getf64() != other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index e2588422c..5427deea1 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -693,6 +693,7 @@ void WasmBinaryWriter::writeElementSegments() { auto start = startSection(BinaryConsts::Section::Element); o << U32LEB(elemCount); + Type funcref = Type(HeapType::func, Nullable); for (auto& segment : wasm->elementSegments) { Index tableIdx = 0; @@ -708,7 +709,7 @@ void WasmBinaryWriter::writeElementSegments() { if (!isPassive) { tableIdx = getTableIndex(segment->table); hasTableIndex = - tableIdx > 0 || wasm->getTable(segment->table)->type != Type::funcref; + tableIdx > 0 || wasm->getTable(segment->table)->type != funcref; } uint32_t flags = 0; @@ -1339,7 +1340,36 @@ void WasmBinaryWriter::writeInlineBuffer(const char* data, size_t size) { } void WasmBinaryWriter::writeType(Type type) { - if (type.isRef() && !type.isBasic()) { + if (type.isRef()) { + auto heapType = type.getHeapType(); + if (heapType.isBasic()) { + if (type.isNullable()) { + switch (heapType.getBasic()) { + case HeapType::any: + o << S32LEB(BinaryConsts::EncodedType::anyref); + return; + case HeapType::func: + o << S32LEB(BinaryConsts::EncodedType::funcref); + return; + case HeapType::eq: + o << S32LEB(BinaryConsts::EncodedType::eqref); + return; + default: + break; + } + } else { + switch (heapType.getBasic()) { + case HeapType::i31: + o << S32LEB(BinaryConsts::EncodedType::i31ref); + return; + case HeapType::data: + o << S32LEB(BinaryConsts::EncodedType::dataref); + return; + default: + break; + } + } + } if (type.isNullable()) { o << S32LEB(BinaryConsts::EncodedType::nullable); } else { @@ -1381,21 +1411,6 @@ void WasmBinaryWriter::writeType(Type type) { case Type::v128: ret = BinaryConsts::EncodedType::v128; break; - case Type::funcref: - ret = BinaryConsts::EncodedType::funcref; - break; - case Type::anyref: - ret = BinaryConsts::EncodedType::anyref; - break; - case Type::eqref: - ret = BinaryConsts::EncodedType::eqref; - break; - case Type::i31ref: - ret = BinaryConsts::EncodedType::i31ref; - break; - case Type::dataref: - ret = BinaryConsts::EncodedType::dataref; - break; default: WASM_UNREACHABLE("unexpected type"); } @@ -1774,13 +1789,13 @@ bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) { out = Type::v128; return true; case BinaryConsts::EncodedType::funcref: - out = Type::funcref; + out = Type(HeapType::func, Nullable); return true; case BinaryConsts::EncodedType::anyref: - out = Type::anyref; + out = Type(HeapType::any, Nullable); return true; case BinaryConsts::EncodedType::eqref: - out = Type::eqref; + out = Type(HeapType::eq, Nullable); return true; case BinaryConsts::EncodedType::i31ref: out = Type(HeapType::i31, NonNullable); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index bfe09280d..97a25d2c4 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1169,20 +1169,20 @@ Type SExpressionWasmBuilder::stringToType(const char* str, } } if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::funcref; + return Type(HeapType::func, Nullable); } if ((strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) || (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0))) { - return Type::anyref; + return Type(HeapType::any, Nullable); } if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { - return Type::eqref; + return Type(HeapType::eq, Nullable); } if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) { - return Type::i31ref; + return Type(HeapType::i31, NonNullable); } if (strncmp(str, "dataref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::dataref; + return Type(HeapType::data, NonNullable); } if (strncmp(str, "stringref", 9) == 0 && (prefix || str[9] == 0)) { return Type(HeapType::string, Nullable); @@ -1763,11 +1763,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { break; } case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: WASM_UNREACHABLE("unexpected const type"); case Type::none: case Type::unreachable: { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 28472aebd..c980d896b 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -187,11 +187,6 @@ void BinaryInstWriter::visitLoad(Load* curr) { // the pointer is unreachable, so we are never reached; just don't emit // a load return; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -290,11 +285,6 @@ void BinaryInstWriter::visitStore(Store* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Store); break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -742,11 +732,6 @@ void BinaryInstWriter::visitConst(Const* curr) { } break; } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index b13b1ecd7..84b11000f 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -567,19 +567,6 @@ Type asCanonical(Type type) { } } -// Given a HeapType that may or may not be backed by the simplest possible -// representation, return the equivalent type that is definitely backed by the -// simplest possible representation. -HeapType asCanonical(HeapType type) { - if (type.isBasic()) { - return type; - } else if (auto canon = getHeapTypeInfo(type)->getCanonical()) { - return *canon; - } else { - return type; - } -} - HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { if (type.isBasic()) { return type.getBasic(); @@ -670,35 +657,6 @@ std::optional<Type> TypeInfo::getCanonical() const { return tuple.types[0]; } } - if (isRef()) { - HeapType basic = asCanonical(ref.heapType); - if (basic.isBasic()) { - if (ref.nullable) { - switch (basic.getBasic()) { - case HeapType::func: - return Type::funcref; - case HeapType::any: - return Type::anyref; - case HeapType::eq: - return Type::eqref; - case HeapType::i31: - case HeapType::data: - case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - break; - } - } else { - if (basic == HeapType::i31) { - return Type::i31ref; - } - if (basic == HeapType::data) { - return Type::dataref; - } - } - } - } return {}; } @@ -1004,7 +962,7 @@ bool Type::isTuple() const { bool Type::isRef() const { if (isBasic()) { - return id >= funcref && id <= _last_basic_type; + return false; } else { return getTypeInfo(*this)->isRef(); } @@ -1012,7 +970,7 @@ bool Type::isRef() const { bool Type::isFunction() const { if (isBasic()) { - return id == funcref; + return false; } else { auto* info = getTypeInfo(*this); return info->isRef() && info->ref.heapType.isFunction(); @@ -1021,7 +979,7 @@ bool Type::isFunction() const { bool Type::isData() const { if (isBasic()) { - return id == dataref; + return false; } else { auto* info = getTypeInfo(*this); return info->isRef() && info->ref.heapType.isData(); @@ -1030,7 +988,7 @@ bool Type::isData() const { bool Type::isNullable() const { if (isBasic()) { - return id >= funcref && id <= eqref; // except i31ref and dataref + return false; } else { return getTypeInfo(*this)->isNullable(); } @@ -1099,11 +1057,6 @@ unsigned Type::getByteSize() const { return 8; case Type::v128: return 16; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: break; @@ -1217,16 +1170,6 @@ HeapType Type::getHeapType() const { case Type::f64: case Type::v128: break; - case Type::funcref: - return HeapType::func; - case Type::anyref: - return HeapType::any; - case Type::eqref: - return HeapType::eq; - case Type::i31ref: - return HeapType::i31; - case Type::dataref: - return HeapType::data; } WASM_UNREACHABLE("Unexpected type"); } else { @@ -2086,16 +2029,6 @@ std::ostream& TypePrinter::print(Type type) { return os << "f64"; case Type::v128: return os << "v128"; - case Type::funcref: - return os << "funcref"; - case Type::anyref: - return os << "anyref"; - case Type::eqref: - return os << "eqref"; - case Type::i31ref: - return os << "i31ref"; - case Type::dataref: - return os << "dataref"; } } @@ -2109,19 +2042,36 @@ std::ostream& TypePrinter::print(Type type) { print(type.getTuple()); } else if (type.isRef()) { auto heapType = type.getHeapType(); - if (type.isNullable() && heapType.isBasic()) { - // Print shorthands for certain nullable basic heap types. - switch (heapType.getBasic()) { - case HeapType::string: - return os << "stringref"; - case HeapType::stringview_wtf8: - return os << "stringview_wtf8"; - case HeapType::stringview_wtf16: - return os << "stringview_wtf16"; - case HeapType::stringview_iter: - return os << "stringview_iter"; - default: - break; + if (heapType.isBasic()) { + // Print shorthands for certain basic heap types. + if (type.isNullable()) { + switch (heapType.getBasic()) { + case HeapType::func: + return os << "funcref"; + case HeapType::any: + return os << "anyref"; + case HeapType::eq: + return os << "eqref"; + case HeapType::string: + return os << "stringref"; + case HeapType::stringview_wtf8: + return os << "stringview_wtf8"; + case HeapType::stringview_wtf16: + return os << "stringview_wtf16"; + case HeapType::stringview_iter: + return os << "stringview_iter"; + default: + break; + } + } else { + switch (heapType.getBasic()) { + case HeapType::i31: + return os << "i31ref"; + case HeapType::data: + return os << "dataref"; + default: + break; + } } } os << "(ref "; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 4c6e8e929..65a910747 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1399,11 +1399,6 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, break; case Type::unreachable: break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -2044,14 +2039,15 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) { } void FunctionValidator::visitRefEq(RefEq* curr) { + Type eqref = Type(HeapType::eq, Nullable); shouldBeTrue( getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled"); shouldBeSubType(curr->left->type, - Type::eqref, + eqref, curr->left, "ref.eq's left argument should be a subtype of eqref"); shouldBeSubType(curr->right->type, - Type::eqref, + eqref, curr->right, "ref.eq's right argument should be a subtype of eqref"); } @@ -2330,7 +2326,7 @@ void FunctionValidator::visitI31Get(I31Get* curr) { curr, "i31.get_s/u requires gc to be enabled"); shouldBeSubType(curr->i31->type, - Type::i31ref, + Type(HeapType::i31, Nullable), curr->i31, "i31.get_s/u's argument should be i31ref"); } @@ -2853,11 +2849,6 @@ void FunctionValidator::validateAlignment( case Type::v128: case Type::unreachable: break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("invalid type"); } @@ -3130,7 +3121,7 @@ static void validateTables(Module& module, ValidationInfo& info) { "--enable-reference-types)"); if (!module.tables.empty()) { auto& table = module.tables.front(); - info.shouldBeTrue(table->type == Type::funcref, + info.shouldBeTrue(table->type == Type(HeapType::func, Nullable), "table", "Only funcref is valid for table type (when reference " "types are disabled)"); @@ -3150,6 +3141,8 @@ static void validateTables(Module& module, ValidationInfo& info) { } } + Type anyref = Type(HeapType::any, Nullable); + Type funcref = Type(HeapType::func, Nullable); for (auto& table : module.tables) { info.shouldBeTrue(table->initial <= table->max, "table", @@ -3159,14 +3152,13 @@ static void validateTables(Module& module, ValidationInfo& info) { "table", "Non-nullable reference types are not yet supported for tables"); if (!module.features.hasGC()) { - info.shouldBeTrue(table->type.isFunction() || table->type == Type::anyref, + info.shouldBeTrue(table->type.isFunction() || table->type == anyref, "table", - "Only function reference types or anyref are valid " + "Only function reference types or externref are valid " "for table type (when GC is disabled)"); } if (!module.features.hasTypedFunctionReferences()) { - info.shouldBeTrue(table->type == Type::funcref || - table->type == Type::anyref, + info.shouldBeTrue(table->type == funcref || table->type == anyref, "table", "Only funcref and anyref are valid for table type " "(when typed-function references are disabled)"); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index eceb4585b..bd83d62ed 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -903,7 +903,7 @@ void I31New::finalize() { if (value->type == Type::unreachable) { type = Type::unreachable; } else { - type = Type::i31ref; + type = Type(HeapType::i31, NonNullable); } } @@ -1024,11 +1024,11 @@ Type BrOn::getSentType() { } return Type(getIntendedType(), NonNullable); case BrOnFunc: - return Type::funcref; + return Type(HeapType::func, NonNullable); case BrOnData: - return Type::dataref; + return Type(HeapType::data, NonNullable); case BrOnI31: - return Type::i31ref; + return Type(HeapType::i31, NonNullable); case BrOnCastFail: case BrOnNonFunc: case BrOnNonData: @@ -1164,10 +1164,10 @@ void RefAs::finalize() { type = Type(HeapType::func, NonNullable); break; case RefAsData: - type = Type::dataref; + type = Type(HeapType::data, NonNullable); break; case RefAsI31: - type = Type::i31ref; + type = Type(HeapType::i31, NonNullable); break; default: WASM_UNREACHABLE("invalid ref.as_*"); diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index e3a2ab588..8b86017ff 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -1488,11 +1488,6 @@ Result<typename Ctx::InstrT> makeConst(Ctx& ctx, ParseInput& in, Type type) { return in.err("unimplemented instruction"); case Type::none: case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } WASM_UNREACHABLE("unexpected type"); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index ecfc73bff..6e5e19b2c 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -68,24 +68,6 @@ function test_types() { console.log(" // BinaryenTypeVec128: " + binaryen.v128); console.log(" //", binaryen.expandType(binaryen.v128).join(",")); - console.log(" // BinaryenTypeFuncref: " + binaryen.funcref); - console.log(" //", binaryen.expandType(binaryen.funcref).join(",")); - - console.log(" // BinaryenTypeExternref: " + binaryen.externref); - console.log(" //", binaryen.expandType(binaryen.externref).join(",")); - - console.log(" // BinaryenTypeAnyref: " + binaryen.anyref); - console.log(" //", binaryen.expandType(binaryen.anyref).join(",")); - - console.log(" // BinaryenTypeEqref: " + binaryen.eqref); - console.log(" //", binaryen.expandType(binaryen.eqref).join(",")); - - console.log(" // BinaryenTypeI31ref: " + binaryen.i31ref); - console.log(" //", binaryen.expandType(binaryen.i31ref).join(",")); - - console.log(" // BinaryenTypeDataref: " + binaryen.dataref); - console.log(" //", binaryen.expandType(binaryen.dataref).join(",")); - console.log(" // BinaryenTypeAuto: " + binaryen.auto); var i32_pair = binaryen.createType([binaryen.i32, binaryen.i32]); diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 36b5c6749..f5b77234d 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -12,18 +12,6 @@ // 5 // BinaryenTypeVec128: 6 // 6 - // BinaryenTypeFuncref: 7 - // 7 - // BinaryenTypeExternref: 8 - // 8 - // BinaryenTypeAnyref: 8 - // 8 - // BinaryenTypeEqref: 9 - // 9 - // BinaryenTypeI31ref: 10 - // 10 - // BinaryenTypeDataref: 11 - // 11 // BinaryenTypeAuto: -1 // 2,2 // 2,2 diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 28e784a05..90ea43e8a 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -229,37 +229,43 @@ void test_types() { assert(valueType == v128); BinaryenType funcref = BinaryenTypeFuncref(); - printf("BinaryenTypeFuncref: %d\n", funcref); + printf("BinaryenTypeFuncref: (ptr)\n", funcref); + assert(funcref == BinaryenTypeFuncref()); assert(BinaryenTypeArity(funcref) == 1); BinaryenTypeExpand(funcref, &valueType); assert(valueType == funcref); BinaryenType externref = BinaryenTypeExternref(); - printf("BinaryenTypeExternref: %d\n", externref); + printf("BinaryenTypeExternref: (ptr)\n", externref); + assert(externref == BinaryenTypeExternref()); assert(BinaryenTypeArity(externref) == 1); BinaryenTypeExpand(externref, &valueType); assert(valueType == externref); BinaryenType anyref = BinaryenTypeAnyref(); - printf("BinaryenTypeAnyref: %d\n", anyref); + printf("BinaryenTypeAnyref: (ptr)\n", anyref); + assert(anyref == BinaryenTypeAnyref()); assert(BinaryenTypeArity(anyref) == 1); BinaryenTypeExpand(anyref, &valueType); assert(valueType == anyref); BinaryenType eqref = BinaryenTypeEqref(); - printf("BinaryenTypeEqref: %d\n", eqref); + printf("BinaryenTypeEqref: (ptr)\n", eqref); + assert(eqref == BinaryenTypeEqref()); assert(BinaryenTypeArity(eqref) == 1); BinaryenTypeExpand(eqref, &valueType); assert(valueType == eqref); BinaryenType i31ref = BinaryenTypeI31ref(); - printf("BinaryenTypeI31ref: %d\n", i31ref); + printf("BinaryenTypeI31ref: (ptr)\n", i31ref); + assert(i31ref == BinaryenTypeI31ref()); assert(BinaryenTypeArity(i31ref) == 1); BinaryenTypeExpand(i31ref, &valueType); assert(valueType == i31ref); BinaryenType dataref = BinaryenTypeDataref(); - printf("BinaryenTypeDataref: %d\n", dataref); + printf("BinaryenTypeDataref: (ptr)\n", dataref); + assert(dataref == BinaryenTypeDataref()); assert(BinaryenTypeArity(dataref) == 1); BinaryenTypeExpand(dataref, &valueType); assert(valueType == dataref); diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 9f8324d48..e3a8e5676 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -5,12 +5,12 @@ BinaryenTypeInt64: 3 BinaryenTypeFloat32: 4 BinaryenTypeFloat64: 5 BinaryenTypeVec128: 6 -BinaryenTypeFuncref: 7 -BinaryenTypeExternref: 8 -BinaryenTypeAnyref: 8 -BinaryenTypeEqref: 9 -BinaryenTypeI31ref: 10 -BinaryenTypeDataref: 11 +BinaryenTypeFuncref: (ptr) +BinaryenTypeExternref: (ptr) +BinaryenTypeAnyref: (ptr) +BinaryenTypeEqref: (ptr) +BinaryenTypeI31ref: (ptr) +BinaryenTypeDataref: (ptr) BinaryenTypeAuto: -1 BinaryenPackedTypeNotPacked: 0 BinaryenPackedTypeInt8: 1 diff --git a/test/example/stack-utils.cpp b/test/example/stack-utils.cpp index 8709396f9..c54040251 100644 --- a/test/example/stack-utils.cpp +++ b/test/example/stack-utils.cpp @@ -250,6 +250,9 @@ void test_signature_composition() { } void test_signature_subtype() { + Type funcref = Type(HeapType::func, Nullable); + Type anyref = Type(HeapType::any, Nullable); + std::cout << ";; Test stack signature subtyping\n"; // Differences in unreachability only { @@ -260,15 +263,15 @@ void test_signature_subtype() { } // Covariance of results { - StackSignature a(Type::none, Type::funcref, StackSignature::Fixed); - StackSignature b(Type::none, Type::anyref, StackSignature::Fixed); + StackSignature a(Type::none, funcref, StackSignature::Fixed); + StackSignature b(Type::none, anyref, StackSignature::Fixed); assert(StackSignature::isSubType(a, b)); assert(!StackSignature::isSubType(b, a)); } // Contravariance of params { - StackSignature a(Type::anyref, Type::none, StackSignature::Fixed); - StackSignature b(Type::funcref, Type::none, StackSignature::Fixed); + StackSignature a(anyref, Type::none, StackSignature::Fixed); + StackSignature b(funcref, Type::none, StackSignature::Fixed); assert(StackSignature::isSubType(a, b)); assert(!StackSignature::isSubType(b, a)); } @@ -355,6 +358,9 @@ void test_signature_subtype() { } void test_signature_lub() { + Type funcref = Type(HeapType::func, Nullable); + Type anyref = Type(HeapType::any, Nullable); + std::cout << ";; Test stack signature lub\n"; { StackSignature a{Type::none, Type::none, StackSignature::Fixed}; @@ -392,30 +398,28 @@ void test_signature_lub() { (StackSignature{Type::i32, Type::i32, StackSignature::Polymorphic})); } { - StackSignature a{Type::none, Type::anyref, StackSignature::Polymorphic}; - StackSignature b{Type::none, Type::funcref, StackSignature::Polymorphic}; + StackSignature a{Type::none, anyref, StackSignature::Polymorphic}; + StackSignature b{Type::none, funcref, StackSignature::Polymorphic}; assert(StackSignature::haveLeastUpperBound(a, b)); - assert( - StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::none, Type::anyref, StackSignature::Polymorphic})); + assert(StackSignature::getLeastUpperBound(a, b) == + (StackSignature{Type::none, anyref, StackSignature::Polymorphic})); } { - StackSignature a{Type::anyref, Type::none, StackSignature::Polymorphic}; - StackSignature b{Type::funcref, Type::none, StackSignature::Polymorphic}; + StackSignature a{anyref, Type::none, StackSignature::Polymorphic}; + StackSignature b{funcref, Type::none, StackSignature::Polymorphic}; // assert(StackSignature::haveLeastUpperBound(a, b)); // assert(StackSignature::getLeastUpperBound(a, b) == - // (StackSignature{Type::funcref, Type::none, + // (StackSignature{funcref, Type::none, // StackSignature::Polymorphic})); } { StackSignature a{ - {Type::i32, Type::funcref}, Type::funcref, StackSignature::Polymorphic}; - StackSignature b{ - Type::funcref, {Type::f32, Type::anyref}, StackSignature::Polymorphic}; + {Type::i32, funcref}, funcref, StackSignature::Polymorphic}; + StackSignature b{funcref, {Type::f32, anyref}, StackSignature::Polymorphic}; assert(StackSignature::haveLeastUpperBound(a, b)); assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{{Type::i32, Type::funcref}, - {Type::f32, Type::anyref}, + (StackSignature{{Type::i32, funcref}, + {Type::f32, anyref}, StackSignature::Polymorphic})); } // No LUB diff --git a/test/example/type-builder-nominal.cpp b/test/example/type-builder-nominal.cpp index 8dbbfcf30..cbda43f1f 100644 --- a/test/example/type-builder-nominal.cpp +++ b/test/example/type-builder-nominal.cpp @@ -123,21 +123,24 @@ void test_canonicalization() { void test_basic() { std::cout << ";; Test basic\n"; + Type canonAnyref = Type(HeapType::any, Nullable); + Type canonI31ref = Type(HeapType::i31, NonNullable); + TypeBuilder builder(6); Type anyref = builder.getTempRefType(builder[4], Nullable); Type i31ref = builder.getTempRefType(builder[5], NonNullable); - builder[0] = Signature(Type::anyref, Type::i31ref); - builder[1] = Signature(anyref, Type::i31ref); - builder[2] = Signature(Type::anyref, i31ref); + builder[0] = Signature(canonAnyref, canonI31ref); + builder[1] = Signature(anyref, canonI31ref); + builder[2] = Signature(canonAnyref, i31ref); builder[3] = Signature(anyref, i31ref); builder[4] = HeapType::any; builder[5] = HeapType::i31; std::vector<HeapType> built = *builder.build(); - assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref)); + assert(built[0].getSignature() == Signature(canonAnyref, canonI31ref)); assert(built[1].getSignature() == built[0].getSignature()); assert(built[2].getSignature() == built[1].getSignature()); assert(built[3].getSignature() == built[2].getSignature()); @@ -150,16 +153,18 @@ void test_basic() { void test_signatures(bool warm) { std::cout << ";; Test canonical signatures\n"; + Type canonAnyref = Type(HeapType::any, Nullable); + Type canonI31ref = Type(HeapType::i31, NonNullable); + TypeBuilder builder(2); Type tempRef = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::i31ref, Type::anyref); + builder[0] = Signature(canonI31ref, canonAnyref); builder[1] = Signature(tempRef, tempRef); std::vector<HeapType> built = *builder.build(); - HeapType small = Signature(Type::i31ref, Type::anyref); - HeapType big = - Signature(Type(Signature(Type::i31ref, Type::anyref), Nullable), - Type(Signature(Type::i31ref, Type::anyref), Nullable)); + HeapType small = Signature(canonI31ref, canonAnyref); + HeapType big = Signature(Type(Signature(canonI31ref, canonAnyref), Nullable), + Type(Signature(canonI31ref, canonAnyref), Nullable)); if (warm) { assert(built[0] != small); assert(built[1] != big); @@ -306,6 +311,9 @@ void test_recursive() { void test_subtypes() { std::cout << ";; Test subtyping\n"; + Type anyref = Type(HeapType::any, Nullable); + Type funcref = Type(HeapType::func, Nullable); + auto LUB = [&](HeapType a, HeapType b) { Type refA = Type(a, Nullable); Type refB = Type(b, Nullable); @@ -362,7 +370,7 @@ void test_subtypes() { Type structRef1 = builder.getTempRefType(builder[1], Nullable); builder[0] = Struct{}; builder[1] = Struct{}; - builder[2] = Signature(Type::none, Type::anyref); + builder[2] = Signature(Type::none, anyref); builder[3] = Signature(Type::none, structRef0); builder[4] = Signature(Type::none, structRef1); built = *builder.build(); @@ -394,12 +402,10 @@ void test_subtypes() { builder[0].subTypeOf(builder[1]); builder[2].subTypeOf(builder[3]); builder[4].subTypeOf(builder[5]); - builder[0] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[1] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[2] = Signature(Type::i32, Type::anyref); - builder[3] = Signature(Type::i32, Type::anyref); + builder[0] = Struct({Field(Type::i32, Mutable), Field(anyref, Mutable)}); + builder[1] = Struct({Field(Type::i32, Mutable), Field(anyref, Mutable)}); + builder[2] = Signature(Type::i32, anyref); + builder[3] = Signature(Type::i32, anyref); builder[4] = Array(Field(Type::i32, Mutable)); builder[5] = Array(Field(Type::i32, Mutable)); built = *builder.build(); @@ -428,8 +434,8 @@ void test_subtypes() { std::vector<HeapType> built; { TypeBuilder builder(2); - builder[0] = Struct({Field(Type::anyref, Immutable)}); - builder[1] = Struct({Field(Type::funcref, Immutable)}); + builder[0] = Struct({Field(anyref, Immutable)}); + builder[1] = Struct({Field(funcref, Immutable)}); builder[1].subTypeOf(builder[0]); built = *builder.build(); } diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp index ce7b74841..219282ea8 100644 --- a/test/example/type-builder.cpp +++ b/test/example/type-builder.cpp @@ -44,21 +44,24 @@ void test_canonicalization() { void test_basic() { std::cout << ";; Test basic\n"; + Type canonAnyref = Type(HeapType::any, Nullable); + Type canonI31ref = Type(HeapType::i31, NonNullable); + TypeBuilder builder(6); Type anyref = builder.getTempRefType(builder[4], Nullable); Type i31ref = builder.getTempRefType(builder[5], NonNullable); - builder[0] = Signature(Type::anyref, Type::i31ref); - builder[1] = Signature(anyref, Type::i31ref); - builder[2] = Signature(Type::anyref, i31ref); + builder[0] = Signature(canonAnyref, canonI31ref); + builder[1] = Signature(anyref, canonI31ref); + builder[2] = Signature(canonAnyref, i31ref); builder[3] = Signature(anyref, i31ref); builder[4] = HeapType::any; builder[5] = HeapType::i31; std::vector<HeapType> built = *builder.build(); - assert(built[0] == Signature(Type::anyref, Type::i31ref)); + assert(built[0] == Signature(canonAnyref, canonI31ref)); assert(built[1] == built[0]); assert(built[2] == built[1]); assert(built[3] == built[2]); @@ -210,8 +213,8 @@ void test_recursive() { std::cout << print(built[1]) << "\n\n"; assert(built[0].getSignature().results.getHeapType() == built[0]); assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0].getSignature().params == Type::anyref); - assert(built[1].getSignature().params == Type::anyref); + assert(built[0].getSignature().params == Type(HeapType::any, Nullable)); + assert(built[1].getSignature().params == Type(HeapType::any, Nullable)); assert(built[0] == built[1]); assert(built[2] == HeapType::any); } @@ -220,6 +223,12 @@ void test_recursive() { void test_lub() { std::cout << ";; Test LUBs\n"; + Type func = Type(HeapType::func, Nullable); + Type any = Type(HeapType::any, Nullable); + Type eq = Type(HeapType::eq, Nullable); + Type i31 = Type(HeapType::i31, Nullable); + Type data = Type(HeapType::data, Nullable); + auto LUB = [&](Type a, Type b) { Type lubAB = Type::getLeastUpperBound(a, b); Type lubBA = Type::getLeastUpperBound(b, a); @@ -238,15 +247,11 @@ void test_lub() { { // Basic Types - for (auto other : {Type::funcref, - Type::anyref, - Type::eqref, - Type::i31ref, - Type::dataref}) { - assert(LUB(Type::anyref, other) == Type::anyref); + for (auto other : {func, any, eq, i31, data}) { + assert(LUB(any, other) == any); } - assert(LUB(Type::eqref, Type::funcref) == Type::anyref); - assert(LUB(Type::i31ref, Type::dataref) == Type(HeapType::eq, NonNullable)); + assert(LUB(eq, func) == any); + assert(LUB(i31, data) == eq); } { @@ -260,22 +265,21 @@ void test_lub() { { // Funcref with specific signature - assert(LUB(Type::funcref, Type(Signature(), Nullable)) == Type::funcref); + assert(LUB(func, Type(Signature(), Nullable)) == func); } { // Incompatible signatures - Type a(Signature(Type::none, Type::anyref), Nullable); - Type b(Signature(Type::anyref, Type::none), Nullable); - assert(LUB(a, b) == Type::funcref); + Type a(Signature(Type::none, any), Nullable); + Type b(Signature(any, Type::none), Nullable); + assert(LUB(a, b) == Type(HeapType::func, Nullable)); } { // Signatures incompatible in tuple size - Type a(Signature(Type::none, {Type::anyref, Type::anyref}), Nullable); - Type b(Signature(Type::none, {Type::anyref, Type::anyref, Type::anyref}), - Nullable); - assert(LUB(a, b) == Type::funcref); + Type a(Signature(Type::none, {any, any}), Nullable); + Type b(Signature(Type::none, {any, any, any}), Nullable); + assert(LUB(a, b) == Type(HeapType::func, Nullable)); } // { @@ -303,24 +307,24 @@ void test_lub() { { // Mutable fields are invariant - Type a(Array(Field(Type::eqref, Mutable)), Nullable); - Type b(Array(Field(Type::funcref, Mutable)), Nullable); - assert(LUB(a, b) == Type(HeapType::data, Nullable)); + Type a(Array(Field(eq, Mutable)), Nullable); + Type b(Array(Field(func, Mutable)), Nullable); + assert(LUB(a, b) == data); } { // Immutable fields are covariant - Type a(Array(Field(Type::eqref, Immutable)), Nullable); - Type b(Array(Field(Type::funcref, Immutable)), Nullable); - Type lub(Array(Field(Type::anyref, Immutable)), Nullable); + Type a(Array(Field(eq, Immutable)), Nullable); + Type b(Array(Field(func, Immutable)), Nullable); + Type lub(Array(Field(any, Immutable)), Nullable); assert(LUB(a, b) == lub); } { // Depth subtyping - Type a(Struct({Field(Type::eqref, Immutable)}), Nullable); - Type b(Struct({Field(Type::funcref, Immutable)}), Nullable); - Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable); + Type a(Struct({Field(eq, Immutable)}), Nullable); + Type b(Struct({Field(func, Immutable)}), Nullable); + Type lub(Struct({Field(any, Immutable)}), Nullable); assert(LUB(a, b) == lub); } @@ -344,32 +348,29 @@ void test_lub() { { // Width and depth subtyping with different suffixes - Type a(Struct({Field(Type::eqref, Immutable), Field(Type::i64, Immutable)}), + Type a(Struct({Field(eq, Immutable), Field(Type::i64, Immutable)}), Nullable); - Type b( - Struct({Field(Type::funcref, Immutable), Field(Type::f32, Immutable)}), - Nullable); - Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable); + Type b(Struct({Field(func, Immutable), Field(Type::f32, Immutable)}), + Nullable); + Type lub(Struct({Field(any, Immutable)}), Nullable); assert(LUB(a, b) == lub); } { // No common prefix - Type a( - Struct({Field(Type::i32, Immutable), Field(Type::anyref, Immutable)}), - Nullable); - Type b( - Struct({Field(Type::f32, Immutable), Field(Type::anyref, Immutable)}), - Nullable); + Type a(Struct({Field(Type::i32, Immutable), Field(any, Immutable)}), + Nullable); + Type b(Struct({Field(Type::f32, Immutable), Field(any, Immutable)}), + Nullable); Type lub(Struct(), Nullable); assert(LUB(a, b) == lub); } { // Nested structs - Type innerA(Struct({Field(Type::eqref, Immutable)}), Nullable); - Type innerB(Struct({Field(Type::funcref, Immutable)}), Nullable); - Type innerLub(Struct({Field(Type::anyref, Immutable)}), Nullable); + Type innerA(Struct({Field(eq, Immutable)}), Nullable); + Type innerB(Struct({Field(func, Immutable)}), Nullable); + Type innerLub(Struct({Field(any, Immutable)}), Nullable); Type a(Struct({Field(innerA, Immutable)}), Nullable); Type b(Struct({Field(innerB, Immutable)}), Nullable); Type lub(Struct({Field(innerLub, Immutable)}), Nullable); @@ -381,18 +382,15 @@ void test_lub() { TypeBuilder builder(2); Type tempA = builder.getTempRefType(builder[0], Nullable); Type tempB = builder.getTempRefType(builder[1], Nullable); - builder[0] = - Struct({Field(tempB, Immutable), Field(Type::eqref, Immutable)}); - builder[1] = - Struct({Field(tempA, Immutable), Field(Type::funcref, Immutable)}); + builder[0] = Struct({Field(tempB, Immutable), Field(eq, Immutable)}); + builder[1] = Struct({Field(tempA, Immutable), Field(func, Immutable)}); auto built = *builder.build(); Type a(built[0], Nullable); Type b(built[1], Nullable); TypeBuilder lubBuilder(1); Type tempLub = builder.getTempRefType(lubBuilder[0], Nullable); - lubBuilder[0] = - Struct({Field(tempLub, Immutable), Field(Type::anyref, Immutable)}); + lubBuilder[0] = Struct({Field(tempLub, Immutable), Field(any, Immutable)}); built = *lubBuilder.build(); Type lub(built[0], Nullable); diff --git a/test/example/typeinfo.cpp b/test/example/typeinfo.cpp index ed5637bd9..55e7b9082 100644 --- a/test/example/typeinfo.cpp +++ b/test/example/typeinfo.cpp @@ -8,7 +8,6 @@ using namespace wasm; void test_compound() { { HeapType func(HeapType::func); - assert(Type(func, Nullable).getID() == Type::funcref); assert(Type(func, NonNullable).getID() == Type(func, NonNullable).getID()); assert(Type(func, NonNullable).getID() != Type(func, Nullable).getID()); HeapType sameFunc(HeapType::func); @@ -16,7 +15,6 @@ void test_compound() { Type(sameFunc, NonNullable).getID()); HeapType any(HeapType::any); - assert(Type(any, Nullable).getID() == Type::anyref); assert(Type(any, NonNullable).getID() == Type(any, NonNullable).getID()); assert(Type(any, NonNullable).getID() != Type(any, Nullable).getID()); HeapType sameAny(HeapType::any); @@ -24,14 +22,12 @@ void test_compound() { Type(sameAny, NonNullable).getID()); HeapType eq(HeapType::eq); - // assert(Type(eq, Nullable).getID() == Type::eqref); assert(Type(eq, NonNullable).getID() == Type(eq, NonNullable).getID()); assert(Type(eq, NonNullable).getID() != Type(eq, Nullable).getID()); HeapType sameEq(HeapType::eq); assert(Type(eq, NonNullable).getID() == Type(sameEq, NonNullable).getID()); HeapType i31(HeapType::i31); - // assert(Type(i31, NonNullable).getID() == Type::i31ref); assert(Type(i31, NonNullable).getID() == Type(i31, NonNullable).getID()); assert(Type(i31, NonNullable).getID() != Type(i31, Nullable).getID()); HeapType sameI31(HeapType::i31); @@ -92,7 +88,7 @@ void test_compound() { Tuple sameTuple({Type::i32, Type::f64}); assert(Type(tuple).getID() == Type(sameTuple).getID()); - Tuple otherTuple({Type::f64, Type::anyref}); + Tuple otherTuple({Type::f64, Type::i64}); assert(Type(tuple).getID() != Type(otherTuple).getID()); } { @@ -165,7 +161,6 @@ void test_printing() { {Type::i64, Immutable}, {Type::f32, Mutable}, {Type::f64, Mutable}, - {Type::anyref, Immutable}, }); std::cout << struct_ << "\n"; std::cout << Type(struct_, NonNullable) << "\n"; @@ -177,7 +172,7 @@ void test_printing() { std::cout << array << "\n"; std::cout << Type(array, NonNullable) << "\n"; std::cout << Type(array, Nullable) << "\n"; - Array arrayMut({Type::anyref, Mutable}); + Array arrayMut({Type::i64, Mutable}); std::cout << arrayMut << "\n"; std::cout << Type(arrayMut, NonNullable) << "\n"; std::cout << Type(arrayMut, Nullable) << "\n"; @@ -190,7 +185,6 @@ void test_printing() { Tuple tuple({ Type::i32, Type::f64, - Type::anyref, }); std::cout << tuple << "\n"; std::cout << Type(tuple) << "\n"; diff --git a/test/example/typeinfo.txt b/test/example/typeinfo.txt index 924fcb3ec..838fd34a3 100644 --- a/test/example/typeinfo.txt +++ b/test/example/typeinfo.txt @@ -27,7 +27,7 @@ i31ref (struct) (ref $struct.0) (ref null $struct.0) -(struct (field i32 i64 (mut f32) (mut f64) anyref)) +(struct (field i32 i64 (mut f32) (mut f64))) (ref $struct.0) (ref null $struct.0) @@ -35,15 +35,15 @@ i31ref (array i32) (ref $array.0) (ref null $array.0) -(array (mut anyref)) +(array (mut i64)) (ref $array.0) (ref null $array.0) ;; Tuple () none -(i32 f64 anyref) -(i32 f64 anyref) +(i32 f64) +(i32 f64) ;; Rtt (rtt 0 func) diff --git a/test/gtest/possible-contents.cpp b/test/gtest/possible-contents.cpp index 2994a6221..2bed9a882 100644 --- a/test/gtest/possible-contents.cpp +++ b/test/gtest/possible-contents.cpp @@ -59,6 +59,9 @@ protected: wasm::setTypeSystem(TypeSystem::Nominal); } + Type anyref = Type(HeapType::any, Nullable); + Type funcref = Type(HeapType::func, Nullable); + PossibleContents none = PossibleContents::none(); PossibleContents i32Zero = PossibleContents::literal(Literal(int32_t(0))); @@ -74,15 +77,14 @@ protected: PossibleContents i32Global2 = PossibleContents::global("i32Global2", Type::i32); PossibleContents f64Global = PossibleContents::global("f64Global", Type::f64); - PossibleContents anyGlobal = - PossibleContents::global("anyGlobal", Type::anyref); + PossibleContents anyGlobal = PossibleContents::global("anyGlobal", anyref); PossibleContents nonNullFunc = PossibleContents::literal( Literal("func", Type(Signature(Type::none, Type::none), NonNullable))); PossibleContents exactI32 = PossibleContents::exactType(Type::i32); - PossibleContents exactAnyref = PossibleContents::exactType(Type::anyref); - PossibleContents exactFuncref = PossibleContents::exactType(Type::funcref); + PossibleContents exactAnyref = PossibleContents::exactType(anyref); + PossibleContents exactFuncref = PossibleContents::exactType(funcref); PossibleContents exactNonNullAnyref = PossibleContents::exactType(Type(HeapType::any, NonNullable)); PossibleContents exactNonNullFuncref = diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index ca9bd865d..d06236130 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -481,11 +481,13 @@ static void testCanonicalizeBasicTypes() { Type anyref = builder.getTempRefType(builder[0], Nullable); Type anyrefs = builder.getTempTupleType({anyref, anyref}); + Type anyrefCanon = Type(HeapType::any, Nullable); + builder[0] = HeapType::any; builder[1] = Struct({Field(anyref, Immutable)}); - builder[2] = Struct({Field(Type::anyref, Immutable)}); + builder[2] = Struct({Field(anyrefCanon, Immutable)}); builder[3] = Signature(anyrefs, Type::none); - builder[4] = Signature({Type::anyref, Type::anyref}, Type::none); + builder[4] = Signature({anyrefCanon, anyrefCanon}, Type::none); auto result = builder.build(); ASSERT_TRUE(result); @@ -504,10 +506,13 @@ TEST_F(IsorecursiveTest, CanonicalizeBasicTypes) { // Test SubTypes utility code. TEST_F(NominalTest, testSubTypes) { + Type anyref = Type(HeapType::any, Nullable); + Type funcref = Type(HeapType::func, Nullable); + // Build type types, the second of which is a subtype. TypeBuilder builder(2); - builder[0] = Struct({Field(Type::anyref, Immutable)}); - builder[1] = Struct({Field(Type::funcref, Immutable)}); + builder[0] = Struct({Field(anyref, Immutable)}); + builder[1] = Struct({Field(funcref, Immutable)}); builder[1].subTypeOf(builder[0]); auto built = *builder.build(); diff --git a/test/lit/fuzz-types/isorecursive.test b/test/lit/fuzz-types/isorecursive.test index 9165d9265..78315c5b1 100644 --- a/test/lit/fuzz-types/isorecursive.test +++ b/test/lit/fuzz-types/isorecursive.test @@ -2,25 +2,25 @@ ;; CHECK: (rec ;; CHECK-NEXT: (type $0 (struct_subtype data)) -;; CHECK-NEXT: (type $1 (func_subtype (param i31ref) (result dataref) func)) -;; CHECK-NEXT: (type $2 (array_subtype i32 data)) -;; CHECK-NEXT: (type $3 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $4 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $5 (array_subtype i32 $3)) -;; CHECK-NEXT: (type $6 (array_subtype i32 $3)) +;; CHECK-NEXT: (type $1 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) func)) +;; CHECK-NEXT: (type $2 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) data)) +;; CHECK-NEXT: (type $3 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) +;; CHECK-NEXT: (type $4 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) +;; CHECK-NEXT: (type $5 (struct_subtype (field f64 v128 (ref null $10) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3)) +;; CHECK-NEXT: (type $6 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3)) ;; CHECK-NEXT: (type $7 (struct_subtype $0)) -;; CHECK-NEXT: (type $8 (struct_subtype $0)) -;; CHECK-NEXT: (type $9 (array_subtype i32 $6)) -;; CHECK-NEXT: (type $10 (struct_subtype $0)) -;; CHECK-NEXT: (type $11 (array_subtype i32 $2)) +;; CHECK-NEXT: (type $8 (struct_subtype (field f32 (mut i16) (ref eq) (mut (rtt $2))) $0)) +;; CHECK-NEXT: (type $9 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6)) +;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $2) (mut (ref $13)) (ref null i31) v128 (ref null $6)) $0)) +;; CHECK-NEXT: (type $11 (struct_subtype (field f64 v128 (ref $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) ;; CHECK-NEXT: (type $12 (struct_subtype $0)) -;; CHECK-NEXT: (type $13 (array_subtype i32 $6)) +;; CHECK-NEXT: (type $13 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6)) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $14 (struct_subtype $10)) -;; CHECK-NEXT: (type $15 (func_subtype (param i31ref) (result dataref) $1)) -;; CHECK-NEXT: (type $16 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $17 (struct_subtype $14)) -;; CHECK-NEXT: (type $18 (struct_subtype (field (mut funcref) (mut (ref null $7)) funcref) $12)) -;; CHECK-NEXT: (type $19 (func_subtype (param i31ref) (result dataref) $15)) +;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $10)) +;; CHECK-NEXT: (type $15 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $1)) +;; CHECK-NEXT: (type $16 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) +;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $14)) +;; CHECK-NEXT: (type $18 (struct_subtype $12)) +;; CHECK-NEXT: (type $19 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $15)) ;; CHECK-NEXT: ) diff --git a/test/lit/fuzz-types/nominal.test b/test/lit/fuzz-types/nominal.test index 248ce6539..299cf2613 100644 --- a/test/lit/fuzz-types/nominal.test +++ b/test/lit/fuzz-types/nominal.test @@ -3,20 +3,20 @@ ;; CHECK: (type $0 (struct_subtype (field (ref null $9) (ref $5)) data)) ;; CHECK-NEXT: (type $1 (func_subtype (param (rtt 0 $8)) func)) ;; CHECK-NEXT: (type $2 (struct_subtype (field (mut (rtt $19)) (ref $4)) data)) -;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $2)) -;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut (ref $13))) $2)) -;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3)) -;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3)) -;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5) eqref (mut (ref null $3)) (mut (rtt $18)) dataref) $0)) -;; CHECK-NEXT: (type $8 (struct_subtype (field (ref $9) (ref $5) (rtt 2 $1) (mut (rtt $17)) (mut (rtt i31)) (rtt $8)) $0)) -;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $15)) $6)) -;; CHECK-NEXT: (type $10 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2)) +;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $2)) +;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2)) +;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3)) +;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3)) +;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5)) $0)) +;; CHECK-NEXT: (type $8 (struct_subtype (field (ref null $9) (ref $5)) $0)) +;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6)) +;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $9) (ref $5) i32) $0)) +;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut f64) i32 (mut f32)) $2)) ;; CHECK-NEXT: (type $12 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $6)) -;; CHECK-NEXT: (type $14 (struct_subtype (field (ref null $9) (ref $5)) $10)) +;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6)) +;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $9) (ref $5) i32) $10)) ;; CHECK-NEXT: (type $15 (func_subtype (param (rtt 0 $8)) $1)) -;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) v128) $2)) -;; CHECK-NEXT: (type $17 (struct_subtype (field (ref null $9) (ref $5)) $14)) +;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut i16) i64 (mut (rtt 0 i31))) $2)) +;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $9) (ref $5) i32) $14)) ;; CHECK-NEXT: (type $18 (struct_subtype (field (ref null $9) (ref $5)) $12)) ;; CHECK-NEXT: (type $19 (func_subtype (param (rtt 0 $8)) $15)) diff --git a/test/lit/fuzz-types/structural.test b/test/lit/fuzz-types/structural.test index a7b38edb4..e0aa75e9e 100644 --- a/test/lit/fuzz-types/structural.test +++ b/test/lit/fuzz-types/structural.test @@ -1,22 +1,22 @@ ;; RUN: wasm-fuzz-types --structural -v --seed=0 | filecheck %s -;; CHECK: (type $0 (struct (field (ref null $9) (ref $3)))) -;; CHECK-NEXT: (type $1 (func (param (rtt 0 $8)))) -;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $4)))) -;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64)))) -;; CHECK-NEXT: (type $4 (struct (field (mut (rtt $1)) (ref $4) (mut (ref $3))))) +;; CHECK: (type $0 (struct (field (ref null $3) (ref $3)))) +;; CHECK-NEXT: (type $1 (func (param (rtt 0 $0)))) +;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $2)))) +;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $2) i64 v128 (mut v128)))) +;; CHECK-NEXT: (type $4 identical to $2) ;; CHECK-NEXT: (type $5 identical to $3) ;; CHECK-NEXT: (type $6 identical to $3) -;; CHECK-NEXT: (type $7 (struct (field (ref null $9) (ref $3) eqref (mut (ref null $3)) (mut (rtt $0)) dataref))) -;; CHECK-NEXT: (type $8 (struct (field (ref $9) (ref $3) (rtt 2 $1) (mut (rtt $0)) (mut (rtt i31)) (rtt $8)))) -;; CHECK-NEXT: (type $9 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $1)))) -;; CHECK-NEXT: (type $10 identical to $0) -;; CHECK-NEXT: (type $11 identical to $2) +;; CHECK-NEXT: (type $7 identical to $0) +;; CHECK-NEXT: (type $8 identical to $0) +;; CHECK-NEXT: (type $9 identical to $3) +;; CHECK-NEXT: (type $10 (struct (field (ref $3) (ref $3) i32))) +;; CHECK-NEXT: (type $11 (struct (field (mut (rtt $1)) (ref $2) (mut f64) i32 (mut f32)))) ;; CHECK-NEXT: (type $12 identical to $0) ;; CHECK-NEXT: (type $13 identical to $3) -;; CHECK-NEXT: (type $14 identical to $0) +;; CHECK-NEXT: (type $14 identical to $10) ;; CHECK-NEXT: (type $15 identical to $1) -;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $4) v128))) -;; CHECK-NEXT: (type $17 identical to $0) +;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $2) (mut i16) i64 (mut (rtt 0 i31))))) +;; CHECK-NEXT: (type $17 identical to $10) ;; CHECK-NEXT: (type $18 identical to $0) ;; CHECK-NEXT: (type $19 identical to $1) diff --git a/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast b/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast index e736253f6..28c42e1fa 100644 --- a/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast +++ b/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast @@ -16,12 +16,6 @@ ;; CHECK: (type $i32_i32_anyref_=>_anyref (func (param i32 i32 anyref) (result anyref))) - ;; CHECK: (type $i32_i32_eqref_=>_eqref (func (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (type $i32_i32_i31ref_=>_i31ref (func (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (type $i32_i32_dataref_=>_dataref (func (param i32 i32 dataref) (result dataref))) - ;; CHECK: (type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128))) ;; CHECK: (type $none_=>_none (func)) @@ -50,18 +44,6 @@ ;; CHECK: (import "env" "set_anyref" (func $set_anyref (param i32 i32 anyref) (result anyref))) - ;; CHECK: (import "env" "get_eqref" (func $get_eqref (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (import "env" "set_eqref" (func $set_eqref (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (import "env" "get_i31ref" (func $get_i31ref (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (import "env" "set_i31ref" (func $set_i31ref (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (import "env" "get_dataref" (func $get_dataref (param i32 i32 dataref) (result dataref))) - - ;; CHECK: (import "env" "set_dataref" (func $set_dataref (param i32 i32 dataref) (result dataref))) - ;; CHECK: (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128))) ;; CHECK: (import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128))) diff --git a/test/lit/strings.wast b/test/lit/strings.wast index c807ac000..03e87e562 100644 --- a/test/lit/strings.wast +++ b/test/lit/strings.wast @@ -5,17 +5,17 @@ ;; RUN: foreach %s %t wasm-opt --enable-strings --enable-reference-types --enable-gc --roundtrip -S -o - | filecheck %s (module - ;; CHECK: (type $ref?|string|_=>_none (func (param stringref))) + ;; CHECK: (type $stringref_=>_none (func (param stringref))) - ;; CHECK: (type $ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter))) + ;; CHECK: (type $stringref_stringview_wtf8_stringview_wtf16_stringview_iter_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter))) - ;; CHECK: (type $ref?|string|_ref?|string|_=>_none (func (param stringref stringref))) + ;; CHECK: (type $stringref_stringref_=>_none (func (param stringref stringref))) - ;; CHECK: (type $ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref|string|_ref|stringview_wtf8|_ref|stringview_wtf16|_ref|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter)))) + ;; CHECK: (type $stringref_stringview_wtf8_stringview_wtf16_stringview_iter_stringref_stringview_wtf8_stringview_wtf16_stringview_iter_ref|string|_ref|stringview_wtf8|_ref|stringview_wtf16|_ref|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter)))) ;; CHECK: (type $none_=>_none (func)) - ;; CHECK: (type $ref?|stringview_wtf16|_=>_none (func (param stringview_wtf16))) + ;; CHECK: (type $stringview_wtf16_=>_none (func (param stringview_wtf16))) ;; CHECK: (type $ref|$array|_=>_none (func (param (ref $array)))) diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt index fa88cc5ef..ad0779876 100644 --- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt +++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt @@ -1,42 +1,40 @@ total - [exports] : 8 - [funcs] : 9 + [exports] : 10 + [funcs] : 12 [globals] : 6 [imports] : 5 [memory-data] : 22 [table-data] : 4 [tables] : 1 [tags] : 0 - [total] : 650 - [vars] : 12 + [total] : 549 + [vars] : 22 AtomicCmpxchg : 1 AtomicFence : 1 - AtomicNotify : 1 - Binary : 83 - Block : 72 - Break : 5 + Binary : 71 + Block : 60 + Break : 2 Call : 23 - CallRef : 4 - Const : 141 + CallRef : 2 + Const : 119 Drop : 3 - GlobalGet : 39 - GlobalSet : 21 - I31New : 10 - If : 31 - Load : 24 - LocalGet : 49 - LocalSet : 25 - Loop : 11 - Nop : 9 - RefEq : 2 - RefFunc : 12 + GlobalGet : 35 + GlobalSet : 19 + I31New : 6 + If : 25 + Load : 16 + LocalGet : 45 + LocalSet : 23 + Loop : 6 + Nop : 7 + RefFunc : 11 RefIs : 1 RefNull : 2 Return : 27 SIMDExtract : 1 - Select : 2 - Store : 2 - StructNew : 4 - TupleExtract : 2 + Select : 1 + Store : 3 + StructNew : 2 TupleMake : 7 - Unary : 35 + Unary : 29 + Unreachable : 1 |