summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp42
-rw-r--r--src/wasm/wasm-binary.cpp12
-rw-r--r--src/wasm/wasm-s-parser.cpp6
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-type.cpp32
-rw-r--r--src/wasm/wasm-validator.cpp4
6 files changed, 86 insertions, 16 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 39a4cea3c..4a89b5cd1 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -70,7 +70,10 @@ Literal::Literal(const Literal& other) : type(other.type) {
break;
case Type::externref:
case Type::anyref:
+ case Type::eqref:
break; // null
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::funcref:
case Type::exnref:
case Type::unreachable:
@@ -223,10 +226,11 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
- if (isNull()) {
- break;
- }
- // falls through
+ case Type::eqref:
+ assert(isNull() && "unexpected non-null reference type literal");
+ break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -379,6 +383,10 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
o << "funcref(" << literal.getFunc() << ")";
}
break;
+ case Type::externref:
+ assert(literal.isNull() && "unexpected non-null externref literal");
+ o << "externref(null)";
+ break;
case Type::exnref:
if (literal.isNull()) {
o << "exnref(null)";
@@ -387,13 +395,15 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
}
break;
case Type::anyref:
- assert(literal.isNull() && "TODO: non-null anyref values");
+ assert(literal.isNull() && "unexpected non-null anyref literal");
o << "anyref(null)";
break;
- case Type::externref:
- assert(literal.isNull() && "TODO: non-null externref values");
- o << "externref(null)";
+ case Type::eqref:
+ assert(literal.isNull() && "unexpected non-null eqref literal");
+ o << "eqref(null)";
break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
}
@@ -619,6 +629,8 @@ Literal Literal::eqz() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -641,6 +653,8 @@ Literal Literal::neg() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -663,6 +677,8 @@ Literal Literal::abs() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -768,6 +784,8 @@ Literal Literal::add(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -790,6 +808,8 @@ Literal Literal::sub(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -908,6 +928,8 @@ Literal Literal::mul(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1154,6 +1176,8 @@ Literal Literal::eq(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1176,6 +1200,8 @@ Literal Literal::ne(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 18a66fb2c..a6299c892 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1206,10 +1206,14 @@ Type WasmBinaryBuilder::getType() {
return Type::exnref;
case BinaryConsts::EncodedType::anyref:
return Type::anyref;
+ case BinaryConsts::EncodedType::eqref:
+ return Type::eqref;
+ case BinaryConsts::EncodedType::i31ref:
+ return Type::i31ref;
default:
throwError("invalid wasm type: " + std::to_string(type));
}
- WASM_UNREACHABLE("unexpeced type");
+ WASM_UNREACHABLE("unexpected type");
}
HeapType WasmBinaryBuilder::getHeapType() {
@@ -1230,10 +1234,14 @@ HeapType WasmBinaryBuilder::getHeapType() {
return HeapType::ExnKind;
case BinaryConsts::EncodedHeapType::any:
return HeapType::AnyKind;
+ case BinaryConsts::EncodedHeapType::eq:
+ return HeapType::EqKind;
+ case BinaryConsts::EncodedHeapType::i31:
+ return HeapType::I31Kind;
default:
throwError("invalid wasm heap type: " + std::to_string(type));
}
- WASM_UNREACHABLE("unexpeced type");
+ WASM_UNREACHABLE("unexpected type");
}
Type WasmBinaryBuilder::getConcreteType() {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 8bbcc9ac0..2aa60979f 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -875,6 +875,12 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) {
return Type::anyref;
}
+ if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) {
+ return Type::eqref;
+ }
+ if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) {
+ return Type::i31ref;
+ }
if (allowError) {
return Type::none;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 30816546a..66f9e02dd 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -192,6 +192,8 @@ void BinaryInstWriter::visitLoad(Load* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -294,6 +296,8 @@ void BinaryInstWriter::visitStore(Store* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -697,6 +701,8 @@ void BinaryInstWriter::visitConst(Const* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index d88b7b027..cf68d92e9 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -260,9 +260,10 @@ std::unordered_map<TypeInfo, uintptr_t> indices = {
{TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref},
{TypeInfo({Type::anyref}), Type::anyref},
{TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref},
- // TODO (GC): Add canonical ids
- // * `(ref null eq) == eqref`
- // * `(ref i31) == i31ref`
+ {TypeInfo({Type::eqref}), Type::eqref},
+ {TypeInfo(HeapType(HeapType::EqKind), true), Type::eqref},
+ {TypeInfo({Type::i31ref}), Type::i31ref},
+ {TypeInfo(HeapType(HeapType::I31Kind), false), Type::i31ref},
};
} // anonymous namespace
@@ -341,7 +342,7 @@ bool Type::isTuple() const {
bool Type::isRef() const {
if (isBasic()) {
- return id >= funcref && id <= anyref;
+ return id >= funcref && id <= i31ref;
} else {
return getTypeInfo(*this)->isRef();
}
@@ -367,7 +368,7 @@ bool Type::isException() const {
bool Type::isNullable() const {
if (isBasic()) {
- return id >= funcref && id <= anyref;
+ return id >= funcref && id <= eqref; // except i31ref
} else {
return getTypeInfo(*this)->isNullable();
}
@@ -409,6 +410,8 @@ unsigned Type::getByteSize() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
break;
@@ -454,6 +457,8 @@ FeatureSet Type::getFeatures() const {
case Type::exnref:
return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling;
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
return FeatureSet::ReferenceTypes | FeatureSet::GC;
default:
return FeatureSet::MVP;
@@ -484,6 +489,10 @@ HeapType Type::getHeapType() const {
return HeapType::ExnKind;
case anyref:
return HeapType::AnyKind;
+ case eqref:
+ return HeapType::EqKind;
+ case i31ref:
+ return HeapType::I31Kind;
default:
break;
}
@@ -512,7 +521,8 @@ bool Type::isSubType(Type left, Type right) {
return true;
}
if (left.isRef() && right.isRef()) {
- return right == Type::anyref;
+ return right == Type::anyref ||
+ (left == Type::i31ref && right == Type::eqref);
}
if (left.isTuple() && right.isTuple()) {
if (left.size() != right.size()) {
@@ -543,6 +553,10 @@ Type Type::getLeastUpperBound(Type a, Type b) {
}
if (a.isRef()) {
if (b.isRef()) {
+ if ((a == Type::i31ref && b == Type::eqref) ||
+ (a == Type::eqref && b == Type::i31ref)) {
+ return Type::eqref;
+ }
// The LUB of two different reference types is anyref, which may or may
// not be a valid type depending on whether the anyref feature is enabled.
// When anyref is disabled, it is possible for the finalization of invalid
@@ -754,6 +768,12 @@ std::ostream& operator<<(std::ostream& os, Type type) {
case Type::anyref:
os << "anyref";
break;
+ case Type::eqref:
+ os << "eqref";
+ break;
+ case Type::i31ref:
+ os << "i31ref";
+ break;
}
} else {
os << *getTypeInfo(type);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 505753c88..16ba60d72 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1396,6 +1396,8 @@ void FunctionValidator::validateMemBytes(uint8_t bytes,
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -2204,6 +2206,8 @@ void FunctionValidator::validateAlignment(
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("invalid type");
}