xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
11db9f3b2SDimitry Andric //===- DWARFLinkerUnit.h ----------------------------------------*- C++ -*-===//
21db9f3b2SDimitry Andric //
31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric //
71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric 
91db9f3b2SDimitry Andric #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
101db9f3b2SDimitry Andric #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
111db9f3b2SDimitry Andric 
121db9f3b2SDimitry Andric #include "DWARFLinkerGlobalData.h"
131db9f3b2SDimitry Andric #include "OutputSections.h"
141db9f3b2SDimitry Andric #include "llvm/CodeGen/DIE.h"
157a6dacacSDimitry Andric #include "llvm/DWARFLinker/IndexedValuesMap.h"
161db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
171db9f3b2SDimitry Andric #include "llvm/DWARFLinker/StringPool.h"
181db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
191db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h"
201db9f3b2SDimitry Andric 
211db9f3b2SDimitry Andric namespace llvm {
221db9f3b2SDimitry Andric namespace dwarf_linker {
231db9f3b2SDimitry Andric namespace parallel {
241db9f3b2SDimitry Andric 
251db9f3b2SDimitry Andric class DwarfUnit;
261db9f3b2SDimitry Andric using MacroOffset2UnitMapTy = DenseMap<uint64_t, DwarfUnit *>;
271db9f3b2SDimitry Andric 
281db9f3b2SDimitry Andric /// Base class for all Dwarf units(Compile unit/Type table unit).
291db9f3b2SDimitry Andric class DwarfUnit : public OutputSections {
301db9f3b2SDimitry Andric public:
311db9f3b2SDimitry Andric   virtual ~DwarfUnit() {}
321db9f3b2SDimitry Andric   DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID,
331db9f3b2SDimitry Andric             StringRef ClangModuleName)
341db9f3b2SDimitry Andric       : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName),
351db9f3b2SDimitry Andric         OutUnitDIE(nullptr) {}
361db9f3b2SDimitry Andric 
371db9f3b2SDimitry Andric   /// Unique id of the unit.
381db9f3b2SDimitry Andric   unsigned getUniqueID() const { return ID; }
391db9f3b2SDimitry Andric 
401db9f3b2SDimitry Andric   /// Returns size of this(newly generated) compile unit.
411db9f3b2SDimitry Andric   uint64_t getUnitSize() const { return UnitSize; }
421db9f3b2SDimitry Andric 
431db9f3b2SDimitry Andric   /// Returns this unit name.
441db9f3b2SDimitry Andric   StringRef getUnitName() const { return UnitName; }
451db9f3b2SDimitry Andric 
461db9f3b2SDimitry Andric   /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
471db9f3b2SDimitry Andric   StringRef getSysRoot() { return SysRoot; }
481db9f3b2SDimitry Andric 
491db9f3b2SDimitry Andric   /// Return true if this compile unit is from Clang module.
501db9f3b2SDimitry Andric   bool isClangModule() const { return !ClangModuleName.empty(); }
511db9f3b2SDimitry Andric 
521db9f3b2SDimitry Andric   /// Return Clang module name;
531db9f3b2SDimitry Andric   const std::string &getClangModuleName() const { return ClangModuleName; }
541db9f3b2SDimitry Andric 
551db9f3b2SDimitry Andric   /// Return global data.
561db9f3b2SDimitry Andric   LinkingGlobalData &getGlobalData() { return GlobalData; }
571db9f3b2SDimitry Andric 
581db9f3b2SDimitry Andric   /// Returns true if unit is inter-connected(it references/referenced by other
591db9f3b2SDimitry Andric   /// unit).
601db9f3b2SDimitry Andric   bool isInterconnectedCU() const { return IsInterconnectedCU; }
611db9f3b2SDimitry Andric 
621db9f3b2SDimitry Andric   /// Mark this unit as inter-connected(it references/referenced by other unit).
631db9f3b2SDimitry Andric   void setInterconnectedCU() { IsInterconnectedCU = true; }
641db9f3b2SDimitry Andric 
651db9f3b2SDimitry Andric   /// Adds \p Abbrev into unit`s abbreviation table.
661db9f3b2SDimitry Andric   void assignAbbrev(DIEAbbrev &Abbrev);
671db9f3b2SDimitry Andric 
681db9f3b2SDimitry Andric   /// Returns abbreviations for this compile unit.
691db9f3b2SDimitry Andric   const std::vector<std::unique_ptr<DIEAbbrev>> &getAbbreviations() const {
701db9f3b2SDimitry Andric     return Abbreviations;
711db9f3b2SDimitry Andric   }
721db9f3b2SDimitry Andric 
731db9f3b2SDimitry Andric   /// Returns output unit DIE.
741db9f3b2SDimitry Andric   DIE *getOutUnitDIE() { return OutUnitDIE; }
751db9f3b2SDimitry Andric 
761db9f3b2SDimitry Andric   /// Set output unit DIE.
771db9f3b2SDimitry Andric   void setOutUnitDIE(DIE *UnitDie) {
781db9f3b2SDimitry Andric     OutUnitDIE = UnitDie;
791db9f3b2SDimitry Andric 
80*0fca6ea1SDimitry Andric     if (OutUnitDIE != nullptr) {
811db9f3b2SDimitry Andric       UnitSize = getDebugInfoHeaderSize() + OutUnitDIE->getSize();
82*0fca6ea1SDimitry Andric       UnitTag = OutUnitDIE->getTag();
831db9f3b2SDimitry Andric     }
84*0fca6ea1SDimitry Andric   }
85*0fca6ea1SDimitry Andric 
86*0fca6ea1SDimitry Andric   /// Returns unit DWARF tag.
87*0fca6ea1SDimitry Andric   dwarf::Tag getTag() const { return UnitTag; }
881db9f3b2SDimitry Andric 
891db9f3b2SDimitry Andric   /// \defgroup Methods used to emit unit's debug info:
901db9f3b2SDimitry Andric   ///
911db9f3b2SDimitry Andric   /// @{
921db9f3b2SDimitry Andric   /// Emit unit's abbreviations.
931db9f3b2SDimitry Andric   Error emitAbbreviations();
941db9f3b2SDimitry Andric 
951db9f3b2SDimitry Andric   /// Emit .debug_info section for unit DIEs.
961db9f3b2SDimitry Andric   Error emitDebugInfo(const Triple &TargetTriple);
971db9f3b2SDimitry Andric 
981db9f3b2SDimitry Andric   /// Emit .debug_line section.
991db9f3b2SDimitry Andric   Error emitDebugLine(const Triple &TargetTriple,
1001db9f3b2SDimitry Andric                       const DWARFDebugLine::LineTable &OutLineTable);
1011db9f3b2SDimitry Andric 
1021db9f3b2SDimitry Andric   /// Emit the .debug_str_offsets section for current unit.
1031db9f3b2SDimitry Andric   Error emitDebugStringOffsetSection();
1041db9f3b2SDimitry Andric   /// @}
1051db9f3b2SDimitry Andric 
1061db9f3b2SDimitry Andric   /// \defgroup Methods used for reporting warnings and errors:
1071db9f3b2SDimitry Andric   ///
1081db9f3b2SDimitry Andric   /// @{
1091db9f3b2SDimitry Andric   void warn(const Twine &Warning) { GlobalData.warn(Warning, getUnitName()); }
1101db9f3b2SDimitry Andric 
1111db9f3b2SDimitry Andric   void error(const Twine &Err) { GlobalData.warn(Err, getUnitName()); }
1121db9f3b2SDimitry Andric   /// @}
1131db9f3b2SDimitry Andric 
1141db9f3b2SDimitry Andric   /// \defgroup Methods and data members used for building accelerator tables:
1151db9f3b2SDimitry Andric   ///
1161db9f3b2SDimitry Andric   /// @{
1171db9f3b2SDimitry Andric 
1181db9f3b2SDimitry Andric   enum class AccelType : uint8_t { None, Name, Namespace, ObjC, Type };
1191db9f3b2SDimitry Andric 
1201db9f3b2SDimitry Andric   /// This structure keeps fields which would be used for creating accelerator
1211db9f3b2SDimitry Andric   /// table.
1221db9f3b2SDimitry Andric   struct AccelInfo {
1231db9f3b2SDimitry Andric     AccelInfo() {
1241db9f3b2SDimitry Andric       AvoidForPubSections = false;
1251db9f3b2SDimitry Andric       ObjcClassImplementation = false;
1261db9f3b2SDimitry Andric     }
1271db9f3b2SDimitry Andric 
1281db9f3b2SDimitry Andric     /// Name of the entry.
1291db9f3b2SDimitry Andric     StringEntry *String = nullptr;
1301db9f3b2SDimitry Andric 
1311db9f3b2SDimitry Andric     /// Output offset of the DIE this entry describes.
1321db9f3b2SDimitry Andric     uint64_t OutOffset;
1331db9f3b2SDimitry Andric 
1341db9f3b2SDimitry Andric     /// Hash of the fully qualified name.
1351db9f3b2SDimitry Andric     uint32_t QualifiedNameHash = 0;
1361db9f3b2SDimitry Andric 
1371db9f3b2SDimitry Andric     /// Tag of the DIE this entry describes.
1381db9f3b2SDimitry Andric     dwarf::Tag Tag = dwarf::DW_TAG_null;
1391db9f3b2SDimitry Andric 
1401db9f3b2SDimitry Andric     /// Type of this accelerator record.
1411db9f3b2SDimitry Andric     AccelType Type = AccelType::None;
1421db9f3b2SDimitry Andric 
1431db9f3b2SDimitry Andric     /// Avoid emitting this entry for pub sections.
1441db9f3b2SDimitry Andric     bool AvoidForPubSections : 1;
1451db9f3b2SDimitry Andric 
1461db9f3b2SDimitry Andric     /// Is this an ObjC class implementation?
1471db9f3b2SDimitry Andric     bool ObjcClassImplementation : 1;
1481db9f3b2SDimitry Andric   };
1491db9f3b2SDimitry Andric 
1501db9f3b2SDimitry Andric   /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
1511db9f3b2SDimitry Andric   void emitPubAccelerators();
1521db9f3b2SDimitry Andric 
1531db9f3b2SDimitry Andric   /// Enumerates accelerator data.
1541db9f3b2SDimitry Andric   virtual void
1551db9f3b2SDimitry Andric   forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0;
1561db9f3b2SDimitry Andric 
1571db9f3b2SDimitry Andric   /// @}
1581db9f3b2SDimitry Andric 
1591db9f3b2SDimitry Andric   /// Returns index(inside .debug_str_offsets) of specified string.
1601db9f3b2SDimitry Andric   virtual uint64_t getDebugStrIndex(const StringEntry *String) {
1611db9f3b2SDimitry Andric     return DebugStringIndexMap.getValueIndex(String);
1621db9f3b2SDimitry Andric   }
1631db9f3b2SDimitry Andric 
1641db9f3b2SDimitry Andric protected:
1651db9f3b2SDimitry Andric   /// Emit single abbreviation entry.
1661db9f3b2SDimitry Andric   void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
1671db9f3b2SDimitry Andric                             SectionDescriptor &AbbrevSection);
1681db9f3b2SDimitry Andric 
1691db9f3b2SDimitry Andric   /// Emit single pubnames/pubtypes accelerator entry.
1701db9f3b2SDimitry Andric   std::optional<uint64_t>
1711db9f3b2SDimitry Andric   emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info,
1721db9f3b2SDimitry Andric                           std::optional<uint64_t> LengthOffset);
1731db9f3b2SDimitry Andric 
1741db9f3b2SDimitry Andric   /// Unique ID for the unit.
1751db9f3b2SDimitry Andric   unsigned ID = 0;
1761db9f3b2SDimitry Andric 
1771db9f3b2SDimitry Andric   /// The name of this unit.
1781db9f3b2SDimitry Andric   std::string UnitName;
1791db9f3b2SDimitry Andric 
1801db9f3b2SDimitry Andric   /// The DW_AT_LLVM_sysroot of this unit.
1811db9f3b2SDimitry Andric   std::string SysRoot;
1821db9f3b2SDimitry Andric 
1831db9f3b2SDimitry Andric   /// If this is a Clang module, this holds the module's name.
1841db9f3b2SDimitry Andric   std::string ClangModuleName;
1851db9f3b2SDimitry Andric 
1861db9f3b2SDimitry Andric   uint64_t UnitSize = 0;
1871db9f3b2SDimitry Andric 
188*0fca6ea1SDimitry Andric   /// DWARF unit tag.
189*0fca6ea1SDimitry Andric   dwarf::Tag UnitTag = dwarf::DW_TAG_null;
190*0fca6ea1SDimitry Andric 
1911db9f3b2SDimitry Andric   /// true if current unit references_to/is_referenced by other unit.
1921db9f3b2SDimitry Andric   std::atomic<bool> IsInterconnectedCU = {false};
1931db9f3b2SDimitry Andric 
1941db9f3b2SDimitry Andric   /// FoldingSet that uniques the abbreviations.
1951db9f3b2SDimitry Andric   FoldingSet<DIEAbbrev> AbbreviationsSet;
1961db9f3b2SDimitry Andric 
1971db9f3b2SDimitry Andric   /// Storage for the unique Abbreviations.
1981db9f3b2SDimitry Andric   std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
1991db9f3b2SDimitry Andric 
2001db9f3b2SDimitry Andric   /// Output unit DIE.
2011db9f3b2SDimitry Andric   DIE *OutUnitDIE = nullptr;
2021db9f3b2SDimitry Andric 
2031db9f3b2SDimitry Andric   /// Cache for file names for this unit.
2041db9f3b2SDimitry Andric   using FileNamesCache =
2051db9f3b2SDimitry Andric       DenseMap<uint64_t, std::pair<std::string, std::string>>;
2061db9f3b2SDimitry Andric   FileNamesCache FileNames;
2071db9f3b2SDimitry Andric 
2081db9f3b2SDimitry Andric   /// Maps a string into the index inside .debug_str_offsets section.
2091db9f3b2SDimitry Andric   IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
2101db9f3b2SDimitry Andric };
2111db9f3b2SDimitry Andric 
2121db9f3b2SDimitry Andric inline bool isODRLanguage(uint16_t Language) {
2131db9f3b2SDimitry Andric   switch (Language) {
2141db9f3b2SDimitry Andric   case dwarf::DW_LANG_C_plus_plus:
2151db9f3b2SDimitry Andric   case dwarf::DW_LANG_C_plus_plus_03:
2161db9f3b2SDimitry Andric   case dwarf::DW_LANG_C_plus_plus_11:
2171db9f3b2SDimitry Andric   case dwarf::DW_LANG_C_plus_plus_14:
2181db9f3b2SDimitry Andric   case dwarf::DW_LANG_ObjC_plus_plus:
2191db9f3b2SDimitry Andric     return true;
2201db9f3b2SDimitry Andric   default:
2211db9f3b2SDimitry Andric     return false;
2221db9f3b2SDimitry Andric   };
2231db9f3b2SDimitry Andric 
2241db9f3b2SDimitry Andric   return false;
2251db9f3b2SDimitry Andric }
2261db9f3b2SDimitry Andric 
2271db9f3b2SDimitry Andric } // end of namespace parallel
2281db9f3b2SDimitry Andric } // end of namespace dwarf_linker
2291db9f3b2SDimitry Andric } // end of namespace llvm
2301db9f3b2SDimitry Andric 
2311db9f3b2SDimitry Andric #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERUNIT_H
232