wardite 0.2.2 → 0.4.0

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