From 8955cf31dae8409cedbd2c3190e9fda4d5287131 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Wed, 23 Apr 2014 11:14:25 +0300 Subject: [PATCH] really remove externs --- lib/asm/arm/arm_assembler.rb | 13 +- lib/asm/arm/generator_label.rb | 8 -- lib/asm/assembler.rb | 32 ----- lib/asm/label_object.rb | 10 -- test/small_program_test.rb | 18 --- unused/addr_table_object.rb | 48 ------- unused/ast_assembler.rb | 85 ------------- unused/code_generator.rb | 29 ----- unused/command_line.rb | 149 ---------------------- unused/elf_object.rb | 19 --- unused/parser.rb | 223 --------------------------------- unused/str_scanner.rb | 65 ---------- 12 files changed, 1 insertion(+), 698 deletions(-) delete mode 100644 unused/addr_table_object.rb delete mode 100644 unused/ast_assembler.rb delete mode 100644 unused/code_generator.rb delete mode 100644 unused/command_line.rb delete mode 100644 unused/elf_object.rb delete mode 100644 unused/parser.rb delete mode 100644 unused/str_scanner.rb diff --git a/lib/asm/arm/arm_assembler.rb b/lib/asm/arm/arm_assembler.rb index 50f0b19f..2061a904 100644 --- a/lib/asm/arm/arm_assembler.rb +++ b/lib/asm/arm/arm_assembler.rb @@ -35,7 +35,7 @@ module Asm node.args << add_string(arg) elsif (arg.is_a?(Symbol)) node.args << Asm::LabelRefNode.new(arg.to_s) - elsif (arg.is_a?(Asm::Arm::GeneratorLabel) or arg.is_a?(Asm::Arm::GeneratorExternLabel)) + elsif (arg.is_a?(Asm::Arm::GeneratorLabel)) node.args << arg else raise 'Invalid argument `%s\' for instruction' % arg.inspect @@ -65,17 +65,6 @@ module Asm } } - #externs dropped for now - def extern(sym) - if (lbl = @externs.find { |extern| extern.name == sym }) - lbl - else - @externs << lbl = Asm::Arm::GeneratorExternLabel.new(sym) - add_value lbl - lbl - end - end - def assemble_to_string #put the strings at the end of the assembled code. # adding them will fix their position and make them assemble after diff --git a/lib/asm/arm/generator_label.rb b/lib/asm/arm/generator_label.rb index 0b16d25b..16eab7b6 100644 --- a/lib/asm/arm/generator_label.rb +++ b/lib/asm/arm/generator_label.rb @@ -15,11 +15,3 @@ class Asm::Arm::GeneratorLabel < Asm::LabelObject self end end - -class Asm::Arm::GeneratorExternLabel < Asm::LabelObject - def initialize(name) - @name = name - extern! - end - attr_reader :name -end diff --git a/lib/asm/assembler.rb b/lib/asm/assembler.rb index 6712aa5b..e439da23 100644 --- a/lib/asm/assembler.rb +++ b/lib/asm/assembler.rb @@ -48,37 +48,5 @@ module Asm end end -# class Relocation -# def initialize(pos, label, type, handler) -# @position = pos -# @label = label -# @type = type -# @handler = handler -# end -# attr_reader :position, :label, :type, :handler -# end - -#old assemble function -#def assemble(io) -# @values.each do |obj| -# obj.assemble io, self -# end -# @relocations.delete_if do |reloc| -# io.seek reloc.position -# #puts "reloc #{reloc.inspect}" -# if (reloc.label.extern?) -# reloc.handler.call(io, io.tell, reloc.type) -# else -# reloc.handler.call(io, reloc.label.address, reloc.type) -# end -# not reloc.label.extern? - #end -#end -#def add_relocation(*args) -# reloc = Asm::Relocation.new(*args) -# #raise "reloc #{reloc.inspect}" -# @relocations << reloc -#end - end diff --git a/lib/asm/label_object.rb b/lib/asm/label_object.rb index 0834aeeb..36c19c9d 100644 --- a/lib/asm/label_object.rb +++ b/lib/asm/label_object.rb @@ -3,13 +3,10 @@ module Asm class LabelObject def initialize @address = nil - @extern = false end attr_writer :address def address - return 0 if extern? - if (@address.nil?) raise 'Tried to use label object that has not been set' end @@ -20,13 +17,6 @@ module Asm self.address = io.tell end - def extern? - @extern - end - - def extern! - @extern = true - end end end \ No newline at end of file diff --git a/test/small_program_test.rb b/test/small_program_test.rb index ff07ae3c..e9946c26 100644 --- a/test/small_program_test.rb +++ b/test/small_program_test.rb @@ -38,24 +38,6 @@ class TestSmallProg < MiniTest::Test write(7 + hello.length/4 + 1 , 'hello') end - #test dropped along with functionality, didn't work and not needed (yet?) TODO - def no_test_extern - @generator.instance_eval { - mov r0 , 50 #1 - push lr #2 - bl extern(:putchar) #3 - pop pc #4 - mov r7, 1 #5 - swi 0 #6 6 instructions - } - #this actually seems to get an extern symbol out there and linker is ok (but doesnt run, hmm) - @generator.relocations.each { |reloc| - #puts "reloc #{reloc.inspect}" - writer.add_reloc_symbol reloc.label.name.to_s - } - write( 6 , "extern") - end - #helper to write the file def write len ,name writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) diff --git a/unused/addr_table_object.rb b/unused/addr_table_object.rb deleted file mode 100644 index 0880eca3..00000000 --- a/unused/addr_table_object.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Asm - module Arm - - # TODO actually find the closest somehow (DROPPED for now) - def self.closest_addrtable(as) - as.values.find do |obj| - obj.is_a?(Asm::Arm::AddrTableObject) - end || (raise Asm::AssemblyError.new('could not find addrtable to use', nil)) - end - - - #this has been DROPPED for now (didn't work) and we can do without it - class AddrTableObject - def initialize - @table = [] - @const = [] - end - - # TODO don't create new entry if there's already an entry for the same label/const - def add_label(label) - d = [label, Asm::LabelObject.new] - @table << d - d[1] - end - - def add_const(const) - d = [const, Asm::LabelObject.new] - @const << d - d[1] - end - - def assemble(io, as) - @table.each do |pair| - target_label, here_label = *pair - here_label.assemble io, as - as.add_relocation io.tell, target_label, Asm::Arm::R_ARM_ABS32, - Asm::Arm::Instruction::RelocHandler - io.write_uint32 0 - end - @const.each do |pair| - const, here_label = *pair - here_label.assemble io, as - io.write_uint32 const - end - end - end - end -end \ No newline at end of file diff --git a/unused/ast_assembler.rb b/unused/ast_assembler.rb deleted file mode 100644 index a30e7b16..00000000 --- a/unused/ast_assembler.rb +++ /dev/null @@ -1,85 +0,0 @@ -module Asm - class AstAssembler - def initialize(asm_arch) - @asm_arch = asm_arch - - @symbols = {} - @inst_label_context = {} - - @asm = Asm::Assembler.new - end - - def assembler - @asm - end - - def load_ast(ast) - label_breadcrumb = [] - ast.children.each do |cmd| - if (cmd.is_a?(Asm::LabelNode)) - m = /^\/+/.match(cmd.name) - count = m ? m[0].length : 0 - label_breadcrumb = label_breadcrumb[0,count] - label_breadcrumb << cmd.name[count..-1] - @asm.add_value object_for_label(label_breadcrumb.join('/')) - elsif (cmd.is_a?(Asm::InstructionNode)) - inst = @asm_arch::Instruction.new(cmd, self) - @asm.add_value inst - @inst_label_context[inst] = label_breadcrumb - elsif (cmd.is_a?(Asm::DirectiveNode)) - if (cmd.name == 'global') - symbol_for_label(cmd.value)[:linkage] = Elf::Constants::STB_GLOBAL - elsif (cmd.name == 'extern') - object_for_label(cmd.value).extern! - elsif (cmd.name == 'hexdata') - bytes = cmd.value.strip.split(/\s+/).map do |hex| - hex.to_i(16) - end.pack('C*') - @asm.add_value Asm::StringNode.new(bytes) - elsif (cmd.name == "asciz") - str = eval(cmd.value) + "\x00" - @asm.add_value Asm::StringNode.new(str) - elsif (defined?(Asm::Arm) and cmd.name == 'addrtable') - @asm.add_value Asm::Arm::AddrTableObject.new - else - raise Asm::AssemblyError.new('unknown directive', cmd) - end - end - end - end - - # instruction is user for label context - def symbol_for_label(name, instruction=nil) - if (instruction) - context = @inst_label_context[instruction] - m = /^(\/*)(.+)/.match(name) - breadcrumb = context[0,m[1].length] - breadcrumb << m[2] - qual_name = breadcrumb.join('/') - else - qual_name = name - end - - if (not @symbols[qual_name]) - @symbols[name] = {:label => Asm::LabelObject.new, :linkage => Elf::Constants::STB_LOCAL, :name => qual_name} - end - @symbols[qual_name] - end - - def object_for_label(name, instruction=nil) - symbol_for_label(name, instruction)[:label] - end - - def assemble(io) - @asm.assemble io - end - - def symbols - @symbols.values - end - - def relocations - @asm.relocations - end - end -end \ No newline at end of file diff --git a/unused/code_generator.rb b/unused/code_generator.rb deleted file mode 100644 index 8a5b9021..00000000 --- a/unused/code_generator.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "asm/arm/code_generator" - -if (__FILE__ == $0) - gen = Asm::Arm::ArmAssembler.new - - gen.instance_eval { - mov r0, 5 - loop_start = label - loop_start.set! - subs r0, r0, 1 - bne loop_start - mov r7, 1 - swi 0 - } - - gen.add_string("printf"+ "\x00") - require 'asm/object_writer' - writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) - writer.set_text gen.assemble_to_string - - - begin - writer.save('arm_as_generated.o') - rescue => err - puts 'as: cannot save output file: ' + err.message - exit - end - -end diff --git a/unused/command_line.rb b/unused/command_line.rb deleted file mode 100644 index e184cf87..00000000 --- a/unused/command_line.rb +++ /dev/null @@ -1,149 +0,0 @@ -require_relative 'parser' -require_relative 'assembler' -require_relative 'objectwriter' -require 'optparse' -require 'ostruct' - -module Asm - class CommandLine - def initialize - options = OpenStruct.new - options.output_file = "a.out" - options.target = :arm - - opts = OptionParser.new do |opts| - opts.banner = "Usage: as [options] " - - opts.separator "" - opts.separator "Options:" - - opts.on("-t", "--target TARGET", - "Specify target architecture (arm [default], ttk91)") { |o| - options.target = o.to_sym - if (not [:arm, :ttk91].include?(options.target)) - puts opts - exit - end - } - - opts.on("-o", "--output FILENAME", - "Specify output filename for object file") { |o| - options.output_file = o - } - - opts.on("-s", "--show-ast", - "Show parse tree") { |o| - options.show_ast = true - } - - opts.on_tail("-h", "--help", "Show this message") { - puts opts - exit - } - end - - opts.parse!(ARGV) - - options.input_file = ARGV.shift - if (not options.input_file) - puts opts - exit - end - - @options = options - end - attr_reader :options - - def run - begin - if (options.input_file == '-') - code = $stdin.read - else - code = File.read(options.input_file) - end - rescue => err - puts 'as: could not read input file: ' + err.message - exit 2 - end - - begin - ast = Asm::Parser.parse(code) - rescue Asm::ParseError => err - puts 'as: parse error on line %d, column %d' % [err.line+1, err.column+1] - line = code.split("\n")[err.line] - puts line.gsub(/\s/, ' ') - puts ' ' * (err.column-1) + '^' - puts ' ' + err.message - exit 3 - end - - if (options.show_ast) - require 'pp' - pp ast - exit 0 - end - - case options.target - when :arm - require_relative 'arm_assembler.rb' - as_module = Asm::Arm - as_target = Elf::Constants::TARGET_ARM - when :ttk91 - require_relative 'ttk91_assembler.rb' - as_module = Asm::TTK91 - as_target = Elf::Constants::TARGET_TTK91 - end - - asm = Asm::AstAssembler.new(as_module) - begin - asm.load_ast ast - data = StringIO.new - asm.assemble(data) - symbols = asm.symbols - rescue Asm::AssemblyError => err - if (err.node) - puts 'as: assembly error on line %d, column %d' % [ - err.node.line+1, err.node.column+1] - line = code.split("\n")[err.node.line] - puts line.gsub(/\s/, ' ') - puts ' ' * (err.node.column-1) + '^' - puts ' ' + err.message - else - puts 'as: ' + err.message - end - exit 4 - end - - writer = Asm::ObjectWriter.new(as_target) - writer.set_text data.string - - reloc_name_ref = {} - - symbols.each { |symbol| - label = symbol[:label] - if (label.extern?) - reloc_name_ref[label] = symbol[:name] - writer.add_reloc_symbol symbol[:name] - else - writer.add_symbol symbol[:name], symbol[:label].address, symbol[:linkage] - end - } - - asm.relocations.each { |reloc| - writer.add_reloc reloc.position, reloc_name_ref[reloc.label], reloc.type - } - - begin - writer.save(options.output_file) - rescue => err - puts 'as: cannot save output file: ' + err.message - end - end - end - -end - - -if (__FILE__ == $0) - Asm::CommandLine.new.run -end diff --git a/unused/elf_object.rb b/unused/elf_object.rb deleted file mode 100644 index 13b44219..00000000 --- a/unused/elf_object.rb +++ /dev/null @@ -1,19 +0,0 @@ -if (__FILE__ == $0) - obj = Elf::ObjectFile.new Elf::TARGET_ARM - - sym_strtab = Elf::StringTableSection.new(".strtab") - obj.add_section sym_strtab - symtab = Elf::SymbolTableSection.new(".symtab", sym_strtab) - obj.add_section symtab - - text_section = Elf::TextSection.new(".text") - obj.add_section text_section - - symtab.add_func_symbol "_start", 0, text_section, Elf::STB_GLOBAL - - fp = File.open("test.o", "wb") - obj.write fp - - fp.close -end - diff --git a/unused/parser.rb b/unused/parser.rb deleted file mode 100644 index ba65068a..00000000 --- a/unused/parser.rb +++ /dev/null @@ -1,223 +0,0 @@ -require_relative 'str_scanner' -require_relative 'nodes' -class NumEquivAddrNode < NumLiteralNode -end -class LabelEquivAddrNode < LabelRefNode -end -class ToplevelNode < Node - attr_accessor :children -end -class DirectiveNode < Node - attr_accessor :name, :value -end -class LabelNode < Node - attr_accessor :name -end -class MathNode < Node - attr_accessor :left, :right, :op - alias_method :argument, :left - alias_method :argument=, :left= -end - - -module Asm - class Parser - def initialize(str) - scanner = Asm::Scanner.new(str) - - @ast = parse_toplevel scanner - end - attr_reader :ast - - def self.parse(str) - new(str).ast - end - - def parse_toplevel(s) - node = ToplevelNode.new(s) - node.children = [] - while (not s.eos?) - node.children << parse(s) - end - node - end - - def parse(s) - s.scan /\s*/ - node = nil - %w(comment directive label instruction).each { |em| - if (node = send('parse_'+em, s)) - break - end - } - raise Asm::ParseError.new('could not parse element', s) unless node - s.scan /\s*/ - node - end - - def parse_comment(s) - if (s.scan(/;.*?$/)) - CommentNode.new(s) - end - end - - def parse_directive(s) - if (m = s.scan(/\.(\w+)(?:(?!$)\s+(.+)\s*?$)?/)) - DirectiveNode.new(s) { |n| - n.name = m[0] - n.value = m[1] - } - end - end - - def parse_label(s) - if (m = s.scan(/(\/*\w+):/)) - LabelNode.new(s) { |n| - n.name = m[0] - } - end - end - - def parse_instruction(s) - if (m = s.scan(/(\w+)/)) - node = InstructionNode.new(s) { |n| - n.opcode = m[0] - n.args = [] - } - if (not s.scan(/\s*($|;)/)) - loop { - arg = parse_arg(s) - node.args << arg - break if not s.scan(/\s*,/) - } - end - node - end - end - - def parse_arg(s) - s.scan /\s*/ - node = nil - %w(reference register register_list num_literal label_ref).each { |em| - if (node = send('parse_'+em, s)) - break - end - } - raise Asm::ParseError.new('expected argument but none found', s) unless node - - if (node2 = parse_arg_op(s)) - node2.argument = node - node = node2 - end - - s.scan /\s*/ - node - end - - def parse_arg_op(s) - s.scan /\s*/ - node = nil - %w(shift math).each do |em| - if (node = send('parse_'+em, s)) - break - end - end - s.scan /\s*/ - node - end - - def parse_shift(s) - if (m = s.scan(/(lsl|lsr|asr|ror|rrx)\s+/i)) - op = m[0].downcase - if (op == 'rrx' or arg = parse_arg(s)) - ShiftNode.new(s) { |n| - n.type = m[0].downcase - n.value = arg - } - else - nil - end - end - end - - def parse_math(s) - if (m = s.scan_str(/[\+\-]/)) - if (arg1 = parse_arg(s)) - MathNode.new(s) do |n| - n.right = arg1 - n.op = m - end - else - raise Asm::ParseError.new('expected right side for arithmetic op', s) - end - end - end - - REGISTER_REGEXP = Regexp.union(*%w(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 - r13 r14 r15 a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 - rfp sl fp ip sp lr pc - )) - def parse_register(s) - if (m = s.scan_str(REGISTER_REGEXP)) - RegisterNode.new(s) { |n| - n.name = m - } - end - end - - def parse_register_list(s) - if (m = s.scan(/\{/)) - node = RegisterListNode.new(s) do |n| - n.registers = [] - end - loop do - s.scan /\s*/ - reg = parse_register(s) - if (not reg) - return nil - end - s.scan /\s*,?/ - - node.registers << reg - - if (s.scan(/\}/)) - break - end - end - node - end - end - - def parse_num_literal(s) - if (m = s.scan(/(=?)#(-?(?:0x)?[0-9A-Fa-f]+)/)) - (m[0] == '=' ? NumEquivAddrNode : NumLiteralNode).new(s) { |n| - n.value = Integer(m[1]) - } - end - end - - def parse_label_ref(s) - if (m = s.scan(/(=?)(\/*\w+)/)) - (m[0] == '=' ? LabelEquivAddrNode : LabelRefNode).new(s) { |n| - n.label = m[1] - } - end - end - - def parse_reference(s) - if (m = s.scan(/\[/)) - arg = parse_arg(s) - if (arg and s.scan(/\]/)) - ReferenceNode.new(s) do |n| - n.argument = arg - end - end - end - end - end - -end - -if (__FILE__ == $0) - p Asm::Parser.parse ARGV[0] -end diff --git a/unused/str_scanner.rb b/unused/str_scanner.rb deleted file mode 100644 index 093aae40..00000000 --- a/unused/str_scanner.rb +++ /dev/null @@ -1,65 +0,0 @@ -module AS; end - -if (not defined? RUBY_ENGINE or not RUBY_ENGINE == 'rbx') - class Regexp - def match_start(str, idx) - Regexp.compile('\A(?:'+source+')').match(str[idx..-1]) - end - end -end - -class Asm::Scanner - def initialize(str) - @string = str - @pos = 0 - @line = 0 - @column = 0 - end - attr_accessor :string, :pos, :line, :column, :prev_line, :prev_column - - def rest - string[pos..-1] - end - - def advance_str(str) - self.prev_line = line - self.prev_column = column - self.pos += str.length - self.line += str.count("\n") - if (str.include?("\n")) - self.column = str.length - str.rindex("\n") - else - self.column += str.length - end - end - - def scan(regexp) - if (match = regexp.match_start(rest, 0)) - advance_str match.to_s - match.captures - else - nil - end - end - - def scan_str(regexp) - if (match = regexp.match_start(rest, 0)) - advance_str match.to_s - match.to_s - else - nil - end - end - - def lookahead(regexp) - if (match = regexp.match_start(rest, 0)) - true - else - false - end - end - - def eos? - pos == string.length - end -end