diff options
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"); } |