create add_code helper and some cleaning
This commit is contained in:
parent
dcbd3c7091
commit
991cc0519f
@ -28,6 +28,10 @@ module Phisol
|
|||||||
compiler.process statement
|
compiler.process statement
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# simple helper to add the given code to the current method (instance variable)
|
||||||
|
def add_code code
|
||||||
|
@method.source.add_code code
|
||||||
|
end
|
||||||
# require a (temporary) register. code must give this back with release_reg
|
# require a (temporary) register. code must give this back with release_reg
|
||||||
def use_reg type , value = nil
|
def use_reg type , value = nil
|
||||||
if @regs.empty?
|
if @regs.empty?
|
||||||
|
@ -17,13 +17,13 @@ module Phisol
|
|||||||
if(index)
|
if(index)
|
||||||
# TODO, check type @method.locals[index].type
|
# TODO, check type @method.locals[index].type
|
||||||
frame = use_reg(:Frame)
|
frame = use_reg(:Frame)
|
||||||
@method.source.add_code Register.get_slot(statement , :message , :frame , frame )
|
add_code Register.get_slot(statement , :message , :frame , frame )
|
||||||
code = Register.set_slot(statement , v , frame , index + Parfait::Frame.offset )
|
code = Register.set_slot(statement , v , frame , index + Parfait::Frame.offset )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if( code )
|
if( code )
|
||||||
#puts "addin code #{code}"
|
#puts "addin code #{code}"
|
||||||
@method.source.add_code code
|
add_code code
|
||||||
else
|
else
|
||||||
raise "must define variable #{name} before using it in #{@method.inspect}"
|
raise "must define variable #{name} before using it in #{@method.inspect}"
|
||||||
end
|
end
|
||||||
|
@ -14,25 +14,25 @@ module Phisol
|
|||||||
def on_int statement
|
def on_int statement
|
||||||
int = statement.first
|
int = statement.first
|
||||||
reg = use_reg :Integer , int
|
reg = use_reg :Integer , int
|
||||||
@method.source.add_code Register::LoadConstant.new( statement, int , reg )
|
add_code Register::LoadConstant.new( statement, int , reg )
|
||||||
return reg
|
return reg
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_true statement
|
def on_true statement
|
||||||
reg = use_reg :Boolean
|
reg = use_reg :Boolean
|
||||||
@method.source.add_code Register::LoadConstant.new( statement, true , reg )
|
add_code Register::LoadConstant.new( statement, true , reg )
|
||||||
return reg
|
return reg
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_false statement
|
def on_false statement
|
||||||
reg = use_reg :Boolean
|
reg = use_reg :Boolean
|
||||||
@method.source.add_code Register::LoadConstant.new( statement, false , reg )
|
add_code Register::LoadConstant.new( statement, false , reg )
|
||||||
return reg
|
return reg
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_nil statement
|
def on_nil statement
|
||||||
reg = use_reg :NilClass
|
reg = use_reg :NilClass
|
||||||
@method.source.add_code Register::LoadConstant.new( statement, nil , reg )
|
add_code Register::LoadConstant.new( statement, nil , reg )
|
||||||
return reg
|
return reg
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ module Phisol
|
|||||||
value = statement.first.to_sym
|
value = statement.first.to_sym
|
||||||
reg = use_reg :Word
|
reg = use_reg :Word
|
||||||
@method.source.constants << value
|
@method.source.constants << value
|
||||||
@method.source.add_code Register::LoadConstant.new( statement, value , reg )
|
add_code Register::LoadConstant.new( statement, value , reg )
|
||||||
return reg
|
return reg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,19 +9,19 @@ module Phisol
|
|||||||
reset_regs
|
reset_regs
|
||||||
#move the new message (that we need to populate to make a call) to std register
|
#move the new message (that we need to populate to make a call) to std register
|
||||||
new_message = Register.resolve_to_register(:new_message)
|
new_message = Register.resolve_to_register(:new_message)
|
||||||
@method.source.add_code Register.get_slot(@method, :message , :next_message , new_message )
|
add_code Register.get_slot(@method, :message , :next_message , new_message )
|
||||||
if receiver
|
if receiver
|
||||||
me = process( receiver.to_a.first )
|
me = process( receiver.to_a.first )
|
||||||
else
|
else
|
||||||
me = use_reg @method.for_class.name
|
me = use_reg @method.for_class.name
|
||||||
@method.source.add_code Register.get_slot(@method, :message , :receiver , me )
|
add_code Register.get_slot(@method, :message , :receiver , me )
|
||||||
end
|
end
|
||||||
# move our receiver there
|
# move our receiver there
|
||||||
@method.source.add_code Register.set_slot( statement , me , :new_message , :receiver)
|
add_code Register.set_slot( statement , me , :new_message , :receiver)
|
||||||
# load method name and set to new message (for exceptions/debug)
|
# load method name and set to new message (for exceptions/debug)
|
||||||
name_tmp = use_reg(:Word)
|
name_tmp = use_reg(:Word)
|
||||||
@method.source.add_code Register::LoadConstant.new(statement, name , name_tmp)
|
add_code Register::LoadConstant.new(statement, name , name_tmp)
|
||||||
@method.source.add_code Register.set_slot( statement , name_tmp , :new_message , :name)
|
add_code Register.set_slot( statement , name_tmp , :new_message , :name)
|
||||||
# next arguments. reset tmp regs for each and load result into new_message
|
# next arguments. reset tmp regs for each and load result into new_message
|
||||||
arguments.to_a.each_with_index do |arg , i|
|
arguments.to_a.each_with_index do |arg , i|
|
||||||
reset_regs
|
reset_regs
|
||||||
@ -30,7 +30,7 @@ module Phisol
|
|||||||
raise "Not register #{val}" unless val.is_a?(Register::RegisterValue)
|
raise "Not register #{val}" unless val.is_a?(Register::RegisterValue)
|
||||||
# which we load int the new_message at the argument's index (the one comes from c index)
|
# which we load int the new_message at the argument's index (the one comes from c index)
|
||||||
set = Register.set_slot( statement , val , :new_message , i + 1 + Parfait::Message.offset)
|
set = Register.set_slot( statement , val , :new_message , i + 1 + Parfait::Message.offset)
|
||||||
@method.source.add_code set
|
add_code set
|
||||||
end
|
end
|
||||||
|
|
||||||
# now we have to resolve the method name (+ receiver) into a callable method
|
# now we have to resolve the method name (+ receiver) into a callable method
|
||||||
@ -43,7 +43,7 @@ module Phisol
|
|||||||
ret = use_reg( method.source.return_type )
|
ret = use_reg( method.source.return_type )
|
||||||
# the effect of the method is that the NewMessage Return slot will be filled, return it
|
# the effect of the method is that the NewMessage Return slot will be filled, return it
|
||||||
# but move it into a register too
|
# but move it into a register too
|
||||||
@method.source.add_code Register.get_slot(@method, :message , :return_value , ret )
|
add_code Register.get_slot(@method, :message , :return_value , ret )
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -12,10 +12,10 @@ module Phisol
|
|||||||
index = @clazz.object_layout.variable_index(field_name)
|
index = @clazz.object_layout.variable_index(field_name)
|
||||||
raise "field access, but no such field:#{field_name} for class #{@clazz.name}" unless index
|
raise "field access, but no such field:#{field_name} for class #{@clazz.name}" unless index
|
||||||
value = use_reg(@clazz.name) #TODO incorrect, this is the self, but should be the type of variable at index
|
value = use_reg(@clazz.name) #TODO incorrect, this is the self, but should be the type of variable at index
|
||||||
@method.source.add_code Register.get_slot(statement , :message , :receiver , value )
|
add_code Register.get_slot(statement , :message , :receiver , value )
|
||||||
# reuse the register for next move
|
# reuse the register for next move
|
||||||
move = Register.get_slot(statement, value , index , value )
|
move = Register.get_slot(statement, value , index , value )
|
||||||
@method.source.add_code move
|
add_code move
|
||||||
return value
|
return value
|
||||||
when :message
|
when :message
|
||||||
#message Slot
|
#message Slot
|
||||||
|
@ -15,7 +15,7 @@ module Phisol
|
|||||||
reset_regs
|
reset_regs
|
||||||
is = process(condition)
|
is = process(condition)
|
||||||
branch_class = Object.const_get "Register::Is#{branch_type.capitalize}"
|
branch_class = Object.const_get "Register::Is#{branch_type.capitalize}"
|
||||||
@method.source.add_code branch_class.new( condition , true_block )
|
add_code branch_class.new( condition , true_block )
|
||||||
|
|
||||||
# compile the true block (as we think of it first, even it is second in sequential order)
|
# compile the true block (as we think of it first, even it is second in sequential order)
|
||||||
@method.source.current true_block
|
@method.source.current true_block
|
||||||
@ -27,7 +27,7 @@ module Phisol
|
|||||||
@method.source.current false_block
|
@method.source.current false_block
|
||||||
reset_regs
|
reset_regs
|
||||||
last = process_all(if_false).last if if_false
|
last = process_all(if_false).last if if_false
|
||||||
@method.source.add_code Register::Branch.new(statement, merge_block )
|
add_code Register::Branch.new(statement, merge_block )
|
||||||
|
|
||||||
#puts "compiled if: end"
|
#puts "compiled if: end"
|
||||||
@method.source.current merge_block
|
@method.source.current merge_block
|
||||||
|
@ -9,21 +9,21 @@ module Phisol
|
|||||||
name = statement.to_a.first
|
name = statement.to_a.first
|
||||||
if( name == :self)
|
if( name == :self)
|
||||||
ret = use_reg @clazz.name
|
ret = use_reg @clazz.name
|
||||||
@method.source.add_code Register.get_slot(statement , :message , :receiver , ret )
|
add_code Register.get_slot(statement , :message , :receiver , ret )
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
# either an argument, so it's stored in message
|
# either an argument, so it's stored in message
|
||||||
if( index = @method.has_arg(name))
|
if( index = @method.has_arg(name))
|
||||||
ret = use_reg @method.arguments[index].type
|
ret = use_reg @method.arguments[index].type
|
||||||
@method.source.add_code Register.get_slot(statement , :message , index + Parfait::Message.offset , ret )
|
add_code Register.get_slot(statement , :message , index + Parfait::Message.offset , ret )
|
||||||
return ret
|
return ret
|
||||||
else # or a local so it is in the frame
|
else # or a local so it is in the frame
|
||||||
index = @method.has_local( name )
|
index = @method.has_local( name )
|
||||||
if(index)
|
if(index)
|
||||||
frame = use_reg :Frame
|
frame = use_reg :Frame
|
||||||
@method.source.add_code Register.get_slot(statement , :message , :frame , frame )
|
add_code Register.get_slot(statement , :message , :frame , frame )
|
||||||
ret = use_reg @method.locals[index].type
|
ret = use_reg @method.locals[index].type
|
||||||
@method.source.add_code Register.get_slot(statement , frame , index + Parfait::Frame.offset , ret )
|
add_code Register.get_slot(statement , frame , index + Parfait::Frame.offset , ret )
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,7 +11,7 @@ module Phisol
|
|||||||
raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue)
|
raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue)
|
||||||
#puts "left #{left_reg}"
|
#puts "left #{left_reg}"
|
||||||
#puts "right #{right_reg}"
|
#puts "right #{right_reg}"
|
||||||
@method.source.add_code Register::OperatorInstruction.new(statement,operator,left_reg,right_reg)
|
add_code Register::OperatorInstruction.new(statement,operator,left_reg,right_reg)
|
||||||
return left_reg # though this has wrong value attached
|
return left_reg # though this has wrong value attached
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -15,12 +15,12 @@ module Phisol
|
|||||||
cond = process(condition)
|
cond = process(condition)
|
||||||
|
|
||||||
branch_class = Object.const_get "Register::Is#{branch_type.capitalize}"
|
branch_class = Object.const_get "Register::Is#{branch_type.capitalize}"
|
||||||
@method.source.add_code branch_class.new( condition , merge )
|
add_code branch_class.new( condition , merge )
|
||||||
|
|
||||||
last = process_all(statements).last
|
last = process_all(statements).last
|
||||||
|
|
||||||
# unconditionally branch to the start
|
# unconditionally branch to the start
|
||||||
@method.source.add_code Register::Branch.new(statement,start)
|
add_code Register::Branch.new(statement,start)
|
||||||
|
|
||||||
# continue execution / compiling at the merge block
|
# continue execution / compiling at the merge block
|
||||||
@method.source.current merge
|
@method.source.current merge
|
||||||
|
@ -14,12 +14,10 @@ module Register
|
|||||||
@method = method
|
@method = method
|
||||||
raise "Method is not Method, but #{method.class}" unless method == :__init__ or method.is_a?(Parfait::Method)
|
raise "Method is not Method, but #{method.class}" unless method == :__init__ or method.is_a?(Parfait::Method)
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
@branch = nil
|
|
||||||
@codes = []
|
@codes = []
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :name , :codes , :method , :position
|
attr_reader :name , :codes , :method , :position
|
||||||
attr_accessor :branch
|
|
||||||
|
|
||||||
def add_code kode
|
def add_code kode
|
||||||
@codes << kode
|
@codes << kode
|
||||||
@ -38,14 +36,6 @@ module Register
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns if this is a block that ends in a call (and thus needs local variable handling)
|
|
||||||
def call_block?
|
|
||||||
raise "called"
|
|
||||||
return false unless codes.last.is_a?(CallInstruction)
|
|
||||||
return false unless codes.last.opcode == :call
|
|
||||||
codes.dup.reverse.find{ |c| c.is_a? StackInstruction }
|
|
||||||
end
|
|
||||||
|
|
||||||
# position is what another block uses to jump to. this is determined by the assembler
|
# position is what another block uses to jump to. this is determined by the assembler
|
||||||
# the assembler allso assembles and assumes a linear instruction sequence
|
# the assembler allso assembles and assumes a linear instruction sequence
|
||||||
# Note: this will have to change for plocks and maybe anyway.
|
# Note: this will have to change for plocks and maybe anyway.
|
||||||
@ -67,24 +57,5 @@ module Register
|
|||||||
@codes.inject(0){|count , instruction| count += instruction.byte_length }
|
@codes.inject(0){|count , instruction| count += instruction.byte_length }
|
||||||
end
|
end
|
||||||
|
|
||||||
# def reachable ret = []
|
|
||||||
# add_next ret
|
|
||||||
# add_branch ret
|
|
||||||
# ret
|
|
||||||
# end
|
|
||||||
# # helper for determining reachable blocks
|
|
||||||
# def add_next ret
|
|
||||||
# return if @next.nil?
|
|
||||||
# return if ret.include? @next
|
|
||||||
# ret << @next
|
|
||||||
# @next.reachable ret
|
|
||||||
# end
|
|
||||||
# # helper for determining reachable blocks
|
|
||||||
# def add_branch ret
|
|
||||||
# return if @branch.nil?
|
|
||||||
# return if ret.include? @branch
|
|
||||||
# ret << @branch
|
|
||||||
# @branch.reachable ret
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -90,18 +90,18 @@ module Register
|
|||||||
|
|
||||||
# return a list of registers that are still in use after the given block
|
# return a list of registers that are still in use after the given block
|
||||||
# a call_site uses pushes and pops these to make them available for code after a call
|
# a call_site uses pushes and pops these to make them available for code after a call
|
||||||
def locals_at l_block
|
# def locals_at l_block
|
||||||
used =[]
|
# used =[]
|
||||||
# call assigns the return register, but as it is in l_block, it is not asked.
|
# # call assigns the return register, but as it is in l_block, it is not asked.
|
||||||
assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ]
|
# assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ]
|
||||||
l_block.reachable.each do |b|
|
# l_block.reachable.each do |b|
|
||||||
b.uses.each {|u|
|
# b.uses.each {|u|
|
||||||
(used << u) unless assigned.include?(u)
|
# (used << u) unless assigned.include?(u)
|
||||||
}
|
# }
|
||||||
assigned += b.assigns
|
# assigned += b.assigns
|
||||||
end
|
# end
|
||||||
used.uniq
|
# used.uniq
|
||||||
end
|
# end
|
||||||
|
|
||||||
# control structures need to see blocks as a graph, but they are stored as a list with implict
|
# control structures need to see blocks as a graph, but they are stored as a list with implict
|
||||||
# branches
|
# branches
|
||||||
|
Loading…
x
Reference in New Issue
Block a user