adding sources to register instructions
This commit is contained in:
parent
f91c9fabe8
commit
36f635f7c1
@ -13,12 +13,12 @@ module Register
|
|||||||
function.source.blocks.last.codes.pop # no Method return
|
function.source.blocks.last.codes.pop # no Method return
|
||||||
#Set up the Space as self upon init
|
#Set up the Space as self upon init
|
||||||
space = Parfait::Space.object_space
|
space = Parfait::Space.object_space
|
||||||
function.source.add_code LoadConstant.new( space , Register.self_reg)
|
function.source.add_code LoadConstant.new(function, space , Register.self_reg)
|
||||||
message_ind = Register.resolve_index( :space , :first_message )
|
message_ind = Register.resolve_index( :space , :first_message )
|
||||||
# Load the message to new message register (r3)
|
# Load the message to new message register (r3)
|
||||||
function.source.add_code Register.get_slot( :self , message_ind , :new_message)
|
function.source.add_code Register.get_slot( function , :self , message_ind , :new_message)
|
||||||
# And store the space as the new self (so the call can move it back as self)
|
# And store the space as the new self (so the call can move it back as self)
|
||||||
function.source.add_code Register.set_slot( :self , :new_message , :receiver)
|
function.source.add_code Register.set_slot( function, :self , :new_message , :receiver)
|
||||||
# now we are set up to issue a call to the main
|
# now we are set up to issue a call to the main
|
||||||
function.source.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 )
|
emit_syscall( function , :exit )
|
||||||
@ -40,29 +40,29 @@ module Register
|
|||||||
|
|
||||||
def emit_syscall function , name
|
def emit_syscall function , name
|
||||||
save_message( function )
|
save_message( function )
|
||||||
function.source.add_code Syscall.new( name )
|
function.source.add_code Syscall.new(function, name )
|
||||||
restore_message(function)
|
restore_message(function)
|
||||||
end
|
end
|
||||||
|
|
||||||
# save the current message, as the syscall destroys all context
|
# save the current message, as the syscall destroys all context
|
||||||
#
|
#
|
||||||
# This relies on linux to save and restore all registers
|
# This relies on linux to save and restore all registers
|
||||||
#
|
#
|
||||||
def save_message(function)
|
def save_message(function)
|
||||||
function.source.add_code RegisterTransfer.new( Register.message_reg , :r8 )
|
function.source.add_code RegisterTransfer.new(function, Register.message_reg , :r8 )
|
||||||
end
|
end
|
||||||
|
|
||||||
def restore_message(function)
|
def restore_message(function)
|
||||||
return_tmp = Register.tmp_reg
|
return_tmp = Register.tmp_reg
|
||||||
# get the sys return out of the way
|
# get the sys return out of the way
|
||||||
function.source.add_code RegisterTransfer.new( Register.message_reg , return_tmp )
|
function.source.add_code RegisterTransfer.new(function, Register.message_reg , return_tmp )
|
||||||
# load the stored message into the base RegisterMachine
|
# load the stored message into the base RegisterMachine
|
||||||
function.source.add_code RegisterTransfer.new( :r8 , Register.message_reg )
|
function.source.add_code RegisterTransfer.new(function, :r8 , Register.message_reg )
|
||||||
# save the return value into the message
|
# save the return value into the message
|
||||||
function.source.add_code Register.set_slot( return_tmp , :message , :return_value )
|
function.source.add_code Register.set_slot( function, return_tmp , :message , :return_value )
|
||||||
# and "unroll" self and frame
|
# and "unroll" self and frame
|
||||||
function.source.add_code Register.get_slot(:message , :receiver, :self )
|
function.source.add_code Register.get_slot(function, :message , :receiver, :self )
|
||||||
function.source.add_code Register.get_slot(:message , :frame , :frame)
|
function.source.add_code Register.get_slot(function, :message , :frame , :frame)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
extend ClassMethods
|
extend ClassMethods
|
||||||
|
@ -12,7 +12,7 @@ module Register
|
|||||||
def initialize source
|
def initialize source
|
||||||
@source = source
|
@source = source
|
||||||
end
|
end
|
||||||
attr_reader :block , :source
|
attr_reader :source
|
||||||
|
|
||||||
# returns an array of registers (RegisterReferences) that this instruction uses.
|
# returns an array of registers (RegisterReferences) that this instruction uses.
|
||||||
# ie for r1 = r2 + r3
|
# ie for r1 = r2 + r3
|
||||||
|
@ -4,7 +4,8 @@ module Register
|
|||||||
# assembly takes care of the rest (ie getting the address)
|
# assembly takes care of the rest (ie getting the address)
|
||||||
|
|
||||||
class FunctionCall < Instruction
|
class FunctionCall < Instruction
|
||||||
def initialize method
|
def initialize source , method
|
||||||
|
super(source)
|
||||||
@method = method
|
@method = method
|
||||||
end
|
end
|
||||||
attr_reader :method
|
attr_reader :method
|
||||||
|
@ -4,7 +4,8 @@ module Register
|
|||||||
# register and index specify where the return address is stored
|
# register and index specify where the return address is stored
|
||||||
|
|
||||||
class FunctionReturn < Instruction
|
class FunctionReturn < Instruction
|
||||||
def initialize register , index
|
def initialize source , register , index
|
||||||
|
super(source)
|
||||||
@register = register
|
@register = register
|
||||||
@index = index
|
@index = index
|
||||||
end
|
end
|
||||||
|
@ -18,30 +18,31 @@ module Register
|
|||||||
# the instruction would do register = array[index]
|
# the instruction would do register = array[index]
|
||||||
# The arguments are in the order that makes sense for the Instruciton name
|
# The arguments are in the order that makes sense for the Instruciton name
|
||||||
# So GetSlot means the slot (array and index) moves to the register (last argument)
|
# So GetSlot means the slot (array and index) moves to the register (last argument)
|
||||||
def initialize array , index , register
|
def initialize source , array , index , register
|
||||||
@register = register
|
super(source)
|
||||||
@array = array
|
@array = array
|
||||||
@index = index
|
@index = index
|
||||||
|
@register = register
|
||||||
raise "not integer #{index}" unless index.is_a? Numeric
|
raise "not integer #{index}" unless index.is_a? Numeric
|
||||||
raise "Not register #{register}" unless Register::RegisterReference.look_like_reg(register)
|
raise "Not register #{register}" unless Register::RegisterReference.look_like_reg(register)
|
||||||
raise "Not register #{array}" unless Register::RegisterReference.look_like_reg(array)
|
raise "Not register #{array}" unless Register::RegisterReference.look_like_reg(array)
|
||||||
end
|
end
|
||||||
attr_accessor :register , :array , :index
|
attr_accessor :array , :index , :register
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"GetSlot: #{register} -> #{array} [#{index}]"
|
"GetSlot: #{array} [#{index}] -> #{register}"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Produce a GetSlot instruction.
|
# Produce a GetSlot instruction.
|
||||||
# From and to are registers or symbols that can be transformed to a register by resolve_to_register
|
# Array and to are registers or symbols that can be transformed to a register by resolve_to_register
|
||||||
# index resolves with resolve_index.
|
# index resolves with resolve_index.
|
||||||
def self.get_slot from , index , to
|
def self.get_slot source , array , index , to
|
||||||
index = resolve_index( from , index)
|
index = resolve_index( array , index)
|
||||||
from = resolve_to_register from
|
array = resolve_to_register array
|
||||||
to = resolve_to_register to
|
to = resolve_to_register to
|
||||||
GetSlot.new( from , index , to)
|
GetSlot.new( source , array , index , to)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,8 @@ module Register
|
|||||||
# second argument is the register the constant is loaded into
|
# second argument is the register the constant is loaded into
|
||||||
|
|
||||||
class LoadConstant < Instruction
|
class LoadConstant < Instruction
|
||||||
def initialize constant , register
|
def initialize source , constant , register
|
||||||
|
super(source)
|
||||||
@register = register
|
@register = register
|
||||||
@constant = constant
|
@constant = constant
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,8 @@ module Register
|
|||||||
# second arguemnt to
|
# second arguemnt to
|
||||||
#
|
#
|
||||||
# Note: this may be reversed from some assembler notations (also arm)
|
# Note: this may be reversed from some assembler notations (also arm)
|
||||||
def initialize from , to
|
def initialize source , from , to
|
||||||
|
super(source)
|
||||||
@from = wrap_register(from)
|
@from = wrap_register(from)
|
||||||
@to = wrap_register(to)
|
@to = wrap_register(to)
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,8 @@ module Register
|
|||||||
# address. In arm that is a register, but intel may (?) push it, and who knows, what other machines do.
|
# address. In arm that is a register, but intel may (?) push it, and who knows, what other machines do.
|
||||||
|
|
||||||
class SaveReturn < Instruction
|
class SaveReturn < Instruction
|
||||||
def initialize register , index
|
def initialize source , register , index
|
||||||
|
super(source)
|
||||||
@register = register
|
@register = register
|
||||||
@index = index
|
@index = index
|
||||||
end
|
end
|
||||||
@ -22,10 +23,10 @@ module Register
|
|||||||
# Produce a SaveReturn instruction.
|
# Produce a SaveReturn instruction.
|
||||||
# From is a register or symbol that can be transformed to a register by resolve_to_register
|
# From is a register or symbol that can be transformed to a register by resolve_to_register
|
||||||
# index resolves with resolve_index.
|
# index resolves with resolve_index.
|
||||||
def self.save_return from , index
|
def self.save_return code, from , index
|
||||||
index = resolve_index( from , index)
|
index = resolve_index( from , index)
|
||||||
from = resolve_to_register from
|
from = resolve_to_register from
|
||||||
SaveReturn.new( from , index )
|
SaveReturn.new( code , from , index )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -17,7 +17,8 @@ module Register
|
|||||||
# If you had a c array and index offset
|
# If you had a c array and index offset
|
||||||
# the instruction would do array[index] = register
|
# the instruction would do array[index] = register
|
||||||
# So SetSlot means the register (first argument) moves to the slot (array and index)
|
# So SetSlot means the register (first argument) moves to the slot (array and index)
|
||||||
def initialize register , array , index
|
def initialize source , register , array , index
|
||||||
|
super(source)
|
||||||
@register = register
|
@register = register
|
||||||
@array = array
|
@array = array
|
||||||
@index = index
|
@index = index
|
||||||
@ -35,11 +36,11 @@ module Register
|
|||||||
# Produce a SetSlot instruction.
|
# Produce a SetSlot instruction.
|
||||||
# From and to are registers or symbols that can be transformed to a register by resolve_to_register
|
# From and to are registers or symbols that can be transformed to a register by resolve_to_register
|
||||||
# index resolves with resolve_index.
|
# index resolves with resolve_index.
|
||||||
def self.set_slot from , to , index
|
def self.set_slot source , from , to , index
|
||||||
index = resolve_index( to , index)
|
|
||||||
from = resolve_to_register from
|
from = resolve_to_register from
|
||||||
|
index = resolve_index( to , index)
|
||||||
to = resolve_to_register to
|
to = resolve_to_register to
|
||||||
SetSlot.new( from , to , index)
|
SetSlot.new( source, from , to , index)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,8 @@ module Register
|
|||||||
|
|
||||||
class Syscall < Instruction
|
class Syscall < Instruction
|
||||||
|
|
||||||
def initialize name
|
def initialize source ,name
|
||||||
|
super(source)
|
||||||
@name = name
|
@name = name
|
||||||
end
|
end
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
@ -13,11 +13,11 @@ module Register
|
|||||||
next unless code.is_a? Virtual::MethodCall
|
next unless code.is_a? Virtual::MethodCall
|
||||||
new_codes = []
|
new_codes = []
|
||||||
# move the current new_message to message
|
# move the current new_message to message
|
||||||
new_codes << RegisterTransfer.new( Register.new_message_reg , Register.message_reg )
|
new_codes << RegisterTransfer.new(code, Register.new_message_reg , Register.message_reg )
|
||||||
# "roll out" self into its register
|
# "roll out" self into its register
|
||||||
new_codes << Register.get_slot( :message , :receiver, :self )
|
new_codes << Register.get_slot( code , :message , :receiver, :self )
|
||||||
# do the register call
|
# do the register call
|
||||||
new_codes << FunctionCall.new( code.method )
|
new_codes << FunctionCall.new( code , code.method )
|
||||||
block.replace(code , new_codes )
|
block.replace(code , new_codes )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ module Register
|
|||||||
block.codes.dup.each do |code|
|
block.codes.dup.each do |code|
|
||||||
next unless code.is_a?(Virtual::NewFrame)
|
next unless code.is_a?(Virtual::NewFrame)
|
||||||
# load the frame from message by index, simple get_slot
|
# load the frame from message by index, simple get_slot
|
||||||
new_codes = [ Register.get_slot( :message , :frame , Register.resolve_to_register(:frame))]
|
new_codes = [ Register.get_slot( code, :message , :frame , Register.resolve_to_register(:frame))]
|
||||||
block.replace(code , new_codes )
|
block.replace(code , new_codes )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -23,7 +23,7 @@ module Register
|
|||||||
block.codes.dup.each do |code|
|
block.codes.dup.each do |code|
|
||||||
next unless code.is_a?(Virtual::NewMessage)
|
next unless code.is_a?(Virtual::NewMessage)
|
||||||
# load the new_message from message by index, simple get_slot
|
# load the new_message from message by index, simple get_slot
|
||||||
new_codes = [ Register.get_slot( :message , :next_message , Register.resolve_to_register(:new_message))]
|
new_codes = [ Register.get_slot(code, :message , :next_message , Register.resolve_to_register(:new_message))]
|
||||||
block.replace(code , new_codes )
|
block.replace(code , new_codes )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,14 +5,14 @@ module Register
|
|||||||
next unless code.is_a? Virtual::MethodReturn
|
next unless code.is_a? Virtual::MethodReturn
|
||||||
new_codes = []
|
new_codes = []
|
||||||
# move the current message to new_message
|
# move the current message to new_message
|
||||||
new_codes << RegisterTransfer.new( Register.message_reg , Register.new_message_reg )
|
new_codes << RegisterTransfer.new(code, Register.message_reg , Register.new_message_reg )
|
||||||
# and restore the message from saved value in new_message
|
# and restore the message from saved value in new_message
|
||||||
new_codes << Register.get_slot(:new_message , :caller , :message )
|
new_codes << Register.get_slot(code,:new_message , :caller , :message )
|
||||||
# "roll out" self and frame into their registers
|
# "roll out" self and frame into their registers
|
||||||
new_codes << Register.get_slot( :message , :receiver , :self )
|
new_codes << Register.get_slot(code, :message , :receiver , :self )
|
||||||
new_codes << Register.get_slot( :message , :frame , :frame )
|
new_codes << Register.get_slot(code, :message , :frame , :frame )
|
||||||
#load the return address into pc, affecting return. (other cpus have commands for this, but not arm)
|
#load the return address into pc, affecting return. (other cpus have commands for this, but not arm)
|
||||||
new_codes << FunctionReturn.new( Register.message_reg , Register.resolve_index(:message , :return_address) )
|
new_codes << FunctionReturn.new( code , Register.message_reg , Register.resolve_index(:message , :return_address) )
|
||||||
block.replace(code , new_codes )
|
block.replace(code , new_codes )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,11 +11,11 @@ module Register
|
|||||||
tmp = Register.tmp_reg
|
tmp = Register.tmp_reg
|
||||||
# for constants we have to "move" the constants value
|
# for constants we have to "move" the constants value
|
||||||
if( code.from.is_a?(Parfait::Value) or code.from.is_a?(Symbol))
|
if( code.from.is_a?(Parfait::Value) or code.from.is_a?(Symbol))
|
||||||
move1 = LoadConstant.new( code.from , tmp )
|
move1 = LoadConstant.new(code, code.from , tmp )
|
||||||
else # while otherwise we "load"
|
else # while otherwise we "load"
|
||||||
move1 = Register.get_slot( code.from.object_name , get_index(code.from) , tmp )
|
move1 = Register.get_slot(code, code.from.object_name , get_index(code.from) , tmp )
|
||||||
end
|
end
|
||||||
move2 = Register.set_slot( tmp , code.to.object_name , get_index(code.to) )
|
move2 = Register.set_slot( code , tmp , code.to.object_name , get_index(code.to) )
|
||||||
block.replace(code , [move1,move2] )
|
block.replace(code , [move1,move2] )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,7 +6,7 @@ module Virtual
|
|||||||
next unless code.is_a? Virtual::MethodEnter
|
next unless code.is_a? Virtual::MethodEnter
|
||||||
new_codes = []
|
new_codes = []
|
||||||
# save return register to the message at instance return_address
|
# save return register to the message at instance return_address
|
||||||
new_codes << Register.save_return(:message , :return_address)
|
new_codes << Register.save_return(code, :message , :return_address)
|
||||||
# and create a new frame if needed
|
# and create a new frame if needed
|
||||||
unless code.method.locals.empty? and code.method.tmps.empty?
|
unless code.method.locals.empty? and code.method.tmps.empty?
|
||||||
new_codes << Virtual::NewFrame.new
|
new_codes << Virtual::NewFrame.new
|
||||||
|
Loading…
Reference in New Issue
Block a user