summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp12
-rw-r--r--src/wasm/wasm-s-parser.cpp16
-rw-r--r--src/wasm/wasm-stack.cpp10
3 files changed, 33 insertions, 5 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 996ee8cf6..0bad4d5ef 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -6904,12 +6904,22 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) {
}
bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
- if (code == BinaryConsts::RefCastStatic ||
+ if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCast ||
code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) {
bool legacy =
code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCastNop;
auto intendedType = legacy ? getIndexedHeapType() : getHeapType();
auto* ref = popNonVoidExpression();
+ // Even though we're parsing new instructions, we only support those that
+ // emulate the legacy polymorphic behavior for now.
+ if (ref->type.isRef()) {
+ if (code == BinaryConsts::RefCast && ref->type.isNullable()) {
+ throwError("ref.cast on nullable input not yet supported");
+ } else if (code == BinaryConsts::RefCastNull &&
+ ref->type.isNonNullable()) {
+ throwError("ref.cast null on non-nullable input not yet supported");
+ }
+ }
auto safety =
code == BinaryConsts::RefCastNop ? RefCast::Unsafe : RefCast::Safe;
out = Builder(wasm).makeRefCast(ref, intendedType, safety);
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 507cf3b6c..98f7c1e87 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2783,13 +2783,25 @@ Expression* SExpressionWasmBuilder::makeRefTest(Element& s) {
Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
int i = 1;
+ std::optional<Nullability> nullability;
if (s[0]->str().str != "ref.cast_static") {
- if (s[i++]->str().str != "null") {
- throw ParseException("ref.cast not yet supported. Use ref.cast null.");
+ nullability = NonNullable;
+ if (s[i]->str().str == "null") {
+ nullability = Nullable;
+ ++i;
}
}
auto heapType = parseHeapType(*s[i++]);
auto* ref = parseExpression(*s[i++]);
+ if (nullability && ref->type.isRef()) {
+ if (*nullability == NonNullable && ref->type.isNullable()) {
+ throw ParseException(
+ "ref.cast on nullable input not yet supported", s.line, s.col);
+ } else if (*nullability == Nullable && ref->type.isNonNullable()) {
+ throw ParseException(
+ "ref.cast null on non-nullable input not yet supported", s.line, s.col);
+ }
+ }
return Builder(wasm).makeRefCast(ref, heapType, RefCast::Safe);
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index c4b9598c7..db40a5980 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2033,10 +2033,16 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) {
o << int8_t(BinaryConsts::GCPrefix);
if (curr->safety == RefCast::Unsafe) {
o << U32LEB(BinaryConsts::RefCastNop);
+ parent.writeIndexedHeapType(curr->intendedType);
} else {
- o << U32LEB(BinaryConsts::RefCastNull);
+ // Emulate legacy polymorphic behavior for now.
+ if (curr->ref->type.isNullable()) {
+ o << U32LEB(BinaryConsts::RefCastNull);
+ } else {
+ o << U32LEB(BinaryConsts::RefCast);
+ }
+ parent.writeHeapType(curr->intendedType);
}
- parent.writeHeapType(curr->intendedType);
}
void BinaryInstWriter::visitBrOn(BrOn* curr) {