wardite 0.2.2 → 0.4.0
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.
- checksums.yaml +4 -4
- data/Rakefile +6 -0
- data/examples/break.wat +13 -0
- data/examples/call_indirect.wat +15 -0
- data/examples/loop.wat +20 -0
- data/examples/memory_init.wat +18 -0
- data/examples/saturate.wat +8 -0
- data/examples/saturate_u.wat +9 -0
- data/examples/start.wat +12 -0
- data/lib/wardite/const.rb +13 -12
- data/lib/wardite/convert.generated.rb +104 -0
- data/lib/wardite/instruction.rb +67 -8
- data/lib/wardite/load.rb +216 -28
- data/lib/wardite/value.rb +247 -70
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +2 -2
- data/lib/wardite.rb +471 -17
- data/scripts/gen_conv.rb +12 -2
- data/sig/generated/wardite/const.rbs +2 -0
- data/sig/generated/wardite/instruction.rbs +15 -3
- data/sig/generated/wardite/load.rbs +63 -7
- data/sig/generated/wardite/value.rbs +142 -82
- data/sig/generated/wardite/wasi.rbs +4 -4
- data/sig/generated/wardite.rbs +103 -17
- data/sig/wardite.rbs +1 -3
- metadata +9 -2
data/lib/wardite/load.rb
CHANGED
@@ -35,8 +35,23 @@ module Wardite
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
class TableSection < Section
|
39
|
+
attr_accessor :table_types #: Array[Symbol]
|
40
|
+
|
41
|
+
attr_accessor :table_limits #: Array[[Integer, Integer?]]
|
42
|
+
|
43
|
+
# @rbs return: void
|
44
|
+
def initialize
|
45
|
+
self.name = "Table"
|
46
|
+
self.code = 0x4
|
47
|
+
|
48
|
+
@table_types = []
|
49
|
+
@table_limits = []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
38
53
|
class MemorySection < Section
|
39
|
-
attr_accessor :limits #: Array[[Integer, Integer
|
54
|
+
attr_accessor :limits #: Array[[Integer, Integer?]]
|
40
55
|
|
41
56
|
# @rbs return: void
|
42
57
|
def initialize
|
@@ -56,7 +71,7 @@ module Wardite
|
|
56
71
|
# TODO: unused in wasm 1.0 spec?
|
57
72
|
attr_accessor :shared #: bool
|
58
73
|
|
59
|
-
attr_accessor :value #:
|
74
|
+
attr_accessor :value #: wasmValue
|
60
75
|
|
61
76
|
# @rbs &blk: (Global) -> void
|
62
77
|
# @rbs return: void
|
@@ -76,6 +91,35 @@ module Wardite
|
|
76
91
|
end
|
77
92
|
end
|
78
93
|
|
94
|
+
class StartSection < Section
|
95
|
+
attr_accessor :func_index #: Integer
|
96
|
+
|
97
|
+
# @rbs return: void
|
98
|
+
def initialize
|
99
|
+
self.name = "Start"
|
100
|
+
self.code = 0x8
|
101
|
+
self.func_index = -1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class ElemSection < Section
|
106
|
+
attr_accessor :table_indices #: Array[Integer]
|
107
|
+
|
108
|
+
attr_accessor :table_offsets #: Array[Integer]
|
109
|
+
|
110
|
+
attr_accessor :element_indices #: Array[Array[Integer]]
|
111
|
+
|
112
|
+
# @rbs return: void
|
113
|
+
def initialize
|
114
|
+
self.name = "Elem"
|
115
|
+
self.code = 0x9
|
116
|
+
|
117
|
+
@table_indices = []
|
118
|
+
@table_offsets = []
|
119
|
+
@element_indices = []
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
79
123
|
class CodeSection < Section
|
80
124
|
class CodeBody
|
81
125
|
attr_accessor :locals_count #: Array[Integer]
|
@@ -104,7 +148,9 @@ module Wardite
|
|
104
148
|
|
105
149
|
class DataSection < Section
|
106
150
|
class Segment
|
107
|
-
attr_accessor :
|
151
|
+
attr_accessor :mode #: :active|:passive
|
152
|
+
|
153
|
+
attr_accessor :mem_index #: Integer
|
108
154
|
|
109
155
|
attr_accessor :offset #: Integer
|
110
156
|
|
@@ -128,6 +174,19 @@ module Wardite
|
|
128
174
|
end
|
129
175
|
end
|
130
176
|
|
177
|
+
class DataCountSection < Section
|
178
|
+
attr_accessor :count #: Integer
|
179
|
+
|
180
|
+
# @rbs count: Integer
|
181
|
+
# @rbs return: void
|
182
|
+
def initialize(count)
|
183
|
+
self.name = "Data"
|
184
|
+
self.code = 0xc
|
185
|
+
|
186
|
+
@count = count
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
131
190
|
class ExportSection < Section
|
132
191
|
class ExportDesc
|
133
192
|
attr_accessor :name #: String
|
@@ -186,8 +245,10 @@ module Wardite
|
|
186
245
|
extend Wardite::Leb128Helper
|
187
246
|
extend Wardite::ValueHelper
|
188
247
|
|
248
|
+
# @rbs self.@buf: File|StringIO
|
249
|
+
|
189
250
|
# @rbs buf: File|StringIO
|
190
|
-
# @rbs import_object: Hash[Symbol, Hash[Symbol,
|
251
|
+
# @rbs import_object: Hash[Symbol, Hash[Symbol, wasmCallable]]
|
191
252
|
# @rbs enable_wasi: boolish
|
192
253
|
# @rbs return: Instance
|
193
254
|
def self.load_from_buffer(buf, import_object: {}, enable_wasi: true)
|
@@ -249,7 +310,7 @@ module Wardite
|
|
249
310
|
when Wardite::SectionFunction
|
250
311
|
function_section
|
251
312
|
when Wardite::SectionTable
|
252
|
-
|
313
|
+
table_section
|
253
314
|
when Wardite::SectionMemory
|
254
315
|
memory_section
|
255
316
|
when Wardite::SectionGlobal
|
@@ -257,13 +318,15 @@ module Wardite
|
|
257
318
|
when Wardite::SectionExport
|
258
319
|
export_section
|
259
320
|
when Wardite::SectionStart
|
260
|
-
|
321
|
+
start_section
|
261
322
|
when Wardite::SectionElement
|
262
|
-
|
323
|
+
elem_section
|
263
324
|
when Wardite::SectionCode
|
264
325
|
code_section
|
265
326
|
when Wardite::SectionData
|
266
327
|
data_section
|
328
|
+
when Wardite::Const::SectionDataCount
|
329
|
+
data_count_section
|
267
330
|
when Wardite::SectionCustom
|
268
331
|
unimplemented_skip_section(code)
|
269
332
|
else
|
@@ -387,6 +450,50 @@ module Wardite
|
|
387
450
|
dest
|
388
451
|
end
|
389
452
|
|
453
|
+
# @rbs return: StartSection
|
454
|
+
def self.start_section
|
455
|
+
dest = StartSection.new
|
456
|
+
size = fetch_uleb128(@buf)
|
457
|
+
dest.size = size
|
458
|
+
# StartSection won't use size
|
459
|
+
func_index = fetch_uleb128(@buf)
|
460
|
+
dest.func_index = func_index
|
461
|
+
dest
|
462
|
+
end
|
463
|
+
|
464
|
+
# @rbs return: ElemSection
|
465
|
+
def self.elem_section
|
466
|
+
dest = ElemSection.new
|
467
|
+
size = fetch_uleb128(@buf)
|
468
|
+
dest.size = size
|
469
|
+
sbuf = StringIO.new(@buf.read(size) || raise("buffer too short"))
|
470
|
+
|
471
|
+
len = fetch_uleb128(sbuf)
|
472
|
+
len.times do |i|
|
473
|
+
etype = fetch_uleb128(sbuf)
|
474
|
+
case etype
|
475
|
+
when 0x0 # expr, vec(funcidx)
|
476
|
+
dest.table_indices << 0 # default and fixed to table[0]
|
477
|
+
|
478
|
+
code = fetch_insn_while_end(sbuf)
|
479
|
+
ops = code_body(StringIO.new(code))
|
480
|
+
offset = decode_expr(ops)
|
481
|
+
dest.table_offsets << offset
|
482
|
+
|
483
|
+
elms = []
|
484
|
+
elen = fetch_uleb128(sbuf)
|
485
|
+
elen.times do |i|
|
486
|
+
index = fetch_uleb128(sbuf)
|
487
|
+
elms << index
|
488
|
+
end
|
489
|
+
dest.element_indices << elms
|
490
|
+
else
|
491
|
+
raise NotImplementedError, "element section type #{etype} is a TODO!"
|
492
|
+
end
|
493
|
+
end
|
494
|
+
dest
|
495
|
+
end
|
496
|
+
|
390
497
|
# @rbs return: GlobalSection
|
391
498
|
def self.global_section
|
392
499
|
dest = GlobalSection.new
|
@@ -433,6 +540,30 @@ module Wardite
|
|
433
540
|
dest
|
434
541
|
end
|
435
542
|
|
543
|
+
# @rbs return: TableSection
|
544
|
+
def self.table_section
|
545
|
+
dest = TableSection.new
|
546
|
+
size = fetch_uleb128(@buf)
|
547
|
+
dest.size = size
|
548
|
+
sbuf = StringIO.new(@buf.read(size) || raise("buffer too short"))
|
549
|
+
|
550
|
+
len = fetch_uleb128(sbuf)
|
551
|
+
len.times do |i|
|
552
|
+
code = fetch_uleb128(sbuf)
|
553
|
+
type = Op.i2type(code)
|
554
|
+
dest.table_types << type
|
555
|
+
|
556
|
+
flags = fetch_uleb128(sbuf)
|
557
|
+
min = fetch_uleb128(sbuf)
|
558
|
+
max = nil
|
559
|
+
if flags != 0
|
560
|
+
max = fetch_uleb128(sbuf)
|
561
|
+
end
|
562
|
+
dest.table_limits << [min, max]
|
563
|
+
end
|
564
|
+
dest
|
565
|
+
end
|
566
|
+
|
436
567
|
# @rbs return: CodeSection
|
437
568
|
def self.code_section
|
438
569
|
dest = CodeSection.new
|
@@ -476,9 +607,9 @@ module Wardite
|
|
476
607
|
def self.code_body(buf)
|
477
608
|
dest = []
|
478
609
|
while c = buf.read(1)
|
479
|
-
namespace, code =
|
610
|
+
namespace, code = resolve_code(c, buf)
|
480
611
|
operand_types = Op.operand_of(code)
|
481
|
-
operand = [] #: Array[
|
612
|
+
operand = [] #: Array[operandItem]
|
482
613
|
operand_types.each do |typ|
|
483
614
|
case typ
|
484
615
|
when :u8
|
@@ -489,6 +620,13 @@ module Wardite
|
|
489
620
|
operand << ope.ord
|
490
621
|
when :u32
|
491
622
|
operand << fetch_uleb128(buf)
|
623
|
+
when :u32_vec
|
624
|
+
len = fetch_uleb128(buf)
|
625
|
+
vec = [] #: Array[Integer]
|
626
|
+
len.times do
|
627
|
+
vec << fetch_uleb128(buf)
|
628
|
+
end
|
629
|
+
operand << vec
|
492
630
|
when :i32
|
493
631
|
operand << fetch_sleb128(buf)
|
494
632
|
when :i64
|
@@ -509,7 +647,7 @@ module Wardite
|
|
509
647
|
v = data.unpack("E")[0]
|
510
648
|
raise "String#unpack is broken" if !v.is_a?(Float)
|
511
649
|
operand << v
|
512
|
-
when :
|
650
|
+
when :u8_block
|
513
651
|
block_ope = buf.read 1
|
514
652
|
if ! block_ope
|
515
653
|
raise LoadError, "buffer too short for if"
|
@@ -531,6 +669,18 @@ module Wardite
|
|
531
669
|
dest
|
532
670
|
end
|
533
671
|
|
672
|
+
# @rbs c: String
|
673
|
+
# @rbs buf: StringIO
|
674
|
+
# @rbs return: [Symbol, Symbol]
|
675
|
+
def self.resolve_code(c, buf)
|
676
|
+
namespace, code = Op.to_sym(c)
|
677
|
+
if namespace == :fc
|
678
|
+
lower = fetch_uleb128(buf)
|
679
|
+
return Op.resolve_fc_sym(lower) #: [Symbol, Symbol]
|
680
|
+
end
|
681
|
+
return [namespace, code] #: [Symbol, Symbol]
|
682
|
+
end
|
683
|
+
|
534
684
|
# @rbs return: DataSection
|
535
685
|
def self.data_section
|
536
686
|
dest = DataSection.new
|
@@ -540,27 +690,54 @@ module Wardite
|
|
540
690
|
|
541
691
|
len = fetch_uleb128(sbuf)
|
542
692
|
len.times do |i|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
693
|
+
data_type = fetch_uleb128(sbuf)
|
694
|
+
case data_type
|
695
|
+
when 0x0
|
696
|
+
# active
|
697
|
+
code = fetch_insn_while_end(sbuf)
|
698
|
+
ops = code_body(StringIO.new(code))
|
699
|
+
offset = decode_expr(ops)
|
700
|
+
len = fetch_uleb128(sbuf)
|
701
|
+
data = sbuf.read len
|
702
|
+
if !data
|
703
|
+
raise LoadError, "buffer too short"
|
704
|
+
end
|
705
|
+
segment = DataSection::Segment.new do |seg|
|
706
|
+
seg.mode = :active
|
707
|
+
seg.mem_index = 0 # memory index
|
708
|
+
seg.offset = offset
|
709
|
+
seg.data = data
|
710
|
+
end
|
711
|
+
dest.segments << segment
|
712
|
+
when 0x1
|
713
|
+
# passive
|
714
|
+
dsize = fetch_uleb128(sbuf)
|
715
|
+
data = sbuf.read dsize
|
716
|
+
if !data
|
717
|
+
raise LoadError, "data too short"
|
718
|
+
end
|
719
|
+
segment = DataSection::Segment.new do |seg|
|
720
|
+
seg.mode = :passive
|
721
|
+
seg.mem_index = 0 # unused
|
722
|
+
seg.offset = 0 # unused
|
723
|
+
seg.data = data
|
724
|
+
end
|
725
|
+
dest.segments << segment
|
558
726
|
end
|
559
|
-
dest.segments << segment
|
560
727
|
end
|
561
728
|
dest
|
562
729
|
end
|
563
730
|
|
731
|
+
# @rbs return: DataCountSection
|
732
|
+
def self.data_count_section
|
733
|
+
size = fetch_uleb128(@buf)
|
734
|
+
sbuf = StringIO.new(@buf.read(size) || raise("buffer too short"))
|
735
|
+
count = fetch_uleb128(sbuf)
|
736
|
+
dest = DataCountSection.new(count)
|
737
|
+
dest.size = size
|
738
|
+
dest
|
739
|
+
end
|
740
|
+
|
564
741
|
# @rbs sbuf: StringIO
|
565
742
|
# @rbs return: String
|
566
743
|
def self.fetch_insn_while_end(sbuf)
|
@@ -599,7 +776,7 @@ module Wardite
|
|
599
776
|
end
|
600
777
|
|
601
778
|
# @rbs ops: Array[Op]
|
602
|
-
# @rbs return:
|
779
|
+
# @rbs return: wasmValue
|
603
780
|
def self.decode_global_expr(ops)
|
604
781
|
# sees first opcode
|
605
782
|
op = ops.first
|
@@ -619,7 +796,18 @@ module Wardite
|
|
619
796
|
raise "Invalid definition of operand"
|
620
797
|
end
|
621
798
|
return I64(arg)
|
622
|
-
|
799
|
+
when :f32_const
|
800
|
+
arg = op.operand[0]
|
801
|
+
if !arg.is_a?(Float)
|
802
|
+
raise "Invalid definition of operand"
|
803
|
+
end
|
804
|
+
return F32(arg)
|
805
|
+
when :f64_const
|
806
|
+
arg = op.operand[0]
|
807
|
+
if !arg.is_a?(Float)
|
808
|
+
raise "Invalid definition of operand"
|
809
|
+
end
|
810
|
+
return F64(arg)
|
623
811
|
else
|
624
812
|
raise "Unimplemented offset op: #{op.code.inspect}"
|
625
813
|
end
|