[gcc r17-3278] debug/126355 - preserve debug info for IPA ICF wrappers
Richard Biener via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:b6477e6c4efd6df2719190cb048cf300ff31af46 commit r17-3278-gb6477e6c4efd6df2719190cb048cf300ff31af46 Author: Longjun Luo <[email protected]> Date: Thu Jul 23 00:01:50 2026 +0800 debug/126355 - preserve debug info for IPA ICF wrappers When IPA ICF keeps a distinct symbol for an address-taken function by replacing its body with a wrapper, cgraph_node::create_wrapper reuses the original function declaration and its early debug DIE. create_wrapper then calls expand_thunk with force_gimple_thunk set. Forced GIMPLE thunks are normally created after early debug, so expand_thunk marks their declarations ignored. For an ICF wrapper this also prevents final debug emission from attaching the wrapper address to the existing DIE. The wrapper consequently has code and an STT_FUNC symbol but no address-bearing DW_TAG_subprogram DIE. Preserve the declaration's original DECL_IGNORED_P value across forced GIMPLE thunk expansion in create_wrapper. Declarations that were already ignored remain ignored, while an original source declaration can receive its final address information. Tested on x86_64-pc-linux-gnu with the new gcc.dg/debug/dwarf2 test. The test fails before the change and passes afterwards. PR debug/126355 gcc/ChangeLog: * cgraphunit.cc (cgraph_node::create_wrapper): Preserve DECL_IGNORED_P across forced GIMPLE thunk expansion. gcc/testsuite/ChangeLog: * gcc.dg/debug/dwarf2/pr126355.c: New test. Signed-off-by: Longjun Luo <[email protected]> Diff: --- gcc/cgraphunit.cc | 5 ++++ gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c | 35 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 67aaebf108b0..d397c9ae4cc0 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2683,7 +2683,12 @@ cgraph_node::create_wrapper (cgraph_node *target) arguments = TREE_CHAIN (arguments); } + /* Forced GIMPLE thunks are normally ignored because they are created + after early debug. ICF wrappers retain the original function decl and + its early DIE, so preserve its original debug state. */ + bool ignored_p = DECL_IGNORED_P (decl); expand_thunk (this, false, true); + DECL_IGNORED_P (decl) = ignored_p; thunk_info::remove (this); /* Inline summary set-up. */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c new file mode 100644 index 000000000000..35e321008aa9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c @@ -0,0 +1,35 @@ +/* PR debug/126355 */ +/* Verify that an IPA ICF wrapper for an address-taken function keeps an + address-bearing subprogram DIE. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g -gdwarf -dA -fdump-ipa-icf-details" } */ + +int +pr_icf_wrapper_a (const char *host) +{ + (void) host; + return 0; +} + +int +pr_icf_wrapper_b (const char *host) +{ + (void) host; + return 0; +} + +int (*keep_a) (const char *) = pr_icf_wrapper_a; +int (*keep_b) (const char *) = pr_icf_wrapper_b; + +int +main (int argc, char **argv) +{ + const char *arg = argc > 1 ? argv[1] : "x"; + return keep_a (arg) + keep_b (arg); +} + +/* Check the ICF direction explicitly because the DWARF scan below inspects + pr_icf_wrapper_b, the wrapper. */ +/* { dg-final { scan-ipa-dump "Semantic equality hit:pr_icf_wrapper_a/\[0-9+\]+->pr_icf_wrapper_b/\[0-9+\]+" "icf" } } */ +/* { dg-final { scan-ipa-dump "Wrapper has been created" "icf" } } */ +/* { dg-final { scan-assembler "\\(DIE \\(0x\[0-9a-f\]+\\) DW_TAG_subprogram\\)\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_name: \"pr_icf_wrapper_b\"\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_low_pc" } } */