fixing assembly

position code changed and linking too
passes not working
This commit is contained in:
Torsten Ruger 2015-05-24 18:05:20 +03:00
parent 95ac024421
commit 2ccbea04b9
15 changed files with 111 additions and 182 deletions

View File

@ -5,8 +5,7 @@ module Arm
def initialize to , from , options = {} def initialize to , from , options = {}
super(options) super(options)
@to = to @to = to
raise "old code, fix this to use LoadConstant" if from.is_a? Virtual::ObjectConstant @from = from #from.is_a?(Fixnum) ? Virtual::IntegerConstant.new(from) : from
@from = from.is_a?(Fixnum) ? Virtual::IntegerConstant.new(from) : from
raise "move must have from set #{inspect}" unless from raise "move must have from set #{inspect}" unless from
@attributes[:update_status] = 0 if @attributes[:update_status] == nil @attributes[:update_status] = 0 if @attributes[:update_status] == nil
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil @attributes[:condition_code] = :al if @attributes[:condition_code] == nil

View File

@ -34,10 +34,6 @@ module Parfait
@object_layout.push name @object_layout.push name
end end
def mem_length
padded_words(3)
end
# ruby 2.1 list (just for reference, keep at bottom) # ruby 2.1 list (just for reference, keep at bottom)
#:allocate, :new, :superclass #:allocate, :new, :superclass
end end

View File

@ -33,7 +33,7 @@ module Parfait
raise "not a method #{method.class} #{method.inspect}" unless method.is_a? Method raise "not a method #{method.class} #{method.inspect}" unless method.is_a? Method
raise "syserr #{method.name.class}" unless method.name.is_a? Word raise "syserr #{method.name.class}" unless method.name.is_a? Word
@instance_methods << method @instance_methods << method
puts "#{self.name} add #{method.name}" #puts "#{self.name} add #{method.name}"
method method
end end

View File

@ -71,6 +71,10 @@ module Parfait
get_layout().index_of(name) get_layout().index_of(name)
end end
def mem_length
padded_words( get_layout().get_length() + 2 )
end
# Object # Object
# :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, # :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint,
# :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, # :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods,

View File

@ -74,10 +74,6 @@ module Parfait
raise "uups " if name.is_a? String raise "uups " if name.is_a? String
@classes[name] = c @classes[name] = c
end end
def mem_length
padded_words( 5 )
end
end end
# ObjectSpace # ObjectSpace
# :each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects # :each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects

View File

@ -22,14 +22,13 @@ module Register
@space.set_position(0) @space.set_position(0)
at = @space.mem_length # first jump instruction at = @space.mem_length # first jump instruction
# then all functions # then all functions
@objects.each_value do | objekt| @space.objects.each do | objekt|
next unless objekt.is_a? Virtual::CompiledMethod next unless objekt.is_a? Parfait::Method
objekt.set_position(at) objekt.info.set_position(at)
at += objekt.mem_length at += objekt.info.mem_length
end end
#and then all data object #and then all data object
@objects.each_value do | objekt| @objects.each do | objekt|
next if objekt.is_a? Virtual::CompiledMethod
objekt.set_position at objekt.set_position at
at += objekt.mem_length at += objekt.mem_length
end end

View File

@ -1,3 +1,4 @@
require "parfait"
require "virtual/machine" require "virtual/machine"
require "virtual/compiler" require "virtual/compiler"
@ -5,7 +6,6 @@ require "virtual/instruction"
require "virtual/compiled_method_info" require "virtual/compiled_method_info"
require "virtual/slots/slot" require "virtual/slots/slot"
require "virtual/type" require "virtual/type"
require "virtual/constants"
# the passes _are_ order dependant # the passes _are_ order dependant
require "virtual/passes/send_implementation" require "virtual/passes/send_implementation"
require "virtual/passes/get_implementation" require "virtual/passes/get_implementation"

View File

@ -7,7 +7,7 @@ module Virtual
# Blocks form a graph, which is managed by the method # Blocks form a graph, which is managed by the method
class Block < Virtual::Object class Block
def initialize(name , method ) def initialize(name , method )
super() super()

View File

@ -140,9 +140,15 @@ module Virtual
l = @blocks.inject(0) { |c , block| c += block.mem_length } l = @blocks.inject(0) { |c , block| c += block.mem_length }
padded(l) padded(l)
end end
def padded len
a = 32 * (1 + (len + 7)/32 )
#puts "#{a} for #{len}"
a
end
# position of the function is the position of the entry block, is where we call # position of the function is the position of the entry block, is where we call
def set_position at def set_position at
super
at += 8 #for the 2 header words at += 8 #for the 2 header words
@blocks.each do |block| @blocks.each do |block|
block.set_position at block.set_position at

View File

@ -1,4 +1,3 @@
require_relative "positioned" require_relative "positioned"
module Virtual module Virtual
@ -12,30 +11,6 @@ module Virtual
class Instruction class Instruction
include Positioned include Positioned
# simple thought: don't recurse for Blocks, just check their names
def == other
return false unless other.class == self.class
Sof::Util.attributes(self).each do |a|
begin
left = send(a)
rescue NoMethodError
next # not using instance variables that are not defined as attr_readers for equality
end
begin
right = other.send(a)
rescue NoMethodError
return false
end
return false unless left.class == right.class
if( left.is_a? Block)
return false unless left.name == right.name
else
return false unless left == right
end
end
return true
end
end end
end end

View File

@ -42,7 +42,9 @@ module Virtual
def run_passes def run_passes
#TODO puts "INIT #{@init}" #TODO puts "INIT #{@init}"
@passes.each do |pass_class| @passes.each do |pass_class|
puts "run pass #{pass_class}"
blocks = []#[@init] #TODO + @main.blocks blocks = []#[@init] #TODO + @main.blocks
@space.classes.values.each do |c| @space.classes.values.each do |c|
c.instance_methods.each do |f| c.instance_methods.each do |f|

View File

@ -7,6 +7,8 @@
module FakeMem module FakeMem
def initialize def initialize
@memory = [0,nil] @memory = [0,nil]
@position = nil
@length = -1
if Parfait::Space.object_space and Parfait::Space.object_space.objects if Parfait::Space.object_space and Parfait::Space.object_space.objects
Parfait::Space.object_space.add_object self Parfait::Space.object_space.add_object self
else else
@ -21,6 +23,30 @@ module FakeMem
raise "Class not found #{vm_name}" unless clazz raise "Class not found #{vm_name}" unless clazz
self.set_layout clazz.object_layout self.set_layout clazz.object_layout
end end
def position
raise "position accessed but not set at #{length} for #{self.inspect[0...500]}" if @position == nil
@position
end
def set_position pos
# resetting of position used to be error, but since relink and dynamic instruction size it is ok.
# in measures (of 32)
if @position != nil and ((@position - pos).abs > 32)
raise "position set again #{pos}!=#{@position} for #{self}"
end
@position = pos
end
# objects only come in lengths of multiple of 8 words
# but there is a constant overhead of 2 words, one for type, one for layout
# and as we would have to subtract 1 to make it work without overhead, we now have to add 7
def padded len
a = 32 * (1 + (len + 7)/32 )
#puts "#{a} for #{len}"
a
end
def padded_words words
padded(words*4) # 4 == word length, a constant waiting for a home
end
end end
module Parfait module Parfait
@ -29,6 +55,7 @@ module Parfait
# These are the same functions that Builtin implements at run-time # These are the same functions that Builtin implements at run-time
class Object class Object
include FakeMem include FakeMem
# these internal functions are _really_ internal # these internal functions are _really_ internal
# they respresent the smallest code needed to build larger functionality # they respresent the smallest code needed to build larger functionality
# but should _never_ be used outside parfait. in fact that should be impossible # but should _never_ be used outside parfait. in fact that should be impossible
@ -67,6 +94,9 @@ module Parfait
end end
class List class List
def mem_length
Virtual::Object.new.padded_words(length())
end
def to_sof_node(writer , level , ref ) def to_sof_node(writer , level , ref )
Sof.array_to_sof_node(self , writer , level , ref ) Sof.array_to_sof_node(self , writer , level , ref )
end end
@ -91,6 +121,10 @@ module Parfait
end end
class Word class Word
def mem_length
Virtual::Object.new.padded(1 + length())
end
def == other def == other
return false unless other.is_a?(String) or other.is_a?(Word) return false unless other.is_a?(String) or other.is_a?(Word)
as_string = self.to_s as_string = self.to_s
@ -112,6 +146,7 @@ module Parfait
end end
end end
module Virtual module Virtual
# Functions to generate parfait objects # Functions to generate parfait objects
def self.new_word( string ) def self.new_word( string )

View File

@ -1,5 +1,4 @@
require_relative "type" require_relative "type"
require "parfait"
module Positioned module Positioned
def position def position
@ -14,67 +13,6 @@ module Positioned
end end
@position = pos @position = pos
end end
end
module Virtual
# our machine is made up of objects, some of which are code, some data
#
# during compilation objects are module Virtual objects, but during execution they are not scoped
#
# So compiling/linking/assembly turns ::virtual objects into binary that represents ruby objects at runtime
# The equivalence is listed below (i'll try and work on clearer correspondence later)
# ::Virtual Runtime / parfait
# Object Object
# BootClass Class
# MetaClass self/Object
# Space ObjectSpace
# CompiledMethod Function
# (ruby)Array Array
# String String
class Object
include Positioned
def initialize
@position = nil
@length = -1
end
attr_accessor :length , :layout
def inspect
Sof::Writer.write(self)
end
def to_s
inspect[0..300]
end
def mem_length
raise "abstract #{self.class}"
end
@@EMPTY = { :names => [] , :types => []}
def old_layout
raise "Find me #{self}"
self.class.layout
end
def self.layout
@@EMPTY
end
# class variables to have _identical_ objects passed back (stops recursion)
@@ARRAY = { :names => [] , :types => []}
# @@HASH = { :names => [:keys,:values] , :types => [Virtual::Reference,Virtual::Reference]}
# @@CLAZZ = { :names => [:name , :super_class_name , :instance_methods] , :types => [Virtual::Reference,Virtual::Reference,Virtual::Reference]}
# @@SPACE = { :names => [:classes,:objects] , :types => [Virtual::Reference,Virtual::Reference]}
def old_layout_for(object)
case object
when Array , Symbol , String , Virtual::CompiledMethod , Virtual::Block , Parfait::Word
@@ARRAY
when Hash
@@HASH.merge :keys => object.keys , :values => object.values
when Virtual::BootClass
@@CLAZZ
when Virtual::Space
@@SPACE
else
raise "linker encounters unknown class #{object.class}"
end
end
# objects only come in lengths of multiple of 8 words # objects only come in lengths of multiple of 8 words
# but there is a constant overhead of 2 words, one for type, one for layout # but there is a constant overhead of 2 words, one for type, one for layout
# and as we would have to subtract 1 to make it work without overhead, we now have to add 7 # and as we would have to subtract 1 to make it work without overhead, we now have to add 7
@ -87,51 +25,4 @@ module Virtual
def padded_words words def padded_words words
padded(words*4) # 4 == word length, a constant waiting for a home padded(words*4) # 4 == word length, a constant waiting for a home
end end
end
end
::Parfait::Message.class_eval do
include Positioned
def old_layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
::Parfait::Frame.class_eval do
include Positioned
def old_layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
Parfait::Dictionary.class_eval do
include Positioned
HASH = { :names => [:keys,:values] , :types => [Virtual::Reference,Virtual::Reference]}
def old_layout
HASH
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
::Parfait::List.class_eval do
include Positioned
def old_layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(length())
end
end
::Parfait::Word.class_eval do
include Positioned
def old_layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded(1 + length())
end
end end

View File

@ -30,7 +30,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
require 'salama' require 'salama'
Virtual::Object.class_eval do class Ignored
def == other def == other
return false unless other.class == self.class return false unless other.class == self.class
Sof::Util.attributes(self).each do |a| Sof::Util.attributes(self).each do |a|

View File

@ -28,3 +28,29 @@ module VirtualHelper
end end
end end
class UnusedSofEquality
# simple thought: don't recurse for Blocks, just check their names
def == other
return false unless other.class == self.class
Sof::Util.attributes(self).each do |a|
begin
left = send(a)
rescue NoMethodError
next # not using instance variables that are not defined as attr_readers for equality
end
begin
right = other.send(a)
rescue NoMethodError
return false
end
return false unless left.class == right.class
if( left.is_a? Block)
return false unless left.name == right.name
else
return false unless left == right
end
end
return true
end
end