diff options
author | Thomas Lively <tlively@google.com> | 2023-08-09 17:18:13 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-09 21:18:13 +0000 |
commit | c003a01aa855bfa1377237eb2ce788b9fa96e839 (patch) | |
tree | 454d2b6de36ea56de5d3e310d81f02155aa73db1 /src | |
parent | d0bdf202463323a0b9f3be95fe2c64765a84a4b7 (diff) | |
download | binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.tar.gz binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.tar.bz2 binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.zip |
Remove legacy WasmGC instructions (#5861)
Remove old, experimental instructions and type encodings that will not be
shipped as part of WasmGC. Updating the encodings and text format to match the
final spec is left as future work.
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 3 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 342 | ||||
-rw-r--r-- | src/ir/stack-utils.h | 6 | ||||
-rw-r--r-- | src/passes/OptimizeCasts.cpp | 6 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 14 | ||||
-rw-r--r-- | src/passes/Print.cpp | 10 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 3 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 3 | ||||
-rw-r--r-- | src/wasm-binary.h | 18 | ||||
-rw-r--r-- | src/wasm-builder.h | 5 | ||||
-rw-r--r-- | src/wasm-delegations-fields.def | 1 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 10 | ||||
-rw-r--r-- | src/wasm.h | 5 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 147 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 68 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 13 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 26 |
17 files changed, 130 insertions, 550 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index dd2ad5c4a..0b7adf92a 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1768,8 +1768,7 @@ BinaryenExpressionRef BinaryenRefCast(BinaryenModuleRef module, BinaryenExpressionRef ref, BinaryenType type) { return static_cast<Expression*>( - Builder(*(Module*)module) - .makeRefCast((Expression*)ref, Type(type), RefCast::Safety::Safe)); + Builder(*(Module*)module).makeRefCast((Expression*)ref, Type(type))); } BinaryenExpressionRef BinaryenBrOn(BinaryenModuleRef module, BinaryenOp op, diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 772847f9b..ce7baadd5 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -117,52 +117,19 @@ switch (buf[0]) { case 'c': { switch (buf[10]) { case '\0': - if (op == "br_on_cast"sv) { return makeBrOnCast(s, std::nullopt); } + if (op == "br_on_cast"sv) { return makeBrOnCast(s); } + goto parse_error; + case '_': + if (op == "br_on_cast_fail"sv) { return makeBrOnCast(s, true); } goto parse_error; - case '_': { - switch (buf[11]) { - case 'f': - if (op == "br_on_cast_fail"sv) { return makeBrOnCast(s, std::nullopt, true); } - goto parse_error; - case 's': { - switch (buf[17]) { - case '\0': - if (op == "br_on_cast_static"sv) { return makeBrOnCast(s, std::nullopt); } - goto parse_error; - case '_': - if (op == "br_on_cast_static_fail"sv) { return makeBrOnCast(s, std::nullopt, true); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } default: goto parse_error; } } - case 'f': - if (op == "br_on_func"sv) { return makeBrOnCast(s, Type(HeapType::func, NonNullable)); } - goto parse_error; - case 'i': - if (op == "br_on_i31"sv) { return makeBrOnCast(s, Type(HeapType::i31, NonNullable)); } - goto parse_error; case 'n': { switch (buf[7]) { - case 'o': { - switch (buf[10]) { - case 'f': - if (op == "br_on_non_func"sv) { return makeBrOnCast(s, Type(HeapType::func, NonNullable), true); } - goto parse_error; - case 'i': - if (op == "br_on_non_i31"sv) { return makeBrOnCast(s, Type(HeapType::i31, NonNullable), true); } - goto parse_error; - case 'n': - if (op == "br_on_non_null"sv) { return makeBrOnNull(s, true); } - goto parse_error; - default: goto parse_error; - } - } + case 'o': + if (op == "br_on_non_null"sv) { return makeBrOnNull(s, true); } + goto parse_error; case 'u': if (op == "br_on_null"sv) { return makeBrOnNull(s); } goto parse_error; @@ -3008,81 +2975,27 @@ switch (buf[0]) { switch (buf[2]) { case 'f': { switch (buf[4]) { - case 'a': { - switch (buf[7]) { - case 'f': - 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 makeRefCast(s, Type(HeapType::i31, NonNullable)); } - goto parse_error; - case 'n': - if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (buf[8]) { - case '\0': - if (op == "ref.cast"sv) { return makeRefCast(s); } - goto parse_error; - case '_': { - switch (buf[9]) { - case 'n': { - switch (buf[12]) { - case '\0': - if (op == "ref.cast_nop"sv) { return makeRefCastNop(s); } - goto parse_error; - case '_': - if (op == "ref.cast_nop_static"sv) { return makeRefCastNop(s); } - goto parse_error; - default: goto parse_error; - } - } - case 's': - if (op == "ref.cast_static"sv) { return makeRefCast(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } + case 'a': + if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); } + goto parse_error; + case 'c': + if (op == "ref.cast"sv) { return makeRefCast(s); } + goto parse_error; case 'e': if (op == "ref.eq"sv) { return makeRefEq(s); } goto parse_error; case 'f': if (op == "ref.func"sv) { return makeRefFunc(s); } goto parse_error; - case 'i': { - switch (buf[7]) { - case 'f': - if (op == "ref.is_func"sv) { return makeRefTest(s, Type(HeapType::func, NonNullable)); } - goto parse_error; - case 'i': - if (op == "ref.is_i31"sv) { return makeRefTest(s, Type(HeapType::i31, NonNullable)); } - goto parse_error; - case 'n': - if (op == "ref.is_null"sv) { return makeRefIsNull(s); } - goto parse_error; - default: goto parse_error; - } - } + case 'i': + if (op == "ref.is_null"sv) { return makeRefIsNull(s); } + goto parse_error; case 'n': if (op == "ref.null"sv) { return makeRefNull(s); } goto parse_error; - case 't': { - switch (buf[8]) { - case '\0': - if (op == "ref.test"sv) { return makeRefTest(s); } - goto parse_error; - case '_': - if (op == "ref.test_static"sv) { return makeRefTest(s); } - goto parse_error; - default: goto parse_error; - } - } + case 't': + if (op == "ref.test"sv) { return makeRefTest(s); } + goto parse_error; default: goto parse_error; } } @@ -3795,87 +3708,30 @@ switch (buf[0]) { switch (buf[10]) { case '\0': if (op == "br_on_cast"sv) { - auto ret = makeBrOnCast(ctx, pos, std::nullopt); + auto ret = makeBrOnCast(ctx, pos); CHECK_ERR(ret); return *ret; } goto parse_error; - case '_': { - switch (buf[11]) { - case 'f': - if (op == "br_on_cast_fail"sv) { - auto ret = makeBrOnCast(ctx, pos, std::nullopt, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 's': { - switch (buf[17]) { - case '\0': - if (op == "br_on_cast_static"sv) { - auto ret = makeBrOnCast(ctx, pos, std::nullopt); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "br_on_cast_static_fail"sv) { - auto ret = makeBrOnCast(ctx, pos, std::nullopt, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; + case '_': + if (op == "br_on_cast_fail"sv) { + auto ret = makeBrOnCast(ctx, pos, true); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; default: goto parse_error; } } - case 'f': - if (op == "br_on_func"sv) { - auto ret = makeBrOnCast(ctx, pos, Type(HeapType::func, NonNullable)); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'i': - if (op == "br_on_i31"sv) { - auto ret = makeBrOnCast(ctx, pos, Type(HeapType::i31, NonNullable)); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; case 'n': { switch (buf[7]) { - case 'o': { - switch (buf[10]) { - case 'f': - if (op == "br_on_non_func"sv) { - auto ret = makeBrOnCast(ctx, pos, Type(HeapType::func, NonNullable), true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'i': - if (op == "br_on_non_i31"sv) { - auto ret = makeBrOnCast(ctx, pos, Type(HeapType::i31, NonNullable), true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'n': - if (op == "br_on_non_null"sv) { - auto ret = makeBrOnNull(ctx, pos, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'o': + if (op == "br_on_non_null"sv) { + auto ret = makeBrOnNull(ctx, pos, true); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; case 'u': if (op == "br_on_null"sv) { auto ret = makeBrOnNull(ctx, pos); @@ -8649,75 +8505,20 @@ switch (buf[0]) { switch (buf[2]) { case 'f': { switch (buf[4]) { - case 'a': { - switch (buf[7]) { - case 'f': - if (op == "ref.as_func"sv) { - 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 = makeRefCast(ctx, pos, Type(HeapType::i31, NonNullable)); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'n': - if (op == "ref.as_non_null"sv) { - auto ret = makeRefAs(ctx, pos, RefAsNonNull); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'a': + if (op == "ref.as_non_null"sv) { + auto ret = makeRefAs(ctx, pos, RefAsNonNull); + CHECK_ERR(ret); + return *ret; } - } - case 'c': { - switch (buf[8]) { - case '\0': - if (op == "ref.cast"sv) { - auto ret = makeRefCast(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': { - switch (buf[9]) { - case 'n': { - switch (buf[12]) { - case '\0': - if (op == "ref.cast_nop"sv) { - auto ret = makeRefCastNop(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "ref.cast_nop_static"sv) { - auto ret = makeRefCastNop(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - case 's': - if (op == "ref.cast_static"sv) { - auto ret = makeRefCast(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; + goto parse_error; + case 'c': + if (op == "ref.cast"sv) { + auto ret = makeRefCast(ctx, pos); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; case 'e': if (op == "ref.eq"sv) { auto ret = makeRefEq(ctx, pos); @@ -8732,32 +8533,13 @@ switch (buf[0]) { return *ret; } goto parse_error; - case 'i': { - switch (buf[7]) { - case 'f': - if (op == "ref.is_func"sv) { - auto ret = makeRefTest(ctx, pos, Type(HeapType::func, NonNullable)); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'i': - if (op == "ref.is_i31"sv) { - auto ret = makeRefTest(ctx, pos, Type(HeapType::i31, NonNullable)); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'n': - if (op == "ref.is_null"sv) { - auto ret = makeRefIsNull(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'i': + if (op == "ref.is_null"sv) { + auto ret = makeRefIsNull(ctx, pos); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; case 'n': if (op == "ref.null"sv) { auto ret = makeRefNull(ctx, pos); @@ -8765,25 +8547,13 @@ switch (buf[0]) { return *ret; } goto parse_error; - case 't': { - switch (buf[8]) { - case '\0': - if (op == "ref.test"sv) { - auto ret = makeRefTest(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "ref.test_static"sv) { - auto ret = makeRefTest(ctx, pos); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 't': + if (op == "ref.test"sv) { + auto ret = makeRefTest(ctx, pos); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; default: goto parse_error; } } diff --git a/src/ir/stack-utils.h b/src/ir/stack-utils.h index aad13f7f0..82d1f5a3d 100644 --- a/src/ir/stack-utils.h +++ b/src/ir/stack-utils.h @@ -131,13 +131,13 @@ struct StackSignature { // // As an example of the first rule, consider this instruction sequence: // - // ref.as_func + // ref.cast (ref i31) // drop // i32.add // // The most specific type you could give this sequence is [i32, i32, anyref] // -> [i32]. But it could also be used in a context that expects [i32, i32, - // funcref] -> [i32] because ref.as_func can accept funcref or any other + // structref] -> [i32] because ref.cast can accept structref or any other // subtype of anyref. That's where the contravariance comes from. This // instruction sequence could also be used anywhere that expects [f32, i32, // i32, anyref] -> [f32, i32] because the f32 simply stays on the stack @@ -145,7 +145,7 @@ struct StackSignature { // // For the second rule, consider this sequence: // - // ref.as_func + // ref.cast (ref i31) // drop // i32.add // unreachable diff --git a/src/passes/OptimizeCasts.cpp b/src/passes/OptimizeCasts.cpp index 599e403ff..7877bea9f 100644 --- a/src/passes/OptimizeCasts.cpp +++ b/src/passes/OptimizeCasts.cpp @@ -385,10 +385,8 @@ struct EarlyCastApplier : public PostWalker<EarlyCastApplier> { auto refCastIter = finder.refCastToApply.find(curr); if (refCastIter != finder.refCastToApply.end()) { - currPtr = replaceCurrent(Builder(*getModule()) - .makeRefCast(currPtr, - refCastIter->second->type, - refCastIter->second->safety)); + currPtr = replaceCurrent( + Builder(*getModule()).makeRefCast(currPtr, refCastIter->second->type)); } auto refAsIter = finder.refAsToApply.find(curr); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 44078545b..965f8b2d8 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1406,13 +1406,13 @@ struct OptimizeInstructions // skipCast do): removing a cast is potentially dangerous, as it removes // information from the IR. For example: // - // (ref.is_func - // (ref.as_func + // (ref.test (ref i31) + // (ref.cast (ref i31) // (local.get $anyref))) // // The local has no useful type info here (it is anyref). The cast forces it - // to be a function, so we know that if we do not trap then the ref.is will - // definitely be 1. But if we removed the ref.as first (which we can do in + // to be an i31, so we know that if we do not trap then the ref.test will + // definitely be 1. But if we removed the ref.cast first (which we can do in // traps-never-happen mode) then we'd not have the type info we need to // optimize that way. // @@ -1420,12 +1420,12 @@ struct OptimizeInstructions // // * Before removing a cast we should use its type information in the best // way we can. Only after doing so should a cast be removed. In the exmaple - // above, that means first seeing that the ref.is must return 1, and only - // then possibly removing the ref.as. + // above, that means first seeing that the ref.test must return 1, and only + // then possibly removing the ref.cast. // * Do not remove a cast if removing it might remove useful information for // others. For example, // - // (ref.cast $A + // (ref.cast (ref null $A) // (ref.as_non_null ..)) // // If we remove the inner cast then the outer cast becomes nullable. That diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 6740bc8ed..dee23d67d 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2102,14 +2102,10 @@ struct PrintExpressionContents if (printUnreachableReplacement(curr)) { return; } - if (curr->safety == RefCast::Unsafe) { - printMedium(o, "ref.cast_nop "); + if (curr->type.isNullable()) { + printMedium(o, "ref.cast null "); } else { - if (curr->type.isNullable()) { - printMedium(o, "ref.cast null "); - } else { - printMedium(o, "ref.cast "); - } + printMedium(o, "ref.cast "); } printHeapType(o, curr->type.getHeapType(), wasm); } diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 197126f5e..dc7741c0e 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -714,9 +714,6 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { // First, check for a possible null which would prevent optimizations on // null checks. - // TODO: Look into using BrOnNonNull here, to replace a br_on_func whose - // input is (ref null func) with br_on_non_null (as only the null check - // would be needed). // TODO: Use the fallthrough to determine in more cases that we // definitely have a null. auto refType = curr->ref->type; diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 8df9b9afc..2317e7d49 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -3394,8 +3394,7 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { // This unreachable avoids a warning on refType being possibly undefined. WASM_UNREACHABLE("bad case"); } - // TODO: Fuzz unsafe casts? - return builder.makeRefCast(make(refType), type, RefCast::Safe); + return builder.makeRefCast(make(refType), type); } Expression* TranslateToFuzzReader::makeStructGet(Type type) { diff --git a/src/wasm-binary.h b/src/wasm-binary.h index c6b3e7b6f..05cd38320 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -389,10 +389,6 @@ enum EncodedType { Array = -0x22, // 0x5e Sub = -0x30, // 0x50 SubFinal = -0x32, // 0x4e - // prototype nominal forms we still parse - FuncSubtype = -0x23, // 0x5d - StructSubtype = -0x24, // 0x5c - ArraySubtype = -0x25, // 0x5b // isorecursive recursion groups Rec = -0x31, // 0x4f // block_type @@ -1108,7 +1104,6 @@ enum ASTNodes { ArrayGetS = 0x14, ArrayGetU = 0x15, ArraySet = 0x16, - ArrayLenAnnotated = 0x17, ArrayCopy = 0x18, ArrayLen = 0x19, ArrayNewFixed = 0x1a, @@ -1120,23 +1115,10 @@ enum ASTNodes { I31GetU = 0x22, RefTest = 0x40, RefCast = 0x41, - BrOnCastLegacy = 0x42, - BrOnCastFailLegacy = 0x43, - BrOnCastNullLegacy = 0x4a, - BrOnCastFailNullLegacy = 0x4b, BrOnCast = 0x4e, BrOnCastFail = 0x4f, - RefTestStatic = 0x44, - RefCastStatic = 0x45, RefTestNull = 0x48, RefCastNull = 0x49, - RefCastNop = 0x4c, - RefAsFunc = 0x58, - RefAsI31 = 0x5a, - BrOnFunc = 0x60, - BrOnI31 = 0x62, - BrOnNonFunc = 0x63, - BrOnNonI31 = 0x65, ExternInternalize = 0x70, ExternExternalize = 0x71, ArrayFill = 0x0f, diff --git a/src/wasm-builder.h b/src/wasm-builder.h index a3bf22fdc..cb7c5e745 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -876,13 +876,10 @@ public: ret->finalize(); return ret; } - RefCast* makeRefCast(Expression* ref, - Type type, - RefCast::Safety safety = RefCast::Safe) { + RefCast* makeRefCast(Expression* ref, Type type) { auto* ret = wasm.allocator.alloc<RefCast>(); ret->ref = ref; ret->type = type; - ret->safety = safety; ret->finalize(); return ret; } diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index 1d9d6244d..cd8976f82 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -648,7 +648,6 @@ switch (DELEGATE_ID) { } case Expression::Id::RefCastId: { DELEGATE_START(RefCast); - DELEGATE_FIELD_INT(RefCast, safety); DELEGATE_FIELD_CHILD(RefCast, ref); DELEGATE_END(RefCast); break; diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index f61a5000a..84299f04b 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -287,14 +287,10 @@ private: Expression* makeCallRef(Element& s, bool isReturn); Expression* makeI31New(Element& s); Expression* makeI31Get(Element& s, bool signed_); - Expression* makeRefTest(Element& s, - std::optional<Type> castType = std::nullopt); - Expression* makeRefCast(Element& s, - std::optional<Type> castType = std::nullopt); - Expression* makeRefCastNop(Element& s); + Expression* makeRefTest(Element& s); + Expression* makeRefCast(Element& s); Expression* makeBrOnNull(Element& s, bool onFail = false); - Expression* - makeBrOnCast(Element& s, std::optional<Type> castType, bool onFail = false); + Expression* makeBrOnCast(Element& s, bool onFail = false); Expression* makeStructNew(Element& s, bool default_); Index getStructIndex(Element& type, Element& field); Expression* makeStructGet(Element& s, bool signed_ = false); diff --git a/src/wasm.h b/src/wasm.h index c059009b6..39cc9fb54 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1525,11 +1525,6 @@ public: Expression* ref; - // Support the unsafe `ref.cast_nop_static` to enable precise cast overhead - // measurements. - enum Safety { Safe, Unsafe }; - Safety safety = Safe; - void finalize(); Type& getCastType() { return type; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 3ceab828b..98e832225 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2256,49 +2256,15 @@ void WasmBinaryReader::readTypes() { } form = getS32LEB(); } - if (form == BinaryConsts::EncodedType::Func || - form == BinaryConsts::EncodedType::FuncSubtype) { + if (form == BinaryConsts::EncodedType::Func) { builder[i] = readSignatureDef(); - } else if (form == BinaryConsts::EncodedType::Struct || - form == BinaryConsts::EncodedType::StructSubtype) { + } else if (form == BinaryConsts::EncodedType::Struct) { builder[i] = readStructDef(); - } else if (form == BinaryConsts::EncodedType::Array || - form == BinaryConsts::EncodedType::ArraySubtype) { + } else if (form == BinaryConsts::EncodedType::Array) { builder[i] = Array(readFieldDef()); } else { throwError("Bad type form " + std::to_string(form)); } - if (form == BinaryConsts::EncodedType::FuncSubtype || - form == BinaryConsts::EncodedType::StructSubtype || - form == BinaryConsts::EncodedType::ArraySubtype) { - int64_t super = getS64LEB(); // TODO: Actually s33 - if (super >= 0) { - superIndex = (uint32_t)super; - } else { - // Validate but otherwise ignore trivial supertypes. - HeapType basicSuper; - if (!getBasicHeapType(super, basicSuper)) { - throwError("Unrecognized supertype " + std::to_string(super)); - } - if (form == BinaryConsts::EncodedType::FuncSubtype) { - if (basicSuper != HeapType::func) { - throwError( - "The only allowed trivial supertype for functions is func"); - } - } else { - // Check for "struct" here even if we are parsing an array definition. - // This is the old nonstandard "struct_subtype" or "array_subtype" - // form of type definitions that used the old "data" type as the - // supertype placeholder when there was no nontrivial supertype. - // "data" no longer exists, but "struct" has the same encoding it used - // to have. - if (basicSuper != HeapType::struct_) { - throwError("The only allowed trivial supertype for structs and " - "arrays is data"); - } - } - } - } if (superIndex) { if (*superIndex > builder.size()) { throwError("Out of bounds supertype index " + @@ -4162,12 +4128,6 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { if (maybeVisitStringSliceIter(curr, opcode)) { break; } - if (opcode == BinaryConsts::RefAsFunc || - 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); @@ -7011,10 +6971,8 @@ bool WasmBinaryReader::maybeVisitI31Get(Expression*& out, uint32_t code) { } bool WasmBinaryReader::maybeVisitRefTest(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefTestStatic || code == BinaryConsts::RefTest || - code == BinaryConsts::RefTestNull) { - bool legacy = code == BinaryConsts::RefTestStatic; - auto castType = legacy ? getIndexedHeapType() : getHeapType(); + if (code == BinaryConsts::RefTest || code == BinaryConsts::RefTestNull) { + auto castType = getHeapType(); auto nullability = (code == BinaryConsts::RefTestNull) ? Nullable : NonNullable; auto* ref = popNonVoidExpression(); @@ -7024,40 +6982,13 @@ bool WasmBinaryReader::maybeVisitRefTest(Expression*& out, uint32_t code) { return false; } -void WasmBinaryReader::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::RefAsI31: - curr->type = Type(HeapType::i31, NonNullable); - break; - default: - WASM_UNREACHABLE("unexpected ref.as*"); - } - curr->ref = popNonVoidExpression(); - curr->safety = RefCast::Safe; - curr->finalize(); -} - bool WasmBinaryReader::maybeVisitRefCast(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCast || - code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) { - bool legacy = code == BinaryConsts::RefCastStatic; - auto heapType = legacy ? getIndexedHeapType() : getHeapType(); - auto* ref = popNonVoidExpression(); - Nullability nullability; - if (legacy) { - // Legacy polymorphic behavior. - nullability = ref->type.getNullability(); - } else { - nullability = code == BinaryConsts::RefCast ? NonNullable : Nullable; - } - auto safety = - code == BinaryConsts::RefCastNop ? RefCast::Unsafe : RefCast::Safe; + if (code == BinaryConsts::RefCast || code == BinaryConsts::RefCastNull) { + auto heapType = getHeapType(); + auto nullability = code == BinaryConsts::RefCast ? NonNullable : Nullable; auto type = Type(heapType, nullability); - out = Builder(wasm).makeRefCast(ref, type, safety); + auto* ref = popNonVoidExpression(); + out = Builder(wasm).makeRefCast(ref, type); return true; } return false; @@ -7074,63 +7005,32 @@ bool WasmBinaryReader::maybeVisitBrOn(Expression*& out, uint32_t code) { op = BrOnNonNull; break; case BinaryConsts::BrOnCast: - case BinaryConsts::BrOnCastLegacy: - case BinaryConsts::BrOnCastNullLegacy: op = BrOnCast; break; case BinaryConsts::BrOnCastFail: - case BinaryConsts::BrOnCastFailLegacy: - case BinaryConsts::BrOnCastFailNullLegacy: op = BrOnCastFail; break; - case BinaryConsts::BrOnFunc: - op = BrOnCast; - castType = Type(HeapType::func, NonNullable); - break; - case BinaryConsts::BrOnNonFunc: - op = BrOnCastFail; - castType = Type(HeapType::func, NonNullable); - break; - case BinaryConsts::BrOnI31: - op = BrOnCast; - castType = Type(HeapType::i31, NonNullable); - break; - case BinaryConsts::BrOnNonI31: - op = BrOnCastFail; - castType = Type(HeapType::i31, NonNullable); - break; default: return false; } - bool hasInputAnnotation = + bool isCast = code == BinaryConsts::BrOnCast || code == BinaryConsts::BrOnCastFail; uint8_t flags = 0; - if (hasInputAnnotation) { + if (isCast) { flags = getInt8(); } auto name = getBreakTarget(getU32LEB()).name; auto* ref = popNonVoidExpression(); - if (op == BrOnCast || op == BrOnCastFail) { - Nullability inputNullability, castNullability; - HeapType inputHeapType, castHeapType; - if (hasInputAnnotation) { - inputNullability = (flags & 1) ? Nullable : NonNullable; - castNullability = (flags & 2) ? Nullable : NonNullable; - inputHeapType = getHeapType(); - } else { - castNullability = (code == BinaryConsts::BrOnCastNullLegacy || - code == BinaryConsts::BrOnCastFailNullLegacy) - ? Nullable - : NonNullable; - } - castHeapType = getHeapType(); + if (isCast) { + auto inputNullability = (flags & 1) ? Nullable : NonNullable; + auto castNullability = (flags & 2) ? Nullable : NonNullable; + auto inputHeapType = getHeapType(); + auto castHeapType = getHeapType(); castType = Type(castHeapType, castNullability); - if (hasInputAnnotation) { - auto inputType = Type(inputHeapType, inputNullability); - if (!Type::isSubType(ref->type, inputType)) { - throwError(std::string("Invalid reference type for ") + - ((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail")); - } + auto inputType = Type(inputHeapType, inputNullability); + if (!Type::isSubType(ref->type, inputType)) { + throwError(std::string("Invalid reference type for ") + + ((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail")); } } out = Builder(wasm).makeBrOn(op, name, ref, castType); @@ -7288,10 +7188,7 @@ bool WasmBinaryReader::maybeVisitArraySet(Expression*& out, uint32_t code) { } bool WasmBinaryReader::maybeVisitArrayLen(Expression*& out, uint32_t code) { - if (code == BinaryConsts::ArrayLenAnnotated) { - // Ignore the type annotation and don't bother validating it. - getU32LEB(); - } else if (code != BinaryConsts::ArrayLen) { + if (code != BinaryConsts::ArrayLen) { return false; } auto* ref = popNonVoidExpression(); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 9b7a1a90d..0115cdac3 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2841,51 +2841,30 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { return ret; } -Expression* SExpressionWasmBuilder::makeRefTest(Element& s, - std::optional<Type> castType) { +Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { int i = 1; - if (!castType) { - auto nullability = NonNullable; - if (s[0]->str().str != "ref.test_static" && s[1]->str().str == "null") { - nullability = Nullable; - ++i; - } - auto type = parseHeapType(*s[i++]); - castType = Type(type, nullability); + auto nullability = NonNullable; + if (s[1]->str().str == "null") { + nullability = Nullable; + ++i; } + auto type = parseHeapType(*s[i++]); + auto castType = Type(type, nullability); auto* ref = parseExpression(*s[i++]); - return Builder(wasm).makeRefTest(ref, *castType); + return Builder(wasm).makeRefTest(ref, castType); } -Expression* SExpressionWasmBuilder::makeRefCast(Element& s, - std::optional<Type> castType) { +Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { int i = 1; - bool legacy = false; - 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); + Nullability nullability = NonNullable; + if (s[i]->str().str == "null") { + nullability = Nullable; + ++i; } + auto type = parseHeapType(*s[i++]); + auto castType = Type(type, nullability); auto* ref = parseExpression(*s[i++]); - if (legacy) { - // Legacy polymorphic behavior. - castType = Type(castType->getHeapType(), ref->type.getNullability()); - } - return Builder(wasm).makeRefCast(ref, *castType, RefCast::Safe); -} - -Expression* SExpressionWasmBuilder::makeRefCastNop(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto* ref = parseExpression(*s[2]); - // Legacy polymorphic behavior. - auto type = Type(heapType, ref->type.getNullability()); - return Builder(wasm).makeRefCast(ref, type, RefCast::Unsafe); + return Builder(wasm).makeRefCast(ref, castType); } Expression* SExpressionWasmBuilder::makeBrOnNull(Element& s, bool onFail) { @@ -2896,23 +2875,18 @@ Expression* SExpressionWasmBuilder::makeBrOnNull(Element& s, bool onFail) { return Builder(wasm).makeBrOn(op, name, ref); } -Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s, - std::optional<Type> castType, - bool onFail) { +Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s, bool onFail) { int i = 1; auto name = getLabel(*s[i++]); - std::optional<Type> inputType; - if (!castType) { - inputType = elementToType(*s[i++]); - castType = elementToType(*s[i++]); - } + auto inputType = elementToType(*s[i++]); + auto castType = elementToType(*s[i++]); auto* ref = parseExpression(*s[i]); - if (inputType && !Type::isSubType(ref->type, *inputType)) { + if (!Type::isSubType(ref->type, inputType)) { throw ParseException( "br_on_cast* ref type does not match expected type", s.line, s.col); } auto op = onFail ? BrOnCastFail : BrOnCast; - return Builder(wasm).makeBrOn(op, name, ref, *castType); + return Builder(wasm).makeBrOn(op, name, ref, castType); } Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index ee457da69..3b7756992 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2021,17 +2021,12 @@ void BinaryInstWriter::visitRefTest(RefTest* curr) { void BinaryInstWriter::visitRefCast(RefCast* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->safety == RefCast::Unsafe) { - o << U32LEB(BinaryConsts::RefCastNop); - parent.writeHeapType(curr->type.getHeapType()); + if (curr->type.isNullable()) { + o << U32LEB(BinaryConsts::RefCastNull); } else { - if (curr->type.isNullable()) { - o << U32LEB(BinaryConsts::RefCastNull); - } else { - o << U32LEB(BinaryConsts::RefCast); - } - parent.writeHeapType(curr->type.getHeapType()); + o << U32LEB(BinaryConsts::RefCast); } + parent.writeHeapType(curr->type.getHeapType()); } void BinaryInstWriter::visitBrOn(BrOn* curr) { diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 528d0d1af..d5bda85fe 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -2374,18 +2374,12 @@ Result<typename Ctx::InstrT> makeCallRef(Ctx&, Index, bool isReturn); template<typename Ctx> Result<typename Ctx::InstrT> makeI31New(Ctx&, Index); template<typename Ctx> 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, std::optional<Type> castType = std::nullopt); -template<typename Ctx> Result<typename Ctx::InstrT> makeRefCastNop(Ctx&, Index); +template<typename Ctx> Result<typename Ctx::InstrT> makeRefTest(Ctx&, Index); +template<typename Ctx> Result<typename Ctx::InstrT> makeRefCast(Ctx&, Index); template<typename Ctx> Result<typename Ctx::InstrT> makeBrOnNull(Ctx&, Index, bool onFail = false); template<typename Ctx> -Result<typename Ctx::InstrT> -makeBrOnCast(Ctx&, Index, std::optional<Type>, bool onFail = false); +Result<typename Ctx::InstrT> makeBrOnCast(Ctx&, Index, bool onFail = false); template<typename Ctx> Result<typename Ctx::InstrT> makeStructNew(Ctx&, Index, bool default_); template<typename Ctx> @@ -3480,19 +3474,12 @@ Result<typename Ctx::InstrT> makeI31Get(Ctx& ctx, Index pos, bool signed_) { } template<typename Ctx> -Result<typename Ctx::InstrT> -makeRefTest(Ctx& ctx, Index pos, std::optional<Type> castType) { - return ctx.in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> -makeRefCast(Ctx& ctx, Index pos, std::optional<Type> castType) { +Result<typename Ctx::InstrT> makeRefTest(Ctx& ctx, Index pos) { return ctx.in.err("unimplemented instruction"); } template<typename Ctx> -Result<typename Ctx::InstrT> makeRefCastNop(Ctx& ctx, Index pos) { +Result<typename Ctx::InstrT> makeRefCast(Ctx& ctx, Index pos) { return ctx.in.err("unimplemented instruction"); } @@ -3502,8 +3489,7 @@ Result<typename Ctx::InstrT> makeBrOnNull(Ctx& ctx, Index pos, bool onFail) { } template<typename Ctx> -Result<typename Ctx::InstrT> -makeBrOnCast(Ctx& ctx, Index pos, std::optional<Type> castType, bool onFail) { +Result<typename Ctx::InstrT> makeBrOnCast(Ctx& ctx, Index pos, bool onFail) { return ctx.in.err("unimplemented instruction"); } |