diff options
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 |