diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/contexts.h | 7 | ||||
-rw-r--r-- | src/parser/parsers.h | 23 | ||||
-rw-r--r-- | src/shared-constants.h | 1 | ||||
-rw-r--r-- | src/wasm-binary.h | 29 | ||||
-rw-r--r-- | src/wasm-type-printing.h | 1 | ||||
-rw-r--r-- | src/wasm-type.h | 26 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 40 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 48 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 107 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 1 |
10 files changed, 250 insertions, 33 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h index 862d9772d..eb47dd502 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -83,6 +83,7 @@ struct NullTypeParserCtx { using ResultsT = size_t; using BlockTypeT = Ok; using SignatureT = Ok; + using ContinuationT = Ok; using StorageT = Ok; using FieldT = Ok; using FieldsT = Ok; @@ -122,6 +123,7 @@ struct NullTypeParserCtx { size_t getResultsSize(size_t results) { return results; } SignatureT makeFuncType(ParamsT*, ResultsT*) { return Ok{}; } + ContinuationT makeContType(HeapTypeT) { return Ok{}; } StorageT makeI8() { return Ok{}; } StorageT makeI16() { return Ok{}; } @@ -162,6 +164,7 @@ template<typename Ctx> struct TypeParserCtx { using ResultsT = std::vector<Type>; using BlockTypeT = HeapType; using SignatureT = Signature; + using ContinuationT = Continuation; using StorageT = Field; using FieldT = Field; using FieldsT = std::pair<std::vector<Name>, std::vector<Field>>; @@ -216,6 +219,8 @@ template<typename Ctx> struct TypeParserCtx { self().makeTupleType(resultTypes)); } + ContinuationT makeContType(HeapTypeT ft) { return Continuation(ft); } + StorageT makeI8() { return Field(Field::i8, Immutable); } StorageT makeI16() { return Field(Field::i16, Immutable); } StorageT makeStorageType(TypeT type) { return Field(type, Immutable); } @@ -469,6 +474,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx { ParseDeclsCtx(std::string_view in, Module& wasm) : in(in), wasm(wasm) {} void addFuncType(SignatureT) {} + void addContType(ContinuationT) {} void addStructType(StructT) {} void addArrayType(ArrayT) {} void setOpen() {} @@ -577,6 +583,7 @@ struct ParseTypeDefsCtx : TypeParserCtx<ParseTypeDefsCtx> { } void addFuncType(SignatureT& type) { builder[index] = type; } + void addContType(ContinuationT& type) { builder[index] = type; } void addStructType(StructT& type) { auto& [fieldNames, str] = type; diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 32f6709df..65fd98a24 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -391,6 +391,23 @@ MaybeResult<typename Ctx::SignatureT> functype(Ctx& ctx) { return ctx.makeFuncType(parsedParams.getPtr(), parsedResults.getPtr()); } +// conttype ::= '(' 'cont' x:typeidx ')' => cont x +template<typename Ctx> +MaybeResult<typename Ctx::ContinuationT> conttype(Ctx& ctx) { + if (!ctx.in.takeSExprStart("cont"sv)) { + return {}; + } + + auto x = typeidx(ctx); + CHECK_ERR(x); + + if (!ctx.in.takeRParen()) { + return ctx.in.err("expected end of cont type"); + } + + return ctx.makeContType(*x); +} + // storagetype ::= valtype | packedtype // packedtype ::= i8 | i16 template<typename Ctx> Result<typename Ctx::FieldT> storagetype(Ctx& ctx) { @@ -1650,6 +1667,7 @@ Result<std::vector<Name>> inlineExports(ParseInput& in) { } // strtype ::= ft:functype => ft +// | ct:conttype => ct // | st:structtype => st // | at:arraytype => at template<typename Ctx> Result<> strtype(Ctx& ctx) { @@ -1658,6 +1676,11 @@ template<typename Ctx> Result<> strtype(Ctx& ctx) { ctx.addFuncType(*type); return Ok{}; } + if (auto type = conttype(ctx)) { + CHECK_ERR(type); + ctx.addContType(*type); + return Ok{}; + } if (auto type = structtype(ctx)) { CHECK_ERR(type); ctx.addStructType(*type); diff --git a/src/shared-constants.h b/src/shared-constants.h index 0d2cc73ad..321ec3884 100644 --- a/src/shared-constants.h +++ b/src/shared-constants.h @@ -25,6 +25,7 @@ extern Name STACK_POINTER; extern Name MODULE; extern Name START; extern Name FUNC; +extern Name CONT; extern Name PARAM; extern Name RESULT; extern Name MEMORY; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ee92fe90e..9e72b3b82 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -379,8 +379,8 @@ enum EncodedType { i8 = -0x8, // 0x78 i16 = -0x9, // 0x77 #else - i8 = -0x6, // 0x7a - i16 = -0x7, // 0x79 + i8 = -0x6, // 0x7a + i16 = -0x7, // 0x79 #endif // reference types #if STANDARD_GC_ENCODINGS @@ -391,12 +391,12 @@ enum EncodedType { structref = -0x15, // 0x6b arrayref = -0x16, // 0x6a #else - nullexternref = -0x17, // 0x69 - nullfuncref = -0x18, // 0x68 - nullref = -0x1b, // 0x65 - i31ref = -0x16, // 0x6a - structref = -0x19, // 0x67 - arrayref = -0x1a, // 0x66 + nullexternref = -0x17, // 0x69 + nullfuncref = -0x18, // 0x68 + nullref = -0x1b, // 0x65 + i31ref = -0x16, // 0x6a + structref = -0x19, // 0x67 + arrayref = -0x1a, // 0x66 #endif funcref = -0x10, // 0x70 externref = -0x11, // 0x6f @@ -409,34 +409,35 @@ enum EncodedType { nonnullable = -0x1c, // 0x64 nullable = -0x1d, // 0x63 #else - nullable = -0x14, // 0x6c - nonnullable = -0x15, // 0x6b + nullable = -0x14, // 0x6c + nonnullable = -0x15, // 0x6b #endif // string reference types #if STANDARD_GC_ENCODINGS stringref = -0x19, // 0x67 stringview_wtf8 = -0x1a, // 0x66 #else - stringref = -0x1c, // 0x64 - stringview_wtf8 = -0x1d, // 0x63 + stringref = -0x1c, // 0x64 + stringview_wtf8 = -0x1d, // 0x63 #endif stringview_wtf16 = -0x1e, // 0x62 stringview_iter = -0x1f, // 0x61 // type forms Func = -0x20, // 0x60 + Cont = -0x23, // 0x5d Struct = -0x21, // 0x5f Array = -0x22, // 0x5e Sub = -0x30, // 0x50 #if STANDARD_GC_ENCODINGS SubFinal = -0x31, // 0x4f #else - SubFinal = -0x32, // 0x4e + SubFinal = -0x32, // 0x4e #endif // isorecursive recursion groups #if STANDARD_GC_ENCODINGS Rec = -0x32, // 0x4e #else - Rec = -0x31, // 0x4f + Rec = -0x31, // 0x4f #endif // block_type Empty = -0x40, // 0x40 diff --git a/src/wasm-type-printing.h b/src/wasm-type-printing.h index 3a8740350..c7277e96d 100644 --- a/src/wasm-type-printing.h +++ b/src/wasm-type-printing.h @@ -53,6 +53,7 @@ template<typename Subclass> struct TypeNameGeneratorBase { struct DefaultTypeNameGenerator : TypeNameGeneratorBase<DefaultTypeNameGenerator> { size_t funcCount = 0; + size_t contCount = 0; size_t structCount = 0; size_t arrayCount = 0; diff --git a/src/wasm-type.h b/src/wasm-type.h index 23ceb9143..0061b9626 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -52,6 +52,7 @@ class Type; class HeapType; class RecGroup; struct Signature; +struct Continuation; struct Field; struct Struct; struct Array; @@ -345,6 +346,8 @@ public: // this signature. HeapType(Signature signature); + HeapType(Continuation cont); + // Create a HeapType with the given structure. In equirecursive mode, this may // be the same as a previous HeapType created with the same contents. In // nominal mode, this will be a fresh type distinct from all previously @@ -358,6 +361,7 @@ public: bool isFunction() const; bool isData() const; bool isSignature() const; + bool isContinuation() const; bool isStruct() const; bool isArray() const; bool isString() const; @@ -365,6 +369,8 @@ public: bool isOpen() const; Signature getSignature() const; + Continuation getContinuation() const; + const Struct& getStruct() const; Array getArray() const; @@ -476,6 +482,16 @@ struct Signature { std::string toString() const; }; +struct Continuation { + HeapType type; + Continuation(HeapType type) : type(type) {} + bool operator==(const Continuation& other) const { + return type == other.type; + } + bool operator!=(const Continuation& other) const { return !(*this == other); } + std::string toString() const; +}; + struct Field { Type type; enum PackedType { @@ -570,6 +586,7 @@ struct TypeBuilder { // Sets the heap type at index `i`. May only be called before `build`. void setHeapType(size_t i, Signature signature); + void setHeapType(size_t i, Continuation continuation); void setHeapType(size_t i, const Struct& struct_); void setHeapType(size_t i, Struct&& struct_); void setHeapType(size_t i, Array array); @@ -640,6 +657,10 @@ struct TypeBuilder { builder.setHeapType(index, signature); return *this; } + Entry& operator=(Continuation continuation) { + builder.setHeapType(index, continuation); + return *this; + } Entry& operator=(const Struct& struct_) { builder.setHeapType(index, struct_); return *this; @@ -687,6 +708,7 @@ std::ostream& operator<<(std::ostream&, HeapType); std::ostream& operator<<(std::ostream&, HeapType::Printed); std::ostream& operator<<(std::ostream&, Tuple); std::ostream& operator<<(std::ostream&, Signature); +std::ostream& operator<<(std::ostream&, Continuation); std::ostream& operator<<(std::ostream&, Field); std::ostream& operator<<(std::ostream&, Struct); std::ostream& operator<<(std::ostream&, Array); @@ -704,6 +726,10 @@ template<> class hash<wasm::Signature> { public: size_t operator()(const wasm::Signature&) const; }; +template<> class hash<wasm::Continuation> { +public: + size_t operator()(const wasm::Continuation&) const; +}; template<> class hash<wasm::Field> { public: size_t operator()(const wasm::Field&) const; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b12cb50c7..6b74f2597 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -292,6 +292,9 @@ void WasmBinaryWriter::writeTypes() { writeType(type); } } + } else if (type.isContinuation()) { + o << S32LEB(BinaryConsts::EncodedType::Cont); + writeHeapType(type.getContinuation().type); } else if (type.isStruct()) { o << S32LEB(BinaryConsts::EncodedType::Struct); auto fields = type.getStruct().fields; @@ -1577,7 +1580,8 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { } } - if (type.isSignature() || type.isStruct() || type.isArray()) { + if (type.isSignature() || type.isContinuation() || type.isStruct() || + type.isArray()) { o << S64LEB(getTypeIndex(type)); // TODO: Actually s33 return; } @@ -2184,6 +2188,17 @@ void WasmBinaryReader::readTypes() { TypeBuilder builder(getU32LEB()); BYN_TRACE("num: " << builder.size() << std::endl); + auto readHeapType = [&]() { + int64_t htCode = getS64LEB(); // TODO: Actually s33 + HeapType ht; + if (getBasicHeapType(htCode, ht)) { + return ht; + } + if (size_t(htCode) >= builder.size()) { + throwError("invalid type index: " + std::to_string(htCode)); + } + return builder.getTempHeapType(size_t(htCode)); + }; auto makeType = [&](int32_t typeCode) { Type type; if (getBasicType(typeCode, type)) { @@ -2196,22 +2211,19 @@ void WasmBinaryReader::readTypes() { auto nullability = typeCode == BinaryConsts::EncodedType::nullable ? Nullable : NonNullable; - int64_t htCode = getS64LEB(); // TODO: Actually s33 - HeapType ht; - if (getBasicHeapType(htCode, ht)) { + + HeapType ht = readHeapType(); + if (ht.isBasic()) { return Type(ht, nullability); } - if (size_t(htCode) >= builder.size()) { - throwError("invalid type index: " + std::to_string(htCode)); - } - return builder.getTempRefType(builder[size_t(htCode)], nullability); + + return builder.getTempRefType(ht, nullability); } default: throwError("unexpected type index: " + std::to_string(typeCode)); } WASM_UNREACHABLE("unexpected type"); }; - auto readType = [&]() { return makeType(getS32LEB()); }; auto readSignatureDef = [&]() { @@ -2231,6 +2243,14 @@ void WasmBinaryReader::readTypes() { builder.getTempTupleType(results)); }; + auto readContinuationDef = [&]() { + HeapType ht = readHeapType(); + if (!ht.isSignature()) { + throw ParseException("cont types must be built from function types"); + } + return Continuation(ht); + }; + auto readMutability = [&]() { switch (getU32LEB()) { case 0: @@ -2303,6 +2323,8 @@ void WasmBinaryReader::readTypes() { } if (form == BinaryConsts::EncodedType::Func) { builder[i] = readSignatureDef(); + } else if (form == BinaryConsts::EncodedType::Cont) { + builder[i] = readContinuationDef(); } else if (form == BinaryConsts::EncodedType::Struct) { builder[i] = readStructDef(); } else if (form == BinaryConsts::EncodedType::Array) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 4074e4792..6f3fbe76b 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -817,22 +817,36 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { }); finishGroup(); + auto parseHeapType = [&](Element& elem) -> HeapType { + auto name = elem.toString(); + if (elem.dollared()) { + auto it = typeIndices.find(name); + if (it == typeIndices.end()) { + throw SParseException("invalid type name", elem); + } else { + return builder[it->second]; + } + } else if (String::isNumber(name)) { + size_t index = parseIndex(elem); + if (index >= numTypes) { + throw SParseException("invalid type index", elem); + } + return builder[index]; + } else { + return stringToHeapType(elem.str()); + } + }; + auto parseRefType = [&](Element& elem) -> Type { // '(' 'ref' 'null'? ht ')' auto nullable = elem[1]->isStr() && *elem[1] == NULL_ ? Nullable : NonNullable; auto& referent = nullable ? *elem[2] : *elem[1]; - auto name = referent.toString(); - if (referent.dollared()) { - return builder.getTempRefType(builder[typeIndices[name]], nullable); - } else if (String::isNumber(name)) { - size_t index = parseIndex(referent); - if (index >= numTypes) { - throw SParseException("invalid type index", elem); - } - return builder.getTempRefType(builder[index], nullable); + auto ht = parseHeapType(referent); + if (ht.isBasic()) { + return Type(ht, nullable); } else { - return Type(stringToHeapType(referent.str()), nullable); + return builder.getTempRefType(ht, nullable); } }; @@ -886,6 +900,16 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { builder.getTempTupleType(results)); }; + auto parseContinuationDef = [&](Element& elem) { + // '(' 'cont' index ')' | '(' 'cont' name ')' + HeapType ft = parseHeapType(*elem[1]); + if (!ft.isSignature()) { + throw ParseException( + "cont type must be created from func type", elem.line, elem.col); + } + return Continuation(ft); + }; + // Parses a field, and notes the name if one is found. auto parseField = [&](Element* elem, Name& name) { Mutability mutable_ = Immutable; @@ -964,6 +988,8 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { Element& subtypeKind = *subtype[0]; if (subtypeKind == FUNC) { builder[index] = parseSignatureDef(subtype, 0); + } else if (kind == CONT) { + builder[index] = parseContinuationDef(subtype); } else if (subtypeKind == STRUCT) { builder[index] = parseStructDef(subtype, index, 0); } else if (subtypeKind == ARRAY) { @@ -974,6 +1000,8 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } else { if (kind == FUNC) { builder[index] = parseSignatureDef(def, 0); + } else if (kind == CONT) { + builder[index] = parseContinuationDef(def); } else if (kind == STRUCT) { builder[index] = parseStructDef(def, index, 0); } else if (kind == ARRAY) { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 68d7f732b..cab68d00d 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -94,16 +94,20 @@ struct HeapTypeInfo { size_t recGroupIndex = 0; enum Kind { SignatureKind, + ContinuationKind, StructKind, ArrayKind, } kind; union { Signature signature; + Continuation continuation; Struct struct_; Array array; }; HeapTypeInfo(Signature sig) : kind(SignatureKind), signature(sig) {} + HeapTypeInfo(Continuation continuation) + : kind(ContinuationKind), continuation(continuation) {} HeapTypeInfo(const Struct& struct_) : kind(StructKind), struct_(struct_) {} HeapTypeInfo(Struct&& struct_) : kind(StructKind), struct_(std::move(struct_)) {} @@ -111,6 +115,7 @@ struct HeapTypeInfo { ~HeapTypeInfo(); constexpr bool isSignature() const { return kind == SignatureKind; } + constexpr bool isContinuation() const { return kind == ContinuationKind; } constexpr bool isStruct() const { return kind == StructKind; } constexpr bool isArray() const { return kind == ArrayKind; } constexpr bool isData() const { return isStruct() || isArray(); } @@ -124,6 +129,7 @@ struct SubTyper { bool isSubType(const Tuple& a, const Tuple& b); bool isSubType(const Field& a, const Field& b); bool isSubType(const Signature& a, const Signature& b); + bool isSubType(const Continuation& a, const Continuation& b); bool isSubType(const Struct& a, const Struct& b); bool isSubType(const Array& a, const Array& b); }; @@ -155,6 +161,7 @@ struct TypePrinter { std::ostream& print(const Tuple& tuple); std::ostream& print(const Field& field); std::ostream& print(const Signature& sig); + std::ostream& print(const Continuation& cont); std::ostream& print(const Struct& struct_, const std::unordered_map<Index, Name>& fieldNames); std::ostream& print(const Array& array); @@ -181,6 +188,7 @@ struct RecGroupHasher { size_t hash(const Tuple& tuple) const; size_t hash(const Field& field) const; size_t hash(const Signature& sig) const; + size_t hash(const Continuation& sig) const; size_t hash(const Struct& struct_) const; size_t hash(const Array& array) const; }; @@ -207,6 +215,7 @@ struct RecGroupEquator { bool eq(const Tuple& a, const Tuple& b) const; bool eq(const Field& a, const Field& b) const; bool eq(const Signature& a, const Signature& b) const; + bool eq(const Continuation& a, const Continuation& b) const; bool eq(const Struct& a, const Struct& b) const; bool eq(const Array& a, const Array& b) const; }; @@ -355,6 +364,7 @@ template<typename Self> struct HeapTypeChildWalker : HeapTypeGraphWalker<Self> { } else { static_cast<Self*>(this)->noteChild(ht); } + isTopLevel = false; } private: @@ -431,6 +441,8 @@ HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { switch (info->kind) { case HeapTypeInfo::SignatureKind: return HeapType::func; + case HeapTypeInfo::ContinuationKind: + return HeapType::any; case HeapTypeInfo::StructKind: return HeapType::struct_; case HeapTypeInfo::ArrayKind: @@ -550,6 +562,9 @@ HeapTypeInfo::~HeapTypeInfo() { case SignatureKind: signature.~Signature(); return; + case ContinuationKind: + continuation.~Continuation(); + return; case StructKind: struct_.~Struct(); return; @@ -922,6 +937,8 @@ FeatureSet Type::getFeatures() const { if (sig.results.isTuple()) { feats |= FeatureSet::Multivalue; } + } else if (heapType->isContinuation()) { + feats |= FeatureSet::TypedContinuations; } // In addition, scan their non-ref children, to add dependencies on @@ -1093,6 +1110,12 @@ HeapType::HeapType(Signature sig) { HeapType(globalRecGroupStore.insert(std::make_unique<HeapTypeInfo>(sig))); } +HeapType::HeapType(Continuation continuation) { + assert(!isTemp(continuation.type) && "Leaking temporary type!"); + new (this) HeapType( + globalRecGroupStore.insert(std::make_unique<HeapTypeInfo>(continuation))); +} + HeapType::HeapType(const Struct& struct_) { #ifndef NDEBUG for (const auto& field : struct_.fields) { @@ -1143,6 +1166,14 @@ bool HeapType::isSignature() const { } } +bool HeapType::isContinuation() const { + if (isBasic()) { + return false; + } else { + return getHeapTypeInfo(*this)->isContinuation(); + } +} + bool HeapType::isStruct() const { if (isBasic()) { return false; @@ -1198,6 +1229,11 @@ Signature HeapType::getSignature() const { return getHeapTypeInfo(*this)->signature; } +Continuation HeapType::getContinuation() const { + assert(isContinuation()); + return getHeapTypeInfo(*this)->continuation; +} + const Struct& HeapType::getStruct() const { assert(isStruct()); return getHeapTypeInfo(*this)->struct_; @@ -1252,6 +1288,8 @@ std::optional<HeapType> HeapType::getSuperType() const { switch (info->kind) { case HeapTypeInfo::SignatureKind: return func; + case HeapTypeInfo::ContinuationKind: + return any; case HeapTypeInfo::StructKind: return struct_; case HeapTypeInfo::ArrayKind: @@ -1273,6 +1311,8 @@ size_t HeapType::getDepth() const { if (!isBasic()) { if (isFunction()) { depth++; + } else if (isContinuation()) { + // cont types <: any, thus nothing to add } else if (isStruct()) { // specific struct types <: struct <: eq <: any depth += 3; @@ -1337,6 +1377,8 @@ HeapType::BasicHeapType HeapType::getBottom() const { switch (info->kind) { case HeapTypeInfo::SignatureKind: return nofunc; + case HeapTypeInfo::ContinuationKind: + return none; case HeapTypeInfo::StructKind: case HeapTypeInfo::ArrayKind: return none; @@ -1376,6 +1418,9 @@ std::vector<Type> HeapType::getTypeChildren() const { } return children; } + if (isContinuation()) { + return {}; + } WASM_UNREACHABLE("unexpected kind"); } @@ -1496,6 +1541,8 @@ TypeNames DefaultTypeNameGenerator::getNames(HeapType type) { std::stringstream stream; if (type.isSignature()) { stream << "func." << funcCount++; + } else if (type.isContinuation()) { + stream << "cont." << contCount++; } else if (type.isStruct()) { stream << "struct." << structCount++; } else if (type.isArray()) { @@ -1516,6 +1563,7 @@ template<typename T> static std::string genericToString(const T& t) { std::string Type::toString() const { return genericToString(*this); } std::string HeapType::toString() const { return genericToString(*this); } std::string Signature::toString() const { return genericToString(*this); } +std::string Continuation::toString() const { return genericToString(*this); } std::string Struct::toString() const { return genericToString(*this); } std::string Array::toString() const { return genericToString(*this); } @@ -1537,6 +1585,9 @@ std::ostream& operator<<(std::ostream& os, Tuple tuple) { std::ostream& operator<<(std::ostream& os, Signature sig) { return TypePrinter(os).print(sig); } +std::ostream& operator<<(std::ostream& os, Continuation cont) { + return TypePrinter(os).print(cont); +} std::ostream& operator<<(std::ostream& os, Field field) { return TypePrinter(os).print(field); } @@ -1671,6 +1722,10 @@ bool SubTyper::isSubType(const Signature& a, const Signature& b) { return isSubType(b.params, a.params) && isSubType(a.results, b.results); } +bool SubTyper::isSubType(const Continuation& a, const Continuation& b) { + return isSubType(a.type, b.type); +} + bool SubTyper::isSubType(const Struct& a, const Struct& b) { // There may be more fields on the left, but not fewer. if (a.fields.size() < b.fields.size()) { @@ -1833,6 +1888,8 @@ std::ostream& TypePrinter::print(HeapType type) { } if (type.isSignature()) { print(type.getSignature()); + } else if (type.isContinuation()) { + print(type.getContinuation()); } else if (type.isStruct()) { print(type.getStruct(), names.fieldNames); } else if (type.isArray()) { @@ -1901,6 +1958,12 @@ std::ostream& TypePrinter::print(const Signature& sig) { return os << ')'; } +std::ostream& TypePrinter::print(const Continuation& continuation) { + os << "(cont "; + printHeapTypeName(continuation.type); + return os << ')'; +} + std::ostream& TypePrinter::print(const Struct& struct_, const std::unordered_map<Index, Name>& fieldNames) { @@ -1998,6 +2061,9 @@ size_t RecGroupHasher::hash(const HeapTypeInfo& info) const { case HeapTypeInfo::SignatureKind: hash_combine(digest, hash(info.signature)); return digest; + case HeapTypeInfo::ContinuationKind: + hash_combine(digest, hash(info.continuation)); + return digest; case HeapTypeInfo::StructKind: hash_combine(digest, hash(info.struct_)); return digest; @@ -2029,6 +2095,14 @@ size_t RecGroupHasher::hash(const Signature& sig) const { return digest; } +size_t RecGroupHasher::hash(const Continuation& continuation) const { + // We throw in a magic constant to distinguish (cont $foo) from $foo + size_t magic = 0xc0117; + size_t digest = hash(continuation.type); + rehash(digest, magic); + return digest; +} + size_t RecGroupHasher::hash(const Struct& struct_) const { size_t digest = wasm::hash(struct_.fields.size()); for (const auto& field : struct_.fields) { @@ -2124,6 +2198,8 @@ bool RecGroupEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) const { switch (a.kind) { case HeapTypeInfo::SignatureKind: return eq(a.signature, b.signature); + case HeapTypeInfo::ContinuationKind: + return eq(a.continuation, b.continuation); case HeapTypeInfo::StructKind: return eq(a.struct_, b.struct_); case HeapTypeInfo::ArrayKind: @@ -2148,6 +2224,10 @@ bool RecGroupEquator::eq(const Signature& a, const Signature& b) const { return eq(a.params, b.params) && eq(a.results, b.results); } +bool RecGroupEquator::eq(const Continuation& a, const Continuation& b) const { + return eq(a.type, b.type); +} + bool RecGroupEquator::eq(const Struct& a, const Struct& b) const { return std::equal(a.fields.begin(), a.fields.end(), @@ -2234,6 +2314,9 @@ void TypeGraphWalkerBase<Self>::scanHeapType(HeapType* ht) { taskList.push_back(Task::scan(&info->signature.results)); taskList.push_back(Task::scan(&info->signature.params)); break; + case HeapTypeInfo::ContinuationKind: + taskList.push_back(Task::scan(&info->continuation.type)); + break; case HeapTypeInfo::StructKind: { auto& fields = info->struct_.fields; for (auto field = fields.rbegin(); field != fields.rend(); ++field) { @@ -2274,6 +2357,9 @@ struct TypeBuilder::Impl { case HeapTypeInfo::SignatureKind: info->signature = hti.signature; break; + case HeapTypeInfo::ContinuationKind: + info->continuation = hti.continuation; + break; case HeapTypeInfo::StructKind: info->struct_ = std::move(hti.struct_); break; @@ -2312,6 +2398,11 @@ void TypeBuilder::setHeapType(size_t i, Signature signature) { impl->entries[i].set(signature); } +void TypeBuilder::setHeapType(size_t i, Continuation continuation) { + assert(i < size() && "index out of bounds"); + impl->entries[i].set(continuation); +} + void TypeBuilder::setHeapType(size_t i, const Struct& struct_) { assert(i < size() && "index out of bounds"); impl->entries[i].set(struct_); @@ -2389,6 +2480,8 @@ bool isValidSupertype(const HeapTypeInfo& sub, const HeapTypeInfo& super) { switch (sub.kind) { case HeapTypeInfo::SignatureKind: return typer.isSubType(sub.signature, super.signature); + case HeapTypeInfo::ContinuationKind: + return typer.isSubType(sub.continuation, super.continuation); case HeapTypeInfo::StructKind: return typer.isSubType(sub.struct_, super.struct_); case HeapTypeInfo::ArrayKind: @@ -2426,7 +2519,12 @@ void updateReferencedHeapTypes( void scanHeapType(HeapType* type) { if (isTopLevel) { + isTopLevel = false; TypeGraphWalkerBase<ChildUpdater>::scanHeapType(type); + } else { + if (auto it = canonicalized.find(*type); it != canonicalized.end()) { + *type = it->second; + } } } }; @@ -2686,6 +2784,15 @@ size_t hash<wasm::Signature>::operator()(const wasm::Signature& sig) const { return digest; } +size_t +hash<wasm::Continuation>::operator()(const wasm::Continuation& cont) const { + // We throw in a magic constant to distinguish (cont $foo) from $foo + auto magic = 0xc0117; + auto digest = wasm::hash(cont.type); + wasm::rehash(digest, magic); + return digest; +} + size_t hash<wasm::Field>::operator()(const wasm::Field& field) const { auto digest = wasm::hash(field.type); wasm::rehash(digest, field.packedType); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index e5f3deb33..fef613cd2 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -60,6 +60,7 @@ Name MODULE("module"); Name START("start"); Name GLOBAL("global"); Name FUNC("func"); +Name CONT("cont"); Name PARAM("param"); Name RESULT("result"); Name MEMORY("memory"); |