Hi,
this is the EH breakage introduced in LTO mode on non-(x86 or Linux):
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00771.html
As Jan explained, in the end it's only a matter of recording whether at least
one function needs a FDE for EH in the compilation unit and, if so, generating
the EH frame at the end. That's why a couple of patches to that effect are
attached, first a cleanup with no functional changes[*] and second the fix.
[*] modulo the dwarf2out_do_cfi_asm hunk, which seems to be another bug fix.
Tested (lightly for now) on x86-64/Linux and SPARC/Solaris, OK for mainline?
2017-11-10 Eric Botcazou <ebotca...@adacore.com>
PR lto/81351
* debug.h (dwarf2out_do_eh_frame): Declare.
* dwarf2cfi.c (dwarf2out_do_eh_frame): New predicate.
(dwarf2out_do_frame): Use it.
(dwarf2out_do_cfi_asm): Likewise.
* dwarf2out.c (dwarf2out_frame_finish): Likewise.
(dwarf2out_assembly_start): Likewise.
(dwarf2out_begin_prologue): Fix comment.
* toplev.c (compile_file): Always call dwarf2out_frame_finish
if the target needs either debug or unwind DWARF2 info.
* lto-opts.c (lto_write_options): Do not save -fexceptions,
-fnon-call-exceptions, -ffp-contract, -fmath-errno, -fsigned-zeros,
-ftrapping-math, -ftrapv and -fwrapv.
PR lto/81351
* dwarf2out.c (do_eh_frame): New static variable.
(dwarf2out_begin_prologue): Set it.
(dwarf2out_frame_finish): Test it instead of dwarf2out_do_eh_frame.
--
Eric Botcazou
Index: debug.h
===================================================================
--- debug.h (revision 254599)
+++ debug.h (working copy)
@@ -241,8 +241,7 @@ extern void dwarf2out_vms_end_prologue (
extern void dwarf2out_vms_begin_epilogue (unsigned int, const char *);
extern void dwarf2out_end_epilogue (unsigned int, const char *);
extern void dwarf2out_frame_finish (void);
-/* Decide whether we want to emit frame unwind information for the current
- translation unit. */
+extern bool dwarf2out_do_eh_frame (void);
extern bool dwarf2out_do_frame (void);
extern bool dwarf2out_do_cfi_asm (void);
extern void dwarf2out_switch_text_section (void);
Index: dwarf2cfi.c
===================================================================
--- dwarf2cfi.c (revision 254599)
+++ dwarf2cfi.c (working copy)
@@ -3402,6 +3402,16 @@ debug_cfi_row (dw_cfi_row *row)
This variable is tri-state, with 0 unset, >0 true, <0 false. */
static GTY(()) signed char saved_do_cfi_asm = 0;
+/* Decide whether to emit EH frame unwind for the current translation unit. */
+
+bool
+dwarf2out_do_eh_frame (void)
+{
+ return
+ (flag_unwind_tables || flag_exceptions)
+ && targetm_common.except_unwind_info (&global_options) == UI_DWARF2;
+}
+
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
@@ -3420,8 +3430,7 @@ dwarf2out_do_frame (void)
if (targetm.debug_unwind_info () == UI_DWARF2)
return true;
- if ((flag_unwind_tables || flag_exceptions)
- && targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
+ if (dwarf2out_do_eh_frame ())
return true;
return false;
@@ -3456,9 +3465,7 @@ dwarf2out_do_cfi_asm (void)
/* If we can't get the assembler to emit only .debug_frame, and we don't need
dwarf2 unwind info for exceptions, then emit .debug_frame by hand. */
- if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE
- && !flag_unwind_tables && !flag_exceptions
- && targetm_common.except_unwind_info (&global_options) != UI_DWARF2)
+ if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE && !dwarf2out_do_eh_frame ())
return false;
/* Success! */
Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 254599)
+++ dwarf2out.c (working copy)
@@ -263,7 +263,6 @@ static GTY(()) int dw2_string_counter;
static GTY(()) bool have_multiple_function_sections = false;
/* Whether the default text and cold text sections have been used at all. */
-
static GTY(()) bool text_section_used = false;
static GTY(()) bool cold_text_section_used = false;
@@ -1060,7 +1059,7 @@ dwarf2out_begin_prologue (unsigned int l
dup_label = xstrdup (label);
current_function_func_begin_label = dup_label;
- /* We can elide the fde allocation if we're not emitting debug info. */
+ /* We can elide FDE allocation if we're not emitting frame unwind info. */
if (!do_frame)
return;
@@ -1180,8 +1179,7 @@ dwarf2out_frame_finish (void)
output_call_frame_info (0);
/* Output another copy for the unwinder. */
- if ((flag_unwind_tables || flag_exceptions)
- && targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
+ if (dwarf2out_do_eh_frame ())
output_call_frame_info (1);
}
@@ -27522,8 +27520,7 @@ dwarf2out_assembly_start (void)
if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE
&& dwarf2out_do_cfi_asm ()
- && (!(flag_unwind_tables || flag_exceptions)
- || targetm_common.except_unwind_info (&global_options) != UI_DWARF2))
+ && !dwarf2out_do_eh_frame ())
fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
}
Index: lto-opts.c
===================================================================
--- lto-opts.c (revision 254599)
+++ lto-opts.c (working copy)
@@ -70,73 +70,10 @@ lto_write_options (void)
obstack_init (&temporary_obstack);
- /* Output options that affect GIMPLE IL semantics and are implicitly
- enabled by the frontend.
- This for now includes an explicit set of options that we also handle
- explicitly in lto-wrapper.c. In the end the effects on GIMPLE IL
- semantics should be explicitely encoded in the IL or saved per
- function rather than per compilation unit. */
- /* -fexceptions causes the EH machinery to be initialized, enabling
- generation of unwind data so that explicit throw() calls work. */
- if (!global_options_set.x_flag_exceptions
- && global_options.x_flag_exceptions)
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- "-fexceptions");
- /* -fnon-call-exceptions changes the generation of exception
- regions. It is enabled implicitly by the Go frontend. */
- if (!global_options_set.x_flag_non_call_exceptions
- && global_options.x_flag_non_call_exceptions)
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- "-fnon-call-exceptions");
- /* The default -ffp-contract changes depending on the language
- standard. Pass thru conservative standard settings. */
- if (!global_options_set.x_flag_fp_contract_mode)
- switch (global_options.x_flag_fp_contract_mode)
- {
- case FP_CONTRACT_OFF:
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- "-ffp-contract=off");
- break;
- case FP_CONTRACT_ON:
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- "-ffp-contract=on");
- break;
- case FP_CONTRACT_FAST:
- /* Nothing. That merges conservatively and is the default for LTO. */
- break;
- default:
- gcc_unreachable ();
- }
- /* The default -fmath-errno, -fsigned-zeros and -ftrapping-math change
- depending on the language (they can be disabled by the Ada front-end).
- Pass thru conservative standard settings. */
- if (!global_options_set.x_flag_errno_math)
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- global_options.x_flag_errno_math
- ? "-fmath-errno"
- : "-fno-math-errno");
- if (!global_options_set.x_flag_signed_zeros)
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- global_options.x_flag_signed_zeros
- ? "-fsigned-zeros"
- : "-fno-signed-zeros");
- if (!global_options_set.x_flag_trapping_math)
- append_to_collect_gcc_options (&temporary_obstack, &first_p,
- global_options.x_flag_trapping_math
- ? "-ftrapping-math"
- : "-fno-trapping-math");
- /* We need to merge -f[no-]strict-overflow, -f[no-]wrapv and -f[no-]trapv
- conservatively, so stream out their defaults. */
- if (!global_options_set.x_flag_wrapv
- && global_options.x_flag_wrapv)
- append_to_collect_gcc_options (&temporary_obstack, &first_p, "-fwrapv");
- if (!global_options_set.x_flag_trapv
- && !global_options.x_flag_trapv)
- append_to_collect_gcc_options (&temporary_obstack, &first_p, "-fno-trapv");
-
if (!global_options_set.x_flag_openmp
&& !global_options.x_flag_openmp)
- append_to_collect_gcc_options (&temporary_obstack, &first_p, "-fno-openmp");
+ append_to_collect_gcc_options (&temporary_obstack, &first_p,
+ "-fno-openmp");
if (!global_options_set.x_flag_openacc
&& !global_options.x_flag_openacc)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
Index: toplev.c
===================================================================
--- toplev.c (revision 254599)
+++ toplev.c (working copy)
@@ -525,10 +525,9 @@ compile_file (void)
/* Do dbx symbols. */
timevar_push (TV_SYMOUT);
- #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
- if (dwarf2out_do_frame ())
- dwarf2out_frame_finish ();
- #endif
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
+ dwarf2out_frame_finish ();
+#endif
(*debug_hooks->finish) (main_input_filename);
timevar_pop (TV_SYMOUT);
--- dwarf2out.c.0 2017-11-10 13:02:25.103559148 +0100
+++ dwarf2out.c 2017-11-10 13:06:14.427951051 +0100
@@ -284,6 +284,9 @@ static void dwarf2out_note_section_used
personality CFI. */
static GTY(()) rtx current_unit_personality;
+/* Whether an eh_frame section is required. */
+static GTY(()) bool do_eh_frame = false;
+
/* .debug_rnglists next index. */
static unsigned int rnglist_idx;
@@ -1063,6 +1066,10 @@ dwarf2out_begin_prologue (unsigned int l
if (!do_frame)
return;
+ /* Unlike the debug version, the EH version of frame unwind info is a per-
+ function setting so we need to record whether we need it for the unit. */
+ do_eh_frame |= dwarf2out_do_eh_frame ();
+
/* Cater to the various TARGET_ASM_OUTPUT_MI_THUNK implementations that
emit insns as rtx but bypass the bulk of rest_of_compilation, which
would include pass_dwarf2_frame. If we've not created the FDE yet,
@@ -1179,7 +1186,7 @@ dwarf2out_frame_finish (void)
output_call_frame_info (0);
/* Output another copy for the unwinder. */
- if (dwarf2out_do_eh_frame ())
+ if (do_eh_frame)
output_call_frame_info (1);
}