xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h (revision a90b9d0159070121c221b966469c3e36d912bf82)
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
405   cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,
406                TypeUnit *ArtificialTypeUnit);
407 
408   /// Clone and emit debug locations(.debug_loc/.debug_loclists).
409   Error cloneAndEmitDebugLocations();
410 
411   /// Clone and emit ranges.
412   Error cloneAndEmitRanges();
413 
414   /// Clone and emit debug macros(.debug_macinfo/.debug_macro).
415   Error cloneAndEmitDebugMacro();
416 
417   // Clone input DIE entry.
418   std::pair<DIE *, TypeEntry *>
419   cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
420            TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
421            std::optional<int64_t> FuncAddressAdjustment,
422            std::optional<int64_t> VarAddressAdjustment,
423            BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
424 
425   // Clone and emit line table.
426   Error cloneAndEmitLineTable(const Triple &TargetTriple);
427 
428   /// Clone attribute location axpression.
429   void cloneDieAttrExpression(const DWARFExpression &InputExpression,
430                               SmallVectorImpl<uint8_t> &OutputExpression,
431                               SectionDescriptor &Section,
432                               std::optional<int64_t> VarAddressAdjustment,
433                               OffsetsPtrVector &PatchesOffsets);
434 
435   /// Returns index(inside .debug_addr) of an address.
436   uint64_t getDebugAddrIndex(uint64_t Addr) {
437     return DebugAddrIndexMap.getValueIndex(Addr);
438   }
439 
440   /// Returns directory and file from the line table by index.
441   std::optional<std::pair<StringRef, StringRef>>
442   getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue);
443 
444   /// Returns directory and file from the line table by index.
445   std::optional<std::pair<StringRef, StringRef>>
446   getDirAndFilenameFromLineTable(uint64_t FileIdx);
447 
448   /// \defgroup Helper methods to access OrigUnit.
449   ///
450   /// @{
451 
452   /// Returns paired compile unit from input DWARF.
453   DWARFUnit &getOrigUnit() const {
454     assert(OrigUnit != nullptr);
455     return *OrigUnit;
456   }
457 
458   const DWARFDebugInfoEntry *
459   getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
460     assert(OrigUnit != nullptr);
461     return OrigUnit->getFirstChildEntry(Die);
462   }
463 
464   const DWARFDebugInfoEntry *
465   getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
466     assert(OrigUnit != nullptr);
467     return OrigUnit->getSiblingEntry(Die);
468   }
469 
470   DWARFDie getParent(const DWARFDebugInfoEntry *Die) {
471     assert(OrigUnit != nullptr);
472     return OrigUnit->getParent(Die);
473   }
474 
475   DWARFDie getDIEAtIndex(unsigned Index) {
476     assert(OrigUnit != nullptr);
477     return OrigUnit->getDIEAtIndex(Index);
478   }
479 
480   const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
481     assert(OrigUnit != nullptr);
482     return OrigUnit->getDebugInfoEntry(Index);
483   }
484 
485   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
486     assert(OrigUnit != nullptr);
487     return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
488   }
489 
490   DWARFDie getDIE(const DWARFDebugInfoEntry *Die) {
491     assert(OrigUnit != nullptr);
492     return DWARFDie(OrigUnit, Die);
493   }
494 
495   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
496     assert(OrigUnit != nullptr);
497     return OrigUnit->getDIEIndex(Die);
498   }
499 
500   uint32_t getDIEIndex(const DWARFDie &Die) const {
501     assert(OrigUnit != nullptr);
502     return OrigUnit->getDIEIndex(Die);
503   }
504 
505   std::optional<DWARFFormValue> find(uint32_t DieIdx,
506                                      ArrayRef<dwarf::Attribute> Attrs) const {
507     assert(OrigUnit != nullptr);
508     return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs);
509   }
510 
511   std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
512                                      ArrayRef<dwarf::Attribute> Attrs) const {
513     if (!Die)
514       return std::nullopt;
515     auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
516     if (AbbrevDecl) {
517       for (auto Attr : Attrs) {
518         if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr,
519                                                        *OrigUnit))
520           return Value;
521       }
522     }
523     return std::nullopt;
524   }
525 
526   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
527     return OrigUnit->getDIEIndexForOffset(Offset);
528   }
529 
530   /// @}
531 
532   /// \defgroup Methods used for reporting warnings and errors:
533   ///
534   /// @{
535 
536   void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
537     GlobalData.warn(Warning, getUnitName(), DIE);
538   }
539 
540   void warn(Error Warning, const DWARFDie *DIE = nullptr) {
541     handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
542       GlobalData.warn(Info.message(), getUnitName(), DIE);
543     });
544   }
545 
546   void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
547     if (DieEntry != nullptr) {
548       DWARFDie DIE(&getOrigUnit(), DieEntry);
549       GlobalData.warn(Warning, getUnitName(), &DIE);
550       return;
551     }
552 
553     GlobalData.warn(Warning, getUnitName());
554   }
555 
556   void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
557     GlobalData.warn(Err, getUnitName(), DIE);
558   }
559 
560   void error(Error Err, const DWARFDie *DIE = nullptr) {
561     handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
562       GlobalData.error(Info.message(), getUnitName(), DIE);
563     });
564   }
565 
566   /// @}
567 
568   /// Save specified accelerator info \p Info.
569   void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
570     AcceleratorRecords.add(Info);
571   }
572 
573   /// Enumerates all units accelerator records.
574   void
575   forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
576     AcceleratorRecords.forEach(Handler);
577   }
578 
579   /// Output unit selector.
580   class OutputUnitVariantPtr {
581   public:
582     OutputUnitVariantPtr(CompileUnit *U);
583     OutputUnitVariantPtr(TypeUnit *U);
584 
585     /// Accessor for common functionality.
586     DwarfUnit *operator->();
587 
588     bool isCompileUnit();
589 
590     bool isTypeUnit();
591 
592     /// Returns CompileUnit if applicable.
593     CompileUnit *getAsCompileUnit();
594 
595     /// Returns TypeUnit if applicable.
596     TypeUnit *getAsTypeUnit();
597 
598   protected:
599     PointerUnion<CompileUnit *, TypeUnit *> Ptr;
600   };
601 
602 private:
603   /// Navigate DWARF tree recursively and set die properties.
604   void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
605                                 bool IsODRUnavailableFunctionScope);
606 
607   struct LinkedLocationExpressionsWithOffsetPatches {
608     DWARFLocationExpression Expression;
609     OffsetsPtrVector Patches;
610   };
611   using LinkedLocationExpressionsVector =
612       SmallVector<LinkedLocationExpressionsWithOffsetPatches>;
613 
614   /// Emit debug locations.
615   void emitLocations(DebugSectionKind LocationSectionKind);
616 
617   /// Emit location list header.
618   uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
619 
620   /// Emit location list fragment.
621   uint64_t emitLocListFragment(
622       const LinkedLocationExpressionsVector &LinkedLocationExpression,
623       SectionDescriptor &OutLocationSection);
624 
625   /// Emit the .debug_addr section fragment for current unit.
626   Error emitDebugAddrSection();
627 
628   /// Emit .debug_aranges.
629   void emitAranges(AddressRanges &LinkedFunctionRanges);
630 
631   /// Clone and emit .debug_ranges/.debug_rnglists.
632   void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
633                              AddressRanges &LinkedFunctionRanges);
634 
635   /// Emit range list header.
636   uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
637 
638   /// Emit range list fragment.
639   void emitRangeListFragment(const AddressRanges &LinkedRanges,
640                              SectionDescriptor &OutRangeSection);
641 
642   /// Insert the new line info sequence \p Seq into the current
643   /// set of already linked line info \p Rows.
644   void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
645                           std::vector<DWARFDebugLine::Row> &Rows);
646 
647   /// Emits body for both macro sections.
648   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
649                           uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
650 
651   /// Creates DIE which would be placed into the "Plain" compile unit.
652   DIE *createPlainDIEandCloneAttributes(
653       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
654       uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
655       std::optional<int64_t> &VarAddressAdjustment);
656 
657   /// Creates DIE which would be placed into the "Type" compile unit.
658   TypeEntry *createTypeDIEandCloneAttributes(
659       const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
660       TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit);
661 
662   /// Create output DIE inside specified \p TypeDescriptor.
663   DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
664                        DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
665                        bool IsDeclaration, bool IsParentDeclaration);
666 
667   /// Enumerate \p DieEntry children and assign names for them.
668   Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
669                            SyntheticTypeNameBuilder &NameBuilder);
670 
671   /// DWARFFile containing this compile unit.
672   DWARFFile &File;
673 
674   /// Pointer to the paired compile unit from the input DWARF.
675   DWARFUnit *OrigUnit = nullptr;
676 
677   /// The DW_AT_language of this unit.
678   std::optional<uint16_t> Language;
679 
680   /// Line table for this unit.
681   const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
682 
683   /// Cached resolved paths from the line table.
684   /// The key is <UniqueUnitID, FileIdx>.
685   using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
686   ResolvedPathsMap ResolvedFullPaths;
687   StringMap<StringEntry *> ResolvedParentPaths;
688 
689   /// Maps an address into the index inside .debug_addr section.
690   IndexedValuesMap<uint64_t> DebugAddrIndexMap;
691 
692   std::unique_ptr<DependencyTracker> Dependencies;
693 
694   /// \defgroup Data Members accessed asinchronously.
695   ///
696   /// @{
697   OffsetToUnitTy getUnitFromOffset;
698 
699   std::optional<uint64_t> LowPc;
700   uint64_t HighPc = 0;
701 
702   /// Flag indicating whether type de-duplication is forbidden.
703   bool NoODR = true;
704 
705   /// The ranges in that map are the PC ranges for functions in this unit,
706   /// associated with the PC offset to apply to the addresses to get
707   /// the linked address.
708   RangesTy Ranges;
709   std::mutex RangesMutex;
710 
711   /// The DW_AT_low_pc of each DW_TAG_label.
712   using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
713   LabelMapTy Labels;
714   std::mutex LabelsMutex;
715 
716   /// This field keeps current stage of overall compile unit processing.
717   std::atomic<Stage> Stage;
718 
719   /// DIE info indexed by DIE index.
720   SmallVector<DIEInfo> DieInfoArray;
721   SmallVector<uint64_t> OutDieOffsetArray;
722   SmallVector<TypeEntry *> TypeEntries;
723 
724   /// The list of accelerator records for this unit.
725   ArrayList<AccelInfo> AcceleratorRecords;
726   /// @}
727 };
728 
729 /// \returns list of attributes referencing type DIEs which might be
730 /// deduplicated.
731 /// Note: it does not include DW_AT_containing_type attribute to avoid
732 /// infinite recursion.
733 ArrayRef<dwarf::Attribute> getODRAttributes();
734 
735 } // end of namespace parallel
736 } // end of namespace dwarf_linker
737 } // end of namespace llvm
738 
739 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
740