xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 //===- DWARFLinkerCompileUnit.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_DWARFLINKERCOMPILEUNIT_H
10 #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
11 
12 #include "DWARFLinkerUnit.h"
13 #include "llvm/DWARFLinker/DWARFFile.h"
14 #include <optional>
15 
16 namespace llvm {
17 namespace dwarf_linker {
18 namespace parallel {
19 
20 using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
21 
22 struct AttributesInfo;
23 class SyntheticTypeNameBuilder;
24 class DIEGenerator;
25 class TypeUnit;
26 class DependencyTracker;
27 
28 class CompileUnit;
29 
30 /// This is a helper structure which keeps a debug info entry
31 /// with it's containing compilation unit.
32 struct UnitEntryPairTy {
33   UnitEntryPairTy() = default;
34   UnitEntryPairTy(CompileUnit *CU, const DWARFDebugInfoEntry *DieEntry)
35       : CU(CU), DieEntry(DieEntry) {}
36 
37   CompileUnit *CU = nullptr;
38   const DWARFDebugInfoEntry *DieEntry = nullptr;
39 
40   UnitEntryPairTy getNamespaceOrigin();
41   std::optional<UnitEntryPairTy> getParent();
42 };
43 
44 enum ResolveInterCUReferencesMode : bool {
45   Resolve = true,
46   AvoidResolving = false,
47 };
48 
49 /// Stores all information related to a compile unit, be it in its original
50 /// instance of the object file or its brand new cloned and generated DIE tree.
51 /// NOTE: we need alignment of at least 8 bytes as we use
52 ///       PointerIntPair<CompileUnit *, 3> in the DependencyTracker.h
53 class alignas(8) CompileUnit : public DwarfUnit {
54 public:
55   /// The stages of new compile unit processing.
56   enum class Stage : uint8_t {
57     /// Created, linked with input DWARF file.
58     CreatedNotLoaded = 0,
59 
60     /// Input DWARF is loaded.
61     Loaded,
62 
63     /// Input DWARF is analysed(DIEs pointing to the real code section are
64     /// discovered, type names are assigned if ODR is requested).
65     LivenessAnalysisDone,
66 
67     /// Check if dependencies have incompatible placement.
68     /// If that is the case modify placement to be compatible.
69     UpdateDependenciesCompleteness,
70 
71     /// Type names assigned to DIEs.
72     TypeNamesAssigned,
73 
74     /// Output DWARF is generated.
75     Cloned,
76 
77     /// Offsets inside patch records are updated.
78     PatchesUpdated,
79 
80     /// Resources(Input DWARF, Output DWARF tree) are released.
81     Cleaned,
82 
83     /// Compile Unit should be skipped
84     Skipped
85   };
86 
87   CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
88               StringRef ClangModuleName, DWARFFile &File,
89               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
90               llvm::endianness Endianess);
91 
92   CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, unsigned ID,
93               StringRef ClangModuleName, DWARFFile &File,
94               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
95               llvm::endianness Endianess);
96 
97   /// Returns stage of overall processing.
98   Stage getStage() const { return Stage; }
99 
100   /// Set stage of overall processing.
101   void setStage(Stage Stage) { this->Stage = Stage; }
102 
103   /// Loads unit line table.
104   void loadLineTable();
105 
106   /// Returns name of the file for the \p FileIdx
107   /// from the unit`s line table.
108   StringEntry *getFileName(unsigned FileIdx, StringPool &GlobalStrings);
109 
110   /// Returns DWARFFile containing this compile unit.
111   const DWARFFile &getContaingFile() const { return File; }
112 
113   /// Load DIEs of input compilation unit. \returns true if input DIEs
114   /// successfully loaded.
115   bool loadInputDIEs();
116 
117   /// Reset compile units data(results of liveness analysis, clonning)
118   /// if current stage greater than Stage::Loaded. We need to reset data
119   /// as we are going to repeat stages.
120   void maybeResetToLoadedStage();
121 
122   /// Collect references to parseable Swift interfaces in imported
123   /// DW_TAG_module blocks.
124   void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry);
125 
126   /// Navigate DWARF tree and set die properties.
127   void analyzeDWARFStructure() {
128     analyzeDWARFStructureRec(getUnitDIE().getDebugInfoEntry(), false);
129   }
130 
131   /// Cleanup unneeded resources after compile unit is cloned.
132   void cleanupDataAfterClonning();
133 
134   /// After cloning stage the output DIEs offsets are deallocated.
135   /// This method copies output offsets for referenced DIEs into DIEs patches.
136   void updateDieRefPatchesWithClonedOffsets();
137 
138   /// Search for subprograms and variables referencing live code and discover
139   /// dependend DIEs. Mark live DIEs, set placement for DIEs.
140   bool resolveDependenciesAndMarkLiveness(
141       bool InterCUProcessingStarted,
142       std::atomic<bool> &HasNewInterconnectedCUs);
143 
144   /// Check dependend DIEs for incompatible placement.
145   /// Make placement to be consistent.
146   bool updateDependenciesCompleteness();
147 
148   /// Check DIEs to have a consistent marking(keep marking, placement marking).
149   void verifyDependencies();
150 
151   /// Search for type entries and assign names.
152   Error assignTypeNames(TypePool &TypePoolRef);
153 
154   /// Kinds of placement for the output die.
155   enum DieOutputPlacement : uint8_t {
156     NotSet = 0,
157 
158     /// Corresponding DIE goes to the type table only.
159     TypeTable = 1,
160 
161     /// Corresponding DIE goes to the plain dwarf only.
162     PlainDwarf = 2,
163 
164     /// Corresponding DIE goes to type table and to plain dwarf.
165     Both = 3,
166   };
167 
168   /// Information gathered about source DIEs.
169   struct DIEInfo {
170     DIEInfo() = default;
171     DIEInfo(const DIEInfo &Other) { Flags = Other.Flags.load(); }
172     DIEInfo &operator=(const DIEInfo &Other) {
173       Flags = Other.Flags.load();
174       return *this;
175     }
176 
177     /// Data member keeping various flags.
178     std::atomic<uint16_t> Flags = {0};
179 
180     /// \returns Placement kind for the corresponding die.
181     DieOutputPlacement getPlacement() const {
182       return DieOutputPlacement(Flags & 0x7);
183     }
184 
185     /// Sets Placement kind for the corresponding die.
186     void setPlacement(DieOutputPlacement Placement) {
187       auto InputData = Flags.load();
188       while (!Flags.compare_exchange_weak(InputData,
189                                           ((InputData & ~0x7) | Placement))) {
190       }
191     }
192 
193     /// Unsets Placement kind for the corresponding die.
194     void unsetPlacement() {
195       auto InputData = Flags.load();
196       while (!Flags.compare_exchange_weak(InputData, (InputData & ~0x7))) {
197       }
198     }
199 
200     /// Sets Placement kind for the corresponding die.
201     bool setPlacementIfUnset(DieOutputPlacement Placement) {
202       auto InputData = Flags.load();
203       if ((InputData & 0x7) == NotSet)
204         if (Flags.compare_exchange_weak(InputData, (InputData | Placement)))
205           return true;
206 
207       return false;
208     }
209 
210 #define SINGLE_FLAG_METHODS_SET(Name, Value)                                   \
211   bool get##Name() const { return Flags & Value; }                             \
212   void set##Name() {                                                           \
213     auto InputData = Flags.load();                                             \
214     while (!Flags.compare_exchange_weak(InputData, InputData | Value)) {       \
215     }                                                                          \
216   }                                                                            \
217   void unset##Name() {                                                         \
218     auto InputData = Flags.load();                                             \
219     while (!Flags.compare_exchange_weak(InputData, InputData & ~Value)) {      \
220     }                                                                          \
221   }
222 
223     /// DIE is a part of the linked output.
224     SINGLE_FLAG_METHODS_SET(Keep, 0x08)
225 
226     /// DIE has children which are part of the linked output.
227     SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10)
228 
229     /// DIE has children which are part of the type table.
230     SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20)
231 
232     /// DIE is in module scope.
233     SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40)
234 
235     /// DIE is in function scope.
236     SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80)
237 
238     /// DIE is in anonymous namespace scope.
239     SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100)
240 
241     /// DIE is available for ODR type deduplication.
242     SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200)
243 
244     /// Track liveness for the DIE.
245     SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400)
246 
247     /// Track liveness for the DIE.
248     SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800)
249 
250     void unsetFlagsWhichSetDuringLiveAnalysis() {
251       auto InputData = Flags.load();
252       while (!Flags.compare_exchange_weak(
253           InputData, InputData & ~(0x7 | 0x8 | 0x10 | 0x20))) {
254       }
255     }
256 
257     /// Erase all flags.
258     void eraseData() { Flags = 0; }
259 
260 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
261     LLVM_DUMP_METHOD void dump();
262 #endif
263 
264     bool needToPlaceInTypeTable() const {
265       return (getKeep() && (getPlacement() == CompileUnit::TypeTable ||
266                             getPlacement() == CompileUnit::Both)) ||
267              getKeepTypeChildren();
268     }
269 
270     bool needToKeepInPlainDwarf() const {
271       return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf ||
272                             getPlacement() == CompileUnit::Both)) ||
273              getKeepPlainChildren();
274     }
275   };
276 
277   /// \defgroup Group of functions returning DIE info.
278   ///
279   /// @{
280 
281   /// \p Idx index of the DIE.
282   /// \returns DieInfo descriptor.
283   DIEInfo &getDIEInfo(unsigned Idx) { return DieInfoArray[Idx]; }
284 
285   /// \p Idx index of the DIE.
286   /// \returns DieInfo descriptor.
287   const DIEInfo &getDIEInfo(unsigned Idx) const { return DieInfoArray[Idx]; }
288 
289   /// \p Idx index of the DIE.
290   /// \returns DieInfo descriptor.
291   DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) {
292     return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
293   }
294 
295   /// \p Idx index of the DIE.
296   /// \returns DieInfo descriptor.
297   const DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) const {
298     return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
299   }
300 
301   /// \p Die
302   /// \returns PlainDieInfo descriptor.
303   DIEInfo &getDIEInfo(const DWARFDie &Die) {
304     return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
305   }
306 
307   /// \p Die
308   /// \returns PlainDieInfo descriptor.
309   const DIEInfo &getDIEInfo(const DWARFDie &Die) const {
310     return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
311   }
312 
313   /// \p Idx index of the DIE.
314   /// \returns DieInfo descriptor.
315   uint64_t getDieOutOffset(uint32_t Idx) {
316     return reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
317         ->load();
318   }
319 
320   /// \p Idx index of the DIE.
321   /// \returns type entry.
322   TypeEntry *getDieTypeEntry(uint32_t Idx) {
323     return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
324         ->load();
325   }
326 
327   /// \p InputDieEntry debug info entry.
328   /// \returns DieInfo descriptor.
329   uint64_t getDieOutOffset(const DWARFDebugInfoEntry *InputDieEntry) {
330     return reinterpret_cast<std::atomic<uint64_t> *>(
331                &OutDieOffsetArray[getOrigUnit().getDIEIndex(InputDieEntry)])
332         ->load();
333   }
334 
335   /// \p InputDieEntry debug info entry.
336   /// \returns type entry.
337   TypeEntry *getDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry) {
338     return reinterpret_cast<std::atomic<TypeEntry *> *>(
339                &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
340         ->load();
341   }
342 
343   /// \p Idx index of the DIE.
344   /// \returns DieInfo descriptor.
345   void rememberDieOutOffset(uint32_t Idx, uint64_t Offset) {
346     reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
347         ->store(Offset);
348   }
349 
350   /// \p Idx index of the DIE.
351   /// \p Type entry.
352   void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry) {
353     reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
354         ->store(Entry);
355   }
356 
357   /// \p InputDieEntry debug info entry.
358   /// \p Type entry.
359   void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry,
360                        TypeEntry *Entry) {
361     reinterpret_cast<std::atomic<TypeEntry *> *>(
362         &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
363         ->store(Entry);
364   }
365 
366   /// @}
367 
368   /// Returns value of DW_AT_low_pc attribute.
369   std::optional<uint64_t> getLowPc() const { return LowPc; }
370 
371   /// Returns value of DW_AT_high_pc attribute.
372   uint64_t getHighPc() const { return HighPc; }
373 
374   /// Returns true if there is a label corresponding to the specified \p Addr.
375   bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
376 
377   /// Add the low_pc of a label that is relocated by applying
378   /// offset \p PCOffset.
379   void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
380 
381   /// Resolve the DIE attribute reference that has been extracted in \p
382   /// RefValue. The resulting DIE might be in another CompileUnit.
383   /// \returns referenced die and corresponding compilation unit.
384   ///          compilation unit is null if reference could not be resolved.
385   std::optional<UnitEntryPairTy>
386   resolveDIEReference(const DWARFFormValue &RefValue,
387                       ResolveInterCUReferencesMode CanResolveInterCUReferences);
388 
389   std::optional<UnitEntryPairTy>
390   resolveDIEReference(const DWARFDebugInfoEntry *DieEntry,
391                       dwarf::Attribute Attr,
392                       ResolveInterCUReferencesMode CanResolveInterCUReferences);
393 
394   /// @}
395 
396   /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
397   /// offset \p PCOffset.
398   void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
399 
400   /// Returns function ranges of this unit.
401   const RangesTy &getFunctionRanges() const { return Ranges; }
402 
403   /// Clone and emit this compilation unit.
404   Error cloneAndEmit(std::optional<Triple> TargetTriple,
405                      TypeUnit *ArtificialTypeUnit);
406 
407   /// Clone and emit debug locations(.debug_loc/.debug_loclists).
408   Error cloneAndEmitDebugLocations();
409 
410   /// Clone and emit ranges.
411   Error cloneAndEmitRanges();
412 
413   /// Clone and emit debug macros(.debug_macinfo/.debug_macro).
414   Error cloneAndEmitDebugMacro();
415 
416   // Clone input DIE entry.
417   std::pair<DIE *, TypeEntry *>
418   cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
419            TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
420            std::optional<int64_t> FuncAddressAdjustment,
421            std::optional<int64_t> VarAddressAdjustment,
422            BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
423 
424   // Clone and emit line table.
425   Error cloneAndEmitLineTable(Triple &TargetTriple);
426 
427   /// Clone attribute location axpression.
428   void cloneDieAttrExpression(const DWARFExpression &InputExpression,
429                               SmallVectorImpl<uint8_t> &OutputExpression,
430                               SectionDescriptor &Section,
431                               std::optional<int64_t> VarAddressAdjustment,
432                               OffsetsPtrVector &PatchesOffsets);
433 
434   /// Returns index(inside .debug_addr) of an address.
435   uint64_t getDebugAddrIndex(uint64_t Addr) {
436     return DebugAddrIndexMap.getValueIndex(Addr);
437   }
438 
439   /// Returns directory and file from the line table by index.
440   std::optional<std::pair<StringRef, StringRef>>
441   getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue);
442 
443   /// Returns directory and file from the line table by index.
444   std::optional<std::pair<StringRef, StringRef>>
445   getDirAndFilenameFromLineTable(uint64_t FileIdx);
446 
447   /// \defgroup Helper methods to access OrigUnit.
448   ///
449   /// @{
450 
451   /// Returns paired compile unit from input DWARF.
452   DWARFUnit &getOrigUnit() const {
453     assert(OrigUnit != nullptr);
454     return *OrigUnit;
455   }
456 
457   const DWARFDebugInfoEntry *
458   getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
459     assert(OrigUnit != nullptr);
460     return OrigUnit->getFirstChildEntry(Die);
461   }
462 
463   const DWARFDebugInfoEntry *
464   getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
465     assert(OrigUnit != nullptr);
466     return OrigUnit->getSiblingEntry(Die);
467   }
468 
469   DWARFDie getParent(const DWARFDebugInfoEntry *Die) {
470     assert(OrigUnit != nullptr);
471     return OrigUnit->getParent(Die);
472   }
473 
474   DWARFDie getDIEAtIndex(unsigned Index) {
475     assert(OrigUnit != nullptr);
476     return OrigUnit->getDIEAtIndex(Index);
477   }
478 
479   const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
480     assert(OrigUnit != nullptr);
481     return OrigUnit->getDebugInfoEntry(Index);
482   }
483 
484   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
485     assert(OrigUnit != nullptr);
486     return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
487   }
488 
489   DWARFDie getDIE(const DWARFDebugInfoEntry *Die) {
490     assert(OrigUnit != nullptr);
491     return DWARFDie(OrigUnit, Die);
492   }
493 
494   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
495     assert(OrigUnit != nullptr);
496     return OrigUnit->getDIEIndex(Die);
497   }
498 
499   uint32_t getDIEIndex(const DWARFDie &Die) const {
500     assert(OrigUnit != nullptr);
501     return OrigUnit->getDIEIndex(Die);
502   }
503 
504   std::optional<DWARFFormValue> find(uint32_t DieIdx,
505                                      ArrayRef<dwarf::Attribute> Attrs) const {
506     assert(OrigUnit != nullptr);
507     return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs);
508   }
509 
510   std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
511                                      ArrayRef<dwarf::Attribute> Attrs) const {
512     if (!Die)
513       return std::nullopt;
514     auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
515     if (AbbrevDecl) {
516       for (auto Attr : Attrs) {
517         if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr,
518                                                        *OrigUnit))
519           return Value;
520       }
521     }
522     return std::nullopt;
523   }
524 
525   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
526     return OrigUnit->getDIEIndexForOffset(Offset);
527   }
528 
529   /// @}
530 
531   /// \defgroup Methods used for reporting warnings and errors:
532   ///
533   /// @{
534 
535   void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
536     GlobalData.warn(Warning, getUnitName(), DIE);
537   }
538 
539   void warn(Error Warning, const DWARFDie *DIE = nullptr) {
540     handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
541       GlobalData.warn(Info.message(), getUnitName(), DIE);
542     });
543   }
544 
545   void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
546     if (DieEntry != nullptr) {
547       DWARFDie DIE(&getOrigUnit(), DieEntry);
548       GlobalData.warn(Warning, getUnitName(), &DIE);
549       return;
550     }
551 
552     GlobalData.warn(Warning, getUnitName());
553   }
554 
555   void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
556     GlobalData.warn(Err, getUnitName(), DIE);
557   }
558 
559   void error(Error Err, const DWARFDie *DIE = nullptr) {
560     handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
561       GlobalData.error(Info.message(), getUnitName(), DIE);
562     });
563   }
564 
565   /// @}
566 
567   /// Save specified accelerator info \p Info.
568   void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
569     AcceleratorRecords.add(Info);
570   }
571 
572   /// Enumerates all units accelerator records.
573   void
574   forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
575     AcceleratorRecords.forEach(Handler);
576   }
577 
578   /// Output unit selector.
579   class OutputUnitVariantPtr {
580   public:
581     OutputUnitVariantPtr(CompileUnit *U);
582     OutputUnitVariantPtr(TypeUnit *U);
583 
584     /// Accessor for common functionality.
585     DwarfUnit *operator->();
586 
587     bool isCompileUnit();
588 
589     bool isTypeUnit();
590 
591     /// Returns CompileUnit if applicable.
592     CompileUnit *getAsCompileUnit();
593 
594     /// Returns TypeUnit if applicable.
595     TypeUnit *getAsTypeUnit();
596 
597   protected:
598     PointerUnion<CompileUnit *, TypeUnit *> Ptr;
599   };
600 
601 private:
602   /// Navigate DWARF tree recursively and set die properties.
603   void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
604                                 bool IsODRUnavailableFunctionScope);
605 
606   struct LinkedLocationExpressionsWithOffsetPatches {
607     DWARFLocationExpression Expression;
608     OffsetsPtrVector Patches;
609   };
610   using LinkedLocationExpressionsVector =
611       SmallVector<LinkedLocationExpressionsWithOffsetPatches>;
612 
613   /// Emit debug locations.
614   void emitLocations(DebugSectionKind LocationSectionKind);
615 
616   /// Emit location list header.
617   uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
618 
619   /// Emit location list fragment.
620   uint64_t emitLocListFragment(
621       const LinkedLocationExpressionsVector &LinkedLocationExpression,
622       SectionDescriptor &OutLocationSection);
623 
624   /// Emit the .debug_addr section fragment for current unit.
625   Error emitDebugAddrSection();
626 
627   /// Emit .debug_aranges.
628   void emitAranges(AddressRanges &LinkedFunctionRanges);
629 
630   /// Clone and emit .debug_ranges/.debug_rnglists.
631   void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
632                              AddressRanges &LinkedFunctionRanges);
633 
634   /// Emit range list header.
635   uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
636 
637   /// Emit range list fragment.
638   void emitRangeListFragment(const AddressRanges &LinkedRanges,
639                              SectionDescriptor &OutRangeSection);
640 
641   /// Insert the new line info sequence \p Seq into the current
642   /// set of already linked line info \p Rows.
643   void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
644                           std::vector<DWARFDebugLine::Row> &Rows);
645 
646   /// Emits body for both macro sections.
647   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
648                           uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
649 
650   /// Creates DIE which would be placed into the "Plain" compile unit.
651   DIE *createPlainDIEandCloneAttributes(
652       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
653       uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
654       std::optional<int64_t> &VarAddressAdjustment);
655 
656   /// Creates DIE which would be placed into the "Type" compile unit.
657   TypeEntry *createTypeDIEandCloneAttributes(
658       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
659       TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit);
660 
661   /// Create output DIE inside specified \p TypeDescriptor.
662   DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
663                        DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
664                        bool IsDeclaration, bool IsParentDeclaration);
665 
666   /// Enumerate \p DieEntry children and assign names for them.
667   Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
668                            SyntheticTypeNameBuilder &NameBuilder);
669 
670   /// DWARFFile containing this compile unit.
671   DWARFFile &File;
672 
673   /// Pointer to the paired compile unit from the input DWARF.
674   DWARFUnit *OrigUnit = nullptr;
675 
676   /// The DW_AT_language of this unit.
677   std::optional<uint16_t> Language;
678 
679   /// Line table for this unit.
680   const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
681 
682   /// Cached resolved paths from the line table.
683   /// The key is <UniqueUnitID, FileIdx>.
684   using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
685   ResolvedPathsMap ResolvedFullPaths;
686   StringMap<StringEntry *> ResolvedParentPaths;
687 
688   /// Maps an address into the index inside .debug_addr section.
689   IndexedValuesMap<uint64_t> DebugAddrIndexMap;
690 
691   std::unique_ptr<DependencyTracker> Dependencies;
692 
693   /// \defgroup Data Members accessed asinchronously.
694   ///
695   /// @{
696   OffsetToUnitTy getUnitFromOffset;
697 
698   std::optional<uint64_t> LowPc;
699   uint64_t HighPc = 0;
700 
701   /// Flag indicating whether type de-duplication is forbidden.
702   bool NoODR = true;
703 
704   /// The ranges in that map are the PC ranges for functions in this unit,
705   /// associated with the PC offset to apply to the addresses to get
706   /// the linked address.
707   RangesTy Ranges;
708   std::mutex RangesMutex;
709 
710   /// The DW_AT_low_pc of each DW_TAG_label.
711   using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
712   LabelMapTy Labels;
713   std::mutex LabelsMutex;
714 
715   /// This field keeps current stage of overall compile unit processing.
716   std::atomic<Stage> Stage;
717 
718   /// DIE info indexed by DIE index.
719   SmallVector<DIEInfo> DieInfoArray;
720   SmallVector<uint64_t> OutDieOffsetArray;
721   SmallVector<TypeEntry *> TypeEntries;
722 
723   /// The list of accelerator records for this unit.
724   ArrayList<AccelInfo> AcceleratorRecords;
725   /// @}
726 };
727 
728 /// \returns list of attributes referencing type DIEs which might be
729 /// deduplicated.
730 /// Note: it does not include DW_AT_containing_type attribute to avoid
731 /// infinite recursion.
732 ArrayRef<dwarf::Attribute> getODRAttributes();
733 
734 } // end of namespace parallel
735 } // end of namespace dwarf_linker
736 } // end of namespace llvm
737 
738 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
739