wardite 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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