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.

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