diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/heap2local.wast | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index 2ce3e12dd..2e38b7e4e 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -4303,3 +4303,128 @@ ) ) ) + +;; Array casts to structs and arrays. +(module + ;; CHECK: (type $1 (func)) + + ;; CHECK: (type $0 (func (result (ref struct)))) + (type $0 (func (result (ref struct)))) + ;; CHECK: (type $3 (func (result structref))) + + ;; CHECK: (type $4 (func (result (ref array)))) + + ;; CHECK: (type $array (array i8)) + (type $array (array i8)) + + ;; CHECK: (func $array.cast.struct (type $0) (result (ref struct)) + ;; CHECK-NEXT: (local $eq (ref eq)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $array.cast.struct (result (ref struct)) + (local $eq (ref eq)) + ;; This cast will fail: we cast an array to struct. That we go through + ;; (ref eq) in the middle, which seems like it could cast to struct, should + ;; not confuse us. And, as the cast fails, the reference does not escape. + ;; We can optimize here and will emit an unreachable for the failing cast. + (ref.cast (ref struct) + (local.tee $eq + (array.new_fixed $array 0) + ) + ) + ) + + ;; CHECK: (func $array.cast.struct.null (type $3) (result structref) + ;; CHECK-NEXT: (local $eq (ref eq)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $array.cast.struct.null (result (ref null struct)) + (local $eq (ref eq)) + ;; As above but the cast is to a nullable type, which changes nothing. + (ref.cast (ref null struct) + (local.tee $eq + (array.new_fixed $array 0) + ) + ) + ) + + ;; CHECK: (func $array.cast.array (type $4) (result (ref array)) + ;; CHECK-NEXT: (local $eq (ref eq)) + ;; CHECK-NEXT: (ref.cast (ref array) + ;; CHECK-NEXT: (local.tee $eq + ;; CHECK-NEXT: (array.new_fixed $array 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array.cast.array (result (ref array)) + (local $eq (ref eq)) + ;; Now we cast to array, and the cast succeeds, so we escape, and do + ;; nothing to optimize. + (ref.cast (ref array) + (local.tee $eq + (array.new_fixed $array 0) + ) + ) + ) + + ;; CHECK: (func $array.cast.array.set (type $1) + ;; CHECK-NEXT: (local $eq (ref eq)) + ;; CHECK-NEXT: (local $array (ref array)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array.cast.array.set + (local $eq (ref eq)) + (local $array (ref array)) + ;; As above, but now we store the result in a local rather than return it + ;; out, so it does not escape. + (local.set $array + (ref.cast (ref array) + (local.tee $eq + (array.new_fixed $array 0) + ) + ) + ) + ) + + ;; CHECK: (func $array.cast.struct.set (type $1) + ;; CHECK-NEXT: (local $eq (ref eq)) + ;; CHECK-NEXT: (local $struct (ref struct)) + ;; CHECK-NEXT: (local.tee $struct + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array.cast.struct.set + (local $eq (ref eq)) + (local $struct (ref struct)) + ;; As above, but now the cast fails and is stored to a struct local. We do not + ;; escape and we emit an unreachable for the cast. + (local.set $struct + (ref.cast (ref struct) + (local.tee $eq + (array.new_fixed $array 0) + ) + ) + ) + ) +) |