PR middle-end/52373: two pc_rtxs, etc.

Richard Sandiford rdsandiford@googlemail.com
Mon Feb 27 20:46:00 GMT 2012


This patch fixed PR 52373, which is a segfault or rtl checking failure
(depending on how lucky you are) on mips-sgi-irix6.5.  I can't reproduce
it on *-elf or *-linux-gnu, probably because we use .cfi_* there.

The problem is that, although pc_rtx is expected to be unique, it is
recreated by each call to target_reinit, so we can end up with different
values through the runtime of the compiler.  This confused dwarf2cfi.c,
which sets up cie_return_save with a pc_rtx reference when first called,
and reuses it for all later functions (by which time we might have
created a new pc_rtx).  Pointer equality can then fail.

The first four global_rtxs aren't target-dependent, so I think
we should treat them in the same way as constants.  It'll also
make debugging slightly easier.

The problem is a bit deeper than that really.  Having only one CIE
isn't fully general, since things like the frame pointer are allowed
to change between subtargets (and do on MIPS).  But it happens that
the CIE we create for MIPS works for both modes, so I think this
patch is good enough in practice.

Tested on mips-sde-elf with rtl checking enabled.  There were no
differences.  Also tested with a mips-sgi-irix6.5 cc1 cross to verify
that it fixes the bug.  OK to install?

Richard


gcc/
	* rtl.h (pc_rtx, ret_rtx, simple_return_rtx, cc0_rtx): Redefine as
	variables.
	(GR_PC, GR_CC0, GR_RETURN, GR_SIMPLE_RETURN): Delete.
	* emit-rtl.c (pc_rtx, ret_rtx, simple_return_rtx, cc0_rtx): New
	variables.
	(init_emit_regs): Move associated initialization to...
	(init_emit_once): ...here.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2012-02-26 10:30:27.817985876 +0000
+++ gcc/rtl.h	2012-02-26 11:21:47.372978342 +0000
@@ -2089,6 +2089,11 @@ #define CONST1_RTX(MODE) (const_tiny_rtx
 #define CONST2_RTX(MODE) (const_tiny_rtx[2][(int) (MODE)])
 #define CONSTM1_RTX(MODE) (const_tiny_rtx[3][(int) (MODE)])
 
+extern rtx pc_rtx;
+extern rtx cc0_rtx;
+extern rtx ret_rtx;
+extern rtx simple_return_rtx;
+
 /* If HARD_FRAME_POINTER_REGNUM is defined, then a special dummy reg
    is used to represent the frame pointer.  This is because the
    hard frame pointer and the automatic variables are separated by an amount
@@ -2112,10 +2117,6 @@ #define HARD_FRAME_POINTER_IS_ARG_POINTE
 /* Index labels for global_rtl.  */
 enum global_rtl_index
 {
-  GR_PC,
-  GR_CC0,
-  GR_RETURN,
-  GR_SIMPLE_RETURN,
   GR_STACK_POINTER,
   GR_FRAME_POINTER,
 /* For register elimination to work properly these hard_frame_pointer_rtx,
@@ -2208,12 +2209,6 @@ #define top_of_stack \
 #define mode_mem_attrs \
   (this_target_rtl->x_mode_mem_attrs)
 
-/* Standard pieces of rtx, to be substituted directly into things.  */
-#define pc_rtx                  (global_rtl[GR_PC])
-#define ret_rtx                 (global_rtl[GR_RETURN])
-#define simple_return_rtx       (global_rtl[GR_SIMPLE_RETURN])
-#define cc0_rtx                 (global_rtl[GR_CC0])
-
 /* All references to certain hard regs, except those created
    by allocating pseudo regs into them (when that's possible),
    go through these unique rtx objects.  */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2012-02-26 10:30:27.817985876 +0000
+++ gcc/emit-rtl.c	2012-02-26 11:21:47.369978342 +0000
@@ -117,6 +117,12 @@ rtx const_tiny_rtx[4][(int) MAX_MACHINE_
 
 rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
 
+/* Standard pieces of rtx, to be substituted directly into things.  */
+rtx pc_rtx;
+rtx ret_rtx;
+rtx simple_return_rtx;
+rtx cc0_rtx;
+
 /* A hash table storing CONST_INTs whose absolute value is greater
    than MAX_SAVED_CONST_INT.  */
 
@@ -5536,10 +5542,6 @@ init_emit_regs (void)
   init_reg_modes_target ();
 
   /* Assign register numbers to the globally defined register rtx.  */
-  pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
-  ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
-  simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
-  cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
   stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
   frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
   hard_frame_pointer_rtx = gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
@@ -5855,6 +5857,11 @@ init_emit_once (void)
   const_tiny_rtx[0][(int) BImode] = const0_rtx;
   if (STORE_FLAG_VALUE == 1)
     const_tiny_rtx[1][(int) BImode] = const1_rtx;
+
+  pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
+  ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
+  simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
+  cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
 }
 
 /* Produce exact duplicate of insn INSN after AFTER.



More information about the Gcc-patches mailing list