diff options
-rw-r--r-- | src/binaryen-c.cpp | 4 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 7 | ||||
-rw-r--r-- | src/tools/fuzzing/heap-types.cpp | 6 | ||||
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm-type.h | 6 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 24 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 40 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.txt | 24 | ||||
-rw-r--r-- | test/gtest/type-builder.cpp | 84 | ||||
-rw-r--r-- | test/lit/basic/typed_continuations.wast | 26 | ||||
-rw-r--r-- | test/spec/typed_continuations.wast | 8 |
13 files changed, 232 insertions, 19 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index a34876078..93e3f609b 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -86,6 +86,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { case HeapType::any: case HeapType::eq: case HeapType::func: + case HeapType::cont: case HeapType::struct_: case HeapType::array: case HeapType::exn: @@ -98,6 +99,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: // Null. return ret; @@ -141,6 +143,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { WASM_UNREACHABLE("TODO: extern literals"); case HeapType::eq: case HeapType::func: + case HeapType::cont: case HeapType::struct_: case HeapType::array: case HeapType::exn: @@ -153,6 +156,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: assert(type.isNullable()); return Literal::makeNull(heapType); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index e20333500..cbf8f2f4d 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -2525,6 +2525,9 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { case HeapType::func: { return makeRefFuncConst(type); } + case HeapType::cont: { + WASM_UNREACHABLE("not implemented"); + } case HeapType::any: { // Choose a subtype we can materialize a constant for. We cannot // materialize non-nullable refs to func or i31 in global contexts. @@ -2652,6 +2655,7 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: { auto null = builder.makeRefNull(heapType); if (!type.isNullable()) { @@ -4076,6 +4080,8 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) { return pick(FeatureOptions<HeapType>() .add(FeatureSet::ReferenceTypes, HeapType::func) .add(FeatureSet::GC, HeapType::nofunc)); + case HeapType::cont: + return pick(HeapType::cont, HeapType::nocont); case HeapType::ext: return pick(FeatureOptions<HeapType>() .add(FeatureSet::ReferenceTypes, HeapType::ext) @@ -4116,6 +4122,7 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: break; } diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index 33a92b796..3d0d29153 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -380,6 +380,8 @@ struct HeapTypeGeneratorImpl { switch (type.getBasic()) { case HeapType::func: return pickSubFunc(); + case HeapType::cont: + WASM_UNREACHABLE("not implemented"); case HeapType::any: return pickSubAny(); case HeapType::eq: @@ -399,6 +401,7 @@ struct HeapTypeGeneratorImpl { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: return type; } @@ -442,6 +445,7 @@ struct HeapTypeGeneratorImpl { case HeapType::ext: case HeapType::func: case HeapType::exn: + case HeapType::cont: case HeapType::any: break; case HeapType::eq: @@ -470,6 +474,8 @@ struct HeapTypeGeneratorImpl { return pickSubAny(); case HeapType::nofunc: return pickSubFunc(); + case HeapType::nocont: + WASM_UNREACHABLE("not implemented"); case HeapType::noext: candidates.push_back(HeapType::ext); break; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index f8463f3b1..4f0796601 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -372,6 +372,8 @@ enum EncodedType { eqref = -0x13, // 0x6d nonnullable = -0x1c, // 0x64 nullable = -0x1d, // 0x63 + contref = -0x18, // 0x68 + nullcontref = -0x0b, // 0x75 // exception handling exnref = -0x17, // 0x69 nullexnref = -0xc, // 0x74 @@ -403,6 +405,8 @@ enum EncodedHeapType { eq = -0x13, // 0x6d exn = -0x17, // 0x69 noexn = -0xc, // 0x74 + cont = -0x18, // 0x68 + nocont = -0x0b, // 0x75 i31 = -0x14, // 0x6c struct_ = -0x15, // 0x6b array = -0x16, // 0x6a diff --git a/src/wasm-type.h b/src/wasm-type.h index 5c47f4051..b18eaa6db 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -321,6 +321,7 @@ public: enum BasicHeapType : uint32_t { ext, func, + cont, any, eq, i31, @@ -334,6 +335,7 @@ public: none, noext, nofunc, + nocont, noexn, }; static constexpr BasicHeapType _last_basic_type = noexn; @@ -367,6 +369,10 @@ public: bool isFunction() const; bool isData() const; bool isSignature() const; + // Indicates whether the given type was defined to be of the form + // `(cont $ft)`. Returns false for `cont`, the top type of the continuation + // type hierarchy (and all other types). In other words, this is analogous to + // `isSignature`, but for continuation types. bool isContinuation() const; bool isStruct() const; bool isArray() const; diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 887c777ec..48ade5447 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -138,10 +138,12 @@ Literal::Literal(const Literal& other) : type(other.type) { case HeapType::noext: case HeapType::nofunc: case HeapType::noexn: + case HeapType::nocont: WASM_UNREACHABLE("null literals should already have been handled"); case HeapType::any: case HeapType::eq: case HeapType::func: + case HeapType::cont: case HeapType::struct_: case HeapType::array: case HeapType::exn: @@ -622,6 +624,9 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { case HeapType::noexn: o << "nullexnref"; break; + case HeapType::nocont: + o << "nullcontref"; + break; case HeapType::ext: o << "externref"; break; @@ -631,6 +636,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { case HeapType::any: case HeapType::eq: case HeapType::func: + case HeapType::cont: case HeapType::struct_: case HeapType::array: WASM_UNREACHABLE("invalid type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 28a630c4a..869b44f2c 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1500,6 +1500,9 @@ void WasmBinaryWriter::writeType(Type type) { case HeapType::func: o << S32LEB(BinaryConsts::EncodedType::funcref); return; + case HeapType::cont: + o << S32LEB(BinaryConsts::EncodedType::contref); + return; case HeapType::eq: o << S32LEB(BinaryConsts::EncodedType::eqref); return; @@ -1539,6 +1542,9 @@ void WasmBinaryWriter::writeType(Type type) { case HeapType::noexn: o << S32LEB(BinaryConsts::EncodedType::nullexnref); return; + case HeapType::nocont: + o << S32LEB(BinaryConsts::EncodedType::nullcontref); + return; } } if (type.isNullable()) { @@ -1612,6 +1618,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { case HeapType::func: ret = BinaryConsts::EncodedHeapType::func; break; + case HeapType::cont: + ret = BinaryConsts::EncodedHeapType::cont; + break; case HeapType::any: ret = BinaryConsts::EncodedHeapType::any; break; @@ -1654,6 +1663,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { case HeapType::noexn: ret = BinaryConsts::EncodedHeapType::noexn; break; + case HeapType::nocont: + ret = BinaryConsts::EncodedHeapType::nocont; + break; } o << S64LEB(ret); // TODO: Actually s33 } @@ -1986,6 +1998,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) { case BinaryConsts::EncodedType::funcref: out = Type(HeapType::func, Nullable); return true; + case BinaryConsts::EncodedType::contref: + out = Type(HeapType::cont, Nullable); + return true; case BinaryConsts::EncodedType::externref: out = Type(HeapType::ext, Nullable); return true; @@ -2031,6 +2046,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) { case BinaryConsts::EncodedType::nullexnref: out = Type(HeapType::noexn, Nullable); return true; + case BinaryConsts::EncodedType::nullcontref: + out = Type(HeapType::nocont, Nullable); + return true; default: return false; } @@ -2041,6 +2059,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) { case BinaryConsts::EncodedHeapType::func: out = HeapType::func; return true; + case BinaryConsts::EncodedHeapType::cont: + out = HeapType::func; + return true; case BinaryConsts::EncodedHeapType::ext: out = HeapType::ext; return true; @@ -2086,6 +2107,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) { case BinaryConsts::EncodedHeapType::noexn: out = HeapType::noexn; return true; + case BinaryConsts::EncodedHeapType::nocont: + out = HeapType::nocont; + return true; default: return false; } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index c7cedfdbd..5ac36fda7 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1257,6 +1257,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str, if (str.substr(0, 7) == "funcref" && (prefix || str.size() == 7)) { return Type(HeapType::func, Nullable); } + if (str.substr(0, 7) == "contref" && (prefix || str.size() == 7)) { + return Type(HeapType::cont, Nullable); + } if (str.substr(0, 9) == "externref" && (prefix || str.size() == 9)) { return Type(HeapType::ext, Nullable); } @@ -1302,6 +1305,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str, if (str.substr(0, 10) == "nullexnref" && (prefix || str.size() == 10)) { return Type(HeapType::noexn, Nullable); } + if (str.substr(0, 11) == "nullcontref" && (prefix || str.size() == 11)) { + return Type(HeapType::nocont, Nullable); + } if (allowError) { return Type::none; } @@ -1314,6 +1320,9 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, if (str.substr(0, 4) == "func" && (prefix || str.size() == 4)) { return HeapType::func; } + if (str.substr(0, 4) == "cont" && (prefix || str.size() == 4)) { + return HeapType::cont; + } if (str.substr(0, 2) == "eq" && (prefix || str.size() == 2)) { return HeapType::eq; } @@ -1362,6 +1371,9 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, if (str.substr(0, 5) == "noexn" && (prefix || str.size() == 5)) { return HeapType::noexn; } + if (str.substr(0, 6) == "nocont" && (prefix || str.size() == 6)) { + return HeapType::nocont; + } throw ParseException(std::string("invalid wasm heap type: ") + std::string(str.data(), str.size())); } diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 32da64470..16ab426ad 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -442,7 +442,7 @@ HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { case HeapTypeInfo::SignatureKind: return HeapType::func; case HeapTypeInfo::ContinuationKind: - return HeapType::any; + return HeapType::cont; case HeapTypeInfo::StructKind: return HeapType::struct_; case HeapTypeInfo::ArrayKind: @@ -472,6 +472,7 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a, switch (a) { case HeapType::ext: case HeapType::func: + case HeapType::cont: case HeapType::exn: return std::nullopt; case HeapType::any: @@ -503,6 +504,7 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a, case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: // Bottom types already handled. break; @@ -930,6 +932,10 @@ FeatureSet Type::getFeatures() const { feats |= FeatureSet::ExceptionHandling | FeatureSet::ReferenceTypes; return; + case HeapType::cont: + case HeapType::nocont: + feats |= FeatureSet::TypedContinuations; + return; } } @@ -1213,6 +1219,7 @@ bool HeapType::isBottom() const { switch (getBasic()) { case ext: case func: + case cont: case any: case eq: case i31: @@ -1227,6 +1234,7 @@ bool HeapType::isBottom() const { case none: case noext: case nofunc: + case nocont: case noexn: return true; } @@ -1286,6 +1294,8 @@ std::optional<HeapType> HeapType::getSuperType() const { case noext: case func: case nofunc: + case cont: + case nocont: case any: case none: case exn: @@ -1309,7 +1319,7 @@ std::optional<HeapType> HeapType::getSuperType() const { case HeapTypeInfo::SignatureKind: return func; case HeapTypeInfo::ContinuationKind: - return any; + return cont; case HeapTypeInfo::StructKind: return struct_; case HeapTypeInfo::ArrayKind: @@ -1329,10 +1339,8 @@ size_t HeapType::getDepth() const { // implicit supertyping wrt basic types. A signature type always has one more // super, HeapType::func, etc. if (!isBasic()) { - if (isFunction()) { + if (isFunction() || isContinuation()) { depth++; - } else if (isContinuation()) { - // cont types <: any, thus nothing to add } else if (isStruct()) { // specific struct types <: struct <: eq <: any depth += 3; @@ -1345,6 +1353,7 @@ size_t HeapType::getDepth() const { switch (getBasic()) { case HeapType::ext: case HeapType::func: + case HeapType::cont: case HeapType::any: case HeapType::exn: break; @@ -1362,6 +1371,7 @@ size_t HeapType::getDepth() const { break; case HeapType::none: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noext: case HeapType::noexn: // Bottom types are infinitely deep. @@ -1378,6 +1388,8 @@ HeapType::BasicHeapType HeapType::getBottom() const { return noext; case func: return nofunc; + case cont: + return nocont; case exn: return noexn; case any: @@ -1395,6 +1407,8 @@ HeapType::BasicHeapType HeapType::getBottom() const { return noext; case nofunc: return nofunc; + case nocont: + return nocont; case noexn: return noexn; } @@ -1404,7 +1418,7 @@ HeapType::BasicHeapType HeapType::getBottom() const { case HeapTypeInfo::SignatureKind: return nofunc; case HeapTypeInfo::ContinuationKind: - return none; + return nocont; case HeapTypeInfo::StructKind: case HeapTypeInfo::ArrayKind: return none; @@ -1426,12 +1440,15 @@ HeapType::BasicHeapType HeapType::getTop() const { return any; case nofunc: return func; + case nocont: + return cont; case noext: return ext; case noexn: return exn; case ext: case func: + case cont: case any: case eq: case i31: @@ -1719,6 +1736,8 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { return a.getTop() == HeapType::ext; case HeapType::func: return a.getTop() == HeapType::func; + case HeapType::cont: + return a.getTop() == HeapType::cont; case HeapType::exn: return a.getTop() == HeapType::exn; case HeapType::any: @@ -1741,6 +1760,7 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { case HeapType::none: case HeapType::noext: case HeapType::nofunc: + case HeapType::nocont: case HeapType::noexn: return false; } @@ -1856,6 +1876,8 @@ std::ostream& TypePrinter::print(Type type) { return os << "externref"; case HeapType::func: return os << "funcref"; + case HeapType::cont: + return os << "contref"; case HeapType::any: return os << "anyref"; case HeapType::eq: @@ -1882,6 +1904,8 @@ std::ostream& TypePrinter::print(Type type) { return os << "nullexternref"; case HeapType::nofunc: return os << "nullfuncref"; + case HeapType::nocont: + return os << "nullcontref"; case HeapType::noexn: return os << "nullexnref"; } @@ -1906,6 +1930,8 @@ std::ostream& TypePrinter::print(HeapType type) { return os << "extern"; case HeapType::func: return os << "func"; + case HeapType::cont: + return os << "cont"; case HeapType::any: return os << "any"; case HeapType::eq: @@ -1932,6 +1958,8 @@ std::ostream& TypePrinter::print(HeapType type) { return os << "noextern"; case HeapType::nofunc: return os << "nofunc"; + case HeapType::nocont: + return os << "nocont"; case HeapType::noexn: return os << "noexn"; } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 469267a4d..8bdf1ba52 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -25,18 +25,18 @@ BinaryenPackedTypeInt8: 1 BinaryenPackedTypeInt16: 2 BinaryenHeapTypeExt: 0 BinaryenHeapTypeFunc: 1 -BinaryenHeapTypeAny: 2 -BinaryenHeapTypeEq: 3 -BinaryenHeapTypeI31: 4 -BinaryenHeapTypeStruct: 5 -BinaryenHeapTypeArray: 6 -BinaryenHeapTypeString: 8 -BinaryenHeapTypeStringviewWTF8: 9 -BinaryenHeapTypeStringviewWTF16: 10 -BinaryenHeapTypeStringviewIter: 11 -BinaryenHeapTypeNone: 12 -BinaryenHeapTypeNoext: 13 -BinaryenHeapTypeNofunc: 14 +BinaryenHeapTypeAny: 3 +BinaryenHeapTypeEq: 4 +BinaryenHeapTypeI31: 5 +BinaryenHeapTypeStruct: 6 +BinaryenHeapTypeArray: 7 +BinaryenHeapTypeString: 9 +BinaryenHeapTypeStringviewWTF8: 10 +BinaryenHeapTypeStringviewWTF16: 11 +BinaryenHeapTypeStringviewIter: 12 +BinaryenHeapTypeNone: 13 +BinaryenHeapTypeNoext: 14 +BinaryenHeapTypeNofunc: 15 BinaryenFeatureMVP: 0 BinaryenFeatureAtomics: 1 BinaryenFeatureBulkMemory: 16 diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index e8c24b06c..3c97028a4 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -521,6 +521,7 @@ TEST_F(TypeTest, CanonicalizeTypesBeforeSubtyping) { TEST_F(TypeTest, TestHeapTypeRelations) { HeapType ext = HeapType::ext; HeapType func = HeapType::func; + HeapType cont = HeapType::cont; HeapType any = HeapType::any; HeapType eq = HeapType::eq; HeapType i31 = HeapType::i31; @@ -533,7 +534,9 @@ TEST_F(TypeTest, TestHeapTypeRelations) { HeapType none = HeapType::none; HeapType noext = HeapType::noext; HeapType nofunc = HeapType::nofunc; + HeapType nocont = HeapType::nocont; HeapType defFunc = Signature(); + HeapType defCont = Continuation(defFunc); HeapType defStruct = Struct(); HeapType defArray = Array(Field(Type::i32, Immutable)); @@ -578,6 +581,7 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(ext, ext, ext); assertLUB(ext, func, {}); + assertLUB(ext, cont, {}); assertLUB(ext, any, {}); assertLUB(ext, eq, {}); assertLUB(ext, i31, {}); @@ -590,11 +594,13 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(ext, none, {}); assertLUB(ext, noext, ext); assertLUB(ext, nofunc, {}); + assertLUB(ext, nocont, {}); assertLUB(ext, defFunc, {}); assertLUB(ext, defStruct, {}); assertLUB(ext, defArray, {}); assertLUB(func, func, func); + assertLUB(func, cont, {}); assertLUB(func, any, {}); assertLUB(func, eq, {}); assertLUB(func, i31, {}); @@ -607,11 +613,34 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(func, none, {}); assertLUB(func, noext, {}); assertLUB(func, nofunc, func); + assertLUB(func, nocont, {}); assertLUB(func, defFunc, func); + assertLUB(func, defCont, {}); assertLUB(func, defStruct, {}); assertLUB(func, defArray, {}); + assertLUB(cont, cont, cont); + assertLUB(cont, func, {}); + assertLUB(cont, any, {}); + assertLUB(cont, eq, {}); + assertLUB(cont, i31, {}); + assertLUB(cont, struct_, {}); + assertLUB(cont, array, {}); + assertLUB(cont, string, {}); + assertLUB(cont, stringview_wtf8, {}); + assertLUB(cont, stringview_wtf16, {}); + assertLUB(cont, stringview_iter, {}); + assertLUB(cont, none, {}); + assertLUB(cont, noext, {}); + assertLUB(cont, nofunc, {}); + assertLUB(cont, nocont, cont); + assertLUB(cont, defFunc, {}); + assertLUB(cont, defCont, cont); + assertLUB(cont, defStruct, {}); + assertLUB(cont, defArray, {}); + assertLUB(any, any, any); + assertLUB(any, cont, {}); assertLUB(any, eq, any); assertLUB(any, i31, any); assertLUB(any, struct_, any); @@ -623,11 +652,14 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(any, none, any); assertLUB(any, noext, {}); assertLUB(any, nofunc, {}); + assertLUB(any, nocont, {}); assertLUB(any, defFunc, {}); + assertLUB(any, defCont, {}); assertLUB(any, defStruct, any); assertLUB(any, defArray, any); assertLUB(eq, eq, eq); + assertLUB(eq, cont, {}); assertLUB(eq, i31, eq); assertLUB(eq, struct_, eq); assertLUB(eq, array, eq); @@ -638,11 +670,14 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(eq, none, eq); assertLUB(eq, noext, {}); assertLUB(eq, nofunc, {}); + assertLUB(eq, nocont, {}); assertLUB(eq, defFunc, {}); + assertLUB(eq, defCont, {}); assertLUB(eq, defStruct, eq); assertLUB(eq, defArray, eq); assertLUB(i31, i31, i31); + assertLUB(i31, cont, {}); assertLUB(i31, struct_, eq); assertLUB(i31, array, eq); assertLUB(i31, string, any); @@ -652,11 +687,14 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(i31, none, i31); assertLUB(i31, noext, {}); assertLUB(i31, nofunc, {}); + assertLUB(i31, nocont, {}); assertLUB(i31, defFunc, {}); + assertLUB(i31, defCont, {}); assertLUB(i31, defStruct, eq); assertLUB(i31, defArray, eq); assertLUB(struct_, struct_, struct_); + assertLUB(struct_, cont, {}); assertLUB(struct_, array, eq); assertLUB(struct_, string, any); assertLUB(struct_, stringview_wtf8, {}); @@ -665,11 +703,14 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(struct_, none, struct_); assertLUB(struct_, noext, {}); assertLUB(struct_, nofunc, {}); + assertLUB(struct_, nocont, {}); assertLUB(struct_, defFunc, {}); + assertLUB(struct_, defCont, {}); assertLUB(struct_, defStruct, struct_); assertLUB(struct_, defArray, eq); assertLUB(array, array, array); + assertLUB(array, cont, {}); assertLUB(array, string, any); assertLUB(array, stringview_wtf8, {}); assertLUB(array, stringview_wtf16, {}); @@ -677,18 +718,23 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(array, none, array); assertLUB(array, noext, {}); assertLUB(array, nofunc, {}); + assertLUB(array, nocont, {}); assertLUB(array, defFunc, {}); + assertLUB(array, defCont, {}); assertLUB(array, defStruct, eq); assertLUB(array, defArray, array); assertLUB(string, string, string); + assertLUB(string, cont, {}); assertLUB(string, stringview_wtf8, {}); assertLUB(string, stringview_wtf16, {}); assertLUB(string, stringview_iter, {}); assertLUB(string, none, string); assertLUB(string, noext, {}); assertLUB(string, nofunc, {}); + assertLUB(string, nocont, {}); assertLUB(string, defFunc, {}); + assertLUB(string, defCont, {}); assertLUB(string, defStruct, any); assertLUB(string, defArray, any); @@ -698,8 +744,10 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(stringview_wtf8, none, stringview_wtf8); assertLUB(stringview_wtf8, noext, {}); assertLUB(stringview_wtf8, nofunc, {}); + assertLUB(stringview_wtf8, nocont, {}); assertLUB(stringview_wtf8, defFunc, {}); assertLUB(stringview_wtf8, defStruct, {}); + assertLUB(stringview_wtf8, defCont, {}); assertLUB(stringview_wtf8, defArray, {}); assertLUB(stringview_wtf16, stringview_wtf16, stringview_wtf16); @@ -707,40 +755,65 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(stringview_wtf16, none, stringview_wtf16); assertLUB(stringview_wtf16, noext, {}); assertLUB(stringview_wtf16, nofunc, {}); + assertLUB(stringview_wtf16, nocont, {}); assertLUB(stringview_wtf16, defFunc, {}); assertLUB(stringview_wtf16, defStruct, {}); + assertLUB(stringview_wtf16, defCont, {}); assertLUB(stringview_wtf16, defArray, {}); assertLUB(stringview_iter, stringview_iter, stringview_iter); assertLUB(stringview_iter, none, stringview_iter); assertLUB(stringview_iter, noext, {}); assertLUB(stringview_iter, nofunc, {}); + assertLUB(stringview_iter, nocont, {}); assertLUB(stringview_iter, defFunc, {}); assertLUB(stringview_iter, defStruct, {}); + assertLUB(stringview_iter, defCont, {}); assertLUB(stringview_iter, defArray, {}); assertLUB(none, none, none); assertLUB(none, noext, {}); assertLUB(none, nofunc, {}); + assertLUB(none, nocont, {}); assertLUB(none, defFunc, {}); + assertLUB(none, defCont, {}); assertLUB(none, defStruct, defStruct); assertLUB(none, defArray, defArray); assertLUB(noext, noext, noext); assertLUB(noext, nofunc, {}); + assertLUB(noext, nocont, {}); assertLUB(noext, defFunc, {}); + assertLUB(noext, defCont, {}); assertLUB(noext, defStruct, {}); assertLUB(noext, defArray, {}); assertLUB(nofunc, nofunc, nofunc); + assertLUB(nofunc, nocont, {}); assertLUB(nofunc, defFunc, defFunc); + assertLUB(nofunc, defCont, {}); assertLUB(nofunc, defStruct, {}); assertLUB(nofunc, defArray, {}); + assertLUB(nocont, nocont, nocont); + assertLUB(nocont, func, {}); + assertLUB(nocont, cont, cont); + assertLUB(nocont, nofunc, {}); + assertLUB(nocont, defFunc, {}); + assertLUB(nocont, defCont, defCont); + assertLUB(nocont, defStruct, {}); + assertLUB(nocont, defArray, {}); + assertLUB(defFunc, defFunc, defFunc); + assertLUB(defFunc, defCont, {}); assertLUB(defFunc, defStruct, {}); assertLUB(defFunc, defArray, {}); + assertLUB(defCont, defCont, defCont); + assertLUB(defCont, defFunc, {}); + assertLUB(defCont, defStruct, {}); + assertLUB(defCont, defArray, {}); + assertLUB(defStruct, defStruct, defStruct); assertLUB(defStruct, defArray, eq); @@ -1005,6 +1078,7 @@ TEST_F(TypeTest, TestMaxArrayDepths) { // Test .depth() helper. TEST_F(TypeTest, TestDepth) { HeapType A, B, C; + HeapType sig = HeapType(Signature(Type::none, Type::none)); { TypeBuilder builder(3); builder[0].setOpen() = Struct(); @@ -1029,7 +1103,11 @@ TEST_F(TypeTest, TestDepth) { // Signature types are subtypes of func. EXPECT_EQ(HeapType(HeapType::func).getDepth(), 0U); - EXPECT_EQ(HeapType(Signature(Type::none, Type::none)).getDepth(), 1U); + EXPECT_EQ(sig.getDepth(), 1U); + + // Continuation types are subtypes of cont. + EXPECT_EQ(HeapType(HeapType::cont).getDepth(), 0U); + EXPECT_EQ(HeapType(Continuation(sig)).getDepth(), 1U); EXPECT_EQ(HeapType(HeapType::ext).getDepth(), 0U); @@ -1097,6 +1175,7 @@ TEST_F(TypeTest, TestSupertypes) { // Basic types: getDeclaredSuperType always returns nothing. ASSERT_FALSE(HeapType(HeapType::ext).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::func).getDeclaredSuperType()); + ASSERT_FALSE(HeapType(HeapType::cont).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::any).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::eq).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::i31).getDeclaredSuperType()); @@ -1109,10 +1188,12 @@ TEST_F(TypeTest, TestSupertypes) { ASSERT_FALSE(HeapType(HeapType::none).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::noext).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::nofunc).getDeclaredSuperType()); + ASSERT_FALSE(HeapType(HeapType::nocont).getDeclaredSuperType()); // Basic types: getSuperType does return a super, when there is one. ASSERT_FALSE(HeapType(HeapType::ext).getSuperType()); ASSERT_FALSE(HeapType(HeapType::func).getSuperType()); + ASSERT_FALSE(HeapType(HeapType::cont).getSuperType()); ASSERT_FALSE(HeapType(HeapType::any).getSuperType()); ASSERT_EQ(HeapType(HeapType::eq).getSuperType(), HeapType::any); ASSERT_EQ(HeapType(HeapType::i31).getSuperType(), HeapType::eq); @@ -1125,6 +1206,7 @@ TEST_F(TypeTest, TestSupertypes) { ASSERT_FALSE(HeapType(HeapType::none).getSuperType()); ASSERT_FALSE(HeapType(HeapType::noext).getSuperType()); ASSERT_FALSE(HeapType(HeapType::nofunc).getSuperType()); + ASSERT_FALSE(HeapType(HeapType::nocont).getSuperType()); // Non-basic types. HeapType struct1, struct2, array1, array2, sig1, sig2; diff --git a/test/lit/basic/typed_continuations.wast b/test/lit/basic/typed_continuations.wast index 998837817..52258403f 100644 --- a/test/lit/basic/typed_continuations.wast +++ b/test/lit/basic/typed_continuations.wast @@ -19,17 +19,37 @@ ;; CHECK-TEXT: (type $2 (func (param (ref $ct)) (result (ref $ct)))) + ;; CHECK-TEXT: (type $3 (func (param contref nullcontref (ref cont) (ref nocont)) (result contref))) + ;; CHECK-TEXT: (func $id (type $2) (param $x (ref $ct)) (result (ref $ct)) ;; CHECK-TEXT-NEXT: (local.get $x) ;; CHECK-TEXT-NEXT: ) ;; CHECK-BIN: (type $2 (func (param (ref $ct)) (result (ref $ct)))) + ;; CHECK-BIN: (type $3 (func (param contref nullcontref (ref func) (ref nocont)) (result contref))) + ;; CHECK-BIN: (func $id (type $2) (param $x (ref $ct)) (result (ref $ct)) ;; CHECK-BIN-NEXT: (local.get $x) ;; CHECK-BIN-NEXT: ) (func $id (param $x (ref $ct)) (result (ref $ct)) (local.get $x) ) + + ;; CHECK-TEXT: (func $id2 (type $3) (param $w contref) (param $x nullcontref) (param $y (ref cont)) (param $z (ref nocont)) (result contref) + ;; CHECK-TEXT-NEXT: (local.get $z) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $id2 (type $3) (param $w contref) (param $x nullcontref) (param $y (ref func)) (param $z (ref nocont)) (result contref) + ;; CHECK-BIN-NEXT: (local.get $z) + ;; CHECK-BIN-NEXT: ) + (func $id2 + (param $w contref) + (param $x nullcontref) + (param $y (ref cont)) + (param $z (ref nocont)) + (result contref) + (local.get $z) + ) + ) ;; CHECK-BIN-NODEBUG: (type $0 (func (param i32) (result i32))) @@ -37,6 +57,12 @@ ;; CHECK-BIN-NODEBUG: (type $2 (func (param (ref $1)) (result (ref $1)))) +;; CHECK-BIN-NODEBUG: (type $3 (func (param contref nullcontref (ref func) (ref nocont)) (result contref))) + ;; CHECK-BIN-NODEBUG: (func $0 (type $2) (param $0 (ref $1)) (result (ref $1)) ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $1 (type $3) (param $0 contref) (param $1 nullcontref) (param $2 (ref func)) (param $3 (ref nocont)) (result contref) +;; CHECK-BIN-NODEBUG-NEXT: (local.get $3) +;; CHECK-BIN-NODEBUG-NEXT: ) diff --git a/test/spec/typed_continuations.wast b/test/spec/typed_continuations.wast index 5f7b86f6c..e3bddbf77 100644 --- a/test/spec/typed_continuations.wast +++ b/test/spec/typed_continuations.wast @@ -5,6 +5,14 @@ (func $id (param $x (ref $ct)) (result (ref $ct)) (local.get $x) ) + + (func $cont-nocont (param $x (ref null $ct)) + (local $l1 (ref null cont)) + (local $l2 (ref null $ct)) + (local.set $l1 (local.get $x)) ;; $ct <: cont + (local.set $l2 (ref.null nocont)) ;; nocont <: $ct + (local.set $l1 (ref.null nocont)) ;; nocont <: cont + ) ) (assert_invalid |