wardite 0.4.3 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/grayscale.rb +64 -0
- data/lib/wardite/alu_i32.generated.rb +27 -13
- data/lib/wardite/alu_i64.generated.rb +27 -13
- data/lib/wardite/errors.rb +9 -0
- data/lib/wardite/instruction.rb +3 -0
- data/lib/wardite/load.rb +6 -1
- data/lib/wardite/revisitor.rb +92 -0
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite.rb +8 -65
- data/scripts/gen_alu.rb +27 -13
- data/sig/generated/wardite/errors.rbs +12 -0
- data/sig/generated/wardite/instruction.rbs +2 -0
- data/sig/generated/wardite/load.rbs +0 -1
- data/sig/generated/wardite/revisitor.rbs +25 -0
- data/sig/generated/wardite.rbs +0 -10
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89b6c42e1a3f16c39c214eb127c5b87966c0d2933257a1da7fdc96236c6a0f9b
|
4
|
+
data.tar.gz: 321d62cdddc61c8a342b966b3e4d7b6c01ffbbcb5788a6787fd3490ba96b1430
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b8b67989d47775828aca0908794f6b02abdea5ed653d794fa308d437f2d1735997a91dee341cdfa51aa5829aa097ca61dd262dba8479e805d1bbfd540f90ff5
|
7
|
+
data.tar.gz: 26face977ed4d76232bdee62f64208a22ec824314cb3d479979705fee327a1c9ce72ee960055a0c26db591f932c598b591651170fedf31b36533c52774f05fbe
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Usage:
|
3
|
+
# $ bundle exec ruby --yjit examples/grayscale.rb \
|
4
|
+
# --wasm-file path/to/grayscale.wasm \
|
5
|
+
# --source tmp/source.png \
|
6
|
+
# --dest tmp/result.png \
|
7
|
+
# --width 660 --height 495
|
8
|
+
#
|
9
|
+
require "wardite"
|
10
|
+
require "base64"
|
11
|
+
require "optparse"
|
12
|
+
require "ostruct"
|
13
|
+
|
14
|
+
$options = OpenStruct.new
|
15
|
+
|
16
|
+
opt = OptionParser.new
|
17
|
+
opt.on('--wasm-file [FILE]') {|v| $options.wasm_file = v }
|
18
|
+
opt.on('--source [IMAGE]') {|v| $options.source = v }
|
19
|
+
opt.on('--dest [IMAGE]') {|v| $options.dest = v }
|
20
|
+
opt.on('--width [W]') {|v| $options.width = v.to_i }
|
21
|
+
opt.on('--height [H]') {|v| $options.height = v.to_i }
|
22
|
+
opt.parse!
|
23
|
+
|
24
|
+
#require 'ruby-prof'
|
25
|
+
#profile = RubyProf::Profile.new
|
26
|
+
|
27
|
+
f = File.open($options.wasm_file)
|
28
|
+
data = IO.read($options.source)
|
29
|
+
orig = Base64.encode64(data).gsub(/(\r|\n)/, "")
|
30
|
+
data_url = "data:image/png;base64," + orig
|
31
|
+
instance = Wardite::BinaryLoader::load_from_buffer(f);
|
32
|
+
instance.store.memories[0].grow(data_url.size / (64*1024) + 1)
|
33
|
+
|
34
|
+
start = instance.exports.__heap_base.value.value
|
35
|
+
instance.store.memories[0].data[start...(start+data_url.size)] = data_url
|
36
|
+
|
37
|
+
offset = 0
|
38
|
+
result = nil
|
39
|
+
begin
|
40
|
+
# pub fn grayscale(width: i32, height: i32, memory_offset: i32, length: i32) -> *const u8
|
41
|
+
#profile.start
|
42
|
+
offset = instance.runtime.grayscale_blob($options.width, $options.height, start, data_url.size)
|
43
|
+
#result = profile.stop
|
44
|
+
rescue => e
|
45
|
+
raise "failed to execute grayscale() " + e.message
|
46
|
+
end
|
47
|
+
|
48
|
+
#printer = RubyProf::GraphPrinter.new(result)
|
49
|
+
#printer.print(STDOUT, {})
|
50
|
+
|
51
|
+
len = 0
|
52
|
+
until instance.store.memories[0].data[offset.value+len] == "\0"
|
53
|
+
len += 1
|
54
|
+
end
|
55
|
+
|
56
|
+
result_b64 = instance.store.memories[0].data[offset.value...(offset.value+len)]
|
57
|
+
result = Base64.decode64(result_b64)
|
58
|
+
|
59
|
+
dest = File.open($options.dest, "w")
|
60
|
+
dest.write result
|
61
|
+
dest.close
|
62
|
+
|
63
|
+
puts "created: #{$options.dest}"
|
64
|
+
|
@@ -311,7 +311,7 @@ module Wardite
|
|
311
311
|
digits = target.memsize
|
312
312
|
count = 0
|
313
313
|
digits.times do |i|
|
314
|
-
if (target.value & (1 << i)).
|
314
|
+
if (target.value & (1 << i)).nonzero?
|
315
315
|
count += 1
|
316
316
|
end
|
317
317
|
end
|
@@ -347,7 +347,13 @@ module Wardite
|
|
347
347
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
348
348
|
raise EvalError, "maybe empty or invalid stack"
|
349
349
|
end
|
350
|
-
|
350
|
+
result = left.value_s / right.value_s.to_f
|
351
|
+
iresult = (result >= 0 ? result.floor : result.ceil).to_i
|
352
|
+
if iresult >= (1 << (left.memsize - 1))
|
353
|
+
raise IntegerOverflow, "integer overflow"
|
354
|
+
end
|
355
|
+
|
356
|
+
runtime.stack.push(I32(iresult))
|
351
357
|
|
352
358
|
|
353
359
|
when :i32_div_u
|
@@ -363,7 +369,13 @@ module Wardite
|
|
363
369
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
364
370
|
raise EvalError, "maybe empty or invalid stack"
|
365
371
|
end
|
366
|
-
|
372
|
+
result = left.value_s % right.value_s
|
373
|
+
if result > 0 && left.value_s < 0
|
374
|
+
result = result - right.value_s
|
375
|
+
elsif result < 0 && left.value_s > 0
|
376
|
+
result = result - right.value_s
|
377
|
+
end
|
378
|
+
runtime.stack.push(I32(result))
|
367
379
|
|
368
380
|
|
369
381
|
when :i32_rem_u
|
@@ -403,8 +415,8 @@ module Wardite
|
|
403
415
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
404
416
|
raise EvalError, "maybe empty or invalid stack"
|
405
417
|
end
|
406
|
-
value = left.value << right.value
|
407
|
-
value %=
|
418
|
+
value = left.value << (right.value % right.memsize)
|
419
|
+
value %= 1 << right.memsize
|
408
420
|
|
409
421
|
runtime.stack.push(I32(value))
|
410
422
|
|
@@ -414,7 +426,7 @@ module Wardite
|
|
414
426
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
415
427
|
raise EvalError, "maybe empty or invalid stack"
|
416
428
|
end
|
417
|
-
value = left.value_s >> right.value
|
429
|
+
value = left.value_s >> (right.value % right.memsize)
|
418
430
|
runtime.stack.push(I32(value))
|
419
431
|
|
420
432
|
|
@@ -423,7 +435,7 @@ module Wardite
|
|
423
435
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
424
436
|
raise EvalError, "maybe empty or invalid stack"
|
425
437
|
end
|
426
|
-
value = left.value >> right.value
|
438
|
+
value = left.value >> (right.value % right.memsize)
|
427
439
|
runtime.stack.push(I32(value))
|
428
440
|
|
429
441
|
|
@@ -432,9 +444,10 @@ module Wardite
|
|
432
444
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
433
445
|
raise EvalError, "maybe empty or invalid stack"
|
434
446
|
end
|
435
|
-
|
436
|
-
|
437
|
-
|
447
|
+
k = (right.value % right.memsize)
|
448
|
+
rotated = left.value << k
|
449
|
+
rest = left.value & (I32::I32_MAX << (right.memsize - k))
|
450
|
+
value = rotated | (rest >> (right.memsize - k))
|
438
451
|
runtime.stack.push(I32(value))
|
439
452
|
|
440
453
|
|
@@ -443,9 +456,10 @@ module Wardite
|
|
443
456
|
if !right.is_a?(I32) || !left.is_a?(I32)
|
444
457
|
raise EvalError, "maybe empty or invalid stack"
|
445
458
|
end
|
446
|
-
|
447
|
-
|
448
|
-
|
459
|
+
k = (right.value % right.memsize)
|
460
|
+
rotated = left.value >> k
|
461
|
+
rest = left.value & (I32::I32_MAX >> (right.memsize - k))
|
462
|
+
value = rotated | (rest << (right.memsize - k))
|
449
463
|
runtime.stack.push(I32(value))
|
450
464
|
|
451
465
|
|
@@ -368,7 +368,7 @@ module Wardite
|
|
368
368
|
digits = target.memsize
|
369
369
|
count = 0
|
370
370
|
digits.times do |i|
|
371
|
-
if (target.value & (1 << i)).
|
371
|
+
if (target.value & (1 << i)).nonzero?
|
372
372
|
count += 1
|
373
373
|
end
|
374
374
|
end
|
@@ -404,7 +404,13 @@ module Wardite
|
|
404
404
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
405
405
|
raise EvalError, "maybe empty or invalid stack"
|
406
406
|
end
|
407
|
-
|
407
|
+
result = left.value_s / right.value_s.to_f
|
408
|
+
iresult = (result >= 0 ? result.floor : result.ceil).to_i
|
409
|
+
if iresult >= (1 << (left.memsize - 1))
|
410
|
+
raise IntegerOverflow, "integer overflow"
|
411
|
+
end
|
412
|
+
|
413
|
+
runtime.stack.push(I64(iresult))
|
408
414
|
|
409
415
|
|
410
416
|
when :i64_div_u
|
@@ -420,7 +426,13 @@ module Wardite
|
|
420
426
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
421
427
|
raise EvalError, "maybe empty or invalid stack"
|
422
428
|
end
|
423
|
-
|
429
|
+
result = left.value_s % right.value_s
|
430
|
+
if result > 0 && left.value_s < 0
|
431
|
+
result = result - right.value_s
|
432
|
+
elsif result < 0 && left.value_s > 0
|
433
|
+
result = result - right.value_s
|
434
|
+
end
|
435
|
+
runtime.stack.push(I64(result))
|
424
436
|
|
425
437
|
|
426
438
|
when :i64_rem_u
|
@@ -460,8 +472,8 @@ module Wardite
|
|
460
472
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
461
473
|
raise EvalError, "maybe empty or invalid stack"
|
462
474
|
end
|
463
|
-
value = left.value << right.value
|
464
|
-
value %=
|
475
|
+
value = left.value << (right.value % right.memsize)
|
476
|
+
value %= 1 << right.memsize
|
465
477
|
|
466
478
|
runtime.stack.push(I64(value))
|
467
479
|
|
@@ -471,7 +483,7 @@ module Wardite
|
|
471
483
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
472
484
|
raise EvalError, "maybe empty or invalid stack"
|
473
485
|
end
|
474
|
-
value = left.value_s >> right.value
|
486
|
+
value = left.value_s >> (right.value % right.memsize)
|
475
487
|
runtime.stack.push(I64(value))
|
476
488
|
|
477
489
|
|
@@ -480,7 +492,7 @@ module Wardite
|
|
480
492
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
481
493
|
raise EvalError, "maybe empty or invalid stack"
|
482
494
|
end
|
483
|
-
value = left.value >> right.value
|
495
|
+
value = left.value >> (right.value % right.memsize)
|
484
496
|
runtime.stack.push(I64(value))
|
485
497
|
|
486
498
|
|
@@ -489,9 +501,10 @@ module Wardite
|
|
489
501
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
490
502
|
raise EvalError, "maybe empty or invalid stack"
|
491
503
|
end
|
492
|
-
|
493
|
-
|
494
|
-
|
504
|
+
k = (right.value % right.memsize)
|
505
|
+
rotated = left.value << k
|
506
|
+
rest = left.value & (I64::I64_MAX << (right.memsize - k))
|
507
|
+
value = rotated | (rest >> (right.memsize - k))
|
495
508
|
runtime.stack.push(I64(value))
|
496
509
|
|
497
510
|
|
@@ -500,9 +513,10 @@ module Wardite
|
|
500
513
|
if !right.is_a?(I64) || !left.is_a?(I64)
|
501
514
|
raise EvalError, "maybe empty or invalid stack"
|
502
515
|
end
|
503
|
-
|
504
|
-
|
505
|
-
|
516
|
+
k = (right.value % right.memsize)
|
517
|
+
rotated = left.value >> k
|
518
|
+
rest = left.value & (I64::I64_MAX >> (right.memsize - k))
|
519
|
+
value = rotated | (rest << (right.memsize - k))
|
506
520
|
runtime.stack.push(I64(value))
|
507
521
|
|
508
522
|
|
data/lib/wardite/instruction.rb
CHANGED
@@ -78,6 +78,8 @@ module Wardite
|
|
78
78
|
# TODO: add types of potential operands
|
79
79
|
attr_accessor :operand #: Array[operandItem]
|
80
80
|
|
81
|
+
attr_accessor :meta #: Hash[Symbol, Integer]
|
82
|
+
|
81
83
|
# @rbs namespace: Symbol
|
82
84
|
# @rbs code: Symbol
|
83
85
|
# @rbs operand: Array[operandItem]
|
@@ -85,6 +87,7 @@ module Wardite
|
|
85
87
|
@namespace = namespace
|
86
88
|
@code = code
|
87
89
|
@operand = operand
|
90
|
+
@meta = {}
|
88
91
|
end
|
89
92
|
|
90
93
|
# @rbs chr: String
|
data/lib/wardite/load.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# rbs_inline: enabled
|
2
|
+
require "wardite/revisitor"
|
3
|
+
|
2
4
|
module Wardite
|
3
5
|
class Section
|
4
6
|
attr_accessor :name #: String
|
@@ -593,10 +595,13 @@ module Wardite
|
|
593
595
|
locals_type << Op.i2type(value_type || -1)
|
594
596
|
end
|
595
597
|
body = code_body(cbuf)
|
598
|
+
revisitor = Revisitor.new(body)
|
599
|
+
revisitor.revisit!
|
600
|
+
|
596
601
|
dest.func_codes << CodeSection::CodeBody.new do |b|
|
597
602
|
b.locals_count = locals_count
|
598
603
|
b.locals_type = locals_type
|
599
|
-
b.body =
|
604
|
+
b.body = revisitor.ops
|
600
605
|
end
|
601
606
|
end
|
602
607
|
dest
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
module Wardite
|
3
|
+
class Revisitor
|
4
|
+
attr_accessor :ops #: Array[Op]
|
5
|
+
|
6
|
+
# @rbs ops: Array[Op]
|
7
|
+
# @rbs return: void
|
8
|
+
def initialize(ops)
|
9
|
+
@ops = ops
|
10
|
+
end
|
11
|
+
|
12
|
+
# @rbs return: void
|
13
|
+
def revisit!
|
14
|
+
@ops.each_with_index do |op, idx|
|
15
|
+
case op.code
|
16
|
+
when :block
|
17
|
+
next_pc = fetch_ops_while_end(idx)
|
18
|
+
op.meta[:end_pos] = next_pc
|
19
|
+
|
20
|
+
when :loop
|
21
|
+
next_pc = fetch_ops_while_end(idx)
|
22
|
+
op.meta[:end_pos] = next_pc
|
23
|
+
|
24
|
+
when :if
|
25
|
+
next_pc = fetch_ops_while_end(idx)
|
26
|
+
else_pc = fetch_ops_while_else_or_end(idx)
|
27
|
+
op.meta[:end_pos] = next_pc
|
28
|
+
op.meta[:else_pos] = else_pc
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @rbs pc_start: Integer
|
34
|
+
# @rbs return: Integer
|
35
|
+
# @rbs return: void
|
36
|
+
def fetch_ops_while_else_or_end(pc_start)
|
37
|
+
cursor = pc_start
|
38
|
+
depth = 0
|
39
|
+
loop {
|
40
|
+
cursor += 1
|
41
|
+
inst = @ops[cursor]
|
42
|
+
case inst&.code
|
43
|
+
when nil
|
44
|
+
raise EvalError, "end op not found"
|
45
|
+
when :if
|
46
|
+
depth += 1
|
47
|
+
when :else
|
48
|
+
if depth == 0
|
49
|
+
return cursor
|
50
|
+
end
|
51
|
+
# do not touch depth
|
52
|
+
when :end
|
53
|
+
if depth == 0
|
54
|
+
return cursor
|
55
|
+
else
|
56
|
+
depth -= 1
|
57
|
+
end
|
58
|
+
else
|
59
|
+
# nop
|
60
|
+
end
|
61
|
+
}
|
62
|
+
raise "not found corresponding end"
|
63
|
+
end
|
64
|
+
|
65
|
+
# @rbs pc_start: Integer
|
66
|
+
# @rbs return: Integer
|
67
|
+
# @rbs return: void
|
68
|
+
def fetch_ops_while_end(pc_start)
|
69
|
+
cursor = pc_start
|
70
|
+
depth = 0
|
71
|
+
loop {
|
72
|
+
cursor += 1
|
73
|
+
inst = @ops[cursor]
|
74
|
+
case inst&.code
|
75
|
+
when nil
|
76
|
+
raise EvalError, "end op not found"
|
77
|
+
when :if, :block, :loop
|
78
|
+
depth += 1
|
79
|
+
when :end
|
80
|
+
if depth == 0
|
81
|
+
return cursor
|
82
|
+
else
|
83
|
+
depth -= 1
|
84
|
+
end
|
85
|
+
else
|
86
|
+
# nop
|
87
|
+
end
|
88
|
+
}
|
89
|
+
raise "not found corresponding end"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/wardite/version.rb
CHANGED
data/lib/wardite.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative "wardite/const"
|
|
7
7
|
require_relative "wardite/instruction"
|
8
8
|
require_relative "wardite/value"
|
9
9
|
require_relative "wardite/load"
|
10
|
+
require_relative "wardite/errors"
|
10
11
|
|
11
12
|
module Wardite
|
12
13
|
module Evaluator
|
@@ -472,7 +473,7 @@ module Wardite
|
|
472
473
|
when :block
|
473
474
|
block = insn.operand[0]
|
474
475
|
raise EvalError, "block op without block" if !block.is_a?(Block)
|
475
|
-
next_pc =
|
476
|
+
next_pc = insn.meta[:end_pos]
|
476
477
|
label = Label.new(:block, next_pc, stack.size, block.result_size)
|
477
478
|
frame.labels.push(label)
|
478
479
|
|
@@ -480,19 +481,19 @@ module Wardite
|
|
480
481
|
block = insn.operand[0]
|
481
482
|
raise EvalError, "loop op without block" if !block.is_a?(Block)
|
482
483
|
start = frame.pc
|
483
|
-
|
484
|
-
label = Label.new(:loop,
|
484
|
+
next_pc = insn.meta[:end_pos]
|
485
|
+
label = Label.new(:loop, next_pc, stack.size, block.result_size, start)
|
485
486
|
frame.labels.push(label)
|
486
487
|
|
487
488
|
when :if
|
488
489
|
block = insn.operand[0]
|
489
490
|
raise EvalError, "if op without block" if !block.is_a?(Block)
|
490
|
-
cond = stack.pop
|
491
|
+
cond = stack.pop
|
491
492
|
raise EvalError, "cond not found" if !cond.is_a?(I32)
|
492
|
-
next_pc =
|
493
|
+
next_pc = insn.meta[:end_pos]
|
493
494
|
|
494
495
|
if cond.value.zero?
|
495
|
-
frame.pc =
|
496
|
+
frame.pc = insn.meta[:else_pos]
|
496
497
|
end
|
497
498
|
|
498
499
|
if frame.pc == next_pc
|
@@ -739,38 +740,6 @@ module Wardite
|
|
739
740
|
raise e
|
740
741
|
end
|
741
742
|
|
742
|
-
# @rbs ops: Array[Op]
|
743
|
-
# @rbs pc_start: Integer
|
744
|
-
# @rbs return: Integer
|
745
|
-
def fetch_ops_while_else_or_end(ops, pc_start)
|
746
|
-
cursor = pc_start
|
747
|
-
depth = 0
|
748
|
-
loop {
|
749
|
-
cursor += 1
|
750
|
-
inst = ops[cursor]
|
751
|
-
case inst&.code
|
752
|
-
when nil
|
753
|
-
raise EvalError, "end op not found"
|
754
|
-
when :if
|
755
|
-
depth += 1
|
756
|
-
when :else
|
757
|
-
if depth == 0
|
758
|
-
return cursor
|
759
|
-
end
|
760
|
-
# do not touch depth
|
761
|
-
when :end
|
762
|
-
if depth == 0
|
763
|
-
return cursor
|
764
|
-
else
|
765
|
-
depth -= 1
|
766
|
-
end
|
767
|
-
else
|
768
|
-
# nop
|
769
|
-
end
|
770
|
-
}
|
771
|
-
raise "[BUG] unreachable"
|
772
|
-
end
|
773
|
-
|
774
743
|
# @rbs labels: Array[Label]
|
775
744
|
# @rbs stack: Array[wasmValue]
|
776
745
|
# @rbs level: Integer
|
@@ -796,33 +765,6 @@ module Wardite
|
|
796
765
|
pc
|
797
766
|
end
|
798
767
|
|
799
|
-
# @rbs ops: Array[Op]
|
800
|
-
# @rbs pc_start: Integer
|
801
|
-
# @rbs return: Integer
|
802
|
-
def fetch_ops_while_end(ops, pc_start)
|
803
|
-
cursor = pc_start
|
804
|
-
depth = 0
|
805
|
-
loop {
|
806
|
-
cursor += 1
|
807
|
-
inst = ops[cursor]
|
808
|
-
case inst&.code
|
809
|
-
when nil
|
810
|
-
raise EvalError, "end op not found"
|
811
|
-
when :if, :block, :loop
|
812
|
-
depth += 1
|
813
|
-
when :end
|
814
|
-
if depth == 0
|
815
|
-
return cursor
|
816
|
-
else
|
817
|
-
depth -= 1
|
818
|
-
end
|
819
|
-
else
|
820
|
-
# nop
|
821
|
-
end
|
822
|
-
}
|
823
|
-
raise "[BUG] unreachable"
|
824
|
-
end
|
825
|
-
|
826
768
|
# unwind the stack and put return value if exists
|
827
769
|
# @rbs sp: Integer
|
828
770
|
# @rbs arity: Integer
|
@@ -1119,6 +1061,7 @@ module Wardite
|
|
1119
1061
|
end
|
1120
1062
|
|
1121
1063
|
@data += String.new("\0" * (delta * 64 * 1024))
|
1064
|
+
self.current = newsize
|
1122
1065
|
prev
|
1123
1066
|
end
|
1124
1067
|
|
data/scripts/gen_alu.rb
CHANGED
@@ -480,7 +480,7 @@ module GenAlu
|
|
480
480
|
digits = target.memsize
|
481
481
|
count = 0
|
482
482
|
digits.times do |i|
|
483
|
-
if (target.value & (1 << i)).
|
483
|
+
if (target.value & (1 << i)).nonzero?
|
484
484
|
count += 1
|
485
485
|
end
|
486
486
|
end
|
@@ -520,7 +520,13 @@ module GenAlu
|
|
520
520
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
521
521
|
raise EvalError, "maybe empty or invalid stack"
|
522
522
|
end
|
523
|
-
|
523
|
+
result = left.value_s / right.value_s.to_f
|
524
|
+
iresult = (result >= 0 ? result.floor : result.ceil).to_i
|
525
|
+
if iresult >= (1 << (left.memsize - 1))
|
526
|
+
raise IntegerOverflow, "integer overflow"
|
527
|
+
end
|
528
|
+
|
529
|
+
runtime.stack.push(${CLASS}(iresult))
|
524
530
|
RUBY
|
525
531
|
|
526
532
|
div_u: <<~RUBY,
|
@@ -547,7 +553,13 @@ module GenAlu
|
|
547
553
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
548
554
|
raise EvalError, "maybe empty or invalid stack"
|
549
555
|
end
|
550
|
-
|
556
|
+
result = left.value_s % right.value_s
|
557
|
+
if result > 0 && left.value_s < 0
|
558
|
+
result = result - right.value_s
|
559
|
+
elsif result < 0 && left.value_s > 0
|
560
|
+
result = result - right.value_s
|
561
|
+
end
|
562
|
+
runtime.stack.push(${CLASS}(result))
|
551
563
|
RUBY
|
552
564
|
|
553
565
|
rem_u: <<~RUBY,
|
@@ -592,8 +604,8 @@ module GenAlu
|
|
592
604
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
593
605
|
raise EvalError, "maybe empty or invalid stack"
|
594
606
|
end
|
595
|
-
value = left.value << right.value
|
596
|
-
value %=
|
607
|
+
value = left.value << (right.value % right.memsize)
|
608
|
+
value %= 1 << right.memsize
|
597
609
|
|
598
610
|
runtime.stack.push(${CLASS}(value))
|
599
611
|
RUBY
|
@@ -604,7 +616,7 @@ module GenAlu
|
|
604
616
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
605
617
|
raise EvalError, "maybe empty or invalid stack"
|
606
618
|
end
|
607
|
-
value = left.value_s >> right.value
|
619
|
+
value = left.value_s >> (right.value % right.memsize)
|
608
620
|
runtime.stack.push(${CLASS}(value))
|
609
621
|
RUBY
|
610
622
|
|
@@ -614,7 +626,7 @@ module GenAlu
|
|
614
626
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
615
627
|
raise EvalError, "maybe empty or invalid stack"
|
616
628
|
end
|
617
|
-
value = left.value >> right.value
|
629
|
+
value = left.value >> (right.value % right.memsize)
|
618
630
|
runtime.stack.push(${CLASS}(value))
|
619
631
|
RUBY
|
620
632
|
|
@@ -624,9 +636,10 @@ module GenAlu
|
|
624
636
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
625
637
|
raise EvalError, "maybe empty or invalid stack"
|
626
638
|
end
|
627
|
-
|
628
|
-
|
629
|
-
|
639
|
+
k = (right.value % right.memsize)
|
640
|
+
rotated = left.value << k
|
641
|
+
rest = left.value & (${CLASS}::${CLASS}_MAX << (right.memsize - k))
|
642
|
+
value = rotated | (rest >> (right.memsize - k))
|
630
643
|
runtime.stack.push(${CLASS}(value))
|
631
644
|
RUBY
|
632
645
|
|
@@ -636,9 +649,10 @@ module GenAlu
|
|
636
649
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
637
650
|
raise EvalError, "maybe empty or invalid stack"
|
638
651
|
end
|
639
|
-
|
640
|
-
|
641
|
-
|
652
|
+
k = (right.value % right.memsize)
|
653
|
+
rotated = left.value >> k
|
654
|
+
rest = left.value & (${CLASS}::${CLASS}_MAX >> (right.memsize - k))
|
655
|
+
value = rotated | (rest << (right.memsize - k))
|
642
656
|
runtime.stack.push(${CLASS}(value))
|
643
657
|
RUBY
|
644
658
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Generated from lib/wardite/errors.rb with RBS::Inline
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
# rbs_inline: enabled
|
5
|
+
module Wardite
|
6
|
+
# basic error class.
|
7
|
+
class WebAssemblyError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
class IntegerOverflow < WebAssemblyError
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Generated from lib/wardite/revisitor.rb with RBS::Inline
|
2
|
+
|
3
|
+
# rbs_inline: enabled
|
4
|
+
module Wardite
|
5
|
+
class Revisitor
|
6
|
+
attr_accessor ops: Array[Op]
|
7
|
+
|
8
|
+
# @rbs ops: Array[Op]
|
9
|
+
# @rbs return: void
|
10
|
+
def initialize: (Array[Op] ops) -> void
|
11
|
+
|
12
|
+
# @rbs return: void
|
13
|
+
def revisit!: () -> void
|
14
|
+
|
15
|
+
# @rbs pc_start: Integer
|
16
|
+
# @rbs return: Integer
|
17
|
+
# @rbs return: void
|
18
|
+
def fetch_ops_while_else_or_end: (Integer pc_start) -> Integer
|
19
|
+
|
20
|
+
# @rbs pc_start: Integer
|
21
|
+
# @rbs return: Integer
|
22
|
+
# @rbs return: void
|
23
|
+
def fetch_ops_while_end: (Integer pc_start) -> Integer
|
24
|
+
end
|
25
|
+
end
|
data/sig/generated/wardite.rbs
CHANGED
@@ -115,22 +115,12 @@ module Wardite
|
|
115
115
|
# @rbs return: void
|
116
116
|
def eval_insn: (Frame frame, Op insn) -> void
|
117
117
|
|
118
|
-
# @rbs ops: Array[Op]
|
119
|
-
# @rbs pc_start: Integer
|
120
|
-
# @rbs return: Integer
|
121
|
-
def fetch_ops_while_else_or_end: (Array[Op] ops, Integer pc_start) -> Integer
|
122
|
-
|
123
118
|
# @rbs labels: Array[Label]
|
124
119
|
# @rbs stack: Array[wasmValue]
|
125
120
|
# @rbs level: Integer
|
126
121
|
# @rbs return: Integer
|
127
122
|
def do_branch: (Array[Label] labels, Array[wasmValue] stack, Integer level) -> Integer
|
128
123
|
|
129
|
-
# @rbs ops: Array[Op]
|
130
|
-
# @rbs pc_start: Integer
|
131
|
-
# @rbs return: Integer
|
132
|
-
def fetch_ops_while_end: (Array[Op] ops, Integer pc_start) -> Integer
|
133
|
-
|
134
124
|
# unwind the stack and put return value if exists
|
135
125
|
# @rbs sp: Integer
|
136
126
|
# @rbs arity: Integer
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wardite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uchio Kondo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A pure-ruby webassembly runtime
|
14
14
|
email:
|
@@ -31,6 +31,7 @@ files:
|
|
31
31
|
- examples/fib.wat
|
32
32
|
- examples/fib2.wat
|
33
33
|
- examples/global.wat
|
34
|
+
- examples/grayscale.rb
|
34
35
|
- examples/helloworld.wat
|
35
36
|
- examples/i32_const.wat
|
36
37
|
- examples/i32_store.wat
|
@@ -49,9 +50,11 @@ files:
|
|
49
50
|
- lib/wardite/alu_i64.generated.rb
|
50
51
|
- lib/wardite/const.rb
|
51
52
|
- lib/wardite/convert.generated.rb
|
53
|
+
- lib/wardite/errors.rb
|
52
54
|
- lib/wardite/instruction.rb
|
53
55
|
- lib/wardite/leb128.rb
|
54
56
|
- lib/wardite/load.rb
|
57
|
+
- lib/wardite/revisitor.rb
|
55
58
|
- lib/wardite/value.rb
|
56
59
|
- lib/wardite/version.rb
|
57
60
|
- lib/wardite/wasi.rb
|
@@ -66,9 +69,11 @@ files:
|
|
66
69
|
- sig/generated/wardite/alu_i64.generated.rbs
|
67
70
|
- sig/generated/wardite/const.rbs
|
68
71
|
- sig/generated/wardite/convert.generated.rbs
|
72
|
+
- sig/generated/wardite/errors.rbs
|
69
73
|
- sig/generated/wardite/instruction.rbs
|
70
74
|
- sig/generated/wardite/leb128.rbs
|
71
75
|
- sig/generated/wardite/load.rbs
|
76
|
+
- sig/generated/wardite/revisitor.rbs
|
72
77
|
- sig/generated/wardite/value.rbs
|
73
78
|
- sig/generated/wardite/version.rbs
|
74
79
|
- sig/generated/wardite/wasi.rbs
|