From b125a7c5c7533533b2528e78bd7c0fb80346f4ed Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Wed, 11 Jun 2014 21:36:22 +0300 Subject: [PATCH] fix passes, add noop reduction, remove the wretched value operators --- lib/arm/arm_machine.rb | 1 - lib/vm/boot_space.rb | 25 ++++++++++++++----------- lib/vm/function.rb | 2 +- lib/vm/passes.rb | 21 +++++++++++++++++---- lib/vm/values.rb | 18 +++++++++--------- test/fragments/test_while_fibo.rb | 1 + 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index f75e945c..06e96081 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -128,7 +128,6 @@ module Arm sys_and_ret = Vm::Integer.new( Vm::RegisterMachine.instance.return_register ) block.do_add mov( sys_and_ret , num ) block.do_add swi( 0 ) - block.do_add mov( sys_and_ret , return_register ) # syscall returns in r0, more to our return #todo should write type into r0 according to syscall sys_and_ret end diff --git a/lib/vm/boot_space.rb b/lib/vm/boot_space.rb index 188aa6a8..0e23795f 100644 --- a/lib/vm/boot_space.rb +++ b/lib/vm/boot_space.rb @@ -39,7 +39,7 @@ module Vm #main gets executed between entry and exit @exit = RegisterMachine.instance.main_exit @context boot_classes - @passes = [ MoveMoveReduction.new, LogicMoveReduction.new, SaveLocals.new ] + @passes = [ MoveMoveReduction.new , LogicMoveReduction.new, NoopReduction.new, SaveLocals.new ] end attr_reader :context , :main , :classes , :entry , :exit @@ -55,6 +55,10 @@ module Vm end end + # boot the classes, ie create a minimal set of classes with a minimal set of functions + # minimal means only that which can not be coded in ruby + # Functions are grabbed from respective modules by sending the sunction name. This should return the + # implementation of the function (ie a function object), not actually try to implement it (as that's impossible in ruby) def boot_classes # very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we have to define some # dummies, just for the other to compile @@ -69,12 +73,16 @@ module Vm obj.add_function Boot::String.send(f , @context) end end + + # Objects are data and get assembled after functions def add_object o return if @objects.include? o raise "must be derived from Code #{o.inspect}" unless o.is_a? Code @objects << o # TODO check type , no basic values allowed (must be wrapped) end - + + # this is the way to instantiate classes (not BootBlass.new) + # so we get and keep exactly one per name def get_or_create_class name raise "uups #{name}.#{name.class}" unless name.is_a? Symbol c = @classes[name] @@ -85,15 +93,15 @@ module Vm c end - # linking entry , main , exit , classes , objects + # linking entry , exit , main , classes , objects def link_at( start , context) super @entry.link_at( start , context ) start += @entry.length - @main.link_at( start , context ) - start += @main.length @exit.link_at( start , context) start += @exit.length + @main.link_at( start , context ) + start += @main.length @classes.values.each do |clazz| clazz.link_at(start , context) start += clazz.length @@ -108,8 +116,8 @@ module Vm def assemble( io ) link_at( @position , nil) #second link in case of forward declarations @entry.assemble( io ) - @main.assemble( io ) @exit.assemble( io ) + @main.assemble( io ) @classes.values.each do |clazz| clazz.assemble(io) end @@ -118,10 +126,5 @@ module Vm end io end - - def main= code - @main = code - end - end end diff --git a/lib/vm/function.rb b/lib/vm/function.rb index 19cfa932..53b37367 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -130,7 +130,7 @@ module Vm # This does _not_ change the insertion point, that has do be done with insert_at(block) def new_block new_name block_name = "#{@insert_at.name}_#{new_name}" - new_b = Block.new( block_name , @function , @insert_at.next ) + new_b = Block.new( block_name , self , @insert_at.next ) @insert_at.set_next new_b return new_b end diff --git a/lib/vm/passes.rb b/lib/vm/passes.rb index 593bbebd..7bdd1158 100644 --- a/lib/vm/passes.rb +++ b/lib/vm/passes.rb @@ -10,7 +10,7 @@ module Vm def run block block.codes.dup.each_with_index do |kode , index| next unless kode.is_a? StackInstruction - if kode.regiters.empty? + if kode.registers.empty? block.codes.delete(kode) puts "deleted stack instruction in #{b.name}" end @@ -31,6 +31,8 @@ module Vm next unless kode.is_a? LogicInstruction next unless n.is_a? MoveInstruction if kode.result == n.from + puts "KODE #{kode.result.inspect}" + puts "N #{n.from.inspect}" kode.result = n.to block.codes.delete(n) end @@ -56,6 +58,19 @@ module Vm end end + #As the name says, remove no-ops. Currently mov x , x supported + class NoopReduction + def run block + block.codes.dup.each_with_index do |kode , index| + next unless kode.is_a? MoveInstruction + if kode.to == kode.from + block.codes.delete(kode) + puts "deleted noop move in #{block.name}" + end + end + end + end + # We insert push/pops as dummies to fill them later in CallSaving # as we can not know ahead of time which locals wil be live in the code to come # and also we don't want to "guess" later where the push/pops should be @@ -64,11 +79,9 @@ module Vm # Or sometimes just remove the push/pops, when no locals needed saving class SaveLocals def run block - unless block.function - puts "No function for #{block.name}" - end push = block.call_block? return unless push + return unless block.function locals = block.function.locals_at block pop = block.next.codes.first if(locals.empty?) diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 9c3e5336..d50df05c 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -126,15 +126,15 @@ module Vm def less_than block , right RegisterMachine.instance.integer_less_than block , self , right end - def == other - code = class_for(CompareInstruction).new(self , other , opcode: :cmp) - end - def + other - class_for(LogicInstruction).new(nil , self , other , opcode: :add) - end - def - other - class_for(LogicInstruction).new(nil , self , other , opcode: :sub )#, update_status: 1 ) - end +# def == other +# code = class_for(CompareInstruction).new(self , other , opcode: :cmp) +# end +# def + other +# class_for(LogicInstruction).new(nil , self , other , opcode: :add) +# end +# def - other +# class_for(LogicInstruction).new(nil , self , other , opcode: :sub )#, update_status: 1 ) +# end def at_index block , left , right RegisterMachine.instance.integer_at_index block , self , left , right end diff --git a/test/fragments/test_while_fibo.rb b/test/fragments/test_while_fibo.rb index 28e12ac6..ba253908 100644 --- a/test/fragments/test_while_fibo.rb +++ b/test/fragments/test_while_fibo.rb @@ -32,6 +32,7 @@ HERE def test_kernel_fibo int = Vm::Integer.new(1) fibo = @object_space.get_or_create_class(:Object).get_or_create_function(:fibo) + #HACk this with send main = @object_space.main main.mov int , 10 ret = main.call( fibo )