diff options
author | Thomas Lively <tlively@google.com> | 2023-01-10 13:53:12 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-10 11:53:12 -0800 |
commit | 36e2abbcdd22b2b1707757b49fb4ac8844f28e5d (patch) | |
tree | f869cebf2c8d772f8f85db83f39aadfd6ac6f7cb /src/wasm | |
parent | e6efd7b991a9c55115771ea121b0eff2bace7d3e (diff) | |
download | binaryen-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.cpp | 37 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 22 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 26 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 9 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 7 |
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"); } |