develooper Front page | perl.daily-build | Postings from April 2004

Re: OpenBSD failures: OS bug, Compiler bug, or Perl bug?

Thread Next
From:
Marcus Holland-Moritz
Date:
April 26, 2004 01:00
Subject:
Re: OpenBSD failures: OS bug, Compiler bug, or Perl bug?
Message ID:
20040426073309.5e32cda1@r2d2
On 2004-04-24, at 18:06:40 +0200, Marcus Holland-Moritz wrote:

> Wow, this one really makes my head ache.
> 
> You've probably noticed the recent smoke failures on OpenBSD 3.5:
> 
> > [stdio] -Duse64bitint
> >     ../lib/Tie/SubstrHash.t.................FAILED 11-20
> >     ../lib/integer.t........................FAILED 10
> >     ../lib/warnings.t.......................FAILED 461
> >     ../t/op/int.t...........................FAILED 8 11-12
> >     ../t/op/pack.t..........................FAILED 332 335 338 442
> > 
> >            [lots of pack.t failures skipped]
> >                                                    12888
> >     ../t/op/sprintf.t.......................FAILED 129
> 
> I especially don't like the t/op/pack.t failures because of my byte
> order patch (which is innocent in this case, as the failures were
> there before my patch already).
> 
> The failures only occur with -Duse64bitint.
> 
> [...]
> 
> So if anyone would like to share their thoughts on the above (or
> OpenBSD knowledge, these are my first three OpenBSD installs)
> with me, that would be great.

Ok, I found it... :)

Looking at the generated assembly code revealed that casting 'double'
to 'unsigned long long' calls __fixunsdfdi(). GCC implements this
function, as does OpenBSD's libc (!). Now, the cool thing is that
casting works as long as you do _not_ link libc to your executable.
I you do (and Perl does), you start getting wrong results for values
larger 2**32:

  $ uname -a
  OpenBSD openbsd34.mhxnet 3.4 GENERIC#18 i386
  $ cat test.c                      
  #include <stdio.h>
  
  typedef double NV;
  typedef unsigned long long UV;
  
  int main(void)
  {
    NV f = 4294967303.15;
    UV u = (UV) f;
    printf("%f => %llu\n", f, u);
    return 0;
  }
  $ cc -o test test.c && ./test     
  4294967303.150000 => 4294967303
  $ cc -o test -lc test.c && ./test 
  4294967303.150000 => 4294967304
                       ^^^^^^^^^^  WRONG

The function in OpenBSD's libc is broken, and it is called instead of
libgcc's one.

I've reported this to the OpenBSD people and they fixed it in their
repository, so I guess it will be fixed in the official 3.5 release.

Marcus

-- 
Machine-Independent, adj.:
	Does not run on any existing machine.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About