keep track of used and assigned registers for each block

This commit is contained in:
Torsten Ruger 2014-06-08 01:41:56 +03:00
parent fbcfa844de
commit b66c4157d5
4 changed files with 78 additions and 12 deletions

View File

@ -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)

View File

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

View File

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

View File

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