more renaming ripples
This commit is contained in:
parent
e398a6b053
commit
4783e6c326
43
README.md
43
README.md
@ -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
|
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"
|
hello = "Hello World\n"
|
||||||
@program.main do
|
@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.
|
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.
|
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.
|
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
|
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.
|
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
|
Instead of having more Layers to go from virtual to arm, i opted to have passes that go over the data structure
|
||||||
our hellos in ruby
|
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
|
### Step 9 - Compound types
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
As of writing Kernel is an "old style" module, aka a bunch of functions.
|
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.
|
function.
|
||||||
|
|
||||||
A normal ruby function is one that is parsed and transformed to code. But not all functionality can be written in ruby,
|
A normal ruby function is one that is parsed and transformed to code. But not all functionality can be written in ruby,
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
require_relative "code"
|
require_relative "code"
|
||||||
module Register
|
module Register
|
||||||
|
|
||||||
# Because the idea of what one instruction does, does not always map one to one to real machine
|
# The register machine model is close to current hardware and has following instruction classes
|
||||||
# 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
|
|
||||||
# - Memory
|
# - Memory
|
||||||
# - Stack
|
# - Stack
|
||||||
# - Logic
|
# - Logic
|
||||||
|
@ -7,19 +7,19 @@ module Register
|
|||||||
|
|
||||||
def less_or_equal block , right
|
def less_or_equal block , right
|
||||||
block.cmp( self , right )
|
block.cmp( self , right )
|
||||||
Vm::BranchCondition.new :le
|
Register::BranchCondition.new :le
|
||||||
end
|
end
|
||||||
def greater_or_equal block , right
|
def greater_or_equal block , right
|
||||||
block.cmp( self , right )
|
block.cmp( self , right )
|
||||||
Vm::BranchCondition.new :ge
|
Register::BranchCondition.new :ge
|
||||||
end
|
end
|
||||||
def greater_than block , right
|
def greater_than block , right
|
||||||
block.cmp( self , right )
|
block.cmp( self , right )
|
||||||
Vm::BranchCondition.new :gt
|
Register::BranchCondition.new :gt
|
||||||
end
|
end
|
||||||
def less_than block , right
|
def less_than block , right
|
||||||
block.cmp( self , right )
|
block.cmp( self , right )
|
||||||
Vm::BranchCondition.new :lt
|
Register::BranchCondition.new :lt
|
||||||
end
|
end
|
||||||
def plus block , first , right
|
def plus block , first , right
|
||||||
block.add( self , left , right )
|
block.add( self , left , right )
|
||||||
@ -35,12 +35,12 @@ module Register
|
|||||||
end
|
end
|
||||||
def equals block , right
|
def equals block , right
|
||||||
block.cmp( self , right )
|
block.cmp( self , right )
|
||||||
Vm::BranchCondition.new :eq
|
Register::BranchCondition.new :eq
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_true? function
|
def is_true? function
|
||||||
function.cmp( self , 0 )
|
function.cmp( self , 0 )
|
||||||
Vm::BranchCondition.new :ne
|
Register::BranchCondition.new :ne
|
||||||
end
|
end
|
||||||
|
|
||||||
def move block , right
|
def move block , right
|
||||||
|
@ -85,7 +85,7 @@ module Register
|
|||||||
c_name = clazz.name
|
c_name = clazz.name
|
||||||
my_module = self.class.name.split("::").first
|
my_module = self.class.name.split("::").first
|
||||||
clazz_name = clazz.name.split("::").last
|
clazz_name = clazz.name.split("::").last
|
||||||
if(my_module != Vm )
|
if(my_module != Register )
|
||||||
module_class = eval("#{my_module}::#{clazz_name}") rescue nil
|
module_class = eval("#{my_module}::#{clazz_name}") rescue nil
|
||||||
clazz = module_class if module_class
|
clazz = module_class if module_class
|
||||||
end
|
end
|
||||||
@ -94,11 +94,11 @@ module Register
|
|||||||
|
|
||||||
private
|
private
|
||||||
#defining the instruction (opcode, symbol) as an given class.
|
#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)
|
# 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
|
# These instruction classes must follow a naming pattern and take a hash in the contructor
|
||||||
# Example, a mov() opcode instantiates a Vm::MoveInstruction
|
# Example, a mov() opcode instantiates a Register::MoveInstruction
|
||||||
# for an Arm machine, a class Arm::MoveInstruction < Vm::MoveInstruction exists, and it will
|
# for an Arm machine, a class Arm::MoveInstruction < Register::MoveInstruction exists, and it will
|
||||||
# be used to define the mov on an arm machine.
|
# 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
|
# This methods picks up that derived class and calls a define_instruction methods that can
|
||||||
# be overriden in subclasses
|
# be overriden in subclasses
|
||||||
@ -108,7 +108,7 @@ module Register
|
|||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
options[:opcode] = inst
|
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)
|
clazz.new(first , options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -119,8 +119,8 @@ module Register
|
|||||||
create_method(inst) do |left ,right , options = nil|
|
create_method(inst) do |left ,right , options = nil|
|
||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
left = Vm::Integer.new(left) if left.is_a? Symbol
|
left = Register::Integer.new(left) if left.is_a? Symbol
|
||||||
right = Vm::Integer.new(right) if right.is_a? Symbol
|
right = Register::Integer.new(right) if right.is_a? Symbol
|
||||||
options[:opcode] = inst
|
options[:opcode] = inst
|
||||||
clazz.new(left , right ,options)
|
clazz.new(left , right ,options)
|
||||||
end
|
end
|
||||||
@ -133,9 +133,9 @@ module Register
|
|||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
options[:opcode] = inst
|
options[:opcode] = inst
|
||||||
result = Vm::Integer.new(result) if result.is_a? Symbol
|
result = Register::Integer.new(result) if result.is_a? Symbol
|
||||||
left = Vm::Integer.new(left) if left.is_a? Symbol
|
left = Register::Integer.new(left) if left.is_a? Symbol
|
||||||
right = Vm::Integer.new(right) if right.is_a? Symbol
|
right = Register::Integer.new(right) if right.is_a? Symbol
|
||||||
clazz.new(result, left , right ,options)
|
clazz.new(result, left , right ,options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
3
lib/register/transformations.rb
Normal file
3
lib/register/transformations.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module Register
|
||||||
|
|
||||||
|
end
|
@ -65,7 +65,7 @@ module Virtual
|
|||||||
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 = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ]
|
assigned = [ RegisterReference.new(Register::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)
|
||||||
|
@ -30,7 +30,7 @@ module Virtual
|
|||||||
# Data gets assembled after methods
|
# Data gets assembled after methods
|
||||||
def add_data o
|
def add_data o
|
||||||
return if @objects.include? 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)
|
@data << o # TODO check type , no basic values allowed (must be wrapped)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ HERE
|
|||||||
# a hand coded version of the fibonachi numbers (moved to kernel to be able to call it)
|
# 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
|
# not my hand off course, found in the net from a basic introduction
|
||||||
def test_kernel_fibo
|
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)
|
fibo = @object_space.get_or_create_class(:Object).resolve_function(:fibo)
|
||||||
main = @object_space.main
|
main = @object_space.main
|
||||||
main.mov int , 10
|
main.mov int , 10
|
||||||
main.call( fibo )
|
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)
|
putint = @object_space.get_or_create_class(:Object).resolve_function(:putint)
|
||||||
main.call( 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]
|
@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]
|
||||||
|
@ -20,7 +20,7 @@ class TestRunner < MiniTest::Test
|
|||||||
def execute file
|
def execute file
|
||||||
string = File.read(file)
|
string = File.read(file)
|
||||||
parser = Parser::Salama.new
|
parser = Parser::Salama.new
|
||||||
object_space = Vm::Program.new "Arm"
|
object_space = Register::Program.new "Arm"
|
||||||
syntax = parser.parse_with_debug(string)
|
syntax = parser.parse_with_debug(string)
|
||||||
assert syntax
|
assert syntax
|
||||||
parts = Parser::Transform.new.apply(syntax)
|
parts = Parser::Transform.new.apply(syntax)
|
||||||
@ -31,7 +31,7 @@ class TestRunner < MiniTest::Test
|
|||||||
expr = part.compile( program.context )
|
expr = part.compile( program.context )
|
||||||
else
|
else
|
||||||
expr = part.compile( program.context )
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user