diff options
90 files changed, 1239 insertions, 4920 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index e43d40dec..bb25dd808 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -340,17 +340,17 @@ def pick_initial_contents(): FEATURE_OPTS += [ # has not been fuzzed in general yet '--disable-memory64', - # avoid multivalue for now due to bad interactions with gc rtts in - # stacky code. for example, this fails to roundtrip as the tuple code - # ends up creating stacky binary code that needs to spill rtts to locals, - # which is not allowed: + # avoid multivalue for now due to bad interactions with gc non-nullable + # locals in stacky code. for example, this fails to roundtrip as the + # tuple code ends up creating stacky binary code that needs to spill + # non-nullable references to locals, which is not allowed: # # (module # (type $other (struct)) - # (func $foo (result (rtt $other)) + # (func $foo (result (ref $other)) # (select - # (rtt.canon $other) - # (rtt.canon $other) + # (struct.new $other) + # (struct.new $other) # (tuple.extract 1 # (tuple.make # (i32.const 0) @@ -1223,9 +1223,10 @@ def randomize_opt_flags(): continue if '--enable-multivalue' in FEATURE_OPTS and '--enable-reference-types' in FEATURE_OPTS: print('avoiding --flatten due to multivalue + reference types not supporting it (spilling of non-nullable tuples)') + print('TODO: Resolving https://github.com/WebAssembly/binaryen/issues/4824 may fix this') continue if '--gc' not in FEATURE_OPTS: - print('avoiding --flatten due to GC not supporting it (spilling of RTTs)') + print('avoiding --flatten due to GC not supporting it (spilling of non-nullable locals)') continue if INITIAL_CONTENTS and os.path.getsize(INITIAL_CONTENTS) > 2000: print('avoiding --flatten due using a large amount of initial contents, which may blow up') diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index e36caf02e..bb56b76e3 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -567,9 +567,7 @@ instructions = [ ("i31.new", "makeI31New(s)"), ("i31.get_s", "makeI31Get(s, true)"), ("i31.get_u", "makeI31Get(s, false)"), - ("ref.test", "makeRefTest(s)"), ("ref.test_static", "makeRefTestStatic(s)"), - ("ref.cast", "makeRefCast(s)"), ("ref.cast_static", "makeRefCastStatic(s)"), ("ref.cast_nop_static", "makeRefCastNopStatic(s)"), ("br_on_null", "makeBrOn(s, BrOnNull)"), @@ -584,22 +582,14 @@ instructions = [ ("br_on_non_data", "makeBrOn(s, BrOnNonData)"), ("br_on_i31", "makeBrOn(s, BrOnI31)"), ("br_on_non_i31", "makeBrOn(s, BrOnNonI31)"), - ("rtt.canon", "makeRttCanon(s)"), - ("rtt.sub", "makeRttSub(s)"), - ("rtt.fresh_sub", "makeRttFreshSub(s)"), - ("struct.new_with_rtt", "makeStructNew(s, false)"), - ("struct.new_default_with_rtt", "makeStructNew(s, true)"), ("struct.new", "makeStructNewStatic(s, false)"), ("struct.new_default", "makeStructNewStatic(s, true)"), ("struct.get", "makeStructGet(s)"), ("struct.get_s", "makeStructGet(s, true)"), ("struct.get_u", "makeStructGet(s, false)"), ("struct.set", "makeStructSet(s)"), - ("array.new_with_rtt", "makeArrayNew(s, false)"), - ("array.new_default_with_rtt", "makeArrayNew(s, true)"), ("array.new", "makeArrayNewStatic(s, false)"), ("array.new_default", "makeArrayNewStatic(s, true)"), - ("array.init", "makeArrayInit(s)"), ("array.init_static", "makeArrayInitStatic(s)"), ("array.get", "makeArrayGet(s)"), ("array.get_s", "makeArrayGet(s, true)"), diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f7e8142f1..1dd9fccd2 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1490,8 +1490,6 @@ BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, // TODO (gc): ref.test // TODO (gc): ref.cast // TODO (gc): br_on_cast -// TODO (gc): rtt.canon -// TODO (gc): rtt.sub // TODO (gc): struct.new // TODO (gc): struct.get // TODO (gc): struct.set @@ -4910,13 +4908,6 @@ BinaryenType TypeBuilderGetTempTupleType(TypeBuilderRef builder, } return ((TypeBuilder*)builder)->getTempTupleType(Tuple(typeList)).getID(); } -BinaryenType TypeBuilderGetTempRttType(TypeBuilderRef builder, - BinaryenIndex depth, - BinaryenHeapType heapType) { - return ((TypeBuilder*)builder) - ->getTempRttType(Rtt(depth, HeapType(heapType))) - .getID(); -} BinaryenType TypeBuilderGetTempRefType(TypeBuilderRef builder, BinaryenHeapType heapType, int nullable) { diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 6a2222f71..f02b2cb19 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -943,8 +943,6 @@ BINARYEN_API BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, // TODO (gc): ref.test // TODO (gc): ref.cast // TODO (gc): br_on_cast -// TODO (gc): rtt.canon -// TODO (gc): rtt.sub // TODO (gc): struct.new // TODO (gc): struct.get // TODO (gc): struct.set @@ -2985,10 +2983,6 @@ BINARYEN_API BinaryenType TypeBuilderGetTempTupleType(TypeBuilderRef builder, BINARYEN_API BinaryenType TypeBuilderGetTempRefType(TypeBuilderRef builder, BinaryenHeapType heapType, int nullable); -// Gets a temporary RTT for use with and owned by the type builder. -BINARYEN_API BinaryenType TypeBuilderGetTempRttType(TypeBuilderRef builder, - BinaryenIndex depth, - BinaryenHeapType heapType); // Sets the type at `index` to be a subtype of the type at `superIndex`. BINARYEN_API void TypeBuilderSetSubType(TypeBuilderRef builder, BinaryenIndex index, diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 301164f87..caf4f5578 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -33,17 +33,9 @@ switch (op[0]) { default: goto parse_error; } } - case 'i': { - switch (op[10]) { - case '\0': - if (strcmp(op, "array.init") == 0) { return makeArrayInit(s); } - goto parse_error; - case '_': - if (strcmp(op, "array.init_static") == 0) { return makeArrayInitStatic(s); } - goto parse_error; - default: goto parse_error; - } - } + case 'i': + if (strcmp(op, "array.init_static") == 0) { return makeArrayInitStatic(s); } + goto parse_error; case 'l': if (strcmp(op, "array.len") == 0) { return makeArrayLen(s); } goto parse_error; @@ -52,25 +44,9 @@ switch (op[0]) { case '\0': if (strcmp(op, "array.new") == 0) { return makeArrayNewStatic(s, false); } goto parse_error; - case '_': { - switch (op[10]) { - case 'd': { - switch (op[17]) { - case '\0': - if (strcmp(op, "array.new_default") == 0) { return makeArrayNewStatic(s, true); } - goto parse_error; - case '_': - if (strcmp(op, "array.new_default_with_rtt") == 0) { return makeArrayNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (strcmp(op, "array.new_with_rtt") == 0) { return makeArrayNew(s, false); } - goto parse_error; - default: goto parse_error; - } - } + case '_': + if (strcmp(op, "array.new_default") == 0) { return makeArrayNewStatic(s, true); } + goto parse_error; default: goto parse_error; } } @@ -2984,113 +2960,92 @@ switch (op[0]) { if (strcmp(op, "pop") == 0) { return makePop(s); } goto parse_error; case 'r': { - switch (op[1]) { - case 'e': { - switch (op[2]) { - case 'f': { - switch (op[4]) { - case 'a': { - switch (op[7]) { - case 'd': - if (strcmp(op, "ref.as_data") == 0) { return makeRefAs(s, RefAsData); } - goto parse_error; - case 'f': - if (strcmp(op, "ref.as_func") == 0) { return makeRefAs(s, RefAsFunc); } - goto parse_error; - case 'i': - if (strcmp(op, "ref.as_i31") == 0) { return makeRefAs(s, RefAsI31); } - goto parse_error; - case 'n': - if (strcmp(op, "ref.as_non_null") == 0) { return makeRefAs(s, RefAsNonNull); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (op[8]) { - case '\0': - if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); } - goto parse_error; - case '_': { - switch (op[9]) { - case 'n': - if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); } - goto parse_error; - case 's': - if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'e': - if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); } + switch (op[2]) { + case 'f': { + switch (op[4]) { + case 'a': { + switch (op[7]) { + case 'd': + if (strcmp(op, "ref.as_data") == 0) { return makeRefAs(s, RefAsData); } goto parse_error; case 'f': - if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); } + if (strcmp(op, "ref.as_func") == 0) { return makeRefAs(s, RefAsFunc); } + goto parse_error; + case 'i': + if (strcmp(op, "ref.as_i31") == 0) { return makeRefAs(s, RefAsI31); } goto parse_error; - case 'i': { - switch (op[7]) { - case 'd': - if (strcmp(op, "ref.is_data") == 0) { return makeRefIs(s, RefIsData); } - goto parse_error; - case 'f': - if (strcmp(op, "ref.is_func") == 0) { return makeRefIs(s, RefIsFunc); } - goto parse_error; - case 'i': - if (strcmp(op, "ref.is_i31") == 0) { return makeRefIs(s, RefIsI31); } - goto parse_error; - case 'n': - if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s, RefIsNull); } - goto parse_error; - default: goto parse_error; - } - } case 'n': - if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } + if (strcmp(op, "ref.as_non_null") == 0) { return makeRefAs(s, RefAsNonNull); } goto parse_error; - case 't': { - switch (op[8]) { - case '\0': - if (strcmp(op, "ref.test") == 0) { return makeRefTest(s); } - goto parse_error; - case '_': - if (strcmp(op, "ref.test_static") == 0) { return makeRefTestStatic(s); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } - case 't': { - switch (op[3]) { - case 'h': - if (strcmp(op, "rethrow") == 0) { return makeRethrow(s); } + case 'c': { + switch (op[9]) { + case 'n': + if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); } goto parse_error; - case 'u': { - switch (op[6]) { + case 's': + if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } + goto parse_error; + default: goto parse_error; + } + } + case 'e': + if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); } + goto parse_error; + case 'f': + if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); } + goto parse_error; + case 'i': { + switch (op[7]) { + case 'd': + if (strcmp(op, "ref.is_data") == 0) { return makeRefIs(s, RefIsData); } + goto parse_error; + case 'f': + if (strcmp(op, "ref.is_func") == 0) { return makeRefIs(s, RefIsFunc); } + goto parse_error; + case 'i': + if (strcmp(op, "ref.is_i31") == 0) { return makeRefIs(s, RefIsI31); } + goto parse_error; + case 'n': + if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s, RefIsNull); } + goto parse_error; + default: goto parse_error; + } + } + case 'n': + if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } + goto parse_error; + case 't': + if (strcmp(op, "ref.test_static") == 0) { return makeRefTestStatic(s); } + goto parse_error; + default: goto parse_error; + } + } + case 't': { + switch (op[3]) { + case 'h': + if (strcmp(op, "rethrow") == 0) { return makeRethrow(s); } + goto parse_error; + case 'u': { + switch (op[6]) { + case '\0': + if (strcmp(op, "return") == 0) { return makeReturn(s); } + goto parse_error; + case '_': { + switch (op[11]) { case '\0': - if (strcmp(op, "return") == 0) { return makeReturn(s); } + if (strcmp(op, "return_call") == 0) { return makeCall(s, /*isReturn=*/true); } goto parse_error; case '_': { - switch (op[11]) { - case '\0': - if (strcmp(op, "return_call") == 0) { return makeCall(s, /*isReturn=*/true); } + switch (op[12]) { + case 'i': + if (strcmp(op, "return_call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/true); } + goto parse_error; + case 'r': + if (strcmp(op, "return_call_ref") == 0) { return makeCallRef(s, /*isReturn=*/true); } goto parse_error; - case '_': { - switch (op[12]) { - case 'i': - if (strcmp(op, "return_call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/true); } - goto parse_error; - case 'r': - if (strcmp(op, "return_call_ref") == 0) { return makeCallRef(s, /*isReturn=*/true); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -3103,20 +3058,6 @@ switch (op[0]) { default: goto parse_error; } } - case 't': { - switch (op[4]) { - case 'c': - if (strcmp(op, "rtt.canon") == 0) { return makeRttCanon(s); } - goto parse_error; - case 'f': - if (strcmp(op, "rtt.fresh_sub") == 0) { return makeRttFreshSub(s); } - goto parse_error; - case 's': - if (strcmp(op, "rtt.sub") == 0) { return makeRttSub(s); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -3321,25 +3262,9 @@ switch (op[0]) { case '\0': if (strcmp(op, "struct.new") == 0) { return makeStructNewStatic(s, false); } goto parse_error; - case '_': { - switch (op[11]) { - case 'd': { - switch (op[18]) { - case '\0': - if (strcmp(op, "struct.new_default") == 0) { return makeStructNewStatic(s, true); } - goto parse_error; - case '_': - if (strcmp(op, "struct.new_default_with_rtt") == 0) { return makeStructNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (strcmp(op, "struct.new_with_rtt") == 0) { return makeStructNew(s, false); } - goto parse_error; - default: goto parse_error; - } - } + case '_': + if (strcmp(op, "struct.new_default") == 0) { return makeStructNewStatic(s, true); } + goto parse_error; default: goto parse_error; } } @@ -3631,25 +3556,13 @@ switch (op[0]) { default: goto parse_error; } } - case 'i': { - switch (op[10]) { - case '\0': - if (op == "array.init"sv) { - auto ret = makeArrayInit(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "array.init_static"sv) { - auto ret = makeArrayInitStatic(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'i': + if (op == "array.init_static"sv) { + auto ret = makeArrayInitStatic(ctx, in); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; case 'l': if (op == "array.len"sv) { auto ret = makeArrayLen(ctx, in); @@ -3666,37 +3579,13 @@ switch (op[0]) { return *ret; } goto parse_error; - case '_': { - switch (op[10]) { - case 'd': { - switch (op[17]) { - case '\0': - if (op == "array.new_default"sv) { - auto ret = makeArrayNewStatic(ctx, in, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "array.new_default_with_rtt"sv) { - auto ret = makeArrayNew(ctx, in, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (op == "array.new_with_rtt"sv) { - auto ret = makeArrayNew(ctx, in, false); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case '_': + if (op == "array.new_default"sv) { + auto ret = makeArrayNewStatic(ctx, in, true); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; default: goto parse_error; } } @@ -8594,197 +8483,168 @@ switch (op[0]) { } goto parse_error; case 'r': { - switch (op[1]) { - case 'e': { - switch (op[2]) { - case 'f': { - switch (op[4]) { - case 'a': { - switch (op[7]) { - case 'd': - if (op == "ref.as_data"sv) { - auto ret = makeRefAs(ctx, in, RefAsData); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'f': - if (op == "ref.as_func"sv) { - auto ret = makeRefAs(ctx, in, RefAsFunc); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'i': - if (op == "ref.as_i31"sv) { - auto ret = makeRefAs(ctx, in, RefAsI31); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'n': - if (op == "ref.as_non_null"sv) { - auto ret = makeRefAs(ctx, in, RefAsNonNull); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + switch (op[2]) { + case 'f': { + switch (op[4]) { + case 'a': { + switch (op[7]) { + case 'd': + if (op == "ref.as_data"sv) { + auto ret = makeRefAs(ctx, in, RefAsData); + CHECK_ERR(ret); + return *ret; } - } - case 'c': { - switch (op[8]) { - case '\0': - if (op == "ref.cast"sv) { - auto ret = makeRefCast(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': { - switch (op[9]) { - case 'n': - if (op == "ref.cast_nop_static"sv) { - auto ret = makeRefCastNopStatic(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 's': - if (op == "ref.cast_static"sv) { - auto ret = makeRefCastStatic(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; + goto parse_error; + case 'f': + if (op == "ref.as_func"sv) { + auto ret = makeRefAs(ctx, in, RefAsFunc); + CHECK_ERR(ret); + return *ret; } - } - case 'e': - if (op == "ref.eq"sv) { - auto ret = makeRefEq(ctx, in); + goto parse_error; + case 'i': + if (op == "ref.as_i31"sv) { + auto ret = makeRefAs(ctx, in, RefAsI31); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 'n': + if (op == "ref.as_non_null"sv) { + auto ret = makeRefAs(ctx, in, RefAsNonNull); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + default: goto parse_error; + } + } + case 'c': { + switch (op[9]) { + case 'n': + if (op == "ref.cast_nop_static"sv) { + auto ret = makeRefCastNopStatic(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 's': + if (op == "ref.cast_static"sv) { + auto ret = makeRefCastStatic(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + default: goto parse_error; + } + } + case 'e': + if (op == "ref.eq"sv) { + auto ret = makeRefEq(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 'f': + if (op == "ref.func"sv) { + auto ret = makeRefFunc(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 'i': { + switch (op[7]) { + case 'd': + if (op == "ref.is_data"sv) { + auto ret = makeRefIs(ctx, in, RefIsData); CHECK_ERR(ret); return *ret; } goto parse_error; case 'f': - if (op == "ref.func"sv) { - auto ret = makeRefFunc(ctx, in); + if (op == "ref.is_func"sv) { + auto ret = makeRefIs(ctx, in, RefIsFunc); CHECK_ERR(ret); return *ret; } goto parse_error; - case 'i': { - switch (op[7]) { - case 'd': - if (op == "ref.is_data"sv) { - auto ret = makeRefIs(ctx, in, RefIsData); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'f': - if (op == "ref.is_func"sv) { - auto ret = makeRefIs(ctx, in, RefIsFunc); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'i': - if (op == "ref.is_i31"sv) { - auto ret = makeRefIs(ctx, in, RefIsI31); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'n': - if (op == "ref.is_null"sv) { - auto ret = makeRefIs(ctx, in, RefIsNull); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'i': + if (op == "ref.is_i31"sv) { + auto ret = makeRefIs(ctx, in, RefIsI31); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; case 'n': - if (op == "ref.null"sv) { - auto ret = makeRefNull(ctx, in); + if (op == "ref.is_null"sv) { + auto ret = makeRefIs(ctx, in, RefIsNull); CHECK_ERR(ret); return *ret; } goto parse_error; - case 't': { - switch (op[8]) { - case '\0': - if (op == "ref.test"sv) { - auto ret = makeRefTest(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "ref.test_static"sv) { - auto ret = makeRefTestStatic(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } - case 't': { - switch (op[3]) { - case 'h': - if (op == "rethrow"sv) { - auto ret = makeRethrow(ctx, in); + case 'n': + if (op == "ref.null"sv) { + auto ret = makeRefNull(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 't': + if (op == "ref.test_static"sv) { + auto ret = makeRefTestStatic(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + default: goto parse_error; + } + } + case 't': { + switch (op[3]) { + case 'h': + if (op == "rethrow"sv) { + auto ret = makeRethrow(ctx, in); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case 'u': { + switch (op[6]) { + case '\0': + if (op == "return"sv) { + auto ret = makeReturn(ctx, in); CHECK_ERR(ret); return *ret; } goto parse_error; - case 'u': { - switch (op[6]) { + case '_': { + switch (op[11]) { case '\0': - if (op == "return"sv) { - auto ret = makeReturn(ctx, in); + if (op == "return_call"sv) { + auto ret = makeCall(ctx, in, /*isReturn=*/true); CHECK_ERR(ret); return *ret; } goto parse_error; case '_': { - switch (op[11]) { - case '\0': - if (op == "return_call"sv) { - auto ret = makeCall(ctx, in, /*isReturn=*/true); + switch (op[12]) { + case 'i': + if (op == "return_call_indirect"sv) { + auto ret = makeCallIndirect(ctx, in, /*isReturn=*/true); CHECK_ERR(ret); return *ret; } goto parse_error; - case '_': { - switch (op[12]) { - case 'i': - if (op == "return_call_indirect"sv) { - auto ret = makeCallIndirect(ctx, in, /*isReturn=*/true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'r': - if (op == "return_call_ref"sv) { - auto ret = makeCallRef(ctx, in, /*isReturn=*/true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case 'r': + if (op == "return_call_ref"sv) { + auto ret = makeCallRef(ctx, in, /*isReturn=*/true); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; default: goto parse_error; } } @@ -8797,32 +8657,6 @@ switch (op[0]) { default: goto parse_error; } } - case 't': { - switch (op[4]) { - case 'c': - if (op == "rtt.canon"sv) { - auto ret = makeRttCanon(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 'f': - if (op == "rtt.fresh_sub"sv) { - auto ret = makeRttFreshSub(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case 's': - if (op == "rtt.sub"sv) { - auto ret = makeRttSub(ctx, in); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -9151,37 +8985,13 @@ switch (op[0]) { return *ret; } goto parse_error; - case '_': { - switch (op[11]) { - case 'd': { - switch (op[18]) { - case '\0': - if (op == "struct.new_default"sv) { - auto ret = makeStructNewStatic(ctx, in, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - case '_': - if (op == "struct.new_default_with_rtt"sv) { - auto ret = makeStructNew(ctx, in, true); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (op == "struct.new_with_rtt"sv) { - auto ret = makeStructNew(ctx, in, false); - CHECK_ERR(ret); - return *ret; - } - goto parse_error; - default: goto parse_error; + case '_': + if (op == "struct.new_default"sv) { + auto ret = makeStructNewStatic(ctx, in, true); + CHECK_ERR(ret); + return *ret; } - } + goto parse_error; default: goto parse_error; } } diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 771553e11..3a5e4172d 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -160,8 +160,6 @@ void ReFinalize::visitBrOn(BrOn* curr) { updateBreakValueType(curr->name, curr->getSentType()); } } -void ReFinalize::visitRttCanon(RttCanon* curr) { curr->finalize(); } -void ReFinalize::visitRttSub(RttSub* curr) { curr->finalize(); } void ReFinalize::visitStructNew(StructNew* curr) { curr->finalize(); } void ReFinalize::visitStructGet(StructGet* curr) { curr->finalize(); } void ReFinalize::visitStructSet(StructSet* curr) { curr->finalize(); } diff --git a/src/ir/cost.h b/src/ir/cost.h index b48b777e1..823e58ded 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -604,35 +604,24 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { // Casts have a very high cost because in the VM they end up implemented as // a combination of loads and branches. Given they contain branches, we do // not want to add any more such work. - return Unacceptable + nullCheckCost(curr->ref) + visit(curr->ref) + - maybeVisit(curr->rtt); + return Unacceptable + nullCheckCost(curr->ref) + visit(curr->ref); } CostType visitRefCast(RefCast* curr) { - return Unacceptable + nullCheckCost(curr->ref) + visit(curr->ref) + - maybeVisit(curr->rtt); + return Unacceptable + nullCheckCost(curr->ref) + visit(curr->ref); } CostType visitBrOn(BrOn* curr) { // BrOn of a null can be fairly fast, but anything else is a cast check // basically, and an unacceptable cost. CostType base = curr->op == BrOnNull || curr->op == BrOnNonNull ? 2 : Unacceptable; - return base + nullCheckCost(curr->ref) + maybeVisit(curr->ref) + - maybeVisit(curr->rtt); - } - CostType visitRttCanon(RttCanon* curr) { - // TODO: investigate actual RTT costs in VMs - return 1; - } - CostType visitRttSub(RttSub* curr) { - // TODO: investigate actual RTT costs in VMs - return 2 + visit(curr->parent); + return base + nullCheckCost(curr->ref) + maybeVisit(curr->ref); } CostType visitStructNew(StructNew* curr) { // While allocation itself is almost free with generational GC, there is // at least some baseline cost, plus writing the fields. (If we use default // values for the fields, then it is possible they are all 0 and if so, we // can get that almost for free as well, so don't add anything there.) - CostType ret = 4 + maybeVisit(curr->rtt) + curr->operands.size(); + CostType ret = 4 + curr->operands.size(); for (auto* child : curr->operands) { ret += visit(child); } @@ -645,11 +634,10 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->value); } CostType visitArrayNew(ArrayNew* curr) { - return 4 + maybeVisit(curr->rtt) + visit(curr->size) + - maybeVisit(curr->init); + return 4 + visit(curr->size) + maybeVisit(curr->init); } CostType visitArrayInit(ArrayInit* curr) { - CostType ret = 4 + maybeVisit(curr->rtt); + CostType ret = 4; for (auto* child : curr->values) { ret += visit(child); } diff --git a/src/ir/effects.h b/src/ir/effects.h index 8d643ffe3..5e50441ac 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -678,8 +678,6 @@ private: parent.implicitTrap = true; } void visitBrOn(BrOn* curr) { parent.breakTargets.insert(curr->name); } - void visitRttCanon(RttCanon* curr) {} - void visitRttSub(RttSub* curr) {} void visitStructNew(StructNew* curr) {} void visitStructGet(StructGet* curr) { if (curr->ref->type == Type::unreachable) { diff --git a/src/ir/gc-type-utils.h b/src/ir/gc-type-utils.h index 584cde83c..cec4490e2 100644 --- a/src/ir/gc-type-utils.h +++ b/src/ir/gc-type-utils.h @@ -56,14 +56,11 @@ inline EvaluationResult evaluateKindCheck(Expression* curr) { flip = true; [[fallthrough]]; case BrOnCast: - if (!br->rtt) { - // This is a static cast check, which we may be able to resolve at - // compile time. Note that the type must be non-nullable for us to - // succeed at that inference, as otherwise a null can make us fail. - if (Type::isSubType(br->ref->type, - Type(br->intendedType, NonNullable))) { - return flip ? Failure : Success; - } + // Note that the type must be non-nullable for us to succeed since a + // null would make us fail. + if (Type::isSubType(br->ref->type, + Type(br->intendedType, NonNullable))) { + return flip ? Failure : Success; } return Unknown; case BrOnNonFunc: diff --git a/src/ir/linear-execution.h b/src/ir/linear-execution.h index 230bafee5..99b3a2a22 100644 --- a/src/ir/linear-execution.h +++ b/src/ir/linear-execution.h @@ -130,7 +130,6 @@ struct LinearExecutionWalker : public PostWalker<SubType, VisitorType> { case Expression::Id::BrOnId: { self->pushTask(SubType::doVisitBrOn, currp); self->pushTask(SubType::doNoteNonLinear, currp); - self->maybePushTask(SubType::scan, &curr->cast<BrOn>()->rtt); self->pushTask(SubType::scan, &curr->cast<BrOn>()->ref); break; } diff --git a/src/ir/literal-utils.h b/src/ir/literal-utils.h index ad022344e..0131ecdc9 100644 --- a/src/ir/literal-utils.h +++ b/src/ir/literal-utils.h @@ -33,17 +33,9 @@ inline bool canMakeZero(Type type) { if (type.isNonNullable()) { return false; } - if (type.isRtt() && type.getRtt().hasDepth()) { - // An rtt with depth cannot be constructed as a simple zero: we'd need to - // create not just a zero (an rtt.canon) but also some rtt.subs that add to - // the depth, so disallow that. Also, there is no practical way to create a - // zero Literal for such a type, as we'd need to supply the list of super - // types somehow, and creating a zero Literal is how makeZero works. - return false; - } if (type.isTuple()) { for (auto t : type) { - if (!canMakeZero(t)) { + if (t.isNonNullable()) { return false; } } diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index 38bb6f3d9..33f8ac926 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -55,8 +55,6 @@ struct CodeScanner counts.note(call->heapType); } else if (curr->is<RefNull>()) { counts.note(curr->type); - } else if (curr->is<RttCanon>() || curr->is<RttSub>()) { - counts.note(curr->type.getRtt().heapType); } else if (auto* make = curr->dynCast<StructNew>()) { handleMake(make); } else if (auto* make = curr->dynCast<ArrayNew>()) { @@ -64,12 +62,12 @@ struct CodeScanner } else if (auto* make = curr->dynCast<ArrayInit>()) { handleMake(make); } else if (auto* cast = curr->dynCast<RefCast>()) { - handleCast(cast); + counts.note(cast->intendedType); } else if (auto* cast = curr->dynCast<RefTest>()) { - handleCast(cast); + counts.note(cast->intendedType); } else if (auto* cast = curr->dynCast<BrOn>()) { if (cast->op == BrOnCast || cast->op == BrOnCastFail) { - handleCast(cast); + counts.note(cast->intendedType); } } else if (auto* get = curr->dynCast<StructGet>()) { counts.note(get->ref->type); @@ -86,18 +84,10 @@ struct CodeScanner } template<typename T> void handleMake(T* curr) { - if (!curr->rtt && curr->type != Type::unreachable) { + if (curr->type != Type::unreachable) { counts.note(curr->type.getHeapType()); } } - - template<typename T> void handleCast(T* curr) { - // Some operations emit a HeapType in the binary format, if they are - // static and not dynamic (if dynamic, the RTT provides the heap type). - if (!curr->rtt) { - counts.note(curr->intendedType); - } - } }; Counts getHeapTypeCounts(Module& wasm) { diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index ab0d379f6..48a632576 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -416,8 +416,6 @@ struct InfoCollector handleBreakValue(curr); receiveChildValue(curr->ref, curr); } - void visitRttCanon(RttCanon* curr) { addRoot(curr); } - void visitRttSub(RttSub* curr) { addRoot(curr); } void visitRefAs(RefAs* curr) { // TODO: optimize when possible: like RefCast, not all values flow through. receiveChildValue(curr->value, curr); @@ -1677,9 +1675,8 @@ void Flower::flowRefCast(const PossibleContents& contents, RefCast* cast) { // emitting a Many in any of these code paths filtered = contents; } else { - auto intendedType = cast->getIntendedType(); bool isSubType = - HeapType::isSubType(contents.getType().getHeapType(), intendedType); + HeapType::isSubType(contents.getType().getHeapType(), cast->intendedType); if (isSubType) { // The contents are not Many, but their heap type is a subtype of the // intended type, so we'll pass that through. Note that we pass the entire @@ -1694,7 +1691,7 @@ void Flower::flowRefCast(const PossibleContents& contents, RefCast* cast) { if (mayBeNull) { // A null is possible, so pass that along. filtered.combine( - PossibleContents::literal(Literal::makeNull(intendedType))); + PossibleContents::literal(Literal::makeNull(cast->intendedType))); } } if (!filtered.isNone()) { diff --git a/src/ir/properties.h b/src/ir/properties.h index 204b33e1e..4bd66b1d5 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -75,8 +75,8 @@ inline bool isNamedControlFlow(Expression* curr) { // at compile time, and passes that propagate constants can try to propagate it. // Constant expressions are also allowed in global initializers in wasm. Also // when two constant expressions compare equal at compile time, their values at -// runtime will be equal as well. -// TODO: look into adding more things here like RttCanon. +// runtime will be equal as well. TODO: combine this with +// isValidInConstantExpression or find better names(#4845) inline bool isSingleConstantExpression(const Expression* curr) { return curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>(); } @@ -407,9 +407,8 @@ bool isGenerative(Expression* curr, FeatureSet features); inline bool isValidInConstantExpression(Expression* expr, FeatureSet features) { if (isSingleConstantExpression(expr) || expr->is<GlobalGet>() || - expr->is<RttCanon>() || expr->is<RttSub>() || expr->is<StructNew>() || - expr->is<ArrayNew>() || expr->is<ArrayInit>() || expr->is<I31New>() || - expr->is<StringConst>()) { + expr->is<StructNew>() || expr->is<ArrayNew>() || expr->is<ArrayInit>() || + expr->is<I31New>() || expr->is<StringConst>()) { return true; } diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp index b08cca295..5452613bb 100644 --- a/src/ir/type-updating.cpp +++ b/src/ir/type-updating.cpp @@ -117,9 +117,6 @@ void GlobalTypeRewriter::update() { if (type.isRef()) { return Type(getNew(type.getHeapType()), type.getNullability()); } - if (type.isRtt()) { - return Type(Rtt(type.getRtt().depth, getNew(type.getHeapType()))); - } if (type.isTuple()) { auto tuple = type.getTuple(); for (auto& t : tuple.types) { @@ -251,18 +248,6 @@ Type GlobalTypeRewriter::getTempType(Type type) { typeBuilder.getTempHeapType(indexedTypes.indices[heapType]), type.getNullability()); } - if (type.isRtt()) { - auto rtt = type.getRtt(); - auto newRtt = rtt; - auto heapType = type.getHeapType(); - if (!indexedTypes.indices.count(heapType)) { - // See above with references. - return type; - } - newRtt.heapType = - typeBuilder.getTempHeapType(indexedTypes.indices[heapType]); - return typeBuilder.getTempRttType(newRtt); - } if (type.isTuple()) { auto& tuple = type.getTuple(); auto newTuple = tuple; diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index d2a8eb7f5..6ba5454e9 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -111,8 +111,6 @@ function initializeConstants() { 'RefTest', 'RefCast', 'BrOn', - 'RttCanon', - 'RttSub', 'StructNew', 'StructGet', 'StructSet', diff --git a/src/literal.h b/src/literal.h index 6696103e3..ffd565c71 100644 --- a/src/literal.h +++ b/src/literal.h @@ -32,7 +32,6 @@ namespace wasm { class Literals; struct GCData; -struct RttSupers; class Literal { // store only integers, whose bits are deterministic. floats @@ -51,21 +50,6 @@ class Literal { // Array, and for a Struct, is just the fields in order). The type is used // to indicate whether this is a Struct or an Array, and of what type. std::shared_ptr<GCData> gcData; - // RTT values are "structural" in that the MVP doc says that multiple - // invocations of ref.canon return things that are observably identical, and - // the same is true for ref.sub. That is, what matters is the types; there - // is no unique identifier created in each ref.canon/sub. To track the - // types, we maintain a simple vector of the supertypes. Thus, an rtt.canon - // of type A will have an empty vector; an rtt.sub of type B of that initial - // canon would have a vector of size 1 containing A; a subsequent rtt.sub - // would have A, B, and so forth. - // (This encoding is very inefficient and not at all what a production VM - // would do, but it is simple.) - // The unique_ptr here is to avoid increasing the size of the union as well - // as the Literal class itself. - // To support the experimental RttFreshSub instruction, we not only store - // the type, but also a reference to an allocation. - std::unique_ptr<RttSupers> rttSupers; // TODO: Literals of type `anyref` can only be `null` currently but we // will need to represent external values eventually, to // 1) run the spec tests and fuzzer with reference types enabled and @@ -97,7 +81,6 @@ public: explicit Literal(Name func, HeapType type) : func(func), type(type, NonNullable) {} explicit Literal(std::shared_ptr<GCData> gcData, HeapType type); - explicit Literal(std::unique_ptr<RttSupers>&& rttSupers, Type type); Literal(const Literal& other); Literal& operator=(const Literal& other); ~Literal(); @@ -267,10 +250,6 @@ public: return lit; } - // Get the canonical RTT value for a given HeapType. For nominal types, the - // canonical RTT reflects the static supertype chain. - static Literal makeCanonicalRtt(HeapType type); - Literal castToF32(); Literal castToF64(); Literal castToI32(); @@ -303,7 +282,6 @@ public: return func; } std::shared_ptr<GCData> getGCData() const; - const RttSupers& getRttSupers() const; // careful! int32_t* geti32Ptr() { @@ -666,11 +644,6 @@ public: Literal relaxedFmaF64x2(const Literal& left, const Literal& right) const; Literal relaxedFmsF64x2(const Literal& left, const Literal& right) const; - // Checks if an RTT value is a sub-rtt of another, that is, whether GC data - // with this object's RTT can be successfuly cast using the other RTT - // according to the wasm rules for that. - bool isSubRtt(const Literal& other) const; - private: Literal addSatSI8(const Literal& other) const; Literal addSatUI8(const Literal& other) const; @@ -721,41 +694,18 @@ public: std::ostream& operator<<(std::ostream& o, wasm::Literal literal); std::ostream& operator<<(std::ostream& o, wasm::Literals literals); -// A GC Struct or Array is a set of values with a run-time type saying what it -// is. In the case of static (rtt-free) typing, the rtt is not present and -// instead we have a static type. +// A GC Struct or Array is a set of values with a type saying how it should be +// interpreted. struct GCData { - // The runtime type info for this struct or array. - Literal rtt; + // The type of this struct or array. + HeapType type; // The element or field values. Literals values; - GCData(Literal rtt, Literals values) : rtt(rtt), values(values) {} -}; - -struct RttSuper { - // The type of the super. - HeapType type; - // A shared allocation, used to implement rtt.fresh_sub. This is null for a - // normal sub, and for a fresh one we allocate a value here, which can then be - // used to differentiate rtts. (The allocation is shared so that when copying - // an rtt we remain equal.) - // TODO: Remove or optimize this when the spec stabilizes. - std::shared_ptr<size_t> freshPtr; - - RttSuper(HeapType type) : type(type) {} - - void makeFresh() { freshPtr = std::make_shared<size_t>(); } - - bool operator==(const RttSuper& other) const { - return type == other.type && freshPtr == other.freshPtr; - } - bool operator!=(const RttSuper& other) const { return !(*this == other); } + GCData(HeapType type, Literals values) : type(type), values(values) {} }; -struct RttSupers : std::vector<RttSuper> {}; - } // namespace wasm namespace std { @@ -801,14 +751,6 @@ template<> struct hash<wasm::Literal> { // other non-null reference type literals cannot represent concrete // values, i.e. there is no concrete anyref or eqref other than null. WASM_UNREACHABLE("unexpected type"); - } else if (a.type.isRtt()) { - const auto& supers = a.getRttSupers(); - wasm::rehash(digest, supers.size()); - for (auto super : supers) { - wasm::rehash(digest, super.type.getID()); - wasm::rehash(digest, uintptr_t(super.freshPtr.get())); - } - return digest; } WASM_UNREACHABLE("unexpected type"); } diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index 19259e864..86235b001 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -43,9 +43,8 @@ // // ;; Allocate a boxed integer of 42 and save the reference to it. // (local.set $ref -// (struct.new_with_rtt $boxed-int +// (struct.new $boxed-int // (i32.const 42) -// (rtt.canon $boxed-int) // ) // ) // @@ -407,10 +406,6 @@ struct Heap2LocalOptimizer { } } - // Drop the RTT (as it may have side effects; leave it to other passes). - if (allocation->rtt) { - contents.push_back(builder.makeDrop(allocation->rtt)); - } // Replace the allocation with a null reference. This changes the type // from non-nullable to nullable, but as we optimize away the code that // the allocation reaches, we will handle that. diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp index 073c78822..1180c5183 100644 --- a/src/passes/InstrumentMemory.cpp +++ b/src/passes/InstrumentMemory.cpp @@ -54,7 +54,7 @@ // // GC struct and array operations are similarly instrumented, but without their // pointers (which are references), and we only log MVP wasm types (i.e., not -// references or rtts). +// references). // #include "asmjs/shared-constants.h" diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 55176a6e9..828b2fdc9 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1434,10 +1434,9 @@ struct OptimizeInstructions // is, if casts of the type do not affect our behavior (which is the case in // ref.eq for example). // - // |requiredType| is the type we require as the final output here, or a - // subtype of it. We will not remove a cast that would leave something that - // would break that. If |requiredType| is not provided we will accept any type - // there. + // |requiredType| is the required supertype of the final output. We will not + // remove a cast that would leave something that would break that. If + // |requiredType| is not provided we will accept any type there. // // See "notes on removing casts", above, for when this is safe to do. void skipCast(Expression*& input, @@ -1453,7 +1452,7 @@ struct OptimizeInstructions continue; } } else if (auto* cast = input->dynCast<RefCast>()) { - if (!cast->rtt && Type::isSubType(cast->ref->type, requiredType)) { + if (Type::isSubType(cast->ref->type, requiredType)) { input = cast->ref; continue; } @@ -1705,7 +1704,7 @@ struct OptimizeInstructions auto fallthrough = Properties::getFallthrough(curr->ref, getPassOptions(), *getModule()); - auto intendedType = curr->getIntendedType(); + auto intendedType = curr->intendedType; // If the value is a null, it will just flow through, and we do not need // the cast. However, if that would change the type, then things are less @@ -1716,13 +1715,8 @@ struct OptimizeInstructions // Replace the expression with drops of the inputs, and a null. Note // that we provide a null of the previous type, so that we do not alter // the type received by our parent. - std::vector<Expression*> items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); - } - items.push_back(builder.makeRefNull(intendedType)); - Expression* rep = builder.makeBlock(items); + Expression* rep = builder.makeSequence(builder.makeDrop(curr->ref), + builder.makeRefNull(intendedType)); if (curr->ref->type.isNonNullable()) { // Avoid a type change by forcing to be non-nullable. In practice, // this would have trapped before we get here, so this is just for @@ -1737,22 +1731,17 @@ struct OptimizeInstructions } // For the cast to be able to succeed, the value being cast must be a - // subtype of the desired type, as RTT subtyping is a subset of static - // subtyping. For example, trying to cast an array to a struct would be - // incompatible. + // subtype of the desired type. For example, trying to cast an array to a + // struct would be incompatible. if (!canBeCastTo(curr->ref->type.getHeapType(), intendedType)) { // This cast cannot succeed. If the input is not a null, it will // definitely trap. if (fallthrough->type.isNonNullable()) { // Make sure to emit a block with the same type as us; leave updating // types for other passes. - std::vector<Expression*> items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); - } - items.push_back(builder.makeUnreachable()); - replaceCurrent(builder.makeBlock(items, curr->type)); + replaceCurrent(builder.makeBlock( + {builder.makeDrop(curr->ref), builder.makeUnreachable()}, + curr->type)); return; } // Otherwise, we are not sure what it is, and need to wait for runtime @@ -1760,46 +1749,29 @@ struct OptimizeInstructions // we can see the value is definitely a null at compile time, earlier.) } - if (passOptions.ignoreImplicitTraps || passOptions.trapsNeverHappen || - !curr->rtt) { - // Aside from the issue of type incompatibility as mentioned above, the - // cast can trap if the types *are* compatible but it happens to be the - // case at runtime that the value is not of the desired subtype. If we - // do not consider such traps possible, we can ignore that. (Note, - // though, that we cannot do this if we cannot replace the current type - // with the reference's type.) We can also do this if this is a static - // cast: in that case, all we need to know about are the types. - if (HeapType::isSubType(curr->ref->type.getHeapType(), intendedType)) { - if (curr->rtt) { - replaceCurrent(getResultOfFirst(curr->ref, - builder.makeDrop(curr->rtt), - getFunction(), - getModule(), - passOptions)); - } else { - replaceCurrent(curr->ref); + // Check whether the cast will definitely succeed. + if (HeapType::isSubType(curr->ref->type.getHeapType(), intendedType)) { + replaceCurrent(curr->ref); - // We must refinalize here, as we may be returning a more specific - // type, which can alter the parent. For example: - // - // (struct.get $parent 0 - // (ref.cast_static $parent - // (local.get $child) - // ) - // ) - // - // Try to cast a $child to its parent, $parent. That always works, - // so the cast can be removed. - // Then once the cast is removed, the outer struct.get - // will have a reference with a different type, making it a - // (struct.get $child ..) instead of $parent. - // But if $parent and $child have different types on field 0 (the - // child may have a more refined one) then the struct.get must be - // refinalized so the IR node has the expected type. - refinalize = true; - } - return; - } + // We must refinalize here, as we may be returning a more specific + // type, which can alter the parent. For example: + // + // (struct.get $parent 0 + // (ref.cast_static $parent + // (local.get $child) + // ) + // ) + // + // Try to cast a $child to its parent, $parent. That always works, + // so the cast can be removed. + // Then once the cast is removed, the outer struct.get + // will have a reference with a different type, making it a + // (struct.get $child ..) instead of $parent. + // But if $parent and $child have different types on field 0 (the + // child may have a more refined one) then the struct.get must be + // refinalized so the IR node has the expected type. + refinalize = true; + return; } // Repeated identical ref.cast operations are unnecessary. First, find the @@ -1818,51 +1790,41 @@ struct OptimizeInstructions } } if (auto* child = ref->dynCast<RefCast>()) { - if (curr->rtt && child->rtt) { - // Check if the casts are identical. - if (ExpressionAnalyzer::equal(curr->rtt, child->rtt) && - !EffectAnalyzer(passOptions, *getModule(), curr->rtt) - .hasSideEffects()) { - replaceCurrent(curr->ref); + // Repeated casts can be removed, leaving just the most demanding of + // them. + auto childIntendedType = child->intendedType; + if (HeapType::isSubType(intendedType, childIntendedType)) { + // Skip the child. + if (curr->ref == child) { + curr->ref = child->ref; return; + } else { + // The child is not the direct child of the parent, but it is a + // fallthrough value, for example, + // + // (ref.cast parent + // (block + // .. other code .. + // (ref.cast child))) + // + // In this case it isn't obvious that we can remove the child, as + // doing so might require updating the types of the things in the + // middle - and in fact the sole purpose of the child may be to get + // a proper type for validation to work. Do nothing in this case, + // and hope that other opts will help here (for example, + // trapsNeverHappen will help if the code validates without the + // child). } - } else if (!curr->rtt && !child->rtt) { - // Repeated static casts can be removed, leaving just the most demanding - // of them. - auto childIntendedType = child->getIntendedType(); - if (HeapType::isSubType(intendedType, childIntendedType)) { - // Skip the child. - if (curr->ref == child) { - curr->ref = child->ref; - return; - } else { - // The child is not the direct child of the parent, but it is a - // fallthrough value, for example, - // - // (ref.cast parent - // (block - // .. other code .. - // (ref.cast child))) - // - // In this case it isn't obvious that we can remove the child, as - // doing so might require updating the types of the things in the - // middle - and in fact the sole purpose of the child may be to get - // a proper type for validation to work. Do nothing in this case, - // and hope that other opts will help here (for example, - // trapsNeverHappen will help if the code validates without the - // child). - } - } else if (!canBeCastTo(intendedType, childIntendedType)) { - // The types are not compatible, so if the input is not null, this - // will trap. - if (!curr->type.isNullable()) { - // Make sure to emit a block with the same type as us; leave - // updating types for other passes. - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->ref), builder.makeUnreachable()}, - curr->type)); - return; - } + } else if (!canBeCastTo(intendedType, childIntendedType)) { + // The types are not compatible, so if the input is not null, this + // will trap. + if (!curr->type.isNullable()) { + // Make sure to emit a block with the same type as us; leave + // updating types for other passes. + replaceCurrent(builder.makeBlock( + {builder.makeDrop(curr->ref), builder.makeUnreachable()}, + curr->type)); + return; } } } @@ -1905,22 +1867,17 @@ struct OptimizeInstructions Builder builder(*getModule()); auto refType = curr->ref->type.getHeapType(); - auto intendedType = curr->getIntendedType(); + auto intendedType = curr->intendedType; // See above in RefCast. if (!canBeCastTo(refType, intendedType)) { // This test cannot succeed, and will definitely return 0. - std::vector<Expression*> items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); - } - items.push_back(builder.makeConst(int32_t(0))); - replaceCurrent(builder.makeBlock(items)); + replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref), + builder.makeConst(int32_t(0)))); return; } - if (!curr->rtt && curr->ref->type.isNonNullable() && + if (curr->ref->type.isNonNullable() && HeapType::isSubType(refType, intendedType)) { // This static test will definitely succeed. replaceCurrent(builder.makeBlock( diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index bbaa6d533..35f218362 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -514,9 +514,8 @@ private: if (type.isRef()) { return false; } - // For now, don't try to precompute an Rtt. TODO figure out when that would - // be safe and useful. - return !type.isRtt(); + + return true; } }; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 962246569..62dc58c48 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -152,7 +152,6 @@ struct TypeNamePrinter { void print(const Signature& sig); void print(const Struct& struct_); void print(const Array& array); - void print(const Rtt& rtt); // FIXME: This hard limit on how many times we call print() avoids extremely // large outputs, which can be inconveniently large in some cases, but @@ -179,8 +178,6 @@ void TypeNamePrinter::print(Type type) { os << type; } else if (type.isTuple()) { print(type.getTuple()); - } else if (type.isRtt()) { - print(type.getRtt()); } else if (type.isRef()) { if (!maybePrintRefShorthand(os, type)) { os << "ref"; @@ -301,14 +298,6 @@ void TypeNamePrinter::print(const Array& array) { os << ']'; } -void TypeNamePrinter::print(const Rtt& rtt) { - os << "rtt_"; - if (rtt.hasDepth()) { - os << rtt.depth << '_'; - } - print(rtt.heapType); -} - } // anonymous namespace static std::ostream& printType(std::ostream& o, Type type, Module* wasm) { @@ -323,14 +312,6 @@ static std::ostream& printType(std::ostream& o, Type type, Module* wasm) { sep = " "; } o << ')'; - } else if (type.isRtt()) { - auto rtt = type.getRtt(); - o << "(rtt "; - if (rtt.hasDepth()) { - o << rtt.depth << ' '; - } - TypeNamePrinter(o, wasm).print(rtt.heapType); - o << ')'; } else if (type.isRef()) { if (!maybePrintRefShorthand(o, type)) { o << "(ref "; @@ -2027,24 +2008,17 @@ struct PrintExpressionContents } } void visitRefTest(RefTest* curr) { - if (curr->rtt) { - printMedium(o, "ref.test"); - } else { - printMedium(o, "ref.test_static "); - printHeapType(o, curr->intendedType, wasm); - } + printMedium(o, "ref.test_static "); + printHeapType(o, curr->intendedType, wasm); } + void visitRefCast(RefCast* curr) { - if (curr->rtt) { - printMedium(o, "ref.cast"); + if (curr->safety == RefCast::Unsafe) { + printMedium(o, "ref.cast_nop_static "); } else { - if (curr->safety == RefCast::Unsafe) { - printMedium(o, "ref.cast_nop_static "); - } else { - printMedium(o, "ref.cast_static "); - } - printHeapType(o, curr->intendedType, wasm); + printMedium(o, "ref.cast_static "); } + printHeapType(o, curr->intendedType, wasm); } void visitBrOn(BrOn* curr) { switch (curr->op) { @@ -2055,27 +2029,17 @@ struct PrintExpressionContents printMedium(o, "br_on_non_null "); break; case BrOnCast: - if (curr->rtt) { - printMedium(o, "br_on_cast "); - } else { - printMedium(o, "br_on_cast_static "); - printName(curr->name, o); - o << ' '; - printHeapType(o, curr->intendedType, wasm); - return; - } - break; + printMedium(o, "br_on_cast_static "); + printName(curr->name, o); + o << ' '; + printHeapType(o, curr->intendedType, wasm); + return; case BrOnCastFail: - if (curr->rtt) { - printMedium(o, "br_on_cast_fail "); - } else { - printMedium(o, "br_on_cast_static_fail "); - printName(curr->name, o); - o << ' '; - printHeapType(o, curr->intendedType, wasm); - return; - } - break; + printMedium(o, "br_on_cast_static_fail "); + printName(curr->name, o); + o << ' '; + printHeapType(o, curr->intendedType, wasm); + return; case BrOnFunc: printMedium(o, "br_on_func "); break; @@ -2099,18 +2063,6 @@ struct PrintExpressionContents } printName(curr->name, o); } - void visitRttCanon(RttCanon* curr) { - printMedium(o, "rtt.canon "); - TypeNamePrinter(o, wasm).print(curr->type.getRtt().heapType); - } - void visitRttSub(RttSub* curr) { - if (curr->fresh) { - printMedium(o, "rtt.fresh_sub "); - } else { - printMedium(o, "rtt.sub "); - } - TypeNamePrinter(o, wasm).print(curr->type.getRtt().heapType); - } // If we cannot print a valid unreachable instruction (say, a struct.get, // where if the ref is unreachable, we don't know what heap type to print), @@ -2135,9 +2087,6 @@ struct PrintExpressionContents if (curr->isWithDefault()) { printMedium(o, "_default"); } - if (curr->rtt) { - printMedium(o, "_with_rtt"); - } o << ' '; TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); } @@ -2188,9 +2137,6 @@ struct PrintExpressionContents if (curr->isWithDefault()) { printMedium(o, "_default"); } - if (curr->rtt) { - printMedium(o, "_with_rtt"); - } o << ' '; TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); } @@ -2198,10 +2144,7 @@ struct PrintExpressionContents if (printUnreachableReplacement(curr)) { return; } - printMedium(o, "array.init"); - if (!curr->rtt) { - printMedium(o, "_static"); - } + printMedium(o, "array.init_static"); o << ' '; TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); } diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp index a3d9442bf..84e19428d 100644 --- a/src/passes/StackIR.cpp +++ b/src/passes/StackIR.cpp @@ -72,7 +72,7 @@ public: // Removing unneeded blocks is dangerous with GC, as if we do this: // // (call - // (rtt) + // (struct.new) // (block // (nop) // (i32) @@ -80,7 +80,7 @@ public: // ) // === remove inner block ==> // (call - // (rtt) + // (struct.new) // (nop) // (i32) // ) @@ -90,7 +90,7 @@ public: // (call // (block // (local.set - // (rtt) + // (struct.new) // ) // (nop) // (local.get) @@ -98,7 +98,9 @@ public: // (i32) // ) // - // However, that is not valid as an rtt cannot be set to a local. + // However, that is not valid as an non-nullable reference cannot be set to + // a local. TODO: double check that this is still true now that we don't + // have RTTs. if (!features.hasGC()) { removeUnneededBlocks(); } diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index d0c92690a..47d55cfef 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -181,11 +181,11 @@ private: // Recombination and mutation can replace a node with another node of the same // type, but should not do so for certain types that are dangerous. For - // example, it would be bad to add an RTT in a tuple, as that would force us - // to use temporary locals for the tuple, but RTTs are not defaultable. - // Also, 'pop' pseudo instruction for EH is supposed to exist only at the - // beginning of a 'catch' block, so it shouldn't be moved around or deleted - // freely. + // example, it would be bad to add a non-nullable reference to a tuple, as + // that would force us to use temporary locals for the tuple, but non-nullable + // references cannot always be stored in locals. Also, the 'pop' pseudo + // instruction for EH is supposed to exist only at the beginning of a 'catch' + // block, so it shouldn't be moved around or deleted freely. bool canBeArbitrarilyReplaced(Expression* curr) { return curr->type.isDefaultable() && !EHUtils::containsValidDanglingPop(curr); @@ -312,7 +312,6 @@ private: bool isLoggableType(Type type); Nullability getSubType(Nullability nullability); HeapType getSubType(HeapType type); - Rtt getSubType(Rtt rtt); Type getSubType(Type type); // Utilities diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 59c9dca45..4d0a8d7b7 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -918,7 +918,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) { &Self::makeSelect) .add(FeatureSet::Multivalue, &Self::makeTupleExtract); } - if (type.isSingle() && !type.isRef() && !type.isRtt()) { + if (type.isSingle() && !type.isRef()) { options.add(FeatureSet::MVP, {&Self::makeLoad, Important}); options.add(FeatureSet::SIMD, &Self::makeSIMD); } @@ -1893,8 +1893,6 @@ Expression* TranslateToFuzzReader::makeConst(Type type) { } else { return makeConstCompoundRef(type); } - } else if (type.isRtt()) { - return builder.makeRtt(type); } else if (type.isTuple()) { std::vector<Expression*> operands; for (const auto& t : type) { @@ -2035,14 +2033,15 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) { // give up return makeTrivial(type); } - // There are no unary ops for reference or RTT types. - if (type.isRef() || type.isRtt()) { + // There are no unary ops for reference types. + // TODO: not quite true if you count struct.new and array.new. + if (type.isRef()) { return makeTrivial(type); } switch (type.getBasic()) { case Type::i32: { auto singleConcreteType = getSingleConcreteType(); - if (singleConcreteType.isRef() || singleConcreteType.isRtt()) { + if (singleConcreteType.isRef()) { // TODO: Do something more interesting here. return makeTrivial(type); } @@ -2241,8 +2240,9 @@ Expression* TranslateToFuzzReader::makeBinary(Type type) { // give up return makeTrivial(type); } - // There are no binary ops for reference or RTT types. - if (type.isRef() || type.isRtt()) { + // There are no binary ops for reference types. + // TODO: Use struct.new + if (type.isRef()) { return makeTrivial(type); } switch (type.getBasic()) { @@ -3056,19 +3056,6 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) { return type; } -Rtt TranslateToFuzzReader::getSubType(Rtt rtt) { - if (getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive) { - // With nominal or isorecursive typing the depth in rtts must match the - // nominal hierarchy, so we cannot create a random depth like we do below. - return rtt; - } - uint32_t depth = rtt.depth != Rtt::NoDepth - ? rtt.depth - : oneIn(2) ? Rtt::NoDepth : upTo(MAX_RTT_DEPTH + 1); - return Rtt(depth, rtt.heapType); -} - Type TranslateToFuzzReader::getSubType(Type type) { if (type.isTuple()) { std::vector<Type> types; @@ -3080,8 +3067,6 @@ Type TranslateToFuzzReader::getSubType(Type type) { auto heapType = getSubType(type.getHeapType()); auto nullability = getSubType(type.getNullability()); return Type(heapType, nullability); - } else if (type.isRtt()) { - return Type(getSubType(type.getRtt())); } else { // This is an MVP type without subtypes. assert(type.isBasic()); diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index edb96977d..364065b8b 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -181,20 +181,12 @@ struct HeapTypeGeneratorImpl { return builder.getTempRefType(heapType, nullability); } - Type generateRttType() { - auto heapType = generateHeapType(); - auto depth = rand.oneIn(2) ? Rtt::NoDepth : rand.upTo(MAX_RTT_DEPTH); - return builder.getTempRttType(Rtt(depth, heapType)); - } - Type generateSingleType() { - switch (rand.upTo(3)) { + switch (rand.upTo(2)) { case 0: return generateBasicType(); case 1: return generateRefType(); - case 2: - return generateRttType(); } WASM_UNREACHABLE("unexpected"); } @@ -412,20 +404,10 @@ struct HeapTypeGeneratorImpl { return {pickSubHeapType(super.type), nullability}; } - Rtt generateSubRtt(Rtt super) { - auto depth = super.hasDepth() - ? super.depth - : rand.oneIn(2) ? Rtt::NoDepth : rand.upTo(MAX_RTT_DEPTH); - return {depth, super.heapType}; - } - Type generateSubtype(Type type) { if (type.isRef()) { auto ref = generateSubRef({type.getHeapType(), type.getNullability()}); return builder.getTempRefType(ref.type, ref.nullability); - } else if (type.isRtt()) { - auto rtt = generateSubRtt(type.getRtt()); - return builder.getTempRttType(rtt); } else if (type.isBasic()) { // Non-reference basic types do not have subtypes. return type; diff --git a/src/tools/fuzzing/parameters.h b/src/tools/fuzzing/parameters.h index 6618ce6db..1ba7b064f 100644 --- a/src/tools/fuzzing/parameters.h +++ b/src/tools/fuzzing/parameters.h @@ -38,9 +38,6 @@ constexpr int MAX_TUPLE_SIZE = 6; // The maximum number of struct fields. static const int MAX_STRUCT_SIZE = 6; -// The maximum rtt depth. -constexpr int MAX_RTT_DEPTH = 3; - // The number of nontrivial heap types to generate. constexpr int MIN_HEAPTYPES = 4; constexpr int MAX_HEAPTYPES = 20; diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 22fa87633..6150441cd 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -558,7 +558,6 @@ public: Expression* init; auto heapType = type.getHeapType(); - // TODO: handle rtts if we need them if (heapType.isStruct()) { init = builder.makeStructNew(heapType, args); } else if (heapType.isArray()) { diff --git a/src/tools/wasm-fuzz-types.cpp b/src/tools/wasm-fuzz-types.cpp index d2540636f..d80c89ea8 100644 --- a/src/tools/wasm-fuzz-types.cpp +++ b/src/tools/wasm-fuzz-types.cpp @@ -386,24 +386,6 @@ void Fuzzer::checkCanonicalization() { } } - CopiedType getRtt(Type old) { - auto copied = getChildHeapType(old.getHeapType()); - auto rtt = old.getRtt(); - rtt.heapType = copied.get(); - if (copied.getNew()) { - // The child is temporary, so we must put it in a temporary type. - return {NewType{builder.getTempRttType(rtt)}}; - } else { - // The child is canonical, so we can either put it in a temporary type - // or use the canonical type. - if (rand.oneIn(2)) { - return {NewType{builder.getTempRttType(rtt)}}; - } else { - return {OldType{Type(rtt)}}; - } - } - } - CopiedType getRef(Type old) { auto copied = getChildHeapType(old.getHeapType()); auto type = copied.get(); @@ -425,8 +407,6 @@ void Fuzzer::checkCanonicalization() { CopiedType getType(Type old) { if (old.isTuple()) { return getTuple(old); - } else if (old.isRtt()) { - return getRtt(old); } else if (old.isRef()) { return getRef(old); } else { diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 200252da7..6b05c38cc 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -373,10 +373,6 @@ enum EncodedType { nonnullable = -0x15, // 0x6b // integer reference type i31ref = -0x16, // 0x6a - // run-time type info type, with depth index n - rtt_n = -0x17, // 0x69 - // run-time type info type, without depth index n - rtt = -0x18, // 0x68 // gc and string reference types dataref = -0x19, // 0x67 stringref = -0x1c, // 0x64 @@ -1089,36 +1085,24 @@ enum ASTNodes { // gc opcodes RefEq = 0xd5, - StructNewWithRtt = 0x01, - StructNewDefaultWithRtt = 0x02, StructGet = 0x03, StructGetS = 0x04, StructGetU = 0x05, StructSet = 0x06, StructNew = 0x07, StructNewDefault = 0x08, - ArrayNewWithRtt = 0x11, - ArrayNewDefaultWithRtt = 0x12, ArrayGet = 0x13, ArrayGetS = 0x14, ArrayGetU = 0x15, ArraySet = 0x16, ArrayLen = 0x17, ArrayCopy = 0x18, - ArrayInit = 0x19, ArrayInitStatic = 0x1a, ArrayNew = 0x1b, ArrayNewDefault = 0x1c, I31New = 0x20, I31GetS = 0x21, I31GetU = 0x22, - RttCanon = 0x30, - RttSub = 0x31, - RttFreshSub = 0x32, - RefTest = 0x40, - RefCast = 0x41, - BrOnCast = 0x42, - BrOnCastFail = 0x43, RefTestStatic = 0x44, RefCastStatic = 0x45, BrOnCastStatic = 0x46, @@ -1708,8 +1692,6 @@ public: bool maybeVisitRefTest(Expression*& out, uint32_t code); bool maybeVisitRefCast(Expression*& out, uint32_t code); bool maybeVisitBrOn(Expression*& out, uint32_t code); - bool maybeVisitRttCanon(Expression*& out, uint32_t code); - bool maybeVisitRttSub(Expression*& out, uint32_t code); bool maybeVisitStructNew(Expression*& out, uint32_t code); bool maybeVisitStructGet(Expression*& out, uint32_t code); bool maybeVisitStructSet(Expression*& out, uint32_t code); @@ -1755,7 +1737,7 @@ public: // Struct/Array instructions have an unnecessary heap type that is just for // validation (except for the case of unreachability, but that's not a problem - // anyhow, we can ignore it there). That is, we also have a reference / rtt + // anyhow, we can ignore it there). That is, we also have a reference typed // child from which we can infer the type anyhow, and we just need to check // that type is the same. void validateHeapTypeUsingChild(Expression* child, HeapType heapType); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 61227a811..1faf95d73 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -805,13 +805,6 @@ public: ret->finalize(); return ret; } - RefTest* makeRefTest(Expression* ref, Expression* rtt) { - auto* ret = wasm.allocator.alloc<RefTest>(); - ret->ref = ref; - ret->rtt = rtt; - ret->finalize(); - return ret; - } RefTest* makeRefTest(Expression* ref, HeapType intendedType) { auto* ret = wasm.allocator.alloc<RefTest>(); ret->ref = ref; @@ -819,14 +812,6 @@ public: ret->finalize(); return ret; } - RefCast* makeRefCast(Expression* ref, Expression* rtt) { - auto* ret = wasm.allocator.alloc<RefCast>(); - ret->ref = ref; - ret->rtt = rtt; - ret->finalize(); - return ret; - } - RefCast* makeRefCast(Expression* ref, HeapType intendedType, RefCast::Safety safety) { auto* ret = wasm.allocator.alloc<RefCast>(); @@ -836,13 +821,11 @@ public: ret->finalize(); return ret; } - BrOn* - makeBrOn(BrOnOp op, Name name, Expression* ref, Expression* rtt = nullptr) { + BrOn* makeBrOn(BrOnOp op, Name name, Expression* ref) { auto* ret = wasm.allocator.alloc<BrOn>(); ret->op = op; ret->name = name; ret->ref = ref; - ret->rtt = rtt; ret->finalize(); return ret; } @@ -855,37 +838,6 @@ public: ret->finalize(); return ret; } - RttCanon* makeRttCanon(HeapType heapType) { - auto* ret = wasm.allocator.alloc<RttCanon>(); - ret->type = Type(Rtt(heapType.getDepth(), heapType)); - ret->finalize(); - return ret; - } - RttSub* makeRttSub(HeapType heapType, Expression* parent) { - auto* ret = wasm.allocator.alloc<RttSub>(); - ret->parent = parent; - auto parentRtt = parent->type.getRtt(); - if (parentRtt.hasDepth()) { - ret->type = Type(Rtt(parentRtt.depth + 1, heapType)); - } else { - ret->type = Type(Rtt(heapType)); - } - ret->finalize(); - return ret; - } - RttSub* makeRttFreshSub(HeapType heapType, Expression* parent) { - auto* ret = makeRttSub(heapType, parent); - ret->fresh = true; - return ret; - } - template<typename T> - StructNew* makeStructNew(Expression* rtt, const T& args) { - auto* ret = wasm.allocator.alloc<StructNew>(); - ret->rtt = rtt; - ret->operands.set(args); - ret->finalize(); - return ret; - } template<typename T> StructNew* makeStructNew(HeapType type, const T& args) { auto* ret = wasm.allocator.alloc<StructNew>(); ret->operands.set(args); @@ -912,15 +864,6 @@ public: return ret; } ArrayNew* - makeArrayNew(Expression* rtt, Expression* size, Expression* init = nullptr) { - auto* ret = wasm.allocator.alloc<ArrayNew>(); - ret->rtt = rtt; - ret->size = size; - ret->init = init; - ret->finalize(); - return ret; - } - ArrayNew* makeArrayNew(HeapType type, Expression* size, Expression* init = nullptr) { auto* ret = wasm.allocator.alloc<ArrayNew>(); ret->size = size; @@ -929,14 +872,6 @@ public: ret->finalize(); return ret; } - ArrayInit* makeArrayInit(Expression* rtt, - const std::vector<Expression*>& values) { - auto* ret = wasm.allocator.alloc<ArrayInit>(); - ret->rtt = rtt; - ret->values.set(values); - ret->finalize(); - return ret; - } ArrayInit* makeArrayInit(HeapType type, const std::vector<Expression*>& values) { auto* ret = wasm.allocator.alloc<ArrayInit>(); @@ -1121,9 +1056,6 @@ public: if (type.isRef() && type.getHeapType() == HeapType::i31) { return makeI31New(makeConst(value.geti31())); } - if (type.isRtt()) { - return makeRtt(value.type); - } TODO_SINGLE_COMPOUND(type); WASM_UNREACHABLE("unsupported constant expression"); } @@ -1141,18 +1073,6 @@ public: } } - // Given a type, creates an RTT expression of that type, using a combination - // of rtt.canon and rtt.subs. - Expression* makeRtt(Type type) { - Expression* ret = makeRttCanon(type.getHeapType()); - if (type.getRtt().hasDepth()) { - for (Index i = 0; i < type.getRtt().depth; i++) { - ret = makeRttSub(type.getHeapType(), ret); - } - } - return ret; - } - // Additional utility functions for building on top of nodes // Convenient to have these on Builder, as it has allocation built in @@ -1322,25 +1242,13 @@ public: ValidatingBuilder(Module& wasm, size_t line, size_t col) : Builder(wasm), line(line), col(col) {} - Expression* validateAndMakeBrOn(BrOnOp op, - Name name, - Expression* ref, - Expression* rtt = nullptr) { - if (op == BrOnCast) { - if (rtt->type == Type::unreachable) { - // An unreachable rtt is not supported: the text and binary formats do - // not provide the type, so if it's unreachable we should not even - // create a br_on_cast in such a case, as we'd have no idea what it - // casts to. - return makeSequence(makeDrop(ref), rtt); - } - } + Expression* validateAndMakeBrOn(BrOnOp op, Name name, Expression* ref) { if (op == BrOnNull) { if (!ref->type.isRef() && ref->type != Type::unreachable) { throw ParseException("Invalid ref for br_on_null", line, col); } } - return makeBrOn(op, name, ref, rtt); + return makeBrOn(op, name, ref); } template<typename T> diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index 55a9edd16..fa1fa229f 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -601,7 +601,6 @@ switch (DELEGATE_ID) { case Expression::Id::RefTestId: { DELEGATE_START(RefTest); DELEGATE_FIELD_HEAPTYPE(RefTest, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(RefTest, rtt); DELEGATE_FIELD_CHILD(RefTest, ref); DELEGATE_END(RefTest); break; @@ -609,7 +608,6 @@ switch (DELEGATE_ID) { case Expression::Id::RefCastId: { DELEGATE_START(RefCast); DELEGATE_FIELD_HEAPTYPE(RefCast, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(RefCast, rtt); DELEGATE_FIELD_CHILD(RefCast, ref); DELEGATE_END(RefCast); break; @@ -619,26 +617,12 @@ switch (DELEGATE_ID) { DELEGATE_FIELD_INT(BrOn, op); DELEGATE_FIELD_SCOPE_NAME_USE(BrOn, name); DELEGATE_FIELD_HEAPTYPE(BrOn, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(BrOn, rtt); DELEGATE_FIELD_CHILD(BrOn, ref); DELEGATE_END(BrOn); break; } - case Expression::Id::RttCanonId: { - DELEGATE_START(RttCanon); - DELEGATE_END(RttCanon); - break; - } - case Expression::Id::RttSubId: { - DELEGATE_START(RttSub); - DELEGATE_FIELD_CHILD(RttSub, parent); - DELEGATE_FIELD_INT(RttSub, fresh); - DELEGATE_END(RttSub); - break; - } case Expression::Id::StructNewId: { DELEGATE_START(StructNew); - DELEGATE_FIELD_OPTIONAL_CHILD(StructNew, rtt); DELEGATE_FIELD_CHILD_VECTOR(StructNew, operands); DELEGATE_END(StructNew); break; @@ -661,7 +645,6 @@ switch (DELEGATE_ID) { } case Expression::Id::ArrayNewId: { DELEGATE_START(ArrayNew); - DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, rtt); DELEGATE_FIELD_CHILD(ArrayNew, size); DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, init); DELEGATE_END(ArrayNew); @@ -669,7 +652,6 @@ switch (DELEGATE_ID) { } case Expression::Id::ArrayInitId: { DELEGATE_START(ArrayInit); - DELEGATE_FIELD_OPTIONAL_CHILD(ArrayInit, rtt); DELEGATE_FIELD_CHILD_VECTOR(ArrayInit, values); DELEGATE_END(ArrayInit); break; diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def index 24531b149..b88a55556 100644 --- a/src/wasm-delegations.def +++ b/src/wasm-delegations.def @@ -73,8 +73,6 @@ DELEGATE(CallRef); DELEGATE(RefTest); DELEGATE(RefCast); DELEGATE(BrOn); -DELEGATE(RttCanon); -DELEGATE(RttSub); DELEGATE(StructNew); DELEGATE(StructGet); DELEGATE(StructSet); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d00ccac43..254a1a2e2 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1467,19 +1467,6 @@ public: if (ref.breaking()) { return typename Cast::Breaking{ref}; } - // The RTT value for the type we are trying to cast to. - Literal intendedRtt; - if (curr->rtt) { - // This is a dynamic check with an RTT. - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return typename Cast::Breaking{rtt}; - } - intendedRtt = rtt.getSingleValue(); - } else { - // If there is no explicit RTT, use the canonical RTT for the static type. - intendedRtt = Literal::makeCanonicalRtt(curr->intendedType); - } Literal original = ref.getSingleValue(); if (original.isNull()) { return typename Cast::Null{original}; @@ -1489,30 +1476,10 @@ public: if (!original.isData() && !original.isFunction()) { return typename Cast::Failure{original}; } - Literal actualRtt; - if (original.isFunction()) { - // Function references always have the canonical RTTs of the functions - // they reference. We must have a module to look up the function's type to - // get that canonical RTT. - auto* func = - module ? module->getFunctionOrNull(original.getFunc()) : nullptr; - if (!func) { - return typename Cast::Breaking{NONCONSTANT_FLOW}; - } - actualRtt = Literal::makeCanonicalRtt(func->type); - } else { - assert(original.isData()); - actualRtt = original.getGCData()->rtt; - }; - // We have the actual and intended RTTs, so perform the cast. - if (actualRtt.isSubRtt(intendedRtt)) { - HeapType resultType = intendedRtt.type.getHeapType(); - if (original.isFunction()) { - return typename Cast::Success{Literal{original.getFunc(), resultType}}; - } else { - return - typename Cast::Success{Literal(original.getGCData(), resultType)}; - } + HeapType actualType = original.type.getHeapType(); + // We have the actual and intended types, so perform the cast. + if (HeapType::isSubType(actualType, curr->intendedType)) { + return typename Cast::Success{original}; } else { return typename Cast::Failure{original}; } @@ -1629,33 +1596,8 @@ public: } return {value}; } - Flow visitRttCanon(RttCanon* curr) { - return Literal::makeCanonicalRtt(curr->type.getHeapType()); - } - Flow visitRttSub(RttSub* curr) { - Flow parent = self()->visit(curr->parent); - if (parent.breaking()) { - return parent; - } - auto parentValue = parent.getSingleValue(); - auto newSupers = std::make_unique<RttSupers>(parentValue.getRttSupers()); - newSupers->push_back(parentValue.type.getHeapType()); - if (curr->fresh) { - newSupers->back().makeFresh(); - } - return Literal(std::move(newSupers), curr->type); - } - Flow visitStructNew(StructNew* curr) { NOTE_ENTER("StructNew"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); - } if (curr->type == Type::unreachable) { // We cannot proceed to compute the heap type, as there isn't one. Just // find why we are unreachable, and stop there. @@ -1681,10 +1623,7 @@ public: data[i] = value.getSingleValue(); } } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared<GCData>(rttVal, data), + return Literal(std::make_shared<GCData>(curr->type.getHeapType(), data), curr->type.getHeapType()); } Flow visitStructGet(StructGet* curr) { @@ -1728,14 +1667,6 @@ public: Flow visitArrayNew(ArrayNew* curr) { NOTE_ENTER("ArrayNew"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); - } auto size = self()->visit(curr->size); if (size.breaking()) { return size; @@ -1769,22 +1700,11 @@ public: data[i] = value; } } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared<GCData>(rttVal, data), + return Literal(std::make_shared<GCData>(curr->type.getHeapType(), data), curr->type.getHeapType()); } Flow visitArrayInit(ArrayInit* curr) { NOTE_ENTER("ArrayInit"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); - } Index num = curr->values.size(); if (num >= ArrayLimit) { hostLimit("allocation failure"); @@ -1810,10 +1730,7 @@ public: } data[i] = truncateForPacking(value.getSingleValue(), field); } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared<GCData>(rttVal, data), + return Literal(std::make_shared<GCData>(curr->type.getHeapType(), data), curr->type.getHeapType()); } Flow visitArrayGet(ArrayGet* curr) { diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 0829a35f2..64f764721 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -279,24 +279,16 @@ private: Expression* makeCallRef(Element& s, bool isReturn); Expression* makeI31New(Element& s); Expression* makeI31Get(Element& s, bool signed_); - Expression* makeRefTest(Element& s); Expression* makeRefTestStatic(Element& s); - Expression* makeRefCast(Element& s); Expression* makeRefCastStatic(Element& s); Expression* makeRefCastNopStatic(Element& s); Expression* makeBrOn(Element& s, BrOnOp op); Expression* makeBrOnStatic(Element& s, BrOnOp op); - Expression* makeRttCanon(Element& s); - Expression* makeRttSub(Element& s); - Expression* makeRttFreshSub(Element& s); - Expression* makeStructNew(Element& s, bool default_); Expression* makeStructNewStatic(Element& s, bool default_); Index getStructIndex(Element& type, Element& field); Expression* makeStructGet(Element& s, bool signed_ = false); Expression* makeStructSet(Element& s); - Expression* makeArrayNew(Element& s, bool default_); Expression* makeArrayNewStatic(Element& s, bool default_); - Expression* makeArrayInit(Element& s); Expression* makeArrayInitStatic(Element& s); Expression* makeArrayGet(Element& s, bool signed_ = false); Expression* makeArraySet(Element& s); @@ -359,7 +351,7 @@ private: // Struct/Array instructions have an unnecessary heap type that is just for // validation (except for the case of unreachability, but that's not a problem - // anyhow, we can ignore it there). That is, we also have a reference / rtt + // anyhow, we can ignore it there). That is, we also have a reference typed // child from which we can infer the type anyhow, and we just need to check // that type is the same. void diff --git a/src/wasm-type.h b/src/wasm-type.h index 4d87ac68d..014e28646 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -67,7 +67,6 @@ struct Signature; struct Field; struct Struct; struct Array; -struct Rtt; enum Nullability { NonNullable, Nullable }; enum Mutability { Immutable, Mutable }; @@ -128,9 +127,6 @@ public: // Signature, Struct or Array via implicit conversion to HeapType. Type(HeapType, Nullability nullable); - // Construct from rtt description - Type(Rtt); - // Predicates // Compound Concrete // Type Basic │ Single│ @@ -152,7 +148,6 @@ public: // ├─ Compound ──╫───┼───┼───┼───┤───────┤ │ // │ Ref ║ │ x │ x │ x │ f? n? │◄┘ // │ Tuple ║ │ x │ │ x │ │ - // │ Rtt ║ │ x │ x │ x │ │ // └─────────────╨───┴───┴───┴───┴───────┘ constexpr bool isBasic() const { return id <= _last_basic_type; } constexpr bool isConcrete() const { return id >= i32; } @@ -174,18 +169,10 @@ public: // is irrelevant. (For that reason, this is only the negation of isNullable() // on references, but both return false on non-references.) bool isNonNullable() const; - bool isRtt() const; bool isStruct() const; bool isArray() const; bool isDefaultable() const; - // Check if a type is either defaultable or non-nullable. This is useful in - // the case where we allow non-nullable types, but we disallow other things - // that are non-defaultable. For example, when GC-non-nullable references are - // allowed we can have a non-nullable reference, but we cannot have any other - // nondefaultable type. - bool isDefaultableOrNonNullable() const; - Nullability getNullability() const; private: @@ -237,12 +224,9 @@ public: const Tuple& getTuple() const; // Gets the heap type corresponding to this type, assuming that it is a - // reference or Rtt type. + // reference type. HeapType getHeapType() const; - // Gets the Rtt for this type, assuming that it is an Rtt type. - Rtt getRtt() const; - // Returns a number type based on its size in bytes and whether it is a float // type. static Type get(unsigned byteSize, bool float_); @@ -561,21 +545,6 @@ struct Array { std::string toString() const; }; -struct Rtt { - // An Rtt can have no depth specified - static constexpr uint32_t NoDepth = -1; - uint32_t depth; - HeapType heapType; - explicit Rtt(HeapType heapType) : depth(NoDepth), heapType(heapType) {} - Rtt(uint32_t depth, HeapType heapType) : depth(depth), heapType(heapType) {} - bool operator==(const Rtt& other) const { - return depth == other.depth && heapType == other.heapType; - } - bool operator!=(const Rtt& other) const { return !(*this == other); } - bool hasDepth() const { return depth != uint32_t(NoDepth); } - std::string toString() const; -}; - // TypeBuilder - allows for the construction of recursive types. Contains a // table of `n` mutable HeapTypes and can construct temporary types that are // backed by those HeapTypes, refering to them by reference. Those temporary @@ -623,11 +592,10 @@ struct TypeBuilder { HeapType getTempHeapType(size_t i); // Gets a temporary type or heap type for use in initializing the - // TypeBuilder's HeapTypes. For Ref and Rtt types, the HeapType may be a - // temporary HeapType owned by this builder or a canonical HeapType. + // TypeBuilder's HeapTypes. For Ref types, the HeapType may be a temporary + // HeapType owned by this builder or a canonical HeapType. Type getTempTupleType(const Tuple&); Type getTempRefType(HeapType heapType, Nullability nullable); - Type getTempRttType(Rtt rtt); // In nominal mode, or for nominal types, declare the HeapType being built at // index `i` to be an immediate subtype of the HeapType being built at index @@ -717,7 +685,6 @@ std::ostream& operator<<(std::ostream&, Signature); std::ostream& operator<<(std::ostream&, Field); std::ostream& operator<<(std::ostream&, Struct); std::ostream& operator<<(std::ostream&, Array); -std::ostream& operator<<(std::ostream&, Rtt); std::ostream& operator<<(std::ostream&, TypeBuilder::ErrorReason); } // namespace wasm @@ -752,10 +719,6 @@ template<> class hash<wasm::HeapType> { public: size_t operator()(const wasm::HeapType&) const; }; -template<> class hash<wasm::Rtt> { -public: - size_t operator()(const wasm::Rtt&) const; -}; template<> class hash<wasm::RecGroup> { public: size_t operator()(const wasm::RecGroup&) const; diff --git a/src/wasm.h b/src/wasm.h index 8c0e48da2..d0f632829 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -712,8 +712,6 @@ public: RefTestId, RefCastId, BrOnId, - RttCanonId, - RttSubId, StructNewId, StructGetId, StructSetId, @@ -1492,16 +1490,9 @@ public: Expression* ref; - // If rtt is provided then this is a dynamic test with an rtt. If nullptr then - // this is a static cast and intendedType is set, and it contains the type we - // intend to cast to. - Expression* rtt = nullptr; HeapType intendedType; void finalize(); - - // Returns the type we intend to cast to. - HeapType getIntendedType(); }; class RefCast : public SpecificExpression<Expression::RefCastId> { @@ -1510,8 +1501,6 @@ public: Expression* ref; - // See above with RefTest. - Expression* rtt = nullptr; HeapType intendedType; // Support the unsafe `ref.cast_nop_static` to enable precise cast overhead @@ -1520,9 +1509,6 @@ public: Safety safety = Safe; void finalize(); - - // Returns the type we intend to cast to. - HeapType getIntendedType(); }; class BrOn : public SpecificExpression<Expression::BrOnId> { @@ -1533,55 +1519,18 @@ public: Name name; Expression* ref; - // BrOnCast* has, like RefCast and RefTest, either an rtt or a static intended - // type. - Expression* rtt = nullptr; HeapType intendedType; - // TODO: BrOnNull also has an optional extra value in the spec, which we do - // not support. See also the discussion on - // https://github.com/WebAssembly/function-references/issues/45 - // - depending on the decision there, we may want to move BrOnNull into - // Break or a new class of its own. - void finalize(); - // Returns the type we intend to cast to. Relevant only for the cast variants. - HeapType getIntendedType(); - // Returns the type sent on the branch, if it is taken. Type getSentType(); }; -class RttCanon : public SpecificExpression<Expression::RttCanonId> { -public: - RttCanon(MixedArena& allocator) {} - - void finalize(); -}; - -class RttSub : public SpecificExpression<Expression::RttSubId> { -public: - RttSub(MixedArena& allocator) {} - - Expression* parent; - - // rtt.fresh_sub is like rtt.sub, but never caching or canonicalizing (i.e., - // it always returns a fresh RTT, non-identical to any other RTT in the - // system). - bool fresh = false; - - void finalize(); -}; - class StructNew : public SpecificExpression<Expression::StructNewId> { public: StructNew(MixedArena& allocator) : operands(allocator) {} - // A dynamic StructNew has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; - // A struct.new_with_default has empty operands. This does leave the case of a // struct with no fields ambiguous, but it doesn't make a difference in that // case, and binaryen doesn't guarantee roundtripping binaries anyhow. @@ -1625,10 +1574,6 @@ public: Expression* init = nullptr; Expression* size; - // A dynamic ArrayNew has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; - bool isWithDefault() { return !init; } void finalize(); @@ -1640,10 +1585,6 @@ public: ExpressionList values; - // A dynamic ArrayInit has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; - void finalize(); }; diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index b8a6c7e7a..05f9d93d5 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -53,8 +53,6 @@ Literal::Literal(Type type) : type(type) { if (isData()) { assert(!type.isNonNullable()); new (&gcData) std::shared_ptr<GCData>(); - } else if (type.isRtt()) { - new (this) Literal(Literal::makeCanonicalRtt(type.getHeapType())); } else { // For anything else, zero out all the union data. memset(&v128, 0, 16); @@ -71,11 +69,6 @@ Literal::Literal(std::shared_ptr<GCData> gcData, HeapType type) assert(isData()); } -Literal::Literal(std::unique_ptr<RttSupers>&& rttSupers, Type type) - : rttSupers(std::move(rttSupers)), type(type) { - assert(type.isRtt()); -} - Literal::Literal(const Literal& other) : type(other.type) { if (type.isBasic()) { switch (type.getBasic()) { @@ -104,11 +97,6 @@ Literal::Literal(const Literal& other) : type(other.type) { func = other.func; return; } - if (type.isRtt()) { - // Allocate a new RttSupers with a copy of the other's data. - new (&rttSupers) auto(std::make_unique<RttSupers>(*other.rttSupers)); - return; - } if (type.isRef()) { auto heapType = type.getHeapType(); if (heapType.isBasic()) { @@ -136,11 +124,8 @@ Literal::~Literal() { if (type.isBasic()) { return; } - if (isData()) { gcData.~shared_ptr(); - } else if (type.isRtt()) { - rttSupers.~unique_ptr(); } } @@ -152,18 +137,6 @@ Literal& Literal::operator=(const Literal& other) { return *this; } -Literal Literal::makeCanonicalRtt(HeapType type) { - auto supers = std::make_unique<RttSupers>(); - std::optional<HeapType> supertype; - for (auto curr = type; (supertype = curr.getSuperType()); curr = *supertype) { - supers->emplace_back(*supertype); - } - // We want the highest types to be first. - std::reverse(supers->begin(), supers->end()); - size_t depth = supers->size(); - return Literal(std::move(supers), Type(Rtt(depth, type))); -} - template<typename LaneT, int Lanes> static void extractBytes(uint8_t (&dest)[16], const LaneArray<Lanes>& lanes) { std::array<uint8_t, 16> bytes; @@ -228,8 +201,6 @@ Literal Literal::makeZero(Type type) { assert(type.isSingle()); if (type.isRef()) { return makeNull(type.getHeapType()); - } else if (type.isRtt()) { - return Literal(type); } else { return makeFromInt32(0, type); } @@ -257,11 +228,6 @@ std::shared_ptr<GCData> Literal::getGCData() const { return gcData; } -const RttSupers& Literal::getRttSupers() const { - assert(type.isRtt()); - return *rttSupers; -} - Literal Literal::castToF32() { assert(type == Type::i32); Literal ret(Type::f32); @@ -383,8 +349,6 @@ bool Literal::operator==(const Literal& other) const { // other non-null reference type literals cannot represent concrete values, // i.e. there is no concrete anyref or eqref other than null. WASM_UNREACHABLE("unexpected type"); - } else if (type.isRtt()) { - return *rttSupers == *other.rttSupers; } WASM_UNREACHABLE("unexpected type"); } @@ -494,7 +458,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { if (literal.isData()) { auto data = literal.getGCData(); if (data) { - o << "[ref " << data->rtt << ' ' << data->values << ']'; + o << "[ref " << data->type << ' ' << data->values << ']'; } else { o << "[ref null " << literal.type << ']'; } @@ -524,15 +488,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { WASM_UNREACHABLE("type should have been handled above"); } } - } else if (literal.type.isRtt()) { - o << "[rtt "; - for (auto& super : literal.getRttSupers()) { - o << super.type << " :> "; - if (super.freshPtr) { - o << " (fresh)"; - } - } - o << literal.type << ']'; } else { TODO_SINGLE_COMPOUND(literal.type); switch (literal.type.getBasic()) { @@ -2564,31 +2519,4 @@ Literal Literal::relaxedFmsF64x2(const Literal& left, return ternary<2, &Literal::getLanesF64x2, &Literal::fms>(*this, left, right); } -bool Literal::isSubRtt(const Literal& other) const { - assert(type.isRtt() && other.type.isRtt()); - // For this literal to be a sub-rtt of the other rtt, the supers must be a - // superset. That is, if other is a->b->c then we should be a->b->c as well - // with possibly ->d->.. added. The rttSupers array represents those chains, - // but only the supers, which means the last item in the chain is simply the - // type of the literal. - const auto& supers = getRttSupers(); - const auto& otherSupers = other.getRttSupers(); - if (otherSupers.size() > supers.size()) { - return false; - } - for (Index i = 0; i < otherSupers.size(); i++) { - if (supers[i] != otherSupers[i]) { - return false; - } - } - // If we have more supers than other, compare that extra super. Otherwise, - // we have the same amount of supers, and must be completely identical to - // other. - if (otherSupers.size() < supers.size()) { - return other.type.getHeapType() == supers[otherSupers.size()].type; - } else { - return other.type == type; - } -} - } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 4e8e3f0d7..b74ef017b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1383,17 +1383,6 @@ void WasmBinaryWriter::writeType(Type type) { writeHeapType(type.getHeapType()); return; } - if (type.isRtt()) { - auto rtt = type.getRtt(); - if (rtt.hasDepth()) { - o << S32LEB(BinaryConsts::EncodedType::rtt_n); - o << U32LEB(rtt.depth); - } else { - o << S32LEB(BinaryConsts::EncodedType::rtt); - } - writeIndexedHeapType(rtt.heapType); - return; - } int ret = 0; TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { @@ -1877,14 +1866,6 @@ Type WasmBinaryBuilder::getType(int initial) { return Type(getHeapType(), Nullable); case BinaryConsts::EncodedType::nonnullable: return Type(getHeapType(), NonNullable); - case BinaryConsts::EncodedType::rtt_n: { - auto depth = getU32LEB(); - auto heapType = getIndexedHeapType(); - return Type(Rtt(depth, heapType)); - } - case BinaryConsts::EncodedType::rtt: { - return Type(Rtt(getIndexedHeapType())); - } default: throwError("invalid wasm type: " + std::to_string(initial)); } @@ -2029,16 +2010,6 @@ void WasmBinaryBuilder::readTypes() { } return builder.getTempRefType(builder[size_t(htCode)], nullability); } - case BinaryConsts::EncodedType::rtt_n: - case BinaryConsts::EncodedType::rtt: { - auto depth = typeCode == BinaryConsts::EncodedType::rtt ? Rtt::NoDepth - : getU32LEB(); - auto htCode = getU32LEB(); - if (size_t(htCode) >= builder.size()) { - throwError("invalid type index: " + std::to_string(htCode)); - } - return builder.getTempRttType(Rtt(depth, builder[htCode])); - } default: throwError("unexpected type index: " + std::to_string(typeCode)); } @@ -3875,12 +3846,6 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitBrOn(curr, opcode)) { break; } - if (maybeVisitRttCanon(curr, opcode)) { - break; - } - if (maybeVisitRttSub(curr, opcode)) { - break; - } if (maybeVisitStructNew(curr, opcode)) { break; } @@ -6793,12 +6758,7 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) { } bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefTest) { - auto* rtt = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeRefTest(ref, rtt); - return true; - } else if (code == BinaryConsts::RefTestStatic) { + if (code == BinaryConsts::RefTestStatic) { auto intendedType = getIndexedHeapType(); auto* ref = popNonVoidExpression(); out = Builder(wasm).makeRefTest(ref, intendedType); @@ -6808,13 +6768,8 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { } bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefCast) { - auto* rtt = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeRefCast(ref, rtt); - return true; - } else if (code == BinaryConsts::RefCastStatic || - code == BinaryConsts::RefCastNopStatic) { + if (code == BinaryConsts::RefCastStatic || + code == BinaryConsts::RefCastNopStatic) { auto intendedType = getIndexedHeapType(); auto* ref = popNonVoidExpression(); auto safety = @@ -6834,11 +6789,9 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) { case BinaryConsts::BrOnNonNull: op = BrOnNonNull; break; - case BinaryConsts::BrOnCast: case BinaryConsts::BrOnCastStatic: op = BrOnCast; break; - case BinaryConsts::BrOnCastFail: case BinaryConsts::BrOnCastStaticFail: op = BrOnCastFail; break; @@ -6871,35 +6824,8 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) { out = Builder(wasm).makeBrOn(op, name, ref, intendedType); return true; } - Expression* rtt = nullptr; - if (op == BrOnCast || op == BrOnCastFail) { - rtt = popNonVoidExpression(); - } auto* ref = popNonVoidExpression(); - out = ValidatingBuilder(wasm, pos).validateAndMakeBrOn(op, name, ref, rtt); - return true; -} - -bool WasmBinaryBuilder::maybeVisitRttCanon(Expression*& out, uint32_t code) { - if (code != BinaryConsts::RttCanon) { - return false; - } - auto heapType = getIndexedHeapType(); - out = Builder(wasm).makeRttCanon(heapType); - return true; -} - -bool WasmBinaryBuilder::maybeVisitRttSub(Expression*& out, uint32_t code) { - if (code != BinaryConsts::RttSub && code != BinaryConsts::RttFreshSub) { - return false; - } - auto targetHeapType = getIndexedHeapType(); - auto* parent = popNonVoidExpression(); - if (code == BinaryConsts::RttSub) { - out = Builder(wasm).makeRttSub(targetHeapType, parent); - } else { - out = Builder(wasm).makeRttFreshSub(targetHeapType, parent); - } + out = ValidatingBuilder(wasm, pos).validateAndMakeBrOn(op, name, ref); return true; } @@ -6917,21 +6843,6 @@ bool WasmBinaryBuilder::maybeVisitStructNew(Expression*& out, uint32_t code) { } out = Builder(wasm).makeStructNew(heapType, operands); return true; - } else if (code == BinaryConsts::StructNewWithRtt || - code == BinaryConsts::StructNewDefaultWithRtt) { - auto heapType = getIndexedHeapType(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - std::vector<Expression*> operands; - if (code == BinaryConsts::StructNewWithRtt) { - auto numOperands = heapType.getStruct().fields.size(); - operands.resize(numOperands); - for (Index i = 0; i < numOperands; i++) { - operands[numOperands - i - 1] = popNonVoidExpression(); - } - } - out = Builder(wasm).makeStructNew(rtt, operands); - return true; } return false; } @@ -6987,18 +6898,6 @@ bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) { } out = Builder(wasm).makeArrayNew(heapType, size, init); return true; - } else if (code == BinaryConsts::ArrayNewWithRtt || - code == BinaryConsts::ArrayNewDefaultWithRtt) { - auto heapType = getIndexedHeapType(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - auto* size = popNonVoidExpression(); - Expression* init = nullptr; - if (code == BinaryConsts::ArrayNewWithRtt) { - init = popNonVoidExpression(); - } - out = Builder(wasm).makeArrayNew(rtt, size, init); - return true; } return false; } @@ -7013,17 +6912,6 @@ bool WasmBinaryBuilder::maybeVisitArrayInit(Expression*& out, uint32_t code) { } out = Builder(wasm).makeArrayInit(heapType, values); return true; - } else if (code == BinaryConsts::ArrayInit) { - auto heapType = getIndexedHeapType(); - auto size = getU32LEB(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - std::vector<Expression*> values(size); - for (size_t i = 0; i < size; i++) { - values[size - i - 1] = popNonVoidExpression(); - } - out = Builder(wasm).makeArrayInit(rtt, values); - return true; } return false; } @@ -7370,7 +7258,7 @@ void WasmBinaryBuilder::validateHeapTypeUsingChild(Expression* child, if (child->type == Type::unreachable) { return; } - if ((!child->type.isRef() && !child->type.isRtt()) || + if (!child->type.isRef() || !HeapType::isSubType(child->type.getHeapType(), heapType)) { throwError("bad heap type: expected " + heapType.toString() + " but found " + child->type.toString()); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 38ec788ba..f13091c91 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -54,7 +54,7 @@ namespace wasm { static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), FUNC_SUBTYPE("func_subtype"), STRUCT_SUBTYPE("struct_subtype"), ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), REC("rec"), I8("i8"), - I16("i16"), RTT("rtt"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); + I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); static Address getAddress(const Element* s) { return atoll(s->c_str()); } @@ -752,46 +752,11 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } }; - auto parseRttType = [&](Element& elem) -> Type { - // '(' 'rtt' depth? typeidx ')' - uint32_t depth; - Element* idx; - switch (elem.size()) { - default: - throw ParseException( - "unexpected number of rtt parameters", elem.line, elem.col); - case 2: - depth = Rtt::NoDepth; - idx = elem[1]; - break; - case 3: - if (!String::isNumber(elem[1]->c_str())) { - throw ParseException( - "invalid rtt depth", elem[1]->line, elem[1]->col); - } - depth = atoi(elem[1]->c_str()); - idx = elem[2]; - break; - } - if (idx->dollared()) { - HeapType type = builder[typeIndices[idx->c_str()]]; - return builder.getTempRttType(Rtt(depth, type)); - } else if (String::isNumber(idx->c_str())) { - size_t index = atoi(idx->c_str()); - if (index < numTypes) { - return builder.getTempRttType(Rtt(depth, builder[index])); - } - } - throw ParseException("invalid type index", idx->line, idx->col); - }; - auto parseValType = [&](Element& elem) { if (elem.isStr()) { return stringToType(elem.c_str()); } else if (*elem[0] == REF) { return parseRefType(elem); - } else if (*elem[0] == RTT) { - return parseRttType(elem); } else { throw ParseException("unknown valtype kind", elem[0]->line, elem[0]->col); } @@ -1281,18 +1246,6 @@ Type SExpressionWasmBuilder::elementToType(Element& s) { } return Type(parseHeapType(*s[i]), nullable); } - if (elementStartsWith(s, RTT)) { - // It's an RTT, something like (rtt N $typename) or just (rtt $typename) - // if there is no depth. - if (s[1]->dollared()) { - auto heapType = parseHeapType(*s[1]); - return Type(Rtt(heapType)); - } else { - auto depth = atoi(s[1]->str().c_str()); - auto heapType = parseHeapType(*s[2]); - return Type(Rtt(depth, heapType)); - } - } // It's a tuple. std::vector<Type> types; for (size_t i = 0; i < s.size(); ++i) { @@ -2702,24 +2655,12 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { return ret; } -Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefTest(ref, rtt); -} - Expression* SExpressionWasmBuilder::makeRefTestStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); return Builder(wasm).makeRefTest(ref, heapType); } -Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, rtt); -} - Expression* SExpressionWasmBuilder::makeRefCastStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); @@ -2735,12 +2676,8 @@ Expression* SExpressionWasmBuilder::makeRefCastNopStatic(Element& s) { Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) { auto name = getLabel(*s[1]); auto* ref = parseExpression(*s[2]); - Expression* rtt = nullptr; - if (op == BrOnCast || op == BrOnCastFail) { - rtt = parseExpression(*s[3]); - } return ValidatingBuilder(wasm, s.line, s.col) - .validateAndMakeBrOn(op, name, ref, rtt); + .validateAndMakeBrOn(op, name, ref); } Expression* SExpressionWasmBuilder::makeBrOnStatic(Element& s, BrOnOp op) { @@ -2750,39 +2687,6 @@ Expression* SExpressionWasmBuilder::makeBrOnStatic(Element& s, BrOnOp op) { return Builder(wasm).makeBrOn(op, name, ref, heapType); } -Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) { - return Builder(wasm).makeRttCanon(parseHeapType(*s[1])); -} - -Expression* SExpressionWasmBuilder::makeRttSub(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto parent = parseExpression(*s[2]); - return Builder(wasm).makeRttSub(heapType, parent); -} - -Expression* SExpressionWasmBuilder::makeRttFreshSub(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto parent = parseExpression(*s[2]); - return Builder(wasm).makeRttFreshSub(heapType, parent); -} - -Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { - auto heapType = parseHeapType(*s[1]); - auto numOperands = s.size() - 3; - if (default_ && numOperands > 0) { - throw ParseException( - "arguments provided for struct.new_with_default", s.line, s.col); - } - std::vector<Expression*> operands; - operands.resize(numOperands); - for (Index i = 0; i < numOperands; i++) { - operands[i] = parseExpression(*s[i + 2]); - } - auto* rtt = parseExpression(*s[s.size() - 1]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeStructNew(rtt, operands); -} - Expression* SExpressionWasmBuilder::makeStructNewStatic(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); @@ -2841,19 +2745,6 @@ Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { return Builder(wasm).makeStructSet(index, ref, value); } -Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) { - auto heapType = parseHeapType(*s[1]); - Expression* init = nullptr; - size_t i = 2; - if (!default_) { - init = parseExpression(*s[i++]); - } - auto* size = parseExpression(*s[i++]); - auto* rtt = parseExpression(*s[i++]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayNew(rtt, size, init); -} - Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); @@ -2866,18 +2757,6 @@ Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, return Builder(wasm).makeArrayNew(heapType, size, init); } -Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) { - auto heapType = parseHeapType(*s[1]); - size_t i = 2; - std::vector<Expression*> values; - while (i < s.size() - 1) { - values.push_back(parseExpression(*s[i++])); - } - auto* rtt = parseExpression(*s[i++]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayInit(rtt, values); -} - Expression* SExpressionWasmBuilder::makeArrayInitStatic(Element& s) { auto heapType = parseHeapType(*s[1]); size_t i = 2; @@ -3853,7 +3732,7 @@ void SExpressionWasmBuilder::validateHeapTypeUsingChild(Expression* child, if (child->type == Type::unreachable) { return; } - if ((!child->type.isRef() && !child->type.isRtt()) || + if (!child->type.isRef() || !HeapType::isSubType(child->type.getHeapType(), heapType)) { throw ParseException("bad heap type: expected " + heapType.toString() + " but found " + child->type.toString(), diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 2fc06b176..c29384dad 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2016,26 +2016,18 @@ void BinaryInstWriter::visitCallRef(CallRef* curr) { void BinaryInstWriter::visitRefTest(RefTest* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefTest); - } else { - o << U32LEB(BinaryConsts::RefTestStatic); - parent.writeIndexedHeapType(curr->intendedType); - } + o << U32LEB(BinaryConsts::RefTestStatic); + parent.writeIndexedHeapType(curr->intendedType); } void BinaryInstWriter::visitRefCast(RefCast* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefCast); + if (curr->safety == RefCast::Unsafe) { + o << U32LEB(BinaryConsts::RefCastNopStatic); } else { - if (curr->safety == RefCast::Unsafe) { - o << U32LEB(BinaryConsts::RefCastNopStatic); - } else { - o << U32LEB(BinaryConsts::RefCastStatic); - } - parent.writeIndexedHeapType(curr->intendedType); + o << U32LEB(BinaryConsts::RefCastStatic); } + parent.writeIndexedHeapType(curr->intendedType); } void BinaryInstWriter::visitBrOn(BrOn* curr) { @@ -2048,19 +2040,11 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) { break; case BrOnCast: o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCast); - } else { - o << U32LEB(BinaryConsts::BrOnCastStatic); - } + o << U32LEB(BinaryConsts::BrOnCastStatic); break; case BrOnCastFail: o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCastFail); - } else { - o << U32LEB(BinaryConsts::BrOnCastStaticFail); - } + o << U32LEB(BinaryConsts::BrOnCastStaticFail); break; case BrOnFunc: o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnFunc); @@ -2084,36 +2068,17 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) { WASM_UNREACHABLE("invalid br_on_*"); } o << U32LEB(getBreakIndex(curr->name)); - if ((curr->op == BrOnCast || curr->op == BrOnCastFail) && !curr->rtt) { + if (curr->op == BrOnCast || curr->op == BrOnCastFail) { parent.writeIndexedHeapType(curr->intendedType); } } -void BinaryInstWriter::visitRttCanon(RttCanon* curr) { - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttCanon); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); -} - -void BinaryInstWriter::visitRttSub(RttSub* curr) { - o << int8_t(BinaryConsts::GCPrefix); - o << U32LEB(curr->fresh ? BinaryConsts::RttFreshSub : BinaryConsts::RttSub); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); -} - void BinaryInstWriter::visitStructNew(StructNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::StructNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::StructNewDefault); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefault); - } else { - o << U32LEB(BinaryConsts::StructNew); - } + o << U32LEB(BinaryConsts::StructNew); } parent.writeIndexedHeapType(curr->type.getHeapType()); } @@ -2142,29 +2107,17 @@ void BinaryInstWriter::visitStructSet(StructSet* curr) { void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::ArrayNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::ArrayNewDefault); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefault); - } else { - o << U32LEB(BinaryConsts::ArrayNew); - } + o << U32LEB(BinaryConsts::ArrayNew); } parent.writeIndexedHeapType(curr->type.getHeapType()); } void BinaryInstWriter::visitArrayInit(ArrayInit* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::ArrayInit); - } else { - o << U32LEB(BinaryConsts::ArrayInitStatic); - } + o << U32LEB(BinaryConsts::ArrayInitStatic); parent.writeIndexedHeapType(curr->type.getHeapType()); o << U32LEB(curr->values.size()); } diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 84b11000f..23d2877f7 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -60,7 +60,6 @@ struct TypeInfo { enum Kind { TupleKind, RefKind, - RttKind, } kind; struct Ref { HeapType heapType; @@ -69,20 +68,17 @@ struct TypeInfo { union { Tuple tuple; Ref ref; - Rtt rtt; }; TypeInfo(const Tuple& tuple) : kind(TupleKind), tuple(tuple) {} TypeInfo(Tuple&& tuple) : kind(TupleKind), tuple(std::move(tuple)) {} TypeInfo(HeapType heapType, Nullability nullable) : kind(RefKind), ref{heapType, nullable} {} - TypeInfo(Rtt rtt) : kind(RttKind), rtt(rtt) {} TypeInfo(const TypeInfo& other); ~TypeInfo(); constexpr bool isTuple() const { return kind == TupleKind; } constexpr bool isRef() const { return kind == RefKind; } - constexpr bool isRtt() const { return kind == RttKind; } bool isNullable() const { return kind == RefKind && ref.nullable; } @@ -165,7 +161,6 @@ struct SubTyper { bool isSubType(const Signature& a, const Signature& b); bool isSubType(const Struct& a, const Struct& b); bool isSubType(const Array& a, const Array& b); - bool isSubType(const Rtt& a, const Rtt& b); }; // Helper for finding the equirecursive least upper bound of two types. @@ -192,7 +187,6 @@ private: std::optional<Signature> lub(const Signature& a, const Signature& b); Struct lub(const Struct& a, const Struct& b); std::optional<Array> lub(const Array& a, const Array& b); - std::optional<Rtt> lub(const Rtt& a, const Rtt& b); }; // Helper for printing types. @@ -231,7 +225,6 @@ struct TypePrinter { std::optional<HeapType> super = std::nullopt); std::ostream& print(const Array& array, std::optional<HeapType> super = std::nullopt); - std::ostream& print(const Rtt& rtt); }; // Helper for hashing the shapes of TypeInfos and HeapTypeInfos. Keeps track of @@ -255,7 +248,6 @@ struct FiniteShapeHasher { size_t hash(const Signature& sig); size_t hash(const Struct& struct_); size_t hash(const Array& array); - size_t hash(const Rtt& rtt); }; // Helper for comparing the shapes of TypeInfos and HeapTypeInfos for equality. @@ -281,7 +273,6 @@ struct FiniteShapeEquator { bool eq(const Signature& a, const Signature& b); bool eq(const Struct& a, const Struct& b); bool eq(const Array& a, const Array& b); - bool eq(const Rtt& a, const Rtt& b); }; struct RecGroupHasher { @@ -307,7 +298,6 @@ struct RecGroupHasher { size_t hash(const Signature& sig) const; size_t hash(const Struct& struct_) const; size_t hash(const Array& array) const; - size_t hash(const Rtt& rtt) const; }; struct RecGroupEquator { @@ -334,7 +324,6 @@ struct RecGroupEquator { bool eq(const Signature& a, const Signature& b) const; bool eq(const Struct& a, const Struct& b) const; bool eq(const Array& a, const Array& b) const; - bool eq(const Rtt& a, const Rtt& b) const; }; // A wrapper around a RecGroup that provides equality and hashing based on the @@ -626,9 +615,6 @@ TypeInfo::TypeInfo(const TypeInfo& other) { case RefKind: new (&ref) auto(other.ref); return; - case RttKind: - new (&rtt) auto(other.rtt); - return; } WASM_UNREACHABLE("unexpected kind"); } @@ -641,9 +627,6 @@ TypeInfo::~TypeInfo() { case RefKind: ref.~Ref(); return; - case RttKind: - rtt.~Rtt(); - return; } WASM_UNREACHABLE("unexpected kind"); } @@ -670,8 +653,6 @@ bool TypeInfo::operator==(const TypeInfo& other) const { case RefKind: return ref.nullable == other.ref.nullable && ref.heapType == other.ref.heapType; - case RttKind: - return rtt == other.rtt; } WASM_UNREACHABLE("unexpected kind"); } @@ -947,11 +928,6 @@ Type::Type(HeapType heapType, Nullability nullable) { new (this) Type(globalTypeStore.insert(TypeInfo(heapType, nullable))); } -Type::Type(Rtt rtt) { - assert(!isTemp(rtt.heapType) && "Leaking temporary type!"); - new (this) Type(globalTypeStore.insert(rtt)); -} - bool Type::isTuple() const { if (isBasic()) { return false; @@ -1002,14 +978,6 @@ bool Type::isNonNullable() const { } } -bool Type::isRtt() const { - if (isBasic()) { - return false; - } else { - return getTypeInfo(*this)->isRtt(); - } -} - bool Type::isStruct() const { return isRef() && getHeapType().isStruct(); } bool Type::isArray() const { return isRef() && getHeapType().isArray(); } @@ -1026,19 +994,7 @@ bool Type::isDefaultable() const { } return true; } - return isConcrete() && !isNonNullable() && !isRtt(); -} - -bool Type::isDefaultableOrNonNullable() const { - if (isTuple()) { - for (auto t : *this) { - if (!t.isDefaultableOrNonNullable()) { - return false; - } - } - return true; - } - return isConcrete() && !isRtt(); + return isConcrete() && !isNonNullable(); } Nullability Type::getNullability() const { @@ -1132,8 +1088,6 @@ FeatureSet Type::getFeatures() const { // load of the wasm we don't know the features yet, so we apply the more // refined types), so we don't add that in any case here. return FeatureSet::ReferenceTypes; - } else if (t.isRtt()) { - return FeatureSet::ReferenceTypes | FeatureSet::GC; } TODO_SINGLE_COMPOUND(t); switch (t.getBasic()) { @@ -1179,18 +1133,11 @@ HeapType Type::getHeapType() const { break; case TypeInfo::RefKind: return info->ref.heapType; - case TypeInfo::RttKind: - return info->rtt.heapType; } WASM_UNREACHABLE("Unexpected type"); } } -Rtt Type::getRtt() const { - assert(isRtt()); - return getTypeInfo(*this)->rtt; -} - Type Type::get(unsigned byteSize, bool float_) { if (byteSize < 4) { return Type::i32; @@ -1264,15 +1211,6 @@ Type Type::getLeastUpperBound(Type a, Type b) { HeapType::getLeastUpperBound(a.getHeapType(), b.getHeapType()); return Type(heapType, nullability); } - if (a.isRtt() && b.isRtt()) { - auto heapType = a.getHeapType(); - if (heapType != b.getHeapType()) { - return Type::none; - } - auto rttA = a.getRtt(), rttB = b.getRtt(); - auto depth = rttA.depth == rttB.depth ? rttA.depth : Rtt::NoDepth; - return Rtt(depth, heapType); - } return Type::none; WASM_UNREACHABLE("unexpected type"); } @@ -1593,7 +1531,6 @@ std::string Tuple::toString() const { return genericToString(*this); } std::string Signature::toString() const { return genericToString(*this); } std::string Struct::toString() const { return genericToString(*this); } std::string Array::toString() const { return genericToString(*this); } -std::string Rtt::toString() const { return genericToString(*this); } std::ostream& operator<<(std::ostream& os, Type type) { return TypePrinter(os).print(type); @@ -1622,9 +1559,6 @@ std::ostream& operator<<(std::ostream& os, Struct struct_) { std::ostream& operator<<(std::ostream& os, Array array) { return TypePrinter(os).print(array); } -std::ostream& operator<<(std::ostream& os, Rtt rtt) { - return TypePrinter(os).print(rtt); -} std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) { switch (reason) { case TypeBuilder::ErrorReason::SelfSupertype: @@ -1670,9 +1604,6 @@ bool SubTyper::isSubType(Type a, Type b) { if (a.isTuple() && b.isTuple()) { return isSubType(a.getTuple(), b.getTuple()); } - if (a.isRtt() && b.isRtt()) { - return isSubType(a.getRtt(), b.getRtt()); - } return false; } @@ -1783,13 +1714,6 @@ bool SubTyper::isSubType(const Array& a, const Array& b) { return isSubType(a.element, b.element); } -bool SubTyper::isSubType(const Rtt& a, const Rtt& b) { - // (rtt n $x) is a subtype of (rtt $x), that is, if the only difference in - // information is that the left side specifies a depth while the right side - // allows any depth. - return a.heapType == b.heapType && a.hasDepth() && !b.hasDepth(); -} - bool TypeBounder::hasLeastUpperBound(Type a, Type b) { return bool(lub(a, b)); } Type TypeBounder::getLeastUpperBound(Type a, Type b) { @@ -1847,12 +1771,6 @@ std::optional<Type> TypeBounder::lub(Type a, Type b) { (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; HeapType heapType = lub(a.getHeapType(), b.getHeapType()); return builder.getTempRefType(heapType, nullability); - } else if (a.isRtt() && b.isRtt()) { - auto rtt = lub(a.getRtt(), b.getRtt()); - if (!rtt) { - return {}; - } - return builder.getTempRttType(*rtt); } return {}; } @@ -1987,14 +1905,6 @@ std::optional<Array> TypeBounder::lub(const Array& a, const Array& b) { } } -std::optional<Rtt> TypeBounder::lub(const Rtt& a, const Rtt& b) { - if (a.heapType != b.heapType) { - return {}; - } - uint32_t depth = (a.depth == b.depth) ? a.depth : Rtt::NoDepth; - return Rtt(depth, a.heapType); -} - void TypePrinter::printHeapTypeName(HeapType type) { if (type.isBasic()) { print(type); @@ -2080,8 +1990,6 @@ std::ostream& TypePrinter::print(Type type) { } printHeapTypeName(heapType); os << ')'; - } else if (type.isRtt()) { - print(type.getRtt()); } else { WASM_UNREACHABLE("unexpected type"); } @@ -2234,15 +2142,6 @@ std::ostream& TypePrinter::print(const Array& array, return os << ')'; } -std::ostream& TypePrinter::print(const Rtt& rtt) { - os << "(rtt "; - if (rtt.hasDepth()) { - os << rtt.depth << ' '; - } - printHeapTypeName(rtt.heapType); - return os << ')'; -} - size_t FiniteShapeHasher::hash(Type type) { size_t digest = wasm::hash(type.isBasic()); if (type.isBasic()) { @@ -2285,9 +2184,6 @@ size_t FiniteShapeHasher::hash(const TypeInfo& info) { rehash(digest, info.ref.nullable); hash_combine(digest, hash(info.ref.heapType)); return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; } WASM_UNREACHABLE("unexpected kind"); } @@ -2355,12 +2251,6 @@ size_t FiniteShapeHasher::hash(const Array& array) { return hash(array.element); } -size_t FiniteShapeHasher::hash(const Rtt& rtt) { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - bool FiniteShapeEquator::eq(Type a, Type b) { if (a.isBasic() != b.isBasic()) { return false; @@ -2404,8 +2294,6 @@ bool FiniteShapeEquator::eq(const TypeInfo& a, const TypeInfo& b) { case TypeInfo::RefKind: return a.ref.nullable == b.ref.nullable && eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); } WASM_UNREACHABLE("unexpected kind"); } @@ -2466,10 +2354,6 @@ bool FiniteShapeEquator::eq(const Array& a, const Array& b) { return eq(a.element, b.element); } -bool FiniteShapeEquator::eq(const Rtt& a, const Rtt& b) { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - size_t RecGroupHasher::operator()() const { size_t digest = wasm::hash(group.size()); for (auto type : group) { @@ -2526,9 +2410,6 @@ size_t RecGroupHasher::hash(const TypeInfo& info) const { rehash(digest, info.ref.nullable); hash_combine(digest, hash(info.ref.heapType)); return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; } WASM_UNREACHABLE("unexpected kind"); } @@ -2589,12 +2470,6 @@ size_t RecGroupHasher::hash(const Array& array) const { return hash(array.element); } -size_t RecGroupHasher::hash(const Rtt& rtt) const { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - bool RecGroupEquator::operator()() const { if (newGroup == otherGroup) { return true; @@ -2655,8 +2530,6 @@ bool RecGroupEquator::eq(const TypeInfo& a, const TypeInfo& b) const { case TypeInfo::RefKind: return a.ref.nullable == b.ref.nullable && eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); } WASM_UNREACHABLE("unexpected kind"); } @@ -2717,10 +2590,6 @@ bool RecGroupEquator::eq(const Array& a, const Array& b) const { return eq(a.element, b.element); } -bool RecGroupEquator::eq(const Rtt& a, const Rtt& b) const { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - template<typename Self> void TypeGraphWalkerBase<Self>::walkRoot(Type* type) { assert(taskList.empty()); taskList.push_back(Task::scan(type)); @@ -2781,9 +2650,6 @@ template<typename Self> void TypeGraphWalkerBase<Self>::scanType(Type* type) { taskList.push_back(Task::scan(&info->ref.heapType)); break; } - case TypeInfo::RttKind: - taskList.push_back(Task::scan(&info->rtt.heapType)); - break; } } @@ -2921,10 +2787,6 @@ Type TypeBuilder::getTempRefType(HeapType type, Nullability nullable) { return markTemp(impl->typeStore.insert(TypeInfo(type, nullable))); } -Type TypeBuilder::getTempRttType(Rtt rtt) { - return markTemp(impl->typeStore.insert(rtt)); -} - void TypeBuilder::setSubType(size_t i, size_t j) { assert(i < size() && j < size() && "index out of bounds"); HeapTypeInfo* sub = impl->entries[i].info.get(); @@ -4031,12 +3893,6 @@ size_t hash<wasm::RecGroup>::operator()(const wasm::RecGroup& group) const { return wasm::hash(group.getID()); } -size_t hash<wasm::Rtt>::operator()(const wasm::Rtt& rtt) const { - auto digest = wasm::hash(rtt.depth); - wasm::rehash(digest, rtt.heapType); - return digest; -} - size_t hash<wasm::TypeInfo>::operator()(const wasm::TypeInfo& info) const { auto digest = wasm::hash(info.kind); switch (info.kind) { @@ -4047,9 +3903,6 @@ size_t hash<wasm::TypeInfo>::operator()(const wasm::TypeInfo& info) const { wasm::rehash(digest, info.ref.nullable); wasm::rehash(digest, info.ref.heapType); return digest; - case wasm::TypeInfo::RttKind: - wasm::rehash(digest, info.rtt); - return digest; } WASM_UNREACHABLE("unexpected kind"); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 65a910747..bc51d8b63 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -383,8 +383,6 @@ public: void visitRefTest(RefTest* curr); void visitRefCast(RefCast* curr); void visitBrOn(BrOn* curr); - void visitRttCanon(RttCanon* curr); - void visitRttSub(RttSub* curr); void visitStructNew(StructNew* curr); void visitStructGet(StructGet* curr); void visitStructSet(StructSet* curr); @@ -2338,23 +2336,12 @@ void FunctionValidator::visitRefTest(RefTest* curr) { shouldBeTrue( curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic ref.test must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.test must set intendedType field"); - shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); - } + "static ref.test must set intendedType field"); + shouldBeTrue( + !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); } void FunctionValidator::visitRefCast(RefCast* curr) { @@ -2364,23 +2351,12 @@ void FunctionValidator::visitRefCast(RefCast* curr) { shouldBeTrue( curr->ref->type.isRef(), curr, "ref.cast ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.cast rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic ref.cast must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.cast must set intendedType field"); - shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.cast must cast to a non-basic"); - } + "static ref.cast must set intendedType field"); + shouldBeTrue( + !curr->intendedType.isBasic(), curr, "ref.cast must cast to a non-basic"); } void FunctionValidator::visitBrOn(BrOn* curr) { @@ -2392,28 +2368,14 @@ void FunctionValidator::visitBrOn(BrOn* curr) { curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type"); } if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - if (curr->rtt) { - // Note that an unreachable rtt is not supported: the text and binary - // formats do not provide the type, so if it's unreachable we should not - // even create a br_on_cast in such a case, as we'd have no idea what it - // casts to. - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type"); - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic br_on_cast* must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static br_on_cast* must set intendedType field"); - shouldBeTrue(!curr->intendedType.isBasic(), - curr, - "br_on_cast* must cast to a non-basic"); - } + "static br_on_cast* must set intendedType field"); + shouldBeTrue(!curr->intendedType.isBasic(), + curr, + "br_on_cast* must cast to a non-basic"); } else { - shouldBeTrue(curr->rtt == nullptr, curr, "non-cast BrOn must not have rtt"); shouldBeEqual(curr->intendedType, HeapType(), curr, @@ -2422,38 +2384,6 @@ void FunctionValidator::visitBrOn(BrOn* curr) { noteBreak(curr->name, curr->getSentType(), curr); } -void FunctionValidator::visitRttCanon(RttCanon* curr) { - shouldBeTrue( - getModule()->features.hasGC(), curr, "rtt.canon requires gc to be enabled"); - shouldBeTrue(curr->type.isRtt(), curr, "rtt.canon must have RTT type"); - auto rtt = curr->type.getRtt(); - shouldBeEqual(rtt.depth, - Index(curr->type.getHeapType().getDepth()), - curr, - "rtt.canon must have the depth of its heap type"); -} - -void FunctionValidator::visitRttSub(RttSub* curr) { - shouldBeTrue( - getModule()->features.hasGC(), curr, "rtt.sub requires gc to be enabled"); - shouldBeTrue(curr->type.isRtt(), curr, "rtt.sub must have RTT type"); - if (curr->parent->type != Type::unreachable) { - shouldBeTrue( - curr->parent->type.isRtt(), curr, "rtt.sub parent must have RTT type"); - auto parentRtt = curr->parent->type.getRtt(); - auto rtt = curr->type.getRtt(); - if (rtt.hasDepth() && parentRtt.hasDepth()) { - shouldBeEqual(rtt.depth, - parentRtt.depth + 1, - curr, - "rtt.canon has a depth of 1 over the parent"); - } - shouldBeTrue(HeapType::isSubType(rtt.heapType, parentRtt.heapType), - curr, - "rtt.sub parent must be a supertype"); - } -} - void FunctionValidator::visitStructNew(StructNew* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, @@ -2461,19 +2391,7 @@ void FunctionValidator::visitStructNew(StructNew* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "struct.new heap type must match rtt"); - } if (!shouldBeTrue( heapType.isStruct(), curr, "struct.new heap type must be struct")) { return; @@ -2565,19 +2483,7 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.new heap type must match rtt"); - } if (!shouldBeTrue( heapType.isArray(), curr, "array.new heap type must be array")) { return; @@ -2607,19 +2513,7 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.init heap type must match rtt"); - } if (!shouldBeTrue( heapType.isArray(), curr, "array.init heap type must be array")) { return; @@ -2716,9 +2610,7 @@ void FunctionValidator::visitFunction(Function* curr) { } for (const auto& var : curr->vars) { features |= var.getFeatures(); - bool valid = getModule()->features.hasGCNNLocals() - ? var.isDefaultableOrNonNullable() - : var.isDefaultable(); + bool valid = getModule()->features.hasGCNNLocals() || var.isDefaultable(); shouldBeTrue(valid, var, "vars must be defaultable"); } shouldBeTrue(features <= getModule()->features, @@ -3167,10 +3059,9 @@ static void validateTables(Module& module, ValidationInfo& info) { for (auto& segment : module.elementSegments) { // Since element segment items need to be constant expressions, that leaves - // us with ref.null, ref.func and global.get. The GC proposal adds rtt.canon - // and rtt.sub to the list, but Binaryen doesn't consider RTTs as reference- - // types yet. As a result, the only possible type for element segments will - // be function references. + // us with ref.null, ref.func and global.get. As a result, the only possible + // type for element segments will be function references. + // TODO: This is not true! Allow GC data here (#4846). info.shouldBeTrue(segment->type.isFunction(), "elem", "element segment type must be of function type."); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 1a6acf5bd..34b1e82b7 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -931,36 +931,25 @@ void CallRef::finalize(Type type_) { } void RefTest::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; } else { type = Type::i32; } } -HeapType RefTest::getIntendedType() { - return rtt ? rtt->type.getHeapType() : intendedType; -} - void RefCast::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; } else { // The output of ref.cast may be null if the input is null (in that case the // null is passed through). - type = Type(getIntendedType(), ref->type.getNullability()); + type = Type(intendedType, ref->type.getNullability()); } } -HeapType RefCast::getIntendedType() { - return rtt ? rtt->type.getHeapType() : intendedType; -} - void BrOn::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; return; } @@ -984,7 +973,7 @@ void BrOn::finalize() { case BrOnCastFail: // If we do not branch, the cast worked, and we have something of the cast // type. - type = Type(getIntendedType(), NonNullable); + type = Type(intendedType, NonNullable); break; case BrOnNonFunc: type = Type(HeapType::func, NonNullable); @@ -1000,11 +989,6 @@ void BrOn::finalize() { } } -HeapType BrOn::getIntendedType() { - assert(op == BrOnCast || op == BrOnCastFail); - return rtt ? rtt->type.getHeapType() : intendedType; -} - Type BrOn::getSentType() { switch (op) { case BrOnNull: @@ -1022,7 +1006,7 @@ Type BrOn::getSentType() { if (ref->type == Type::unreachable) { return Type::unreachable; } - return Type(getIntendedType(), NonNullable); + return Type(intendedType, NonNullable); case BrOnFunc: return Type(HeapType::func, NonNullable); case BrOnData: @@ -1039,31 +1023,10 @@ Type BrOn::getSentType() { } } -void RttCanon::finalize() { - // Nothing to do - the type must have been set already during construction. -} - -void RttSub::finalize() { - if (parent->type == Type::unreachable) { - type = Type::unreachable; - } - // Else nothing to do - the type must have been set already during - // construction. -} - void StructNew::finalize() { - if (rtt && rtt->type == Type::unreachable) { - type = Type::unreachable; - return; - } if (handleUnreachableOperands(this)) { return; } - // A dynamic StructNew infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void StructGet::finalize() { @@ -1083,35 +1046,20 @@ void StructSet::finalize() { } void ArrayNew::finalize() { - if ((rtt && rtt->type == Type::unreachable) || - size->type == Type::unreachable || + if (size->type == Type::unreachable || (init && init->type == Type::unreachable)) { type = Type::unreachable; return; } - // A dynamic ArrayNew infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void ArrayInit::finalize() { - if (rtt && rtt->type == Type::unreachable) { - type = Type::unreachable; - return; - } for (auto* value : values) { if (value->type == Type::unreachable) { type = Type::unreachable; return; } } - // A dynamic ArrayInit infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void ArrayGet::finalize() { diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 8b86017ff..89eab3297 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -967,14 +967,6 @@ Result<typename Ctx::InstrT> makeBrOn(Ctx&, ParseInput&, BrOnOp op); template<typename Ctx> Result<typename Ctx::InstrT> makeBrOnStatic(Ctx&, ParseInput&, BrOnOp op); template<typename Ctx> -Result<typename Ctx::InstrT> makeRttCanon(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttSub(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttFreshSub(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeStructNew(Ctx&, ParseInput&, bool default_); -template<typename Ctx> Result<typename Ctx::InstrT> makeStructNewStatic(Ctx&, ParseInput&, bool default_); template<typename Ctx> @@ -983,13 +975,9 @@ makeStructGet(Ctx&, ParseInput&, bool signed_ = false); template<typename Ctx> Result<typename Ctx::InstrT> makeStructSet(Ctx&, ParseInput&); template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayNew(Ctx&, ParseInput&, bool default_); -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayNewStatic(Ctx&, ParseInput&, bool default_); template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayInit(Ctx&, ParseInput&); -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx&, ParseInput&); template<typename Ctx> Result<typename Ctx::InstrT> @@ -1779,27 +1767,6 @@ makeBrOnStatic(Ctx& ctx, ParseInput& in, BrOnOp op) { } template<typename Ctx> -Result<typename Ctx::InstrT> makeRttCanon(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttFreshSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> -makeStructNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> Result<typename Ctx::InstrT> makeStructNewStatic(Ctx& ctx, ParseInput& in, bool default_) { return in.err("unimplemented instruction"); @@ -1818,22 +1785,11 @@ Result<typename Ctx::InstrT> makeStructSet(Ctx& ctx, ParseInput& in) { template<typename Ctx> Result<typename Ctx::InstrT> -makeArrayNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayNewStatic(Ctx& ctx, ParseInput& in, bool default_) { return in.err("unimplemented instruction"); } template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayInit(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx& ctx, ParseInput& in) { return in.err("unimplemented instruction"); } diff --git a/src/wasm2js.h b/src/wasm2js.h index 034f9a215..442fd0d6e 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2259,14 +2259,6 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitRttCanon(RttCanon* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitRttSub(RttSub* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitStructNew(StructNew* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index c613ae1a5..59f398da9 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -163,8 +163,6 @@ function test_ids() { console.log("RefTestId: " + binaryen.RefTestId); console.log("RefCastId: " + binaryen.RefCastId); console.log("BrOnId: " + binaryen.BrOnId); - console.log("RttCanonId: " + binaryen.RttCanonId); - console.log("RttSubId: " + binaryen.RttSubId); console.log("StructNewId: " + binaryen.StructNewId); console.log("StructGetId: " + binaryen.StructGetId); console.log("StructSetId: " + binaryen.StructSetId); diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index a026d4be1..2a5a05fe8 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -93,16 +93,14 @@ CallRefId: 56 RefTestId: 57 RefCastId: 58 BrOnId: 59 -RttCanonId: 60 -RttSubId: 61 -StructNewId: 62 -StructGetId: 63 -StructSetId: 64 -ArrayNewId: 65 -ArrayInitId: 66 -ArrayGetId: 67 -ArraySetId: 68 -ArrayLenId: 69 +StructNewId: 60 +StructGetId: 61 +StructSetId: 62 +ArrayNewId: 63 +ArrayInitId: 64 +ArrayGetId: 65 +ArraySetId: 66 +ArrayLenId: 67 getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) diff --git a/test/example/type-builder-nominal.cpp b/test/example/type-builder-nominal.cpp index cbda43f1f..13224f55e 100644 --- a/test/example/type-builder-nominal.cpp +++ b/test/example/type-builder-nominal.cpp @@ -12,7 +12,7 @@ void test_builder() { std::cout << ";; Test TypeBuilder\n"; // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) - // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) + // (type $struct (struct (field (ref null $array)))) // (type $array (array (mut anyref))) TypeBuilder builder; @@ -24,11 +24,10 @@ void test_builder() { Type refStruct = builder.getTempRefType(builder[1], NonNullable); Type refArray = builder.getTempRefType(builder[2], NonNullable); Type refNullArray = builder.getTempRefType(builder[2], Nullable); - Type rttArray = builder.getTempRttType(Rtt(0, builder[2])); Type refNullAny(HeapType::any, Nullable); Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); - Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); + Struct struct_({Field(refNullArray, Immutable)}); Array array(Field(refNullAny, Mutable)); { @@ -41,7 +40,6 @@ void test_builder() { std::cout << "(ref $struct) => " << print(refStruct) << "\n"; std::cout << "(ref $array) => " << print(refArray) << "\n"; std::cout << "(ref null $array) => " << print(refNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n"; } builder[0] = sig; @@ -58,7 +56,6 @@ void test_builder() { std::cout << "(ref $struct) => " << print(refStruct) << "\n"; std::cout << "(ref $array) => " << print(refArray) << "\n"; std::cout << "(ref null $array) => " << print(refNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n"; } std::vector<HeapType> built = *builder.build(); @@ -67,7 +64,6 @@ void test_builder() { Type newRefStruct = Type(built[1], NonNullable); Type newRefArray = Type(built[2], NonNullable); Type newRefNullArray = Type(built[2], Nullable); - Type newRttArray = Type(Rtt(0, built[2])); { IndexedTypeNameGenerator print(built); @@ -79,7 +75,6 @@ void test_builder() { std::cout << "(ref $struct) => " << print(newRefStruct) << "\n"; std::cout << "(ref $array) => " << print(newRefArray) << "\n"; std::cout << "(ref null $array) => " << print(newRefNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(newRttArray) << "\n\n"; } } diff --git a/test/example/type-builder-nominal.txt b/test/example/type-builder-nominal.txt index 745f63df2..8d146cc1f 100644 --- a/test/example/type-builder-nominal.txt +++ b/test/example/type-builder-nominal.txt @@ -7,28 +7,22 @@ $array => (; temp ;) (func_subtype func) (ref $struct) => (; temp ;) (ref $1) (ref $array) => (; temp ;) (ref $2) (ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - After setting heap types: $sig => (; temp ;) (func_subtype (param (; temp ;) (ref $1)) (result (; temp ;) (ref $2) i32) func) -$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2) (mut (; temp ;) (rtt 0 $2))) data) +$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2)) data) $array => (; temp ;) (array_subtype (mut anyref) data) (ref $sig) => (; temp ;) (ref $0) (ref $struct) => (; temp ;) (ref $1) (ref $array) => (; temp ;) (ref $2) (ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - After building types: $sig => (func_subtype (param (ref $1)) (result (ref $2) i32) func) -$struct => (struct_subtype (field (ref null $2) (mut (rtt 0 $2))) data) +$struct => (struct_subtype (field (ref null $2)) data) $array => (array_subtype (mut anyref) data) (ref $sig) => (ref $0) (ref $struct) => (ref $1) (ref $array) => (ref $2) (ref null $array) => (ref null $2) -(rtt 0 $array) => (rtt 0 $2) - ;; Test canonicalization ;; Test basic ;; Test canonical signatures @@ -64,28 +58,22 @@ $array => (; temp ;) (func_subtype func) (ref $struct) => (; temp ;) (ref $1) (ref $array) => (; temp ;) (ref $2) (ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - After setting heap types: $sig => (; temp ;) (func_subtype (param (; temp ;) (ref $1)) (result (; temp ;) (ref $2) i32) func) -$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2) (mut (; temp ;) (rtt 0 $2))) data) +$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2)) data) $array => (; temp ;) (array_subtype (mut anyref) data) (ref $sig) => (; temp ;) (ref $0) (ref $struct) => (; temp ;) (ref $1) (ref $array) => (; temp ;) (ref $2) (ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - After building types: $sig => (func_subtype (param (ref $1)) (result (ref $2) i32) func) -$struct => (struct_subtype (field (ref null $2) (mut (rtt 0 $2))) data) +$struct => (struct_subtype (field (ref null $2)) data) $array => (array_subtype (mut anyref) data) (ref $sig) => (ref $0) (ref $struct) => (ref $1) (ref $array) => (ref $2) (ref null $array) => (ref null $2) -(rtt 0 $array) => (rtt 0 $2) - ;; Test canonicalization ;; Test basic ;; Test canonical signatures diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp index 219282ea8..41c556878 100644 --- a/test/example/type-builder.cpp +++ b/test/example/type-builder.cpp @@ -396,40 +396,6 @@ void test_lub() { assert(LUB(a, b) == lub); } - - { - // Incompatible Rtts - Type a{Rtt(HeapType::eq)}; - Type b{Rtt(HeapType::func)}; - assert(LUB(a, b) == Type::none); - } - - { - // Rtts with matching depth - Type a(Rtt(42, HeapType::any)); - assert(LUB(a, a) == a); - } - - { - // Rtts with mismatched depth - Type a(Rtt(42, HeapType::any)); - Type b(Rtt(50, HeapType::any)); - Type lub{Rtt(HeapType::any)}; - assert(LUB(a, b) == lub); - } - - { - // Rtts with and without depth - Type a(Rtt(42, HeapType::any)); - Type b{Rtt(HeapType::any)}; - assert(LUB(a, b) == b); - } - - { - // Rtts without depth - Type a{Rtt(HeapType::any)}; - assert(LUB(a, a) == a); - } } int main() { diff --git a/test/example/typeinfo.cpp b/test/example/typeinfo.cpp index 55e7b9082..ff20753b1 100644 --- a/test/example/typeinfo.cpp +++ b/test/example/typeinfo.cpp @@ -91,33 +91,6 @@ void test_compound() { Tuple otherTuple({Type::f64, Type::i64}); assert(Type(tuple).getID() != Type(otherTuple).getID()); } - { - Rtt rtt(0, HeapType::func); - assert(Type(rtt).getID() == Type(rtt).getID()); - - Rtt sameRtt(0, HeapType::func); - assert(rtt == sameRtt); - assert(Type(rtt).getID() == Type(sameRtt).getID()); - - Rtt otherDepthRtt(1, HeapType::func); - assert(rtt != otherDepthRtt); - assert(Type(rtt).getID() != Type(otherDepthRtt).getID()); - - Rtt otherHeapTypeRtt(0, HeapType::any); - assert(rtt != otherHeapTypeRtt); - assert(Type(rtt).getID() != Type(otherHeapTypeRtt).getID()); - - Rtt structRtt(0, Struct{}); - assert(Type(structRtt).getID() == Type(structRtt).getID()); - - Rtt sameStructRtt(0, Struct{}); - assert(structRtt == sameStructRtt); - assert(Type(structRtt).getID() == Type(sameStructRtt).getID()); - - Rtt otherStructRtt(0, Struct({{Type::i32, Immutable}})); - assert(structRtt != otherStructRtt); - assert(Type(structRtt).getID() != Type(otherStructRtt).getID()); - } } void test_printing() { @@ -190,26 +163,6 @@ void test_printing() { std::cout << Type(tuple) << "\n"; } { - std::cout << "\n;; Rtt\n"; - std::cout << Rtt(0, HeapType::func) << "\n"; - std::cout << Type(Rtt(0, HeapType::func)) << "\n"; - std::cout << Rtt(2, HeapType::any) << "\n"; - std::cout << Type(Rtt(2, HeapType::any)) << "\n"; - std::cout << Rtt(3, HeapType::eq) << "\n"; - std::cout << Type(Rtt(3, HeapType::eq)) << "\n"; - std::cout << Rtt(4, HeapType::i31) << "\n"; - std::cout << Type(Rtt(4, HeapType::i31)) << "\n"; - Rtt signatureRtt(6, Signature(Type::none, Type::none)); - std::cout << signatureRtt << "\n"; - std::cout << Type(signatureRtt) << "\n"; - Rtt structRtt(7, Struct{}); - std::cout << structRtt << "\n"; - std::cout << Type(structRtt) << "\n"; - Rtt arrayRtt(8, Array({Type::i32, Immutable})); - std::cout << arrayRtt << "\n"; - std::cout << Type(arrayRtt) << "\n"; - } - { std::cout << "\n;; Signature of references (param/result)\n"; Signature signature(Type(Struct{}, Nullable), Type(Array({Type::i32, Mutable}), NonNullable)); diff --git a/test/example/typeinfo.txt b/test/example/typeinfo.txt index 838fd34a3..2fbd8ec52 100644 --- a/test/example/typeinfo.txt +++ b/test/example/typeinfo.txt @@ -45,22 +45,6 @@ none (i32 f64) (i32 f64) -;; Rtt -(rtt 0 func) -(rtt 0 func) -(rtt 2 any) -(rtt 2 any) -(rtt 3 eq) -(rtt 3 eq) -(rtt 4 i31) -(rtt 4 i31) -(rtt 6 $func.0) -(rtt 6 $func.0) -(rtt 7 $struct.0) -(rtt 7 $struct.0) -(rtt 8 $array.0) -(rtt 8 $array.0) - ;; Signature of references (param/result) (func (param (ref null $struct.0)) (result (ref $array.0))) diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index d06236130..563ea0933 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -120,7 +120,7 @@ TEST_F(TypeTest, IndexedTypePrinter) { TEST_F(EquirecursiveTest, Basics) { // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) - // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) + // (type $struct (struct (field (ref null $array)))) // (type $array (array (mut anyref))) TypeBuilder builder(3); ASSERT_EQ(builder.size(), size_t{3}); @@ -129,11 +129,10 @@ TEST_F(EquirecursiveTest, Basics) { Type refStruct = builder.getTempRefType(builder[1], NonNullable); Type refArray = builder.getTempRefType(builder[2], NonNullable); Type refNullArray = builder.getTempRefType(builder[2], Nullable); - Type rttArray = builder.getTempRttType(Rtt(0, builder[2])); Type refNullAny(HeapType::any, Nullable); Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); - Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); + Struct struct_({Field(refNullArray, Immutable)}); Array array(Field(refNullAny, Mutable)); builder[0] = sig; @@ -155,13 +154,10 @@ TEST_F(EquirecursiveTest, Basics) { Type newRefStruct = Type(built[1], NonNullable); Type newRefArray = Type(built[2], NonNullable); Type newRefNullArray = Type(built[2], Nullable); - Type newRttArray = Type(Rtt(0, built[2])); EXPECT_EQ(built[0].getSignature(), Signature(newRefStruct, {newRefArray, Type::i32})); - EXPECT_EQ( - built[1].getStruct(), - Struct({Field(newRefNullArray, Immutable), Field(newRttArray, Mutable)})); + EXPECT_EQ(built[1].getStruct(), Struct({Field(newRefNullArray, Immutable)})); EXPECT_EQ(built[2].getArray(), Array(Field(refNullAny, Mutable))); // The built types should be different from the temporary types. @@ -169,7 +165,6 @@ TEST_F(EquirecursiveTest, Basics) { EXPECT_NE(newRefStruct, refStruct); EXPECT_NE(newRefArray, refArray); EXPECT_NE(newRefNullArray, refNullArray); - EXPECT_NE(newRttArray, rttArray); } static void testDirectSelfSupertype() { diff --git a/test/heap-types.wast b/test/heap-types.wast index 3c0a5a0ef..d34eaf5eb 100644 --- a/test/heap-types.wast +++ b/test/heap-types.wast @@ -29,22 +29,15 @@ (type $bytes (array (mut i8))) (type $words (array (mut i32))) - ;; RTT (type $parent (struct)) (type $child (struct i32)) (type $grandchild (struct i32 i64)) - (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) - (global $rttchild (rtt 1 $child) (rtt.sub $child (global.get $rttparent))) - (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild (global.get $rttchild))) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild (global.get $rttchild))) (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_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) @@ -120,16 +113,13 @@ ) ) (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 1) (f32.const 2.345) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) @@ -140,16 +130,14 @@ (local $tb (ref null $bytes)) (local $tw (ref null $words)) (drop - (array.new_with_rtt $vector + (array.new $vector (f64.const 3.14159) (i32.const 3) - (rtt.canon $vector) ) ) (drop - (array.new_default_with_rtt $matrix + (array.new_default $matrix (i32.const 10) - (rtt.canon $matrix) ) ) (drop @@ -196,42 +184,6 @@ ) (unreachable) ) - ;; RTT types as parameters - (func $rtt-param-with-depth (param $rtt (rtt 1 $parent))) - (func $rtt-param-without-depth (param $rtt (rtt $parent))) - (func $rtt-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test (ref.null $struct.A) (rtt.canon $struct.B)) - ) - (drop - (ref.cast (ref.null $struct.A) (rtt.canon $struct.B)) - ) - (drop - (block $out (result (ref $struct.B)) - ;; set the value to a local with type $struct.A, showing that the value - ;; flowing out has the right type - (local.set $temp.A - (br_on_cast $out (ref.null $struct.A) (rtt.canon $struct.B)) - ) - ;; an untaken br_on_cast, with unreachable rtt - so we cannot use the - ;; RTT in binaryen IR to find the cast type. - (br_on_cast $out (ref.null $struct.A) (unreachable)) - (unreachable) - ) - ) - (drop - (block $out2 (result (ref null $struct.A)) - ;; set the value to a local with type $struct.A, showing that the value - ;; flowing out has the right type - (local.set $temp.B - (br_on_cast_fail $out2 (ref.null $struct.A) (rtt.canon $struct.B)) - ) - (ref.null $struct.A) - ) - ) - ) (func $ref.is_X (param $x anyref) (if (ref.is_func (local.get $x)) (unreachable)) (if (ref.is_data (local.get $x)) (unreachable)) @@ -363,13 +315,6 @@ ) ) ) - (func $unreachables-7 - (drop - (struct.new_default_with_rtt $struct.A - (unreachable) - ) - ) - ) (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) (array.copy $vector $vector (local.get $x) @@ -380,20 +325,18 @@ ) ) (func $array-init (result (ref $vector)) - (array.init $vector + (array.init_static $vector (f64.const 1) (f64.const 2) (f64.const 4) (f64.const 8) - (rtt.canon $vector) ) ) (func $array-init-packed (result (ref $bytes)) - (array.init $bytes + (array.init_static $bytes (i32.const 4) (i32.const 2) (i32.const 1) - (rtt.canon $bytes) ) ) (func $static-operations @@ -422,35 +365,4 @@ ) ) ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.345) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast index 937b4e6b5..705e545ef 100644 --- a/test/heap-types.wast.from-wast +++ b/test/heap-types.wast.from-wast @@ -1,38 +1,23 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) - (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) (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 $grandchild (struct (field i32) (field i64))) - (type $matrix (array (mut (ref null $vector)))) (type $struct.C (struct (field $named-mut (mut f32)))) - (type $parent (struct )) - (type $child (struct (field i32))) + (type $matrix (array (mut (ref null $vector)))) + (type $grandchild (struct (field i32) (field i64))) (type $bytes (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type $nested-child-struct (struct (field (mut (ref $child))))) + (type $child (struct (field i32))) (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) (type $words (array (mut i32))) (type $nested-child-array (array (mut (ref $child)))) - (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) - (type $rtt_$parent_=>_none (func (param (rtt $parent)))) (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 $rttparent (rtt 0 $parent) (rtt.canon $parent)) - (global $rttchild (rtt 1 $child) (rtt.sub $child - (global.get $rttparent) - )) - (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild - (global.get $rttchild) - )) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild - (global.get $rttchild) - )) - (global $struct.new-in-global (ref $struct.A) (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - )) + (global $struct.new-in-global (ref $struct.A) (struct.new_default $struct.A)) (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) (local $tA (ref null $struct.A)) (local $tB (ref null $struct.B)) @@ -120,16 +105,13 @@ ) ) (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) @@ -140,16 +122,14 @@ (local $tb (ref null $bytes)) (local $tw (ref null $words)) (drop - (array.new_with_rtt $vector + (array.new $vector (f64.const 3.14159) (i32.const 3) - (rtt.canon $vector) ) ) (drop - (array.new_default_with_rtt $matrix + (array.new_default $matrix (i32.const 10) - (rtt.canon $matrix) ) ) (drop @@ -195,56 +175,6 @@ ) (unreachable) ) - (func $rtt-param-with-depth (param $rtt (rtt 1 $parent)) - (nop) - ) - (func $rtt-param-without-depth (param $rtt (rtt $parent)) - (nop) - ) - (func $rtt-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (ref.cast - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (block $out (result (ref $struct.B)) - (local.set $temp.A - (br_on_cast $out - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (block - (drop - (ref.null $struct.A) - ) - (unreachable) - ) - (unreachable) - ) - ) - (drop - (block $out2 (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_fail $out2 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (ref.null $struct.A) - ) - ) - ) (func $ref.is_X (param $x anyref) (if (ref.is_func @@ -454,15 +384,6 @@ ) ) ) - (func $unreachables-7 - (drop - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - ) - ) - ) (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) (array.copy $vector $vector (local.get $x) @@ -473,20 +394,18 @@ ) ) (func $array-init (result (ref $vector)) - (array.init $vector + (array.init_static $vector (f64.const 1) (f64.const 2) (f64.const 4) (f64.const 8) - (rtt.canon $vector) ) ) (func $array-init-packed (result (ref $bytes)) - (array.init $bytes + (array.init_static $bytes (i32.const 4) (i32.const 2) (i32.const 1) - (rtt.canon $bytes) ) ) (func $static-operations @@ -523,35 +442,4 @@ ) ) ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary index 2f1cac1c5..6c847ff69 100644 --- a/test/heap-types.wast.fromBinary +++ b/test/heap-types.wast.fromBinary @@ -1,38 +1,23 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) - (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) (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 $grandchild (struct (field i32) (field i64))) (type $matrix (array (mut (ref null $vector)))) - (type $parent (struct )) - (type $child (struct (field i32))) (type $struct.C (struct (field $named-mut (mut f32)))) + (type $grandchild (struct (field i32) (field i64))) (type $bytes (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type $nested-child-struct (struct (field (mut (ref $child))))) + (type $child (struct (field i32))) (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) (type $words (array (mut i32))) (type $nested-child-array (array (mut (ref $child)))) - (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) - (type $rtt_$parent_=>_none (func (param (rtt $parent)))) (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 $rttparent (rtt 0 $parent) (rtt.canon $parent)) - (global $rttchild (rtt 1 $child) (rtt.sub $child - (global.get $rttparent) - )) - (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild - (global.get $rttchild) - )) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild - (global.get $rttchild) - )) - (global $struct.new-in-global (ref $struct.A) (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - )) + (global $struct.new-in-global (ref $struct.A) (struct.new_default $struct.A)) (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) (local $tA (ref null $struct.A)) (local $tB (ref null $struct.B)) @@ -120,16 +105,13 @@ ) ) (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) @@ -140,16 +122,14 @@ (local $tb (ref null $bytes)) (local $tw (ref null $words)) (drop - (array.new_with_rtt $vector + (array.new $vector (f64.const 3.14159) (i32.const 3) - (rtt.canon $vector) ) ) (drop - (array.new_default_with_rtt $matrix + (array.new_default $matrix (i32.const 10) - (rtt.canon $matrix) ) ) (drop @@ -195,55 +175,6 @@ ) (unreachable) ) - (func $rtt-param-with-depth (param $rtt (rtt 1 $parent)) - (nop) - ) - (func $rtt-param-without-depth (param $rtt (rtt $parent)) - (nop) - ) - (func $rtt-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (ref.cast - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (block $label$1 (result (ref $struct.B)) - (local.set $temp.A - (br_on_cast $label$1 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (block $label$2 - (drop - (ref.null $struct.A) - ) - (unreachable) - ) - ) - ) - (drop - (block $label$3 (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_fail $label$3 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (ref.null $struct.A) - ) - ) - ) (func $ref.is_X (param $x anyref) (if (ref.is_func @@ -413,9 +344,6 @@ (func $unreachables-array-6 (unreachable) ) - (func $unreachables-7 - (unreachable) - ) (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) (array.copy $vector $vector (local.get $x) @@ -426,20 +354,18 @@ ) ) (func $array-init (result (ref $vector)) - (array.init $vector + (array.init_static $vector (f64.const 1) (f64.const 2) (f64.const 4) (f64.const 8) - (rtt.canon $vector) ) ) (func $array-init-packed (result (ref $bytes)) - (array.init $bytes + (array.init_static $bytes (i32.const 4) (i32.const 2) (i32.const 1) - (rtt.canon $bytes) ) ) (func $static-operations @@ -476,36 +402,5 @@ ) ) ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo index 6e5e5e06d..ba10f28fd 100644 --- a/test/heap-types.wast.fromBinary.noDebugInfo +++ b/test/heap-types.wast.fromBinary.noDebugInfo @@ -1,38 +1,23 @@ (module (type ${i32_f32_f64} (struct (field i32) (field f32) (field 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 $[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 ${i32_i64} (struct (field i32) (field i64))) (type $[mut:ref?|[mut:f64]|] (array (mut (ref null $[mut:f64])))) - (type ${} (struct )) - (type ${i32} (struct (field i32))) (type ${mut:f32} (struct (field (mut f32)))) + (type ${i32_i64} (struct (field i32) (field i64))) (type $[mut:i8] (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type ${mut:ref|{i32}|} (struct (field (mut (ref ${i32}))))) + (type ${i32} (struct (field i32))) (type $ref|{i32_f32_f64}|_=>_ref|{i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}| (func (param (ref ${i32_f32_f64})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})))) (type $ref|[mut:f64]|_=>_ref|[mut:ref?|[mut:f64]|]| (func (param (ref $[mut:f64])) (result (ref $[mut:ref?|[mut:f64]|])))) (type $[mut:i32] (array (mut i32))) (type $[mut:ref|{i32}|] (array (mut (ref ${i32})))) - (type $rtt_1_{}_=>_none (func (param (rtt 1 ${})))) - (type $rtt_{}_=>_none (func (param (rtt ${})))) (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 (rtt 0 ${}) (rtt.canon ${})) - (global $global$1 (rtt 1 ${i32}) (rtt.sub ${i32} - (global.get $global$0) - )) - (global $global$2 (rtt 2 ${i32_i64}) (rtt.sub ${i32_i64} - (global.get $global$1) - )) - (global $global$3 (rtt 2 ${i32_i64}) (rtt.fresh_sub ${i32_i64} - (global.get $global$1) - )) - (global $global$4 (ref ${i32_f32_f64}) (struct.new_default_with_rtt ${i32_f32_f64} - (rtt.canon ${i32_f32_f64}) - )) + (global $global$0 (ref ${i32_f32_f64}) (struct.new_default ${i32_f32_f64})) (func $0 (param $0 (ref ${i32_f32_f64})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) (local $1 (ref null ${i32_f32_f64})) (local $2 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) @@ -120,16 +105,13 @@ ) ) (drop - (struct.new_default_with_rtt ${i32_f32_f64} - (rtt.canon ${i32_f32_f64}) - ) + (struct.new_default ${i32_f32_f64}) ) (drop - (struct.new_with_rtt ${i32_f32_f64} + (struct.new ${i32_f32_f64} (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon ${i32_f32_f64}) ) ) (unreachable) @@ -140,16 +122,14 @@ (local $3 (ref null $[mut:i8])) (local $4 (ref null $[mut:i32])) (drop - (array.new_with_rtt $[mut:f64] + (array.new $[mut:f64] (f64.const 3.14159) (i32.const 3) - (rtt.canon $[mut:f64]) ) ) (drop - (array.new_default_with_rtt $[mut:ref?|[mut:f64]|] + (array.new_default $[mut:ref?|[mut:f64]|] (i32.const 10) - (rtt.canon $[mut:ref?|[mut:f64]|]) ) ) (drop @@ -195,56 +175,7 @@ ) (unreachable) ) - (func $2 (param $0 (rtt 1 ${})) - (nop) - ) - (func $3 (param $0 (rtt ${})) - (nop) - ) - (func $4 - (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 - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (drop - (ref.cast - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (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 - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (block $label$2 - (drop - (ref.null ${i32_f32_f64}) - ) - (unreachable) - ) - ) - ) - (drop - (block $label$3 (result (ref null ${i32_f32_f64})) - (local.set $1 - (br_on_cast_fail $label$3 - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (ref.null ${i32_f32_f64}) - ) - ) - ) - (func $5 (param $0 anyref) + (func $2 (param $0 anyref) (if (ref.is_func (local.get $0) @@ -264,7 +195,7 @@ (unreachable) ) ) - (func $6 (param $0 anyref) + (func $3 (param $0 anyref) (drop (ref.as_non_null (local.get $0) @@ -286,7 +217,7 @@ ) ) ) - (func $7 (param $0 anyref) + (func $4 (param $0 anyref) (local $1 anyref) (local $2 anyref) (local $3 funcref) @@ -368,40 +299,40 @@ ) ) ) - (func $8 + (func $5 (unreachable) ) - (func $9 + (func $6 (drop (ref.null ${mut:f32}) ) (unreachable) ) - (func $10 + (func $7 (unreachable) ) - (func $11 + (func $8 (unreachable) ) - (func $12 + (func $9 (unreachable) ) - (func $13 + (func $10 (drop (ref.null $[mut:f64]) ) (unreachable) ) - (func $14 + (func $11 (unreachable) ) - (func $15 + (func $12 (drop (ref.null $[mut:f64]) ) (unreachable) ) - (func $16 + (func $13 (drop (ref.null $[mut:f64]) ) @@ -410,13 +341,10 @@ ) (unreachable) ) - (func $17 - (unreachable) - ) - (func $18 + (func $14 (unreachable) ) - (func $19 (param $0 (ref $[mut:f64])) (param $1 (ref null $[mut:f64])) + (func $15 (param $0 (ref $[mut:f64])) (param $1 (ref null $[mut:f64])) (array.copy $[mut:f64] $[mut:f64] (local.get $0) (i32.const 11) @@ -425,24 +353,22 @@ (i32.const 1337) ) ) - (func $20 (result (ref $[mut:f64])) - (array.init $[mut:f64] + (func $16 (result (ref $[mut:f64])) + (array.init_static $[mut:f64] (f64.const 1) (f64.const 2) (f64.const 4) (f64.const 8) - (rtt.canon $[mut:f64]) ) ) - (func $21 (result (ref $[mut:i8])) - (array.init $[mut:i8] + (func $17 (result (ref $[mut:i8])) + (array.init_static $[mut:i8] (i32.const 4) (i32.const 2) (i32.const 1) - (rtt.canon $[mut:i8]) ) ) - (func $22 + (func $18 (local $0 (ref null ${i32_f32_f64})) (local $1 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) (drop @@ -476,36 +402,5 @@ ) ) ) - (func $23 - (drop - (struct.new_default ${i32_f32_f64}) - ) - (drop - (struct.new ${i32_f32_f64} - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (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.init_static $[mut:f64] - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff --git a/test/lit/exec/rtts.wast b/test/lit/exec/rtts.wast deleted file mode 100644 index 7c090f180..000000000 --- a/test/lit/exec/rtts.wast +++ /dev/null @@ -1,153 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; Check that allocation and casting instructions with and without RTTs can be -;; mixed correctly. - -;; RUN: wasm-opt %s -all --fuzz-exec-before -q --structural -o /dev/null 2>&1 \ -;; RUN: | filecheck %s --check-prefix=EQREC - -;; RUN: wasm-opt %s -all --fuzz-exec-before -q --nominal -o /dev/null 2>&1 \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -(module - (type $struct (struct_subtype i32 data)) - (type $sub-struct (struct_subtype i32 i32 $struct)) - - (import "fuzzing-support" "log-i32" (func $log (param i32))) - - (global $sub-rtt (rtt 1 $sub-struct) - (rtt.sub $sub-struct - (rtt.canon $struct) - ) - ) - - (func $make-sub-struct-canon (result (ref $struct)) - (struct.new_default_with_rtt $sub-struct - (rtt.canon $sub-struct) - ) - ) - - (func $make-sub-struct-sub (result (ref $struct)) - (struct.new_default_with_rtt $sub-struct - (global.get $sub-rtt) - ) - ) - - (func $make-sub-struct-static (result (ref $struct)) - (struct.new_default $sub-struct) - ) - - ;; EQREC: [fuzz-exec] calling canon-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling canon-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-canon" - (call $log - (ref.test - (call $make-sub-struct-canon) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling canon-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling canon-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-sub" - (call $log - (ref.test - (call $make-sub-struct-canon) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling canon-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling canon-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-canon) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling sub-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-canon" - (call $log - (ref.test - (call $make-sub-struct-sub) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling sub-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-sub" - (call $log - (ref.test - (call $make-sub-struct-sub) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling sub-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-sub) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling static-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-canon" - (call $log - (ref.test - (call $make-sub-struct-static) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling static-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-sub" - (call $log - (ref.test - (call $make-sub-struct-static) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling static-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-static) - ) - ) - ) -) diff --git a/test/lit/forward-declared-types.wast b/test/lit/forward-declared-types.wast deleted file mode 100644 index c20cc3a1e..000000000 --- a/test/lit/forward-declared-types.wast +++ /dev/null @@ -1,26 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; Test that types can be used before they are defined - -;; RUN: wasm-opt %s -all -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $func (func)) - - ;; CHECK: (type $struct (struct (field (ref $array)) (field (ref null $func)))) - ;; NOMNL: (type $func (func_subtype func)) - - ;; NOMNL: (type $struct (struct_subtype (field (ref $array)) (field (ref null $func)) data)) - (type $struct (struct - (field (ref $array)) - (field (ref null $func)) - )) - ;; CHECK: (type $array (array (rtt 2 $func))) - ;; NOMNL: (type $array (array_subtype (rtt 2 $func) data)) - (type $array (array (field (rtt 2 $func)))) - (type $func (func)) - - (func (result (ref null $struct)) - (unreachable) - ) -) diff --git a/test/lit/fuzz-types/isorecursive.test b/test/lit/fuzz-types/isorecursive.test index 78315c5b1..18fade75b 100644 --- a/test/lit/fuzz-types/isorecursive.test +++ b/test/lit/fuzz-types/isorecursive.test @@ -2,25 +2,25 @@ ;; CHECK: (rec ;; CHECK-NEXT: (type $0 (struct_subtype data)) -;; CHECK-NEXT: (type $1 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) func)) -;; CHECK-NEXT: (type $2 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) data)) -;; CHECK-NEXT: (type $3 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) -;; CHECK-NEXT: (type $4 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) -;; CHECK-NEXT: (type $5 (struct_subtype (field f64 v128 (ref null $10) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3)) -;; CHECK-NEXT: (type $6 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3)) +;; CHECK-NEXT: (type $1 (func_subtype (param (ref $0)) func)) +;; CHECK-NEXT: (type $2 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32) data)) +;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32) $2)) +;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32) $2)) +;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32) $3)) +;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32 v128) $3)) ;; CHECK-NEXT: (type $7 (struct_subtype $0)) -;; CHECK-NEXT: (type $8 (struct_subtype (field f32 (mut i16) (ref eq) (mut (rtt $2))) $0)) -;; CHECK-NEXT: (type $9 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6)) -;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $2) (mut (ref $13)) (ref null i31) v128 (ref null $6)) $0)) -;; CHECK-NEXT: (type $11 (struct_subtype (field f64 v128 (ref $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) +;; CHECK-NEXT: (type $8 (struct_subtype $0)) +;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32 v128) $6)) +;; CHECK-NEXT: (type $10 (struct_subtype (field (mut i64)) $0)) +;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32) $2)) ;; CHECK-NEXT: (type $12 (struct_subtype $0)) -;; CHECK-NEXT: (type $13 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6)) +;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32 v128) $6)) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $10)) -;; CHECK-NEXT: (type $15 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $1)) -;; CHECK-NEXT: (type $16 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2)) -;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $14)) -;; CHECK-NEXT: (type $18 (struct_subtype $12)) -;; CHECK-NEXT: (type $19 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $15)) +;; CHECK-NEXT: (type $14 (struct_subtype (field (mut i64) (ref null $11) v128) $10)) +;; CHECK-NEXT: (type $15 (func_subtype (param (ref $0)) $1)) +;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (ref null $2)) v128 i8 (mut i8) f32 (mut i64)) $2)) +;; CHECK-NEXT: (type $17 (struct_subtype (field (mut i64) (ref $11) v128 i16 i8) $14)) +;; CHECK-NEXT: (type $18 (struct_subtype (field (mut f64)) $12)) +;; CHECK-NEXT: (type $19 (func_subtype (param (ref $0)) $15)) ;; CHECK-NEXT: ) diff --git a/test/lit/fuzz-types/nominal.test b/test/lit/fuzz-types/nominal.test index 299cf2613..7ef381bfe 100644 --- a/test/lit/fuzz-types/nominal.test +++ b/test/lit/fuzz-types/nominal.test @@ -1,22 +1,22 @@ ;; RUN: wasm-fuzz-types --nominal -v --seed=0 | filecheck %s -;; CHECK: (type $0 (struct_subtype (field (ref null $9) (ref $5)) data)) -;; CHECK-NEXT: (type $1 (func_subtype (param (rtt 0 $8)) func)) -;; CHECK-NEXT: (type $2 (struct_subtype (field (mut (rtt $19)) (ref $4)) data)) -;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $2)) -;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2)) -;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3)) -;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3)) -;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $8 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6)) -;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $9) (ref $5) i32) $0)) -;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut f64) i32 (mut f32)) $2)) -;; CHECK-NEXT: (type $12 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6)) -;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $9) (ref $5) i32) $10)) -;; CHECK-NEXT: (type $15 (func_subtype (param (rtt 0 $8)) $1)) -;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut i16) i64 (mut (rtt 0 i31))) $2)) -;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $9) (ref $5) i32) $14)) -;; CHECK-NEXT: (type $18 (struct_subtype (field (ref null $9) (ref $5)) $12)) -;; CHECK-NEXT: (type $19 (func_subtype (param (rtt 0 $8)) $15)) +;; CHECK: (type $0 (struct_subtype (field v128 (ref null $4)) data)) +;; CHECK-NEXT: (type $1 (func_subtype (param (ref $3)) (result i32) func)) +;; CHECK-NEXT: (type $2 (struct_subtype (field (mut i64) f64) data)) +;; CHECK-NEXT: (type $3 (struct_subtype (field (mut i64) f64 (mut (ref $12)) i64) $2)) +;; CHECK-NEXT: (type $4 (struct_subtype (field (mut i64) f64) $2)) +;; CHECK-NEXT: (type $5 (struct_subtype (field (mut i64) f64 (mut (ref $12)) i64) $3)) +;; CHECK-NEXT: (type $6 (struct_subtype (field (mut i64) f64 (mut (ref $12)) i64) $3)) +;; CHECK-NEXT: (type $7 (struct_subtype (field v128 (ref null $4)) $0)) +;; CHECK-NEXT: (type $8 (struct_subtype (field v128 (ref $4) (ref null $3) v128) $0)) +;; CHECK-NEXT: (type $9 (struct_subtype (field (mut i64) f64 (mut (ref $12)) i64) $6)) +;; CHECK-NEXT: (type $10 (struct_subtype (field v128 (ref null $4)) $0)) +;; CHECK-NEXT: (type $11 (struct_subtype (field (mut i64) f64) $2)) +;; CHECK-NEXT: (type $12 (struct_subtype (field v128 (ref null $4) (mut (ref null $3))) $0)) +;; CHECK-NEXT: (type $13 (struct_subtype (field (mut i64) f64 (mut (ref $12)) i64) $6)) +;; CHECK-NEXT: (type $14 (struct_subtype (field v128 (ref null $4)) $10)) +;; CHECK-NEXT: (type $15 (func_subtype (param (ref $3)) (result i32) $1)) +;; CHECK-NEXT: (type $16 (struct_subtype (field (mut i64) f64) $2)) +;; CHECK-NEXT: (type $17 (struct_subtype (field v128 (ref null $4) i32) $14)) +;; CHECK-NEXT: (type $18 (struct_subtype (field v128 (ref null $4) (mut (ref null $3)) i16 f64) $12)) +;; CHECK-NEXT: (type $19 (func_subtype (param (ref $3)) (result i32) $15)) diff --git a/test/lit/fuzz-types/structural.test b/test/lit/fuzz-types/structural.test index e0aa75e9e..345590e2b 100644 --- a/test/lit/fuzz-types/structural.test +++ b/test/lit/fuzz-types/structural.test @@ -1,22 +1,22 @@ ;; RUN: wasm-fuzz-types --structural -v --seed=0 | filecheck %s -;; CHECK: (type $0 (struct (field (ref null $3) (ref $3)))) -;; CHECK-NEXT: (type $1 (func (param (rtt 0 $0)))) -;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $2)))) -;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $2) i64 v128 (mut v128)))) +;; CHECK: (type $0 (struct (field v128 (ref null $2)))) +;; CHECK-NEXT: (type $1 (func (param (ref $3)) (result i32))) +;; CHECK-NEXT: (type $2 (struct (field (mut i64) f64))) +;; CHECK-NEXT: (type $3 (struct (field (mut i64) f64 (mut (ref $12)) i64))) ;; CHECK-NEXT: (type $4 identical to $2) ;; CHECK-NEXT: (type $5 identical to $3) ;; CHECK-NEXT: (type $6 identical to $3) ;; CHECK-NEXT: (type $7 identical to $0) -;; CHECK-NEXT: (type $8 identical to $0) +;; CHECK-NEXT: (type $8 (struct (field v128 (ref $2) (ref null $3) v128))) ;; CHECK-NEXT: (type $9 identical to $3) -;; CHECK-NEXT: (type $10 (struct (field (ref $3) (ref $3) i32))) -;; CHECK-NEXT: (type $11 (struct (field (mut (rtt $1)) (ref $2) (mut f64) i32 (mut f32)))) -;; CHECK-NEXT: (type $12 identical to $0) +;; CHECK-NEXT: (type $10 identical to $0) +;; CHECK-NEXT: (type $11 identical to $2) +;; CHECK-NEXT: (type $12 (struct (field v128 (ref null $2) (mut (ref null $3))))) ;; CHECK-NEXT: (type $13 identical to $3) -;; CHECK-NEXT: (type $14 identical to $10) +;; CHECK-NEXT: (type $14 identical to $0) ;; CHECK-NEXT: (type $15 identical to $1) -;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $2) (mut i16) i64 (mut (rtt 0 i31))))) -;; CHECK-NEXT: (type $17 identical to $10) -;; CHECK-NEXT: (type $18 identical to $0) +;; CHECK-NEXT: (type $16 identical to $2) +;; CHECK-NEXT: (type $17 (struct (field v128 (ref null $2) i32))) +;; CHECK-NEXT: (type $18 (struct (field v128 (ref null $2) (mut (ref null $3)) i16 f64))) ;; CHECK-NEXT: (type $19 identical to $1) diff --git a/test/lit/passes/cfp.wast b/test/lit/passes/cfp.wast index 5caadf16d..782a30af2 100644 --- a/test/lit/passes/cfp.wast +++ b/test/lit/passes/cfp.wast @@ -37,9 +37,7 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block (result i64) @@ -61,9 +59,7 @@ ;; references escaping and being stored etc. - it just thinks at the type ;; level.) (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) (drop (struct.get $struct 0 @@ -80,9 +76,8 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -100,9 +95,8 @@ ;; The only place this type is created is with a constant value, and so we ;; can optimize the later get into a constant (plus a drop of the ref). (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) (drop @@ -120,9 +114,8 @@ ;; CHECK: (func $test (type $f32_=>_none) (param $f f32) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -134,9 +127,8 @@ (func $test (param $f f32) ;; The value given is not a constant, and so we cannot optimize. (drop - (struct.new_with_rtt $struct + (struct.new $struct (local.get $f) - (rtt.canon $struct) ) ) (drop @@ -156,17 +148,15 @@ (type $struct (struct i32)) ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ) @@ -221,17 +211,15 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ) @@ -246,15 +234,13 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 1337) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -265,15 +251,13 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 1337) - (rtt.canon $struct) ) ) (drop @@ -292,17 +276,15 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ) @@ -343,17 +325,15 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ) @@ -400,24 +380,22 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (block (result f32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (f32.const 42) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct ;; Fall though a 42 via a block. (block (result f32) (nop) (f32.const 42) ) - (rtt.canon $struct) ) ) ) @@ -473,9 +451,8 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (ref.func $test) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -491,9 +468,8 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_with_rtt $struct + (struct.new $struct (ref.func $test) - (rtt.canon $struct) ) ) (drop @@ -513,9 +489,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -538,8 +511,7 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_with_rtt $struct - (i32.const 10) + (struct.new $struct (unreachable) ) ) @@ -568,17 +540,15 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ) @@ -615,9 +585,8 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 0 @@ -627,9 +596,8 @@ ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (struct.set $struct 0 @@ -673,19 +641,17 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 10) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -722,31 +688,27 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (drop - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 10) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -784,31 +746,27 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (drop - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -844,31 +802,27 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (drop - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -905,9 +859,8 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 0 @@ -915,18 +868,16 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (struct.set $struct 0 @@ -934,10 +885,9 @@ (i32.const 10) ) (drop - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -975,21 +925,19 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 20) (f64.const 3.14159) (ref.null any) - (rtt.canon $struct3) ) ) ) @@ -1114,34 +1062,31 @@ ;; CHECK: (func $create (type $anyref_=>_none) (param $any anyref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (i32.const 999) ;; CHECK-NEXT: (f64.const 2.71828) ;; CHECK-NEXT: (f64.const 9.9999999) ;; CHECK-NEXT: (ref.null any) ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (param $any anyref) (drop - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) (i32.const 20) - (rtt.canon $struct1) ) ) (drop - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (i32.const 999) ;; use a different value here (f64.const 2.71828) @@ -1149,7 +1094,6 @@ (ref.null any) (local.get $any) ;; use a non-constant value here, which can never be ;; optimized. - (rtt.canon $struct3) ) ) ) @@ -1344,47 +1288,41 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 + ;; CHECK-NEXT: (struct.new $struct2 ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) - (rtt.canon $struct1) ) ) (drop - (struct.new_with_rtt $struct2 + (struct.new $struct2 (i32.const 9999) ;; use a different value here (f64.const 0) - (rtt.canon $struct2) ) ) (drop - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (f64.const 0) (ref.null any) - (rtt.canon $struct3) ) ) ) @@ -1447,16 +1385,14 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 + ;; CHECK-NEXT: (struct.new $struct2 ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct2 0 @@ -1464,26 +1400,23 @@ ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) - (rtt.canon $struct1) ) ) (drop - (struct.new_with_rtt $struct2 + (struct.new $struct2 (i32.const 9999) ;; use a different value here (f64.const 0) - (rtt.canon $struct2) ) ) (struct.set $struct2 0 @@ -1492,11 +1425,10 @@ (f64.const 0) ) (drop - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (f64.const 0) (ref.null any) - (rtt.canon $struct3) ) ) ) @@ -1547,7 +1479,7 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) @@ -1557,19 +1489,17 @@ ;; CHECK-NEXT: (f64.const 2.71828) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.eqz (i32.const 10)) ;; not a constant (as far as this pass knows) (f64.const 3.14159) (i32.const 20) (f64.abs (f64.const 2.71828)) ;; not a constant (i32.const 30) - (rtt.canon $struct) ) ) ) @@ -1683,17 +1613,15 @@ ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $C + ;; CHECK-NEXT: (struct.new $C ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $C) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (drop - (struct.new_with_rtt $C + (struct.new $C (i32.const 10) - (rtt.canon $C) ) ) ) @@ -1735,9 +1663,7 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 0 ;; CHECK-NEXT: (ref.null $struct) @@ -1763,9 +1689,7 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; This copy does not actually introduce any new possible values, and so it ;; remains true that the only possible value is the default. @@ -1795,9 +1719,7 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 1 ;; CHECK-NEXT: (ref.null $struct) @@ -1816,9 +1738,7 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; As this is not a copy, we cannot optimize struct.1's get lower down. (struct.set $struct 1 @@ -1844,9 +1764,7 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 0 ;; CHECK-NEXT: (ref.null $struct) @@ -1867,9 +1785,7 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; As this is not a copy, we cannot optimize struct.0's get lower down. (struct.set $struct 0 @@ -2182,4 +2098,3 @@ ) ) ) - diff --git a/test/lit/passes/dae-gc.wast b/test/lit/passes/dae-gc.wast index a8e078468..ea4cce506 100644 --- a/test/lit/passes/dae-gc.wast +++ b/test/lit/passes/dae-gc.wast @@ -69,30 +69,28 @@ (unreachable) ) ) - ;; a function that gets an rtt that is never used. we cannot create a local for - ;; that parameter, as it is not defaultable, so do not remove the parameter. - ;; CHECK: (func $get-rtt (param $0 (rtt ${})) + ;; A function that gets a non-nullable reference that is never used. We can + ;; still create a nullable local for that parameter. + ;; CHECK: (func $get-nonnull + ;; CHECK-NEXT: (local $0 (ref null ${})) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-rtt (type $rtt_${}_=>_none) (param $0 (rtt ${})) + ;; NOMNL: (func $get-nonnull (type $none_=>_none) + ;; NOMNL-NEXT: (local $0 (ref null ${})) ;; NOMNL-NEXT: (nop) ;; NOMNL-NEXT: ) - (func $get-rtt (param $0 (rtt ${})) + (func $get-nonnull (param $0 (ref ${})) (nop) ) - ;; CHECK: (func $send-rtt - ;; CHECK-NEXT: (call $get-rtt - ;; CHECK-NEXT: (rtt.canon ${}) - ;; CHECK-NEXT: ) + ;; CHECK: (func $send-nonnull + ;; CHECK-NEXT: (call $get-nonnull) ;; CHECK-NEXT: ) - ;; NOMNL: (func $send-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (call $get-rtt - ;; NOMNL-NEXT: (rtt.canon ${}) - ;; NOMNL-NEXT: ) + ;; NOMNL: (func $send-nonnull (type $none_=>_none) + ;; NOMNL-NEXT: (call $get-nonnull) ;; NOMNL-NEXT: ) - (func $send-rtt - (call $get-rtt - (rtt.canon ${}) + (func $send-nonnull + (call $get-nonnull + (struct.new ${}) ) ) ) diff --git a/test/lit/passes/gto-removals.wast b/test/lit/passes/gto-removals.wast index 41c7fc950..1bc0d2b73 100644 --- a/test/lit/passes/gto-removals.wast +++ b/test/lit/passes/gto-removals.wast @@ -399,8 +399,8 @@ (module ;; A new with side effects - ;; CHECK: (type $struct (struct_subtype (field i32) (field (rtt $struct)) data)) - (type $struct (struct i32 f64 (ref any) (rtt $struct))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) + (type $struct (struct i32 f64 (ref any))) ;; CHECK: (type $none_=>_none (func_subtype func)) @@ -425,11 +425,6 @@ ;; CHECK-NEXT: (ref.null $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $gets (param $x (ref any)) ;; Gets to keep certain fields alive. @@ -438,11 +433,6 @@ (ref.null $struct) ) ) - (drop - (struct.get $struct 3 - (ref.null $struct) - ) - ) ) ;; CHECK: (func $new-side-effect (type $none_=>_none) @@ -468,24 +458,20 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $new-side-effect ;; The 2nd&3rd fields here will be removed, since those fields have no - ;; reads. They has side effects, though, so the operands will be saved in - ;; locals. Note that we can't save the rtt.canon in locals, but it has - ;; no effects, and we leave such arguments as they are. - ;; Note also that one of the fields is non-nullable, and we need to use a + ;; reads. They have side effects, though, so the operands will be saved in + ;; locals. Note that one of the fields is non-nullable, and we need to use a ;; nullable local for it. (drop (struct.new $struct (call $helper0 (i32.const 0)) (call $helper1 (i32.const 1)) (call $helper2 (i32.const 2)) - (rtt.canon $struct) ) ) ) @@ -507,7 +493,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (global.get $imm-i32) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -522,7 +507,6 @@ (global.get $imm-i32) (call $helper1 (i32.const 0)) (call $helper2 (i32.const 1)) - (rtt.canon $struct) ) ) ) @@ -548,7 +532,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -561,7 +544,6 @@ (global.get $mut-i32) (call $helper1 (i32.const 0)) (call $helper2 (i32.const 1)) - (rtt.canon $struct) ) ) ) @@ -580,9 +562,6 @@ ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -594,7 +573,6 @@ (i32.const 2) (unreachable) (call $helper2 (i32.const 3)) - (rtt.canon $struct) ) ) ) @@ -605,7 +583,6 @@ ;; CHECK-NEXT: (call $helper0 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -617,7 +594,6 @@ (call $helper0 (i32.const 0)) (f64.const 3.14159) (local.get $any) - (rtt.canon $struct) ) ) ) diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast index 19ca922f4..ddd10e7f9 100644 --- a/test/lit/passes/gufa-refs.wast +++ b/test/lit/passes/gufa-refs.wast @@ -2896,11 +2896,10 @@ ;; they might appear as if no content were possible there, and we'd emit an ;; unreachable. That should not happen anywhere here. (module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $A (struct_subtype data)) (type $A (struct_subtype data)) + ;; CHECK: (type $none_=>_none (func_subtype func)) + ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) ;; CHECK: (type $B (array_subtype (mut anyref) data)) @@ -3146,44 +3145,6 @@ ) ) - ;; CHECK: (func $refs-rtts (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (ref.null data) - ;; CHECK-NEXT: (ref.null data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: (rtt.sub $A - ;; CHECK-NEXT: (rtt.canon $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $refs-rtts - (drop - (ref.eq - (ref.null data) - (ref.null data) - ) - ) - (drop - (ref.cast - (ref.null $A) - (rtt.sub $A - (rtt.canon $A) - ) - ) - ) - ) - ;; CHECK: (func $table (type $none_=>_none) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (table.get $t diff --git a/test/lit/passes/gufa-vs-cfp.wast b/test/lit/passes/gufa-vs-cfp.wast index 38dbf72fd..9cb74fbe7 100644 --- a/test/lit/passes/gufa-vs-cfp.wast +++ b/test/lit/passes/gufa-vs-cfp.wast @@ -66,9 +66,7 @@ ;; its reference is non-nullable). (drop (struct.get $struct 0 - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ) ) @@ -89,9 +87,8 @@ ;; passed in, as opposed to being a default value as in the last testcase). (drop (struct.get $struct 0 - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ) @@ -112,9 +109,8 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -123,9 +119,8 @@ ;; The value given is not a constant, and so we cannot optimize. (drop (struct.get $struct 0 - (struct.new_with_rtt $struct + (struct.new $struct (call $import) - (rtt.canon $struct) ) ) ) @@ -142,15 +137,13 @@ ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ;; CHECK: (func $get (type $none_=>_none) @@ -204,15 +197,13 @@ ) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ) @@ -226,34 +217,30 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 1337) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $test (drop - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ;; (A better analysis could see that the first struct.new is dropped and its ;; value cannot reach this struct.get.) (drop (struct.get $struct 0 - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 1337) - (rtt.canon $struct) ) ) ) @@ -269,15 +256,13 @@ ;; CHECK: (type $none_=>_ref|$struct| (func_subtype (result (ref $struct)) func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ;; CHECK: (func $set (type $none_=>_none) @@ -319,15 +304,13 @@ ;; CHECK: (type $none_=>_ref|$struct| (func_subtype (result (ref $struct)) func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (f32.const 42) - (rtt.canon $struct) ) ) ;; CHECK: (func $set (type $none_=>_none) @@ -376,19 +359,17 @@ (import "a" "b" (func $import (result i32))) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct ;; Fall though a 42. The block can be optimized to a constant. (block $named (result f32) (nop) (f32.const 42) ) - (rtt.canon $struct) ) ) ;; CHECK: (func $set (type $none_=>_none) @@ -453,9 +434,8 @@ (func $test (drop (struct.get $struct 0 - (struct.new_with_rtt $struct + (struct.new $struct (ref.func $test) - (rtt.canon $struct) ) ) ) @@ -493,7 +473,7 @@ ;; CHECK-NEXT: ) (func $test (drop - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) (unreachable) ) @@ -520,15 +500,13 @@ ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) ;; CHECK: (func $get (type $none_=>_none) @@ -569,15 +547,13 @@ ;; CHECK: (type $none_=>_ref|$struct| (func_subtype (result (ref $struct)) func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) @@ -631,9 +607,8 @@ ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (local $ref (ref null $struct)) ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.set $struct 0 @@ -659,9 +634,8 @@ (func $test (local $ref (ref null $struct)) (local.set $ref - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) ) (struct.set $struct 0 @@ -700,10 +674,9 @@ (func $test (drop (struct.get $struct 0 - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 10) (f64.const 3.14159) - (rtt.canon $substruct) ) ) ) @@ -730,14 +703,12 @@ ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: ) @@ -751,14 +722,12 @@ (drop (struct.get $struct 0 (select - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 10) (f64.const 3.14159) - (rtt.canon $substruct) ) (call $import) ) @@ -787,14 +756,12 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get $struct 0 ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: ) @@ -805,14 +772,12 @@ (drop (struct.get $struct 0 (select - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) ;; this constant changed (f64.const 3.14159) - (rtt.canon $substruct) ) (call $import) ) @@ -846,14 +811,12 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.cast_static $substruct ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: ) @@ -869,14 +832,12 @@ ;; This cast is added, ensuring only a $substruct can reach the get. (ref.cast_static $substruct (select - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) (call $import) ) @@ -905,14 +866,12 @@ ;; CHECK-NEXT: (local $ref (ref null $struct)) ;; CHECK-NEXT: (local.set $ref ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: ) @@ -933,14 +892,12 @@ (local $ref (ref null $struct)) (local.set $ref (select - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) (call $import) ) @@ -981,14 +938,12 @@ ;; CHECK-NEXT: (local $ref (ref null $struct)) ;; CHECK-NEXT: (local.set $ref ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_with_rtt $substruct + ;; CHECK-NEXT: (struct.new $substruct ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: ) @@ -1014,14 +969,12 @@ (local $ref (ref null $struct)) (local.set $ref (select - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 10) - (rtt.canon $struct) ) - (struct.new_with_rtt $substruct + (struct.new $substruct (i32.const 20) (f64.const 3.14159) - (rtt.canon $substruct) ) (call $import) ) @@ -1059,19 +1012,17 @@ ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (type $none_=>_ref|$struct3|) (result (ref $struct3)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (f64.const 3.14159) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct3)) - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 20) (f64.const 3.14159) (ref.null any) - (rtt.canon $struct3) ) ) ;; CHECK: (func $get (type $none_=>_none) @@ -1209,33 +1160,30 @@ (import "a" "b" (func $import (result anyref))) ;; CHECK: (func $create1 (type $none_=>_ref|$struct1|) (result (ref $struct1)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create1 (result (ref $struct1)) - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) (i32.const 20) - (rtt.canon $struct1) ) ) ;; CHECK: (func $create3 (type $none_=>_ref|$struct3|) (result (ref $struct3)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (i32.const 999) ;; CHECK-NEXT: (f64.const 2.71828) ;; CHECK-NEXT: (f64.const 9.9999999) ;; CHECK-NEXT: (ref.null any) ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create3 (result (ref $struct3)) - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (i32.const 999) ;; use a different value here (f64.const 2.71828) @@ -1243,7 +1191,6 @@ (ref.null any) (call $import) ;; use an unknown value here, which can never be ;; optimized. - (rtt.canon $struct3) ) ) @@ -1447,47 +1394,41 @@ (import "a" "b" (func $import (result i32))) ;; CHECK: (func $create1 (type $none_=>_ref|$struct1|) (result (ref $struct1)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create1 (result (ref $struct1)) - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) - (rtt.canon $struct1) ) ) ;; CHECK: (func $create2 (type $none_=>_ref|$struct2|) (result (ref $struct2)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 + ;; CHECK-NEXT: (struct.new $struct2 ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create2 (result (ref $struct2)) - (struct.new_with_rtt $struct2 + (struct.new $struct2 (i32.const 9999) ;; use a different value here (f64.const 0) - (rtt.canon $struct2) ) ) ;; CHECK: (func $create3 (type $none_=>_ref|$struct3|) (result (ref $struct3)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create3 (result (ref $struct3)) - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (f64.const 0) (ref.null any) - (rtt.canon $struct3) ) ) @@ -1758,47 +1699,41 @@ (import "a" "b" (func $import (result i32))) ;; CHECK: (func $create1 (type $none_=>_ref|$struct1|) (result (ref $struct1)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create1 (result (ref $struct1)) - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) - (rtt.canon $struct1) ) ) ;; CHECK: (func $create2 (type $none_=>_ref|$struct2|) (result (ref $struct2)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 + ;; CHECK-NEXT: (struct.new $struct2 ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create2 (result (ref $struct2)) - (struct.new_with_rtt $struct2 + (struct.new $struct2 (i32.const 9999) ;; use a different value here (f64.const 0) - (rtt.canon $struct2) ) ) ;; CHECK: (func $create3 (type $none_=>_ref|$struct3|) (result (ref $struct3)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create3 (result (ref $struct3)) - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (f64.const 0) (ref.null any) - (rtt.canon $struct3) ) ) @@ -1880,47 +1815,41 @@ (import "a" "b" (func $import (result i32))) ;; CHECK: (func $create1 (type $none_=>_ref|$struct1|) (result (ref $struct1)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 + ;; CHECK-NEXT: (struct.new $struct1 ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create1 (result (ref $struct1)) - (struct.new_with_rtt $struct1 + (struct.new $struct1 (i32.const 10) - (rtt.canon $struct1) ) ) ;; CHECK: (func $create2 (type $none_=>_ref|$struct2|) (result (ref $struct2)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 + ;; CHECK-NEXT: (struct.new $struct2 ;; CHECK-NEXT: (i32.const 9999) ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create2 (result (ref $struct2)) - (struct.new_with_rtt $struct2 + (struct.new $struct2 (i32.const 9999) ;; use a different value here (f64.const 0) - (rtt.canon $struct2) ) ) ;; CHECK: (func $create3 (type $none_=>_ref|$struct3|) (result (ref $struct3)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 + ;; CHECK-NEXT: (struct.new $struct3 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create3 (result (ref $struct3)) - (struct.new_with_rtt $struct3 + (struct.new $struct3 (i32.const 10) (f64.const 0) (ref.null any) - (rtt.canon $struct3) ) ) @@ -1988,7 +1917,7 @@ ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) @@ -1998,17 +1927,15 @@ ;; CHECK-NEXT: (f64.const 2.71828) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_with_rtt $struct + (struct.new $struct (i32.eqz (i32.const 10)) ;; not a constant (as far as this pass knows) (f64.const 3.14159) (i32.const 20) (f64.abs (f64.const 2.71828)) ;; not a constant (i32.const 30) - (rtt.canon $struct) ) ) ;; CHECK: (func $get (type $none_=>_none) @@ -2110,15 +2037,13 @@ ;; CHECK: (type $none_=>_ref|$C| (func_subtype (result (ref $C)) func)) ;; CHECK: (func $create-C (type $none_=>_ref|$C|) (result (ref $C)) - ;; CHECK-NEXT: (struct.new_with_rtt $C + ;; CHECK-NEXT: (struct.new $C ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $C) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $create-C (result (ref $C)) - (struct.new_with_rtt $C + (struct.new $C (i32.const 10) - (rtt.canon $C) ) ) ;; CHECK: (func $set (type $none_=>_none) @@ -2167,14 +2092,10 @@ ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) (func $create (result (ref $struct)) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; CHECK: (func $test (type $none_=>_none) diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index ebe5d1db9..b7ed9bd0f 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -11,22 +11,20 @@ ;; CHECK: (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) - ;; CHECK: (type $struct.nonnullable (struct (field (ref $struct.A)))) + ;; CHECK: (type $struct.nondefaultable (struct (field (ref $struct.A)))) ;; CHECK: (type $struct.packed (struct (field (mut i8)))) ;; NOMNL: (type $struct.recursive (struct_subtype (field (mut (ref null $struct.recursive))) data)) - ;; NOMNL: (type $struct.nonnullable (struct_subtype (field (ref $struct.A)) data)) - ;; NOMNL: (type $struct.packed (struct_subtype (field (mut i8)) data)) (type $struct.packed (struct (field (mut i8)))) - ;; CHECK: (type $struct.nondefaultable (struct (field (rtt $struct.A)))) - ;; NOMNL: (type $struct.nondefaultable (struct_subtype (field (rtt $struct.A)) data)) - (type $struct.nondefaultable (struct (field (rtt $struct.A)))) + ;; NOMNL: (type $struct.nondefaultable (struct_subtype (field (ref $struct.A)) data)) + (type $struct.nondefaultable (struct (field (ref $struct.A)))) (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) + ;; NOMNL: (type $struct.nonnullable (struct_subtype (field (ref $struct.A)) data)) (type $struct.nonnullable (struct (field (ref $struct.A)))) ;; CHECK: (func $simple @@ -40,9 +38,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -58,9 +53,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -69,9 +61,7 @@ ;; Other passes can remove such a trivial case of an unused allocation, but ;; we still optimize it. (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) @@ -87,9 +77,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -106,9 +93,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -120,9 +104,7 @@ ;; drop (and adding some unnecessary code to allocate the values, which we ;; depend on other passes to remove). (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) @@ -139,9 +121,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -162,9 +141,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -180,9 +156,7 @@ ;; locals, and we read from the locals instead of the struct.get. (drop (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) ) @@ -200,9 +174,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -223,9 +194,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -237,9 +205,7 @@ ;; Similar to the above, but using a different field index. (drop (struct.get $struct.A 1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) ) @@ -255,9 +221,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -276,9 +239,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -289,9 +249,7 @@ (func $one-set ;; A simple optimizable allocation only used in one set. (struct.set $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) (i32.const 1) ) ) @@ -299,18 +257,14 @@ ;; CHECK: (func $packed ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get_u $struct.packed 0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.packed - ;; CHECK-NEXT: (rtt.canon $struct.packed) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.packed) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $packed (type $none_=>_none) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (struct.get_u $struct.packed 0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.packed - ;; NOMNL-NEXT: (rtt.canon $struct.packed) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.packed) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -318,9 +272,7 @@ ;; We do not optimize packed structs yet. (drop (struct.get $struct.packed 0 - (struct.new_default_with_rtt $struct.packed - (rtt.canon $struct.packed) - ) + (struct.new_default $struct.packed) ) ) ) @@ -346,9 +298,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -377,9 +326,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (local.get $3) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -392,10 +338,9 @@ ;; proper locals. (drop (struct.get $struct.A 0 - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 2) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) ) @@ -412,9 +357,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -431,9 +373,6 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -444,43 +383,70 @@ ;; remove it. (drop (struct.get $struct.A 0 - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 2) (unreachable) - (rtt.canon $struct.A) ) ) ) ) ;; CHECK: (func $nondefaultable + ;; CHECK-NEXT: (local $0 (ref null $struct.A)) + ;; CHECK-NEXT: (local $1 (ref null $struct.A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct.nondefaultable 0 - ;; CHECK-NEXT: (struct.new_with_rtt $struct.nondefaultable - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: (rtt.canon $struct.nondefaultable) + ;; CHECK-NEXT: (block (result (ref $struct.A)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result (ref null $struct.nondefaultable)) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (struct.new_default $struct.A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null $struct.nondefaultable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $nondefaultable (type $none_=>_none) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 (ref null $struct.A)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get $struct.nondefaultable 0 - ;; NOMNL-NEXT: (struct.new_with_rtt $struct.nondefaultable - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: (rtt.canon $struct.nondefaultable) + ;; NOMNL-NEXT: (block (result (ref $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.nondefaultable)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (struct.new_default $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.nondefaultable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $0) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $nondefaultable ;; We do not optimize structs with nondefaultable types that we cannot - ;; handle, like rtts. + ;; handle. + ;; TODO: We should be able to handle this after #4824 is resolved. (drop (struct.get $struct.nondefaultable 0 - (struct.new_with_rtt $struct.nondefaultable - (rtt.canon $struct.A) - (rtt.canon $struct.nondefaultable) + (struct.new $struct.nondefaultable + (struct.new_default $struct.A) ) ) ) @@ -498,9 +464,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -525,9 +488,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -546,9 +506,7 @@ ;; to a local. The local.set should not prevent our optimization, and the ;; local.set can be turned into a drop. (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.set $struct.A 0 (local.get $ref) @@ -568,9 +526,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -593,9 +548,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -609,9 +561,7 @@ (func $simple-one-local-get (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; A simple optimizable allocation only used in one get, via a local. (struct.get $struct.A 1 @@ -640,9 +590,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -668,9 +615,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -687,9 +631,7 @@ (func $safe-to-drop (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; An extra drop does not let the allocation escape. (drop @@ -703,9 +645,7 @@ ;; CHECK: (func $escape-via-call (result f64) ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $send-ref ;; CHECK-NEXT: (local.get $ref) @@ -717,9 +657,7 @@ ;; NOMNL: (func $escape-via-call (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (call $send-ref ;; NOMNL-NEXT: (local.get $ref) @@ -731,9 +669,7 @@ (func $escape-via-call (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; The allocation escapes into a call. (call $send-ref @@ -756,9 +692,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -788,9 +721,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -811,9 +741,7 @@ (func $safe-to-drop-multiflow (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; An extra drop + multiple flows through things do not stop us. (drop @@ -833,9 +761,7 @@ ;; CHECK: (func $escape-after-multiflow (result f64) ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $send-ref ;; CHECK-NEXT: (block (result (ref null $struct.A)) @@ -851,9 +777,7 @@ ;; NOMNL: (func $escape-after-multiflow (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (call $send-ref ;; NOMNL-NEXT: (block (result (ref null $struct.A)) @@ -869,9 +793,7 @@ (func $escape-after-multiflow (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; An escape after multiple flows. (call $send-ref @@ -892,12 +814,8 @@ ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local.set $ref ;; CHECK-NEXT: (select (result (ref $struct.A)) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -909,12 +827,8 @@ ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $ref ;; NOMNL-NEXT: (select (result (ref $struct.A)) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: (i32.const 1) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -928,12 +842,8 @@ ;; to optimize it. (local.set $ref (select - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) + (struct.new_default $struct.A) (i32.const 1) ) ) @@ -954,9 +864,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -982,9 +889,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1001,9 +905,7 @@ (func $local-copies (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; Copying our allocation through locals does not bother us. (local.set $ref @@ -1027,9 +929,6 @@ ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1066,9 +965,6 @@ ;; NOMNL-NEXT: (local.set $3 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1096,9 +992,7 @@ (local $ref (ref null $struct.A)) (local $ref-2 (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; Copying our allocation through locals does not bother us, even if it's ;; another local. @@ -1129,9 +1023,6 @@ ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1160,9 +1051,6 @@ ;; NOMNL-NEXT: (local.set $3 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1182,9 +1070,7 @@ (func $local-copies-conditional (param $x i32) (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; Possibly copying our allocation through locals does not bother us. Note ;; that as a result of this the final local.get has two sets that send it @@ -1211,9 +1097,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1241,9 +1124,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1262,9 +1142,7 @@ (func $block-value (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; Returning our allocation from a block does not bother us. (struct.get $struct.A 1 @@ -1281,9 +1159,7 @@ ;; CHECK: (func $non-exclusive-get (param $x i32) (result f64) ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $x) @@ -1298,9 +1174,7 @@ ;; NOMNL: (func $non-exclusive-get (type $i32_=>_f64) (param $x i32) (result f64) ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (if ;; NOMNL-NEXT: (local.get $x) @@ -1315,9 +1189,7 @@ (func $non-exclusive-get (param $x i32) (result f64) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (if (local.get $x) (local.set $ref @@ -1343,9 +1215,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1363,9 +1232,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1376,9 +1242,7 @@ (struct.get $struct.A 0 ;; A tee flows out the value, and we can optimize this allocation. (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) ) @@ -1391,9 +1255,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (ref.null $struct.recursive) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.recursive) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1409,9 +1270,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (ref.null $struct.recursive) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.recursive) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1424,9 +1282,7 @@ ;; As above, but with a set, and also a recursive type. (struct.set $struct.recursive 0 (local.tee $ref - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) + (struct.new_default $struct.recursive) ) (ref.null $struct.recursive) ) @@ -1437,9 +1293,7 @@ ;; CHECK-NEXT: (struct.set $struct.recursive 0 ;; CHECK-NEXT: (ref.null $struct.recursive) ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.recursive) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1448,9 +1302,7 @@ ;; NOMNL-NEXT: (struct.set $struct.recursive 0 ;; NOMNL-NEXT: (ref.null $struct.recursive) ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.recursive) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1461,9 +1313,7 @@ ;; As above, but operands reversed: the allocation is now the value, not ;; the reference, and so it escapes. (local.tee $ref - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) + (struct.new_default $struct.recursive) ) ) ) @@ -1475,16 +1325,11 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block (result (ref null $struct.recursive)) ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.recursive) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.recursive) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1504,16 +1349,11 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.recursive) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (local.get $2) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.recursive) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1530,7 +1370,7 @@ (local $0 (ref null $struct.recursive)) (local.set $0 ;; The outer allocation can be optimized, as it does not escape. - (struct.new_with_rtt $struct.recursive + (struct.new $struct.recursive ;; The inner allocation should not prevent the outer one from being ;; optimized through some form of confusion. ;; After the outer one is optimized, the inner one can be optimized in @@ -1538,10 +1378,7 @@ ;; on other optimizations to actually remove the outer allocation (like ;; vacuum), and so it cannot be optimized. If we ran vaccum, and then ;; additional iterations, this might be handled. - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) - (rtt.canon $struct.recursive) + (struct.new_default $struct.recursive) ) ) (drop @@ -1555,9 +1392,7 @@ ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (struct.set $struct.A 0 ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) @@ -1567,9 +1402,7 @@ ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (struct.set $struct.A 0 ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (i32.const 1) ;; NOMNL-NEXT: ) @@ -1579,9 +1412,7 @@ (local $ref (ref null $struct.A)) (struct.set $struct.A 0 (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (i32.const 1) ) @@ -1593,9 +1424,7 @@ ;; CHECK-NEXT: (local $ref (ref null $struct.A)) ;; CHECK-NEXT: (struct.set $struct.A 0 ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) @@ -1607,9 +1436,7 @@ ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) ;; NOMNL-NEXT: (struct.set $struct.A 0 ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (i32.const 1) ;; NOMNL-NEXT: ) @@ -1621,9 +1448,7 @@ (local $ref (ref null $struct.A)) (struct.set $struct.A 0 (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (i32.const 1) ) @@ -1639,7 +1464,7 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block (result (ref $struct.A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.nonnullable)) + ;; CHECK-NEXT: (block (result (ref null $struct.nondefaultable)) ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: ) @@ -1648,10 +1473,7 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.nonnullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.nonnullable) + ;; CHECK-NEXT: (ref.null $struct.nondefaultable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.as_non_null @@ -1675,9 +1497,6 @@ ;; NOMNL-NEXT: (local.get $2) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.nonnullable) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.nonnullable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1692,9 +1511,8 @@ ;; An optimizable case where the type is non-nullable, which requires ;; special handling in locals. (struct.get $struct.nonnullable 0 - (struct.new_with_rtt $struct.nonnullable + (struct.new $struct.nonnullable (local.get $a) - (rtt.canon $struct.nonnullable) ) ) ) @@ -1721,9 +1539,6 @@ ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1818,9 +1633,6 @@ ;; NOMNL-NEXT: (local.set $3 ;; NOMNL-NEXT: (local.get $5) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1900,10 +1712,9 @@ ;; in various ways inside. (loop $outer (local.set $ref - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 2) (f64.const 2.1828) - (rtt.canon $struct.A) ) ) (drop @@ -1969,9 +1780,6 @@ ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1988,9 +1796,6 @@ ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2007,9 +1812,6 @@ ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2034,9 +1836,6 @@ ;; NOMNL-NEXT: (local.set $1 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2053,9 +1852,6 @@ ;; NOMNL-NEXT: (local.set $3 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2072,9 +1868,6 @@ ;; NOMNL-NEXT: (local.set $5 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2086,23 +1879,17 @@ ;; Multiple independent things we can optimize. (drop (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) (drop (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) (drop (struct.get $struct.A 1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) ) @@ -2121,9 +1908,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2143,9 +1927,6 @@ ;; CHECK-NEXT: (local.set $4 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2172,9 +1953,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2194,9 +1972,6 @@ ;; NOMNL-NEXT: (local.set $4 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2214,9 +1989,7 @@ ;; Multiple independent things we can optimize that use the same local ;; index, but they do not conflict in their live ranges. (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop (struct.get $struct.A 0 @@ -2224,9 +1997,7 @@ ) ) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop (struct.get $struct.A 0 @@ -2250,9 +2021,6 @@ ;; CHECK-NEXT: (local.set $3 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2264,9 +2032,6 @@ ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2302,9 +2067,6 @@ ;; NOMNL-NEXT: (local.set $3 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2316,9 +2078,6 @@ ;; NOMNL-NEXT: (local.set $5 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2345,14 +2104,10 @@ ;; Multiple independent things we can optimize that use different local ;; indexes, but whose lifetimes overlap. We should not be confused by that. (local.set $ref1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (local.set $ref2 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (drop (struct.get $struct.A 0 @@ -2369,9 +2124,7 @@ ;; CHECK: (func $get-through-block (result f64) ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.get $struct.A 1 ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) @@ -2388,9 +2141,7 @@ ;; NOMNL: (func $get-through-block (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (struct.get $struct.A 1 ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) @@ -2407,9 +2158,7 @@ (func $get-through-block (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2431,9 +2180,7 @@ ;; CHECK: (func $branch-to-block (result f64) ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.get $struct.A 1 ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) @@ -2450,9 +2197,7 @@ ;; NOMNL: (func $branch-to-block (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (struct.get $struct.A 1 ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) @@ -2469,9 +2214,7 @@ (func $branch-to-block (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2500,9 +2243,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2535,9 +2275,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2561,9 +2298,7 @@ (func $branch-to-block-no-fallthrough (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2584,9 +2319,7 @@ ;; CHECK: (func $two-branches (result f64) ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.get $struct.A 1 ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) @@ -2611,9 +2344,7 @@ ;; NOMNL: (func $two-branches (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (struct.get $struct.A 1 ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) @@ -2638,9 +2369,7 @@ (func $two-branches (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2666,9 +2395,7 @@ ;; CHECK: (func $two-branches-b (result f64) ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.get $struct.A 1 ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) @@ -2693,9 +2420,7 @@ ;; NOMNL: (func $two-branches-b (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (struct.get $struct.A 1 ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) @@ -2720,9 +2445,7 @@ (func $two-branches-b (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2749,9 +2472,7 @@ ;; CHECK: (func $br_if_flow (result f64) ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (struct.get $struct.A 1 ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) @@ -2770,9 +2491,7 @@ ;; NOMNL: (func $br_if_flow (type $none_=>_f64) (result f64) ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (struct.get $struct.A 1 ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) @@ -2791,9 +2510,7 @@ (func $br_if_flow (result f64) (local $0 (ref null $struct.A)) (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.get $struct.A 1 (block $block (result (ref null $struct.A)) @@ -2823,9 +2540,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2855,9 +2569,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2878,9 +2589,7 @@ (func $ref-as-non-null (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) (struct.set $struct.A 0 ;; We can see that the input to this RefAsNonNull is always non-null, as @@ -2911,9 +2620,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2939,9 +2645,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2958,9 +2661,7 @@ (func $ref-as-non-null-through-local (result i32) (local $ref (ref null $struct.A)) (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ;; Copy the allocation through a ref.as_non_null. This must not trap: it may ;; trap if we leave the ref.as_non_null there and also we do not assign @@ -3001,9 +2702,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) @@ -3039,9 +2737,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (local.get $4) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (i32.const 0) @@ -3062,10 +2757,9 @@ ;; Our allocation flows into a br_if, which therefore has non-nullable ;; type, which we must update after optimizing. (br_if $block - (struct.new_with_rtt $struct.A + (struct.new $struct.A (i32.const 42) (f64.const 13.37) - (rtt.canon $struct.A) ) (i32.const 0) ) @@ -3075,44 +2769,6 @@ ) ) - ;; CHECK: (func $simple-no-rtt - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $simple-no-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $simple-no-rtt - (drop - ;; This allocation has no rtt, so we have nothing to drop from it when - ;; we optimize. - (struct.new_default $struct.A) - ) - ) - ;; CHECK: (func $pass-through-loop ;; CHECK-NEXT: (local $0 (ref null $struct.A)) ;; CHECK-NEXT: (local $1 i32) @@ -3129,9 +2785,6 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3153,9 +2806,6 @@ ;; NOMNL-NEXT: (local.set $2 ;; NOMNL-NEXT: (f64.const 0) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $struct.A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -3172,9 +2822,7 @@ ;; block). (br_if $loop (i32.const 0)) ;; The allocation that will be turned into locals. - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) + (struct.new_default $struct.A) ) ) ) diff --git a/test/lit/passes/inlining-optimizing.wast b/test/lit/passes/inlining-optimizing.wast index ac29ba1f9..74748c6a4 100644 --- a/test/lit/passes/inlining-optimizing.wast +++ b/test/lit/passes/inlining-optimizing.wast @@ -30,12 +30,10 @@ (call $0) (drop (call_ref - (ref.cast + (ref.cast_static $none_=>_i32 (ref.func $0) - (rtt.canon $none_=>_i32) ) ) ) ) ) - diff --git a/test/lit/passes/inlining_all-features.wast b/test/lit/passes/inlining_all-features.wast index 051201b23..3b2f3a458 100644 --- a/test/lit/passes/inlining_all-features.wast +++ b/test/lit/passes/inlining_all-features.wast @@ -208,41 +208,3 @@ ) ) ) - -;; never inline an rtt parameter, as those cannot be handled as locals -(module - ;; CHECK: (type $struct (struct )) - ;; NOMNL: (type $struct (struct_subtype data)) - (type $struct (struct)) - ;; CHECK: (type $rtt_$struct_=>_none (func (param (rtt $struct)))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 (param $rtt (rtt $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (type $rtt_$struct_=>_none (func_subtype (param (rtt $struct)) func)) - - ;; NOMNL: (type $none_=>_none (func_subtype func)) - - ;; NOMNL: (func $0 (type $rtt_$struct_=>_none) (param $rtt (rtt $struct)) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $0 (param $rtt (rtt $struct)) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call $0 - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $none_=>_none) - ;; NOMNL-NEXT: (call $0 - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 - (call $0 - (rtt.canon $struct) - ) - ) -) diff --git a/test/lit/passes/inlining_splitting.wast b/test/lit/passes/inlining_splitting.wast index 599bb9cc6..678400c7f 100644 --- a/test/lit/passes/inlining_splitting.wast +++ b/test/lit/passes/inlining_splitting.wast @@ -14,8 +14,6 @@ ;; CHECK: (type $struct (struct )) (type $struct (struct)) - ;; CHECK: (type $i32_rtt_$struct_=>_none (func (param i32 (rtt $struct)))) - ;; CHECK: (type $i64_i32_f64_=>_none (func (param i64 i32 f64))) ;; CHECK: (import "out" "func" (func $import)) @@ -203,19 +201,8 @@ (call $br-to-toplevel (i32.const 2)) ) - ;; CHECK: (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) - ;; The RTT param here prevents us from even being inlined, even with - ;; splitting. + (func $nondefaultable-param (param $x i32) (param $y (ref $struct)) + ;; We can inline despite the non-initial, non-defaultable param. (if (local.get $x) (return) @@ -227,13 +214,30 @@ ) ;; CHECK: (func $call-nondefaultable-param - ;; CHECK-NEXT: (call $nondefaultable-param - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (rtt.canon $struct) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 (ref null $struct)) + ;; CHECK-NEXT: (block $__inlined_func$nondefaultable-param + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (struct.new_default $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (br $__inlined_func$nondefaultable-param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $__inlined_func$nondefaultable-param) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-nondefaultable-param - (call $nondefaultable-param (i32.const 0) (rtt.canon $struct)) + (call $nondefaultable-param (i32.const 0) (struct.new $struct)) ) (func $many-params (param $x i64) (param $y i32) (param $z f64) diff --git a/test/lit/passes/local-cse_all-features.wast b/test/lit/passes/local-cse_all-features.wast index 8ff3bc253..ff0a746d4 100644 --- a/test/lit/passes/local-cse_all-features.wast +++ b/test/lit/passes/local-cse_all-features.wast @@ -187,29 +187,25 @@ ;; CHECK: (func $creations ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $A + ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $A + ;; CHECK-NEXT: (struct.new $A ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.new_with_rtt $B + ;; CHECK-NEXT: (array.new $B ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $B) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.new_with_rtt $B + ;; CHECK-NEXT: (array.new $B ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $B) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -217,29 +213,25 @@ ;; Allocating GC data has no side effects, but each allocation is unique ;; and so we cannot replace separate allocations with a single one. (drop - (struct.new_with_rtt $A + (struct.new $A (i32.const 1) - (rtt.canon $A) ) ) (drop - (struct.new_with_rtt $A + (struct.new $A (i32.const 1) - (rtt.canon $A) ) ) (drop - (array.new_with_rtt $B + (array.new $B (i32.const 1) (i32.const 1) - (rtt.canon $B) ) ) (drop - (array.new_with_rtt $B + (array.new $B (i32.const 1) (i32.const 1) - (rtt.canon $B) ) ) ) diff --git a/test/lit/passes/optimize-instructions-call_ref.wast b/test/lit/passes/optimize-instructions-call_ref.wast index b92e976bb..c3a607d07 100644 --- a/test/lit/passes/optimize-instructions-call_ref.wast +++ b/test/lit/passes/optimize-instructions-call_ref.wast @@ -163,9 +163,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.func $return-nothing) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $none_=>_i32) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -178,9 +175,8 @@ ;; call_ref that returns nothing with a call that returns an i32. In fact, we ;; end up optimizing the cast into an unreachable. (call_ref - (ref.cast + (ref.cast_static $none_=>_i32 (ref.func $return-nothing) - (rtt.canon $none_=>_i32) ) ) ) diff --git a/test/lit/passes/optimize-instructions-gc-iit.wast b/test/lit/passes/optimize-instructions-gc-iit.wast index 4117dce19..3f0c926d3 100644 --- a/test/lit/passes/optimize-instructions-gc-iit.wast +++ b/test/lit/passes/optimize-instructions-gc-iit.wast @@ -33,107 +33,65 @@ (func $foo) - ;; CHECK: (func $ref-cast-iit (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) + ;; CHECK: (func $ref-cast-iit (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $parent)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $parent) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $child) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $child ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: (local.get $child-rtt) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $other)) + ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $child) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $other-rtt) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_rtt_$parent_rtt_$child_rtt_$other_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) + ;; NOMNL: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $parent)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $parent) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $child)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $child) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $child) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $child ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: (local.get $child-rtt) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $other)) + ;; NOMNL-NEXT: (block ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (local.get $child) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $other-rtt) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_rtt_$parent_rtt_$child_rtt_$other_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) + ;; NOMNL-TNH: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: ) + ;; NOMNL-TNH-NEXT: (local.get $parent) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $child)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (local.get $child) - ;; NOMNL-TNH-NEXT: ) + ;; NOMNL-TNH-NEXT: (local.get $child) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast + ;; NOMNL-TNH-NEXT: (ref.cast_static $child ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: (local.get $child-rtt) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $other)) + ;; NOMNL-TNH-NEXT: (block ;; NOMNL-TNH-NEXT: (drop ;; NOMNL-TNH-NEXT: (local.get $child) ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $other-rtt) - ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: (unreachable) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: ) @@ -143,174 +101,91 @@ (param $child (ref $child)) (param $other (ref $other)) - (param $parent-rtt (rtt $parent)) - (param $child-rtt (rtt $child)) - (param $other-rtt (rtt $other)) - - ;; a cast of parent to an rtt of parent: assuming no traps as we do, we can - ;; optimize this as the new type will be valid. + ;; a cast of parent to parent. We can optimize this as the new type will be + ;; valid. (drop - (ref.cast + (ref.cast_static $parent (local.get $parent) - (local.get $parent-rtt) ) ) ;; a cast of child to a supertype: again, we replace with a valid type. (drop - (ref.cast + (ref.cast_static $parent (local.get $child) - (local.get $parent-rtt) ) ) ;; a cast of parent to a subtype: we cannot replace the original heap type ;; $child with one that is not equal or more specific, like $parent, so we ;; cannot optimize here. (drop - (ref.cast + (ref.cast_static $child (local.get $parent) - (local.get $child-rtt) ) ) ;; a cast of child to an unrelated type: it will trap anyhow (drop - (ref.cast + (ref.cast_static $other (local.get $child) - (local.get $other-rtt) ) ) ) - ;; CHECK: (func $ref-cast-iit-bad (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; CHECK-NEXT: (local $2 (ref null $parent)) + ;; CHECK: (func $ref-cast-iit-bad (param $parent (ref $parent)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $parent)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $block (result (ref $parent)) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block0 (result (rtt $parent)) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (block $block (result (ref $parent)) + ;; CHECK-NEXT: (call $foo) ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $parent ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.get $parent-rtt) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-iit-bad (type $ref|$parent|_rtt_$parent_=>_none) (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; NOMNL-NEXT: (local $2 (ref null $parent)) + ;; NOMNL: (func $ref-cast-iit-bad (type $ref|$parent|_=>_none) (param $parent (ref $parent)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $parent)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (block $block (result (ref $parent)) - ;; NOMNL-NEXT: (call $foo) - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block $block0 (result (rtt $parent)) - ;; NOMNL-NEXT: (call $foo) - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (block $block (result (ref $parent)) + ;; NOMNL-NEXT: (call $foo) ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $parent ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: (local.get $parent-rtt) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $ref-cast-iit-bad (type $ref|$parent|_rtt_$parent_=>_none) (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; NOMNL-TNH-NEXT: (local $2 (ref null $parent)) + ;; NOMNL-TNH: (func $ref-cast-iit-bad (type $ref|$parent|_=>_none) (param $parent (ref $parent)) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (local.set $2 - ;; NOMNL-TNH-NEXT: (block $block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (call $foo) - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block $block0 (result (rtt $parent)) - ;; NOMNL-TNH-NEXT: (call $foo) - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (ref.as_non_null - ;; NOMNL-TNH-NEXT: (local.get $2) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast + ;; NOMNL-TNH-NEXT: (block $block (result (ref $parent)) + ;; NOMNL-TNH-NEXT: (call $foo) ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: (unreachable) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast + ;; NOMNL-TNH-NEXT: (ref.cast_static $parent ;; NOMNL-TNH-NEXT: (unreachable) - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: ) ;; NOMNL-TNH-NEXT: ) (func $ref-cast-iit-bad (param $parent (ref $parent)) - (param $parent-rtt (rtt $parent)) ;; optimizing this cast away requires reordering. (drop - (ref.cast + (ref.cast_static $parent (block (result (ref $parent)) (call $foo) (local.get $parent) ) - (block (result (rtt $parent)) - (call $foo) - (local.get $parent-rtt) - ) ) ) ;; ignore unreachability (drop - (ref.cast - (local.get $parent) - (unreachable) - ) - ) - (drop - (ref.cast + (ref.cast_static $parent (unreachable) - (local.get $parent-rtt) ) ) ) @@ -335,9 +210,8 @@ (drop (ref.eq (local.get $x) - (ref.cast + (ref.cast_static $parent (local.get $x) - (rtt.canon $parent) ) ) ) diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index f53237f02..f6a1b5d09 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -18,24 +18,26 @@ ;; NOMNL: (type $A (struct_subtype (field i32) data)) (type $A (struct (field i32))) + ;; CHECK: (type $B (struct (field i32) (field i32) (field f32))) + ;; CHECK: (type $array (array (mut i8))) + ;; NOMNL: (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) + ;; NOMNL: (type $array (array_subtype (mut i8) data)) (type $array (array (mut i8))) - ;; CHECK: (type $B (struct (field i32) (field i32) (field f32))) - ;; NOMNL: (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) ;; CHECK: (type $B-child (struct (field i32) (field i32) (field f32) (field i64))) ;; NOMNL: (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) - ;; CHECK: (type $empty (struct )) + ;; NOMNL: (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) + ;; NOMNL: (type $empty (struct_subtype data)) (type $empty (struct)) ;; CHECK: (type $C (struct (field i32) (field i32) (field f64))) - ;; NOMNL: (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) ;; CHECK: (import "env" "get-i32" (func $get-i32 (result i32))) @@ -966,12 +968,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $struct) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -1003,12 +1001,8 @@ ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $struct) + ;; NOMNL-NEXT: (struct.new_default $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop @@ -1042,12 +1036,8 @@ ;; allocation prevents optimization (drop (ref.eq - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) + (struct.new_default $struct) ) ) ;; but irrelevant allocations do not prevent optimization @@ -1056,17 +1046,13 @@ (block (result eqref) ;; an allocation that does not trouble us (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) (local.get $x) ) (block (result eqref) (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; add a nop to make the two inputs to ref.eq not structurally equal, ;; but in a way that does not matter (since only the value falling @@ -1091,9 +1077,8 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.eq ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1102,9 +1087,8 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (ref.eq ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1115,9 +1099,8 @@ (drop (ref.eq (local.get $x) - (ref.cast + (ref.cast_static $struct (local.get $x) - (rtt.canon $struct) ) ) ) @@ -1126,132 +1109,117 @@ ;; CHECK: (func $flip-cast-of-as-non-null (param $x anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (ref.as_func ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (ref.as_data ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (ref.as_i31 ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $flip-cast-of-as-non-null (type $anyref_=>_none) (param $x anyref) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (ref.as_func ;; NOMNL-NEXT: (local.get $x) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (ref.as_data ;; NOMNL-NEXT: (local.get $x) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (ref.as_i31 ;; NOMNL-NEXT: (local.get $x) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $flip-cast-of-as-non-null (param $x anyref) (drop - (ref.cast + (ref.cast_static $struct ;; this can be moved through the ref.cast outward. (ref.as_non_null (local.get $x) ) - (rtt.canon $struct) ) ) (drop ;; an example of how this helps: the struct.get will trap on null anyhow (struct.get_u $struct 0 - (ref.cast + (ref.cast_static $struct ;; this can be moved through the ref.cast outward. (ref.as_non_null (local.get $x) ) - (rtt.canon $struct) ) ) ) ;; other ref.as* operations are ignored for now (drop - (ref.cast + (ref.cast_static $struct (ref.as_func (local.get $x) ) - (rtt.canon $struct) ) ) (drop - (ref.cast + (ref.cast_static $struct (ref.as_data (local.get $x) ) - (rtt.canon $struct) ) ) (drop - (ref.cast + (ref.cast_static $struct (ref.as_i31 (local.get $x) ) - (rtt.canon $struct) ) ) ) @@ -1461,48 +1429,46 @@ ;; CHECK: (func $ref-cast-squared (param $x eqref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $ref-cast-squared (type $eqref_=>_none) (param $x eqref) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $ref-cast-squared (param $x eqref) ;; Identical ref.casts can be folded together. (drop - (ref.cast - (ref.cast + (ref.cast_static $struct + (ref.cast_static $struct (local.get $x) - (rtt.canon $struct) ) - (rtt.canon $struct) ) ) ) ;; CHECK: (func $ref-cast-squared-fallthrough (param $x eqref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) + ;; CHECK-NEXT: (ref.cast_static $struct + ;; CHECK-NEXT: (local.tee $x + ;; CHECK-NEXT: (ref.cast_static $struct + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $ref-cast-squared-fallthrough (type $eqref_=>_none) (param $x eqref) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.tee $x - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: (ref.cast_static $struct + ;; NOMNL-NEXT: (local.tee $x + ;; NOMNL-NEXT: (ref.cast_static $struct + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -1510,128 +1476,68 @@ (func $ref-cast-squared-fallthrough (param $x eqref) ;; A fallthrough in the middle does not prevent this optimization. (drop - (ref.cast + (ref.cast_static $struct (local.tee $x - (ref.cast + (ref.cast_static $struct (local.get $x) - (rtt.canon $struct) ) ) - (rtt.canon $struct) ) ) ) ;; CHECK: (func $ref-cast-cubed (param $x eqref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $ref-cast-cubed (type $eqref_=>_none) (param $x eqref) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $ref-cast-cubed (param $x eqref) ;; Three and more also work. (drop - (ref.cast - (ref.cast - (ref.cast + (ref.cast_static $struct + (ref.cast_static $struct + (ref.cast_static $struct (local.get $x) - (rtt.canon $struct) ) - (rtt.canon $struct) ) - (rtt.canon $struct) ) ) ) ;; CHECK: (func $ref-cast-squared-different (param $x eqref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) + ;; CHECK-NEXT: (ref.cast_static $struct + ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $ref-cast-squared-different (type $eqref_=>_none) (param $x eqref) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct + ;; NOMNL-NEXT: (ref.cast_static $empty ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $empty) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $ref-cast-squared-different (param $x eqref) ;; Different casts cannot be folded. (drop - (ref.cast - (ref.cast - (local.get $x) - (rtt.canon $empty) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $ref-cast-squared-effects (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $get-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $get-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-squared-effects (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $get-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $get-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-squared-effects (param $x eqref) - ;; The rtts are equal but have side effects, preventing optimization. - (drop - (ref.cast - (ref.cast + (ref.cast_static $struct + (ref.cast_static $empty (local.get $x) - (call $get-rtt) ) - (call $get-rtt) ) ) ) - ;; Helper function for above. - ;; CHECK: (func $get-rtt (result (rtt $empty)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-rtt (type $none_=>_rtt_$empty) (result (rtt $empty)) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get-rtt (result (rtt $empty)) - (unreachable) - ) - ;; CHECK: (func $ref-eq-null (param $x eqref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.is_null @@ -2024,9 +1930,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2037,18 +1940,14 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (local.get $struct) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $incompatible-cast-of-non-null (param $struct (ref $struct)) (drop - (ref.cast + (ref.cast_static $array (local.get $struct) - (rtt.canon $array) ) ) ) @@ -2059,9 +1958,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.null $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $array) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2073,9 +1969,6 @@ ;; CHECK-NEXT: (ref.null $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null $array) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2087,9 +1980,6 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (ref.null $struct) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $array) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2101,9 +1991,6 @@ ;; NOMNL-NEXT: (ref.null $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (ref.null $array) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2111,45 +1998,40 @@ ;; NOMNL-NEXT: ) (func $incompatible-cast-of-null (drop - (ref.cast + (ref.cast_static $array (ref.null $struct) - (rtt.canon $array) ) ) (drop - (ref.cast + (ref.cast_static $array ;; The fallthrough is null, but the node's child's type is non-nullable, ;; so we must add a ref.as_non_null on the outside to keep the type ;; identical. (ref.as_non_null (ref.null $struct) ) - (rtt.canon $array) ) ) ) ;; CHECK: (func $incompatible-cast-of-unknown (param $struct (ref null $struct)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $array ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (rtt.canon $array) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $incompatible-cast-of-unknown (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $array ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: (rtt.canon $array) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $incompatible-cast-of-unknown (param $struct (ref null $struct)) (drop - (ref.cast + (ref.cast_static $array (local.get $struct) - (rtt.canon $array) ) ) ) @@ -2160,9 +2042,6 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $struct) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2173,9 +2052,6 @@ ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (local.get $struct) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (i32.const 0) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2183,70 +2059,61 @@ (func $incompatible-test (param $struct (ref null $struct)) (drop ;; This test will definitely fail, so we can turn it into 0. - (ref.test + (ref.test_static $array (local.get $struct) - (rtt.canon $array) ) ) ) ;; CHECK: (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test + ;; CHECK-NEXT: (ref.test_static $B ;; CHECK-NEXT: (local.get $A) - ;; CHECK-NEXT: (rtt.canon $B) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test + ;; CHECK-NEXT: (ref.test_static $A ;; CHECK-NEXT: (local.get $B) - ;; CHECK-NEXT: (rtt.canon $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $subtype-compatible (type $ref?|$A|_ref?|$B|_=>_none) (param $A (ref null $A)) (param $B (ref null $B)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test + ;; NOMNL-NEXT: (ref.test_static $B ;; NOMNL-NEXT: (local.get $A) - ;; NOMNL-NEXT: (rtt.canon $B) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test + ;; NOMNL-NEXT: (ref.test_static $A ;; NOMNL-NEXT: (local.get $B) - ;; NOMNL-NEXT: (rtt.canon $A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B)) (drop ;; B is a subtype of A, so this can work. - (ref.test + (ref.test_static $B (local.get $A) - (rtt.canon $B) ) ) (drop ;; The other direction works too. - (ref.test + (ref.test_static $A (local.get $B) - (rtt.canon $A) ) ) ) ;; CHECK: (func $ref.test-unreachable (param $A (ref null $A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test + ;; CHECK-NEXT: (ref.test_static $A ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (rtt.canon $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $ref.test-unreachable (type $ref?|$A|_=>_none) (param $A (ref null $A)) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test + ;; NOMNL-NEXT: (ref.test_static $A ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: (rtt.canon $A) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -2254,42 +2121,39 @@ (drop ;; We should ignore unreachable ref.tests and not try to compare their ;; HeapTypes. - (ref.test + (ref.test_static $A (unreachable) - (rtt.canon $A) ) ) ) ;; CHECK: (func $consecutive-opts-with-unreachable (param $func funcref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $struct ;; CHECK-NEXT: (block (result dataref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $func) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $consecutive-opts-with-unreachable (type $funcref_=>_none) (param $func funcref) ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $struct ;; NOMNL-NEXT: (block (result dataref) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (local.get $func) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $consecutive-opts-with-unreachable (param $func funcref) (drop - (ref.cast + (ref.cast_static $struct ;; Casting a funcref to data will definitely fail, so this will be ;; replaced with an unreachable. But it should be enclosed in a block of ;; the previous type, so that the outside ref.cast is not confused. This @@ -2302,7 +2166,6 @@ (ref.as_data (local.get $func) ) - (rtt.canon $struct) ) ) ) diff --git a/test/lit/passes/optimize-instructions-iit-eh.wast b/test/lit/passes/optimize-instructions-iit-eh.wast index b297cb7df..ee6b78738 100644 --- a/test/lit/passes/optimize-instructions-iit-eh.wast +++ b/test/lit/passes/optimize-instructions-iit-eh.wast @@ -5,33 +5,17 @@ (module ;; CHECK: (type $struct.A (struct (field i32))) (type $struct.A (struct i32)) - ;; CHECK: (global $g-struct.A (rtt $struct.A) (rtt.canon $struct.A)) - ;; CHECK: (tag $e (param (ref null $struct.A))) (tag $e (param (ref null $struct.A))) - (global $g-struct.A (rtt $struct.A) (rtt.canon $struct.A)) ;; CHECK: (func $ref-cast-statically-removed - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 (ref null $struct.A)) ;; CHECK-NEXT: (try $try ;; CHECK-NEXT: (do ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop (ref null $struct.A)) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $g-struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (pop (ref null $struct.A)) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -41,15 +25,14 @@ (do) (catch $e (throw $e - ;; Because --ignore-implicit-traps is given, this ref.cast is assumed - ;; not to throw so this ref.cast can be statically removed. But that - ;; creates a block around this, making 'pop' nested into it, which is - ;; invalid. We fix this up at the end up OptimizeInstruction, + ;; Because --ignore-implicit-traps is given, this ref.cast_static is + ;; assumed not to throw so this ref.cast can be statically removed. + ;; But that creates a block around this, making 'pop' nested into it, + ;; which is invalid. We fix this up at the end up OptimizeInstruction, ;; assigning the 'pop' to a local at the start of this 'catch' body ;; and later using 'local.get' to get it. - (ref.cast + (ref.cast_static $struct.A (pop (ref null $struct.A)) - (global.get $g-struct.A) ) ) ) diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast index 14347bd3c..161b1fe07 100644 --- a/test/lit/passes/precompute-gc.wast +++ b/test/lit/passes/precompute-gc.wast @@ -74,9 +74,8 @@ ;; CHECK: (func $load-from-struct ;; CHECK-NEXT: (local $x (ref null $struct)) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $log @@ -85,9 +84,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $log @@ -108,9 +106,8 @@ ;; NOMNL: (func $load-from-struct (type $none_=>_none) ;; NOMNL-NEXT: (local $x (ref null $struct)) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (call $log @@ -119,9 +116,8 @@ ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (call $log @@ -142,9 +138,8 @@ (func $load-from-struct (local $x (ref null $struct)) (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 1) - (rtt.canon $struct) ) ) ;; we don't precompute these, as we don't know if the GC data was modified @@ -154,9 +149,8 @@ ) ;; Assign a new struct (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 2) - (rtt.canon $struct) ) ) (call $log @@ -176,15 +170,13 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $i) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -199,15 +191,13 @@ ;; NOMNL-NEXT: (if ;; NOMNL-NEXT: (local.get $i) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -223,15 +213,13 @@ (if (local.get $i) (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 1) - (rtt.canon $struct) ) ) (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 2) - (rtt.canon $struct) ) ) ) @@ -277,9 +265,8 @@ ;; CHECK: (func $load-from-struct-bad-escape ;; CHECK-NEXT: (local $x (ref null $struct)) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $modify-gc-heap @@ -294,9 +281,8 @@ ;; NOMNL: (func $load-from-struct-bad-escape (type $none_=>_none) ;; NOMNL-NEXT: (local $x (ref null $struct)) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (call $modify-gc-heap @@ -311,9 +297,8 @@ (func $load-from-struct-bad-escape (export "test") (local $x (ref null $struct)) (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 1) - (rtt.canon $struct) ) ) (call $modify-gc-heap @@ -431,9 +416,8 @@ ;; CHECK-NEXT: (local $y (ref null $struct)) ;; CHECK-NEXT: (local $tempresult i32) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct + ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $y @@ -449,9 +433,8 @@ ;; NOMNL-NEXT: (local $y (ref null $struct)) ;; NOMNL-NEXT: (local $tempresult i32) ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (struct.new $struct ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $y @@ -467,9 +450,8 @@ (local $y (ref null $struct)) (local $tempresult i32) (local.set $x - (struct.new_with_rtt $struct + (struct.new $struct (i32.const 1) - (rtt.canon $struct) ) ) (local.set $y @@ -492,9 +474,7 @@ ;; CHECK-NEXT: (local.set $tempresult ;; CHECK-NEXT: (ref.eq ;; CHECK-NEXT: (local.tee $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $tempref) ;; CHECK-NEXT: ) @@ -507,9 +487,7 @@ ;; NOMNL-NEXT: (local.set $tempresult ;; NOMNL-NEXT: (ref.eq ;; NOMNL-NEXT: (local.tee $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.get $tempref) ;; NOMNL-NEXT: ) @@ -524,9 +502,7 @@ (ref.eq ;; allocate one struct (local.tee $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (local.get $tempref) ) @@ -561,12 +537,8 @@ (local.set $tempresult ;; allocate two different structs (ref.eq - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) + (struct.new $empty) ) ) (local.get $tempresult) @@ -577,9 +549,7 @@ ;; CHECK-NEXT: (local $tempref (ref null $empty)) ;; CHECK-NEXT: (local.set $tempresult ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: (local.get $input) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -590,9 +560,7 @@ ;; NOMNL-NEXT: (local $tempref (ref null $empty)) ;; NOMNL-NEXT: (local.set $tempresult ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: (local.get $input) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) @@ -605,9 +573,7 @@ ;; allocate a struct and compare it to a param, which we know nothing about, ;; so we can infer nothing here at all. (ref.eq - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) (local.get $input) ) ) @@ -684,9 +650,7 @@ ;; CHECK-NEXT: (local $tempref (ref null $empty)) ;; CHECK-NEXT: (local $stashedref (ref null $empty)) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $stashedref ;; CHECK-NEXT: (local.get $tempref) @@ -696,9 +660,7 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $tempresult @@ -714,9 +676,7 @@ ;; NOMNL-NEXT: (local $tempref (ref null $empty)) ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $stashedref ;; NOMNL-NEXT: (local.get $tempref) @@ -726,9 +686,7 @@ ;; NOMNL-NEXT: (i32.const 0) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $tempresult @@ -744,9 +702,7 @@ (local $tempref (ref null $empty)) (local $stashedref (ref null $empty)) (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (local.set $stashedref (local.get $tempref) @@ -758,9 +714,7 @@ (i32.const 0) ) (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) ) (local.set $tempresult @@ -777,9 +731,7 @@ ;; CHECK-NEXT: (local $tempref (ref null $empty)) ;; CHECK-NEXT: (local $stashedref (ref null $empty)) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $stashedref ;; CHECK-NEXT: (local.get $tempref) @@ -792,9 +744,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $loop ;; CHECK-NEXT: (call $helper @@ -808,9 +758,7 @@ ;; NOMNL-NEXT: (local $tempref (ref null $empty)) ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $stashedref ;; NOMNL-NEXT: (local.get $tempref) @@ -823,9 +771,7 @@ ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (br_if $loop ;; NOMNL-NEXT: (call $helper @@ -839,9 +785,7 @@ (local $tempref (ref null $empty)) (local $stashedref (ref null $empty)) (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (local.set $stashedref (local.get $tempref) @@ -856,9 +800,7 @@ ) ) (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (br_if $loop (call $helper @@ -873,9 +815,7 @@ ;; CHECK-NEXT: (local $tempref (ref null $empty)) ;; CHECK-NEXT: (local $stashedref (ref null $empty)) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $stashedref ;; CHECK-NEXT: (local.get $tempref) @@ -896,9 +836,7 @@ ;; NOMNL-NEXT: (local $tempref (ref null $empty)) ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $stashedref ;; NOMNL-NEXT: (local.get $tempref) @@ -921,9 +859,7 @@ ;; As above, but remove the new in the loop, so that each loop iteration does ;; in fact have the ref locals identical, and we can precompute a 1. (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (local.set $stashedref (local.get $tempref) @@ -949,9 +885,7 @@ ;; CHECK-NEXT: (local $stashedref (ref null $empty)) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $stashedref ;; CHECK-NEXT: (local.get $tempref) @@ -972,9 +906,7 @@ ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) ;; NOMNL-NEXT: (loop $loop ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $stashedref ;; NOMNL-NEXT: (local.get $tempref) @@ -997,9 +929,7 @@ ;; Another example of a loop where we can optimize. Here the new is inside ;; the loop. (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) (local.set $stashedref (local.get $tempref) @@ -1028,9 +958,7 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (struct.new_default $empty) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $stashedref @@ -1059,9 +987,7 @@ ;; NOMNL-NEXT: (i32.const 0) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default $empty) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (local.set $stashedref @@ -1094,9 +1020,7 @@ (i32.const 0) ) (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) + (struct.new $empty) ) ) (local.set $stashedref @@ -1155,9 +1079,8 @@ ;; ref.cast instruction has, that is, the value is a null of type $B). So this ;; is an odd cast that "works". (local.set $temp - (ref.cast + (ref.cast_static $B (ref.null $A) - (rtt.canon $B) ) ) (drop @@ -1202,9 +1125,8 @@ ;; As above, but with a tuple. (local.set $temp (tuple.make - (ref.cast + (ref.cast_static $B (ref.null $A) - (rtt.canon $B) ) (i32.const 10) ) @@ -1230,9 +1152,8 @@ ;; CHECK: (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.cast + ;; CHECK-NEXT: (ref.cast_static $func-return-i32 ;; CHECK-NEXT: (ref.func $receive-f64) - ;; CHECK-NEXT: (rtt.canon $func-return-i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -1243,9 +1164,8 @@ ;; CHECK-NEXT: ) ;; NOMNL: (func $odd-cast-and-get-non-null (type $ref|$func-return-i32|_=>_none) (param $temp (ref $func-return-i32)) ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.cast_static $func-return-i32 ;; NOMNL-NEXT: (ref.func $receive-f64) - ;; NOMNL-NEXT: (rtt.canon $func-return-i32) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop @@ -1257,9 +1177,8 @@ (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) ;; Try to cast a function to an incompatible type. (local.set $temp - (ref.cast + (ref.cast_static $func-return-i32 (ref.func $receive-f64) - (rtt.canon $func-return-i32) ) ) (drop @@ -1271,51 +1190,6 @@ ) ) - ;; Regression test checking that breaking RTTs are interpreted correctly. - ;; CHECK: (func $cast-breaking-rtt - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (call $unreachable-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $unreachable-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $cast-breaking-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (struct.new_default $struct) - ;; NOMNL-NEXT: (call $unreachable-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $unreachable-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $cast-breaking-rtt - (drop - (ref.cast - (ref.cast - (struct.new_default $struct) - (call $unreachable-rtt) - ) - (call $unreachable-rtt) - ) - ) - ) - - ;; CHECK: (func $unreachable-rtt (result (rtt $struct)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unreachable-rtt (type $none_=>_rtt_$struct) (result (rtt $struct)) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $unreachable-rtt (result (rtt $struct)) - (unreachable) - ) - ;; CHECK: (func $new_block_unreachable (result anyref) ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) ;; CHECK-NEXT: (drop @@ -1323,9 +1197,6 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; NOMNL: (func $new_block_unreachable (type $none_=>_anyref) (result anyref) @@ -1335,67 +1206,20 @@ ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) (func $new_block_unreachable (result anyref) - (struct.new_with_rtt $struct + (struct.new $struct ;; The value is a block with an unreachable. precompute will get rid of the ;; block, after which fuzz-exec should not crash - this is a regression test ;; for us being careful in how we execute an unreachable struct.new (block $label$1 (result i32) (unreachable) ) - (rtt.canon $struct) - ) - ) - - ;; CHECK: (func $br_on_cast-on-creation-rtt (result (ref $empty)) - ;; CHECK-NEXT: (block $label (result (ref $empty)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $label - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_on_cast-on-creation-rtt (type $none_=>_ref|$empty|) (result (ref $empty)) - ;; NOMNL-NEXT: (block $label (result (ref $empty)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_on_cast $label - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $br_on_cast-on-creation-rtt (result (ref $empty)) - (block $label (result (ref $empty)) - (drop - ;; The br_on_cast will read the GC data created from struct.new, which must - ;; emit it properly, including with an RTT which it will read from (since - ;; this instructions uses an RTT). - (br_on_cast $label - (struct.new_default_with_rtt $empty - (rtt.canon $empty) - ) - (rtt.canon $empty) - ) - ) - (unreachable) ) ) - ;; CHECK: (func $br_on_cast-on-creation-nortt (result (ref $empty)) + ;; CHECK: (func $br_on_cast-on-creation (result (ref $empty)) ;; CHECK-NEXT: (block $label (result (ref $empty)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (br_on_cast_static $label $empty @@ -1405,7 +1229,7 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_on_cast-on-creation-nortt (type $none_=>_ref|$empty|) (result (ref $empty)) + ;; NOMNL: (func $br_on_cast-on-creation (type $none_=>_ref|$empty|) (result (ref $empty)) ;; NOMNL-NEXT: (block $label (result (ref $empty)) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (br_on_cast_static $label $empty @@ -1415,10 +1239,9 @@ ;; NOMNL-NEXT: (unreachable) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) - (func $br_on_cast-on-creation-nortt (result (ref $empty)) + (func $br_on_cast-on-creation (result (ref $empty)) (block $label (result (ref $empty)) (drop - ;; As above, but with no RTTs. (br_on_cast_static $label $empty (struct.new_default $empty) ) diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast index 33aa08af5..eb5baa846 100644 --- a/test/lit/passes/remove-unused-brs-gc.wast +++ b/test/lit/passes/remove-unused-brs-gc.wast @@ -184,38 +184,6 @@ ) ) - ;; CHECK: (func $br_on_cast_dynamic (result (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (block $block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $block - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_cast_dynamic (result (ref $struct)) - (local $temp (ref null $struct)) - (block $block (result (ref $struct)) - (drop - ;; This dynamic cast happens to be optimizable since we see both sides use - ;; rtt.canon, but we do not inspect things that closely, and leave such - ;; dynamic casts to runtime. - (br_on_cast $block - (struct.new_with_rtt $struct - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - ) - (unreachable) - ) - ) - ;; CHECK: (func $casts-are-costly (param $x i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (if (result i32) diff --git a/test/lit/passes/roundtrip-gc-types.wast b/test/lit/passes/roundtrip-gc-types.wast index 24d0ef40c..acbfea3a8 100644 --- a/test/lit/passes/roundtrip-gc-types.wast +++ b/test/lit/passes/roundtrip-gc-types.wast @@ -10,29 +10,24 @@ ;; CHECK: (type $A (struct (field (ref $C)))) ;; NOMNL: (type $A (struct_subtype (field (ref $C)) data)) (type $A (struct (field (ref $C)))) - ;; CHECK: (type $D (struct (field (ref $C)) (field (ref $A)))) - ;; CHECK: (type $C (struct (field (mut (ref $B))))) ;; CHECK: (type $B (func (param (ref $A)) (result (ref $B)))) - ;; NOMNL: (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) - ;; NOMNL: (type $C (struct_subtype (field (mut (ref $B))) data)) ;; NOMNL: (type $B (func_subtype (param (ref $A)) (result (ref $B)) func)) (type $B (func (param (ref $A)) (result (ref $B)))) (type $C (struct (field (mut (ref $B))))) + ;; CHECK: (type $D (struct (field (ref $C)) (field (ref $A)))) + ;; NOMNL: (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) - ;; CHECK: (global $g0 (rtt 0 $A) (rtt.canon $A)) - ;; NOMNL: (global $g0 (rtt 0 $A) (rtt.canon $A)) - (global $g0 (rtt 0 $A) (rtt.canon $A)) - ;; CHECK: (global $g1 (rtt 1 $D) (rtt.sub $D - ;; CHECK-NEXT: (global.get $g0) - ;; CHECK-NEXT: )) - ;; NOMNL: (global $g1 (rtt 1 $D) (rtt.sub $D - ;; NOMNL-NEXT: (global.get $g0) - ;; NOMNL-NEXT: )) - (global $g1 (rtt 1 $D) (rtt.sub $D - (global.get $g0) - )) + ;; CHECK: (func $use-types (param $0 (ref $A)) (param $1 (ref $D)) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; NOMNL: (func $use-types (type $ref|$A|_ref|$D|_=>_none) (param $0 (ref $A)) (param $1 (ref $D)) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) + (func $use-types (param (ref $A) (ref $D)) + (nop) + ) ) diff --git a/test/lit/passes/roundtrip-gc.wast b/test/lit/passes/roundtrip-gc.wast index 2fb5d57b2..cc38de819 100644 --- a/test/lit/passes/roundtrip-gc.wast +++ b/test/lit/passes/roundtrip-gc.wast @@ -9,7 +9,7 @@ (export "export" (func $test)) ;; CHECK: (func $test ;; CHECK-NEXT: (call $help - ;; CHECK-NEXT: (rtt.canon $\7bi32\7d) + ;; CHECK-NEXT: (struct.new_default $\7bi32\7d) ;; CHECK-NEXT: (block $label$1 (result i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (i32.const 1) @@ -18,7 +18,7 @@ ;; CHECK-NEXT: ) ;; NOMNL: (func $test (type $none_=>_none) ;; NOMNL-NEXT: (call $help - ;; NOMNL-NEXT: (rtt.canon $\7bi32\7d) + ;; NOMNL-NEXT: (struct.new_default $\7bi32\7d) ;; NOMNL-NEXT: (block $label$1 (result i32) ;; NOMNL-NEXT: (nop) ;; NOMNL-NEXT: (i32.const 1) @@ -27,25 +27,27 @@ ;; NOMNL-NEXT: ) (func $test (call $help - (rtt.canon ${i32}) + (struct.new_default ${i32}) ;; Stack IR optimizations can remove this block, leaving a nop in an odd ;; "stacky" location. On load, we would normally use a local to work around - ;; that, creating a block to contain the rtt before us and the nop, and then - ;; returning the local. But we can't use a local for an rtt, so we should not - ;; optimize this sort of thing in stack IR. + ;; that, creating a block to contain the non-nullable reference before us and + ;; the nop, and then returning the local. But we can't use a local for a + ;; non-nullable reference, so we should not optimize this sort of thing in + ;; stack IR. + ;; TODO: This shouldn't be true after #4824 is resolved. (block (result i32) (nop) (i32.const 1) ) ) ) - ;; CHECK: (func $help (param $3 (rtt $\7bi32\7d)) (param $4 i32) + ;; CHECK: (func $help (param $3 (ref $\7bi32\7d)) (param $4 i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - ;; NOMNL: (func $help (type $rtt_$\7bi32\7d_i32_=>_none) (param $3 (rtt $\7bi32\7d)) (param $4 i32) + ;; NOMNL: (func $help (type $ref|$\7bi32\7d|_i32_=>_none) (param $3 (ref $\7bi32\7d)) (param $4 i32) ;; NOMNL-NEXT: (nop) ;; NOMNL-NEXT: ) - (func $help (param $3 (rtt ${i32})) (param $4 i32) + (func $help (param $3 (ref ${i32})) (param $4 i32) (nop) ) ) diff --git a/test/lit/passes/vacuum-gc.wast b/test/lit/passes/vacuum-gc.wast index 71f0e39c2..57b298443 100644 --- a/test/lit/passes/vacuum-gc.wast +++ b/test/lit/passes/vacuum-gc.wast @@ -51,39 +51,31 @@ ) ) - ;; CHECK: (func $vacuum-rtt-with-depth + ;; CHECK: (func $vacuum-nonnull ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - (func $vacuum-rtt-with-depth + (func $vacuum-nonnull (drop - (if (result (rtt 1 ${})) + (if (result (ref ${})) (i32.const 1) ;; This block's result is not used. As a consequence vacuum will try to - ;; generate a replacement zero for the block's fallthrough value. An rtt - ;; with depth is a problem for that, since we can't just create an - ;; rtt.canon - we'd need to add some rtt.subs, and it's not clear that we'd - ;; be improving code size while doing so, hence we do not allow making a - ;; zero of that type. Vacuum should not error on trying to do so. And - ;; the end result of this function should simply be empty, as everything - ;; here can be vacuumed away. - (block (result (rtt 1 ${})) - (rtt.sub ${} - (rtt.canon ${}) - ) + ;; generate a replacement zero for the block's fallthrough value. A + ;; non-nullable reference is a problem for that, since we don't want to + ;; synthesize and allocate a new struct value. Vacuum should not error + ;; on this case, though. Instead, the end result of this function should + ;; simply be empty, as everything here can be vacuumed away. + (block (result (ref ${})) + (struct.new ${}) ) (unreachable) ) ) ) - ;; CHECK: (func $drop-i31.get (param $ref (ref null i31)) (param $ref-nn i31ref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i31.get_s - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK: (func $drop-i31.get (param $ref i31ref) (param $ref-nn i31ref) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - (func $drop-i31.get (param $ref (ref null i31)) (param $ref-nn (ref i31)) + (func $drop-i31.get (param $ref i31ref) (param $ref-nn (ref i31)) ;; A nullable get might trap, so only the second item can be removed. (drop (i31.get_s diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt index 14ef78a8c..410bf37c1 100644 --- a/test/passes/Oz_fuzz-exec_all-features.txt +++ b/test/passes/Oz_fuzz-exec_all-features.txt @@ -9,18 +9,8 @@ [LoggingExternalInterface logging 128] [LoggingExternalInterface logging -128] [LoggingExternalInterface logging 42] -[fuzz-exec] calling rtts -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] [fuzz-exec] calling br_on_cast [LoggingExternalInterface logging 3] -[trap unreachable] [fuzz-exec] calling br_on_failed_cast-1 [LoggingExternalInterface logging 1] [fuzz-exec] calling br_on_failed_cast-2 @@ -44,12 +34,10 @@ [fuzz-exec] calling ref-as-func-of-data [trap not a func] [fuzz-exec] calling ref-as-func-of-func -[fuzz-exec] calling rtt-and-cast-on-func +[fuzz-exec] calling cast-on-func [LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 2] [LoggingExternalInterface logging 1337] -[LoggingExternalInterface logging 3] +[LoggingExternalInterface logging 1] [trap cast error] [fuzz-exec] calling array-alloc-failure [host limit allocation failure] @@ -63,10 +51,6 @@ [LoggingExternalInterface logging 99] [LoggingExternalInterface logging 0] [LoggingExternalInterface logging 10] -[fuzz-exec] calling rtt_Fresh -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] [fuzz-exec] calling array.init [LoggingExternalInterface logging 2] [LoggingExternalInterface logging 42] @@ -79,7 +63,7 @@ [LoggingExternalInterface logging 0] [LoggingExternalInterface logging 1] [LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] +[LoggingExternalInterface logging 1] [fuzz-exec] calling static-br_on_cast [LoggingExternalInterface logging 3] [fuzz-exec] calling static-br_on_cast_fail @@ -87,41 +71,38 @@ (module (type $void_func (func)) (type $bytes (array (mut i8))) - (type $extendedstruct (struct (field (mut i32)) (field f64))) (type $struct (struct (field (mut i32)))) (type $i32_=>_none (func (param i32))) + (type $extendedstruct (struct (field (mut i32)) (field f64))) (type $anyref_=>_none (func (param anyref))) (type $int_func (func (result i32))) (import "fuzzing-support" "log-i32" (func $log (param i32))) - (global $rtt (mut (rtt $extendedstruct)) (rtt.canon $extendedstruct)) (export "structs" (func $0)) (export "arrays" (func $1)) - (export "rtts" (func $2)) - (export "br_on_cast" (func $3)) - (export "br_on_failed_cast-1" (func $4)) - (export "br_on_failed_cast-2" (func $5)) - (export "cast-null-anyref-to-gc" (func $6)) - (export "br_on_data" (func $8)) - (export "br_on_non_data-null" (func $9)) - (export "br_on_non_data-data" (func $10)) - (export "br_on_non_data-other" (func $9)) - (export "br-on_non_null" (func $9)) - (export "br-on_non_null-2" (func $13)) - (export "ref-as-data-of-func" (func $14)) - (export "ref-as-data-of-data" (func $9)) - (export "ref-as-func-of-data" (func $14)) - (export "ref-as-func-of-func" (func $9)) - (export "rtt-and-cast-on-func" (func $19)) - (export "array-alloc-failure" (func $9)) - (export "init-array-packed" (func $21)) - (export "cast-func-to-struct" (func $14)) - (export "array-copy" (func $24)) - (export "rtt_Fresh" (func $25)) - (export "array.init" (func $26)) - (export "array.init-packed" (func $27)) - (export "static-casts" (func $28)) - (export "static-br_on_cast" (func $29)) - (export "static-br_on_cast_fail" (func $30)) + (export "br_on_cast" (func $2)) + (export "br_on_failed_cast-1" (func $3)) + (export "br_on_failed_cast-2" (func $4)) + (export "cast-null-anyref-to-gc" (func $5)) + (export "br_on_data" (func $7)) + (export "br_on_non_data-null" (func $8)) + (export "br_on_non_data-data" (func $9)) + (export "br_on_non_data-other" (func $8)) + (export "br-on_non_null" (func $8)) + (export "br-on_non_null-2" (func $12)) + (export "ref-as-data-of-func" (func $13)) + (export "ref-as-data-of-data" (func $8)) + (export "ref-as-func-of-data" (func $13)) + (export "ref-as-func-of-func" (func $8)) + (export "cast-on-func" (func $18)) + (export "array-alloc-failure" (func $8)) + (export "init-array-packed" (func $20)) + (export "cast-func-to-struct" (func $13)) + (export "array-copy" (func $23)) + (export "array.init" (func $24)) + (export "array.init-packed" (func $25)) + (export "static-casts" (func $26)) + (export "static-br_on_cast" (func $2)) + (export "static-br_on_cast_fail" (func $28)) (func $0 (; has Stack IR ;) (local $0 i32) (call $log @@ -144,10 +125,9 @@ (call $log (array.len $bytes (local.tee $0 - (array.new_with_rtt $bytes + (array.new $bytes (i32.const 42) (i32.const 50) - (rtt.canon $bytes) ) ) ) @@ -184,42 +164,13 @@ ) (func $2 (; has Stack IR ;) (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - ) - (func $3 (; has Stack IR ;) - (call $log (i32.const 3) ) - (unreachable) ) - (func $4 (; has Stack IR ;) + (func $3 (; has Stack IR ;) (local $0 (ref null $struct)) (local.set $0 - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) (drop (block $any (result anyref) @@ -227,9 +178,8 @@ (i32.const 1) ) (drop - (br_on_cast_fail $any + (br_on_cast_static_fail $any $extendedstruct (local.get $0) - (rtt.canon $extendedstruct) ) ) (call $log @@ -239,7 +189,7 @@ ) ) ) - (func $5 (; has Stack IR ;) + (func $4 (; has Stack IR ;) (call $log (i32.const 1) ) @@ -247,12 +197,12 @@ (i32.const 999) ) ) - (func $6 (; has Stack IR ;) + (func $5 (; has Stack IR ;) (call $log (i32.const 0) ) ) - (func $8 (; has Stack IR ;) (param $0 anyref) + (func $7 (; has Stack IR ;) (param $0 anyref) (drop (block $data (result dataref) (drop @@ -263,21 +213,19 @@ (call $log (i32.const 1) ) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ) ) - (func $9 (; has Stack IR ;) + (func $8 (; has Stack IR ;) (nop) ) - (func $10 (; has Stack IR ;) + (func $9 (; has Stack IR ;) (call $log (i32.const 1) ) ) - (func $13 (; has Stack IR ;) + (func $12 (; has Stack IR ;) (drop (block (call $log @@ -287,47 +235,39 @@ ) ) ) - (func $14 (; has Stack IR ;) + (func $13 (; has Stack IR ;) (drop (unreachable) ) ) - (func $19 (; has Stack IR ;) + (func $18 (; has Stack IR ;) (call $log (i32.const 0) ) (call $log - (i32.const 1) - ) - (call $log - (i32.const 2) - ) - (call $log (i32.const 1337) ) (call $log - (i32.const 3) + (i32.const 1) ) (unreachable) ) - (func $21 (; has Stack IR ;) (result i32) + (func $20 (; has Stack IR ;) (result i32) (array.get_u $bytes - (array.new_with_rtt $bytes + (array.new $bytes (i32.const -43) (i32.const 50) - (rtt.canon $bytes) ) (i32.const 10) ) ) - (func $24 (; has Stack IR ;) + (func $23 (; has Stack IR ;) (local $0 (ref null $bytes)) (local $1 (ref null $bytes)) (array.set $bytes (local.tee $1 - (array.new_default_with_rtt $bytes + (array.new_default $bytes (i32.const 200) - (rtt.canon $bytes) ) ) (i32.const 42) @@ -336,10 +276,9 @@ (call $log (array.get_u $bytes (local.tee $0 - (array.new_with_rtt $bytes + (array.new $bytes (i32.const 10) (i32.const 100) - (rtt.canon $bytes) ) ) (i32.const 10) @@ -377,36 +316,14 @@ ) ) ) - (func $25 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (global.set $rtt - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) - ) - ) - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (global.get $rtt) - ) - (global.get $rtt) - ) - ) - ) - (func $26 (; has Stack IR ;) + (func $24 (; has Stack IR ;) (local $0 (ref null $bytes)) (call $log (array.len $bytes (local.tee $0 - (array.init $bytes + (array.init_static $bytes (i32.const 42) (i32.const 50) - (rtt.canon $bytes) ) ) ) @@ -424,18 +341,17 @@ ) ) ) - (func $27 (; has Stack IR ;) + (func $25 (; has Stack IR ;) (call $log (array.get_u $bytes - (array.init $bytes + (array.init_static $bytes (i32.const -11512) - (rtt.canon $bytes) ) (i32.const 0) ) ) ) - (func $28 (; has Stack IR ;) + (func $26 (; has Stack IR ;) (call $log (i32.const 1) ) @@ -455,12 +371,7 @@ (i32.const 1) ) ) - (func $29 (; has Stack IR ;) - (call $log - (i32.const 3) - ) - ) - (func $30 (; has Stack IR ;) + (func $28 (; has Stack IR ;) (call $log (i32.const -2) ) @@ -477,18 +388,8 @@ [LoggingExternalInterface logging 128] [LoggingExternalInterface logging -128] [LoggingExternalInterface logging 42] -[fuzz-exec] calling rtts -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] [fuzz-exec] calling br_on_cast [LoggingExternalInterface logging 3] -[trap unreachable] [fuzz-exec] calling br_on_failed_cast-1 [LoggingExternalInterface logging 1] [fuzz-exec] calling br_on_failed_cast-2 @@ -512,12 +413,10 @@ [fuzz-exec] calling ref-as-func-of-data [trap unreachable] [fuzz-exec] calling ref-as-func-of-func -[fuzz-exec] calling rtt-and-cast-on-func +[fuzz-exec] calling cast-on-func [LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 2] [LoggingExternalInterface logging 1337] -[LoggingExternalInterface logging 3] +[LoggingExternalInterface logging 1] [trap unreachable] [fuzz-exec] calling array-alloc-failure [fuzz-exec] calling init-array-packed @@ -530,10 +429,6 @@ [LoggingExternalInterface logging 99] [LoggingExternalInterface logging 0] [LoggingExternalInterface logging 10] -[fuzz-exec] calling rtt_Fresh -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] [fuzz-exec] calling array.init [LoggingExternalInterface logging 2] [LoggingExternalInterface logging 42] diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast index 7ab9116dd..c8ad3700a 100644 --- a/test/passes/Oz_fuzz-exec_all-features.wast +++ b/test/passes/Oz_fuzz-exec_all-features.wast @@ -8,15 +8,11 @@ (import "fuzzing-support" "log-i32" (func $log (param i32))) - (global $rtt (mut (rtt $extendedstruct)) (rtt.canon $extendedstruct)) - (func "structs" (local $x (ref null $struct)) (local $y (ref null $struct)) (local.set $x - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ;; The value is initialized to 0 ;; Note: We cannot optimize these to constants without either immutability or @@ -49,10 +45,9 @@ (func "arrays" (local $x (ref null $bytes)) (local.set $x - (array.new_with_rtt $bytes + (array.new $bytes (i32.const 42) ;; value to splat into the array (i32.const 50) ;; size - (rtt.canon $bytes) ) ) ;; The length should be 50 @@ -77,78 +72,11 @@ (array.get_s $bytes (local.get $x) (i32.const 20)) ) ) - (func "rtts" - (local $any anyref) - ;; Casting null returns null. - (call $log (ref.is_null - (ref.cast (ref.null $struct) (rtt.canon $struct)) - )) - ;; Testing null returns 0. - (call $log - (ref.test (ref.null $struct) (rtt.canon $struct)) - ) - ;; Testing something completely wrong (struct vs array) returns 0. - (call $log - (ref.test - (array.new_with_rtt $bytes - (i32.const 20) - (i32.const 10) - (rtt.canon $bytes) - ) - (rtt.canon $struct) - ) - ) - ;; Testing a thing with the same RTT returns 1. - (call $log - (ref.test - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - ) - ;; A bad downcast returns 0: we create a struct, which is not a extendedstruct. - (call $log - (ref.test - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - (rtt.canon $extendedstruct) - ) - ) - ;; Create a extendedstruct with RTT y, and upcast statically to anyref. - (local.set $any - (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct (rtt.canon $struct)) - ) - ) - ;; Casting to y, the exact same RTT, works. - (call $log - (ref.test - (local.get $any) - (rtt.sub $extendedstruct (rtt.canon $struct)) - ) - ) - ;; Casting to z, another RTT of the same data type, fails. - (call $log - (ref.test - (local.get $any) - (rtt.canon $extendedstruct) - ) - ) - ;; Casting to x, the parent of y, works. - (call $log - (ref.test - (local.get $any) - (rtt.canon $struct) - ) - ) - ) (func "br_on_cast" (local $any anyref) ;; create a simple $struct, store it in an anyref (local.set $any - (struct.new_default_with_rtt $struct (rtt.canon $struct)) + (struct.new_default $struct) ) (drop (block $block (result ($ref $struct)) @@ -156,12 +84,11 @@ (block $extendedblock (result (ref $extendedstruct)) (drop ;; second, try to cast our simple $struct to what it is, which will work - (br_on_cast $block + (br_on_cast_static $block $struct ;; first, try to cast our simple $struct to an extended, which will fail - (br_on_cast $extendedblock - (local.get $any) (rtt.canon $extendedstruct) + (br_on_cast_static $extendedblock $extendedstruct + (local.get $any) ) - (rtt.canon $struct) ) ) (call $log (i32.const -1)) ;; we should never get here @@ -173,20 +100,12 @@ ) ) (call $log (i32.const 3)) ;; we should get here - (drop - (block $never (result (ref $extendedstruct)) - ;; an untaken br_on_cast, with unreachable rtt - so we cannot use the - ;; RTT in binaryen IR to find the cast type. - (br_on_cast $never (ref.null $struct) (unreachable)) - (unreachable) - ) - ) ) (func "br_on_failed_cast-1" (local $any anyref) ;; create a simple $struct, store it in an anyref (local.set $any - (struct.new_default_with_rtt $struct (rtt.canon $struct)) + (struct.new_default $struct) ) (drop (block $any (result (ref null any)) @@ -194,9 +113,8 @@ (drop ;; try to cast our simple $struct to an extended, which will fail, and ;; so we will branch, skipping the next logging. - (br_on_cast_fail $any + (br_on_cast_static_fail $any $extendedstruct (local.get $any) - (rtt.canon $extendedstruct) ) ) (call $log (i32.const 999)) ;; we should skip this @@ -208,7 +126,7 @@ (local $any anyref) ;; create an $extendedstruct, store it in an anyref (local.set $any - (struct.new_default_with_rtt $extendedstruct (rtt.canon $extendedstruct)) + (struct.new_default $extendedstruct) ) (drop (block $any (result (ref null any)) @@ -216,9 +134,8 @@ (drop ;; try to cast our simple $struct to an extended, which will succeed, and ;; so we will continue to the next logging. - (br_on_cast_fail $any + (br_on_cast_static_fail $any $extendedstruct (local.get $any) - (rtt.canon $extendedstruct) ) ) (call $log (i32.const 999)) @@ -231,16 +148,13 @@ ;; array or a struct, so our casting code should not assume it is. it is ok ;; to try to cast it, and the result should be 0. (call $log - (ref.test + (ref.test_static $struct (ref.null any) - (rtt.canon $struct) ) ) ) (func $get_data (result dataref) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) (func "br_on_data" (param $x anyref) (local $y anyref) @@ -272,9 +186,7 @@ (local $x anyref) ;; set x to valid data (local.set $x - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) (drop (block $any (result anyref) @@ -336,9 +248,7 @@ (func "ref-as-data-of-data" (drop (ref.as_data - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ) ) @@ -346,9 +256,7 @@ (drop ;; This should trap. (ref.as_func - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) + (struct.new_default $struct) ) ) ) @@ -362,43 +270,33 @@ (func $a-void-func (call $log (i32.const 1337)) ) - (func "rtt-and-cast-on-func" + (func "cast-on-func" (call $log (i32.const 0)) - (drop - (rtt.canon $void_func) - ) - (call $log (i32.const 1)) - (drop - (rtt.canon $int_func) - ) - (call $log (i32.const 2)) ;; a valid cast (call_ref - (ref.cast (ref.func $a-void-func) (rtt.canon $void_func)) + (ref.cast_static $void_func (ref.func $a-void-func)) ) - (call $log (i32.const 3)) + (call $log (i32.const 1)) ;; an invalid cast (drop (call_ref - (ref.cast (ref.func $a-void-func) (rtt.canon $int_func)) + (ref.cast_static $int_func (ref.func $a-void-func)) )) ;; will never be reached - (call $log (i32.const 4)) + (call $log (i32.const 2)) ) (func "array-alloc-failure" (drop - (array.new_default_with_rtt $bytes + (array.new_default $bytes (i32.const -1) ;; un-allocatable size (4GB * sizeof(Literal)) - (rtt.canon $bytes) ) ) ) (func "init-array-packed" (result i32) (local $x (ref null $bytes)) (local.set $x - (array.new_with_rtt $bytes + (array.new $bytes (i32.const -43) ;; initialize the i8 values with a negative i32 (i32.const 50) - (rtt.canon $bytes) ) ) ;; read the value, which should be -43 & 255 ==> 213 @@ -413,9 +311,8 @@ (func "cast-func-to-struct" (drop ;; An impossible cast of a function to a struct, which should fail. - (ref.cast + (ref.cast_static $struct (ref.func $call-target) - (rtt.canon $struct) ) ) ) @@ -424,17 +321,15 @@ (local $y (ref null $bytes)) ;; Create an array of 10's, of size 100. (local.set $x - (array.new_with_rtt $bytes + (array.new $bytes (i32.const 10) (i32.const 100) - (rtt.canon $bytes) ) ) ;; Create an array of zeros of size 200, and also set one index there. (local.set $y - (array.new_default_with_rtt $bytes + (array.new_default $bytes (i32.const 200) - (rtt.canon $bytes) ) ) (array.set $bytes @@ -467,55 +362,12 @@ (array.get_u $bytes (local.get $x) (i32.const 12)) ) ) - (func "rtt_Fresh" - ;; Casting to the same sequence of rtt.subs works. - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - ) - ;; But not with fresh! - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) - ) - ) - ) - ;; Casts with fresh succeed, if we use the same fresh rtt. - (global.set $rtt - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) - ) - ) - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (global.get $rtt) - ) - (global.get $rtt) - ) - ) - ) (func "array.init" (local $x (ref null $bytes)) (local.set $x - (array.init $bytes + (array.init_static $bytes (i32.const 42) ;; first value (i32.const 50) ;; second value - (rtt.canon $bytes) ) ) ;; The length should be 2 @@ -534,9 +386,8 @@ (func "array.init-packed" (local $x (ref null $bytes)) (local.set $x - (array.init $bytes + (array.init_static $bytes (i32.const -11512) - (rtt.canon $bytes) ) ) ;; The value should be be -11512 & 255 => 8 @@ -574,9 +425,7 @@ (struct.new_default $struct) ) ) - ;; Casting to a supertype does not work because the canonical RTT for the - ;; subtype is not a sub-rtt of the canonical RTT of the supertype in - ;; structural mode. + ;; Casting to a supertype works. (call $log (ref.test_static $struct (struct.new_default $extendedstruct) @@ -641,9 +490,8 @@ ;; opts the unused value is removed so there is no trap, and a value is ;; returned, which should not confuse the fuzzer. (drop - (array.new_default_with_rtt $[mut:i8] + (array.new_default $[mut:i8] (i32.const -1) - (rtt.canon $[mut:i8]) ) ) (i32.const 0) diff --git a/test/passes/remove-unused-brs_all-features.txt b/test/passes/remove-unused-brs_all-features.txt index abfcc3e76..631c4ffe3 100644 --- a/test/passes/remove-unused-brs_all-features.txt +++ b/test/passes/remove-unused-brs_all-features.txt @@ -13,12 +13,10 @@ (func $foo (result (ref null $struct)) (if (result (ref null $struct)) (i32.const 1) - (struct.new_with_rtt $struct - (array.new_default_with_rtt $vector + (struct.new $struct + (array.new_default $vector (i32.const 1) - (rtt.canon $vector) ) - (rtt.canon $struct) ) (ref.null $struct) ) @@ -88,18 +86,16 @@ (block $data (result (ref $vector)) (drop (br $data - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 1) - (rtt.canon $vector) ) ) ) (call $log (i32.const 5) ) - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) ) @@ -160,9 +156,8 @@ (drop (block $func (result funcref) (drop - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) (ref.null func) @@ -181,9 +176,8 @@ (drop (block $i31 (result (ref null i31)) (drop - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) (ref.null i31) diff --git a/test/passes/remove-unused-brs_all-features.wast b/test/passes/remove-unused-brs_all-features.wast index 9614f7f5c..56a6ab98f 100644 --- a/test/passes/remove-unused-brs_all-features.wast +++ b/test/passes/remove-unused-brs_all-features.wast @@ -5,14 +5,12 @@ (func $foo (result (ref null $struct)) (if (result (ref null $struct)) (i32.const 1) - (struct.new_with_rtt $struct + (struct.new $struct ;; regression test for computing the cost of an array.new_default, which ;; lacks the optional field "init" - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 1) - (rtt.canon $vector) ) - (rtt.canon $struct) ) (ref.null $struct) ) @@ -81,16 +79,14 @@ ;; a non-null data reference means we always take the br (drop (br_on_data $data - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 1) - (rtt.canon $vector) ) ) ) (call $log (i32.const 5)) - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) ) @@ -147,9 +143,8 @@ (block $func (result (ref null func)) (drop (br_on_func $func - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) ) @@ -171,9 +166,8 @@ (block $i31 (result (ref null i31)) (drop (br_on_i31 $i31 - (array.new_default_with_rtt $vector + (array.new_default $vector (i32.const 2) - (rtt.canon $vector) ) ) ) diff --git a/test/passes/vacuum_all-features.wast b/test/passes/vacuum_all-features.wast index 8a6d52022..1dbb6e39b 100644 --- a/test/passes/vacuum_all-features.wast +++ b/test/passes/vacuum_all-features.wast @@ -805,9 +805,7 @@ ;; nullable reference type and we don't have a type to put in its place, so ;; don't try to replace it. (later operations will remove all the body of ;; this function; this test verifies we don't crash along the way) - (struct.new_default_with_rtt $A - (rtt.canon $A) - ) + (struct.new_default $A) ) ) ) diff --git a/test/spec/array.wast b/test/spec/array.wast index 243431319..fd151669e 100644 --- a/test/spec/array.wast +++ b/test/spec/array.wast @@ -1,5 +1,3 @@ -;; XXX BINARYEN: rename array.new_default => array.new_default_with_rtt - ;; Type syntax (module @@ -13,8 +11,6 @@ (type (array (ref data))) (type (array (ref 0))) (type (array (ref null 1))) - (type (array (rtt 1))) - (type (array (rtt 10 1))) (type (array (mut i8))) (type (array (mut i16))) (type (array (mut i32))) @@ -25,8 +21,6 @@ (type (array (mut (ref data)))) (type (array (mut (ref 0)))) (type (array (mut (ref null i31)))) - (type (array (mut (rtt 0)))) - (type (array (mut (rtt 10 0)))) ) @@ -70,7 +64,7 @@ ) (func (export "get") (param $i i32) (result f32) (call $get (local.get $i) - (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec)) + (array.new_default $vec (i32.const 3)) ) ) @@ -80,7 +74,7 @@ ) (func (export "set_get") (param $i i32) (param $y f32) (result f32) (call $set_get (local.get $i) - (array.new_default_with_rtt $mvec (i32.const 3) (rtt.canon $mvec)) + (array.new_default $mvec (i32.const 3)) (local.get $y) ) ) @@ -89,7 +83,7 @@ (array.len $vec (local.get $v)) ) (func (export "len") (result i32) - (call $len (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec))) + (call $len (array.new_default $vec (i32.const 3))) ) ) @@ -130,16 +124,8 @@ (module (type $t (array i32)) (func (export "array.new-null") - (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 1) (i32.const 3) (local.get 0))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (type $t (array (mut i32))) - (func (export "array.new_default_with_rtt-null") - (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 3) (local.get 0))) + (local i64) + (drop (array.new_default $t (local.get 0))) ) ) "type mismatch" diff --git a/test/spec/ref_cast.wast b/test/spec/ref_cast.wast index 8712e5954..1af96d9d4 100644 --- a/test/spec/ref_cast.wast +++ b/test/spec/ref_cast.wast @@ -6,15 +6,6 @@ (type $t2' (struct (field i32) (field i32))) (type $t3 (struct (field i32) (field i32))) - (global $t0 (rtt $t0) (rtt.canon $t0)) - (global $t0' (rtt $t0) (rtt.canon $t0)) - (global $t1 (rtt $t1) (rtt.sub $t1 (global.get $t0))) - (global $t1' (rtt $t1') (rtt.sub $t1' (global.get $t0))) - (global $t2 (rtt $t2) (rtt.sub $t2 (global.get $t1))) - (global $t2' (rtt $t2') (rtt.sub $t2' (global.get $t1'))) - (global $t3 (rtt $t3) (rtt.sub $t3 (global.get $t0))) - (global $t4 (rtt $t3) (rtt.sub $t3 (rtt.sub $t0 (global.get $t0)))) - (global $tab.0 (mut (ref null data)) (ref.null data)) (global $tab.1 (mut (ref null data)) (ref.null data)) (global $tab.2 (mut (ref null data)) (ref.null data)) @@ -25,62 +16,55 @@ (global $tab.12 (mut (ref null data)) (ref.null data)) (func $init - (global.set $tab.0 (struct.new_default_with_rtt $t0 (global.get $t0))) - (global.set $tab.10 (struct.new_default_with_rtt $t0 (global.get $t0'))) - (global.set $tab.1 (struct.new_default_with_rtt $t1 (global.get $t1))) - (global.set $tab.11 (struct.new_default_with_rtt $t1' (global.get $t1'))) - (global.set $tab.2 (struct.new_default_with_rtt $t2 (global.get $t2))) - (global.set $tab.12 (struct.new_default_with_rtt $t2' (global.get $t2'))) - (global.set $tab.3 (struct.new_default_with_rtt $t3 (global.get $t3))) - (global.set $tab.4 (struct.new_default_with_rtt $t3 (global.get $t4))) + (global.set $tab.0 (struct.new_default $t0)) + (global.set $tab.10 (struct.new_default $t0)) + (global.set $tab.1 (struct.new_default $t1)) + (global.set $tab.11 (struct.new_default $t1')) + (global.set $tab.2 (struct.new_default $t2)) + (global.set $tab.12 (struct.new_default $t2')) + (global.set $tab.3 (struct.new_default $t3)) + (global.set $tab.4 (struct.new_default $t3)) ) (func (export "test-sub") (call $init) - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.0) (global.get $t0))) - (drop (ref.cast (global.get $tab.1) (global.get $t0))) - (drop (ref.cast (global.get $tab.2) (global.get $t0))) - (drop (ref.cast (global.get $tab.3) (global.get $t0))) - (drop (ref.cast (global.get $tab.4) (global.get $t0))) + (drop (ref.cast_static $t0 (ref.null data))) + (drop (ref.cast_static $t0 (global.get $tab.0))) + (drop (ref.cast_static $t0 (global.get $tab.1))) + (drop (ref.cast_static $t0 (global.get $tab.2))) + (drop (ref.cast_static $t0 (global.get $tab.3))) + (drop (ref.cast_static $t0 (global.get $tab.4))) - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.1) (global.get $t1))) - (drop (ref.cast (global.get $tab.2) (global.get $t1))) + (drop (ref.cast_static $t0 (ref.null data))) + (drop (ref.cast_static $t1 (global.get $tab.1))) + (drop (ref.cast_static $t1 (global.get $tab.2))) - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.2) (global.get $t2))) + (drop (ref.cast_static $t0 (ref.null data))) + (drop (ref.cast_static $t2 (global.get $tab.2))) - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.3) (global.get $t3))) + (drop (ref.cast_static $t0 (ref.null data))) + (drop (ref.cast_static $t3 (global.get $tab.3))) - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.4) (global.get $t4))) + (drop (ref.cast_static $t0 (ref.null data))) ) (func (export "test-canon") (call $init) - (drop (ref.cast (global.get $tab.0) (global.get $t0'))) - (drop (ref.cast (global.get $tab.1) (global.get $t0'))) - (drop (ref.cast (global.get $tab.2) (global.get $t0'))) - (drop (ref.cast (global.get $tab.3) (global.get $t0'))) - (drop (ref.cast (global.get $tab.4) (global.get $t0'))) - - (drop (ref.cast (global.get $tab.10) (global.get $t0))) - (drop (ref.cast (global.get $tab.11) (global.get $t0))) - (drop (ref.cast (global.get $tab.12) (global.get $t0))) + (drop (ref.cast_static $t0 (global.get $tab.10))) + (drop (ref.cast_static $t0 (global.get $tab.11))) + (drop (ref.cast_static $t0 (global.get $tab.12))) - (drop (ref.cast (global.get $tab.1) (global.get $t1'))) - (drop (ref.cast (global.get $tab.2) (global.get $t1'))) + (drop (ref.cast_static $t1' (global.get $tab.1))) + (drop (ref.cast_static $t1' (global.get $tab.2))) - (drop (ref.cast (global.get $tab.11) (global.get $t1))) - (drop (ref.cast (global.get $tab.12) (global.get $t1))) + (drop (ref.cast_static $t1 (global.get $tab.11))) + (drop (ref.cast_static $t1 (global.get $tab.12))) - (drop (ref.cast (global.get $tab.2) (global.get $t2'))) + (drop (ref.cast_static $t2' (global.get $tab.2))) - (drop (ref.cast (global.get $tab.12) (global.get $t2))) + (drop (ref.cast_static $t2 (global.get $tab.12))) ) ) diff --git a/test/spec/struct.wast b/test/spec/struct.wast index bac4d4520..5bc8e2f2e 100644 --- a/test/spec/struct.wast +++ b/test/spec/struct.wast @@ -28,7 +28,7 @@ (struct.get $vec 0 (local.get $v)) ) (func (export "get_0") (result f32) - (call $get_0 (struct.new_default_with_rtt $vec (rtt.canon $vec))) + (call $get_0 (struct.new_default $vec)) ) (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32) @@ -36,7 +36,7 @@ (struct.get $vec $y (local.get $v)) ) (func (export "set_get_y") (param $y f32) (result f32) - (call $set_get_y (struct.new_default_with_rtt $vec (rtt.canon $vec)) (local.get $y)) + (call $set_get_y (struct.new_default $vec) (local.get $y)) ) (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32) @@ -44,7 +44,7 @@ (struct.get $vec $y (local.get $v)) ) (func (export "set_get_1") (param $y f32) (result f32) - (call $set_get_1 (struct.new_default_with_rtt $vec (rtt.canon $vec)) (local.get $y)) + (call $set_get_1 (struct.new_default $vec) (local.get $y)) ) ) @@ -82,29 +82,12 @@ (module (type $t (struct (field i32) (field (mut i32)))) (func (export "struct.new-null") - (local (ref null (rtt $t))) (drop (struct.new $t (i32.const 1) (i32.const 2) (local.get 0))) + (local i64) + (drop (struct.new $t (i32.const 1) (i32.const 2) (local.get 0))) ) ) "type mismatch" ) -(assert_invalid - (module - (type $t (struct (field i32) (field (mut i32)))) - (func (export "struct.new_default-null") - (local (ref null (rtt $t))) (drop (struct.new_default_with_rtt $t (local.get 0))) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (type $A (struct (field i32))) - (type $B (struct (field i64))) - (global $glob (rtt $A) (rtt.sub $A (rtt.canon $B))) - ) - "invalid rtt" -) (assert_invalid (module @@ -112,7 +95,7 @@ (func $test (drop ;; too many arguments - (struct.new_with_rtt $vec (i32.const 1) (i32.const 2) (rtt.canon $vec)) + (struct.new $vec (i32.const 1) (i32.const 2)) ) ) ) @@ -125,7 +108,7 @@ (func $test (drop ;; too few arguments - (struct.new_with_rtt $vec (i32.const 1) (rtt.canon $vec)) + (struct.new $vec (i32.const 1)) ) ) ) |