add a statistics command to compiler
just to see how many objects make up a binary
This commit is contained in:
parent
91995dc1b3
commit
7d92ee9e6a
@ -3,11 +3,17 @@ require_relative "binary_writer"
|
|||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
|
|
||||||
# From code, the next step down is Vool, then Mom (in two steps)
|
# A RiscCollection is the last virtual stop on the way to binary.
|
||||||
#
|
# It creates a Linker to go to binary. The name linker came in analogy to
|
||||||
# The next step transforms to the register machine layer, which is quite close to what actually
|
# "normal" (ie c world) lingo, because there too the linker is all about
|
||||||
# executes. The step after transforms to Arm, which creates executables.
|
# positioning code and data.
|
||||||
#
|
#
|
||||||
|
# Here we also do the assembling, which (at least in arm) creates this mess
|
||||||
|
# of dependencies. As a simple example imagine a branch, a load and the label
|
||||||
|
# to which we jump. The brnahc needs the address, but the load may be 4 or 8
|
||||||
|
# instructions, and thus the label address is only known after the load.
|
||||||
|
# Exrapolate times 10, that's why this works with listeners and a sort
|
||||||
|
# of self organizing aproach (see class Position).
|
||||||
|
|
||||||
class Linker
|
class Linker
|
||||||
include Util::Logging
|
include Util::Logging
|
||||||
|
@ -7,7 +7,7 @@ module Risc
|
|||||||
# into one stream or binary text object. This is then written to an ELF text section.
|
# into one stream or binary text object. This is then written to an ELF text section.
|
||||||
#
|
#
|
||||||
# A word about positions: The c world has a thing called position independent code, and
|
# A word about positions: The c world has a thing called position independent code, and
|
||||||
# baically we follw that idea. Code (ie jumps and constant loads) are all relative.
|
# basically we follw that idea. Code (ie jumps and constant loads) are all relative.
|
||||||
# But we have pointers. In C the linker takes care of bending those, we have to
|
# But we have pointers. In C the linker takes care of bending those, we have to
|
||||||
# do that ourselves, in write_ref. That's why we need the load adddess and basically
|
# do that ourselves, in write_ref. That's why we need the load adddess and basically
|
||||||
# we just add it to pointers.
|
# we just add it to pointers.
|
||||||
|
@ -7,10 +7,35 @@ class RubyXC < Thor
|
|||||||
class_option :mesages , type: :numeric
|
class_option :mesages , type: :numeric
|
||||||
class_option :elf , type: :boolean
|
class_option :elf , type: :boolean
|
||||||
|
|
||||||
|
desc "stats FILE" , "Give object statistics on compiled FILE"
|
||||||
|
long_desc <<-LONGDESC
|
||||||
|
Compile the give file name and print statistics on the binary.
|
||||||
|
A Binary file is in essence an ObjectSpace, ie a collection of objects.
|
||||||
|
|
||||||
|
This command tells you how many objects of each kind, the amount of bytes
|
||||||
|
objects of that class take, and the total amount of bytes taken.
|
||||||
|
|
||||||
|
Together with various options this may be used to tune the executable, or just fyi.
|
||||||
|
LONGDESC
|
||||||
|
def stats(file)
|
||||||
|
compile(file)
|
||||||
|
by_class = Hash.new(0)
|
||||||
|
Risc::Position.positions.each do |object , _ |
|
||||||
|
by_class[object.class] += 1 if Risc::Position.is_object(object)
|
||||||
|
end
|
||||||
|
obj, total = 0 , 0
|
||||||
|
by_class.each do |clazz , num|
|
||||||
|
dis = (clazz == Symbol) ? 8 : clazz.memory_size
|
||||||
|
puts clazz.name.split("::").last + " == #{num} / #{num*dis}"
|
||||||
|
obj += num
|
||||||
|
total += num * dis
|
||||||
|
end
|
||||||
|
puts "\nTotal Objects=#{obj} Words=#{total}"
|
||||||
|
end
|
||||||
|
|
||||||
desc "compile FILE" , "Compile given FILE to binary"
|
desc "compile FILE" , "Compile given FILE to binary"
|
||||||
long_desc <<-LONGDESC
|
long_desc <<-LONGDESC
|
||||||
Compile the give file name to binary object file (see long descr.)
|
Compile the give file name to binary object file (see below.)
|
||||||
|
|
||||||
Output will be elf object file of the same name, with .o, in root directory.
|
Output will be elf object file of the same name, with .o, in root directory.
|
||||||
|
|
||||||
@ -18,16 +43,9 @@ class RubyXC < Thor
|
|||||||
executing it. This can be done on a mac by installing a cross linker
|
executing it. This can be done on a mac by installing a cross linker
|
||||||
(brew install arm-linux-gnueabihf-binutils), or on the target arm machine.
|
(brew install arm-linux-gnueabihf-binutils), or on the target arm machine.
|
||||||
LONGDESC
|
LONGDESC
|
||||||
|
|
||||||
def compile(file)
|
def compile(file)
|
||||||
begin
|
linker = do_compile(file)
|
||||||
ruby = File.read(file)
|
|
||||||
rescue
|
|
||||||
fail MalformattedArgumentError , "No such file #{file}"
|
|
||||||
end
|
|
||||||
puts "compiling #{file}"
|
|
||||||
|
|
||||||
linker = ::RubyX::RubyXCompiler.new(extract_options).ruby_to_binary( ruby , :arm )
|
|
||||||
elf = { debug: options[:elf] || false }
|
elf = { debug: options[:elf] || false }
|
||||||
writer = Elf::ObjectWriter.new(linker , elf)
|
writer = Elf::ObjectWriter.new(linker , elf)
|
||||||
|
|
||||||
@ -100,6 +118,17 @@ class RubyXC < Thor
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Open file, create compiler, compile and return linker
|
||||||
|
def do_compile(file)
|
||||||
|
begin
|
||||||
|
ruby = File.read(file)
|
||||||
|
rescue
|
||||||
|
fail MalformattedArgumentError , "No such file #{file}"
|
||||||
|
end
|
||||||
|
puts "compiling #{file}"
|
||||||
|
::RubyX::RubyXCompiler.new(extract_options).ruby_to_binary( ruby , :arm )
|
||||||
|
end
|
||||||
|
|
||||||
def extract_options
|
def extract_options
|
||||||
opt = { Integer: options[:integers] || 1024 ,
|
opt = { Integer: options[:integers] || 1024 ,
|
||||||
Message: options[:messages] || 1024}
|
Message: options[:messages] || 1024}
|
||||||
|
@ -20,5 +20,14 @@ module RubyX
|
|||||||
def test_interpret
|
def test_interpret
|
||||||
assert_output(/interpreting/) {RubyXC.start(["interpret" , "test/mains/source/add__4.rb"])}
|
assert_output(/interpreting/) {RubyXC.start(["interpret" , "test/mains/source/add__4.rb"])}
|
||||||
end
|
end
|
||||||
|
def test_execute
|
||||||
|
assert_output(/Running/) {RubyXC.start(["execute" , "test/mains/source/add__4.rb"])}
|
||||||
|
end
|
||||||
|
def test_stats
|
||||||
|
out, err = capture_io {RubyXC.start(["stats" , "test/mains/source/add__4.rb"])}
|
||||||
|
assert out.include?("Space") , out
|
||||||
|
assert out.include?("Total") , out
|
||||||
|
assert out.include?("Objects=") , out
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user