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