remove the old add_new_int and calls

last orrurences in syscalls replaced, 2 variants
- exit does not actually need the int
- all else, preallocate the int beforehand and in syscall assume the reg name (integer_tmp)

test missing
This commit is contained in:
Torsten Ruger 2018-11-22 09:16:56 +02:00
parent a8d1f070f1
commit e6615d0a6a
4 changed files with 43 additions and 34 deletions

View File

@ -58,7 +58,10 @@ module Mom
branch while_start_label branch while_start_label
add_code exit_label add_code exit_label
Risc::Builtin::Object.emit_syscall( builder , :exit ) # temporary, need to raise really.
factory! << Parfait.object_space.get_factory_for(:Integer)
integer_tmp! << factory[:reserve]
Risc::Builtin::Object.emit_syscall( builder , :exit ) #uses integer_tmp
add_code ok_label add_code ok_label
cache_entry[:cached_method] << callable_method cache_entry[:cached_method] << callable_method

View File

@ -38,7 +38,7 @@ module Risc
if last_char == "!" or last_char == "?" if last_char == "!" or last_char == "?"
if @names.has_key?(name) if @names.has_key?(name)
return @names[name] if last_char == "?" return @names[name] if last_char == "?"
raise "Name exists before creating it #{name}#{last_char}" raise "Name exists (#{@names.keys})before creating it #{name}#{last_char}"
end end
else else
raise "Must create (with ! or ?) before using #{name}#{last_char}" raise "Must create (with ! or ?) before using #{name}#{last_char}"
@ -50,7 +50,7 @@ module Risc
reg reg
end end
# Infer the type from a symbol. In the simplest case the sybbol is the class name. # Infer the type from a symbol. In the simplest case the symbol is the class name.
# But in building, sometimes variations are needed, so next_message or caller work # But in building, sometimes variations are needed, so next_message or caller work
# too (and both return "Message") # too (and both return "Message")
# A general "_reg"/"_obj"/"_const" or "_tmp" at the end of the name will be removed # A general "_reg"/"_obj"/"_const" or "_tmp" at the end of the name will be removed
@ -114,8 +114,8 @@ module Risc
compiler.reset_regs compiler.reset_regs
end end
# Build code using dsl (see __init__ or MessageSetup for examples) # Build code using dsl (see __init__ or MessageSetup for examples).
# names (that ruby would resolve to a variable/method) are converted # Names (that ruby would resolve to a variable/method) are converted
# to registers. << means assignment and [] is supported both on # to registers. << means assignment and [] is supported both on
# L and R values (but only one at a time). R values may also be constants. # L and R values (but only one at a time). R values may also be constants.
# #
@ -123,7 +123,7 @@ module Risc
# Transfer instructions with extremely readable code. # Transfer instructions with extremely readable code.
# example: # example:
# space << Parfait.object_space # load constant # space << Parfait.object_space # load constant
# message[:receiver] << space #make current message (r0) receiver the space # message[:receiver] << space #make current message's (r0) receiver the space
# #
# build result is added to compiler directly # build result is added to compiler directly
# #
@ -137,22 +137,37 @@ module Risc
return ins return ins
end end
# for some methods that return an integer it is beneficial to pre allocate the
# integer and store it in the return value. That is what this function does.
#
# Those (builtin) methods, mostly syscall wrappers then go on to do this and that
# clobbering registers and so the allocate and even move would be difficult.
# We sidestep all that by pre-allocating.
def prepare_int_return
integer_tmp = allocate_int
build do
message[:return_value] << integer_tmp
end
end
# allocate int fetches a new int, for sure. It is a builder method, rather than # allocate int fetches a new int, for sure. It is a builder method, rather than
# an inbuilt one, to avoid call overhead for 99.9% # an inbuilt one, to avoid call overhead for 99.9%
# The factories allocate in 1k, so only when that runs out do we really need a call. # The factories allocate in 1k, so only when that runs out do we really need a call.
# Note: # Note:
# Unfortunately (or so me thinks), this creates code bloat, as the calling is # Unfortunately (or so me thinks), this creates code bloat, as the calling is
# included in 100%, but only needed in 0.1. Risc-levelBlocks or Macros may be needed. # included in 100%, but only needed in 0.1. Risc-level Blocks or Macros may be needed.
# as the calling in (the same) 30-40 instructions for every basic int op. # as the calling in (the same) 40-50 instructions for every basic int op.
# #
# The method # The method
# - grabs a Integer instance from the Integer factory # - grabs a Integer instance from the Integer factory
# - checks for nil and calls (get_more) for more if needed # - checks for nil and calls (get_more) for more if needed
# - returns the RiscValue (Regster) where the object is found # - returns the RiscValue (Register) where the object is found
# #
# The implicit condition is that the method is called at the entry of a method. # The implicit condition is that the method is called at the entry of a method.
# It uses a fair few registers and resets all at the end. The returned object # It uses a fair few registers and resets all at the end. The returned object
# will always be in r1, because the method resets, and all others will be clobbered # will always be in r1, because the method resets, and all others will be clobbered.
#
# Return RegisterValue(:r1) that will be named integer_tmp
def allocate_int def allocate_int
compiler.reset_regs compiler.reset_regs
integer = self.integer! integer = self.integer!
@ -194,17 +209,6 @@ module Risc
Mom::SimpleCall.new(calling).to_risc(compiler) Mom::SimpleCall.new(calling).to_risc(compiler)
end end
def add_new_int( source , from, to )
to.set_builder( self ) # esecially div10 comes in without having used builder
from.set_builder( self ) # not named regs, different regs ==> silent errors
build do
factory! << Parfait.object_space.get_factory_for(:Integer)
to << factory[:next_object]
integer_2! << to[:next_integer]
factory[:next_object] << integer_2
to[Parfait::Integer.integer_index] << from
end
end
end end
end end

View File

@ -41,7 +41,9 @@ module Risc
# Even if it's just this one, sys_exit (later raise) # Even if it's just this one, sys_exit (later raise)
def _method_missing( context ) def _method_missing( context )
compiler = compiler_for(:Object,:method_missing ,{}) compiler = compiler_for(:Object,:method_missing ,{})
emit_syscall( compiler.builder(compiler.source) , :exit ) builder = compiler.builder(compiler.source)
builder.prepare_int_return # makes integer_tmp variable as return
emit_syscall( builder , :exit )
return compiler return compiler
end end
@ -83,6 +85,16 @@ module Risc
return compiler return compiler
end end
# the exit function
# mainly calls exit_sequence
def exit( context )
compiler = compiler_for(:Object,:exit ,{})
builder = compiler.builder(compiler.source)
builder.prepare_int_return # makes integer_tmp variable as return
exit_sequence(builder)
return compiler
end
# a sort of inline version of exit method. # a sort of inline version of exit method.
# Used by exit and __init__ (so it doesn't have to call it) # Used by exit and __init__ (so it doesn't have to call it)
# Assumes int return value and extracts the fixnum for process exit code # Assumes int return value and extracts the fixnum for process exit code
@ -95,15 +107,6 @@ module Risc
end end
end end
# the exit function
# mainly calls exit_sequence
def exit( context )
compiler = compiler_for(:Object,:exit ,{})
builder = compiler.builder(compiler.source)
exit_sequence(builder)
return compiler
end
# emit the syscall with given name # emit the syscall with given name
# there is a Syscall instruction, but the message has to be saved and restored # there is a Syscall instruction, but the message has to be saved and restored
def emit_syscall( builder , name ) def emit_syscall( builder , name )
@ -128,12 +131,10 @@ module Risc
# the int gets retured, ie is the return_value of the message # the int gets retured, ie is the return_value of the message
def restore_message(builder) def restore_message(builder)
r8 = RegisterValue.new( :r8 , :Message) r8 = RegisterValue.new( :r8 , :Message)
int = builder.compiler.use_reg(:Integer)
builder.build do builder.build do
integer_reg! << message integer_reg! << message
message << r8 message << r8
add_new_int( "_restore_message", integer_reg , int ) integer_tmp[Parfait::Integer.integer_index] << integer_reg
message[:return_value] << int
end end
end end

View File

@ -13,6 +13,7 @@ module Risc
def putstring( context) def putstring( context)
compiler = compiler_for(:Word , :putstring ,{}) compiler = compiler_for(:Word , :putstring ,{})
builder = compiler.builder(compiler.source) builder = compiler.builder(compiler.source)
builder.prepare_int_return # makes integer_tmp variable as return
builder.build do builder.build do
word! << message[:receiver] word! << message[:receiver]
integer! << word[Parfait::Word.get_length_index] integer! << word[Parfait::Word.get_length_index]