watr 0.0.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/amp.wasm +0 -0
- package/example/amp.wat +81 -0
- package/example/array.wat +26 -0
- package/example/global.wasm +0 -0
- package/example/global.wat +28 -0
- package/example/loops.wasm +0 -0
- package/example/loops.wat +34 -0
- package/example/memory.wasm +0 -0
- package/example/memory.wat +34 -0
- package/example/multivar.wasm +0 -0
- package/example/multivar.wat +13 -0
- package/example/stack.wasm +0 -0
- package/example/stack.wat +38 -0
- package/example/table.wasm +0 -0
- package/example/table.wat +24 -0
- package/example/types.wasm +0 -0
- package/example/types.wat +21 -0
- package/lib/wabt.js +36 -0
- package/lib/wat-compiler.js +1 -0
- package/package.json +14 -4
- package/plan.md +21 -0
- package/readme.md +145 -0
- package/repl.html +44 -0
- package/src/compile.js +456 -0
- package/src/parse.js +31 -0
- package/src/watr.js +8 -0
- package/test/compile.js +1090 -0
- package/test/examples.js +155 -0
- package/test/index.html +14 -0
- package/test/index.js +2 -0
- package/test/parse.js +179 -0
- package/watr.js +428 -0
- package/watr.min.js +1 -0
package/test/compile.js
ADDED
|
@@ -0,0 +1,1090 @@
|
|
|
1
|
+
import t, { is, ok, same, throws } from 'tst'
|
|
2
|
+
import compile from '../src/compile.js'
|
|
3
|
+
import parse from '../src/parse.js'
|
|
4
|
+
import Wabt from '../lib/wabt.js'
|
|
5
|
+
import watCompiler from '../lib/wat-compiler.js'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// examples from https://ontouchstart.pages.dev/chapter_wasm_binary
|
|
9
|
+
|
|
10
|
+
t('compile: empty', t => {
|
|
11
|
+
is(compile(['module']), hex`00 61 73 6d 01 00 00 00`)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
t('compile: (module (func))', t => {
|
|
15
|
+
let buffer
|
|
16
|
+
is(compile(['module', ['func']]), buffer = hex`
|
|
17
|
+
00 61 73 6d 01 00 00 00
|
|
18
|
+
01 04 01 60 00 00 ; type section
|
|
19
|
+
03 02 01 00 ; func section
|
|
20
|
+
0a 04 01 02 00 0b ; code section
|
|
21
|
+
`)
|
|
22
|
+
|
|
23
|
+
new WebAssembly.Module(buffer)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
t('compile: (module (memory 1) (func))', t => {
|
|
27
|
+
let buffer = hex`
|
|
28
|
+
00 61 73 6d 01 00 00 00
|
|
29
|
+
01 04 01 60 00 00 ; type
|
|
30
|
+
03 02 01 00 ; func
|
|
31
|
+
05 03 01 00 01 ; memory
|
|
32
|
+
0a 04 01 02 00 0b ; code
|
|
33
|
+
`
|
|
34
|
+
new WebAssembly.Module(buffer)
|
|
35
|
+
|
|
36
|
+
is(compile(['module', ['memory', 1], ['func']]), buffer )
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
t('compile: (module (memory (import "js" "mem") 1) (func))', t => {
|
|
40
|
+
let buffer = hex`
|
|
41
|
+
00 61 73 6d 01 00 00 00
|
|
42
|
+
01 04 01 60 00 00 ; type
|
|
43
|
+
02 0b 01 02 6a 73 03 6d 65 6d 02 00 01 ; import
|
|
44
|
+
03 02 01 00 ; func
|
|
45
|
+
0a 04 01 02 00 0b ; code
|
|
46
|
+
`
|
|
47
|
+
new WebAssembly.Module(buffer)
|
|
48
|
+
is(compile(['module', ['memory', ['import', 'js', 'mem'], 1], ['func']]), buffer)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
t('compile: export mem/func', t => {
|
|
52
|
+
let buffer = hex`
|
|
53
|
+
00 61 73 6d 01 00 00 00
|
|
54
|
+
01 07 01 60 02 7f 7f 01 7f ; type
|
|
55
|
+
03 02 01 00 ; function
|
|
56
|
+
05 03 01 00 01 ; memory
|
|
57
|
+
07 09 02 01 6d 02 00 01 66 00 00 ; export
|
|
58
|
+
0a 0d 01 0b 00 20 00 20 01 36 02 00 20 01 0b ; code
|
|
59
|
+
`
|
|
60
|
+
is(compile(['module', // (module
|
|
61
|
+
['memory', 1], // (memory 1)
|
|
62
|
+
['func', ['param', 'i32', 'i32'], ['result', 'i32'], // (func (param i32 i32) (result i32)
|
|
63
|
+
// ['local.get', 0], // local.get 0
|
|
64
|
+
// ['local.get', 1], // local.get 1
|
|
65
|
+
// ['i32.store', ['align','4']], // i32.store
|
|
66
|
+
['i32.store', ['align','4'], ['local.get', 0], ['local.get', 1]],
|
|
67
|
+
['local.get', 1] // local.get 1
|
|
68
|
+
], // )
|
|
69
|
+
['export', '"m"', ['memory', 0]], // (export "m" (memory 0 ))
|
|
70
|
+
['export', '"f"', ['func', 0]], // (export "f" (func 0 ))
|
|
71
|
+
]), // )
|
|
72
|
+
buffer)
|
|
73
|
+
|
|
74
|
+
new WebAssembly.Module(buffer)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
t('compiler: reexport', () => {
|
|
78
|
+
let src = `
|
|
79
|
+
(export "f0" (func 0))
|
|
80
|
+
(export "f1" (func 1))
|
|
81
|
+
(import "math" "add" (func (param i32 i32) (result i32)))
|
|
82
|
+
(func (param i32 i32) (result i32)
|
|
83
|
+
(i32.sub (local.get 0) (local.get 1))
|
|
84
|
+
)
|
|
85
|
+
`
|
|
86
|
+
|
|
87
|
+
let {f0, f1} = run(src, {math:{add(a,b){return a+b}}}).exports
|
|
88
|
+
is(f0(3,1), 4)
|
|
89
|
+
is(f1(3,1), 2)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
t('compiler: memory $foo (import "a" "b" ) 1 2 shared', () => {
|
|
93
|
+
let src = `(memory $foo (import "env" "mem") 1 2 shared)`
|
|
94
|
+
run(src, {env:{mem: new WebAssembly.Memory({initial:1, maximum: 1, shared: 1})}})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
t('compiler: stacked syntax should not be supported', () => {
|
|
98
|
+
throws(t => {
|
|
99
|
+
compile(parse(`
|
|
100
|
+
(func (export "answer") (param i32 i32) (result i32)
|
|
101
|
+
(local.get 0)
|
|
102
|
+
(local.get 1)
|
|
103
|
+
(i32.add)
|
|
104
|
+
)
|
|
105
|
+
`))
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
t('compiler: inline syntax is not supported', () => {
|
|
110
|
+
throws(t => {
|
|
111
|
+
compile(parse(`
|
|
112
|
+
(func $f1 (result i32)
|
|
113
|
+
i32.const 42)
|
|
114
|
+
`))
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
// wat-compiler
|
|
120
|
+
t('wat-compiler: minimal function', t => {
|
|
121
|
+
run('(module (func (export "answer") (result i32) (i32.const 42)))')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
t('wat-compiler: function with 1 param', t => {
|
|
125
|
+
run('(func (export "answer") (param i32) (result i32) (local.get 0))')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
t('wat-compiler: function with 1 param', () => {
|
|
129
|
+
let {answer} = run(`
|
|
130
|
+
(func (export "answer") (param i32) (result i32) (local.get 0))
|
|
131
|
+
`).exports
|
|
132
|
+
is(answer(42), 42)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
t('wat-compiler: function with 2 params', () => {
|
|
136
|
+
let {answer} = run(`
|
|
137
|
+
(func (export "answer") (param i32 i32) (result i32)
|
|
138
|
+
(i32.add (local.get 0) (local.get 1))
|
|
139
|
+
)
|
|
140
|
+
`).exports
|
|
141
|
+
is(answer(20,22), 42)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
t('wat-compiler: function with 2 params 2 results', () => {
|
|
145
|
+
let {answer} = run(`
|
|
146
|
+
(func (export "answer") (param i32 i32) (result i32 i32)
|
|
147
|
+
(i32.add (local.get 0) (local.get 1))
|
|
148
|
+
(i32.const 666)
|
|
149
|
+
)
|
|
150
|
+
`).exports
|
|
151
|
+
|
|
152
|
+
is(answer(20,22), [42,666])
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
t('wat-compiler: named function named param', () => {
|
|
156
|
+
let {dbl} = run(`
|
|
157
|
+
(func $dbl (export "dbl") (param $a i32) (result i32)
|
|
158
|
+
(i32.add (local.get $a) (local.get $a))
|
|
159
|
+
)
|
|
160
|
+
`).exports
|
|
161
|
+
|
|
162
|
+
is(dbl(21), 42)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
t('wat-compiler: call function direct', () => {
|
|
167
|
+
let {call_function_direct} = run(`
|
|
168
|
+
(func $dbl (param $a i32) (result i32)
|
|
169
|
+
(i32.add (local.get $a) (local.get $a))
|
|
170
|
+
)
|
|
171
|
+
(func (export "call_function_direct") (param $a i32) (result i32)
|
|
172
|
+
(call $dbl (local.get $a))
|
|
173
|
+
)
|
|
174
|
+
`).exports
|
|
175
|
+
is(call_function_direct(333), 666)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
t('wat-compiler: function param + local', () => {
|
|
179
|
+
let {add} = run(`
|
|
180
|
+
(func (export "add") (param $a i32) (result i32)
|
|
181
|
+
(local $b i32)
|
|
182
|
+
(i32.add (local.get $a) (local.tee $b (i32.const 20)))
|
|
183
|
+
)
|
|
184
|
+
`).exports
|
|
185
|
+
|
|
186
|
+
is(add(22), 42)
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
t('wat-compiler: call function indirect (table)', () => {
|
|
190
|
+
let {call_function_indirect} = run(`
|
|
191
|
+
(type $return_i32 (func (result i32)))
|
|
192
|
+
(table 2 funcref)
|
|
193
|
+
(elem (i32.const 0) $f1 $f2)
|
|
194
|
+
(func $f1 (result i32)
|
|
195
|
+
(i32.const 42))
|
|
196
|
+
(func $f2 (result i32)
|
|
197
|
+
(i32.const 13))
|
|
198
|
+
(func (export "call_function_indirect") (param $a i32) (result i32)
|
|
199
|
+
(call_indirect (type $return_i32) (local.get $a))
|
|
200
|
+
)
|
|
201
|
+
`).exports
|
|
202
|
+
|
|
203
|
+
is(call_function_indirect(0), 42)
|
|
204
|
+
is(call_function_indirect(1), 13)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
t('wat-compiler: call function indirect (table) non zero indexed ref types', () => {
|
|
208
|
+
let {call_function_indirect} = run(`
|
|
209
|
+
(type $return_i32 (func (result i32)))
|
|
210
|
+
(type $return_i64 (func (result i64)))
|
|
211
|
+
(table 2 funcref)
|
|
212
|
+
(elem (i32.const 0) $f1 $f2)
|
|
213
|
+
(func $xx (result i32)
|
|
214
|
+
(i32.const 42))
|
|
215
|
+
(func $f1 (result i32)
|
|
216
|
+
(i32.const 42))
|
|
217
|
+
(func $f2 (result i32)
|
|
218
|
+
(i32.const 13))
|
|
219
|
+
(func (export "call_function_indirect") (param $a i32) (result i32)
|
|
220
|
+
(call_indirect (type $return_i32) (local.get $a))
|
|
221
|
+
)
|
|
222
|
+
`).exports
|
|
223
|
+
|
|
224
|
+
is(call_function_indirect(0), 42)
|
|
225
|
+
is(call_function_indirect(1), 13)
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
t('wat-compiler: 1 global const (immutable)', () => {
|
|
229
|
+
let {get} = run(`
|
|
230
|
+
(global $answer i32 (i32.const 42))
|
|
231
|
+
(func (export "get") (result i32)
|
|
232
|
+
(global.get $answer)
|
|
233
|
+
)
|
|
234
|
+
`).exports
|
|
235
|
+
|
|
236
|
+
is(get(), 42)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
t('wat-compiler: 1 global var (mut)', () => {
|
|
240
|
+
let {get} = run(`
|
|
241
|
+
(global $answer (mut i32) (i32.const 42))
|
|
242
|
+
(func (export "get") (result i32)
|
|
243
|
+
(global.get $answer)
|
|
244
|
+
)
|
|
245
|
+
`).exports
|
|
246
|
+
|
|
247
|
+
is(get(), 42)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
t('wat-compiler: 1 global var (mut) + mutate', () => {
|
|
251
|
+
let {get} = run(`
|
|
252
|
+
(global $answer (mut i32) (i32.const 42))
|
|
253
|
+
(func (export "get") (result i32)
|
|
254
|
+
(global.set $answer (i32.const 777))
|
|
255
|
+
(global.get $answer)
|
|
256
|
+
)
|
|
257
|
+
`).exports
|
|
258
|
+
|
|
259
|
+
is(get(), 777)
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
t('wat-compiler: memory.grow', () => {
|
|
263
|
+
run(`
|
|
264
|
+
(memory 1)
|
|
265
|
+
(func (export "main") (result i32)
|
|
266
|
+
(memory.grow (i32.const 2))
|
|
267
|
+
)
|
|
268
|
+
`)
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
t('wat-compiler: local memory page min 1 - data 1 offset 0 i32', () => {
|
|
272
|
+
let {get} = run(String.raw`
|
|
273
|
+
(memory 1)
|
|
274
|
+
(data (i32.const 0) "\2a")
|
|
275
|
+
(func (export "get") (result i32)
|
|
276
|
+
(i32.load (i32.const 0))
|
|
277
|
+
)
|
|
278
|
+
`).exports
|
|
279
|
+
|
|
280
|
+
is(get(), 42)
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
t('wat-compiler: local memory page min 1 max 2 - data 1 offset 0 i32', () => {
|
|
284
|
+
let {get} = run(String.raw`
|
|
285
|
+
(memory 1 2)
|
|
286
|
+
(data (i32.const 0) "\2a")
|
|
287
|
+
(func (export "get") (result i32)
|
|
288
|
+
(drop (i32.const 1))
|
|
289
|
+
(drop (i32.const 2))
|
|
290
|
+
(i32.load offset=0 align=4 (i32.const 0))
|
|
291
|
+
)
|
|
292
|
+
`).exports
|
|
293
|
+
|
|
294
|
+
is(get(), 42)
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
t('wat-compiler: import function', () => {
|
|
298
|
+
let src = `
|
|
299
|
+
(import "math" "add" (func $add (param i32 i32) (result i32)))
|
|
300
|
+
(func (export "call_imported_function") (result i32)
|
|
301
|
+
(call $add (i32.const 20) (i32.const 22))
|
|
302
|
+
)
|
|
303
|
+
`
|
|
304
|
+
let {call_imported_function} = run(src, {math:{ add: (a, b) => a + b }}).exports
|
|
305
|
+
|
|
306
|
+
is(call_imported_function(), 42)
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
t('wat-compiler: import memory 1', () => {
|
|
310
|
+
run(`
|
|
311
|
+
(import "env" "mem" (memory 1))
|
|
312
|
+
`, {env: {mem: new WebAssembly.Memory({initial:1})}})
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
t('wat-compiler: import memory 1 2', () => {
|
|
316
|
+
run(`
|
|
317
|
+
(import "env" "mem" (memory 1 2))
|
|
318
|
+
`, {env: {mem: new WebAssembly.Memory({initial:1, maximum:1})}})
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
t('wat-compiler: import memory 1 2 shared', () => {
|
|
322
|
+
run(`
|
|
323
|
+
(import "env" "mem" (memory 1 2 shared))
|
|
324
|
+
`, {env: {mem: new WebAssembly.Memory({initial:1, maximum:1, shared:1})}})
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
t('wat-compiler: import memory $foo 1 2 shared', () => run(`
|
|
328
|
+
(import "env" "mem" (memory $foo 1 2 shared))
|
|
329
|
+
`, {env:{mem: new WebAssembly.Memory({initial:1, maximum: 1, shared: 1})}}))
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
t('wat-compiler: set a start function', () => {
|
|
333
|
+
let src = `
|
|
334
|
+
(global $answer (mut i32) (i32.const 42))
|
|
335
|
+
(start $main)
|
|
336
|
+
(func $main
|
|
337
|
+
(global.set $answer (i32.const 666))
|
|
338
|
+
)
|
|
339
|
+
(func (export "get") (result i32)
|
|
340
|
+
(global.get $answer)
|
|
341
|
+
)
|
|
342
|
+
`
|
|
343
|
+
let {get} = run(src).exports
|
|
344
|
+
|
|
345
|
+
is(get(), 666)
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
t('wat-compiler: if else', () => {
|
|
349
|
+
let src1 = `
|
|
350
|
+
(func $dummy)
|
|
351
|
+
(func (export "foo") (param i32) (result i32)
|
|
352
|
+
(if (result i32) (local.get 0)
|
|
353
|
+
(then (call $dummy) (i32.const 1))
|
|
354
|
+
(else (call $dummy) (i32.const 0))
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
`, src2 = `
|
|
358
|
+
(func $dummy)
|
|
359
|
+
(func (export "foo") (param i32) (result i32)
|
|
360
|
+
(local.get 0)
|
|
361
|
+
if (result i32)
|
|
362
|
+
(call $dummy)
|
|
363
|
+
(i32.const 1)
|
|
364
|
+
else
|
|
365
|
+
(call $dummy)
|
|
366
|
+
(i32.const 0)
|
|
367
|
+
end
|
|
368
|
+
)
|
|
369
|
+
`
|
|
370
|
+
// these are identical parts, but we restrict only lisp syntax src1
|
|
371
|
+
// console.log(wat(src1))
|
|
372
|
+
is(wat(src1).buffer, wat(src2).buffer)
|
|
373
|
+
let {foo} = run(src1).exports
|
|
374
|
+
is(foo(0), 0)
|
|
375
|
+
is(foo(1), 1)
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
t.skip('bench: if', () => {
|
|
379
|
+
let src = `(func $dummy)
|
|
380
|
+
(func (export "foo") (param i32) (result i32)
|
|
381
|
+
(if (result i32) (local.get 0)
|
|
382
|
+
(then (call $dummy) (i32.const 1))
|
|
383
|
+
(else (call $dummy) (i32.const 0))
|
|
384
|
+
)
|
|
385
|
+
)`
|
|
386
|
+
is(compile(parse(src)), watCompiler(src))
|
|
387
|
+
let N = 5000
|
|
388
|
+
|
|
389
|
+
console.time('watr')
|
|
390
|
+
for (let i = 0; i < N; i++) compile(parse(src))
|
|
391
|
+
console.timeEnd('watr')
|
|
392
|
+
|
|
393
|
+
console.time('wat-compiler')
|
|
394
|
+
for (let i = 0; i < N; i++) watCompiler(src, {metrics: false})
|
|
395
|
+
console.timeEnd('wat-compiler')
|
|
396
|
+
|
|
397
|
+
console.time('wabt')
|
|
398
|
+
for (let i = 0; i < N; i++) wat(src, {metrics: false})
|
|
399
|
+
console.timeEnd('wabt')
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
t('wat-compiler: block', () => {
|
|
403
|
+
let src = `
|
|
404
|
+
(func (export "answer") (result i32)
|
|
405
|
+
(block (nop))
|
|
406
|
+
(block (result i32) (i32.const 42))
|
|
407
|
+
)
|
|
408
|
+
`
|
|
409
|
+
let {answer} = run(src).exports
|
|
410
|
+
is(answer(), 42)
|
|
411
|
+
is(answer(), 42)
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
t('wat-compiler: block multi', () => {
|
|
415
|
+
let src = `
|
|
416
|
+
(func $dummy)
|
|
417
|
+
(func (export "multi") (result i32)
|
|
418
|
+
(block (call $dummy) (call $dummy) (call $dummy) (call $dummy))
|
|
419
|
+
(block (result i32) (call $dummy) (call $dummy) (call $dummy) (i32.const 8))
|
|
420
|
+
)
|
|
421
|
+
`
|
|
422
|
+
let {multi} = run(src).exports
|
|
423
|
+
is(multi(), 8)
|
|
424
|
+
is(multi(), 8)
|
|
425
|
+
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
t('wat-compiler: br', () => {
|
|
429
|
+
let src = `
|
|
430
|
+
(global $answer (mut i32) (i32.const 42))
|
|
431
|
+
(func $set
|
|
432
|
+
(global.set $answer (i32.const 666))
|
|
433
|
+
)
|
|
434
|
+
(func (export "main") (result i32)
|
|
435
|
+
(block (br 0) (call $set))
|
|
436
|
+
(global.get $answer)
|
|
437
|
+
)
|
|
438
|
+
`
|
|
439
|
+
|
|
440
|
+
let {main} = run(src).exports
|
|
441
|
+
is(main(), 42)
|
|
442
|
+
is(main(), 42)
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
t('wat-compiler: br mid', () => {
|
|
446
|
+
let src = `
|
|
447
|
+
(global $answer (mut i32) (i32.const 42))
|
|
448
|
+
(func $set
|
|
449
|
+
(global.set $answer (i32.const 666))
|
|
450
|
+
)
|
|
451
|
+
(func (export "main") (result i32)
|
|
452
|
+
(block (call $set) (br 0) (global.set $answer (i32.const 0)))
|
|
453
|
+
(global.get $answer)
|
|
454
|
+
)
|
|
455
|
+
`
|
|
456
|
+
let {main} = run(src).exports
|
|
457
|
+
is(main(), 666)
|
|
458
|
+
is(main(), 666)
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
t('wat-compiler: block named + br', () => {
|
|
462
|
+
let src = `
|
|
463
|
+
(global $answer (mut i32) (i32.const 42))
|
|
464
|
+
(func $set
|
|
465
|
+
(global.set $answer (i32.const 666))
|
|
466
|
+
)
|
|
467
|
+
(func (export "main") (result i32)
|
|
468
|
+
(block $outerer ;; 3
|
|
469
|
+
(block $outer ;; 2
|
|
470
|
+
(block $inner ;; 1
|
|
471
|
+
(block $innerer ;; 0
|
|
472
|
+
(call $set)
|
|
473
|
+
(br 1)
|
|
474
|
+
)
|
|
475
|
+
)
|
|
476
|
+
(global.set $answer (i32.const 0))
|
|
477
|
+
)
|
|
478
|
+
)
|
|
479
|
+
(global.get $answer)
|
|
480
|
+
)
|
|
481
|
+
`
|
|
482
|
+
// console.log(wat(src))
|
|
483
|
+
let {main} = run(src).exports
|
|
484
|
+
is(main(), 0)
|
|
485
|
+
is(main(), 0)
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
t('wat-compiler: block named 2 + br', () => {
|
|
489
|
+
let src = `
|
|
490
|
+
(global $answer (mut i32) (i32.const 42))
|
|
491
|
+
(func $set
|
|
492
|
+
(global.set $answer (i32.const 666))
|
|
493
|
+
)
|
|
494
|
+
(func (export "main") (result i32)
|
|
495
|
+
(block $outer
|
|
496
|
+
(block $inner
|
|
497
|
+
(call $set)
|
|
498
|
+
(br $inner)
|
|
499
|
+
)
|
|
500
|
+
(block $inner2
|
|
501
|
+
(global.set $answer (i32.const 444))
|
|
502
|
+
(br $inner2)
|
|
503
|
+
)
|
|
504
|
+
(global.set $answer (i32.const 0))
|
|
505
|
+
)
|
|
506
|
+
(global.get $answer)
|
|
507
|
+
)
|
|
508
|
+
`
|
|
509
|
+
let {main} = run(src).exports
|
|
510
|
+
|
|
511
|
+
is(main(), 0)
|
|
512
|
+
is(main(), 0)
|
|
513
|
+
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
t('wat-compiler: br_table', () => {
|
|
517
|
+
let src = `
|
|
518
|
+
(func (export "main") (param i32) (result i32)
|
|
519
|
+
(block
|
|
520
|
+
(block
|
|
521
|
+
(br_table 1 0 (local.get 0))
|
|
522
|
+
(return (i32.const 21))
|
|
523
|
+
)
|
|
524
|
+
(return (i32.const 20))
|
|
525
|
+
)
|
|
526
|
+
(i32.const 22)
|
|
527
|
+
)
|
|
528
|
+
`
|
|
529
|
+
// console.log(wat(src))
|
|
530
|
+
let {main} = run(src).exports
|
|
531
|
+
is(main(0), 22)
|
|
532
|
+
is(main(1), 20)
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
t('wat-compiler: br_table multiple', () => {
|
|
536
|
+
let src = `
|
|
537
|
+
(func (export "main") (param i32) (result i32)
|
|
538
|
+
(block
|
|
539
|
+
(block
|
|
540
|
+
(block
|
|
541
|
+
(block
|
|
542
|
+
(block
|
|
543
|
+
(br_table 3 2 1 0 4 (local.get 0))
|
|
544
|
+
(return (i32.const 99))
|
|
545
|
+
)
|
|
546
|
+
(return (i32.const 100))
|
|
547
|
+
)
|
|
548
|
+
(return (i32.const 101))
|
|
549
|
+
)
|
|
550
|
+
(return (i32.const 102))
|
|
551
|
+
)
|
|
552
|
+
(return (i32.const 103))
|
|
553
|
+
)
|
|
554
|
+
(i32.const 104)
|
|
555
|
+
)
|
|
556
|
+
`
|
|
557
|
+
let {main} = run(src).exports
|
|
558
|
+
|
|
559
|
+
is(main(0), 103)
|
|
560
|
+
is(main(1), 102)
|
|
561
|
+
is(main(2), 101)
|
|
562
|
+
is(main(3), 100)
|
|
563
|
+
is(main(4), 104)
|
|
564
|
+
})
|
|
565
|
+
|
|
566
|
+
t('wat-compiler: loop', () => {
|
|
567
|
+
let src = `
|
|
568
|
+
(func (export "main") (result i32)
|
|
569
|
+
(loop (nop))
|
|
570
|
+
(loop (result i32) (i32.const 42))
|
|
571
|
+
)
|
|
572
|
+
`
|
|
573
|
+
let {main} = run(src).exports
|
|
574
|
+
is(main(), 42)
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
t('wat-compiler: break-value', () => {
|
|
578
|
+
let src = `
|
|
579
|
+
(func (export "main") (result i32)
|
|
580
|
+
(block (result i32)
|
|
581
|
+
(loop (result i32) (br 1 (i32.const 18)) (br 0) (i32.const 19))
|
|
582
|
+
)
|
|
583
|
+
)
|
|
584
|
+
`
|
|
585
|
+
// console.log(wat(src))
|
|
586
|
+
let {main} = run(src).exports
|
|
587
|
+
is(main(), 18)
|
|
588
|
+
is(main(), 18)
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
t('wat-compiler: br_if', () => {
|
|
592
|
+
let src = `
|
|
593
|
+
(func (export "main") (result i32)
|
|
594
|
+
(block (result i32)
|
|
595
|
+
(loop (result i32)
|
|
596
|
+
(br 1 (i32.const 18))
|
|
597
|
+
(br 1 (i32.const 19))
|
|
598
|
+
(drop (br_if 1 (i32.const 20) (i32.const 0)))
|
|
599
|
+
(drop (br_if 1 (i32.const 20) (i32.const 1)))
|
|
600
|
+
(br 1 (i32.const 21))
|
|
601
|
+
(br_table 1 (i32.const 22) (i32.const 0))
|
|
602
|
+
(br_table 1 1 1 (i32.const 23) (i32.const 1))
|
|
603
|
+
(i32.const 21)
|
|
604
|
+
)
|
|
605
|
+
)
|
|
606
|
+
)
|
|
607
|
+
`
|
|
608
|
+
let {main} = run(src).exports
|
|
609
|
+
is(main(), 18)
|
|
610
|
+
})
|
|
611
|
+
|
|
612
|
+
t('wat-compiler: while', () => {
|
|
613
|
+
let src = `
|
|
614
|
+
(func (export "main") (param i32) (result i32)
|
|
615
|
+
(local i32)
|
|
616
|
+
(local.set 1 (i32.const 1))
|
|
617
|
+
(block
|
|
618
|
+
(loop
|
|
619
|
+
(br_if 1 (i32.eqz (local.get 0)))
|
|
620
|
+
(local.set 1 (i32.mul (local.get 0) (local.get 1)))
|
|
621
|
+
(local.set 0 (i32.sub (local.get 0) (i32.const 1)))
|
|
622
|
+
(br 0)
|
|
623
|
+
)
|
|
624
|
+
)
|
|
625
|
+
(local.get 1)
|
|
626
|
+
)
|
|
627
|
+
`
|
|
628
|
+
let {main} = run(src).exports
|
|
629
|
+
is(main(), 1)
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
t('wat-compiler: select', () => {
|
|
633
|
+
let src = `
|
|
634
|
+
(func (export "main") (result i32)
|
|
635
|
+
(select (loop (result i32) (i32.const 1)) (i32.const 2) (i32.const 3))
|
|
636
|
+
)
|
|
637
|
+
`
|
|
638
|
+
let {main} = run(src).exports
|
|
639
|
+
is(main(), 1)
|
|
640
|
+
})
|
|
641
|
+
|
|
642
|
+
t('wat-compiler: select mid', () => {
|
|
643
|
+
let src = `
|
|
644
|
+
(func (export "main") (result i32)
|
|
645
|
+
(select (i32.const 2) (loop (result i32) (i32.const 1)) (i32.const 3))
|
|
646
|
+
)
|
|
647
|
+
`
|
|
648
|
+
let {main} = run(src).exports
|
|
649
|
+
is(main(), 2)
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
t('wat-compiler: block labels', () => {
|
|
653
|
+
let src = `
|
|
654
|
+
(func (export "main") (result i32)
|
|
655
|
+
(block $exit (result i32)
|
|
656
|
+
(br $exit (i32.const 1))
|
|
657
|
+
(i32.const 0)
|
|
658
|
+
)
|
|
659
|
+
)
|
|
660
|
+
`
|
|
661
|
+
let {main} = run(src).exports
|
|
662
|
+
is(main(), 1)
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
t('wat-compiler: loop labels', () => {
|
|
666
|
+
let src = `
|
|
667
|
+
(func (export "main") (result i32)
|
|
668
|
+
(local $i i32)
|
|
669
|
+
(local.set $i (i32.const 0))
|
|
670
|
+
(block $exit (result i32)
|
|
671
|
+
(loop $cont (result i32)
|
|
672
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
673
|
+
(if (i32.eq (local.get $i) (i32.const 5))
|
|
674
|
+
(then (br $exit (local.get $i)))
|
|
675
|
+
)
|
|
676
|
+
(br $cont)
|
|
677
|
+
)
|
|
678
|
+
)
|
|
679
|
+
)
|
|
680
|
+
`
|
|
681
|
+
// console.log(wat(src))
|
|
682
|
+
let {main} = run(src).exports
|
|
683
|
+
is(main(), 5)
|
|
684
|
+
})
|
|
685
|
+
|
|
686
|
+
t('wat-compiler: loop labels 2', () => {
|
|
687
|
+
let src = `
|
|
688
|
+
(func (export "main") (result i32)
|
|
689
|
+
(local $i i32)
|
|
690
|
+
(local.set $i (i32.const 0))
|
|
691
|
+
(block $exit (result i32)
|
|
692
|
+
(loop $cont (result i32)
|
|
693
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
694
|
+
(if (i32.eq (local.get $i) (i32.const 5))
|
|
695
|
+
(then (br $cont))
|
|
696
|
+
)
|
|
697
|
+
(if (i32.eq (local.get $i) (i32.const 8))
|
|
698
|
+
(then (br $exit (local.get $i)))
|
|
699
|
+
)
|
|
700
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
701
|
+
(br $cont)
|
|
702
|
+
)
|
|
703
|
+
)
|
|
704
|
+
)
|
|
705
|
+
`
|
|
706
|
+
let {main} = run(src).exports
|
|
707
|
+
is(main(), 8)
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
t('wat-compiler: switch', () => {
|
|
711
|
+
let src = `
|
|
712
|
+
(func (export "main") (param i32) (result i32)
|
|
713
|
+
(block $ret (result i32)
|
|
714
|
+
(i32.mul (i32.const 10)
|
|
715
|
+
(block $exit (result i32)
|
|
716
|
+
(block $0
|
|
717
|
+
(block $default
|
|
718
|
+
(block $3
|
|
719
|
+
(block $2
|
|
720
|
+
(block $1
|
|
721
|
+
(br_table $0 $1 $2 $3 $default (local.get 0))
|
|
722
|
+
) ;; 1
|
|
723
|
+
) ;; 2
|
|
724
|
+
(br $exit (i32.const 2))
|
|
725
|
+
) ;; 3
|
|
726
|
+
(br $ret (i32.const 3))
|
|
727
|
+
) ;; default
|
|
728
|
+
) ;; 0
|
|
729
|
+
(i32.const 5)
|
|
730
|
+
)
|
|
731
|
+
)
|
|
732
|
+
)
|
|
733
|
+
)
|
|
734
|
+
`
|
|
735
|
+
// console.log(wat(src))
|
|
736
|
+
let {main} = run(src).exports
|
|
737
|
+
is(main(0), 50)
|
|
738
|
+
is(main(1), 20)
|
|
739
|
+
is(main(3), 3)
|
|
740
|
+
})
|
|
741
|
+
|
|
742
|
+
t('wat-compiler: label redefinition', () => {
|
|
743
|
+
let src = `
|
|
744
|
+
(func (export "main") (result i32)
|
|
745
|
+
(block $l1 (result i32)
|
|
746
|
+
(i32.add
|
|
747
|
+
(block $l1 (result i32) (i32.const 2))
|
|
748
|
+
(block $l1 (result i32) (br $l1 (i32.const 3)))
|
|
749
|
+
)
|
|
750
|
+
)
|
|
751
|
+
)
|
|
752
|
+
`
|
|
753
|
+
let {main} = run(src).exports
|
|
754
|
+
is(main(), 5)
|
|
755
|
+
})
|
|
756
|
+
|
|
757
|
+
t('wat-compiler: address', () => {
|
|
758
|
+
let src = `
|
|
759
|
+
(memory 1)
|
|
760
|
+
(data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
|
|
761
|
+
(func (export "a") (param $i i32) (result i32)
|
|
762
|
+
(i32.load8_u offset=0 (local.get $i)) ;; 97 'a'
|
|
763
|
+
)
|
|
764
|
+
(func (export "b") (param $i i32) (result i32)
|
|
765
|
+
(i32.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
|
|
766
|
+
)
|
|
767
|
+
(func (export "ab") (param $i i32) (result i32)
|
|
768
|
+
(i32.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
|
|
769
|
+
)
|
|
770
|
+
(func (export "cd") (param $i i32) (result i32)
|
|
771
|
+
(i32.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
|
|
772
|
+
)
|
|
773
|
+
(func (export "z") (param $i i32) (result i32)
|
|
774
|
+
(i32.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
|
|
775
|
+
)
|
|
776
|
+
`
|
|
777
|
+
// console.log(wat(src))
|
|
778
|
+
let {a,b,ab,cd,z}=run(src).exports
|
|
779
|
+
is(a(), 97)
|
|
780
|
+
is(b(), 98)
|
|
781
|
+
is(ab(), 25185)
|
|
782
|
+
is(cd(), 25699)
|
|
783
|
+
is(z(), 122)
|
|
784
|
+
})
|
|
785
|
+
|
|
786
|
+
t('wat-compiler: int literals', () => {
|
|
787
|
+
let src = `
|
|
788
|
+
(func (export "i32.test") (result i32) (return (i32.const 0x0bAdD00D)))
|
|
789
|
+
(func (export "i32.umax") (result i32) (return (i32.const 0xffffffff)))
|
|
790
|
+
(func (export "i32.smax") (result i32) (return (i32.const 0x7fffffff)))
|
|
791
|
+
(func (export "i32.neg_smax") (result i32) (return (i32.const -0x7fffffff)))
|
|
792
|
+
(func (export "i32.smin") (result i32) (return (i32.const -0x80000000)))
|
|
793
|
+
(func (export "i32.alt_smin") (result i32) (return (i32.const 0x80000000)))
|
|
794
|
+
(func (export "i32.inc_smin") (result i32) (return (i32.add (i32.const -0x80000000) (i32.const 1))))
|
|
795
|
+
(func (export "i32.neg_zero") (result i32) (return (i32.const -0x0)))
|
|
796
|
+
(func (export "i32.not_octal") (result i32) (return (i32.const 010)))
|
|
797
|
+
(func (export "i32.plus_sign") (result i32) (return (i32.const +42)))
|
|
798
|
+
(func (export "i32.unsigned_decimal") (result i32) (return (i32.const 4294967295)))
|
|
799
|
+
(func (export "i64.neg_zero") (result i64) (return (i64.const -0x0)))
|
|
800
|
+
(func (export "i64.not_octal") (result i64) (return (i64.const 010)))
|
|
801
|
+
(func (export "i64.plus_sign") (result i64) (return (i64.const +42)))
|
|
802
|
+
(;func (export "i64.test") (result i64) (return (i64.const 0x0CABBA6E0ba66a6e)))
|
|
803
|
+
(func (export "i64.umax") (result i64) (return (i64.const 0xffffffffffffffff)))
|
|
804
|
+
(func (export "i32-dec-sep1") (result i32) (i32.const 1_000_000))
|
|
805
|
+
(func (export "i32-dec-sep2") (result i32) (i32.const 1_0_0_0))
|
|
806
|
+
(func (export "i32-hex-sep1") (result i32) (i32.const 0xa_0f_00_99))
|
|
807
|
+
(func (export "i32-hex-sep2") (result i32) (i32.const 0x1_a_A_0_f))
|
|
808
|
+
(func (export "i64-dec-sep1") (result i64) (i64.const 1_000_000))
|
|
809
|
+
(func (export "i64-dec-sep2") (result i64) (i64.const 1_0_0_0))
|
|
810
|
+
(func (export "i64-hex-sep2") (result i64) (i64.const 0x1_a_A_0_f))
|
|
811
|
+
(func (export "i64.smax") (result i64) (return (i64.const 0x7fffffffffffffff)))
|
|
812
|
+
(func (export "i64.neg_smax") (result i64) (return (i64.const -0x7fffffffffffffff)))
|
|
813
|
+
(func (export "i64.smin") (result i64) (return (i64.const -0x8000000000000000)))
|
|
814
|
+
(func (export "i64.alt_smin") (result i64) (return (i64.const 0x8000000000000000)))
|
|
815
|
+
(func (export "i64.inc_smin") (result i64) (return (i64.add (i64.const -0x8000000000000000) (i64.const 1))))
|
|
816
|
+
(func (export "i64.unsigned_decimal") (result i64) (return (i64.const 18446744073709551615)))
|
|
817
|
+
(func (export "i64-hex-sep1") (result i64) (i64.const 0xa_f00f_0000_9999);)
|
|
818
|
+
`
|
|
819
|
+
run(src)
|
|
820
|
+
})
|
|
821
|
+
|
|
822
|
+
t('wat-compiler: float literals', () => {
|
|
823
|
+
let src = `
|
|
824
|
+
;; f32 in decimal format
|
|
825
|
+
(func (export "f32_dec.zero") (result i32) (i32.reinterpret_f32 (f32.const 0.0e0)))
|
|
826
|
+
(func (export "f32_dec.positive_zero") (result i32) (i32.reinterpret_f32 (f32.const +0.0e0)))
|
|
827
|
+
(func (export "f32_dec.negative_zero") (result i32) (i32.reinterpret_f32 (f32.const -0.0e0)))
|
|
828
|
+
(func (export "f32_dec.misc") (result i32) (i32.reinterpret_f32 (f32.const 6.28318548202514648)))
|
|
829
|
+
(func (export "f32_dec.min_positive") (result i32) (i32.reinterpret_f32 (f32.const 1.4013e-45)))
|
|
830
|
+
(func (export "f32_dec.min_normal") (result i32) (i32.reinterpret_f32 (f32.const 1.1754944e-38)))
|
|
831
|
+
(func (export "f32_dec.max_subnormal") (result i32) (i32.reinterpret_f32 (f32.const 1.1754942e-38)))
|
|
832
|
+
(func (export "f32_dec.max_finite") (result i32) (i32.reinterpret_f32 (f32.const 3.4028234e+38)))
|
|
833
|
+
(func (export "f32_dec.trailing_dot") (result i32) (i32.reinterpret_f32 (f32.const 1.e10)))
|
|
834
|
+
;; https://twitter.com/Archivd/status/994637336506912768
|
|
835
|
+
(func (export "f32_dec.root_beer_float") (result i32) (i32.reinterpret_f32 (f32.const 1.000000119)))
|
|
836
|
+
;; f64 numbers in decimal format
|
|
837
|
+
(func (export "f64_dec.zero") (result i64) (i64.reinterpret_f64 (f64.const 0.0e0)))
|
|
838
|
+
(func (export "f64_dec.positive_zero") (result i64) (i64.reinterpret_f64 (f64.const +0.0e0)))
|
|
839
|
+
(func (export "f64_dec.negative_zero") (result i64) (i64.reinterpret_f64 (f64.const -0.0e0)))
|
|
840
|
+
(func (export "f64_dec.misc") (result i64) (i64.reinterpret_f64 (f64.const 6.28318530717958623)))
|
|
841
|
+
(func (export "f64_dec.min_positive") (result i64) (i64.reinterpret_f64 (f64.const 4.94066e-324)))
|
|
842
|
+
(func (export "f64_dec.min_normal") (result i64) (i64.reinterpret_f64 (f64.const 2.2250738585072012e-308)))
|
|
843
|
+
(func (export "f64_dec.max_subnormal") (result i64) (i64.reinterpret_f64 (f64.const 2.2250738585072011e-308)))
|
|
844
|
+
(func (export "f64_dec.max_finite") (result i64) (i64.reinterpret_f64 (f64.const 1.7976931348623157e+308)))
|
|
845
|
+
(func (export "f64_dec.trailing_dot") (result i64) (i64.reinterpret_f64 (f64.const 1.e100)))
|
|
846
|
+
;; https://twitter.com/Archivd/status/994637336506912768
|
|
847
|
+
(func (export "f64_dec.root_beer_float") (result i64) (i64.reinterpret_f64 (f64.const 1.000000119)))
|
|
848
|
+
`
|
|
849
|
+
run(src)
|
|
850
|
+
|
|
851
|
+
let special = `
|
|
852
|
+
;; f32 special values
|
|
853
|
+
(func (export "f32.nan") (result i32) (i32.reinterpret_f32 (f32.const nan)))
|
|
854
|
+
(func (export "f32.positive_nan") (result i32) (i32.reinterpret_f32 (f32.const +nan)))
|
|
855
|
+
(func (export "f32.negative_nan") (result i32) (i32.reinterpret_f32 (f32.const -nan)))
|
|
856
|
+
(func (export "f32.plain_nan") (result i32) (i32.reinterpret_f32 (f32.const nan:0x400000)))
|
|
857
|
+
(func (export "f32.informally_known_as_plain_snan") (result i32) (i32.reinterpret_f32 (f32.const nan:0x200000)))
|
|
858
|
+
(func (export "f32.all_ones_nan") (result i32) (i32.reinterpret_f32 (f32.const -nan:0x7fffff)))
|
|
859
|
+
(func (export "f32.misc_nan") (result i32) (i32.reinterpret_f32 (f32.const nan:0x012345)))
|
|
860
|
+
(func (export "f32.misc_positive_nan") (result i32) (i32.reinterpret_f32 (f32.const +nan:0x304050)))
|
|
861
|
+
(func (export "f32.misc_negative_nan") (result i32) (i32.reinterpret_f32 (f32.const -nan:0x2abcde)))
|
|
862
|
+
(func (export "f32.infinity") (result i32) (i32.reinterpret_f32 (f32.const inf)))
|
|
863
|
+
(func (export "f32.positive_infinity") (result i32) (i32.reinterpret_f32 (f32.const +inf)))
|
|
864
|
+
(func (export "f32.negative_infinity") (result i32) (i32.reinterpret_f32 (f32.const -inf)))
|
|
865
|
+
;; f32 numbers
|
|
866
|
+
(;func (export "f32.zero") (result i32) (i32.reinterpret_f32 (f32.const 0x0.0p0)))
|
|
867
|
+
(func (export "f32.positive_zero") (result i32) (i32.reinterpret_f32 (f32.const +0x0.0p0)))
|
|
868
|
+
(func (export "f32.negative_zero") (result i32) (i32.reinterpret_f32 (f32.const -0x0.0p0)))
|
|
869
|
+
(func (export "f32.misc") (result i32) (i32.reinterpret_f32 (f32.const 0x1.921fb6p+2)))
|
|
870
|
+
(func (export "f32.min_positive") (result i32) (i32.reinterpret_f32 (f32.const 0x1p-149)))
|
|
871
|
+
(func (export "f32.min_normal") (result i32) (i32.reinterpret_f32 (f32.const 0x1p-126)))
|
|
872
|
+
(func (export "f32.max_finite") (result i32) (i32.reinterpret_f32 (f32.const 0x1.fffffep+127)))
|
|
873
|
+
(func (export "f32.max_subnormal") (result i32) (i32.reinterpret_f32 (f32.const 0x1.fffffcp-127)))
|
|
874
|
+
(func (export "f32.trailing_dot") (result i32) (i32.reinterpret_f32 (f32.const 0x1.p10));)
|
|
875
|
+
|
|
876
|
+
;; f64 special values
|
|
877
|
+
(func (export "f64.nan") (result i64) (i64.reinterpret_f64 (f64.const nan)))
|
|
878
|
+
(func (export "f64.positive_nan") (result i64) (i64.reinterpret_f64 (f64.const +nan)))
|
|
879
|
+
(func (export "f64.negative_nan") (result i64) (i64.reinterpret_f64 (f64.const -nan)))
|
|
880
|
+
(func (export "f64.plain_nan") (result i64) (i64.reinterpret_f64 (f64.const nan:0x8000000000000)))
|
|
881
|
+
(func (export "f64.informally_known_as_plain_snan") (result i64) (i64.reinterpret_f64 (f64.const nan:0x4000000000000)))
|
|
882
|
+
(func (export "f64.all_ones_nan") (result i64) (i64.reinterpret_f64 (f64.const -nan:0xfffffffffffff)))
|
|
883
|
+
(func (export "f64.misc_nan") (result i64) (i64.reinterpret_f64 (f64.const nan:0x0123456789abc)))
|
|
884
|
+
(func (export "f64.misc_positive_nan") (result i64) (i64.reinterpret_f64 (f64.const +nan:0x3040506070809)))
|
|
885
|
+
(func (export "f64.misc_negative_nan") (result i64) (i64.reinterpret_f64 (f64.const -nan:0x2abcdef012345)))
|
|
886
|
+
(func (export "f64.infinity") (result i64) (i64.reinterpret_f64 (f64.const inf)))
|
|
887
|
+
(func (export "f64.positive_infinity") (result i64) (i64.reinterpret_f64 (f64.const +inf)))
|
|
888
|
+
(func (export "f64.negative_infinity") (result i64) (i64.reinterpret_f64 (f64.const -inf)))
|
|
889
|
+
;; f64 numbers
|
|
890
|
+
(;func (export "f64.zero") (result i64) (i64.reinterpret_f64 (f64.const 0x0.0p0)))
|
|
891
|
+
(func (export "f64.positive_zero") (result i64) (i64.reinterpret_f64 (f64.const +0x0.0p0)))
|
|
892
|
+
(func (export "f64.negative_zero") (result i64) (i64.reinterpret_f64 (f64.const -0x0.0p0)))
|
|
893
|
+
(func (export "f64.misc") (result i64) (i64.reinterpret_f64 (f64.const 0x1.921fb54442d18p+2)))
|
|
894
|
+
(func (export "f64.min_positive") (result i64) (i64.reinterpret_f64 (f64.const 0x0.0000000000001p-1022)))
|
|
895
|
+
(func (export "f64.min_normal") (result i64) (i64.reinterpret_f64 (f64.const 0x1p-1022)))
|
|
896
|
+
(func (export "f64.max_subnormal") (result i64) (i64.reinterpret_f64 (f64.const 0x0.fffffffffffffp-1022)))
|
|
897
|
+
(func (export "f64.max_finite") (result i64) (i64.reinterpret_f64 (f64.const 0x1.fffffffffffffp+1023)))
|
|
898
|
+
(func (export "f64.trailing_dot") (result i64) (i64.reinterpret_f64 (f64.const 0x1.p100));)
|
|
899
|
+
|
|
900
|
+
(;func (export "f32-dec-sep1") (result f32) (f32.const 1_000_000))
|
|
901
|
+
(func (export "f32-dec-sep2") (result f32) (f32.const 1_0_0_0))
|
|
902
|
+
(func (export "f32-dec-sep3") (result f32) (f32.const 100_3.141_592))
|
|
903
|
+
(func (export "f32-dec-sep4") (result f32) (f32.const 99e+1_3))
|
|
904
|
+
(func (export "f32-dec-sep5") (result f32) (f32.const 122_000.11_3_54E0_2_3))
|
|
905
|
+
(func (export "f32-hex-sep1") (result f32) (f32.const 0xa_0f_00_99))
|
|
906
|
+
(func (export "f32-hex-sep2") (result f32) (f32.const 0x1_a_A_0_f))
|
|
907
|
+
(func (export "f32-hex-sep3") (result f32) (f32.const 0xa0_ff.f141_a59a))
|
|
908
|
+
(func (export "f32-hex-sep4") (result f32) (f32.const 0xf0P+1_3))
|
|
909
|
+
(func (export "f32-hex-sep5") (result f32) (f32.const 0x2a_f00a.1f_3_eep2_3))
|
|
910
|
+
(func (export "f64-dec-sep1") (result f64) (f64.const 1_000_000))
|
|
911
|
+
(func (export "f64-dec-sep2") (result f64) (f64.const 1_0_0_0))
|
|
912
|
+
(func (export "f64-dec-sep3") (result f64) (f64.const 100_3.141_592))
|
|
913
|
+
(func (export "f64-dec-sep4") (result f64) (f64.const 99e-1_23))
|
|
914
|
+
(func (export "f64-dec-sep5") (result f64) (f64.const 122_000.11_3_54e0_2_3))
|
|
915
|
+
(func (export "f64-hex-sep1") (result f64) (f64.const 0xa_f00f_0000_9999))
|
|
916
|
+
(func (export "f64-hex-sep2") (result f64) (f64.const 0x1_a_A_0_f))
|
|
917
|
+
(func (export "f64-hex-sep3") (result f64) (f64.const 0xa0_ff.f141_a59a))
|
|
918
|
+
(func (export "f64-hex-sep4") (result f64) (f64.const 0xf0P+1_3))
|
|
919
|
+
(func (export "f64-hex-sep5") (result f64) (f64.const 0x2a_f00a.1f_3_eep2_3);)`
|
|
920
|
+
|
|
921
|
+
run(special)
|
|
922
|
+
})
|
|
923
|
+
|
|
924
|
+
t(`export 2 funcs`, () => run(`
|
|
925
|
+
(func (export "value") (result i32)
|
|
926
|
+
(i32.const 42)
|
|
927
|
+
)
|
|
928
|
+
(func (export "another") (result i32)
|
|
929
|
+
(i32.const 666)
|
|
930
|
+
)
|
|
931
|
+
`))
|
|
932
|
+
|
|
933
|
+
t(`exported & unexported function`, () => {
|
|
934
|
+
run(`
|
|
935
|
+
(func (export "value") (result i32)
|
|
936
|
+
(i32.const 42)
|
|
937
|
+
)
|
|
938
|
+
(func (result i32)
|
|
939
|
+
(i32.const 666)
|
|
940
|
+
)
|
|
941
|
+
`)
|
|
942
|
+
})
|
|
943
|
+
|
|
944
|
+
t(`2 different locals`, () => {
|
|
945
|
+
let src = `
|
|
946
|
+
(func (export "value") (result i32)
|
|
947
|
+
(local i32)
|
|
948
|
+
(local i64)
|
|
949
|
+
(i32.const 42)
|
|
950
|
+
)
|
|
951
|
+
`
|
|
952
|
+
let {value} = run(src).exports
|
|
953
|
+
is(value(), 42)
|
|
954
|
+
})
|
|
955
|
+
|
|
956
|
+
t(`3 locals [i32, i64, i32] (disjointed)`, () => {
|
|
957
|
+
let src = `
|
|
958
|
+
(func (export "value") (result i32)
|
|
959
|
+
(local i32)
|
|
960
|
+
(local i64)
|
|
961
|
+
(local i32)
|
|
962
|
+
(i32.const 42)
|
|
963
|
+
)
|
|
964
|
+
`
|
|
965
|
+
let {value} = run(src).exports
|
|
966
|
+
is(value(), 42)
|
|
967
|
+
})
|
|
968
|
+
|
|
969
|
+
t(`3 locals [i32, i32, i64] (joined)`, () => {
|
|
970
|
+
let src = `
|
|
971
|
+
(func (export "value") (result i32)
|
|
972
|
+
(local i32)
|
|
973
|
+
(local i32)
|
|
974
|
+
(local i64)
|
|
975
|
+
(i32.const 42)
|
|
976
|
+
)
|
|
977
|
+
`
|
|
978
|
+
let {value} = run(src).exports
|
|
979
|
+
is(value(), 42)
|
|
980
|
+
})
|
|
981
|
+
|
|
982
|
+
t('call function indirect (table)', () => {
|
|
983
|
+
let src = `
|
|
984
|
+
(type $return_i32 (func (result i32)))
|
|
985
|
+
(table 2 funcref)
|
|
986
|
+
(elem (i32.const 0) $f1 $f2)
|
|
987
|
+
(func $f1 (result i32)
|
|
988
|
+
(i32.const 42))
|
|
989
|
+
(func $f2 (result i32)
|
|
990
|
+
(i32.const 13))
|
|
991
|
+
(func (export "call_function_indirect") (param $a i32) (result i32)
|
|
992
|
+
(call_indirect (type $return_i32) (local.get $a))
|
|
993
|
+
)
|
|
994
|
+
`
|
|
995
|
+
let {call_function_indirect} = run(src).exports
|
|
996
|
+
|
|
997
|
+
is(call_function_indirect(0), 42)
|
|
998
|
+
is(call_function_indirect(1), 13)
|
|
999
|
+
})
|
|
1000
|
+
|
|
1001
|
+
t('call function indirect (table) non zero indexed ref types', () => {
|
|
1002
|
+
let src = `
|
|
1003
|
+
(type $return_i64 (func (result i64)))
|
|
1004
|
+
(type $return_i32 (func (result i32)))
|
|
1005
|
+
(table 2 funcref)
|
|
1006
|
+
(elem (i32.const 0) $f1 $f2)
|
|
1007
|
+
(func $xx (result i64)
|
|
1008
|
+
(i64.const 42))
|
|
1009
|
+
(func $f1 (result i32)
|
|
1010
|
+
(i32.const 42))
|
|
1011
|
+
(func $f2 (result i32)
|
|
1012
|
+
(i32.const 13))
|
|
1013
|
+
(func (export "call_function_indirect") (param $a i32) (result i32)
|
|
1014
|
+
(call_indirect (type $return_i32) (local.get $a))
|
|
1015
|
+
)
|
|
1016
|
+
`
|
|
1017
|
+
let {call_function_indirect} = run(src).exports
|
|
1018
|
+
|
|
1019
|
+
is(call_function_indirect(0), 42)
|
|
1020
|
+
is(call_function_indirect(1), 13)
|
|
1021
|
+
})
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
// e2e
|
|
1026
|
+
// TODO: examples
|
|
1027
|
+
const e2e = [
|
|
1028
|
+
'malloc',
|
|
1029
|
+
'brownian',
|
|
1030
|
+
'containers',
|
|
1031
|
+
'quine',
|
|
1032
|
+
'fire',
|
|
1033
|
+
'metaball',
|
|
1034
|
+
'raytrace',
|
|
1035
|
+
'snake',
|
|
1036
|
+
'maze',
|
|
1037
|
+
'dino',
|
|
1038
|
+
'raycast',
|
|
1039
|
+
]
|
|
1040
|
+
|
|
1041
|
+
e2e.forEach(name => {
|
|
1042
|
+
t.todo('wat-compiler: e2e: '+name, () =>
|
|
1043
|
+
fetch('/test/fixtures/e2e/'+name+'.wat')
|
|
1044
|
+
.then(res => res.text())
|
|
1045
|
+
.then(text => buffers(text))
|
|
1046
|
+
.then(([exp,act]) => hexAssertEqual(exp,act)))
|
|
1047
|
+
})
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
let wabt = await Wabt()
|
|
1053
|
+
|
|
1054
|
+
const hex = (str, ...fields) =>
|
|
1055
|
+
new Uint8Array(
|
|
1056
|
+
String.raw.call(null, str, fields)
|
|
1057
|
+
.trim()
|
|
1058
|
+
.replace(/;[^\n]*/g,'')
|
|
1059
|
+
.split(/[\s\n]+/)
|
|
1060
|
+
.filter(n => n !== '')
|
|
1061
|
+
.map(n => parseInt(n, 16))
|
|
1062
|
+
)
|
|
1063
|
+
|
|
1064
|
+
function wat (code, config) {
|
|
1065
|
+
let metrics = config ? config.metrics : true
|
|
1066
|
+
const parsed = wabt.parseWat('inline', code, {})
|
|
1067
|
+
metrics && console.time('wabt build')
|
|
1068
|
+
const binary = parsed.toBinary({
|
|
1069
|
+
log: true,
|
|
1070
|
+
canonicalize_lebs: true,
|
|
1071
|
+
relocatable: false,
|
|
1072
|
+
write_debug_names: false,
|
|
1073
|
+
})
|
|
1074
|
+
parsed.destroy()
|
|
1075
|
+
metrics && console.timeEnd('wabt build')
|
|
1076
|
+
|
|
1077
|
+
return binary
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// run test case against wabt, return instance
|
|
1081
|
+
// FIXME: rename to something more meaningful? testCase?
|
|
1082
|
+
const run = (src, importObj) => {
|
|
1083
|
+
let tree = parse(src)
|
|
1084
|
+
const freeze = node => Array.isArray(node) && (Object.freeze(node), node.forEach(freeze))
|
|
1085
|
+
freeze(tree)
|
|
1086
|
+
let buffer = compile(tree)
|
|
1087
|
+
is(buffer, wat(src).buffer)
|
|
1088
|
+
const mod = new WebAssembly.Module(buffer)
|
|
1089
|
+
return new WebAssembly.Instance(mod, importObj)
|
|
1090
|
+
}
|