wardite 0.1.2 → 0.2.1

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