Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby

$LOAD_PATH.unshift('../lib')

require 'compiler'

???
116 changes: 116 additions & 0 deletions lib/compiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
this_dir = File.dirname(__FILE__)
Dir.chdir(File.expand_path('..', this_dir))
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)

require 'compiler/parser'

class Compiler

attr_reader :platform, :arch_name, :format, :binformat

attr_reader :arch, :asm, :symbol_table_factory, :object_file_factor

# platform [String] "linux" or "darwin"
# arch_name [String] "x86" or "arm"
# format [String] "text" or "bin"
# binform [String, nil] "elf" or "macho", only used when format is "bin"
def initialize(platform, arch_name, format, binformat = nil)
@platform = platform
@arch_name = arch_name
@format = format
@binformat = binformat
wire
end

def compile(input)
parser = Parser.new(input, asm)
parser.parse
parser.compile
end


#######
private
#######

def wire
if format == 'bin'
case binformat

when 'elf'
wire_elf

when 'macho'
wire_macho

else
raise "unsupported binary format: #{binformat}"
end
end

case @arch_name

when 'x86'
wire_x86

when 'arm'
wire_arm

else
raise "unsupported arch: #{arch}"
end
end

def wire_elf
require 'compiler/asm/elf/object_file'
require 'compiler/asm/elf/symbol_table'

@symbol_table_factory = ASM::ELF::SymbolTable
@object_file_factory = ASM::ELF::ObjectFile
end

def wire_macho
require 'compiler/asm/macho/object_file'
require 'compiler/asm/macho/symbol_table'

@symbol_table_factory = ASM::MachO::SymbolTable
@object_file_factory = ASM::MachO::ObjectFile
end

def wire_arm
require 'compiler/asm/arm/binary_assembler'
require 'compiler/asm/arm/text_assembler'

@arch = ASM::ARM::Arch.instance
@asm =
case format
when 'text'
ASM::ARM::TextAssembler.new(self)

when 'bin'
ASM::ARM::BinaryAssembler.new(self)

else
raise "unsupported output format: #{format}"
end
end

def wire_x86
require 'compiler/asm/x86/binary_assembler'
require 'compiler/asm/x86/text_assembler'

@arch = ASM::X86::Arch.instance
@asm =
case format
when 'text'
ASM::X86::TextAssembler.new(self)

when 'bin'
ASM::X86::BinaryAssembler.new(self)

else
raise "unsupported output format: #{format}"
end
end

end
67 changes: 67 additions & 0 deletions lib/compiler/asm/arch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
class Compiler
module ASM

class Arch

attr_reader :bits, :word_bits
attr_reader :preamble, :postamble
attr_reader :endianness

# config:
# - bits: native register / pointer size
# - word_bits: number of bits in a word
# - endianness: "big" or "little"
# - preamble: binary preamble
# - postamble: binary postamble
def initialize(config)
@bits = config['bits']
@word_bits = config['word_bits']
@endianness = config['endianness']
@preamble = config['preamble']
@postamble = config['postamble']
end

def bytes
bits / 8
end

def word_bytes
word_bits / 8
end

def big_endian?
endianness == 'big'
end

def little_endian?
endianness == 'little'
end

def pointer_bytes
bytes
end

def min_signed
-1 * 2 ** (bits - 1)
end

def max_signed
2 ** (bits - 1) - 1
end

def min_unsigned
0
end

def max_unsigned
2 ** bits - 1
end

def signed_int
@signed_int ||= min_signed..max_signed
end

end

end
end
82 changes: 82 additions & 0 deletions lib/compiler/asm/assembler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# sjs
# may 2009

class Compiler
module ASM

# Abstract class for common functionality between different code
# generators. Also defines somewhat of an interface that must be
# implemented to be useful.
class Assembler

def initialize(delegate)
@delegate = delegate
end

def arch
delegate.arch
end

def block(*args, &block)
instance_eval(&block)
end

def load(n)
end

def load_var(name)
end

def store_var(name, reg)
end

def neg(reg)
end

def stack_add(reg)
end

def stack_sub(reg)
end

def stack_mul_signed(reg)
end

def stack_div(reg)
end

def stack_or(reg)
end

def stack_xor(reg)
end

def stack_and(reg)
end

def not_(reg)
end
alias_method :not, :not_

def compare(reg, n)
end

def je(label)
end

def jne(label)
end

def jmp(label)
end

def mov_reg_imm(reg, n)
end

def call(label)
end

end

end
end
Loading