renamed info to MethodSource

This commit is contained in:
Torsten Ruger
2015-07-03 20:13:03 +03:00
parent e959c5b0f5
commit b61c73acdd
24 changed files with 103 additions and 103 deletions

View File

@ -1,17 +1,17 @@
Register Machine
Register Machine
===============
This is the logic that uses the compiled virtual object space to produce code and an executable binary.
There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the
There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the
plain ones in this directory don't assemble to binary). Currently there is only the Arm module to actually do
that.
The elf module is used to generate the actual binary from the final Space. Space is a virtual class representing
all objects that will be in the executable. Other than CompiledMethods, objects get transformed to data.
all objects that will be in the executable. Other than MethodSource, objects get transformed to data.
But CompiledMethods, which are made up of Blocks, are compiled into a stream of bytes, which are the binary code for the
function.
But MethodSource, which are made up of Blocks, are compiled into a stream of bytes,
which are the binary code for the function.
Virtual Objects
----------------
@ -32,13 +32,13 @@ and then into the destination. And then we need some fiddling of bits to shift t
Another simple example is a Call. A simple case of a Class function call resolves the class object,
and with the method name the function to be found at compile-time.
And so this results in a Register::Call, which is an Arm instruction.
And so this results in a Register::Call, which is an Arm instruction.
A C call
A C call
---------
Ok, there are no c calls. But syscalls are very similar.
This is not at all as simple as the nice Class call described above.
This is not at all as simple as the nice Class call described above.
For syscall in Arm (linux) you have to load registers 0-x (depending on call), load R7 with the
syscall number and then issue the software interupt instruction.

View File

@ -28,7 +28,7 @@ module Register
@machine.objects.each do |objekt|
next unless objekt.is_a? Parfait::Method
# should be fill_to_length (with zeros)
objekt.code.set_length(objekt.info.byte_length , 0)
objekt.code.set_length(objekt.source.byte_length , 0)
end
#need the initial jump at 0 and then functions
@machine.init.set_position(at)
@ -47,7 +47,7 @@ module Register
# have to tell the code that will be assembled where it is to
# get the jumps/calls right
if objekt.is_a? Parfait::Method
objekt.info.set_position( objekt.code.position )
objekt.source.set_position( objekt.code.position )
end
next if objekt.is_a? Parfait::BinaryCode
objekt.set_position at
@ -102,16 +102,16 @@ module Register
return @stream.string
end
# assemble the CompiledMethodInfo into a stringio
# assemble the MethodSource into a stringio
# and then plonk that binary data into the method.code array
def assemble_binary_method method
stream = StringIO.new
method.info.blocks.each do |block|
method.source.blocks.each do |block|
block.codes.each do |code|
begin
code.assemble( stream )
rescue => e
puts "Method error #{method.name}\n#{Sof.write(method.info.blocks).to_s[0...2000]}"
puts "Method error #{method.name}\n#{Sof.write(method.source.blocks).to_s[0...2000]}"
puts Sof.write(code)
raise e
end
@ -121,8 +121,8 @@ module Register
index = 1
stream.rewind
#puts "Assembled #{method.name} with length #{stream.length}"
raise "length error #{method.code.length} != #{method.info.byte_length}" if method.code.length != method.info.byte_length
raise "length error #{stream.length} != #{method.info.byte_length}" if method.info.byte_length != stream.length
raise "length error #{method.code.length} != #{method.source.byte_length}" if method.code.length != method.source.byte_length
raise "length error #{stream.length} != #{method.source.byte_length}" if method.source.byte_length != stream.length
stream.each_byte do |b|
method.code.set_char(index , b )
index = index + 1

View File

@ -6,8 +6,8 @@ It is the other side of the parfait coin, part of the runtime.
The functions are organized by their respective class and get loaded in boot_classes! ,
right at the start. (see virtual/boot.rb)
These functions return their code, ie a Virtual::CompiledMethod object, which can then be called by
ruby code as if it were a "normal" function.
These functions return their code, ie a Parfait::Method with a Virtual::MethodSource object,
which can then be called by ruby code as if it were a "normal" function.
A normal ruby function is one that is parsed and transformed to code. But not all functionality can
be written in ruby, one of those chicken and egg things.

View File

@ -10,9 +10,9 @@ module Register
# As we write before we recurse (save a push) we write the number backwards
# arguments: string address , integer
def utoa context
utoa_function = Virtual::CompiledMethodInfo.create_method(:Integer ,:utoa , [ Virtual::Integer ] )
function.info.return_type = Virtual::Integer
function.info.receiver = Virtual::Integer
utoa_function = Virtual::MethodSource.create_method(:Integer ,:utoa , [ Virtual::Integer ] )
function.source.return_type = Virtual::Integer
function.source.receiver = Virtual::Integer
return utoa_function
str_addr = utoa_function.receiver
number = utoa_function.args.first
@ -30,9 +30,9 @@ module Register
end
def putint context
putint_function = Virtual::CompiledMethodInfo.create_method(:Integer,:putint , [] )
putint_function.info.return_type = Virtual::Integer
putint_function.info.receiver = Virtual::Integer
putint_function = Virtual::MethodSource.create_method(:Integer,:putint , [] )
putint_function.source.return_type = Virtual::Integer
putint_function.source.receiver = Virtual::Integer
return putint_function
buffer = Parfait::Word.new(" ") # create a buffer
context.object_space.add_object buffer # and save it (function local variable: a no no)
@ -59,9 +59,9 @@ module Register
# a hand coded version of the fibonachi numbers
# not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html
def fibo context
fibo_function = Virtual::CompiledMethodInfo.create_method(:Integer,:fibo , [] )
fibo_function.info.return_type = Virtual::Integer
fibo_function.info.receiver = Virtual::Integer
fibo_function = Virtual::MethodSource.create_method(:Integer,:fibo , [] )
fibo_function.source.return_type = Virtual::Integer
fibo_function.source.receiver = Virtual::Integer
return fibo_function
result = fibo_function.return_type
int = fibo_function.receiver

View File

@ -6,41 +6,41 @@ module Register
# it isn't really a function, ie it is jumped to (not called), exits and may not return
# so it is responsible for initial setup
def __init__ context
function = Virtual::CompiledMethodInfo.create_method(:Kernel,:__init__ , [])
function.info.return_type = Virtual::Integer
function = Virtual::MethodSource.create_method(:Kernel,:__init__ , [])
function.source.return_type = Virtual::Integer
# no method enter or return (automatically added), remove
function.info.blocks.first.codes.pop # no Method enter
function.info.blocks.last.codes.pop # no Method return
function.source.blocks.first.codes.pop # no Method enter
function.source.blocks.last.codes.pop # no Method return
#Set up the Space as self upon init
space = Parfait::Space.object_space
function.info.add_code LoadConstant.new( space , Register.self_reg)
function.source.add_code LoadConstant.new( space , Register.self_reg)
message_ind = Register.resolve_index( :space , :first_message )
# Load the message to new message register (r3)
function.info.add_code Register.get_slot( :self , message_ind , :new_message)
function.source.add_code Register.get_slot( :self , message_ind , :new_message)
# And store the space as the new self (so the call can move it back as self)
function.info.add_code Register.set_slot( :self , :new_message , :receiver)
function.source.add_code Register.set_slot( :self , :new_message , :receiver)
# now we are set up to issue a call to the main
function.info.add_code Virtual::MethodCall.new(Virtual.machine.space.get_main)
function.source.add_code Virtual::MethodCall.new(Virtual.machine.space.get_main)
emit_syscall( function , :exit )
return function
end
def exit context
function = Virtual::CompiledMethodInfo.create_method(:Kernel,:exit , [])
function.info.return_type = Virtual::Integer
function = Virtual::MethodSource.create_method(:Kernel,:exit , [])
function.source.return_type = Virtual::Integer
return function
ret = Virtual::RegisterMachine.instance.exit(function)
function.set_return ret
function
end
def __send context
function = Virtual::CompiledMethodInfo.create_method(:Kernel ,:__send , [] )
function.info.return_type = Virtual::Integer
function = Virtual::MethodSource.create_method(:Kernel ,:__send , [] )
function.source.return_type = Virtual::Integer
return function
end
def emit_syscall function , name
save_message( function )
function.info.add_code Syscall.new( name )
function.source.add_code Syscall.new( name )
restore_message(function)
end
@ -49,20 +49,20 @@ module Register
# This relies on linux to save and restore all registers
#
def save_message(function)
function.info.add_code RegisterTransfer.new( Register.message_reg , :r8 )
function.source.add_code RegisterTransfer.new( Register.message_reg , :r8 )
end
def restore_message(function)
return_tmp = Register.tmp_reg
# get the sys return out of the way
function.info.add_code RegisterTransfer.new( Register.message_reg , return_tmp )
function.source.add_code RegisterTransfer.new( Register.message_reg , return_tmp )
# load the stored message into the base RegisterMachine
function.info.add_code RegisterTransfer.new( :r8 , Register.message_reg )
function.source.add_code RegisterTransfer.new( :r8 , Register.message_reg )
# save the return value into the message
function.info.add_code Register.set_slot( return_tmp , :message , :return_value )
function.source.add_code Register.set_slot( return_tmp , :message , :return_value )
# and "unroll" self and frame
function.info.add_code Register.get_slot(:message , :receiver, :self )
function.info.add_code Register.get_slot(:message , :frame , :frame)
function.source.add_code Register.get_slot(:message , :receiver, :self )
function.source.add_code Register.get_slot(:message , :frame , :frame)
end
end
extend ClassMethods

View File

@ -5,15 +5,15 @@ module Register
class List
module ClassMethods
def get context , index = Virtual::Integer
get_function = Virtual::CompiledMethodInfo.create_method(:get , [ Virtual::Integer] , Virtual::Integer , Virtual::Integer )
get_function = Virtual::MethodSource.create_method(:get , [ Virtual::Integer] , Virtual::Integer , Virtual::Integer )
return get_function
end
def set context , index = Virtual::Integer , object = Virtual::Reference
set_function = Virtual::CompiledMethodInfo.create_method(:set , [Virtual::Integer, Virtual::Reference] )
set_function = Virtual::MethodSource.create_method(:set , [Virtual::Integer, Virtual::Reference] )
return set_function
end
def push context , object = Virtual::Reference
push_function = Virtual::CompiledMethodInfo.create_method(:push , [Virtual::Reference] )
push_function = Virtual::MethodSource.create_method(:push , [Virtual::Reference] )
return push_function
end
end

View File

@ -6,7 +6,7 @@ module Register
# main entry point, ie __init__ calls this
# defined here as empty, to be redefined
def main context
function = Virtual::CompiledMethodInfo.create_method(:Object,:main , [])
function = Virtual::MethodSource.create_method(:Object,:main , [])
return function
end
@ -18,7 +18,7 @@ module Register
# The at_index is just "below" the api, something we need but don't want to expose,
# so we can't code the above in ruby
def _get_instance_variable context , name = Virtual::Integer
get_function = Virtual::CompiledMethodInfo.create_method(:Object,:_get_instance_variable , [ Virtual::Reference ] )
get_function = Virtual::MethodSource.create_method(:Object,:_get_instance_variable , [ Virtual::Reference ] )
return get_function
me = get_function.receiver
var_name = get_function.args.first
@ -39,7 +39,7 @@ module Register
end
def _set_instance_variable(context , name = Virtual::Integer , value = Virtual::Integer )
set_function = Virtual::CompiledMethodInfo.create_method(:Object,:_set_instance_variable ,[Virtual::Reference ,Virtual::Reference] )
set_function = Virtual::MethodSource.create_method(:Object,:_set_instance_variable ,[Virtual::Reference ,Virtual::Reference] )
return set_function
receiver set_function
me = set_function.receiver

View File

@ -3,7 +3,7 @@ module Register
module Word
module ClassMethods
def putstring context
function = Virtual::CompiledMethodInfo.create_method(:Word , :putstring , [] )
function = Virtual::MethodSource.create_method(:Word , :putstring , [] )
Kernel.emit_syscall( function , :putstring )
function
end