working on registers, awip (a work in progress)
This commit is contained in:
parent
1e326e00b9
commit
6ac92cac3a
@ -10,6 +10,10 @@ require_relative "constants"
|
|||||||
module Arm
|
module Arm
|
||||||
class ArmMachine < Vm::RegisterMachine
|
class ArmMachine < Vm::RegisterMachine
|
||||||
|
|
||||||
|
def integer_equals block , left , right
|
||||||
|
block << cmp( left , right )
|
||||||
|
Vm::BranchCondition.new :eq
|
||||||
|
end
|
||||||
def integer_less_or_equal block , left , right
|
def integer_less_or_equal block , left , right
|
||||||
block << cmp( left , right )
|
block << cmp( left , right )
|
||||||
Vm::BranchCondition.new :le
|
Vm::BranchCondition.new :le
|
||||||
|
@ -12,6 +12,10 @@ module Arm
|
|||||||
|
|
||||||
@immediate = 0
|
@immediate = 0
|
||||||
@rn = :r0 # register zero = zero bit pattern
|
@rn = :r0 # register zero = zero bit pattern
|
||||||
|
raise inspect if to.is_a?(Vm::Value) and
|
||||||
|
from.is_a?(Vm::Value) and
|
||||||
|
!@attributes[:shift_lsr] and
|
||||||
|
to.register == from.register
|
||||||
end
|
end
|
||||||
|
|
||||||
# arm intrucions are pretty sensible, and always 4 bytes (thumb not supported)
|
# arm intrucions are pretty sensible, and always 4 bytes (thumb not supported)
|
||||||
|
@ -35,12 +35,21 @@ module Ast
|
|||||||
context.function = function
|
context.function = function
|
||||||
|
|
||||||
into = function.body
|
into = function.body
|
||||||
|
last_compiled = nil
|
||||||
body.each do |b|
|
body.each do |b|
|
||||||
compiled = b.compile(context , into)
|
last_compiled = b.compile(context , into)
|
||||||
function.return_type = compiled
|
puts "compiled in function #{last_compiled.inspect}"
|
||||||
puts "compiled in function #{compiled.inspect}"
|
raise "alarm #{last_compiled} \n #{b}" unless last_compiled.is_a? Vm::Word
|
||||||
raise "alarm #{compiled} \n #{b}" unless compiled.is_a? Vm::Word
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return_reg = Vm::Integer.new(0)
|
||||||
|
if last_compiled.is_a?(Vm::IntegerConstant) or last_compiled.is_a?(Vm::StringConstant)
|
||||||
|
return_reg.load into , last_compiled if last_compiled.register != return_reg.register
|
||||||
|
else
|
||||||
|
return_reg.move( into, last_compiled ) if last_compiled.register != return_reg.register
|
||||||
|
end
|
||||||
|
function.set_return return_reg
|
||||||
|
|
||||||
context.locals = parent_locals
|
context.locals = parent_locals
|
||||||
context.function = parent_function
|
context.function = parent_function
|
||||||
function
|
function
|
||||||
|
@ -23,7 +23,7 @@ module Ast
|
|||||||
raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression)
|
raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression)
|
||||||
l_val = context.locals[left.name]
|
l_val = context.locals[left.name]
|
||||||
if( l_val ) #variable existed, move data there
|
if( l_val ) #variable existed, move data there
|
||||||
l_val = l_val.move( into , r_val)
|
l_val = l_val.move( into , r_val) if r_val.is_a?(Vm::Value) and l_val.register != r_val.register
|
||||||
else
|
else
|
||||||
l_val = context.function.new_local.move( into , r_val )
|
l_val = context.function.new_local.move( into , r_val )
|
||||||
end
|
end
|
||||||
@ -39,10 +39,11 @@ module Ast
|
|||||||
code = l_val.greater_than into , r_val
|
code = l_val.greater_than into , r_val
|
||||||
when "<"
|
when "<"
|
||||||
code = l_val.less_than into , r_val
|
code = l_val.less_than into , r_val
|
||||||
|
when "=="
|
||||||
|
code = l_val.equals into , r_val
|
||||||
when "+"
|
when "+"
|
||||||
res = context.function.new_local
|
res = context.function.new_local
|
||||||
into.res = l_val + r_val
|
into.res = l_val + r_val
|
||||||
# code = res.plus into , l_val , r_val
|
|
||||||
code = res
|
code = res
|
||||||
when "-"
|
when "-"
|
||||||
res = context.function.new_local
|
res = context.function.new_local
|
||||||
|
@ -28,7 +28,7 @@ module Core
|
|||||||
block = function.body
|
block = function.body
|
||||||
# should be another level of indirection, ie write(io,str)
|
# should be another level of indirection, ie write(io,str)
|
||||||
ret = Vm::RegisterMachine.instance.write_stdout(block)
|
ret = Vm::RegisterMachine.instance.write_stdout(block)
|
||||||
function.return_type = ret
|
function.set_return ret
|
||||||
function
|
function
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,23 +39,25 @@ module Vm
|
|||||||
@args[i] = arg.new(i)
|
@args[i] = arg.new(i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@return_type = return_type || Vm::Integer
|
set_return return_type
|
||||||
if @return_type.is_a?(Value)
|
@exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_exit" , self) , name )
|
||||||
raise "return in non std register #{@return_type.inspect}" unless 0 == @return_type.register
|
@return = Block.new("#{name}_return", self , @exit)
|
||||||
else
|
@body = Block.new("#{name}_body", self , @return)
|
||||||
@return_type = @return_type.new(0)
|
@entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_entry" , self , @body) ,name )
|
||||||
end
|
@locals = []
|
||||||
@exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_exit" , self) , name )
|
@blocks = []
|
||||||
@return = Block.new("#{name}_return", self , @exit)
|
|
||||||
@body = Block.new("#{name}_body", self , @return)
|
|
||||||
@entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_entry" , self , @body) ,name )
|
|
||||||
@locals = []
|
|
||||||
@blocks = []
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :args , :entry , :exit , :body , :name
|
attr_reader :args , :entry , :exit , :body , :name , :return_type
|
||||||
attr_accessor :return_type
|
|
||||||
|
|
||||||
|
def set_return type_or_value
|
||||||
|
@return_type = type_or_value || Vm::Integer
|
||||||
|
if @return_type.is_a?(Value)
|
||||||
|
raise "return in non std register #{@return_type.inspect}" unless 0 == @return_type.register
|
||||||
|
else
|
||||||
|
@return_type = @return_type.new(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
def arity
|
def arity
|
||||||
@args.length
|
@args.length
|
||||||
end
|
end
|
||||||
@ -69,11 +71,14 @@ module Vm
|
|||||||
|
|
||||||
def save_locals context , into
|
def save_locals context , into
|
||||||
save = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
save = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
||||||
|
save.delete_at(0)
|
||||||
into.push save
|
into.push save
|
||||||
end
|
end
|
||||||
|
|
||||||
def restore_locals context , into
|
def restore_locals context , into
|
||||||
|
#TODO assumes allocation in order, as the pop must be get regs in ascending order (also push)
|
||||||
restore = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
restore = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
||||||
|
restore.delete_at(0)
|
||||||
into.pop restore
|
into.pop restore
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ module Vm
|
|||||||
:le
|
:le
|
||||||
when :lt
|
when :lt
|
||||||
:ge
|
:ge
|
||||||
|
when :eq
|
||||||
|
:ne
|
||||||
else
|
else
|
||||||
raise "no implemented #{@operator}"
|
raise "no implemented #{@operator}"
|
||||||
end
|
end
|
||||||
@ -98,6 +100,9 @@ module Vm
|
|||||||
def greater_than block , right
|
def greater_than block , right
|
||||||
RegisterMachine.instance.integer_greater_than block , self , right
|
RegisterMachine.instance.integer_greater_than block , self , right
|
||||||
end
|
end
|
||||||
|
def equals block , right
|
||||||
|
RegisterMachine.instance.integer_equals block , self , right
|
||||||
|
end
|
||||||
def less_than block , right
|
def less_than block , right
|
||||||
RegisterMachine.instance.integer_less_than block , self , right
|
RegisterMachine.instance.integer_less_than block , self , right
|
||||||
end
|
end
|
||||||
|
@ -1,22 +1,3 @@
|
|||||||
function plus(a, b) {
|
|
||||||
minus(a, minus(0, b))
|
|
||||||
}
|
|
||||||
|
|
||||||
function times(a, b) {
|
|
||||||
if (eq(b, 0)) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
plus(a, times(a, minus(b, 1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function eq(a, b) {
|
|
||||||
if (minus(a, b)) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function factorial(n) {
|
function factorial(n) {
|
||||||
if (eq(n, 1)) {
|
if (eq(n, 1)) {
|
||||||
|
31
test/fragments/test_functions.rb
Normal file
31
test/fragments/test_functions.rb
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
require_relative 'helper'
|
||||||
|
|
||||||
|
class TestFunctions < MiniTest::Test
|
||||||
|
include Fragments
|
||||||
|
|
||||||
|
def test_hello
|
||||||
|
@string_input = <<HERE
|
||||||
|
def minus(a,b)
|
||||||
|
a - b
|
||||||
|
end
|
||||||
|
def plus(a, b)
|
||||||
|
a + b
|
||||||
|
end
|
||||||
|
def times(a, b)
|
||||||
|
if( b == 0 )
|
||||||
|
a = 0
|
||||||
|
else
|
||||||
|
m = minus(b, 1)
|
||||||
|
t = times(a, m)
|
||||||
|
a = plus(a,t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
putint(times(4,1))
|
||||||
|
HERE
|
||||||
|
@should = [0x0,0xb0,0xa0,0xe3,0x28,0x0,0x8f,0xe2,0x28,0x10,0xa0,0xe3,0x1,0x0,0x0,0xeb,0x1,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x40,0x2d,0xe9,0x1,0x20,0xa0,0xe1,0x0,0x10,0xa0,0xe1,0x1,0x0,0xa0,0xe3,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x80,0xbd,0xe8,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x52,0x61,0x69,0x73,0x61,0x2c,0x20,0x49,0x20,0x61,0x6d,0x20,0x63,0x72,0x79,0x73,0x74,0x6b,0x73,0x64,0x66,0x6b,0x6c,0x6a,0x73,0x6e,0x63,0x6a,0x6e,0x63,0x6e,0x0,0x0,0x0]
|
||||||
|
parse
|
||||||
|
write "functions"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user