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.
@@ -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