diff --git a/lib/phisol/compiler.rb b/lib/phisol/compiler.rb index 9865156c..b6ad1f6f 100644 --- a/lib/phisol/compiler.rb +++ b/lib/phisol/compiler.rb @@ -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? diff --git a/lib/phisol/compiler/assignment.rb b/lib/phisol/compiler/assignment.rb index 0b3ecf71..c328427a 100644 --- a/lib/phisol/compiler/assignment.rb +++ b/lib/phisol/compiler/assignment.rb @@ -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 diff --git a/lib/phisol/compiler/basic_values.rb b/lib/phisol/compiler/basic_values.rb index 680fc260..ed34ecd1 100644 --- a/lib/phisol/compiler/basic_values.rb +++ b/lib/phisol/compiler/basic_values.rb @@ -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 diff --git a/lib/phisol/compiler/call_site.rb b/lib/phisol/compiler/call_site.rb index 75afdad3..c24cfccc 100644 --- a/lib/phisol/compiler/call_site.rb +++ b/lib/phisol/compiler/call_site.rb @@ -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 diff --git a/lib/phisol/compiler/field_access.rb b/lib/phisol/compiler/field_access.rb index 3b36817b..7c950852 100644 --- a/lib/phisol/compiler/field_access.rb +++ b/lib/phisol/compiler/field_access.rb @@ -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 diff --git a/lib/phisol/compiler/if_statement.rb b/lib/phisol/compiler/if_statement.rb index 5e4b3d21..7a98fe06 100644 --- a/lib/phisol/compiler/if_statement.rb +++ b/lib/phisol/compiler/if_statement.rb @@ -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 diff --git a/lib/phisol/compiler/name_expression.rb b/lib/phisol/compiler/name_expression.rb index 5f6bcf27..bdc55295 100644 --- a/lib/phisol/compiler/name_expression.rb +++ b/lib/phisol/compiler/name_expression.rb @@ -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 diff --git a/lib/phisol/compiler/operator_value.rb b/lib/phisol/compiler/operator_value.rb index 5f865e5d..6615624a 100644 --- a/lib/phisol/compiler/operator_value.rb +++ b/lib/phisol/compiler/operator_value.rb @@ -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 diff --git a/lib/phisol/compiler/while_statement.rb b/lib/phisol/compiler/while_statement.rb index 592422b8..32a4def8 100644 --- a/lib/phisol/compiler/while_statement.rb +++ b/lib/phisol/compiler/while_statement.rb @@ -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 diff --git a/lib/register/block.rb b/lib/register/block.rb index 472feb9a..6447aee5 100644 --- a/lib/register/block.rb +++ b/lib/register/block.rb @@ -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 diff --git a/lib/register/method_source.rb b/lib/register/method_source.rb index 65b5afb0..63be47ff 100644 --- a/lib/register/method_source.rb +++ b/lib/register/method_source.rb @@ -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