adds the simple object dependency

where the next object is dependent on the previous one
and just behind it, the padded_length away
This commit is contained in:
Torsten Ruger 2018-05-31 20:41:04 +03:00
parent 21a9c56ba9
commit 46fbfb7101
5 changed files with 79 additions and 12 deletions

View File

@ -86,9 +86,9 @@ module Risc
raise "Not translated " unless @translated
#need the initial jump at 0 and then functions
Position.set(cpu_init , 0 , nil)
@code_start = position_objects( @platform.padding )
code_start = position_objects( @platform.padding )
# and then everything code
position_code
position_code(code_start)
end
# go through everything that is not code (BinaryCode) and set position
@ -97,10 +97,13 @@ module Risc
def position_objects(at)
# want to have the objects first in the executable
sorted = objects.values.sort{|left,right| left.class.name <=> right.class.name}
previous = nil
sorted.each do | objekt|
next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label )
before = at
Position.set(objekt,at)
position = Position.set(objekt,at)
previous.register_event(:position_changed , Position::ObjectListener.new(objekt)) if previous
previous = position
at += objekt.padded_length
log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
end
@ -112,17 +115,14 @@ module Risc
# So that all code from one method is layed out linearly (for debugging)
# we go through methods, and then through all codes from the method
#
# start at @code_start. The method is called until
# assembly stops throwing errors
def position_code
at = @code_start
# start at code_start.
def position_code(code_start)
first_method = Parfait.object_space.types.values.first.methods
before = at
Position.set( first_method.binary , at , first_method)
Position.set( first_method.cpu_instructions, at + Parfait::BinaryCode.byte_offset , first_method.binary)
log.debug "Method #{first_method.name}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
before = code_start
Position.set( first_method.binary , code_start , first_method)
Position.set( first_method.cpu_instructions, code_start + Parfait::BinaryCode.byte_offset , first_method.binary)
log.debug "Method #{first_method.name}:#{before.to_s(16)} len: #{(code_start - before).to_s(16)}"
log.debug "Instructions #{first_method.cpu_instructions.object_id.to_s(16)}:#{(before+Parfait::BinaryCode.byte_offset).to_s(16)}"
at
end
# Create Binary code for all methods and the initial jump

View File

@ -0,0 +1,31 @@
module Risc
module Position
# Listeners localise the changes that need to happen.
#
# An object listener assmes it is set up to the previous object.
# so when position changes, it places itself just behind the previous object
#
# This is handy, since the "normal" chaining of object is forward
# But the dependencies are backwards. This way we don't clutter the
# actual object (or even the position), but keep the logic seperate.
class ObjectListener
# initialize with the object that needs to react to change
def initialize(object)
@object = object
end
# when the argument changes position, we update the objects
# position to reflect that change
#
def position_changed(previous)
me = previous.at + previous.object.padded_length
object_pos = Position.get(@object)
return if me == object_pos.at
Position.set(@object , me)
end
end
end
end

View File

@ -31,6 +31,7 @@ module Risc
end
def reset_to(pos , guaranteed_nil )
return false if pos == at
trigger(:position_changed , self)
if((at - pos).abs > 1000)
raise "position set too far off #{pos}!=#{at} for #{object}:#{object.class}"
end

View File

@ -105,5 +105,6 @@ module Risc
end
end
require_relative "object_position"
require_relative "object_listener"
require_relative "instruction_position"
require_relative "code_position"

View File

@ -0,0 +1,34 @@
require_relative "../helper"
module Risc
module Position
class Dummy
def padded_length
4
end
end
class TestObjectListener < MiniTest::Test
def setup
@object = Dummy.new
@dependent = Dummy.new
@pos = Position.set(@object,0)
Position.set(@dependent,0)
@listener = ObjectListener.new(@dependent)
end
def test_register
assert @pos.register_event(:position_changed , @listener)
end
def test_no_fire
@pos.register_event(:position_changed , self)
@pos = Position.set(@object,0)
assert_equal 0 , Position.get(@dependent).at
end
def test_reset
@pos.register_event(:position_changed , @listener)
@pos = Position.set(@object,4)
assert_equal 4 , Position.get(@dependent).at
end
end
end
end