to make smaller binaries with larger integer heaps also ran some benchmarks to see if it makes a difference at least the binaries are smaller, calling also faster
108 lines
3.4 KiB
Ruby
108 lines
3.4 KiB
Ruby
require "thor"
|
|
require "rubyx"
|
|
require "risc/interpreter"
|
|
|
|
class RubyXC < Thor
|
|
class_option :integers , type: :numeric
|
|
class_option :mesages , type: :numeric
|
|
|
|
|
|
desc "compile FILE" , "Compile given FILE to binary"
|
|
long_desc <<-LONGDESC
|
|
Compile the give file name to binary object file (see long descr.)
|
|
|
|
Output will be elf object file of the same name, with .o, in root directory.
|
|
|
|
Note: Because of Bug #13, you need to run "ld -N file.o" on the file, before
|
|
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.
|
|
LONGDESC
|
|
|
|
def compile(file)
|
|
begin
|
|
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 )
|
|
writer = Elf::ObjectWriter.new(linker)
|
|
|
|
outfile = file.split("/").last.gsub(".rb" , ".o")
|
|
writer.save outfile
|
|
|
|
return outfile
|
|
end
|
|
|
|
|
|
desc "interpret FILE" , "Interpret given FILE "
|
|
long_desc <<-LONGDESC
|
|
Compiles the given file to an intermediate RISC format, and runs the
|
|
Interpreter.
|
|
|
|
RISC is the last abstract layer inside the compiler. It is in nature
|
|
very close to arm (without quirks and much smaller).
|
|
|
|
An interpreter was originally developed for the RISC layer for debugging purposes.
|
|
Running the interpreter is about 50k slower than binary, but it can be used
|
|
to veryfy simple programs.
|
|
|
|
No output file will be generated, the only output is generated by the
|
|
given program.
|
|
|
|
The program must define a main method on the Space class, which will be invoked.
|
|
LONGDESC
|
|
|
|
def interpret(file)
|
|
begin
|
|
ruby = File.read(file)
|
|
rescue
|
|
fail MalformattedArgumentError , "No such file #{file}"
|
|
end
|
|
compiler = RubyX::RubyXCompiler.new(extract_options)
|
|
linker = compiler.ruby_to_binary(ruby, :interpreter)
|
|
|
|
puts "interpreting #{file}"
|
|
|
|
interpreter = Risc::Interpreter.new(linker , STDOUT )
|
|
interpreter.start_program
|
|
interpreter.tick while(interpreter.instruction)
|
|
|
|
end
|
|
|
|
desc "execute FILE" , "Compile given FILE and execute resulting binary"
|
|
long_desc <<-LONGDESC
|
|
Just like the compile task, this compiles the file to an object/binary file.
|
|
|
|
Then rubyxc will link and run the resulting object file. For this to work,
|
|
qemu needs to be set up correctly on the system. Specifically, because of
|
|
bug #13, arm-linux-gnueabihf-ld needs to exist (it's part of the cross compiled
|
|
arm binutils).
|
|
|
|
The resulting a.out will be run via qemu-arm. This is part of the qemu "linux" package
|
|
and interprets the arm binary on the host, assuming a linux os.
|
|
|
|
This whole approach should only be used for preliminary checking that no core-dumps
|
|
are generated by the program, or when no benchmarking (as the times will be whatever).
|
|
|
|
For simple functional test though, it is a much much quicker way to run the binary
|
|
than transferring it to another machine. The a.out is left in place to be run again.
|
|
LONGDESC
|
|
|
|
def execute(file)
|
|
outfile = compile(file)
|
|
system "arm-linux-gnu-ld -N #{outfile}"
|
|
puts "Linked ok, now running #{outfile}"
|
|
system "qemu-arm ./a.out ; echo $?"
|
|
end
|
|
|
|
private
|
|
def extract_options
|
|
opt = { Integer: options[:integers] || 1024 ,
|
|
Message: options[:messages] || 1024}
|
|
return {parfait: opt}
|
|
end
|
|
|
|
end
|