This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Cope with exception_receiver on Alpha/Tru64 5.x


Hi,

We recently run into a checking failure on Alpha/Tru64 5.x with a modified 
4.1-based compiler (unfortunately no testcase for FSF compilers).  This is an 
ICE triggered by the CFG verification code during the RTL EH finalization 
pass.  dw2_build_landing_pads emits the exception_receiver pattern in the RTL 
stream if present for the target.  Now on the Alpha:

(define_expand "exception_receiver"
  [(unspec_volatile [(match_dup 0)] UNSPECV_EHR)]
  "TARGET_ABI_OSF"
{
  if (TARGET_LD_BUGGY_LDGP)
    operands[0] = alpha_gp_save_rtx ();
  else
    operands[0] = const0_rtx;
})

And in config/alpha/osf5.h:

/* The linker appears to perform invalid code optimizations that result
   in the ldgp emitted for the exception_receiver pattern being incorrectly
   linked.  */
#undef TARGET_LD_BUGGY_LDGP
#define TARGET_LD_BUGGY_LDGP 1

And in config/alpha/alpha.c:

/* Return or create a memory slot containing the gp value for the current
   function.  Needed only if TARGET_LD_BUGGY_LDGP.  */

rtx
alpha_gp_save_rtx (void)
{
  rtx seq, m = cfun->machine->gp_save_rtx;

  if (m == NULL)
    {
      start_sequence ();

      m = assign_stack_local (DImode, UNITS_PER_WORD, BITS_PER_WORD);
      m = validize_mem (m);
      emit_move_insn (m, pic_offset_table_rtx);

      seq = get_insns ();
      end_sequence ();
      emit_insn_after (seq, entry_of_function ());

      cfun->machine->gp_save_rtx = m;
    }

  return m;
}


The problem is that the first BB of the function starts with a label:

;; Start of basic block 0, registers live: (nil)
(code_label 7 6 8 2 78 "" [3 uses])

(note 8 7 10 2 [bb 0] NOTE_INSN_BASIC_BLOCK)

(insn 10 8 11 2 (set (reg:DI 75)
        (symbol_ref:DI ("p__all_events") [flags 0x2] <var_decl 0x2a961e8a50 
p__all_events>)) -1 (nil)
    (nil))

(insn 11 10 12 2 (set (reg:DI 16 $16)
        (reg:DI 75)) -1 (nil)
    (nil))

and entry_of_function () returns the label.  So alpha_gp_save_rtx will insert

(insn 93 104 7 0 (set (mem/c:DI (reg/f:DI 65 virtual-stack-vars) [0 S8 A64])
        (reg:DI 29 $29)) -1 (nil)
    (nil))

between the label and the NOTE_INSN_BASIC_BLOCK, which is invalid.


entry_of_function () was added for CFG transparent RTL expansion and I think 
it is OK for that purpose.  It was later reused in alpha_gp_save_rtx and this 
latter use is clearly problematic.

The proposed fix is to insert properly the insns on the entry edge using a 
little kludge.  OK for mainline?


2006-11-20  Eric Botcazou  <ebotcazou@adacore.com>

        * except.c (finish_eh_generation): Call commit_edge_insertions if
        there are insns queued on the entry edge.
        * config/alpha/alpha.c (alpha_gp_save_rtx): Insert the insns on
        the entry edge.


:ADDPATCH middle-end:

-- 
Eric Botcazou
Index: except.c
===================================================================
--- except.c	(revision 119010)
+++ except.c	(working copy)
@@ -2102,7 +2102,9 @@ finish_eh_generation (void)
   /* We've totally changed the CFG.  Start over.  */
   find_exception_handler_labels ();
   break_superblocks ();
-  if (USING_SJLJ_EXCEPTIONS)
+  if (USING_SJLJ_EXCEPTIONS
+      /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx).  */
+      || EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->insns.r)
     commit_edge_insertions ();
   FOR_EACH_BB (bb)
     {
Index: config/alpha/alpha.c
===================================================================
--- config/alpha/alpha.c	(revision 119010)
+++ config/alpha/alpha.c	(working copy)
@@ -4870,7 +4870,14 @@ alpha_gp_save_rtx (void)
 
       seq = get_insns ();
       end_sequence ();
-      emit_insn_after (seq, entry_of_function ());
+
+      /* We used to simply emit the sequence after entry_of_function.
+	 However this breaks the CFG if the first instruction in the
+	 first block is not the NOTE_INSN_BASIC_BLOCK, for example a
+	 label.  Emit the sequence properly on the edge.  We are only
+	 invoked from dw2_build_landing_pads and finish_eh_generation
+	 will call commit_edge_insertions thanks to a kludge.  */
+      insert_insn_on_edge (seq, EDGE_SUCC (ENTRY_BLOCK_PTR, 0));
 
       cfun->machine->gp_save_rtx = m;
     }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]