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:
parent
f2c853821c
commit
0ce14bdfd1
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user