llvm.org GIT mirror llvm / 78b8f9d
[DebugInfo] Add support for DWARF5 call site-related attributes DWARF v5 introduces DW_AT_call_all_calls, a subprogram attribute which indicates that all calls (both regular and tail) within the subprogram have call site entries. The information within these call site entries can be used by a debugger to populate backtraces with synthetic tail call frames. Tail calling frames go missing in backtraces because the frame of the caller is reused by the callee. Call site entries allow a debugger to reconstruct a sequence of (tail) calls which led from one function to another. This improves backtrace quality. There are limitations: tail recursion isn't handled, variables within synthetic frames may not survive to be inspected, etc. This approach is not novel, see: https://gcc.gnu.org/wiki/summit2010?action=AttachFile&do=get&target=jelinek.pdf This patch adds an IR-level flag (DIFlagAllCallsDescribed) which lowers to DW_AT_call_all_calls. It adds the minimal amount of DWARF generation support needed to emit standards-compliant call site entries. For easier deployment, when the debugger tuning is LLDB, the DWARF requirement is adjusted to v4. Testing: Apart from check-{llvm, clang}, I built a stage2 RelWithDebInfo clang binary. Its dSYM passed verification and grew by 1.4% compared to the baseline. 151,879 call site entries were added. rdar://42001377 Differential Revision: https://reviews.llvm.org/D49887 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343883 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 1 year, 18 days ago
13 changed file(s) with 725 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
147147 /// - That the root DIE is a unit DIE.
148148 /// - If a unit type is provided, that the unit DIE matches the unit type.
149149 /// - The DIE ranges.
150 /// - That call site entries are only nested within subprograms with a
151 /// DW_AT_call attribute.
150152 ///
151153 /// \param Unit The DWARF Unit to verify.
152154 ///
162164 /// \returns The number of errors that occurred during verification.
163165 unsigned verifyUnitSection(const DWARFSection &S,
164166 DWARFSectionKind SectionKind);
167
168 /// Verifies that a call site entry is nested within a subprogram with a
169 /// DW_AT_call attribute.
170 ///
171 /// \returns Number of errors that occurred during verification.
172 unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
165173
166174 /// Verify that all Die ranges are valid.
167175 ///
4949 HANDLE_DI_FLAG((1 << 26), Trivial)
5050 HANDLE_DI_FLAG((1 << 27), BigEndian)
5151 HANDLE_DI_FLAG((1 << 28), LittleEndian)
52 HANDLE_DI_FLAG((1 << 29), AllCallsDescribed)
5253
5354 // To avoid needing a dedicated value for IndirectVirtualBase, we use
5455 // the bitwise or of Virtual and FwdDecl, which does not otherwise
5859 #ifdef DI_FLAG_LARGEST_NEEDED
5960 // intended to be used with ADT/BitmaskEnum.h
6061 // NOTE: always must be equal to largest flag, check this when adding new flag
61 HANDLE_DI_FLAG((1 << 28), Largest)
62 HANDLE_DI_FLAG((1 << 29), Largest)
6263 #undef DI_FLAG_LARGEST_NEEDED
6364 #endif
6465
17351735 }
17361736 bool isExplicit() const { return getFlags() & FlagExplicit; }
17371737 bool isPrototyped() const { return getFlags() & FlagPrototyped; }
1738 bool areAllCallsDescribed() const {
1739 return getFlags() & FlagAllCallsDescribed;
1740 }
17381741 bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; }
17391742
17401743 /// Check if this is reference-qualified.
729729 return ObjectPointer;
730730 }
731731
732 void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) {
732 DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
733 LexicalScope *Scope) {
733734 DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
734735
735736 if (Scope) {
752753 !includeMinimalInlineScopes())
753754 ScopeDIE.addChild(
754755 DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));
756
757 return ScopeDIE;
755758 }
756759
757760 DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
804807 ContextCU->addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
805808 if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef))
806809 ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
810 }
811
812 DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
813 const DISubprogram &CalleeSP,
814 bool IsTail,
815 const MCSymbol *ReturnPC) {
816 // Insert a call site entry DIE within ScopeDIE.
817 DIE &CallSiteDIE =
818 createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
819
820 // For the purposes of showing tail call frames in backtraces, a key piece of
821 // information is DW_AT_call_origin, a pointer to the callee DIE.
822 DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP);
823 assert(CalleeDIE && "Could not create DIE for call site entry origin");
824 addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE);
825
826 if (IsTail) {
827 // Attach DW_AT_call_tail_call to tail calls for standards compliance.
828 addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call);
829 } else {
830 // Attach the return PC to allow the debugger to disambiguate call paths
831 // from one function to another.
832 assert(ReturnPC && "Missing return PC information for a call");
833 addLabelAddress(CallSiteDIE, dwarf::DW_AT_call_return_pc, ReturnPC);
834 }
835 return CallSiteDIE;
807836 }
808837
809838 DIE *DwarfCompileUnit::constructImportedEntityDIE(
202202 bool *HasNonScopeChildren = nullptr);
203203
204204 /// Construct a DIE for this subprogram scope.
205 void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope);
205 DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
206 LexicalScope *Scope);
206207
207208 DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);
208209
209210 void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
211
212 /// Construct a call site entry DIE describing a call within \p Scope to a
213 /// callee described by \p CalleeSP. \p IsTail specifies whether the call is
214 /// a tail call. \p ReturnPC must be non-null for non-tail calls and point
215 /// to the PC value after the call returns.
216 DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
217 bool IsTail, const MCSymbol *ReturnPC);
210218
211219 /// Construct import_module DIE.
212220 DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
3838 #include "llvm/CodeGen/MachineInstr.h"
3939 #include "llvm/CodeGen/MachineModuleInfo.h"
4040 #include "llvm/CodeGen/MachineOperand.h"
41 #include "llvm/CodeGen/TargetInstrInfo.h"
4142 #include "llvm/CodeGen/TargetRegisterInfo.h"
4243 #include "llvm/CodeGen/TargetSubtargetInfo.h"
4344 #include "llvm/IR/Constants.h"
501502 }
502503 }
503504
505 void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
506 DwarfCompileUnit &CU, DIE &ScopeDIE,
507 const MachineFunction &MF) {
508 // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if
509 // the subprogram is required to have one.
510 if (!SP.areAllCallsDescribed() || !SP.isDefinition())
511 return;
512
513 // Use DW_AT_call_all_calls to express that call site entries are present
514 // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls
515 // because one of its requirements is not met: call site entries for
516 // optimized-out calls are elided.
517 CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls);
518
519 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
520 assert(TII && "TargetInstrInfo not found: cannot label tail calls");
521
522 // Emit call site entries for each call or tail call in the function.
523 for (const MachineBasicBlock &MBB : MF) {
524 for (const MachineInstr &MI : MBB.instrs()) {
525 // Skip instructions which aren't calls. Both calls and tail-calling jump
526 // instructions (e.g TAILJMPd64) are classified correctly here.
527 if (!MI.isCall())
528 continue;
529
530 // TODO: Add support for targets with delay slots (see: beginInstruction).
531 if (MI.hasDelaySlot())
532 return;
533
534 // If this is a direct call, find the callee's subprogram.
535 const MachineOperand &CalleeOp = MI.getOperand(0);
536 if (!CalleeOp.isGlobal())
537 continue;
538 const Function *CalleeDecl = dyn_cast(CalleeOp.getGlobal());
539 if (!CalleeDecl || !CalleeDecl->getSubprogram())
540 continue;
541
542 // TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
543 // TODO: Add support for indirect calls.
544
545 bool IsTail = TII->isTailCall(MI);
546
547 // For tail calls, no return PC information is needed. For regular calls,
548 // the return PC is needed to disambiguate paths in the call graph which
549 // could lead to some target function.
550 const MCSymbol *ReturnPC = IsTail ? nullptr : getLabelAfterInsn(&MI);
551
552 assert((IsTail || ReturnPC) && "Call without return PC information");
553 LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
554 << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
555 << "\n");
556 CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
557 IsTail, ReturnPC);
558 }
559 }
560 }
561
504562 void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const {
505563 if (!U.hasDwarfPubSections())
506564 return;
13751433 unsigned LastAsmLine =
13761434 Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
13771435
1436 // Request a label after the call in order to emit AT_return_pc information
1437 // in call site entries. TODO: Add support for targets with delay slots.
1438 if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot())
1439 requestLabelAfterInsn(MI);
1440
13781441 if (DL == PrevInstLoc) {
13791442 // If we have an ongoing unspecified location, nothing to do here.
13801443 if (!DL)
15451608 }
15461609
15471610 ProcessedSPNodes.insert(SP);
1548 TheCU.constructSubprogramScopeDIE(SP, FnScope);
1611 DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope);
15491612 if (auto *SkelCU = TheCU.getSkeleton())
15501613 if (!LScopes.getAbstractScopesList().empty() &&
15511614 TheCU.getCUNode()->getSplitDebugInlining())
15521615 SkelCU->constructSubprogramScopeDIE(SP, FnScope);
1616
1617 // Construct call site entries.
1618 constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
15531619
15541620 // Clear debug info
15551621 // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
423423 /// Construct a DIE for this abstract scope.
424424 void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
425425
426 /// Construct DIEs for call site entries describing the calls in \p MF.
427 void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
428 DIE &ScopeDIE, const MachineFunction &MF);
429
426430 template
427431 void addAccelNameImpl(const DICompileUnit &CU, AccelTable &AppleAccel,
428432 StringRef Name, const DIE &Die);
193193 dump(Die) << '\n';
194194 NumUnitErrors++;
195195 }
196 NumUnitErrors += verifyDebugInfoCallSite(Die);
196197 }
197198
198199 DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
220221 NumUnitErrors += verifyDieRanges(Die, RI);
221222
222223 return NumUnitErrors;
224 }
225
226 unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
227 if (Die.getTag() != DW_TAG_call_site)
228 return 0;
229
230 DWARFDie Curr = Die.getParent();
231 for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) {
232 if (Curr.getTag() == DW_TAG_inlined_subroutine) {
233 error() << "Call site entry nested within inlined subroutine:";
234 Curr.dump(OS);
235 return 1;
236 }
237 }
238
239 if (!Curr.isValid()) {
240 error() << "Call site entry not nested within a valid subprogram:";
241 Die.dump(OS);
242 return 1;
243 }
244
245 Optional CallAttr =
246 Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
247 DW_AT_call_all_tail_calls});
248 if (!CallAttr) {
249 error() << "Subprogram with call site entry has no DW_AT_call attribute:";
250 Curr.dump(OS);
251 Die.dump(OS, /*indent*/ 1);
252 return 1;
253 }
254
255 return 0;
223256 }
224257
225258 unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
11181118 AssertDI(Op && isa(Op), "invalid thrown type", &N, ThrownTypes,
11191119 Op);
11201120 }
1121
1122 if (N.areAllCallsDescribed())
1123 AssertDI(N.isDefinition(),
1124 "DIFlagAllCallsDescribed must be attached to a definition");
11211125 }
11221126
11231127 void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) {
0 ; RUN: opt -verify < %s 2>&1 | FileCheck %s
1
2 ; CHECK: DIFlagAllCallsDescribed must be attached to a definition
3 ; CHECK: warning: ignoring invalid debug info
4
5 ; Source:
6 ; struct A { ~A(); };
7 ; void foo() { A x; }
8
9 %struct.A = type { i8 }
10
11 define void @_Z3foov() !dbg !8 {
12 entry:
13 %x = alloca %struct.A, align 1
14 call void @llvm.dbg.declare(metadata %struct.A* %x, metadata !12, metadata !DIExpression()), !dbg !19
15 call void @_ZN1AD1Ev(%struct.A* %x) #3, !dbg !20
16 ret void, !dbg !20
17 }
18
19 declare void @llvm.dbg.declare(metadata, metadata, metadata)
20
21 declare void @_ZN1AD1Ev(%struct.A*)
22
23 !llvm.dbg.cu = !{!0}
24 !llvm.module.flags = !{!3, !4, !5, !6}
25 !llvm.ident = !{!7}
26
27 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
28 !1 = !DIFile(filename: "-", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA")
29 !2 = !{}
30 !3 = !{i32 2, !"Dwarf Version", i32 4}
31 !4 = !{i32 2, !"Debug Info Version", i32 3}
32 !5 = !{i32 1, !"wchar_size", i32 4}
33 !6 = !{i32 7, !"PIC Level", i32 2}
34 !7 = !{!"clang version 8.0.0 "}
35 !8 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !9, file: !9, line: 1, type: !10, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
36 !9 = !DIFile(filename: "", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA")
37 !10 = !DISubroutineType(types: !11)
38 !11 = !{null}
39 !12 = !DILocalVariable(name: "x", scope: !8, file: !9, line: 1, type: !13)
40 !13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !9, line: 1, size: 8, flags: DIFlagTypePassByReference, elements: !14, identifier: "_ZTS1A")
41 !14 = !{!15}
42 !15 = !DISubprogram(name: "~A", scope: !13, file: !9, line: 1, type: !16, isLocal: false, isDefinition: false, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: false)
43 !16 = !DISubroutineType(types: !17)
44 !17 = !{null, !18}
45 !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
46 !19 = !DILocation(line: 1, column: 36, scope: !8)
47 !20 = !DILocation(line: 1, column: 39, scope: !8)
0 ; $ clang++ -S -emit-llvm -o - -gdwarf-5 -o - -O1 tail2.cc
1 ; volatile int sink;
2 ; void __attribute__((noinline)) bat() { sink++; }
3 ; void __attribute__((noinline)) bar() { sink++; }
4 ; void __attribute__((noinline)) foo() {
5 ; bar(); bat();
6 ; bar(); bat();
7 ; }
8 ; int __attribute__((disable_tail_calls)) main() { foo(); }
9
10 ; REQUIRES: object-emission
11 ; RUN: %llc_dwarf < %s -o - | FileCheck %s -check-prefix=ASM
12 ; RUN: %llc_dwarf < %s -filetype=obj -o %t.o
13 ; RUN: llvm-dwarfdump %t.o -o - | FileCheck %s -check-prefix=OBJ -implicit-check-not=DW_TAG_call_site
14 ; RUN: llvm-dwarfdump -verify %t.o 2>&1 | FileCheck %s -check-prefix=VERIFY
15 ; RUN: llvm-dwarfdump -statistics %t.o | FileCheck %s -check-prefix=STATS
16 ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis -o /dev/null
17
18 ; VERIFY: No errors.
19 ; STATS: "call site entries":5
20
21 @sink = global i32 0, align 4, !dbg !0
22
23 ; ASM: DW_TAG_subprogram
24 ; ASM: DW_AT_call_all_calls
25 ; OBJ: [[bat_sp:.*]]: DW_TAG_subprogram
26 ; OBJ: DW_AT_call_all_calls (true)
27 ; OBJ: DW_AT_name ("bat")
28 define void @_Z3batv() !dbg !13 {
29 entry:
30 %0 = load volatile i32, i32* @sink, align 4, !dbg !16, !tbaa !17
31 %inc = add nsw i32 %0, 1, !dbg !16
32 store volatile i32 %inc, i32* @sink, align 4, !dbg !16, !tbaa !17
33 ret void, !dbg !21
34 }
35
36 ; ASM: DW_TAG_subprogram
37 ; ASM: DW_AT_call_all_calls
38 ; OBJ: [[bar_sp:.*]]: DW_TAG_subprogram
39 ; OBJ: DW_AT_call_all_calls (true)
40 ; OBJ: DW_AT_name ("bar")
41 define void @_Z3barv() !dbg !22 {
42 entry:
43 %0 = load volatile i32, i32* @sink, align 4, !dbg !23, !tbaa !17
44 %inc = add nsw i32 %0, 1, !dbg !23
45 store volatile i32 %inc, i32* @sink, align 4, !dbg !23, !tbaa !17
46 ret void, !dbg !24
47 }
48
49 ; ASM: DW_TAG_subprogram
50 ; ASM: DW_AT_call_all_calls
51 ; OBJ: [[foo_sp:.*]]: DW_TAG_subprogram
52 ; OBJ: DW_AT_call_all_calls (true)
53 ; OBJ: DW_AT_name ("foo")
54 ; OBJ: DW_TAG_call_site
55 ; OBJ: DW_AT_call_origin ([[bar_sp]])
56 ; OBJ: DW_AT_call_return_pc ({{[0x]+}}26)
57 ; OBJ: DW_TAG_call_site
58 ; OBJ: DW_AT_call_origin ([[bat_sp]])
59 ; OBJ: DW_AT_call_return_pc ({{[0x]+}}2b)
60 ; OBJ: DW_TAG_call_site
61 ; OBJ: DW_AT_call_origin ([[bar_sp]])
62 ; OBJ: DW_AT_call_return_pc ({{[0x]+}}30)
63 ; OBJ: DW_TAG_call_site
64 ; OBJ: DW_AT_call_origin ([[bat_sp]])
65 ; OBJ: DW_AT_call_tail_call
66 define void @_Z3foov() !dbg !25 {
67 entry:
68 tail call void @_Z3barv(), !dbg !26
69 tail call void @_Z3batv(), !dbg !27
70 tail call void @_Z3barv(), !dbg !26
71 tail call void @_Z3batv(), !dbg !27
72 ret void, !dbg !28
73 }
74
75 ; ASM: DW_TAG_subprogram
76 ; ASM: DW_AT_call_all_calls
77 ; OBJ: DW_TAG_subprogram
78 ; OBJ: DW_AT_call_all_calls (true)
79 ; OBJ: DW_AT_name ("main")
80 ; OBJ: DW_TAG_call_site
81 ; OBJ: DW_AT_call_origin ([[foo_sp]])
82 ; OBJ: DW_AT_call_return_pc ({{[0x]+}}46)
83 define i32 @main() !dbg !29 {
84 entry:
85 call void @_Z3foov(), !dbg !32
86
87 %indirect_target = load void ()*, void ()** undef
88 call void %indirect_target()
89
90 call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
91
92 ret i32 0, !dbg !33
93 }
94
95 !llvm.dbg.cu = !{!2}
96 !llvm.module.flags = !{!8, !9, !10, !11}
97 !llvm.ident = !{!12}
98
99 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
100 !1 = distinct !DIGlobalVariable(name: "sink", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
101 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
102 !3 = !DIFile(filename: "/Users/vsk/src/llvm.org-tailcall/tail2.cc", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA", checksumkind: CSK_MD5, checksum: "3b61952c21b7f657ddb7c0ad44cf5529")
103 !4 = !{}
104 !5 = !{!0}
105 !6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
106 !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
107 !8 = !{i32 2, !"Dwarf Version", i32 5}
108 !9 = !{i32 2, !"Debug Info Version", i32 3}
109 !10 = !{i32 1, !"wchar_size", i32 4}
110 !11 = !{i32 7, !"PIC Level", i32 2}
111 !12 = !{!"clang version 7.0.0 "}
112 !13 = distinct !DISubprogram(name: "bat", linkageName: "_Z3batv", scope: !3, file: !3, line: 2, type: !14, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
113 !14 = !DISubroutineType(types: !15)
114 !15 = !{null}
115 !16 = !DILocation(line: 2, column: 44, scope: !13)
116 !17 = !{!18, !18, i64 0}
117 !18 = !{!"int", !19, i64 0}
118 !19 = !{!"omnipotent char", !20, i64 0}
119 !20 = !{!"Simple C++ TBAA"}
120 !21 = !DILocation(line: 2, column: 48, scope: !13)
121 !22 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 3, type: !14, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
122 !23 = !DILocation(line: 3, column: 44, scope: !22)
123 !24 = !DILocation(line: 3, column: 48, scope: !22)
124 !25 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
125 !26 = !DILocation(line: 5, column: 3, scope: !25)
126 !27 = !DILocation(line: 6, column: 3, scope: !25)
127 !28 = !DILocation(line: 7, column: 1, scope: !25)
128 !29 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !30, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
129 !30 = !DISubroutineType(types: !31)
130 !31 = !{!7}
131 !32 = !DILocation(line: 8, column: 50, scope: !29)
132 !33 = !DILocation(line: 8, column: 57, scope: !29)
0 # RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t.o
1 # RUN: not llvm-dwarfdump -verify %t.o 2>&1 | FileCheck %s
2
3 # CHECK: error: Subprogram with call site entry has no DW_AT_call attribute:
4 # CHECK: DW_TAG_subprogram
5 # CHECK: DW_AT_name ("main")
6 # CHECK: DW_TAG_call_site
7 # CHECK: DW_AT_call_origin
8 # CHECK: Errors detected.
9
10 # Source:
11 ## define void @foo() !dbg !25 {
12 ## ret void, !dbg !28
13 ## }
14 ##
15 ## define i32 @main() !dbg !29 {
16 ## call void @foo(), !dbg !32
17 ## ret i32 0, !dbg !33
18 ## }
19 ##
20 ## !llvm.dbg.cu = !{!2}
21 ## !llvm.module.flags = !{!8, !9, !10, !11}
22 ## !llvm.ident = !{!12}
23 ##
24 ## !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
25 ## !1 = distinct !DIGlobalVariable(name: "sink", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
26 ## !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
27 ## !3 = !DIFile(filename: "/Users/vsk/src/llvm.org-tailcall/tail2.cc", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA", checksumkind: CSK_MD5, checksum: "3b61952c21b7f657ddb7c0ad44cf5529")
28 ## !4 = !{}
29 ## !5 = !{!0}
30 ## !6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
31 ## !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
32 ## !8 = !{i32 2, !"Dwarf Version", i32 5}
33 ## !9 = !{i32 2, !"Debug Info Version", i32 3}
34 ## !10 = !{i32 1, !"wchar_size", i32 4}
35 ## !11 = !{i32 7, !"PIC Level", i32 2}
36 ## !12 = !{!"clang version 7.0.0 "}
37 ## !13 = distinct !DISubprogram(name: "bat", linkageName: "_Z3batv", scope: !3, file: !3, line: 2, type: !14, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
38 ## !14 = !DISubroutineType(types: !15)
39 ## !15 = !{null}
40 ## !16 = !DILocation(line: 2, column: 44, scope: !13)
41 ## !17 = !{!18, !18, i64 0}
42 ## !18 = !{!"int", !19, i64 0}
43 ## !19 = !{!"omnipotent char", !20, i64 0}
44 ## !20 = !{!"Simple C++ TBAA"}
45 ## !21 = !DILocation(line: 2, column: 48, scope: !13)
46 ## !22 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 3, type: !14, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
47 ## !23 = !DILocation(line: 3, column: 44, scope: !22)
48 ## !24 = !DILocation(line: 3, column: 48, scope: !22)
49 ## !25 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
50 ## !26 = !DILocation(line: 5, column: 3, scope: !25)
51 ## !27 = !DILocation(line: 6, column: 3, scope: !25)
52 ## !28 = !DILocation(line: 7, column: 1, scope: !25)
53 ## !29 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !30, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
54 ## !30 = !DISubroutineType(types: !31)
55 ## !31 = !{!7}
56 ## !32 = !DILocation(line: 8, column: 50, scope: !29)
57 ## !33 = !DILocation(line: 8, column: 57, scope: !29)
58
59 .section __TEXT,__text,regular,pure_instructions
60 .globl _foo ## -- Begin function foo
61 _foo: ## @foo
62 Lfunc_begin0:
63 .cfi_startproc
64 ## %bb.0:
65 retq
66 Ltmp0:
67 Lfunc_end0:
68 .cfi_endproc
69 ## -- End function
70 .globl _main ## -- Begin function main
71 _main: ## @main
72 Lfunc_begin1:
73 .cfi_startproc
74 ## %bb.0:
75 pushq %rax
76 .cfi_def_cfa_offset 16
77 Ltmp1:
78 callq _foo
79 xorl %eax, %eax
80 popq %rcx
81 retq
82 Ltmp2:
83 Lfunc_end1:
84 .cfi_endproc
85 ## -- End function
86 .section __DWARF,__debug_str_offs,regular,debug
87 Lsection_str_off:
88 .long 36
89 .short 5
90 .short 0
91 Lstr_offsets_base0:
92 .section __DWARF,__debug_str,regular,debug
93 Linfo_string:
94 .asciz "clang version 7.0.0 " ## string offset=0
95 .asciz "/Users/vsk/src/llvm.org-tailcall/tail2.cc" ## string offset=21
96 .asciz "/Users/vsk/src/builds/llvm-project-tailcall-RA" ## string offset=63
97 .asciz "sink" ## string offset=110
98 .asciz "int" ## string offset=115
99 .asciz "foo" ## string offset=119
100 .asciz "_Z3foov" ## string offset=123
101 .asciz "main" ## string offset=131
102 .section __DWARF,__debug_str_offs,regular,debug
103 .long 0
104 .long 21
105 .long 63
106 .long 110
107 .long 115
108 .long 119
109 .long 123
110 .long 131
111 .section __DWARF,__debug_abbrev,regular,debug
112 Lsection_abbrev:
113 .byte 1 ## Abbreviation Code
114 .byte 17 ## DW_TAG_compile_unit
115 .byte 1 ## DW_CHILDREN_yes
116 .byte 37 ## DW_AT_producer
117 .byte 37 ## DW_FORM_strx1
118 .byte 19 ## DW_AT_language
119 .byte 5 ## DW_FORM_data2
120 .byte 3 ## DW_AT_name
121 .byte 37 ## DW_FORM_strx1
122 .byte 114 ## DW_AT_str_offsets_base
123 .byte 23 ## DW_FORM_sec_offset
124 .byte 16 ## DW_AT_stmt_list
125 .byte 23 ## DW_FORM_sec_offset
126 .byte 27 ## DW_AT_comp_dir
127 .byte 37 ## DW_FORM_strx1
128 .ascii "\341\177" ## DW_AT_APPLE_optimized
129 .byte 25 ## DW_FORM_flag_present
130 .byte 17 ## DW_AT_low_pc
131 .byte 1 ## DW_FORM_addr
132 .byte 18 ## DW_AT_high_pc
133 .byte 6 ## DW_FORM_data4
134 .byte 0 ## EOM(1)
135 .byte 0 ## EOM(2)
136 .byte 2 ## Abbreviation Code
137 .byte 52 ## DW_TAG_variable
138 .byte 0 ## DW_CHILDREN_no
139 .byte 3 ## DW_AT_name
140 .byte 37 ## DW_FORM_strx1
141 .byte 73 ## DW_AT_type
142 .byte 19 ## DW_FORM_ref4
143 .byte 63 ## DW_AT_external
144 .byte 25 ## DW_FORM_flag_present
145 .byte 58 ## DW_AT_decl_file
146 .byte 11 ## DW_FORM_data1
147 .byte 59 ## DW_AT_decl_line
148 .byte 11 ## DW_FORM_data1
149 .byte 0 ## EOM(1)
150 .byte 0 ## EOM(2)
151 .byte 3 ## Abbreviation Code
152 .byte 53 ## DW_TAG_volatile_type
153 .byte 0 ## DW_CHILDREN_no
154 .byte 73 ## DW_AT_type
155 .byte 19 ## DW_FORM_ref4
156 .byte 0 ## EOM(1)
157 .byte 0 ## EOM(2)
158 .byte 4 ## Abbreviation Code
159 .byte 36 ## DW_TAG_base_type
160 .byte 0 ## DW_CHILDREN_no
161 .byte 3 ## DW_AT_name
162 .byte 37 ## DW_FORM_strx1
163 .byte 62 ## DW_AT_encoding
164 .byte 11 ## DW_FORM_data1
165 .byte 11 ## DW_AT_byte_size
166 .byte 11 ## DW_FORM_data1
167 .byte 0 ## EOM(1)
168 .byte 0 ## EOM(2)
169 .byte 5 ## Abbreviation Code
170 .byte 46 ## DW_TAG_subprogram
171 .byte 0 ## DW_CHILDREN_no
172 .byte 17 ## DW_AT_low_pc
173 .byte 1 ## DW_FORM_addr
174 .byte 18 ## DW_AT_high_pc
175 .byte 6 ## DW_FORM_data4
176 .ascii "\347\177" ## DW_AT_APPLE_omit_frame_ptr
177 .byte 25 ## DW_FORM_flag_present
178 .byte 64 ## DW_AT_frame_base
179 .byte 24 ## DW_FORM_exprloc
180 ## .byte 122 ## DW_AT_call_all_calls
181 ## .byte 25 ## DW_FORM_flag_present
182 .byte 110 ## DW_AT_linkage_name
183 .byte 37 ## DW_FORM_strx1
184 .byte 3 ## DW_AT_name
185 .byte 37 ## DW_FORM_strx1
186 .byte 58 ## DW_AT_decl_file
187 .byte 11 ## DW_FORM_data1
188 .byte 59 ## DW_AT_decl_line
189 .byte 11 ## DW_FORM_data1
190 .byte 63 ## DW_AT_external
191 .byte 25 ## DW_FORM_flag_present
192 .ascii "\341\177" ## DW_AT_APPLE_optimized
193 .byte 25 ## DW_FORM_flag_present
194 .byte 0 ## EOM(1)
195 .byte 0 ## EOM(2)
196 .byte 6 ## Abbreviation Code
197 .byte 46 ## DW_TAG_subprogram
198 .byte 1 ## DW_CHILDREN_yes
199 .byte 17 ## DW_AT_low_pc
200 .byte 1 ## DW_FORM_addr
201 .byte 18 ## DW_AT_high_pc
202 .byte 6 ## DW_FORM_data4
203 .ascii "\347\177" ## DW_AT_APPLE_omit_frame_ptr
204 .byte 25 ## DW_FORM_flag_present
205 .byte 64 ## DW_AT_frame_base
206 .byte 24 ## DW_FORM_exprloc
207 ## .byte 122 ## DW_AT_call_all_calls
208 ## .byte 25 ## DW_FORM_flag_present
209 .byte 3 ## DW_AT_name
210 .byte 37 ## DW_FORM_strx1
211 .byte 58 ## DW_AT_decl_file
212 .byte 11 ## DW_FORM_data1
213 .byte 59 ## DW_AT_decl_line
214 .byte 11 ## DW_FORM_data1
215 .byte 73 ## DW_AT_type
216 .byte 19 ## DW_FORM_ref4
217 .byte 63 ## DW_AT_external
218 .byte 25 ## DW_FORM_flag_present
219 .ascii "\341\177" ## DW_AT_APPLE_optimized
220 .byte 25 ## DW_FORM_flag_present
221 .byte 0 ## EOM(1)
222 .byte 0 ## EOM(2)
223 .byte 7 ## Abbreviation Code
224 .byte 72 ## DW_TAG_call_site
225 .byte 0 ## DW_CHILDREN_no
226 .byte 127 ## DW_AT_call_origin
227 .byte 19 ## DW_FORM_ref4
228 .byte 0 ## EOM(1)
229 .byte 0 ## EOM(2)
230 .byte 0 ## EOM(3)
231 .section __DWARF,__debug_info,regular,debug
232 Lsection_info:
233 Lcu_begin0:
234 .long 99 ## Length of Unit
235 .short 5 ## DWARF version number
236 .byte 1 ## DWARF Unit Type
237 .byte 8 ## Address Size (in bytes)
238 .set Lset0, Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
239 .long Lset0
240 .byte 1 ## Abbrev [1] 0xc:0x5b DW_TAG_compile_unit
241 .byte 0 ## DW_AT_producer
242 .short 4 ## DW_AT_language
243 .byte 1 ## DW_AT_name
244 .set Lset1, Lstr_offsets_base0-Lsection_str_off ## DW_AT_str_offsets_base
245 .long Lset1
246 .set Lset2, Lline_table_start0-Lsection_line ## DW_AT_stmt_list
247 .long Lset2
248 .byte 2 ## DW_AT_comp_dir
249 ## DW_AT_APPLE_optimized
250 .quad Lfunc_begin0 ## DW_AT_low_pc
251 .set Lset3, Lfunc_end1-Lfunc_begin0 ## DW_AT_high_pc
252 .long Lset3
253 .byte 2 ## Abbrev [2] 0x26:0x8 DW_TAG_variable
254 .byte 3 ## DW_AT_name
255 .long 46 ## DW_AT_type
256 ## DW_AT_external
257 .byte 1 ## DW_AT_decl_file
258 .byte 1 ## DW_AT_decl_line
259 .byte 3 ## Abbrev [3] 0x2e:0x5 DW_TAG_volatile_type
260 .long 51 ## DW_AT_type
261 .byte 4 ## Abbrev [4] 0x33:0x4 DW_TAG_base_type
262 .byte 4 ## DW_AT_name
263 .byte 5 ## DW_AT_encoding
264 .byte 4 ## DW_AT_byte_size
265 .byte 5 ## Abbrev [5] 0x37:0x13 DW_TAG_subprogram
266 .quad Lfunc_begin0 ## DW_AT_low_pc
267 .set Lset4, Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc
268 .long Lset4
269 ## DW_AT_APPLE_omit_frame_ptr
270 .byte 1 ## DW_AT_frame_base
271 .byte 87
272 ## DW_AT_call_all_calls
273 .byte 6 ## DW_AT_linkage_name
274 .byte 5 ## DW_AT_name
275 .byte 1 ## DW_AT_decl_file
276 .byte 4 ## DW_AT_decl_line
277 ## DW_AT_external
278 ## DW_AT_APPLE_optimized
279 .byte 6 ## Abbrev [6] 0x4a:0x1c DW_TAG_subprogram
280 .quad Lfunc_begin1 ## DW_AT_low_pc
281 .set Lset5, Lfunc_end1-Lfunc_begin1 ## DW_AT_high_pc
282 .long Lset5
283 ## DW_AT_APPLE_omit_frame_ptr
284 .byte 1 ## DW_AT_frame_base
285 .byte 87
286 ## DW_AT_call_all_calls
287 .byte 7 ## DW_AT_name
288 .byte 1 ## DW_AT_decl_file
289 .byte 8 ## DW_AT_decl_line
290 .long 51 ## DW_AT_type
291 ## DW_AT_external
292 ## DW_AT_APPLE_optimized
293 .byte 7 ## Abbrev [7] 0x60:0x5 DW_TAG_call_site
294 .long 55 ## DW_AT_call_origin
295 .byte 0 ## End Of Children Mark
296 .byte 0 ## End Of Children Mark
297 .section __DWARF,__debug_macinfo,regular,debug
298 Ldebug_macinfo:
299 .byte 0 ## End Of Macro List Mark
300 .section __DWARF,__debug_names,regular,debug
301 Ldebug_names_begin:
302 .set Lset6, Lnames_end0-Lnames_start0 ## Header: unit length
303 .long Lset6
304 Lnames_start0:
305 .short 5 ## Header: version
306 .short 0 ## Header: padding
307 .long 1 ## Header: compilation unit count
308 .long 0 ## Header: local type unit count
309 .long 0 ## Header: foreign type unit count
310 .long 4 ## Header: bucket count
311 .long 4 ## Header: name count
312 .set Lset7, Lnames_abbrev_end0-Lnames_abbrev_start0 ## Header: abbreviation table size
313 .long Lset7
314 .long 8 ## Header: augmentation string size
315 .ascii "LLVM0700" ## Header: augmentation string
316 .set Lset8, Lcu_begin0-Lsection_info ## Compilation unit 0
317 .long Lset8
318 .long 1 ## Bucket 0
319 .long 2 ## Bucket 1
320 .long 3 ## Bucket 2
321 .long 4 ## Bucket 3
322 .long 193495088 ## Hash in Bucket 0
323 .long 193491849 ## Hash in Bucket 1
324 .long 2090499946 ## Hash in Bucket 2
325 .long -1257882357 ## Hash in Bucket 3
326 .long 115 ## String in Bucket 0: int
327 .long 119 ## String in Bucket 1: foo
328 .long 131 ## String in Bucket 2: main
329 .long 123 ## String in Bucket 3: _Z3foov
330 .set Lset9, Lnames3-Lnames_entries0 ## Offset in Bucket 0
331 .long Lset9
332 .set Lset10, Lnames0-Lnames_entries0 ## Offset in Bucket 1
333 .long Lset10
334 .set Lset11, Lnames1-Lnames_entries0 ## Offset in Bucket 2
335 .long Lset11
336 .set Lset12, Lnames2-Lnames_entries0 ## Offset in Bucket 3
337 .long Lset12
338 Lnames_abbrev_start0:
339 .byte 46 ## Abbrev code
340 .byte 46 ## DW_TAG_subprogram
341 .byte 3 ## DW_IDX_die_offset
342 .byte 19 ## DW_FORM_ref4
343 .byte 0 ## End of abbrev
344 .byte 0 ## End of abbrev
345 .byte 36 ## Abbrev code
346 .byte 36 ## DW_TAG_base_type
347 .byte 3 ## DW_IDX_die_offset
348 .byte 19 ## DW_FORM_ref4
349 .byte 0 ## End of abbrev
350 .byte 0 ## End of abbrev
351 .byte 0 ## End of abbrev list
352 Lnames_abbrev_end0:
353 Lnames_entries0:
354 Lnames3:
355 .byte 36 ## Abbreviation code
356 .long 51 ## DW_IDX_die_offset
357 .long 0 ## End of list: int
358 Lnames0:
359 .byte 46 ## Abbreviation code
360 .long 55 ## DW_IDX_die_offset
361 .long 0 ## End of list: foo
362 Lnames1:
363 .byte 46 ## Abbreviation code
364 .long 74 ## DW_IDX_die_offset
365 .long 0 ## End of list: main
366 Lnames2:
367 .byte 46 ## Abbreviation code
368 .long 55 ## DW_IDX_die_offset
369 .long 0 ## End of list: _Z3foov
370 Lnames_end0:
371
372 .subsections_via_symbols
373 .section __DWARF,__debug_line,regular,debug
374 Lsection_line:
375 Lline_table_start0:
3131 /// Total number of PC range bytes in each variable's enclosing scope,
3232 /// starting from the first definition of the variable.
3333 unsigned ScopeBytesFromFirstDefinition = 0;
34 /// Total number of call site entries (DW_TAG_call_site).
35 unsigned CallSiteEntries = 0;
3436 };
3537
3638 /// Extract the low pc from a Die.
5557 bool HasLoc = false;
5658 uint64_t BytesCovered = 0;
5759 uint64_t OffsetToFirstDefinition = 0;
60
61 if (Die.getTag() == dwarf::DW_TAG_call_site) {
62 GlobalStats.CallSiteEntries++;
63 return;
64 }
5865
5966 if (Die.getTag() != dwarf::DW_TAG_formal_parameter &&
6067 Die.getTag() != dwarf::DW_TAG_variable &&
259266 printDatum(OS, "unique source variables", VarUnique);
260267 printDatum(OS, "source variables", VarTotal);
261268 printDatum(OS, "variables with location", VarWithLoc);
269 printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
262270 printDatum(OS, "scope bytes total",
263271 GlobalStats.ScopeBytesFromFirstDefinition);
264272 printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);