diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index 5f1ce2a1..b15f820c 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -106,7 +106,7 @@ module Arm end def syscall block , num - sys_and_ret = Vm::Integer.new(7) + sys_and_ret = Vm::Integer.new( Vm::Function::RETURN_REG ) block << mov( sys_and_ret , num ) block << swi( 0 ) #small todo, is this actually correct for all (that they return int) diff --git a/lib/vm/block.rb b/lib/vm/block.rb index 2865bcfd..74186655 100644 --- a/lib/vm/block.rb +++ b/lib/vm/block.rb @@ -27,13 +27,18 @@ module Vm @next = next_block @codes = [] @insert_at = self + # keeping track of register usage, left (assigns) or right (uses) + @assigns = [] + @uses = [] end - attr_reader :name , :next , :codes , :function + attr_reader :name , :next , :codes , :function , :assigns , :uses def add_code(kode) raise "alarm #{kode}" if kode.is_a? Word raise "alarm #{kode.class} #{kode}" unless kode.is_a? Code + @assigns += kode.assigns + @uses += kode.uses @insert_at.codes << kode self end diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb index e2f188f0..00922a2e 100644 --- a/lib/vm/instruction.rb +++ b/lib/vm/instruction.rb @@ -27,7 +27,23 @@ module Vm def opcode @attributes[:opcode] end - + + # returns an array of registers (RegisterUses) that this instruction uses. + # ie for r1 = r2 + r3 + # which in assembler is add r1 , r2 , r3 + # it would return [r2,r3] + # for pushes the list may be longer, whereas for a jump empty + def uses + raise "abstract called for #{self.class}" + end + # returns an array of registers (RegisterUses) that this instruction assigns to. + # ie for r1 = r2 + r3 + # which in assembler is add r1 , r2 , r3 + # it would return [r1] + # for most instruction this is one, but comparisons and jumps 0 , and pop's as long as 16 + def assigns + raise "abstract called for #{self.class}" + end def method_missing name , *args , &block return super unless (args.length <= 1) or block_given? set , attribute = name.to_s.split("set_") @@ -46,6 +62,21 @@ module Vm @first = first super(options) end + def is_push? + opcode == :push + end + def is_pop? + !is_push? + end + def uses + is_push? ? regs : [] + end + def assigns + is_pop? ? regs : [] + end + def regs + @first + end end class MemoryInstruction < Instruction def initialize result , left , right = nil , options = {} @@ -54,6 +85,14 @@ module Vm @right = right super(options) end + def uses + ret = [@left.used_register ] + ret << @right.used_register unless @right.nil? + ret + end + def assigns + [@result.used_register] + end end class LogicInstruction < Instruction # result = left op right @@ -64,30 +103,47 @@ module Vm def initialize result , left , right , options = {} @result = result @left = left - @right = right + @right = right.is_a?(Fixnum) ? IntegerConstant.new(right) : right super(options) end - end - class MathInstruction < Instruction - def initialize first , options = {} - @first = first - super(options) + def uses + ret = [] + ret << @left.used_register if @left and not @left.is_a? Constant + ret << @right.used_register if @right and not @right.is_a?(Constant) + ret + end + def assigns + [@result.used_register] end end class CompareInstruction < Instruction def initialize left , right , options = {} @left = left - @right = right + @right = right.is_a?(Fixnum) ? IntegerConstant.new(right) : right super(options) end + def uses + ret = [@left.used_register ] + ret << @right.used_register unless @right.is_a? Constant + ret + end + def assigns + [] + end end class MoveInstruction < Instruction def initialize to , from , options = {} @to = to - @from = from + @from = from.is_a?(Fixnum) ? IntegerConstant.new(from) : from raise "move must have from set #{inspect}" unless from super(options) end + def uses + @from.is_a?(Constant) ? [] : [@from.used_register] + end + def assigns + [@to.used_register] + end end class CallInstruction < Instruction def initialize first , options = {} @@ -103,5 +159,11 @@ module Vm @attributes[:opcode] = :call end end + def uses + [] + end + def assigns + [] + end end end diff --git a/test/fragments/test_recursive_fibo.rb b/test/fragments/test_recursive_fibo.rb index 44d27616..4418c197 100644 --- a/test/fragments/test_recursive_fibo.rb +++ b/test/fragments/test_recursive_fibo.rb @@ -11,7 +11,6 @@ def fibonaccir( n ) else a = fibonaccir( n - 1 ) b = fibonaccir( n - 2 ) - c = fibonaccir( n - 3 ) return a + b end end