wardite 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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 :u8_block # :if specific
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|Block]
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|Block]
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), capacity: 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