1//===- DWARFLinkerUnit.h ----------------------------------------*- 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#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
10#define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
11
12#include "DWARFLinkerGlobalData.h"
13#include "OutputSections.h"
14#include "llvm/CodeGen/DIE.h"
15#include "llvm/DWARFLinker/IndexedValuesMap.h"
16#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
17#include "llvm/DWARFLinker/StringPool.h"
18#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
19#include "llvm/Support/LEB128.h"
20
21namespace llvm {
22namespace dwarf_linker {
23namespace parallel {
24
25class DwarfUnit;
26using MacroOffset2UnitMapTy = DenseMap<uint64_t, DwarfUnit *>;
27
28/// Base class for all Dwarf units(Compile unit/Type table unit).
29class DwarfUnit : public OutputSections {
30public:
31  virtual ~DwarfUnit() {}
32  DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID,
33            StringRef ClangModuleName)
34      : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName),
35        OutUnitDIE(nullptr) {}
36
37  /// Unique id of the unit.
38  unsigned getUniqueID() const { return ID; }
39
40  /// Returns size of this(newly generated) compile unit.
41  uint64_t getUnitSize() const { return UnitSize; }
42
43  /// Returns this unit name.
44  StringRef getUnitName() const { return UnitName; }
45
46  /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
47  StringRef getSysRoot() { return SysRoot; }
48
49  /// Return true if this compile unit is from Clang module.
50  bool isClangModule() const { return !ClangModuleName.empty(); }
51
52  /// Return Clang module name;
53  const std::string &getClangModuleName() const { return ClangModuleName; }
54
55  /// Return global data.
56  LinkingGlobalData &getGlobalData() { return GlobalData; }
57
58  /// Returns true if unit is inter-connected(it references/referenced by other
59  /// unit).
60  bool isInterconnectedCU() const { return IsInterconnectedCU; }
61
62  /// Mark this unit as inter-connected(it references/referenced by other unit).
63  void setInterconnectedCU() { IsInterconnectedCU = true; }
64
65  /// Adds \p Abbrev into unit`s abbreviation table.
66  void assignAbbrev(DIEAbbrev &Abbrev);
67
68  /// Returns abbreviations for this compile unit.
69  const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const {
70    return Abbreviations;
71  }
72
73  /// Returns output unit DIE.
74  DIE *getOutUnitDIE() { return OutUnitDIE; }
75
76  /// Set output unit DIE.
77  void setOutUnitDIE(DIE *UnitDie) {
78    OutUnitDIE = UnitDie;
79
80    if (OutUnitDIE != nullptr)
81      UnitSize = getDebugInfoHeaderSize() + OutUnitDIE->getSize();
82  }
83
84  /// \defgroup Methods used to emit unit's debug info:
85  ///
86  /// @{
87  /// Emit unit's abbreviations.
88  Error emitAbbreviations();
89
90  /// Emit .debug_info section for unit DIEs.
91  Error emitDebugInfo(const Triple &TargetTriple);
92
93  /// Emit .debug_line section.
94  Error emitDebugLine(const Triple &TargetTriple,
95                      const DWARFDebugLine::LineTable &OutLineTable);
96
97  /// Emit the .debug_str_offsets section for current unit.
98  Error emitDebugStringOffsetSection();
99  /// @}
100
101  /// \defgroup Methods used for reporting warnings and errors:
102  ///
103  /// @{
104  void warn(const Twine &Warning) { GlobalData.warn(Warning, getUnitName()); }
105
106  void error(const Twine &Err) { GlobalData.warn(Err, getUnitName()); }
107  /// @}
108
109  /// \defgroup Methods and data members used for building accelerator tables:
110  ///
111  /// @{
112
113  enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type };
114
115  /// This structure keeps fields which would be used for creating accelerator
116  /// table.
117  struct AccelInfo {
118    AccelInfo() {
119      AvoidForPubSections = false;
120      ObjcClassImplementation = false;
121    }
122
123    /// Name of the entry.
124    StringEntry *String = nullptr;
125
126    /// Output offset of the DIE this entry describes.
127    uint64_t OutOffset;
128
129    /// Hash of the fully qualified name.
130    uint32_t QualifiedNameHash = 0;
131
132    /// Tag of the DIE this entry describes.
133    dwarf::Tag Tag = dwarf::DW_TAG_null;
134
135    /// Type of this accelerator record.
136    AccelType Type = AccelType::None;
137
138    /// Avoid emitting this entry for pub sections.
139    bool AvoidForPubSections : 1;
140
141    /// Is this an ObjC class implementation?
142    bool ObjcClassImplementation : 1;
143  };
144
145  /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
146  void emitPubAccelerators();
147
148  /// Enumerates accelerator data.
149  virtual void
150  forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0;
151
152  /// @}
153
154  /// Returns index(inside .debug_str_offsets) of specified string.
155  virtual uint64_t getDebugStrIndex(const StringEntry *String) {
156    return DebugStringIndexMap.getValueIndex(String);
157  }
158
159protected:
160  /// Emit single abbreviation entry.
161  void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
162                            SectionDescriptor &AbbrevSection);
163
164  /// Emit single pubnames/pubtypes accelerator entry.
165  std::optional<uint64_t>
166  emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info,
167                          std::optional<uint64_t> LengthOffset);
168
169  /// Unique ID for the unit.
170  unsigned ID = 0;
171
172  /// The name of this unit.
173  std::string UnitName;
174
175  /// The DW_AT_LLVM_sysroot of this unit.
176  std::string SysRoot;
177
178  /// If this is a Clang module, this holds the module's name.
179  std::string ClangModuleName;
180
181  uint64_t UnitSize = 0;
182
183  /// true if current unit references_to/is_referenced by other unit.
184  std::atomic<bool> IsInterconnectedCU = {false};
185
186  /// FoldingSet that uniques the abbreviations.
187  FoldingSet<DIEAbbrev> AbbreviationsSet;
188
189  /// Storage for the unique Abbreviations.
190  std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
191
192  /// Output unit DIE.
193  DIE *OutUnitDIE = nullptr;
194
195  /// Cache for file names for this unit.
196  using FileNamesCache =
197      DenseMap<uint64_t, std::pair<std::string, std::string>>;
198  FileNamesCache FileNames;
199
200  /// Maps a string into the index inside .debug_str_offsets section.
201  IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
202};
203
204inline bool isODRLanguage(uint16_t Language) {
205  switch (Language) {
206  case dwarf::DW_LANG_C_plus_plus:
207  case dwarf::DW_LANG_C_plus_plus_03:
208  case dwarf::DW_LANG_C_plus_plus_11:
209  case dwarf::DW_LANG_C_plus_plus_14:
210  case dwarf::DW_LANG_ObjC_plus_plus:
211    return true;
212  default:
213    return false;
214  };
215
216  return false;
217}
218
219} // end of namespace parallel
220} // end of namespace dwarf_linker
221} // end of namespace llvm
222
223#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
224