Bug 18597 - gcc internal code gen error with -fPIC
Summary: gcc internal code gen error with -fPIC
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc
Version: 7.0
Hardware: i386
OS: Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: David Lawrence
URL: http://wozzle.geeksrus.net/gcc-error/
Depends On:
TreeView+ depends on / blocked
Reported: 2000-10-07 11:37 UTC by j. alan eldridge
Modified: 2005-10-31 22:00 UTC (History)
3 users (show)

Clone Of:
Last Closed: 2002-12-15 02:17:12 UTC

Attachments (Terms of Use)
all files per jakub@redhat.com both with -fPIC and without (101.01 KB, application/x-gtar)
2000-10-13 01:00 UTC, j. alan eldridge
no flags Details

Description j. alan eldridge 2000-10-07 11:37:10 UTC
Since the gcc folks won't handle this (7.0 includes an unsupported,
*development* release of gcc, and the GCC Steering COmmittee is rather
unhappy about that fact), it falls on RedHat to fix. This is a 
showstopper for compiling the libvrml package.

I do not expect RH to fix the compiler; however, i would like RH to 
come up with a way to compile the offending source file with the 2.96
compiler using the -fPIC option. This may include, but is not limited to,
modifying the source code file e_hypot.c, or supplying an alternate
implementation of the function which will produce the same results (within
reason) for all possible inputs, including erroneous inputs.

e_hypot.c: In function `__ieee754_hypot':
e_hypot.c:148: Unable to find a register to spill in class `AREG'.
e_hypot.c:148: This is the insn:

(insn 418 303 306 (set (subreg:SI (reg/v:DF 9 st(1)) 0)
        (reg/v:SI 54)) 32 {*movsi_1} (insn_list 300 (nil))
    (expr_list:REG_DEAD (reg/v:SI 54)
e_hypot.c:148: Internal compiler error in spill_failure, at reload1.c:1826

All relevant files may be found at the above URL. In additonal, a tarball
'gcc-error.allfiles.tar.gz' may be found in that directory which contains
all the other files.

Comment 1 Jakub Jelinek 2000-10-07 15:30:34 UTC
The mentioned URL gives 404 error, can you please either make sure
it works or supply another URL? You can attach the tarball
as an attachment to this report as well.
Could you also make sure e_hypot.i (generated e.g. if you pass
-save-temps -v options to gcc in addition to the ones being passed
by the Makefiles) is present in the tarball and also the output
of that gcc ... -save-temps -v command?
We'll be issuing errata gcc packages in the near future and will try
to fix your testcase till then.

Comment 2 Daniel Thompson 2000-10-12 15:52:29 UTC
xracer (http://xracer.annexia.org/files/) should provide an example
(tracks/simple2/objTrackScenery.c I think). The file includes a massive array of
static doubles which may give some clues.

gcc (2.96) appears to masively leak memory before reporting an internal error.
Changing optimisations makes no difference. The file works fine under kgcc, it
also provides an obvious (if inconvient) workaround for C-only code.

Comment 3 Jakub Jelinek 2000-10-12 19:27:35 UTC
The xracer issue is actually completely different to the above
mentioned (which I'm still waiting for testcase, hint, hint),
could you please resubmit this as a special new bugzilla report,
so that we can track it separately?
From what I know so far about it, it has nothing to do with -fPIC,
nothing to do with the huge static arrays of floats, but the issue
is that schedule2 with -O2 and above gets upset from the 5160
function calls in one function. I'll run it under debugger tomorrow.

Comment 4 j. alan eldridge 2000-10-13 01:00:16 UTC
Created attachment 4113 [details]
all files per jakub@redhat.com both with -fPIC and without

Comment 5 j. alan eldridge 2000-10-13 01:11:11 UTC
sorry bout the url; it's http://wozzle.geeksrus.net/~alane/gcc-error/, and i
just tested that to make sure the perms were ok. in any event, i reran the test
compile with "--save-temps -v", both with and with -fPIC, and attached a tarball
of the dir pointed to by the url. the file typescript in the tar archive is the
log of the session. there are two output dirs, with-PIC and without-PIC; each
contains all the temp and dump files from gcc.

i don't think kgcc is an option; can it produce shared libraries and object
files which are link compatible with those produced by gcc-2.96? or would this
entail having to run cpp and cc1 from kgcc, but all the binutils from 2.96? and
could i do that without a months supply of diazepam?

oh, btw, this code is from libvrml97-0.8.2, in case you were wondering.

Comment 6 Need Real Name 2000-10-21 22:19:49 UTC
I see the same behavior with the following code.  If it is compiled without
-O, with -DMAKE_BUG_GO_AWAY or with gcc rather than g++, the bug vanishes.

rh7% g++ -Wall -c -O bug.cc
bug.cc: In function `int pthread_mutex_lock (pthread_mutex_t *)':
bug.cc:107: `__pthread_mutex_lock' undeclared (first use this function)
bug.cc:107: (Each undeclared identifier is reported only once for each 
function it appears in.)
bug.cc:108: Unable to find a register to spill in class `AREG'.
bug.cc:108: This is the insn:
(insn 6 434 7 (set (reg/v:SI 42)
        (mem/f:SI (reg:SI 16 argp) 0)) 32 {*movsi_1} (nil)
    (expr_list:REG_DEAD (reg:SI 16 argp)
        (expr_list:REG_EQUIV (mem/f:SI (reg:SI 16 argp) 0)
bug.cc:108: Internal compiler error in spill_failure, at reload1.c:1826
Please submit a full bug report.
See <URL:http://www.gnu.org/software/gcc/bugs.html> for instructions.
rh7% cp bug.cc bug.c
rh7% gcc -Wall -c -O bug.c
bug.c: In function `pthread_mutex_lock':
bug.c:107: warning: implicit declaration of function `__pthread_mutex_lock'
rh7% g++ -Wall -c -O -DMAKE_BUG_GO_AWAY bug.c

I've enclosed the code.  I hope it helps in tracking down the problems.


P.S. Even with bugs like this one, I'm *pleased* you shipped this compiler.
Also, I don't think I need this code anymore anyway, because of the fixes
in glibc 2.2.


#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>

unsigned long int __pthread_spin_limit = 8192;
unsigned long int __pthread_yield_limit = 0;
void *lock_breakpoint = (void *) -1;

#define MUTEX_ISHELD(mutex) \
    *((volatile long int *) &(mutex)->__m_lock.__status)
#define real_pthread_mutex_lock	__pthread_mutex_lock

extern int real_pthread_mutex_lock(pthread_mutex_t * mutex);

#define error_printf(printf_args...)				\
    ((void) ({ char __stringbuffer[4096]; 			\
       sprintf(__stringbuffer, printf_args);			\
       write(2, __stringbuffer, strlen(__stringbuffer));	\
#define debug_printf(printf_args,...)  ((void) 0)

int pthread_mutex_lock(pthread_mutex_t * mutex) {
    int ret;
    unsigned long int spins;
    // SPIN PHASE:
    //   Here we spin around, basically hoping that the other task that
    //   is running only needs the processor for a few instructions.
    //   N.B. There is *no point* in spinning on a uniprocessor machine,
    //   so __pthread_spin_limit should be zero for those machines.
    spins = 0;
    for ( ; ; ) {
	long int status;
	for ( ; ; ) {
	    status = MUTEX_ISHELD(mutex);
	    if (status == 0)
	    #if __linux__
		if (status != 1)
		    goto sleep_phase;
	    if ((lock_breakpoint == 0 || (void *) mutex == lock_breakpoint)
	        && ((spins % 16) == 0)) {
	        error_printf("waiting for %p to be released, spin %lu\n",
		    mutex, spins);
	    if (++spins >= __pthread_spin_limit)
		goto yield_phase;
	if (spins > 0) {
	    debug_printf("lock %p released after %lu spins\n", mutex, spins);
	ret = pthread_mutex_trylock(mutex);
	if (ret != EBUSY) {
	    return ret;
    //   Here we hope that a sched_yield (or perhaps a few) is going to
    //   be enough to persuade whoever has the lock to let go of it.
    //   The hope is that yielding is much easier on system resources than
    //   going to sleep with suspend and getting woken up again.  If so,
    //   this is a good strategy on both uniprocessors and SMP machines.
    //   Experience seems to show that this hope is false-to-fact, however,
    //   so __pthread_yield_limit is set to zero.
    debug_printf("lock %p not released after %lu spins\n", mutex, --spins);
    spins = 0;
    for ( ; ; ) {
	long int status;
	for ( ; ; ) {
	    if (++spins > __pthread_yield_limit)
		goto sleep_phase;
	    if ((lock_breakpoint == 0 || (void *) mutex == lock_breakpoint)
	        && ((spins % 16) == 0)) {
	        error_printf("waiting for %p to be released, yield %lu\n",
			     mutex, spins);
	    status = MUTEX_ISHELD(mutex);
	    if (status == 0)
	    if (status != 1)
		goto sleep_phase;
	if (spins > 0) {
	    debug_printf("lock %p released after %lu yields\n", mutex, spins);
	ret = pthread_mutex_trylock(mutex);
	if (ret != EBUSY)
	    return ret;

    //   By this point, we've either wasted enough of our own time and have
    //   decided to give up, or we have noticed that someone else has given
    //   up.    
    debug_printf("lock %p not released after %lu yields\n", mutex, --spins);
    return real_pthread_mutex_lock(mutex); 

Comment 7 Need Real Name 2000-10-21 23:05:26 UTC
Note that my bug is gone in gcc version 2.97 20001009 (experimental),
as tested using <http://www.codesourcery.com/gcc-compile.shtml>.
(I had to change the name of the undefined symbol, because 
__pthread_mutex_lock is defined in glibc 2.1 and earlier).


GCC Output

These are the results of processing your source code with the following command:

      g++ -c -O -Wall [input] 

Exit code: 256


      /tmp/@12762.7.cc: In function `int pthread_mutex_lock(pthread_mutex_t *)':
      /tmp/@12762.7.cc:107: `__undeclared_pthread_mutex_lock' undeclared (first
      this function)
      /tmp/@12762.7.cc:107: (Each undeclared identifier is reported only once
      each function it appears in.)

Note You need to log in before you can comment on or make changes to this bug.