2014-07-14 14:06:09 +03:00
|
|
|
|
2015-10-22 18:16:29 +03:00
|
|
|
module Register
|
2015-05-20 16:43:26 +03:00
|
|
|
# the static info of a method (with its compiled code, argument names etc ) is part of the
|
|
|
|
# runtime, ie found in Parfait::Method
|
|
|
|
|
2015-10-28 12:19:10 +02:00
|
|
|
# Code-wise Methods are made up from a list of Instructions.
|
2015-05-04 23:03:52 +03:00
|
|
|
|
2015-10-28 12:19:10 +02:00
|
|
|
# Instructions can be of three tyes:
|
2015-03-28 20:20:01 +02:00
|
|
|
# -linear: flow continues from one to the next as they are sequential both logically and
|
2015-10-28 12:19:10 +02:00
|
|
|
# "physically" use the set_next for this (or add_code).
|
2015-03-28 20:20:01 +02:00
|
|
|
# This "straight line", there must be a continuous sequence from body to return
|
2015-10-28 12:19:10 +02:00
|
|
|
# - branched: Any of the Branch instructions creates a fork. The else branch is the "next"
|
|
|
|
# of a branch. The only valid branch targets are Labels.
|
|
|
|
#
|
2015-05-04 23:03:52 +03:00
|
|
|
|
2015-07-03 20:13:03 +03:00
|
|
|
class MethodSource
|
2015-05-20 16:43:26 +03:00
|
|
|
|
|
|
|
# create method does two things
|
|
|
|
# first it creates the parfait method, for the given class, with given argument names
|
2015-07-03 20:13:03 +03:00
|
|
|
# second, it creates MethodSource and attaches it to the method
|
2015-05-20 16:43:26 +03:00
|
|
|
#
|
|
|
|
# compile code then works with the method, but adds code tot the info
|
2015-10-28 12:19:10 +02:00
|
|
|
def self.create_method( class_name , method_name , args)
|
2015-08-17 02:37:07 +03:00
|
|
|
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
|
2015-10-22 18:16:29 +03:00
|
|
|
clazz = Register.machine.space.get_class_by_name class_name
|
2015-05-20 16:43:26 +03:00
|
|
|
raise "No such class #{class_name}" unless clazz
|
2015-10-28 12:19:10 +02:00
|
|
|
create_method_for( clazz , method_name , args)
|
2015-10-25 15:04:40 +02:00
|
|
|
end
|
2015-10-28 12:19:10 +02:00
|
|
|
def self.create_method_for clazz , method_name , args
|
2015-10-25 15:04:40 +02:00
|
|
|
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
|
2015-10-06 00:27:13 +03:00
|
|
|
arguments = []
|
2015-09-27 14:30:41 +03:00
|
|
|
args.each_with_index do | arg , index |
|
|
|
|
unless arg.is_a? Parfait::Variable
|
|
|
|
arg = Parfait::Variable.new arg , "arg#{index}".to_sym
|
|
|
|
end
|
2015-10-06 00:27:13 +03:00
|
|
|
arguments << arg
|
2015-09-27 14:30:41 +03:00
|
|
|
end
|
2015-10-22 18:16:29 +03:00
|
|
|
method = clazz.create_instance_method( method_name , Register.new_list(arguments))
|
2015-10-28 12:19:10 +02:00
|
|
|
method.source = MethodSource.new(method)
|
2015-05-20 16:43:26 +03:00
|
|
|
method
|
2014-07-10 17:14:38 +03:00
|
|
|
end
|
2015-06-28 22:03:21 +03:00
|
|
|
# just passing the method object in for Instructions to make decisions (later)
|
2015-10-28 12:19:10 +02:00
|
|
|
def initialize method
|
|
|
|
init( method )
|
2015-10-06 00:27:13 +03:00
|
|
|
end
|
|
|
|
|
2015-10-28 12:19:10 +02:00
|
|
|
def init method
|
2015-10-28 14:33:38 +02:00
|
|
|
@method = method
|
|
|
|
method.instructions = Label.new(self, "#{method.for_class.name}_#{method.name}")
|
|
|
|
@current = method.instructions
|
2015-10-23 21:27:36 +03:00
|
|
|
add_code enter = Register.save_return(self, :message , :return_address)
|
|
|
|
add_code Label.new( method, "return")
|
2015-10-18 17:32:32 +03:00
|
|
|
# move the current message to new_message
|
2015-10-23 21:27:36 +03:00
|
|
|
add_code RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg )
|
2015-10-18 17:32:32 +03:00
|
|
|
# and restore the message from saved value in new_message
|
2015-10-23 21:27:36 +03:00
|
|
|
add_code Register.get_slot(self,:new_message , :caller , :message )
|
2015-10-18 17:32:32 +03:00
|
|
|
#load the return address into pc, affecting return. (other cpus have commands for this, but not arm)
|
2015-10-23 21:27:36 +03:00
|
|
|
add_code FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) )
|
|
|
|
@current = enter
|
2014-07-10 17:14:38 +03:00
|
|
|
end
|
2015-10-28 14:33:38 +02:00
|
|
|
attr_accessor :current , :method
|
2014-07-10 17:14:38 +03:00
|
|
|
|
2014-07-18 11:56:46 +03:00
|
|
|
# add an instruction after the current (insertion point)
|
|
|
|
# the added instruction will become the new insertion point
|
2014-08-13 11:59:51 +03:00
|
|
|
def add_code instruction
|
2015-10-22 18:16:29 +03:00
|
|
|
unless instruction.is_a?(Instruction)
|
2015-07-18 19:02:54 +03:00
|
|
|
raise instruction.to_s
|
2015-05-30 12:20:39 +03:00
|
|
|
end
|
2015-10-23 21:27:36 +03:00
|
|
|
@current.insert(instruction) #insert after current
|
|
|
|
@current = instruction
|
2014-08-13 11:59:51 +03:00
|
|
|
self
|
2014-07-10 17:14:38 +03:00
|
|
|
end
|
|
|
|
|
2015-10-23 21:27:36 +03:00
|
|
|
# set the insertion point (where code is added with add_code)
|
|
|
|
def current ins
|
|
|
|
@current = ins
|
2014-08-13 11:59:51 +03:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2015-10-25 10:54:19 +02:00
|
|
|
def total_byte_length
|
2015-10-28 14:33:38 +02:00
|
|
|
@method.instructions.total_byte_length
|
2014-09-16 17:16:56 +03:00
|
|
|
end
|
2015-05-24 18:05:20 +03:00
|
|
|
|
2014-08-30 13:47:51 +03:00
|
|
|
# position of the function is the position of the entry block, is where we call
|
|
|
|
def set_position at
|
2014-09-11 15:19:29 +03:00
|
|
|
at += 8 #for the 2 header words
|
2015-10-28 14:33:38 +02:00
|
|
|
@method.instructions.set_position at
|
2014-08-22 17:26:49 +03:00
|
|
|
end
|
2015-07-18 16:12:50 +03:00
|
|
|
|
2014-07-10 17:14:38 +03:00
|
|
|
end
|
2014-08-22 17:26:49 +03:00
|
|
|
|
2014-07-10 17:14:38 +03:00
|
|
|
end
|