diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/type-generalizing.wast | 1335 |
1 files changed, 1316 insertions, 19 deletions
diff --git a/test/lit/passes/type-generalizing.wast b/test/lit/passes/type-generalizing.wast index fed327727..c874cc76c 100644 --- a/test/lit/passes/type-generalizing.wast +++ b/test/lit/passes/type-generalizing.wast @@ -3,20 +3,54 @@ ;; RUN: foreach %s %t wasm-opt --experimental-type-generalizing -all -S -o - | filecheck %s (module + ;; CHECK: (type $void (func)) + (type $void (func)) - ;; CHECK: (type $0 (func (result eqref))) + ;; CHECK: (type $1 (func (result eqref))) - ;; CHECK: (type $1 (func)) + ;; CHECK: (type $2 (func (param eqref))) - ;; CHECK: (type $2 (func (param anyref))) + ;; CHECK: (type $3 (func (param eqref anyref))) - ;; CHECK: (type $3 (func (param i31ref))) + ;; CHECK: (type $4 (func (param anyref))) - ;; CHECK: (type $4 (func (param anyref eqref))) + ;; CHECK: (type $5 (func (param i31ref))) - ;; CHECK: (type $5 (func (param eqref))) + ;; CHECK: (type $6 (func (param anyref eqref))) - ;; CHECK: (func $unconstrained (type $1) + ;; CHECK: (type $7 (func (result i32))) + + ;; CHECK: (type $8 (func (result nullref))) + + ;; CHECK: (type $9 (func (result structref))) + + ;; CHECK: (type $10 (func (result (ref eq)))) + + ;; CHECK: (type $11 (func (param (ref noextern)) (result anyref))) + + ;; CHECK: (type $12 (func (param (ref noextern)) (result (ref any)))) + + ;; CHECK: (type $13 (func (result externref))) + + ;; CHECK: (type $14 (func (result (ref extern)))) + + ;; CHECK: (type $15 (func (param anyref anyref))) + + ;; CHECK: (global $global-eq (mut eqref) (ref.null none)) + (global $global-eq (mut eqref) (ref.null none)) + + ;; CHECK: (global $global-i32 (mut i32) (i32.const 0)) + (global $global-i32 (mut i32) (i32.const 0)) + + ;; CHECK: (table $func-table 0 0 funcref) + (table $func-table 0 0 funcref) + + ;; CHECK: (table $eq-table 0 0 eqref) + (table $eq-table 0 0 eqref) + + ;; CHECK: (elem declare func $ref-func) + + ;; CHECK: (func $unconstrained (type $void) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local $y anyref) ;; CHECK-NEXT: (local $z (anyref i32)) @@ -31,7 +65,7 @@ (local $z (anyref i32)) ) - ;; CHECK: (func $implicit-return (type $0) (result eqref) + ;; CHECK: (func $implicit-return (type $1) (result eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) @@ -42,7 +76,7 @@ (local.get $var) ) - ;; CHECK: (func $implicit-return-unreachable (type $0) (result eqref) + ;; CHECK: (func $implicit-return-unreachable (type $1) (result eqref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) @@ -54,7 +88,7 @@ (local.get $var) ) - ;; CHECK: (func $if (type $0) (result eqref) + ;; CHECK: (func $if (type $1) (result eqref) ;; CHECK-NEXT: (local $x eqref) ;; CHECK-NEXT: (local $y eqref) ;; CHECK-NEXT: (if (result eqref) @@ -63,7 +97,7 @@ ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $if (result (eqref)) + (func $if (result eqref) (local $x i31ref) (local $y i31ref) (if (result i31ref) @@ -75,7 +109,147 @@ ) ) - ;; CHECK: (func $local-set (type $1) + ;; CHECK: (func $loop (type $1) (result eqref) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (loop $loop-in (result eqref) + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $loop (result eqref) + (local $var i31ref) + ;; Require that typeof($var) <: eqref. + (loop (result i31ref) + (local.get $var) + ) + ) + + ;; CHECK: (func $br-sent (type $1) (result eqref) + ;; CHECK-NEXT: (local $var1 anyref) + ;; CHECK-NEXT: (local $var2 eqref) + ;; CHECK-NEXT: (block $l (result eqref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $var1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $l + ;; CHECK-NEXT: (local.get $var2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br-sent (result eqref) + (local $var1 i31ref) + (local $var2 i31ref) + (block $l (result i31ref) + ;; The call will be DCEd out, but this test and the implementation for `br` + ;; should be forward-compatible with a future where we do not have to run DCE + ;; before this pass. + (call $helper-any_any + ;; No requirements on $var1 + (local.get $var1) + ;; Require that typeof($var2) <: eqref. + (br $l + (local.get $var2) + ) + ) + ) + ) + + ;; CHECK: (func $br-no-sent (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (block $l + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br-no-sent + (local $var i31ref) + (block $l + ;; This call is DCEd out just like in the previous test. + (call $helper-any_any + ;; No requirements on $var + (local.get $var) + (br $l) + ) + ) + ) + + ;; CHECK: (func $br_table-sent (type $3) (param $eq eqref) (param $any anyref) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (local.set $eq + ;; CHECK-NEXT: (block $l1 (result eqref) + ;; CHECK-NEXT: (local.set $any + ;; CHECK-NEXT: (block $l2 (result eqref) + ;; CHECK-NEXT: (br_table $l1 $l2 + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br_table-sent (param $eq eqref) (param $any anyref) + (local $var i31ref) + ;; Require typeof($var) <: eqref. + (local.set $eq + (block $l1 (result i31ref) + ;; Require typeof($var) <: anyref. + (local.set $any + (block $l2 (result i31ref) + (br_table $l1 $l2 + (local.get $var) + (i32.const 0) + ) + ) + ) + (unreachable) + ) + ) + ) + + ;; CHECK: (func $br_table-sent-reversed (type $3) (param $eq eqref) (param $any anyref) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (local.set $any + ;; CHECK-NEXT: (block $l1 (result eqref) + ;; CHECK-NEXT: (local.set $eq + ;; CHECK-NEXT: (block $l2 (result eqref) + ;; CHECK-NEXT: (br_table $l1 $l2 + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br_table-sent-reversed (param $eq eqref) (param $any anyref) + ;; Same as above, but with the sources of requirements flipped. + (local $var i31ref) + ;; Require typeof($var) <: anyref. + (local.set $any + (block $l1 (result i31ref) + ;; Require typeof($var) <: eqref. + (local.set $eq + (block $l2 (result i31ref) + (br_table $l1 $l2 + (local.get $var) + (i32.const 0) + ) + ) + ) + (unreachable) + ) + ) + ) + + ;; CHECK: (func $local-set (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.i31 @@ -94,7 +268,7 @@ ) ) - ;; CHECK: (func $local-get-set (type $2) (param $dest anyref) + ;; CHECK: (func $local-get-set (type $4) (param $dest anyref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $dest ;; CHECK-NEXT: (local.get $var) @@ -109,7 +283,7 @@ ) ) - ;; CHECK: (func $local-get-set-unreachable (type $3) (param $dest i31ref) + ;; CHECK: (func $local-get-set-unreachable (type $5) (param $dest i31ref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) @@ -126,7 +300,7 @@ ) ) - ;; CHECK: (func $local-get-set-join (type $4) (param $dest1 anyref) (param $dest2 eqref) + ;; CHECK: (func $local-get-set-join (type $6) (param $dest1 anyref) (param $dest2 eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.set $dest1 ;; CHECK-NEXT: (local.get $var) @@ -148,7 +322,7 @@ ) ) - ;; CHECK: (func $local-get-set-chain (type $0) (result eqref) + ;; CHECK: (func $local-get-set-chain (type $1) (result eqref) ;; CHECK-NEXT: (local $a eqref) ;; CHECK-NEXT: (local $b eqref) ;; CHECK-NEXT: (local $c eqref) @@ -176,7 +350,7 @@ (local.get $c) ) - ;; CHECK: (func $local-get-set-chain-out-of-order (type $0) (result eqref) + ;; CHECK: (func $local-get-set-chain-out-of-order (type $1) (result eqref) ;; CHECK-NEXT: (local $a eqref) ;; CHECK-NEXT: (local $b eqref) ;; CHECK-NEXT: (local $c eqref) @@ -205,7 +379,7 @@ (local.get $c) ) - ;; CHECK: (func $local-tee (type $5) (param $dest eqref) + ;; CHECK: (func $local-tee (type $2) (param $dest eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.tee $dest @@ -231,7 +405,7 @@ ) ) - ;; CHECK: (func $i31-get (type $1) + ;; CHECK: (func $i31-get (type $void) ;; CHECK-NEXT: (local $nullable i31ref) ;; CHECK-NEXT: (local $nonnullable i31ref) ;; CHECK-NEXT: (local.set $nonnullable @@ -274,4 +448,1127 @@ ) ) ) + + ;; CHECK: (func $call (type $2) (param $x eqref) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (call $call + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call (param $x eqref) + ;; This will be optimized to eqref. + (local $var i31ref) + ;; Requires typeof($var) <: eqref. + (call $call + (local.get $var) + ) + ) + + ;; CHECK: (func $call_indirect (type $void) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (call_indirect $func-table (type $2) + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call_indirect + ;; This will be optimized to eqref. + (local $var i31ref) + ;; Requires typeof($var) <: eqref. + (call_indirect (param eqref) + (local.get $var) + (i32.const 0) + ) + ) + + ;; CHECK: (func $global-get (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (local $i32 i32) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (global.get $global-eq) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $i32 + ;; CHECK-NEXT: (global.get $global-i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $global-get + (local $var eqref) + (local $i32 i32) + ;; The global type will remain unchanged and the local will be generalized. + (local.set $var + (global.get $global-eq) + ) + ;; Non-reference typed globals are ok, too. + (local.set $i32 + (global.get $global-i32) + ) + ) + + ;; CHECK: (func $global-set (type $void) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (local $i32 i32) + ;; CHECK-NEXT: (global.set $global-eq + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (global.set $global-i32 + ;; CHECK-NEXT: (local.get $i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $global-set + (local $var i31ref) + (local $i32 i32) + ;; Requires typeof($var) <: eqref. + (global.set $global-eq + (local.get $var) + ) + ;; Non-reference typed globals are ok, too. + (global.set $global-i32 + (local.get $i32) + ) + ) + + ;; CHECK: (func $select (type $1) (result eqref) + ;; CHECK-NEXT: (local $var1 eqref) + ;; CHECK-NEXT: (local $var2 eqref) + ;; CHECK-NEXT: (select (result eqref) + ;; CHECK-NEXT: (local.get $var1) + ;; CHECK-NEXT: (local.get $var2) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $select (result eqref) + ;; Both of these will be generalized to eqref. + (local $var1 i31ref) + (local $var2 i31ref) + ;; Requires typeof($var1) <: eqref and typeof($var2) <: eqref. + (select (result i31ref) + (local.get $var1) + (local.get $var2) + (i32.const 0) + ) + ) + + ;; CHECK: (func $ref-null (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-null + (local $var i31ref) + ;; No constraints on $var. + (local.set $var + (ref.null none) + ) + ) + + ;; CHECK: (func $ref-is-null (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-is-null + (local $var i31ref) + (drop + ;; No constraints on $var. + (ref.is_null + (local.get $var) + ) + ) + ) + + ;; CHECK: (func $ref-func (type $void) + ;; CHECK-NEXT: (local $var funcref) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (ref.func $ref-func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-func + (local $var (ref null $void)) + ;; No constraints on $var. + (local.set $var + (ref.func $ref-func) + ) + ) + + ;; CHECK: (func $ref-eq (type $void) + ;; CHECK-NEXT: (local $var1 eqref) + ;; CHECK-NEXT: (local $var2 eqref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $var1) + ;; CHECK-NEXT: (local.get $var2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-eq + (local $var1 i31ref) + (local $var2 i31ref) + (drop + ;; Require that typeof($var1) <: eqref and that typeof($var2) <: eqref. + (ref.eq + (local.get $var1) + (local.get $var2) + ) + ) + ) + + ;; CHECK: (func $table-get (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (table.get $eq-table + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-get + (local $var eqref) + ;; No constraints on $var. + (local.set $var + (table.get $eq-table + (i32.const 0) + ) + ) + ) + + ;; CHECK: (func $table-set (type $void) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (table.set $eq-table + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-set + (local $var i31ref) + ;; Require typeof($var) <: eqref. + (table.set $eq-table + (i32.const 0) + (local.get $var) + ) + ) + + ;; CHECK: (func $table-fill (type $void) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (table.fill $eq-table + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-fill + (local $var i31ref) + ;; Require typeof($var) <: eqref. + (table.fill $eq-table + (i32.const 0) + (local.get $var) + (i32.const 0) + ) + ) + + ;; CHECK: (func $ref-test (type $7) (result i32) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (ref.test nullref + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-test (result i32) + (local $var i31ref) + ;; No constraint on $var. + (ref.test structref + (local.get $var) + ) + ) + + ;; CHECK: (func $ref-cast (type $void) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast i31ref + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-cast + (local $var i31ref) + ;; No constraint on $var. + (drop + (ref.cast i31ref + (local.get $var) + ) + ) + ) + + ;; CHECK: (func $ref-cast-limited (type $1) (result eqref) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (ref.cast i31ref + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-cast-limited (result eqref) + (local $var i31ref) + ;; No constraint on $var. + ;; TODO: We could eliminate the cast if we did constrain $var. + (ref.cast i31ref + (local.get $var) + ) + ) + + ;; CHECK: (func $ref-cast-more-limited (type $8) (result nullref) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (ref.cast nullref + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-cast-more-limited (result nullref) + (local $var i31ref) + ;; No constraint on $var. + (ref.cast nullref + (local.get $var) + ) + ) + + ;; CHECK: (func $ref-cast-lub (type $9) (result structref) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (ref.cast nullref + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-cast-lub (result structref) + (local $var i31ref) + ;; No constraint on $var. + (ref.cast structref + (local.get $var) + ) + ) + + ;; CHECK: (func $ref-as-non-null (type $10) (result (ref eq)) + ;; CHECK-NEXT: (local $var eqref) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref-as-non-null (result (ref eq)) + (local $var i31ref) + ;; Require that typeof($var) <: eqref. + (ref.as_non_null + (local.get $var) + ) + ) + + ;; CHECK: (func $any-convert-extern-nullable (type $11) (param $x (ref noextern)) (result anyref) + ;; CHECK-NEXT: (local $var externref) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (extern.internalize + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $any-convert-extern-nullable (param $x (ref noextern)) (result anyref) + (local $var (ref noextern)) + (local.set $var + (local.get $x) + ) + ;; Require that typeof($var) <: externref. + (extern.internalize + (local.get $var) + ) + ) + + ;; CHECK: (func $any-convert-extern-non-nullable (type $12) (param $x (ref noextern)) (result (ref any)) + ;; CHECK-NEXT: (local $var (ref extern)) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (extern.internalize + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $any-convert-extern-non-nullable (param $x (ref noextern)) (result (ref any)) + (local $var (ref noextern)) + (local.set $var + (local.get $x) + ) + ;; Require that typeof($var) <: (ref extern). + (extern.internalize + (local.get $var) + ) + ) + + ;; CHECK: (func $extern-convert-any-nullable (type $13) (result externref) + ;; CHECK-NEXT: (local $var anyref) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (extern.externalize + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $extern-convert-any-nullable (result externref) + (local $var (ref i31)) + (local.set $var + (i31.new + (i32.const 0) + ) + ) + ;; Require that typeof($var) <: anyref. + (extern.externalize + (local.get $var) + ) + ) + + ;; CHECK: (func $extern-convert-any-non-nullable (type $14) (result (ref extern)) + ;; CHECK-NEXT: (local $var (ref any)) + ;; CHECK-NEXT: (local.set $var + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (extern.externalize + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $extern-convert-any-non-nullable (result (ref extern)) + (local $var (ref i31)) + (local.set $var + (i31.new + (i32.const 0) + ) + ) + ;; Require that typeof($var) <: anyref. + (extern.externalize + (local.get $var) + ) + ) + + ;; CHECK: (func $helper-any_any (type $15) (param $0 anyref) (param $1 anyref) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $helper-any_any (param anyref anyref) + (unreachable) + ) +) + +(module + ;; CHECK: (type $top (sub (func (param i31ref) (result anyref)))) + (type $top (sub (func (param i31ref) (result anyref)))) + ;; CHECK: (type $mid (sub $top (func (param eqref) (result anyref)))) + (type $mid (sub $top (func (param eqref) (result anyref)))) + ;; CHECK: (type $2 (func (result eqref))) + + ;; CHECK: (type $bot (sub $mid (func (param eqref) (result eqref)))) + (type $bot (sub $mid (func (param eqref) (result eqref)))) + + ;; CHECK: (type $4 (func (result anyref))) + + ;; CHECK: (func $call-ref-params-limited (type $4) (result anyref) + ;; CHECK-NEXT: (local $f (ref null $mid)) + ;; CHECK-NEXT: (local $arg eqref) + ;; CHECK-NEXT: (call_ref $mid + ;; CHECK-NEXT: (local.get $arg) + ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-ref-params-limited (result anyref) + (local $f (ref null $bot)) + (local $arg i31ref) + ;; Require that typeof($f) <: $mid and that typeof($arg) <: eqref. In + ;; principle we could generalize $f up to $top, but then we wouldn't be able + ;; to generalize $arg at all. + (call_ref $bot + (local.get $arg) + (local.get $f) + ) + ) + + ;; CHECK: (func $call-ref-results-limited (type $2) (result eqref) + ;; CHECK-NEXT: (local $f (ref null $bot)) + ;; CHECK-NEXT: (local $arg eqref) + ;; CHECK-NEXT: (call_ref $bot + ;; CHECK-NEXT: (local.get $arg) + ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-ref-results-limited (result eqref) + (local $f (ref null $bot)) + (local $arg i31ref) + ;; Require that typeof($f) <: $bot because anything better would require a + ;; cast on the output. Also require that typeof($arg) <: eqref. + (call_ref $bot + (local.get $arg) + (local.get $f) + ) + ) + + ;; CHECK: (func $call-ref-impossible (type $2) (result eqref) + ;; CHECK-NEXT: (local $f nullfuncref) + ;; CHECK-NEXT: (local $arg anyref) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $arg) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-ref-impossible (result eqref) + (local $f nullfuncref) + (local $arg i31ref) + ;; Require that typeof($f) <: nullref, but do not constrain $arg because the + ;; call_ref will not be reached. + (call_ref $bot + (local.get $arg) + (local.get $f) + ) + ) +) + +(module + ;; CHECK: (type $top (sub (func (result anyref)))) + (type $top (sub (func (result anyref)))) + (type $mid (sub $top (func (result eqref)))) + (type $bot (sub $mid (func (result i31ref)))) + + ;; CHECK: (type $1 (func (result anyref))) + + ;; CHECK: (func $call-ref-no-limit (type $1) (result anyref) + ;; CHECK-NEXT: (local $f (ref null $top)) + ;; CHECK-NEXT: (call_ref $top + ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-ref-no-limit (result anyref) + (local $f (ref null $bot)) + ;; Require that typeof($f) <: $top because that does not limit us in any way + ;; and we cannot possibly do better. + (call_ref $bot + (local.get $f) + ) + ) +) + +(module + + ;; CHECK: (type $0 (func (result anyref))) + + ;; CHECK: (type $top (sub (struct (field (mut eqref)) (field eqref)))) + (type $top (sub (struct (field (mut eqref)) (field eqref)))) + ;; CHECK: (type $mid (sub $top (struct (field (mut eqref)) (field eqref) (field (mut eqref))))) + (type $mid (sub $top (struct (field (mut eqref)) (field eqref) (field (mut eqref))))) + ;; CHECK: (type $3 (func)) + + ;; CHECK: (type $bot (sub $mid (struct (field (mut eqref)) (field i31ref) (field (mut eqref))))) + (type $bot (sub $mid (struct (field (mut eqref)) (field i31ref) (field (mut eqref))))) + + ;; CHECK: (type $struct (struct (field eqref) (field anyref))) + (type $struct (struct (field eqref) (field anyref))) + + ;; CHECK: (type $6 (func (result i31ref))) + + ;; CHECK: (func $struct-new (type $0) (result anyref) + ;; CHECK-NEXT: (local $var1 eqref) + ;; CHECK-NEXT: (local $var2 anyref) + ;; CHECK-NEXT: (struct.new $struct + ;; CHECK-NEXT: (local.get $var1) + ;; CHECK-NEXT: (local.get $var2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-new (result anyref) + (local $var1 i31ref) + (local $var2 i31ref) + ;; Require that typeof($var1) <: eqref and that typeof($var2) <: anyref. + (struct.new $struct + (local.get $var1) + (local.get $var2) + ) + ) + + ;; CHECK: (func $struct-get (type $0) (result anyref) + ;; CHECK-NEXT: (local $var (ref null $top)) + ;; CHECK-NEXT: (struct.get $top 1 + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-get (result anyref) + (local $var (ref null $bot)) + ;; Require that typeof($var) <: (ref null $top) because it has a field of the + ;; right type at index 1. + (struct.get $bot 1 + (local.get $var) + ) + ) + + ;; CHECK: (func $struct-get-type (type $6) (result i31ref) + ;; CHECK-NEXT: (local $var (ref null $bot)) + ;; CHECK-NEXT: (struct.get $bot 1 + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-get-type (result i31ref) + (local $var (ref null $bot)) + ;; Require that typeof($var) <: (ref null $bot) because further supertypes do + ;; not satisfy the requirement on the result type. + (struct.get $bot 1 + (local.get $var) + ) + ) + + ;; CHECK: (func $struct-get-index (type $0) (result anyref) + ;; CHECK-NEXT: (local $var (ref null $mid)) + ;; CHECK-NEXT: (struct.get $mid 2 + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-get-index (result anyref) + (local $var (ref null $bot)) + ;; Require that typeof($var) <: (ref null $mid) because further supertypes do + ;; not have a field at index 2. + (struct.get $bot 2 + (local.get $var) + ) + ) + + ;; CHECK: (func $struct-get-impossible (type $0) (result anyref) + ;; CHECK-NEXT: (local $var nullref) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $var) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-get-impossible (result anyref) + (local $var nullref) + (struct.get $bot 0 + (local.get $var) + ) + ) + + ;; CHECK: (func $struct-set (type $3) + ;; CHECK-NEXT: (local $ref (ref null $top)) + ;; CHECK-NEXT: (local $val eqref) + ;; CHECK-NEXT: (struct.set $top 0 + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-set + (local $ref (ref null $bot)) + (local $val i31ref) + ;; Require that typeof($ref) <: (ref null $top) because it has a field at + ;; index 0 and require that typeof($val) <: eqref because that is the type of + ;; the field. + (struct.set $bot 0 + (local.get $ref) + (local.get $val) + ) + ) + + ;; CHECK: (func $struct-set-index (type $3) + ;; CHECK-NEXT: (local $ref (ref null $mid)) + ;; CHECK-NEXT: (local $val eqref) + ;; CHECK-NEXT: (struct.set $mid 2 + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-set-index + (local $ref (ref null $bot)) + (local $val i31ref) + ;; Require that typeof($ref) <: (ref null $mid) because further supertypes do + ;; not have a field at index 2 and require that typeof($val) <: eqref because + ;; that is the type of the field. + (struct.set $bot 2 + (local.get $ref) + (local.get $val) + ) + ) + + ;; CHECK: (func $struct-set-impossible (type $3) + ;; CHECK-NEXT: (local $ref nullref) + ;; CHECK-NEXT: (local $val anyref) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-set-impossible + (local $ref nullref) + (local $val nullref) + ;; Require that typeof($ref) <: nullref, but do not constrain $val. + (struct.set $bot 0 + (local.get $ref) + (local.get $val) + ) + ) +) + +(module + ;; CHECK: (type $0 (func)) + + ;; CHECK: (type $super-mut (sub (array (mut eqref)))) + + ;; CHECK: (type $super (sub (array eqref))) + (type $super (sub (array (field eqref)))) + ;; CHECK: (type $3 (func (result anyref))) + + ;; CHECK: (type $mut-bytes (sub (array (mut i8)))) + + ;; CHECK: (type $bytes (sub (array i8))) + + ;; CHECK: (type $sub (sub $super (array i31ref))) + (type $sub (sub $super (array (field i31ref)))) + + (type $super-mut (sub (array (field (mut eqref))))) + (type $sub-mut (sub $super-mut (array (field (mut eqref))))) + + (type $bytes (sub (array i8))) + (type $sub-bytes (sub $bytes (array i8))) + + (type $mut-bytes (sub (array (mut i8)))) + (type $sub-mut-bytes (sub $mut-bytes (array (mut i8)))) + + ;; CHECK: (data $data "") + + ;; CHECK: (elem $elem i31ref) + (elem $elem i31ref) + + (data $data "") + + ;; CHECK: (func $array-new (type $3) (result anyref) + ;; CHECK-NEXT: (local $val eqref) + ;; CHECK-NEXT: (array.new $super + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-new (result anyref) + (local $val i31ref) + ;; Require that typeof($val) <: eqref. + (array.new $super + (local.get $val) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-new-data (type $0) + ;; CHECK-NEXT: (local $val anyref) + ;; CHECK-NEXT: (local.set $val + ;; CHECK-NEXT: (array.new_data $bytes $data + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-new-data + (local $val arrayref) + ;; No constraint on $val. + (local.set $val + (array.new_data $bytes $data + (i32.const 0) + (i32.const 0) + ) + ) + ) + + ;; CHECK: (func $array-new-elem (type $0) + ;; CHECK-NEXT: (local $val anyref) + ;; CHECK-NEXT: (local.set $val + ;; CHECK-NEXT: (array.new_elem $sub $elem + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-new-elem + (local $val arrayref) + ;; No constraint on $val. + (local.set $val + (array.new_elem $sub $elem + (i32.const 0) + (i32.const 0) + ) + ) + ) + + ;; CHECK: (func $array-new-fixed (type $3) (result anyref) + ;; CHECK-NEXT: (local $val1 eqref) + ;; CHECK-NEXT: (local $val2 eqref) + ;; CHECK-NEXT: (array.new_fixed $super 2 + ;; CHECK-NEXT: (local.get $val1) + ;; CHECK-NEXT: (local.get $val2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-new-fixed (result anyref) + (local $val1 i31ref) + (local $val2 i31ref) + ;; Require that typeof($val1) <: eqref and that typeof($val2) <: eqref. + (array.new_fixed $super 2 + (local.get $val1) + (local.get $val2) + ) + ) + + ;; CHECK: (func $array-get (type $3) (result anyref) + ;; CHECK-NEXT: (local $val (ref null $super)) + ;; CHECK-NEXT: (array.get $super + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-get (result anyref) + (local $val (ref null $sub)) + ;; Require that typeof($val) <: (ref null $super). + (array.get $sub + (local.get $val) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-get-impossible (type $3) (result anyref) + ;; CHECK-NEXT: (local $val nullref) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-get-impossible (result anyref) + (local $val nullref) + ;; Require that typeof($val) <: nullref. + (array.get $sub + (local.get $val) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-set (type $0) + ;; CHECK-NEXT: (local $ref (ref null $super-mut)) + ;; CHECK-NEXT: (local $val eqref) + ;; CHECK-NEXT: (array.set $super-mut + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-set + (local $ref (ref null $sub-mut)) + (local $val i31ref) + ;; Require that typeof($ref) <: (ref null $super-mut) and that typeof($val) <: + ;; eqref. + (array.set $sub-mut + (local.get $ref) + (i32.const 0) + (local.get $val) + ) + ) + + ;; CHECK: (func $array-set-impossible (type $0) + ;; CHECK-NEXT: (local $ref nullref) + ;; CHECK-NEXT: (local $val anyref) + ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-set-impossible + (local $ref nullref) + (local $val i31ref) + ;; Require that typeof($ref) <: nullref and do not constrain $ref. + (array.set $sub-mut + (local.get $ref) + (i32.const 0) + (local.get $val) + ) + ) + + ;; CHECK: (func $array-len (type $0) + ;; CHECK-NEXT: (local $ref arrayref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (array.len + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-len + (local $ref (ref null $super)) + (drop + ;; Require that typeof($ref) <: arrayref. + (array.len + (local.get $ref) + ) + ) + ) + + ;; CHECK: (func $array-copy-ref (type $0) + ;; CHECK-NEXT: (local $dest (ref null $super-mut)) + ;; CHECK-NEXT: (local $src (ref null $super)) + ;; CHECK-NEXT: (array.copy $super-mut $super + ;; CHECK-NEXT: (local.get $dest) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-copy-ref + (local $dest (ref null $sub-mut)) + (local $src (ref null $sub)) + ;; Require that typeof($dest) <: $super-mut and that typeof($src) <: $super. + (array.copy $sub-mut $sub + (local.get $dest) + (i32.const 0) + (local.get $src) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-copy-i8 (type $0) + ;; CHECK-NEXT: (local $dest (ref null $mut-bytes)) + ;; CHECK-NEXT: (local $src (ref null $bytes)) + ;; CHECK-NEXT: (array.copy $mut-bytes $bytes + ;; CHECK-NEXT: (local.get $dest) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-copy-i8 + ;; Same as above, but now the copied element type is not a ref. + (local $dest (ref null $sub-mut-bytes)) + (local $src (ref null $sub-bytes)) + ;; Require that typeof($dest) <: $mut-bytes and that typeof($src) <: $bytes. + (array.copy $sub-mut-bytes $sub-bytes + (local.get $dest) + (i32.const 0) + (local.get $src) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-copy-impossible-dest (type $0) + ;; CHECK-NEXT: (local $dest nullref) + ;; CHECK-NEXT: (local $src anyref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $dest) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-copy-impossible-dest + ;; Same as above, but now the dest is bottom. + (local $dest nullref) + (local $src (ref null $sub)) + ;; Require that typeof($dest) <: nullref but do not constrain $src. + (array.copy $sub-mut $sub + (local.get $dest) + (i32.const 0) + (local.get $src) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-copy-impossible-src (type $0) + ;; CHECK-NEXT: (local $dest anyref) + ;; CHECK-NEXT: (local $src nullref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $dest) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-copy-impossible-src + ;; Same as above, but now the src is bottom instead. + (local $dest (ref null $sub-mut)) + (local $src nullref) + ;; Require that typeof($src) <: nullref but do not constrain $dest. + (array.copy $sub-mut $sub + (local.get $dest) + (i32.const 0) + (local.get $src) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-copy-impossible-both (type $0) + ;; CHECK-NEXT: (local $dest nullref) + ;; CHECK-NEXT: (local $src nullref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $dest) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-copy-impossible-both + ;; Same as above, but now both src and dest are bottom. + (local $dest nullref) + (local $src nullref) + ;; Do not constrain $src or $dest. + (array.copy $sub-mut $sub + (local.get $dest) + (i32.const 0) + (local.get $src) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-fill (type $0) + ;; CHECK-NEXT: (local $ref (ref null $super-mut)) + ;; CHECK-NEXT: (local $val eqref) + ;; CHECK-NEXT: (array.fill $super-mut + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-fill + (local $ref (ref null $sub-mut)) + (local $val i31ref) + ;; Require that typeof($ref) <: (ref null $super-mut) and that typeof($val) <: + ;; eqref. + (array.fill $sub-mut + (local.get $ref) + (i32.const 0) + (local.get $val) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-fill-impossible (type $0) + ;; CHECK-NEXT: (local $ref nullref) + ;; CHECK-NEXT: (local $val anyref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-fill-impossible + (local $ref nullref) + (local $val i31ref) + ;; Require that typeof($ref) <: nullref, but do not constrain $val. + (array.fill $sub-mut + (local.get $ref) + (i32.const 0) + (local.get $val) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-init-data (type $0) + ;; CHECK-NEXT: (local $ref (ref null $mut-bytes)) + ;; CHECK-NEXT: (array.init_data $mut-bytes $data + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-init-data + (local $ref (ref null $sub-mut-bytes)) + ;; Require that typeof($ref) <: (ref null $mut-bytes). + (array.init_data $sub-mut-bytes $data + (local.get $ref) + (i32.const 0) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-init-data-impossible (type $0) + ;; CHECK-NEXT: (local $ref nullref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-init-data-impossible + (local $ref nullref) + ;; Require that typeof($ref) <: nullref. + (array.init_data $sub-mut-bytes $data + (local.get $ref) + (i32.const 0) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-init-elem (type $0) + ;; CHECK-NEXT: (local $ref (ref null $super-mut)) + ;; CHECK-NEXT: (array.init_elem $super-mut $elem + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-init-elem + (local $ref (ref null $sub-mut)) + ;; Require that typeof($ref) <: (ref null $super-mut). + (array.init_elem $sub-mut $elem + (local.get $ref) + (i32.const 0) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; CHECK: (func $array-init-elem-impossible (type $0) + ;; CHECK-NEXT: (local $ref nullref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.get $ref) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-init-elem-impossible + (local $ref nullref) + ;; Require that typeof($ref) <: nullref. + (array.init_elem $sub-mut $elem + (local.get $ref) + (i32.const 0) + (i32.const 0) + (i32.const 0) + ) + ) ) |