Monday, May 7, 2007

Everything is a Register!

My exploitration of Exupery brings some fruits - an assembler generator using smalltalk syntax.
I don't know how this package might be useful - you decide.
I'm just make it accessible for potential users.

Generator takes a given method source code (not bytecode) and transforms it to pure asm instructions (with help of Exupery).
The way its done is like what VMMaker does, which also parses a method and creates it analogue in C.

Take a look at sample asm program:

message3
| a b c |
c := 1.
b := 2.
(b + c) ifLess: [
a := 5.
(b - 1) ifZero: [ a := 10 ]
].
^ a
First thing to remember: everything is a register not an object!
You allowed to assign them, return , make ariphmetic/logical ops.
The control flow selectors is based on processor flags (so using ifTrue/IfFalse is pointless here and will lead to DNU). All set of selectors you can find in #AsmSelectors

The example given before produces a following immediate form:

#(#(#block 1
#(#mov 1 't2')
#(#mov 2 't3')
#(#add 't3' 't2')
#(#jge #block5))
#(#block 2
#(#mov 5 't1')
#(#sub 't3' 1)
#(#jnz #block4))
#(#block 3
#(#mov #(#mov 10 't1') 't5'))
#(#block 4
#(#mov 't5' 't4'))
#(#block 5
#(#return 't1')))
It then can be processed furter with Exupery with optimization/registers allocation to get a ready to run assembler code.

I plan to add support to far calls and inlining (which is easiest part).
The call (and any special instruction) started from self as receiver.

I plan to add following:

self pragma: #inline
self pragma: #cdecl
self pragma: #apicall

- to indicate which prologue/epilogue generate for function. #inline can be compiled as standalone function only in case if you do not have any parameters on it (unary selector).

self call: #selector:with:with with: .. with: .. ...

- this one for local call of a function which must be present in same class, where parsed method resides. It can be inlined if you put self pragma: #inline in source

self inlinecall: #selector:with:with with: .. with: .. ...

- same as above, but forcing inline.

self callC: #selector:with:with with: .. with: .. ...
self callApi: #selector:with:with with: .. with: .. ...

- this one for external calls using appropriate calling convention far beyond the squeak :) You must register an Integer address for given selector in dictionary of external selectors.

A potential use of this stuff is a callbacks. I'm not decided yet how to hook with VM (some advice with Bryce is needed) , but i think that can be solved in elegant manner.
Also, i have pervasive intentions to allow hot-swapping a core VM routines, so VM will recompile itself without knowing about it :)

And moreover, in some far future i might want that full C source of VM will look like following:
int main(...)
{
buf = loadImage();
(void fn*) = buf->entryPoint;

return fn();
}

No comments: