starting on mom to risc

some docs too
This commit is contained in:
2019-08-08 12:19:27 +03:00
parent 82c9f1d97f
commit 5994cd3276
9 changed files with 102 additions and 77 deletions

View File

@ -4,23 +4,21 @@ module Risc
# class shared by BlockCompiler and MethodCompiler
# - risc_instructions: The sequence of risc level instructions that mom was compiled to
# - cpu_instructions: The sequence of cpu specific instructions that the
# risc_instructions was compiled to
# Instructions derive from class Instruction and form a linked list
# - constants is an array of Parfait objects that need to be available
# - callable is a Method of Block
# - current instruction is where addidion happens
#
class CallableCompiler
def initialize( callable )
# Must pass the callable (method/block) and the constants that were parsed
# Also start instuction, usually a label is mandatory
def initialize( callable , constants , start)
@callable = callable
@regs = []
@constants = []
@constants = constants
@block_compilers = []
@risc_instructions = Risc.label(source_name, source_name)
@current = start = @risc_instructions
add_code Risc.label( source_name, "return_label")
Mom::ReturnSequence.new.to_risc(self)
add_code Risc.label( source_name, "unreachable")
@current = start
@current = @risc_instructions = start
reset_regs
end
attr_reader :risc_instructions , :constants , :block_compilers , :callable , :current
@ -32,19 +30,6 @@ module Risc
end
end
# convert the given mom instruction to_risc and then add it (see add_code)
# continue down the instruction chain unti depleted
# (adding moves the insertion point so the whole mom chain is added as a risc chain)
def add_mom( instruction )
while( instruction )
raise "whats this a #{instruction}" unless instruction.is_a?(Mom::Instruction)
#puts "adding mom #{instruction.to_s}:#{instruction.next.to_s}"
instruction.to_risc( self )
reset_regs
#puts "adding risc #{risc.to_s}:#{risc.next.to_s}"
instruction = instruction.next
end
end
# add a constant (which get created during compilation and need to be linked)
def add_constant(const)

View File

@ -0,0 +1,82 @@
module Risc
# The Collection for the Risc level is a collection of Risc level Method compilers,
# plus functions to translate from the risc to cpu specific code.
#
class RiscCollection
attr_reader :method_compilers
# Initialize with an array of risc MethodCompilers
def initialize(compilers = [])
@method_compilers = compilers
end
# lazily instantiate the compilers for boot functions
# (in the hope of only booting the functions once)
def boot_compilers
@boot_compilers ||= Risc::Builtin.boot_functions
end
# Return all compilers, namely the MethodCompilers passed in, plus the
# boot_function's compilers (boot_compilers)
def compilers
@method_compilers + boot_compilers
end
# collects constants from all compilers into one array
def constants
compilers.inject([]){|sum ,comp| sum + comp.constants }
end
# Append another MomCompilers method_compilers to this one.
def append(mom_compiler)
@method_compilers += mom_compiler.method_compilers
self
end
# Translate code to whatever cpu is specified.
# Currently only :arm and :interpret
#
# Translating means translating the initial jump
# and then translating all methods
def translate( platform_sym )
platform_sym = platform_sym.to_s.capitalize
platform = Risc::Platform.for(platform_sym)
assemblers = translate_methods( platform.translator )
Risc::Linker.new(platform , assemblers , constants)
end
# go through all methods and translate them to cpu, given the translator
def translate_methods(translator)
compilers.collect do |compiler|
#log.debug "Translate method #{compiler.method.name}"
translate_method(compiler , translator)
end.flatten
end
# translate one method, which means the method itself and all blocks inside it
# returns an array of assemblers
def translate_method( method_compiler , translator)
all = []
all << translate_cpu( method_compiler , translator )
method_compiler.block_compilers.each do |block_compiler|
all << translate_cpu(block_compiler , translator)
end
all
end
# compile the callable (method or block) to cpu
# return an Assembler that will then translate to binary
def translate_cpu(compiler , translator)
risc = compiler.risc_instructions
cpu_instructions = risc.to_cpu(translator)
nekst = risc.next
while(nekst)
cpu = nekst.to_cpu(translator) # returning nil means no replace
cpu_instructions << cpu if cpu
nekst = nekst.next
end
Risc::Assembler.new(compiler.callable , cpu_instructions )
end
end
end