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

;; Check that string types are emitted properly in the binary format.
;;
;; runs --precompute in order to verify no problems occur in the optimizer's
;; invocation of the interpreter.

;; RUN: wasm-opt %s --enable-strings --enable-reference-types --enable-gc --roundtrip --precompute -S -o - | filecheck %s

;; Check that we can roundtrip through the text format as well.

;; RUN: wasm-opt %s -all -S -o - | wasm-opt -all --precompute -S -o - | filecheck %s

(module
  ;; CHECK:      (type $0 (func (param stringref stringref)))

  ;; CHECK:      (type $array (array (mut i8)))
  (type $array (array (mut i8)))
  ;; CHECK:      (type $array16 (array (mut i16)))
  (type $array16 (array (mut i16)))

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

  ;; CHECK:      (type $4 (func (result externref)))

  ;; CHECK:      (type $5 (func (param (ref string))))

  ;; CHECK:      (type $6 (func (param stringref)))

  ;; CHECK:      (type $7 (func (param (ref $array) (ref $array16))))

  ;; CHECK:      (type $8 (func (param stringref (ref $array) (ref $array16))))

  ;; CHECK:      (import "env" "get-string-ref" (func $get-string-ref (type $4) (result externref)))
  (import "env" "get-string-ref" (func $get-string-ref  (result externref)))

  ;; CHECK:      (global $string-const stringref (string.const "string in a global \c2\a3_\e2\82\ac_\f0\90\8d\88 \01\00\t\t\n\n\r\r\"\"\'\'\\\\ "))
  (global $string-const stringref (string.const "string in a global \C2\A3_\E2\82\AC_\F0\90\8D\88 \01\00\t\t\n\n\r\r\"\"\'\'\\\\ "))

  ;; CHECK:      (memory $0 10 10)
  (memory $0 10 10)

  ;; CHECK:      (func $string.const (type $5) (param $param (ref string))
  ;; CHECK-NEXT:  (call $string.const
  ;; CHECK-NEXT:   (string.const "foo")
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (call $string.const
  ;; CHECK-NEXT:   (string.const "foo")
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (call $string.const
  ;; CHECK-NEXT:   (string.const "bar")
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.const (param $param (ref string))
    ;; Use calls to avoid precompute removing dropped constants.
    (call $string.const
      (string.const "foo")
    )
    (call $string.const
      (string.const "foo") ;; intentionally repeat the previous one
    )
    (call $string.const
      (string.const "bar")
    )
  )

  ;; CHECK:      (func $string.measure (type $6) (param $ref stringref)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (string.measure_wtf16
  ;; CHECK-NEXT:     (local.get $ref)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (string.measure_utf8
  ;; CHECK-NEXT:    (local.get $ref)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.measure (param $ref stringref)
    (drop
      (i32.eqz ;; validate the output is i32
        (string.measure_wtf16
          (local.get $ref)
        )
      )
    )
    (drop
      (string.measure_utf8
        (local.get $ref)
      )
    )
  )

  ;; CHECK:      (func $string.concat (type $0) (param $a stringref) (param $b stringref)
  ;; CHECK-NEXT:  (local.set $a
  ;; CHECK-NEXT:   (string.concat
  ;; CHECK-NEXT:    (local.get $a)
  ;; CHECK-NEXT:    (local.get $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.concat (param $a stringref) (param $b stringref)
    (local.set $a ;; validate the output is a stringref
      (string.concat
        (local.get $a)
        (local.get $b)
      )
    )
  )

  ;; CHECK:      (func $string.eq (type $0) (param $a stringref) (param $b stringref)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (string.eq
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.eq (param $a stringref) (param $b stringref)
    (drop
      (i32.eqz ;; validate the output is an i32
        (string.eq
          (local.get $a)
          (local.get $b)
        )
      )
    )
  )

  ;; CHECK:      (func $string.compare (type $0) (param $a stringref) (param $b stringref)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (string.compare
  ;; CHECK-NEXT:     (local.get $a)
  ;; CHECK-NEXT:     (local.get $b)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.compare (param $a stringref) (param $b stringref)
    (drop
      (i32.eqz ;; validate the output is an i32
        (string.compare
          (local.get $a)
          (local.get $b)
        )
      )
    )
  )

  ;; CHECK:      (func $string.new.gc (type $7) (param $array (ref $array)) (param $array16 (ref $array16))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (string.new_wtf16_array
  ;; CHECK-NEXT:    (local.get $array16)
  ;; CHECK-NEXT:    (i32.const 7)
  ;; CHECK-NEXT:    (i32.const 8)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (string.new_lossy_utf8_array
  ;; CHECK-NEXT:    (local.get $array)
  ;; CHECK-NEXT:    (i32.const 5)
  ;; CHECK-NEXT:    (i32.const 6)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.new.gc (param $array (ref $array)) (param $array16 (ref $array16))
    (drop
      (string.new_wtf16_array
        (local.get $array16)
        (i32.const 7)
        (i32.const 8)
      )
    )
    (drop
      (string.new_lossy_utf8_array
        (local.get $array)
        (i32.const 5)
        (i32.const 6)
      )
    )
  )

  ;; CHECK:      (func $string.encode.gc (type $8) (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (string.encode_wtf16_array
  ;; CHECK-NEXT:     (local.get $ref)
  ;; CHECK-NEXT:     (local.get $array16)
  ;; CHECK-NEXT:     (i32.const 30)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (string.encode_lossy_utf8_array
  ;; CHECK-NEXT:    (local.get $ref)
  ;; CHECK-NEXT:    (local.get $array)
  ;; CHECK-NEXT:    (i32.const 10)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.encode.gc (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16))
    (drop
      (i32.eqz ;; validate the output is i32
        (string.encode_wtf16_array
          (local.get $ref)
          (local.get $array16)
          (i32.const 30)
        )
      )
    )
    (drop
      (string.encode_lossy_utf8_array
        (local.get $ref)
        (local.get $array)
        (i32.const 10)
      )
    )
  )

  ;; CHECK:      (func $string.from_code_point (type $3)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (string.from_code_point
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.from_code_point
    (drop
      (string.from_code_point
        (i32.const 1)
      )
    )
  )

  ;; CHECK:      (func $string.test (type $3)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.eqz
  ;; CHECK-NEXT:    (string.test
  ;; CHECK-NEXT:     (call $get-string-ref)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $string.test
    (drop
      (i32.eqz
        (string.test
          (call $get-string-ref)
        )
      )
    )
  )
)
