aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
blob: 1b7ea2673ac09b25535b6c25db586ac6dda45738 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
//===- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing dwarf compile unit.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H

#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>

namespace llvm {

class AsmPrinter;
class DwarfFile;
class GlobalVariable;
class MCExpr;
class MCSymbol;
class MDNode;

class DwarfCompileUnit final : public DwarfUnit {
  /// A numeric ID unique among all CUs in the module
  unsigned UniqueID;
  bool HasRangeLists = false;

  /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
  /// the need to search for it in applyStmtList.
  DIE::value_iterator StmtListValue;

  /// Skeleton unit associated with this unit.
  DwarfCompileUnit *Skeleton = nullptr;

  /// The start of the unit within its section.
  MCSymbol *LabelBegin;

  /// The start of the unit macro info within macro section.
  MCSymbol *MacroLabelBegin;

  using ImportedEntityList = SmallVector<const MDNode *, 8>;
  using ImportedEntityMap = DenseMap<const MDNode *, ImportedEntityList>;

  ImportedEntityMap ImportedEntities;

  /// GlobalNames - A map of globally visible named entities for this unit.
  StringMap<const DIE *> GlobalNames;

  /// GlobalTypes - A map of globally visible types for this unit.
  StringMap<const DIE *> GlobalTypes;

  // List of ranges for a given compile unit.
  SmallVector<RangeSpan, 2> CURanges;

  // The base address of this unit, if any. Used for relative references in
  // ranges/locs.
  const MCSymbol *BaseAddress = nullptr;

  DenseMap<const MDNode *, DIE *> AbstractSPDies;
  DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;

  /// DWO ID for correlating skeleton and split units.
  uint64_t DWOId = 0;

  /// Construct a DIE for the given DbgVariable without initializing the
  /// DbgVariable's DIE reference.
  DIE *constructVariableDIEImpl(const DbgVariable &DV, bool Abstract);

  bool isDwoUnit() const override;

  DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
    if (isDwoUnit() && !DD->shareAcrossDWOCUs())
      return AbstractSPDies;
    return DU->getAbstractSPDies();
  }

  DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {
    if (isDwoUnit() && !DD->shareAcrossDWOCUs())
      return AbstractEntities;
    return DU->getAbstractEntities();
  }

  void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override;

public:
  DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A,
                   DwarfDebug *DW, DwarfFile *DWU);

  bool hasRangeLists() const { return HasRangeLists; }
  unsigned getUniqueID() const { return UniqueID; }

  DwarfCompileUnit *getSkeleton() const {
    return Skeleton;
  }

  bool includeMinimalInlineScopes() const;

  void initStmtList();

  /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE.
  void applyStmtList(DIE &D);

  /// A pair of GlobalVariable and DIExpression.
  struct GlobalExpr {
    const GlobalVariable *Var;
    const DIExpression *Expr;
  };

  struct BaseTypeRef {
    BaseTypeRef(unsigned BitSize, dwarf::TypeKind Encoding) :
      BitSize(BitSize), Encoding(Encoding) {}
    unsigned BitSize;
    dwarf::TypeKind Encoding;
    DIE *Die = nullptr;
  };

  std::vector<BaseTypeRef> ExprRefedBaseTypes;

  /// Get or create global variable DIE.
  DIE *
  getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV,
                               ArrayRef<GlobalExpr> GlobalExprs);

  DIE *getOrCreateCommonBlock(const DICommonBlock *CB,
                              ArrayRef<GlobalExpr> GlobalExprs);

  void addLocationAttribute(DIE *ToDIE, const DIGlobalVariable *GV,
                            ArrayRef<GlobalExpr> GlobalExprs);

  /// addLabelAddress - Add a dwarf label attribute data and value using
  /// either DW_FORM_addr or DW_FORM_GNU_addr_index.
  void addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
                       const MCSymbol *Label);

  /// addLocalLabelAddress - Add a dwarf label attribute data and value using
  /// DW_FORM_addr only.
  void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute,
                            const MCSymbol *Label);

  DwarfCompileUnit &getCU() override { return *this; }

  unsigned getOrCreateSourceID(const DIFile *File) override;

  void addImportedEntity(const DIImportedEntity* IE) {
    DIScope *Scope = IE->getScope();
    assert(Scope && "Invalid Scope encoding!");
    if (!isa<DILocalScope>(Scope))
      // No need to add imported enities that are not local declaration.
      return;

    auto *LocalScope = cast<DILocalScope>(Scope)->getNonLexicalBlockFileScope();
    ImportedEntities[LocalScope].push_back(IE);
  }

  /// addRange - Add an address range to the list of ranges for this unit.
  void addRange(RangeSpan Range);

  void attachLowHighPC(DIE &D, const MCSymbol *Begin, const MCSymbol *End);

  /// Find DIE for the given subprogram and attach appropriate
  /// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global
  /// variables in this scope then create and insert DIEs for these
  /// variables.
  DIE &updateSubprogramScopeDIE(const DISubprogram *SP);

  void constructScopeDIE(LexicalScope *Scope,
                         SmallVectorImpl<DIE *> &FinalChildren);

  /// A helper function to construct a RangeSpanList for a given
  /// lexical scope.
  void addScopeRangeList(DIE &ScopeDIE, SmallVector<RangeSpan, 2> Range);

  void attachRangesOrLowHighPC(DIE &D, SmallVector<RangeSpan, 2> Ranges);

  void attachRangesOrLowHighPC(DIE &D,
                               const SmallVectorImpl<InsnRange> &Ranges);

  /// This scope represents inlined body of a function. Construct
  /// DIE to represent this concrete inlined copy of the function.
  DIE *constructInlinedScopeDIE(LexicalScope *Scope);

  /// Construct new DW_TAG_lexical_block for this scope and
  /// attach DW_AT_low_pc/DW_AT_high_pc labels.
  DIE *constructLexicalScopeDIE(LexicalScope *Scope);

  /// constructVariableDIE - Construct a DIE for the given DbgVariable.
  DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false);

  DIE *constructVariableDIE(DbgVariable &DV, const LexicalScope &Scope,
                            DIE *&ObjectPointer);

  /// Construct a DIE for the given DbgLabel.
  DIE *constructLabelDIE(DbgLabel &DL, const LexicalScope &Scope);

  /// A helper function to create children of a Scope DIE.
  DIE *createScopeChildrenDIE(LexicalScope *Scope,
                              SmallVectorImpl<DIE *> &Children,
                              bool *HasNonScopeChildren = nullptr);

  void createBaseTypeDIEs();

  /// Construct a DIE for this subprogram scope.
  DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
                                   LexicalScope *Scope);

  DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);

  void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);

  /// This takes a DWARF 5 tag and returns it or a GNU analog.
  dwarf::Tag getDwarf5OrGNUTag(dwarf::Tag Tag) const;

  /// This takes a DWARF 5 attribute and returns it or a GNU analog.
  dwarf::Attribute getDwarf5OrGNUAttr(dwarf::Attribute Attr) const;

  /// This takes a DWARF 5 location atom and either returns it or a GNU analog.
  dwarf::LocationAtom getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const;

  /// Construct a call site entry DIE describing a call within \p Scope to a
  /// callee described by \p CalleeSP.
  /// \p IsTail specifies whether the call is a tail call.
  /// \p PCAddr (used for GDB + DWARF 4 tuning) points to the PC value after
  /// the call instruction.
  /// \p PCOffset (used for cases other than GDB + DWARF 4 tuning) must be
  /// non-zero for non-tail calls (in the case of non-gdb tuning, since for
  /// GDB + DWARF 5 tuning we still generate PC info for tail calls) or be the
  /// function-local offset to PC value after the call instruction.
  /// \p CallReg is a register location for an indirect call. For direct calls
  /// the \p CallReg is set to 0.
  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
                                 bool IsTail, const MCSymbol *PCAddr,
                                 const MCExpr *PCOffset, unsigned CallReg);
  /// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params
  /// were collected by the \ref collectCallSiteParameters.
  /// Note: The order of parameters does not matter, since debuggers recognize
  ///       call site parameters by the DW_AT_location attribute.
  void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
                                      SmallVector<DbgCallSiteParam, 4> &Params);

  /// Construct import_module DIE.
  DIE *constructImportedEntityDIE(const DIImportedEntity *Module);

  void finishSubprogramDefinition(const DISubprogram *SP);
  void finishEntityDefinition(const DbgEntity *Entity);

  /// Find abstract variable associated with Var.
  using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
  DbgEntity *getExistingAbstractEntity(const DINode *Node);
  void createAbstractEntity(const DINode *Node, LexicalScope *Scope);

  /// Set the skeleton unit associated with this unit.
  void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }

  unsigned getHeaderSize() const override {
    // DWARF v5 added the DWO ID to the header for split/skeleton units.
    unsigned DWOIdSize =
        DD->getDwarfVersion() >= 5 && DD->useSplitDwarf() ? sizeof(uint64_t)
                                                          : 0;
    return DwarfUnit::getHeaderSize() + DWOIdSize;
  }
  unsigned getLength() {
    return sizeof(uint32_t) + // Length field
        getHeaderSize() + getUnitDie().getSize();
  }

  void emitHeader(bool UseOffsets) override;

  /// Add the DW_AT_addr_base attribute to the unit DIE.
  void addAddrTableBase();

  MCSymbol *getLabelBegin() const {
    assert(getSection());
    return LabelBegin;
  }

  MCSymbol *getMacroLabelBegin() const {
    return MacroLabelBegin;
  }

  /// Add a new global name to the compile unit.
  void addGlobalName(StringRef Name, const DIE &Die,
                     const DIScope *Context) override;

  /// Add a new global name present in a type unit to this compile unit.
  void addGlobalNameForTypeUnit(StringRef Name, const DIScope *Context);

  /// Add a new global type to the compile unit.
  void addGlobalType(const DIType *Ty, const DIE &Die,
                     const DIScope *Context) override;

  /// Add a new global type present in a type unit to this compile unit.
  void addGlobalTypeUnitType(const DIType *Ty, const DIScope *Context);

  const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; }
  const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; }

  /// Add DW_AT_location attribute for a DbgVariable based on provided
  /// MachineLocation.
  void addVariableAddress(const DbgVariable &DV, DIE &Die,
                          MachineLocation Location);
  /// Add an address attribute to a die based on the location provided.
  void addAddress(DIE &Die, dwarf::Attribute Attribute,
                  const MachineLocation &Location);

  /// Start with the address based on the location provided, and generate the
  /// DWARF information necessary to find the actual variable (navigating the
  /// extra location information encoded in the type) based on the starting
  /// location.  Add the DWARF information to the die.
  void addComplexAddress(const DbgVariable &DV, DIE &Die,
                         dwarf::Attribute Attribute,
                         const MachineLocation &Location);

  /// Add a Dwarf loclistptr attribute data and value.
  void addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index);
  void applyVariableAttributes(const DbgVariable &Var, DIE &VariableDie);

  /// Add a Dwarf expression attribute data and value.
  void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr);

  /// Add an attribute containing an address expression to \p Die.
  void addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr);

  void applySubprogramAttributesToDefinition(const DISubprogram *SP,
                                             DIE &SPDie);

  void applyLabelAttributes(const DbgLabel &Label, DIE &LabelDie);

  /// getRanges - Get the list of ranges for this unit.
  const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
  SmallVector<RangeSpan, 2> takeRanges() { return std::move(CURanges); }

  void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; }
  const MCSymbol *getBaseAddress() const { return BaseAddress; }

  uint64_t getDWOId() const { return DWOId; }
  void setDWOId(uint64_t DwoId) { DWOId = DwoId; }

  bool hasDwarfPubSections() const;

  void addBaseTypeRef(DIEValueList &Die, int64_t Idx);
};

} // end namespace llvm

#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H