summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp5
-rw-r--r--src/wasm/wasm-binary.cpp12
-rw-r--r--src/wasm/wasm-s-parser.cpp8
-rw-r--r--src/wasm/wasm-type.cpp62
-rw-r--r--src/wasm/wasm-validator.cpp8
-rw-r--r--src/wasm/wat-parser.cpp2
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; }