1 | //===- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit -----*- C++ -*-===// |
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 writing dwarf compile unit. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H |
14 | #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H |
15 | |
16 | #include "DwarfDebug.h" |
17 | #include "DwarfUnit.h" |
18 | #include "llvm/ADT/ArrayRef.h" |
19 | #include "llvm/ADT/DenseMap.h" |
20 | #include "llvm/ADT/SmallVector.h" |
21 | #include "llvm/ADT/StringMap.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/BinaryFormat/Dwarf.h" |
24 | #include "llvm/CodeGen/DbgEntityHistoryCalculator.h" |
25 | #include "llvm/CodeGen/LexicalScopes.h" |
26 | #include "llvm/IR/DebugInfoMetadata.h" |
27 | #include "llvm/Support/Casting.h" |
28 | #include <cstdint> |
29 | #include <memory> |
30 | |
31 | namespace llvm { |
32 | |
33 | class AsmPrinter; |
34 | class DIE; |
35 | class DIELoc; |
36 | class DIEValueList; |
37 | class DwarfFile; |
38 | class GlobalVariable; |
39 | class MCExpr; |
40 | class MCSymbol; |
41 | class MDNode; |
42 | |
43 | enum class UnitKind { Skeleton, Full }; |
44 | |
45 | class DwarfCompileUnit final : public DwarfUnit { |
46 | bool HasRangeLists = false; |
47 | |
48 | /// The start of the unit line section, this is also |
49 | /// reused in appyStmtList. |
50 | MCSymbol *LineTableStartSym; |
51 | |
52 | /// Skeleton unit associated with this unit. |
53 | DwarfCompileUnit *Skeleton = nullptr; |
54 | |
55 | /// The start of the unit macro info within macro section. |
56 | MCSymbol *MacroLabelBegin; |
57 | |
58 | /// GlobalNames - A map of globally visible named entities for this unit. |
59 | StringMap<const DIE *> GlobalNames; |
60 | |
61 | /// GlobalTypes - A map of globally visible types for this unit. |
62 | StringMap<const DIE *> GlobalTypes; |
63 | |
64 | // List of ranges for a given compile unit. |
65 | SmallVector<RangeSpan, 2> CURanges; |
66 | |
67 | // The base address of this unit, if any. Used for relative references in |
68 | // ranges/locs. |
69 | const MCSymbol *BaseAddress = nullptr; |
70 | |
71 | using MDNodeSetVector = |
72 | SetVector<const MDNode *, SmallVector<const MDNode *, 4>, |
73 | SmallPtrSet<const MDNode *, 4>>; |
74 | |
75 | // List of entities (either static locals, types or imports) that |
76 | // belong to subprograms within this CU. |
77 | MDNodeSetVector DeferredLocalDecls; |
78 | |
79 | // List of concrete lexical block scopes belong to subprograms within this CU. |
80 | DenseMap<const DILocalScope *, DIE *> LexicalBlockDIEs; |
81 | |
82 | // List of abstract local scopes (either DISubprogram or DILexicalBlock). |
83 | DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs; |
84 | |
85 | // List of inlined lexical block scopes that belong to subprograms within this |
86 | // CU. |
87 | DenseMap<const DILocalScope *, SmallVector<DIE *, 2>> InlinedLocalScopeDIEs; |
88 | |
89 | DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities; |
90 | |
91 | /// DWO ID for correlating skeleton and split units. |
92 | uint64_t DWOId = 0; |
93 | |
94 | const DIFile *LastFile = nullptr; |
95 | unsigned LastFileID; |
96 | |
97 | /// \anchor applyConcreteDbgVariableAttribute |
98 | /// \name applyConcreteDbgVariableAttribute |
99 | /// Overload set which applies attributes to \c VariableDie based on |
100 | /// the active variant of \c DV, which is passed as the first argument. |
101 | ///@{ |
102 | |
103 | /// See \ref applyConcreteDbgVariableAttribute |
104 | void applyConcreteDbgVariableAttributes(const Loc::Single &Single, |
105 | const DbgVariable &DV, |
106 | DIE &VariableDie); |
107 | /// See \ref applyConcreteDbgVariableAttribute |
108 | void applyConcreteDbgVariableAttributes(const Loc::Multi &Multi, |
109 | const DbgVariable &DV, |
110 | DIE &VariableDie); |
111 | /// See \ref applyConcreteDbgVariableAttribute |
112 | void applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, |
113 | const DbgVariable &DV, |
114 | DIE &VariableDie); |
115 | /// See \ref applyConcreteDbgVariableAttribute |
116 | void applyConcreteDbgVariableAttributes(const Loc::EntryValue &EntryValue, |
117 | const DbgVariable &DV, |
118 | DIE &VariableDie); |
119 | /// See \ref applyConcreteDbgVariableAttribute |
120 | void applyConcreteDbgVariableAttributes(const std::monostate &, |
121 | const DbgVariable &DV, |
122 | DIE &VariableDie); |
123 | |
124 | ///@} |
125 | |
126 | bool isDwoUnit() const override; |
127 | |
128 | DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() { |
129 | if (isDwoUnit() && !DD->shareAcrossDWOCUs()) |
130 | return AbstractLocalScopeDIEs; |
131 | return DU->getAbstractScopeDIEs(); |
132 | } |
133 | |
134 | DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() { |
135 | if (isDwoUnit() && !DD->shareAcrossDWOCUs()) |
136 | return AbstractEntities; |
137 | return DU->getAbstractEntities(); |
138 | } |
139 | |
140 | void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override; |
141 | |
142 | /// Add info for Wasm-global-based relocation. |
143 | void addWasmRelocBaseGlobal(DIELoc *Loc, StringRef GlobalName, |
144 | uint64_t GlobalIndex); |
145 | |
146 | public: |
147 | DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, |
148 | DwarfDebug *DW, DwarfFile *DWU, |
149 | UnitKind Kind = UnitKind::Full); |
150 | |
151 | bool hasRangeLists() const { return HasRangeLists; } |
152 | |
153 | DwarfCompileUnit *getSkeleton() const { |
154 | return Skeleton; |
155 | } |
156 | |
157 | bool includeMinimalInlineScopes() const; |
158 | |
159 | bool emitFuncLineTableOffsets() const; |
160 | |
161 | void initStmtList(); |
162 | |
163 | /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. |
164 | void applyStmtList(DIE &D); |
165 | |
166 | /// Get line table start symbol for this unit. |
167 | MCSymbol *getLineTableStartSym() const { return LineTableStartSym; } |
168 | |
169 | /// A pair of GlobalVariable and DIExpression. |
170 | struct GlobalExpr { |
171 | const GlobalVariable *Var; |
172 | const DIExpression *Expr; |
173 | }; |
174 | |
175 | struct BaseTypeRef { |
176 | BaseTypeRef(unsigned BitSize, dwarf::TypeKind Encoding) : |
177 | BitSize(BitSize), Encoding(Encoding) {} |
178 | unsigned BitSize; |
179 | dwarf::TypeKind Encoding; |
180 | DIE *Die = nullptr; |
181 | }; |
182 | |
183 | std::vector<BaseTypeRef> ExprRefedBaseTypes; |
184 | |
185 | /// Get or create global variable DIE. |
186 | DIE * |
187 | getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, |
188 | ArrayRef<GlobalExpr> GlobalExprs); |
189 | |
190 | DIE *getOrCreateCommonBlock(const DICommonBlock *CB, |
191 | ArrayRef<GlobalExpr> GlobalExprs); |
192 | |
193 | void addLocationAttribute(DIE *ToDIE, const DIGlobalVariable *GV, |
194 | ArrayRef<GlobalExpr> GlobalExprs); |
195 | |
196 | /// addLabelAddress - Add a dwarf label attribute data and value using |
197 | /// either DW_FORM_addr or DW_FORM_GNU_addr_index. |
198 | void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, |
199 | const MCSymbol *Label); |
200 | |
201 | /// addLocalLabelAddress - Add a dwarf label attribute data and value using |
202 | /// DW_FORM_addr only. |
203 | void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, |
204 | const MCSymbol *Label); |
205 | |
206 | DwarfCompileUnit &getCU() override { return *this; } |
207 | |
208 | unsigned getOrCreateSourceID(const DIFile *File) override; |
209 | |
210 | /// addRange - Add an address range to the list of ranges for this unit. |
211 | void addRange(RangeSpan Range); |
212 | |
213 | void attachLowHighPC(DIE &D, const MCSymbol *Begin, const MCSymbol *End); |
214 | |
215 | /// Find DIE for the given subprogram and attach appropriate |
216 | /// DW_AT_low_pc, DW_AT_high_pc and DW_AT_LLVM_stmt_sequence attributes. |
217 | /// If there are global variables in this scope then create and insert DIEs |
218 | /// for these variables. |
219 | DIE &updateSubprogramScopeDIE(const DISubprogram *SP, MCSymbol *LineTableSym); |
220 | |
221 | void constructScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); |
222 | |
223 | /// A helper function to construct a RangeSpanList for a given |
224 | /// lexical scope. |
225 | void addScopeRangeList(DIE &ScopeDIE, SmallVector<RangeSpan, 2> Range); |
226 | |
227 | void attachRangesOrLowHighPC(DIE &D, SmallVector<RangeSpan, 2> Ranges); |
228 | |
229 | void attachRangesOrLowHighPC(DIE &D, |
230 | const SmallVectorImpl<InsnRange> &Ranges); |
231 | |
232 | /// This scope represents an inlined body of a function. Construct a |
233 | /// DIE to represent this concrete inlined copy of the function. |
234 | DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); |
235 | |
236 | /// Construct new DW_TAG_lexical_block for this scope and |
237 | /// attach DW_AT_low_pc/DW_AT_high_pc labels. |
238 | DIE *constructLexicalScopeDIE(LexicalScope *Scope); |
239 | |
240 | /// Get a DIE for the given DILexicalBlock. |
241 | /// Note that this function assumes that the DIE has been already created |
242 | /// and it's an error, if it hasn't. |
243 | DIE *getLexicalBlockDIE(const DILexicalBlock *LB); |
244 | |
245 | /// Construct a DIE for the given DbgVariable. |
246 | DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false); |
247 | |
248 | /// Convenience overload which writes the DIE pointer into an out variable |
249 | /// ObjectPointer in addition to returning it. |
250 | DIE *constructVariableDIE(DbgVariable &DV, const LexicalScope &Scope, |
251 | DIE *&ObjectPointer); |
252 | |
253 | /// Construct a DIE for the given DbgLabel. |
254 | DIE *constructLabelDIE(DbgLabel &DL, const LexicalScope &Scope); |
255 | |
256 | void createBaseTypeDIEs(); |
257 | |
258 | /// Construct a DIE for a given scope. |
259 | /// This instance of 'getOrCreateContextDIE()' can handle DILocalScope. |
260 | DIE *getOrCreateContextDIE(const DIScope *Ty) override; |
261 | |
262 | /// Construct a DIE for this subprogram scope. |
263 | DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope, |
264 | MCSymbol *LineTableSym); |
265 | |
266 | DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE); |
267 | |
268 | void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); |
269 | |
270 | /// Whether to use the GNU analog for a DWARF5 tag, attribute, or location |
271 | /// atom. Only applicable when emitting otherwise DWARF4-compliant debug info. |
272 | bool useGNUAnalogForDwarf5Feature() const; |
273 | |
274 | /// This takes a DWARF 5 tag and returns it or a GNU analog. |
275 | dwarf::Tag getDwarf5OrGNUTag(dwarf::Tag Tag) const; |
276 | |
277 | /// This takes a DWARF 5 attribute and returns it or a GNU analog. |
278 | dwarf::Attribute getDwarf5OrGNUAttr(dwarf::Attribute Attr) const; |
279 | |
280 | /// This takes a DWARF 5 location atom and either returns it or a GNU analog. |
281 | dwarf::LocationAtom getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const; |
282 | |
283 | /// Construct a call site entry DIE describing a call within \p Scope to a |
284 | /// callee described by \p CalleeSP. |
285 | /// \p IsTail specifies whether the call is a tail call. |
286 | /// \p PCAddr points to the PC value after the call instruction. |
287 | /// \p CallAddr points to the PC value at the call instruction (or is null). |
288 | /// \p CallReg is a register location for an indirect call. For direct calls |
289 | /// the \p CallReg is set to 0. |
290 | DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP, |
291 | bool IsTail, const MCSymbol *PCAddr, |
292 | const MCSymbol *CallAddr, unsigned CallReg); |
293 | /// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params |
294 | /// were collected by the \ref collectCallSiteParameters. |
295 | /// Note: The order of parameters does not matter, since debuggers recognize |
296 | /// call site parameters by the DW_AT_location attribute. |
297 | void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE, |
298 | SmallVector<DbgCallSiteParam, 4> &Params); |
299 | |
300 | /// Get or create a DIE for an imported entity. |
301 | DIE *getOrCreateImportedEntityDIE(const DIImportedEntity *IE); |
302 | DIE *constructImportedEntityDIE(const DIImportedEntity *IE); |
303 | |
304 | void finishSubprogramDefinition(const DISubprogram *SP); |
305 | void finishEntityDefinition(const DbgEntity *Entity); |
306 | void attachLexicalScopesAbstractOrigins(); |
307 | |
308 | /// Find abstract variable associated with Var. |
309 | using InlinedEntity = DbgValueHistoryMap::InlinedEntity; |
310 | DbgEntity *getExistingAbstractEntity(const DINode *Node); |
311 | void createAbstractEntity(const DINode *Node, LexicalScope *Scope); |
312 | |
313 | /// Set the skeleton unit associated with this unit. |
314 | void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; } |
315 | |
316 | unsigned () const override { |
317 | // DWARF v5 added the DWO ID to the header for split/skeleton units. |
318 | unsigned DWOIdSize = |
319 | DD->getDwarfVersion() >= 5 && DD->useSplitDwarf() ? sizeof(uint64_t) |
320 | : 0; |
321 | return DwarfUnit::getHeaderSize() + DWOIdSize; |
322 | } |
323 | unsigned getLength() { |
324 | return Asm->getUnitLengthFieldByteSize() + // Length field |
325 | getHeaderSize() + getUnitDie().getSize(); |
326 | } |
327 | |
328 | void (bool UseOffsets) override; |
329 | |
330 | /// Add the DW_AT_addr_base attribute to the unit DIE. |
331 | void addAddrTableBase(); |
332 | |
333 | MCSymbol *getMacroLabelBegin() const { |
334 | return MacroLabelBegin; |
335 | } |
336 | |
337 | /// Add a new global name to the compile unit. |
338 | void addGlobalName(StringRef Name, const DIE &Die, |
339 | const DIScope *Context) override; |
340 | |
341 | /// Add a new global name present in a type unit to this compile unit. |
342 | void addGlobalNameForTypeUnit(StringRef Name, const DIScope *Context); |
343 | |
344 | /// Add a new global type to the compile unit. |
345 | void addGlobalTypeImpl(const DIType *Ty, const DIE &Die, |
346 | const DIScope *Context) override; |
347 | |
348 | /// Add a new global type present in a type unit to this compile unit. |
349 | void addGlobalTypeUnitType(const DIType *Ty, const DIScope *Context); |
350 | |
351 | const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; } |
352 | const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; } |
353 | |
354 | /// Add DW_AT_location attribute for a DbgVariable based on provided |
355 | /// MachineLocation. |
356 | void addVariableAddress(const DbgVariable &DV, DIE &Die, |
357 | MachineLocation Location); |
358 | /// Add an address attribute to a die based on the location provided. |
359 | void addAddress(DIE &Die, dwarf::Attribute Attribute, |
360 | const MachineLocation &Location); |
361 | |
362 | /// Start with the address based on the location provided, and generate the |
363 | /// DWARF information necessary to find the actual variable (navigating the |
364 | /// extra location information encoded in the type) based on the starting |
365 | /// location. Add the DWARF information to the die. |
366 | void addComplexAddress(const DIExpression *DIExpr, DIE &Die, |
367 | dwarf::Attribute Attribute, |
368 | const MachineLocation &Location); |
369 | |
370 | /// Add a Dwarf loclistptr attribute data and value. |
371 | void addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index); |
372 | |
373 | /// Add attributes to \p Var which reflect the common attributes of \p |
374 | /// VariableDie, namely those which are not dependant on the active variant. |
375 | void applyCommonDbgVariableAttributes(const DbgVariable &Var, |
376 | DIE &VariableDie); |
377 | |
378 | /// Add a Dwarf expression attribute data and value. |
379 | void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); |
380 | |
381 | void applySubprogramAttributesToDefinition(const DISubprogram *SP, |
382 | DIE &SPDie); |
383 | |
384 | void applyLabelAttributes(const DbgLabel &Label, DIE &LabelDie); |
385 | |
386 | /// getRanges - Get the list of ranges for this unit. |
387 | const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; } |
388 | SmallVector<RangeSpan, 2> takeRanges() { return std::move(CURanges); } |
389 | |
390 | void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; } |
391 | const MCSymbol *getBaseAddress() const { return BaseAddress; } |
392 | |
393 | uint64_t getDWOId() const { return DWOId; } |
394 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } |
395 | |
396 | bool hasDwarfPubSections() const; |
397 | |
398 | void addBaseTypeRef(DIEValueList &Die, int64_t Idx); |
399 | |
400 | MDNodeSetVector &getDeferredLocalDecls() { return DeferredLocalDecls; } |
401 | }; |
402 | |
403 | } // end namespace llvm |
404 | |
405 | #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H |
406 | |