summaryrefslogtreecommitdiff
path: root/test/spec
diff options
context:
space:
mode:
Diffstat (limited to 'test/spec')
-rw-r--r--test/spec/address64.wast589
-rw-r--r--test/spec/align64.wast866
-rw-r--r--test/spec/bulk-memory64.wast167
-rw-r--r--test/spec/endianness64.wast217
-rw-r--r--test/spec/float_memory64.wast157
-rw-r--r--test/spec/load64.wast567
-rw-r--r--test/spec/memory64.wast188
-rw-r--r--test/spec/memory_grow64.wast95
-rw-r--r--test/spec/memory_redundancy64.wast65
-rw-r--r--test/spec/memory_trap64.wast269
-rw-r--r--test/spec/old_address64.wast34
-rw-r--r--test/spec/resizing64.wast58
12 files changed, 3272 insertions, 0 deletions
diff --git a/test/spec/address64.wast b/test/spec/address64.wast
new file mode 100644
index 000000000..0003e5d00
--- /dev/null
+++ b/test/spec/address64.wast
@@ -0,0 +1,589 @@
+;; Load i32 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i64) (result i32)
+ (i32.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i64) (result i32)
+ (i32.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i64) (result i32)
+ (i32.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i64) (result i32)
+ (i32.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i64) (result i32)
+ (i32.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i64) (result i32)
+ (i32.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i64) (result i32)
+ (i32.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i64) (result i32)
+ (i32.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i64) (result i32)
+ (i32.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i64) (result i32)
+ (i32.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i64) (result i32)
+ (i32.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i64) (result i32)
+ (i32.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i64) (result i32)
+ (i32.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i64) (result i32)
+ (i32.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i64) (result i32)
+ (i32.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i64) (result i32)
+ (i32.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i64) (result i32)
+ (i32.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i64) (result i32)
+ (i32.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i64) (result i32)
+ (i32.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i64) (result i32)
+ (i32.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32_good1") (param $i i64) (result i32)
+ (i32.load offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good2") (param $i i64) (result i32)
+ (i32.load align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good3") (param $i i64) (result i32)
+ (i32.load offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32_good4") (param $i i64) (result i32)
+ (i32.load offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32_good5") (param $i i64) (result i32)
+ (i32.load offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i64)
+ (drop (i32.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i64)
+ (drop (i32.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i64)
+ (drop (i32.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i64)
+ (drop (i32.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32_bad") (param $i i64)
+ (drop (i32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good2" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good3" (i64.const 0)) (i32.const 98))
+(assert_return (invoke "8u_good4" (i64.const 0)) (i32.const 99))
+(assert_return (invoke "8u_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "8s_good1" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good2" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good3" (i64.const 0)) (i32.const 98))
+(assert_return (invoke "8s_good4" (i64.const 0)) (i32.const 99))
+(assert_return (invoke "8s_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "16u_good1" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good2" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good3" (i64.const 0)) (i32.const 25442))
+(assert_return (invoke "16u_good4" (i64.const 0)) (i32.const 25699))
+(assert_return (invoke "16u_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "16s_good1" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good2" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good3" (i64.const 0)) (i32.const 25442))
+(assert_return (invoke "16s_good4" (i64.const 0)) (i32.const 25699))
+(assert_return (invoke "16s_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "32_good1" (i64.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good2" (i64.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good3" (i64.const 0)) (i32.const 1701077858))
+(assert_return (invoke "32_good4" (i64.const 0)) (i32.const 1717920867))
+(assert_return (invoke "32_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "8u_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8u_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good4" (i64.const 65508)) (i32.const 0))
+(assert_trap (invoke "32_good5" (i64.const 65508)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 1)) "out of bounds memory access")
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (drop (i32.load offset=4294967296 (i64.const 0))))"
+ )
+ "i32 constant"
+)
+
+;; Load i64 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i64) (result i64)
+ (i64.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i64) (result i64)
+ (i64.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i64) (result i64)
+ (i64.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i64) (result i64)
+ (i64.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i64) (result i64)
+ (i64.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i64) (result i64)
+ (i64.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i64) (result i64)
+ (i64.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i64) (result i64)
+ (i64.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i64) (result i64)
+ (i64.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i64) (result i64)
+ (i64.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i64) (result i64)
+ (i64.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i64) (result i64)
+ (i64.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i64) (result i64)
+ (i64.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i64) (result i64)
+ (i64.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i64) (result i64)
+ (i64.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i64) (result i64)
+ (i64.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i64) (result i64)
+ (i64.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i64) (result i64)
+ (i64.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i64) (result i64)
+ (i64.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i64) (result i64)
+ (i64.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32u_good1") (param $i i64) (result i64)
+ (i64.load32_u offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good2") (param $i i64) (result i64)
+ (i64.load32_u align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good3") (param $i i64) (result i64)
+ (i64.load32_u offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32u_good4") (param $i i64) (result i64)
+ (i64.load32_u offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32u_good5") (param $i i64) (result i64)
+ (i64.load32_u offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "32s_good1") (param $i i64) (result i64)
+ (i64.load32_s offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good2") (param $i i64) (result i64)
+ (i64.load32_s align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good3") (param $i i64) (result i64)
+ (i64.load32_s offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32s_good4") (param $i i64) (result i64)
+ (i64.load32_s offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32s_good5") (param $i i64) (result i64)
+ (i64.load32_s offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "64_good1") (param $i i64) (result i64)
+ (i64.load offset=0 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good2") (param $i i64) (result i64)
+ (i64.load align=1 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good3") (param $i i64) (result i64)
+ (i64.load offset=1 align=1 (local.get $i)) ;; 0x6968676665646362 'bcdefghi'
+ )
+ (func (export "64_good4") (param $i i64) (result i64)
+ (i64.load offset=2 align=2 (local.get $i)) ;; 0x6a69686766656463 'cdefghij'
+ )
+ (func (export "64_good5") (param $i i64) (result i64)
+ (i64.load offset=25 align=8 (local.get $i)) ;; 122 'z\0\0\0\0\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i64)
+ (drop (i64.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i64)
+ (drop (i64.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i64)
+ (drop (i64.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i64)
+ (drop (i64.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32u_bad") (param $i i64)
+ (drop (i64.load32_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "32s_bad") (param $i i64)
+ (drop (i64.load32_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "64_bad") (param $i i64)
+ (drop (i64.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good2" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good3" (i64.const 0)) (i64.const 98))
+(assert_return (invoke "8u_good4" (i64.const 0)) (i64.const 99))
+(assert_return (invoke "8u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "8s_good1" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good2" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good3" (i64.const 0)) (i64.const 98))
+(assert_return (invoke "8s_good4" (i64.const 0)) (i64.const 99))
+(assert_return (invoke "8s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "16u_good1" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good2" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good3" (i64.const 0)) (i64.const 25442))
+(assert_return (invoke "16u_good4" (i64.const 0)) (i64.const 25699))
+(assert_return (invoke "16u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "16s_good1" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good2" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good3" (i64.const 0)) (i64.const 25442))
+(assert_return (invoke "16s_good4" (i64.const 0)) (i64.const 25699))
+(assert_return (invoke "16s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "32u_good1" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good2" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good3" (i64.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32u_good4" (i64.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "32s_good1" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good2" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good3" (i64.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32s_good4" (i64.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "64_good1" (i64.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good2" (i64.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good3" (i64.const 0)) (i64.const 0x6968676665646362))
+(assert_return (invoke "64_good4" (i64.const 0)) (i64.const 0x6a69686766656463))
+(assert_return (invoke "64_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "8u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good4" (i64.const 65504)) (i64.const 0))
+(assert_trap (invoke "64_good5" (i64.const 65504)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 1)) "out of bounds memory access")
+
+;; Load f32 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\a0\7f\01\00\d0\7f")
+
+ (func (export "32_good1") (param $i i64) (result f32)
+ (f32.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good2") (param $i i64) (result f32)
+ (f32.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good3") (param $i i64) (result f32)
+ (f32.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good4") (param $i i64) (result f32)
+ (f32.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good5") (param $i i64) (result f32)
+ (f32.load offset=8 align=4 (local.get $i)) ;; nan:0x500001 '\01\00\d0\7f'
+ )
+ (func (export "32_bad") (param $i i64)
+ (drop (f32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "32_good1" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good5" (i64.const 0)) (f32.const nan:0x500001))
+
+(assert_return (invoke "32_good1" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good5" (i64.const 65524)) (f32.const 0.0))
+
+(assert_return (invoke "32_good1" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 65525)) (f32.const 0.0))
+(assert_trap (invoke "32_good5" (i64.const 65525)) "out of bounds memory access")
+
+(assert_trap (invoke "32_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 1)) "out of bounds memory access")
+
+;; Load f64 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f\01\00\00\00\00\00\fc\7f")
+
+ (func (export "64_good1") (param $i i64) (result f64)
+ (f64.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good2") (param $i i64) (result f64)
+ (f64.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good3") (param $i i64) (result f64)
+ (f64.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good4") (param $i i64) (result f64)
+ (f64.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good5") (param $i i64) (result f64)
+ (f64.load offset=18 align=8 (local.get $i)) ;; nan:0xc000000000001 '\01\00\00\00\00\00\fc\7f'
+ )
+ (func (export "64_bad") (param $i i64)
+ (drop (f64.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "64_good1" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good5" (i64.const 0)) (f64.const nan:0xc000000000001))
+
+(assert_return (invoke "64_good1" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good5" (i64.const 65510)) (f64.const 0.0))
+
+(assert_return (invoke "64_good1" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 65511)) (f64.const 0.0))
+(assert_trap (invoke "64_good5" (i64.const 65511)) "out of bounds memory access")
+
+(assert_trap (invoke "64_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 1)) "out of bounds memory access")
diff --git a/test/spec/align64.wast b/test/spec/align64.wast
new file mode 100644
index 000000000..da34947f6
--- /dev/null
+++ b/test/spec/align64.wast
@@ -0,0 +1,866 @@
+;; Test alignment annotation rules
+
+(module (memory i64 0) (func (drop (i32.load8_s align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load8_u align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load16_s align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load16_u align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load8_s align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load8_u align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load16_s align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load16_u align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load32_s align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load32_u align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load align=8 (i64.const 0)))))
+(module (memory i64 0) (func (drop (f32.load align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (f64.load align=8 (i64.const 0)))))
+(module (memory i64 0) (func (i32.store8 align=1 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i32.store16 align=2 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i32.store align=4 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i64.store8 align=1 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store16 align=2 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store32 align=4 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store align=8 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (f32.store align=4 (i64.const 0) (f32.const 1.0))))
+(module (memory i64 0) (func (f64.store align=8 (i64.const 0) (f64.const 1.0))))
+
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f32.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f32.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f64.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f64.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store8 align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store8 align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store16 align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store16 align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store8 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store8 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store16 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store16 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store32 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store32 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f32.store align=0 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f32.store align=7 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f64.store align=0 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f64.store align=7 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_s align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_u align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_s align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_u align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (i32.store8 align=2 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i32.store16 align=4 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i32.store align=8 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store8 align=2 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store16 align=4 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store32 align=8 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store align=16 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (f32.store align=8 (i64.const 0) (f32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (f64.store align=16 (i64.const 0) (f64.const 0))))
+ "alignment must not be larger than natural"
+)
+
+;; Test aligned and unaligned read/write
+
+(module
+ (memory i64 1)
+
+ ;; $default: natural alignment, $1: align=1, $2: align=2, $4: align=4, $8: align=8
+
+ (func (export "f32_align_switch") (param i32) (result f32)
+ (local f32 f32)
+ (local.set 1 (f32.const 10.0))
+ (block $4
+ (block $2
+ (block $1
+ (block $default
+ (block $0
+ (br_table $0 $default $1 $2 $4 (local.get 0))
+ ) ;; 0
+ (f32.store (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load (i64.const 0)))
+ (br $4)
+ ) ;; default
+ (f32.store align=1 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=1 (i64.const 0)))
+ (br $4)
+ ) ;; 1
+ (f32.store align=2 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=2 (i64.const 0)))
+ (br $4)
+ ) ;; 2
+ (f32.store align=4 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=4 (i64.const 0)))
+ ) ;; 4
+ (local.get 2)
+ )
+
+ (func (export "f64_align_switch") (param i32) (result f64)
+ (local f64 f64)
+ (local.set 1 (f64.const 10.0))
+ (block $8
+ (block $4
+ (block $2
+ (block $1
+ (block $default
+ (block $0
+ (br_table $0 $default $1 $2 $4 $8 (local.get 0))
+ ) ;; 0
+ (f64.store (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load (i64.const 0)))
+ (br $8)
+ ) ;; default
+ (f64.store align=1 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=1 (i64.const 0)))
+ (br $8)
+ ) ;; 1
+ (f64.store align=2 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=2 (i64.const 0)))
+ (br $8)
+ ) ;; 2
+ (f64.store align=4 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=4 (i64.const 0)))
+ (br $8)
+ ) ;; 4
+ (f64.store align=8 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=8 (i64.const 0)))
+ ) ;; 8
+ (local.get 2)
+ )
+
+ ;; $8s: i32/i64.load8_s, $8u: i32/i64.load8_u, $16s: i32/i64.load16_s, $16u: i32/i64.load16_u, $32: i32.load
+ ;; $32s: i64.load32_s, $32u: i64.load32_u, $64: i64.load
+
+ (func (export "i32_align_switch") (param i32 i32) (result i32)
+ (local i32 i32)
+ (local.set 2 (i32.const 10))
+ (block $32
+ (block $16u
+ (block $16s
+ (block $8u
+ (block $8s
+ (block $0
+ (br_table $0 $8s $8u $16s $16u $32 (local.get 0))
+ ) ;; 0
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_s align=1 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 8s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_u align=1 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 8u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s align=2 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 16s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u align=2 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 16u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i32.store align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=4 (i64.const 0)))
+ )
+ )
+ ) ;; 32
+ (local.get 3)
+ )
+
+ (func (export "i64_align_switch") (param i32 i32) (result i64)
+ (local i64 i64)
+ (local.set 2 (i64.const 10))
+ (block $64
+ (block $32u
+ (block $32s
+ (block $16u
+ (block $16s
+ (block $8u
+ (block $8s
+ (block $0
+ (br_table $0 $8s $8u $16s $16u $32s $32u $64 (local.get 0))
+ ) ;; 0
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_s align=1 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 8s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_u align=1 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 8u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s align=2 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 16s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u align=2 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 16u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store32 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store32 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store32 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store32 align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=4 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 32s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store32 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store32 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store32 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store32 align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=4 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 32u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=4 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 8))
+ (then
+ (i64.store align=8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=8 (i64.const 0)))
+ )
+ )
+ ) ;; 64
+ (local.get 3)
+ )
+)
+
+(assert_return (invoke "f32_align_switch" (i32.const 0)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 1)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 2)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 3)) (f32.const 10.0))
+
+(assert_return (invoke "f64_align_switch" (i32.const 0)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 1)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 2)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 3)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 4)) (f64.const 10.0))
+
+(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 4)) (i32.const 10))
+
+(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 8)) (i64.const 10))
+
+;; Test that an i64 store with 4-byte alignment that's 4 bytes out of bounds traps without storing anything
+
+(module
+ (memory i64 1)
+ (func (export "store") (param i64 i64)
+ (i64.store align=4 (local.get 0) (local.get 1))
+ )
+ (func (export "load") (param i64) (result i32)
+ (i32.load (local.get 0))
+ )
+)
+
+(assert_trap (invoke "store" (i64.const 65532) (i64.const -1)) "out of bounds memory access")
+;; No memory was changed
+(assert_return (invoke "load" (i64.const 65532)) (i32.const 0))
diff --git a/test/spec/bulk-memory64.wast b/test/spec/bulk-memory64.wast
new file mode 100644
index 000000000..060191216
--- /dev/null
+++ b/test/spec/bulk-memory64.wast
@@ -0,0 +1,167 @@
+;; Passive segment syntax
+(module
+ (memory i64 1)
+ (data passive "foo"))
+
+;; memory.fill
+(module
+ (memory i64 1)
+
+ (func (export "fill") (param i64 i32 i64)
+ (memory.fill
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+;; Basic fill test.
+(invoke "fill" (i64.const 1) (i32.const 0xff) (i64.const 3))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 3)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 4)) (i32.const 0))
+
+;; Fill value is stored as a byte.
+(invoke "fill" (i64.const 0) (i32.const 0xbbaa) (i64.const 2))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xaa))
+
+;; Fill all of memory
+(invoke "fill" (i64.const 0) (i32.const 0) (i64.const 0x10000))
+
+;; Succeed when writing 0 bytes at the end of the region.
+(invoke "fill" (i64.const 0x10000) (i32.const 0) (i64.const 0))
+
+;; Writing 0 bytes outside of memory limit is NOT allowed.
+(assert_trap (invoke "fill" (i64.const 0x10001) (i32.const 0) (i64.const 0)))
+
+;; memory.copy
+(module
+ (memory i64 1 1)
+ (data (i32.const 0) "\aa\bb\cc\dd")
+
+ (func (export "copy") (param i64 i64 i64)
+ (memory.copy
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+;; Non-overlapping copy.
+(invoke "copy" (i64.const 10) (i64.const 0) (i64.const 4))
+
+(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0))
+
+;; Overlap, source > dest
+(invoke "copy" (i64.const 8) (i64.const 10) (i64.const 4))
+(assert_return (invoke "load8_u" (i64.const 8)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
+
+;; Overlap, source < dest
+(invoke "copy" (i64.const 10) (i64.const 7) (i64.const 6))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
+
+;; Overlap, source < dest but size is out of bounds
+(assert_trap (invoke "copy" (i64.const 13) (i64.const 11) (i64.const -1)))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
+
+;; Copy ending at memory limit is ok.
+(invoke "copy" (i64.const 0xff00) (i64.const 0) (i64.const 0x100))
+(invoke "copy" (i64.const 0xfe00) (i64.const 0xff00) (i64.const 0x100))
+
+;; Succeed when copying 0 bytes at the end of the region.
+(invoke "copy" (i64.const 0x10000) (i64.const 0) (i64.const 0))
+(invoke "copy" (i64.const 0) (i64.const 0x10000) (i64.const 0))
+
+;; Copying 0 bytes outside of memory limit is NOT allowed.
+(assert_trap (invoke "copy" (i64.const 0x10001) (i64.const 0) (i64.const 0)))
+(assert_trap (invoke "copy" (i64.const 0) (i64.const 0x10001) (i64.const 0)))
+
+;; memory.init
+(module
+ (memory i64 1)
+ (data passive "\aa\bb\cc\dd")
+
+ (func (export "init") (param i64 i32 i32)
+ (memory.init 0
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+(invoke "init" (i64.const 0) (i32.const 1) (i32.const 2))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0))
+
+;; Init ending at memory limit and segment limit is ok.
+(invoke "init" (i64.const 0xfffc) (i32.const 0) (i32.const 4))
+
+;; Out-of-bounds writes trap, and no partial writes has been made.
+(assert_trap (invoke "init" (i64.const 0xfffe) (i32.const 0) (i32.const 3))
+ "out of bounds memory access")
+(assert_return (invoke "load8_u" (i64.const 0xfffe)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 0xffff)) (i32.const 0xdd))
+
+;; Succeed when writing 0 bytes at the end of either region.
+(invoke "init" (i64.const 0x10000) (i32.const 0) (i32.const 0))
+(invoke "init" (i64.const 0) (i32.const 4) (i32.const 0))
+
+;; Writing 0 bytes outside of memory / segment limit is NOT allowed.
+(assert_trap (invoke "init" (i64.const 0x10001) (i32.const 0) (i32.const 0)))
+(assert_trap (invoke "init" (i64.const 0) (i32.const 5) (i32.const 0)))
+
+;; OK to access 0 bytes at offset 0 in a dropped segment.
+(invoke "init" (i64.const 0) (i32.const 0) (i32.const 0))
+
+;; data.drop
+(module
+ (memory i64 1)
+ (data passive "")
+ (data (i32.const 0) "")
+
+ (func (export "drop_passive") (data.drop 0))
+ (func (export "init_passive")
+ (memory.init 0 (i64.const 0) (i32.const 0) (i32.const 0)))
+
+ (func (export "drop_active") (data.drop 1))
+ (func (export "init_active")
+ (memory.init 1 (i64.const 0) (i32.const 0) (i32.const 0)))
+)
+
+;; OK to drop the same segment multiple times or drop an active segment.
+(invoke "init_passive")
+(invoke "drop_passive")
+(invoke "drop_passive")
+(invoke "drop_active")
diff --git a/test/spec/endianness64.wast b/test/spec/endianness64.wast
new file mode 100644
index 000000000..e583ea9b4
--- /dev/null
+++ b/test/spec/endianness64.wast
@@ -0,0 +1,217 @@
+(module
+ (memory i64 1)
+
+ ;; Stores an i16 value in little-endian-format
+ (func $i16_store_little (param $address i64) (param $value i32)
+ (i32.store8 (local.get $address) (local.get $value))
+ (i32.store8 (i64.add (local.get $address) (i64.const 1)) (i32.shr_u (local.get $value) (i32.const 8)))
+ )
+
+ ;; Stores an i32 value in little-endian format
+ (func $i32_store_little (param $address i64) (param $value i32)
+ (call $i16_store_little (local.get $address) (local.get $value))
+ (call $i16_store_little (i64.add (local.get $address) (i64.const 2)) (i32.shr_u (local.get $value) (i32.const 16)))
+ )
+
+ ;; Stores an i64 value in little-endian format
+ (func $i64_store_little (param $address i64) (param $value i64)
+ (call $i32_store_little (local.get $address) (i32.wrap_i64 (local.get $value)))
+ (call $i32_store_little (i64.add (local.get $address) (i64.const 4)) (i32.wrap_i64 (i64.shr_u (local.get $value) (i64.const 32))))
+ )
+
+ ;; Loads an i16 value in little-endian format
+ (func $i16_load_little (param $address i64) (result i32)
+ (i32.or
+ (i32.load8_u (local.get $address))
+ (i32.shl (i32.load8_u (i64.add (local.get $address) (i64.const 1))) (i32.const 8))
+ )
+ )
+
+ ;; Loads an i32 value in little-endian format
+ (func $i32_load_little (param $address i64) (result i32)
+ (i32.or
+ (call $i16_load_little (local.get $address))
+ (i32.shl (call $i16_load_little (i64.add (local.get $address) (i64.const 2))) (i32.const 16))
+ )
+ )
+
+ ;; Loads an i64 value in little-endian format
+ (func $i64_load_little (param $address i64) (result i64)
+ (i64.or
+ (i64.extend_i32_u (call $i32_load_little (local.get $address)))
+ (i64.shl (i64.extend_i32_u (call $i32_load_little (i64.add (local.get $address) (i64.const 4)))) (i64.const 32))
+ )
+ )
+
+ (func (export "i32_load16_s") (param $value i32) (result i32)
+ (call $i16_store_little (i64.const 0) (local.get $value))
+ (i32.load16_s (i64.const 0))
+ )
+
+ (func (export "i32_load16_u") (param $value i32) (result i32)
+ (call $i16_store_little (i64.const 0) (local.get $value))
+ (i32.load16_u (i64.const 0))
+ )
+
+ (func (export "i32_load") (param $value i32) (result i32)
+ (call $i32_store_little (i64.const 0) (local.get $value))
+ (i32.load (i64.const 0))
+ )
+
+ (func (export "i64_load16_s") (param $value i64) (result i64)
+ (call $i16_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load16_s (i64.const 0))
+ )
+
+ (func (export "i64_load16_u") (param $value i64) (result i64)
+ (call $i16_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load16_u (i64.const 0))
+ )
+
+ (func (export "i64_load32_s") (param $value i64) (result i64)
+ (call $i32_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load32_s (i64.const 0))
+ )
+
+ (func (export "i64_load32_u") (param $value i64) (result i64)
+ (call $i32_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load32_u (i64.const 0))
+ )
+
+ (func (export "i64_load") (param $value i64) (result i64)
+ (call $i64_store_little (i64.const 0) (local.get $value))
+ (i64.load (i64.const 0))
+ )
+
+ (func (export "f32_load") (param $value f32) (result f32)
+ (call $i32_store_little (i64.const 0) (i32.reinterpret_f32 (local.get $value)))
+ (f32.load (i64.const 0))
+ )
+
+ (func (export "f64_load") (param $value f64) (result f64)
+ (call $i64_store_little (i64.const 0) (i64.reinterpret_f64 (local.get $value)))
+ (f64.load (i64.const 0))
+ )
+
+
+ (func (export "i32_store16") (param $value i32) (result i32)
+ (i32.store16 (i64.const 0) (local.get $value))
+ (call $i16_load_little (i64.const 0))
+ )
+
+ (func (export "i32_store") (param $value i32) (result i32)
+ (i32.store (i64.const 0) (local.get $value))
+ (call $i32_load_little (i64.const 0))
+ )
+
+ (func (export "i64_store16") (param $value i64) (result i64)
+ (i64.store16 (i64.const 0) (local.get $value))
+ (i64.extend_i32_u (call $i16_load_little (i64.const 0)))
+ )
+
+ (func (export "i64_store32") (param $value i64) (result i64)
+ (i64.store32 (i64.const 0) (local.get $value))
+ (i64.extend_i32_u (call $i32_load_little (i64.const 0)))
+ )
+
+ (func (export "i64_store") (param $value i64) (result i64)
+ (i64.store (i64.const 0) (local.get $value))
+ (call $i64_load_little (i64.const 0))
+ )
+
+ (func (export "f32_store") (param $value f32) (result f32)
+ (f32.store (i64.const 0) (local.get $value))
+ (f32.reinterpret_i32 (call $i32_load_little (i64.const 0)))
+ )
+
+ (func (export "f64_store") (param $value f64) (result f64)
+ (f64.store (i64.const 0) (local.get $value))
+ (f64.reinterpret_i64 (call $i64_load_little (i64.const 0)))
+ )
+)
+
+(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load16_s" (i32.const -4242)) (i32.const -4242))
+(assert_return (invoke "i32_load16_s" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_load16_s" (i32.const 0x3210)) (i32.const 0x3210))
+
+(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 0xFFFF))
+(assert_return (invoke "i32_load16_u" (i32.const -4242)) (i32.const 61294))
+(assert_return (invoke "i32_load16_u" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_load16_u" (i32.const 0xCAFE)) (i32.const 0xCAFE))
+
+(assert_return (invoke "i32_load" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load" (i32.const -42424242)) (i32.const -42424242))
+(assert_return (invoke "i32_load" (i32.const 42424242)) (i32.const 42424242))
+(assert_return (invoke "i32_load" (i32.const 0xABAD1DEA)) (i32.const 0xABAD1DEA))
+
+(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load16_s" (i64.const -4242)) (i64.const -4242))
+(assert_return (invoke "i64_load16_s" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_load16_s" (i64.const 0x3210)) (i64.const 0x3210))
+
+(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 0xFFFF))
+(assert_return (invoke "i64_load16_u" (i64.const -4242)) (i64.const 61294))
+(assert_return (invoke "i64_load16_u" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_load16_u" (i64.const 0xCAFE)) (i64.const 0xCAFE))
+
+(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load32_s" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_load32_s" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_load32_s" (i64.const 0x12345678)) (i64.const 0x12345678))
+
+(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 0xFFFFFFFF))
+(assert_return (invoke "i64_load32_u" (i64.const -42424242)) (i64.const 4252543054))
+(assert_return (invoke "i64_load32_u" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_load32_u" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+
+(assert_return (invoke "i64_load" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_load" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+(assert_return (invoke "i64_load" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA))
+
+(assert_return (invoke "f32_load" (f32.const -1)) (f32.const -1))
+(assert_return (invoke "f32_load" (f32.const 1234e-5)) (f32.const 1234e-5))
+(assert_return (invoke "f32_load" (f32.const 4242.4242)) (f32.const 4242.4242))
+(assert_return (invoke "f32_load" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127))
+
+(assert_return (invoke "f64_load" (f64.const -1)) (f64.const -1))
+(assert_return (invoke "f64_load" (f64.const 123456789e-5)) (f64.const 123456789e-5))
+(assert_return (invoke "f64_load" (f64.const 424242.424242)) (f64.const 424242.424242))
+(assert_return (invoke "f64_load" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023))
+
+
+(assert_return (invoke "i32_store16" (i32.const -1)) (i32.const 0xFFFF))
+(assert_return (invoke "i32_store16" (i32.const -4242)) (i32.const 61294))
+(assert_return (invoke "i32_store16" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_store16" (i32.const 0xCAFE)) (i32.const 0xCAFE))
+
+(assert_return (invoke "i32_store" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_store" (i32.const -4242)) (i32.const -4242))
+(assert_return (invoke "i32_store" (i32.const 42424242)) (i32.const 42424242))
+(assert_return (invoke "i32_store" (i32.const 0xDEADCAFE)) (i32.const 0xDEADCAFE))
+
+(assert_return (invoke "i64_store16" (i64.const -1)) (i64.const 0xFFFF))
+(assert_return (invoke "i64_store16" (i64.const -4242)) (i64.const 61294))
+(assert_return (invoke "i64_store16" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_store16" (i64.const 0xCAFE)) (i64.const 0xCAFE))
+
+(assert_return (invoke "i64_store32" (i64.const -1)) (i64.const 0xFFFFFFFF))
+(assert_return (invoke "i64_store32" (i64.const -4242)) (i64.const 4294963054))
+(assert_return (invoke "i64_store32" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_store32" (i64.const 0xDEADCAFE)) (i64.const 0xDEADCAFE))
+
+(assert_return (invoke "i64_store" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_store" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_store" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+(assert_return (invoke "i64_store" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA))
+
+(assert_return (invoke "f32_store" (f32.const -1)) (f32.const -1))
+(assert_return (invoke "f32_store" (f32.const 1234e-5)) (f32.const 1234e-5))
+(assert_return (invoke "f32_store" (f32.const 4242.4242)) (f32.const 4242.4242))
+(assert_return (invoke "f32_store" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127))
+
+(assert_return (invoke "f64_store" (f64.const -1)) (f64.const -1))
+(assert_return (invoke "f64_store" (f64.const 123456789e-5)) (f64.const 123456789e-5))
+(assert_return (invoke "f64_store" (f64.const 424242.424242)) (f64.const 424242.424242))
+(assert_return (invoke "f64_store" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023))
diff --git a/test/spec/float_memory64.wast b/test/spec/float_memory64.wast
new file mode 100644
index 000000000..6834fdf60
--- /dev/null
+++ b/test/spec/float_memory64.wast
@@ -0,0 +1,157 @@
+;; Test that floating-point load and store are bit-preserving.
+
+;; Test that load and store do not canonicalize NaNs as x87 does.
+
+(module
+ (memory (data i64 "\00\00\a0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 0)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 0)))
+ (func (export "f32.store") (f32.store (i64.const 0) (f32.const nan:0x200000)))
+ (func (export "i32.store") (i32.store (i64.const 0) (i32.const 0x7fa00000)))
+ (func (export "reset") (i32.store (i64.const 0) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+
+(module
+ (memory (data i64 "\00\00\00\00\00\00\f4\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 0)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 0)))
+ (func (export "f64.store") (f64.store (i64.const 0) (f64.const nan:0x4000000000000)))
+ (func (export "i64.store") (i64.store (i64.const 0) (i64.const 0x7ff4000000000000)))
+ (func (export "reset") (i64.store (i64.const 0) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+
+;; Test that unaligned load and store do not canonicalize NaNs.
+
+(module
+ (memory (data i64 "\00\00\00\a0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 1)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 1)))
+ (func (export "f32.store") (f32.store (i64.const 1) (f32.const nan:0x200000)))
+ (func (export "i32.store") (i32.store (i64.const 1) (i32.const 0x7fa00000)))
+ (func (export "reset") (i32.store (i64.const 1) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+
+(module
+ (memory (data i64 "\00\00\00\00\00\00\00\f4\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 1)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 1)))
+ (func (export "f64.store") (f64.store (i64.const 1) (f64.const nan:0x4000000000000)))
+ (func (export "i64.store") (i64.store (i64.const 1) (i64.const 0x7ff4000000000000)))
+ (func (export "reset") (i64.store (i64.const 1) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+
+;; Test that load and store do not canonicalize NaNs as some JS engines do.
+
+(module
+ (memory (data i64 "\01\00\d0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 0)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 0)))
+ (func (export "f32.store") (f32.store (i64.const 0) (f32.const nan:0x500001)))
+ (func (export "i32.store") (i32.store (i64.const 0) (i32.const 0x7fd00001)))
+ (func (export "reset") (i32.store (i64.const 0) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+
+(module
+ (memory (data i64 "\01\00\00\00\00\00\fc\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 0)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 0)))
+ (func (export "f64.store") (f64.store (i64.const 0) (f64.const nan:0xc000000000001)))
+ (func (export "i64.store") (i64.store (i64.const 0) (i64.const 0x7ffc000000000001)))
+ (func (export "reset") (i64.store (i64.const 0) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
diff --git a/test/spec/load64.wast b/test/spec/load64.wast
new file mode 100644
index 000000000..e4a6a9833
--- /dev/null
+++ b/test/spec/load64.wast
@@ -0,0 +1,567 @@
+;; Load operator as the argument of control constructs and instructions
+
+(module
+ (memory i64 1)
+
+ (func (export "as-br-value") (result i32)
+ (block (result i32) (br 0 (i32.load (i64.const 0))))
+ )
+
+ (func (export "as-br_if-cond")
+ (block (br_if 0 (i32.load (i64.const 0))))
+ )
+ (func (export "as-br_if-value") (result i32)
+ (block (result i32)
+ (drop (br_if 0 (i32.load (i64.const 0)) (i32.const 1))) (i32.const 7)
+ )
+ )
+ (func (export "as-br_if-value-cond") (result i32)
+ (block (result i32)
+ (drop (br_if 0 (i32.const 6) (i32.load (i64.const 0)))) (i32.const 7)
+ )
+ )
+
+ (func (export "as-br_table-index")
+ (block (br_table 0 0 0 (i32.load (i64.const 0))))
+ )
+ (func (export "as-br_table-value") (result i32)
+ (block (result i32)
+ (br_table 0 0 0 (i32.load (i64.const 0)) (i32.const 1)) (i32.const 7)
+ )
+ )
+ (func (export "as-br_table-value-index") (result i32)
+ (block (result i32)
+ (br_table 0 0 (i32.const 6) (i32.load (i64.const 0))) (i32.const 7)
+ )
+ )
+
+ (func (export "as-return-value") (result i32)
+ (return (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-if-cond") (result i32)
+ (if (result i32) (i32.load (i64.const 0))
+ (then (i32.const 0)) (else (i32.const 1))
+ )
+ )
+ (func (export "as-if-then") (result i32)
+ (if (result i32) (i32.const 1)
+ (then (i32.load (i64.const 0))) (else (i32.const 0))
+ )
+ )
+ (func (export "as-if-else") (result i32)
+ (if (result i32) (i32.const 0)
+ (then (i32.const 0)) (else (i32.load (i64.const 0)))
+ )
+ )
+
+ (func (export "as-select-first") (param i32 i32) (result i32)
+ (select (i32.load (i64.const 0)) (local.get 0) (local.get 1))
+ )
+ (func (export "as-select-second") (param i32 i32) (result i32)
+ (select (local.get 0) (i32.load (i64.const 0)) (local.get 1))
+ )
+ (func (export "as-select-cond") (result i32)
+ (select (i32.const 0) (i32.const 1) (i32.load (i64.const 0)))
+ )
+
+ (func $f (param i32 i32 i32) (result i32) (i32.const -1))
+ (func (export "as-call-first") (result i32)
+ (call $f (i32.load (i64.const 0)) (i32.const 2) (i32.const 3))
+ )
+ (func (export "as-call-mid") (result i32)
+ (call $f (i32.const 1) (i32.load (i64.const 0)) (i32.const 3))
+ )
+ (func (export "as-call-last") (result i32)
+ (call $f (i32.const 1) (i32.const 2) (i32.load (i64.const 0)))
+ )
+
+ (type $sig (func (param i32 i32 i32) (result i32)))
+ (table funcref (elem $f))
+ (func (export "as-call_indirect-first") (result i32)
+ (call_indirect (type $sig)
+ (i32.load (i64.const 0)) (i32.const 2) (i32.const 3) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-mid") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.load (i64.const 0)) (i32.const 3) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-last") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.const 2) (i32.load (i64.const 0)) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-index") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.const 2) (i32.const 3) (i32.load (i64.const 0))
+ )
+ )
+
+ (func (export "as-local.set-value") (local i32)
+ (local.set 0 (i32.load (i64.const 0)))
+ )
+ (func (export "as-local.tee-value") (result i32) (local i32)
+ (local.tee 0 (i32.load (i64.const 0)))
+ )
+ (global $g (mut i32) (i32.const 0))
+ (func (export "as-global.set-value") (local i32)
+ (global.set $g (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-load-address") (result i32)
+ (i32.load (i64.load (i64.const 0)))
+ )
+ (func (export "as-loadN-address") (result i32)
+ (i32.load8_s (i64.load (i64.const 0)))
+ )
+
+ (func (export "as-store-address")
+ (i32.store (i64.load (i64.const 0)) (i32.const 7))
+ )
+ (func (export "as-store-value")
+ (i32.store (i64.const 2) (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-storeN-address")
+ (i32.store8 (i64.load8_s (i64.const 0)) (i32.const 7))
+ )
+ (func (export "as-storeN-value")
+ (i32.store16 (i64.const 2) (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-unary-operand") (result i32)
+ (i32.clz (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-binary-left") (result i32)
+ (i32.add (i32.load (i64.const 100)) (i32.const 10))
+ )
+ (func (export "as-binary-right") (result i32)
+ (i32.sub (i32.const 10) (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-test-operand") (result i32)
+ (i32.eqz (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-compare-left") (result i32)
+ (i32.le_s (i32.load (i64.const 100)) (i32.const 10))
+ )
+ (func (export "as-compare-right") (result i32)
+ (i32.ne (i32.const 10) (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-memory.grow-size") (result i64)
+ (memory.grow (i64.load (i64.const 100)))
+ )
+)
+
+(assert_return (invoke "as-br-value") (i32.const 0))
+
+(assert_return (invoke "as-br_if-cond"))
+(assert_return (invoke "as-br_if-value") (i32.const 0))
+(assert_return (invoke "as-br_if-value-cond") (i32.const 7))
+
+(assert_return (invoke "as-br_table-index"))
+(assert_return (invoke "as-br_table-value") (i32.const 0))
+(assert_return (invoke "as-br_table-value-index") (i32.const 6))
+
+(assert_return (invoke "as-return-value") (i32.const 0))
+
+(assert_return (invoke "as-if-cond") (i32.const 1))
+(assert_return (invoke "as-if-then") (i32.const 0))
+(assert_return (invoke "as-if-else") (i32.const 0))
+
+(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "as-select-cond") (i32.const 1))
+
+(assert_return (invoke "as-call-first") (i32.const -1))
+(assert_return (invoke "as-call-mid") (i32.const -1))
+(assert_return (invoke "as-call-last") (i32.const -1))
+
+(assert_return (invoke "as-call_indirect-first") (i32.const -1))
+(assert_return (invoke "as-call_indirect-mid") (i32.const -1))
+(assert_return (invoke "as-call_indirect-last") (i32.const -1))
+(assert_return (invoke "as-call_indirect-index") (i32.const -1))
+
+(assert_return (invoke "as-local.set-value"))
+(assert_return (invoke "as-local.tee-value") (i32.const 0))
+(assert_return (invoke "as-global.set-value"))
+
+(assert_return (invoke "as-load-address") (i32.const 0))
+(assert_return (invoke "as-loadN-address") (i32.const 0))
+(assert_return (invoke "as-store-address"))
+(assert_return (invoke "as-store-value"))
+(assert_return (invoke "as-storeN-address"))
+(assert_return (invoke "as-storeN-value"))
+
+(assert_return (invoke "as-unary-operand") (i32.const 32))
+
+(assert_return (invoke "as-binary-left") (i32.const 10))
+(assert_return (invoke "as-binary-right") (i32.const 10))
+
+(assert_return (invoke "as-test-operand") (i32.const 1))
+
+(assert_return (invoke "as-compare-left") (i32.const 1))
+(assert_return (invoke "as-compare-right") (i32.const 1))
+
+(assert_return (invoke "as-memory.grow-size") (i64.const 1))
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f32) (f32.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f32) (f32.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f64) (f64.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f64) (f64.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+
+;; load should have retval
+
+(assert_invalid
+ (module (memory i64 1) (func $load_i32 (i32.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_s_i32 (i32.load8_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_u_i32 (i32.load8_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_s_i32 (i32.load16_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_u_i32 (i32.load16_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_i64 (i64.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_s_i64 (i64.load8_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_u_i64 (i64.load8_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_s_i64 (i64.load16_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_u_i64 (i64.load16_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load32_s_i64 (i64.load32_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load32_u_i64 (i64.load32_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_f32 (f32.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_f64 (f64.load (i64.const 0))))
+ "type mismatch"
+)
+
+
+;; Type check
+
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load8_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load8_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load16_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load16_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load8_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load8_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load16_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load16_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load32_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load32_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result f32) (f32.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result f64) (f64.load (f32.const 0)))) "type mismatch")
+
+
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty
+ (i32.load) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-block
+ (i32.const 0)
+ (block (i32.load) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-loop
+ (i32.const 0)
+ (loop (i32.load) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-then
+ (i32.const 0) (i32.const 0)
+ (if (then (i32.load) (drop)))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-else
+ (i32.const 0) (i32.const 0)
+ (if (result i32) (then (i32.const 0)) (else (i32.load))) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br
+ (i32.const 0)
+ (block (br 0 (i32.load)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br_if
+ (i32.const 0)
+ (block (br_if 0 (i32.load) (i32.const 1)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br_table
+ (i32.const 0)
+ (block (br_table 0 (i32.load)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-return
+ (return (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-select
+ (select (i32.load) (i32.const 1) (i32.const 2)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-call
+ (call 1 (i32.load)) (drop)
+ )
+ (func (param i32) (result i32) (local.get 0))
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $f (param i32) (result i32) (local.get 0))
+ (type $sig (func (param i32) (result i32)))
+ (table funcref (elem $f))
+ (func $type-address-empty-in-call_indirect
+ (block (result i32)
+ (call_indirect (type $sig)
+ (i32.load) (i32.const 0)
+ )
+ (drop)
+ )
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-local.set
+ (local i32)
+ (local.set 0 (i32.load)) (local.get 0) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-local.tee
+ (local i32)
+ (local.tee 0 (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (global $x (mut i32) (i32.const 0))
+ (func $type-address-empty-in-global.set
+ (global.set $x (i32.load)) (global.get $x) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-memory.grow
+ (memory.grow (i64.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-load
+ (i32.load (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 1)
+ (func $type-address-empty-in-store
+ (i32.store (i32.load) (i32.const 1))
+ )
+ )
+ "type mismatch"
+)
diff --git a/test/spec/memory64.wast b/test/spec/memory64.wast
new file mode 100644
index 000000000..8424e0c0e
--- /dev/null
+++ b/test/spec/memory64.wast
@@ -0,0 +1,188 @@
+;; Test memory section structure
+
+(module (memory i64 0 0))
+(module (memory i64 0 1))
+(module (memory i64 1 256))
+(module (memory i64 0 65536))
+
+(assert_invalid (module (memory i64 0) (memory i64 0)) "multiple memories")
+(assert_invalid (module (memory (import "spectest" "memory") i64 0) (memory i64 0)) "multiple memories")
+
+(module (memory i64 (data)) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 0))
+(module (memory i64 (data "")) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 0))
+(module (memory i64 (data "x")) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 1))
+
+(assert_invalid (module (data (i32.const 0))) "unknown memory")
+(assert_invalid (module (data (i32.const 0) "")) "unknown memory")
+(assert_invalid (module (data (i32.const 0) "x")) "unknown memory")
+
+(assert_invalid
+ (module (func (drop (f32.load (i64.const 0)))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (f32.store (i64.const 0) (f32.const 0))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (i32.load8_s (i64.const 0)))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (i32.store8 (i64.const 0) (i32.const 0))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (memory.size))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (memory.grow (i64.const 0)))))
+ "unknown memory"
+)
+
+
+(assert_invalid
+ (module (memory i64 1 0))
+ "size minimum must not be greater than maximum"
+)
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "ABC\a7D") (data (i32.const 20) "WASM")
+
+ ;; Data section
+ (func (export "data") (result i32)
+ (i32.and
+ (i32.and
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 0)) (i32.const 65))
+ (i32.eq (i32.load8_u (i64.const 3)) (i32.const 167))
+ )
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 6)) (i32.const 0))
+ (i32.eq (i32.load8_u (i64.const 19)) (i32.const 0))
+ )
+ )
+ (i32.and
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 20)) (i32.const 87))
+ (i32.eq (i32.load8_u (i64.const 23)) (i32.const 77))
+ )
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 24)) (i32.const 0))
+ (i32.eq (i32.load8_u (i64.const 1023)) (i32.const 0))
+ )
+ )
+ )
+ )
+
+ ;; Memory cast
+ (func (export "cast") (result f64)
+ (i64.store (i64.const 8) (i64.const -12345))
+ (if
+ (f64.eq
+ (f64.load (i64.const 8))
+ (f64.reinterpret_i64 (i64.const -12345))
+ )
+ (then (return (f64.const 0)))
+ )
+ (i64.store align=1 (i64.const 9) (i64.const 0))
+ (i32.store16 align=1 (i64.const 15) (i32.const 16453))
+ (f64.load align=1 (i64.const 9))
+ )
+
+ ;; Sign and zero extending memory loads
+ (func (export "i32_load8_s") (param $i i32) (result i32)
+ (i32.store8 (i64.const 8) (local.get $i))
+ (i32.load8_s (i64.const 8))
+ )
+ (func (export "i32_load8_u") (param $i i32) (result i32)
+ (i32.store8 (i64.const 8) (local.get $i))
+ (i32.load8_u (i64.const 8))
+ )
+ (func (export "i32_load16_s") (param $i i32) (result i32)
+ (i32.store16 (i64.const 8) (local.get $i))
+ (i32.load16_s (i64.const 8))
+ )
+ (func (export "i32_load16_u") (param $i i32) (result i32)
+ (i32.store16 (i64.const 8) (local.get $i))
+ (i32.load16_u (i64.const 8))
+ )
+ (func (export "i64_load8_s") (param $i i64) (result i64)
+ (i64.store8 (i64.const 8) (local.get $i))
+ (i64.load8_s (i64.const 8))
+ )
+ (func (export "i64_load8_u") (param $i i64) (result i64)
+ (i64.store8 (i64.const 8) (local.get $i))
+ (i64.load8_u (i64.const 8))
+ )
+ (func (export "i64_load16_s") (param $i i64) (result i64)
+ (i64.store16 (i64.const 8) (local.get $i))
+ (i64.load16_s (i64.const 8))
+ )
+ (func (export "i64_load16_u") (param $i i64) (result i64)
+ (i64.store16 (i64.const 8) (local.get $i))
+ (i64.load16_u (i64.const 8))
+ )
+ (func (export "i64_load32_s") (param $i i64) (result i64)
+ (i64.store32 (i64.const 8) (local.get $i))
+ (i64.load32_s (i64.const 8))
+ )
+ (func (export "i64_load32_u") (param $i i64) (result i64)
+ (i64.store32 (i64.const 8) (local.get $i))
+ (i64.load32_u (i64.const 8))
+ )
+)
+
+(assert_return (invoke "data") (i32.const 1))
+(assert_return (invoke "cast") (f64.const 42.0))
+
+(assert_return (invoke "i32_load8_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load8_u" (i32.const -1)) (i32.const 255))
+(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 65535))
+
+(assert_return (invoke "i32_load8_s" (i32.const 100)) (i32.const 100))
+(assert_return (invoke "i32_load8_u" (i32.const 200)) (i32.const 200))
+(assert_return (invoke "i32_load16_s" (i32.const 20000)) (i32.const 20000))
+(assert_return (invoke "i32_load16_u" (i32.const 40000)) (i32.const 40000))
+
+(assert_return (invoke "i32_load8_s" (i32.const 0xfedc6543)) (i32.const 0x43))
+(assert_return (invoke "i32_load8_s" (i32.const 0x3456cdef)) (i32.const 0xffffffef))
+(assert_return (invoke "i32_load8_u" (i32.const 0xfedc6543)) (i32.const 0x43))
+(assert_return (invoke "i32_load8_u" (i32.const 0x3456cdef)) (i32.const 0xef))
+(assert_return (invoke "i32_load16_s" (i32.const 0xfedc6543)) (i32.const 0x6543))
+(assert_return (invoke "i32_load16_s" (i32.const 0x3456cdef)) (i32.const 0xffffcdef))
+(assert_return (invoke "i32_load16_u" (i32.const 0xfedc6543)) (i32.const 0x6543))
+(assert_return (invoke "i32_load16_u" (i32.const 0x3456cdef)) (i32.const 0xcdef))
+
+(assert_return (invoke "i64_load8_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load8_u" (i64.const -1)) (i64.const 255))
+(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 65535))
+(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 4294967295))
+
+(assert_return (invoke "i64_load8_s" (i64.const 100)) (i64.const 100))
+(assert_return (invoke "i64_load8_u" (i64.const 200)) (i64.const 200))
+(assert_return (invoke "i64_load16_s" (i64.const 20000)) (i64.const 20000))
+(assert_return (invoke "i64_load16_u" (i64.const 40000)) (i64.const 40000))
+(assert_return (invoke "i64_load32_s" (i64.const 20000)) (i64.const 20000))
+(assert_return (invoke "i64_load32_u" (i64.const 40000)) (i64.const 40000))
+
+(assert_return (invoke "i64_load8_s" (i64.const 0xfedcba9856346543)) (i64.const 0x43))
+(assert_return (invoke "i64_load8_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffffef))
+(assert_return (invoke "i64_load8_u" (i64.const 0xfedcba9856346543)) (i64.const 0x43))
+(assert_return (invoke "i64_load8_u" (i64.const 0x3456436598bacdef)) (i64.const 0xef))
+(assert_return (invoke "i64_load16_s" (i64.const 0xfedcba9856346543)) (i64.const 0x6543))
+(assert_return (invoke "i64_load16_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffcdef))
+(assert_return (invoke "i64_load16_u" (i64.const 0xfedcba9856346543)) (i64.const 0x6543))
+(assert_return (invoke "i64_load16_u" (i64.const 0x3456436598bacdef)) (i64.const 0xcdef))
+(assert_return (invoke "i64_load32_s" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543))
+(assert_return (invoke "i64_load32_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffff98bacdef))
+(assert_return (invoke "i64_load32_u" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543))
+(assert_return (invoke "i64_load32_u" (i64.const 0x3456436598bacdef)) (i64.const 0x98bacdef))
diff --git a/test/spec/memory_grow64.wast b/test/spec/memory_grow64.wast
new file mode 100644
index 000000000..90d8de607
--- /dev/null
+++ b/test/spec/memory_grow64.wast
@@ -0,0 +1,95 @@
+(module
+ (memory i64 0)
+
+ (func (export "load_at_zero") (result i32) (i32.load (i64.const 0)))
+ (func (export "store_at_zero") (i32.store (i64.const 0) (i32.const 2)))
+
+ (func (export "load_at_page_size") (result i32) (i32.load (i64.const 0x10000)))
+ (func (export "store_at_page_size") (i32.store (i64.const 0x10000) (i32.const 3)))
+
+ (func (export "grow") (param $sz i64) (result i64) (memory.grow (local.get $sz)))
+ (func (export "size") (result i64) (memory.size))
+)
+
+(assert_return (invoke "size") (i64.const 0))
+(assert_trap (invoke "store_at_zero") "out of bounds memory access")
+(assert_trap (invoke "load_at_zero") "out of bounds memory access")
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "size") (i64.const 1))
+(assert_return (invoke "load_at_zero") (i32.const 0))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 4)) (i64.const 1))
+(assert_return (invoke "size") (i64.const 5))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "load_at_page_size") (i32.const 0))
+(assert_return (invoke "store_at_page_size"))
+(assert_return (invoke "load_at_page_size") (i32.const 3))
+
+
+(module
+ (memory i64 0)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 800)) (i64.const 3))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 803))
+
+(module
+ (memory i64 0 10)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 2))
+(assert_return (invoke "grow" (i64.const 6)) (i64.const 4))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 10))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const -1))
+(assert_return (invoke "grow" (i64.const 0x10000)) (i64.const -1))
+
+;; Test that newly allocated memory (program start and memory.grow) is zeroed
+
+(module
+ (memory i64 1)
+ (func (export "grow") (param i64) (result i64)
+ (memory.grow (local.get 0))
+ )
+ (func (export "check-memory-zero") (param i64 i64) (result i32)
+ (local i32)
+ (local.set 2 (i32.const 1))
+ (block
+ (loop
+ (local.set 2 (i32.load8_u (local.get 0)))
+ (br_if 1 (i32.ne (local.get 2) (i32.const 0)))
+ (br_if 1 (i64.ge_u (local.get 0) (local.get 1)))
+ (local.set 0 (i64.add (local.get 0) (i64.const 1)))
+ (br_if 0 (i64.le_u (local.get 0) (local.get 1)))
+ )
+ )
+ (local.get 2)
+ )
+)
+
+(assert_return (invoke "check-memory-zero" (i64.const 0) (i64.const 0xffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "check-memory-zero" (i64.const 0x10000) (i64.const 0x1_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 2))
+(assert_return (invoke "check-memory-zero" (i64.const 0x20000) (i64.const 0x2_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 3))
+(assert_return (invoke "check-memory-zero" (i64.const 0x30000) (i64.const 0x3_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 4))
+(assert_return (invoke "check-memory-zero" (i64.const 0x40000) (i64.const 0x4_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 5))
+(assert_return (invoke "check-memory-zero" (i64.const 0x50000) (i64.const 0x5_ffff)) (i32.const 0))
diff --git a/test/spec/memory_redundancy64.wast b/test/spec/memory_redundancy64.wast
new file mode 100644
index 000000000..4aa1ebac1
--- /dev/null
+++ b/test/spec/memory_redundancy64.wast
@@ -0,0 +1,65 @@
+;; Test that optimizers don't do redundant-load, store-to-load, or dead-store
+;; optimizations when there are interfering stores, even of different types
+;; and to non-identical addresses.
+
+(module
+ (memory i64 1 1)
+
+ (func (export "zero_everything")
+ (i32.store (i64.const 0) (i32.const 0))
+ (i32.store (i64.const 4) (i32.const 0))
+ (i32.store (i64.const 8) (i32.const 0))
+ (i32.store (i64.const 12) (i32.const 0))
+ )
+
+ (func (export "test_store_to_load") (result i32)
+ (i32.store (i64.const 8) (i32.const 0))
+ (f32.store (i64.const 5) (f32.const -0.0))
+ (i32.load (i64.const 8))
+ )
+
+ (func (export "test_redundant_load") (result i32)
+ (local $t i32)
+ (local $s i32)
+ (local.set $t (i32.load (i64.const 8)))
+ (i32.store (i64.const 5) (i32.const 0x80000000))
+ (local.set $s (i32.load (i64.const 8)))
+ (i32.add (local.get $t) (local.get $s))
+ )
+
+ (func (export "test_dead_store") (result f32)
+ (local $t f32)
+ (i32.store (i64.const 8) (i32.const 0x23232323))
+ (local.set $t (f32.load (i64.const 11)))
+ (i32.store (i64.const 8) (i32.const 0))
+ (local.get $t)
+ )
+
+ ;; A function named "malloc" which implementations nonetheless shouldn't
+ ;; assume behaves like C malloc.
+ (func $malloc (export "malloc")
+ (param $size i64)
+ (result i64)
+ (i64.const 16)
+ )
+
+ ;; Call malloc twice, but unlike C malloc, we don't get non-aliasing pointers.
+ (func (export "malloc_aliasing")
+ (result i32)
+ (local $x i64)
+ (local $y i64)
+ (local.set $x (call $malloc (i64.const 4)))
+ (local.set $y (call $malloc (i64.const 4)))
+ (i32.store (local.get $x) (i32.const 42))
+ (i32.store (local.get $y) (i32.const 43))
+ (i32.load (local.get $x))
+ )
+)
+
+(assert_return (invoke "test_store_to_load") (i32.const 0x00000080))
+(invoke "zero_everything")
+(assert_return (invoke "test_redundant_load") (i32.const 0x00000080))
+(invoke "zero_everything")
+(assert_return (invoke "test_dead_store") (f32.const 0x1.18p-144))
+(invoke "zero_everything")
+(assert_return (invoke "malloc_aliasing") (i32.const 43))
diff --git a/test/spec/memory_trap64.wast b/test/spec/memory_trap64.wast
new file mode 100644
index 000000000..77e802ae3
--- /dev/null
+++ b/test/spec/memory_trap64.wast
@@ -0,0 +1,269 @@
+(module
+ (memory i64 1)
+
+ (func $addr_limit (result i64)
+ (i64.mul (memory.size) (i64.const 0x10000))
+ )
+
+ (func (export "store") (param $i i64) (param $v i32)
+ (i32.store (i64.add (call $addr_limit) (local.get $i)) (local.get $v))
+ )
+
+ (func (export "load") (param $i i64) (result i32)
+ (i32.load (i64.add (call $addr_limit) (local.get $i)))
+ )
+
+ (func (export "memory.grow") (param i64) (result i64)
+ (memory.grow (local.get 0))
+ )
+)
+
+(assert_return (invoke "store" (i64.const -4) (i32.const 42)))
+(assert_return (invoke "load" (i64.const -4)) (i32.const 42))
+(assert_trap (invoke "store" (i64.const -3) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const -2) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const -1) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const 0) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const 0x80000000) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const 0x80000000)) "out of bounds memory access")
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefgh")
+ (data (i32.const 0xfff8) "abcdefgh")
+
+ (func (export "i32.load") (param $a i64) (result i32)
+ (i32.load (local.get $a))
+ )
+ (func (export "i64.load") (param $a i64) (result i64)
+ (i64.load (local.get $a))
+ )
+ (func (export "f32.load") (param $a i64) (result f32)
+ (f32.load (local.get $a))
+ )
+ (func (export "f64.load") (param $a i64) (result f64)
+ (f64.load (local.get $a))
+ )
+ (func (export "i32.load8_s") (param $a i64) (result i32)
+ (i32.load8_s (local.get $a))
+ )
+ (func (export "i32.load8_u") (param $a i64) (result i32)
+ (i32.load8_u (local.get $a))
+ )
+ (func (export "i32.load16_s") (param $a i64) (result i32)
+ (i32.load16_s (local.get $a))
+ )
+ (func (export "i32.load16_u") (param $a i64) (result i32)
+ (i32.load16_u (local.get $a))
+ )
+ (func (export "i64.load8_s") (param $a i64) (result i64)
+ (i64.load8_s (local.get $a))
+ )
+ (func (export "i64.load8_u") (param $a i64) (result i64)
+ (i64.load8_u (local.get $a))
+ )
+ (func (export "i64.load16_s") (param $a i64) (result i64)
+ (i64.load16_s (local.get $a))
+ )
+ (func (export "i64.load16_u") (param $a i64) (result i64)
+ (i64.load16_u (local.get $a))
+ )
+ (func (export "i64.load32_s") (param $a i64) (result i64)
+ (i64.load32_s (local.get $a))
+ )
+ (func (export "i64.load32_u") (param $a i64) (result i64)
+ (i64.load32_u (local.get $a))
+ )
+ (func (export "i32.store") (param $a i64) (param $v i32)
+ (i32.store (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store") (param $a i64) (param $v i64)
+ (i64.store (local.get $a) (local.get $v))
+ )
+ (func (export "f32.store") (param $a i64) (param $v f32)
+ (f32.store (local.get $a) (local.get $v))
+ )
+ (func (export "f64.store") (param $a i64) (param $v f64)
+ (f64.store (local.get $a) (local.get $v))
+ )
+ (func (export "i32.store8") (param $a i64) (param $v i32)
+ (i32.store8 (local.get $a) (local.get $v))
+ )
+ (func (export "i32.store16") (param $a i64) (param $v i32)
+ (i32.store16 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store8") (param $a i64) (param $v i64)
+ (i64.store8 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store16") (param $a i64) (param $v i64)
+ (i64.store16 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store32") (param $a i64) (param $v i64)
+ (i64.store32 (local.get $a) (local.get $v))
+ )
+)
+
+(assert_trap (invoke "i32.store" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xffff) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xfffe) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xfffd) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -2) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -3) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -4) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffe) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffd) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffc) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffb) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffa) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfff9) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -3) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -4) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -5) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -6) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -7) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -8) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0x10000) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xffff) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xfffe) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xfffd) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -1) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -2) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -3) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -4) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0x10000) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xffff) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffe) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffd) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffc) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffb) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffa) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfff9) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -1) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -2) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -3) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -4) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -5) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -6) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -7) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -8) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store8" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store8" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const 0xffff) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const -2) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store8" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store8" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xfffe) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xfffd) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -3) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -4) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffc)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffb)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffa)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfff9)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -5)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -6)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -7)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -8)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffc)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffb)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffa)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfff9)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -5)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -6)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -7)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -8)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -4)) "out of bounds memory access")
+
+;; No memory was changed
+(assert_return (invoke "i64.load" (i64.const 0xfff8)) (i64.const 0x6867666564636261))
+(assert_return (invoke "i64.load" (i64.const 0)) (i64.const 0x6867666564636261))
diff --git a/test/spec/old_address64.wast b/test/spec/old_address64.wast
new file mode 100644
index 000000000..5fd193b2a
--- /dev/null
+++ b/test/spec/old_address64.wast
@@ -0,0 +1,34 @@
+(module
+ (import "spectest" "print" (func $print (param i32)))
+
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "good") (param $i i64)
+ (call $print (i32.load8_u offset=0 (local.get $i))) ;; 97 'a'
+ (call $print (i32.load8_u offset=1 (local.get $i))) ;; 98 'b'
+ (call $print (i32.load8_u offset=2 (local.get $i))) ;; 99 'c'
+ (call $print (i32.load8_u offset=25 (local.get $i))) ;; 122 'z'
+
+ (call $print (i32.load16_u offset=0 (local.get $i))) ;; 25185 'ab'
+ (call $print (i32.load16_u align=1 (local.get $i))) ;; 25185 'ab'
+ (call $print (i32.load16_u offset=1 align=1 (local.get $i))) ;; 25442 'bc'
+ (call $print (i32.load16_u offset=2 (local.get $i))) ;; 25699 'cd'
+ (call $print (i32.load16_u offset=25 align=1 (local.get $i))) ;; 122 'z\0'
+
+ (call $print (i32.load offset=0 (local.get $i))) ;; 1684234849 'abcd'
+ (call $print (i32.load offset=1 align=1 (local.get $i))) ;; 1701077858 'bcde'
+ (call $print (i32.load offset=2 align=2 (local.get $i))) ;; 1717920867 'cdef'
+ (call $print (i32.load offset=25 align=1 (local.get $i))) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "bad") (param $i i64)
+ (drop (i32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(invoke "good" (i64.const 0))
+(invoke "good" (i64.const 65507))
+(assert_trap (invoke "good" (i64.const 65508)) "out of bounds memory access")
+(assert_trap (invoke "bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "bad" (i64.const 1)) "out of bounds memory access")
diff --git a/test/spec/resizing64.wast b/test/spec/resizing64.wast
new file mode 100644
index 000000000..3bd9e288d
--- /dev/null
+++ b/test/spec/resizing64.wast
@@ -0,0 +1,58 @@
+(module
+ (memory i64 0)
+
+ (func (export "load_at_zero") (result i32) (i32.load (i64.const 0)))
+ (func (export "store_at_zero") (i32.store (i64.const 0) (i32.const 2)))
+
+ (func (export "load_at_page_size") (result i32) (i32.load (i64.const 0x10000)))
+ (func (export "store_at_page_size") (i32.store (i64.const 0x10000) (i32.const 3)))
+
+ (func (export "grow") (param $sz i64) (result i64) (memory.grow (local.get $sz)))
+ (func (export "size") (result i64) (memory.size))
+)
+
+(assert_return (invoke "size") (i64.const 0))
+(assert_trap (invoke "store_at_zero") "out of bounds memory access")
+(assert_trap (invoke "load_at_zero") "out of bounds memory access")
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "size") (i64.const 1))
+(assert_return (invoke "load_at_zero") (i32.const 0))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 4)) (i64.const 1))
+(assert_return (invoke "size") (i64.const 5))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "load_at_page_size") (i32.const 0))
+(assert_return (invoke "store_at_page_size"))
+(assert_return (invoke "load_at_page_size") (i32.const 3))
+
+
+(module
+ (memory i64 0)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 10000)) (i64.const 3))
+
+(module
+ (memory i64 0 10)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 2))
+(assert_return (invoke "grow" (i64.const 6)) (i64.const 4))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 10))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const -1))