[CLN-list] Build problems on Solaris 8

Richard B. Kreckel kreckel at ginac.de
Sun Dec 16 21:50:29 CET 2007


Hi Bruno,

Bruno Haible wrote:
>> I had the opportunity to do some testing on a SPARC machine and it turns 
>> out that CLN is indeed broken. However, if one configures with 
>> CPPFLAGS="-DNO_ASM" it works fine and passes all checks.
>>
>> One thing that is sure broken are the functions in cl_low.h that use the 
>> _get_g1 macro. It appears like %g1 contains garbage. Googling around I 
>> was unable to find any useful information. Is there some SPARC expert 
>> who can provide insight into what's going on?
> 
> I'm not a SPARC expert; my info is mostly taken from the GCC machine
> description for SPARC:
> The SPARC registers %g0 ... %g7 are called "global" registers because they
> retain their value upon entry into and exit from a function. %g0 is always 0.
> 
> gcc-2.7.2.3 had this info:
> 
>   On pre-v9 systems                              On v9 systems
>   -----------------                              -------------
>   %g1 used as a temporary by gcc.                likewise
>   %g2..%g4 reserved for the program.             likewise
>   %g5 reserved for the operating system.         used as a temporary by gcc.
>   %g6,%g7 reserved for the operating system.(*)  likewise
> 
> gcc-4.2.2 also notes that on v9 systems:
>   - %g1 and %g5 are not only used as temporaries by gcc but also during
>     calls to external functions via the PLT (the usual case for external
>     symbols in a shared library).
>   - %g4 is now also used as a temporary by gcc.
> 
> So if there is trouble with using %g1, it can be due to one of these:
>   a) use of %g1 as a scratch register by gcc (either due to the use of
>      newer gcc versions, or because some CLN types are now 64-bit that
>      were 32-bit previously),
>   b) use of %g1 by the PLT code.
> 
> You can distinguish these in two ways:
>   - Look at the code generated by gcc (e.g. "make cl_DS_mul.s"). Does it
>     contain use of %g1 as a scratch register between the return from mulu32_
>     and the fetching of the high part of the multiplication result? And in
>     similar locations. If yes, then (a) is the culprit.
>   - Compile cln with  CFLAGS="-fPIC -O2" --disable-shared --enable-static.
>     As I understand it, the PLT will then not contain symbols like mulu32_
>     any more but the code generated is otherwise the same as in the shared
>     library case. If the problems persist, it was (a), otherwise (b).
> 
> Possible fixes: Replace the use of %g1 with %g2 or %g3 (look at the assembly
> code produced by gcc to guess which of the two is likely to work better).
> 
> Bruno
> 
> (*) As I understand it, one of these two is used as the "current thread"
>     pointer. On Linux, it is %g7, see glibc-2.7/nptl/sysdeps/sparc/tls.h :
>       register struct pthread *__thread_self __asm__("%g7");

I was cut off from that sparc machine for a while. But now, I've tried 
compiling the static library with -fPIC and it did not help. However, I 
am also unable to find any scratch usage of %g1 after calls to mulu32_. 
And trying to use %g2, %g3, or %g4 instead of %g1 doesn't help, either.

I'm also unable to reproduce this bug in a tiny laboratory setting:

~/cln-1.2.0$ cat cl_asm_.s
         .seg "text"
         .global mulu32_

         .type mulu32_,#function
mulu32_:
         umul %o0,%o1,%o0
         jmp %o7+8
         rd %y,%g1

~/cln-1.2.0$ cat ltest.cc
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define var
typedef unsigned int uint32;
typedef unsigned long long uint64;

extern "C" uint32 mulu32_ (uint32 arg1, uint32 arg2); // -> Low-Teil

   #define mulu32(x,y,hi_zuweisung,lo_zuweisung)  \
     ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */     \
       {var register uint32 _hi __asm__("%g1");                  \
        hi_zuweisung _hi;                                        \
      }})

int f(uint32 x, uint32 y)
{
     uint32 hi;
     uint32 lo;
     mulu32(x,y,hi=,lo=);
     uint64 ref = (uint64)x * (uint64)y;
     uint32 rhi = ref >> 32;
     uint32 rlo = ref;
     //printf("%d %d\n",hi,lo);
     if (rhi != hi || rlo != lo) {
         printf("Ouch: %d %d vs. %d %d\n", rhi, rlo, hi, lo);
         return 1;
     }
     return 0;
}

int main()
{
     while(!f(rand(),rand()));
}
~/cln-1.2.0$ gcc -O -c cl_asm_.s  &&  g++ -O ltest.cc cl_asm_.o
~/cln-1.2.0$ ./a.out
(*endless loop*)

In such controlled environments, I see no failures. It's only in the 
library where mulu32_ apparently fails.

Say, these functions are the same as the ones in CLisp's arisparc.d. Are 
you sure they work there when compiled with GCC 4.1? If they do, things 
become even more mysterious.

Cheers
   -richy.
-- 
Richard B. Kreckel
<http://www.ginac.de/~kreckel/>


More information about the CLN-list mailing list