diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index ebbe5cf3..698bc9b7 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -132,8 +132,8 @@ module Arm def syscall block , num # This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up - sys = Vm::Integer.new( Vm::RegisterUse.new(:r7) ) - ret = Vm::Integer.new( Vm::RegisterUse.new(RETURN_REG) ) + sys = Vm::Integer.new( Vm::RegisterReference.new(:r7) ) + ret = Vm::Integer.new( Vm::RegisterReference.new(RETURN_REG) ) block.do_add mov( sys , num ) block.do_add swi( 0 ) #todo should write type into r1 according to syscall diff --git a/lib/ast/function_expression.rb b/lib/ast/function_expression.rb index 7ced017d..f406fbd0 100644 --- a/lib/ast/function_expression.rb +++ b/lib/ast/function_expression.rb @@ -6,7 +6,7 @@ module Ast locals = {} params.each_with_index do |param , index| arg = param.name - register = Vm::RegisterUse.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1) + register = Vm::RegisterReference.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1) arg_value = Vm::Integer.new(register) locals[arg] = arg_value args << arg_value diff --git a/lib/vm/function.rb b/lib/vm/function.rb index 4efb8c03..3c4f2ccb 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -40,7 +40,7 @@ module Vm @args = Array.new(args.length) args.each_with_index do |arg , i| - shouldda = RegisterUse.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1) + shouldda = RegisterReference.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1) if arg.is_a?(Value) @args[i] = arg raise "arg #{i} in non std register #{arg.used_register}, expecting #{shouldda}" unless shouldda == arg.used_register @@ -88,7 +88,7 @@ module Vm def locals_at l_block used =[] # call assigns the return register, but as it is in l_block, it is not asked. - assigned = [ RegisterUse.new(Vm::RegisterMachine.instance.return_register) ] + assigned = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ] l_block.reachable.each do |b| b.uses.each {|u| (used << u) unless assigned.include?(u) diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb index f3a6a2fa..13bbbdde 100644 --- a/lib/vm/instruction.rb +++ b/lib/vm/instruction.rb @@ -36,7 +36,7 @@ module Vm atts.delete(:condition_code) if atts[:condition_code] == :al atts.empty? ? "" : ", #{atts}" end - # returns an array of registers (RegisterUses) that this instruction uses. + # returns an array of registers (RegisterReferences) that this instruction uses. # ie for r1 = r2 + r3 # which in assembler is add r1 , r2 , r3 # it would return [r2,r3] @@ -44,7 +44,7 @@ module Vm def uses raise "abstract called for #{self.class}" end - # returns an array of registers (RegisterUses) that this instruction assigns to. + # returns an array of registers (RegisterReferences) that this instruction assigns to. # ie for r1 = r2 + r3 # which in assembler is add r1 , r2 , r3 # it would return [r1] @@ -191,7 +191,7 @@ module Vm end def assigns if opcode == :call - [RegisterUse.new(RegisterMachine.instance.return_register)] + [RegisterReference.new(RegisterMachine.instance.return_register)] else [] end diff --git a/lib/vm/register_reference.rb b/lib/vm/register_reference.rb new file mode 100644 index 00000000..7cf49df0 --- /dev/null +++ b/lib/vm/register_reference.rb @@ -0,0 +1,33 @@ +module Vm + + # RegisterReference is not the name for a register, "only" for a certain use of it. + # In a way it is like a variable name, a storage location. The location is a register off course, + # but which register can be changed, and _all_ instructions sharing the RegisterReference then use that register + # In other words a simple level of indirection, or change from value to reference sematics. + + class RegisterReference + attr_accessor :symbol + def initialize r + if( r.is_a? Fixnum) + r = "r#{r}".to_sym + end + raise "wrong type for register init #{r}" unless r.is_a? Symbol + raise "double r #{r}" if r == :rr1 + @symbol = r + end + + def == other + return false if other.nil? + return false if other.class != RegisterReference + symbol == other.symbol + end + + #helper method to calculate with register symbols + def next_reg_use by = 1 + int = @symbol[1,3].to_i + sym = "r#{int + by}".to_sym + RegisterReference.new( sym ) + end + end + +end diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 0c8a35a8..56cb9247 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -1,4 +1,5 @@ require_relative "code" +require_relative "register_reference" module Vm @@ -7,12 +8,7 @@ module Vm # The oprerations on values is what makes a machine do things. Operations are captured as # subclasses of Instruction and saved to Blocks - # Values are immutable! (that's why they are called values) - # Operations on values _always_ produce new values (conceptionally) - # Values are a way to reason about (create/validate) instructions. - # In fact a linked lists of values is created by invoking instructions - # the linked list goes from value to instruction to value, backwards # Word Values are what fits in a register. Derived classes # Float, Reference , Integer(s) must fit the same registers @@ -48,35 +44,6 @@ module Vm end end - # RegisterUSe is _not_ the name for a register, "only" for a certain use of it. - # In a way it is like a variable name, a storage location. The location is a register off course, - # but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register - # In other words a simple level of indirection, or change from value to reference sematics. - class RegisterUse - attr_accessor :symbol - def initialize r - if( r.is_a? Fixnum) - r = "r#{r}".to_sym - end - raise "wrong type for register init #{r}" unless r.is_a? Symbol - raise "double r #{r}" if r == :rr1 - @symbol = r - end - - def == other - return false if other.nil? - return false if other.class != RegisterUse - symbol == other.symbol - end - - #helper method to calculate with register symbols - def next_reg_use by = 1 - int = @symbol[1,3].to_i - sym = "r#{int + by}".to_sym - RegisterUse.new( sym ) - end - end - # This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base # Must be promoted to A Word-Value to to anything makes is_a chaecking easier # remembering that our oo machine is typed, no overloading or stuff @@ -94,10 +61,10 @@ module Vm inspect end def initialize reg - if reg.is_a? RegisterUse + if reg.is_a? RegisterReference @used_register = reg else - @used_register = RegisterUse.new(reg) + @used_register = RegisterReference.new(reg) end end def length diff --git a/test/fragments/test_if.rb b/test/fragments/test_if.rb index f4d01642..4a699faa 100644 --- a/test/fragments/test_if.rb +++ b/test/fragments/test_if.rb @@ -15,7 +15,7 @@ end itest(20) HERE - @should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x44,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x4,0x0,0x0,0xeb,0x2,0x0,0x0,0xea,0x3c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x0,0x0,0x0,0xeb,0x0,0x80,0xbd,0xe8] + @should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x34,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd4,0xff,0xff,0xeb,0x2,0x0,0x0,0xea,0x2c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd0,0xff,0xff,0xeb,0x0,0x80,0xbd,0xe8] @output = "else " @target = [:Object , :itest] parse diff --git a/test/fragments/test_putint.rb b/test/fragments/test_putint.rb index e7d055ee..366a57d9 100644 --- a/test/fragments/test_putint.rb +++ b/test/fragments/test_putint.rb @@ -7,7 +7,7 @@ class TestPutint < MiniTest::Test @string_input = <