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
16namespace llvm {
17namespace dwarf_linker {
18namespace parallel {
19
20using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
21
22struct AttributesInfo;
23class SyntheticTypeNameBuilder;
24class DIEGenerator;
25class TypeUnit;
26class DependencyTracker;
27
28class CompileUnit;
29
30/// This is a helper structure which keeps a debug info entry
31/// with it's containing compilation unit.
32struct 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
44enum 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
53class alignas(8) CompileUnit : public DwarfUnit {
54public:
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
602private:
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.
733ArrayRef<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