[llvm] [RFC] Emit dwarf data for signature-changed or new functions (PR #157349)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 26 02:04:53 PDT 2025


dzhidzhoev wrote:

Thank you for checking that!

Yes, having the exapmle, I understand better, what you're trying to achieve.
What if we try to _keep_ linkage name of the original subprogram in the original DISugbprogram (!0) in the example, to get the DWARF like this:
```
LOC_A: DW_TAG_subprogram
                DW_AT_name	("mul")
                DW_AT_linkage_name	("_Z3mulii")
                DW_AT_decl_file	("/app/example.cpp")
                DW_AT_decl_line	(...)
                DW_AT_type	(0x0000003d "int")
                DW_AT_inline	(DW_INL_inlined)

      LOC_B: DW_TAG_formal_parameter
                  DW_AT_name	("num1")
                  DW_AT_decl_file	("/app/example.cpp")
                  DW_AT_decl_line	(...)
                  DW_AT_type	(0x0000003d "int")
      LOC_C: DW_TAG_formal_parameter
                  DW_AT_name	("num2")
                  DW_AT_decl_file	("/app/example.cpp")
                  DW_AT_decl_line	(...)
                  DW_AT_type	(0x0000003d "int")
     NULL

DW_TAG_subprogram
                DW_AT_low_pc	(0x0000000000000000)
                DW_AT_high_pc	(0x0000000000000006)
                DW_AT_frame_base	(DW_OP_reg7 RSP)
                DW_AT_call_all_calls	(true)
                DW_AT_name	("mul")
                ...

              DW_TAG_formal_parameter
                  DW_AT_location	(DW_OP_reg5 RDI)
                  DW_AT_name	("num1")
                  DW_AT_decl_file	("/app/example.cpp")
                  DW_AT_decl_line	(...)
                  DW_AT_type	(0x0000003d "int")

              DW_TAG_inlined_subroutine
                  DW_AT_abstract_origin	(LOC_A "mul")
                  DW_AT_low_pc	(...)
                  DW_AT_high_pc	(...)
                  DW_AT_call_file	("/app/example.cpp")
                  DW_AT_call_line	(...)
                  DW_AT_call_column	(...)

                    DW_TAG_formal_parameter
                            DW_AT_location	(DW_OP_reg5 RDI)
                            DW_AT_abstract_origin	(LOC_B "num1")
                    DW_TAG_formal_parameter
                            DW_AT_location	(DW_OP_reg5 RDI)
                            DW_AT_abstract_origin	(LOC_C "num2")
             NULL
NULL
```

With LLVM IR produced by the EmitChangedFuncDebugInfo pass like this:
```
define dso_local noundef i32 @_Z3mulii(i32 noundef %0) local_unnamed_addr #0 !dbg !0 {
    #dbg_value(i32 %0, !14, !DIExpression(), !15)
    #dbg_value(i32 %0, !5, !DIExpression(), !16)
    #dbg_value(i32 %0, !6, !DIExpression(), !16)
  %3 = mul nsw i32 %0, %0, !dbg !18
  ret i32 %3, !dbg !19
}

; Old metadata for the function.
!0 = distinct !DISubprogram(name: "mul", linkageName: "_Z3mulii", line: 2, type: !1, spFlags: DISPFlagDefinition | DISPFlagOptimized, retainedNodes: !4)
!1 = !DISubroutineType(types: !2)
!2 = !{!3, !3, !3}
!3 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!4 = !{!5, !6}
!5 = !DILocalVariable(name: "num1", arg: 1, scope: !0, line: 2, type: !3)
!6 = !DILocalVariable(name: "num2", arg: 2, scope: !0, line: 2, type: !3)
!8 = !DILocation(line: 3, column: 17, scope: !0, atomGroup: 1, atomRank: 2)
!9 = !DILocation(line: 3, column: 5, scope: !0, atomGroup: 1, atomRank: 1)

; New metadata for the function (and with removed linkageName, or with linkageName=="F.getName()", if "F.getName() != !0.getLinkageName()").
!10 = distinct !DISubprogram(name: "mul", line: 6, type: !11, spFlags: DISPFlagDefinition | DISPFlagOptimized, retainedNodes: !13)
!11 = !DISubroutineType(types: !12)
!12 = !{!3, !3}
!13 = !{!14}
!14 = !DILocalVariable(name: "num1", arg: 1, scope: !10, line: 6, type: !3)
!15 = !DILocation(line: 0, scope: !10)
!16 = !DILocation(line: 0, scope: !0, inlinedAt: !17)
!17 = distinct !DILocation(line: 0, scope: !10)
!18 = !DILocation(line: 3, column: 17, scope: !0, inlinedAt: !17, atomGroup: 1, atomRank: 2)
!19 = !DILocation(line: 3, column: 5, scope: !0, inlinedAt: !17, atomGroup: 1, atomRank: 1)
```

Will the result meet the conditions:
(1) the tool (pahole?) will correctly identify the signature of _Z3mulii,
(2) the tool will understand that mul() is not callable with "original" set of arguments (since LOC_A is an abstract subprogram DIE)?

Btw, I believe this is what the colleagues proposed in the course of the earlier discussion on https://github.com/llvm/llvm-project/pull/127855:
> > The idea, which we were briefly discussing today in the #gcc IRC channel, would be to have the signature change of some given function represented in DWARF using a DW_TAG_artificial "container" with an inlined subroutine reflecting the original signature. Something like:
> > ```
> > foo.clone (int a, int b) { foo (1, { a, b }); } 
> > ```
> > 
> > 
> >     
> >       
> >     
> > 
> >       
> >     
> > 
> >     
> >   
> > The signature change would be described in the formal parameters of the DW_TAG_inlined_subroutine.
> 
> It's an interesting idea... I don't totally object to it. Handles the case of "you can't call this" (because it's inlined) and I suppose with the WIP DWARFv6 feature you could even describe the return value even if it's ABI-optimized away (while still being present/computable within `foo.clone`).

https://github.com/llvm/llvm-project/pull/157349


More information about the llvm-commits mailing list