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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1960efc493205587db2fbb0e21504247d120831417b081dc169c0b7c10fccaf
4
- data.tar.gz: cbdbf5e122fe118ccee7a615b184be2032b6000a043b3642a9b5336f6b0fbe19
3
+ metadata.gz: 89b6c42e1a3f16c39c214eb127c5b87966c0d2933257a1da7fdc96236c6a0f9b
4
+ data.tar.gz: 321d62cdddc61c8a342b966b3e4d7b6c01ffbbcb5788a6787fd3490ba96b1430
5
5
  SHA512:
6
- metadata.gz: 207a1cd23ab5f25fdf9dd421ab42c70528be1987e57f41d656f47e205ee78ba321b9553364f988f6f039f87a77878e040075e690b00b97ace0bf91e35c07431f
7
- data.tar.gz: 944b8112be80c9c3b78dd7cdec01ac3c72f7e4e077196a315bfaa14ffeb4dfa6cdb868570ae0bc55fb4f07da858f968807fee8bb50d5846fa763dd7b82359f98
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)).zero?
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
- runtime.stack.push(I32(left.value_s / right.value_s))
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
- runtime.stack.push(I32(left.value_s % right.value_s))
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 %= (1 << right.memsize)
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
- rotated = left.value << right.value
436
- rest = left.value & (I32::I32_MAX << (right.memsize - right.value))
437
- value = rotated | (rest >> (right.memsize - right.value))
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
- rotated = left.value >> right.value
447
- rest = left.value & (I32::I32_MAX >> (right.memsize - right.value))
448
- value = rotated | (rest << (right.memsize - right.value))
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)).zero?
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
- runtime.stack.push(I64(left.value_s / right.value_s))
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
- runtime.stack.push(I64(left.value_s % right.value_s))
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 %= (1 << right.memsize)
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
- rotated = left.value << right.value
493
- rest = left.value & (I64::I64_MAX << (right.memsize - right.value))
494
- value = rotated | (rest >> (right.memsize - right.value))
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
- rotated = left.value >> right.value
504
- rest = left.value & (I64::I64_MAX >> (right.memsize - right.value))
505
- value = rotated | (rest << (right.memsize - right.value))
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
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+ module Wardite
4
+ # basic error class.
5
+ class WebAssemblyError < StandardError
6
+ end
7
+
8
+ class IntegerOverflow < WebAssemblyError; end
9
+ end
@@ -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 = 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
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Wardite
5
- VERSION = "0.4.3" #: String
5
+ VERSION = "0.5.1" #: String
6
6
  end
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 = fetch_ops_while_end(frame.body, frame.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
- end_pc = fetch_ops_while_end(frame.body, frame.pc)
484
- label = Label.new(:loop, end_pc, stack.size, block.result_size, start)
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 = fetch_ops_while_end(frame.body, frame.pc)
493
+ next_pc = insn.meta[:end_pos]
493
494
 
494
495
  if cond.value.zero?
495
- frame.pc = fetch_ops_while_else_or_end(frame.body, 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)).zero?
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
- runtime.stack.push(${CLASS}(left.value_s / right.value_s))
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
- runtime.stack.push(${CLASS}(left.value_s % right.value_s))
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 %= (1 << right.memsize)
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
- rotated = left.value << right.value
628
- rest = left.value & (${CLASS}::${CLASS}_MAX << (right.memsize - right.value))
629
- value = rotated | (rest >> (right.memsize - right.value))
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
- rotated = left.value >> right.value
640
- rest = left.value & (${CLASS}::${CLASS}_MAX >> (right.memsize - right.value))
641
- value = rotated | (rest << (right.memsize - right.value))
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
@@ -22,6 +22,8 @@ module Wardite
22
22
  # TODO: add types of potential operands
23
23
  attr_accessor operand: Array[operandItem]
24
24
 
25
+ attr_accessor meta: Hash[Symbol, Integer]
26
+
25
27
  # @rbs namespace: Symbol
26
28
  # @rbs code: Symbol
27
29
  # @rbs operand: Array[operandItem]
@@ -1,6 +1,5 @@
1
1
  # Generated from lib/wardite/load.rb with RBS::Inline
2
2
 
3
- # rbs_inline: enabled
4
3
  module Wardite
5
4
  class Section
6
5
  attr_accessor name: String
@@ -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
@@ -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.3
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-17 00:00:00.000000000 Z
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