start with register assigning
have to find a way to set them next
This commit is contained in:
parent
4f290ee246
commit
3f131a4018
@ -14,7 +14,7 @@ module Risc
|
|||||||
@platform = platform
|
@platform = platform
|
||||||
@used_regs = {}
|
@used_regs = {}
|
||||||
@release_points = Hash.new( [] )
|
@release_points = Hash.new( [] )
|
||||||
@reg_names = (0 ... platform.num_registers).collect{|i| "r#{i-1}".to_sym }
|
@reg_names = (0 ... platform.num_registers).collect{|i| "r#{i}".to_sym }
|
||||||
end
|
end
|
||||||
attr_reader :used_regs , :compiler , :platform , :reg_names
|
attr_reader :used_regs , :compiler , :platform , :reg_names
|
||||||
|
|
||||||
@ -24,17 +24,29 @@ module Risc
|
|||||||
# Ie on arm register names are r0 .. . r15 , so it keeps a list of unused
|
# Ie on arm register names are r0 .. . r15 , so it keeps a list of unused
|
||||||
# regs and frees regs according to live ranges
|
# regs and frees regs according to live ranges
|
||||||
def allocate_regs
|
def allocate_regs
|
||||||
determine_liveness
|
walk_and_mark(@compiler.risc_instructions)
|
||||||
|
pointer = @compiler.risc_instructions
|
||||||
|
while(pointer)
|
||||||
|
names = assign(pointer)
|
||||||
|
names.each {|name| release_reg(name)}
|
||||||
|
pointer = pointer.next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign(instruction)
|
||||||
|
names = instruction.register_names
|
||||||
|
names.each do |for_name|
|
||||||
|
new_reg = get_reg(for_name)
|
||||||
|
# swap name out
|
||||||
|
end
|
||||||
|
names
|
||||||
end
|
end
|
||||||
|
|
||||||
# determines when registers can be freed
|
# determines when registers can be freed
|
||||||
#
|
#
|
||||||
# this is done by walking the instructions backwards and saving the first
|
# this is done by walking the instructions backwards and saving the first
|
||||||
# occurence of a register name. (The last, as we walk backwards)
|
# occurence of a register name. (The last, as we walk backwards)
|
||||||
def determine_liveness
|
#
|
||||||
walk_and_mark(@compiler.risc_instructions)
|
|
||||||
end
|
|
||||||
|
|
||||||
# First walk down, and on the way up mark register occurences, unless they
|
# First walk down, and on the way up mark register occurences, unless they
|
||||||
# have been marked already
|
# have been marked already
|
||||||
def walk_and_mark(instruction)
|
def walk_and_mark(instruction)
|
||||||
@ -53,26 +65,23 @@ module Risc
|
|||||||
@used_regs.empty?
|
@used_regs.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def use_reg(reg)
|
def use_reg(reg , for_name)
|
||||||
raise "not reg #{reg.class}" unless reg.is_a?(RegisterValue)
|
reg = reg.symbol if reg.is_a?(RegisterValue)
|
||||||
@used_regs[reg.symbol] = reg
|
raise "Stupid error #{reg}" unless reg.is_a?(Symbol)
|
||||||
|
puts "Using #{reg} for #{for_name}"
|
||||||
|
@used_regs[reg] = for_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# if a register has been assigned to the given name, return that
|
||||||
#
|
#
|
||||||
def release_reg(reg)
|
# otherwise find the first free register by going through the available names
|
||||||
@used_regs.pop
|
# and checking if it is used
|
||||||
end
|
def get_reg(for_name)
|
||||||
|
@used_regs.each {|reg,name| return reg if for_name == name }
|
||||||
def clear_used_regs
|
@reg_names.each do |name|
|
||||||
@used_regs.clear
|
return use_reg(name , for_name) unless @used_regs.has_key?(name)
|
||||||
end
|
end
|
||||||
|
raise "No more registers #{self}"
|
||||||
#helper method to calculate with register symbols
|
|
||||||
def next_reg_use( type , extra = {} )
|
|
||||||
int = @symbol[1,3].to_i
|
|
||||||
raise "No more registers #{self}" if int > 11
|
|
||||||
sym = "r#{int + 1}".to_sym
|
|
||||||
RegisterValue.new( sym , type, extra)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# releasing a register (accuired by use_reg) makes it available for use again
|
# releasing a register (accuired by use_reg) makes it available for use again
|
||||||
|
@ -27,29 +27,24 @@ module Risc
|
|||||||
assert_equal Arm::ArmPlatform , @allocator.platform.class
|
assert_equal Arm::ArmPlatform , @allocator.platform.class
|
||||||
end
|
end
|
||||||
def test_allocate_runs
|
def test_allocate_runs
|
||||||
assert @allocator.allocate_regs
|
assert_nil @allocator.allocate_regs
|
||||||
end
|
end
|
||||||
def test_live
|
def test_live
|
||||||
live = @allocator.determine_liveness
|
live = @allocator.walk_and_mark(@allocator.compiler.risc_instructions)
|
||||||
assert_equal 0 , live.length
|
assert_equal 0 , live.length
|
||||||
end
|
end
|
||||||
def test_add_ok
|
def test_add_ok
|
||||||
assert_equal RegisterValue, @allocator.use_reg(tmp_reg).class
|
assert_equal Symbol, @allocator.use_reg(:r1, :some).class
|
||||||
|
assert @allocator.used_regs.include?(:r1)
|
||||||
end
|
end
|
||||||
def test_add_fail
|
def test_add_fail
|
||||||
assert_raises{ @allocator.use_reg(1)}
|
assert_raises{ @allocator.use_reg(1)}
|
||||||
end
|
end
|
||||||
def test_release_reg
|
def test_release_reg
|
||||||
@allocator.use_reg(tmp_reg)
|
@allocator.use_reg(:r1 , :some)
|
||||||
assert_equal RegisterValue , @allocator.release_reg(tmp_reg).class
|
assert @allocator.used_regs.include?(:r1)
|
||||||
end
|
assert_equal Symbol , @allocator.release_reg(tmp_reg).class
|
||||||
def test_remove_symbol
|
assert !@allocator.used_regs.include?(:r1)
|
||||||
@allocator.use_reg(tmp_reg)
|
|
||||||
assert_equal RegisterValue , @allocator.release_reg(tmp_reg.symbol).class
|
|
||||||
end
|
|
||||||
def test_clear
|
|
||||||
@allocator.clear_used_regs
|
|
||||||
assert @allocator.used_regs_empty?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -12,10 +12,11 @@ module Risc
|
|||||||
assert_equal :main , @compiler.callable.name
|
assert_equal :main , @compiler.callable.name
|
||||||
end
|
end
|
||||||
def test_allocate_runs
|
def test_allocate_runs
|
||||||
assert @allocator.allocate_regs
|
assert_nil @allocator.allocate_regs
|
||||||
|
assert_equal 10 , @allocator.used_regs.length
|
||||||
end
|
end
|
||||||
def test_live_length
|
def test_live_length
|
||||||
live = @allocator.determine_liveness
|
live = @allocator.walk_and_mark(@compiler.risc_instructions)
|
||||||
assert_equal 10 , live.length
|
assert_equal 10 , live.length
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user