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);
 }
 

Reply via email to