Bug 91794 - exception and unwind state is not carried to LTO but controls EH vs debug frame
Summary: exception and unwind state is not carried to LTO but controls EH vs debug frame
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: lto (show other bugs)
Version: 9.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: EH, lto
Depends on:
Blocks: 47819 91763
  Show dependency treegraph
 
Reported: 2019-09-17 10:57 UTC by Richard Biener
Modified: 2021-12-29 06:26 UTC (History)
2 users (show)

See Also:
Host:
Target: riscv
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-09-17 00:00:00


Attachments
patch for lto-wrapper (558 bytes, patch)
2019-09-17 13:39 UTC, Richard Biener
Details | Diff
fixed patch (557 bytes, patch)
2019-09-17 13:42 UTC, Richard Biener
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2019-09-17 10:57:31 UTC
On targets where -funwind-tables is not enabled by default doing

gcc -c -flto -funwind-tables t.c -g
gcc t.o -g

ends up without unwind tables even if the flags state is recorded in
per-function settings.  dwarf2out.c suggests the state is accumulated
from all functions in the TU

  /* 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 ();

but that doesn't work since dwarf2out_do_eh_frame looks at the global
flag_unwind_tables (and global flag_exceptions and passes global opts to
the target hook).

We probably can switch between EH-frame and debug-frame per function but
a way out would be to handle flag_{,asynchronous_}unwind_tables in
lto-wrapper.

Eric was here fixing the similar PR81351.

One target where this shows is riscv.
Comment 1 Richard Biener 2019-09-17 11:09:50 UTC
Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame ()
works per function?

We could also fix this similar to how we do lto_init_eh which forces
the global flag_exceptions to 1, force flag_unwind_tables to 1 in
case any function had it enabled (that's still finer-grained than
enabling it for all LTRANS units via lto-wrapper).  Similar on targets
where EH unwind is the default disabling it via -fno-unwind-tables would
have no effect with LTO even if all functions have it disabled.
Comment 2 Richard Biener 2019-09-17 11:15:02 UTC
So one possible fix would be

Index: gcc/dwarf2cfi.c
===================================================================
--- gcc/dwarf2cfi.c     (revision 275639)
+++ gcc/dwarf2cfi.c     (working copy)
@@ -3489,7 +3489,7 @@ bool
 dwarf2out_do_eh_frame (void)
 {
   return
-    (flag_unwind_tables || flag_exceptions)
+    (opt_for_fn (cfun->decl, flag_unwind_tables) || flag_exceptions)
     && targetm_common.except_unwind_info (&global_options) == UI_DWARF2;
 }
 
note this predicate also controls the 'dwarf2' RTL pass so you'd get
per function CFI notes(?).
Comment 3 Richard Biener 2019-09-17 13:39:12 UTC
Created attachment 46890 [details]
patch for lto-wrapper

This instead makes lto-wrapper append -funwind-tables when one CU had that enabled.
Comment 4 Richard Biener 2019-09-17 13:42:41 UTC
Created attachment 46891 [details]
fixed patch
Comment 5 Eric Botcazou 2019-09-17 16:50:54 UTC
> Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame ()
> works per function?

No, dwarf2out_do_eh_frame is global but whether the CFI for EH is emitted is decided on a per-function basis in the end, see my explanation in:
  https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00771.html
Comment 6 Richard Biener 2019-09-18 06:59:48 UTC
(In reply to Eric Botcazou from comment #5)
> > Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame ()
> > works per function?
> 
> No, dwarf2out_do_eh_frame is global but whether the CFI for EH is emitted is
> decided on a per-function basis in the end, see my explanation in:
>   https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00771.html

Hmm, that doesn't give a lot of detail.  Clearly it doesn't yet work.
I see dwarf2out_do_eh_frame is also used as gate for the "dwarf2" pass.
That probably should use per-function settings then, thus an alternate
predicate?  Because the global setting simply tells the assembler to either
emit everything into eh_frame or debug_frame (seems the assembler cannot
have different settings on a per function basis?).

So I guess an appropriate cleanup would be to pass a struct function
to dwarf2out_do_eh_frame but also deal with it being NULL?
Comment 7 Eric Botcazou 2019-09-18 07:47:28 UTC
> So I guess an appropriate cleanup would be to pass a struct function
> to dwarf2out_do_eh_frame but also deal with it being NULL?

You need to ask Jan, my fix for 81351 was minimal and based on his insight.