;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; RUN: foreach %s %t wasm-opt --type-ssa -all -S -o - | filecheck %s

;; TypeSSA should not fail on shared types.
(module
  ;; CHECK:      (type $struct (sub (shared (struct (field i32)))))
  (type $struct (sub (shared (struct (field i32)))))

  ;; CHECK:      (type $1 (func))

  ;; CHECK:      (rec
  ;; CHECK-NEXT:  (type $struct_1 (sub $struct (shared (struct (field i32)))))

  ;; CHECK:       (type $struct_2 (sub $struct (shared (struct (field i32)))))

  ;; CHECK:       (type $struct_3 (sub $struct (shared (struct (field i32)))))

  ;; CHECK:       (type $struct_4 (sub $struct (shared (struct (field i32)))))

  ;; CHECK:       (type $struct_5 (sub $struct (shared (struct (field i32)))))

  ;; CHECK:      (global $g (ref $struct) (struct.new $struct_4
  ;; CHECK-NEXT:  (i32.const 42)
  ;; CHECK-NEXT: ))
  (global $g (ref $struct) (struct.new $struct
    (i32.const 42)
  ))

  ;; CHECK:      (global $h (ref $struct) (struct.new $struct_5
  ;; CHECK-NEXT:  (i32.const 42)
  ;; CHECK-NEXT: ))
  (global $h (ref $struct) (struct.new $struct
    (i32.const 42)
  ))

  ;; CHECK:      (func $foo (type $1)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new_default $struct_1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $struct_2
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $foo
    (drop
      (struct.new_default $struct)
    )
    (drop
      (struct.new $struct
        (i32.const 10)
      )
    )
  )

  ;; CHECK:      (func $another-func (type $1)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $struct_3
  ;; CHECK-NEXT:    (i32.const 100)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $another-func
    (drop
      (struct.new $struct
        (i32.const 100)
      )
    )
  )
)

;; We end up needing to do some extra work to ensure types are in a new rec
;; group, that is, that it does not overlap with an existing rec group. While
;; doing so we should apply shareability properly and not error. (Specifically,
;; when we create a new subtype of $A, it must differ from $B.)
(module
  ;; CHECK:      (type $A (sub (shared (array (mut i32)))))
  (type $A (sub (shared (array (mut i32)))))
  ;; CHECK:      (type $1 (func))

  ;; CHECK:      (type $B (sub $A (shared (array (mut i32)))))
  (type $B (sub $A (shared (array (mut i32)))))

  ;; CHECK:      (rec
  ;; CHECK-NEXT:  (type $A_1 (sub $A (shared (array (mut i32)))))

  ;; CHECK:       (type $4 (struct))

  ;; CHECK:      (func $func (type $1)
  ;; CHECK-NEXT:  (local $local (ref $B))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new_default $A_1
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $func
    ;; Keep the type $B alive.
    (local $local (ref $B))

    ;; Create an $A, which TypeSSA can specialize.
    (drop
      (array.new_default $A
        (i32.const 0)
      )
    )
  )
)

