wardite 0.2.0 → 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,514 @@
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.i64_eval_insn(runtime, frame, insn)
11
+ case insn.code
12
+
13
+ when :i64_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 + I64.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(I64.from_bytes(buf))
31
+
32
+
33
+ when :i64_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(I64.from_bytes(buf, size: 8, signed: true))
51
+
52
+
53
+ when :i64_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(I64.from_bytes(buf, size: 8, signed: false))
71
+
72
+
73
+ when :i64_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(I64.from_bytes(buf, size: 16, signed: true))
91
+
92
+
93
+ when :i64_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(I64.from_bytes(buf, size: 16, signed: false))
111
+
112
+
113
+ when :i64_load32_s
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
+ addr = runtime.stack.pop
119
+ if !addr.is_a?(I32)
120
+ raise EvalError, "maybe stack too short"
121
+ end
122
+
123
+ at = addr.value + offset
124
+ data_end = at + 4
125
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
126
+ buf = memory.data[at...data_end]
127
+ if !buf
128
+ raise EvalError, "invalid memory range"
129
+ end
130
+ runtime.stack.push(I64.from_bytes(buf, size: 32, signed: true))
131
+
132
+
133
+ when :i64_load32_u
134
+ _align = insn.operand[0] # TODO: alignment support?
135
+ offset = insn.operand[1]
136
+ raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
137
+
138
+ addr = runtime.stack.pop
139
+ if !addr.is_a?(I32)
140
+ raise EvalError, "maybe stack too short"
141
+ end
142
+
143
+ at = addr.value + offset
144
+ data_end = at + 4
145
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
146
+ buf = memory.data[at...data_end]
147
+ if !buf
148
+ raise EvalError, "invalid memory range"
149
+ end
150
+ runtime.stack.push(I64.from_bytes(buf, size: 32, signed: false))
151
+
152
+
153
+ when :i64_store
154
+ _align = insn.operand[0] # TODO: alignment support?
155
+ offset = insn.operand[1]
156
+ raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
157
+
158
+ value = runtime.stack.pop
159
+ addr = runtime.stack.pop
160
+ if !value.is_a?(I64) || !addr.is_a?(I32)
161
+ raise EvalError, "maybe stack too short"
162
+ end
163
+
164
+ at = addr.value + offset
165
+ data_end = at + value.packed.size
166
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
167
+ memory.data[at...data_end] = value.packed
168
+
169
+
170
+ when :i64_store8
171
+ _align = insn.operand[0] # TODO: alignment support?
172
+ offset = insn.operand[1]
173
+ raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
174
+
175
+ value = runtime.stack.pop
176
+ addr = runtime.stack.pop
177
+ if !value.is_a?(I64) || !addr.is_a?(I32)
178
+ raise EvalError, "maybe stack too short"
179
+ end
180
+
181
+ at = addr.value + offset
182
+ data_end = at + 1
183
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
184
+ memory.data[at...data_end] = value.packed(size: 8)
185
+
186
+
187
+ when :i64_store16
188
+ _align = insn.operand[0] # TODO: alignment support?
189
+ offset = insn.operand[1]
190
+ raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
191
+
192
+ value = runtime.stack.pop
193
+ addr = runtime.stack.pop
194
+ if !value.is_a?(I64) || !addr.is_a?(I32)
195
+ raise EvalError, "maybe stack too short"
196
+ end
197
+
198
+ at = addr.value + offset
199
+ data_end = at + 2
200
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
201
+ memory.data[at...data_end] = value.packed(size: 16)
202
+
203
+
204
+ when :i64_store32
205
+ _align = insn.operand[0] # TODO: alignment support?
206
+ offset = insn.operand[1]
207
+ raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
208
+
209
+ value = runtime.stack.pop
210
+ addr = runtime.stack.pop
211
+ if !value.is_a?(I64) || !addr.is_a?(I32)
212
+ raise EvalError, "maybe stack too short"
213
+ end
214
+
215
+ at = addr.value + offset
216
+ data_end = at + 4
217
+ memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
218
+ memory.data[at...data_end] = value.packed(size: 32)
219
+
220
+
221
+ when :i64_const
222
+ const = insn.operand[0]
223
+ if !const.is_a?(Integer)
224
+ raise EvalError, "invalid type of operand"
225
+ end
226
+ runtime.stack.push(I64(const))
227
+
228
+
229
+ when :i64_eqz
230
+ target = runtime.stack.pop
231
+ if !target.is_a?(I64)
232
+ raise EvalError, "maybe empty or invalid stack"
233
+ end
234
+ value = target.value.zero? ? 1 : 0
235
+ runtime.stack.push(I32(value))
236
+
237
+
238
+ when :i64_eq
239
+ right, left = runtime.stack.pop, runtime.stack.pop
240
+ if !right.is_a?(I64) || !left.is_a?(I64)
241
+ raise EvalError, "maybe empty or invalid stack"
242
+ end
243
+ value = (left.value == right.value) ? 1 : 0
244
+ runtime.stack.push(I32(value))
245
+
246
+
247
+ when :i64_ne
248
+ right, left = runtime.stack.pop, runtime.stack.pop
249
+ if !right.is_a?(I64) || !left.is_a?(I64)
250
+ raise EvalError, "maybe empty or invalid stack"
251
+ end
252
+ value = (left.value != right.value) ? 1 : 0
253
+ runtime.stack.push(I32(value))
254
+
255
+
256
+ when :i64_lts
257
+ right, left = runtime.stack.pop, runtime.stack.pop
258
+ if !right.is_a?(I64) || !left.is_a?(I64)
259
+ raise EvalError, "maybe empty or invalid stack"
260
+ end
261
+ value = (left.value_s < right.value_s) ? 1 : 0
262
+ runtime.stack.push(I32(value))
263
+
264
+
265
+ when :i64_ltu
266
+ right, left = runtime.stack.pop, runtime.stack.pop
267
+ if !right.is_a?(I64) || !left.is_a?(I64)
268
+ raise EvalError, "maybe empty or invalid stack"
269
+ end
270
+ value = (left.value < right.value) ? 1 : 0
271
+ runtime.stack.push(I32(value))
272
+
273
+
274
+ when :i64_gts
275
+ right, left = runtime.stack.pop, runtime.stack.pop
276
+ if !right.is_a?(I64) || !left.is_a?(I64)
277
+ raise EvalError, "maybe empty or invalid stack"
278
+ end
279
+ value = (left.value_s > right.value_s) ? 1 : 0
280
+ runtime.stack.push(I32(value))
281
+
282
+
283
+ when :i64_gtu
284
+ right, left = runtime.stack.pop, runtime.stack.pop
285
+ if !right.is_a?(I64) || !left.is_a?(I64)
286
+ raise EvalError, "maybe empty or invalid stack"
287
+ end
288
+ value = (left.value > right.value) ? 1 : 0
289
+ runtime.stack.push(I32(value))
290
+
291
+
292
+ when :i64_les
293
+ right, left = runtime.stack.pop, runtime.stack.pop
294
+ if !right.is_a?(I64) || !left.is_a?(I64)
295
+ raise EvalError, "maybe empty or invalid stack"
296
+ end
297
+ value = (left.value_s <= right.value_s) ? 1 : 0
298
+ runtime.stack.push(I32(value))
299
+
300
+
301
+ when :i64_leu
302
+ right, left = runtime.stack.pop, runtime.stack.pop
303
+ if !right.is_a?(I64) || !left.is_a?(I64)
304
+ raise EvalError, "maybe empty or invalid stack"
305
+ end
306
+ value = (left.value <= right.value) ? 1 : 0
307
+ runtime.stack.push(I32(value))
308
+
309
+
310
+ when :i64_ges
311
+ right, left = runtime.stack.pop, runtime.stack.pop
312
+ if !right.is_a?(I64) || !left.is_a?(I64)
313
+ raise EvalError, "maybe empty or invalid stack"
314
+ end
315
+ value = (left.value_s >= right.value_s) ? 1 : 0
316
+ runtime.stack.push(I32(value))
317
+
318
+
319
+ when :i64_geu
320
+ right, left = runtime.stack.pop, runtime.stack.pop
321
+ if !right.is_a?(I64) || !left.is_a?(I64)
322
+ raise EvalError, "maybe empty or invalid stack"
323
+ end
324
+ value = (left.value >= right.value) ? 1 : 0
325
+ runtime.stack.push(I32(value))
326
+
327
+
328
+ when :i64_clz
329
+ target = runtime.stack.pop
330
+ if !target.is_a?(I64)
331
+ raise EvalError, "maybe empty or invalid stack"
332
+ end
333
+ start = target.memsize - 1
334
+ count = 0
335
+ while start > -1
336
+ if (target.value >> start).zero?
337
+ count += 1
338
+ start -= 1
339
+ else
340
+ break
341
+ end
342
+ end
343
+ runtime.stack.push(I64(count))
344
+
345
+
346
+ when :i64_ctz
347
+ target = runtime.stack.pop
348
+ if !target.is_a?(I64)
349
+ raise EvalError, "maybe empty or invalid stack"
350
+ end
351
+ finish = target.memsize
352
+ count = 0
353
+ while count < finish
354
+ if (target.value & (1 << count)).zero?
355
+ count += 1
356
+ else
357
+ break
358
+ end
359
+ end
360
+ runtime.stack.push(I64(count))
361
+
362
+
363
+ when :i64_popcnt
364
+ target = runtime.stack.pop
365
+ if !target.is_a?(I64)
366
+ raise EvalError, "maybe empty or invalid stack"
367
+ end
368
+ digits = target.memsize
369
+ count = 0
370
+ digits.times do |i|
371
+ if (target.value & (1 << i)).zero?
372
+ count += 1
373
+ end
374
+ end
375
+ runtime.stack.push(I64(count))
376
+
377
+
378
+ when :i64_add
379
+ right, left = runtime.stack.pop, runtime.stack.pop
380
+ if !right.is_a?(I64) || !left.is_a?(I64)
381
+ raise EvalError, "maybe empty or invalid stack"
382
+ end
383
+ runtime.stack.push(I64(left.value + right.value))
384
+
385
+
386
+ when :i64_sub
387
+ right, left = runtime.stack.pop, runtime.stack.pop
388
+ if !right.is_a?(I64) || !left.is_a?(I64)
389
+ raise EvalError, "maybe empty or invalid stack"
390
+ end
391
+ runtime.stack.push(I64(left.value - right.value))
392
+
393
+
394
+ when :i64_mul
395
+ right, left = runtime.stack.pop, runtime.stack.pop
396
+ if !right.is_a?(I64) || !left.is_a?(I64)
397
+ raise EvalError, "maybe empty or invalid stack"
398
+ end
399
+ runtime.stack.push(I64(left.value * right.value))
400
+
401
+
402
+ when :i64_div_s
403
+ right, left = runtime.stack.pop, runtime.stack.pop
404
+ if !right.is_a?(I64) || !left.is_a?(I64)
405
+ raise EvalError, "maybe empty or invalid stack"
406
+ end
407
+ runtime.stack.push(I64(left.value_s / right.value_s))
408
+
409
+
410
+ when :i64_div_u
411
+ right, left = runtime.stack.pop, runtime.stack.pop
412
+ if !right.is_a?(I64) || !left.is_a?(I64)
413
+ raise EvalError, "maybe empty or invalid stack"
414
+ end
415
+ runtime.stack.push(I64(left.value / right.value))
416
+
417
+
418
+ when :i64_rem_s
419
+ right, left = runtime.stack.pop, runtime.stack.pop
420
+ if !right.is_a?(I64) || !left.is_a?(I64)
421
+ raise EvalError, "maybe empty or invalid stack"
422
+ end
423
+ runtime.stack.push(I64(left.value_s % right.value_s))
424
+
425
+
426
+ when :i64_rem_u
427
+ right, left = runtime.stack.pop, runtime.stack.pop
428
+ if !right.is_a?(I64) || !left.is_a?(I64)
429
+ raise EvalError, "maybe empty or invalid stack"
430
+ end
431
+ runtime.stack.push(I64(left.value % right.value))
432
+
433
+
434
+ when :i64_and
435
+ right, left = runtime.stack.pop, runtime.stack.pop
436
+ if !right.is_a?(I64) || !left.is_a?(I64)
437
+ raise EvalError, "maybe empty or invalid stack"
438
+ end
439
+ runtime.stack.push(I64(left.value & right.value))
440
+
441
+
442
+ when :i64_or
443
+ right, left = runtime.stack.pop, runtime.stack.pop
444
+ if !right.is_a?(I64) || !left.is_a?(I64)
445
+ raise EvalError, "maybe empty or invalid stack"
446
+ end
447
+ runtime.stack.push(I64(left.value | right.value))
448
+
449
+
450
+ when :i64_xor
451
+ right, left = runtime.stack.pop, runtime.stack.pop
452
+ if !right.is_a?(I64) || !left.is_a?(I64)
453
+ raise EvalError, "maybe empty or invalid stack"
454
+ end
455
+ runtime.stack.push(I64(left.value ^ right.value))
456
+
457
+
458
+ when :i64_shl
459
+ right, left = runtime.stack.pop, runtime.stack.pop
460
+ if !right.is_a?(I64) || !left.is_a?(I64)
461
+ raise EvalError, "maybe empty or invalid stack"
462
+ end
463
+ value = left.value << right.value
464
+ value %= (1 << right.memsize)
465
+
466
+ runtime.stack.push(I64(value))
467
+
468
+
469
+ when :i64_shr_s
470
+ right, left = runtime.stack.pop, runtime.stack.pop
471
+ if !right.is_a?(I64) || !left.is_a?(I64)
472
+ raise EvalError, "maybe empty or invalid stack"
473
+ end
474
+ value = left.value_s >> right.value
475
+ runtime.stack.push(I64(value))
476
+
477
+
478
+ when :i64_shr_u
479
+ right, left = runtime.stack.pop, runtime.stack.pop
480
+ if !right.is_a?(I64) || !left.is_a?(I64)
481
+ raise EvalError, "maybe empty or invalid stack"
482
+ end
483
+ value = left.value >> right.value
484
+ runtime.stack.push(I64(value))
485
+
486
+
487
+ when :i64_rotl
488
+ right, left = runtime.stack.pop, runtime.stack.pop
489
+ if !right.is_a?(I64) || !left.is_a?(I64)
490
+ raise EvalError, "maybe empty or invalid stack"
491
+ end
492
+ rotated = left.value << right.value
493
+ rest = left.value & (I64::I64_MAX << (right.memsize - right.value))
494
+ value = rotated | (rest >> (right.memsize - right.value))
495
+ runtime.stack.push(I64(value))
496
+
497
+
498
+ when :i64_rotr
499
+ right, left = runtime.stack.pop, runtime.stack.pop
500
+ if !right.is_a?(I64) || !left.is_a?(I64)
501
+ raise EvalError, "maybe empty or invalid stack"
502
+ end
503
+ rotated = left.value >> right.value
504
+ rest = left.value & (I64::I64_MAX >> (right.memsize - right.value))
505
+ value = rotated | (rest << (right.memsize - right.value))
506
+ runtime.stack.push(I64(value))
507
+
508
+
509
+ else
510
+ raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
511
+ end
512
+ end
513
+ end
514
+ end