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.
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|nil]]
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 #: I32|I64|F32|F64
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 :flags #: Integer
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, Proc]]
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
- unimplemented_skip_section(code)
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
- unimplemented_skip_section(code)
321
+ start_section
261
322
  when Wardite::SectionElement
262
- unimplemented_skip_section(code)
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 = Op.to_sym(c)
610
+ namespace, code = resolve_code(c, buf)
480
611
  operand_types = Op.operand_of(code)
481
- operand = [] #: Array[Integer|Float|Block]
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 :u8_if_block # :if specific
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
- mem_index = fetch_uleb128(sbuf)
544
- code = fetch_insn_while_end(sbuf)
545
- ops = code_body(StringIO.new(code))
546
- offset = decode_expr(ops)
547
-
548
- len = fetch_uleb128(sbuf)
549
- data = sbuf.read len
550
- if !data
551
- raise LoadError, "buffer too short"
552
- end
553
-
554
- segment = DataSection::Segment.new do |seg|
555
- seg.flags = mem_index
556
- seg.offset = offset
557
- seg.data = data
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: I32|I64|F32|F64
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
- # TODO: floats
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