test-wasm-assembler.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. ;;; WebAssembly binary parser
  2. ;;; Copyright (C) 2023, 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Parser for WebAssembly binary format
  18. ;;;
  19. ;;; Code:
  20. (use-modules (wasm assemble)
  21. (wasm lower)
  22. (wasm wat)
  23. (wasm parse)
  24. (ice-9 binary-ports)
  25. (srfi srfi-64)
  26. (test utils))
  27. (define (scope-file file-name)
  28. (in-vicinity (getenv "HOOT_TEST_DATA_DIR") file-name))
  29. (test-begin "test-wasm-assembler")
  30. (define-syntax-rule (test-wat->wasm expected wat)
  31. (begin
  32. (test-equal expected (assemble-wasm (lower-wasm (wat->wasm 'wat))))
  33. (test-equal expected
  34. (assemble-wasm (call-with-input-bytevector expected parse-wasm)))))
  35. (define-syntax-rule (test-wat->wasm/emit-names expected wat)
  36. (begin
  37. (test-equal expected (assemble-wasm (lower-wasm (wat->wasm 'wat) #:emit-names? #t)))
  38. (test-equal expected
  39. (assemble-wasm (call-with-input-bytevector expected parse-wasm)))))
  40. (test-wat->wasm
  41. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 127 3 2 1 0 10 6 1 4 0 65 42 11)
  42. (module
  43. (func (param) (result i32)
  44. (i32.const 42))))
  45. (define basic-types.wasm
  46. (call-with-input-file (scope-file "basic-types.wasm") get-bytevector-all))
  47. (define basic-types/1
  48. (call-with-input-bytevector basic-types.wasm parse-wasm))
  49. (define basic-types.wasm/2
  50. (assemble-wasm basic-types/1))
  51. (define basic-types/2
  52. (call-with-input-bytevector basic-types.wasm/2 parse-wasm))
  53. (define basic-types.wasm/3
  54. (assemble-wasm basic-types/2))
  55. ;; For wasm files like basic-types.wasm that are produced by external
  56. ;; tools, we don't aim for byte-for-byte parsing and re-serialization,
  57. ;; notably because binaryen emits deprecated GC opcodes which we rewrite
  58. ;; to the updated ones. But if we parse a file that we generate and
  59. ;; then re-serialize it, they should be the same.
  60. (test-equal "basic types reassembly"
  61. basic-types.wasm/2 basic-types.wasm/3)
  62. ;; Test type resolution for functions with similar signatures
  63. (test-wat->wasm
  64. #vu8(0 97 115 109 1 0 0 0 1 6 1 96 1 127 1 127 3 3 2 0 0 10 11 2 4 0 32
  65. 0 11 4 0 32 0 11)
  66. (module
  67. (func $a (param $x i32) (result i32)
  68. (local.get $x))
  69. (func $b (param $y i32) (result i32)
  70. (local.get $y))))
  71. ;; Test vector instructions
  72. (test-wat->wasm
  73. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 8 1 6 0 65 23 253
  74. 15 11)
  75. (module (func (result v128) (i8x16.splat (i32.const 23)))))
  76. (test-wat->wasm
  77. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 8 1 6 0 65 23 253
  78. 16 11)
  79. (module (func (result v128) (i16x8.splat (i32.const 23)))))
  80. (test-wat->wasm
  81. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 8 1 6 0 65 23 253
  82. 17 11)
  83. (module (func (result v128) (i32x4.splat (i32.const 23)))))
  84. (test-wat->wasm
  85. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 8 1 6 0 66 23 253
  86. 18 11)
  87. (module (func (result v128) (i64x2.splat (i64.const 23)))))
  88. (test-wat->wasm
  89. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 11 1 9 0 67 208
  90. 15 73 64 253 19 11)
  91. (module (func (result v128) (f32x4.splat (f32.const 3.14159)))))
  92. (test-wat->wasm
  93. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 123 3 2 1 0 10 15 1 13 0 68 110
  94. 134 27 240 249 33 9 64 253 20 11)
  95. (module (func (result v128) (f64x2.splat (f64.const 3.14159)))))
  96. (test-wat->wasm
  97. #vu8(0 97 115 109 1 0 0 0 1 4 1 94 127 0)
  98. (module (type $foo (array i32))))
  99. (test-wat->wasm
  100. #vu8(0 97 115 109 1 0 0 0 1 4 1 94 127 1)
  101. (module (type $foo (array (mut i32)))))
  102. (test-wat->wasm
  103. #vu8(0 97 115 109 1 0 0 0 1 7 1 95 2 127 0 127 0)
  104. (module (type $foo (struct (field $foo i32) (field $bar i32)))))
  105. (test-wat->wasm
  106. #vu8(0 97 115 109 1 0 0 0 1 7 1 95 2 127 1 127 0)
  107. (module (type $foo (struct (field $a (mut i32)) (field $b i32)))))
  108. (test-wat->wasm
  109. #vu8(0 97 115 109 1 0 0 0 1 7 1 95 2 127 0 127 1)
  110. (module (type $foo (struct (field $a i32) (field $b (mut i32))))))
  111. (test-wat->wasm
  112. #vu8(0 97 115 109 1 0 0 0 1 7 1 95 2 127 1 127 1)
  113. (module (type $foo (struct (field $a (mut i32)) (field $b (mut i32))))))
  114. (test-wat->wasm
  115. #vu8(0 97 115 109 1 0 0 0 1 7 1 78 1 95 1 127 1)
  116. (module
  117. (rec
  118. (type $heap-object
  119. (struct (field $hash (mut i32)))))))
  120. (test-wat->wasm
  121. #vu8(0 97 115 109 1 0 0 0 1 17 1 78 2 95 1 127 1 80 1 0 95 2 127 1
  122. 100 111 0)
  123. (module
  124. (rec
  125. (type $heap-object
  126. (struct (field $hash (mut i32))))
  127. (type $extern-ref
  128. (sub $heap-object
  129. (struct
  130. (field $hash (mut i32))
  131. (field $val (ref extern))))))))
  132. (test-wat->wasm
  133. #vu8(0 97 115 109 1 0 0 0 1 33 1 78 3 95 1 127 1 80 1 0 95 3 127 1
  134. 100 109 1 100 109 1 80 1 1 95 3 127 1 100 109 1 100 109 1)
  135. (module
  136. (rec
  137. (type $heap-object
  138. (struct (field $hash (mut i32))))
  139. (type $pair
  140. (sub $heap-object
  141. (struct
  142. (field $hash (mut i32))
  143. (field $car (mut (ref eq)))
  144. (field $cdr (mut (ref eq))))))
  145. (type $mutable-pair
  146. (sub $pair
  147. (struct
  148. (field $hash (mut i32))
  149. (field $car (mut (ref eq)))
  150. (field $cdr (mut (ref eq)))))))))
  151. (test-wat->wasm
  152. #vu8(0 97 115 109 1 0 0 0 1 4 1 96 0 0 3 2 1 0 10 9 1 7 0 65 0 14 0 0 11)
  153. (module (func (i32.const 0) (br_table 0))))
  154. (test-wat->wasm
  155. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 1 127 0 3 2 1 0 10 20 1 18 0 2 64 2
  156. 64 2 64 32 0 14 2 2 1 0 11 11 11 11)
  157. (module
  158. (func (param $i i32)
  159. (block $l1
  160. (block $l2
  161. (block $l3
  162. (br_table $l1 $l2 $l3 (local.get $i))))))))
  163. (test-wat->wasm
  164. #vu8(0 97 115 109 1 0 0 0 1 5 1 96 0 1 127 3 2 1 0 10 14 1 12 0 65 0 4
  165. 127 65 1 5 65 2 11 11)
  166. (module
  167. (func (result i32)
  168. (if i32
  169. (i32.const 0)
  170. (then (i32.const 1))
  171. (else (i32.const 2))))))
  172. ;; Test exceptions
  173. (test-wat->wasm
  174. #vu8(0 97 115 109 1 0 0 0 1 4 1 96 0 0 13 3 1 0 0)
  175. (module (tag $foo)))
  176. (test-wat->wasm
  177. #vu8(0 97 115 109 1 0 0 0 1 4 1 96 0 0 2 13 1 4 116 97 103 115 3 102 111 111 4 0 0)
  178. (module (tag $foo (import "tags" "foo"))))
  179. (test-wat->wasm
  180. #vu8(0 97 115 109 1 0 0 0 1 4 1 96 0 0 13 3 1 0 0 7 7 1 3 102 111 111 4 0)
  181. (module (tag $foo (export "foo"))))
  182. (test-wat->wasm
  183. #vu8(0 97 115 109 1 0 0 0 1 8 2 96 0 0 96 0 1 127 3 2 1 1 13 5 2 0 0 0 0 10
  184. 17 1 15 0 6 127 8 0 7 1 65 42 25 65 205 0 11 11)
  185. (module
  186. (tag $foo)
  187. (tag $bar)
  188. (func (result i32)
  189. (try (result i32)
  190. (do (throw $foo))
  191. (catch $bar (i32.const 42))
  192. (catch_all (i32.const 77))))))
  193. (test-wat->wasm
  194. #vu8(0 97 115 109 1 0 0 0 1 9 2 96 1 127 0 96 0 1 127 3 2 1 1 13 3 1 0 0 10
  195. 26 1 24 0 6 127 6 64 65 197 0 8 0 24 0 0 7 0 65 42 106 25 65 205 0 11 11)
  196. (module
  197. (tag $foo (param i32))
  198. (func (result i32)
  199. (try $bloop (result i32)
  200. (do (try
  201. (do (i32.const 69)
  202. (throw $foo))
  203. (delegate $bloop))
  204. (unreachable))
  205. (catch $foo
  206. (i32.const 42)
  207. (i32.add))
  208. (catch_all (i32.const 77))))))
  209. (test-wat->wasm
  210. #vu8(0 97 115 109 1 0 0 0 1 8 2 96 0 0 96 0 1 127 3 2 1 1 13 3 1 0 0 10 24 1
  211. 22 0 6 127 6 127 8 0 7 0 9 0 25 0 11 7 0 65 42 25 0 11 11)
  212. (module
  213. (tag $foo)
  214. (func (result i32)
  215. (try $l1 (result i32)
  216. (do (try $l2 (result i32)
  217. (do (throw $foo))
  218. (catch $foo
  219. (rethrow $l2))
  220. (catch_all (unreachable))))
  221. (catch $foo
  222. (i32.const 42))
  223. (catch_all (unreachable))))))
  224. ;; Test name section
  225. (test-wat->wasm/emit-names
  226. #vu8(0 97 115 109 1 0 0 0 1 6 1 96 1 127 1 127 3 2 1 0 10 7 1 5 0 32 0 106 11
  227. 0 29 4 110 97 109 101 0 5 4 116 101 115 116 1 7 1 0 4 97 100 100 49 2
  228. 6 1 0 1 0 1 120)
  229. (module $test
  230. (func $add1 (param $x i32) (result i32)
  231. (i32.add (local.get $x)))))
  232. (test-end* "test-wasm-assembler")