diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 5 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 62 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 2 |
6 files changed, 65 insertions, 32 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 05f9d93d5..684108581 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -101,6 +101,7 @@ Literal::Literal(const Literal& other) : type(other.type) { auto heapType = type.getHeapType(); if (heapType.isBasic()) { switch (heapType.getBasic()) { + case HeapType::ext: case HeapType::any: case HeapType::eq: return; // null @@ -464,6 +465,10 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { } } else { switch (literal.type.getHeapType().getBasic()) { + case HeapType::ext: + assert(literal.isNull() && "unexpected non-null externref literal"); + o << "externref(null)"; + break; case HeapType::any: assert(literal.isNull() && "unexpected non-null anyref literal"); o << "anyref(null)"; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 7008d185c..fe827f291 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1368,6 +1368,9 @@ void WasmBinaryWriter::writeType(Type type) { auto heapType = type.getHeapType(); if (heapType.isBasic() && type.isNullable()) { switch (heapType.getBasic()) { + case HeapType::ext: + o << S32LEB(BinaryConsts::EncodedType::externref); + return; case HeapType::any: o << S32LEB(BinaryConsts::EncodedType::anyref); return; @@ -1443,6 +1446,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { int ret = 0; if (type.isBasic()) { switch (type.getBasic()) { + case HeapType::ext: + ret = BinaryConsts::EncodedHeapType::ext; + break; case HeapType::func: ret = BinaryConsts::EncodedHeapType::func; break; @@ -1805,6 +1811,9 @@ bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) { case BinaryConsts::EncodedType::funcref: out = Type(HeapType::func, Nullable); return true; + case BinaryConsts::EncodedType::externref: + out = Type(HeapType::ext, Nullable); + return true; case BinaryConsts::EncodedType::anyref: out = Type(HeapType::any, Nullable); return true; @@ -1839,6 +1848,9 @@ bool WasmBinaryBuilder::getBasicHeapType(int64_t code, HeapType& out) { case BinaryConsts::EncodedHeapType::func: out = HeapType::func; return true; + case BinaryConsts::EncodedHeapType::ext: + out = HeapType::ext; + return true; case BinaryConsts::EncodedHeapType::any: out = HeapType::any; return true; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 55551ef58..86d7b27e9 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1169,8 +1169,10 @@ Type SExpressionWasmBuilder::stringToType(const char* str, if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) { return Type(HeapType::func, Nullable); } - if ((strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) || - (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0))) { + if (strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) { + return Type(HeapType::ext, Nullable); + } + if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) { return Type(HeapType::any, Nullable); } if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { @@ -1214,7 +1216,7 @@ HeapType SExpressionWasmBuilder::stringToHeapType(const char* str, } if (str[1] == 'x' && str[2] == 't' && str[3] == 'e' && str[4] == 'r' && str[5] == 'n' && (prefix || str[6] == 0)) { - return HeapType::any; + return HeapType::ext; } } if (str[0] == 'a') { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 23d2877f7..f9ccea9f6 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -172,7 +172,7 @@ struct TypeBounder { bool hasLeastUpperBound(Type a, Type b); Type getLeastUpperBound(Type a, Type b); - HeapType getLeastUpperBound(HeapType a, HeapType b); + std::optional<HeapType> getLeastUpperBound(HeapType a, HeapType b); private: // Return the LUB iff a LUB was found. The HeapType and Struct overloads are @@ -181,7 +181,7 @@ private: // Note that these methods can return temporary types, so they should never be // used directly. std::optional<Type> lub(Type a, Type b); - HeapType lub(HeapType a, HeapType b); + std::optional<HeapType> lub(HeapType a, HeapType b); std::optional<Tuple> lub(const Tuple& a, const Tuple& b); std::optional<Field> lub(const Field& a, const Field& b); std::optional<Signature> lub(const Signature& a, const Signature& b); @@ -573,8 +573,8 @@ HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { WASM_UNREACHABLE("unexpected kind"); }; -HeapType getBasicHeapTypeLUB(HeapType::BasicHeapType a, - HeapType::BasicHeapType b) { +std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a, + HeapType::BasicHeapType b) { if (a == b) { return a; } @@ -583,25 +583,27 @@ HeapType getBasicHeapTypeLUB(HeapType::BasicHeapType a, std::swap(a, b); } switch (a) { + case HeapType::ext: + return {}; case HeapType::func: case HeapType::any: - return HeapType::any; + return {HeapType::any}; case HeapType::eq: if (b == HeapType::i31 || b == HeapType::data) { - return HeapType::eq; + return {HeapType::eq}; } - return HeapType::any; + return {HeapType::any}; case HeapType::i31: if (b == HeapType::data) { - return HeapType::eq; + return {HeapType::eq}; } - return HeapType::any; + return {HeapType::any}; case HeapType::data: case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: case HeapType::stringview_iter: - return HeapType::any; + return {HeapType::any}; } WASM_UNREACHABLE("unexpected basic type"); } @@ -1205,11 +1207,12 @@ Type Type::getLeastUpperBound(Type a, Type b) { return Type(elems); } if (a.isRef() && b.isRef()) { - auto nullability = - (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; - auto heapType = - HeapType::getLeastUpperBound(a.getHeapType(), b.getHeapType()); - return Type(heapType, nullability); + if (auto heapType = + HeapType::getLeastUpperBound(a.getHeapType(), b.getHeapType())) { + auto nullability = + (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; + return Type(*heapType, nullability); + } } return Type::none; WASM_UNREACHABLE("unexpected type"); @@ -1411,7 +1414,7 @@ std::vector<HeapType> HeapType::getReferencedHeapTypes() const { return types; } -HeapType HeapType::getLeastUpperBound(HeapType a, HeapType b) { +std::optional<HeapType> HeapType::getLeastUpperBound(HeapType a, HeapType b) { if (a == b) { return a; } @@ -1616,10 +1619,13 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { } if (b.isBasic()) { switch (b.getBasic()) { + case HeapType::ext: + return a == HeapType::ext; case HeapType::func: return a.isSignature(); case HeapType::any: - return true; + // TODO: exclude functions as well. + return a != HeapType::ext; case HeapType::eq: return a == HeapType::i31 || a.isData(); case HeapType::i31: @@ -1735,8 +1741,13 @@ Type TypeBounder::getLeastUpperBound(Type a, Type b) { return built.back().getArray().element.type; } -HeapType TypeBounder::getLeastUpperBound(HeapType a, HeapType b) { - HeapType l = lub(a, b); +std::optional<HeapType> TypeBounder::getLeastUpperBound(HeapType a, + HeapType b) { + auto maybeLub = lub(a, b); + if (!maybeLub) { + return std::nullopt; + } + HeapType l = *maybeLub; if (!isTemp(l)) { // The LUB is already canonical, so we're done. return l; @@ -1767,15 +1778,16 @@ std::optional<Type> TypeBounder::lub(Type a, Type b) { } return builder.getTempTupleType(*tuple); } else if (a.isRef() && b.isRef()) { - auto nullability = - (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; - HeapType heapType = lub(a.getHeapType(), b.getHeapType()); - return builder.getTempRefType(heapType, nullability); + if (auto heapType = lub(a.getHeapType(), b.getHeapType())) { + auto nullability = + (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; + return builder.getTempRefType(*heapType, nullability); + } } return {}; } -HeapType TypeBounder::lub(HeapType a, HeapType b) { +std::optional<HeapType> TypeBounder::lub(HeapType a, HeapType b) { if (a == b) { return a; } @@ -1999,6 +2011,8 @@ std::ostream& TypePrinter::print(Type type) { std::ostream& TypePrinter::print(HeapType type) { if (type.isBasic()) { switch (type.getBasic()) { + case HeapType::ext: + return os << "extern"; case HeapType::func: return os << "func"; case HeapType::any: diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 92f6c76bf..e837c2dd6 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -3099,7 +3099,7 @@ static void validateTables(Module& module, ValidationInfo& info) { } } - Type anyref = Type(HeapType::any, Nullable); + Type externref = Type(HeapType::ext, Nullable); Type funcref = Type(HeapType::func, Nullable); for (auto& table : module.tables) { info.shouldBeTrue(table->initial <= table->max, @@ -3110,15 +3110,15 @@ 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 == anyref, + info.shouldBeTrue(table->type.isFunction() || table->type == externref, "table", "Only function reference types or externref are valid " "for table type (when GC is disabled)"); } if (!module.features.hasTypedFunctionReferences()) { - info.shouldBeTrue(table->type == funcref || table->type == anyref, + info.shouldBeTrue(table->type == funcref || table->type == externref, "table", - "Only funcref and anyref are valid for table type " + "Only funcref and externref are valid for table type " "(when typed-function references are disabled)"); } } diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 89eab3297..5455c0438 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -431,7 +431,7 @@ template<typename Ctx> struct TypeParserCtx { HeapTypeT makeFunc() { return HeapType::func; } HeapTypeT makeAny() { return HeapType::any; } - HeapTypeT makeExtern() { return HeapType::any; } + HeapTypeT makeExtern() { return HeapType::ext; } HeapTypeT makeEq() { return HeapType::eq; } HeapTypeT makeI31() { return HeapType::i31; } HeapTypeT makeData() { return HeapType::data; } |