This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix unwind info for i?86 set_got (PR debug/43293)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Jan Hubicka <jh at suse dot cz>, Uros Bizjak <ubizjak at gmail dot com>
- Cc: gcc-patches at gcc dot gnu dot org, hjl dot tools at gmail dot com
- Date: Tue, 9 Mar 2010 00:47:56 +0100
- Subject: [PATCH] Fix unwind info for i?86 set_got (PR debug/43293)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
I've noticed we generate wrong unwind info for i?86 -fpic set_got sequences.
As 4.5 now generates correct unwind info for epilogues this means we still
can't trust the unwind info (e.g. for async signal interrupted code),
even with -fasynchronous-unwind-tables.
For deep branch prediction there are 2 issues - the queued register saves
are flushed only after the whole sequence, as the whole set_got is
considered one insn, while already the called thunk clobbers %ebx and
the thunks don't have unwind info.
For non-deep branch prediction, the call acts as a push and thus
for -fomit-frame-pointer the unwind info is wrong for one insn, and
similarly queued register saves aren't flushed after the popl, but only
after the final addl.
While it would be possible to change output_set_got into a "#" insn
with define_split being regstack_complete guarded, it wouldn't solve this
completely and we'd need hacks in dwarf2out.c and final.c to handle it,
as e.g. it is undesirable to make the call an actual CALL_INSN.
The following patch handles this in the backend, by calling
dwarf2out_frame_debug with made up insns that represent what is interesting
from unwind info POV. Unwind info for the thunks is only handled for cfi
directive unwind info ATM, handling it for manual .eh_frame would be more
difficult and would need at least some dwarf2out.c changes.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2010-03-09 Jakub Jelinek <jakub@redhat.com>
PR debug/43293
* config/i386/t-i386 (i386.o): Depend on debug.h and dwarf2out.h.
* config/i386/i386.c: Include debug.h and dwarf2out.h.
(ix86_file_end): If dwarf2out_do_cfi_asm (), emit .cfi_startproc
and .cfi_endproc around the pic thunks.
(output_set_got): For TARGET_DEEP_BRANCH_PREDICTION pic, ensure
all queued unwind info register saves are saved before the call.
For !TARGET_DEEP_BRANCH_PREDICTION pic, ensure the call is
considered as sp-=4 for unwind info and the pop as sp+=4 which
also clobbers dest, but doesn't actually restore it.
--- gcc/config/i386/t-i386.jj 2009-11-23 13:04:31.000000000 +0100
+++ gcc/config/i386/t-i386 2009-11-23 13:04:31.000000000 +0100
@@ -23,7 +23,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretype
$(RECOG_H) $(EXPR_H) $(OPTABS_H) toplev.h $(BASIC_BLOCK_H) \
$(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
$(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \
- i386-builtin-types.inc
+ i386-builtin-types.inc debug.h dwarf2out.h
i386-c.o: $(srcdir)/config/i386/i386-c.c \
$(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
--- gcc/config/i386/i386.c.jj 2010-03-01 16:31:50.000000000 +0100
+++ gcc/config/i386/i386.c 2010-03-08 21:56:51.000000000 +0100
@@ -53,6 +53,8 @@ along with GCC; see the file COPYING3.
#include "tm-constrs.h"
#include "params.h"
#include "cselib.h"
+#include "debug.h"
+#include "dwarf2out.h"
static rtx legitimize_dllimport_symbol (rtx, bool);
@@ -7584,6 +7586,9 @@ ix86_file_end (void)
for (regno = 0; regno < 8; ++regno)
{
char name[32];
+#ifdef DWARF2_UNWIND_INFO
+ bool do_cfi;
+#endif
if (! ((pic_labels_used >> regno) & 1))
continue;
@@ -7629,10 +7634,19 @@ ix86_file_end (void)
ASM_OUTPUT_LABEL (asm_out_file, name);
}
+#ifdef DWARF2_UNWIND_INFO
+ do_cfi = dwarf2out_do_cfi_asm ();
+ if (do_cfi)
+ fprintf (asm_out_file, "\t.cfi_startproc\n");
+#endif
xops[0] = gen_rtx_REG (Pmode, regno);
xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
output_asm_insn ("ret", xops);
+#ifdef DWARF2_UNWIND_INFO
+ if (do_cfi)
+ fprintf (asm_out_file, "\t.cfi_endproc\n");
+#endif
}
if (NEED_INDICATE_EXEC_STACK)
@@ -7673,7 +7687,24 @@ output_set_got (rtx dest, rtx label ATTR
if (!flag_pic)
output_asm_insn ("mov%z0\t{%2, %0|%0, %2}", xops);
else
- output_asm_insn ("call\t%a2", xops);
+ {
+ output_asm_insn ("call\t%a2", xops);
+#ifdef DWARF2_UNWIND_INFO
+ /* The call to next label acts as a push. */
+ if (dwarf2out_do_frame ())
+ {
+ rtx insn;
+ start_sequence ();
+ insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (-4))));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ dwarf2out_frame_debug (insn, true);
+ end_sequence ();
+ }
+#endif
+ }
#if TARGET_MACHO
/* Output the Mach-O "canonical" label name ("Lxx$pb") here too. This
@@ -7686,7 +7717,27 @@ output_set_got (rtx dest, rtx label ATTR
CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
if (flag_pic)
- output_asm_insn ("pop%z0\t%0", xops);
+ {
+ output_asm_insn ("pop%z0\t%0", xops);
+#ifdef DWARF2_UNWIND_INFO
+ /* The pop is a pop and clobbers dest, but doesn't restore it
+ for unwind info purposes. */
+ if (dwarf2out_do_frame ())
+ {
+ rtx insn;
+ start_sequence ();
+ insn = emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+ dwarf2out_frame_debug (insn, true);
+ insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (4))));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ dwarf2out_frame_debug (insn, true);
+ end_sequence ();
+ }
+#endif
+ }
}
else
{
@@ -7694,6 +7745,18 @@ output_set_got (rtx dest, rtx label ATTR
get_pc_thunk_name (name, REGNO (dest));
pic_labels_used |= 1 << REGNO (dest);
+#ifdef DWARF2_UNWIND_INFO
+ /* Ensure all queued register saves are flushed before the
+ call. */
+ if (dwarf2out_do_frame ())
+ {
+ rtx insn;
+ start_sequence ();
+ insn = emit_barrier ();
+ end_sequence ();
+ dwarf2out_frame_debug (insn, false);
+ }
+#endif
xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
xops[2] = gen_rtx_MEM (QImode, xops[2]);
output_asm_insn ("call\t%X2", xops);
Jakub