Browse Source

Winch: Add v128 load and store (#9006)

* Winch: Add `v128.load` and `v128.store` support

* Add additional Wast tests
pull/9011/head
Jeffrey Charles 4 months ago
committed by GitHub
parent
commit
488e50563c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 28
      tests/disas/winch/x64/load/v128.wat
  2. 38
      tests/disas/winch/x64/store/v128.wat
  3. 157
      tests/misc_testsuite/winch/simd_address.wast
  4. 12
      tests/misc_testsuite/winch/simd_linking.wast
  5. 188
      tests/misc_testsuite/winch/simd_load.wast
  6. 166
      tests/misc_testsuite/winch/simd_store.wast
  7. 3
      winch/codegen/src/codegen/context.rs
  8. 1
      winch/codegen/src/codegen/mod.rs
  9. 10
      winch/codegen/src/visitor.rs

28
tests/disas/winch/x64/load/v128.wat

@ -0,0 +1,28 @@
;;! target = "x86_64"
;;! test = "winch"
(module
(memory (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\a0\7f"))
(func (export "v128.load") (result v128) (v128.load (i32.const 0)))
)
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq (%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x41
;; 1b: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movdqu (%rcx), %xmm0
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 41: ud2

38
tests/disas/winch/x64/store/v128.wat

@ -0,0 +1,38 @@
;;! target = "x86_64"
;;! test = "winch"
(module
(memory (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f"))
(func (export "v128.store") (v128.store (i32.const 0) (v128.const i64x2 1 2)))
)
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq (%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x49
;; 1b: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movdqu 0x1d(%rip), %xmm0
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movdqu %xmm0, (%rcx)
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 49: ud2
;; 4b: addb %al, (%rax)
;; 4d: addb %al, (%rax)
;; 4f: addb %al, (%rcx)
;; 51: addb %al, (%rax)
;; 53: addb %al, (%rax)
;; 55: addb %al, (%rax)
;; 57: addb %al, (%rdx)
;; 59: addb %al, (%rax)
;; 5b: addb %al, (%rax)
;; 5d: addb %al, (%rax)

157
tests/misc_testsuite/winch/simd_address.wast

@ -0,0 +1,157 @@
;; Load/Store v128 data with different valid offset/alignment
(module
(memory 1)
(data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\10\11\12\13\14\15")
(data (offset (i32.const 65505)) "\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31")
(func (export "load_data_1") (param $i i32) (result v128)
(v128.load offset=0 (local.get $i)) ;; 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15
)
(func (export "load_data_2") (param $i i32) (result v128)
(v128.load align=1 (local.get $i)) ;; 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15
)
(func (export "load_data_3") (param $i i32) (result v128)
(v128.load offset=1 align=1 (local.get $i)) ;; 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15 0x00
)
(func (export "load_data_4") (param $i i32) (result v128)
(v128.load offset=2 align=1 (local.get $i)) ;; 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15 0x00 0x00
)
(func (export "load_data_5") (param $i i32) (result v128)
(v128.load offset=15 align=1 (local.get $i)) ;; 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
)
(func (export "store_data_0") (result v128)
(v128.store offset=0 (i32.const 0) (v128.const f32x4 0 1 2 3))
(v128.load offset=0 (i32.const 0))
)
(func (export "store_data_1") (result v128)
(v128.store align=1 (i32.const 0) (v128.const i32x4 0 1 2 3))
(v128.load align=1 (i32.const 0))
)
(func (export "store_data_2") (result v128)
(v128.store offset=1 align=1 (i32.const 0) (v128.const i16x8 0 1 2 3 4 5 6 7))
(v128.load offset=1 align=1 (i32.const 0))
)
(func (export "store_data_3") (result v128)
(v128.store offset=2 align=1 (i32.const 0) (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
(v128.load offset=2 align=1 (i32.const 0))
)
(func (export "store_data_4") (result v128)
(v128.store offset=15 align=1 (i32.const 0) (v128.const i32x4 0 1 2 3))
(v128.load offset=15 (i32.const 0))
)
(func (export "store_data_5") (result v128)
(v128.store offset=65520 align=1 (i32.const 0) (v128.const i32x4 0 1 2 3))
(v128.load offset=65520 (i32.const 0))
)
(func (export "store_data_6") (param $i i32)
(v128.store offset=1 align=1 (local.get $i) (v128.const i32x4 0 1 2 3))
)
)
(assert_return (invoke "load_data_1" (i32.const 0)) (v128.const i32x4 0x03020100 0x07060504 0x11100908 0x15141312))
(assert_return (invoke "load_data_2" (i32.const 0)) (v128.const i32x4 0x03020100 0x07060504 0x11100908 0x15141312))
(assert_return (invoke "load_data_3" (i32.const 0)) (v128.const i32x4 0x04030201 0x08070605 0x12111009 0x00151413))
(assert_return (invoke "load_data_4" (i32.const 0)) (v128.const i32x4 0x05040302 0x09080706 0x13121110 0x00001514))
(assert_return (invoke "load_data_5" (i32.const 0)) (v128.const i32x4 0x00000015 0x00000000 0x00000000 0x00000000))
(assert_return (invoke "load_data_1" (i32.const 0)) (v128.const i16x8 0x0100 0x0302 0x0504 0x0706 0x0908 0x1110 0x1312 0x1514))
(assert_return (invoke "load_data_2" (i32.const 0)) (v128.const i16x8 0x0100 0x0302 0x0504 0x0706 0x0908 0x1110 0x1312 0x1514))
(assert_return (invoke "load_data_3" (i32.const 0)) (v128.const i16x8 0x0201 0x0403 0x0605 0x0807 0x1009 0x1211 0x1413 0x0015))
(assert_return (invoke "load_data_4" (i32.const 0)) (v128.const i16x8 0x0302 0x0504 0x0706 0x0908 0x1110 0x1312 0x1514 0x0000))
(assert_return (invoke "load_data_5" (i32.const 0)) (v128.const i16x8 0x0015 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000))
(assert_return (invoke "load_data_1" (i32.const 0)) (v128.const i8x16 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15))
(assert_return (invoke "load_data_2" (i32.const 0)) (v128.const i8x16 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15))
(assert_return (invoke "load_data_3" (i32.const 0)) (v128.const i8x16 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15 0x00))
(assert_return (invoke "load_data_4" (i32.const 0)) (v128.const i8x16 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11 0x12 0x13 0x14 0x15 0x00 0x00))
(assert_return (invoke "load_data_5" (i32.const 0)) (v128.const i8x16 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00))
(assert_return (invoke "load_data_1" (i32.const 65505)) (v128.const i32x4 0x19181716 0x23222120 0x27262524 0x31302928))
(assert_return (invoke "load_data_2" (i32.const 65505)) (v128.const i32x4 0x19181716 0x23222120 0x27262524 0x31302928))
(assert_return (invoke "load_data_3" (i32.const 65505)) (v128.const i32x4 0x20191817 0x24232221 0x28272625 0x00313029))
(assert_return (invoke "load_data_4" (i32.const 65505)) (v128.const i32x4 0x21201918 0x25242322 0x29282726 0x00003130))
(assert_return (invoke "load_data_5" (i32.const 65505)) (v128.const i32x4 0x00000031 0x00000000 0x00000000 0x00000000))
(assert_return (invoke "load_data_1" (i32.const 65505)) (v128.const i16x8 0x1716 0x1918 0x2120 0x2322 0x2524 0x2726 0x2928 0x3130))
(assert_return (invoke "load_data_2" (i32.const 65505)) (v128.const i16x8 0x1716 0x1918 0x2120 0x2322 0x2524 0x2726 0x2928 0x3130))
(assert_return (invoke "load_data_3" (i32.const 65505)) (v128.const i16x8 0x1817 0x2019 0x2221 0x2423 0x2625 0x2827 0x3029 0x0031))
(assert_return (invoke "load_data_4" (i32.const 65505)) (v128.const i16x8 0x1918 0x2120 0x2322 0x2524 0x2726 0x2928 0x3130 0x0000))
(assert_return (invoke "load_data_5" (i32.const 65505)) (v128.const i16x8 0x0031 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000))
(assert_return (invoke "load_data_1" (i32.const 65505)) (v128.const i8x16 0x16 0x17 0x18 0x19 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x30 0x31))
(assert_return (invoke "load_data_2" (i32.const 65505)) (v128.const i8x16 0x16 0x17 0x18 0x19 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x30 0x31))
(assert_return (invoke "load_data_3" (i32.const 65505)) (v128.const i8x16 0x17 0x18 0x19 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x30 0x31 0x00))
(assert_return (invoke "load_data_4" (i32.const 65505)) (v128.const i8x16 0x18 0x19 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x30 0x31 0x00 0x00))
(assert_return (invoke "load_data_5" (i32.const 65505)) (v128.const i8x16 0x31 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00))
(assert_trap (invoke "load_data_3" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "load_data_5" (i32.const 65506)) "out of bounds memory access")
(assert_return (invoke "store_data_0") (v128.const f32x4 0 1 2 3))
(assert_return (invoke "store_data_1") (v128.const i32x4 0 1 2 3))
(assert_return (invoke "store_data_2") (v128.const i16x8 0 1 2 3 4 5 6 7))
(assert_return (invoke "store_data_3") (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
(assert_return (invoke "store_data_4") (v128.const i32x4 0 1 2 3))
(assert_return (invoke "store_data_5") (v128.const i32x4 0 1 2 3))
(assert_trap (invoke "store_data_6" (i32.const -1)) "out of bounds memory access")
(assert_trap (invoke "store_data_6" (i32.const 65535)) "out of bounds memory access")
;; Load/Store v128 data with invalid offset
(module
(memory 1)
(func (export "v128.load_offset_65521")
(drop (v128.load offset=65521 (i32.const 0)))
)
)
(assert_trap (invoke "v128.load_offset_65521") "out of bounds memory access")
(assert_malformed
(module quote
"(memory 1)"
"(func"
" (drop (v128.load offset=-1 (i32.const 0)))"
")"
)
"unknown operator"
)
(module
(memory 1)
(func (export "v128.store_offset_65521")
(v128.store offset=65521 (i32.const 0) (v128.const i32x4 0 0 0 0))
)
)
(assert_trap (invoke "v128.store_offset_65521") "out of bounds memory access")
(assert_malformed
(module quote
"(memory 1)"
"(func"
" (v128.store offset=-1 (i32.const 0) (v128.const i32x4 0 0 0 0))"
")"
)
"unknown operator"
)
;; Offset constant out of range
(assert_malformed
(module quote
"(memory 1)"
"(func (drop (v128.load offset=4294967296 (i32.const 0))))"
)
"i32 constant"
)
(assert_malformed
(module quote
"(memory 1)"
"(func (v128.store offset=4294967296 (i32.const 0) (v128.const i32x4 0 0 0 0)))"
)
"i32 constant"
)

12
tests/misc_testsuite/winch/simd_linking.wast

@ -0,0 +1,12 @@
(module
(global (export "g-v128") v128 (v128.const i64x2 0 0))
(global (export "mg-v128") (mut v128) (v128.const i64x2 0 0))
)
(register "Mv128")
(module
;; TODO: Reactivate once the fix for https://bugs.chromium.org/p/v8/issues/detail?id=13732
;; has made it to the downstream node.js that we use on CI.
;; (import "Mv128" "g-v128" (global v128))
(import "Mv128" "mg-v128" (global (mut v128)))
)

188
tests/misc_testsuite/winch/simd_load.wast

@ -0,0 +1,188 @@
;; v128.load operater with normal argument (e.g. (i8x16, i16x8 i32x4))
(module
(memory 1)
(data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
(func (export "v128.load") (result v128)
(v128.load (i32.const 0))
)
)
(assert_return (invoke "v128.load") (v128.const i8x16 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f))
(assert_return (invoke "v128.load") (v128.const i16x8 0x0100 0x0302 0x0504 0x0706 0x0908 0x0b0a 0x0d0c 0x0f0e))
(assert_return (invoke "v128.load") (v128.const i32x4 0x03020100 0x07060504 0x0b0a0908 0x0f0e0d0c))
;; v128.load operater as the argument of other SIMD instructions
;; (module (memory 1)
;; (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
;; (func (export "as-i8x16_extract_lane_s-value/0") (result i32)
;; (i8x16.extract_lane_s 0 (v128.load (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-i8x16_extract_lane_s-value/0") (i32.const 0x00))
;; (module (memory 1)
;; (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
;; (func (export "as-i8x16.eq-operand") (result v128)
;; (i8x16.eq (v128.load offset=0 (i32.const 0)) (v128.load offset=16 (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-i8x16.eq-operand") (v128.const i32x4 0xffffffff 0x00000000 0x00000000 0x00000000))
;; (module (memory 1)
;; (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
;; (func (export "as-v128.not-operand") (result v128)
;; (v128.not (v128.load (i32.const 0)))
;; )
;; (func (export "as-i8x16.all_true-operand") (result i32)
;; (i8x16.all_true (v128.load (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-v128.not-operand") (v128.const i32x4 0xfcfdfeff 0xf8f9fafb 0xf4f5f6f7 0xf0f1f2f3))
;; (assert_return (invoke "as-i8x16.all_true-operand") (i32.const 0))
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA")
;; (data (offset (i32.const 16)) "\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB\BB")
;; (data (offset (i32.const 32)) "\F0\F0\F0\F0\FF\FF\FF\FF\00\00\00\00\FF\00\FF\00")
;; (func (export "as-v128.bitselect-operand") (result v128)
;; (v128.bitselect (v128.load (i32.const 0)) (v128.load (i32.const 16)) (v128.load (i32.const 32)))
;; )
;; )
;; (assert_return (invoke "as-v128.bitselect-operand") (v128.const i32x4 0xabababab 0xaaaaaaaa 0xbbbbbbbb 0xbbaabbaa))
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA")
;; (func (export "as-i8x16.shl-operand") (result v128)
;; (i8x16.shl (v128.load (i32.const 0)) (i32.const 1))
;; )
;; )
;; (assert_return (invoke "as-i8x16.shl-operand") (v128.const i32x4 0x54545454 0x54545454 0x54545454 0x54545454)) ;; 1010 1000 << 1010 1010
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\02\00\00\00\02\00\00\00\02\00\00\00\02\00\00\00")
;; (data (offset (i32.const 16)) "\03\00\00\00\03\00\00\00\03\00\00\00\03\00\00\00")
;; (func (export "as-add/sub-operand") (result v128)
;; ;; 2 2 2 2 + 3 3 3 3 = 5 5 5 5
;; ;; 5 5 5 5 - 3 3 3 3 = 2 2 2 2
;; (i8x16.sub
;; (i8x16.add (v128.load (i32.const 0)) (v128.load (i32.const 16)))
;; (v128.load (i32.const 16))
;; )
;; )
;; )
;; (assert_return (invoke "as-add/sub-operand") (v128.const i32x4 2 2 2 2))
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\00\00\00\43\00\00\80\3f\66\66\e6\3f\00\00\80\bf") ;; 128 1.0 1.8 -1
;; (data (offset (i32.const 16)) "\00\00\00\40\00\00\00\40\00\00\00\40\00\00\00\40") ;; 2.0 2.0 2.0 2.0
;; (func (export "as-f32x4.mul-operand") (result v128)
;; (f32x4.mul (v128.load (i32.const 0)) (v128.load (i32.const 16)))
;; )
;; )
;; (assert_return (invoke "as-f32x4.mul-operand") (v128.const f32x4 256 2 3.6 -2))
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff") ;; 1111 ...
;; (func (export "as-f32x4.abs-operand") (result v128)
;; (f32x4.abs (v128.load (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-f32x4.abs-operand") (v128.const i32x4 0x7fffffff 0x7fffffff 0x7fffffff 0x7fffffff)) ;; 1111 -> 0111
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA\AA")
;; (data (offset (i32.const 16)) "\02\00\00\00\02\00\00\00\02\00\00\00\02\00\00\00")
;; (func (export "as-f32x4.min-operand") (result v128)
;; (f32x4.min (v128.load (i32.const 0)) (v128.load offset=16 (i32.const 1)))
;; )
;; )
;; (assert_return (invoke "as-f32x4.min-operand") (v128.const i32x4 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa)) ;; signed 1010 < 0010
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\00\00\00\43\00\00\80\3f\66\66\e6\3f\00\00\80\bf") ;; 128 1.0 1.8 -1
;; (func (export "as-i32x4.trunc_sat_f32x4_s-operand") (result v128)
;; (i32x4.trunc_sat_f32x4_s (v128.load (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-i32x4.trunc_sat_f32x4_s-operand") (v128.const i32x4 128 1 1 -1)) ;; 128 1.0 1.8 -1 -> 128 1 1 -1
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\02\00\00\00\02\00\00\00\02\00\00\00\02\00\00\00")
;; (func (export "as-f32x4.convert_i32x4_u-operand") (result v128)
;; (f32x4.convert_i32x4_u (v128.load (i32.const 0)))
;; )
;; )
;; (assert_return (invoke "as-f32x4.convert_i32x4_u-operand") (v128.const f32x4 2 2 2 2))
;; (module (memory 1)
;; (data (offset (i32.const 0)) "\64\65\66\67\68\69\6a\6b\6c\6d\6e\6f\70\71\72\73") ;; 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
;; (data (offset (i32.const 16)) "\0f\0e\0d\0c\0b\0a\09\08\07\06\05\04\03\02\01\00") ;; 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
;; (func (export "as-i8x16.swizzle-operand") (result v128)
;; (i8x16.swizzle (v128.load (i32.const 0)) (v128.load offset=15 (i32.const 1)))
;; )
;; )
;; (assert_return(invoke "as-i8x16.swizzle-operand") (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100))
(module (memory 1)
(data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
(func (export "as-br-value") (result v128)
(block (result v128) (br 0 (v128.load (i32.const 0))))
)
)
(assert_return (invoke "as-br-value") (v128.const i32x4 0x03020100 0x07060504 0x0b0a0908 0x0f0e0d0c))
;; Unknown operator(e.g. v128.load8, v128.load16, v128.load32)
(assert_malformed
(module quote
"(memory 1)"
"(func (local v128) (drop (v128.load8 (i32.const 0))))"
)
"unknown operator"
)
(assert_malformed
(module quote
"(memory 1)"
"(func (local v128) (drop (v128.load16 (i32.const 0))))"
)
"unknown operator"
)
(assert_malformed
(module quote
"(memory 1)"
"(func (local v128) (drop (v128.load32 (i32.const 0))))"
)
"unknown operator"
)
;; Type mismatched (e.g. v128.load(f32.const 0), type address empty)
(assert_invalid
(module (memory 1) (func (local v128) (drop (v128.load (f32.const 0)))))
"type mismatch"
)
(assert_invalid
(module (memory 1) (func (local v128) (block (br_if 0 (v128.load (i32.const 0))))))
"type mismatch"
)
(assert_invalid
(module (memory 1) (func (local v128) (v128.load (i32.const 0))))
"type mismatch"
)
;; Type address empty
(assert_invalid
(module (memory 1) (func (drop (v128.load (local.get 2)))))
"unknown local 2"
)
(assert_invalid
(module (memory 1) (func (drop (v128.load))))
"type mismatch"
)

166
tests/misc_testsuite/winch/simd_store.wast

@ -0,0 +1,166 @@
;; v128.store operater with normal argument (e.g. (i8x16, i16x8, i32x4, f32x4))
(module
(memory 1)
(func (export "v128.store_i8x16") (result v128)
(v128.store (i32.const 0) (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
(v128.load (i32.const 0))
)
(func (export "v128.store_i16x8") (result v128)
(v128.store (i32.const 0) (v128.const i16x8 0 1 2 3 4 5 6 7))
(v128.load (i32.const 0))
)
(func (export "v128.store_i16x8_2") (result v128)
(v128.store (i32.const 0) (v128.const i16x8 012_345 012_345 012_345 012_345 012_345 012_345 012_345 012_345))
(v128.load (i32.const 0))
)
(func (export "v128.store_i16x8_3") (result v128)
(v128.store (i32.const 0) (v128.const i16x8 0x0_1234 0x0_1234 0x0_1234 0x0_1234 0x0_1234 0x0_1234 0x0_1234 0x0_1234))
(v128.load (i32.const 0))
)
(func (export "v128.store_i32x4") (result v128)
(v128.store (i32.const 0) (v128.const i32x4 0 1 2 3))
(v128.load (i32.const 0))
)
(func (export "v128.store_i32x4_2") (result v128)
(v128.store (i32.const 0) (v128.const i32x4 0_123_456_789 0_123_456_789 0_123_456_789 0_123_456_789))
(v128.load (i32.const 0))
)
(func (export "v128.store_i32x4_3") (result v128)
(v128.store (i32.const 0) (v128.const i32x4 0x0_1234_5678 0x0_1234_5678 0x0_1234_5678 0x0_1234_5678))
(v128.load (i32.const 0))
)
(func (export "v128.store_f32x4") (result v128)
(v128.store (i32.const 0) (v128.const f32x4 0 1 2 3))
(v128.load (i32.const 0))
)
)
(assert_return (invoke "v128.store_i8x16") (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
(assert_return (invoke "v128.store_i16x8") (v128.const i16x8 0 1 2 3 4 5 6 7))
(assert_return (invoke "v128.store_i16x8_2") (v128.const i16x8 12345 12345 12345 12345 12345 12345 12345 12345))
(assert_return (invoke "v128.store_i16x8_3") (v128.const i16x8 0x1234 0x1234 0x1234 0x1234 0x1234 0x1234 0x1234 0x1234))
(assert_return (invoke "v128.store_i32x4") (v128.const i32x4 0 1 2 3))
(assert_return (invoke "v128.store_i32x4_2") (v128.const i32x4 123456789 123456789 123456789 123456789))
(assert_return (invoke "v128.store_i32x4_3") (v128.const i32x4 0x12345678 0x12345678 0x12345678 0x12345678))
(assert_return (invoke "v128.store_f32x4") (v128.const f32x4 0 1 2 3))
;; v128.store operator as the argument of control constructs and instructions
(module
(memory 1)
(func (export "as-block-value")
(block (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)))
)
(func (export "as-loop-value")
(loop (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)))
)
(func (export "as-br-value")
(block (br 0 (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0))))
)
(func (export "as-br_if-value")
(block
(br_if 0 (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)) (i32.const 1))
)
)
(func (export "as-br_if-value-cond")
(block
(br_if 0 (i32.const 6) (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)))
)
)
(func (export "as-br_table-value")
(block
(br_table 0 (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)) (i32.const 1))
)
)
(func (export "as-return-value")
(return (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0)))
)
(func (export "as-if-then")
(if (i32.const 1) (then (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0))))
)
(func (export "as-if-else")
(if (i32.const 0) (then) (else (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0))))
)
)
(assert_return (invoke "as-block-value"))
(assert_return (invoke "as-loop-value"))
(assert_return (invoke "as-br-value"))
(assert_return (invoke "as-br_if-value"))
(assert_return (invoke "as-br_if-value-cond"))
(assert_return (invoke "as-br_table-value"))
(assert_return (invoke "as-return-value"))
(assert_return (invoke "as-if-then"))
(assert_return (invoke "as-if-else"))
;; Unknown operator(e.g. v128.store8, v128.store16, v128.store32)
(assert_malformed
(module quote
"(memory 1)"
"(func (v128.store8 (i32.const 0) (v128.const i32x4 0 0 0 0)))"
)
"unknown operator"
)
(assert_malformed
(module quote
"(memory 1)"
"(func (v128.store16 (i32.const 0) (v128.const i32x4 0 0 0 0)))"
)
"unknown operator"
)
(assert_malformed
(module quote
"(memory 1)"
"(func (v128.store32 (i32.const 0) (v128.const i32x4 0 0 0 0)))"
)
"unknown operator"
)
;; Type mismatched (e.g. v128.load(f32.const 0), type address empty)
(assert_invalid
(module (memory 1) (func (v128.store (f32.const 0) (v128.const i32x4 0 0 0 0))))
"type mismatch"
)
(assert_invalid
(module (memory 1) (func (local v128) (block (br_if 0 (v128.store)))))
"type mismatch"
)
(assert_invalid
(module (memory 1) (func (result v128) (v128.store (i32.const 0) (v128.const i32x4 0 0 0 0))))
"type mismatch"
)
;; Test operation with empty argument
(assert_invalid
(module (memory 0)
(func $v128.store-1st-arg-empty
(v128.store (v128.const i32x4 0 0 0 0))
)
)
"type mismatch"
)
(assert_invalid
(module (memory 0)
(func $v128.store-2nd-arg-empty
(v128.store (i32.const 0))
)
)
"type mismatch"
)
(assert_invalid
(module (memory 0)
(func $v128.store-arg-empty
(v128.store)
)
)
"type mismatch"
)

3
winch/codegen/src/codegen/context.rs

@ -70,11 +70,12 @@ impl<'a> CodeGenContext<'a> {
match ty {
I32 | I64 => self.reg_for_class(RegClass::Int, masm),
F32 | F64 => self.reg_for_class(RegClass::Float, masm),
// All of our supported architectures use the float registers for vector operations.
V128 => self.reg_for_class(RegClass::Float, masm),
Ref(rt) => match rt.heap_type {
WasmHeapType::Func => self.reg_for_class(RegClass::Int, masm),
ht => unimplemented!("Support for WasmHeapType: {ht}"),
},
t => unimplemented!("Support for WasmType: {t}"),
}
}

1
winch/codegen/src/codegen/mod.rs

@ -723,6 +723,7 @@ where
let dst = match ty {
WasmValType::I32 | WasmValType::I64 => self.context.any_gpr(self.masm),
WasmValType::F32 | WasmValType::F64 => self.context.any_fpr(self.masm),
WasmValType::V128 => self.context.reg_for_type(ty, self.masm),
_ => unreachable!(),
};

10
winch/codegen/src/visitor.rs

@ -241,6 +241,8 @@ macro_rules! def_unsupported {
(emit I64TruncSatF32U $($rest:tt)*) => {};
(emit I64TruncSatF64S $($rest:tt)*) => {};
(emit I64TruncSatF64U $($rest:tt)*) => {};
(emit V128Load $($rest:tt)*) => {};
(emit V128Store $($rest:tt)*) => {};
(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
}
@ -2015,6 +2017,14 @@ where
self.emit_wasm_store(&memarg, OperandSize::S64)
}
fn visit_v128_load(&mut self, memarg: MemArg) {
self.emit_wasm_load(&memarg, WasmValType::V128, OperandSize::S128, None)
}
fn visit_v128_store(&mut self, memarg: MemArg) {
self.emit_wasm_store(&memarg, OperandSize::S128)
}
fn visit_i32_trunc_sat_f32_s(&mut self) {
use OperandSize::*;

Loading…
Cancel
Save