narrowed down the problem area [naked asm]

Tomas Lindquist Olsen tomas at famolsen.dk
Tue Oct 28 11:08:20 PDT 2008


Don wrote:
> bearophile wrote:
>>
>> The LDC docs say:
>>
>>> One thing the D spec isn't clear about at all is how asm blocks mixed 
>>> with normal D code (for example code between two asm blocks) interacts.<
>>> Currently 'naked' in D is treated as a compile time error in LDC. 
>>> Reason for this is that LLVM does not support directly controlling 
>>> prologue/epilogue generation. Also the documentation from the D spec 
>>> on this topic is extremely limited and doesn't mention anything about 
>>> how normal D code in a naked function works. In particular local 
>>> (stack) variables are unclear, also accessing named parameters etc.<
> 
> I can answer this.

Thank you very much. This will help me a lot implementing 'naked' in LDC :)

> 
> 'naked' in DMD is quite simple: almost nothing works.

:P

> 
> Stack variables with 'naked' don't work. Parameters don't work, either. 
> Nor do contracts. Here's why:
> 
> Regardless of whether 'naked' is specified or not, the compiler creates 
> code exactly as if the function began with 'push EBP; mov EBP, ESP; ' 
> and ended with 'pop EBP; '
> If 'naked' is specified, it just doesn't put that prologue and epilogue in.
> So the only way to use 'naked' is to manually keep track of where 
> everything is on the stack, and index it off the stack pointer.
> 

This actually makes things quite simple, LLVM does frame pointer elimination by default (we 
force it to emit one when normal inline asm is used though), so this condition should just be 
changed to 'if (asmIsUsed && !isNaked) doEBP();'
There's a few other technical issues, mostly related to LLVM using an SSA form and function 
arguments being l-values in D, but that's not really important here...

> Why use 'naked' at all, then?
> (1) so that you can use the EBP register;
> (2) because non-naked asm doesn't work properly, either. If you pass an 
> array into an asm function, you can't get the ".ptr" part of it, because 
> the "ptr" conflicts with the asm "ptr" keyword. This is a big problem, 
> since almost all asm functions that I write work on arrays.
> 

Could we work around this somehow ? Actually I'm not sure we even handle this kind of thing 
properly yet (accessing aggregate fields in asm). I should test that :)

> I don't think that this is how naked asm _should_ work, though. It 
> should allow you to reference parameters without adjusting the offsets 
> assuming you're using EBP. So the following should work:
> 
> void nakedfunc(uint [] dest, uint [] src)
> {
>   asm {
>     naked;
>     mov ECX, dest.ptr[ESP];
>   }
> }

So this should work since you've not modified ESP right? I'm not sure what facilities LLVM 
currently has to get stack offsets of parameters before the actual native codegen, probably 
none.. So this might be a bit difficult to implement in LDC, but again, I'm not really aware of 
all that LLVM's inline asm can really do, since there is basically no documentation, and we've 
only read so much of their source code :P

> 
> Since the spec says:
> "If the [EBP] is omitted, it is assumed for local variables. If naked is 
> used, this no longer holds."
> True, it doesn't put in an [EBP], but it adjusts the offset assuming 
> that a stack frame has been set up. And ".ptr" doesn't work.
> 

This .ptr issue certainly seems like something that should be fixed somehow :)

> 
> Curious fact:
> Whenever I'm naked, my body disappears!
> 
> void fkk()
> {
>    asm { naked; }
> }
> 
> void main() { fkk(); }
> 
> --> generates a linker error. Fair enough, really. But kind of interesting.

This will not happen in LDC, it will just produce what it does without the naked:

_D3bar3fooFZv:
                 ret

Again thanx for these explanations.
Maybe we'll have 'naked' soon in LDC after all :)

-Tomas



More information about the Digitalmars-d mailing list