wardite 0.2.2 → 0.3.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/examples/break.wat +13 -0
- data/examples/call_indirect.wat +15 -0
- data/examples/loop.wat +20 -0
- data/examples/start.wat +12 -0
- data/lib/wardite/instruction.rb +11 -5
- data/lib/wardite/load.rb +130 -9
- data/lib/wardite/value.rb +45 -42
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +2 -2
- data/lib/wardite.rb +387 -15
- data/sig/generated/wardite/instruction.rbs +6 -3
- data/sig/generated/wardite/load.rbs +44 -6
- data/sig/generated/wardite/value.rbs +82 -80
- data/sig/generated/wardite/wasi.rbs +4 -4
- data/sig/generated/wardite.rbs +97 -17
- data/sig/wardite.rbs +1 -3
- metadata +6 -2
data/lib/wardite/wasi.rb
CHANGED
@@ -14,7 +14,7 @@ module Wardite
|
|
14
14
|
end
|
15
15
|
|
16
16
|
# @rbs store: Store
|
17
|
-
# @rbs args: Array[
|
17
|
+
# @rbs args: Array[wasmValue]
|
18
18
|
# @rbs return: Object
|
19
19
|
def fd_write(store, args)
|
20
20
|
iargs = args.map do |elm|
|
@@ -45,7 +45,7 @@ module Wardite
|
|
45
45
|
0
|
46
46
|
end
|
47
47
|
|
48
|
-
# @rbs return: Hash[Symbol,
|
48
|
+
# @rbs return: Hash[Symbol, wasmCallable]
|
49
49
|
def to_module
|
50
50
|
{
|
51
51
|
fd_write: lambda{|store, args| self.fd_write(store, args) },
|
data/lib/wardite.rb
CHANGED
@@ -31,13 +31,15 @@ module Wardite
|
|
31
31
|
|
32
32
|
attr_accessor :runtime #: Runtime
|
33
33
|
|
34
|
+
attr_accessor :types #: Array[Type]
|
35
|
+
|
34
36
|
attr_accessor :store #: Store
|
35
37
|
|
36
38
|
attr_accessor :exports #: Exports
|
37
39
|
|
38
|
-
attr_reader :import_object #: Hash[Symbol, Hash[Symbol,
|
40
|
+
attr_reader :import_object #: Hash[Symbol, Hash[Symbol, wasmCallable]]
|
39
41
|
|
40
|
-
# @rbs import_object: Hash[Symbol, Hash[Symbol,
|
42
|
+
# @rbs import_object: Hash[Symbol, Hash[Symbol, wasmCallable]]
|
41
43
|
# @rbs &blk: (Instance) -> void
|
42
44
|
def initialize(import_object, &blk)
|
43
45
|
blk.call(self)
|
@@ -46,6 +48,15 @@ module Wardite
|
|
46
48
|
@store = Store.new(self)
|
47
49
|
@exports = Exports.new(self.export_section, store)
|
48
50
|
@runtime = Runtime.new(self)
|
51
|
+
|
52
|
+
@types = []
|
53
|
+
type_section = self.type_section
|
54
|
+
if type_section
|
55
|
+
type_section.defined_types.each_with_index do |calltype, idx|
|
56
|
+
rettype = type_section.defined_results[idx]
|
57
|
+
@types << Type.new(calltype, rettype)
|
58
|
+
end
|
59
|
+
end
|
49
60
|
end
|
50
61
|
|
51
62
|
# @rbs return: ImportSection
|
@@ -82,6 +93,18 @@ module Wardite
|
|
82
93
|
sec
|
83
94
|
end
|
84
95
|
|
96
|
+
# @rbs return: StartSection|nil
|
97
|
+
def start_section
|
98
|
+
sec = @sections.find{|s| s.code == Const::SectionStart }
|
99
|
+
if !sec
|
100
|
+
return nil
|
101
|
+
end
|
102
|
+
if !sec.is_a?(StartSection)
|
103
|
+
raise(GenericError, "[BUG] found invalid start section")
|
104
|
+
end
|
105
|
+
sec
|
106
|
+
end
|
107
|
+
|
85
108
|
# @rbs return: GlobalSection|nil
|
86
109
|
def global_section
|
87
110
|
sec = @sections.find{|s| s.code == Const::SectionGlobal }
|
@@ -118,6 +141,30 @@ module Wardite
|
|
118
141
|
sec
|
119
142
|
end
|
120
143
|
|
144
|
+
# @rbs return: TableSection?
|
145
|
+
def table_section
|
146
|
+
sec = @sections.find{|s| s.code == Const::SectionTable }
|
147
|
+
if !sec
|
148
|
+
return nil
|
149
|
+
end
|
150
|
+
if !sec.is_a?(TableSection)
|
151
|
+
raise(GenericError, "instance doesn't have required section")
|
152
|
+
end
|
153
|
+
sec
|
154
|
+
end
|
155
|
+
|
156
|
+
# @rbs return: ElemSection?
|
157
|
+
def elem_section
|
158
|
+
sec = @sections.find{|s| s.code == Const::SectionElement }
|
159
|
+
if !sec
|
160
|
+
return nil
|
161
|
+
end
|
162
|
+
if !sec.is_a?(ElemSection)
|
163
|
+
raise(GenericError, "instance doesn't have required section")
|
164
|
+
end
|
165
|
+
sec
|
166
|
+
end
|
167
|
+
|
121
168
|
# @rbs return: CodeSection|nil
|
122
169
|
def code_section
|
123
170
|
sec = @sections.find{|s| s.code == Const::SectionCode }
|
@@ -147,7 +194,7 @@ module Wardite
|
|
147
194
|
include ValueHelper
|
148
195
|
|
149
196
|
# TODO: add types of class that the stack accomodates
|
150
|
-
attr_accessor :stack #: Array[
|
197
|
+
attr_accessor :stack #: Array[wasmValue]
|
151
198
|
|
152
199
|
attr_accessor :call_stack #: Array[Frame]
|
153
200
|
|
@@ -158,8 +205,18 @@ module Wardite
|
|
158
205
|
@stack = []
|
159
206
|
@call_stack = []
|
160
207
|
@instance = inst
|
208
|
+
|
209
|
+
invoke_start_section
|
161
210
|
end
|
162
211
|
|
212
|
+
# @rbs return: void
|
213
|
+
def invoke_start_section
|
214
|
+
start_section = instance.start_section
|
215
|
+
if start_section
|
216
|
+
call_by_index(start_section.func_index)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
163
220
|
# @rbs name: String|Symbol
|
164
221
|
# @rbs return: bool
|
165
222
|
def callable?(name)
|
@@ -200,6 +257,21 @@ module Wardite
|
|
200
257
|
end
|
201
258
|
end
|
202
259
|
|
260
|
+
# @rbs idx: Integer
|
261
|
+
# @rbs return: void
|
262
|
+
def call_by_index(idx)
|
263
|
+
fn = @instance.store.funcs[idx]
|
264
|
+
|
265
|
+
case fn
|
266
|
+
when WasmFunction
|
267
|
+
invoke_internal(fn)
|
268
|
+
when ExternalFunction
|
269
|
+
invoke_external(fn)
|
270
|
+
else
|
271
|
+
raise GenericError, "registered pointer is not to a function"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
203
275
|
# @rbs wasm_function: WasmFunction
|
204
276
|
# @rbs return: void
|
205
277
|
def push_frame(wasm_function)
|
@@ -249,7 +321,7 @@ module Wardite
|
|
249
321
|
end
|
250
322
|
|
251
323
|
# @rbs external_function: ExternalFunction
|
252
|
-
# @rbs return:
|
324
|
+
# @rbs return: wasmValue|nil
|
253
325
|
def invoke_external(external_function)
|
254
326
|
local_start = stack.size - external_function.callsig.size
|
255
327
|
args = stack[local_start..]
|
@@ -326,19 +398,80 @@ module Wardite
|
|
326
398
|
when :nop
|
327
399
|
return
|
328
400
|
|
401
|
+
when :br
|
402
|
+
level = insn.operand[0]
|
403
|
+
raise EvalError, "br op without level" if !level.is_a?(Integer)
|
404
|
+
pc = do_branch(frame.labels, stack, level)
|
405
|
+
frame.pc = pc
|
406
|
+
|
407
|
+
when :br_if
|
408
|
+
level = insn.operand[0]
|
409
|
+
raise EvalError, "br op without level" if !level.is_a?(Integer)
|
410
|
+
cond = stack.pop
|
411
|
+
raise EvalError, "cond not found" if !cond.is_a?(I32)
|
412
|
+
if cond.value.zero?
|
413
|
+
return
|
414
|
+
end
|
415
|
+
pc = do_branch(frame.labels, stack, level)
|
416
|
+
frame.pc = pc
|
417
|
+
|
418
|
+
when :br_table
|
419
|
+
level_vec = insn.operand[0]
|
420
|
+
raise EvalError, "no level vector" if !level_vec.is_a?(Array)
|
421
|
+
default = insn.operand[1]
|
422
|
+
raise EvalError, "no default specified" if !default.is_a?(Integer)
|
423
|
+
idx = stack.pop
|
424
|
+
raise EvalError, "idx not found" if !idx.is_a?(I32)
|
425
|
+
level = if idx.value_s < 0 || idx.value_s >= level_vec.size
|
426
|
+
default
|
427
|
+
else
|
428
|
+
level_vec[idx.value_s]
|
429
|
+
end
|
430
|
+
pc = do_branch(frame.labels, stack, level)
|
431
|
+
frame.pc = pc
|
432
|
+
|
433
|
+
when :block
|
434
|
+
block = insn.operand[0]
|
435
|
+
raise EvalError, "block op without block" if !block.is_a?(Block)
|
436
|
+
next_pc = fetch_ops_while_end(frame.body, frame.pc)
|
437
|
+
label = Label.new(:block, next_pc, stack.size, block.result_size)
|
438
|
+
frame.labels.push(label)
|
439
|
+
|
440
|
+
when :loop
|
441
|
+
block = insn.operand[0]
|
442
|
+
raise EvalError, "loop op without block" if !block.is_a?(Block)
|
443
|
+
start = frame.pc
|
444
|
+
end_pc = fetch_ops_while_end(frame.body, frame.pc)
|
445
|
+
label = Label.new(:loop, end_pc, stack.size, block.result_size, start)
|
446
|
+
frame.labels.push(label)
|
447
|
+
|
329
448
|
when :if
|
330
449
|
block = insn.operand[0]
|
331
450
|
raise EvalError, "if op without block" if !block.is_a?(Block)
|
332
451
|
cond = stack.pop
|
333
452
|
raise EvalError, "cond not found" if !cond.is_a?(I32)
|
334
453
|
next_pc = fetch_ops_while_end(frame.body, frame.pc)
|
454
|
+
|
335
455
|
if cond.value.zero?
|
336
|
-
frame.pc =
|
456
|
+
frame.pc = fetch_ops_while_else_or_end(frame.body, frame.pc)
|
457
|
+
end
|
458
|
+
|
459
|
+
if frame.pc == next_pc
|
460
|
+
# This means if block has no else instr.
|
461
|
+
return
|
337
462
|
end
|
338
463
|
|
339
464
|
label = Label.new(:if, next_pc, stack.size, block.result_size)
|
340
465
|
frame.labels.push(label)
|
341
466
|
|
467
|
+
when :else
|
468
|
+
if old_label = frame.labels.pop
|
469
|
+
frame.pc = old_label.pc
|
470
|
+
stack_unwind(old_label.sp, old_label.arity)
|
471
|
+
else
|
472
|
+
raise EvalError, "else should be in if block"
|
473
|
+
end
|
474
|
+
|
342
475
|
when :call
|
343
476
|
idx = insn.operand[0]
|
344
477
|
raise EvalError, "[BUG] local operand not found" if !idx.is_a?(Integer)
|
@@ -353,6 +486,45 @@ module Wardite
|
|
353
486
|
raise GenericError, "got a non-function pointer"
|
354
487
|
end
|
355
488
|
|
489
|
+
when :call_indirect
|
490
|
+
table = self.instance.store.tables[0]
|
491
|
+
raise EvalError, "table required but not found" if !table
|
492
|
+
type_idx = insn.operand[0]
|
493
|
+
raise EvalError, "[BUG] index operand invalid" if !type_idx.is_a?(Integer)
|
494
|
+
nullbyte = insn.operand[1]
|
495
|
+
raise EvalError, "[BUG] invalid bytearray of call_indirect" if nullbyte != 0x0
|
496
|
+
table_idx = stack.pop
|
497
|
+
raise EvalError, "[BUG] index stack invalid" if !table_idx.is_a?(I32)
|
498
|
+
fntype = self.instance.types[type_idx]
|
499
|
+
if !fntype
|
500
|
+
raise EvalError, "undefined type index: idx=#{type_idx}"
|
501
|
+
end
|
502
|
+
refs = self.instance.store.tables[0]&.refs
|
503
|
+
if !refs
|
504
|
+
raise EvalError, "uninitialized element idx:#{table_idx}"
|
505
|
+
end
|
506
|
+
|
507
|
+
fn = refs[table_idx.value]
|
508
|
+
case fn
|
509
|
+
when WasmFunction
|
510
|
+
if table.type != :funcref
|
511
|
+
raise EvalError, "invalid type of elem; expected: #{table.type}"
|
512
|
+
end
|
513
|
+
fn = fn.clone(override_type: fntype)
|
514
|
+
push_frame(fn)
|
515
|
+
when ExternalFunction
|
516
|
+
if table.type != :externref
|
517
|
+
raise EvalError, "invalid type of elem; expected: #{table.type}"
|
518
|
+
end
|
519
|
+
fn = fn.clone(override_type: fntype)
|
520
|
+
ret = invoke_external(fn)
|
521
|
+
self.stack.push ret if ret
|
522
|
+
when nil
|
523
|
+
raise EvalError, "uninitialized element idx:#{table_idx.value}"
|
524
|
+
else
|
525
|
+
raise EvalError, "[BUG] unknwon function type #{fn}"
|
526
|
+
end
|
527
|
+
|
356
528
|
when :return
|
357
529
|
old_frame = call_stack.pop
|
358
530
|
if !old_frame
|
@@ -408,6 +580,18 @@ module Wardite
|
|
408
580
|
end
|
409
581
|
frame.locals[idx] = value
|
410
582
|
|
583
|
+
when :local_tee
|
584
|
+
idx = insn.operand[0]
|
585
|
+
if !idx.is_a?(Integer)
|
586
|
+
raise EvalError, "[BUG] invalid type of operand"
|
587
|
+
end
|
588
|
+
value = stack.pop
|
589
|
+
if !value
|
590
|
+
raise EvalError, "value should be pushed"
|
591
|
+
end
|
592
|
+
frame.locals[idx] = value
|
593
|
+
stack.push value
|
594
|
+
|
411
595
|
when :global_get
|
412
596
|
idx = insn.operand[0]
|
413
597
|
if !idx.is_a?(Integer)
|
@@ -456,11 +640,69 @@ module Wardite
|
|
456
640
|
|
457
641
|
rescue => e
|
458
642
|
require "pp"
|
643
|
+
$stderr.puts "instance:::\n#{self.instance.pretty_inspect}"
|
459
644
|
$stderr.puts "frame:::\n#{frame.pretty_inspect}"
|
460
645
|
$stderr.puts "stack:::\n#{stack.pretty_inspect}"
|
461
646
|
raise e
|
462
647
|
end
|
463
648
|
|
649
|
+
# @rbs ops: Array[Op]
|
650
|
+
# @rbs pc_start: Integer
|
651
|
+
# @rbs return: Integer
|
652
|
+
def fetch_ops_while_else_or_end(ops, pc_start)
|
653
|
+
cursor = pc_start
|
654
|
+
depth = 0
|
655
|
+
loop {
|
656
|
+
cursor += 1
|
657
|
+
inst = ops[cursor]
|
658
|
+
case inst&.code
|
659
|
+
when nil
|
660
|
+
raise EvalError, "end op not found"
|
661
|
+
when :if
|
662
|
+
depth += 1
|
663
|
+
when :else
|
664
|
+
if depth == 0
|
665
|
+
return cursor
|
666
|
+
end
|
667
|
+
# do not touch depth
|
668
|
+
when :end
|
669
|
+
if depth == 0
|
670
|
+
return cursor
|
671
|
+
else
|
672
|
+
depth -= 1
|
673
|
+
end
|
674
|
+
else
|
675
|
+
# nop
|
676
|
+
end
|
677
|
+
}
|
678
|
+
raise "[BUG] unreachable"
|
679
|
+
end
|
680
|
+
|
681
|
+
# @rbs labels: Array[Label]
|
682
|
+
# @rbs stack: Array[wasmValue]
|
683
|
+
# @rbs level: Integer
|
684
|
+
# @rbs return: Integer
|
685
|
+
def do_branch(labels, stack, level)
|
686
|
+
idx = labels.size - 1 - level
|
687
|
+
label = labels[idx]
|
688
|
+
pc = if label.kind == :loop
|
689
|
+
# keep the top of labels for loop again...
|
690
|
+
while labels.size > idx + 1
|
691
|
+
labels.pop
|
692
|
+
end
|
693
|
+
stack_unwind(label.sp, 0)
|
694
|
+
label.start || raise(EvalError, "loop withour start")
|
695
|
+
else
|
696
|
+
while labels.size > idx
|
697
|
+
labels.pop
|
698
|
+
end
|
699
|
+
stack_unwind(label.sp, label.arity)
|
700
|
+
label.pc
|
701
|
+
end
|
702
|
+
|
703
|
+
pc
|
704
|
+
end
|
705
|
+
|
464
706
|
# @rbs ops: Array[Op]
|
465
707
|
# @rbs pc_start: Integer
|
466
708
|
# @rbs return: Integer
|
@@ -473,7 +715,7 @@ module Wardite
|
|
473
715
|
case inst&.code
|
474
716
|
when nil
|
475
717
|
raise EvalError, "end op not found"
|
476
|
-
when :
|
718
|
+
when :if, :block, :loop
|
477
719
|
depth += 1
|
478
720
|
when :end
|
479
721
|
if depth == 0
|
@@ -509,7 +751,7 @@ module Wardite
|
|
509
751
|
end
|
510
752
|
|
511
753
|
# @rbs finish: Integer
|
512
|
-
# @rbs return: Array[
|
754
|
+
# @rbs return: Array[wasmValue]
|
513
755
|
def drained_stack(finish)
|
514
756
|
drained = stack[0...finish]
|
515
757
|
if ! drained
|
@@ -537,6 +779,20 @@ module Wardite
|
|
537
779
|
end
|
538
780
|
end
|
539
781
|
|
782
|
+
class Type
|
783
|
+
attr_accessor :callsig #: Array[Symbol]
|
784
|
+
|
785
|
+
attr_accessor :retsig #: Array[Symbol]
|
786
|
+
|
787
|
+
# @rbs callsig: Array[Symbol]
|
788
|
+
# @rbs retsig: Array[Symbol]
|
789
|
+
# @rbs returb: void
|
790
|
+
def initialize(callsig, retsig)
|
791
|
+
@callsig = callsig
|
792
|
+
@retsig = retsig
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
540
796
|
class Frame
|
541
797
|
attr_accessor :pc #: Integer
|
542
798
|
attr_accessor :sp #: Integer
|
@@ -547,13 +803,13 @@ module Wardite
|
|
547
803
|
|
548
804
|
attr_accessor :labels #: Array[Label]
|
549
805
|
|
550
|
-
attr_accessor :locals #: Array[
|
806
|
+
attr_accessor :locals #: Array[wasmValue]
|
551
807
|
|
552
808
|
# @rbs pc: Integer
|
553
809
|
# @rbs sp: Integer
|
554
810
|
# @rbs body: Array[Op]
|
555
811
|
# @rbs arity: Integer
|
556
|
-
# @rbs locals: Array[
|
812
|
+
# @rbs locals: Array[wasmValue]
|
557
813
|
# @rbs returb: void
|
558
814
|
def initialize(pc, sp, body, arity, locals)
|
559
815
|
@pc = pc
|
@@ -573,16 +829,20 @@ module Wardite
|
|
573
829
|
|
574
830
|
attr_accessor :arity #: Integer
|
575
831
|
|
832
|
+
attr_accessor :start #: Integer|nil
|
833
|
+
|
576
834
|
# @rbs kind: (:if|:loop|:block)
|
577
835
|
# @rbs pc: Integer
|
578
836
|
# @rbs sp: Integer
|
579
837
|
# @rbs arity: Integer
|
580
|
-
# @rbs
|
581
|
-
|
838
|
+
# @rbs start: Integer|nil
|
839
|
+
# @rbs return: void
|
840
|
+
def initialize(kind, pc, sp, arity, start=nil)
|
582
841
|
@kind = kind
|
583
842
|
@pc = pc
|
584
843
|
@sp = sp
|
585
844
|
@arity = arity
|
845
|
+
@start = start
|
586
846
|
end
|
587
847
|
end
|
588
848
|
|
@@ -595,6 +855,10 @@ module Wardite
|
|
595
855
|
|
596
856
|
attr_accessor :globals #: Array[Global]
|
597
857
|
|
858
|
+
attr_accessor :tables #: Array[Table]
|
859
|
+
|
860
|
+
attr_accessor :elements #: Array[[Symbol, Integer, Array[Integer]]]
|
861
|
+
|
598
862
|
# @rbs inst: Instance
|
599
863
|
# @rbs return: void
|
600
864
|
def initialize(inst)
|
@@ -669,6 +933,56 @@ module Wardite
|
|
669
933
|
end
|
670
934
|
end
|
671
935
|
end
|
936
|
+
|
937
|
+
@tables = []
|
938
|
+
@elements = []
|
939
|
+
table_section = inst.table_section
|
940
|
+
if table_section
|
941
|
+
table_section.table_types.each_with_index do |typ, idx|
|
942
|
+
init, max = *table_section.table_limits[idx]
|
943
|
+
if !init
|
944
|
+
raise LoadError, "empty limits"
|
945
|
+
end
|
946
|
+
table = Table.new(typ, init, max)
|
947
|
+
@tables << table
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
951
|
+
elem_section = inst.elem_section
|
952
|
+
if elem_section
|
953
|
+
elem_section.table_indices.each_with_index do |tidx, idx|
|
954
|
+
table = @tables[tidx]
|
955
|
+
if !table
|
956
|
+
raise LoadError, "invalid table index #{tidx}"
|
957
|
+
end
|
958
|
+
typ = table.type
|
959
|
+
offset = elem_section.table_offsets[idx]
|
960
|
+
if !offset
|
961
|
+
raise LoadError, "invalid element index #{idx}"
|
962
|
+
end
|
963
|
+
indices = elem_section.element_indices[idx]
|
964
|
+
if !indices
|
965
|
+
raise LoadError, "invalid element index #{idx}"
|
966
|
+
end
|
967
|
+
elms = [typ, offset, indices] #: [Symbol, Integer, Array[Integer]]
|
968
|
+
@elements << elms
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
972
|
+
@elements.each_with_index do |(typ, offset, indices), idx|
|
973
|
+
table = @tables[idx]
|
974
|
+
if !table
|
975
|
+
raise LoadError, "invalid table index #{idx}"
|
976
|
+
end
|
977
|
+
indices.each_with_index do |eidx, tidx|
|
978
|
+
case typ
|
979
|
+
when :funcref
|
980
|
+
table.set(offset + tidx, @funcs[eidx])
|
981
|
+
when :externref
|
982
|
+
raise NotImplementedError, "no support :externref"
|
983
|
+
end
|
984
|
+
end
|
985
|
+
end
|
672
986
|
end
|
673
987
|
|
674
988
|
# @rbs idx: Integer
|
@@ -711,6 +1025,38 @@ module Wardite
|
|
711
1025
|
end
|
712
1026
|
end
|
713
1027
|
|
1028
|
+
class Table
|
1029
|
+
attr_accessor :type #: Symbol
|
1030
|
+
|
1031
|
+
attr_accessor :current #: Integer
|
1032
|
+
|
1033
|
+
attr_accessor :max #: Integer|nil
|
1034
|
+
|
1035
|
+
attr_accessor :refs #: Array[WasmFunction|ExternalFunction|nil]
|
1036
|
+
|
1037
|
+
# @rbs type: Symbol
|
1038
|
+
# @rbs init: Integer
|
1039
|
+
# @rbs max: Integer|nil
|
1040
|
+
# @rbs return: void
|
1041
|
+
def initialize(type, init, max)
|
1042
|
+
@type = type
|
1043
|
+
@current = init
|
1044
|
+
@max = max
|
1045
|
+
|
1046
|
+
@refs = Array.new(3, nil)
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
# @rbs idx: Integer
|
1050
|
+
# @rbs elem: WasmFunction|ExternalFunction|nil
|
1051
|
+
# @rbs return: void
|
1052
|
+
def set(idx, elem)
|
1053
|
+
if idx >= @current
|
1054
|
+
raise GenericError, "idx too large for table"
|
1055
|
+
end
|
1056
|
+
@refs[idx] = elem
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
|
714
1060
|
class Global
|
715
1061
|
attr_accessor :type #: Symbol
|
716
1062
|
|
@@ -719,7 +1065,7 @@ module Wardite
|
|
719
1065
|
# TODO: unused in wasm 1.0 spec?
|
720
1066
|
attr_accessor :shared #: bool
|
721
1067
|
|
722
|
-
attr_accessor :value #:
|
1068
|
+
attr_accessor :value #: wasmValue
|
723
1069
|
|
724
1070
|
# @rbs &blk: (Global) -> void
|
725
1071
|
# @rbs return: void
|
@@ -829,25 +1175,51 @@ module Wardite
|
|
829
1175
|
# @rbs return: Array[Integer]
|
830
1176
|
def locals_count
|
831
1177
|
code_body.locals_count
|
832
|
-
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
# @rbs override_type: Type?
|
1181
|
+
# @rbs return: WasmFunction
|
1182
|
+
def clone(override_type: nil)
|
1183
|
+
if override_type
|
1184
|
+
# code_body is assumed to be frozen, so we can copy its ref
|
1185
|
+
WasmFunction.new(override_type.callsig, override_type.retsig, code_body)
|
1186
|
+
else
|
1187
|
+
WasmFunction.new(callsig, retsig, code_body)
|
1188
|
+
end
|
1189
|
+
end
|
833
1190
|
end
|
834
1191
|
|
1192
|
+
# @rbs!
|
1193
|
+
# type wasmFuncReturn = Object|nil
|
1194
|
+
# type wasmCallable = ^(Store, Array[wasmValue]) -> wasmFuncReturn
|
1195
|
+
|
835
1196
|
class ExternalFunction
|
836
1197
|
attr_accessor :callsig #: Array[Symbol]
|
837
1198
|
|
838
1199
|
attr_accessor :retsig #: Array[Symbol]
|
839
1200
|
|
840
|
-
attr_accessor :callable #:
|
1201
|
+
attr_accessor :callable #: wasmCallable
|
841
1202
|
|
842
1203
|
# @rbs callsig: Array[Symbol]
|
843
1204
|
# @rbs retsig: Array[Symbol]
|
844
|
-
# @rbs callable:
|
1205
|
+
# @rbs callable: wasmCallable
|
845
1206
|
# @rbs return: void
|
846
1207
|
def initialize(callsig, retsig, callable)
|
847
1208
|
@callsig = callsig
|
848
1209
|
@retsig = retsig
|
849
1210
|
@callable = callable
|
850
1211
|
end
|
1212
|
+
|
1213
|
+
# @rbs override_type: Type?
|
1214
|
+
# @rbs return: ExternalFunction
|
1215
|
+
def clone(override_type: nil)
|
1216
|
+
if override_type
|
1217
|
+
# callable is assumed to be frozen, so we can copy its ref
|
1218
|
+
ExternalFunction.new(override_type.callsig, override_type.retsig, callable)
|
1219
|
+
else
|
1220
|
+
ExternalFunction.new(callsig, retsig, callable)
|
1221
|
+
end
|
1222
|
+
end
|
851
1223
|
end
|
852
1224
|
|
853
1225
|
class GenericError < StandardError; end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# Generated from lib/wardite/instruction.rb with RBS::Inline
|
2
2
|
|
3
3
|
module Wardite
|
4
|
+
type operandItem = Integer | Array[Integer] | Float | Block
|
5
|
+
|
4
6
|
class Op
|
5
7
|
# @see https://pengowray.github.io/wasm-ops/
|
6
8
|
SYMS: Array[Symbol]
|
@@ -13,12 +15,12 @@ module Wardite
|
|
13
15
|
attr_accessor code: Symbol
|
14
16
|
|
15
17
|
# TODO: add types of potential operands
|
16
|
-
attr_accessor operand: Array[
|
18
|
+
attr_accessor operand: Array[operandItem]
|
17
19
|
|
18
20
|
# @rbs namespace: Symbol
|
19
21
|
# @rbs code: Symbol
|
20
|
-
# @rbs operand: Array[
|
21
|
-
def initialize: (Symbol namespace, Symbol code, Array[
|
22
|
+
# @rbs operand: Array[operandItem]
|
23
|
+
def initialize: (Symbol namespace, Symbol code, Array[operandItem] operand) -> untyped
|
22
24
|
|
23
25
|
# @rbs chr: String
|
24
26
|
# @rbs return: [Symbol, Symbol]
|
@@ -29,6 +31,7 @@ module Wardite
|
|
29
31
|
def self.operand_of: (Symbol code) -> Array[Symbol]
|
30
32
|
|
31
33
|
# @see https://www.w3.org/TR/wasm-core-1/#value-types%E2%91%A2
|
34
|
+
# We use this for reftype conversion. https://webassembly.github.io/spec/core/binary/types.html#binary-reftype
|
32
35
|
# @rbs code: Integer
|
33
36
|
# @rbs return: Symbol
|
34
37
|
def self.i2type: (Integer code) -> Symbol
|