summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-01-10 13:53:12 -0600
committerGitHub <noreply@github.com>2023-01-10 11:53:12 -0800
commit36e2abbcdd22b2b1707757b49fb4ac8844f28e5d (patch)
treef869cebf2c8d772f8f85db83f39aadfd6ac6f7cb /src/wasm
parente6efd7b991a9c55115771ea121b0eff2bace7d3e (diff)
downloadbinaryen-36e2abbcdd22b2b1707757b49fb4ac8844f28e5d.tar.gz
binaryen-36e2abbcdd22b2b1707757b49fb4ac8844f28e5d.tar.bz2
binaryen-36e2abbcdd22b2b1707757b49fb4ac8844f28e5d.zip
Represent ref.as_{func,data,i31} with RefCast (#5413)
These operations are deprecated and directly representable as casts, so remove their opcodes in the internal IR and parse them as casts instead. For now, add logic to the printing and binary writing of RefCast to continue emitting the legacy instructions to minimize test changes. The few test changes necessary are because it is no longer valid to perform a ref.as_func on values outside the func type hierarchy now that ref.as_func is subject to the ref.cast validation rules. RefAsExternInternalize, RefAsExternExternalize, and RefAsNonNull are left unmodified. A future PR may remove RefAsNonNull as well, since it is also expressible with casts.
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp37
-rw-r--r--src/wasm/wasm-s-parser.cpp22
-rw-r--r--src/wasm/wasm-stack.cpp26
-rw-r--r--src/wasm/wasm.cpp9
-rw-r--r--src/wasm/wat-parser.cpp7
5 files changed, 59 insertions, 42 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b1f4b8907..767e0c2ab 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -4032,8 +4032,12 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
}
if (opcode == BinaryConsts::RefAsFunc ||
opcode == BinaryConsts::RefAsData ||
- opcode == BinaryConsts::RefAsI31 ||
- opcode == BinaryConsts::ExternInternalize ||
+ opcode == BinaryConsts::RefAsI31) {
+ visitRefAsCast((curr = allocator.alloc<RefCast>())->cast<RefCast>(),
+ opcode);
+ break;
+ }
+ if (opcode == BinaryConsts::ExternInternalize ||
opcode == BinaryConsts::ExternExternalize) {
visitRefAs((curr = allocator.alloc<RefAs>())->cast<RefAs>(), opcode);
break;
@@ -6910,6 +6914,26 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) {
return false;
}
+void WasmBinaryBuilder::visitRefAsCast(RefCast* curr, uint32_t code) {
+ // TODO: These instructions are deprecated. Remove them.
+ switch (code) {
+ case BinaryConsts::RefAsFunc:
+ curr->type = Type(HeapType::func, NonNullable);
+ break;
+ case BinaryConsts::RefAsData:
+ curr->type = Type(HeapType::data, NonNullable);
+ break;
+ case BinaryConsts::RefAsI31:
+ curr->type = Type(HeapType::i31, NonNullable);
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected ref.as*");
+ }
+ curr->ref = popNonVoidExpression();
+ curr->safety = RefCast::Safe;
+ curr->finalize();
+}
+
bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCast ||
code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) {
@@ -7439,15 +7463,6 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
case BinaryConsts::RefAsNonNull:
curr->op = RefAsNonNull;
break;
- case BinaryConsts::RefAsFunc:
- curr->op = RefAsFunc;
- break;
- case BinaryConsts::RefAsData:
- curr->op = RefAsData;
- break;
- case BinaryConsts::RefAsI31:
- curr->op = RefAsI31;
- break;
case BinaryConsts::ExternInternalize:
curr->op = ExternInternalize;
break;
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 4f725d48b..03dba223b 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2790,27 +2790,27 @@ Expression* SExpressionWasmBuilder::makeRefTest(Element& s,
return Builder(wasm).makeRefTest(ref, *castType);
}
-Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
+Expression* SExpressionWasmBuilder::makeRefCast(Element& s,
+ std::optional<Type> castType) {
int i = 1;
- Nullability nullability;
bool legacy = false;
- if (s[0]->str().str == "ref.cast_static") {
- legacy = true;
- } else {
- nullability = NonNullable;
- if (s[i]->str().str == "null") {
+ if (!castType) {
+ Nullability nullability = NonNullable;
+ if (s[0]->str().str == "ref.cast_static") {
+ legacy = true;
+ } else if (s[i]->str().str == "null") {
nullability = Nullable;
++i;
}
+ auto type = parseHeapType(*s[i++]);
+ castType = Type(type, nullability);
}
- auto heapType = parseHeapType(*s[i++]);
auto* ref = parseExpression(*s[i++]);
if (legacy) {
// Legacy polymorphic behavior.
- nullability = ref->type.getNullability();
+ castType = Type(castType->getHeapType(), ref->type.getNullability());
}
- auto type = Type(heapType, nullability);
- return Builder(wasm).makeRefCast(ref, type, RefCast::Safe);
+ return Builder(wasm).makeRefCast(ref, *castType, RefCast::Safe);
}
Expression* SExpressionWasmBuilder::makeRefCastNop(Element& s) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 82c7c511f..c4e1a863c 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2041,6 +2041,23 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) {
o << U32LEB(BinaryConsts::RefCastNop);
parent.writeIndexedHeapType(curr->type.getHeapType());
} else {
+ // TODO: These instructions are deprecated. Remove them.
+ if (auto type = curr->type.getHeapType();
+ type.isBasic() && curr->type.isNonNullable()) {
+ switch (type.getBasic()) {
+ case HeapType::func:
+ o << U32LEB(BinaryConsts::RefAsFunc);
+ return;
+ case HeapType::data:
+ o << U32LEB(BinaryConsts::RefAsData);
+ return;
+ case HeapType::i31:
+ o << U32LEB(BinaryConsts::RefAsI31);
+ return;
+ default:
+ break;
+ }
+ }
if (curr->type.isNullable()) {
o << U32LEB(BinaryConsts::RefCastNull);
} else {
@@ -2244,15 +2261,6 @@ void BinaryInstWriter::visitRefAs(RefAs* curr) {
case RefAsNonNull:
o << int8_t(BinaryConsts::RefAsNonNull);
break;
- case RefAsFunc:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsFunc);
- break;
- case RefAsData:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsData);
- break;
- case RefAsI31:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsI31);
- break;
case ExternInternalize:
o << int8_t(BinaryConsts::GCPrefix)
<< U32LEB(BinaryConsts::ExternInternalize);
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index c121ba89a..4a72f6ea6 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1115,15 +1115,6 @@ void RefAs::finalize() {
case RefAsNonNull:
type = Type(value->type.getHeapType(), NonNullable);
break;
- case RefAsFunc:
- type = Type(HeapType::func, NonNullable);
- break;
- case RefAsData:
- type = Type(HeapType::data, NonNullable);
- break;
- case RefAsI31:
- type = Type(HeapType::i31, NonNullable);
- break;
case ExternInternalize:
type = Type(HeapType::any, value->type.getNullability());
break;
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 08eec41c6..c2d06ae90 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -2346,7 +2346,9 @@ Result<typename Ctx::InstrT> makeI31Get(Ctx&, Index, bool signed_);
template<typename Ctx>
Result<typename Ctx::InstrT>
makeRefTest(Ctx&, Index, std::optional<Type> castType = std::nullopt);
-template<typename Ctx> Result<typename Ctx::InstrT> makeRefCast(Ctx&, Index);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeRefCast(Ctx&, Index, std::optional<Type> castType = std::nullopt);
template<typename Ctx> Result<typename Ctx::InstrT> makeRefCastNop(Ctx&, Index);
template<typename Ctx>
Result<typename Ctx::InstrT> makeBrOnNull(Ctx&, Index, bool onFail = false);
@@ -3444,7 +3446,8 @@ makeRefTest(Ctx& ctx, Index pos, std::optional<Type> castType) {
}
template<typename Ctx>
-Result<typename Ctx::InstrT> makeRefCast(Ctx& ctx, Index pos) {
+Result<typename Ctx::InstrT>
+makeRefCast(Ctx& ctx, Index pos, std::optional<Type> castType) {
return ctx.in.err("unimplemented instruction");
}