diff --git a/lib/risc/standard_allocator.rb b/lib/risc/standard_allocator.rb index ff38a331..2d70c583 100644 --- a/lib/risc/standard_allocator.rb +++ b/lib/risc/standard_allocator.rb @@ -14,7 +14,7 @@ module Risc @platform = platform @used_regs = {} @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 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 # regs and frees regs according to live ranges 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 # determines when registers can be freed # # this is done by walking the instructions backwards and saving the first # 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 # have been marked already def walk_and_mark(instruction) @@ -53,26 +65,23 @@ module Risc @used_regs.empty? end - def use_reg(reg) - raise "not reg #{reg.class}" unless reg.is_a?(RegisterValue) - @used_regs[reg.symbol] = reg + def use_reg(reg , for_name) + reg = reg.symbol if reg.is_a?(RegisterValue) + raise "Stupid error #{reg}" unless reg.is_a?(Symbol) + puts "Using #{reg} for #{for_name}" + @used_regs[reg] = for_name end + # if a register has been assigned to the given name, return that # - def release_reg(reg) - @used_regs.pop - end - - def clear_used_regs - @used_regs.clear - end - - #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) + # otherwise find the first free register by going through the available names + # and checking if it is used + def get_reg(for_name) + @used_regs.each {|reg,name| return reg if for_name == name } + @reg_names.each do |name| + return use_reg(name , for_name) unless @used_regs.has_key?(name) + end + raise "No more registers #{self}" end # releasing a register (accuired by use_reg) makes it available for use again diff --git a/test/risc/test_standard_allocator.rb b/test/risc/test_standard_allocator.rb index 16fbb5af..8ce80ca0 100644 --- a/test/risc/test_standard_allocator.rb +++ b/test/risc/test_standard_allocator.rb @@ -27,29 +27,24 @@ module Risc assert_equal Arm::ArmPlatform , @allocator.platform.class end def test_allocate_runs - assert @allocator.allocate_regs + assert_nil @allocator.allocate_regs end def test_live - live = @allocator.determine_liveness + live = @allocator.walk_and_mark(@allocator.compiler.risc_instructions) assert_equal 0 , live.length end 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 def test_add_fail assert_raises{ @allocator.use_reg(1)} end def test_release_reg - @allocator.use_reg(tmp_reg) - assert_equal RegisterValue , @allocator.release_reg(tmp_reg).class - end - def test_remove_symbol - @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? + @allocator.use_reg(:r1 , :some) + assert @allocator.used_regs.include?(:r1) + assert_equal Symbol , @allocator.release_reg(tmp_reg).class + assert !@allocator.used_regs.include?(:r1) end end end diff --git a/test/risc/test_standard_allocator1.rb b/test/risc/test_standard_allocator1.rb index c34d8293..b65116e7 100644 --- a/test/risc/test_standard_allocator1.rb +++ b/test/risc/test_standard_allocator1.rb @@ -12,10 +12,11 @@ module Risc assert_equal :main , @compiler.callable.name end def test_allocate_runs - assert @allocator.allocate_regs + assert_nil @allocator.allocate_regs + assert_equal 10 , @allocator.used_regs.length end def test_live_length - live = @allocator.determine_liveness + live = @allocator.walk_and_mark(@compiler.risc_instructions) assert_equal 10 , live.length end end