This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Cope with exception_receiver on Alpha/Tru64 5.x
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 20 Nov 2006 23:04:25 +0100
- Subject: [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;
}