[LLVMdev] How to represent __attribute__((fastcall)) functions in the IL

Chandler Carruth chandlerc at google.com
Fri Oct 19 08:40:27 PDT 2012


Personally, I'd love to see a setup where instead of LLVM implementing each
calling convention and ABI hack, we provide a means of actually describing
this. Specifically, I'd love to see a design for how to specify in the IR
which register(s) (if any register(s)) a particular value should be placed
into.

Don't get me wrong, I don't have any good ideas about how to do this, I'm
just hoping someone does. End result might allow something like:

declare void @foo(double inreg <eax,edx> %x)


On Fri, Oct 19, 2012 at 8:17 AM, Rafael EspĂ­ndola <
rafael.espindola at gmail.com> wrote:

> Functions with __attribute__((fastcall)) pop their arguments and take
> up to two arguments in ecx and edx. Currently we represent them by
> just setting the x86_fastcallcc calling convention. The problem is
> that the ABI has some strange conventions on when a register is used
> or not. For example:
>
> void __attribute__((fastcall)) foo1(int y);
>
> will take 'y' in ecx, but
>
> struct S1 {
>   int x;
> };
> void __attribute__((fastcall)) foo2(struct S1 y);
>
> will use the stack. Even more surprising is that
>
> void __attribute__((fastcall)) foo8(struct S1 a, int b);
>
> will take 'a' in the stack but 'b' in *edx*. That is, the first
> argument consumed ecx but didn't use it. The implement this the IL
> needs to be able to represent that
> * an argument will go on registers
> * a register was consumed but unused
>
> A way to do this is to make clang produce byval for anything that goes
> on the stack, but that produces worse code as the caller now has to
> use an alloca instead of a simple value.
>
> Another option (which I implemented in a patch just sent to
> llvm-commits) is use the inreg attribute which we already use for the
> regparm C attribute. The above requirements are handled by putting
> inreg in the arguments that should go in register and creating a inreg
> padding argument when a register should be consumed but not used.
>
> The above examples would be irgened to:
>
> declare x86_fastcallcc void @foo1(i32 inreg
>
> declare x86_fastcallcc void @foo2(i32 inreg  /*dummy*/ , i32)
>
> declare x86_fastcallcc void @foo8(i32 inreg /*dummy*/, i32, i32 inreg)
>
> As Eli pointed out on llvm-commits, this would change the meaning of
> existing  x86_fastcallcc IL files, but given that they are only
> produced for fastcall C functions and those are fairly broken without
> this fix, I assume that is OK.
>
> Cheers,
> Rafael
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121019/c587325e/attachment.html>


More information about the llvm-dev mailing list