diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 3 | ||||
-rw-r--r-- | src/binaryen-c.h | 3 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 12 | ||||
-rw-r--r-- | src/ir/gc-type-utils.h | 22 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 12 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 28 | ||||
-rw-r--r-- | src/passes/Print.cpp | 26 | ||||
-rw-r--r-- | src/wasm-binary.h | 1 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 21 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 4 | ||||
-rw-r--r-- | src/wasm.h | 3 | ||||
-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 |
16 files changed, 91 insertions, 145 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 416c8d45b..e37270f61 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1009,9 +1009,6 @@ BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void) { } BinaryenOp BinaryenSwizzleVecI8x16(void) { return SwizzleVecI8x16; } BinaryenOp BinaryenRefAsNonNull(void) { return RefAsNonNull; } -BinaryenOp BinaryenRefAsFunc(void) { return RefAsFunc; } -BinaryenOp BinaryenRefAsData(void) { return RefAsData; } -BinaryenOp BinaryenRefAsI31(void) { return RefAsI31; } BinaryenOp BinaryenRefAsExternInternalize(void) { return ExternInternalize; } BinaryenOp BinaryenRefAsExternExternalize(void) { return ExternExternalize; } BinaryenOp BinaryenBrOnNull(void) { return BrOnNull; } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 2c861a141..b9f78e2a7 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -671,9 +671,6 @@ BINARYEN_API BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void); BINARYEN_API BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void); BINARYEN_API BinaryenOp BinaryenSwizzleVecI8x16(void); BINARYEN_API BinaryenOp BinaryenRefAsNonNull(void); -BINARYEN_API BinaryenOp BinaryenRefAsFunc(void); -BINARYEN_API BinaryenOp BinaryenRefAsData(void); -BINARYEN_API BinaryenOp BinaryenRefAsI31(void); BINARYEN_API BinaryenOp BinaryenRefAsExternInternalize(void); BINARYEN_API BinaryenOp BinaryenRefAsExternExternalize(void); BINARYEN_API BinaryenOp BinaryenBrOnNull(void); diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 70644827c..dbf3b71bf 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -3000,13 +3000,13 @@ switch (buf[0]) { case 'a': { switch (buf[7]) { case 'd': - if (op == "ref.as_data"sv) { return makeRefAs(s, RefAsData); } + if (op == "ref.as_data"sv) { return makeRefCast(s, Type(HeapType::data, NonNullable)); } goto parse_error; case 'f': - if (op == "ref.as_func"sv) { return makeRefAs(s, RefAsFunc); } + if (op == "ref.as_func"sv) { return makeRefCast(s, Type(HeapType::func, NonNullable)); } goto parse_error; case 'i': - if (op == "ref.as_i31"sv) { return makeRefAs(s, RefAsI31); } + if (op == "ref.as_i31"sv) { return makeRefCast(s, Type(HeapType::i31, NonNullable)); } goto parse_error; case 'n': if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); } @@ -8599,21 +8599,21 @@ switch (buf[0]) { switch (buf[7]) { case 'd': if (op == "ref.as_data"sv) { - auto ret = makeRefAs(ctx, pos, RefAsData); + auto ret = makeRefCast(ctx, pos, Type(HeapType::data, NonNullable)); CHECK_ERR(ret); return *ret; } goto parse_error; case 'f': if (op == "ref.as_func"sv) { - auto ret = makeRefAs(ctx, pos, RefAsFunc); + auto ret = makeRefCast(ctx, pos, Type(HeapType::func, NonNullable)); CHECK_ERR(ret); return *ret; } goto parse_error; case 'i': if (op == "ref.as_i31"sv) { - auto ret = makeRefAs(ctx, pos, RefAsI31); + auto ret = makeRefCast(ctx, pos, Type(HeapType::i31, NonNullable)); CHECK_ERR(ret); return *ret; } diff --git a/src/ir/gc-type-utils.h b/src/ir/gc-type-utils.h index c8f2b26af..318b1b3a3 100644 --- a/src/ir/gc-type-utils.h +++ b/src/ir/gc-type-utils.h @@ -119,28 +119,6 @@ inline EvaluationResult evaluateKindCheck(Expression* curr) { WASM_UNREACHABLE("unhandled BrOn"); } child = br->ref; - } else if (auto* as = curr->dynCast<RefAs>()) { - switch (as->op) { - // We don't check nullability here. - case RefAsNonNull: - return Unknown; - case RefAsFunc: - expected = Func; - break; - case RefAsData: - expected = Data; - break; - case RefAsI31: - expected = I31; - break; - case ExternInternalize: - case ExternExternalize: - // These instructions can never be removed. - return Unknown; - default: - WASM_UNREACHABLE("unhandled RefAs"); - } - child = as->value; } else { WASM_UNREACHABLE("invalid input to evaluateKindCheck"); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 2a08c5e5a..da121e23a 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -550,9 +550,6 @@ function initializeConstants() { 'PromoteLowVecF32x4ToVecF64x2', 'SwizzleVecI8x16', 'RefAsNonNull', - 'RefAsFunc', - 'RefAsData', - 'RefAsI31', 'RefAsExternInternalize', 'RefAsExternExternalize', 'BrOnNull', @@ -2345,15 +2342,6 @@ function wrapModule(module, self = {}) { 'as_non_null'(value) { return Module['_BinaryenRefAs'](module, Module['RefAsNonNull'], value); }, - 'as_func'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsFunc'], value); - }, - 'as_data'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsData'], value); - }, - 'as_i31'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsI31'], value); - }, 'func'(func, type) { return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func), type)); }, diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 884afcdd4..e8c6dc1fe 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2118,35 +2118,13 @@ struct OptimizeInstructions if (curr->op == ExternExternalize || curr->op == ExternInternalize) { // We can't optimize these. Even removing a non-null cast is not valid as - // they allow nulls to filter through, unlike other RefAs* + // they allow nulls to filter through, unlike other RefAs*. return; } + assert(curr->op == RefAsNonNull); skipNonNullCast(curr->value); - - // Check if the type is the kind we are checking for. - auto result = GCTypeUtils::evaluateKindCheck(curr); - - if (result == GCTypeUtils::Success) { - // We know the kind is correct, so all that is left is a check for - // non-nullability, which we do lower down. - curr->op = RefAsNonNull; - } else if (result == GCTypeUtils::Failure) { - // This is the wrong kind, so it will trap. The binaryen optimizer does - // not differentiate traps, so we can perform a replacement here. We - // replace 2 bytes of ref.as_* with one byte of unreachable and one of a - // drop, which is no worse, and the value and the drop can be optimized - // out later if the value has no side effects. - Builder builder(*getModule()); - // Make sure to emit a block with the same type as us; leave updating - // types for other passes. - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->value), builder.makeUnreachable()}, - curr->type)); - return; - } - - if (curr->op == RefAsNonNull && !curr->value->type.isNullable()) { + if (!curr->value->type.isNullable()) { replaceCurrent(curr->value); return; } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 12c185e69..e0d9a46a3 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2122,6 +2122,23 @@ struct PrintExpressionContents if (curr->safety == RefCast::Unsafe) { printMedium(o, "ref.cast_nop "); } 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: + printMedium(o, "ref.as_func"); + return; + case HeapType::data: + printMedium(o, "ref.as_data"); + return; + case HeapType::i31: + printMedium(o, "ref.as_i31"); + return; + default: + break; + } + } if (curr->type.isNullable()) { printMedium(o, "ref.cast null "); } else { @@ -2329,15 +2346,6 @@ struct PrintExpressionContents case RefAsNonNull: printMedium(o, "ref.as_non_null"); break; - case RefAsFunc: - printMedium(o, "ref.as_func"); - break; - case RefAsData: - printMedium(o, "ref.as_data"); - break; - case RefAsI31: - printMedium(o, "ref.as_i31"); - break; case ExternInternalize: printMedium(o, "extern.internalize"); break; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1a3e5c82b..b2e1ef0c6 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1748,6 +1748,7 @@ public: void visitThrow(Throw* curr); void visitRethrow(Rethrow* curr); void visitCallRef(CallRef* curr); + void visitRefAsCast(RefCast* curr, uint32_t code); void visitRefAs(RefAs* curr, uint8_t code); [[noreturn]] void throwError(std::string text); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 104f06585..43b001f35 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1787,29 +1787,12 @@ public: switch (curr->op) { case RefAsNonNull: // We've already checked for a null. - break; - case RefAsFunc: - if (!value.type.isFunction()) { - trap("not a func"); - } - break; - case RefAsData: - if (!value.isData()) { - trap("not a data"); - } - break; - case RefAsI31: - if (value.type.getHeapType() != HeapType::i31) { - trap("not an i31"); - } - break; + return value; case ExternInternalize: case ExternExternalize: WASM_UNREACHABLE("unimplemented extern conversion"); - default: - WASM_UNREACHABLE("unimplemented ref.as_*"); } - return value; + WASM_UNREACHABLE("unimplemented ref.as_*"); } Flow visitStringNew(StringNew* curr) { WASM_UNREACHABLE("unimp"); } Flow visitStringConst(StringConst* curr) { WASM_UNREACHABLE("unimp"); } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 6ae3e57be..013730c52 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -285,7 +285,8 @@ private: Expression* makeI31Get(Element& s, bool signed_); Expression* makeRefTest(Element& s, std::optional<Type> castType = std::nullopt); - Expression* makeRefCast(Element& s); + Expression* makeRefCast(Element& s, + std::optional<Type> castType = std::nullopt); Expression* makeRefCastNop(Element& s); Expression* makeBrOnNull(Element& s, bool onFail = false); Expression* @@ -302,6 +303,7 @@ private: Expression* makeArrayLen(Element& s); Expression* makeArrayCopy(Element& s); Expression* makeRefAs(Element& s, RefAsOp op); + Expression* makeRefAsNonNull(Element& s); Expression* makeStringNew(Element& s, StringNewOp op); Expression* makeStringConst(Element& s); Expression* makeStringMeasure(Element& s, StringMeasureOp op); diff --git a/src/wasm.h b/src/wasm.h index 7b75ec3b8..f7683e6bb 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -559,9 +559,6 @@ enum SIMDTernaryOp { enum RefAsOp { RefAsNonNull, - RefAsFunc, - RefAsData, - RefAsI31, ExternInternalize, ExternExternalize, }; 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"); } |