moving to SA register names (wip)

starting to implement register allocation by first creating SA
Single Assignment means a register is only every assigned a value once. Hence for any operation involving another register, a new register is created.
We do this with a naming scheme for the registers in dot notation (as it would be in c) which means 2 registers with the same name, should have the same contents. This does not apply to temporaries, but that is another day.
Starting WIP now, and will create many red commits before merging when green.
This commit is contained in:
Torsten 2020-02-29 17:16:52 +02:00
parent f2c853821c
commit 0ce14bdfd1
4 changed files with 36 additions and 29 deletions

View File

@ -22,9 +22,8 @@ module Risc
def initialize( reg , type , extra = {}) def initialize( reg , type , extra = {})
extra = {} unless extra extra = {} unless extra
raise "Not Hash #{extra}" unless extra.is_a?(Hash) raise "Not Hash #{extra}" unless extra.is_a?(Hash)
raise "not reg #{reg}" unless self.class.look_like_reg( reg )
raise "No type " unless type
type = Parfait.object_space.get_type_by_class_name(type) if type.is_a?(Symbol) type = Parfait.object_space.get_type_by_class_name(type) if type.is_a?(Symbol)
raise "No type #{reg}" unless type
@type = type @type = type
@symbol = reg @symbol = reg
@extra = extra @extra = extra
@ -61,9 +60,13 @@ module Risc
return index return index
end end
def type_at(index)
type.type_at(index)
end
# reduce integer to fixnum and add instruction if builder is used # reduce integer to fixnum and add instruction if builder is used
def reduce_int def reduce_int
reduce = Risc.slot_to_reg( "int -> fix" , self , Parfait::Integer.integer_index , self) reduce = Risc::SlotToReg.new( "int -> fix" , self , Parfait::Integer.integer_index , self)
builder.add_code(reduce) if builder builder.add_code(reduce) if builder
reduce reduce
end end
@ -77,11 +80,10 @@ module Risc
def get_new_left(slot, compiler) def get_new_left(slot, compiler)
new_type = extra["type_#{slot}".to_sym] new_type = extra["type_#{slot}".to_sym]
new_type , extra = compiler.slot_type(slot , type) unless new_type new_type , extra = compiler.slot_type(slot , type) unless new_type
if( @symbol == :r0 ) new_name = "#{@symbol}.#{slot}"
new_left = compiler.use_reg( new_type , extra) raise "no #{self}" if RegisterValue.look_like_reg(@symbol)
else puts "New name #{new_name}"
new_left = RegisterValue.new( @symbol , new_type , extra) new_left = RegisterValue.new( new_name.to_sym , new_type , extra)
end
new_left new_left
end end
@ -135,12 +137,12 @@ module Risc
def <<( right ) def <<( right )
case right case right
when Symbol when Symbol
ins = Risc.load_constant("#{right.class} to #{self.type}" , right , self) ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
when Parfait::Object when Parfait::Object
ins = Risc.load_constant("#{right.class} to #{self.type}" , right , self) ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
builder.compiler.add_constant(right) if builder builder.compiler.add_constant(right) if builder
when Label when Label
ins = Risc.load_constant("#{right.class} to #{self.type}" , right , self) ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
builder.compiler.add_constant(right.address) if builder builder.compiler.add_constant(right.address) if builder
when ::Integer when ::Integer
ins = Risc.load_data("#{right.class} to #{self.type}" , right , self) ins = Risc.load_data("#{right.class} to #{self.type}" , right , self)
@ -218,7 +220,10 @@ module Risc
def self.message_reg def self.message_reg
RegisterValue.new :r0 , :Message RegisterValue.new :r0 , :Message
end end
# a named version of the message register, called :message
def self.message_named_reg
RegisterValue.new :message , :Message
end
# The register we use to store the new message object is :r3 # The register we use to store the new message object is :r3
# The new message is the one being built, to be sent # The new message is the one being built, to be sent
def self.new_message_reg def self.new_message_reg

View File

@ -11,18 +11,18 @@ module Risc
def setup def setup
Parfait.boot!(Parfait.default_test_options) Parfait.boot!(Parfait.default_test_options)
@r0 = RegisterValue.new(:r0 , :Message) @r0 = RegisterValue.new(:message , :Message)
@r1 = RegisterValue.new(:r1 , :Space) @r1 = RegisterValue.new(:id_1234 , :Space)
@r2 = RegisterValue.new(:r1 , :Factory) @r2 = RegisterValue.new(:id_1256 , :Factory)
end end
def test_class_name_type def test_class_name_type
assert_equal :Message , @r0.class_name assert_equal :Message , @r0.class_name
end end
def test_class_name_fix def test_class_name_fix
assert_equal :fixnum , RegisterValue.new(:r0 , :fixnum).class_name assert_equal :Integer , RegisterValue.new(:id_234 , :Integer).class_name
end end
def test_r0 def test_r0
assert_equal :r0 , @r0.symbol assert_equal :message , @r0.symbol
end end
def test_load_space def test_load_space
move = @r0 << Parfait.object_space move = @r0 << Parfait.object_space
@ -72,12 +72,12 @@ module Risc
assert_equal @r0 , instr.register assert_equal @r0 , instr.register
assert_equal 1 , instr.index assert_equal 1 , instr.index
end end
def test_slot_to_reg def est_slot_to_reg
instr = @r0 << @r2[:next_object] instr = @r0 << @r2[:next_object]
assert_equal SlotToReg , instr.class assert_equal SlotToReg , instr.class
assert_equal @r1 , instr.array
assert_equal @r0 , instr.register assert_equal @r0 , instr.register
assert_equal 2 , instr.index assert_equal 2 , instr.index
assert_equal @r1 , instr.array
end end
def test_reg_to_byte def test_reg_to_byte
instr = @r1[1] <= @r0 instr = @r1[1] <= @r0
@ -86,12 +86,12 @@ module Risc
assert_equal @r0 , instr.register assert_equal @r0 , instr.register
assert_equal 1 , instr.index assert_equal 1 , instr.index
end end
def test_reg_to_slot def est_reg_to_slot
instr = @r2[:next_object] << @r0 instr = @r2[:next_object] << @r0
assert_equal RegToSlot , instr.class assert_equal RegToSlot , instr.class
assert_equal @r1 , instr.array
assert_equal @r0 , instr.register assert_equal @r0 , instr.register
assert_equal 2 , instr.index assert_equal 2 , instr.index
assert_equal @r1 , instr.array
end end
end end
end end

View File

@ -5,8 +5,8 @@ module Risc
def setup def setup
Parfait.boot!(Parfait.default_test_options) Parfait.boot!(Parfait.default_test_options)
@r0 = RegisterValue.new(:r0 , :Message) @r0 = RegisterValue.new(:message , :Message)
@r1 = RegisterValue.new(:r1 , :Space) @r1 = RegisterValue.new(:id_1234 , :Space)
@compiler = Risc.test_compiler @compiler = Risc.test_compiler
end end
@ -28,16 +28,16 @@ module Risc
assert @r0.get_new_left(:caller , @compiler).extra.empty? assert @r0.get_new_left(:caller , @compiler).extra.empty?
end end
def test_get_new_left_0_reg def test_get_new_left_0_reg
assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol assert_equal :"message.caller" , @r0.get_new_left(:caller , @compiler).symbol
end end
def test_get_new_left_1 def test_get_new_left_1
assert_equal RegisterValue , @r0.get_new_left(:caller , @compiler).class assert_equal RegisterValue , @r0.get_new_left(:caller , @compiler).class
end end
def test_get_new_left_1_reg def test_get_new_left_1_reg
assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol assert_equal :"id_1234.classes" , @r1.get_new_left(:classes , @compiler).symbol
end end
def test_get_left_uses_extra def test_get_left_uses_extra
@r1 = RegisterValue.new(:r1 , :Space , type_arguments: @r0.type) @r1 = RegisterValue.new(:message , :Space , type_arguments: @r0.type)
# works with nil as compiler, because extra is used # works with nil as compiler, because extra is used
assert_equal :Message , @r1.get_new_left(:arguments , nil).type.class_name assert_equal :Message , @r1.get_new_left(:arguments , nil).type.class_name
end end

View File

@ -27,12 +27,14 @@ module Risc
def resolve_type(name) def resolve_type(name)
Parfait.object_space.types.values.first Parfait.object_space.types.values.first
end end
def use_reg(type , extra = {})
RegisterValue.new(:r1 , type)
end
def reset_regs def reset_regs
end end
def add_constant(c) def add_constant(c)
end end
end end
class RegisterValue
def is_object?
@symbol.to_s.start_with?("id_")
end
end
end end