From 2d218bbc48964a5cf44334438e95a0c72f86e6b6 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 7 Jun 2018 19:26:02 +0300 Subject: [PATCH] work on jump insertion continues Now registering CodeListener instead of PositionListener Also instead of on the previous, in itself, which is simpler and allows to react to insertion at end --- lib/parfait/binary_code.rb | 6 +--- lib/risc/machine.rb | 3 +- lib/risc/position/code_listener.rb | 44 +++++++++++++---------- test/risc/position/test_code_listener.rb | 11 +++--- test/risc/position/test_code_listener1.rb | 26 ++++++++++++++ 5 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 test/risc/position/test_code_listener1.rb diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index 9ed41117..15b88148 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -39,11 +39,7 @@ module Parfait def extend_one() @next = BinaryCode.new(1) - if Risc::Position.set?(self) - Risc::Position.log.debug "extending one in #{self}" - my_pos = Risc::Position.get(self) - Risc::CodeListener.init( @next , my_pos + self.padded_length) - end + Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self) end def ensure_next diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index 0af309d5..2754e340 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -121,7 +121,8 @@ module Risc Parfait.object_space.types.values.each do |type| next unless type.methods type.methods.each_method do |method| - last_code = CodeListener.init(method.binary , code_start) + last_code = CodeListener.init(method.binary) + last_code.set(code_start) first_position = InstructionListener.init(method.cpu_instructions, method.binary) first_position.set( code_start + Parfait::BinaryCode.byte_offset) last_code.position_listener( prev_code.object) if prev_code diff --git a/lib/risc/position/code_listener.rb b/lib/risc/position/code_listener.rb index 90c9d632..0da5cce5 100644 --- a/lib/risc/position/code_listener.rb +++ b/lib/risc/position/code_listener.rb @@ -9,15 +9,8 @@ module Risc # class CodeListener - attr_reader :code , :method - - def initialize(code , method) - super(code,pos) - @code = code - @method = method - raise "Method nil" unless method - end - def set(at ) + def set(at) + raise "Called" next_pos = at + code.padded_length if code.next Position.set(code.next , next_pos, method) @@ -33,7 +26,9 @@ module Risc # insert a jump to the next instruction, at the last instruction # thus hopping over the object header - def set_jump(at) + def set_jump_for(position) + at = position.at + code = position.object jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next) translator = Risc.machine.platform.translator cpu_jump = translator.translate(jump) @@ -42,20 +37,31 @@ module Risc cpu_jump.assemble(JumpWriter.new(code)) end + def position_inserted(position) + Position.log.debug "extending one in #{self}" + pos = CodeListener.init( position.object.next ) + pos.set( position + position.object.padded_length) + return unless position.valid? + set_jump_for(position) + end + + def position_changed(position) + return unless position.object.next + raise "Called" + end + # Create Position for the given BinaryCode object - # return the last position that was created, for chaining - def self.init( code , at = -1) + # return the first position that was created, to set it + def self.init( code ) + first = nil while code raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode) - position = Position.new(code , at) - if code.next - listener = PositionListener.new(code.next) - position.position_listener( listener) - end - at += code.padded_length unless at < 0 + position = Position.new(code , -1) + first = position unless first + position.position_listener(CodeListener.new) code = code.next end - position + first end end end diff --git a/test/risc/position/test_code_listener.rb b/test/risc/position/test_code_listener.rb index 10539d02..350eb6bb 100644 --- a/test/risc/position/test_code_listener.rb +++ b/test/risc/position/test_code_listener.rb @@ -20,16 +20,19 @@ module Risc def test_init_returns_position assert_equal Position , CodeListener.init(@binary).class end + def test_not_init_listner + pos = CodeListener.init(@binary) + assert CodeListener == pos.event_table[:position_changed].last.class + end def test_init_listner @binary.extend_one CodeListener.init(@binary) pos = Position.get(@binary) - assert !pos.event_table[:position_changed].empty? + assert_equal CodeListener , pos.event_table[:position_changed].first.class end - def test_not_init_listner + def test_extends_creates_jump + @binary.extend_one CodeListener.init(@binary) - pos = Position.get(@binary) - assert pos.event_table[:position_changed].empty? end end end diff --git a/test/risc/position/test_code_listener1.rb b/test/risc/position/test_code_listener1.rb new file mode 100644 index 00000000..c1c0e556 --- /dev/null +++ b/test/risc/position/test_code_listener1.rb @@ -0,0 +1,26 @@ +require_relative "helper" + +module Risc + # tests that require a boot and test propagation + class TestCodeListenerFull < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + @method = Parfait.object_space.types.values.first.methods + @label = Risc.label("hi","ho") + @machine.translate(:arm) + @machine.position_all + end + def test_listener_after_extend + CodeListener.init(@binary).set(0) + @binary.extend_one + pos = Position.get(@binary.next) + assert_equal CodeListener , pos.event_table[:position_changed].first.class + end + def test_extend_sets_next_pos + CodeListener.init(@binary).set(0) + @binary.extend_one + assert Position.get(@binary.next) + end + end +end