Kees van Reeuwijk
2010-Jul-08 12:58 UTC
[LLVMdev] X86 gcc and clang have incompatible calling conventions for returning some small structs?
Hello, I think I have come across an inconsistency between gcc and clang/llvm with respect to returning small structs. Given the following code:> struct s { > int a; > int b; > }; > > struct s3 { > int a; > int b; > int c; > }; > > struct s new_s(int v){ > struct s res; > res.a = v; > res.b = -v; > return res; > } > > struct s3 new_s3(int v){ > struct s3 res; > res.a = v; > res.b = -v; > res.c = v<<2; > return res; > }For the function new_s() both the current Ubuntu gcc and the current Ubuntu clang generate code to return struct s in registers. However for the function new_s3() the gcc compiler uses the stack, whereas clang uses registers, so the generated code is not compatible. $ gcc --version gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3 $ clang --version clang version 1.1 (branches/release_27) Target: x86_64-pc-linux-gnu Thread model: posix It is possible that this is specific to the Ubuntu clang or gcc, but it seems unlikely that the Ubuntu people would tinker with this. More generally, I'm looking for the exact specification of the calling conventions that llvm supports, in particular for returning small structs. I'm also looking for a way to let llvm always use the stack for such small structures, since that's the calling convention on the platform I'm porting to (Minix 3). Thanks for any help with this. -- Dr. Ir. Kees van Reeuwijk, Vrije Universiteit Amsterdam
Eli Friedman
2010-Jul-08 17:32 UTC
[LLVMdev] X86 gcc and clang have incompatible calling conventions for returning some small structs?
On Thu, Jul 8, 2010 at 5:58 AM, Kees van Reeuwijk <reeuwijk at few.vu.nl> wrote:> For the function new_s() both the current Ubuntu gcc and the current Ubuntu clang generate code to return struct s in registers. > However for the function new_s3() the gcc compiler uses the stack, whereas clang uses registers, so the generated code is not > compatible.clang code: new_s3: movl %edi, %edx movl %edx, %eax negl %eax shlq $32, %rax addq %rdx, %rax shll $2, %edx ret gcc code: new_s3: movl %edi, %eax leal 0(,%rdi,4), %edx movl %edi, -24(%rsp) negl %eax movl %eax, -20(%rsp) movq -24(%rsp), %rax ret Both compilers are in fact returning the struct in RAX and RDX. gcc is just preferring to compute the value of RAX using the stack; -24(%rsp) is scratch space. The relevant specification is http://www.x86-64.org/documentation/abi.pdf . -Eli