rubyx/lib/register
2014-09-16 18:50:44 +03:00
..
assembler.rb collect all add functions at bottom (rename too) 2014-09-16 18:50:44 +03:00
call_implementation.rb make block replace take array or single instruction 2014-08-30 16:57:56 +03:00
code.rb rename code.length tp mem_length with lots of noise impact 2014-09-16 17:16:56 +03:00
enter_implementation.rb use slot constants 2014-09-11 21:30:40 +03:00
instruction.rb rename code.length tp mem_length with lots of noise impact 2014-09-16 17:16:56 +03:00
integer.rb renamed true,false,nil class to constant (from value) 2014-09-14 18:15:33 +03:00
optimisations.rb make space for new passes 2014-08-22 17:46:09 +03:00
README.md fix spelling 2014-08-28 22:32:53 +03:00
reference.rb rename code.length tp mem_length with lots of noise impact 2014-09-16 17:16:56 +03:00
register_machine.rb get some old builtin code backonline and improve imports 2014-09-09 18:03:13 +03:00
register_reference.rb adjusted module name accordingly 2014-08-22 17:40:09 +03:00
return_implementation.rb use slot constants 2014-09-11 21:30:40 +03:00
set_implementation.rb just checking which part of unimplemented i hit 2014-09-14 21:26:30 +03:00
transformations.rb more renaming ripples 2014-08-22 18:00:23 +03:00

Register Machine

This is the logic that uses the compiled virtual object space to produce code and an executable binary.

There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the plain ones in this directory don't assemble to binary). Currently there is only the Arm module to actually do that.

The elf module is used to generate the actual binary from the final BootSpace. BootSpace is a virtual class representing all objects that will be in the executable. Other than CompiledMethods, objects get transformed to data.

But CompiledMethods, which are made up of Blocks, are compiled into a stream of bytes, which are the binary code for the function.

Virtual Objects

There are four virtual objects that are accessible (we can access their variables):

  • Self
  • Message (arguments, method name, self)
  • Frame (local and tmp variables)
  • NewMessage ( to build the next message sent)

These are pretty much the first four registers. When the code goes from virtual to register, we use register instructions to replace virtual ones.

Eg: A Virtual::Set can move data around inside those objects. And since in Arm this can not be done in one instruciton, we use two, one to move to an unused register and then into the destination. And then we need some fiddling of bits to shift the type info.

Another simple example is a Call. A simple case of a Class function call resolves the class object, and with the method name the function to be found at compile-time. And so this results in a Register::Call, which is an Arm instruction.

A C call

Ok, there are no c calls. But syscalls are very similar. This is not at all as simple as the nice Class call described above.

For syscall in Arm (linux) you have to load registers 0-x (depending on call), load R7 with the syscall number and then issue the software interupt instruction. If you get back something back, it's in R0.

In short, lots of shuffling. And to make it fit with our four object architecture, we need the Message to hold the data for the call and Sys (module) to be self. And then the actual functions do the shuffle, saving the data and restoring it. And setting type information according to kernel documentation (as there is no runtime info)