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
|
||||
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
|
||||
def use_reg type , value = nil
|
||||
if @regs.empty?
|
||||
|
@ -17,13 +17,13 @@ module Phisol
|
||||
if(index)
|
||||
# TODO, check type @method.locals[index].type
|
||||
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 )
|
||||
end
|
||||
end
|
||||
if( code )
|
||||
#puts "addin code #{code}"
|
||||
@method.source.add_code code
|
||||
add_code code
|
||||
else
|
||||
raise "must define variable #{name} before using it in #{@method.inspect}"
|
||||
end
|
||||
|
@ -14,25 +14,25 @@ module Phisol
|
||||
def on_int statement
|
||||
int = statement.first
|
||||
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
|
||||
end
|
||||
|
||||
def on_true statement
|
||||
reg = use_reg :Boolean
|
||||
@method.source.add_code Register::LoadConstant.new( statement, true , reg )
|
||||
add_code Register::LoadConstant.new( statement, true , reg )
|
||||
return reg
|
||||
end
|
||||
|
||||
def on_false statement
|
||||
reg = use_reg :Boolean
|
||||
@method.source.add_code Register::LoadConstant.new( statement, false , reg )
|
||||
add_code Register::LoadConstant.new( statement, false , reg )
|
||||
return reg
|
||||
end
|
||||
|
||||
def on_nil statement
|
||||
reg = use_reg :NilClass
|
||||
@method.source.add_code Register::LoadConstant.new( statement, nil , reg )
|
||||
add_code Register::LoadConstant.new( statement, nil , reg )
|
||||
return reg
|
||||
end
|
||||
|
||||
@ -40,7 +40,7 @@ module Phisol
|
||||
value = statement.first.to_sym
|
||||
reg = use_reg :Word
|
||||
@method.source.constants << value
|
||||
@method.source.add_code Register::LoadConstant.new( statement, value , reg )
|
||||
add_code Register::LoadConstant.new( statement, value , reg )
|
||||
return reg
|
||||
end
|
||||
end
|
||||
|
@ -9,19 +9,19 @@ module Phisol
|
||||
reset_regs
|
||||
#move the new message (that we need to populate to make a call) to std register
|
||||
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
|
||||
me = process( receiver.to_a.first )
|
||||
else
|
||||
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
|
||||
# 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)
|
||||
name_tmp = use_reg(:Word)
|
||||
@method.source.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::LoadConstant.new(statement, name , name_tmp)
|
||||
add_code Register.set_slot( statement , name_tmp , :new_message , :name)
|
||||
# next arguments. reset tmp regs for each and load result into new_message
|
||||
arguments.to_a.each_with_index do |arg , i|
|
||||
reset_regs
|
||||
@ -30,7 +30,7 @@ module Phisol
|
||||
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)
|
||||
set = Register.set_slot( statement , val , :new_message , i + 1 + Parfait::Message.offset)
|
||||
@method.source.add_code set
|
||||
add_code set
|
||||
end
|
||||
|
||||
# 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 )
|
||||
# the effect of the method is that the NewMessage Return slot will be filled, return it
|
||||
# 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
|
||||
end
|
||||
end
|
||||
|
@ -12,10 +12,10 @@ module Phisol
|
||||
index = @clazz.object_layout.variable_index(field_name)
|
||||
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
|
||||
@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
|
||||
move = Register.get_slot(statement, value , index , value )
|
||||
@method.source.add_code move
|
||||
add_code move
|
||||
return value
|
||||
when :message
|
||||
#message Slot
|
||||
|
@ -15,7 +15,7 @@ module Phisol
|
||||
reset_regs
|
||||
is = process(condition)
|
||||
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)
|
||||
@method.source.current true_block
|
||||
@ -27,7 +27,7 @@ module Phisol
|
||||
@method.source.current false_block
|
||||
reset_regs
|
||||
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"
|
||||
@method.source.current merge_block
|
||||
|
@ -9,21 +9,21 @@ module Phisol
|
||||
name = statement.to_a.first
|
||||
if( name == :self)
|
||||
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
|
||||
end
|
||||
# either an argument, so it's stored in message
|
||||
if( index = @method.has_arg(name))
|
||||
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
|
||||
else # or a local so it is in the frame
|
||||
index = @method.has_local( name )
|
||||
if(index)
|
||||
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
|
||||
@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
|
||||
end
|
||||
end
|
||||
|
@ -11,7 +11,7 @@ module Phisol
|
||||
raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue)
|
||||
#puts "left #{left_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
|
||||
end
|
||||
end
|
||||
|
@ -15,12 +15,12 @@ module Phisol
|
||||
cond = process(condition)
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
@method.source.current merge
|
||||
|
@ -14,12 +14,10 @@ module Register
|
||||
@method = method
|
||||
raise "Method is not Method, but #{method.class}" unless method == :__init__ or method.is_a?(Parfait::Method)
|
||||
@name = name.to_sym
|
||||
@branch = nil
|
||||
@codes = []
|
||||
end
|
||||
|
||||
attr_reader :name , :codes , :method , :position
|
||||
attr_accessor :branch
|
||||
|
||||
def add_code kode
|
||||
@codes << kode
|
||||
@ -38,14 +36,6 @@ module Register
|
||||
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
|
||||
# the assembler allso assembles and assumes a linear instruction sequence
|
||||
# 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 }
|
||||
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
|
||||
|
@ -90,18 +90,18 @@ module Register
|
||||
|
||||
# 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
|
||||
def locals_at l_block
|
||||
used =[]
|
||||
# call assigns the return register, but as it is in l_block, it is not asked.
|
||||
assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ]
|
||||
l_block.reachable.each do |b|
|
||||
b.uses.each {|u|
|
||||
(used << u) unless assigned.include?(u)
|
||||
}
|
||||
assigned += b.assigns
|
||||
end
|
||||
used.uniq
|
||||
end
|
||||
# def locals_at l_block
|
||||
# used =[]
|
||||
# # call assigns the return register, but as it is in l_block, it is not asked.
|
||||
# assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ]
|
||||
# l_block.reachable.each do |b|
|
||||
# b.uses.each {|u|
|
||||
# (used << u) unless assigned.include?(u)
|
||||
# }
|
||||
# assigned += b.assigns
|
||||
# end
|
||||
# used.uniq
|
||||
# end
|
||||
|
||||
# control structures need to see blocks as a graph, but they are stored as a list with implict
|
||||
# branches
|
||||
|
Loading…
Reference in New Issue
Block a user