make elf symbols optional
and default to false. Smaller executables by at least half also add option for compiler cli
This commit is contained in:
parent
160d860db2
commit
91995dc1b3
@ -7,7 +7,9 @@ require_relative 'string_table_section'
|
||||
module Elf
|
||||
|
||||
class ObjectWriter
|
||||
def initialize( linker )
|
||||
attr_reader :text
|
||||
|
||||
def initialize( linker , options = {} )
|
||||
@linker = linker
|
||||
target = Elf::Constants::TARGET_ARM
|
||||
@object = Elf::ObjectFile.new(target)
|
||||
@ -22,7 +24,15 @@ module Elf
|
||||
assembler = Risc::TextWriter.new(@linker)
|
||||
set_text assembler.write_as_string
|
||||
|
||||
# for debug add labels for labels
|
||||
add_debug_symbols(options)
|
||||
|
||||
end
|
||||
|
||||
# for debug add labels for labels
|
||||
def add_debug_symbols(options)
|
||||
debug = options[:debug]
|
||||
return unless debug
|
||||
|
||||
@linker.assemblers.each do |asm|
|
||||
meth = asm.callable
|
||||
asm.instructions.each do |label|
|
||||
@ -34,7 +44,6 @@ module Elf
|
||||
add_symbol label , Risc::Position.get(code).at
|
||||
end
|
||||
end
|
||||
|
||||
@linker.object_positions.each do |slot , position|
|
||||
next if slot.is_a?(Parfait::BinaryCode)
|
||||
next if slot.class.name.include?("Arm")
|
||||
@ -48,8 +57,6 @@ module Elf
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :text
|
||||
|
||||
def set_text(text)
|
||||
@text.text = text
|
||||
add_symbol "_start", 0
|
||||
|
@ -5,6 +5,7 @@ require "risc/interpreter"
|
||||
class RubyXC < Thor
|
||||
class_option :integers , type: :numeric
|
||||
class_option :mesages , type: :numeric
|
||||
class_option :elf , type: :boolean
|
||||
|
||||
|
||||
desc "compile FILE" , "Compile given FILE to binary"
|
||||
@ -27,11 +28,13 @@ class RubyXC < Thor
|
||||
puts "compiling #{file}"
|
||||
|
||||
linker = ::RubyX::RubyXCompiler.new(extract_options).ruby_to_binary( ruby , :arm )
|
||||
writer = Elf::ObjectWriter.new(linker)
|
||||
elf = { debug: options[:elf] || false }
|
||||
writer = Elf::ObjectWriter.new(linker , elf)
|
||||
|
||||
outfile = file.split("/").last.gsub(".rb" , ".o")
|
||||
writer.save outfile
|
||||
|
||||
system "arm-linux-gnu-ld -N #{outfile}"
|
||||
File.delete outfile
|
||||
return outfile
|
||||
end
|
||||
|
||||
@ -92,16 +95,15 @@ class RubyXC < Thor
|
||||
|
||||
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 $?"
|
||||
puts "Running #{outfile}\n\n"
|
||||
system "qemu-arm ./a.out ;echo $?"
|
||||
end
|
||||
|
||||
private
|
||||
def extract_options
|
||||
opt = { Integer: options[:integers] || 1024 ,
|
||||
Message: options[:messages] || 1024}
|
||||
return {parfait: opt}
|
||||
return {parfait: opt }
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,47 +0,0 @@
|
||||
require_relative 'helper'
|
||||
require "yaml"
|
||||
require "parslet/convenience"
|
||||
class TestRunner < MiniTest::Test
|
||||
|
||||
# this creates test methods dynamically , one for each file in runners directory
|
||||
def self.runnable_methods
|
||||
methods = []
|
||||
Dir[File.join(File.dirname(__FILE__) , "runners" , "*.rb")].each do |file|
|
||||
meth = File.basename(file).split(".").first
|
||||
name = "test_#{meth}"
|
||||
methods << name
|
||||
self.send(:define_method, name ) {
|
||||
execute file
|
||||
}
|
||||
end
|
||||
methods
|
||||
end
|
||||
|
||||
def execute file
|
||||
string = File.read(file)
|
||||
parser = Parser::RubyX.new
|
||||
object_space = Risc::Program.new "Arm"
|
||||
#TODO : files would have to include s-expressions now
|
||||
syntax = parser.parse_with_debug(string, reporter: Parslet::ErrorReporter::Deepest.new)
|
||||
assert syntax
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
# file is a list of statements, all but the last must be a function
|
||||
# and the last is wrapped as a main
|
||||
parts.each_with_index do |part,index|
|
||||
if index == (parts.length - 1)
|
||||
expr = part.compile( program.context )
|
||||
else
|
||||
expr = part.compile( program.context )
|
||||
raise "should be function definition for now" unless expr.is_a? Risc::Function
|
||||
end
|
||||
end
|
||||
|
||||
#object writer takes machine
|
||||
writer = Elf::ObjectWriter.new(program , Elf::Constants::TARGET_ARM)
|
||||
|
||||
writer.save(file.gsub(".rb" , ".o"))
|
||||
|
||||
# puts program.to_yaml
|
||||
end
|
||||
|
||||
end
|
@ -21,61 +21,5 @@ module Elf
|
||||
writer = Elf::ObjectWriter.new(linker)
|
||||
writer.save "test/#{file}.o"
|
||||
end
|
||||
|
||||
def check_remote(file)
|
||||
check(file)
|
||||
stdout , exit_code = run_ssh(file)
|
||||
@stdout = "" unless @stdout
|
||||
assert_equal @stdout , stdout
|
||||
assert_equal @exit_code , exit_code
|
||||
end
|
||||
|
||||
def run_ssh( file )
|
||||
host = ENV["ARM_HOST"]
|
||||
return unless host
|
||||
port = (ENV["ARM_PORT"] || 2222)
|
||||
user = (ENV["ARM_USER"] || "pi")
|
||||
binary_file = "/tmp/#{file}"
|
||||
object_file = binary_file + ".o"
|
||||
Net::SCP.start(host, user , port: port ) do |scp|
|
||||
puts "Copying test/#{file}.o to #{object_file}" if DEBUG
|
||||
scp.upload! "test/#{file}.o", object_file
|
||||
end
|
||||
Net::SSH.start(host, user , port: port ) do |ssh|
|
||||
puts "Linking #{object_file}" if DEBUG
|
||||
stdout , exit_code = ssh_exec!(ssh , "ld -N -o #{binary_file} #{object_file}")
|
||||
assert_equal 0 , exit_code , "Linking #{binary_file} failed"
|
||||
puts "Running #{binary_file}" if DEBUG
|
||||
stdout , exit_code = ssh_exec!(ssh , binary_file)
|
||||
puts "Result #{stdout} #{exit_code}" if DEBUG
|
||||
return stdout , exit_code
|
||||
end
|
||||
end
|
||||
|
||||
def ssh_exec!(ssh, command)
|
||||
stdout_data = ""
|
||||
exit_code = nil
|
||||
ssh.open_channel do |channel|
|
||||
channel.exec(command) do |ch, success|
|
||||
unless success
|
||||
raise "FAILED: couldn't execute command (ssh.channel.exec)"
|
||||
end
|
||||
channel.on_data do |c,data|
|
||||
stdout_data+=data
|
||||
end
|
||||
channel.on_extended_data do |c,type,data|
|
||||
raise "#{ssh} received stderr #{data}"
|
||||
end
|
||||
channel.on_request("exit-status") do |c,data|
|
||||
exit_code = data.read_long
|
||||
end
|
||||
channel.on_request("exit-signal") do |c, data|
|
||||
raise "#{ssh} received signal #{data.read_long}"
|
||||
end
|
||||
end
|
||||
end
|
||||
ssh.loop
|
||||
[stdout_data, exit_code]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -15,7 +15,7 @@ module RubyX
|
||||
end
|
||||
def test_file_open
|
||||
assert_output(/compiling/) {RubyXC.start(["compile" , "test/mains/source/add__4.rb"])}
|
||||
File.delete "add__4.o"
|
||||
#File.delete "add__4.o"
|
||||
end
|
||||
def test_interpret
|
||||
assert_output(/interpreting/) {RubyXC.start(["interpret" , "test/mains/source/add__4.rb"])}
|
||||
|
Loading…
Reference in New Issue
Block a user