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