1 | //===- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Units ------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains support for constructing a dwarf compile unit. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "DwarfCompileUnit.h" |
14 | #include "AddressPool.h" |
15 | #include "DwarfExpression.h" |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/SmallString.h" |
18 | #include "llvm/BinaryFormat/Dwarf.h" |
19 | #include "llvm/CodeGen/AsmPrinter.h" |
20 | #include "llvm/CodeGen/DIE.h" |
21 | #include "llvm/CodeGen/MachineFunction.h" |
22 | #include "llvm/CodeGen/MachineInstr.h" |
23 | #include "llvm/CodeGen/TargetFrameLowering.h" |
24 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
25 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
26 | #include "llvm/IR/DataLayout.h" |
27 | #include "llvm/IR/DebugInfo.h" |
28 | #include "llvm/IR/GlobalVariable.h" |
29 | #include "llvm/MC/MCAsmInfo.h" |
30 | #include "llvm/MC/MCSection.h" |
31 | #include "llvm/MC/MCStreamer.h" |
32 | #include "llvm/MC/MCSymbol.h" |
33 | #include "llvm/MC/MCSymbolWasm.h" |
34 | #include "llvm/MC/MachineLocation.h" |
35 | #include "llvm/Support/CommandLine.h" |
36 | #include "llvm/Target/TargetLoweringObjectFile.h" |
37 | #include "llvm/Target/TargetMachine.h" |
38 | #include "llvm/Target/TargetOptions.h" |
39 | #include <iterator> |
40 | #include <optional> |
41 | #include <string> |
42 | #include <utility> |
43 | |
44 | using namespace llvm; |
45 | |
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 | |
60 | static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) { |
61 | |
62 | // According to DWARF Debugging Information Format Version 5, |
63 | // 3.1.2 Skeleton Compilation Unit Entries: |
64 | // "When generating a split DWARF object file (see Section 7.3.2 |
65 | // on page 187), the compilation unit in the .debug_info section |
66 | // is a "skeleton" compilation unit with the tag DW_TAG_skeleton_unit" |
67 | if (DW->getDwarfVersion() >= 5 && Kind == UnitKind::Skeleton) |
68 | return dwarf::DW_TAG_skeleton_unit; |
69 | |
70 | return dwarf::DW_TAG_compile_unit; |
71 | } |
72 | |
73 | DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, |
74 | AsmPrinter *A, DwarfDebug *DW, |
75 | DwarfFile *DWU, UnitKind Kind) |
76 | : DwarfUnit(GetCompileUnitType(Kind, DW), Node, A, DW, DWU, UID) { |
77 | insertDIE(Desc: Node, D: &getUnitDie()); |
78 | MacroLabelBegin = Asm->createTempSymbol(Name: "cu_macro_begin" ); |
79 | } |
80 | |
81 | /// addLabelAddress - Add a dwarf label attribute data and value using |
82 | /// DW_FORM_addr or DW_FORM_GNU_addr_index. |
83 | void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, |
84 | const MCSymbol *Label) { |
85 | if ((Skeleton || !DD->useSplitDwarf()) && Label) |
86 | DD->addArangeLabel(SCU: SymbolCU(this, Label)); |
87 | |
88 | // Don't use the address pool in non-fission or in the skeleton unit itself. |
89 | if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5) |
90 | return addLocalLabelAddress(Die, Attribute, Label); |
91 | |
92 | bool UseAddrOffsetFormOrExpressions = |
93 | DD->useAddrOffsetForm() || DD->useAddrOffsetExpressions(); |
94 | |
95 | const MCSymbol *Base = nullptr; |
96 | if (Label->isInSection() && UseAddrOffsetFormOrExpressions) |
97 | Base = DD->getSectionLabel(S: &Label->getSection()); |
98 | |
99 | if (!Base || Base == Label) { |
100 | unsigned idx = DD->getAddressPool().getIndex(Sym: Label); |
101 | addAttribute(Die, Attribute, |
102 | Form: DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx |
103 | : dwarf::DW_FORM_GNU_addr_index, |
104 | Value: DIEInteger(idx)); |
105 | return; |
106 | } |
107 | |
108 | // Could be extended to work with DWARFv4 Split DWARF if that's important for |
109 | // someone. In that case DW_FORM_data would be used. |
110 | assert(DD->getDwarfVersion() >= 5 && |
111 | "Addr+offset expressions are only valuable when using debug_addr (to " |
112 | "reduce relocations) available in DWARFv5 or higher" ); |
113 | if (DD->useAddrOffsetExpressions()) { |
114 | auto *Loc = new (DIEValueAllocator) DIEBlock(); |
115 | addPoolOpAddress(Die&: *Loc, Label); |
116 | addBlock(Die, Attribute, Form: dwarf::DW_FORM_exprloc, Block: Loc); |
117 | } else |
118 | addAttribute(Die, Attribute, Form: dwarf::DW_FORM_LLVM_addrx_offset, |
119 | Value: new (DIEValueAllocator) DIEAddrOffset( |
120 | DD->getAddressPool().getIndex(Sym: Base), Label, Base)); |
121 | } |
122 | |
123 | void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, |
124 | dwarf::Attribute Attribute, |
125 | const MCSymbol *Label) { |
126 | if (Label) |
127 | addAttribute(Die, Attribute, Form: dwarf::DW_FORM_addr, Value: DIELabel(Label)); |
128 | else |
129 | addAttribute(Die, Attribute, Form: dwarf::DW_FORM_addr, Value: DIEInteger(0)); |
130 | } |
131 | |
132 | unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) { |
133 | // If we print assembly, we can't separate .file entries according to |
134 | // compile units. Thus all files will belong to the default compile unit. |
135 | |
136 | // FIXME: add a better feature test than hasRawTextSupport. Even better, |
137 | // extend .file to support this. |
138 | unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID(); |
139 | if (!File) |
140 | return Asm->OutStreamer->emitDwarfFileDirective(FileNo: 0, Directory: "" , Filename: "" , Checksum: std::nullopt, |
141 | Source: std::nullopt, CUID); |
142 | |
143 | if (LastFile != File) { |
144 | LastFile = File; |
145 | LastFileID = Asm->OutStreamer->emitDwarfFileDirective( |
146 | FileNo: 0, Directory: File->getDirectory(), Filename: File->getFilename(), Checksum: DD->getMD5AsBytes(File), |
147 | Source: File->getSource(), CUID); |
148 | } |
149 | return LastFileID; |
150 | } |
151 | |
152 | DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( |
153 | const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) { |
154 | // Check for pre-existence. |
155 | if (DIE *Die = getDIE(D: GV)) |
156 | return Die; |
157 | |
158 | assert(GV); |
159 | |
160 | auto *GVContext = GV->getScope(); |
161 | const DIType *GTy = GV->getType(); |
162 | |
163 | auto *CB = GVContext ? dyn_cast<DICommonBlock>(Val: GVContext) : nullptr; |
164 | DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs) |
165 | : getOrCreateContextDIE(Ty: GVContext); |
166 | |
167 | // Add to map. |
168 | DIE *VariableDIE = &createAndAddDIE(Tag: GV->getTag(), Parent&: *ContextDIE, N: GV); |
169 | DIScope *DeclContext; |
170 | if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) { |
171 | DeclContext = SDMDecl->getScope(); |
172 | assert(SDMDecl->isStaticMember() && "Expected static member decl" ); |
173 | assert(GV->isDefinition()); |
174 | // We need the declaration DIE that is in the static member's class. |
175 | DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(DT: SDMDecl); |
176 | addDIEEntry(Die&: *VariableDIE, Attribute: dwarf::DW_AT_specification, Entry&: *VariableSpecDIE); |
177 | // If the global variable's type is different from the one in the class |
178 | // member type, assume that it's more specific and also emit it. |
179 | if (GTy != SDMDecl->getBaseType()) |
180 | addType(Entity&: *VariableDIE, Ty: GTy); |
181 | } else { |
182 | DeclContext = GV->getScope(); |
183 | // Add name and type. |
184 | StringRef DisplayName = GV->getDisplayName(); |
185 | if (!DisplayName.empty()) |
186 | addString(Die&: *VariableDIE, Attribute: dwarf::DW_AT_name, Str: GV->getDisplayName()); |
187 | if (GTy) |
188 | addType(Entity&: *VariableDIE, Ty: GTy); |
189 | |
190 | // Add scoping info. |
191 | if (!GV->isLocalToUnit()) |
192 | addFlag(Die&: *VariableDIE, Attribute: dwarf::DW_AT_external); |
193 | |
194 | // Add line number info. |
195 | addSourceLine(Die&: *VariableDIE, G: GV); |
196 | } |
197 | |
198 | if (!GV->isDefinition()) |
199 | addFlag(Die&: *VariableDIE, Attribute: dwarf::DW_AT_declaration); |
200 | else |
201 | addGlobalName(Name: GV->getName(), Die: *VariableDIE, Context: DeclContext); |
202 | |
203 | addAnnotation(Buffer&: *VariableDIE, Annotations: GV->getAnnotations()); |
204 | |
205 | if (uint32_t AlignInBytes = GV->getAlignInBytes()) |
206 | addUInt(Die&: *VariableDIE, Attribute: dwarf::DW_AT_alignment, Form: dwarf::DW_FORM_udata, |
207 | Integer: AlignInBytes); |
208 | |
209 | if (MDTuple *TP = GV->getTemplateParams()) |
210 | addTemplateParams(Buffer&: *VariableDIE, TParams: DINodeArray(TP)); |
211 | |
212 | // Add location. |
213 | addLocationAttribute(ToDIE: VariableDIE, GV, GlobalExprs); |
214 | |
215 | return VariableDIE; |
216 | } |
217 | |
218 | void DwarfCompileUnit::addLocationAttribute( |
219 | DIE *VariableDIE, const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) { |
220 | bool addToAccelTable = false; |
221 | DIELoc *Loc = nullptr; |
222 | std::optional<unsigned> NVPTXAddressSpace; |
223 | std::unique_ptr<DIEDwarfExpression> DwarfExpr; |
224 | for (const auto &GE : GlobalExprs) { |
225 | const GlobalVariable *Global = GE.Var; |
226 | const DIExpression *Expr = GE.Expr; |
227 | |
228 | // For compatibility with DWARF 3 and earlier, |
229 | // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) or |
230 | // DW_AT_location(DW_OP_consts, X, DW_OP_stack_value) becomes |
231 | // DW_AT_const_value(X). |
232 | if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) { |
233 | addToAccelTable = true; |
234 | addConstantValue( |
235 | Die&: *VariableDIE, |
236 | Unsigned: DIExpression::SignedOrUnsignedConstant::UnsignedConstant == |
237 | *Expr->isConstant(), |
238 | Val: Expr->getElement(I: 1)); |
239 | break; |
240 | } |
241 | |
242 | // We cannot describe the location of dllimport'd variables: the |
243 | // computation of their address requires loads from the IAT. |
244 | if (Global && Global->hasDLLImportStorageClass()) |
245 | continue; |
246 | |
247 | // Nothing to describe without address or constant. |
248 | if (!Global && (!Expr || !Expr->isConstant())) |
249 | continue; |
250 | |
251 | if (Global && Global->isThreadLocal() && |
252 | !Asm->getObjFileLowering().supportDebugThreadLocalLocation()) |
253 | continue; |
254 | |
255 | if (!Loc) { |
256 | addToAccelTable = true; |
257 | Loc = new (DIEValueAllocator) DIELoc; |
258 | DwarfExpr = std::make_unique<DIEDwarfExpression>(args&: *Asm, args&: *this, args&: *Loc); |
259 | } |
260 | |
261 | if (Expr) { |
262 | // According to |
263 | // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf |
264 | // cuda-gdb requires DW_AT_address_class for all variables to be able to |
265 | // correctly interpret address space of the variable address. |
266 | // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef |
267 | // sequence for the NVPTX + gdb target. |
268 | unsigned LocalNVPTXAddressSpace; |
269 | if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { |
270 | const DIExpression *NewExpr = |
271 | DIExpression::extractAddressClass(Expr, AddrClass&: LocalNVPTXAddressSpace); |
272 | if (NewExpr != Expr) { |
273 | Expr = NewExpr; |
274 | NVPTXAddressSpace = LocalNVPTXAddressSpace; |
275 | } |
276 | } |
277 | DwarfExpr->addFragmentOffset(Expr); |
278 | } |
279 | |
280 | if (Global) { |
281 | const MCSymbol *Sym = Asm->getSymbol(GV: Global); |
282 | // 16-bit platforms like MSP430 and AVR take this path, so sink this |
283 | // assert to platforms that use it. |
284 | auto GetPointerSizedFormAndOp = [this]() { |
285 | unsigned PointerSize = Asm->MAI->getCodePointerSize(); |
286 | assert((PointerSize == 4 || PointerSize == 8) && |
287 | "Add support for other sizes if necessary" ); |
288 | struct FormAndOp { |
289 | dwarf::Form Form; |
290 | dwarf::LocationAtom Op; |
291 | }; |
292 | return PointerSize == 4 |
293 | ? FormAndOp{.Form: dwarf::DW_FORM_data4, .Op: dwarf::DW_OP_const4u} |
294 | : FormAndOp{.Form: dwarf::DW_FORM_data8, .Op: dwarf::DW_OP_const8u}; |
295 | }; |
296 | if (Global->isThreadLocal()) { |
297 | if (Asm->TM.getTargetTriple().isWasm()) { |
298 | // FIXME This is not guaranteed, but in practice, in static linking, |
299 | // if present, __tls_base's index is 1. This doesn't hold for dynamic |
300 | // linking, so TLS variables used in dynamic linking won't have |
301 | // correct debug info for now. See |
302 | // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823 |
303 | addWasmRelocBaseGlobal(Loc, GlobalName: "__tls_base" , GlobalIndex: 1); |
304 | addOpAddress(Die&: *Loc, Sym); |
305 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_plus); |
306 | } else if (Asm->TM.useEmulatedTLS()) { |
307 | // TODO: add debug info for emulated thread local mode. |
308 | } else { |
309 | // FIXME: Make this work with -gsplit-dwarf. |
310 | // Based on GCC's support for TLS: |
311 | if (!DD->useSplitDwarf()) { |
312 | auto FormAndOp = GetPointerSizedFormAndOp(); |
313 | // 1) Start with a constNu of the appropriate pointer size |
314 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: FormAndOp.Op); |
315 | // 2) containing the (relocated) offset of the TLS variable |
316 | // within the module's TLS block. |
317 | addExpr(Die&: *Loc, Form: FormAndOp.Form, |
318 | Expr: Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); |
319 | } else { |
320 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_GNU_const_index); |
321 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_udata, |
322 | Integer: DD->getAddressPool().getIndex(Sym, /* TLS */ true)); |
323 | } |
324 | // 3) followed by an OP to make the debugger do a TLS lookup. |
325 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, |
326 | Integer: DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address |
327 | : dwarf::DW_OP_form_tls_address); |
328 | } |
329 | } else if (Asm->TM.getTargetTriple().isWasm() && |
330 | Asm->TM.getRelocationModel() == Reloc::PIC_) { |
331 | // FIXME This is not guaranteed, but in practice, if present, |
332 | // __memory_base's index is 1. See |
333 | // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823 |
334 | addWasmRelocBaseGlobal(Loc, GlobalName: "__memory_base" , GlobalIndex: 1); |
335 | addOpAddress(Die&: *Loc, Sym); |
336 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_plus); |
337 | } else if ((Asm->TM.getRelocationModel() == Reloc::RWPI || |
338 | Asm->TM.getRelocationModel() == Reloc::ROPI_RWPI) && |
339 | !Asm->getObjFileLowering() |
340 | .getKindForGlobal(GO: Global, TM: Asm->TM) |
341 | .isReadOnly()) { |
342 | auto FormAndOp = GetPointerSizedFormAndOp(); |
343 | // Constant |
344 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: FormAndOp.Op); |
345 | // Relocation offset |
346 | addExpr(Die&: *Loc, Form: FormAndOp.Form, |
347 | Expr: Asm->getObjFileLowering().getIndirectSymViaRWPI(Sym)); |
348 | // Base register |
349 | Register BaseReg = Asm->getObjFileLowering().getStaticBase(); |
350 | BaseReg = Asm->TM.getMCRegisterInfo()->getDwarfRegNum(RegNum: BaseReg, isEH: false); |
351 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_breg0 + BaseReg); |
352 | // Offset from base register |
353 | addSInt(Die&: *Loc, Form: dwarf::DW_FORM_sdata, Integer: 0); |
354 | // Operation |
355 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_plus); |
356 | } else { |
357 | DD->addArangeLabel(SCU: SymbolCU(this, Sym)); |
358 | addOpAddress(Die&: *Loc, Sym); |
359 | } |
360 | } |
361 | // Global variables attached to symbols are memory locations. |
362 | // It would be better if this were unconditional, but malformed input that |
363 | // mixes non-fragments and fragments for the same variable is too expensive |
364 | // to detect in the verifier. |
365 | if (DwarfExpr->isUnknownLocation()) |
366 | DwarfExpr->setMemoryLocationKind(); |
367 | DwarfExpr->addExpression(Expr); |
368 | } |
369 | if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { |
370 | // According to |
371 | // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf |
372 | // cuda-gdb requires DW_AT_address_class for all variables to be able to |
373 | // correctly interpret address space of the variable address. |
374 | const unsigned NVPTX_ADDR_global_space = 5; |
375 | addUInt(Die&: *VariableDIE, Attribute: dwarf::DW_AT_address_class, Form: dwarf::DW_FORM_data1, |
376 | Integer: NVPTXAddressSpace.value_or(u: NVPTX_ADDR_global_space)); |
377 | } |
378 | if (Loc) |
379 | addBlock(Die&: *VariableDIE, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr->finalize()); |
380 | |
381 | if (DD->useAllLinkageNames()) |
382 | addLinkageName(Die&: *VariableDIE, LinkageName: GV->getLinkageName()); |
383 | |
384 | if (addToAccelTable) { |
385 | DD->addAccelName(Unit: *this, NameTableKind: CUNode->getNameTableKind(), Name: GV->getName(), |
386 | Die: *VariableDIE); |
387 | |
388 | // If the linkage name is different than the name, go ahead and output |
389 | // that as well into the name table. |
390 | if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() && |
391 | DD->useAllLinkageNames()) |
392 | DD->addAccelName(Unit: *this, NameTableKind: CUNode->getNameTableKind(), Name: GV->getLinkageName(), |
393 | Die: *VariableDIE); |
394 | } |
395 | } |
396 | |
397 | DIE *DwarfCompileUnit::getOrCreateCommonBlock( |
398 | const DICommonBlock *CB, ArrayRef<GlobalExpr> GlobalExprs) { |
399 | // Check for pre-existence. |
400 | if (DIE *NDie = getDIE(D: CB)) |
401 | return NDie; |
402 | DIE *ContextDIE = getOrCreateContextDIE(Ty: CB->getScope()); |
403 | DIE &NDie = createAndAddDIE(Tag: dwarf::DW_TAG_common_block, Parent&: *ContextDIE, N: CB); |
404 | StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName(); |
405 | addString(Die&: NDie, Attribute: dwarf::DW_AT_name, Str: Name); |
406 | addGlobalName(Name, Die: NDie, Context: CB->getScope()); |
407 | if (CB->getFile()) |
408 | addSourceLine(Die&: NDie, Line: CB->getLineNo(), File: CB->getFile()); |
409 | if (DIGlobalVariable *V = CB->getDecl()) |
410 | getCU().addLocationAttribute(VariableDIE: &NDie, GV: V, GlobalExprs); |
411 | return &NDie; |
412 | } |
413 | |
414 | void DwarfCompileUnit::addRange(RangeSpan Range) { |
415 | DD->insertSectionLabel(S: Range.Begin); |
416 | |
417 | auto *PrevCU = DD->getPrevCU(); |
418 | bool SameAsPrevCU = this == PrevCU; |
419 | DD->setPrevCU(this); |
420 | // If we have no current ranges just add the range and return, otherwise, |
421 | // check the current section and CU against the previous section and CU we |
422 | // emitted into and the subprogram was contained within. If these are the |
423 | // same then extend our current range, otherwise add this as a new range. |
424 | if (CURanges.empty() || !SameAsPrevCU || |
425 | (&CURanges.back().End->getSection() != |
426 | &Range.End->getSection())) { |
427 | // Before a new range is added, always terminate the prior line table. |
428 | if (PrevCU) |
429 | DD->terminateLineTable(CU: PrevCU); |
430 | CURanges.push_back(Elt: Range); |
431 | return; |
432 | } |
433 | |
434 | CURanges.back().End = Range.End; |
435 | } |
436 | |
437 | void DwarfCompileUnit::initStmtList() { |
438 | if (CUNode->isDebugDirectivesOnly()) |
439 | return; |
440 | |
441 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
442 | if (DD->useSectionsAsReferences()) { |
443 | LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol(); |
444 | } else { |
445 | LineTableStartSym = |
446 | Asm->OutStreamer->getDwarfLineTableSymbol(CUID: getUniqueID()); |
447 | } |
448 | |
449 | // DW_AT_stmt_list is a offset of line number information for this |
450 | // compile unit in debug_line section. For split dwarf this is |
451 | // left in the skeleton CU and so not included. |
452 | // The line table entries are not always emitted in assembly, so it |
453 | // is not okay to use line_table_start here. |
454 | addSectionLabel(Die&: getUnitDie(), Attribute: dwarf::DW_AT_stmt_list, Label: LineTableStartSym, |
455 | Sec: TLOF.getDwarfLineSection()->getBeginSymbol()); |
456 | } |
457 | |
458 | void DwarfCompileUnit::applyStmtList(DIE &D) { |
459 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
460 | addSectionLabel(Die&: D, Attribute: dwarf::DW_AT_stmt_list, Label: LineTableStartSym, |
461 | Sec: TLOF.getDwarfLineSection()->getBeginSymbol()); |
462 | } |
463 | |
464 | void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, |
465 | const MCSymbol *End) { |
466 | assert(Begin && "Begin label should not be null!" ); |
467 | assert(End && "End label should not be null!" ); |
468 | assert(Begin->isDefined() && "Invalid starting label" ); |
469 | assert(End->isDefined() && "Invalid end label" ); |
470 | |
471 | addLabelAddress(Die&: D, Attribute: dwarf::DW_AT_low_pc, Label: Begin); |
472 | if (DD->getDwarfVersion() < 4) |
473 | addLabelAddress(Die&: D, Attribute: dwarf::DW_AT_high_pc, Label: End); |
474 | else |
475 | addLabelDelta(Die&: D, Attribute: dwarf::DW_AT_high_pc, Hi: End, Lo: Begin); |
476 | } |
477 | |
478 | // Add info for Wasm-global-based relocation. |
479 | // 'GlobalIndex' is used for split dwarf, which currently relies on a few |
480 | // assumptions that are not guaranteed in a formal way but work in practice. |
481 | void DwarfCompileUnit::addWasmRelocBaseGlobal(DIELoc *Loc, StringRef GlobalName, |
482 | uint64_t GlobalIndex) { |
483 | // FIXME: duplicated from Target/WebAssembly/WebAssembly.h |
484 | // don't want to depend on target specific headers in this code? |
485 | const unsigned TI_GLOBAL_RELOC = 3; |
486 | unsigned PointerSize = Asm->getDataLayout().getPointerSize(); |
487 | auto *Sym = cast<MCSymbolWasm>(Val: Asm->GetExternalSymbolSymbol(Sym: GlobalName)); |
488 | // FIXME: this repeats what WebAssemblyMCInstLower:: |
489 | // GetExternalSymbolSymbol does, since if there's no code that |
490 | // refers to this symbol, we have to set it here. |
491 | Sym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); |
492 | Sym->setGlobalType(wasm::WasmGlobalType{ |
493 | .Type: static_cast<uint8_t>(PointerSize == 4 ? wasm::WASM_TYPE_I32 |
494 | : wasm::WASM_TYPE_I64), |
495 | .Mutable: true}); |
496 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_WASM_location); |
497 | addSInt(Die&: *Loc, Form: dwarf::DW_FORM_sdata, Integer: TI_GLOBAL_RELOC); |
498 | if (!isDwoUnit()) { |
499 | addLabel(Die&: *Loc, Form: dwarf::DW_FORM_data4, Label: Sym); |
500 | } else { |
501 | // FIXME: when writing dwo, we need to avoid relocations. Probably |
502 | // the "right" solution is to treat globals the way func and data |
503 | // symbols are (with entries in .debug_addr). |
504 | // For now we hardcode the indices in the callsites. Global indices are not |
505 | // fixed, but in practice a few are fixed; for example, __stack_pointer is |
506 | // always index 0. |
507 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data4, Integer: GlobalIndex); |
508 | } |
509 | } |
510 | |
511 | // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc |
512 | // and DW_AT_high_pc attributes. If there are global variables in this |
513 | // scope then create and insert DIEs for these variables. |
514 | DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { |
515 | DIE *SPDie = getOrCreateSubprogramDIE(SP, Minimal: includeMinimalInlineScopes()); |
516 | SmallVector<RangeSpan, 2> BB_List; |
517 | // If basic block sections are on, ranges for each basic block section has |
518 | // to be emitted separately. |
519 | for (const auto &R : Asm->MBBSectionRanges) |
520 | BB_List.push_back(Elt: {.Begin: R.second.BeginLabel, .End: R.second.EndLabel}); |
521 | |
522 | attachRangesOrLowHighPC(D&: *SPDie, Ranges: BB_List); |
523 | |
524 | if (DD->useAppleExtensionAttributes() && |
525 | !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( |
526 | MF: *DD->getCurrentFunction())) |
527 | addFlag(Die&: *SPDie, Attribute: dwarf::DW_AT_APPLE_omit_frame_ptr); |
528 | |
529 | // Only include DW_AT_frame_base in full debug info |
530 | if (!includeMinimalInlineScopes()) { |
531 | const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); |
532 | TargetFrameLowering::DwarfFrameBase FrameBase = |
533 | TFI->getDwarfFrameBase(MF: *Asm->MF); |
534 | switch (FrameBase.Kind) { |
535 | case TargetFrameLowering::DwarfFrameBase::Register: { |
536 | if (Register::isPhysicalRegister(Reg: FrameBase.Location.Reg)) { |
537 | MachineLocation Location(FrameBase.Location.Reg); |
538 | addAddress(Die&: *SPDie, Attribute: dwarf::DW_AT_frame_base, Location); |
539 | } |
540 | break; |
541 | } |
542 | case TargetFrameLowering::DwarfFrameBase::CFA: { |
543 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
544 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_call_frame_cfa); |
545 | if (FrameBase.Location.Offset != 0) { |
546 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_consts); |
547 | addSInt(Die&: *Loc, Form: dwarf::DW_FORM_sdata, Integer: FrameBase.Location.Offset); |
548 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_plus); |
549 | } |
550 | addBlock(Die&: *SPDie, Attribute: dwarf::DW_AT_frame_base, Loc); |
551 | break; |
552 | } |
553 | case TargetFrameLowering::DwarfFrameBase::WasmFrameBase: { |
554 | // FIXME: duplicated from Target/WebAssembly/WebAssembly.h |
555 | const unsigned TI_GLOBAL_RELOC = 3; |
556 | if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC) { |
557 | // These need to be relocatable. |
558 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
559 | assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far. |
560 | // For now, since we only ever use index 0, this should work as-is. |
561 | addWasmRelocBaseGlobal(Loc, GlobalName: "__stack_pointer" , |
562 | GlobalIndex: FrameBase.Location.WasmLoc.Index); |
563 | addUInt(Block&: *Loc, Form: dwarf::DW_FORM_data1, Integer: dwarf::DW_OP_stack_value); |
564 | addBlock(Die&: *SPDie, Attribute: dwarf::DW_AT_frame_base, Loc); |
565 | } else { |
566 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
567 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
568 | DIExpressionCursor Cursor({}); |
569 | DwarfExpr.addWasmLocation(Index: FrameBase.Location.WasmLoc.Kind, |
570 | Offset: FrameBase.Location.WasmLoc.Index); |
571 | DwarfExpr.addExpression(Expr: std::move(Cursor)); |
572 | addBlock(Die&: *SPDie, Attribute: dwarf::DW_AT_frame_base, Loc: DwarfExpr.finalize()); |
573 | } |
574 | break; |
575 | } |
576 | } |
577 | } |
578 | |
579 | // Add name to the name table, we do this here because we're guaranteed |
580 | // to have concrete versions of our DW_TAG_subprogram nodes. |
581 | DD->addSubprogramNames(Unit: *this, NameTableKind: CUNode->getNameTableKind(), SP, Die&: *SPDie); |
582 | |
583 | return *SPDie; |
584 | } |
585 | |
586 | // Construct a DIE for this scope. |
587 | void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope, |
588 | DIE &ParentScopeDIE) { |
589 | if (!Scope || !Scope->getScopeNode()) |
590 | return; |
591 | |
592 | auto *DS = Scope->getScopeNode(); |
593 | |
594 | assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) && |
595 | "Only handle inlined subprograms here, use " |
596 | "constructSubprogramScopeDIE for non-inlined " |
597 | "subprograms" ); |
598 | |
599 | // Emit inlined subprograms. |
600 | if (Scope->getParent() && isa<DISubprogram>(Val: DS)) { |
601 | DIE *ScopeDIE = constructInlinedScopeDIE(Scope, ParentScopeDIE); |
602 | assert(ScopeDIE && "Scope DIE should not be null." ); |
603 | createAndAddScopeChildren(Scope, ScopeDIE&: *ScopeDIE); |
604 | return; |
605 | } |
606 | |
607 | // Early exit when we know the scope DIE is going to be null. |
608 | if (DD->isLexicalScopeDIENull(Scope)) |
609 | return; |
610 | |
611 | // Emit lexical blocks. |
612 | DIE *ScopeDIE = constructLexicalScopeDIE(Scope); |
613 | assert(ScopeDIE && "Scope DIE should not be null." ); |
614 | |
615 | ParentScopeDIE.addChild(Child: ScopeDIE); |
616 | createAndAddScopeChildren(Scope, ScopeDIE&: *ScopeDIE); |
617 | } |
618 | |
619 | void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, |
620 | SmallVector<RangeSpan, 2> Range) { |
621 | |
622 | HasRangeLists = true; |
623 | |
624 | // Add the range list to the set of ranges to be emitted. |
625 | auto IndexAndList = |
626 | (DD->getDwarfVersion() < 5 && Skeleton ? Skeleton->DU : DU) |
627 | ->addRange(CU: *(Skeleton ? Skeleton : this), R: std::move(Range)); |
628 | |
629 | uint32_t Index = IndexAndList.first; |
630 | auto &List = *IndexAndList.second; |
631 | |
632 | // Under fission, ranges are specified by constant offsets relative to the |
633 | // CU's DW_AT_GNU_ranges_base. |
634 | // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under |
635 | // fission until we support the forms using the .debug_addr section |
636 | // (DW_RLE_startx_endx etc.). |
637 | if (DD->getDwarfVersion() >= 5) |
638 | addUInt(Die&: ScopeDIE, Attribute: dwarf::DW_AT_ranges, Form: dwarf::DW_FORM_rnglistx, Integer: Index); |
639 | else { |
640 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
641 | const MCSymbol *RangeSectionSym = |
642 | TLOF.getDwarfRangesSection()->getBeginSymbol(); |
643 | if (isDwoUnit()) |
644 | addSectionDelta(Die&: ScopeDIE, Attribute: dwarf::DW_AT_ranges, Hi: List.Label, |
645 | Lo: RangeSectionSym); |
646 | else |
647 | addSectionLabel(Die&: ScopeDIE, Attribute: dwarf::DW_AT_ranges, Label: List.Label, |
648 | Sec: RangeSectionSym); |
649 | } |
650 | } |
651 | |
652 | void DwarfCompileUnit::attachRangesOrLowHighPC( |
653 | DIE &Die, SmallVector<RangeSpan, 2> Ranges) { |
654 | assert(!Ranges.empty()); |
655 | if (!DD->useRangesSection() || |
656 | (Ranges.size() == 1 && |
657 | (!DD->alwaysUseRanges(*this) || |
658 | DD->getSectionLabel(S: &Ranges.front().Begin->getSection()) == |
659 | Ranges.front().Begin))) { |
660 | const RangeSpan &Front = Ranges.front(); |
661 | const RangeSpan &Back = Ranges.back(); |
662 | attachLowHighPC(D&: Die, Begin: Front.Begin, End: Back.End); |
663 | } else |
664 | addScopeRangeList(ScopeDIE&: Die, Range: std::move(Ranges)); |
665 | } |
666 | |
667 | void DwarfCompileUnit::attachRangesOrLowHighPC( |
668 | DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) { |
669 | SmallVector<RangeSpan, 2> List; |
670 | List.reserve(N: Ranges.size()); |
671 | for (const InsnRange &R : Ranges) { |
672 | auto *BeginLabel = DD->getLabelBeforeInsn(MI: R.first); |
673 | auto *EndLabel = DD->getLabelAfterInsn(MI: R.second); |
674 | |
675 | const auto *BeginMBB = R.first->getParent(); |
676 | const auto *EndMBB = R.second->getParent(); |
677 | |
678 | const auto *MBB = BeginMBB; |
679 | // Basic block sections allows basic block subsets to be placed in unique |
680 | // sections. For each section, the begin and end label must be added to the |
681 | // list. If there is more than one range, debug ranges must be used. |
682 | // Otherwise, low/high PC can be used. |
683 | // FIXME: Debug Info Emission depends on block order and this assumes that |
684 | // the order of blocks will be frozen beyond this point. |
685 | do { |
686 | if (MBB->sameSection(MBB: EndMBB) || MBB->isEndSection()) { |
687 | auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionID()]; |
688 | List.push_back( |
689 | Elt: {.Begin: MBB->sameSection(MBB: BeginMBB) ? BeginLabel |
690 | : MBBSectionRange.BeginLabel, |
691 | .End: MBB->sameSection(MBB: EndMBB) ? EndLabel : MBBSectionRange.EndLabel}); |
692 | } |
693 | if (MBB->sameSection(MBB: EndMBB)) |
694 | break; |
695 | MBB = MBB->getNextNode(); |
696 | } while (true); |
697 | } |
698 | attachRangesOrLowHighPC(Die, Ranges: std::move(List)); |
699 | } |
700 | |
701 | DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, |
702 | DIE &ParentScopeDIE) { |
703 | assert(Scope->getScopeNode()); |
704 | auto *DS = Scope->getScopeNode(); |
705 | auto *InlinedSP = getDISubprogram(Scope: DS); |
706 | // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram |
707 | // was inlined from another compile unit. |
708 | DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP]; |
709 | assert(OriginDIE && "Unable to find original DIE for an inlined subprogram." ); |
710 | |
711 | auto ScopeDIE = DIE::get(Alloc&: DIEValueAllocator, Tag: dwarf::DW_TAG_inlined_subroutine); |
712 | ParentScopeDIE.addChild(Child: ScopeDIE); |
713 | addDIEEntry(Die&: *ScopeDIE, Attribute: dwarf::DW_AT_abstract_origin, Entry&: *OriginDIE); |
714 | |
715 | attachRangesOrLowHighPC(Die&: *ScopeDIE, Ranges: Scope->getRanges()); |
716 | |
717 | // Add the call site information to the DIE. |
718 | const DILocation *IA = Scope->getInlinedAt(); |
719 | addUInt(Die&: *ScopeDIE, Attribute: dwarf::DW_AT_call_file, Form: std::nullopt, |
720 | Integer: getOrCreateSourceID(File: IA->getFile())); |
721 | addUInt(Die&: *ScopeDIE, Attribute: dwarf::DW_AT_call_line, Form: std::nullopt, Integer: IA->getLine()); |
722 | if (IA->getColumn()) |
723 | addUInt(Die&: *ScopeDIE, Attribute: dwarf::DW_AT_call_column, Form: std::nullopt, Integer: IA->getColumn()); |
724 | if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4) |
725 | addUInt(Die&: *ScopeDIE, Attribute: dwarf::DW_AT_GNU_discriminator, Form: std::nullopt, |
726 | Integer: IA->getDiscriminator()); |
727 | |
728 | // Add name to the name table, we do this here because we're guaranteed |
729 | // to have concrete versions of our DW_TAG_inlined_subprogram nodes. |
730 | DD->addSubprogramNames(Unit: *this, NameTableKind: CUNode->getNameTableKind(), SP: InlinedSP, |
731 | Die&: *ScopeDIE); |
732 | |
733 | return ScopeDIE; |
734 | } |
735 | |
736 | // Construct new DW_TAG_lexical_block for this scope and attach |
737 | // DW_AT_low_pc/DW_AT_high_pc labels. |
738 | DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { |
739 | if (DD->isLexicalScopeDIENull(Scope)) |
740 | return nullptr; |
741 | const auto *DS = Scope->getScopeNode(); |
742 | |
743 | auto ScopeDIE = DIE::get(Alloc&: DIEValueAllocator, Tag: dwarf::DW_TAG_lexical_block); |
744 | if (Scope->isAbstractScope()) { |
745 | assert(!getAbstractScopeDIEs().count(DS) && |
746 | "Abstract DIE for this scope exists!" ); |
747 | getAbstractScopeDIEs()[DS] = ScopeDIE; |
748 | return ScopeDIE; |
749 | } |
750 | if (!Scope->getInlinedAt()) { |
751 | assert(!LexicalBlockDIEs.count(DS) && |
752 | "Concrete out-of-line DIE for this scope exists!" ); |
753 | LexicalBlockDIEs[DS] = ScopeDIE; |
754 | } |
755 | |
756 | attachRangesOrLowHighPC(Die&: *ScopeDIE, Ranges: Scope->getRanges()); |
757 | |
758 | return ScopeDIE; |
759 | } |
760 | |
761 | DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) { |
762 | auto *VariableDie = DIE::get(Alloc&: DIEValueAllocator, Tag: DV.getTag()); |
763 | insertDIE(Desc: DV.getVariable(), D: VariableDie); |
764 | DV.setDIE(*VariableDie); |
765 | // Abstract variables don't get common attributes later, so apply them now. |
766 | if (Abstract) { |
767 | applyCommonDbgVariableAttributes(Var: DV, VariableDie&: *VariableDie); |
768 | } else { |
769 | std::visit( |
770 | visitor: [&](const auto &V) { |
771 | applyConcreteDbgVariableAttributes(V, DV, *VariableDie); |
772 | }, |
773 | variants&: DV.asVariant()); |
774 | } |
775 | return VariableDie; |
776 | } |
777 | |
778 | void DwarfCompileUnit::applyConcreteDbgVariableAttributes( |
779 | const Loc::Single &Single, const DbgVariable &DV, DIE &VariableDie) { |
780 | const DbgValueLoc *DVal = &Single.getValueLoc(); |
781 | if (!DVal->isVariadic()) { |
782 | const DbgValueLocEntry *Entry = DVal->getLocEntries().begin(); |
783 | if (Entry->isLocation()) { |
784 | addVariableAddress(DV, Die&: VariableDie, Location: Entry->getLoc()); |
785 | } else if (Entry->isInt()) { |
786 | auto *Expr = Single.getExpr(); |
787 | if (Expr && Expr->getNumElements()) { |
788 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
789 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
790 | // If there is an expression, emit raw unsigned bytes. |
791 | DwarfExpr.addFragmentOffset(Expr); |
792 | DwarfExpr.addUnsignedConstant(Value: Entry->getInt()); |
793 | DwarfExpr.addExpression(Expr); |
794 | addBlock(Die&: VariableDie, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr.finalize()); |
795 | if (DwarfExpr.TagOffset) |
796 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_LLVM_tag_offset, |
797 | Form: dwarf::DW_FORM_data1, Integer: *DwarfExpr.TagOffset); |
798 | } else |
799 | addConstantValue(Die&: VariableDie, Val: Entry->getInt(), Ty: DV.getType()); |
800 | } else if (Entry->isConstantFP()) { |
801 | addConstantFPValue(Die&: VariableDie, CFP: Entry->getConstantFP()); |
802 | } else if (Entry->isConstantInt()) { |
803 | addConstantValue(Die&: VariableDie, CI: Entry->getConstantInt(), Ty: DV.getType()); |
804 | } else if (Entry->isTargetIndexLocation()) { |
805 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
806 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
807 | const DIBasicType *BT = dyn_cast<DIBasicType>( |
808 | Val: static_cast<const Metadata *>(DV.getVariable()->getType())); |
809 | DwarfDebug::emitDebugLocValue(AP: *Asm, BT, Value: *DVal, DwarfExpr); |
810 | addBlock(Die&: VariableDie, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr.finalize()); |
811 | } |
812 | return; |
813 | } |
814 | // If any of the location entries are registers with the value 0, |
815 | // then the location is undefined. |
816 | if (any_of(Range: DVal->getLocEntries(), P: [](const DbgValueLocEntry &Entry) { |
817 | return Entry.isLocation() && !Entry.getLoc().getReg(); |
818 | })) |
819 | return; |
820 | const DIExpression *Expr = Single.getExpr(); |
821 | assert(Expr && "Variadic Debug Value must have an Expression." ); |
822 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
823 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
824 | DwarfExpr.addFragmentOffset(Expr); |
825 | DIExpressionCursor Cursor(Expr); |
826 | const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); |
827 | |
828 | auto AddEntry = [&](const DbgValueLocEntry &Entry, |
829 | DIExpressionCursor &Cursor) { |
830 | if (Entry.isLocation()) { |
831 | if (!DwarfExpr.addMachineRegExpression(TRI, Expr&: Cursor, |
832 | MachineReg: Entry.getLoc().getReg())) |
833 | return false; |
834 | } else if (Entry.isInt()) { |
835 | // If there is an expression, emit raw unsigned bytes. |
836 | DwarfExpr.addUnsignedConstant(Value: Entry.getInt()); |
837 | } else if (Entry.isConstantFP()) { |
838 | // DwarfExpression does not support arguments wider than 64 bits |
839 | // (see PR52584). |
840 | // TODO: Consider chunking expressions containing overly wide |
841 | // arguments into separate pointer-sized fragment expressions. |
842 | APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt(); |
843 | if (RawBytes.getBitWidth() > 64) |
844 | return false; |
845 | DwarfExpr.addUnsignedConstant(Value: RawBytes.getZExtValue()); |
846 | } else if (Entry.isConstantInt()) { |
847 | APInt RawBytes = Entry.getConstantInt()->getValue(); |
848 | if (RawBytes.getBitWidth() > 64) |
849 | return false; |
850 | DwarfExpr.addUnsignedConstant(Value: RawBytes.getZExtValue()); |
851 | } else if (Entry.isTargetIndexLocation()) { |
852 | TargetIndexLocation Loc = Entry.getTargetIndexLocation(); |
853 | // TODO TargetIndexLocation is a target-independent. Currently |
854 | // only the WebAssembly-specific encoding is supported. |
855 | assert(Asm->TM.getTargetTriple().isWasm()); |
856 | DwarfExpr.addWasmLocation(Index: Loc.Index, Offset: static_cast<uint64_t>(Loc.Offset)); |
857 | } else { |
858 | llvm_unreachable("Unsupported Entry type." ); |
859 | } |
860 | return true; |
861 | }; |
862 | |
863 | if (!DwarfExpr.addExpression( |
864 | Expr: std::move(Cursor), |
865 | InsertArg: [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool { |
866 | return AddEntry(DVal->getLocEntries()[Idx], Cursor); |
867 | })) |
868 | return; |
869 | |
870 | // Now attach the location information to the DIE. |
871 | addBlock(Die&: VariableDie, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr.finalize()); |
872 | if (DwarfExpr.TagOffset) |
873 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_LLVM_tag_offset, Form: dwarf::DW_FORM_data1, |
874 | Integer: *DwarfExpr.TagOffset); |
875 | } |
876 | |
877 | void DwarfCompileUnit::applyConcreteDbgVariableAttributes( |
878 | const Loc::Multi &Multi, const DbgVariable &DV, DIE &VariableDie) { |
879 | addLocationList(Die&: VariableDie, Attribute: dwarf::DW_AT_location, |
880 | Index: Multi.getDebugLocListIndex()); |
881 | auto TagOffset = Multi.getDebugLocListTagOffset(); |
882 | if (TagOffset) |
883 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_LLVM_tag_offset, Form: dwarf::DW_FORM_data1, |
884 | Integer: *TagOffset); |
885 | } |
886 | |
887 | void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, |
888 | const DbgVariable &DV, |
889 | DIE &VariableDie) { |
890 | std::optional<unsigned> NVPTXAddressSpace; |
891 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
892 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
893 | for (const auto &Fragment : MMI.getFrameIndexExprs()) { |
894 | Register FrameReg; |
895 | const DIExpression *Expr = Fragment.Expr; |
896 | const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); |
897 | StackOffset Offset = |
898 | TFI->getFrameIndexReference(MF: *Asm->MF, FI: Fragment.FI, FrameReg); |
899 | DwarfExpr.addFragmentOffset(Expr); |
900 | |
901 | auto *TRI = Asm->MF->getSubtarget().getRegisterInfo(); |
902 | SmallVector<uint64_t, 8> Ops; |
903 | TRI->getOffsetOpcodes(Offset, Ops); |
904 | |
905 | // According to |
906 | // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf |
907 | // cuda-gdb requires DW_AT_address_class for all variables to be |
908 | // able to correctly interpret address space of the variable |
909 | // address. Decode DW_OP_constu <DWARF Address Space> DW_OP_swap |
910 | // DW_OP_xderef sequence for the NVPTX + gdb target. |
911 | unsigned LocalNVPTXAddressSpace; |
912 | if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { |
913 | const DIExpression *NewExpr = |
914 | DIExpression::extractAddressClass(Expr, AddrClass&: LocalNVPTXAddressSpace); |
915 | if (NewExpr != Expr) { |
916 | Expr = NewExpr; |
917 | NVPTXAddressSpace = LocalNVPTXAddressSpace; |
918 | } |
919 | } |
920 | if (Expr) |
921 | Ops.append(in_start: Expr->elements_begin(), in_end: Expr->elements_end()); |
922 | DIExpressionCursor Cursor(Ops); |
923 | DwarfExpr.setMemoryLocationKind(); |
924 | if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol()) |
925 | addOpAddress(Die&: *Loc, Sym: FrameSymbol); |
926 | else |
927 | DwarfExpr.addMachineRegExpression( |
928 | TRI: *Asm->MF->getSubtarget().getRegisterInfo(), Expr&: Cursor, MachineReg: FrameReg); |
929 | DwarfExpr.addExpression(Expr: std::move(Cursor)); |
930 | } |
931 | if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { |
932 | // According to |
933 | // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf |
934 | // cuda-gdb requires DW_AT_address_class for all variables to be |
935 | // able to correctly interpret address space of the variable |
936 | // address. |
937 | const unsigned NVPTX_ADDR_local_space = 6; |
938 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_address_class, Form: dwarf::DW_FORM_data1, |
939 | Integer: NVPTXAddressSpace.value_or(u: NVPTX_ADDR_local_space)); |
940 | } |
941 | addBlock(Die&: VariableDie, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr.finalize()); |
942 | if (DwarfExpr.TagOffset) |
943 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_LLVM_tag_offset, Form: dwarf::DW_FORM_data1, |
944 | Integer: *DwarfExpr.TagOffset); |
945 | } |
946 | |
947 | void DwarfCompileUnit::applyConcreteDbgVariableAttributes( |
948 | const Loc::EntryValue &EntryValue, const DbgVariable &DV, |
949 | DIE &VariableDie) { |
950 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
951 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
952 | // Emit each expression as: EntryValue(Register) <other ops> <Fragment>. |
953 | for (auto [Register, Expr] : EntryValue.EntryValues) { |
954 | DwarfExpr.addFragmentOffset(Expr: &Expr); |
955 | DIExpressionCursor Cursor(Expr.getElements()); |
956 | DwarfExpr.beginEntryValueExpression(ExprCursor&: Cursor); |
957 | DwarfExpr.addMachineRegExpression( |
958 | TRI: *Asm->MF->getSubtarget().getRegisterInfo(), Expr&: Cursor, MachineReg: Register); |
959 | DwarfExpr.addExpression(Expr: std::move(Cursor)); |
960 | } |
961 | addBlock(Die&: VariableDie, Attribute: dwarf::DW_AT_location, Loc: DwarfExpr.finalize()); |
962 | } |
963 | |
964 | void DwarfCompileUnit::applyConcreteDbgVariableAttributes( |
965 | const std::monostate &, const DbgVariable &DV, DIE &VariableDie) {} |
966 | |
967 | DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, |
968 | const LexicalScope &Scope, |
969 | DIE *&ObjectPointer) { |
970 | auto Var = constructVariableDIE(DV, Abstract: Scope.isAbstractScope()); |
971 | if (DV.isObjectPointer()) |
972 | ObjectPointer = Var; |
973 | return Var; |
974 | } |
975 | |
976 | DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL, |
977 | const LexicalScope &Scope) { |
978 | auto LabelDie = DIE::get(Alloc&: DIEValueAllocator, Tag: DL.getTag()); |
979 | insertDIE(Desc: DL.getLabel(), D: LabelDie); |
980 | DL.setDIE(*LabelDie); |
981 | |
982 | if (Scope.isAbstractScope()) |
983 | applyLabelAttributes(Label: DL, LabelDie&: *LabelDie); |
984 | |
985 | return LabelDie; |
986 | } |
987 | |
988 | /// Return all DIVariables that appear in count: expressions. |
989 | static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) { |
990 | SmallVector<const DIVariable *, 2> Result; |
991 | auto *Array = dyn_cast<DICompositeType>(Val: Var->getType()); |
992 | if (!Array || Array->getTag() != dwarf::DW_TAG_array_type) |
993 | return Result; |
994 | if (auto *DLVar = Array->getDataLocation()) |
995 | Result.push_back(Elt: DLVar); |
996 | if (auto *AsVar = Array->getAssociated()) |
997 | Result.push_back(Elt: AsVar); |
998 | if (auto *AlVar = Array->getAllocated()) |
999 | Result.push_back(Elt: AlVar); |
1000 | for (auto *El : Array->getElements()) { |
1001 | if (auto *Subrange = dyn_cast<DISubrange>(Val: El)) { |
1002 | if (auto Count = Subrange->getCount()) |
1003 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: Count)) |
1004 | Result.push_back(Elt: Dependency); |
1005 | if (auto LB = Subrange->getLowerBound()) |
1006 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: LB)) |
1007 | Result.push_back(Elt: Dependency); |
1008 | if (auto UB = Subrange->getUpperBound()) |
1009 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: UB)) |
1010 | Result.push_back(Elt: Dependency); |
1011 | if (auto ST = Subrange->getStride()) |
1012 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: ST)) |
1013 | Result.push_back(Elt: Dependency); |
1014 | } else if (auto *GenericSubrange = dyn_cast<DIGenericSubrange>(Val: El)) { |
1015 | if (auto Count = GenericSubrange->getCount()) |
1016 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: Count)) |
1017 | Result.push_back(Elt: Dependency); |
1018 | if (auto LB = GenericSubrange->getLowerBound()) |
1019 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: LB)) |
1020 | Result.push_back(Elt: Dependency); |
1021 | if (auto UB = GenericSubrange->getUpperBound()) |
1022 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: UB)) |
1023 | Result.push_back(Elt: Dependency); |
1024 | if (auto ST = GenericSubrange->getStride()) |
1025 | if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Val&: ST)) |
1026 | Result.push_back(Elt: Dependency); |
1027 | } |
1028 | } |
1029 | return Result; |
1030 | } |
1031 | |
1032 | /// Sort local variables so that variables appearing inside of helper |
1033 | /// expressions come first. |
1034 | static SmallVector<DbgVariable *, 8> |
1035 | sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) { |
1036 | SmallVector<DbgVariable *, 8> Result; |
1037 | SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList; |
1038 | // Map back from a DIVariable to its containing DbgVariable. |
1039 | SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar; |
1040 | // Set of DbgVariables in Result. |
1041 | SmallDenseSet<DbgVariable *, 8> Visited; |
1042 | // For cycle detection. |
1043 | SmallDenseSet<DbgVariable *, 8> Visiting; |
1044 | |
1045 | // Initialize the worklist and the DIVariable lookup table. |
1046 | for (auto *Var : reverse(C&: Input)) { |
1047 | DbgVar.insert(KV: {Var->getVariable(), Var}); |
1048 | WorkList.push_back(Elt: {Var, 0}); |
1049 | } |
1050 | |
1051 | // Perform a stable topological sort by doing a DFS. |
1052 | while (!WorkList.empty()) { |
1053 | auto Item = WorkList.back(); |
1054 | DbgVariable *Var = Item.getPointer(); |
1055 | bool visitedAllDependencies = Item.getInt(); |
1056 | WorkList.pop_back(); |
1057 | |
1058 | assert(Var); |
1059 | |
1060 | // Already handled. |
1061 | if (Visited.count(V: Var)) |
1062 | continue; |
1063 | |
1064 | // Add to Result if all dependencies are visited. |
1065 | if (visitedAllDependencies) { |
1066 | Visited.insert(V: Var); |
1067 | Result.push_back(Elt: Var); |
1068 | continue; |
1069 | } |
1070 | |
1071 | // Detect cycles. |
1072 | auto Res = Visiting.insert(V: Var); |
1073 | if (!Res.second) { |
1074 | assert(false && "dependency cycle in local variables" ); |
1075 | return Result; |
1076 | } |
1077 | |
1078 | // Push dependencies and this node onto the worklist, so that this node is |
1079 | // visited again after all of its dependencies are handled. |
1080 | WorkList.push_back(Elt: {Var, 1}); |
1081 | for (const auto *Dependency : dependencies(Var)) { |
1082 | // Don't add dependency if it is in a different lexical scope or a global. |
1083 | if (const auto *Dep = dyn_cast<const DILocalVariable>(Val: Dependency)) |
1084 | if (DbgVariable *Var = DbgVar.lookup(Val: Dep)) |
1085 | WorkList.push_back(Elt: {Var, 0}); |
1086 | } |
1087 | } |
1088 | return Result; |
1089 | } |
1090 | |
1091 | DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, |
1092 | LexicalScope *Scope) { |
1093 | DIE &ScopeDIE = updateSubprogramScopeDIE(SP: Sub); |
1094 | |
1095 | if (Scope) { |
1096 | assert(!Scope->getInlinedAt()); |
1097 | assert(!Scope->isAbstractScope()); |
1098 | // Collect lexical scope children first. |
1099 | // ObjectPointer might be a local (non-argument) local variable if it's a |
1100 | // block's synthetic this pointer. |
1101 | if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) |
1102 | addDIEEntry(Die&: ScopeDIE, Attribute: dwarf::DW_AT_object_pointer, Entry&: *ObjectPointer); |
1103 | } |
1104 | |
1105 | // If this is a variadic function, add an unspecified parameter. |
1106 | DITypeRefArray FnArgs = Sub->getType()->getTypeArray(); |
1107 | |
1108 | // If we have a single element of null, it is a function that returns void. |
1109 | // If we have more than one elements and the last one is null, it is a |
1110 | // variadic function. |
1111 | if (FnArgs.size() > 1 && !FnArgs[FnArgs.size() - 1] && |
1112 | !includeMinimalInlineScopes()) |
1113 | ScopeDIE.addChild( |
1114 | Child: DIE::get(Alloc&: DIEValueAllocator, Tag: dwarf::DW_TAG_unspecified_parameters)); |
1115 | |
1116 | return ScopeDIE; |
1117 | } |
1118 | |
1119 | DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, |
1120 | DIE &ScopeDIE) { |
1121 | DIE *ObjectPointer = nullptr; |
1122 | |
1123 | // Emit function arguments (order is significant). |
1124 | auto Vars = DU->getScopeVariables().lookup(Val: Scope); |
1125 | for (auto &DV : Vars.Args) |
1126 | ScopeDIE.addChild(Child: constructVariableDIE(DV&: *DV.second, Scope: *Scope, ObjectPointer)); |
1127 | |
1128 | // Emit local variables. |
1129 | auto Locals = sortLocalVars(Input&: Vars.Locals); |
1130 | for (DbgVariable *DV : Locals) |
1131 | ScopeDIE.addChild(Child: constructVariableDIE(DV&: *DV, Scope: *Scope, ObjectPointer)); |
1132 | |
1133 | // Emit labels. |
1134 | for (DbgLabel *DL : DU->getScopeLabels().lookup(Val: Scope)) |
1135 | ScopeDIE.addChild(Child: constructLabelDIE(DL&: *DL, Scope: *Scope)); |
1136 | |
1137 | // Track other local entities (skipped in gmlt-like data). |
1138 | // This creates mapping between CU and a set of local declarations that |
1139 | // should be emitted for subprograms in this CU. |
1140 | if (!includeMinimalInlineScopes() && !Scope->getInlinedAt()) { |
1141 | auto &LocalDecls = DD->getLocalDeclsForScope(S: Scope->getScopeNode()); |
1142 | DeferredLocalDecls.insert(Start: LocalDecls.begin(), End: LocalDecls.end()); |
1143 | } |
1144 | |
1145 | // Emit inner lexical scopes. |
1146 | auto skipLexicalScope = [this](LexicalScope *S) -> bool { |
1147 | if (isa<DISubprogram>(Val: S->getScopeNode())) |
1148 | return false; |
1149 | auto Vars = DU->getScopeVariables().lookup(Val: S); |
1150 | if (!Vars.Args.empty() || !Vars.Locals.empty()) |
1151 | return false; |
1152 | return includeMinimalInlineScopes() || |
1153 | DD->getLocalDeclsForScope(S: S->getScopeNode()).empty(); |
1154 | }; |
1155 | for (LexicalScope *LS : Scope->getChildren()) { |
1156 | // If the lexical block doesn't have non-scope children, skip |
1157 | // its emission and put its children directly to the parent scope. |
1158 | if (skipLexicalScope(LS)) |
1159 | createAndAddScopeChildren(Scope: LS, ScopeDIE); |
1160 | else |
1161 | constructScopeDIE(Scope: LS, ParentScopeDIE&: ScopeDIE); |
1162 | } |
1163 | |
1164 | return ObjectPointer; |
1165 | } |
1166 | |
1167 | void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( |
1168 | LexicalScope *Scope) { |
1169 | auto *SP = cast<DISubprogram>(Val: Scope->getScopeNode()); |
1170 | if (getAbstractScopeDIEs().count(Val: SP)) |
1171 | return; |
1172 | |
1173 | DIE *ContextDIE; |
1174 | DwarfCompileUnit *ContextCU = this; |
1175 | |
1176 | if (includeMinimalInlineScopes()) |
1177 | ContextDIE = &getUnitDie(); |
1178 | // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with |
1179 | // the important distinction that the debug node is not associated with the |
1180 | // DIE (since the debug node will be associated with the concrete DIE, if |
1181 | // any). It could be refactored to some common utility function. |
1182 | else if (auto *SPDecl = SP->getDeclaration()) { |
1183 | ContextDIE = &getUnitDie(); |
1184 | getOrCreateSubprogramDIE(SP: SPDecl); |
1185 | } else { |
1186 | ContextDIE = getOrCreateContextDIE(Ty: SP->getScope()); |
1187 | // The scope may be shared with a subprogram that has already been |
1188 | // constructed in another CU, in which case we need to construct this |
1189 | // subprogram in the same CU. |
1190 | ContextCU = DD->lookupCU(Die: ContextDIE->getUnitDie()); |
1191 | } |
1192 | |
1193 | // Passing null as the associated node because the abstract definition |
1194 | // shouldn't be found by lookup. |
1195 | DIE &AbsDef = ContextCU->createAndAddDIE(Tag: dwarf::DW_TAG_subprogram, |
1196 | Parent&: *ContextDIE, N: nullptr); |
1197 | |
1198 | // Store the DIE before creating children. |
1199 | ContextCU->getAbstractScopeDIEs()[SP] = &AbsDef; |
1200 | |
1201 | ContextCU->applySubprogramAttributesToDefinition(SP, SPDie&: AbsDef); |
1202 | ContextCU->addSInt(Die&: AbsDef, Attribute: dwarf::DW_AT_inline, |
1203 | Form: DD->getDwarfVersion() <= 4 ? std::optional<dwarf::Form>() |
1204 | : dwarf::DW_FORM_implicit_const, |
1205 | Integer: dwarf::DW_INL_inlined); |
1206 | if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, ScopeDIE&: AbsDef)) |
1207 | ContextCU->addDIEEntry(Die&: AbsDef, Attribute: dwarf::DW_AT_object_pointer, Entry&: *ObjectPointer); |
1208 | } |
1209 | |
1210 | bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const { |
1211 | return DD->getDwarfVersion() == 4 && !DD->tuneForLLDB(); |
1212 | } |
1213 | |
1214 | dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUTag(dwarf::Tag Tag) const { |
1215 | if (!useGNUAnalogForDwarf5Feature()) |
1216 | return Tag; |
1217 | switch (Tag) { |
1218 | case dwarf::DW_TAG_call_site: |
1219 | return dwarf::DW_TAG_GNU_call_site; |
1220 | case dwarf::DW_TAG_call_site_parameter: |
1221 | return dwarf::DW_TAG_GNU_call_site_parameter; |
1222 | default: |
1223 | llvm_unreachable("DWARF5 tag with no GNU analog" ); |
1224 | } |
1225 | } |
1226 | |
1227 | dwarf::Attribute |
1228 | DwarfCompileUnit::getDwarf5OrGNUAttr(dwarf::Attribute Attr) const { |
1229 | if (!useGNUAnalogForDwarf5Feature()) |
1230 | return Attr; |
1231 | switch (Attr) { |
1232 | case dwarf::DW_AT_call_all_calls: |
1233 | return dwarf::DW_AT_GNU_all_call_sites; |
1234 | case dwarf::DW_AT_call_target: |
1235 | return dwarf::DW_AT_GNU_call_site_target; |
1236 | case dwarf::DW_AT_call_origin: |
1237 | return dwarf::DW_AT_abstract_origin; |
1238 | case dwarf::DW_AT_call_return_pc: |
1239 | return dwarf::DW_AT_low_pc; |
1240 | case dwarf::DW_AT_call_value: |
1241 | return dwarf::DW_AT_GNU_call_site_value; |
1242 | case dwarf::DW_AT_call_tail_call: |
1243 | return dwarf::DW_AT_GNU_tail_call; |
1244 | default: |
1245 | llvm_unreachable("DWARF5 attribute with no GNU analog" ); |
1246 | } |
1247 | } |
1248 | |
1249 | dwarf::LocationAtom |
1250 | DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const { |
1251 | if (!useGNUAnalogForDwarf5Feature()) |
1252 | return Loc; |
1253 | switch (Loc) { |
1254 | case dwarf::DW_OP_entry_value: |
1255 | return dwarf::DW_OP_GNU_entry_value; |
1256 | default: |
1257 | llvm_unreachable("DWARF5 location atom with no GNU analog" ); |
1258 | } |
1259 | } |
1260 | |
1261 | DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, |
1262 | const DISubprogram *CalleeSP, |
1263 | bool IsTail, |
1264 | const MCSymbol *PCAddr, |
1265 | const MCSymbol *CallAddr, |
1266 | unsigned CallReg) { |
1267 | // Insert a call site entry DIE within ScopeDIE. |
1268 | DIE &CallSiteDIE = createAndAddDIE(Tag: getDwarf5OrGNUTag(Tag: dwarf::DW_TAG_call_site), |
1269 | Parent&: ScopeDIE, N: nullptr); |
1270 | |
1271 | if (CallReg) { |
1272 | // Indirect call. |
1273 | addAddress(Die&: CallSiteDIE, Attribute: getDwarf5OrGNUAttr(Attr: dwarf::DW_AT_call_target), |
1274 | Location: MachineLocation(CallReg)); |
1275 | } else { |
1276 | DIE *CalleeDIE = getOrCreateSubprogramDIE(SP: CalleeSP); |
1277 | assert(CalleeDIE && "Could not create DIE for call site entry origin" ); |
1278 | if (AddLinkageNamesToDeclCallOriginsForTuning(DD) && |
1279 | !CalleeSP->isDefinition() && |
1280 | !CalleeDIE->findAttribute(Attribute: dwarf::DW_AT_linkage_name)) { |
1281 | addLinkageName(Die&: *CalleeDIE, LinkageName: CalleeSP->getLinkageName()); |
1282 | } |
1283 | |
1284 | addDIEEntry(Die&: CallSiteDIE, Attribute: getDwarf5OrGNUAttr(Attr: dwarf::DW_AT_call_origin), |
1285 | Entry&: *CalleeDIE); |
1286 | } |
1287 | |
1288 | if (IsTail) { |
1289 | // Attach DW_AT_call_tail_call to tail calls for standards compliance. |
1290 | addFlag(Die&: CallSiteDIE, Attribute: getDwarf5OrGNUAttr(Attr: dwarf::DW_AT_call_tail_call)); |
1291 | |
1292 | // Attach the address of the branch instruction to allow the debugger to |
1293 | // show where the tail call occurred. This attribute has no GNU analog. |
1294 | // |
1295 | // GDB works backwards from non-standard usage of DW_AT_low_pc (in DWARF4 |
1296 | // mode -- equivalently, in DWARF5 mode, DW_AT_call_return_pc) at tail-call |
1297 | // site entries to figure out the PC of tail-calling branch instructions. |
1298 | // This means it doesn't need the compiler to emit DW_AT_call_pc, so we |
1299 | // don't emit it here. |
1300 | // |
1301 | // There's no need to tie non-GDB debuggers to this non-standardness, as it |
1302 | // adds unnecessary complexity to the debugger. For non-GDB debuggers, emit |
1303 | // the standard DW_AT_call_pc info. |
1304 | if (!useGNUAnalogForDwarf5Feature()) |
1305 | addLabelAddress(Die&: CallSiteDIE, Attribute: dwarf::DW_AT_call_pc, Label: CallAddr); |
1306 | } |
1307 | |
1308 | // Attach the return PC to allow the debugger to disambiguate call paths |
1309 | // from one function to another. |
1310 | // |
1311 | // The return PC is only really needed when the call /isn't/ a tail call, but |
1312 | // GDB expects it in DWARF4 mode, even for tail calls (see the comment above |
1313 | // the DW_AT_call_pc emission logic for an explanation). |
1314 | if (!IsTail || useGNUAnalogForDwarf5Feature()) { |
1315 | assert(PCAddr && "Missing return PC information for a call" ); |
1316 | addLabelAddress(Die&: CallSiteDIE, |
1317 | Attribute: getDwarf5OrGNUAttr(Attr: dwarf::DW_AT_call_return_pc), Label: PCAddr); |
1318 | } |
1319 | |
1320 | return CallSiteDIE; |
1321 | } |
1322 | |
1323 | void DwarfCompileUnit::constructCallSiteParmEntryDIEs( |
1324 | DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params) { |
1325 | for (const auto &Param : Params) { |
1326 | unsigned Register = Param.getRegister(); |
1327 | auto CallSiteDieParam = |
1328 | DIE::get(Alloc&: DIEValueAllocator, |
1329 | Tag: getDwarf5OrGNUTag(Tag: dwarf::DW_TAG_call_site_parameter)); |
1330 | insertDIE(D: CallSiteDieParam); |
1331 | addAddress(Die&: *CallSiteDieParam, Attribute: dwarf::DW_AT_location, |
1332 | Location: MachineLocation(Register)); |
1333 | |
1334 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
1335 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
1336 | DwarfExpr.setCallSiteParamValueFlag(); |
1337 | |
1338 | DwarfDebug::emitDebugLocValue(AP: *Asm, BT: nullptr, Value: Param.getValue(), DwarfExpr); |
1339 | |
1340 | addBlock(Die&: *CallSiteDieParam, Attribute: getDwarf5OrGNUAttr(Attr: dwarf::DW_AT_call_value), |
1341 | Loc: DwarfExpr.finalize()); |
1342 | |
1343 | CallSiteDIE.addChild(Child: CallSiteDieParam); |
1344 | } |
1345 | } |
1346 | |
1347 | DIE *DwarfCompileUnit::constructImportedEntityDIE( |
1348 | const DIImportedEntity *Module) { |
1349 | DIE *IMDie = DIE::get(Alloc&: DIEValueAllocator, Tag: (dwarf::Tag)Module->getTag()); |
1350 | insertDIE(Desc: Module, D: IMDie); |
1351 | DIE *EntityDie; |
1352 | auto *Entity = Module->getEntity(); |
1353 | if (auto *NS = dyn_cast<DINamespace>(Val: Entity)) |
1354 | EntityDie = getOrCreateNameSpace(NS); |
1355 | else if (auto *M = dyn_cast<DIModule>(Val: Entity)) |
1356 | EntityDie = getOrCreateModule(M); |
1357 | else if (auto *SP = dyn_cast<DISubprogram>(Val: Entity)) { |
1358 | // If there is an abstract subprogram, refer to it. Note that this assumes |
1359 | // that all the abstract subprograms have been already created (which is |
1360 | // correct until imported entities get emitted in DwarfDebug::endModule()). |
1361 | if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(Val: SP)) |
1362 | EntityDie = AbsSPDie; |
1363 | else |
1364 | EntityDie = getOrCreateSubprogramDIE(SP); |
1365 | } else if (auto *T = dyn_cast<DIType>(Val: Entity)) |
1366 | EntityDie = getOrCreateTypeDIE(TyNode: T); |
1367 | else if (auto *GV = dyn_cast<DIGlobalVariable>(Val: Entity)) |
1368 | EntityDie = getOrCreateGlobalVariableDIE(GV, GlobalExprs: {}); |
1369 | else if (auto *IE = dyn_cast<DIImportedEntity>(Val: Entity)) |
1370 | EntityDie = getOrCreateImportedEntityDIE(IE); |
1371 | else |
1372 | EntityDie = getDIE(D: Entity); |
1373 | assert(EntityDie); |
1374 | addSourceLine(Die&: *IMDie, Line: Module->getLine(), File: Module->getFile()); |
1375 | addDIEEntry(Die&: *IMDie, Attribute: dwarf::DW_AT_import, Entry&: *EntityDie); |
1376 | StringRef Name = Module->getName(); |
1377 | if (!Name.empty()) { |
1378 | addString(Die&: *IMDie, Attribute: dwarf::DW_AT_name, Str: Name); |
1379 | |
1380 | // FIXME: if consumers ever start caring about handling |
1381 | // unnamed import declarations such as `using ::nullptr_t` |
1382 | // or `using namespace std::ranges`, we could add the |
1383 | // import declaration into the accelerator table with the |
1384 | // name being the one of the entity being imported. |
1385 | DD->addAccelNamespace(Unit: *this, NameTableKind: CUNode->getNameTableKind(), Name, Die: *IMDie); |
1386 | } |
1387 | |
1388 | // This is for imported module with renamed entities (such as variables and |
1389 | // subprograms). |
1390 | DINodeArray Elements = Module->getElements(); |
1391 | for (const auto *Element : Elements) { |
1392 | if (!Element) |
1393 | continue; |
1394 | IMDie->addChild( |
1395 | Child: constructImportedEntityDIE(Module: cast<DIImportedEntity>(Val: Element))); |
1396 | } |
1397 | |
1398 | return IMDie; |
1399 | } |
1400 | |
1401 | DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE( |
1402 | const DIImportedEntity *IE) { |
1403 | |
1404 | // Check for pre-existence. |
1405 | if (DIE *Die = getDIE(D: IE)) |
1406 | return Die; |
1407 | |
1408 | DIE *ContextDIE = getOrCreateContextDIE(Ty: IE->getScope()); |
1409 | assert(ContextDIE && "Empty scope for the imported entity!" ); |
1410 | |
1411 | DIE *IMDie = constructImportedEntityDIE(Module: IE); |
1412 | ContextDIE->addChild(Child: IMDie); |
1413 | return IMDie; |
1414 | } |
1415 | |
1416 | void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { |
1417 | DIE *D = getDIE(D: SP); |
1418 | if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(Val: SP)) { |
1419 | if (D) |
1420 | // If this subprogram has an abstract definition, reference that |
1421 | addDIEEntry(Die&: *D, Attribute: dwarf::DW_AT_abstract_origin, Entry&: *AbsSPDIE); |
1422 | } else { |
1423 | assert(D || includeMinimalInlineScopes()); |
1424 | if (D) |
1425 | // And attach the attributes |
1426 | applySubprogramAttributesToDefinition(SP, SPDie&: *D); |
1427 | } |
1428 | } |
1429 | |
1430 | void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) { |
1431 | DbgEntity *AbsEntity = getExistingAbstractEntity(Node: Entity->getEntity()); |
1432 | |
1433 | auto *Die = Entity->getDIE(); |
1434 | /// Label may be used to generate DW_AT_low_pc, so put it outside |
1435 | /// if/else block. |
1436 | const DbgLabel *Label = nullptr; |
1437 | if (AbsEntity && AbsEntity->getDIE()) { |
1438 | addDIEEntry(Die&: *Die, Attribute: dwarf::DW_AT_abstract_origin, Entry&: *AbsEntity->getDIE()); |
1439 | Label = dyn_cast<const DbgLabel>(Val: Entity); |
1440 | } else { |
1441 | if (const DbgVariable *Var = dyn_cast<const DbgVariable>(Val: Entity)) |
1442 | applyCommonDbgVariableAttributes(Var: *Var, VariableDie&: *Die); |
1443 | else if ((Label = dyn_cast<const DbgLabel>(Val: Entity))) |
1444 | applyLabelAttributes(Label: *Label, LabelDie&: *Die); |
1445 | else |
1446 | llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel." ); |
1447 | } |
1448 | |
1449 | if (!Label) |
1450 | return; |
1451 | |
1452 | const auto *Sym = Label->getSymbol(); |
1453 | if (!Sym) |
1454 | return; |
1455 | |
1456 | addLabelAddress(Die&: *Die, Attribute: dwarf::DW_AT_low_pc, Label: Sym); |
1457 | |
1458 | // A TAG_label with a name and an AT_low_pc must be placed in debug_names. |
1459 | if (StringRef Name = Label->getName(); !Name.empty()) |
1460 | getDwarfDebug().addAccelName(Unit: *this, NameTableKind: CUNode->getNameTableKind(), Name, Die: *Die); |
1461 | } |
1462 | |
1463 | DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) { |
1464 | auto &AbstractEntities = getAbstractEntities(); |
1465 | auto I = AbstractEntities.find(Val: Node); |
1466 | if (I != AbstractEntities.end()) |
1467 | return I->second.get(); |
1468 | return nullptr; |
1469 | } |
1470 | |
1471 | void DwarfCompileUnit::createAbstractEntity(const DINode *Node, |
1472 | LexicalScope *Scope) { |
1473 | assert(Scope && Scope->isAbstractScope()); |
1474 | auto &Entity = getAbstractEntities()[Node]; |
1475 | if (isa<const DILocalVariable>(Val: Node)) { |
1476 | Entity = std::make_unique<DbgVariable>(args: cast<const DILocalVariable>(Val: Node), |
1477 | args: nullptr /* IA */); |
1478 | DU->addScopeVariable(LS: Scope, Var: cast<DbgVariable>(Val: Entity.get())); |
1479 | } else if (isa<const DILabel>(Val: Node)) { |
1480 | Entity = std::make_unique<DbgLabel>( |
1481 | args: cast<const DILabel>(Val: Node), args: nullptr /* IA */); |
1482 | DU->addScopeLabel(LS: Scope, Label: cast<DbgLabel>(Val: Entity.get())); |
1483 | } |
1484 | } |
1485 | |
1486 | void DwarfCompileUnit::(bool UseOffsets) { |
1487 | // Don't bother labeling the .dwo unit, as its offset isn't used. |
1488 | if (!Skeleton && !DD->useSectionsAsReferences()) { |
1489 | LabelBegin = Asm->createTempSymbol(Name: "cu_begin" ); |
1490 | Asm->OutStreamer->emitLabel(Symbol: LabelBegin); |
1491 | } |
1492 | |
1493 | dwarf::UnitType UT = Skeleton ? dwarf::DW_UT_split_compile |
1494 | : DD->useSplitDwarf() ? dwarf::DW_UT_skeleton |
1495 | : dwarf::DW_UT_compile; |
1496 | DwarfUnit::emitCommonHeader(UseOffsets, UT); |
1497 | if (DD->getDwarfVersion() >= 5 && UT != dwarf::DW_UT_compile) |
1498 | Asm->emitInt64(Value: getDWOId()); |
1499 | } |
1500 | |
1501 | bool DwarfCompileUnit::hasDwarfPubSections() const { |
1502 | switch (CUNode->getNameTableKind()) { |
1503 | case DICompileUnit::DebugNameTableKind::None: |
1504 | return false; |
1505 | // Opting in to GNU Pubnames/types overrides the default to ensure these are |
1506 | // generated for things like Gold's gdb_index generation. |
1507 | case DICompileUnit::DebugNameTableKind::GNU: |
1508 | return true; |
1509 | case DICompileUnit::DebugNameTableKind::Apple: |
1510 | return false; |
1511 | case DICompileUnit::DebugNameTableKind::Default: |
1512 | return DD->tuneForGDB() && !includeMinimalInlineScopes() && |
1513 | !CUNode->isDebugDirectivesOnly() && |
1514 | DD->getAccelTableKind() != AccelTableKind::Apple && |
1515 | DD->getDwarfVersion() < 5; |
1516 | } |
1517 | llvm_unreachable("Unhandled DICompileUnit::DebugNameTableKind enum" ); |
1518 | } |
1519 | |
1520 | /// addGlobalName - Add a new global name to the compile unit. |
1521 | void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die, |
1522 | const DIScope *Context) { |
1523 | if (!hasDwarfPubSections()) |
1524 | return; |
1525 | std::string FullName = getParentContextString(Context) + Name.str(); |
1526 | GlobalNames[FullName] = &Die; |
1527 | } |
1528 | |
1529 | void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name, |
1530 | const DIScope *Context) { |
1531 | if (!hasDwarfPubSections()) |
1532 | return; |
1533 | std::string FullName = getParentContextString(Context) + Name.str(); |
1534 | // Insert, allowing the entry to remain as-is if it's already present |
1535 | // This way the CU-level type DIE is preferred over the "can't describe this |
1536 | // type as a unit offset because it's not really in the CU at all, it's only |
1537 | // in a type unit" |
1538 | GlobalNames.insert(KV: std::make_pair(x: std::move(FullName), y: &getUnitDie())); |
1539 | } |
1540 | |
1541 | /// Add a new global type to the unit. |
1542 | void DwarfCompileUnit::addGlobalTypeImpl(const DIType *Ty, const DIE &Die, |
1543 | const DIScope *Context) { |
1544 | if (!hasDwarfPubSections()) |
1545 | return; |
1546 | std::string FullName = getParentContextString(Context) + Ty->getName().str(); |
1547 | GlobalTypes[FullName] = &Die; |
1548 | } |
1549 | |
1550 | void DwarfCompileUnit::addGlobalTypeUnitType(const DIType *Ty, |
1551 | const DIScope *Context) { |
1552 | if (!hasDwarfPubSections()) |
1553 | return; |
1554 | std::string FullName = getParentContextString(Context) + Ty->getName().str(); |
1555 | // Insert, allowing the entry to remain as-is if it's already present |
1556 | // This way the CU-level type DIE is preferred over the "can't describe this |
1557 | // type as a unit offset because it's not really in the CU at all, it's only |
1558 | // in a type unit" |
1559 | GlobalTypes.insert(KV: std::make_pair(x: std::move(FullName), y: &getUnitDie())); |
1560 | } |
1561 | |
1562 | void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, |
1563 | MachineLocation Location) { |
1564 | auto *Single = std::get_if<Loc::Single>(ptr: &DV); |
1565 | if (Single && Single->getExpr()) |
1566 | addComplexAddress(DIExpr: Single->getExpr(), Die, Attribute: dwarf::DW_AT_location, Location); |
1567 | else |
1568 | addAddress(Die, Attribute: dwarf::DW_AT_location, Location); |
1569 | } |
1570 | |
1571 | /// Add an address attribute to a die based on the location provided. |
1572 | void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, |
1573 | const MachineLocation &Location) { |
1574 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
1575 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
1576 | if (Location.isIndirect()) |
1577 | DwarfExpr.setMemoryLocationKind(); |
1578 | |
1579 | DIExpressionCursor Cursor({}); |
1580 | const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); |
1581 | if (!DwarfExpr.addMachineRegExpression(TRI, Expr&: Cursor, MachineReg: Location.getReg())) |
1582 | return; |
1583 | DwarfExpr.addExpression(Expr: std::move(Cursor)); |
1584 | |
1585 | // Now attach the location information to the DIE. |
1586 | addBlock(Die, Attribute, Loc: DwarfExpr.finalize()); |
1587 | |
1588 | if (DwarfExpr.TagOffset) |
1589 | addUInt(Die, Attribute: dwarf::DW_AT_LLVM_tag_offset, Form: dwarf::DW_FORM_data1, |
1590 | Integer: *DwarfExpr.TagOffset); |
1591 | } |
1592 | |
1593 | /// Start with the address based on the location provided, and generate the |
1594 | /// DWARF information necessary to find the actual variable given the extra |
1595 | /// address information encoded in the DbgVariable, starting from the starting |
1596 | /// location. Add the DWARF information to the die. |
1597 | void DwarfCompileUnit::addComplexAddress(const DIExpression *DIExpr, DIE &Die, |
1598 | dwarf::Attribute Attribute, |
1599 | const MachineLocation &Location) { |
1600 | DIELoc *Loc = new (DIEValueAllocator) DIELoc; |
1601 | DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); |
1602 | DwarfExpr.addFragmentOffset(Expr: DIExpr); |
1603 | DwarfExpr.setLocation(Loc: Location, DIExpr); |
1604 | |
1605 | DIExpressionCursor Cursor(DIExpr); |
1606 | |
1607 | if (DIExpr->isEntryValue()) |
1608 | DwarfExpr.beginEntryValueExpression(ExprCursor&: Cursor); |
1609 | |
1610 | const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); |
1611 | if (!DwarfExpr.addMachineRegExpression(TRI, Expr&: Cursor, MachineReg: Location.getReg())) |
1612 | return; |
1613 | DwarfExpr.addExpression(Expr: std::move(Cursor)); |
1614 | |
1615 | // Now attach the location information to the DIE. |
1616 | addBlock(Die, Attribute, Loc: DwarfExpr.finalize()); |
1617 | |
1618 | if (DwarfExpr.TagOffset) |
1619 | addUInt(Die, Attribute: dwarf::DW_AT_LLVM_tag_offset, Form: dwarf::DW_FORM_data1, |
1620 | Integer: *DwarfExpr.TagOffset); |
1621 | } |
1622 | |
1623 | /// Add a Dwarf loclistptr attribute data and value. |
1624 | void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, |
1625 | unsigned Index) { |
1626 | dwarf::Form Form = (DD->getDwarfVersion() >= 5) |
1627 | ? dwarf::DW_FORM_loclistx |
1628 | : DD->getDwarfSectionOffsetForm(); |
1629 | addAttribute(Die, Attribute, Form, Value: DIELocList(Index)); |
1630 | } |
1631 | |
1632 | void DwarfCompileUnit::applyCommonDbgVariableAttributes(const DbgVariable &Var, |
1633 | DIE &VariableDie) { |
1634 | StringRef Name = Var.getName(); |
1635 | if (!Name.empty()) |
1636 | addString(Die&: VariableDie, Attribute: dwarf::DW_AT_name, Str: Name); |
1637 | const auto *DIVar = Var.getVariable(); |
1638 | if (DIVar) { |
1639 | if (uint32_t AlignInBytes = DIVar->getAlignInBytes()) |
1640 | addUInt(Die&: VariableDie, Attribute: dwarf::DW_AT_alignment, Form: dwarf::DW_FORM_udata, |
1641 | Integer: AlignInBytes); |
1642 | addAnnotation(Buffer&: VariableDie, Annotations: DIVar->getAnnotations()); |
1643 | } |
1644 | |
1645 | addSourceLine(Die&: VariableDie, V: DIVar); |
1646 | addType(Entity&: VariableDie, Ty: Var.getType()); |
1647 | if (Var.isArtificial()) |
1648 | addFlag(Die&: VariableDie, Attribute: dwarf::DW_AT_artificial); |
1649 | } |
1650 | |
1651 | void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label, |
1652 | DIE &LabelDie) { |
1653 | StringRef Name = Label.getName(); |
1654 | if (!Name.empty()) |
1655 | addString(Die&: LabelDie, Attribute: dwarf::DW_AT_name, Str: Name); |
1656 | const auto *DILabel = Label.getLabel(); |
1657 | addSourceLine(Die&: LabelDie, L: DILabel); |
1658 | } |
1659 | |
1660 | /// Add a Dwarf expression attribute data and value. |
1661 | void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form, |
1662 | const MCExpr *Expr) { |
1663 | addAttribute(Die, Attribute: (dwarf::Attribute)0, Form, Value: DIEExpr(Expr)); |
1664 | } |
1665 | |
1666 | void DwarfCompileUnit::applySubprogramAttributesToDefinition( |
1667 | const DISubprogram *SP, DIE &SPDie) { |
1668 | auto *SPDecl = SP->getDeclaration(); |
1669 | auto *Context = SPDecl ? SPDecl->getScope() : SP->getScope(); |
1670 | applySubprogramAttributes(SP, SPDie, SkipSPAttributes: includeMinimalInlineScopes()); |
1671 | addGlobalName(Name: SP->getName(), Die: SPDie, Context); |
1672 | } |
1673 | |
1674 | bool DwarfCompileUnit::isDwoUnit() const { |
1675 | return DD->useSplitDwarf() && Skeleton; |
1676 | } |
1677 | |
1678 | void DwarfCompileUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) { |
1679 | constructTypeDIE(Buffer&: D, CTy); |
1680 | } |
1681 | |
1682 | bool DwarfCompileUnit::includeMinimalInlineScopes() const { |
1683 | return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly || |
1684 | (DD->useSplitDwarf() && !Skeleton); |
1685 | } |
1686 | |
1687 | void DwarfCompileUnit::addAddrTableBase() { |
1688 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
1689 | MCSymbol *Label = DD->getAddressPool().getLabel(); |
1690 | addSectionLabel(Die&: getUnitDie(), |
1691 | Attribute: DD->getDwarfVersion() >= 5 ? dwarf::DW_AT_addr_base |
1692 | : dwarf::DW_AT_GNU_addr_base, |
1693 | Label, Sec: TLOF.getDwarfAddrSection()->getBeginSymbol()); |
1694 | } |
1695 | |
1696 | void DwarfCompileUnit::addBaseTypeRef(DIEValueList &Die, int64_t Idx) { |
1697 | addAttribute(Die, Attribute: (dwarf::Attribute)0, Form: dwarf::DW_FORM_udata, |
1698 | Value: new (DIEValueAllocator) DIEBaseTypeRef(this, Idx)); |
1699 | } |
1700 | |
1701 | void DwarfCompileUnit::createBaseTypeDIEs() { |
1702 | // Insert the base_type DIEs directly after the CU so that their offsets will |
1703 | // fit in the fixed size ULEB128 used inside the location expressions. |
1704 | // Maintain order by iterating backwards and inserting to the front of CU |
1705 | // child list. |
1706 | for (auto &Btr : reverse(C&: ExprRefedBaseTypes)) { |
1707 | DIE &Die = getUnitDie().addChildFront( |
1708 | Child: DIE::get(Alloc&: DIEValueAllocator, Tag: dwarf::DW_TAG_base_type)); |
1709 | SmallString<32> Str; |
1710 | addString(Die, Attribute: dwarf::DW_AT_name, |
1711 | Str: Twine(dwarf::AttributeEncodingString(Encoding: Btr.Encoding) + |
1712 | "_" + Twine(Btr.BitSize)).toStringRef(Out&: Str)); |
1713 | addUInt(Die, Attribute: dwarf::DW_AT_encoding, Form: dwarf::DW_FORM_data1, Integer: Btr.Encoding); |
1714 | // Round up to smallest number of bytes that contains this number of bits. |
1715 | addUInt(Die, Attribute: dwarf::DW_AT_byte_size, Form: std::nullopt, |
1716 | Integer: divideCeil(Numerator: Btr.BitSize, Denominator: 8)); |
1717 | |
1718 | Btr.Die = &Die; |
1719 | } |
1720 | } |
1721 | |
1722 | DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) { |
1723 | // Assume if there is an abstract tree all the DIEs are already emitted. |
1724 | bool isAbstract = getAbstractScopeDIEs().count(Val: LB->getSubprogram()); |
1725 | if (isAbstract && getAbstractScopeDIEs().count(Val: LB)) |
1726 | return getAbstractScopeDIEs()[LB]; |
1727 | assert(!isAbstract && "Missed lexical block DIE in abstract tree!" ); |
1728 | |
1729 | // Return a concrete DIE if it exists or nullptr otherwise. |
1730 | return LexicalBlockDIEs.lookup(Val: LB); |
1731 | } |
1732 | |
1733 | DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) { |
1734 | if (isa_and_nonnull<DILocalScope>(Val: Context)) { |
1735 | if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Val: Context)) |
1736 | Context = LFScope->getNonLexicalBlockFileScope(); |
1737 | if (auto *LScope = dyn_cast<DILexicalBlock>(Val: Context)) |
1738 | return getLexicalBlockDIE(LB: LScope); |
1739 | |
1740 | // Otherwise the context must be a DISubprogram. |
1741 | auto *SPScope = cast<DISubprogram>(Val: Context); |
1742 | if (getAbstractScopeDIEs().count(Val: SPScope)) |
1743 | return getAbstractScopeDIEs()[SPScope]; |
1744 | } |
1745 | return DwarfUnit::getOrCreateContextDIE(Context); |
1746 | } |
1747 | |