change platform to return register names

not just the number of them
also adds protocol to map registers
(like message to r0 , or syscalls)
This commit is contained in:
Torsten 2020-03-19 18:18:22 +02:00
parent f13e6dcf57
commit 0137056b89
4 changed files with 50 additions and 17 deletions

View File

@ -8,17 +8,19 @@ module Risc
# return the translator instance that traslates risc intructions into # return the translator instance that traslates risc intructions into
# platform specific ones # platform specific ones
def translator def translator
raise "not implemented" raise "not implemented in #{self.class}"
end end
# return an integer where the binary is loaded # return an integer where the binary is loaded
def loaded_at def loaded_at
raise "not implemented" raise "not implemented in #{self.class}"
end end
# return the number of registers the platform supports # return an array of register names that should be used by the allocator
def num_registers # does not include :message
raise "not implemented" # could be in interpreter and arm, but here for now
def register_names
(1 ... 16).collect{|i| "r#{i}".to_sym }
end end
# return the Allocator for the platform # return the Allocator for the platform
@ -30,6 +32,19 @@ module Risc
StandardAllocator.new(compiler , self ) StandardAllocator.new(compiler , self )
end end
def assign_reg?(name)
case name
when :message
:r0
when :syscall_1
:r0
when :syscall_2
:r1
else
nil
end
end
# Factory method to create a Platform object according to the platform # Factory method to create a Platform object according to the platform
# string given. # string given.
# Currently only "Arm" and "Interpreter" # Currently only "Arm" and "Interpreter"

View File

@ -14,7 +14,7 @@ module Risc
@platform = platform @platform = platform
@used_regs = {} @used_regs = {}
@release_points = Hash.new {|hash , key | hash[key] = [] } @release_points = Hash.new {|hash , key | hash[key] = [] }
@reg_names = (0 ... platform.num_registers).collect{|i| "r#{i}".to_sym } @reg_names = platform.register_names
end end
attr_reader :used_regs , :compiler , :platform , :reg_names attr_reader :used_regs , :compiler , :platform , :reg_names
@ -49,9 +49,11 @@ module Risc
def assign(instruction) def assign(instruction)
names = instruction.register_names names = instruction.register_names
names.each do |for_name| #puts "AT #{instruction}"
new_reg = get_reg(for_name) names.each do |ssa_name|
new_reg = get_reg(ssa_name)
# swap name out # swap name out
#puts "Assign #{new_reg} for #{ssa_name}"
end end
names names
end end
@ -76,10 +78,6 @@ module Risc
released released
end end
def used_regs_empty?
@used_regs.empty?
end
# use the given reg (first) parameter and mark it as assigned to # use the given reg (first) parameter and mark it as assigned to
# it's ssa form, the second parameter. # it's ssa form, the second parameter.
# forward check is trivial, and reverse_used provides reverse check # forward check is trivial, and reverse_used provides reverse check
@ -88,6 +86,7 @@ module Risc
raise "Stupid error #{reg}" unless reg.is_a?(Symbol) raise "Stupid error #{reg}" unless reg.is_a?(Symbol)
#puts "Using #{reg} for #{ssa_name}" #puts "Using #{reg} for #{ssa_name}"
@used_regs[reg] = ssa_name @used_regs[reg] = ssa_name
reg
end end
# Check whether a register has been assigned to the given ssa form given. # Check whether a register has been assigned to the given ssa form given.
@ -104,6 +103,12 @@ module Risc
def get_reg(ssa_name) def get_reg(ssa_name)
name = reverse_used( ssa_name ) name = reverse_used( ssa_name )
return name if name return name if name
get_next_free(ssa_name)
end
def get_next_free(ssa_name)
reg = platform.assign_reg?( ssa_name )
return use_reg(reg , ssa_name) if reg
@reg_names.each do |name| @reg_names.each do |name|
return use_reg(name , ssa_name) unless @used_regs.has_key?(name) return use_reg(name , ssa_name) unless @used_regs.has_key?(name)
end end

View File

@ -13,8 +13,24 @@ module Risc
assert_raises{ Platform.for("NotArm")} assert_raises{ Platform.for("NotArm")}
end end
def test_allocate def test_allocate
allocator = Platform.new.allocator(FakeCompiler.new) allocator = Platform.for("Interpreter").allocator(FakeCompiler.new)
assert_equal FakeCompiler , allocator.compiler.class assert_equal FakeCompiler , allocator.compiler.class
end end
def test_map_message
assert_equal :r0 , Platform.new.assign_reg?(:message)
end
def test_map_sys
assert_equal :r0 , Platform.new.assign_reg?(:syscall_1)
end
def test_map_id
assert_nil Platform.new.assign_reg?(:id_some_id)
end
def test_names_len
assert_equal 15 , Platform.new.register_names.length
end
def test_names_r
assert_equal "r" , Platform.new.register_names.first.to_s[0]
assert_equal "r" , Platform.new.register_names.last.to_s[0]
end
end end
end end

View File

@ -13,11 +13,8 @@ module Risc
def test_regs def test_regs
assert_equal Hash , @allocator.used_regs.class assert_equal Hash , @allocator.used_regs.class
end end
def test_empty
assert @allocator.used_regs_empty?
end
def test_reg_names def test_reg_names
assert_equal 16 , @allocator.reg_names.length assert_equal 15 , @allocator.reg_names.length
end end
def test_compiler def test_compiler
assert_equal CallableCompiler , @allocator.compiler.class assert_equal CallableCompiler , @allocator.compiler.class