create add_code helper and some cleaning

This commit is contained in:
Torsten Ruger 2015-10-23 14:08:12 +03:00
parent dcbd3c7091
commit 991cc0519f
11 changed files with 41 additions and 66 deletions

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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