checkpointing on the mad road to register allocation
This commit is contained in:
parent
b0302948dd
commit
f6711ea49c
@ -31,45 +31,45 @@ module Arm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def integer_less_or_equal left , right
|
def integer_less_or_equal block , left , right
|
||||||
cmp(:left => left , :right => right )
|
block.add_code cmp(:left => left , :right => right )
|
||||||
|
Vm::Bool.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def integer_plus left , right
|
def integer_plus block , left , right
|
||||||
add(:left => left , :right => right )
|
block.add_code add(:left => left , :right => right )
|
||||||
|
left
|
||||||
end
|
end
|
||||||
|
|
||||||
def word_load value , reg
|
def integer_load block , left , right
|
||||||
raise "not a register :#{reg}:" unless reg.class == Symbol
|
reg = "r#{left.register}".to_sym
|
||||||
mov( :left => reg , :right => value )
|
block.add_code mov( :left => reg , :right => right )
|
||||||
|
left
|
||||||
end
|
end
|
||||||
def string_load str_lit , reg
|
def string_load block , str_lit , reg
|
||||||
[ add( :left => "r#{reg}".to_sym , :extra => str_lit ) , #right is pc, implicit
|
block.add_code add( :left => "r#{reg}".to_sym , :extra => str_lit ) #right is pc, implicit
|
||||||
#second arg is a hack to get the stringlength without coding
|
#second arg is a hack to get the stringlength without coding
|
||||||
mov( :left => "r#{reg+1}".to_sym , :right => str_lit.length ) ]
|
block.add_code mov( :left => "r#{reg+1}".to_sym , :right => str_lit.length )
|
||||||
|
str_lit
|
||||||
end
|
end
|
||||||
|
|
||||||
def function_call call
|
def function_call call
|
||||||
raise "Not FunctionCall #{call.inspect}" unless call.is_a? Vm::FunctionCall
|
raise "Not FunctionCall #{call.inspect}" unless call.is_a? Vm::FunctionCall
|
||||||
call.args.each do | arg |
|
block.add_code bl( :left => call.function )
|
||||||
end
|
call.function.return_value
|
||||||
bl( :left => call.function )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def main_start
|
def main_start entry
|
||||||
entry = Vm::Block.new("main_entry")
|
|
||||||
entry.add_code mov( :left => :fp , :right => 0 )
|
entry.add_code mov( :left => :fp , :right => 0 )
|
||||||
end
|
end
|
||||||
def main_exit
|
def main_exit exit
|
||||||
entry = Vm::Block.new("main_exit")
|
exit.add_code syscall(1)
|
||||||
entry.add_code syscall(1)
|
|
||||||
end
|
end
|
||||||
def function_entry f_name
|
def function_entry block, f_name
|
||||||
entry = Vm::Block.new("#{f_name}_entry")
|
# entry.add_code push( :regs => [:lr] )
|
||||||
# entry.add_code push( :regs => [:lr] )
|
block
|
||||||
end
|
end
|
||||||
def function_exit f_name
|
def function_exit entry , f_name
|
||||||
entry = Vm::Block.new("#{f_name}_exit")
|
|
||||||
entry.add_code mov( :left => :pc , :right => :lr )
|
entry.add_code mov( :left => :pc , :right => :lr )
|
||||||
end
|
end
|
||||||
def putstring
|
def putstring
|
||||||
|
@ -14,7 +14,7 @@ module Ast
|
|||||||
value.to_s
|
value.to_s
|
||||||
end
|
end
|
||||||
def compile context , into
|
def compile context , into
|
||||||
Vm::Integer.new value
|
Vm::IntegerConstant.new value
|
||||||
end
|
end
|
||||||
def attributes
|
def attributes
|
||||||
[:value]
|
[:value]
|
||||||
|
@ -18,16 +18,20 @@ module Ast
|
|||||||
end
|
end
|
||||||
def compile context , into
|
def compile context , into
|
||||||
raise "function does not compile into anything #{self}" if into
|
raise "function does not compile into anything #{self}" if into
|
||||||
parent_locals = context.locals
|
|
||||||
context.locals = {}
|
|
||||||
args = []
|
args = []
|
||||||
|
locals = {}
|
||||||
params.each_with_index do |param , index|
|
params.each_with_index do |param , index|
|
||||||
arg = param.name
|
arg = param.name
|
||||||
arg_value = Vm::Integer.new(index)
|
arg_value = Vm::Integer.new(index)
|
||||||
context.locals[arg] = arg_value
|
locals[arg] = arg_value
|
||||||
args << arg_value
|
args << arg_value
|
||||||
end
|
end
|
||||||
function = Vm::Function.new(name , args )
|
function = Vm::Function.new(name , args )
|
||||||
|
parent_locals = context.locals
|
||||||
|
parent_function = context.function
|
||||||
|
context.locals = locals
|
||||||
|
context.function = function
|
||||||
|
|
||||||
context.program.add_function function
|
context.program.add_function function
|
||||||
into = function.entry
|
into = function.entry
|
||||||
block.each do |b|
|
block.each do |b|
|
||||||
@ -41,6 +45,7 @@ module Ast
|
|||||||
puts compiled.inspect
|
puts compiled.inspect
|
||||||
end
|
end
|
||||||
context.locals = parent_locals
|
context.locals = parent_locals
|
||||||
|
context.function = parent_function
|
||||||
function
|
function
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,10 +43,15 @@ module Ast
|
|||||||
"#{left} #{operator} #{right}"
|
"#{left} #{operator} #{right}"
|
||||||
end
|
end
|
||||||
def compile context , into
|
def compile context , into
|
||||||
|
puts "compile #{to_s}"
|
||||||
r_val = right.compile(context , into)
|
r_val = right.compile(context , into)
|
||||||
|
|
||||||
if operator == "=" # assignemnt
|
if operator == "=" # assignemnt
|
||||||
raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression)
|
raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression)
|
||||||
|
if r_val.is_a? Vm::IntegerConstant
|
||||||
|
puts context.attributes.keys.join(" ")
|
||||||
|
next_register = context.function.next_register
|
||||||
|
r_val = Vm::Integer.new(next_register).load( into , r_val )
|
||||||
|
end
|
||||||
context.locals[left.name] = r_val
|
context.locals[left.name] = r_val
|
||||||
return r_val
|
return r_val
|
||||||
end
|
end
|
||||||
@ -54,9 +59,9 @@ module Ast
|
|||||||
|
|
||||||
case operator
|
case operator
|
||||||
when ">"
|
when ">"
|
||||||
code = l_val.less_or_equal r_val
|
code = l_val.less_or_equal into , r_val
|
||||||
when "+"
|
when "+"
|
||||||
code = l_val.plus r_val
|
code = l_val.plus into , r_val
|
||||||
else
|
else
|
||||||
raise "unimplemented operator #{operator} #{self}"
|
raise "unimplemented operator #{operator} #{self}"
|
||||||
end
|
end
|
||||||
|
@ -4,19 +4,19 @@ module Core
|
|||||||
#there are no Kernel instances, only class methods.
|
#there are no Kernel instances, only class methods.
|
||||||
# We use this module syntax to avoid the (ugly) self (also eases searching).
|
# We use this module syntax to avoid the (ugly) self (also eases searching).
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
def main_start
|
def main_start block
|
||||||
#TODO extract args into array of strings
|
#TODO extract args into array of strings
|
||||||
Vm::CMachine.instance.main_start
|
Vm::CMachine.instance.main_start block
|
||||||
end
|
end
|
||||||
def main_exit
|
def main_exit block
|
||||||
# Machine.exit mov r7 , 0 + swi 0
|
# Machine.exit mov r7 , 0 + swi 0
|
||||||
Vm::CMachine.instance.main_exit
|
Vm::CMachine.instance.main_exit block
|
||||||
end
|
end
|
||||||
def function_entry f_name
|
def function_entry block , f_name
|
||||||
Vm::CMachine.instance.function_entry f_name
|
Vm::CMachine.instance.function_entry block , f_name
|
||||||
end
|
end
|
||||||
def function_exit f_name
|
def function_exit block , f_name
|
||||||
Vm::CMachine.instance.function_exit f_name
|
Vm::CMachine.instance.function_exit block , f_name
|
||||||
end
|
end
|
||||||
def putstring
|
def putstring
|
||||||
# should unwrap from string to char*
|
# should unwrap from string to char*
|
||||||
|
@ -34,11 +34,7 @@ module Vm
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_code(kode)
|
def add_code(kode)
|
||||||
if( kode.is_a? Array )
|
@codes << kode
|
||||||
kode.each { |code| @codes << code }
|
|
||||||
else
|
|
||||||
@codes << kode
|
|
||||||
end
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ module Vm
|
|||||||
|
|
||||||
|
|
||||||
class IntegerConstant < Constant
|
class IntegerConstant < Constant
|
||||||
def init int
|
def initialize int
|
||||||
@integer = int
|
@integer = int
|
||||||
end
|
end
|
||||||
attr_reader :integer
|
attr_reader :integer
|
||||||
|
@ -12,6 +12,6 @@ module Vm
|
|||||||
@attributes = {}
|
@attributes = {}
|
||||||
@attributes[:program] = program
|
@attributes[:program] = program
|
||||||
end
|
end
|
||||||
|
attr_reader :attributes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,24 +22,24 @@ module Vm
|
|||||||
super()
|
super()
|
||||||
@name = name
|
@name = name
|
||||||
@args = args
|
@args = args
|
||||||
@entry = Core::Kernel::function_entry( name )
|
@entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_exit") ,name )
|
||||||
@exit = Core::Kernel::function_exit( name )
|
@exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_entry") , name )
|
||||||
@body = Block.new("#{name}_body")
|
@body = Block.new("#{name}_body")
|
||||||
|
@reg_count = 0
|
||||||
branch_body
|
branch_body
|
||||||
end
|
end
|
||||||
attr_reader :args , :entry , :exit , :body , :name
|
attr_reader :args , :entry , :exit , :body , :name
|
||||||
|
|
||||||
# this creates a branch from entry here and from here to exit
|
|
||||||
# unless there is a link existing, in which you are resposible
|
|
||||||
def set_body body
|
|
||||||
@body = body
|
|
||||||
branch_body
|
|
||||||
end
|
|
||||||
|
|
||||||
def arity
|
def arity
|
||||||
@args.length
|
@args.length
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def next_register
|
||||||
|
next_free = @reg_count
|
||||||
|
@reg_count += 1
|
||||||
|
next_free + args.length
|
||||||
|
end
|
||||||
|
|
||||||
def link_at address , context
|
def link_at address , context
|
||||||
raise "undefined code #{inspect}" if @body.nil?
|
raise "undefined code #{inspect}" if @body.nil?
|
||||||
super #just sets the position
|
super #just sets the position
|
||||||
@ -66,10 +66,5 @@ module Vm
|
|||||||
@entry.set_next(@body)
|
@entry.set_next(@body)
|
||||||
@body.set_next(@exit) if @body and !@body.next
|
@body.set_next(@exit) if @body and !@body.next
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_arg value
|
|
||||||
# TODO check
|
|
||||||
@args << value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -12,9 +12,9 @@ module Vm
|
|||||||
attr_reader :function , :args , :name
|
attr_reader :function , :args , :name
|
||||||
|
|
||||||
def load_args into
|
def load_args into
|
||||||
raise args.inspect
|
|
||||||
args.each_with_index do |arg , index|
|
args.each_with_index do |arg , index|
|
||||||
into.add_code arg.load("r#{index}".to_sym)
|
puts "load " + arg.inspect
|
||||||
|
into.add_code arg.move("r#{index}".to_sym)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ module Vm
|
|||||||
@objects = []
|
@objects = []
|
||||||
# global functions
|
# global functions
|
||||||
@functions = []
|
@functions = []
|
||||||
@entry = Core::Kernel::main_start
|
@entry = Core::Kernel::main_start Vm::Block.new("main_entry")
|
||||||
#main gets executed between entry and exit
|
#main gets executed between entry and exit
|
||||||
@main = Block.new("main")
|
@main = Block.new("main")
|
||||||
@exit = Core::Kernel::main_exit
|
@exit = Core::Kernel::main_exit Vm::Block.new("main_exit")
|
||||||
end
|
end
|
||||||
attr_reader :context , :main , :functions
|
attr_reader :context , :main , :functions
|
||||||
|
|
||||||
@ -58,9 +58,7 @@ module Vm
|
|||||||
fun = get_function name
|
fun = get_function name
|
||||||
unless fun
|
unless fun
|
||||||
puts @functions.inspect
|
puts @functions.inspect
|
||||||
fun = Function.new(name)
|
fun = Core::Kernel.send(name)
|
||||||
block = Core::Kernel.send(name)
|
|
||||||
fun.set_body block
|
|
||||||
@functions << fun
|
@functions << fun
|
||||||
end
|
end
|
||||||
fun
|
fun
|
||||||
|
@ -27,6 +27,11 @@ module Vm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Just a nice way to write branches
|
||||||
|
class Bool < Value
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
# This is what it is when we don't know what it is.
|
# This is what it is when we don't know what it is.
|
||||||
# Must be promoted to A Word-Value to to anything
|
# Must be promoted to A Word-Value to to anything
|
||||||
# remembering that our oo machine is typed, no overloading or stuff
|
# remembering that our oo machine is typed, no overloading or stuff
|
||||||
@ -34,10 +39,12 @@ module Vm
|
|||||||
|
|
||||||
attr_accessor :register
|
attr_accessor :register
|
||||||
|
|
||||||
def initialize reg
|
def inspect
|
||||||
register = reg
|
self.class.name + ":reg:#{register}:"
|
||||||
|
end
|
||||||
|
def initialize reg
|
||||||
|
@register = reg
|
||||||
end
|
end
|
||||||
|
|
||||||
def length
|
def length
|
||||||
4
|
4
|
||||||
end
|
end
|
||||||
@ -45,19 +52,23 @@ module Vm
|
|||||||
|
|
||||||
class Unsigned < Word
|
class Unsigned < Word
|
||||||
|
|
||||||
def plus unsigned
|
def plus block , unsigned
|
||||||
Machine.instance.unsigned_plus self , unsigned
|
CMachine.instance.unsigned_plus self , unsigned
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Integer < Word
|
class Integer < Word
|
||||||
|
|
||||||
def less_or_equal right
|
def less_or_equal block , right
|
||||||
Machine.instance.integer_less_or_equal self , right
|
CMachine.instance.integer_less_or_equal block , self , right
|
||||||
end
|
end
|
||||||
|
|
||||||
def plus right
|
def plus block , right
|
||||||
Machine.instance.integer_plus self , right
|
CMachine.instance.integer_plus block , self , right
|
||||||
|
end
|
||||||
|
|
||||||
|
def load block , right
|
||||||
|
CMachine.instance.integer_load block , self , right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user