diff options
author | Thomas Lively <tlively@google.com> | 2023-11-16 00:56:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-15 15:56:39 -0800 |
commit | bf7635728e80ddda845e0b893b775e75a154e48e (patch) | |
tree | 78ab40302d5a45e748b7e328eff0df3a125a41cc /test | |
parent | 20fe882b47c4b2570c70b2f9d82189c5b2144d03 (diff) | |
download | binaryen-bf7635728e80ddda845e0b893b775e75a154e48e.tar.gz binaryen-bf7635728e80ddda845e0b893b775e75a154e48e.tar.bz2 binaryen-bf7635728e80ddda845e0b893b775e75a154e48e.zip |
Implement more TypeGeneralizing transfer functions (#6118)
Finish the transfer functions for all expressions except for string
instructions, exception handling instructions, tuple instructions, and branch
instructions that carry values. The latter require more work in the CFG builder
because dropping the extra stack values happens after the branch but before the
target block.
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) + ) + ) ) |