summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py18
-rw-r--r--src/binaryen-c.cpp3
-rw-r--r--src/gen-s-parser.inc342
-rw-r--r--src/ir/stack-utils.h6
-rw-r--r--src/passes/OptimizeCasts.cpp6
-rw-r--r--src/passes/OptimizeInstructions.cpp14
-rw-r--r--src/passes/Print.cpp10
-rw-r--r--src/passes/RemoveUnusedBrs.cpp3
-rw-r--r--src/tools/fuzzing/fuzzing.cpp3
-rw-r--r--src/wasm-binary.h18
-rw-r--r--src/wasm-builder.h5
-rw-r--r--src/wasm-delegations-fields.def1
-rw-r--r--src/wasm-s-parser.h10
-rw-r--r--src/wasm.h5
-rw-r--r--src/wasm/wasm-binary.cpp147
-rw-r--r--src/wasm/wasm-s-parser.cpp68
-rw-r--r--src/wasm/wasm-stack.cpp13
-rw-r--r--src/wasm/wat-parser.cpp26
-rw-r--r--test/heap-types.wast334
-rw-r--r--test/heap-types.wast.from-wast399
-rw-r--r--test/heap-types.wast.fromBinary353
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo353
-rw-r--r--test/lit/binary/annotated-array-len.test18
-rw-r--r--test/lit/binary/annotated-array-len.test.wasmbin36 -> 0 bytes
-rw-r--r--test/lit/binary/bad-ref-as.test5
-rw-r--r--test/lit/binary/bad-ref-as.test.wasmbin29 -> 0 bytes
-rw-r--r--test/lit/legacy-static-casts.wast47
-rw-r--r--test/lit/passes/abstract-type-refining.wast15
-rw-r--r--test/lit/passes/code-pushing-gc.wast18
-rw-r--r--test/lit/passes/gufa-refs.wast2
-rw-r--r--test/lit/passes/merge-blocks.wast2
-rw-r--r--test/lit/passes/optimize-instructions-gc-tnh.wast58
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast42
-rw-r--r--test/lit/passes/remove-unused-brs-gc.wast101
-rw-r--r--test/lit/passes/remove-unused-brs_all-features.wast135
-rw-r--r--test/lit/passes/vacuum-gc.wast6
-rw-r--r--test/lit/passes/vacuum-tnh.wast6
-rw-r--r--test/lit/ref-cast-nop.wast29
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.wast2
39 files changed, 281 insertions, 2342 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index d9d013b9b..f82156b43 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -568,21 +568,11 @@ instructions = [
("i31.get_s", "makeI31Get(s, true)"),
("i31.get_u", "makeI31Get(s, false)"),
("ref.test", "makeRefTest(s)"),
- ("ref.test_static", "makeRefTest(s)"),
("ref.cast", "makeRefCast(s)"),
- ("ref.cast_static", "makeRefCast(s)"),
- ("ref.cast_nop", "makeRefCastNop(s)"),
- ("ref.cast_nop_static", "makeRefCastNop(s)"),
("br_on_null", "makeBrOnNull(s)"),
("br_on_non_null", "makeBrOnNull(s, true)"),
- ("br_on_cast", "makeBrOnCast(s, std::nullopt)"),
- ("br_on_cast_static", "makeBrOnCast(s, std::nullopt)"),
- ("br_on_cast_fail", "makeBrOnCast(s, std::nullopt, true)"),
- ("br_on_cast_static_fail", "makeBrOnCast(s, std::nullopt, true)"),
- ("br_on_func", "makeBrOnCast(s, Type(HeapType::func, NonNullable))"),
- ("br_on_non_func", "makeBrOnCast(s, Type(HeapType::func, NonNullable), true)"),
- ("br_on_i31", "makeBrOnCast(s, Type(HeapType::i31, NonNullable))"),
- ("br_on_non_i31", "makeBrOnCast(s, Type(HeapType::i31, NonNullable), true)"),
+ ("br_on_cast", "makeBrOnCast(s)"),
+ ("br_on_cast_fail", "makeBrOnCast(s, true)"),
("struct.new", "makeStructNew(s, false)"),
("struct.new_default", "makeStructNew(s, true)"),
("struct.get", "makeStructGet(s)"),
@@ -604,11 +594,7 @@ instructions = [
("array.fill", "makeArrayFill(s)"),
("array.init_data", "makeArrayInitData(s)"),
("array.init_elem", "makeArrayInitElem(s)"),
- ("ref.is_func", "makeRefTest(s, Type(HeapType::func, NonNullable))"),
- ("ref.is_i31", "makeRefTest(s, Type(HeapType::i31, NonNullable))"),
("ref.as_non_null", "makeRefAs(s, RefAsNonNull)"),
- ("ref.as_func", "makeRefCast(s, Type(HeapType::func, NonNullable))"),
- ("ref.as_i31", "makeRefCast(s, Type(HeapType::i31, NonNullable))"),
("extern.internalize", "makeRefAs(s, ExternInternalize)"),
("extern.externalize", "makeRefAs(s, ExternExternalize)"),
("string.new_wtf8", "makeStringNew(s, StringNewWTF8, false)"),
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");
}
diff --git a/test/heap-types.wast b/test/heap-types.wast
deleted file mode 100644
index 1d297f82e..000000000
--- a/test/heap-types.wast
+++ /dev/null
@@ -1,334 +0,0 @@
-;; Test that we can roundtrip struct and array types
-(module
- ;; Structs
- (type $struct.A (struct
- i32
- (field f32)
- (field $named f64)
- ))
- ;; identical to $struct.A, so will be canonicalized with it, but field names
- ;; are different
- (type $struct.A.prime (struct
- i32
- (field f32)
- (field $othername f64)
- ))
- (type $struct.B (struct
- (field i8)
- (field (mut i16))
- (field (ref $struct.A))
- (field (mut (ref $struct.A)))
- ))
- (type $struct.C (struct
- (field $named-mut (mut f32))
- ))
-
- ;; Arrays
- (type $vector (array (mut f64)))
- (type $matrix (array (mut (ref null $vector))))
- (type $bytes (array (mut i8)))
- (type $words (array (mut i32)))
-
- (type $parent (struct))
- (type $child (struct_subtype i32 $parent))
- (type $grandchild (struct_subtype i32 i64 $child))
-
- (type $nested-child-struct (struct (field (mut (ref $child)))))
- (type $nested-child-array (array (mut (ref $child))))
-
- (global $struct.new-in-global (ref $struct.A)
- (struct.new_default $struct.A)
- )
-
- (func $structs (param $x (ref $struct.A)) (param $struct.A.prime (ref null $struct.A.prime)) (param $grandchild (ref null $grandchild)) (param $struct.C (ref null $struct.C)) (param $nested-child-struct (ref null $nested-child-struct)) (result (ref $struct.B))
- (local $tA (ref null $struct.A))
- (local $tB (ref null $struct.B))
- (local $tc (ref null $struct.C))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (drop
- (local.get $x)
- )
- (drop
- (struct.get $struct.A 0 (local.get $x))
- )
- (drop
- (struct.get $struct.A 1 (local.get $x))
- )
- (drop
- (struct.get $struct.A 2 (local.get $x))
- )
- (drop
- (struct.get $struct.A $named (local.get $x))
- )
- (drop
- (struct.get $struct.A.prime $othername (local.get $struct.A.prime))
- )
- (drop
- (struct.get_u $struct.B 0 (local.get $tB))
- )
- (drop
- (struct.get_s $struct.B 0 (local.get $tB))
- )
- ;; immutable fields allow subtyping.
- (drop
- (struct.get $child 0 (local.get $grandchild))
- )
- (drop
- (block (result (ref null $struct.A))
- (local.get $x)
- )
- )
- (drop
- (if (result (ref null $struct.A))
- (i32.const 1)
- (local.get $x)
- (local.get $x)
- )
- )
- (drop
- (loop (result (ref null $struct.A))
- (local.get $x)
- )
- )
- (drop
- (select (result (ref null $struct.A))
- (local.get $x)
- (local.get $x)
- (i32.const 1)
- )
- )
- (struct.set $struct.C 0
- (local.get $struct.C)
- (f32.const 100)
- )
- ;; values may be subtypes
- (struct.set $nested-child-struct 0
- (local.get $nested-child-struct)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (struct.new_default $struct.A)
- )
- (drop
- (struct.new $struct.A
- (i32.const 1)
- (f32.const 2.345)
- (f64.const 3.14159)
- )
- )
- (unreachable)
- )
- (func $arrays (param $x (ref $vector)) (param $nested-child-array (ref null $nested-child-array)) (param $grandchild (ref null $grandchild)) (result (ref $matrix))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (local $tb (ref null $bytes))
- (local $tw (ref null $words))
- (drop
- (array.new $vector
- (f64.const 3.14159)
- (i32.const 3)
- )
- )
- (drop
- (array.new_default $matrix
- (i32.const 10)
- )
- )
- (drop
- (array.get $vector
- (local.get $x)
- (i32.const 2)
- )
- )
- (array.set $vector
- (local.get $x)
- (i32.const 2)
- (f64.const 2.18281828)
- )
- ;; values may be subtypes
- (array.set $nested-child-array
- (local.get $nested-child-array)
- (i32.const 3)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (array.len $vector
- (local.get $x)
- )
- )
- (drop
- (array.get $words
- (local.get $tw)
- (i32.const 1)
- )
- )
- (drop
- (array.get_u $bytes
- (local.get $tb)
- (i32.const 2)
- )
- )
- (drop
- (array.get_s $bytes
- (local.get $tb)
- (i32.const 3)
- )
- )
- (unreachable)
- )
- (func $ref.is_X (param $x anyref)
- (if (ref.is_null (local.get $x)) (unreachable))
- (if (ref.is_i31 (local.get $x)) (unreachable))
- )
- (func $ref.as_X (param $x anyref) (param $f funcref)
- (drop (ref.as_non_null (local.get $x)))
- (drop (ref.as_func (local.get $f)))
- (drop (ref.as_i31 (local.get $x)))
- )
- (func $br_on_X (param $x anyref)
- (local $y anyref)
- (local $z (ref null any))
- (local $temp-func (ref null func))
- (local $temp-i31 (ref null i31))
- (block $null
- (local.set $z
- (br_on_null $null (local.get $x))
- )
- )
- (drop
- (block $i31 (result (ref null i31))
- (local.set $y
- (br_on_i31 $i31 (local.get $x))
- )
- (ref.null i31)
- )
- )
- (drop
- (block $non-null (result (ref any))
- (br_on_non_null $non-null (local.get $x))
- (unreachable)
- )
- )
- (drop
- (block $non-i31 (result anyref)
- (local.set $temp-i31
- (br_on_non_i31 $non-i31 (local.get $x))
- )
- (ref.null any)
- )
- )
- )
- (func $unreachables-1
- (drop
- (struct.get $struct.C 0 (unreachable))
- )
- )
- (func $unreachables-2 (param $struct.C (ref null $struct.C))
- (struct.set $struct.C 0 (local.get $struct.C) (unreachable))
- )
- (func $unreachables-3
- (struct.set $struct.C 0 (unreachable) (unreachable))
- )
- (func $unreachables-4
- (struct.set $struct.C 0 (unreachable) (f32.const 1))
- )
- (func $unreachables-array-1
- (array.get $vector
- (unreachable)
- (i32.const 2)
- )
- )
- (func $unreachables-array-2 (param $vector (ref null $vector))
- (array.get $vector
- (local.get $vector)
- (unreachable)
- )
- )
- (func $unreachables-array-3
- (array.set $vector
- (unreachable)
- (i32.const 2)
- (f64.const 2.18281828)
- )
- )
- (func $unreachables-array-4 (param $vector (ref null $vector))
- (array.set $vector
- (local.get $vector)
- (unreachable)
- (f64.const 2.18281828)
- )
- )
- (func $unreachables-array-5 (param $vector (ref null $vector))
- (array.set $vector
- (local.get $vector)
- (i32.const 2)
- (unreachable)
- )
- )
- (func $unreachables-array-6
- (drop
- (array.len $vector
- (unreachable)
- )
- )
- )
- (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector))
- (array.copy $vector $vector
- (local.get $x)
- (i32.const 11)
- (local.get $y)
- (i32.const 42)
- (i32.const 1337)
- )
- )
- (func $array-init (result (ref $vector))
- (array.new_fixed $vector
- (f64.const 1)
- (f64.const 2)
- (f64.const 4)
- (f64.const 8)
- )
- )
- (func $array-init-packed (result (ref $bytes))
- (array.new_fixed $bytes
- (i32.const 4)
- (i32.const 2)
- (i32.const 1)
- )
- )
- (func $static-operations
- (local $temp.A (ref null $struct.A))
- (local $temp.B (ref null $struct.B))
- (drop
- (ref.test $struct.B (ref.null $struct.A))
- )
- (drop
- (ref.cast null $struct.B (ref.null $struct.A))
- )
- (drop
- (block $out-B (result (ref $struct.B))
- (local.set $temp.A
- (br_on_cast $out-B (ref null $struct.A) (ref $struct.B)
- (ref.null $struct.A)
- )
- )
- (unreachable)
- )
- )
- (drop
- (block $out-A (result (ref null $struct.A))
- (local.set $temp.B
- (br_on_cast_fail $out-A (ref null $struct.A) (ref $struct.B)
- (ref.null $struct.A)
- )
- )
- (unreachable)
- )
- )
- )
-)
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
deleted file mode 100644
index 2504a6f82..000000000
--- a/test/heap-types.wast.from-wast
+++ /dev/null
@@ -1,399 +0,0 @@
-(module
- (type $struct.A (struct (field i32) (field f32) (field $named f64)))
- (type $vector (array (mut f64)))
- (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A)))))
- (type $none_=>_none (func))
- (type $struct.C (struct (field $named-mut (mut f32))))
- (type $matrix (array (mut (ref null $vector))))
- (type $bytes (array (mut i8)))
- (type $parent (struct ))
- (type $child (sub $parent (struct (field i32))))
- (type $grandchild (sub $child (struct (field i32) (field i64))))
- (type $ref?|$vector|_=>_none (func (param (ref null $vector))))
- (type $nested-child-struct (struct (field (mut (ref $child)))))
- (type $words (array (mut i32)))
- (type $nested-child-array (array (mut (ref $child))))
- (type $anyref_=>_none (func (param anyref)))
- (type $ref|$struct.A|_ref?|$struct.A|_ref?|$grandchild|_ref?|$struct.C|_ref?|$nested-child-struct|_=>_ref|$struct.B| (func (param (ref $struct.A) (ref null $struct.A) (ref null $grandchild) (ref null $struct.C) (ref null $nested-child-struct)) (result (ref $struct.B))))
- (type $ref|$vector|_ref?|$nested-child-array|_ref?|$grandchild|_=>_ref|$matrix| (func (param (ref $vector) (ref null $nested-child-array) (ref null $grandchild)) (result (ref $matrix))))
- (type $anyref_funcref_=>_none (func (param anyref funcref)))
- (type $ref?|$struct.C|_=>_none (func (param (ref null $struct.C))))
- (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector))))
- (type $none_=>_ref|$vector| (func (result (ref $vector))))
- (type $none_=>_ref|$bytes| (func (result (ref $bytes))))
- (global $struct.new-in-global (ref $struct.A) (struct.new_default $struct.A))
- (func $structs (type $ref|$struct.A|_ref?|$struct.A|_ref?|$grandchild|_ref?|$struct.C|_ref?|$nested-child-struct|_=>_ref|$struct.B|) (param $x (ref $struct.A)) (param $struct.A.prime (ref null $struct.A)) (param $grandchild (ref null $grandchild)) (param $struct.C (ref null $struct.C)) (param $nested-child-struct (ref null $nested-child-struct)) (result (ref $struct.B))
- (local $tA (ref null $struct.A))
- (local $tB (ref null $struct.B))
- (local $tc (ref null $struct.C))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (drop
- (local.get $x)
- )
- (drop
- (struct.get $struct.A 0
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A 1
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $struct.A.prime)
- )
- )
- (drop
- (struct.get_u $struct.B 0
- (local.get $tB)
- )
- )
- (drop
- (struct.get_s $struct.B 0
- (local.get $tB)
- )
- )
- (drop
- (struct.get $grandchild 0
- (local.get $grandchild)
- )
- )
- (drop
- (block (result (ref null $struct.A))
- (local.get $x)
- )
- )
- (drop
- (if (result (ref null $struct.A))
- (i32.const 1)
- (local.get $x)
- (local.get $x)
- )
- )
- (drop
- (loop $loop-in (result (ref null $struct.A))
- (local.get $x)
- )
- )
- (drop
- (select (result (ref null $struct.A))
- (local.get $x)
- (local.get $x)
- (i32.const 1)
- )
- )
- (struct.set $struct.C $named-mut
- (local.get $struct.C)
- (f32.const 100)
- )
- (struct.set $nested-child-struct 0
- (local.get $nested-child-struct)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (struct.new_default $struct.A)
- )
- (drop
- (struct.new $struct.A
- (i32.const 1)
- (f32.const 2.3450000286102295)
- (f64.const 3.14159)
- )
- )
- (unreachable)
- )
- (func $arrays (type $ref|$vector|_ref?|$nested-child-array|_ref?|$grandchild|_=>_ref|$matrix|) (param $x (ref $vector)) (param $nested-child-array (ref null $nested-child-array)) (param $grandchild (ref null $grandchild)) (result (ref $matrix))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (local $tb (ref null $bytes))
- (local $tw (ref null $words))
- (drop
- (array.new $vector
- (f64.const 3.14159)
- (i32.const 3)
- )
- )
- (drop
- (array.new_default $matrix
- (i32.const 10)
- )
- )
- (drop
- (array.get $vector
- (local.get $x)
- (i32.const 2)
- )
- )
- (array.set $vector
- (local.get $x)
- (i32.const 2)
- (f64.const 2.18281828)
- )
- (array.set $nested-child-array
- (local.get $nested-child-array)
- (i32.const 3)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (array.len
- (local.get $x)
- )
- )
- (drop
- (array.get $words
- (local.get $tw)
- (i32.const 1)
- )
- )
- (drop
- (array.get_u $bytes
- (local.get $tb)
- (i32.const 2)
- )
- )
- (drop
- (array.get_s $bytes
- (local.get $tb)
- (i32.const 3)
- )
- )
- (unreachable)
- )
- (func $ref.is_X (type $anyref_=>_none) (param $x anyref)
- (if
- (ref.is_null
- (local.get $x)
- )
- (unreachable)
- )
- (if
- (ref.test i31
- (local.get $x)
- )
- (unreachable)
- )
- )
- (func $ref.as_X (type $anyref_funcref_=>_none) (param $x anyref) (param $f funcref)
- (drop
- (ref.as_non_null
- (local.get $x)
- )
- )
- (drop
- (ref.cast func
- (local.get $f)
- )
- )
- (drop
- (ref.cast i31
- (local.get $x)
- )
- )
- )
- (func $br_on_X (type $anyref_=>_none) (param $x anyref)
- (local $y anyref)
- (local $z anyref)
- (local $temp-func funcref)
- (local $temp-i31 i31ref)
- (block $null
- (local.set $z
- (br_on_null $null
- (local.get $x)
- )
- )
- )
- (drop
- (block $i31 (result i31ref)
- (local.set $y
- (br_on_cast $i31 anyref (ref i31)
- (local.get $x)
- )
- )
- (ref.null none)
- )
- )
- (drop
- (block $non-null (result (ref any))
- (br_on_non_null $non-null
- (local.get $x)
- )
- (unreachable)
- )
- )
- (drop
- (block $non-i31 (result anyref)
- (local.set $temp-i31
- (br_on_cast_fail $non-i31 anyref (ref i31)
- (local.get $x)
- )
- )
- (ref.null none)
- )
- )
- )
- (func $unreachables-1 (type $none_=>_none)
- (drop
- (block ;; (replaces something unreachable we can't emit)
- (drop
- (unreachable)
- )
- (unreachable)
- )
- )
- )
- (func $unreachables-2 (type $ref?|$struct.C|_=>_none) (param $struct.C (ref null $struct.C))
- (struct.set $struct.C $named-mut
- (local.get $struct.C)
- (unreachable)
- )
- )
- (func $unreachables-3 (type $none_=>_none)
- (block ;; (replaces something unreachable we can't emit)
- (drop
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (unreachable)
- )
- )
- (func $unreachables-4 (type $none_=>_none)
- (block ;; (replaces something unreachable we can't emit)
- (drop
- (unreachable)
- )
- (drop
- (f32.const 1)
- )
- (unreachable)
- )
- )
- (func $unreachables-array-1 (type $none_=>_none)
- (block ;; (replaces something unreachable we can't emit)
- (drop
- (unreachable)
- )
- (drop
- (i32.const 2)
- )
- (unreachable)
- )
- )
- (func $unreachables-array-2 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (array.get $vector
- (local.get $vector)
- (unreachable)
- )
- )
- (func $unreachables-array-3 (type $none_=>_none)
- (block ;; (replaces something unreachable we can't emit)
- (drop
- (unreachable)
- )
- (drop
- (i32.const 2)
- )
- (drop
- (f64.const 2.18281828)
- )
- (unreachable)
- )
- )
- (func $unreachables-array-4 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (array.set $vector
- (local.get $vector)
- (unreachable)
- (f64.const 2.18281828)
- )
- )
- (func $unreachables-array-5 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (array.set $vector
- (local.get $vector)
- (i32.const 2)
- (unreachable)
- )
- )
- (func $unreachables-array-6 (type $none_=>_none)
- (drop
- (array.len
- (unreachable)
- )
- )
- )
- (func $array-copy (type $ref|$vector|_ref?|$vector|_=>_none) (param $x (ref $vector)) (param $y (ref null $vector))
- (array.copy $vector $vector
- (local.get $x)
- (i32.const 11)
- (local.get $y)
- (i32.const 42)
- (i32.const 1337)
- )
- )
- (func $array-init (type $none_=>_ref|$vector|) (result (ref $vector))
- (array.new_fixed $vector
- (f64.const 1)
- (f64.const 2)
- (f64.const 4)
- (f64.const 8)
- )
- )
- (func $array-init-packed (type $none_=>_ref|$bytes|) (result (ref $bytes))
- (array.new_fixed $bytes
- (i32.const 4)
- (i32.const 2)
- (i32.const 1)
- )
- )
- (func $static-operations (type $none_=>_none)
- (local $temp.A (ref null $struct.A))
- (local $temp.B (ref null $struct.B))
- (drop
- (ref.test $struct.B
- (ref.null none)
- )
- )
- (drop
- (ref.cast null none
- (ref.null none)
- )
- )
- (drop
- (block $out-B (result (ref $struct.B))
- (local.set $temp.A
- (br_on_cast $out-B nullref (ref $struct.B)
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- (drop
- (block $out-A (result (ref null $struct.A))
- (local.set $temp.B
- (br_on_cast_fail $out-A nullref (ref $struct.B)
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- )
-)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
deleted file mode 100644
index f95e1508d..000000000
--- a/test/heap-types.wast.fromBinary
+++ /dev/null
@@ -1,353 +0,0 @@
-(module
- (type $struct.A (struct (field i32) (field f32) (field $named f64)))
- (type $vector (array (mut f64)))
- (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A)))))
- (type $none_=>_none (func))
- (type $matrix (array (mut (ref null $vector))))
- (type $bytes (array (mut i8)))
- (type $struct.C (struct (field $named-mut (mut f32))))
- (type $parent (struct ))
- (type $child (sub $parent (struct (field i32))))
- (type $grandchild (sub $child (struct (field i32) (field i64))))
- (type $ref?|$vector|_=>_none (func (param (ref null $vector))))
- (type $nested-child-struct (struct (field (mut (ref $child)))))
- (type $words (array (mut i32)))
- (type $nested-child-array (array (mut (ref $child))))
- (type $anyref_=>_none (func (param anyref)))
- (type $ref|$struct.A|_ref?|$struct.A|_ref?|$grandchild|_ref?|$struct.C|_ref?|$nested-child-struct|_=>_ref|$struct.B| (func (param (ref $struct.A) (ref null $struct.A) (ref null $grandchild) (ref null $struct.C) (ref null $nested-child-struct)) (result (ref $struct.B))))
- (type $ref|$vector|_ref?|$nested-child-array|_ref?|$grandchild|_=>_ref|$matrix| (func (param (ref $vector) (ref null $nested-child-array) (ref null $grandchild)) (result (ref $matrix))))
- (type $anyref_funcref_=>_none (func (param anyref funcref)))
- (type $ref?|$struct.C|_=>_none (func (param (ref null $struct.C))))
- (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector))))
- (type $none_=>_ref|$vector| (func (result (ref $vector))))
- (type $none_=>_ref|$bytes| (func (result (ref $bytes))))
- (global $struct.new-in-global (ref $struct.A) (struct.new_default $struct.A))
- (func $structs (type $ref|$struct.A|_ref?|$struct.A|_ref?|$grandchild|_ref?|$struct.C|_ref?|$nested-child-struct|_=>_ref|$struct.B|) (param $x (ref $struct.A)) (param $struct.A.prime (ref null $struct.A)) (param $grandchild (ref null $grandchild)) (param $struct.C (ref null $struct.C)) (param $nested-child-struct (ref null $nested-child-struct)) (result (ref $struct.B))
- (local $tA (ref null $struct.A))
- (local $tB (ref null $struct.B))
- (local $tc (ref null $struct.C))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (drop
- (local.get $x)
- )
- (drop
- (struct.get $struct.A 0
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A 1
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $x)
- )
- )
- (drop
- (struct.get $struct.A $named
- (local.get $struct.A.prime)
- )
- )
- (drop
- (struct.get_u $struct.B 0
- (local.get $tB)
- )
- )
- (drop
- (struct.get_s $struct.B 0
- (local.get $tB)
- )
- )
- (drop
- (struct.get $grandchild 0
- (local.get $grandchild)
- )
- )
- (drop
- (local.get $x)
- )
- (drop
- (if (result (ref null $struct.A))
- (i32.const 1)
- (local.get $x)
- (local.get $x)
- )
- )
- (drop
- (loop $label$3 (result (ref null $struct.A))
- (local.get $x)
- )
- )
- (drop
- (select (result (ref null $struct.A))
- (local.get $x)
- (local.get $x)
- (i32.const 1)
- )
- )
- (struct.set $struct.C $named-mut
- (local.get $struct.C)
- (f32.const 100)
- )
- (struct.set $nested-child-struct 0
- (local.get $nested-child-struct)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (struct.new_default $struct.A)
- )
- (drop
- (struct.new $struct.A
- (i32.const 1)
- (f32.const 2.3450000286102295)
- (f64.const 3.14159)
- )
- )
- (unreachable)
- )
- (func $arrays (type $ref|$vector|_ref?|$nested-child-array|_ref?|$grandchild|_=>_ref|$matrix|) (param $x (ref $vector)) (param $nested-child-array (ref null $nested-child-array)) (param $grandchild (ref null $grandchild)) (result (ref $matrix))
- (local $tv (ref null $vector))
- (local $tm (ref null $matrix))
- (local $tb (ref null $bytes))
- (local $tw (ref null $words))
- (drop
- (array.new $vector
- (f64.const 3.14159)
- (i32.const 3)
- )
- )
- (drop
- (array.new_default $matrix
- (i32.const 10)
- )
- )
- (drop
- (array.get $vector
- (local.get $x)
- (i32.const 2)
- )
- )
- (array.set $vector
- (local.get $x)
- (i32.const 2)
- (f64.const 2.18281828)
- )
- (array.set $nested-child-array
- (local.get $nested-child-array)
- (i32.const 3)
- (ref.as_non_null
- (local.get $grandchild)
- )
- )
- (drop
- (array.len
- (local.get $x)
- )
- )
- (drop
- (array.get $words
- (local.get $tw)
- (i32.const 1)
- )
- )
- (drop
- (array.get_u $bytes
- (local.get $tb)
- (i32.const 2)
- )
- )
- (drop
- (array.get_s $bytes
- (local.get $tb)
- (i32.const 3)
- )
- )
- (unreachable)
- )
- (func $ref.is_X (type $anyref_=>_none) (param $x anyref)
- (if
- (ref.is_null
- (local.get $x)
- )
- (unreachable)
- )
- (if
- (ref.test i31
- (local.get $x)
- )
- (unreachable)
- )
- )
- (func $ref.as_X (type $anyref_funcref_=>_none) (param $x anyref) (param $f funcref)
- (drop
- (ref.as_non_null
- (local.get $x)
- )
- )
- (drop
- (ref.cast func
- (local.get $f)
- )
- )
- (drop
- (ref.cast i31
- (local.get $x)
- )
- )
- )
- (func $br_on_X (type $anyref_=>_none) (param $x anyref)
- (local $y anyref)
- (local $z anyref)
- (local $temp-func funcref)
- (local $temp-i31 i31ref)
- (block $label$1
- (local.set $z
- (br_on_null $label$1
- (local.get $x)
- )
- )
- )
- (drop
- (block $label$2 (result i31ref)
- (local.set $y
- (br_on_cast $label$2 anyref (ref i31)
- (local.get $x)
- )
- )
- (ref.null none)
- )
- )
- (drop
- (block $label$3 (result (ref any))
- (br_on_non_null $label$3
- (local.get $x)
- )
- (unreachable)
- )
- )
- (drop
- (block $label$4 (result anyref)
- (local.set $temp-i31
- (br_on_cast_fail $label$4 anyref (ref i31)
- (local.get $x)
- )
- )
- (ref.null none)
- )
- )
- )
- (func $unreachables-1 (type $none_=>_none)
- (unreachable)
- )
- (func $unreachables-2 (type $ref?|$struct.C|_=>_none) (param $struct.C (ref null $struct.C))
- (drop
- (local.get $struct.C)
- )
- (unreachable)
- )
- (func $unreachables-3 (type $none_=>_none)
- (unreachable)
- )
- (func $unreachables-4 (type $none_=>_none)
- (unreachable)
- )
- (func $unreachables-array-1 (type $none_=>_none)
- (unreachable)
- )
- (func $unreachables-array-2 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (drop
- (local.get $vector)
- )
- (unreachable)
- )
- (func $unreachables-array-3 (type $none_=>_none)
- (unreachable)
- )
- (func $unreachables-array-4 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (drop
- (local.get $vector)
- )
- (unreachable)
- )
- (func $unreachables-array-5 (type $ref?|$vector|_=>_none) (param $vector (ref null $vector))
- (drop
- (local.get $vector)
- )
- (drop
- (i32.const 2)
- )
- (unreachable)
- )
- (func $unreachables-array-6 (type $none_=>_none)
- (unreachable)
- )
- (func $array-copy (type $ref|$vector|_ref?|$vector|_=>_none) (param $x (ref $vector)) (param $y (ref null $vector))
- (array.copy $vector $vector
- (local.get $x)
- (i32.const 11)
- (local.get $y)
- (i32.const 42)
- (i32.const 1337)
- )
- )
- (func $array-init (type $none_=>_ref|$vector|) (result (ref $vector))
- (array.new_fixed $vector
- (f64.const 1)
- (f64.const 2)
- (f64.const 4)
- (f64.const 8)
- )
- )
- (func $array-init-packed (type $none_=>_ref|$bytes|) (result (ref $bytes))
- (array.new_fixed $bytes
- (i32.const 4)
- (i32.const 2)
- (i32.const 1)
- )
- )
- (func $static-operations (type $none_=>_none)
- (local $temp.A (ref null $struct.A))
- (local $temp.B (ref null $struct.B))
- (drop
- (ref.test $struct.B
- (ref.null none)
- )
- )
- (drop
- (ref.cast null none
- (ref.null none)
- )
- )
- (drop
- (block $label$1 (result (ref $struct.B))
- (local.set $temp.A
- (br_on_cast $label$1 nullref (ref $struct.B)
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- (drop
- (block $label$2 (result (ref null $struct.A))
- (local.set $temp.B
- (br_on_cast_fail $label$2 nullref (ref $struct.B)
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- )
-)
-
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
deleted file mode 100644
index 904caa825..000000000
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ /dev/null
@@ -1,353 +0,0 @@
-(module
- (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64)))
- (type $[mut:f64] (array (mut f64)))
- (type ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref ${i32_f32_f64})) (field (mut (ref ${i32_f32_f64})))))
- (type $none_=>_none (func))
- (type $[mut:ref?|[mut:f64]|] (array (mut (ref null $[mut:f64]))))
- (type $[mut:i8] (array (mut i8)))
- (type ${mut:f32} (struct (field (mut f32))))
- (type ${} (struct ))
- (type ${i32} (sub ${} (struct (field i32))))
- (type ${i32_i64} (sub ${i32} (struct (field i32) (field i64))))
- (type $ref?|[mut:f64]|_=>_none (func (param (ref null $[mut:f64]))))
- (type ${mut:ref|{i32}|} (struct (field (mut (ref ${i32})))))
- (type $[mut:i32] (array (mut i32)))
- (type $[mut:ref|{i32}|] (array (mut (ref ${i32}))))
- (type $anyref_=>_none (func (param anyref)))
- (type $ref|{i32_f32_f64}|_ref?|{i32_f32_f64}|_ref?|{i32_i64}|_ref?|{mut:f32}|_ref?|{mut:ref|{i32}|}|_=>_ref|{i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}| (func (param (ref ${i32_f32_f64}) (ref null ${i32_f32_f64}) (ref null ${i32_i64}) (ref null ${mut:f32}) (ref null ${mut:ref|{i32}|})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))))
- (type $ref|[mut:f64]|_ref?|[mut:ref|{i32}|]|_ref?|{i32_i64}|_=>_ref|[mut:ref?|[mut:f64]|]| (func (param (ref $[mut:f64]) (ref null $[mut:ref|{i32}|]) (ref null ${i32_i64})) (result (ref $[mut:ref?|[mut:f64]|]))))
- (type $anyref_funcref_=>_none (func (param anyref funcref)))
- (type $ref?|{mut:f32}|_=>_none (func (param (ref null ${mut:f32}))))
- (type $ref|[mut:f64]|_ref?|[mut:f64]|_=>_none (func (param (ref $[mut:f64]) (ref null $[mut:f64]))))
- (type $none_=>_ref|[mut:f64]| (func (result (ref $[mut:f64]))))
- (type $none_=>_ref|[mut:i8]| (func (result (ref $[mut:i8]))))
- (global $global$0 (ref ${i32_f32_f64}) (struct.new_default ${i32_f32_f64}))
- (func $0 (type $ref|{i32_f32_f64}|_ref?|{i32_f32_f64}|_ref?|{i32_i64}|_ref?|{mut:f32}|_ref?|{mut:ref|{i32}|}|_=>_ref|{i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}|) (param $0 (ref ${i32_f32_f64})) (param $1 (ref null ${i32_f32_f64})) (param $2 (ref null ${i32_i64})) (param $3 (ref null ${mut:f32})) (param $4 (ref null ${mut:ref|{i32}|})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))
- (local $5 (ref null ${i32_f32_f64}))
- (local $6 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))
- (local $7 (ref null ${mut:f32}))
- (local $8 (ref null $[mut:f64]))
- (local $9 (ref null $[mut:ref?|[mut:f64]|]))
- (drop
- (local.get $0)
- )
- (drop
- (struct.get ${i32_f32_f64} 0
- (local.get $0)
- )
- )
- (drop
- (struct.get ${i32_f32_f64} 1
- (local.get $0)
- )
- )
- (drop
- (struct.get ${i32_f32_f64} 2
- (local.get $0)
- )
- )
- (drop
- (struct.get ${i32_f32_f64} 2
- (local.get $0)
- )
- )
- (drop
- (struct.get ${i32_f32_f64} 2
- (local.get $1)
- )
- )
- (drop
- (struct.get_u ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} 0
- (local.get $6)
- )
- )
- (drop
- (struct.get_s ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} 0
- (local.get $6)
- )
- )
- (drop
- (struct.get ${i32_i64} 0
- (local.get $2)
- )
- )
- (drop
- (local.get $0)
- )
- (drop
- (if (result (ref null ${i32_f32_f64}))
- (i32.const 1)
- (local.get $0)
- (local.get $0)
- )
- )
- (drop
- (loop $label$3 (result (ref null ${i32_f32_f64}))
- (local.get $0)
- )
- )
- (drop
- (select (result (ref null ${i32_f32_f64}))
- (local.get $0)
- (local.get $0)
- (i32.const 1)
- )
- )
- (struct.set ${mut:f32} 0
- (local.get $3)
- (f32.const 100)
- )
- (struct.set ${mut:ref|{i32}|} 0
- (local.get $4)
- (ref.as_non_null
- (local.get $2)
- )
- )
- (drop
- (struct.new_default ${i32_f32_f64})
- )
- (drop
- (struct.new ${i32_f32_f64}
- (i32.const 1)
- (f32.const 2.3450000286102295)
- (f64.const 3.14159)
- )
- )
- (unreachable)
- )
- (func $1 (type $ref|[mut:f64]|_ref?|[mut:ref|{i32}|]|_ref?|{i32_i64}|_=>_ref|[mut:ref?|[mut:f64]|]|) (param $0 (ref $[mut:f64])) (param $1 (ref null $[mut:ref|{i32}|])) (param $2 (ref null ${i32_i64})) (result (ref $[mut:ref?|[mut:f64]|]))
- (local $3 (ref null $[mut:f64]))
- (local $4 (ref null $[mut:ref?|[mut:f64]|]))
- (local $5 (ref null $[mut:i8]))
- (local $6 (ref null $[mut:i32]))
- (drop
- (array.new $[mut:f64]
- (f64.const 3.14159)
- (i32.const 3)
- )
- )
- (drop
- (array.new_default $[mut:ref?|[mut:f64]|]
- (i32.const 10)
- )
- )
- (drop
- (array.get $[mut:f64]
- (local.get $0)
- (i32.const 2)
- )
- )
- (array.set $[mut:f64]
- (local.get $0)
- (i32.const 2)
- (f64.const 2.18281828)
- )
- (array.set $[mut:ref|{i32}|]
- (local.get $1)
- (i32.const 3)
- (ref.as_non_null
- (local.get $2)
- )
- )
- (drop
- (array.len
- (local.get $0)
- )
- )
- (drop
- (array.get $[mut:i32]
- (local.get $6)
- (i32.const 1)
- )
- )
- (drop
- (array.get_u $[mut:i8]
- (local.get $5)
- (i32.const 2)
- )
- )
- (drop
- (array.get_s $[mut:i8]
- (local.get $5)
- (i32.const 3)
- )
- )
- (unreachable)
- )
- (func $2 (type $anyref_=>_none) (param $0 anyref)
- (if
- (ref.is_null
- (local.get $0)
- )
- (unreachable)
- )
- (if
- (ref.test i31
- (local.get $0)
- )
- (unreachable)
- )
- )
- (func $3 (type $anyref_funcref_=>_none) (param $0 anyref) (param $1 funcref)
- (drop
- (ref.as_non_null
- (local.get $0)
- )
- )
- (drop
- (ref.cast func
- (local.get $1)
- )
- )
- (drop
- (ref.cast i31
- (local.get $0)
- )
- )
- )
- (func $4 (type $anyref_=>_none) (param $0 anyref)
- (local $1 anyref)
- (local $2 anyref)
- (local $3 funcref)
- (local $4 i31ref)
- (block $label$1
- (local.set $2
- (br_on_null $label$1
- (local.get $0)
- )
- )
- )
- (drop
- (block $label$2 (result i31ref)
- (local.set $1
- (br_on_cast $label$2 anyref (ref i31)
- (local.get $0)
- )
- )
- (ref.null none)
- )
- )
- (drop
- (block $label$3 (result (ref any))
- (br_on_non_null $label$3
- (local.get $0)
- )
- (unreachable)
- )
- )
- (drop
- (block $label$4 (result anyref)
- (local.set $4
- (br_on_cast_fail $label$4 anyref (ref i31)
- (local.get $0)
- )
- )
- (ref.null none)
- )
- )
- )
- (func $5 (type $none_=>_none)
- (unreachable)
- )
- (func $6 (type $ref?|{mut:f32}|_=>_none) (param $0 (ref null ${mut:f32}))
- (drop
- (local.get $0)
- )
- (unreachable)
- )
- (func $7 (type $none_=>_none)
- (unreachable)
- )
- (func $8 (type $none_=>_none)
- (unreachable)
- )
- (func $9 (type $none_=>_none)
- (unreachable)
- )
- (func $10 (type $ref?|[mut:f64]|_=>_none) (param $0 (ref null $[mut:f64]))
- (drop
- (local.get $0)
- )
- (unreachable)
- )
- (func $11 (type $none_=>_none)
- (unreachable)
- )
- (func $12 (type $ref?|[mut:f64]|_=>_none) (param $0 (ref null $[mut:f64]))
- (drop
- (local.get $0)
- )
- (unreachable)
- )
- (func $13 (type $ref?|[mut:f64]|_=>_none) (param $0 (ref null $[mut:f64]))
- (drop
- (local.get $0)
- )
- (drop
- (i32.const 2)
- )
- (unreachable)
- )
- (func $14 (type $none_=>_none)
- (unreachable)
- )
- (func $15 (type $ref|[mut:f64]|_ref?|[mut:f64]|_=>_none) (param $0 (ref $[mut:f64])) (param $1 (ref null $[mut:f64]))
- (array.copy $[mut:f64] $[mut:f64]
- (local.get $0)
- (i32.const 11)
- (local.get $1)
- (i32.const 42)
- (i32.const 1337)
- )
- )
- (func $16 (type $none_=>_ref|[mut:f64]|) (result (ref $[mut:f64]))
- (array.new_fixed $[mut:f64]
- (f64.const 1)
- (f64.const 2)
- (f64.const 4)
- (f64.const 8)
- )
- )
- (func $17 (type $none_=>_ref|[mut:i8]|) (result (ref $[mut:i8]))
- (array.new_fixed $[mut:i8]
- (i32.const 4)
- (i32.const 2)
- (i32.const 1)
- )
- )
- (func $18 (type $none_=>_none)
- (local $0 (ref null ${i32_f32_f64}))
- (local $1 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))
- (drop
- (ref.test ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}
- (ref.null none)
- )
- )
- (drop
- (ref.cast null none
- (ref.null none)
- )
- )
- (drop
- (block $label$1 (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))
- (local.set $0
- (br_on_cast $label$1 nullref (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- (drop
- (block $label$2 (result (ref null ${i32_f32_f64}))
- (local.set $1
- (br_on_cast_fail $label$2 nullref (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})
- (ref.null none)
- )
- )
- (unreachable)
- )
- )
- )
-)
-
diff --git a/test/lit/binary/annotated-array-len.test b/test/lit/binary/annotated-array-len.test
deleted file mode 100644
index 9cf6eecbe..000000000
--- a/test/lit/binary/annotated-array-len.test
+++ /dev/null
@@ -1,18 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
-
-;; Test the we can properly parse the annotated array.len format that we no
-;; longer emit.
-
-;; RUN: wasm-dis %s.wasm -all | filecheck %s
-
-;; CHECK: (type $none_=>_i32 (func (result i32)))
-
-;; CHECK: (type $[mut:i8] (array (mut i8)))
-
-;; CHECK: (func $0 (type $none_=>_i32) (result i32)
-;; CHECK-NEXT: (array.len
-;; CHECK-NEXT: (array.new_default $[mut:i8]
-;; CHECK-NEXT: (i32.const 0)
-;; CHECK-NEXT: )
-;; CHECK-NEXT: )
-;; CHECK-NEXT: )
diff --git a/test/lit/binary/annotated-array-len.test.wasm b/test/lit/binary/annotated-array-len.test.wasm
deleted file mode 100644
index b199f58de..000000000
--- a/test/lit/binary/annotated-array-len.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/binary/bad-ref-as.test b/test/lit/binary/bad-ref-as.test
deleted file mode 100644
index 3accdd553..000000000
--- a/test/lit/binary/bad-ref-as.test
+++ /dev/null
@@ -1,5 +0,0 @@
-;; Test that we error properly on a file with a ref.as of a non-ref type.
-
-;; RUN: not wasm-opt -all %s.wasm 2>&1 | filecheck %s
-
-;; CHECK: ref.cast ref must have ref type
diff --git a/test/lit/binary/bad-ref-as.test.wasm b/test/lit/binary/bad-ref-as.test.wasm
deleted file mode 100644
index 637537dd2..000000000
--- a/test/lit/binary/bad-ref-as.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/legacy-static-casts.wast b/test/lit/legacy-static-casts.wast
deleted file mode 100644
index 893fb0a33..000000000
--- a/test/lit/legacy-static-casts.wast
+++ /dev/null
@@ -1,47 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
-
-;; Check that the deprecated *_static instruction names are still parsed correctly.
-
-;; RUN: wasm-opt %s -all -S -o - | filecheck %s
-
-(module
- ;; CHECK: (type $none_=>_none (func))
-
- ;; CHECK: (type $struct (struct ))
- (type $struct (struct))
-
- ;; CHECK: (func $test (type $none_=>_none)
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.test $struct
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.cast null none
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.cast_nop none
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- (func $test
- (drop
- (ref.test_static $struct
- (ref.null none)
- )
- )
- (drop
- (ref.cast_static $struct
- (ref.null none)
- )
- )
- (drop
- (ref.cast_nop_static $struct
- (ref.null none)
- )
- )
- )
-)
diff --git a/test/lit/passes/abstract-type-refining.wast b/test/lit/passes/abstract-type-refining.wast
index 220de9656..af2b210fd 100644
--- a/test/lit/passes/abstract-type-refining.wast
+++ b/test/lit/passes/abstract-type-refining.wast
@@ -217,11 +217,6 @@
;; YESTNH-NEXT: (local.get $x)
;; YESTNH-NEXT: )
;; YESTNH-NEXT: )
- ;; YESTNH-NEXT: (drop
- ;; YESTNH-NEXT: (ref.cast i31
- ;; YESTNH-NEXT: (local.get $x)
- ;; YESTNH-NEXT: )
- ;; YESTNH-NEXT: )
;; YESTNH-NEXT: )
;; NO_TNH: (func $basic (type $anyref_=>_none) (param $x anyref)
;; NO_TNH-NEXT: (drop
@@ -229,11 +224,6 @@
;; NO_TNH-NEXT: (local.get $x)
;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
- ;; NO_TNH-NEXT: (drop
- ;; NO_TNH-NEXT: (ref.cast i31
- ;; NO_TNH-NEXT: (local.get $x)
- ;; NO_TNH-NEXT: )
- ;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
(func $basic (param $x anyref)
;; Casts to basic types should not be modified.
@@ -242,11 +232,6 @@
(local.get $x)
)
)
- (drop
- (ref.as_i31
- (local.get $x)
- )
- )
)
;; YESTNH: (func $locals (type $none_=>_none)
diff --git a/test/lit/passes/code-pushing-gc.wast b/test/lit/passes/code-pushing-gc.wast
index 56cfc8777..9587d5ab7 100644
--- a/test/lit/passes/code-pushing-gc.wast
+++ b/test/lit/passes/code-pushing-gc.wast
@@ -7,8 +7,8 @@
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $out (result (ref func))
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br_on_cast $out (ref $none_=>_none) (ref func)
- ;; CHECK-NEXT: (ref.func $br_on)
+ ;; CHECK-NEXT: (br_on_cast $out nullfuncref (ref func)
+ ;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $x
@@ -28,8 +28,8 @@
;; We can push the local.set past the br_on.
(local.set $x (ref.func $br_on))
(drop
- (br_on_func $out
- (ref.func $br_on)
+ (br_on_cast $out funcref (ref func)
+ (ref.null nofunc)
)
)
(drop
@@ -48,8 +48,8 @@
;; CHECK-NEXT: (ref.func $br_on_no)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br_on_cast $out (ref $none_=>_none) (ref func)
- ;; CHECK-NEXT: (ref.func $br_on_no)
+ ;; CHECK-NEXT: (br_on_cast $out nullfuncref (ref func)
+ ;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.func $br_on_no)
@@ -61,13 +61,13 @@
;; CHECK-NEXT: )
(func $br_on_no
(local $x (ref null func))
- ;; We can't push here since the local.get is outside of the loop.
+ ;; We can't push here since the local.get is outside of the block.
(drop
(block $out (result (ref func))
(local.set $x (ref.func $br_on_no))
(drop
- (br_on_func $out
- (ref.func $br_on_no)
+ (br_on_cast $out funcref (ref func)
+ (ref.null nofunc)
)
)
(ref.func $br_on_no)
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index 7c7aa8c40..b82fbf148 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -54,7 +54,7 @@
(ref.is_null
(loop $loop (result (ref func))
(nop)
- (ref.as_func
+ (ref.cast func
(ref.as_non_null
(ref.null func)
)
diff --git a/test/lit/passes/merge-blocks.wast b/test/lit/passes/merge-blocks.wast
index 2b3afa771..02772c9b6 100644
--- a/test/lit/passes/merge-blocks.wast
+++ b/test/lit/passes/merge-blocks.wast
@@ -34,7 +34,7 @@
(block $label$1 (result (ref null i31)) ;; this block type must stay, we
;; cannot remove it due to the br_on
(drop
- (br_on_i31 $label$1
+ (br_on_cast $label$1 anyref (ref i31)
(ref.null any)
)
)
diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast
index 831d229a2..155ac82cf 100644
--- a/test/lit/passes/optimize-instructions-gc-tnh.wast
+++ b/test/lit/passes/optimize-instructions-gc-tnh.wast
@@ -146,7 +146,7 @@
;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
(func $ref.is_b (param $a eqref) (param $f funcref) (result i32)
- ;; Here we only have a cast, and no ref.as operations that force the value
+ ;; Here we only have a cast, and no cast operations that force the value
;; to be non-nullable. That means we cannot remove the ref.is, but we can
;; remove the cast in TNH.
(drop
@@ -164,28 +164,56 @@
)
)
- ;; TNH: (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32)
+ ;; TNH: (func $ref.test (type $eqref_=>_i32) (param $a eqref) (result i32)
;; TNH-NEXT: (drop
- ;; TNH-NEXT: (ref.as_non_null
- ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: (block (result i32)
+ ;; TNH-NEXT: (drop
+ ;; TNH-NEXT: (ref.cast null i31
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: (i32.const 1)
;; TNH-NEXT: )
;; TNH-NEXT: )
- ;; TNH-NEXT: (i32.const 1)
+ ;; TNH-NEXT: (block (result i32)
+ ;; TNH-NEXT: (drop
+ ;; TNH-NEXT: (ref.as_non_null
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: (i32.const 1)
+ ;; TNH-NEXT: )
;; TNH-NEXT: )
- ;; NO_TNH: (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32)
+ ;; NO_TNH: (func $ref.test (type $eqref_=>_i32) (param $a eqref) (result i32)
;; NO_TNH-NEXT: (drop
- ;; NO_TNH-NEXT: (ref.as_non_null
- ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: (block (result i32)
+ ;; NO_TNH-NEXT: (drop
+ ;; NO_TNH-NEXT: (ref.cast null i31
+ ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: (i32.const 1)
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: (block (result i32)
+ ;; NO_TNH-NEXT: (drop
+ ;; NO_TNH-NEXT: (ref.as_non_null
+ ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: (i32.const 1)
;; NO_TNH-NEXT: )
- ;; NO_TNH-NEXT: (i32.const 1)
;; NO_TNH-NEXT: )
- (func $ref.is_func (param $a funcref) (result i32)
- ;; The check must succeed. We can return 1 here, and drop the rest, with or
- ;; without TNH (in particular, TNH should not just remove the cast but not
- ;; return a 1).
- (ref.is_func
- (ref.as_func
+ (func $ref.test (param $a eqref) (result i32)
+ (drop
+ (ref.test null i31
+ (ref.cast null i31
+ (local.get $a)
+ )
+ )
+ )
+ (ref.test eq
+ (ref.cast eq
(local.get $a)
)
)
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index 34070487b..9f33c55a3 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -122,8 +122,8 @@
)
;; ref.is_null is not needed on a non-nullable value, and if something is
- ;; a func we don't need that either etc. if we know the result
- ;; CHECK: (func $unneeded_is (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
+ ;; cast to its own type, we don't need that either, etc.
+ ;; CHECK: (func $unneeded_test (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (drop
@@ -149,7 +149,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $unneeded_is
+ (func $unneeded_test
(param $struct (ref $struct))
(param $func (ref func))
(param $i31 (ref i31))
@@ -157,16 +157,16 @@
(ref.is_null (local.get $struct))
)
(drop
- (ref.is_func (local.get $func))
+ (ref.test func (local.get $func))
)
(drop
- (ref.is_i31 (local.get $i31))
+ (ref.test i31 (local.get $i31))
)
)
;; similar to $unneeded_is, but the values are nullable. we can at least
;; leave just the null check.
- ;; CHECK: (func $unneeded_is_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
+ ;; CHECK: (func $unneeded_test_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $struct)
@@ -187,7 +187,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $unneeded_is_null
+ (func $unneeded_test_null
(param $struct (ref null $struct))
(param $func (ref null func))
(param $i31 (ref null i31))
@@ -197,17 +197,17 @@
;; This can be optimized to !is_null rather than ref.test func, since we
;; know the heap type is what we want, so the only possible issue is a null.
(drop
- (ref.is_func (local.get $func))
+ (ref.test func (local.get $func))
)
;; This can be optimized similarly.
(drop
- (ref.is_i31 (local.get $i31))
+ (ref.test i31 (local.get $i31))
)
)
;; ref.as_non_null is not needed on a non-nullable value, and if something is
;; a func we don't need that either etc., and can just return the value.
- ;; CHECK: (func $unneeded_as (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
+ ;; CHECK: (func $unneeded_cast (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $struct)
;; CHECK-NEXT: )
@@ -218,7 +218,7 @@
;; CHECK-NEXT: (local.get $i31)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $unneeded_as
+ (func $unneeded_cast
(param $struct (ref $struct))
(param $func (ref func))
(param $i31 (ref i31))
@@ -226,16 +226,16 @@
(ref.as_non_null (local.get $struct))
)
(drop
- (ref.as_func (local.get $func))
+ (ref.cast func (local.get $func))
)
(drop
- (ref.as_i31 (local.get $i31))
+ (ref.cast i31 (local.get $i31))
)
)
- ;; similar to $unneeded_as, but the values are nullable. we can turn the
+ ;; similar to $unneeded_cast, but the values are nullable. we can turn the
;; more specific things into ref.as_non_null.
- ;; CHECK: (func $unneeded_as_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
+ ;; CHECK: (func $unneeded_cast_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (local.get $struct)
@@ -252,7 +252,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $unneeded_as_null
+ (func $unneeded_cast_null
(param $struct (ref null $struct))
(param $func (ref null func))
(param $i31 (ref null i31))
@@ -260,10 +260,10 @@
(ref.as_non_null (local.get $struct))
)
(drop
- (ref.as_func (local.get $func))
+ (ref.cast func (local.get $func))
)
(drop
- (ref.as_i31 (local.get $i31))
+ (ref.cast i31 (local.get $i31))
)
)
@@ -285,10 +285,10 @@
(func $unneeded_unreachability
;; unreachable instructions can simply be ignored
(drop
- (ref.is_func (unreachable))
+ (ref.test func (unreachable))
)
(drop
- (ref.as_func (unreachable))
+ (ref.cast func (unreachable))
)
)
@@ -617,7 +617,7 @@
;; This will trap, so we can emit an unreachable.
(drop
(ref.cast $struct
- (ref.as_i31
+ (ref.cast i31
(local.get $x)
)
)
diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast
index e063fa482..50ffd9583 100644
--- a/test/lit/passes/remove-unused-brs-gc.wast
+++ b/test/lit/passes/remove-unused-brs-gc.wast
@@ -11,57 +11,6 @@
(type $struct2 (struct))
)
- ;; CHECK: (func $br_on_non_i31-1 (type $none_=>_none)
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $any (result (ref null $struct))
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br $any
- ;; CHECK-NEXT: (struct.new_default $struct)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- (func $br_on_non_i31-1
- (drop
- (block $any (result anyref)
- (drop
- ;; An struct is not an i31, and so we should branch.
- (br_on_non_i31 $any
- (struct.new $struct)
- )
- )
- (ref.null any)
- )
- )
- )
- ;; CHECK: (func $br_on_non_i31-2 (type $none_=>_none)
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $any (result nullref)
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (i31.new
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- (func $br_on_non_i31-2
- (drop
- (block $any (result anyref)
- (drop
- ;; An i31 is provided here, and so we will not branch.
- (br_on_non_i31 $any
- (i31.new (i32.const 0))
- )
- )
- (ref.null any)
- )
- )
- )
-
;; CHECK: (func $br_on-if (type $ref|struct|_=>_none) (param $0 (ref struct))
;; CHECK-NEXT: (block $label
;; CHECK-NEXT: (drop
@@ -93,51 +42,51 @@
)
)
- ;; CHECK: (func $nested_br_on (type $none_=>_i31ref) (result i31ref)
- ;; CHECK-NEXT: (block $label$1 (result (ref i31))
+ ;; CHECK: (func $br_on_cast (type $none_=>_ref|$struct|) (result (ref $struct))
+ ;; CHECK-NEXT: (block $block (result (ref $struct))
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br $label$1
- ;; CHECK-NEXT: (i31.new
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $block
+ ;; CHECK-NEXT: (struct.new_default $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $nested_br_on (result i31ref)
- (block $label$1 (result i31ref)
+ (func $br_on_cast (result (ref $struct))
+ (block $block (result (ref $struct))
(drop
- ;; The inner br_on_i31 will become a direct br since the type proves it
- ;; is in fact data. That then becomes unreachable, and the parent must
- ;; handle that properly (do nothing without hitting an assertion).
- (br_on_i31 $label$1
- (br_on_i31 $label$1
- (i31.new (i32.const 0))
- )
+ ;; This static cast can be computed at compile time: it will definitely be
+ ;; taken, so we can turn it into a normal br.
+ (br_on_cast $block anyref (ref $struct)
+ (struct.new $struct)
)
)
(unreachable)
)
)
- ;; CHECK: (func $br_on_cast (type $none_=>_ref|$struct|) (result (ref $struct))
- ;; CHECK-NEXT: (block $block (result (ref $struct))
+ ;; CHECK: (func $nested_br_on_cast (type $none_=>_i31ref) (result i31ref)
+ ;; CHECK-NEXT: (block $label$1 (result (ref i31))
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br $block
- ;; CHECK-NEXT: (struct.new_default $struct)
+ ;; CHECK-NEXT: (br $label$1
+ ;; CHECK-NEXT: (i31.new
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $br_on_cast (result (ref $struct))
- (block $block (result (ref $struct))
+ (func $nested_br_on_cast (result i31ref)
+ (block $label$1 (result i31ref)
(drop
- ;; This static cast can be computed at compile time: it will definitely be
- ;; taken, so we can turn it into a normal br.
- (br_on_cast $block anyref (ref $struct)
- (struct.new $struct)
+ ;; The inner br_on_cast will become a direct br since the type proves it
+ ;; is in fact i31. That then becomes unreachable, and the parent must
+ ;; handle that properly (do nothing without hitting an assertion).
+ (br_on_cast $label$1 (ref any) (ref i31)
+ (br_on_cast $label$1 (ref any) (ref i31)
+ (i31.new (i32.const 0))
+ )
)
)
(unreachable)
diff --git a/test/lit/passes/remove-unused-brs_all-features.wast b/test/lit/passes/remove-unused-brs_all-features.wast
index 8ca632040..c93f25df2 100644
--- a/test/lit/passes/remove-unused-brs_all-features.wast
+++ b/test/lit/passes/remove-unused-brs_all-features.wast
@@ -8,10 +8,10 @@
(type $vector (array (mut i32)))
;; CHECK: (type $struct (struct (field (ref null $vector))))
(type $struct (struct (field (ref null $vector))))
- ;; CHECK: (type $ref|func|_=>_none (func (param (ref func))))
-
;; CHECK: (type $i32_=>_none (func (param i32)))
+ ;; CHECK: (type $none_=>_funcref (func (result funcref)))
+
;; CHECK: (type $none_=>_ref?|$struct| (func (result (ref null $struct))))
;; CHECK: (type $none_=>_f64 (func (result f64)))
@@ -20,9 +20,11 @@
;; CHECK: (type $i32_=>_funcref (func (param i32) (result funcref)))
+ ;; CHECK: (type $none_=>_none (func))
+
;; CHECK: (import "out" "log" (func $log (type $i32_=>_none) (param i32)))
(import "out" "log" (func $log (param i32)))
- ;; CHECK: (elem declare func $br_on-to-br $i32_=>_none $none_=>_i32)
+ ;; CHECK: (elem declare func $br_on_non_null $br_on_null $i32_=>_none $none_=>_i32)
;; CHECK: (func $foo (type $none_=>_ref?|$struct|) (result (ref null $struct))
;; CHECK-NEXT: (if (result (ref null $struct))
@@ -116,110 +118,57 @@
)
)
- ;; CHECK: (func $br_on-to-br (type $ref|func|_=>_none) (param $func (ref func))
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: )
+ ;; CHECK: (func $br_on_null (type $none_=>_none)
;; CHECK-NEXT: (block $null
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.func $br_on-to-br)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 1)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 2)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $func (result (ref $ref|func|_=>_none))
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br $func
- ;; CHECK-NEXT: (ref.func $br_on-to-br)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 3)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (ref.func $br_on-to-br)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 4)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $i31 (result (ref i31))
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (br $i31
- ;; CHECK-NEXT: (i31.new
- ;; CHECK-NEXT: (i32.const 42)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 5)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (i31.new
- ;; CHECK-NEXT: (i32.const 1337)
+ ;; CHECK-NEXT: (br_on_null $null
+ ;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 6)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $non-null (result (ref $ref|func|_=>_none))
- ;; CHECK-NEXT: (br $non-null
- ;; CHECK-NEXT: (ref.func $br_on-to-br)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $log
- ;; CHECK-NEXT: (i32.const 7)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (ref.func $br_on-to-br)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.func $br_on_null)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $br_on-to-br (param $func (ref func))
- (call $log (i32.const 0))
+ (func $br_on_null
(block $null
- ;; a non-null reference is not null, and the br is never taken
+ ;; A null reference to bottom is definitely null, and the br is always taken.
+ ;; TODO: Optimize this.
(drop
- (br_on_null $null (ref.func $br_on-to-br))
+ (br_on_null $null (ref.null nofunc))
)
- (call $log (i32.const 1))
- )
- (call $log (i32.const 2))
- (drop
- (block $func (result funcref)
- ;; a non-null function reference means we always take the br
- (drop
- (br_on_func $func (ref.func $br_on-to-br))
- )
- (call $log (i32.const 3))
- (ref.func $br_on-to-br)
+ ;; On the other hand, if we know the input is not null, the branch will never
+ ;; be taken.
+ (drop
+ (br_on_null $null (ref.func $br_on_null))
)
)
- (call $log (i32.const 4))
- (drop
- (block $i31 (result i31ref)
- ;; a non-null i31 reference means we always take the br
- (drop
- (br_on_i31 $i31
- (i31.new (i32.const 42))
- )
- )
- (call $log (i32.const 5))
- (i31.new (i32.const 1337))
+ )
+
+ ;; CHECK: (func $br_on_non_null (type $none_=>_funcref) (result funcref)
+ ;; CHECK-NEXT: (block $non-null (result (ref $none_=>_funcref))
+ ;; CHECK-NEXT: (br $non-null
+ ;; CHECK-NEXT: (ref.func $br_on_non_null)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_on_non_null $non-null
+ ;; CHECK-NEXT: (ref.null nofunc)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.func $br_on_non_null)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br_on_non_null (result funcref)
+ (block $non-null (result (ref func))
+ ;; A non-null reference is not null, and the br is always taken.
+ (br_on_non_null $non-null
+ (ref.func $br_on_non_null)
)
- )
- (call $log (i32.const 6))
- (drop
- (block $non-null (result (ref func))
- ;; a non-null reference is not null, and the br is always taken
- (br_on_non_null $non-null (ref.func $br_on-to-br))
- (call $log (i32.const 7))
- (ref.func $br_on-to-br)
+ ;; On the other hand, if we know the input is null, the branch will never be
+ ;; taken.
+ ;; TODO: Optimize this.
+ (br_on_non_null $non-null
+ (ref.null nofunc)
)
+ (ref.func $br_on_non_null)
)
)
)
diff --git a/test/lit/passes/vacuum-gc.wast b/test/lit/passes/vacuum-gc.wast
index 69dbe0b89..fcdeb8cd2 100644
--- a/test/lit/passes/vacuum-gc.wast
+++ b/test/lit/passes/vacuum-gc.wast
@@ -18,13 +18,13 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.cast i31
+ ;; CHECK-NEXT: (ref.cast null i31
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $drop-ref-as (param $x anyref)
- ;; Without -tnh, we must assume all ref_as* can have a trap effect, and so
+ ;; Without -tnh, we must assume all casts can have a trap effect, and so
;; we cannot remove anything here.
(drop
(ref.as_non_null
@@ -32,7 +32,7 @@
)
)
(drop
- (ref.as_i31
+ (ref.cast null i31
(local.get $x)
)
)
diff --git a/test/lit/passes/vacuum-tnh.wast b/test/lit/passes/vacuum-tnh.wast
index f60c4c5cb..c3de8c21c 100644
--- a/test/lit/passes/vacuum-tnh.wast
+++ b/test/lit/passes/vacuum-tnh.wast
@@ -33,7 +33,7 @@
;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: (drop
- ;; NO_TNH-NEXT: (ref.cast i31
+ ;; NO_TNH-NEXT: (ref.cast null i31
;; NO_TNH-NEXT: (local.get $y)
;; NO_TNH-NEXT: )
;; NO_TNH-NEXT: )
@@ -55,9 +55,9 @@
)
)
- ;; Other ref.as* as well.
+ ;; Other casts as well.
(drop
- (ref.as_i31
+ (ref.cast null i31
(local.get $y)
)
)
diff --git a/test/lit/ref-cast-nop.wast b/test/lit/ref-cast-nop.wast
deleted file mode 100644
index 3b284db04..000000000
--- a/test/lit/ref-cast-nop.wast
+++ /dev/null
@@ -1,29 +0,0 @@
-;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
-
-;; RUN: wasm-opt -all %s -S --roundtrip -o - | filecheck %s
-
-(module
- ;; CHECK: (type $struct (struct (field i32)))
- (type $struct (struct i32))
- ;; CHECK: (func $ref.cast_nop (type $ref|any|_=>_ref|$struct|) (param $x (ref any)) (result (ref $struct))
- ;; CHECK-NEXT: (ref.cast_nop $struct
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- (func $ref.cast_nop (param $x (ref any)) (result (ref $struct))
- (ref.cast_nop $struct
- (local.get $x)
- )
- )
-
- ;; CHECK: (func $ref.cast_nop.null (type $ref|any|_=>_ref|none|) (param $x (ref any)) (result (ref none))
- ;; CHECK-NEXT: (ref.cast_nop none
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- (func $ref.cast_nop.null (param $x (ref any)) (result (ref none))
- (ref.cast_nop none
- (local.get $x)
- )
- )
-)
diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast
index 3155c3855..b057e0c16 100644
--- a/test/passes/Oz_fuzz-exec_all-features.wast
+++ b/test/passes/Oz_fuzz-exec_all-features.wast
@@ -179,7 +179,7 @@
)
(func "ref-as-func-of-func"
(drop
- (ref.as_func
+ (ref.cast func
(ref.func $0)
)
)