wardite 0.2.0 → 0.2.1
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/Rakefile +163 -0
- data/Steepfile +1 -0
- data/examples/consts.wat +12 -0
- data/lib/wardite/alu_f32.generated.rb +250 -0
- data/lib/wardite/alu_f64.generated.rb +250 -0
- data/lib/wardite/alu_i32.generated.rb +398 -18
- data/lib/wardite/alu_i64.generated.rb +514 -0
- data/lib/wardite/convert.generated.rb +234 -0
- data/lib/wardite/instruction.rb +62 -31
- data/lib/wardite/value.rb +576 -31
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +1 -1
- data/lib/wardite.rb +127 -77
- data/scripts/gen_alu.rb +653 -27
- data/scripts/gen_conv.rb +76 -0
- data/scripts/templates/conv_module.rb.tmpl +18 -0
- data/sig/generated/wardite/alu_f32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_f64.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i64.generated.rbs +11 -0
- data/sig/generated/wardite/convert.generated.rbs +11 -0
- data/sig/generated/wardite/instruction.rbs +6 -0
- data/sig/generated/wardite/value.rbs +263 -19
- data/sig/generated/wardite.rbs +12 -3
- metadata +13 -2
data/lib/wardite.rb
CHANGED
@@ -13,6 +13,10 @@ module Wardite
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
require_relative "wardite/alu_i32.generated"
|
16
|
+
require_relative "wardite/alu_i64.generated"
|
17
|
+
require_relative "wardite/alu_f32.generated"
|
18
|
+
require_relative "wardite/alu_f64.generated"
|
19
|
+
require_relative "wardite/convert.generated"
|
16
20
|
|
17
21
|
require_relative "wardite/wasi"
|
18
22
|
|
@@ -290,6 +294,10 @@ module Wardite
|
|
290
294
|
arg << :i32
|
291
295
|
when 0x7e
|
292
296
|
arg << :i64
|
297
|
+
when 0x7d
|
298
|
+
arg << :f32
|
299
|
+
when 0x7c
|
300
|
+
arg << :f64
|
293
301
|
else
|
294
302
|
raise NotImplementedError, "unsupported for now: #{ty.inspect}"
|
295
303
|
end
|
@@ -304,6 +312,10 @@ module Wardite
|
|
304
312
|
ret << :i32
|
305
313
|
when 0x7e
|
306
314
|
ret << :i64
|
315
|
+
when 0x7d
|
316
|
+
ret << :f32
|
317
|
+
when 0x7c
|
318
|
+
ret << :f64
|
307
319
|
else
|
308
320
|
raise NotImplementedError, "unsupported for now: #{ty.inspect}"
|
309
321
|
end
|
@@ -432,14 +444,38 @@ module Wardite
|
|
432
444
|
operand = [] #: Array[Integer|Float|Block]
|
433
445
|
operand_types.each do |typ|
|
434
446
|
case typ
|
447
|
+
when :u8
|
448
|
+
ope = buf.read 1
|
449
|
+
if ! ope
|
450
|
+
raise LoadError, "buffer too short"
|
451
|
+
end
|
452
|
+
operand << ope.ord
|
435
453
|
when :u32
|
436
454
|
operand << fetch_uleb128(buf)
|
437
455
|
when :i32
|
438
456
|
operand << fetch_sleb128(buf)
|
439
|
-
when :
|
457
|
+
when :i64
|
458
|
+
operand << fetch_sleb128(buf)
|
459
|
+
when :f32
|
460
|
+
data = buf.read 4
|
461
|
+
if !data || data.size != 4
|
462
|
+
raise LoadError, "buffer too short"
|
463
|
+
end
|
464
|
+
v = data.unpack("e")[0]
|
465
|
+
raise "String#unpack is broken" if !v.is_a?(Float)
|
466
|
+
operand << v
|
467
|
+
when :f64
|
468
|
+
data = buf.read 8
|
469
|
+
if !data || data.size != 8
|
470
|
+
raise LoadError, "buffer too short"
|
471
|
+
end
|
472
|
+
v = data.unpack("E")[0]
|
473
|
+
raise "String#unpack is broken" if !v.is_a?(Float)
|
474
|
+
operand << v
|
475
|
+
when :u8_if_block # :if specific
|
440
476
|
block_ope = buf.read 1
|
441
477
|
if ! block_ope
|
442
|
-
raise "buffer too short for if"
|
478
|
+
raise LoadError, "buffer too short for if"
|
443
479
|
end
|
444
480
|
if block_ope.ord == 0x40
|
445
481
|
operand << Block.void
|
@@ -688,7 +724,7 @@ module Wardite
|
|
688
724
|
include ValueHelper
|
689
725
|
|
690
726
|
# TODO: add types of class that the stack accomodates
|
691
|
-
attr_accessor :stack #: Array[I32|I64|F32|F64
|
727
|
+
attr_accessor :stack #: Array[I32|I64|F32|F64]
|
692
728
|
|
693
729
|
attr_accessor :call_stack #: Array[Frame]
|
694
730
|
|
@@ -848,12 +884,25 @@ module Wardite
|
|
848
884
|
# @rbs return: void
|
849
885
|
def eval_insn(frame, insn)
|
850
886
|
case insn.namespace
|
887
|
+
when :convert
|
888
|
+
return Evaluator.convert_eval_insn(self, frame, insn)
|
851
889
|
when :i32
|
852
890
|
return Evaluator.i32_eval_insn(self, frame, insn)
|
891
|
+
when :i64
|
892
|
+
return Evaluator.i64_eval_insn(self, frame, insn)
|
893
|
+
when :f32
|
894
|
+
return Evaluator.f32_eval_insn(self, frame, insn)
|
895
|
+
when :f64
|
896
|
+
return Evaluator.f64_eval_insn(self, frame, insn)
|
853
897
|
end
|
854
898
|
|
855
899
|
# unmached namespace...
|
856
900
|
case insn.code
|
901
|
+
when :unreachable
|
902
|
+
raise Unreachable, "unreachable op"
|
903
|
+
when :nop
|
904
|
+
return
|
905
|
+
|
857
906
|
when :if
|
858
907
|
block = insn.operand[0]
|
859
908
|
raise EvalError, "if op without block" if !block.is_a?(Block)
|
@@ -866,78 +915,6 @@ module Wardite
|
|
866
915
|
|
867
916
|
label = Label.new(:if, next_pc, stack.size, block.result_size)
|
868
917
|
frame.labels.push(label)
|
869
|
-
|
870
|
-
when :local_get
|
871
|
-
idx = insn.operand[0]
|
872
|
-
if !idx.is_a?(Integer)
|
873
|
-
raise EvalError, "[BUG] invalid type of operand"
|
874
|
-
end
|
875
|
-
local = frame.locals[idx]
|
876
|
-
if !local
|
877
|
-
raise EvalError, "local not found"
|
878
|
-
end
|
879
|
-
stack.push(local)
|
880
|
-
when :local_set
|
881
|
-
idx = insn.operand[0]
|
882
|
-
if !idx.is_a?(Integer)
|
883
|
-
raise EvalError, "[BUG] invalid type of operand"
|
884
|
-
end
|
885
|
-
value = stack.pop
|
886
|
-
if !value
|
887
|
-
raise EvalError, "value should be pushed"
|
888
|
-
end
|
889
|
-
if value.is_a?(Block)
|
890
|
-
raise EvalError, "block value detected"
|
891
|
-
end
|
892
|
-
frame.locals[idx] = value
|
893
|
-
|
894
|
-
# when :i32_lts
|
895
|
-
# right, left = stack.pop, stack.pop
|
896
|
-
# if !right.is_a?(Integer) || !left.is_a?(Integer)
|
897
|
-
# raise EvalError, "maybe empty stack"
|
898
|
-
# end
|
899
|
-
# value = (left < right) ? 1 : 0
|
900
|
-
# stack.push(value)
|
901
|
-
# when :i32_leu
|
902
|
-
# right, left = stack.pop, stack.pop
|
903
|
-
# if !right.is_a?(Integer) || !left.is_a?(Integer)
|
904
|
-
# raise EvalError, "maybe empty stack"
|
905
|
-
# end
|
906
|
-
# value = (left >= right) ? 1 : 0
|
907
|
-
# stack.push(value)
|
908
|
-
# when :i32_add
|
909
|
-
# right, left = stack.pop, stack.pop
|
910
|
-
# if !right.is_a?(Integer) || !left.is_a?(Integer)
|
911
|
-
# raise EvalError, "maybe empty stack"
|
912
|
-
# end
|
913
|
-
# stack.push(left + right)
|
914
|
-
# when :i32_sub
|
915
|
-
# right, left = stack.pop, stack.pop
|
916
|
-
# if !right.is_a?(Integer) || !left.is_a?(Integer)
|
917
|
-
# raise EvalError, "maybe empty stack"
|
918
|
-
# end
|
919
|
-
# stack.push(left - right)
|
920
|
-
# when :i32_const
|
921
|
-
# const = insn.operand[0]
|
922
|
-
# if !const.is_a?(Integer)
|
923
|
-
# raise EvalError, "[BUG] invalid type of operand"
|
924
|
-
# end
|
925
|
-
# stack.push(const)
|
926
|
-
# when :i32_store
|
927
|
-
# _align = insn.operand[0] # TODO: alignment support?
|
928
|
-
# offset = insn.operand[1]
|
929
|
-
# raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
930
|
-
|
931
|
-
# value = stack.pop
|
932
|
-
# addr = stack.pop
|
933
|
-
# if !value.is_a?(Integer) || !addr.is_a?(Integer)
|
934
|
-
# raise EvalError, "maybe stack too short"
|
935
|
-
# end
|
936
|
-
|
937
|
-
# at = addr + offset
|
938
|
-
# data_end = at + 4 # sizeof(i32)
|
939
|
-
# memory = self.instance.store.memories[0] || raise("[BUG] no memory")
|
940
|
-
# memory.data[at...data_end] = [value].pack("I")
|
941
918
|
|
942
919
|
when :call
|
943
920
|
idx = insn.operand[0]
|
@@ -972,7 +949,63 @@ module Wardite
|
|
972
949
|
end
|
973
950
|
stack_unwind(old_frame.sp, old_frame.arity)
|
974
951
|
end
|
952
|
+
|
953
|
+
when :drop
|
954
|
+
stack.pop
|
955
|
+
|
956
|
+
when :select
|
957
|
+
cond, right, left = stack.pop, stack.pop, stack.pop
|
958
|
+
if !cond.is_a?(I32)
|
959
|
+
raise EvalError, "invalid stack for select"
|
960
|
+
end
|
961
|
+
if !right || !left
|
962
|
+
raise EvalError, "stack too short"
|
963
|
+
end
|
964
|
+
stack.push(cond.value != 0 ? left : right)
|
965
|
+
|
966
|
+
when :local_get
|
967
|
+
idx = insn.operand[0]
|
968
|
+
if !idx.is_a?(Integer)
|
969
|
+
raise EvalError, "[BUG] invalid type of operand"
|
970
|
+
end
|
971
|
+
local = frame.locals[idx]
|
972
|
+
if !local
|
973
|
+
raise EvalError, "local not found"
|
974
|
+
end
|
975
|
+
stack.push(local)
|
976
|
+
|
977
|
+
when :local_set
|
978
|
+
idx = insn.operand[0]
|
979
|
+
if !idx.is_a?(Integer)
|
980
|
+
raise EvalError, "[BUG] invalid type of operand"
|
981
|
+
end
|
982
|
+
value = stack.pop
|
983
|
+
if !value
|
984
|
+
raise EvalError, "value should be pushed"
|
985
|
+
end
|
986
|
+
frame.locals[idx] = value
|
987
|
+
|
988
|
+
when :memory_size
|
989
|
+
memory = instance.store.memories[0] || raise("[BUG] no memory")
|
990
|
+
stack.push(I32(memory.current))
|
991
|
+
|
992
|
+
when :memory_grow
|
993
|
+
delta = stack.pop
|
994
|
+
if !delta.is_a?(I32)
|
995
|
+
raise EvalError, "maybe stack too short"
|
996
|
+
end
|
997
|
+
memory = instance.store.memories[0] || raise("[BUG] no memory")
|
998
|
+
stack.push(I32(memory.grow(delta.value)))
|
999
|
+
|
1000
|
+
else
|
1001
|
+
raise "TODO! unsupported #{insn.inspect}"
|
975
1002
|
end
|
1003
|
+
|
1004
|
+
rescue => e
|
1005
|
+
require "pp"
|
1006
|
+
$stderr.puts "frame:::\n#{frame.pretty_inspect}"
|
1007
|
+
$stderr.puts "stack:::\n#{stack.pretty_inspect}"
|
1008
|
+
raise e
|
976
1009
|
end
|
977
1010
|
|
978
1011
|
# @rbs ops: Array[Op]
|
@@ -1023,7 +1056,7 @@ module Wardite
|
|
1023
1056
|
end
|
1024
1057
|
|
1025
1058
|
# @rbs finish: Integer
|
1026
|
-
# @rbs return: Array[I32|I64|F32|F64
|
1059
|
+
# @rbs return: Array[I32|I64|F32|F64]
|
1027
1060
|
def drained_stack(finish)
|
1028
1061
|
drained = stack[0...finish]
|
1029
1062
|
if ! drained
|
@@ -1179,16 +1212,32 @@ module Wardite
|
|
1179
1212
|
class Memory
|
1180
1213
|
attr_accessor :data #: String
|
1181
1214
|
|
1215
|
+
attr_accessor :current #: Integer
|
1216
|
+
|
1182
1217
|
attr_accessor :max #: Integer|nil
|
1183
1218
|
|
1184
1219
|
# @rbs min: Integer
|
1185
1220
|
# @rbs max: Integer|nil
|
1186
1221
|
# @rbs return: void
|
1187
1222
|
def initialize(min, max)
|
1188
|
-
@data = String.new("\0" * (min * 64 * 1024)
|
1223
|
+
@data = String.new("\0" * (min * 64 * 1024))
|
1224
|
+
@current = min
|
1189
1225
|
@max = max
|
1190
1226
|
end
|
1191
1227
|
|
1228
|
+
# @rbs delta: Integer
|
1229
|
+
# @rbs return: Integer
|
1230
|
+
def grow(delta)
|
1231
|
+
prev = current
|
1232
|
+
newsize = current + delta
|
1233
|
+
if max && (newsize > max)
|
1234
|
+
return -1
|
1235
|
+
end
|
1236
|
+
|
1237
|
+
@data += String.new("\0" * (delta * 64 * 1024))
|
1238
|
+
prev
|
1239
|
+
end
|
1240
|
+
|
1192
1241
|
def inspect
|
1193
1242
|
"#<Wardite::Memory initial=#{@data.size.inspect} max=#{@max.inspect} @data=#{@data[0...64].inspect}...>"
|
1194
1243
|
end
|
@@ -1317,6 +1366,7 @@ module Wardite
|
|
1317
1366
|
class LoadError < StandardError; end
|
1318
1367
|
class ArgumentError < StandardError; end
|
1319
1368
|
class EvalError < StandardError; end
|
1369
|
+
class Unreachable < StandardError; end
|
1320
1370
|
|
1321
1371
|
# @rbs path: String|nil
|
1322
1372
|
# @rbs buffer: File|StringIO|nil
|