(module
  (memory 0)
  (memory 0)
  (memory $m 1)
  (data (memory 2) (i32.const 0) "abcdefgh")
  (data (memory 2) (i32.const 0xfff8) "abcdefgh")

  (func (export "i32.load") (param $a i32) (result i32)
    (i32.load $m (local.get $a))
  )
  (func (export "i64.load") (param $a i32) (result i64)
    (i64.load $m (local.get $a))
  )
  (func (export "f32.load") (param $a i32) (result f32)
    (f32.load $m (local.get $a))
  )
  (func (export "f64.load") (param $a i32) (result f64)
    (f64.load $m (local.get $a))
  )
  (func (export "i32.load8_s") (param $a i32) (result i32)
    (i32.load8_s $m (local.get $a))
  )
  (func (export "i32.load8_u") (param $a i32) (result i32)
    (i32.load8_u $m (local.get $a))
  )
  (func (export "i32.load16_s") (param $a i32) (result i32)
    (i32.load16_s $m (local.get $a))
  )
  (func (export "i32.load16_u") (param $a i32) (result i32)
    (i32.load16_u $m (local.get $a))
  )
  (func (export "i64.load8_s") (param $a i32) (result i64)
    (i64.load8_s $m (local.get $a))
  )
  (func (export "i64.load8_u") (param $a i32) (result i64)
    (i64.load8_u $m (local.get $a))
  )
  (func (export "i64.load16_s") (param $a i32) (result i64)
    (i64.load16_s $m (local.get $a))
  )
  (func (export "i64.load16_u") (param $a i32) (result i64)
    (i64.load16_u $m (local.get $a))
  )
  (func (export "i64.load32_s") (param $a i32) (result i64)
    (i64.load32_s $m (local.get $a))
  )
  (func (export "i64.load32_u") (param $a i32) (result i64)
    (i64.load32_u $m (local.get $a))
  )
  (func (export "i32.store") (param $a i32) (param $v i32)
    (i32.store $m (local.get $a) (local.get $v))
  )
  (func (export "i64.store") (param $a i32) (param $v i64)
    (i64.store $m (local.get $a) (local.get $v))
  )
  (func (export "f32.store") (param $a i32) (param $v f32)
    (f32.store $m (local.get $a) (local.get $v))
  )
  (func (export "f64.store") (param $a i32) (param $v f64)
    (f64.store $m (local.get $a) (local.get $v))
  )
  (func (export "i32.store8") (param $a i32) (param $v i32)
    (i32.store8 $m (local.get $a) (local.get $v))
  )
  (func (export "i32.store16") (param $a i32) (param $v i32)
    (i32.store16 $m (local.get $a) (local.get $v))
  )
  (func (export "i64.store8") (param $a i32) (param $v i64)
    (i64.store8 $m (local.get $a) (local.get $v))
  )
  (func (export "i64.store16") (param $a i32) (param $v i64)
    (i64.store16 $m (local.get $a) (local.get $v))
  )
  (func (export "i64.store32") (param $a i32) (param $v i64)
    (i64.store32 $m (local.get $a) (local.get $v))
  )
)

(assert_trap (invoke "i32.store" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const 0xfffe) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const -1) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const -2) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const -3) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store" (i32.const -4) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfffc) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfffb) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfffa) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -1) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -2) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -3) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -4) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -5) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -6) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -7) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store" (i32.const -8) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const 0x10000) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const 0xffff) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const 0xfffe) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const -1) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const -2) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const -3) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f32.store" (i32.const -4) (f32.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0x10000) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xffff) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfffe) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfffd) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfffc) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfffb) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfffa) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -1) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -2) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -3) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -4) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -5) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -6) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -7) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "f64.store" (i32.const -8) (f64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store8" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store8" (i32.const -1) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store16" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store16" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store16" (i32.const -1) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.store16" (i32.const -2) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store8" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store8" (i32.const -1) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store16" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store16" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store16" (i32.const -1) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store16" (i32.const -2) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const -1) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const -2) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const -3) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i64.store32" (i32.const -4) (i64.const 0)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "i32.load" (i32.const -4)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfffc)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfffb)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfffa)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const 0xfff9)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -4)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -5)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -6)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -7)) "out of bounds memory access")
(assert_trap (invoke "i64.load" (i32.const -8)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "f32.load" (i32.const -4)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfffc)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfffb)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfffa)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const 0xfff9)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -4)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -5)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -6)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -7)) "out of bounds memory access")
(assert_trap (invoke "f64.load" (i32.const -8)) "out of bounds memory access")
(assert_trap (invoke "i32.load8_s" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i32.load8_s" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i32.load8_u" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i32.load8_u" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_s" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_s" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_s" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_s" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_u" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_u" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_u" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i32.load16_u" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load8_s" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load8_s" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load8_u" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load8_u" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_s" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_s" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_s" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_s" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_u" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_u" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_u" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load16_u" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_s" (i32.const -4)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const 0x10000)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const 0xffff)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const 0xfffe)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const 0xfffd)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const -2)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const -3)) "out of bounds memory access")
(assert_trap (invoke "i64.load32_u" (i32.const -4)) "out of bounds memory access")

;; No memory was changed
(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0x6867666564636261))
(assert_return (invoke "i64.load" (i32.const 0)) (i64.const 0x6867666564636261))

;; Check that out of bounds store do not store partial data.
;; Zero last 8 bytes.
(assert_return (invoke "i64.store" (i32.const 0xfff8) (i64.const 0)))
(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0x12345678)) "out of bounds memory access")
(assert_return (invoke "i32.load" (i32.const 0xfffc)) (i32.const 0))
(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0x1234567890abcdef)) "out of bounds memory access")
(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0))
(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0x12345678)) "out of bounds memory access")
(assert_return (invoke "f32.load" (i32.const 0xfffc)) (f32.const 0))
(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0x1234567890abcdef)) "out of bounds memory access")
(assert_return (invoke "f64.load" (i32.const 0xfff8)) (f64.const 0))
