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.
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