wardite 0.1.2 → 0.2.1
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.
- checksums.yaml +4 -4
- data/Rakefile +178 -0
- data/Steepfile +1 -0
- data/examples/consts.wat +12 -0
- data/lib/wardite/alu_f32.generated.rb +250 -0
- data/lib/wardite/alu_f64.generated.rb +250 -0
- data/lib/wardite/alu_i32.generated.rb +457 -0
- data/lib/wardite/alu_i64.generated.rb +514 -0
- data/lib/wardite/convert.generated.rb +234 -0
- data/lib/wardite/instruction.rb +82 -33
- data/lib/wardite/leb128.rb +1 -1
- data/lib/wardite/value.rb +627 -0
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +6 -4
- data/lib/wardite.rb +192 -115
- data/scripts/gen_alu.rb +750 -0
- data/scripts/gen_conv.rb +76 -0
- data/scripts/templates/alu_module.rb.tmpl +18 -0
- data/scripts/templates/conv_module.rb.tmpl +18 -0
- data/sig/generated/wardite/alu_f32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_f64.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i64.generated.rbs +11 -0
- data/sig/generated/wardite/convert.generated.rbs +11 -0
- data/sig/generated/wardite/instruction.rbs +15 -6
- data/sig/generated/wardite/leb128.rbs +1 -1
- data/sig/generated/wardite/value.rbs +302 -0
- data/sig/generated/wardite/wasi.rbs +4 -2
- data/sig/generated/wardite.rbs +27 -12
- metadata +19 -2
@@ -0,0 +1,457 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
require_relative "value"
|
3
|
+
|
4
|
+
module Wardite
|
5
|
+
module Evaluator
|
6
|
+
# @rbs runtime: Runtime
|
7
|
+
# @rbs frame: Frame
|
8
|
+
# @rbs insn: Op
|
9
|
+
# @rbs return: void
|
10
|
+
def self.i32_eval_insn(runtime, frame, insn)
|
11
|
+
case insn.code
|
12
|
+
|
13
|
+
when :i32_load
|
14
|
+
_align = insn.operand[0] # TODO: alignment support?
|
15
|
+
offset = insn.operand[1]
|
16
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
17
|
+
|
18
|
+
addr = runtime.stack.pop
|
19
|
+
if !addr.is_a?(I32)
|
20
|
+
raise EvalError, "maybe stack too short"
|
21
|
+
end
|
22
|
+
|
23
|
+
at = addr.value + offset
|
24
|
+
data_end = at + I32.new.memsize / 8
|
25
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
26
|
+
buf = memory.data[at...data_end]
|
27
|
+
if !buf
|
28
|
+
raise EvalError, "invalid memory range"
|
29
|
+
end
|
30
|
+
runtime.stack.push(I32.from_bytes(buf))
|
31
|
+
|
32
|
+
|
33
|
+
when :i32_load8_s
|
34
|
+
_align = insn.operand[0] # TODO: alignment support?
|
35
|
+
offset = insn.operand[1]
|
36
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
37
|
+
|
38
|
+
addr = runtime.stack.pop
|
39
|
+
if !addr.is_a?(I32)
|
40
|
+
raise EvalError, "maybe stack too short"
|
41
|
+
end
|
42
|
+
|
43
|
+
at = addr.value + offset
|
44
|
+
data_end = at + 1
|
45
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
46
|
+
buf = memory.data[at...data_end]
|
47
|
+
if !buf
|
48
|
+
raise EvalError, "invalid memory range"
|
49
|
+
end
|
50
|
+
runtime.stack.push(I32.from_bytes(buf, size: 8, signed: true))
|
51
|
+
|
52
|
+
|
53
|
+
when :i32_load8_u
|
54
|
+
_align = insn.operand[0] # TODO: alignment support?
|
55
|
+
offset = insn.operand[1]
|
56
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
57
|
+
|
58
|
+
addr = runtime.stack.pop
|
59
|
+
if !addr.is_a?(I32)
|
60
|
+
raise EvalError, "maybe stack too short"
|
61
|
+
end
|
62
|
+
|
63
|
+
at = addr.value + offset
|
64
|
+
data_end = at + 1
|
65
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
66
|
+
buf = memory.data[at...data_end]
|
67
|
+
if !buf
|
68
|
+
raise EvalError, "invalid memory range"
|
69
|
+
end
|
70
|
+
runtime.stack.push(I32.from_bytes(buf, size: 8, signed: false))
|
71
|
+
|
72
|
+
|
73
|
+
when :i32_load16_s
|
74
|
+
_align = insn.operand[0] # TODO: alignment support?
|
75
|
+
offset = insn.operand[1]
|
76
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
77
|
+
|
78
|
+
addr = runtime.stack.pop
|
79
|
+
if !addr.is_a?(I32)
|
80
|
+
raise EvalError, "maybe stack too short"
|
81
|
+
end
|
82
|
+
|
83
|
+
at = addr.value + offset
|
84
|
+
data_end = at + 2
|
85
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
86
|
+
buf = memory.data[at...data_end]
|
87
|
+
if !buf
|
88
|
+
raise EvalError, "invalid memory range"
|
89
|
+
end
|
90
|
+
runtime.stack.push(I32.from_bytes(buf, size: 16, signed: true))
|
91
|
+
|
92
|
+
|
93
|
+
when :i32_load16_u
|
94
|
+
_align = insn.operand[0] # TODO: alignment support?
|
95
|
+
offset = insn.operand[1]
|
96
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
97
|
+
|
98
|
+
addr = runtime.stack.pop
|
99
|
+
if !addr.is_a?(I32)
|
100
|
+
raise EvalError, "maybe stack too short"
|
101
|
+
end
|
102
|
+
|
103
|
+
at = addr.value + offset
|
104
|
+
data_end = at + 2
|
105
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
106
|
+
buf = memory.data[at...data_end]
|
107
|
+
if !buf
|
108
|
+
raise EvalError, "invalid memory range"
|
109
|
+
end
|
110
|
+
runtime.stack.push(I32.from_bytes(buf, size: 16, signed: false))
|
111
|
+
|
112
|
+
|
113
|
+
when :i32_store
|
114
|
+
_align = insn.operand[0] # TODO: alignment support?
|
115
|
+
offset = insn.operand[1]
|
116
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
117
|
+
|
118
|
+
value = runtime.stack.pop
|
119
|
+
addr = runtime.stack.pop
|
120
|
+
if !value.is_a?(I32) || !addr.is_a?(I32)
|
121
|
+
raise EvalError, "maybe stack too short"
|
122
|
+
end
|
123
|
+
|
124
|
+
at = addr.value + offset
|
125
|
+
data_end = at + value.packed.size
|
126
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
127
|
+
memory.data[at...data_end] = value.packed
|
128
|
+
|
129
|
+
|
130
|
+
when :i32_store8
|
131
|
+
_align = insn.operand[0] # TODO: alignment support?
|
132
|
+
offset = insn.operand[1]
|
133
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
134
|
+
|
135
|
+
value = runtime.stack.pop
|
136
|
+
addr = runtime.stack.pop
|
137
|
+
if !value.is_a?(I32) || !addr.is_a?(I32)
|
138
|
+
raise EvalError, "maybe stack too short"
|
139
|
+
end
|
140
|
+
|
141
|
+
at = addr.value + offset
|
142
|
+
data_end = at + 1
|
143
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
144
|
+
memory.data[at...data_end] = value.packed(size: 8)
|
145
|
+
|
146
|
+
|
147
|
+
when :i32_store16
|
148
|
+
_align = insn.operand[0] # TODO: alignment support?
|
149
|
+
offset = insn.operand[1]
|
150
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
151
|
+
|
152
|
+
value = runtime.stack.pop
|
153
|
+
addr = runtime.stack.pop
|
154
|
+
if !value.is_a?(I32) || !addr.is_a?(I32)
|
155
|
+
raise EvalError, "maybe stack too short"
|
156
|
+
end
|
157
|
+
|
158
|
+
at = addr.value + offset
|
159
|
+
data_end = at + 2
|
160
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
161
|
+
memory.data[at...data_end] = value.packed(size: 16)
|
162
|
+
|
163
|
+
|
164
|
+
when :i32_const
|
165
|
+
const = insn.operand[0]
|
166
|
+
if !const.is_a?(Integer)
|
167
|
+
raise EvalError, "invalid type of operand"
|
168
|
+
end
|
169
|
+
runtime.stack.push(I32(const))
|
170
|
+
|
171
|
+
|
172
|
+
when :i32_eqz
|
173
|
+
target = runtime.stack.pop
|
174
|
+
if !target.is_a?(I32)
|
175
|
+
raise EvalError, "maybe empty or invalid stack"
|
176
|
+
end
|
177
|
+
value = target.value.zero? ? 1 : 0
|
178
|
+
runtime.stack.push(I32(value))
|
179
|
+
|
180
|
+
|
181
|
+
when :i32_eq
|
182
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
183
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
184
|
+
raise EvalError, "maybe empty or invalid stack"
|
185
|
+
end
|
186
|
+
value = (left.value == right.value) ? 1 : 0
|
187
|
+
runtime.stack.push(I32(value))
|
188
|
+
|
189
|
+
|
190
|
+
when :i32_ne
|
191
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
192
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
193
|
+
raise EvalError, "maybe empty or invalid stack"
|
194
|
+
end
|
195
|
+
value = (left.value != right.value) ? 1 : 0
|
196
|
+
runtime.stack.push(I32(value))
|
197
|
+
|
198
|
+
|
199
|
+
when :i32_lts
|
200
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
201
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
202
|
+
raise EvalError, "maybe empty or invalid stack"
|
203
|
+
end
|
204
|
+
value = (left.value_s < right.value_s) ? 1 : 0
|
205
|
+
runtime.stack.push(I32(value))
|
206
|
+
|
207
|
+
|
208
|
+
when :i32_ltu
|
209
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
210
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
211
|
+
raise EvalError, "maybe empty or invalid stack"
|
212
|
+
end
|
213
|
+
value = (left.value < right.value) ? 1 : 0
|
214
|
+
runtime.stack.push(I32(value))
|
215
|
+
|
216
|
+
|
217
|
+
when :i32_gts
|
218
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
219
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
220
|
+
raise EvalError, "maybe empty or invalid stack"
|
221
|
+
end
|
222
|
+
value = (left.value_s > right.value_s) ? 1 : 0
|
223
|
+
runtime.stack.push(I32(value))
|
224
|
+
|
225
|
+
|
226
|
+
when :i32_gtu
|
227
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
228
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
229
|
+
raise EvalError, "maybe empty or invalid stack"
|
230
|
+
end
|
231
|
+
value = (left.value > right.value) ? 1 : 0
|
232
|
+
runtime.stack.push(I32(value))
|
233
|
+
|
234
|
+
|
235
|
+
when :i32_les
|
236
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
237
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
238
|
+
raise EvalError, "maybe empty or invalid stack"
|
239
|
+
end
|
240
|
+
value = (left.value_s <= right.value_s) ? 1 : 0
|
241
|
+
runtime.stack.push(I32(value))
|
242
|
+
|
243
|
+
|
244
|
+
when :i32_leu
|
245
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
246
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
247
|
+
raise EvalError, "maybe empty or invalid stack"
|
248
|
+
end
|
249
|
+
value = (left.value <= right.value) ? 1 : 0
|
250
|
+
runtime.stack.push(I32(value))
|
251
|
+
|
252
|
+
|
253
|
+
when :i32_ges
|
254
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
255
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
256
|
+
raise EvalError, "maybe empty or invalid stack"
|
257
|
+
end
|
258
|
+
value = (left.value_s >= right.value_s) ? 1 : 0
|
259
|
+
runtime.stack.push(I32(value))
|
260
|
+
|
261
|
+
|
262
|
+
when :i32_geu
|
263
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
264
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
265
|
+
raise EvalError, "maybe empty or invalid stack"
|
266
|
+
end
|
267
|
+
value = (left.value >= right.value) ? 1 : 0
|
268
|
+
runtime.stack.push(I32(value))
|
269
|
+
|
270
|
+
|
271
|
+
when :i32_clz
|
272
|
+
target = runtime.stack.pop
|
273
|
+
if !target.is_a?(I32)
|
274
|
+
raise EvalError, "maybe empty or invalid stack"
|
275
|
+
end
|
276
|
+
start = target.memsize - 1
|
277
|
+
count = 0
|
278
|
+
while start > -1
|
279
|
+
if (target.value >> start).zero?
|
280
|
+
count += 1
|
281
|
+
start -= 1
|
282
|
+
else
|
283
|
+
break
|
284
|
+
end
|
285
|
+
end
|
286
|
+
runtime.stack.push(I32(count))
|
287
|
+
|
288
|
+
|
289
|
+
when :i32_ctz
|
290
|
+
target = runtime.stack.pop
|
291
|
+
if !target.is_a?(I32)
|
292
|
+
raise EvalError, "maybe empty or invalid stack"
|
293
|
+
end
|
294
|
+
finish = target.memsize
|
295
|
+
count = 0
|
296
|
+
while count < finish
|
297
|
+
if (target.value & (1 << count)).zero?
|
298
|
+
count += 1
|
299
|
+
else
|
300
|
+
break
|
301
|
+
end
|
302
|
+
end
|
303
|
+
runtime.stack.push(I32(count))
|
304
|
+
|
305
|
+
|
306
|
+
when :i32_popcnt
|
307
|
+
target = runtime.stack.pop
|
308
|
+
if !target.is_a?(I32)
|
309
|
+
raise EvalError, "maybe empty or invalid stack"
|
310
|
+
end
|
311
|
+
digits = target.memsize
|
312
|
+
count = 0
|
313
|
+
digits.times do |i|
|
314
|
+
if (target.value & (1 << i)).zero?
|
315
|
+
count += 1
|
316
|
+
end
|
317
|
+
end
|
318
|
+
runtime.stack.push(I32(count))
|
319
|
+
|
320
|
+
|
321
|
+
when :i32_add
|
322
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
323
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
324
|
+
raise EvalError, "maybe empty or invalid stack"
|
325
|
+
end
|
326
|
+
runtime.stack.push(I32(left.value + right.value))
|
327
|
+
|
328
|
+
|
329
|
+
when :i32_sub
|
330
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
331
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
332
|
+
raise EvalError, "maybe empty or invalid stack"
|
333
|
+
end
|
334
|
+
runtime.stack.push(I32(left.value - right.value))
|
335
|
+
|
336
|
+
|
337
|
+
when :i32_mul
|
338
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
339
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
340
|
+
raise EvalError, "maybe empty or invalid stack"
|
341
|
+
end
|
342
|
+
runtime.stack.push(I32(left.value * right.value))
|
343
|
+
|
344
|
+
|
345
|
+
when :i32_div_s
|
346
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
347
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
348
|
+
raise EvalError, "maybe empty or invalid stack"
|
349
|
+
end
|
350
|
+
runtime.stack.push(I32(left.value_s / right.value_s))
|
351
|
+
|
352
|
+
|
353
|
+
when :i32_div_u
|
354
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
355
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
356
|
+
raise EvalError, "maybe empty or invalid stack"
|
357
|
+
end
|
358
|
+
runtime.stack.push(I32(left.value / right.value))
|
359
|
+
|
360
|
+
|
361
|
+
when :i32_rem_s
|
362
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
363
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
364
|
+
raise EvalError, "maybe empty or invalid stack"
|
365
|
+
end
|
366
|
+
runtime.stack.push(I32(left.value_s % right.value_s))
|
367
|
+
|
368
|
+
|
369
|
+
when :i32_rem_u
|
370
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
371
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
372
|
+
raise EvalError, "maybe empty or invalid stack"
|
373
|
+
end
|
374
|
+
runtime.stack.push(I32(left.value % right.value))
|
375
|
+
|
376
|
+
|
377
|
+
when :i32_and
|
378
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
379
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
380
|
+
raise EvalError, "maybe empty or invalid stack"
|
381
|
+
end
|
382
|
+
runtime.stack.push(I32(left.value & right.value))
|
383
|
+
|
384
|
+
|
385
|
+
when :i32_or
|
386
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
387
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
388
|
+
raise EvalError, "maybe empty or invalid stack"
|
389
|
+
end
|
390
|
+
runtime.stack.push(I32(left.value | right.value))
|
391
|
+
|
392
|
+
|
393
|
+
when :i32_xor
|
394
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
395
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
396
|
+
raise EvalError, "maybe empty or invalid stack"
|
397
|
+
end
|
398
|
+
runtime.stack.push(I32(left.value ^ right.value))
|
399
|
+
|
400
|
+
|
401
|
+
when :i32_shl
|
402
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
403
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
404
|
+
raise EvalError, "maybe empty or invalid stack"
|
405
|
+
end
|
406
|
+
value = left.value << right.value
|
407
|
+
value %= (1 << right.memsize)
|
408
|
+
|
409
|
+
runtime.stack.push(I32(value))
|
410
|
+
|
411
|
+
|
412
|
+
when :i32_shr_s
|
413
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
414
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
415
|
+
raise EvalError, "maybe empty or invalid stack"
|
416
|
+
end
|
417
|
+
value = left.value_s >> right.value
|
418
|
+
runtime.stack.push(I32(value))
|
419
|
+
|
420
|
+
|
421
|
+
when :i32_shr_u
|
422
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
423
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
424
|
+
raise EvalError, "maybe empty or invalid stack"
|
425
|
+
end
|
426
|
+
value = left.value >> right.value
|
427
|
+
runtime.stack.push(I32(value))
|
428
|
+
|
429
|
+
|
430
|
+
when :i32_rotl
|
431
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
432
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
433
|
+
raise EvalError, "maybe empty or invalid stack"
|
434
|
+
end
|
435
|
+
rotated = left.value << right.value
|
436
|
+
rest = left.value & (I32::I32_MAX << (right.memsize - right.value))
|
437
|
+
value = rotated | (rest >> (right.memsize - right.value))
|
438
|
+
runtime.stack.push(I32(value))
|
439
|
+
|
440
|
+
|
441
|
+
when :i32_rotr
|
442
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
443
|
+
if !right.is_a?(I32) || !left.is_a?(I32)
|
444
|
+
raise EvalError, "maybe empty or invalid stack"
|
445
|
+
end
|
446
|
+
rotated = left.value >> right.value
|
447
|
+
rest = left.value & (I32::I32_MAX >> (right.memsize - right.value))
|
448
|
+
value = rotated | (rest << (right.memsize - right.value))
|
449
|
+
runtime.stack.push(I32(value))
|
450
|
+
|
451
|
+
|
452
|
+
else
|
453
|
+
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|