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