On Fri, Jan 13, 2012 at 2:53 PM, Richard Pennington <rich at pennware.com>
wrote:> 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?
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