;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited.

;; RUN: wasm-opt %s --enable-bulk-memory --llvm-memory-copy-fill-lowering --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s

;; Tests derived from bulk-memory.wast spec tests

;; memory.copy
(module
  (import "fuzzing-support" "log-i32" (func $log-i32 (param i32)))
  (memory 1 1)
  (data (i32.const 0) "\aa\bb\cc\dd")

  (func $assert_load (param i32 i32)
    (if (i32.ne (local.get 1) (i32.load8_u (local.get 0)))
    (then (unreachable)))
  )

  (func $print_memory
    (local $i i32)
    (local.set 0 (i32.const 9))
    (loop $loop
      (call $log-i32 (local.get 0))
      (call $log-i32 (i32.load8_u (local.get 0)))
      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
      (br_if $loop (i32.ne (local.get 0) (i32.const 17)))
    )
  )

  ;; non-overlapping copy
  ;; CHECK:      [fuzz-exec] calling test1
  ;; CHECK-NEXT: [LoggingExternalInterface logging 9]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 10]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 11]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 13]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 14]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 15]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 16]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 9]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 10]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 170]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 11]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 187]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 204]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 13]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 221]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 14]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 15]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 16]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  (func $test1 (export "test1")
    (call $print_memory)
    (memory.copy (i32.const 10) (i32.const 0) (i32.const 4))
    (call $print_memory)
    (call $assert_load (i32.const 9) (i32.const 0))
    (call $assert_load (i32.const 10) (i32.const 0xaa))
    (call $assert_load (i32.const 11) (i32.const 0xbb))
    (call $assert_load (i32.const 12) (i32.const 0xcc))
    (call $assert_load (i32.const 13) (i32.const 0xdd))
    (call $assert_load (i32.const 14) (i32.const 0))
  )
  ;; Overlap, src > dst
  ;; CHECK:      [fuzz-exec] calling test2
  ;; CHECK-NEXT: [LoggingExternalInterface logging 9]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 187]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 10]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 204]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 11]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 221]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 204]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 13]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 221]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 14]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 15]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 16]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  (func $test2 (export "test2")
    (memory.copy (i32.const 8) (i32.const 10) (i32.const 4))
    (call $print_memory)
    (call $assert_load (i32.const 8) (i32.const 0xaa))
    (call $assert_load (i32.const 9) (i32.const 0xbb))
    (call $assert_load (i32.const 10) (i32.const 0xcc))
    (call $assert_load (i32.const 11) (i32.const 0xdd))
    (call $assert_load (i32.const 12) (i32.const 0xcc))
    (call $assert_load (i32.const 13) (i32.const 0xdd))
  )
  ;; Overlap, src < dst
  ;; CHECK:      [fuzz-exec] calling test3
  ;; CHECK-NEXT: [LoggingExternalInterface logging 9]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 187]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 10]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 11]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 170]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 187]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 13]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 204]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 14]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 221]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 15]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 204]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 16]
  ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
  (func $test3 (export "test3")
    (memory.copy (i32.const 10) (i32.const 7) (i32.const 6))
    (call $print_memory)
    (call $assert_load (i32.const 10) (i32.const 0x0))
    (call $assert_load (i32.const 11) (i32.const 0xaa))
    (call $assert_load (i32.const 12) (i32.const 0xbb))
    (call $assert_load (i32.const 13) (i32.const 0xcc))
    (call $assert_load (i32.const 14) (i32.const 0xdd))
    (call $assert_load (i32.const 15) (i32.const 0xcc))
    (call $assert_load (i32.const 16) (i32.const 0))
  )
  ;; Overlap src < dst but size is OOB (but the address does not overflow)
  ;; CHECK:      [fuzz-exec] calling test4a
  ;; CHECK-NEXT: [trap out of bounds segment access in memory.copy]
  (func $test4a (export "test4a")
    (memory.copy (i32.const 13) (i32.const 11) (i32.const 0x10000))
    (call $print_memory) ;; not reached.
  )
  ;; CHECK:      [fuzz-exec] calling test4b
  (func $test4b (export "test4b")
    (call $assert_load (i32.const 10) (i32.const 0x0))
    (call $assert_load (i32.const 11) (i32.const 0xaa))
    (call $assert_load (i32.const 12) (i32.const 0xbb))
    (call $assert_load (i32.const 13) (i32.const 0xcc))
    (call $assert_load (i32.const 14) (i32.const 0xdd))
    (call $assert_load (i32.const 15) (i32.const 0xcc))
    (call $assert_load (i32.const 16) (i32.const 0))
  )
  ;; Copy ending at memory limit is ok
  ;; CHECK:      [fuzz-exec] calling test5
  (func $test5 (export "test5")
    (memory.copy (i32.const 0xff00) (i32.const 0) (i32.const 0x100))
    (memory.copy (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100))
  )
  ;; Succeed when copying 0 bytes at the end of the region
  ;; CHECK:      [fuzz-exec] calling test6
  (func $test6 (export "test6")
    (memory.copy (i32.const 0x10000) (i32.const 0) (i32.const 0))
    (memory.copy (i32.const 0x0) (i32.const 0x10000) (i32.const 0))
  )
  ;; copying 0 bytes outside of the limit is not allowed.
  ;; CHECK:      [fuzz-exec] calling test7
  ;; CHECK-NEXT: [trap out of bounds segment access in memory.copy]
  (func $test7 (export "test7")
    (memory.copy (i32.const 0x10001) (i32.const 0) (i32.const 0x0))
  )
  ;; CHECK:      [fuzz-exec] calling test8
  ;; CHECK-NEXT: [trap out of bounds segment access in memory.copy]
  (func $test8 (export "test8")
    (memory.copy (i32.const 0x0) (i32.const 0x10001) (i32.const 0))
  )
)



;; CHECK:      [fuzz-exec] calling test1
;; CHECK-NEXT: [LoggingExternalInterface logging 9]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 11]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 12]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 13]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 14]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 15]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 16]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 9]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
;; CHECK-NEXT: [LoggingExternalInterface logging 170]
;; CHECK-NEXT: [LoggingExternalInterface logging 11]
;; CHECK-NEXT: [LoggingExternalInterface logging 187]
;; CHECK-NEXT: [LoggingExternalInterface logging 12]
;; CHECK-NEXT: [LoggingExternalInterface logging 204]
;; CHECK-NEXT: [LoggingExternalInterface logging 13]
;; CHECK-NEXT: [LoggingExternalInterface logging 221]
;; CHECK-NEXT: [LoggingExternalInterface logging 14]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 15]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 16]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]

;; CHECK:      [fuzz-exec] calling test2
;; CHECK-NEXT: [LoggingExternalInterface logging 9]
;; CHECK-NEXT: [LoggingExternalInterface logging 187]
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
;; CHECK-NEXT: [LoggingExternalInterface logging 204]
;; CHECK-NEXT: [LoggingExternalInterface logging 11]
;; CHECK-NEXT: [LoggingExternalInterface logging 221]
;; CHECK-NEXT: [LoggingExternalInterface logging 12]
;; CHECK-NEXT: [LoggingExternalInterface logging 204]
;; CHECK-NEXT: [LoggingExternalInterface logging 13]
;; CHECK-NEXT: [LoggingExternalInterface logging 221]
;; CHECK-NEXT: [LoggingExternalInterface logging 14]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 15]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 16]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]

;; CHECK:      [fuzz-exec] calling test3
;; CHECK-NEXT: [LoggingExternalInterface logging 9]
;; CHECK-NEXT: [LoggingExternalInterface logging 187]
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 11]
;; CHECK-NEXT: [LoggingExternalInterface logging 170]
;; CHECK-NEXT: [LoggingExternalInterface logging 12]
;; CHECK-NEXT: [LoggingExternalInterface logging 187]
;; CHECK-NEXT: [LoggingExternalInterface logging 13]
;; CHECK-NEXT: [LoggingExternalInterface logging 204]
;; CHECK-NEXT: [LoggingExternalInterface logging 14]
;; CHECK-NEXT: [LoggingExternalInterface logging 221]
;; CHECK-NEXT: [LoggingExternalInterface logging 15]
;; CHECK-NEXT: [LoggingExternalInterface logging 204]
;; CHECK-NEXT: [LoggingExternalInterface logging 16]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]

;; CHECK:      [fuzz-exec] calling test4a
;; CHECK-NEXT: [trap unreachable]

;; CHECK:      [fuzz-exec] calling test4b

;; CHECK:      [fuzz-exec] calling test5

;; CHECK:      [fuzz-exec] calling test6

;; CHECK:      [fuzz-exec] calling test7
;; CHECK-NEXT: [trap unreachable]

;; CHECK:      [fuzz-exec] calling test8
;; CHECK-NEXT: [trap unreachable]
;; CHECK-NEXT: [fuzz-exec] comparing test1
;; CHECK-NEXT: [fuzz-exec] comparing test2
;; CHECK-NEXT: [fuzz-exec] comparing test3
;; CHECK-NEXT: [fuzz-exec] comparing test4a
;; CHECK-NEXT: [fuzz-exec] comparing test4b
;; CHECK-NEXT: [fuzz-exec] comparing test5
;; CHECK-NEXT: [fuzz-exec] comparing test6
;; CHECK-NEXT: [fuzz-exec] comparing test7
;; CHECK-NEXT: [fuzz-exec] comparing test8
