xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
11db9f3b2SDimitry Andric //===- DWARFLinkerCompileUnit.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_DWARFLINKERCOMPILEUNIT_H
101db9f3b2SDimitry Andric #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
111db9f3b2SDimitry Andric 
121db9f3b2SDimitry Andric #include "DWARFLinkerUnit.h"
131db9f3b2SDimitry Andric #include "llvm/DWARFLinker/DWARFFile.h"
141db9f3b2SDimitry Andric #include <optional>
151db9f3b2SDimitry Andric 
161db9f3b2SDimitry Andric namespace llvm {
171db9f3b2SDimitry Andric namespace dwarf_linker {
181db9f3b2SDimitry Andric namespace parallel {
191db9f3b2SDimitry Andric 
201db9f3b2SDimitry Andric using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
211db9f3b2SDimitry Andric 
221db9f3b2SDimitry Andric struct AttributesInfo;
231db9f3b2SDimitry Andric class SyntheticTypeNameBuilder;
241db9f3b2SDimitry Andric class DIEGenerator;
251db9f3b2SDimitry Andric class TypeUnit;
261db9f3b2SDimitry Andric class DependencyTracker;
271db9f3b2SDimitry Andric 
281db9f3b2SDimitry Andric class CompileUnit;
291db9f3b2SDimitry Andric 
301db9f3b2SDimitry Andric /// This is a helper structure which keeps a debug info entry
311db9f3b2SDimitry Andric /// with it's containing compilation unit.
321db9f3b2SDimitry Andric struct UnitEntryPairTy {
331db9f3b2SDimitry Andric   UnitEntryPairTy() = default;
UnitEntryPairTyUnitEntryPairTy341db9f3b2SDimitry Andric   UnitEntryPairTy(CompileUnit *CU, const DWARFDebugInfoEntry *DieEntry)
351db9f3b2SDimitry Andric       : CU(CU), DieEntry(DieEntry) {}
361db9f3b2SDimitry Andric 
371db9f3b2SDimitry Andric   CompileUnit *CU = nullptr;
381db9f3b2SDimitry Andric   const DWARFDebugInfoEntry *DieEntry = nullptr;
391db9f3b2SDimitry Andric 
401db9f3b2SDimitry Andric   UnitEntryPairTy getNamespaceOrigin();
411db9f3b2SDimitry Andric   std::optional<UnitEntryPairTy> getParent();
421db9f3b2SDimitry Andric };
431db9f3b2SDimitry Andric 
441db9f3b2SDimitry Andric enum ResolveInterCUReferencesMode : bool {
451db9f3b2SDimitry Andric   Resolve = true,
461db9f3b2SDimitry Andric   AvoidResolving = false,
471db9f3b2SDimitry Andric };
481db9f3b2SDimitry Andric 
491db9f3b2SDimitry Andric /// Stores all information related to a compile unit, be it in its original
501db9f3b2SDimitry Andric /// instance of the object file or its brand new cloned and generated DIE tree.
511db9f3b2SDimitry Andric /// NOTE: we need alignment of at least 8 bytes as we use
521db9f3b2SDimitry Andric ///       PointerIntPair<CompileUnit *, 3> in the DependencyTracker.h
531db9f3b2SDimitry Andric class alignas(8) CompileUnit : public DwarfUnit {
541db9f3b2SDimitry Andric public:
551db9f3b2SDimitry Andric   /// The stages of new compile unit processing.
561db9f3b2SDimitry Andric   enum class Stage : uint8_t {
571db9f3b2SDimitry Andric     /// Created, linked with input DWARF file.
581db9f3b2SDimitry Andric     CreatedNotLoaded = 0,
591db9f3b2SDimitry Andric 
601db9f3b2SDimitry Andric     /// Input DWARF is loaded.
611db9f3b2SDimitry Andric     Loaded,
621db9f3b2SDimitry Andric 
631db9f3b2SDimitry Andric     /// Input DWARF is analysed(DIEs pointing to the real code section are
641db9f3b2SDimitry Andric     /// discovered, type names are assigned if ODR is requested).
651db9f3b2SDimitry Andric     LivenessAnalysisDone,
661db9f3b2SDimitry Andric 
671db9f3b2SDimitry Andric     /// Check if dependencies have incompatible placement.
681db9f3b2SDimitry Andric     /// If that is the case modify placement to be compatible.
691db9f3b2SDimitry Andric     UpdateDependenciesCompleteness,
701db9f3b2SDimitry Andric 
711db9f3b2SDimitry Andric     /// Type names assigned to DIEs.
721db9f3b2SDimitry Andric     TypeNamesAssigned,
731db9f3b2SDimitry Andric 
741db9f3b2SDimitry Andric     /// Output DWARF is generated.
751db9f3b2SDimitry Andric     Cloned,
761db9f3b2SDimitry Andric 
771db9f3b2SDimitry Andric     /// Offsets inside patch records are updated.
781db9f3b2SDimitry Andric     PatchesUpdated,
791db9f3b2SDimitry Andric 
801db9f3b2SDimitry Andric     /// Resources(Input DWARF, Output DWARF tree) are released.
811db9f3b2SDimitry Andric     Cleaned,
821db9f3b2SDimitry Andric 
831db9f3b2SDimitry Andric     /// Compile Unit should be skipped
841db9f3b2SDimitry Andric     Skipped
851db9f3b2SDimitry Andric   };
861db9f3b2SDimitry Andric 
871db9f3b2SDimitry Andric   CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
881db9f3b2SDimitry Andric               StringRef ClangModuleName, DWARFFile &File,
891db9f3b2SDimitry Andric               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
901db9f3b2SDimitry Andric               llvm::endianness Endianess);
911db9f3b2SDimitry Andric 
921db9f3b2SDimitry Andric   CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, unsigned ID,
931db9f3b2SDimitry Andric               StringRef ClangModuleName, DWARFFile &File,
941db9f3b2SDimitry Andric               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
951db9f3b2SDimitry Andric               llvm::endianness Endianess);
961db9f3b2SDimitry Andric 
971db9f3b2SDimitry Andric   /// Returns stage of overall processing.
getStage()981db9f3b2SDimitry Andric   Stage getStage() const { return Stage; }
991db9f3b2SDimitry Andric 
1001db9f3b2SDimitry Andric   /// Set stage of overall processing.
setStage(Stage Stage)1011db9f3b2SDimitry Andric   void setStage(Stage Stage) { this->Stage = Stage; }
1021db9f3b2SDimitry Andric 
1031db9f3b2SDimitry Andric   /// Loads unit line table.
1041db9f3b2SDimitry Andric   void loadLineTable();
1051db9f3b2SDimitry Andric 
1061db9f3b2SDimitry Andric   /// Returns name of the file for the \p FileIdx
1071db9f3b2SDimitry Andric   /// from the unit`s line table.
1081db9f3b2SDimitry Andric   StringEntry *getFileName(unsigned FileIdx, StringPool &GlobalStrings);
1091db9f3b2SDimitry Andric 
1101db9f3b2SDimitry Andric   /// Returns DWARFFile containing this compile unit.
getContaingFile()1111db9f3b2SDimitry Andric   const DWARFFile &getContaingFile() const { return File; }
1121db9f3b2SDimitry Andric 
1131db9f3b2SDimitry Andric   /// Load DIEs of input compilation unit. \returns true if input DIEs
1141db9f3b2SDimitry Andric   /// successfully loaded.
1151db9f3b2SDimitry Andric   bool loadInputDIEs();
1161db9f3b2SDimitry Andric 
1171db9f3b2SDimitry Andric   /// Reset compile units data(results of liveness analysis, clonning)
1181db9f3b2SDimitry Andric   /// if current stage greater than Stage::Loaded. We need to reset data
1191db9f3b2SDimitry Andric   /// as we are going to repeat stages.
1201db9f3b2SDimitry Andric   void maybeResetToLoadedStage();
1211db9f3b2SDimitry Andric 
1221db9f3b2SDimitry Andric   /// Collect references to parseable Swift interfaces in imported
1231db9f3b2SDimitry Andric   /// DW_TAG_module blocks.
1241db9f3b2SDimitry Andric   void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry);
1251db9f3b2SDimitry Andric 
1261db9f3b2SDimitry Andric   /// Navigate DWARF tree and set die properties.
analyzeDWARFStructure()1271db9f3b2SDimitry Andric   void analyzeDWARFStructure() {
1281db9f3b2SDimitry Andric     analyzeDWARFStructureRec(getUnitDIE().getDebugInfoEntry(), false);
1291db9f3b2SDimitry Andric   }
1301db9f3b2SDimitry Andric 
1311db9f3b2SDimitry Andric   /// Cleanup unneeded resources after compile unit is cloned.
1321db9f3b2SDimitry Andric   void cleanupDataAfterClonning();
1331db9f3b2SDimitry Andric 
1341db9f3b2SDimitry Andric   /// After cloning stage the output DIEs offsets are deallocated.
1351db9f3b2SDimitry Andric   /// This method copies output offsets for referenced DIEs into DIEs patches.
1361db9f3b2SDimitry Andric   void updateDieRefPatchesWithClonedOffsets();
1371db9f3b2SDimitry Andric 
1381db9f3b2SDimitry Andric   /// Search for subprograms and variables referencing live code and discover
1391db9f3b2SDimitry Andric   /// dependend DIEs. Mark live DIEs, set placement for DIEs.
1401db9f3b2SDimitry Andric   bool resolveDependenciesAndMarkLiveness(
1411db9f3b2SDimitry Andric       bool InterCUProcessingStarted,
1421db9f3b2SDimitry Andric       std::atomic<bool> &HasNewInterconnectedCUs);
1431db9f3b2SDimitry Andric 
1441db9f3b2SDimitry Andric   /// Check dependend DIEs for incompatible placement.
1451db9f3b2SDimitry Andric   /// Make placement to be consistent.
1461db9f3b2SDimitry Andric   bool updateDependenciesCompleteness();
1471db9f3b2SDimitry Andric 
1481db9f3b2SDimitry Andric   /// Check DIEs to have a consistent marking(keep marking, placement marking).
1491db9f3b2SDimitry Andric   void verifyDependencies();
1501db9f3b2SDimitry Andric 
1511db9f3b2SDimitry Andric   /// Search for type entries and assign names.
1521db9f3b2SDimitry Andric   Error assignTypeNames(TypePool &TypePoolRef);
1531db9f3b2SDimitry Andric 
1541db9f3b2SDimitry Andric   /// Kinds of placement for the output die.
1551db9f3b2SDimitry Andric   enum DieOutputPlacement : uint8_t {
1561db9f3b2SDimitry Andric     NotSet = 0,
1571db9f3b2SDimitry Andric 
1581db9f3b2SDimitry Andric     /// Corresponding DIE goes to the type table only.
1591db9f3b2SDimitry Andric     TypeTable = 1,
1601db9f3b2SDimitry Andric 
1611db9f3b2SDimitry Andric     /// Corresponding DIE goes to the plain dwarf only.
1621db9f3b2SDimitry Andric     PlainDwarf = 2,
1631db9f3b2SDimitry Andric 
1641db9f3b2SDimitry Andric     /// Corresponding DIE goes to type table and to plain dwarf.
1651db9f3b2SDimitry Andric     Both = 3,
1661db9f3b2SDimitry Andric   };
1671db9f3b2SDimitry Andric 
1681db9f3b2SDimitry Andric   /// Information gathered about source DIEs.
1691db9f3b2SDimitry Andric   struct DIEInfo {
1701db9f3b2SDimitry Andric     DIEInfo() = default;
DIEInfoDIEInfo1711db9f3b2SDimitry Andric     DIEInfo(const DIEInfo &Other) { Flags = Other.Flags.load(); }
1721db9f3b2SDimitry Andric     DIEInfo &operator=(const DIEInfo &Other) {
1731db9f3b2SDimitry Andric       Flags = Other.Flags.load();
1741db9f3b2SDimitry Andric       return *this;
1751db9f3b2SDimitry Andric     }
1761db9f3b2SDimitry Andric 
1771db9f3b2SDimitry Andric     /// Data member keeping various flags.
1781db9f3b2SDimitry Andric     std::atomic<uint16_t> Flags = {0};
1791db9f3b2SDimitry Andric 
1801db9f3b2SDimitry Andric     /// \returns Placement kind for the corresponding die.
getPlacementDIEInfo1811db9f3b2SDimitry Andric     DieOutputPlacement getPlacement() const {
1821db9f3b2SDimitry Andric       return DieOutputPlacement(Flags & 0x7);
1831db9f3b2SDimitry Andric     }
1841db9f3b2SDimitry Andric 
1851db9f3b2SDimitry Andric     /// Sets Placement kind for the corresponding die.
setPlacementDIEInfo1861db9f3b2SDimitry Andric     void setPlacement(DieOutputPlacement Placement) {
1871db9f3b2SDimitry Andric       auto InputData = Flags.load();
1881db9f3b2SDimitry Andric       while (!Flags.compare_exchange_weak(InputData,
1891db9f3b2SDimitry Andric                                           ((InputData & ~0x7) | Placement))) {
1901db9f3b2SDimitry Andric       }
1911db9f3b2SDimitry Andric     }
1921db9f3b2SDimitry Andric 
1931db9f3b2SDimitry Andric     /// Unsets Placement kind for the corresponding die.
unsetPlacementDIEInfo1941db9f3b2SDimitry Andric     void unsetPlacement() {
1951db9f3b2SDimitry Andric       auto InputData = Flags.load();
1961db9f3b2SDimitry Andric       while (!Flags.compare_exchange_weak(InputData, (InputData & ~0x7))) {
1971db9f3b2SDimitry Andric       }
1981db9f3b2SDimitry Andric     }
1991db9f3b2SDimitry Andric 
2001db9f3b2SDimitry Andric     /// Sets Placement kind for the corresponding die.
setPlacementIfUnsetDIEInfo2011db9f3b2SDimitry Andric     bool setPlacementIfUnset(DieOutputPlacement Placement) {
2021db9f3b2SDimitry Andric       auto InputData = Flags.load();
2031db9f3b2SDimitry Andric       if ((InputData & 0x7) == NotSet)
2041db9f3b2SDimitry Andric         if (Flags.compare_exchange_weak(InputData, (InputData | Placement)))
2051db9f3b2SDimitry Andric           return true;
2061db9f3b2SDimitry Andric 
2071db9f3b2SDimitry Andric       return false;
2081db9f3b2SDimitry Andric     }
2091db9f3b2SDimitry Andric 
2101db9f3b2SDimitry Andric #define SINGLE_FLAG_METHODS_SET(Name, Value)                                   \
2111db9f3b2SDimitry Andric   bool get##Name() const { return Flags & Value; }                             \
2121db9f3b2SDimitry Andric   void set##Name() {                                                           \
2131db9f3b2SDimitry Andric     auto InputData = Flags.load();                                             \
2141db9f3b2SDimitry Andric     while (!Flags.compare_exchange_weak(InputData, InputData | Value)) {       \
2151db9f3b2SDimitry Andric     }                                                                          \
2161db9f3b2SDimitry Andric   }                                                                            \
2171db9f3b2SDimitry Andric   void unset##Name() {                                                         \
2181db9f3b2SDimitry Andric     auto InputData = Flags.load();                                             \
2191db9f3b2SDimitry Andric     while (!Flags.compare_exchange_weak(InputData, InputData & ~Value)) {      \
2201db9f3b2SDimitry Andric     }                                                                          \
2211db9f3b2SDimitry Andric   }
2221db9f3b2SDimitry Andric 
2231db9f3b2SDimitry Andric     /// DIE is a part of the linked output.
2241db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(Keep, 0x08)
2251db9f3b2SDimitry Andric 
2261db9f3b2SDimitry Andric     /// DIE has children which are part of the linked output.
2271db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10)
2281db9f3b2SDimitry Andric 
2291db9f3b2SDimitry Andric     /// DIE has children which are part of the type table.
2301db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20)
2311db9f3b2SDimitry Andric 
2321db9f3b2SDimitry Andric     /// DIE is in module scope.
2331db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40)
2341db9f3b2SDimitry Andric 
2351db9f3b2SDimitry Andric     /// DIE is in function scope.
2361db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80)
2371db9f3b2SDimitry Andric 
2381db9f3b2SDimitry Andric     /// DIE is in anonymous namespace scope.
2391db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100)
2401db9f3b2SDimitry Andric 
2411db9f3b2SDimitry Andric     /// DIE is available for ODR type deduplication.
2421db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200)
2431db9f3b2SDimitry Andric 
2441db9f3b2SDimitry Andric     /// Track liveness for the DIE.
2451db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400)
2461db9f3b2SDimitry Andric 
2471db9f3b2SDimitry Andric     /// Track liveness for the DIE.
2481db9f3b2SDimitry Andric     SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800)
2491db9f3b2SDimitry Andric 
unsetFlagsWhichSetDuringLiveAnalysisDIEInfo2501db9f3b2SDimitry Andric     void unsetFlagsWhichSetDuringLiveAnalysis() {
2511db9f3b2SDimitry Andric       auto InputData = Flags.load();
2521db9f3b2SDimitry Andric       while (!Flags.compare_exchange_weak(
2531db9f3b2SDimitry Andric           InputData, InputData & ~(0x7 | 0x8 | 0x10 | 0x20))) {
2541db9f3b2SDimitry Andric       }
2551db9f3b2SDimitry Andric     }
2561db9f3b2SDimitry Andric 
2571db9f3b2SDimitry Andric     /// Erase all flags.
eraseDataDIEInfo2581db9f3b2SDimitry Andric     void eraseData() { Flags = 0; }
2591db9f3b2SDimitry Andric 
2601db9f3b2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2611db9f3b2SDimitry Andric     LLVM_DUMP_METHOD void dump();
2621db9f3b2SDimitry Andric #endif
2631db9f3b2SDimitry Andric 
needToPlaceInTypeTableDIEInfo2641db9f3b2SDimitry Andric     bool needToPlaceInTypeTable() const {
2651db9f3b2SDimitry Andric       return (getKeep() && (getPlacement() == CompileUnit::TypeTable ||
2661db9f3b2SDimitry Andric                             getPlacement() == CompileUnit::Both)) ||
2671db9f3b2SDimitry Andric              getKeepTypeChildren();
2681db9f3b2SDimitry Andric     }
2691db9f3b2SDimitry Andric 
needToKeepInPlainDwarfDIEInfo2701db9f3b2SDimitry Andric     bool needToKeepInPlainDwarf() const {
2711db9f3b2SDimitry Andric       return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf ||
2721db9f3b2SDimitry Andric                             getPlacement() == CompileUnit::Both)) ||
2731db9f3b2SDimitry Andric              getKeepPlainChildren();
2741db9f3b2SDimitry Andric     }
2751db9f3b2SDimitry Andric   };
2761db9f3b2SDimitry Andric 
2771db9f3b2SDimitry Andric   /// \defgroup Group of functions returning DIE info.
2781db9f3b2SDimitry Andric   ///
2791db9f3b2SDimitry Andric   /// @{
2801db9f3b2SDimitry Andric 
2811db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
2821db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDIEInfo(unsigned Idx)2831db9f3b2SDimitry Andric   DIEInfo &getDIEInfo(unsigned Idx) { return DieInfoArray[Idx]; }
2841db9f3b2SDimitry Andric 
2851db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
2861db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDIEInfo(unsigned Idx)2871db9f3b2SDimitry Andric   const DIEInfo &getDIEInfo(unsigned Idx) const { return DieInfoArray[Idx]; }
2881db9f3b2SDimitry Andric 
2891db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
2901db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDIEInfo(const DWARFDebugInfoEntry * Entry)2911db9f3b2SDimitry Andric   DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) {
2921db9f3b2SDimitry Andric     return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
2931db9f3b2SDimitry Andric   }
2941db9f3b2SDimitry Andric 
2951db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
2961db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDIEInfo(const DWARFDebugInfoEntry * Entry)2971db9f3b2SDimitry Andric   const DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) const {
2981db9f3b2SDimitry Andric     return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
2991db9f3b2SDimitry Andric   }
3001db9f3b2SDimitry Andric 
3011db9f3b2SDimitry Andric   /// \p Die
3021db9f3b2SDimitry Andric   /// \returns PlainDieInfo descriptor.
getDIEInfo(const DWARFDie & Die)3031db9f3b2SDimitry Andric   DIEInfo &getDIEInfo(const DWARFDie &Die) {
3041db9f3b2SDimitry Andric     return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
3051db9f3b2SDimitry Andric   }
3061db9f3b2SDimitry Andric 
3071db9f3b2SDimitry Andric   /// \p Die
3081db9f3b2SDimitry Andric   /// \returns PlainDieInfo descriptor.
getDIEInfo(const DWARFDie & Die)3091db9f3b2SDimitry Andric   const DIEInfo &getDIEInfo(const DWARFDie &Die) const {
3101db9f3b2SDimitry Andric     return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
3111db9f3b2SDimitry Andric   }
3121db9f3b2SDimitry Andric 
3131db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
3141db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDieOutOffset(uint32_t Idx)3151db9f3b2SDimitry Andric   uint64_t getDieOutOffset(uint32_t Idx) {
3161db9f3b2SDimitry Andric     return reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
3171db9f3b2SDimitry Andric         ->load();
3181db9f3b2SDimitry Andric   }
3191db9f3b2SDimitry Andric 
3201db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
3211db9f3b2SDimitry Andric   /// \returns type entry.
getDieTypeEntry(uint32_t Idx)3221db9f3b2SDimitry Andric   TypeEntry *getDieTypeEntry(uint32_t Idx) {
3231db9f3b2SDimitry Andric     return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
3241db9f3b2SDimitry Andric         ->load();
3251db9f3b2SDimitry Andric   }
3261db9f3b2SDimitry Andric 
3271db9f3b2SDimitry Andric   /// \p InputDieEntry debug info entry.
3281db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
getDieOutOffset(const DWARFDebugInfoEntry * InputDieEntry)3291db9f3b2SDimitry Andric   uint64_t getDieOutOffset(const DWARFDebugInfoEntry *InputDieEntry) {
3301db9f3b2SDimitry Andric     return reinterpret_cast<std::atomic<uint64_t> *>(
3311db9f3b2SDimitry Andric                &OutDieOffsetArray[getOrigUnit().getDIEIndex(InputDieEntry)])
3321db9f3b2SDimitry Andric         ->load();
3331db9f3b2SDimitry Andric   }
3341db9f3b2SDimitry Andric 
3351db9f3b2SDimitry Andric   /// \p InputDieEntry debug info entry.
3361db9f3b2SDimitry Andric   /// \returns type entry.
getDieTypeEntry(const DWARFDebugInfoEntry * InputDieEntry)3371db9f3b2SDimitry Andric   TypeEntry *getDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry) {
3381db9f3b2SDimitry Andric     return reinterpret_cast<std::atomic<TypeEntry *> *>(
3391db9f3b2SDimitry Andric                &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
3401db9f3b2SDimitry Andric         ->load();
3411db9f3b2SDimitry Andric   }
3421db9f3b2SDimitry Andric 
3431db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
3441db9f3b2SDimitry Andric   /// \returns DieInfo descriptor.
rememberDieOutOffset(uint32_t Idx,uint64_t Offset)3451db9f3b2SDimitry Andric   void rememberDieOutOffset(uint32_t Idx, uint64_t Offset) {
3461db9f3b2SDimitry Andric     reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
3471db9f3b2SDimitry Andric         ->store(Offset);
3481db9f3b2SDimitry Andric   }
3491db9f3b2SDimitry Andric 
3501db9f3b2SDimitry Andric   /// \p Idx index of the DIE.
3511db9f3b2SDimitry Andric   /// \p Type entry.
setDieTypeEntry(uint32_t Idx,TypeEntry * Entry)3521db9f3b2SDimitry Andric   void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry) {
3531db9f3b2SDimitry Andric     reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
3541db9f3b2SDimitry Andric         ->store(Entry);
3551db9f3b2SDimitry Andric   }
3561db9f3b2SDimitry Andric 
3571db9f3b2SDimitry Andric   /// \p InputDieEntry debug info entry.
3581db9f3b2SDimitry Andric   /// \p Type entry.
setDieTypeEntry(const DWARFDebugInfoEntry * InputDieEntry,TypeEntry * Entry)3591db9f3b2SDimitry Andric   void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry,
3601db9f3b2SDimitry Andric                        TypeEntry *Entry) {
3611db9f3b2SDimitry Andric     reinterpret_cast<std::atomic<TypeEntry *> *>(
3621db9f3b2SDimitry Andric         &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
3631db9f3b2SDimitry Andric         ->store(Entry);
3641db9f3b2SDimitry Andric   }
3651db9f3b2SDimitry Andric 
3661db9f3b2SDimitry Andric   /// @}
3671db9f3b2SDimitry Andric 
3681db9f3b2SDimitry Andric   /// Returns value of DW_AT_low_pc attribute.
getLowPc()3691db9f3b2SDimitry Andric   std::optional<uint64_t> getLowPc() const { return LowPc; }
3701db9f3b2SDimitry Andric 
3711db9f3b2SDimitry Andric   /// Returns value of DW_AT_high_pc attribute.
getHighPc()3721db9f3b2SDimitry Andric   uint64_t getHighPc() const { return HighPc; }
3731db9f3b2SDimitry Andric 
3741db9f3b2SDimitry Andric   /// Returns true if there is a label corresponding to the specified \p Addr.
hasLabelAt(uint64_t Addr)3751db9f3b2SDimitry Andric   bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
3761db9f3b2SDimitry Andric 
3771db9f3b2SDimitry Andric   /// Add the low_pc of a label that is relocated by applying
3781db9f3b2SDimitry Andric   /// offset \p PCOffset.
3791db9f3b2SDimitry Andric   void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
3801db9f3b2SDimitry Andric 
3811db9f3b2SDimitry Andric   /// Resolve the DIE attribute reference that has been extracted in \p
3821db9f3b2SDimitry Andric   /// RefValue. The resulting DIE might be in another CompileUnit.
3831db9f3b2SDimitry Andric   /// \returns referenced die and corresponding compilation unit.
3841db9f3b2SDimitry Andric   ///          compilation unit is null if reference could not be resolved.
3851db9f3b2SDimitry Andric   std::optional<UnitEntryPairTy>
3861db9f3b2SDimitry Andric   resolveDIEReference(const DWARFFormValue &RefValue,
3871db9f3b2SDimitry Andric                       ResolveInterCUReferencesMode CanResolveInterCUReferences);
3881db9f3b2SDimitry Andric 
3891db9f3b2SDimitry Andric   std::optional<UnitEntryPairTy>
3901db9f3b2SDimitry Andric   resolveDIEReference(const DWARFDebugInfoEntry *DieEntry,
3911db9f3b2SDimitry Andric                       dwarf::Attribute Attr,
3921db9f3b2SDimitry Andric                       ResolveInterCUReferencesMode CanResolveInterCUReferences);
3931db9f3b2SDimitry Andric 
3941db9f3b2SDimitry Andric   /// @}
3951db9f3b2SDimitry Andric 
3961db9f3b2SDimitry Andric   /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
3971db9f3b2SDimitry Andric   /// offset \p PCOffset.
3981db9f3b2SDimitry Andric   void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
3991db9f3b2SDimitry Andric 
4001db9f3b2SDimitry Andric   /// Returns function ranges of this unit.
getFunctionRanges()4011db9f3b2SDimitry Andric   const RangesTy &getFunctionRanges() const { return Ranges; }
4021db9f3b2SDimitry Andric 
4031db9f3b2SDimitry Andric   /// Clone and emit this compilation unit.
404*7a6dacacSDimitry Andric   Error
405*7a6dacacSDimitry Andric   cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,
4061db9f3b2SDimitry Andric                TypeUnit *ArtificialTypeUnit);
4071db9f3b2SDimitry Andric 
4081db9f3b2SDimitry Andric   /// Clone and emit debug locations(.debug_loc/.debug_loclists).
4091db9f3b2SDimitry Andric   Error cloneAndEmitDebugLocations();
4101db9f3b2SDimitry Andric 
4111db9f3b2SDimitry Andric   /// Clone and emit ranges.
4121db9f3b2SDimitry Andric   Error cloneAndEmitRanges();
4131db9f3b2SDimitry Andric 
4141db9f3b2SDimitry Andric   /// Clone and emit debug macros(.debug_macinfo/.debug_macro).
4151db9f3b2SDimitry Andric   Error cloneAndEmitDebugMacro();
4161db9f3b2SDimitry Andric 
4171db9f3b2SDimitry Andric   // Clone input DIE entry.
4181db9f3b2SDimitry Andric   std::pair<DIE *, TypeEntry *>
4191db9f3b2SDimitry Andric   cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
4201db9f3b2SDimitry Andric            TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
4211db9f3b2SDimitry Andric            std::optional<int64_t> FuncAddressAdjustment,
4221db9f3b2SDimitry Andric            std::optional<int64_t> VarAddressAdjustment,
4231db9f3b2SDimitry Andric            BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
4241db9f3b2SDimitry Andric 
4251db9f3b2SDimitry Andric   // Clone and emit line table.
426*7a6dacacSDimitry Andric   Error cloneAndEmitLineTable(const Triple &TargetTriple);
4271db9f3b2SDimitry Andric 
4281db9f3b2SDimitry Andric   /// Clone attribute location axpression.
4291db9f3b2SDimitry Andric   void cloneDieAttrExpression(const DWARFExpression &InputExpression,
4301db9f3b2SDimitry Andric                               SmallVectorImpl<uint8_t> &OutputExpression,
4311db9f3b2SDimitry Andric                               SectionDescriptor &Section,
4321db9f3b2SDimitry Andric                               std::optional<int64_t> VarAddressAdjustment,
4331db9f3b2SDimitry Andric                               OffsetsPtrVector &PatchesOffsets);
4341db9f3b2SDimitry Andric 
4351db9f3b2SDimitry Andric   /// Returns index(inside .debug_addr) of an address.
getDebugAddrIndex(uint64_t Addr)4361db9f3b2SDimitry Andric   uint64_t getDebugAddrIndex(uint64_t Addr) {
4371db9f3b2SDimitry Andric     return DebugAddrIndexMap.getValueIndex(Addr);
4381db9f3b2SDimitry Andric   }
4391db9f3b2SDimitry Andric 
4401db9f3b2SDimitry Andric   /// Returns directory and file from the line table by index.
4411db9f3b2SDimitry Andric   std::optional<std::pair<StringRef, StringRef>>
4421db9f3b2SDimitry Andric   getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue);
4431db9f3b2SDimitry Andric 
4441db9f3b2SDimitry Andric   /// Returns directory and file from the line table by index.
4451db9f3b2SDimitry Andric   std::optional<std::pair<StringRef, StringRef>>
4461db9f3b2SDimitry Andric   getDirAndFilenameFromLineTable(uint64_t FileIdx);
4471db9f3b2SDimitry Andric 
4481db9f3b2SDimitry Andric   /// \defgroup Helper methods to access OrigUnit.
4491db9f3b2SDimitry Andric   ///
4501db9f3b2SDimitry Andric   /// @{
4511db9f3b2SDimitry Andric 
4521db9f3b2SDimitry Andric   /// Returns paired compile unit from input DWARF.
getOrigUnit()4531db9f3b2SDimitry Andric   DWARFUnit &getOrigUnit() const {
4541db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4551db9f3b2SDimitry Andric     return *OrigUnit;
4561db9f3b2SDimitry Andric   }
4571db9f3b2SDimitry Andric 
4581db9f3b2SDimitry Andric   const DWARFDebugInfoEntry *
getFirstChildEntry(const DWARFDebugInfoEntry * Die)4591db9f3b2SDimitry Andric   getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
4601db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4611db9f3b2SDimitry Andric     return OrigUnit->getFirstChildEntry(Die);
4621db9f3b2SDimitry Andric   }
4631db9f3b2SDimitry Andric 
4641db9f3b2SDimitry Andric   const DWARFDebugInfoEntry *
getSiblingEntry(const DWARFDebugInfoEntry * Die)4651db9f3b2SDimitry Andric   getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
4661db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4671db9f3b2SDimitry Andric     return OrigUnit->getSiblingEntry(Die);
4681db9f3b2SDimitry Andric   }
4691db9f3b2SDimitry Andric 
getParent(const DWARFDebugInfoEntry * Die)4701db9f3b2SDimitry Andric   DWARFDie getParent(const DWARFDebugInfoEntry *Die) {
4711db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4721db9f3b2SDimitry Andric     return OrigUnit->getParent(Die);
4731db9f3b2SDimitry Andric   }
4741db9f3b2SDimitry Andric 
getDIEAtIndex(unsigned Index)4751db9f3b2SDimitry Andric   DWARFDie getDIEAtIndex(unsigned Index) {
4761db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4771db9f3b2SDimitry Andric     return OrigUnit->getDIEAtIndex(Index);
4781db9f3b2SDimitry Andric   }
4791db9f3b2SDimitry Andric 
getDebugInfoEntry(unsigned Index)4801db9f3b2SDimitry Andric   const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
4811db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4821db9f3b2SDimitry Andric     return OrigUnit->getDebugInfoEntry(Index);
4831db9f3b2SDimitry Andric   }
4841db9f3b2SDimitry Andric 
4851db9f3b2SDimitry Andric   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
4861db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4871db9f3b2SDimitry Andric     return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
4881db9f3b2SDimitry Andric   }
4891db9f3b2SDimitry Andric 
getDIE(const DWARFDebugInfoEntry * Die)4901db9f3b2SDimitry Andric   DWARFDie getDIE(const DWARFDebugInfoEntry *Die) {
4911db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4921db9f3b2SDimitry Andric     return DWARFDie(OrigUnit, Die);
4931db9f3b2SDimitry Andric   }
4941db9f3b2SDimitry Andric 
getDIEIndex(const DWARFDebugInfoEntry * Die)4951db9f3b2SDimitry Andric   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
4961db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
4971db9f3b2SDimitry Andric     return OrigUnit->getDIEIndex(Die);
4981db9f3b2SDimitry Andric   }
4991db9f3b2SDimitry Andric 
getDIEIndex(const DWARFDie & Die)5001db9f3b2SDimitry Andric   uint32_t getDIEIndex(const DWARFDie &Die) const {
5011db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
5021db9f3b2SDimitry Andric     return OrigUnit->getDIEIndex(Die);
5031db9f3b2SDimitry Andric   }
5041db9f3b2SDimitry Andric 
find(uint32_t DieIdx,ArrayRef<dwarf::Attribute> Attrs)5051db9f3b2SDimitry Andric   std::optional<DWARFFormValue> find(uint32_t DieIdx,
5061db9f3b2SDimitry Andric                                      ArrayRef<dwarf::Attribute> Attrs) const {
5071db9f3b2SDimitry Andric     assert(OrigUnit != nullptr);
5081db9f3b2SDimitry Andric     return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs);
5091db9f3b2SDimitry Andric   }
5101db9f3b2SDimitry Andric 
find(const DWARFDebugInfoEntry * Die,ArrayRef<dwarf::Attribute> Attrs)5111db9f3b2SDimitry Andric   std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
5121db9f3b2SDimitry Andric                                      ArrayRef<dwarf::Attribute> Attrs) const {
5131db9f3b2SDimitry Andric     if (!Die)
5141db9f3b2SDimitry Andric       return std::nullopt;
5151db9f3b2SDimitry Andric     auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
5161db9f3b2SDimitry Andric     if (AbbrevDecl) {
5171db9f3b2SDimitry Andric       for (auto Attr : Attrs) {
5181db9f3b2SDimitry Andric         if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr,
5191db9f3b2SDimitry Andric                                                        *OrigUnit))
5201db9f3b2SDimitry Andric           return Value;
5211db9f3b2SDimitry Andric       }
5221db9f3b2SDimitry Andric     }
5231db9f3b2SDimitry Andric     return std::nullopt;
5241db9f3b2SDimitry Andric   }
5251db9f3b2SDimitry Andric 
getDIEIndexForOffset(uint64_t Offset)5261db9f3b2SDimitry Andric   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
5271db9f3b2SDimitry Andric     return OrigUnit->getDIEIndexForOffset(Offset);
5281db9f3b2SDimitry Andric   }
5291db9f3b2SDimitry Andric 
5301db9f3b2SDimitry Andric   /// @}
5311db9f3b2SDimitry Andric 
5321db9f3b2SDimitry Andric   /// \defgroup Methods used for reporting warnings and errors:
5331db9f3b2SDimitry Andric   ///
5341db9f3b2SDimitry Andric   /// @{
5351db9f3b2SDimitry Andric 
5361db9f3b2SDimitry Andric   void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
5371db9f3b2SDimitry Andric     GlobalData.warn(Warning, getUnitName(), DIE);
5381db9f3b2SDimitry Andric   }
5391db9f3b2SDimitry Andric 
5401db9f3b2SDimitry Andric   void warn(Error Warning, const DWARFDie *DIE = nullptr) {
5411db9f3b2SDimitry Andric     handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
5421db9f3b2SDimitry Andric       GlobalData.warn(Info.message(), getUnitName(), DIE);
5431db9f3b2SDimitry Andric     });
5441db9f3b2SDimitry Andric   }
5451db9f3b2SDimitry Andric 
warn(const Twine & Warning,const DWARFDebugInfoEntry * DieEntry)5461db9f3b2SDimitry Andric   void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
5471db9f3b2SDimitry Andric     if (DieEntry != nullptr) {
5481db9f3b2SDimitry Andric       DWARFDie DIE(&getOrigUnit(), DieEntry);
5491db9f3b2SDimitry Andric       GlobalData.warn(Warning, getUnitName(), &DIE);
5501db9f3b2SDimitry Andric       return;
5511db9f3b2SDimitry Andric     }
5521db9f3b2SDimitry Andric 
5531db9f3b2SDimitry Andric     GlobalData.warn(Warning, getUnitName());
5541db9f3b2SDimitry Andric   }
5551db9f3b2SDimitry Andric 
5561db9f3b2SDimitry Andric   void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
5571db9f3b2SDimitry Andric     GlobalData.warn(Err, getUnitName(), DIE);
5581db9f3b2SDimitry Andric   }
5591db9f3b2SDimitry Andric 
5601db9f3b2SDimitry Andric   void error(Error Err, const DWARFDie *DIE = nullptr) {
5611db9f3b2SDimitry Andric     handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
5621db9f3b2SDimitry Andric       GlobalData.error(Info.message(), getUnitName(), DIE);
5631db9f3b2SDimitry Andric     });
5641db9f3b2SDimitry Andric   }
5651db9f3b2SDimitry Andric 
5661db9f3b2SDimitry Andric   /// @}
5671db9f3b2SDimitry Andric 
5681db9f3b2SDimitry Andric   /// Save specified accelerator info \p Info.
saveAcceleratorInfo(const DwarfUnit::AccelInfo & Info)5691db9f3b2SDimitry Andric   void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
5701db9f3b2SDimitry Andric     AcceleratorRecords.add(Info);
5711db9f3b2SDimitry Andric   }
5721db9f3b2SDimitry Andric 
5731db9f3b2SDimitry Andric   /// Enumerates all units accelerator records.
5741db9f3b2SDimitry Andric   void
forEachAcceleratorRecord(function_ref<void (AccelInfo &)> Handler)5751db9f3b2SDimitry Andric   forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
5761db9f3b2SDimitry Andric     AcceleratorRecords.forEach(Handler);
5771db9f3b2SDimitry Andric   }
5781db9f3b2SDimitry Andric 
5791db9f3b2SDimitry Andric   /// Output unit selector.
5801db9f3b2SDimitry Andric   class OutputUnitVariantPtr {
5811db9f3b2SDimitry Andric   public:
5821db9f3b2SDimitry Andric     OutputUnitVariantPtr(CompileUnit *U);
5831db9f3b2SDimitry Andric     OutputUnitVariantPtr(TypeUnit *U);
5841db9f3b2SDimitry Andric 
5851db9f3b2SDimitry Andric     /// Accessor for common functionality.
5861db9f3b2SDimitry Andric     DwarfUnit *operator->();
5871db9f3b2SDimitry Andric 
5881db9f3b2SDimitry Andric     bool isCompileUnit();
5891db9f3b2SDimitry Andric 
5901db9f3b2SDimitry Andric     bool isTypeUnit();
5911db9f3b2SDimitry Andric 
5921db9f3b2SDimitry Andric     /// Returns CompileUnit if applicable.
5931db9f3b2SDimitry Andric     CompileUnit *getAsCompileUnit();
5941db9f3b2SDimitry Andric 
5951db9f3b2SDimitry Andric     /// Returns TypeUnit if applicable.
5961db9f3b2SDimitry Andric     TypeUnit *getAsTypeUnit();
5971db9f3b2SDimitry Andric 
5981db9f3b2SDimitry Andric   protected:
5991db9f3b2SDimitry Andric     PointerUnion<CompileUnit *, TypeUnit *> Ptr;
6001db9f3b2SDimitry Andric   };
6011db9f3b2SDimitry Andric 
6021db9f3b2SDimitry Andric private:
6031db9f3b2SDimitry Andric   /// Navigate DWARF tree recursively and set die properties.
6041db9f3b2SDimitry Andric   void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
6051db9f3b2SDimitry Andric                                 bool IsODRUnavailableFunctionScope);
6061db9f3b2SDimitry Andric 
6071db9f3b2SDimitry Andric   struct LinkedLocationExpressionsWithOffsetPatches {
6081db9f3b2SDimitry Andric     DWARFLocationExpression Expression;
6091db9f3b2SDimitry Andric     OffsetsPtrVector Patches;
6101db9f3b2SDimitry Andric   };
6111db9f3b2SDimitry Andric   using LinkedLocationExpressionsVector =
6121db9f3b2SDimitry Andric       SmallVector<LinkedLocationExpressionsWithOffsetPatches>;
6131db9f3b2SDimitry Andric 
6141db9f3b2SDimitry Andric   /// Emit debug locations.
6151db9f3b2SDimitry Andric   void emitLocations(DebugSectionKind LocationSectionKind);
6161db9f3b2SDimitry Andric 
6171db9f3b2SDimitry Andric   /// Emit location list header.
6181db9f3b2SDimitry Andric   uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
6191db9f3b2SDimitry Andric 
6201db9f3b2SDimitry Andric   /// Emit location list fragment.
6211db9f3b2SDimitry Andric   uint64_t emitLocListFragment(
6221db9f3b2SDimitry Andric       const LinkedLocationExpressionsVector &LinkedLocationExpression,
6231db9f3b2SDimitry Andric       SectionDescriptor &OutLocationSection);
6241db9f3b2SDimitry Andric 
6251db9f3b2SDimitry Andric   /// Emit the .debug_addr section fragment for current unit.
6261db9f3b2SDimitry Andric   Error emitDebugAddrSection();
6271db9f3b2SDimitry Andric 
6281db9f3b2SDimitry Andric   /// Emit .debug_aranges.
6291db9f3b2SDimitry Andric   void emitAranges(AddressRanges &LinkedFunctionRanges);
6301db9f3b2SDimitry Andric 
6311db9f3b2SDimitry Andric   /// Clone and emit .debug_ranges/.debug_rnglists.
6321db9f3b2SDimitry Andric   void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
6331db9f3b2SDimitry Andric                              AddressRanges &LinkedFunctionRanges);
6341db9f3b2SDimitry Andric 
6351db9f3b2SDimitry Andric   /// Emit range list header.
6361db9f3b2SDimitry Andric   uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
6371db9f3b2SDimitry Andric 
6381db9f3b2SDimitry Andric   /// Emit range list fragment.
6391db9f3b2SDimitry Andric   void emitRangeListFragment(const AddressRanges &LinkedRanges,
6401db9f3b2SDimitry Andric                              SectionDescriptor &OutRangeSection);
6411db9f3b2SDimitry Andric 
6421db9f3b2SDimitry Andric   /// Insert the new line info sequence \p Seq into the current
6431db9f3b2SDimitry Andric   /// set of already linked line info \p Rows.
6441db9f3b2SDimitry Andric   void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
6451db9f3b2SDimitry Andric                           std::vector<DWARFDebugLine::Row> &Rows);
6461db9f3b2SDimitry Andric 
6471db9f3b2SDimitry Andric   /// Emits body for both macro sections.
6481db9f3b2SDimitry Andric   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
6491db9f3b2SDimitry Andric                           uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
6501db9f3b2SDimitry Andric 
6511db9f3b2SDimitry Andric   /// Creates DIE which would be placed into the "Plain" compile unit.
6521db9f3b2SDimitry Andric   DIE *createPlainDIEandCloneAttributes(
6531db9f3b2SDimitry Andric       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
6541db9f3b2SDimitry Andric       uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
6551db9f3b2SDimitry Andric       std::optional<int64_t> &VarAddressAdjustment);
6561db9f3b2SDimitry Andric 
6571db9f3b2SDimitry Andric   /// Creates DIE which would be placed into the "Type" compile unit.
6581db9f3b2SDimitry Andric   TypeEntry *createTypeDIEandCloneAttributes(
6591db9f3b2SDimitry Andric       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
6601db9f3b2SDimitry Andric       TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit);
6611db9f3b2SDimitry Andric 
6621db9f3b2SDimitry Andric   /// Create output DIE inside specified \p TypeDescriptor.
6631db9f3b2SDimitry Andric   DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
6641db9f3b2SDimitry Andric                        DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
6651db9f3b2SDimitry Andric                        bool IsDeclaration, bool IsParentDeclaration);
6661db9f3b2SDimitry Andric 
6671db9f3b2SDimitry Andric   /// Enumerate \p DieEntry children and assign names for them.
6681db9f3b2SDimitry Andric   Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
6691db9f3b2SDimitry Andric                            SyntheticTypeNameBuilder &NameBuilder);
6701db9f3b2SDimitry Andric 
6711db9f3b2SDimitry Andric   /// DWARFFile containing this compile unit.
6721db9f3b2SDimitry Andric   DWARFFile &File;
6731db9f3b2SDimitry Andric 
6741db9f3b2SDimitry Andric   /// Pointer to the paired compile unit from the input DWARF.
6751db9f3b2SDimitry Andric   DWARFUnit *OrigUnit = nullptr;
6761db9f3b2SDimitry Andric 
6771db9f3b2SDimitry Andric   /// The DW_AT_language of this unit.
6781db9f3b2SDimitry Andric   std::optional<uint16_t> Language;
6791db9f3b2SDimitry Andric 
6801db9f3b2SDimitry Andric   /// Line table for this unit.
6811db9f3b2SDimitry Andric   const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
6821db9f3b2SDimitry Andric 
6831db9f3b2SDimitry Andric   /// Cached resolved paths from the line table.
6841db9f3b2SDimitry Andric   /// The key is <UniqueUnitID, FileIdx>.
6851db9f3b2SDimitry Andric   using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
6861db9f3b2SDimitry Andric   ResolvedPathsMap ResolvedFullPaths;
6871db9f3b2SDimitry Andric   StringMap<StringEntry *> ResolvedParentPaths;
6881db9f3b2SDimitry Andric 
6891db9f3b2SDimitry Andric   /// Maps an address into the index inside .debug_addr section.
6901db9f3b2SDimitry Andric   IndexedValuesMap<uint64_t> DebugAddrIndexMap;
6911db9f3b2SDimitry Andric 
6921db9f3b2SDimitry Andric   std::unique_ptr<DependencyTracker> Dependencies;
6931db9f3b2SDimitry Andric 
6941db9f3b2SDimitry Andric   /// \defgroup Data Members accessed asinchronously.
6951db9f3b2SDimitry Andric   ///
6961db9f3b2SDimitry Andric   /// @{
6971db9f3b2SDimitry Andric   OffsetToUnitTy getUnitFromOffset;
6981db9f3b2SDimitry Andric 
6991db9f3b2SDimitry Andric   std::optional<uint64_t> LowPc;
7001db9f3b2SDimitry Andric   uint64_t HighPc = 0;
7011db9f3b2SDimitry Andric 
7021db9f3b2SDimitry Andric   /// Flag indicating whether type de-duplication is forbidden.
7031db9f3b2SDimitry Andric   bool NoODR = true;
7041db9f3b2SDimitry Andric 
7051db9f3b2SDimitry Andric   /// The ranges in that map are the PC ranges for functions in this unit,
7061db9f3b2SDimitry Andric   /// associated with the PC offset to apply to the addresses to get
7071db9f3b2SDimitry Andric   /// the linked address.
7081db9f3b2SDimitry Andric   RangesTy Ranges;
7091db9f3b2SDimitry Andric   std::mutex RangesMutex;
7101db9f3b2SDimitry Andric 
7111db9f3b2SDimitry Andric   /// The DW_AT_low_pc of each DW_TAG_label.
7121db9f3b2SDimitry Andric   using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
7131db9f3b2SDimitry Andric   LabelMapTy Labels;
7141db9f3b2SDimitry Andric   std::mutex LabelsMutex;
7151db9f3b2SDimitry Andric 
7161db9f3b2SDimitry Andric   /// This field keeps current stage of overall compile unit processing.
7171db9f3b2SDimitry Andric   std::atomic<Stage> Stage;
7181db9f3b2SDimitry Andric 
7191db9f3b2SDimitry Andric   /// DIE info indexed by DIE index.
7201db9f3b2SDimitry Andric   SmallVector<DIEInfo> DieInfoArray;
7211db9f3b2SDimitry Andric   SmallVector<uint64_t> OutDieOffsetArray;
7221db9f3b2SDimitry Andric   SmallVector<TypeEntry *> TypeEntries;
7231db9f3b2SDimitry Andric 
7241db9f3b2SDimitry Andric   /// The list of accelerator records for this unit.
7251db9f3b2SDimitry Andric   ArrayList<AccelInfo> AcceleratorRecords;
7261db9f3b2SDimitry Andric   /// @}
7271db9f3b2SDimitry Andric };
7281db9f3b2SDimitry Andric 
7291db9f3b2SDimitry Andric /// \returns list of attributes referencing type DIEs which might be
7301db9f3b2SDimitry Andric /// deduplicated.
7311db9f3b2SDimitry Andric /// Note: it does not include DW_AT_containing_type attribute to avoid
7321db9f3b2SDimitry Andric /// infinite recursion.
7331db9f3b2SDimitry Andric ArrayRef<dwarf::Attribute> getODRAttributes();
7341db9f3b2SDimitry Andric 
7351db9f3b2SDimitry Andric } // end of namespace parallel
7361db9f3b2SDimitry Andric } // end of namespace dwarf_linker
7371db9f3b2SDimitry Andric } // end of namespace llvm
7381db9f3b2SDimitry Andric 
7391db9f3b2SDimitry Andric #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
740