summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-c.cpp4
-rw-r--r--src/tools/fuzzing/fuzzing.cpp7
-rw-r--r--src/tools/fuzzing/heap-types.cpp6
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-type.h6
-rw-r--r--src/wasm/literal.cpp6
-rw-r--r--src/wasm/wasm-binary.cpp24
-rw-r--r--src/wasm/wasm-s-parser.cpp12
-rw-r--r--src/wasm/wasm-type.cpp40
-rw-r--r--test/example/c-api-kitchen-sink.txt24
-rw-r--r--test/gtest/type-builder.cpp84
-rw-r--r--test/lit/basic/typed_continuations.wast26
-rw-r--r--test/spec/typed_continuations.wast8
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