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(DieEntry: getUnitDIE().getDebugInfoEntry(), IsODRUnavailableFunctionScope: 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(i1&: InputData,
189 i2: ((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(i1&: InputData, i2: (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(i1&: InputData, i2: (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 i1&: InputData, i2: 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(Die: 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(Die: Entry)];
299 }
300
301 /// \p Die
302 /// \returns PlainDieInfo descriptor.
303 DIEInfo &getDIEInfo(const DWARFDie &Die) {
304 return DieInfoArray[getOrigUnit().getDIEIndex(D: Die)];
305 }
306
307 /// \p Die
308 /// \returns PlainDieInfo descriptor.
309 const DIEInfo &getDIEInfo(const DWARFDie &Die) const {
310 return DieInfoArray[getOrigUnit().getDIEIndex(D: 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(Die: 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(Die: 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(i: 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(p: 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(Die: InputDieEntry)])
363 ->store(p: 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(Val: 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(Value: 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(D: Die);
503 }
504
505 std::optional<DWARFFormValue> find(uint32_t DieIdx,
506 ArrayRef<dwarf::Attribute> Attrs) const {
507 assert(OrigUnit != nullptr);
508 return find(Die: OrigUnit->getDebugInfoEntry(Index: 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(DIEOffset: Die->getOffset(), Attr,
519 U: *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, Context: getUnitName(), DIE);
538 }
539
540 void warn(Error Warning, const DWARFDie *DIE = nullptr) {
541 handleAllErrors(E: std::move(Warning), Handlers: [&](ErrorInfoBase &Info) {
542 GlobalData.warn(Warning: Info.message(), Context: 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, Context: getUnitName(), DIE: &DIE);
550 return;
551 }
552
553 GlobalData.warn(Warning, Context: getUnitName());
554 }
555
556 void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
557 GlobalData.warn(Warning: Err, Context: getUnitName(), DIE);
558 }
559
560 void error(Error Err, const DWARFDie *DIE = nullptr) {
561 handleAllErrors(E: std::move(Err), Handlers: [&](ErrorInfoBase &Info) {
562 GlobalData.error(Err: Info.message(), Context: getUnitName(), DIE);
563 });
564 }
565
566 /// @}
567
568 /// Save specified accelerator info \p Info.
569 void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
570 AcceleratorRecords.add(Item: 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