Odd weak symbol thing on i386

Hi,

I'm compiling lldiv.c from the NetBSD standard library. It works on ARM, Mips,
Microblaze,ppc, ppc64, and x86_64. On i386 a very strange thing happens.
Here's the source:

#include <stdlib.h>
#define __weak_alias(sym) __attribute__ ((weak, alias (#sym)))
    
lldiv_t lldiv(long long int num, long long int denom) __weak_alias(_lldiv);

lldiv_t _lldiv(long long num, long long denom)
{
        lldiv_t r;
        r.quot = num / denom;
        r.rem = num % denom;
        if (num >= 0 && r.rem < 0) {
                r.quot++;
                r.rem -= denom;
        }
        return (r);
}

I get the following code emitted for the return if the alias line is present:

LBB0_3: # %if.end
  movl 64(%esp), %eax
  movsd 24(%esp), %xmm0
  movsd 32(%esp), %xmm1
  movsd %xmm1, 8(%eax)
  movsd %xmm0, (%eax)
  addl $56, %esp
  popl %esi
  ret
.Ltmp0:
  .size _lldiv, .Ltmp0-_lldiv

  .weak lldiv
lldiv = _lldiv

And this if it isn't:
LBB0_3: # %if.end
  movl 64(%esp), %eax
  movsd 24(%esp), %xmm0
  movsd 32(%esp), %xmm1
  movsd %xmm1, 8(%eax)
  movsd %xmm0, (%eax)
  addl $56, %esp
  popl %esi
  ret $4
.Ltmp0:
  .size _lldiv, .Ltmp0-_lldiv

Other than the $4 on the return address, the code is otherwise identical. The
alias version crashes, of course. Is there supposed to be an implicit pop of
the return structure pointer? What could cause an alias to mess this up?

-Rich

Bad version:
define void @_lldiv(%struct.lldiv_t* noalias %agg.result, i64 %num,
i64 %denom) nounwind {

Good version:
define void @_lldiv(%struct.lldiv_t* noalias sret %agg.result, i64
%num, i64 %denom) nounwind {

Looks like a bug in clang's IR generation; please file a bug.

-Eli

Looks like a bug in clang's IR generation; please file a bug.

I reported pr11770. Thanks Richard!

-Eli

Cheers,
Rafael