My explo[it]ration 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 making 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 mem/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 intermediate 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 calls (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 its 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 some dictionary of external selectors. A potential use of this stuff is a callbacks. I'm not decided yet how to hook it with VM (some advice with Bryce is needed) , but i think this 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(); } You can filein an .st file in attached rar. Its not overrides anything, so if you curious you can file it in without a risk of breaking image. Translation to ASM.rar (5K) Download Attachment |
Why do you have this special syntaxe? Why don't you use the Smalltalk
bytcode? Mth On May 7, 2007, at 12:54 PM, sig wrote: > ((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'))) |
On 07/05/07, Mathieu Suen <[hidden email]> wrote:
> Why do you have this special syntaxe? Why don't you use the Smalltalk > bytcode? > because a set of asm instructions is very small. And this syntax reflects them, nothing more, nothing less. I left a way for possible extensions/replacement - you can supply own class with instruction set to parser. And external libraries don't know how to deal with smallints/oops. They understand only raw values and pointers to data. As for bytecode you already having Exupery. But it will generate an assembly which targeted for using with oops (tagged integers everywhere, e.t.c). My generator acting with variables/values as with registers, not oops. That's why i called the topic 'Everything is a Register'. |
and in addition, a simple example why i'm not using a smalltalk
standart selectors. for loading a value via indirect pointer you might put with my syntax: val := b loadDword loadDword. " load value from memory location pointed by b, then load value pointed by value " same , but using smalltalk standart selectors: val := self at: (self at: b) . more complex case: val := (b loadDword + 4) loadDword in smalltalk will look like: val := self at: (self at: b) + 4 . --- conditional branching smalltalk: (a > b ) ifTrue: [] ifFalse:[] my syntax: (a cmp: b) ifGreater: [] else: [] or a = b ifGreater: [] else: [] -- checking for a zero: ( a := b - 1 ) ifZero: [] .. smalltalk: a := b - 1. a = 0 ifTrue: [] .. -- there also branching selectors like ifCarry, ifOverflow which don't have a meaning in smalltalk at all. |
In reply to this post by Mathieu SUEN
Mathieu Suen writes:
> Why do you have this special syntaxe? Why don't you use the Smalltalk > bytcode? > On May 7, 2007, at 12:54 PM, sig wrote: > > > ((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'))) The format shown is just a written form of Exupery's low level intermediate. It was originally created for unit testing, it can be used to create intermediate objects, to compare outupt, and to set up mocks. In normal operation, Exupery will translate bytecode through several intermediate forms to create tolerably efficient machine code. Bryce |
lol.. i missed the collapsed quoted text and thought that Mathieu
complaining about smalltalk syntax given in example, not intermediate form. :))) No, Mathieu, you'll write an asm routine as regular smalltalk method, just using special set of selectors :) Everything else is not your problem. |
On May 7, 2007, at 2:50 PM, sig wrote:
> lol.. i missed the collapsed quoted text and thought that Mathieu > complaining about smalltalk syntax given in example, not intermediate > form. :))) Not complaining juste asking :) > > No, Mathieu, you'll write an asm routine as regular smalltalk method, > just using special set of selectors :) > Everything else is not your problem. > You can take a look at the NewCompiler you can write somthings like: | iRMethod aCompiledMethod | iRMethod := IRBuilder new numRargs: 1; addTemps: #(self); "receiver and args declarations" pushLiteral: $e; returnTop; ir. aCompiledMethod := iRMethod compiledMethod. aCompiledMethod valueWithReceiver: nil arguments: #() Mth |
On 07/05/07, Mathieu Suen <[hidden email]> wrote:
> On May 7, 2007, at 2:50 PM, sig wrote: > > > lol.. i missed the collapsed quoted text and thought that Mathieu > > complaining about smalltalk syntax given in example, not intermediate > > form. :))) > > Not complaining juste asking :) > sorry, my English is bad :) > You can take a look at the NewCompiler you can write somthings like: > > | iRMethod aCompiledMethod | > iRMethod := IRBuilder new > numRargs: 1; > addTemps: #(self); "receiver and args declarations" > pushLiteral: $e; > returnTop; > ir. > > aCompiledMethod := iRMethod compiledMethod. > aCompiledMethod valueWithReceiver: nil arguments: #() > well this will produce a CompiledMethod instance. I am right? Maybe i was unclear in explaining what my generator produces? It not produces bytecode for squeak VM. It produces bytecode for PC CPU, also known as assembler instructions. You can't run them from squeak directly, a special plugin/primitive will be required to do so. If your PC CPU understands ST-80 bytecode then my generator is useless. |
In reply to this post by Igor Stasenko
Hello Sig,
s> My explo[it]ration of Exupery brings some fruits - an assembler s> generator using smalltalk syntax. :) I like that very much but I didn't manage to find out - who will translate the assembler into actual X86 machine code - how to run the generated code from Squeak. Am I being dense? Me having still one leg in a world where I replaced C-code by handwritten assembler to speed up digital signal processing :-)) Cheers, Herbert mailto:[hidden email] |
On 07/05/07, Herbert König <[hidden email]> wrote:
> Hello Sig, > > s> My explo[it]ration of Exupery brings some fruits - an assembler > s> generator using smalltalk syntax. :) > > I like that very much but I didn't manage to find out > - who will translate the assembler into actual X86 machine code > - how to run the generated code from Squeak. > I'm not finished yet. It require to perform few additional steps to produce final code: replace returns and add prologue/epilogue to function corresponding to supplied calling convention. In case if you using a local calls, there also need to keep track relocation points, to replace them by concrete absolute address values when code is placed in fixed memory (Exupery have this already, i just didn't developped to that point). In any case you need an Exupery to produce final code, and ExuperyPlugin if you want to install and run it. You'd better ask Bryce about that, i don't know details yet (have to dig details). It may require to add few primitives especially designed to run my pure assembly. Or you can write own plugin, which i not recommend to do (Increasing a code written in C is the worst solution as for me :) ). Its simple enough to implement by own: allocate fixed system memory with execution permission, place generated code there and return a pointer to function entry point. Then you can use FFI to run the code. Also, some trickery can be used to register the function as primitive. The consequences of running pure assembler of course laying on solely on the author. There a high risk that buggy assembler code will attempt to access protected memory or broke C stack using incorrectly set calling convention. But these risks get rewarded considerably :) > Am I being dense? > > Me having still one leg in a world where I replaced C-code by > handwritten assembler to speed up digital signal processing :-)) > I'm greatly inspired by Ian Pumiatra COLA/Pepsi project. I want to free from shackles of C. |
In reply to this post by Mathieu SUEN
>From: Mathieu Suen <[hidden email]>
>Reply-To: The general-purpose Squeak developers >list<[hidden email]> >To: The general-purpose Squeak developers >list<[hidden email]> >Subject: Re: Everything is a Register! >Date: Mon, 7 May 2007 15:08:49 +0200 > >You can take a look at the NewCompiler you can write somthings like: > > | iRMethod aCompiledMethod | > iRMethod := IRBuilder new > numRargs: 1; > addTemps: #(self); "receiver and args declarations" > pushLiteral: $e; > returnTop; > ir. > > aCompiledMethod := iRMethod compiledMethod. > aCompiledMethod valueWithReceiver: nil arguments: #() > > Mth But this is talking to the Smalltalk VM, which is a stack machine. He is trying to write directly to the host CPU, which is more register oriented. _________________________________________________________________ Download Messenger. Join the im Initiative. Help make a difference today. http://im.live.com/messenger/im/home/?source=TAGHM_APR07 |
well, IRBuilder can be used too :)
Suppose you wrote a class, which methods is solely in asm. Then, adding something like this in your class will do funny trick: MyClass class>>new | gen | self isAlreadyWrapped ifTrue: [ ^ self basicNew ]. gen := AsmGenerator new createAssemblyFor: self. " compile instance methods and prepare them for use" gen GenerateWrappersFor: self ^ self basicNew --- A GenerateWrappersFor must do the following: generate a CompiledMethod for each method in class which actually wraps call to assembler function, and replace a method in MyClass methods dictionary. As result you get an easy and transparent form for calling your asm code. instance := MyClass new. "create an instance, and have fun" instance myAsmRoutine1: 5 with: 10 ... "call an assemler method via wrapper " On 07/05/07, J J <[hidden email]> wrote: > >From: Mathieu Suen <[hidden email]> > >Reply-To: The general-purpose Squeak developers > >list<[hidden email]> > >To: The general-purpose Squeak developers > >list<[hidden email]> > >Subject: Re: Everything is a Register! > >Date: Mon, 7 May 2007 15:08:49 +0200 > > > >You can take a look at the NewCompiler you can write somthings like: > > > > | iRMethod aCompiledMethod | > > iRMethod := IRBuilder new > > numRargs: 1; > > addTemps: #(self); "receiver and args declarations" > > pushLiteral: $e; > > returnTop; > > ir. > > > > aCompiledMethod := iRMethod compiledMethod. > > aCompiledMethod valueWithReceiver: nil arguments: #() > > > > Mth > > But this is talking to the Smalltalk VM, which is a stack machine. He is > trying to write directly to the host CPU, which is more register oriented. > > _________________________________________________________________ > Download Messenger. Join the i'm Initiative. Help make a difference today. > http://im.live.com/messenger/im/home/?source=TAGHM_APR07 > > > |
Free forum by Nabble | Edit this page |