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