🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gcc.bug
Article #1896

(mostly) benign bug in global-alloc.c (GCC 1.30)

#1896
From: Ron Guilmette
Date: Wed, 26 Oct 1988 22:57
129 lines
4906 bytes
BUG in GCC 1.30  -- suggested fix included below

In GCC 1.30 (and GCC 1.29) there is an insidious little bug which is
apparently benign in most circumstances, but which can wreak havoc on
some machines and with some native compilers used for bootstraping GCC
(e.g. The GNX 3.X C compiler).

It seems that GCC somtimes tries to put 2 word (8-byte) struct's into
registers.  Then, when it needs to access one of the fields of the struct
in question, it has to calculate the REGNO which holds the field in
question.  This happens in global-alloc.c in the set_preference()
function.

Unfortunately, the offset calculation there is screwy, so that it sometimes
ends up yielding a (-1) offset.  If this gets added to a (base) REGNO value
which ahppens to be ZERO then you end up with a REGNO of -1.  This incorrect
REGNO is then used as a shift count to set a bit in one of the entries in the
table of bit-arrays called hard_reg_preferences.

NOTE THAT THE INCORRECT NEGATIVE REGNO APPEARS ON BOTH A NATIONAL VME532 AND
ON THE SEQUENT-BALANCE.  You can see it happen if you use the stage1 compiler
to recompile either of the files {stmt.c or expr.c} from GCC 1.30.

God only knows what other machines this happens on!

Now ANSI says that if you do:

	x |= (1 << (-1));

that the result is undefined.  Apparently, the Sequent-Balance C compiler
causes something entirely benign to happen with this shift count, but, due
to a bug in our native GNX C compiler, all sorts of screwy things happen
when shifts counts outside of the range (0 <= N <= 31) are used.  Anyway
it is just plain wrong to use the negative shift count anyway so it should
be fixed.

The following patches prevent the negative REGNO's from being calculated
and they make the code a bit clearer anyway.

diff -rc2 1.30/global-alloc.c 1.30-gnx/global-alloc.c
*** 1.30/global-alloc.c	Sat Oct  8 10:06:43 1988
--- 1.30-gnx/global-alloc.c	Wed Oct 26 12:18:08 1988
***************
*** 890,894
  {
    int src_regno, dest_regno;
!   /* Amount to add to the hard regno for SRC, or subtract from that for DEST,
       to compensate for subregs in SRC or DEST.  */
    int offset = 0;

--- 890,894 -----
  {
    int src_regno, dest_regno;
!   /* Amount to add to the hard regno for SRC or DEST
       to compensate for subregs in SRC or DEST.  */
    int src_offset = 0, dest_offset = 0;
***************
*** 892,896
    /* Amount to add to the hard regno for SRC, or subtract from that for DEST,
       to compensate for subregs in SRC or DEST.  */
!   int offset = 0;
  
    if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e')

--- 892,896 -----
    /* Amount to add to the hard regno for SRC or DEST
       to compensate for subregs in SRC or DEST.  */
!   int src_offset = 0, dest_offset = 0;
  
    if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e')
***************
*** 905,909
      {
        src_regno = REGNO (SUBREG_REG (src));
!       offset += SUBREG_WORD (src);
      }
    else

--- 905,909 -----
      {
        src_regno = REGNO (SUBREG_REG (src));
!       src_offset = SUBREG_WORD (src);
      }
    else
***************
*** 915,919
      {
        dest_regno = REGNO (SUBREG_REG (dest));
!       offset -= SUBREG_WORD (dest);
      }
    else

--- 915,919 -----
      {
        dest_regno = REGNO (SUBREG_REG (dest));
!       dest_offset = SUBREG_WORD (dest);
      }
    else
***************
*** 934,938
        && reg_allocno[src_regno] >= 0)
      {
!       dest_regno -= offset;
        SET_REGBIT (hard_reg_preferences, reg_allocno[src_regno], dest_regno);
        SET_HARD_REG_BIT (regs_someone_prefers, dest_regno);

--- 934,940 -----
        && reg_allocno[src_regno] >= 0)
      {
!       dest_regno += dest_offset;
!       if ((dest_regno < 0) || (dest_regno >= FIRST_PSEUDO_REGISTER))
! 	abort ();
        SET_REGBIT (hard_reg_preferences, reg_allocno[src_regno], dest_regno);
        SET_HARD_REG_BIT (regs_someone_prefers, dest_regno);
***************
*** 942,946
        && reg_allocno[dest_regno] >= 0)
      {
!       src_regno += offset;
        SET_REGBIT (hard_reg_preferences, reg_allocno[dest_regno], src_regno);
        SET_HARD_REG_BIT (regs_someone_prefers, src_regno);

--- 944,948 -----
        && reg_allocno[dest_regno] >= 0)
      {
!       src_regno += src_offset;
        SET_REGBIT (hard_reg_preferences, reg_allocno[dest_regno], src_regno);
        SET_HARD_REG_BIT (regs_someone_prefers, src_regno);
Technical Details
Message-ID: <8810262257.AA08272@nsc.NSC.COM>
Path: arc1-ca.pugleaf.net!utzoo!telly!ddsw1!lll-winken!uunet!tut.cis.ohio-state.edu!nsc.nsc.com!rfg

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!telly!ddsw1!lll-winken!uunet!tut.cis.ohio-state.edu!nsc.nsc.com!rfg
From: rfg@nsc.nsc.com (Ron Guilmette)
Newsgroups: gnu.gcc.bug
Subject: (mostly) benign bug in global-alloc.c (GCC 1.30)
Message-ID: <8810262257.AA08272@nsc.NSC.COM>
Date: 26 Oct 88 22:57:12 GMT
Sender: daemon@tut.cis.ohio-state.edu
Distribution: gnu
Organization: GNUs Not Usenet
Lines: 128