/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Units ------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file contains support for constructing a dwarf compile unit. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "DwarfCompileUnit.h" |
15 | | #include "AddressPool.h" |
16 | | #include "DwarfDebug.h" |
17 | | #include "DwarfExpression.h" |
18 | | #include "DwarfUnit.h" |
19 | | #include "llvm/ADT/None.h" |
20 | | #include "llvm/ADT/STLExtras.h" |
21 | | #include "llvm/ADT/SmallVector.h" |
22 | | #include "llvm/ADT/StringRef.h" |
23 | | #include "llvm/BinaryFormat/Dwarf.h" |
24 | | #include "llvm/CodeGen/AsmPrinter.h" |
25 | | #include "llvm/CodeGen/DIE.h" |
26 | | #include "llvm/CodeGen/LexicalScopes.h" |
27 | | #include "llvm/CodeGen/MachineFunction.h" |
28 | | #include "llvm/CodeGen/MachineInstr.h" |
29 | | #include "llvm/CodeGen/MachineOperand.h" |
30 | | #include "llvm/IR/DataLayout.h" |
31 | | #include "llvm/IR/DebugInfo.h" |
32 | | #include "llvm/IR/DebugInfoMetadata.h" |
33 | | #include "llvm/IR/GlobalVariable.h" |
34 | | #include "llvm/MC/MachineLocation.h" |
35 | | #include "llvm/MC/MCSection.h" |
36 | | #include "llvm/MC/MCStreamer.h" |
37 | | #include "llvm/MC/MCSymbol.h" |
38 | | #include "llvm/Support/Casting.h" |
39 | | #include "llvm/Target/TargetFrameLowering.h" |
40 | | #include "llvm/Target/TargetLoweringObjectFile.h" |
41 | | #include "llvm/Target/TargetMachine.h" |
42 | | #include "llvm/Target/TargetOptions.h" |
43 | | #include "llvm/Target/TargetRegisterInfo.h" |
44 | | #include "llvm/Target/TargetSubtargetInfo.h" |
45 | | #include <algorithm> |
46 | | #include <cassert> |
47 | | #include <cstdint> |
48 | | #include <iterator> |
49 | | #include <memory> |
50 | | #include <string> |
51 | | #include <utility> |
52 | | |
53 | | using namespace llvm; |
54 | | |
55 | | DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, |
56 | | AsmPrinter *A, DwarfDebug *DW, |
57 | | DwarfFile *DWU) |
58 | 1.20k | : DwarfUnit(dwarf::DW_TAG_compile_unit, Node, A, DW, DWU), UniqueID(UID) { |
59 | 1.20k | insertDIE(Node, &getUnitDie()); |
60 | 1.20k | MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin"); |
61 | 1.20k | } |
62 | | |
63 | | /// addLabelAddress - Add a dwarf label attribute data and value using |
64 | | /// DW_FORM_addr or DW_FORM_GNU_addr_index. |
65 | | void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, |
66 | 70.6k | const MCSymbol *Label) { |
67 | 70.6k | // Don't use the address pool in non-fission or in the skeleton unit itself. |
68 | 70.6k | // FIXME: Once GDB supports this, it's probably worthwhile using the address |
69 | 70.6k | // pool from the skeleton - maybe even in non-fission (possibly fewer |
70 | 70.6k | // relocations by sharing them in the pool, but we have other ideas about how |
71 | 70.6k | // to reduce the number of relocations as well/instead). |
72 | 70.6k | if (!DD->useSplitDwarf() || 70.6k !Skeleton72 ) |
73 | 70.5k | return addLocalLabelAddress(Die, Attribute, Label); |
74 | 45 | |
75 | 45 | if (45 Label45 ) |
76 | 45 | DD->addArangeLabel(SymbolCU(this, Label)); |
77 | 70.6k | |
78 | 70.6k | unsigned idx = DD->getAddressPool().getIndex(Label); |
79 | 70.6k | Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_GNU_addr_index, |
80 | 70.6k | DIEInteger(idx)); |
81 | 70.6k | } |
82 | | |
83 | | void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, |
84 | | dwarf::Attribute Attribute, |
85 | 70.5k | const MCSymbol *Label) { |
86 | 70.5k | if (Label) |
87 | 70.5k | DD->addArangeLabel(SymbolCU(this, Label)); |
88 | 70.5k | |
89 | 70.5k | if (Label) |
90 | 70.5k | Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, |
91 | 70.5k | DIELabel(Label)); |
92 | 70.5k | else |
93 | 0 | Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, |
94 | 0 | DIEInteger(0)); |
95 | 70.5k | } |
96 | | |
97 | | unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, |
98 | 209k | StringRef DirName) { |
99 | 209k | // If we print assembly, we can't separate .file entries according to |
100 | 209k | // compile units. Thus all files will belong to the default compile unit. |
101 | 209k | |
102 | 209k | // FIXME: add a better feature test than hasRawTextSupport. Even better, |
103 | 209k | // extend .file to support this. |
104 | 209k | return Asm->OutStreamer->EmitDwarfFileDirective( |
105 | 209k | 0, DirName, FileName, |
106 | 209k | Asm->OutStreamer->hasRawTextSupport() ? 02.42k : getUniqueID()206k ); |
107 | 209k | } |
108 | | |
109 | | DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( |
110 | 417 | const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) { |
111 | 417 | // Check for pre-existence. |
112 | 417 | if (DIE *Die = getDIE(GV)) |
113 | 3 | return Die; |
114 | 414 | |
115 | 417 | assert(GV); |
116 | 414 | |
117 | 414 | auto *GVContext = GV->getScope(); |
118 | 414 | auto *GTy = DD->resolve(GV->getType()); |
119 | 414 | |
120 | 414 | // Construct the context before querying for the existence of the DIE in |
121 | 414 | // case such construction creates the DIE. |
122 | 414 | DIE *ContextDIE = getOrCreateContextDIE(GVContext); |
123 | 414 | |
124 | 414 | // Add to map. |
125 | 414 | DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV); |
126 | 414 | DIScope *DeclContext; |
127 | 414 | if (auto *SDMDecl414 = GV->getStaticDataMemberDeclaration()) { |
128 | 20 | DeclContext = resolve(SDMDecl->getScope()); |
129 | 20 | assert(SDMDecl->isStaticMember() && "Expected static member decl"); |
130 | 20 | assert(GV->isDefinition()); |
131 | 20 | // We need the declaration DIE that is in the static member's class. |
132 | 20 | DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl); |
133 | 20 | addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE); |
134 | 20 | // If the global variable's type is different from the one in the class |
135 | 20 | // member type, assume that it's more specific and also emit it. |
136 | 20 | if (GTy != DD->resolve(SDMDecl->getBaseType())) |
137 | 1 | addType(*VariableDIE, GTy); |
138 | 414 | } else { |
139 | 394 | DeclContext = GV->getScope(); |
140 | 394 | // Add name and type. |
141 | 394 | addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName()); |
142 | 394 | addType(*VariableDIE, GTy); |
143 | 394 | |
144 | 394 | // Add scoping info. |
145 | 394 | if (!GV->isLocalToUnit()) |
146 | 252 | addFlag(*VariableDIE, dwarf::DW_AT_external); |
147 | 394 | |
148 | 394 | // Add line number info. |
149 | 394 | addSourceLine(*VariableDIE, GV); |
150 | 394 | } |
151 | 414 | |
152 | 414 | if (!GV->isDefinition()) |
153 | 3 | addFlag(*VariableDIE, dwarf::DW_AT_declaration); |
154 | 414 | else |
155 | 411 | addGlobalName(GV->getName(), *VariableDIE, DeclContext); |
156 | 414 | |
157 | 414 | if (uint32_t AlignInBytes = GV->getAlignInBytes()) |
158 | 2 | addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, |
159 | 2 | AlignInBytes); |
160 | 414 | |
161 | 414 | // Add location. |
162 | 414 | bool addToAccelTable = false; |
163 | 414 | DIELoc *Loc = nullptr; |
164 | 414 | std::unique_ptr<DIEDwarfExpression> DwarfExpr; |
165 | 416 | for (const auto &GE : GlobalExprs) { |
166 | 416 | const GlobalVariable *Global = GE.Var; |
167 | 416 | const DIExpression *Expr = GE.Expr; |
168 | 416 | |
169 | 416 | // For compatibility with DWARF 3 and earlier, |
170 | 416 | // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) becomes |
171 | 416 | // DW_AT_const_value(X). |
172 | 416 | if (GlobalExprs.size() == 1 && 416 Expr406 && Expr->isConstant()406 ) { |
173 | 2 | addToAccelTable = true; |
174 | 2 | addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1)); |
175 | 2 | break; |
176 | 2 | } |
177 | 414 | |
178 | 414 | // We cannot describe the location of dllimport'd variables: the |
179 | 414 | // computation of their address requires loads from the IAT. |
180 | 414 | if (414 Global && 414 Global->hasDLLImportStorageClass()279 ) |
181 | 1 | continue; |
182 | 413 | |
183 | 413 | // Nothing to describe without address or constant. |
184 | 413 | if (413 !Global && 413 (!Expr || 135 !Expr->isConstant()135 )) |
185 | 128 | continue; |
186 | 285 | |
187 | 285 | if (285 !Loc285 ) { |
188 | 280 | addToAccelTable = true; |
189 | 280 | Loc = new (DIEValueAllocator) DIELoc; |
190 | 280 | DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc); |
191 | 280 | } |
192 | 285 | |
193 | 285 | if (Global285 ) { |
194 | 278 | const MCSymbol *Sym = Asm->getSymbol(Global); |
195 | 278 | if (Global->isThreadLocal()278 ) { |
196 | 16 | if (Asm->TM.Options.EmulatedTLS16 ) { |
197 | 3 | // TODO: add debug info for emulated thread local mode. |
198 | 16 | } else { |
199 | 13 | // FIXME: Make this work with -gsplit-dwarf. |
200 | 13 | unsigned PointerSize = Asm->getDataLayout().getPointerSize(); |
201 | 13 | assert((PointerSize == 4 || PointerSize == 8) && |
202 | 13 | "Add support for other sizes if necessary"); |
203 | 13 | // Based on GCC's support for TLS: |
204 | 13 | if (!DD->useSplitDwarf()13 ) { |
205 | 11 | // 1) Start with a constNu of the appropriate pointer size |
206 | 11 | addUInt(*Loc, dwarf::DW_FORM_data1, |
207 | 4 | PointerSize == 4 ? dwarf::DW_OP_const4u |
208 | 7 | : dwarf::DW_OP_const8u); |
209 | 11 | // 2) containing the (relocated) offset of the TLS variable |
210 | 11 | // within the module's TLS block. |
211 | 11 | addExpr(*Loc, dwarf::DW_FORM_udata, |
212 | 11 | Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); |
213 | 13 | } else { |
214 | 2 | addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); |
215 | 2 | addUInt(*Loc, dwarf::DW_FORM_udata, |
216 | 2 | DD->getAddressPool().getIndex(Sym, /* TLS */ true)); |
217 | 2 | } |
218 | 13 | // 3) followed by an OP to make the debugger do a TLS lookup. |
219 | 13 | addUInt(*Loc, dwarf::DW_FORM_data1, |
220 | 7 | DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address |
221 | 6 | : dwarf::DW_OP_form_tls_address); |
222 | 13 | } |
223 | 278 | } else { |
224 | 262 | DD->addArangeLabel(SymbolCU(this, Sym)); |
225 | 262 | addOpAddress(*Loc, Sym); |
226 | 262 | } |
227 | 278 | } |
228 | 285 | if (Expr285 ) { |
229 | 285 | DwarfExpr->addFragmentOffset(Expr); |
230 | 285 | DwarfExpr->addExpression(Expr); |
231 | 285 | } |
232 | 416 | } |
233 | 414 | if (Loc) |
234 | 280 | addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize()); |
235 | 414 | |
236 | 414 | if (DD->useAllLinkageNames()) |
237 | 405 | addLinkageName(*VariableDIE, GV->getLinkageName()); |
238 | 414 | |
239 | 414 | if (addToAccelTable414 ) { |
240 | 282 | DD->addAccelName(GV->getName(), *VariableDIE); |
241 | 282 | |
242 | 282 | // If the linkage name is different than the name, go ahead and output |
243 | 282 | // that as well into the name table. |
244 | 282 | if (GV->getLinkageName() != "" && 282 GV->getName() != GV->getLinkageName()45 ) |
245 | 43 | DD->addAccelName(GV->getLinkageName(), *VariableDIE); |
246 | 282 | } |
247 | 417 | |
248 | 417 | return VariableDIE; |
249 | 417 | } |
250 | | |
251 | 9.36k | void DwarfCompileUnit::addRange(RangeSpan Range) { |
252 | 9.36k | bool SameAsPrevCU = this == DD->getPrevCU(); |
253 | 9.36k | DD->setPrevCU(this); |
254 | 9.36k | // If we have no current ranges just add the range and return, otherwise, |
255 | 9.36k | // check the current section and CU against the previous section and CU we |
256 | 9.36k | // emitted into and the subprogram was contained within. If these are the |
257 | 9.36k | // same then extend our current range, otherwise add this as a new range. |
258 | 9.36k | if (CURanges.empty() || 9.36k !SameAsPrevCU8.33k || |
259 | 8.32k | (&CURanges.back().getEnd()->getSection() != |
260 | 9.36k | &Range.getEnd()->getSection())) { |
261 | 1.06k | CURanges.push_back(Range); |
262 | 1.06k | return; |
263 | 1.06k | } |
264 | 8.29k | |
265 | 8.29k | CURanges.back().setEnd(Range.getEnd()); |
266 | 8.29k | } |
267 | | |
268 | 1.18k | void DwarfCompileUnit::initStmtList() { |
269 | 1.18k | // Define start line table label for each Compile Unit. |
270 | 1.18k | MCSymbol *LineTableStartSym = |
271 | 1.18k | Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID()); |
272 | 1.18k | |
273 | 1.18k | // DW_AT_stmt_list is a offset of line number information for this |
274 | 1.18k | // compile unit in debug_line section. For split dwarf this is |
275 | 1.18k | // left in the skeleton CU and so not included. |
276 | 1.18k | // The line table entries are not always emitted in assembly, so it |
277 | 1.18k | // is not okay to use line_table_start here. |
278 | 1.18k | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
279 | 1.18k | StmtListValue = |
280 | 1.18k | addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym, |
281 | 1.18k | TLOF.getDwarfLineSection()->getBeginSymbol()); |
282 | 1.18k | } |
283 | | |
284 | 17 | void DwarfCompileUnit::applyStmtList(DIE &D) { |
285 | 17 | D.addValue(DIEValueAllocator, *StmtListValue); |
286 | 17 | } |
287 | | |
288 | | void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, |
289 | 35.9k | const MCSymbol *End) { |
290 | 35.9k | assert(Begin && "Begin label should not be null!"); |
291 | 35.9k | assert(End && "End label should not be null!"); |
292 | 35.9k | assert(Begin->isDefined() && "Invalid starting label"); |
293 | 35.9k | assert(End->isDefined() && "Invalid end label"); |
294 | 35.9k | |
295 | 35.9k | addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); |
296 | 35.9k | if (DD->getDwarfVersion() < 4) |
297 | 34.6k | addLabelAddress(D, dwarf::DW_AT_high_pc, End); |
298 | 35.9k | else |
299 | 1.26k | addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); |
300 | 35.9k | } |
301 | | |
302 | | // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc |
303 | | // and DW_AT_high_pc attributes. If there are global variables in this |
304 | | // scope then create and insert DIEs for these variables. |
305 | 9.36k | DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { |
306 | 9.36k | DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); |
307 | 9.36k | |
308 | 9.36k | attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); |
309 | 9.36k | if (DD->useAppleExtensionAttributes() && |
310 | 9.03k | !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( |
311 | 9.03k | *DD->getCurrentFunction())) |
312 | 305 | addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr); |
313 | 9.36k | |
314 | 9.36k | // Only include DW_AT_frame_base in full debug info |
315 | 9.36k | if (!includeMinimalInlineScopes()9.36k ) { |
316 | 802 | const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); |
317 | 802 | MachineLocation Location(RI->getFrameRegister(*Asm->MF)); |
318 | 802 | if (RI->isPhysicalRegister(Location.getReg())) |
319 | 784 | addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); |
320 | 802 | } |
321 | 9.36k | |
322 | 9.36k | // Add name to the name table, we do this here because we're guaranteed |
323 | 9.36k | // to have concrete versions of our DW_TAG_subprogram nodes. |
324 | 9.36k | DD->addSubprogramNames(SP, *SPDie); |
325 | 9.36k | |
326 | 9.36k | return *SPDie; |
327 | 9.36k | } |
328 | | |
329 | | // Construct a DIE for this scope. |
330 | | void DwarfCompileUnit::constructScopeDIE( |
331 | 34.5k | LexicalScope *Scope, SmallVectorImpl<DIE *> &FinalChildren) { |
332 | 34.5k | if (!Scope || 34.5k !Scope->getScopeNode()34.5k ) |
333 | 0 | return; |
334 | 34.5k | |
335 | 34.5k | auto *DS = Scope->getScopeNode(); |
336 | 34.5k | |
337 | 34.5k | assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) && |
338 | 34.5k | "Only handle inlined subprograms here, use " |
339 | 34.5k | "constructSubprogramScopeDIE for non-inlined " |
340 | 34.5k | "subprograms"); |
341 | 34.5k | |
342 | 34.5k | SmallVector<DIE *, 8> Children; |
343 | 34.5k | |
344 | 34.5k | // We try to create the scope DIE first, then the children DIEs. This will |
345 | 34.5k | // avoid creating un-used children then removing them later when we find out |
346 | 34.5k | // the scope DIE is null. |
347 | 34.5k | DIE *ScopeDIE; |
348 | 34.5k | if (Scope->getParent() && 34.5k isa<DISubprogram>(DS)34.5k ) { |
349 | 34.1k | ScopeDIE = constructInlinedScopeDIE(Scope); |
350 | 34.1k | if (!ScopeDIE) |
351 | 0 | return; |
352 | 34.1k | // We create children when the scope DIE is not null. |
353 | 34.1k | createScopeChildrenDIE(Scope, Children); |
354 | 34.5k | } else { |
355 | 387 | // Early exit when we know the scope DIE is going to be null. |
356 | 387 | if (DD->isLexicalScopeDIENull(Scope)) |
357 | 0 | return; |
358 | 387 | |
359 | 387 | bool HasNonScopeChildren = false; |
360 | 387 | |
361 | 387 | // We create children here when we know the scope DIE is not going to be |
362 | 387 | // null and the children will be added to the scope DIE. |
363 | 387 | createScopeChildrenDIE(Scope, Children, &HasNonScopeChildren); |
364 | 387 | |
365 | 387 | // If there are only other scopes as children, put them directly in the |
366 | 387 | // parent instead, as this scope would serve no purpose. |
367 | 387 | if (!HasNonScopeChildren387 ) { |
368 | 297 | FinalChildren.insert(FinalChildren.end(), |
369 | 297 | std::make_move_iterator(Children.begin()), |
370 | 297 | std::make_move_iterator(Children.end())); |
371 | 297 | return; |
372 | 297 | } |
373 | 90 | ScopeDIE = constructLexicalScopeDIE(Scope); |
374 | 90 | assert(ScopeDIE && "Scope DIE should not be null."); |
375 | 90 | } |
376 | 34.5k | |
377 | 34.5k | // Add children |
378 | 34.2k | for (auto &I : Children) |
379 | 22.2k | ScopeDIE->addChild(std::move(I)); |
380 | 34.5k | |
381 | 34.5k | FinalChildren.push_back(std::move(ScopeDIE)); |
382 | 34.5k | } |
383 | | |
384 | | void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, |
385 | 8.68k | SmallVector<RangeSpan, 2> Range) { |
386 | 8.68k | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
387 | 8.68k | |
388 | 8.68k | // Emit offset in .debug_range as a relocatable label. emitDIE will handle |
389 | 8.68k | // emitting it appropriately. |
390 | 8.68k | const MCSymbol *RangeSectionSym = |
391 | 8.68k | TLOF.getDwarfRangesSection()->getBeginSymbol(); |
392 | 8.68k | |
393 | 8.68k | RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range)); |
394 | 8.68k | |
395 | 8.68k | // Under fission, ranges are specified by constant offsets relative to the |
396 | 8.68k | // CU's DW_AT_GNU_ranges_base. |
397 | 8.68k | if (isDwoUnit()) |
398 | 2 | addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), |
399 | 2 | RangeSectionSym); |
400 | 8.68k | else |
401 | 8.68k | addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), |
402 | 8.68k | RangeSectionSym); |
403 | 8.68k | |
404 | 8.68k | // Add the range list to the set of ranges to be emitted. |
405 | 8.68k | (Skeleton ? Skeleton2 : this8.68k )->CURangeLists.push_back(std::move(List)); |
406 | 8.68k | } |
407 | | |
408 | | void DwarfCompileUnit::attachRangesOrLowHighPC( |
409 | 35.2k | DIE &Die, SmallVector<RangeSpan, 2> Ranges) { |
410 | 35.2k | if (Ranges.size() == 135.2k ) { |
411 | 26.5k | const auto &single = Ranges.front(); |
412 | 26.5k | attachLowHighPC(Die, single.getStart(), single.getEnd()); |
413 | 26.5k | } else |
414 | 8.68k | addScopeRangeList(Die, std::move(Ranges)); |
415 | 35.2k | } |
416 | | |
417 | | void DwarfCompileUnit::attachRangesOrLowHighPC( |
418 | 34.2k | DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) { |
419 | 34.2k | SmallVector<RangeSpan, 2> List; |
420 | 34.2k | List.reserve(Ranges.size()); |
421 | 34.2k | for (const InsnRange &R : Ranges) |
422 | 45.8k | List.push_back(RangeSpan(DD->getLabelBeforeInsn(R.first), |
423 | 45.8k | DD->getLabelAfterInsn(R.second))); |
424 | 34.2k | attachRangesOrLowHighPC(Die, std::move(List)); |
425 | 34.2k | } |
426 | | |
427 | | // This scope represents inlined body of a function. Construct DIE to |
428 | | // represent this concrete inlined copy of the function. |
429 | 34.1k | DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) { |
430 | 34.1k | assert(Scope->getScopeNode()); |
431 | 34.1k | auto *DS = Scope->getScopeNode(); |
432 | 34.1k | auto *InlinedSP = getDISubprogram(DS); |
433 | 34.1k | // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram |
434 | 34.1k | // was inlined from another compile unit. |
435 | 34.1k | DIE *OriginDIE = getAbstractSPDies()[InlinedSP]; |
436 | 34.1k | assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); |
437 | 34.1k | |
438 | 34.1k | auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine); |
439 | 34.1k | addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); |
440 | 34.1k | |
441 | 34.1k | attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); |
442 | 34.1k | |
443 | 34.1k | // Add the call site information to the DIE. |
444 | 34.1k | const DILocation *IA = Scope->getInlinedAt(); |
445 | 34.1k | addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None, |
446 | 34.1k | getOrCreateSourceID(IA->getFilename(), IA->getDirectory())); |
447 | 34.1k | addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine()); |
448 | 34.1k | if (IA->getDiscriminator() && 34.1k DD->getDwarfVersion() >= 45 ) |
449 | 4 | addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None, |
450 | 4 | IA->getDiscriminator()); |
451 | 34.1k | |
452 | 34.1k | // Add name to the name table, we do this here because we're guaranteed |
453 | 34.1k | // to have concrete versions of our DW_TAG_inlined_subprogram nodes. |
454 | 34.1k | DD->addSubprogramNames(InlinedSP, *ScopeDIE); |
455 | 34.1k | |
456 | 34.1k | return ScopeDIE; |
457 | 34.1k | } |
458 | | |
459 | | // Construct new DW_TAG_lexical_block for this scope and attach |
460 | | // DW_AT_low_pc/DW_AT_high_pc labels. |
461 | 90 | DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { |
462 | 90 | if (DD->isLexicalScopeDIENull(Scope)) |
463 | 0 | return nullptr; |
464 | 90 | |
465 | 90 | auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); |
466 | 90 | if (Scope->isAbstractScope()) |
467 | 8 | return ScopeDIE; |
468 | 82 | |
469 | 82 | attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); |
470 | 82 | |
471 | 82 | return ScopeDIE; |
472 | 82 | } |
473 | | |
474 | | /// constructVariableDIE - Construct a DIE for the given DbgVariable. |
475 | 1.12k | DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) { |
476 | 1.12k | auto D = constructVariableDIEImpl(DV, Abstract); |
477 | 1.12k | DV.setDIE(*D); |
478 | 1.12k | return D; |
479 | 1.12k | } |
480 | | |
481 | | DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, |
482 | 1.12k | bool Abstract) { |
483 | 1.12k | // Define variable debug information entry. |
484 | 1.12k | auto VariableDie = DIE::get(DIEValueAllocator, DV.getTag()); |
485 | 1.12k | |
486 | 1.12k | if (Abstract1.12k ) { |
487 | 94 | applyVariableAttributes(DV, *VariableDie); |
488 | 94 | return VariableDie; |
489 | 94 | } |
490 | 1.03k | |
491 | 1.03k | // Add variable address. |
492 | 1.03k | |
493 | 1.03k | unsigned Offset = DV.getDebugLocListIndex(); |
494 | 1.03k | if (Offset != ~0U1.03k ) { |
495 | 322 | addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); |
496 | 322 | return VariableDie; |
497 | 322 | } |
498 | 713 | |
499 | 713 | // Check if variable is described by a DBG_VALUE instruction. |
500 | 713 | if (const MachineInstr *713 DVInsn713 = DV.getMInsn()) { |
501 | 114 | assert(DVInsn->getNumOperands() == 4); |
502 | 114 | if (DVInsn->getOperand(0).isReg()114 ) { |
503 | 75 | auto RegOp = DVInsn->getOperand(0); |
504 | 75 | auto Op1 = DVInsn->getOperand(1); |
505 | 75 | // If the second operand is an immediate, this is an indirect value. |
506 | 75 | assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); |
507 | 75 | MachineLocation Location(RegOp.getReg(), Op1.isImm()); |
508 | 75 | addVariableAddress(DV, *VariableDie, Location); |
509 | 114 | } else if (39 DVInsn->getOperand(0).isImm()39 ) { |
510 | 38 | // This variable is described by a single constant. |
511 | 38 | // Check whether it has a DIExpression. |
512 | 38 | auto *Expr = DV.getSingleExpression(); |
513 | 38 | if (Expr && 38 Expr->getNumElements()2 ) { |
514 | 2 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
515 | 2 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
516 | 2 | // If there is an expression, emit raw unsigned bytes. |
517 | 2 | DwarfExpr.addFragmentOffset(Expr); |
518 | 2 | DwarfExpr.addUnsignedConstant(DVInsn->getOperand(0).getImm()); |
519 | 2 | DwarfExpr.addExpression(Expr); |
520 | 2 | addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); |
521 | 2 | } else |
522 | 36 | addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType()); |
523 | 39 | } else if (1 DVInsn->getOperand(0).isFPImm()1 ) |
524 | 0 | addConstantFPValue(*VariableDie, DVInsn->getOperand(0)); |
525 | 1 | else if (1 DVInsn->getOperand(0).isCImm()1 ) |
526 | 1 | addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(), |
527 | 1 | DV.getType()); |
528 | 114 | |
529 | 114 | return VariableDie; |
530 | 114 | } |
531 | 599 | |
532 | 599 | // .. else use frame index. |
533 | 599 | if (599 !DV.hasFrameIndexExprs()599 ) |
534 | 80 | return VariableDie; |
535 | 519 | |
536 | 519 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
537 | 519 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
538 | 522 | for (auto &Fragment : DV.getFrameIndexExprs()) { |
539 | 522 | unsigned FrameReg = 0; |
540 | 522 | const DIExpression *Expr = Fragment.Expr; |
541 | 522 | const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); |
542 | 522 | int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg); |
543 | 522 | DwarfExpr.addFragmentOffset(Expr); |
544 | 522 | SmallVector<uint64_t, 8> Ops; |
545 | 522 | Ops.push_back(dwarf::DW_OP_plus_uconst); |
546 | 522 | Ops.push_back(Offset); |
547 | 522 | Ops.append(Expr->elements_begin(), Expr->elements_end()); |
548 | 522 | DIExpressionCursor Cursor(Ops); |
549 | 522 | DwarfExpr.setMemoryLocationKind(); |
550 | 522 | DwarfExpr.addMachineRegExpression( |
551 | 522 | *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg); |
552 | 522 | DwarfExpr.addExpression(std::move(Cursor)); |
553 | 522 | } |
554 | 1.12k | addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); |
555 | 1.12k | |
556 | 1.12k | return VariableDie; |
557 | 1.12k | } |
558 | | |
559 | | DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, |
560 | | const LexicalScope &Scope, |
561 | 1.12k | DIE *&ObjectPointer) { |
562 | 1.12k | auto Var = constructVariableDIE(DV, Scope.isAbstractScope()); |
563 | 1.12k | if (DV.isObjectPointer()) |
564 | 167 | ObjectPointer = Var; |
565 | 1.12k | return Var; |
566 | 1.12k | } |
567 | | |
568 | | DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope, |
569 | | SmallVectorImpl<DIE *> &Children, |
570 | 55.3k | bool *HasNonScopeChildren) { |
571 | 55.3k | assert(Children.empty()); |
572 | 55.3k | DIE *ObjectPointer = nullptr; |
573 | 55.3k | |
574 | 55.3k | for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope)) |
575 | 1.12k | Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer)); |
576 | 55.3k | |
577 | 55.3k | // Skip imported directives in gmlt-like data. |
578 | 55.3k | if (!includeMinimalInlineScopes()55.3k ) { |
579 | 1.34k | // There is no need to emit empty lexical block DIE. |
580 | 1.34k | for (const auto *IE : ImportedEntities[Scope->getScopeNode()]) |
581 | 19 | Children.push_back( |
582 | 19 | constructImportedEntityDIE(cast<DIImportedEntity>(IE))); |
583 | 1.34k | } |
584 | 55.3k | |
585 | 55.3k | if (HasNonScopeChildren) |
586 | 387 | *HasNonScopeChildren = !Children.empty(); |
587 | 55.3k | |
588 | 55.3k | for (LexicalScope *LS : Scope->getChildren()) |
589 | 34.5k | constructScopeDIE(LS, Children); |
590 | 55.3k | |
591 | 55.3k | return ObjectPointer; |
592 | 55.3k | } |
593 | | |
594 | 9.36k | void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) { |
595 | 9.36k | DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); |
596 | 9.36k | |
597 | 9.36k | if (Scope9.36k ) { |
598 | 9.32k | assert(!Scope->getInlinedAt()); |
599 | 9.32k | assert(!Scope->isAbstractScope()); |
600 | 9.32k | // Collect lexical scope children first. |
601 | 9.32k | // ObjectPointer might be a local (non-argument) local variable if it's a |
602 | 9.32k | // block's synthetic this pointer. |
603 | 9.32k | if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) |
604 | 128 | addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); |
605 | 9.32k | } |
606 | 9.36k | |
607 | 9.36k | // If this is a variadic function, add an unspecified parameter. |
608 | 9.36k | DITypeRefArray FnArgs = Sub->getType()->getTypeArray(); |
609 | 9.36k | |
610 | 9.36k | // If we have a single element of null, it is a function that returns void. |
611 | 9.36k | // If we have more than one elements and the last one is null, it is a |
612 | 9.36k | // variadic function. |
613 | 9.36k | if (FnArgs.size() > 1 && 9.36k !FnArgs[FnArgs.size() - 1]406 && |
614 | 3 | !includeMinimalInlineScopes()) |
615 | 2 | ScopeDIE.addChild( |
616 | 2 | DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters)); |
617 | 9.36k | } |
618 | | |
619 | | DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, |
620 | 20.8k | DIE &ScopeDIE) { |
621 | 20.8k | // We create children when the scope DIE is not null. |
622 | 20.8k | SmallVector<DIE *, 8> Children; |
623 | 20.8k | DIE *ObjectPointer = createScopeChildrenDIE(Scope, Children); |
624 | 20.8k | |
625 | 20.8k | // Add children |
626 | 20.8k | for (auto &I : Children) |
627 | 13.1k | ScopeDIE.addChild(std::move(I)); |
628 | 20.8k | |
629 | 20.8k | return ObjectPointer; |
630 | 20.8k | } |
631 | | |
632 | | void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( |
633 | 22.5k | LexicalScope *Scope) { |
634 | 22.5k | DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()]; |
635 | 22.5k | if (AbsDef) |
636 | 10.9k | return; |
637 | 11.5k | |
638 | 11.5k | auto *SP = cast<DISubprogram>(Scope->getScopeNode()); |
639 | 11.5k | |
640 | 11.5k | DIE *ContextDIE; |
641 | 11.5k | |
642 | 11.5k | if (includeMinimalInlineScopes()) |
643 | 11.4k | ContextDIE = &getUnitDie(); |
644 | 11.5k | // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with |
645 | 11.5k | // the important distinction that the debug node is not associated with the |
646 | 11.5k | // DIE (since the debug node will be associated with the concrete DIE, if |
647 | 11.5k | // any). It could be refactored to some common utility function. |
648 | 88 | else if (auto *88 SPDecl88 = SP->getDeclaration()) { |
649 | 28 | ContextDIE = &getUnitDie(); |
650 | 28 | getOrCreateSubprogramDIE(SPDecl); |
651 | 28 | } else |
652 | 60 | ContextDIE = getOrCreateContextDIE(resolve(SP->getScope())); |
653 | 11.5k | |
654 | 11.5k | // Passing null as the associated node because the abstract definition |
655 | 11.5k | // shouldn't be found by lookup. |
656 | 11.5k | AbsDef = &createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr); |
657 | 11.5k | applySubprogramAttributesToDefinition(SP, *AbsDef); |
658 | 11.5k | |
659 | 11.5k | if (!includeMinimalInlineScopes()) |
660 | 88 | addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); |
661 | 11.5k | if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, *AbsDef)) |
662 | 18 | addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); |
663 | 22.5k | } |
664 | | |
665 | | DIE *DwarfCompileUnit::constructImportedEntityDIE( |
666 | 36 | const DIImportedEntity *Module) { |
667 | 36 | DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag()); |
668 | 36 | insertDIE(Module, IMDie); |
669 | 36 | DIE *EntityDie; |
670 | 36 | auto *Entity = resolve(Module->getEntity()); |
671 | 36 | if (auto *NS = dyn_cast<DINamespace>(Entity)) |
672 | 12 | EntityDie = getOrCreateNameSpace(NS); |
673 | 24 | else if (auto *24 M24 = dyn_cast<DIModule>(Entity)) |
674 | 3 | EntityDie = getOrCreateModule(M); |
675 | 21 | else if (auto *21 SP21 = dyn_cast<DISubprogram>(Entity)) |
676 | 5 | EntityDie = getOrCreateSubprogramDIE(SP); |
677 | 16 | else if (auto *16 T16 = dyn_cast<DIType>(Entity)) |
678 | 9 | EntityDie = getOrCreateTypeDIE(T); |
679 | 7 | else if (auto *7 GV7 = dyn_cast<DIGlobalVariable>(Entity)) |
680 | 6 | EntityDie = getOrCreateGlobalVariableDIE(GV, {}); |
681 | 7 | else |
682 | 1 | EntityDie = getDIE(Entity); |
683 | 36 | assert(EntityDie); |
684 | 36 | auto *File = Module->getFile(); |
685 | 36 | addSourceLine(*IMDie, Module->getLine(), File ? File->getFilename()35 : ""1 , |
686 | 36 | File ? File->getDirectory()35 : ""1 ); |
687 | 36 | addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); |
688 | 36 | StringRef Name = Module->getName(); |
689 | 36 | if (!Name.empty()) |
690 | 3 | addString(*IMDie, dwarf::DW_AT_name, Name); |
691 | 36 | |
692 | 36 | return IMDie; |
693 | 36 | } |
694 | | |
695 | 9.38k | void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { |
696 | 9.38k | DIE *D = getDIE(SP); |
697 | 9.38k | if (DIE *AbsSPDIE9.38k = getAbstractSPDies().lookup(SP)) { |
698 | 1.54k | if (D) |
699 | 1.54k | // If this subprogram has an abstract definition, reference that |
700 | 1.54k | addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); |
701 | 9.38k | } else { |
702 | 7.84k | assert(D || includeMinimalInlineScopes()); |
703 | 7.84k | if (D) |
704 | 7.84k | // And attach the attributes |
705 | 7.81k | applySubprogramAttributesToDefinition(SP, *D); |
706 | 7.84k | } |
707 | 9.38k | } |
708 | | |
709 | 1.03k | void DwarfCompileUnit::finishVariableDefinition(const DbgVariable &Var) { |
710 | 1.03k | DbgVariable *AbsVar = getExistingAbstractVariable( |
711 | 1.03k | InlinedVariable(Var.getVariable(), Var.getInlinedAt())); |
712 | 1.03k | auto *VariableDie = Var.getDIE(); |
713 | 1.03k | if (AbsVar && 1.03k AbsVar->getDIE()107 ) { |
714 | 107 | addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, |
715 | 107 | *AbsVar->getDIE()); |
716 | 107 | } else |
717 | 928 | applyVariableAttributes(Var, *VariableDie); |
718 | 1.03k | } |
719 | | |
720 | 1.03k | DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(InlinedVariable IV) { |
721 | 1.03k | const DILocalVariable *Cleansed; |
722 | 1.03k | return getExistingAbstractVariable(IV, Cleansed); |
723 | 1.03k | } |
724 | | |
725 | | // Find abstract variable, if any, associated with Var. |
726 | | DbgVariable *DwarfCompileUnit::getExistingAbstractVariable( |
727 | 2.15k | InlinedVariable IV, const DILocalVariable *&Cleansed) { |
728 | 2.15k | // More then one inlined variable corresponds to one abstract variable. |
729 | 2.15k | Cleansed = IV.first; |
730 | 2.15k | auto &AbstractVariables = getAbstractVariables(); |
731 | 2.15k | auto I = AbstractVariables.find(Cleansed); |
732 | 2.15k | if (I != AbstractVariables.end()) |
733 | 184 | return I->second.get(); |
734 | 1.97k | return nullptr; |
735 | 1.97k | } |
736 | | |
737 | | void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var, |
738 | 94 | LexicalScope *Scope) { |
739 | 94 | assert(Scope && Scope->isAbstractScope()); |
740 | 94 | auto AbsDbgVariable = llvm::make_unique<DbgVariable>(Var, /* IA */ nullptr); |
741 | 94 | DU->addScopeVariable(Scope, AbsDbgVariable.get()); |
742 | 94 | getAbstractVariables()[Var] = std::move(AbsDbgVariable); |
743 | 94 | } |
744 | | |
745 | 1.20k | void DwarfCompileUnit::emitHeader(bool UseOffsets) { |
746 | 1.20k | // Don't bother labeling the .dwo unit, as its offset isn't used. |
747 | 1.20k | if (!Skeleton1.20k ) { |
748 | 1.18k | LabelBegin = Asm->createTempSymbol("cu_begin"); |
749 | 1.18k | Asm->OutStreamer->EmitLabel(LabelBegin); |
750 | 1.18k | } |
751 | 1.20k | |
752 | 28 | dwarf::UnitType UT = Skeleton ? dwarf::DW_UT_split_compile |
753 | 1.18k | : DD->useSplitDwarf() ? 1.18k dwarf::DW_UT_skeleton28 |
754 | 1.15k | : dwarf::DW_UT_compile; |
755 | 1.20k | DwarfUnit::emitCommonHeader(UseOffsets, UT); |
756 | 1.20k | } |
757 | | |
758 | 23.3k | bool DwarfCompileUnit::hasDwarfPubSections() const { |
759 | 23.3k | // Opting in to GNU Pubnames/types overrides the default to ensure these are |
760 | 23.3k | // generated for things like Gold's gdb_index generation. |
761 | 23.3k | if (CUNode->getGnuPubnames()) |
762 | 67 | return true; |
763 | 23.3k | |
764 | 23.3k | return DD->tuneForGDB() && 23.3k !includeMinimalInlineScopes()1.66k ; |
765 | 23.3k | } |
766 | | |
767 | | /// addGlobalName - Add a new global name to the compile unit. |
768 | | void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die, |
769 | 19.8k | const DIScope *Context) { |
770 | 19.8k | if (!hasDwarfPubSections()) |
771 | 19.1k | return; |
772 | 629 | std::string FullName = getParentContextString(Context) + Name.str(); |
773 | 629 | GlobalNames[FullName] = &Die; |
774 | 629 | } |
775 | | |
776 | | void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name, |
777 | 8 | const DIScope *Context) { |
778 | 8 | if (!hasDwarfPubSections()) |
779 | 0 | return; |
780 | 8 | std::string FullName = getParentContextString(Context) + Name.str(); |
781 | 8 | // Insert, allowing the entry to remain as-is if it's already present |
782 | 8 | // This way the CU-level type DIE is preferred over the "can't describe this |
783 | 8 | // type as a unit offset because it's not really in the CU at all, it's only |
784 | 8 | // in a type unit" |
785 | 8 | GlobalNames.insert(std::make_pair(std::move(FullName), &getUnitDie())); |
786 | 8 | } |
787 | | |
788 | | /// Add a new global type to the unit. |
789 | | void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die, |
790 | 1.11k | const DIScope *Context) { |
791 | 1.11k | if (!hasDwarfPubSections()) |
792 | 714 | return; |
793 | 399 | std::string FullName = getParentContextString(Context) + Ty->getName().str(); |
794 | 399 | GlobalTypes[FullName] = &Die; |
795 | 399 | } |
796 | | |
797 | | void DwarfCompileUnit::addGlobalTypeUnitType(const DIType *Ty, |
798 | 70 | const DIScope *Context) { |
799 | 70 | if (!hasDwarfPubSections()) |
800 | 0 | return; |
801 | 70 | std::string FullName = getParentContextString(Context) + Ty->getName().str(); |
802 | 70 | // Insert, allowing the entry to remain as-is if it's already present |
803 | 70 | // This way the CU-level type DIE is preferred over the "can't describe this |
804 | 70 | // type as a unit offset because it's not really in the CU at all, it's only |
805 | 70 | // in a type unit" |
806 | 70 | GlobalTypes.insert(std::make_pair(std::move(FullName), &getUnitDie())); |
807 | 70 | } |
808 | | |
809 | | /// addVariableAddress - Add DW_AT_location attribute for a |
810 | | /// DbgVariable based on provided MachineLocation. |
811 | | void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, |
812 | 75 | MachineLocation Location) { |
813 | 75 | if (DV.hasComplexAddress()) |
814 | 15 | addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); |
815 | 60 | else if (60 DV.isBlockByrefVariable()60 ) |
816 | 0 | addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); |
817 | 60 | else |
818 | 60 | addAddress(Die, dwarf::DW_AT_location, Location); |
819 | 75 | } |
820 | | |
821 | | /// Add an address attribute to a die based on the location provided. |
822 | | void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, |
823 | 844 | const MachineLocation &Location) { |
824 | 844 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
825 | 844 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
826 | 844 | if (Location.isIndirect()) |
827 | 5 | DwarfExpr.setMemoryLocationKind(); |
828 | 844 | |
829 | 844 | DIExpressionCursor Cursor({}); |
830 | 844 | const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); |
831 | 844 | if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) |
832 | 1 | return; |
833 | 843 | DwarfExpr.addExpression(std::move(Cursor)); |
834 | 843 | |
835 | 843 | // Now attach the location information to the DIE. |
836 | 843 | addBlock(Die, Attribute, DwarfExpr.finalize()); |
837 | 843 | } |
838 | | |
839 | | /// Start with the address based on the location provided, and generate the |
840 | | /// DWARF information necessary to find the actual variable given the extra |
841 | | /// address information encoded in the DbgVariable, starting from the starting |
842 | | /// location. Add the DWARF information to the die. |
843 | | void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, |
844 | | dwarf::Attribute Attribute, |
845 | 15 | const MachineLocation &Location) { |
846 | 15 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
847 | 15 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
848 | 15 | const DIExpression *DIExpr = DV.getSingleExpression(); |
849 | 15 | DwarfExpr.addFragmentOffset(DIExpr); |
850 | 15 | if (Location.isIndirect()) |
851 | 9 | DwarfExpr.setMemoryLocationKind(); |
852 | 15 | |
853 | 15 | DIExpressionCursor Cursor(DIExpr); |
854 | 15 | const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); |
855 | 15 | if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) |
856 | 0 | return; |
857 | 15 | DwarfExpr.addExpression(std::move(Cursor)); |
858 | 15 | |
859 | 15 | // Now attach the location information to the DIE. |
860 | 15 | addBlock(Die, Attribute, DwarfExpr.finalize()); |
861 | 15 | } |
862 | | |
863 | | /// Add a Dwarf loclistptr attribute data and value. |
864 | | void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, |
865 | 322 | unsigned Index) { |
866 | 276 | dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset |
867 | 46 | : dwarf::DW_FORM_data4; |
868 | 322 | Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index)); |
869 | 322 | } |
870 | | |
871 | | void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var, |
872 | 1.02k | DIE &VariableDie) { |
873 | 1.02k | StringRef Name = Var.getName(); |
874 | 1.02k | if (!Name.empty()) |
875 | 982 | addString(VariableDie, dwarf::DW_AT_name, Name); |
876 | 1.02k | const auto *DIVar = Var.getVariable(); |
877 | 1.02k | if (DIVar) |
878 | 1.02k | if (uint32_t 1.02k AlignInBytes1.02k = DIVar->getAlignInBytes()) |
879 | 2 | addUInt(VariableDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, |
880 | 2 | AlignInBytes); |
881 | 1.02k | |
882 | 1.02k | addSourceLine(VariableDie, DIVar); |
883 | 1.02k | addType(VariableDie, Var.getType()); |
884 | 1.02k | if (Var.isArtificial()) |
885 | 204 | addFlag(VariableDie, dwarf::DW_AT_artificial); |
886 | 1.02k | } |
887 | | |
888 | | /// Add a Dwarf expression attribute data and value. |
889 | | void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form, |
890 | 11 | const MCExpr *Expr) { |
891 | 11 | Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr)); |
892 | 11 | } |
893 | | |
894 | | void DwarfCompileUnit::applySubprogramAttributesToDefinition( |
895 | 19.3k | const DISubprogram *SP, DIE &SPDie) { |
896 | 19.3k | auto *SPDecl = SP->getDeclaration(); |
897 | 19.3k | auto *Context = resolve(SPDecl ? SPDecl->getScope()146 : SP->getScope()19.1k ); |
898 | 19.3k | applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes()); |
899 | 19.3k | addGlobalName(SP->getName(), SPDie, Context); |
900 | 19.3k | } |
901 | | |
902 | 142k | bool DwarfCompileUnit::isDwoUnit() const { |
903 | 1.09k | return DD->useSplitDwarf() && Skeleton; |
904 | 142k | } |
905 | | |
906 | 118k | bool DwarfCompileUnit::includeMinimalInlineScopes() const { |
907 | 118k | return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly || |
908 | 5.66k | (DD->useSplitDwarf() && 5.66k !Skeleton456 ); |
909 | 118k | } |