diff --git a/lib/parfait/object.rb b/lib/parfait/object.rb index c2ff6fd8..d80d942f 100644 --- a/lib/parfait/object.rb +++ b/lib/parfait/object.rb @@ -65,7 +65,7 @@ module Parfait def get_layout() l = internal_object_get(LAYOUT_INDEX) - raise "No layout #{self.class}:#{self.class} #{self.object_id}" unless l + raise "No layout #{self.to_s}:#{self.class} #{self.object_id}" unless l return l end diff --git a/lib/parfait/space.rb b/lib/parfait/space.rb index 9ef1017d..a7e4bbc6 100644 --- a/lib/parfait/space.rb +++ b/lib/parfait/space.rb @@ -43,6 +43,7 @@ module Parfait end @next_message = @messages.first @next_frame = @frames.first + init_layout end @@object_space = nil diff --git a/lib/register/builtin/kernel.rb b/lib/register/builtin/kernel.rb index cda39cdf..69858853 100644 --- a/lib/register/builtin/kernel.rb +++ b/lib/register/builtin/kernel.rb @@ -17,7 +17,7 @@ module Builtin end def putstring context function = Virtual::CompiledMethodInfo.create_method(:Kernel , :putstring , [] ) - return function + emit_syscall( function , :putstring ) ret = Virtual::RegisterMachine.instance.write_stdout(function) function.set_return ret function @@ -35,6 +35,39 @@ module Builtin function.info.return_type = Virtual::Integer return function end + + private + def emit_syscall function , name + save_message( function ) + function.info.add_code Register::Syscall.new( name ) + restore_message(function) + end + # save the current message, as the syscall destroys all context + # + # currently HACKED into the space as a temporary varaible. As the space is a globally + # unique object we can retrieve it from there + # TODO : fix this to use global (later per thread) variable + def save_message(function) + space_tmp = Register::RegisterReference.tmp_reg + ind = Parfait::Space.object_space.get_layout().index_of( :syscall_message ) + raise "index not found for :syscall_message" unless ind + function.info.add_code LoadConstant.new( space_tmp , Parfait::Space.object_space ) + function.info.add_code << SetSlot.new( Virtual::Slot::MESSAGE_REGISTER , space_tmp , ind) + end + def restore_message(function) + # get the sys return out of the way + return_tmp = Register::RegisterReference.tmp_reg + # load the space into the base register + function.info.add_code RegisterTransfer.new( Virtual::Slot::MESSAGE_REGISTER , return_tmp ) + # find the stored message + ind = Parfait::Space.object_space.get_layout().index_of( :syscall_message ) + raise "index not found for #{kind}.#{kind.class}" unless ind + # and load it into the base RegisterMachine + function.info.add_code GetSlot.new( Virtual::Slot::MESSAGE_REGISTER , ind , Virtual::Slot::MESSAGE_REGISTER ) + # and "unroll" self and frame + function.info.add_code GetSlot.new( slot::MESSAGE_REGISTER , Virtual::SELF_INDEX, slot::SELF_REGISTER ) + function.info.add_code GetSlot.new( slot::MESSAGE_REGISTER , Virtual::FRAME_INDEX, slot::FRAME_REGISTER ) + end end extend ClassMethods end diff --git a/lib/register/instruction.rb b/lib/register/instruction.rb index 18520883..ac45a232 100644 --- a/lib/register/instruction.rb +++ b/lib/register/instruction.rb @@ -38,6 +38,7 @@ end require_relative "instructions/set_slot" require_relative "instructions/get_slot" require_relative "instructions/load_constant" +require_relative "instructions/syscall" require_relative "instructions/function_call" require_relative "instructions/function_return" require_relative "instructions/save_return" diff --git a/lib/register/instructions/syscall.rb b/lib/register/instructions/syscall.rb new file mode 100644 index 00000000..d967ae9c --- /dev/null +++ b/lib/register/instructions/syscall.rb @@ -0,0 +1,17 @@ +module Register + + # name says it all really + # only arg is the method syscall name + # how the layer below executes these is really up to it + + # Any function issuing a Syscall should also save the current message + # and restore it after the syscall, saving the return value in Return_index + + class Syscall < Instruction + + def initialize name + @name = name + end + attr_reader :name + end +end diff --git a/lib/register/passes/call_implementation.rb b/lib/register/passes/call_implementation.rb index ff535f11..021ac3b1 100644 --- a/lib/register/passes/call_implementation.rb +++ b/lib/register/passes/call_implementation.rb @@ -16,7 +16,7 @@ module Register # move the current new_message to message new_codes << RegisterTransfer.new( slot::NEW_MESSAGE_REGISTER , slot::MESSAGE_REGISTER ) # "roll out" self into its register - new_codes << GetSlot.new( slot::SELF_REGISTER ,slot::MESSAGE_REGISTER , Virtual::SELF_INDEX ) + new_codes << GetSlot.new( slot::MESSAGE_REGISTER , Virtual::SELF_INDEX, slot::SELF_REGISTER ) # do the register call new_codes << FunctionCall.new( code.method ) block.replace(code , new_codes ) diff --git a/test/virtual/test_hello.rb b/test/virtual/test_hello.rb index db7e5bc0..f88d371e 100644 --- a/test/virtual/test_hello.rb +++ b/test/virtual/test_hello.rb @@ -6,7 +6,7 @@ class HelloTest < MiniTest::Test def check machine = Virtual::Machine.boot expressions = machine.compile_main @string_input - output_at = "Virtual::SetOptimisation" + output_at = "Register::CallImplementation" #{}"Register::CallImplementation" machine.run_before output_at puts Sof.write(machine.space)