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() = default;
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 UnitTag = OutUnitDIE->getTag();
83 }
84 }
85
86 /// Returns unit DWARF tag.
87 dwarf::Tag getTag() const { return UnitTag; }
88
89 /// \defgroup Methods used to emit unit's debug info:
90 ///
91 /// @{
92 /// Emit unit's abbreviations.
93 Error emitAbbreviations();
94
95 /// Emit .debug_info section for unit DIEs.
96 Error emitDebugInfo(const Triple &TargetTriple);
97
98 /// Emit .debug_line section. When \p OrigRowIndices is non-empty it
99 /// must be the same length as \p OutLineTable.Rows and carry the input
100 /// row index each output row originated from (or an invalid-row
101 /// sentinel for manufactured end-of-range rows); if
102 /// \p RowIndexToSeqStartOffset is non-null, the emitter populates it
103 /// with an entry for each real row mapping input row index to the
104 /// byte offset of the DW_LNE_set_address that opens the output
105 /// sequence containing the row.
106 Error emitDebugLine(
107 const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable,
108 ArrayRef<uint64_t> OrigRowIndices = {},
109 DenseMap<uint64_t, uint64_t> *RowIndexToSeqStartOffset = nullptr);
110
111 /// Emit the .debug_str_offsets section for current unit.
112 Error emitDebugStringOffsetSection();
113 /// @}
114
115 /// \defgroup Methods used for reporting warnings and errors:
116 ///
117 /// @{
118 void warn(const Twine &Warning) { GlobalData.warn(Warning, Context: getUnitName()); }
119
120 void error(const Twine &Err) { GlobalData.warn(Warning: Err, Context: getUnitName()); }
121 /// @}
122
123 /// \defgroup Methods and data members used for building accelerator tables:
124 ///
125 /// @{
126
127 enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type };
128
129 /// This structure keeps fields which would be used for creating accelerator
130 /// table.
131 struct AccelInfo {
132 AccelInfo() {
133 AvoidForPubSections = false;
134 ObjcClassImplementation = false;
135 }
136
137 /// Name of the entry.
138 StringEntry *String = nullptr;
139
140 /// Output offset of the DIE this entry describes.
141 uint64_t OutOffset;
142
143 /// Output offset of the enclosing non-declaration DIE, used for the
144 /// DW_IDX_parent field of DWARF 5 name index entries.
145 std::optional<uint64_t> ParentOffset;
146
147 /// Hash of the fully qualified name.
148 uint32_t QualifiedNameHash = 0;
149
150 /// Tag of the DIE this entry describes.
151 dwarf::Tag Tag = dwarf::DW_TAG_null;
152
153 /// Type of this accelerator record.
154 AccelType Type = AccelType::None;
155
156 /// Avoid emitting this entry for pub sections.
157 bool AvoidForPubSections : 1;
158
159 /// Is this an ObjC class implementation?
160 bool ObjcClassImplementation : 1;
161 };
162
163 /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
164 void emitPubAccelerators();
165
166 /// Enumerates accelerator data.
167 virtual void
168 forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0;
169
170 /// @}
171
172 /// Returns index(inside .debug_str_offsets) of specified string.
173 virtual uint64_t getDebugStrIndex(const StringEntry *String) {
174 return DebugStringIndexMap.getValueIndex(Value: String);
175 }
176
177protected:
178 /// Emit single abbreviation entry.
179 void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
180 SectionDescriptor &AbbrevSection);
181
182 /// Emit single pubnames/pubtypes accelerator entry.
183 std::optional<uint64_t>
184 emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info,
185 std::optional<uint64_t> LengthOffset);
186
187 /// Unique ID for the unit.
188 unsigned ID = 0;
189
190 /// The name of this unit.
191 std::string UnitName;
192
193 /// The DW_AT_LLVM_sysroot of this unit.
194 std::string SysRoot;
195
196 /// If this is a Clang module, this holds the module's name.
197 std::string ClangModuleName;
198
199 uint64_t UnitSize = 0;
200
201 /// DWARF unit tag.
202 dwarf::Tag UnitTag = dwarf::DW_TAG_null;
203
204 /// true if current unit references_to/is_referenced by other unit.
205 std::atomic<bool> IsInterconnectedCU = {false};
206
207 /// FoldingSet that uniques the abbreviations.
208 FoldingSet<DIEAbbrev> AbbreviationsSet;
209
210 /// Storage for the unique Abbreviations.
211 std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
212
213 /// Output unit DIE.
214 DIE *OutUnitDIE = nullptr;
215
216 /// Cache for file names for this unit.
217 using FileNamesCache =
218 DenseMap<uint64_t, std::pair<std::string, std::string>>;
219 FileNamesCache FileNames;
220
221 /// Maps a string into the index inside .debug_str_offsets section.
222 IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
223};
224
225inline bool isODRLanguage(uint16_t Language) {
226 switch (Language) {
227 case dwarf::DW_LANG_C_plus_plus:
228 case dwarf::DW_LANG_C_plus_plus_03:
229 case dwarf::DW_LANG_C_plus_plus_11:
230 case dwarf::DW_LANG_C_plus_plus_14:
231 case dwarf::DW_LANG_ObjC_plus_plus:
232 return true;
233 default:
234 return false;
235 };
236
237 return false;
238}
239
240} // end of namespace parallel
241} // end of namespace dwarf_linker
242} // end of namespace llvm
243
244#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
245