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