Skip to content

Commit 0e44ffe

Browse files
authored
[DWARF] Add option to add linkage_names to call_origin declaration refs (#89640)
If -mllvm -add-linkage-names-to-external-call-origins is true then add DW_AT_linkage_name attributes to DW_TAG_subprogram DIEs referenced by DW_AT_call_origin attributes that would otherwise be omitted. A debugger may use DW_TAG_call_origin attributes to determine whether any frames in a callstack are missing due to optimisations (e.g. tail calls). For example, say a() calls b() tail-calls c(), and you stop in your debugger in c(): The callstack looks like this: c() a() Looking "up" from c(), call site information can be found in a(). This includes a DW_AT_call_origin referencing b()'s subprogram DIE, which means the call at this call site was to b(), not c() where we are currently stopped. This indicates b()'s frame has been lost due to optimisation (or is misleading due to ICF). This patch makes it easier for a debugger to check whether the referenced DIE describes the target function or not, for example by comparing the referenced function name to the current frame. There's already an option to apply DW_AT_linkage_name in a targeted manner: -dwarf-linkage-names=Abstract, which limits adding DW_AT_linkage_names to abstract subprogram DIEs (this is default for SCE tuning). The new flag shouldn't affect non-SCE-tuned behaviour whether it is enabled or not because the non-SCE-tuned behaviour is to always add linkage names to subprogram DIEs.
1 parent 55fc5eb commit 0e44ffe

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/MC/MCSymbol.h"
3333
#include "llvm/MC/MCSymbolWasm.h"
3434
#include "llvm/MC/MachineLocation.h"
35+
#include "llvm/Support/CommandLine.h"
3536
#include "llvm/Target/TargetLoweringObjectFile.h"
3637
#include "llvm/Target/TargetMachine.h"
3738
#include "llvm/Target/TargetOptions.h"
@@ -42,6 +43,20 @@
4243

4344
using namespace llvm;
4445

46+
/// Query value using AddLinkageNamesToDeclCallOriginsForTuning.
47+
cl::opt<cl::boolOrDefault> AddLinkageNamesToDeclCallOrigins(
48+
"add-linkage-names-to-declaration-call-origins", cl::Hidden,
49+
cl::desc("Add DW_AT_linkage_name to function declaration DIEs "
50+
"referenced by DW_AT_call_origin attributes. Enabled by default "
51+
"for -gsce debugger tuning."));
52+
53+
static bool AddLinkageNamesToDeclCallOriginsForTuning(const DwarfDebug *DD) {
54+
bool EnabledByDefault = DD->tuneForSCE();
55+
if (EnabledByDefault)
56+
return AddLinkageNamesToDeclCallOrigins != cl::boolOrDefault::BOU_FALSE;
57+
return AddLinkageNamesToDeclCallOrigins == cl::boolOrDefault::BOU_TRUE;
58+
}
59+
4560
static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) {
4661

4762
// According to DWARF Debugging Information Format Version 5,
@@ -1260,6 +1275,12 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
12601275
} else {
12611276
DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
12621277
assert(CalleeDIE && "Could not create DIE for call site entry origin");
1278+
if (AddLinkageNamesToDeclCallOriginsForTuning(DD) &&
1279+
!CalleeSP->isDefinition() &&
1280+
!CalleeDIE->findAttribute(dwarf::DW_AT_linkage_name)) {
1281+
addLinkageName(*CalleeDIE, CalleeSP->getLinkageName());
1282+
}
1283+
12631284
addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin),
12641285
*CalleeDIE);
12651286
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
; RUN: llc %s --filetype=obj -o - -dwarf-linkage-names=Abstract -add-linkage-names-to-declaration-call-origins=false \
2+
; RUN: | llvm-dwarfdump - | FileCheck %s --check-prefixes=COMMON,DISABLE --implicit-check-not=DW_AT_linkage_name
3+
; RUN: llc %s --filetype=obj -o - -dwarf-linkage-names=Abstract -add-linkage-names-to-declaration-call-origins=true \
4+
; RUN: | llvm-dwarfdump - | FileCheck %s --check-prefixes=COMMON,ENABLE --implicit-check-not=DW_AT_linkage_name
5+
6+
;; Check that -add-linkage-names-to-declaration-call-origins controls whether
7+
;; linkage names are added to declarations referenced by DW_AT_call_origin
8+
;; attributes.
9+
;;
10+
;; $ cat test.cpp
11+
;; void a();
12+
;; __attribute__((optnone))
13+
;; void b() {}
14+
;; void c();
15+
;; extern "C" {
16+
;; void d();
17+
;; }
18+
;;
19+
;; void e() {
20+
;; a(); //< Reference declaration DIE (add linkage name).
21+
;; b(); //< Reference definition DIE (don't add linkage name).
22+
;; c(); //< Reference definition DIE (don't add linkage name).
23+
;; d(); //< Reference declaration DIE, but there's no linkage name.
24+
;; }
25+
;;
26+
;; __attribute__((optnone))
27+
;; void c() {}
28+
;; $ clang++ -emit-llvm -S -O1 -g
29+
30+
; COMMON: DW_TAG_call_site
31+
; ENABLE-NEXT: DW_AT_call_origin (0x[[a:[a-z0-9]+]] "_Z1av")
32+
; DISABLE-NEXT: DW_AT_call_origin (0x[[a:[a-z0-9]+]] "a")
33+
; COMMON: DW_TAG_call_site
34+
; COMMON-NEXT: DW_AT_call_origin (0x[[b:[a-z0-9]+]] "b")
35+
; COMMON: DW_TAG_call_site
36+
; COMMON-NEXT: DW_AT_call_origin (0x[[c:[a-z0-9]+]] "c")
37+
; COMMON: DW_TAG_call_site
38+
; COMMON-NEXT: DW_AT_call_origin (0x[[d:[a-z0-9]+]] "d")
39+
40+
; COMMON: 0x[[a]]: DW_TAG_subprogram
41+
; COMMON: DW_AT_name ("a")
42+
; ENABLE: DW_AT_linkage_name ("_Z1av")
43+
; COMMON: 0x[[b]]: DW_TAG_subprogram
44+
; COMMON: DW_AT_name ("b")
45+
; COMMON: 0x[[c]]: DW_TAG_subprogram
46+
; COMMON: DW_AT_name ("c")
47+
; COMMON: 0x[[d]]: DW_TAG_subprogram
48+
; COMMON: DW_AT_name ("d")
49+
50+
target triple = "x86_64-unknown-linux-gnu"
51+
52+
define dso_local void @_Z1ev() local_unnamed_addr !dbg !13 {
53+
entry:
54+
tail call void @_Z1av(), !dbg !14
55+
tail call void @_Z1bv(), !dbg !15
56+
tail call void @_Z1cv(), !dbg !16
57+
tail call void @d(), !dbg !17
58+
ret void, !dbg !18
59+
}
60+
61+
define dso_local void @_Z1bv() local_unnamed_addr !dbg !9 {
62+
entry:
63+
ret void, !dbg !12
64+
}
65+
66+
declare !dbg !19 void @_Z1av() local_unnamed_addr
67+
68+
define dso_local void @_Z1cv() local_unnamed_addr !dbg !20 {
69+
entry:
70+
ret void, !dbg !21
71+
}
72+
declare !dbg !22 void @d() local_unnamed_addr
73+
74+
!llvm.dbg.cu = !{!0}
75+
!llvm.module.flags = !{!2, !3}
76+
!llvm.ident = !{!8}
77+
78+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 19.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
79+
!1 = !DIFile(filename: "test.cpp", directory: "/")
80+
!2 = !{i32 7, !"Dwarf Version", i32 5}
81+
!3 = !{i32 2, !"Debug Info Version", i32 3}
82+
!8 = !{!"clang version 19.0.0"}
83+
!9 = distinct !DISubprogram(name: "b", linkageName: "_Z1bv", scope: !1, file: !1, line: 3, type: !10, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
84+
!10 = !DISubroutineType(types: !11)
85+
!11 = !{null}
86+
!12 = !DILocation(line: 3, column: 11, scope: !9)
87+
!13 = distinct !DISubprogram(name: "e", linkageName: "_Z1ev", scope: !1, file: !1, line: 9, type: !10, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
88+
!14 = !DILocation(line: 10, column: 3, scope: !13)
89+
!15 = !DILocation(line: 11, column: 3, scope: !13)
90+
!16 = !DILocation(line: 12, column: 3, scope: !13)
91+
!17 = !DILocation(line: 13, column: 3, scope: !13)
92+
!18 = !DILocation(line: 14, column: 1, scope: !13)
93+
!19 = !DISubprogram(name: "a", linkageName: "_Z1av", scope: !1, file: !1, line: 1, type: !10, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
94+
!20 = distinct !DISubprogram(name: "c", linkageName: "_Z1cv", scope: !1, file: !1, line: 17, type: !10, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
95+
!21 = !DILocation(line: 17, column: 11, scope: !20)
96+
!22 = !DISubprogram(name: "d", scope: !1, file: !1, line: 6, type: !10, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)

0 commit comments

Comments
 (0)