fix all tests and a little cleaning
This commit is contained in:
parent
2c26415de7
commit
0dbaebf647
@ -132,8 +132,8 @@ module Arm
|
|||||||
|
|
||||||
def syscall block , num
|
def syscall block , num
|
||||||
# This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up
|
# This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up
|
||||||
sys = Vm::Integer.new( Vm::RegisterUse.new(:r7) )
|
sys = Vm::Integer.new( Vm::RegisterReference.new(:r7) )
|
||||||
ret = Vm::Integer.new( Vm::RegisterUse.new(RETURN_REG) )
|
ret = Vm::Integer.new( Vm::RegisterReference.new(RETURN_REG) )
|
||||||
block.do_add mov( sys , num )
|
block.do_add mov( sys , num )
|
||||||
block.do_add swi( 0 )
|
block.do_add swi( 0 )
|
||||||
#todo should write type into r1 according to syscall
|
#todo should write type into r1 according to syscall
|
||||||
|
@ -6,7 +6,7 @@ module Ast
|
|||||||
locals = {}
|
locals = {}
|
||||||
params.each_with_index do |param , index|
|
params.each_with_index do |param , index|
|
||||||
arg = param.name
|
arg = param.name
|
||||||
register = Vm::RegisterUse.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1)
|
register = Vm::RegisterReference.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1)
|
||||||
arg_value = Vm::Integer.new(register)
|
arg_value = Vm::Integer.new(register)
|
||||||
locals[arg] = arg_value
|
locals[arg] = arg_value
|
||||||
args << arg_value
|
args << arg_value
|
||||||
|
@ -40,7 +40,7 @@ module Vm
|
|||||||
|
|
||||||
@args = Array.new(args.length)
|
@args = Array.new(args.length)
|
||||||
args.each_with_index do |arg , i|
|
args.each_with_index do |arg , i|
|
||||||
shouldda = RegisterUse.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1)
|
shouldda = RegisterReference.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1)
|
||||||
if arg.is_a?(Value)
|
if arg.is_a?(Value)
|
||||||
@args[i] = arg
|
@args[i] = arg
|
||||||
raise "arg #{i} in non std register #{arg.used_register}, expecting #{shouldda}" unless shouldda == arg.used_register
|
raise "arg #{i} in non std register #{arg.used_register}, expecting #{shouldda}" unless shouldda == arg.used_register
|
||||||
@ -88,7 +88,7 @@ module Vm
|
|||||||
def locals_at l_block
|
def locals_at l_block
|
||||||
used =[]
|
used =[]
|
||||||
# call assigns the return register, but as it is in l_block, it is not asked.
|
# call assigns the return register, but as it is in l_block, it is not asked.
|
||||||
assigned = [ RegisterUse.new(Vm::RegisterMachine.instance.return_register) ]
|
assigned = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ]
|
||||||
l_block.reachable.each do |b|
|
l_block.reachable.each do |b|
|
||||||
b.uses.each {|u|
|
b.uses.each {|u|
|
||||||
(used << u) unless assigned.include?(u)
|
(used << u) unless assigned.include?(u)
|
||||||
|
@ -36,7 +36,7 @@ module Vm
|
|||||||
atts.delete(:condition_code) if atts[:condition_code] == :al
|
atts.delete(:condition_code) if atts[:condition_code] == :al
|
||||||
atts.empty? ? "" : ", #{atts}"
|
atts.empty? ? "" : ", #{atts}"
|
||||||
end
|
end
|
||||||
# returns an array of registers (RegisterUses) that this instruction uses.
|
# returns an array of registers (RegisterReferences) that this instruction uses.
|
||||||
# ie for r1 = r2 + r3
|
# ie for r1 = r2 + r3
|
||||||
# which in assembler is add r1 , r2 , r3
|
# which in assembler is add r1 , r2 , r3
|
||||||
# it would return [r2,r3]
|
# it would return [r2,r3]
|
||||||
@ -44,7 +44,7 @@ module Vm
|
|||||||
def uses
|
def uses
|
||||||
raise "abstract called for #{self.class}"
|
raise "abstract called for #{self.class}"
|
||||||
end
|
end
|
||||||
# returns an array of registers (RegisterUses) that this instruction assigns to.
|
# returns an array of registers (RegisterReferences) that this instruction assigns to.
|
||||||
# ie for r1 = r2 + r3
|
# ie for r1 = r2 + r3
|
||||||
# which in assembler is add r1 , r2 , r3
|
# which in assembler is add r1 , r2 , r3
|
||||||
# it would return [r1]
|
# it would return [r1]
|
||||||
@ -191,7 +191,7 @@ module Vm
|
|||||||
end
|
end
|
||||||
def assigns
|
def assigns
|
||||||
if opcode == :call
|
if opcode == :call
|
||||||
[RegisterUse.new(RegisterMachine.instance.return_register)]
|
[RegisterReference.new(RegisterMachine.instance.return_register)]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
33
lib/vm/register_reference.rb
Normal file
33
lib/vm/register_reference.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
module Vm
|
||||||
|
|
||||||
|
# RegisterReference is not the name for a register, "only" for a certain use of it.
|
||||||
|
# In a way it is like a variable name, a storage location. The location is a register off course,
|
||||||
|
# but which register can be changed, and _all_ instructions sharing the RegisterReference then use that register
|
||||||
|
# In other words a simple level of indirection, or change from value to reference sematics.
|
||||||
|
|
||||||
|
class RegisterReference
|
||||||
|
attr_accessor :symbol
|
||||||
|
def initialize r
|
||||||
|
if( r.is_a? Fixnum)
|
||||||
|
r = "r#{r}".to_sym
|
||||||
|
end
|
||||||
|
raise "wrong type for register init #{r}" unless r.is_a? Symbol
|
||||||
|
raise "double r #{r}" if r == :rr1
|
||||||
|
@symbol = r
|
||||||
|
end
|
||||||
|
|
||||||
|
def == other
|
||||||
|
return false if other.nil?
|
||||||
|
return false if other.class != RegisterReference
|
||||||
|
symbol == other.symbol
|
||||||
|
end
|
||||||
|
|
||||||
|
#helper method to calculate with register symbols
|
||||||
|
def next_reg_use by = 1
|
||||||
|
int = @symbol[1,3].to_i
|
||||||
|
sym = "r#{int + by}".to_sym
|
||||||
|
RegisterReference.new( sym )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -1,4 +1,5 @@
|
|||||||
require_relative "code"
|
require_relative "code"
|
||||||
|
require_relative "register_reference"
|
||||||
|
|
||||||
module Vm
|
module Vm
|
||||||
|
|
||||||
@ -7,12 +8,7 @@ module Vm
|
|||||||
# The oprerations on values is what makes a machine do things. Operations are captured as
|
# The oprerations on values is what makes a machine do things. Operations are captured as
|
||||||
# subclasses of Instruction and saved to Blocks
|
# subclasses of Instruction and saved to Blocks
|
||||||
|
|
||||||
# Values are immutable! (that's why they are called values)
|
|
||||||
# Operations on values _always_ produce new values (conceptionally)
|
|
||||||
|
|
||||||
# Values are a way to reason about (create/validate) instructions.
|
# Values are a way to reason about (create/validate) instructions.
|
||||||
# In fact a linked lists of values is created by invoking instructions
|
|
||||||
# the linked list goes from value to instruction to value, backwards
|
|
||||||
|
|
||||||
# Word Values are what fits in a register. Derived classes
|
# Word Values are what fits in a register. Derived classes
|
||||||
# Float, Reference , Integer(s) must fit the same registers
|
# Float, Reference , Integer(s) must fit the same registers
|
||||||
@ -48,35 +44,6 @@ module Vm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# RegisterUSe is _not_ the name for a register, "only" for a certain use of it.
|
|
||||||
# In a way it is like a variable name, a storage location. The location is a register off course,
|
|
||||||
# but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register
|
|
||||||
# In other words a simple level of indirection, or change from value to reference sematics.
|
|
||||||
class RegisterUse
|
|
||||||
attr_accessor :symbol
|
|
||||||
def initialize r
|
|
||||||
if( r.is_a? Fixnum)
|
|
||||||
r = "r#{r}".to_sym
|
|
||||||
end
|
|
||||||
raise "wrong type for register init #{r}" unless r.is_a? Symbol
|
|
||||||
raise "double r #{r}" if r == :rr1
|
|
||||||
@symbol = r
|
|
||||||
end
|
|
||||||
|
|
||||||
def == other
|
|
||||||
return false if other.nil?
|
|
||||||
return false if other.class != RegisterUse
|
|
||||||
symbol == other.symbol
|
|
||||||
end
|
|
||||||
|
|
||||||
#helper method to calculate with register symbols
|
|
||||||
def next_reg_use by = 1
|
|
||||||
int = @symbol[1,3].to_i
|
|
||||||
sym = "r#{int + by}".to_sym
|
|
||||||
RegisterUse.new( sym )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base
|
# This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base
|
||||||
# Must be promoted to A Word-Value to to anything makes is_a chaecking easier
|
# Must be promoted to A Word-Value to to anything makes is_a chaecking easier
|
||||||
# remembering that our oo machine is typed, no overloading or stuff
|
# remembering that our oo machine is typed, no overloading or stuff
|
||||||
@ -94,10 +61,10 @@ module Vm
|
|||||||
inspect
|
inspect
|
||||||
end
|
end
|
||||||
def initialize reg
|
def initialize reg
|
||||||
if reg.is_a? RegisterUse
|
if reg.is_a? RegisterReference
|
||||||
@used_register = reg
|
@used_register = reg
|
||||||
else
|
else
|
||||||
@used_register = RegisterUse.new(reg)
|
@used_register = RegisterReference.new(reg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def length
|
def length
|
||||||
|
@ -15,7 +15,7 @@ end
|
|||||||
|
|
||||||
itest(20)
|
itest(20)
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x44,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x4,0x0,0x0,0xeb,0x2,0x0,0x0,0xea,0x3c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x0,0x0,0x0,0xeb,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x34,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd4,0xff,0xff,0xeb,0x2,0x0,0x0,0xea,0x2c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd0,0xff,0xff,0xeb,0x0,0x80,0xbd,0xe8]
|
||||||
@output = "else "
|
@output = "else "
|
||||||
@target = [:Object , :itest]
|
@target = [:Object , :itest]
|
||||||
parse
|
parse
|
||||||
|
@ -7,7 +7,7 @@ class TestPutint < MiniTest::Test
|
|||||||
@string_input = <<HERE
|
@string_input = <<HERE
|
||||||
42.putint()
|
42.putint()
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0xa0,0xe1,0x34,0x20,0x8f,0xe2,0x9,0x20,0x82,0xe2,0xe9,0xff,0xff,0xeb,0x28,0x20,0x8f,0xe2,0xc,0x30,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x2,0x10,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0xa0,0xe1,0x78,0x20,0x8f,0xe2,0x9,0x20,0x82,0xe2,0xe2,0xff,0xff,0xeb,0x6c,0x20,0x8f,0xe2,0xc,0x30,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x2,0x10,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 42 "
|
@output = " 42 "
|
||||||
@target = [:Object , :putint]
|
@target = [:Object , :putint]
|
||||||
parse
|
parse
|
||||||
|
@ -20,7 +20,7 @@ end # r0 <- r5
|
|||||||
|
|
||||||
fibonaccit( 10 )
|
fibonaccit( 10 )
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x0,0x40,0xa0,0xe3,0x1,0x50,0xa0,0xe3,0x1,0x0,0x53,0xe3,0x4,0x0,0x0,0xda,0x4,0x60,0xa0,0xe1,0x5,0x40,0xa0,0xe1,0x5,0x50,0x86,0xe0,0x1,0x30,0x43,0xe2,0xf8,0xff,0xff,0xea,0x20,0x0,0x2d,0xe9,0x5,0x20,0xa0,0xe1,0x13,0x0,0x0,0xeb,0x20,0x0,0xbd,0xe8,0x5,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x0,0x40,0xa0,0xe3,0x1,0x50,0xa0,0xe3,0x1,0x0,0x53,0xe3,0x4,0x0,0x0,0xda,0x4,0x60,0xa0,0xe1,0x5,0x40,0xa0,0xe1,0x5,0x50,0x86,0xe0,0x1,0x30,0x43,0xe2,0xf8,0xff,0xff,0xea,0x20,0x0,0x2d,0xe9,0x5,0x20,0xa0,0xe1,0xd4,0xff,0xff,0xeb,0x20,0x0,0xbd,0xe8,0x5,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 55 "
|
@output = " 55 "
|
||||||
@target = [:Object , :fibonaccit]
|
@target = [:Object , :fibonaccit]
|
||||||
parse
|
parse
|
||||||
|
Loading…
Reference in New Issue
Block a user