llvm.org GIT mirror llvm / f1c527b
AsmPrinter: Don't emit empty .debug_loc entries If we don't know how to represent a .debug_loc entry, skip the entry entirely rather than emitting an empty one. Similarly, if a .debug_loc list has no entries, don't create the list. We still want to create the variables, just in an optimized-out form that doesn't have a DW_AT_location. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240244 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
6 changed file(s) with 188 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
44 AsmPrinterDwarf.cpp
55 AsmPrinterInlineAsm.cpp
66 DbgValueHistoryCalculator.cpp
7 DebugLocStream.cpp
78 DIE.cpp
89 DIEHash.cpp
910 DwarfAccelTable.cpp
141141 }
142142
143143 /// \brief Lower this entry into a DWARF expression.
144 void finalize(const AsmPrinter &AP, DebugLocStream &Locs,
144 void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List,
145145 const DIBasicType *BT);
146146 };
147147
0 //===- DebugLocStream.cpp - DWARF debug_loc stream --------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "DebugLocStream.h"
10 #include "DwarfDebug.h"
11 #include "llvm/CodeGen/AsmPrinter.h"
12
13 using namespace llvm;
14
15 bool DebugLocStream::finalizeList(AsmPrinter &Asm) {
16 if (Lists.back().EntryOffset == Entries.size()) {
17 // Empty list. Delete it.
18 Lists.pop_back();
19 return false;
20 }
21
22 // Real list. Generate a label for it.
23 Lists.back().Label = Asm.createTempSymbol("debug_loc");
24 return true;
25 }
26
27 void DebugLocStream::finalizeEntry() {
28 if (Entries.back().ByteOffset != DWARFBytes.size())
29 return;
30
31 // The last entry was empty. Delete it.
32 Comments.erase(Comments.begin() + Entries.back().CommentOffset,
33 Comments.end());
34 Entries.pop_back();
35
36 assert(Lists.back().EntryOffset <= Entries.size() &&
37 "Popped off more entries than are in the list");
38 }
39
40 DebugLocStream::ListBuilder::~ListBuilder() {
41 if (!Locs.finalizeList(Asm))
42 return;
43 V.initializeDbgValue(&MI);
44 V.setDebugLocListIndex(ListIndex);
45 }
1414 #include "ByteStreamer.h"
1515
1616 namespace llvm {
17
18 class AsmPrinter;
19 class DbgVariable;
1720 class DwarfCompileUnit;
21 class MachineInstr;
1822 class MCSymbol;
1923
2024 /// \brief Byte stream of .debug_loc entries.
2832 public:
2933 struct List {
3034 DwarfCompileUnit *CU;
31 MCSymbol *Label;
35 MCSymbol *Label = nullptr;
3236 size_t EntryOffset;
33 List(DwarfCompileUnit *CU, MCSymbol *Label, size_t EntryOffset)
34 : CU(CU), Label(Label), EntryOffset(EntryOffset) {}
37 List(DwarfCompileUnit *CU, size_t EntryOffset)
38 : CU(CU), EntryOffset(EntryOffset) {}
3539 };
3640 struct Entry {
3741 const MCSymbol *BeginSym;
6064 const List &getList(size_t LI) const { return Lists[LI]; }
6165 ArrayRef getLists() const { return Lists; }
6266
67 class ListBuilder;
68 class EntryBuilder;
69
70 private:
6371 /// \brief Start a new .debug_loc entry list.
6472 ///
6573 /// Start a new .debug_loc entry list. Return the new list's index so it can
6674 /// be retrieved later via \a getList().
6775 ///
6876 /// Until the next call, \a startEntry() will add entries to this list.
69 size_t startList(DwarfCompileUnit *CU, MCSymbol *Label) {
77 size_t startList(DwarfCompileUnit *CU) {
7078 size_t LI = Lists.size();
71 Lists.emplace_back(CU, Label, Entries.size());
79 Lists.emplace_back(CU, Entries.size());
7280 return LI;
7381 }
82
83 /// Finalize a .debug_loc entry list.
84 ///
85 /// If there are no entries in this list, delete it outright. Otherwise,
86 /// create a label with \a Asm.
87 ///
88 /// \return false iff the list is deleted.
89 bool finalizeList(AsmPrinter &Asm);
7490
7591 /// \brief Start a new .debug_loc entry.
7692 ///
8096 Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size());
8197 }
8298
99 /// Finalize a .debug_loc entry, deleting if it's empty.
100 void finalizeEntry();
101
102 public:
83103 BufferByteStreamer getStreamer() {
84104 return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
85105 }
128148 return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
129149 }
130150 };
151
152 /// Builder for DebugLocStream lists.
153 class DebugLocStream::ListBuilder {
154 DebugLocStream &Locs;
155 AsmPrinter &Asm;
156 DbgVariable &V;
157 const MachineInstr &MI;
158 size_t ListIndex;
159
160 public:
161 ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
162 DbgVariable &V, const MachineInstr &MI)
163 : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {}
164
165 /// Finalize the list.
166 ///
167 /// If the list is empty, delete it. Otherwise, finalize it by creating a
168 /// temp symbol in \a Asm and setting up the \a DbgVariable.
169 ~ListBuilder();
170
171 DebugLocStream &getLocs() { return Locs; }
172 };
173
174 /// Builder for DebugLocStream entries.
175 class DebugLocStream::EntryBuilder {
176 DebugLocStream &Locs;
177
178 public:
179 EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
180 : Locs(List.getLocs()) {
181 Locs.startEntry(Begin, End);
182 }
183
184 /// Finalize the entry, deleting it if it's empty.
185 ~EntryBuilder() { Locs.finalizeEntry(); }
186
187 BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
188 };
189
131190 } // namespace llvm
191
132192 #endif
907907
908908 const MachineInstr *MInsn = Ranges.front().first;
909909 assert(MInsn->isDebugValue() && "History must begin with debug value");
910 RegVar->initializeDbgValue(MInsn);
911910
912911 // Check if the first DBG_VALUE is valid for the rest of the function.
913 if (Ranges.size() == 1 && Ranges.front().second == nullptr)
912 if (Ranges.size() == 1 && Ranges.front().second == nullptr) {
913 RegVar->initializeDbgValue(MInsn);
914914 continue;
915 }
915916
916917 // Handle multiple DBG_VALUE instructions describing one variable.
917 RegVar->setDebugLocListIndex(
918 DebugLocs.startList(&TheCU, Asm->createTempSymbol("debug_loc")));
918 DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn);
919919
920920 // Build the location list for this variable.
921921 SmallVector Entries;
929929
930930 // Finalize the entry by lowering it into a DWARF bytestream.
931931 for (auto &Entry : Entries)
932 Entry.finalize(*Asm, DebugLocs, BT);
932 Entry.finalize(*Asm, List, BT);
933933 }
934934
935935 // Collect info for variables that were optimized out.
15031503 // FIXME: ^
15041504 }
15051505
1506 void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream &Locs,
1506 void DebugLocEntry::finalize(const AsmPrinter &AP,
1507 DebugLocStream::ListBuilder &List,
15071508 const DIBasicType *BT) {
1508 Locs.startEntry(Begin, End);
1509 BufferByteStreamer Streamer = Locs.getStreamer();
1509 DebugLocStream::EntryBuilder Entry(List, Begin, End);
1510 BufferByteStreamer Streamer = Entry.getStreamer();
15101511 const DebugLocEntry::Value &Value = Values[0];
15111512 if (Value.isBitPiece()) {
15121513 // Emit all pieces that belong to the same variable and range.
0 ; RUN: llc -mtriple=x86_64-apple-macosx <%s | FileCheck %s
1 ; Test that we don't generate empty .debug_loc entries. Originally, there were
2 ; two empty .debug_loc entries for 'a' in an otherwise empty .debug_loc list.
3 ;
4 ; CHECK: .section __DWARF,__debug_loc,regular,debug
5 ; CHECK-NEXT: Lsection_debug_loc:
6 ; CHECK-NEXT: .section __DWARF,__debug_abbrev,regular,debug
7 ;
8 ; Test that the variable stuck around.
9 ; CHECK: .section __DWARF,__debug_info,regular,debug
10 ; CHECK: DW_TAG_variable
11 ; CHECK-NOT: DW_AT_location
12
13 ; Generated using clang -cc1 with the following args:
14 ;
15 ; -triple x86_64-apple-macosx -emit-llvm -gdwarf-4 -O1
16 ;
17 ; From this testcase:
18 ;
19 ;; void fn1() {
20 ;; float a = 1;
21 ;; for (;;)
22 ;; a = 0;
23 ;; }
24
25 ; Function Attrs: noreturn nounwind readnone
26 define void @_Z3fn1v() #0 {
27 entry:
28 tail call void @llvm.dbg.value(metadata float 1.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
29 br label %for.cond, !dbg !16
30
31 for.cond: ; preds = %for.cond, %entry
32 tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
33 br label %for.cond, !dbg !17
34 }
35
36 ; Function Attrs: nounwind readnone
37 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
38
39 attributes #0 = { noreturn nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
40 attributes #1 = { nounwind readnone }
41
42 !llvm.dbg.cu = !{!0}
43 !llvm.module.flags = !{!11, !12}
44 !llvm.ident = !{!13}
45
46 !0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2)
47 !1 = !DIFile(filename: "", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
48 !2 = !{}
49 !3 = !{!4}
50 !4 = !DISubprogram(name: "fn1", linkageName: "_Z3fn1v", scope: !5, file: !5, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @_Z3fn1v, variables: !8)
51 !5 = !DIFile(filename: "t.cpp", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
52 !6 = !DISubroutineType(types: !7)
53 !7 = !{null}
54 !8 = !{!9}
55 !9 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "a", scope: !4, file: !5, line: 2, type: !10)
56 !10 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
57 !11 = !{i32 2, !"Dwarf Version", i32 4}
58 !12 = !{i32 2, !"Debug Info Version", i32 3}
59 !13 = !{!"clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)"}
60 !14 = !DIExpression()
61 !15 = !DILocation(line: 2, scope: !4)
62 !16 = !DILocation(line: 3, scope: !4)
63 !17 = !DILocation(line: 3, scope: !18)
64 !18 = distinct !DILexicalBlock(scope: !19, file: !5, line: 3)
65 !19 = distinct !DILexicalBlock(scope: !4, file: !5, line: 3)