diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index 9240ce4d..a8912808 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -85,7 +85,7 @@ module Risc def position_all raise "Not translated " unless @translated #need the initial jump at 0 and then functions - Position.set(cpu_init , 0 , nil) + Position::ObjectPosition.init(cpu_init , -1) code_start = position_objects( @platform.padding ) # and then everything code position_code(code_start) @@ -101,7 +101,7 @@ module Risc sorted.each do | objekt| next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label ) before = at - position = Position.set(objekt,at) + position = Position::ObjectPosition.init(objekt,at) previous.register_event(:position_changed , Position::ObjectListener.new(objekt)) if previous previous = position at += objekt.padded_length diff --git a/lib/risc/position/code_position.rb b/lib/risc/position/code_position.rb index d3154def..d68e9ec3 100644 --- a/lib/risc/position/code_position.rb +++ b/lib/risc/position/code_position.rb @@ -12,14 +12,13 @@ module Risc attr_reader :code , :method - def initialize(code, pos , method) + def initialize(code , method) super(code,pos) @code = code @method = method raise "Method nil" unless method end - def init(at , method) - raise "No no" unless method.name == @method.name + def set(at ) next_pos = at + code.padded_length if code.next Position.set(code.next , next_pos, method) @@ -32,11 +31,7 @@ module Risc Position.set( next_meth.cpu_instructions, next_cpu_pos , next_meth.binary) end end - def reset_to(pos , ignored) - super(pos, ignored) - init(pos , ignored) - Position.log.debug "ResetCode (#{pos.to_s(16)}) #{code}" - end + # insert a jump to the next instruction, at the last instruction # thus hopping over the object header def set_jump(at) diff --git a/lib/risc/position/instruction_position.rb b/lib/risc/position/instruction_position.rb index ac190038..7922a8b2 100644 --- a/lib/risc/position/instruction_position.rb +++ b/lib/risc/position/instruction_position.rb @@ -16,9 +16,9 @@ module Risc # class InstructionPosition < ObjectPosition attr_reader :instruction , :binary - def initialize(instruction, pos , binary) - raise "not set #{binary}" if pos != 0 and !binary.is_a?(Parfait::BinaryCode) - super(instruction,pos) + def initialize(instruction , binary) + pos = 0 + super(instruction) @instruction = instruction @binary = binary end @@ -47,6 +47,25 @@ module Risc init(pos , binary) Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}" end + + # initialize the dependency graph for instructions + # + # starting from the given instruction, create InstructionPositions + # for it and the whole chain + # + # Set the next created to be dependent on the previous + def self.init( instruction , code) + while(instruction) + position = InstructionPosition.new(instruction , code) + nekst = instruction.next + if nekst + listener = InstructionListener.new( nekst ) + position.register_event(:position_changed , listener) + end + instruction = nekst + end + position + end end end end diff --git a/lib/risc/position/object_position.rb b/lib/risc/position/object_position.rb index 01af52da..68ba9eda 100644 --- a/lib/risc/position/object_position.rb +++ b/lib/risc/position/object_position.rb @@ -7,11 +7,13 @@ module Risc attr_reader :at , :object - def initialize( object, at) - @at = at + # initialize with a given object, first parameter + # The object ill be the key in global position map + # Give an integer as the actual position, where -1 + # which means no legal position known + def initialize(object , pos ) + @at = 0 @object = object - @listeners = [] - raise "not int #{self}-#{at}" unless @at.is_a?(Integer) end def +(offset) @@ -31,13 +33,17 @@ 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 @at = pos + trigger(:position_changed , self) true end + def self.init(object , at = -1) + position = ObjectPosition.new(object , at) + Position.set_to( position , at) + end end end end diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index 6fb77b63..2b2eec58 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -56,52 +56,19 @@ module Risc old.reset_to( old.at ) end - # resetting of position used to be error, but since relink and dynamic instruction size it is ok. - # in measures - # - # reseting to the same position as before, triggers code that propagates - def self.reset(position , to , extra) - log.debug "ReSetting #{position}, to:#{to.to_s(16)}, for #{position.object.class}-#{position.object}" - position.reset_to(to, extra) - if testing = @reverse_cache[ to ] - if testing.class != position.class - raise "Mismatch (at #{to.to_s(16)}) new:#{position}:#{position.class} , was #{testing}:#{testing.class}" - end - end - unless position.object.is_a? Label - @reverse_cache.delete(to) - @reverse_cache[position.at] = position - end - log.debug "Reset #{position} (#{to.to_s(16)}) for #{position.class}" - return position - end - - def self.set( object , pos , extra = nil) - old = Position.positions[object] - return self.reset(old , pos , extra) if old - log.debug "Setting #{pos.to_s(16)} for #{object.class}-#{object}" - testing = self.at( pos ) - position = for_at( object , pos , extra) + def self.set_to( position , to) + postest = Position.positions[position.object] + raise "Mismatch #{position}" if postest and postest != position + @reverse_cache.delete(position.at) unless position.object.is_a? Label + testing = self.at( position.at ) if position.at >= 0 if testing and testing.class != position.class raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" end - self.positions[object] = position - position.init(pos , extra) - @reverse_cache[position.at] = position unless object.is_a? Label - log.debug "Set #{position} (#{pos.to_s(16)}) for #{position.class}" + self.positions[position.object] = position + @reverse_cache[to] = position unless position.object.is_a? Label + log.debug "Set #{position} (#{to.to_s(16)}) for #{position.class}" position end - - def self.for_at(object , at , extra) - case object - when Parfait::BinaryCode - CodePosition.new(object,at , extra) - when Arm::Instruction , Risc::Instruction - InstructionPosition.new(object,at , extra) - else - ObjectPosition.new(object,at) - end - end end end require_relative "object_position" diff --git a/test/risc/position/test_instruction_position.rb b/test/risc/position/test_instruction_position.rb index 469b7b31..2e7ff51b 100644 --- a/test/risc/position/test_instruction_position.rb +++ b/test/risc/position/test_instruction_position.rb @@ -3,32 +3,35 @@ require_relative "helper" module Risc module Position # tests that require a boot and test propagation - class TestPositionBasic < MiniTest::Test + class TestInstructionPosition < MiniTest::Test def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) - Position.set(@binary , 0 , Parfait.object_space.get_main) + #Position.set(@binary , 0 , Parfait.object_space.get_main) @label = Risc.label("hi","ho") end - def test_set_instr + def test_init + assert InstructionPosition.init(@label , nil) + end + def pest_set_instr pos = Position.set( @label , 8 , @binary) assert_equal InstructionPosition , pos.class end - def test_label_set_int + def pest_label_set_int Position.set( @label , 8 , @binary) assert_equal 8 , @label.address.value end - def test_label_reset_int + def pest_label_reset_int Position.set( @label , 8 , @binary) Position.set( @label , 18 , @binary) assert_equal 18 , @label.address.value end - def test_ins_propagates + def pest_ins_propagates @label.set_next Arm::ArmMachine.b( @label) Position.set( @label , 8 , @binary) assert_equal 8 , Position.get(@label.next).at end - def test_ins_propagates_again + def pest_ins_propagates_again second = Arm::ArmMachine.b( @label) @label.set_next(second) Position.set( @label , 8 , @binary) @@ -36,7 +39,7 @@ module Risc Position.set( @label , 8 , @binary) assert_equal 8 , Position.get(@label.next).at end - def test_label_at + def pest_label_at branch = Branch.new("b" , @label) Position.set(@label , 8 , @binary) Position.set(branch , 8 , @binary) @@ -44,7 +47,7 @@ module Risc assert_equal InstructionPosition , at_4.class assert_equal Branch , at_4.instruction.class end - def test_label_at_reverse + def pest_label_at_reverse branch = Branch.new("b" , @label) Position.set(branch , 8 , @binary) Position.set(@label , 8 , @binary) @@ -52,7 +55,7 @@ module Risc assert_equal InstructionPosition , at_4.class assert_equal Branch , at_4.instruction.class end - def test_reset_false_type + def pest_reset_false_type assert_raises {Position.set(@label , 0 , @binary)} end end diff --git a/test/risc/position/test_object_position.rb b/test/risc/position/test_object_position.rb index d2879613..568ad54d 100644 --- a/test/risc/position/test_object_position.rb +++ b/test/risc/position/test_object_position.rb @@ -5,44 +5,47 @@ module Risc # tests that do no require a boot and only test basic positioning class TestPositionBasic < MiniTest::Test - def test_creation_ok + def test_init + assert_equal ObjectPosition.init(self) + end + def pest_creation_ok assert ObjectPosition.new(self,0) end - def test_creation_fail + def pest_creation_fail assert_raises {Position.new("0")} end - def test_add + def pest_add res = ObjectPosition.new(self,0) + 5 assert_equal 5 , res end - def test_sub + def pest_sub res = ObjectPosition.new(self,0) - 1 assert_equal -1 , res end - def test_sub_pos + def pest_sub_pos res = ObjectPosition.new(self,0) - ObjectPosition.new(self,0) assert_equal 0 , res end - def test_set + def pest_set pos = Position.set(self , 5) assert_equal 5 , pos.at end def tet_tos assert_equal "0x10" , Position.set(self).to_s end - def test_reset_ok + def pest_reset_ok pos = Position.set(self , 5) pos = Position.set(self , 10) assert_equal 10 , pos.at end - def test_reset_fail + def pest_reset_fail Position.set(self , 5) assert_raises{Position.set(self , 10000)} end - def test_raises_set_nil + def pest_raises_set_nil assert_raises { Position.set(self,nil)} end - def test_at + def pest_at pos = Position.set(self , 5) pos = Position.at(5) assert_equal 5 , pos.at @@ -50,21 +53,21 @@ module Risc end class TestPositionEvents < MiniTest::Test def setup - @position = ObjectPosition.new(self,0) + @position = ObjectPosition.new(self) end - def test_has_register + def pest_has_register assert @position.register_event(:position_changed , self) end - def test_can_unregister + def pest_can_unregister assert @position.register_event(:position_changed ,self) assert @position.unregister_event(:position_changed ,self) end - def test_fires + def pest_fires @position.register_event(:position_changed ,self) @position.trigger(:position_changed , @position) assert_equal @position , @trigger end - def test_no_fire_after_unregister + def pest_no_fire_after_unregister assert @position.register_event(:position_changed ,self) assert @position.unregister_event(:position_changed ,self) @position.trigger(:position_changed , @position) diff --git a/test/risc/position/test_position.rb b/test/risc/position/test_position.rb index 933fada4..cd5c5ecf 100644 --- a/test/risc/position/test_position.rb +++ b/test/risc/position/test_position.rb @@ -5,25 +5,25 @@ module Risc def setup @machine = Risc.machine.boot end - def test_cpu_init + def pest_cpu_init @machine.translate(:interpreter) @machine.position_all assert Position.get @machine.cpu_init end - def test_cpu_label + def pest_cpu_label @machine.translate(:interpreter) @machine.position_all assert Position.get( @machine.cpu_init.label ) end - def test_cpu_first_arm + def pest_cpu_first_arm @machine.translate(:arm) @machine.position_all assert Position.get( @machine.cpu_init.first ) end - def test_has_arm_pos + def pest_has_arm_pos has_positions(:arm) end - def test_has_int_pos + def pest_has_int_pos has_positions(:interpreter) end def has_positions(platform) @@ -33,10 +33,10 @@ module Risc assert Position.get(obj) end end - def test_has_arm_meth + def pest_has_arm_meth meth_positions(:arm) end - def test_has_int_meth + def pest_has_int_meth meth_positions(:interpreter) end def meth_positions(platform)