more renaming ripples

This commit is contained in:
Torsten Ruger 2014-08-22 18:00:23 +03:00
parent e398a6b053
commit 4783e6c326
10 changed files with 37 additions and 65 deletions

View File

@ -12,7 +12,7 @@ Ie only in ruby code do i want to create machine code.
Most instructions are in fact assembling correctly. Meaning i have tests, and i can use objbump to verify the correct assembler code is disasembled
I even polished the dsl an so (from the tests), this is a valid hello world:
I even polished the dsl and so (from the tests), this is a valid hello world:
hello = "Hello World\n"
@program.main do
@ -31,7 +31,7 @@ I even polished the dsl an so (from the tests), this is a valid hello world:
Package the code into an executable. Run that and verify it's output. But full elf support (including externs) is eluding me for now.
Still, this has proven to be a good review point for the arcitecture and means no libc for now.
Full rationale on the web (pages rep for now), but it means starting an extra step
Full rationale on the web pages, but it means starting an extra step.
Above Hello World can be linked and run. And will say its thing.
@ -46,43 +46,20 @@ Parse simple code, using Parslet.
Parsing is a surprisingly fiddly process, very space and order sensitive. But Parslet is great and simple
expressions (including function definitions and calls) are starting to work.
I Spent some time on the parse testing framework, so it is safe to fiddle and add.
I spent some time on the parse testing framework, so it is safe to fiddle and add.
### Step 5 - Vm: Compile the Ast
### Step 5 - Virtual: Compile the Ast
Since we now have an Abstact syntax tree, it needs to be compiled to a machine Instruction format.
Since we now have an Abstact syntax tree, it needs to be compiled to a virtual machine Instruction format.
The machine/instruction/data definitions make up the Virtual Machine layer (vm directory)
It took me a while to come up with a decent but simple machine model. I had tried to map straight to hardware
but failed. The current Virtual directory represent a machine with basic oo features.
After some trying around, something has emerged. As it uses the instructions from Step 1, we are ready to say
our hellos in ruby
Instead of having more Layers to go from virtual to arm, i opted to have passes that go over the data structure
and modify it.
puts("Hello World")
This is where it's at really :-)
was the first to make the trip: parsed to ast, compiled to Instructions/Code, linked and assembled to binary
and executed, gives the surprising output of "Hello World"
Time to add some meat.
### Step 6 - Register allocation
A first version of register allocation is done. I moved away from the standard c calling convention to pin a
type register and also not have passing and return overlapping.
That at least simplified thinking about register allocation. One has to remember the machine level is completely
value and pass by value based.
As a side i got a return statement done now, and implicit return at the end has been working. Just making sure all
branches actually return implicitly is not done. But no rush there, as one can always write the return explicitly.
### Step 7 - Basic type instructions
As we want to work on values, all the value methods have to be implemented to map to machine instructions.
Some are done, most are not. But they are straightforward.
### Step 8 - Object creation
Move to objects, static memory manager, class, superclass, metaclass stuff
### Step 9 - Compound types

View File

@ -2,7 +2,7 @@
As of writing Kernel is an "old style" module, aka a bunch of functions.
These functions return their code, ie a Vm::Function object, which can then be called by ruby code as if it were a "normal"
These functions return their code, ie a Register::Function object, which can then be called by ruby code as if it were a "normal"
function.
A normal ruby function is one that is parsed and transformed to code. But not all functionality can be written in ruby,

View File

@ -1,15 +1,7 @@
require_relative "code"
module Register
# Because the idea of what one instruction does, does not always map one to one to real machine
# instructions, and instruction may link to another instruction thus creating an arbitrary list
# to get the job (the original instruciton) done
# Admittately it would be simpler just to create the (abstract) instructions and let the machine
# encode them into what-ever is neccessary, but this approach leaves more possibility to
# optimize the actual instruction stream (not just the salama instruction stream). Makes sense?
# We have basic classes (literally) of instructions
# The register machine model is close to current hardware and has following instruction classes
# - Memory
# - Stack
# - Logic

View File

@ -7,19 +7,19 @@ module Register
def less_or_equal block , right
block.cmp( self , right )
Vm::BranchCondition.new :le
Register::BranchCondition.new :le
end
def greater_or_equal block , right
block.cmp( self , right )
Vm::BranchCondition.new :ge
Register::BranchCondition.new :ge
end
def greater_than block , right
block.cmp( self , right )
Vm::BranchCondition.new :gt
Register::BranchCondition.new :gt
end
def less_than block , right
block.cmp( self , right )
Vm::BranchCondition.new :lt
Register::BranchCondition.new :lt
end
def plus block , first , right
block.add( self , left , right )
@ -35,12 +35,12 @@ module Register
end
def equals block , right
block.cmp( self , right )
Vm::BranchCondition.new :eq
Register::BranchCondition.new :eq
end
def is_true? function
function.cmp( self , 0 )
Vm::BranchCondition.new :ne
Register::BranchCondition.new :ne
end
def move block , right

View File

@ -85,7 +85,7 @@ module Register
c_name = clazz.name
my_module = self.class.name.split("::").first
clazz_name = clazz.name.split("::").last
if(my_module != Vm )
if(my_module != Register )
module_class = eval("#{my_module}::#{clazz_name}") rescue nil
clazz = module_class if module_class
end
@ -94,11 +94,11 @@ module Register
private
#defining the instruction (opcode, symbol) as an given class.
# the class is a Vm::Instruction derived base class and to create machine specific function
# the class is a Register::Instruction derived base class and to create machine specific function
# an actual machine must create derived classes (from this base class)
# These instruction classes must follow a naming pattern and take a hash in the contructor
# Example, a mov() opcode instantiates a Vm::MoveInstruction
# for an Arm machine, a class Arm::MoveInstruction < Vm::MoveInstruction exists, and it will
# Example, a mov() opcode instantiates a Register::MoveInstruction
# for an Arm machine, a class Arm::MoveInstruction < Register::MoveInstruction exists, and it will
# be used to define the mov on an arm machine.
# This methods picks up that derived class and calls a define_instruction methods that can
# be overriden in subclasses
@ -108,7 +108,7 @@ module Register
options = {} if options == nil
options.merge defaults
options[:opcode] = inst
first = Vm::Integer.new(first) if first.is_a? Symbol
first = Register::Integer.new(first) if first.is_a? Symbol
clazz.new(first , options)
end
end
@ -119,8 +119,8 @@ module Register
create_method(inst) do |left ,right , options = nil|
options = {} if options == nil
options.merge defaults
left = Vm::Integer.new(left) if left.is_a? Symbol
right = Vm::Integer.new(right) if right.is_a? Symbol
left = Register::Integer.new(left) if left.is_a? Symbol
right = Register::Integer.new(right) if right.is_a? Symbol
options[:opcode] = inst
clazz.new(left , right ,options)
end
@ -133,9 +133,9 @@ module Register
options = {} if options == nil
options.merge defaults
options[:opcode] = inst
result = Vm::Integer.new(result) if result.is_a? Symbol
left = Vm::Integer.new(left) if left.is_a? Symbol
right = Vm::Integer.new(right) if right.is_a? Symbol
result = Register::Integer.new(result) if result.is_a? Symbol
left = Register::Integer.new(left) if left.is_a? Symbol
right = Register::Integer.new(right) if right.is_a? Symbol
clazz.new(result, left , right ,options)
end
end

View File

@ -0,0 +1,3 @@
module Register
end

View File

@ -65,7 +65,7 @@ module Virtual
def locals_at l_block
used =[]
# call assigns the return register, but as it is in l_block, it is not asked.
assigned = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ]
assigned = [ RegisterReference.new(Register::RegisterMachine.instance.return_register) ]
l_block.reachable.each do |b|
b.uses.each {|u|
(used << u) unless assigned.include?(u)

View File

@ -30,7 +30,7 @@ module Virtual
# Data gets assembled after methods
def add_data o
return if @objects.include? o
raise "must be derived from Code #{o.inspect}" unless o.is_a? Vm::Code
raise "must be derived from Code #{o.inspect}" unless o.is_a? Register::Code
@data << o # TODO check type , no basic values allowed (must be wrapped)
end

View File

@ -30,12 +30,12 @@ HERE
# a hand coded version of the fibonachi numbers (moved to kernel to be able to call it)
# not my hand off course, found in the net from a basic introduction
def test_kernel_fibo
int = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
int = Register::Integer.new(Register::RegisterMachine.instance.receiver_register)
fibo = @object_space.get_or_create_class(:Object).resolve_function(:fibo)
main = @object_space.main
main.mov int , 10
main.call( fibo )
main.mov( Vm::RegisterMachine.instance.receiver_register , Vm::RegisterMachine.instance.return_register )
main.mov( Register::RegisterMachine.instance.receiver_register , Register::RegisterMachine.instance.return_register )
putint = @object_space.get_or_create_class(:Object).resolve_function(:putint)
main.call( putint )
@should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x52,0xe3,0x2,0x0,0xa0,0xd1,0x7,0x0,0x0,0xda,0x1,0x30,0xa0,0xe3,0x0,0x40,0xa0,0xe3,0x4,0x30,0x83,0xe0,0x4,0x40,0x43,0xe0,0x1,0x20,0x42,0xe2,0x1,0x0,0x52,0xe3,0xfa,0xff,0xff,0x1a,0x3,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]

View File

@ -20,7 +20,7 @@ class TestRunner < MiniTest::Test
def execute file
string = File.read(file)
parser = Parser::Salama.new
object_space = Vm::Program.new "Arm"
object_space = Register::Program.new "Arm"
syntax = parser.parse_with_debug(string)
assert syntax
parts = Parser::Transform.new.apply(syntax)
@ -31,7 +31,7 @@ class TestRunner < MiniTest::Test
expr = part.compile( program.context )
else
expr = part.compile( program.context )
raise "should be function definition for now" unless expr.is_a? Vm::Function
raise "should be function definition for now" unless expr.is_a? Register::Function
end
end