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