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 <limits>
15#include <optional>
16
17namespace llvm {
18namespace dwarf_linker {
19namespace parallel {
20
21using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
22
23struct AttributesInfo;
24class SyntheticTypeNameBuilder;
25class DIEGenerator;
26class TypeUnit;
27class DependencyTracker;
28
29class CompileUnit;
30
31/// This is a helper structure which keeps a debug info entry
32/// with it's containing compilation unit.
33struct UnitEntryPairTy {
34 UnitEntryPairTy() = default;
35 UnitEntryPairTy(CompileUnit *CU, const DWARFDebugInfoEntry *DieEntry)
36 : CU(CU), DieEntry(DieEntry) {}
37
38 CompileUnit *CU = nullptr;
39 const DWARFDebugInfoEntry *DieEntry = nullptr;
40
41 UnitEntryPairTy getNamespaceOrigin();
42 std::optional<UnitEntryPairTy> getParent();
43};
44
45enum ResolveInterCUReferencesMode : bool {
46 Resolve = true,
47 AvoidResolving = false,
48};
49
50/// Stores all information related to a compile unit, be it in its original
51/// instance of the object file or its brand new cloned and generated DIE tree.
52/// NOTE: we need alignment of at least 8 bytes as we use
53/// PointerIntPair<CompileUnit *, 3> in the DependencyTracker.h
54class alignas(8) CompileUnit : public DwarfUnit {
55public:
56 /// The stages of new compile unit processing.
57 enum class Stage : uint8_t {
58 /// Created, linked with input DWARF file.
59 CreatedNotLoaded = 0,
60
61 /// Input DWARF is loaded.
62 Loaded,
63
64 /// Input DWARF is analysed(DIEs pointing to the real code section are
65 /// discovered, type names are assigned if ODR is requested).
66 LivenessAnalysisDone,
67
68 /// Check if dependencies have incompatible placement.
69 /// If that is the case modify placement to be compatible.
70 UpdateDependenciesCompleteness,
71
72 /// Type names assigned to DIEs.
73 TypeNamesAssigned,
74
75 /// Output DWARF is generated.
76 Cloned,
77
78 /// Offsets inside patch records are updated.
79 PatchesUpdated,
80
81 /// Resources(Input DWARF, Output DWARF tree) are released.
82 Cleaned,
83
84 /// Compile Unit should be skipped
85 Skipped
86 };
87
88 CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
89 StringRef ClangModuleName, DWARFFile &File,
90 OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
91 llvm::endianness Endianess);
92
93 CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, unsigned ID,
94 StringRef ClangModuleName, DWARFFile &File,
95 OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
96 llvm::endianness Endianess);
97
98 /// Returns stage of overall processing.
99 Stage getStage() const { return Stage; }
100
101 /// Returns raw DW_AT_language of the input compile unit.
102 std::optional<uint16_t> getLanguage() const { return Language; }
103
104 /// Set stage of overall processing.
105 void setStage(Stage Stage) { this->Stage = Stage; }
106
107 /// Loads unit line table.
108 void loadLineTable();
109
110 /// Returns name of the file for the \p FileIdx
111 /// from the unit`s line table.
112 StringEntry *getFileName(unsigned FileIdx, StringPool &GlobalStrings);
113
114 /// Returns DWARFFile containing this compile unit.
115 const DWARFFile &getContainingFile() const { return File; }
116
117 /// Appends the names of the DW_TAG_module enclosing \p DieEntry, outermost
118 /// first. Returns false when one of them has no name making the module
119 /// unidentifiable across units.
120 bool getModulePath(const DWARFDebugInfoEntry *DieEntry,
121 SmallVectorImpl<char> &Path);
122
123 /// Must run while the output offsets are still available, and once they are
124 /// final.
125 void noteModuleAnchors();
126
127 /// Set deterministic priority for type DIE allocation ordering. Units compare
128 /// by \p ObjFileIdx first and by \p LocalIdx second.
129 /// Lower priority values win when multiple CUs race to define the same type.
130 llvm::Error setPriority(uint64_t ObjFileIdx, uint64_t LocalIdx);
131
132 uint64_t getPriority() const { return Priority; }
133
134 /// Load DIEs of input compilation unit. \returns true if input DIEs
135 /// successfully loaded.
136 bool loadInputDIEs();
137
138 /// Reset compile units data(results of liveness analysis, clonning)
139 /// if current stage greater than Stage::Loaded. We need to reset data
140 /// as we are going to repeat stages.
141 void maybeResetToLoadedStage();
142
143 /// Collect references to parseable Swift interfaces in imported
144 /// DW_TAG_module blocks. The entries are staged on the CompileUnit and
145 /// merged into the shared map after the parallel analysis phase.
146 void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry);
147
148 /// Merge the Swift interface entries collected by analyzeImportedModule
149 /// into \p Map, emitting a warning for each conflicting path. Must be
150 /// called serially after analysis has completed.
151 void mergeSwiftInterfaces(DWARFLinkerBase::SwiftInterfacesMapTy &Map);
152
153 /// Navigate DWARF tree and set die properties.
154 void analyzeDWARFStructure() {
155 analyzeDWARFStructureRec(DieEntry: getUnitDIE().getDebugInfoEntry(), IsODRUnavailableFunctionScope: false);
156 }
157
158 /// Cleanup unneeded resources after compile unit is cloned.
159 void cleanupDataAfterClonning();
160
161 /// After cloning stage the output DIEs offsets are deallocated.
162 /// This method copies output offsets for referenced DIEs into DIEs patches.
163 void updateDieRefPatchesWithClonedOffsets();
164
165 /// Search for subprograms and variables referencing live code and discover
166 /// dependend DIEs. Mark live DIEs, set placement for DIEs.
167 bool resolveDependenciesAndMarkLiveness(
168 bool InterCUProcessingStarted,
169 std::atomic<bool> &HasNewInterconnectedCUs);
170
171 /// Check dependend DIEs for incompatible placement.
172 /// Make placement to be consistent.
173 bool updateDependenciesCompleteness();
174
175 /// Check DIEs to have a consistent marking(keep marking, placement marking).
176 void verifyDependencies();
177
178 /// Search for type entries and assign names.
179 Error assignTypeNames(TypePool &TypePoolRef);
180
181 /// Kinds of placement for the output die.
182 enum DieOutputPlacement : uint8_t {
183 NotSet = 0,
184
185 /// Corresponding DIE goes to the type table only.
186 TypeTable = 1,
187
188 /// Corresponding DIE goes to the plain dwarf only.
189 PlainDwarf = 2,
190
191 /// Corresponding DIE goes to type table and to plain dwarf.
192 Both = 3,
193 };
194
195 /// Information gathered about source DIEs.
196 struct DIEInfo {
197 DIEInfo() = default;
198 DIEInfo(const DIEInfo &Other) { Flags = Other.Flags.load(); }
199 DIEInfo &operator=(const DIEInfo &Other) {
200 Flags = Other.Flags.load();
201 return *this;
202 }
203
204 /// Data member keeping various flags.
205 std::atomic<uint16_t> Flags = {0};
206
207 /// \returns Placement kind for the corresponding die.
208 DieOutputPlacement getPlacement() const {
209 return DieOutputPlacement(Flags & 0x7);
210 }
211
212 /// Sets Placement kind for the corresponding die.
213 void setPlacement(DieOutputPlacement Placement) {
214 auto InputData = Flags.load();
215 while (!Flags.compare_exchange_weak(i1&: InputData,
216 i2: ((InputData & ~0x7) | Placement))) {
217 }
218 }
219
220 /// Unsets Placement kind for the corresponding die.
221 void unsetPlacement() {
222 auto InputData = Flags.load();
223 while (!Flags.compare_exchange_weak(i1&: InputData, i2: (InputData & ~0x7))) {
224 }
225 }
226
227 /// Sets Placement kind for the corresponding die.
228 bool setPlacementIfUnset(DieOutputPlacement Placement) {
229 auto InputData = Flags.load();
230 if ((InputData & 0x7) == NotSet)
231 if (Flags.compare_exchange_strong(i1&: InputData, i2: (InputData | Placement)))
232 return true;
233
234 return false;
235 }
236
237 /// Atomically joins \p Placement into the current placement: the
238 /// least-upper-bound of the lattice NotSet < {TypeTable, PlainDwarf} <
239 /// Both, which is a plain OR because the values are bit flags. The join is
240 /// monotone and never clears a bit, so unlike setPlacement it composes
241 /// correctly when applied concurrently from several marks.
242 void joinPlacement(DieOutputPlacement Placement) {
243 auto InputData = Flags.load();
244 while (!Flags.compare_exchange_weak(i1&: InputData, i2: (InputData | Placement))) {
245 }
246 }
247
248 /// Atomically joins \p Placement for a DW_TAG_variable, for which
249 /// PlainDwarf is absorbing because a variable cannot occupy the type table
250 /// and plain DWARF at once. Once the placement is (or concurrently becomes)
251 /// PlainDwarf it stays PlainDwarf, otherwise \p Placement is OR-joined.
252 /// Recomputing inside the compare_exchange loop keeps a racing PlainDwarf
253 /// mark from turning the variable into Both.
254 void joinVariablePlacement(DieOutputPlacement Placement) {
255 auto InputData = Flags.load();
256 uint16_t Desired;
257 do {
258 DieOutputPlacement Current = DieOutputPlacement(InputData & 0x7);
259 DieOutputPlacement Joined =
260 (Current == PlainDwarf || Current == Both)
261 ? PlainDwarf
262 : DieOutputPlacement(Current | Placement);
263 Desired = (InputData & ~0x7) | Joined;
264 } while (!Flags.compare_exchange_weak(i1&: InputData, i2: Desired));
265 }
266
267#define SINGLE_FLAG_METHODS_SET(Name, Value) \
268 bool get##Name() const { return Flags & Value; } \
269 void set##Name() { \
270 auto InputData = Flags.load(); \
271 while (!Flags.compare_exchange_weak(InputData, InputData | Value)) { \
272 } \
273 } \
274 void unset##Name() { \
275 auto InputData = Flags.load(); \
276 while (!Flags.compare_exchange_weak(InputData, InputData & ~Value)) { \
277 } \
278 }
279
280 /// DIE is a part of the linked output.
281 SINGLE_FLAG_METHODS_SET(Keep, 0x08)
282
283 /// DIE has children which are part of the linked output.
284 SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10)
285
286 /// DIE has children which are part of the type table.
287 SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20)
288
289 /// DIE is in module scope.
290 SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40)
291
292 /// DIE is in function scope.
293 SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80)
294
295 /// DIE is in anonymous namespace scope.
296 SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100)
297
298 /// DIE is available for ODR type deduplication.
299 SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200)
300
301 /// Track liveness for the DIE.
302 SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400)
303
304 /// Track liveness for the DIE.
305 SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800)
306
307 void unsetFlagsWhichSetDuringLiveAnalysis() {
308 auto InputData = Flags.load();
309 while (!Flags.compare_exchange_weak(
310 i1&: InputData, i2: InputData & ~(0x7 | 0x8 | 0x10 | 0x20))) {
311 }
312 }
313
314 /// Erase all flags.
315 void eraseData() { Flags = 0; }
316
317#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
318 LLVM_DUMP_METHOD void dump();
319#endif
320
321 bool needToPlaceInTypeTable() const {
322 return (getKeep() && (getPlacement() == CompileUnit::TypeTable ||
323 getPlacement() == CompileUnit::Both)) ||
324 getKeepTypeChildren();
325 }
326
327 bool needToKeepInPlainDwarf() const {
328 return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf ||
329 getPlacement() == CompileUnit::Both)) ||
330 getKeepPlainChildren();
331 }
332 };
333
334 /// \defgroup Group of functions returning DIE info.
335 ///
336 /// @{
337
338 /// \p Idx index of the DIE.
339 /// \returns DieInfo descriptor.
340 DIEInfo &getDIEInfo(unsigned Idx) { return DieInfoArray[Idx]; }
341
342 /// \p Idx index of the DIE.
343 /// \returns DieInfo descriptor.
344 const DIEInfo &getDIEInfo(unsigned Idx) const { return DieInfoArray[Idx]; }
345
346 /// \p Idx index of the DIE.
347 /// \returns DieInfo descriptor.
348 DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) {
349 return DieInfoArray[getOrigUnit().getDIEIndex(Die: Entry)];
350 }
351
352 /// \p Idx index of the DIE.
353 /// \returns DieInfo descriptor.
354 const DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) const {
355 return DieInfoArray[getOrigUnit().getDIEIndex(Die: Entry)];
356 }
357
358 /// \p Die
359 /// \returns PlainDieInfo descriptor.
360 DIEInfo &getDIEInfo(const DWARFDie &Die) {
361 return DieInfoArray[getOrigUnit().getDIEIndex(D: Die)];
362 }
363
364 /// \p Die
365 /// \returns PlainDieInfo descriptor.
366 const DIEInfo &getDIEInfo(const DWARFDie &Die) const {
367 return DieInfoArray[getOrigUnit().getDIEIndex(D: Die)];
368 }
369
370 /// \p Idx index of the DIE.
371 /// \returns DieInfo descriptor.
372 uint64_t getDieOutOffset(uint32_t Idx) {
373 return reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
374 ->load();
375 }
376
377 /// \p Idx index of the DIE.
378 /// \returns type entry.
379 TypeEntry *getDieTypeEntry(uint32_t Idx) {
380 return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
381 ->load();
382 }
383
384 /// \p InputDieEntry debug info entry.
385 /// \returns DieInfo descriptor.
386 uint64_t getDieOutOffset(const DWARFDebugInfoEntry *InputDieEntry) {
387 return reinterpret_cast<std::atomic<uint64_t> *>(
388 &OutDieOffsetArray[getOrigUnit().getDIEIndex(Die: InputDieEntry)])
389 ->load();
390 }
391
392 /// \p InputDieEntry debug info entry.
393 /// \returns type entry.
394 TypeEntry *getDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry) {
395 return reinterpret_cast<std::atomic<TypeEntry *> *>(
396 &TypeEntries[getOrigUnit().getDIEIndex(Die: InputDieEntry)])
397 ->load();
398 }
399
400 /// \p Idx index of the DIE.
401 /// \returns DieInfo descriptor.
402 void rememberDieOutOffset(uint32_t Idx, uint64_t Offset) {
403 reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
404 ->store(i: Offset);
405 }
406
407 /// \p Idx index of the DIE.
408 /// \p Type entry.
409 void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry) {
410 reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
411 ->store(p: Entry);
412 }
413
414 /// \p InputDieEntry debug info entry.
415 /// \p Type entry.
416 void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry,
417 TypeEntry *Entry) {
418 reinterpret_cast<std::atomic<TypeEntry *> *>(
419 &TypeEntries[getOrigUnit().getDIEIndex(Die: InputDieEntry)])
420 ->store(p: Entry);
421 }
422
423 /// @}
424
425 /// Returns value of DW_AT_low_pc attribute.
426 std::optional<uint64_t> getLowPc() const { return LowPc; }
427
428 /// Returns value of DW_AT_high_pc attribute.
429 uint64_t getHighPc() const { return HighPc; }
430
431 /// Returns true if there is a label corresponding to the specified \p Addr.
432 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Val: Addr); }
433
434 /// Add the low_pc of a label that is relocated by applying
435 /// offset \p PCOffset.
436 void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
437
438 /// Resolve the DIE attribute reference that has been extracted in \p
439 /// RefValue. The resulting DIE might be in another CompileUnit.
440 /// \returns referenced die and corresponding compilation unit.
441 /// compilation unit is null if reference could not be resolved.
442 std::optional<UnitEntryPairTy>
443 resolveDIEReference(const DWARFFormValue &RefValue,
444 ResolveInterCUReferencesMode CanResolveInterCUReferences);
445
446 std::optional<UnitEntryPairTy>
447 resolveDIEReference(const DWARFDebugInfoEntry *DieEntry,
448 dwarf::Attribute Attr,
449 ResolveInterCUReferencesMode CanResolveInterCUReferences);
450
451 /// @}
452
453 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
454 /// offset \p PCOffset.
455 void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
456
457 /// Returns function ranges of this unit.
458 const RangesTy &getFunctionRanges() const { return Ranges; }
459
460 /// Record that a DW_AT_LLVM_stmt_sequence attribute on this unit
461 /// references the input line-table sequence whose header sits at
462 /// \p InputStmtSeqOffset. Resolution of that offset to an input
463 /// first-row index (via parser results plus a manual boundary-based
464 /// fallback) happens in a post-cloning pass, before \p V is rewritten
465 /// to the byte offset of the matching output sequence. Keying on row
466 /// index rather than address avoids collisions when two input
467 /// sequences would relocate to the same output address (e.g. ICF).
468 void noteStmtSeqListAttribute(DIEValue *V, uint64_t InputStmtSeqOffset) {
469 StmtSeqListAttributes.push_back(Elt: {.Value: V, .InputStmtSeqOffset: InputStmtSeqOffset});
470 }
471
472 /// Clone and emit this compilation unit.
473 Error
474 cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,
475 TypeUnit *ArtificialTypeUnit);
476
477 /// Clone and emit debug locations(.debug_loc/.debug_loclists).
478 Error cloneAndEmitDebugLocations();
479
480 /// Clone and emit ranges.
481 Error cloneAndEmitRanges();
482
483 /// Clone and emit debug macros(.debug_macinfo/.debug_macro).
484 Error cloneAndEmitDebugMacro();
485
486 // Clone input DIE entry. \p SiblingOrdinal is this DIE's position in its
487 // parent's child list, or UINT32_MAX for the unit DIE.
488 std::pair<DIE *, TypeEntry *>
489 cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
490 TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
491 std::optional<int64_t> FuncAddressAdjustment,
492 std::optional<int64_t> VarAddressAdjustment,
493 BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit,
494 uint32_t SiblingOrdinal = std::numeric_limits<uint32_t>::max());
495
496 // Clone and emit line table.
497 Error cloneAndEmitLineTable(const Triple &TargetTriple);
498
499 /// Clone attribute location axpression.
500 void cloneDieAttrExpression(const DWARFExpression &InputExpression,
501 SmallVectorImpl<uint8_t> &OutputExpression,
502 SectionDescriptor &Section,
503 std::optional<int64_t> VarAddressAdjustment,
504 OffsetsPtrVector &PatchesOffsets);
505
506 /// Returns index(inside .debug_addr) of an address.
507 uint64_t getDebugAddrIndex(uint64_t Addr) {
508 return DebugAddrIndexMap.getValueIndex(Value: Addr);
509 }
510
511 /// Returns directory and file from the line table by index.
512 std::optional<std::pair<StringRef, StringRef>>
513 getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue);
514
515 /// Returns directory and file from the line table by index.
516 std::optional<std::pair<StringRef, StringRef>>
517 getDirAndFilenameFromLineTable(uint64_t FileIdx);
518
519 /// \defgroup Helper methods to access OrigUnit.
520 ///
521 /// @{
522
523 /// Returns paired compile unit from input DWARF.
524 DWARFUnit &getOrigUnit() const {
525 assert(OrigUnit != nullptr);
526 return *OrigUnit;
527 }
528
529 const DWARFDebugInfoEntry *
530 getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
531 assert(OrigUnit != nullptr);
532 return OrigUnit->getFirstChildEntry(Die);
533 }
534
535 const DWARFDebugInfoEntry *
536 getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
537 assert(OrigUnit != nullptr);
538 return OrigUnit->getSiblingEntry(Die);
539 }
540
541 DWARFDie getParent(const DWARFDebugInfoEntry *Die) {
542 assert(OrigUnit != nullptr);
543 return OrigUnit->getParent(Die);
544 }
545
546 DWARFDie getDIEAtIndex(unsigned Index) {
547 assert(OrigUnit != nullptr);
548 return OrigUnit->getDIEAtIndex(Index);
549 }
550
551 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
552 assert(OrigUnit != nullptr);
553 return OrigUnit->getDebugInfoEntry(Index);
554 }
555
556 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
557 assert(OrigUnit != nullptr);
558 return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
559 }
560
561 DWARFDie getDIE(const DWARFDebugInfoEntry *Die) {
562 assert(OrigUnit != nullptr);
563 return DWARFDie(OrigUnit, Die);
564 }
565
566 uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
567 assert(OrigUnit != nullptr);
568 return OrigUnit->getDIEIndex(Die);
569 }
570
571 uint32_t getDIEIndex(const DWARFDie &Die) const {
572 assert(OrigUnit != nullptr);
573 return OrigUnit->getDIEIndex(D: Die);
574 }
575
576 std::optional<DWARFFormValue> find(uint32_t DieIdx,
577 ArrayRef<dwarf::Attribute> Attrs) const {
578 assert(OrigUnit != nullptr);
579 return find(Die: OrigUnit->getDebugInfoEntry(Index: DieIdx), Attrs);
580 }
581
582 std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
583 ArrayRef<dwarf::Attribute> Attrs) const {
584 if (!Die)
585 return std::nullopt;
586 auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
587 if (AbbrevDecl) {
588 for (auto Attr : Attrs) {
589 if (auto Value = AbbrevDecl->getAttributeValue(DIEOffset: Die->getOffset(), Attr,
590 U: *OrigUnit))
591 return Value;
592 }
593 }
594 return std::nullopt;
595 }
596
597 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
598 return OrigUnit->getDIEIndexForOffset(Offset);
599 }
600
601 /// @}
602
603 /// \defgroup Methods used for reporting warnings and errors:
604 ///
605 /// @{
606
607 void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
608 GlobalData.warn(Warning, Context: getUnitName(), DIE);
609 }
610
611 void warn(Error Warning, const DWARFDie *DIE = nullptr) {
612 handleAllErrors(E: std::move(Warning), Handlers: [&](ErrorInfoBase &Info) {
613 GlobalData.warn(Warning: Info.message(), Context: getUnitName(), DIE);
614 });
615 }
616
617 void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
618 if (DieEntry != nullptr) {
619 DWARFDie DIE(&getOrigUnit(), DieEntry);
620 GlobalData.warn(Warning, Context: getUnitName(), DIE: &DIE);
621 return;
622 }
623
624 GlobalData.warn(Warning, Context: getUnitName());
625 }
626
627 void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
628 GlobalData.warn(Warning: Err, Context: getUnitName(), DIE);
629 }
630
631 void error(Error Err, const DWARFDie *DIE = nullptr) {
632 handleAllErrors(E: std::move(Err), Handlers: [&](ErrorInfoBase &Info) {
633 GlobalData.error(Err: Info.message(), Context: getUnitName(), DIE);
634 });
635 }
636
637 /// @}
638
639 /// Save specified accelerator info \p Info.
640 void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
641 AcceleratorRecords.add(Item: Info);
642 }
643
644 /// Enumerates all units accelerator records.
645 void
646 forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
647 AcceleratorRecords.forEach(Handler);
648 }
649
650 /// Output unit selector.
651 class OutputUnitVariantPtr {
652 public:
653 OutputUnitVariantPtr(CompileUnit *U);
654 OutputUnitVariantPtr(TypeUnit *U);
655
656 /// Accessor for common functionality.
657 DwarfUnit *operator->();
658
659 bool isCompileUnit();
660
661 bool isTypeUnit();
662
663 /// Returns CompileUnit if applicable.
664 CompileUnit *getAsCompileUnit();
665
666 /// Returns TypeUnit if applicable.
667 TypeUnit *getAsTypeUnit();
668
669 protected:
670 PointerUnion<CompileUnit *, TypeUnit *> Ptr;
671 };
672
673private:
674 /// Navigate DWARF tree recursively and set die properties.
675 void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
676 bool IsODRUnavailableFunctionScope);
677
678 struct LinkedLocationExpressionsWithOffsetPatches {
679 DWARFLocationExpression Expression;
680 OffsetsPtrVector Patches;
681 };
682 using LinkedLocationExpressionsVector =
683 SmallVector<LinkedLocationExpressionsWithOffsetPatches>;
684
685 /// Emit debug locations.
686 void emitLocations(DebugSectionKind LocationSectionKind);
687
688 /// Emit location list header.
689 uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
690
691 /// Emit location list fragment.
692 uint64_t emitLocListFragment(
693 const LinkedLocationExpressionsVector &LinkedLocationExpression,
694 SectionDescriptor &OutLocationSection);
695
696 /// Emit the .debug_addr section fragment for current unit.
697 Error emitDebugAddrSection();
698
699 /// Emit .debug_aranges.
700 void emitAranges(AddressRanges &LinkedFunctionRanges);
701
702 /// Clone and emit .debug_ranges/.debug_rnglists.
703 void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
704 AddressRanges &LinkedFunctionRanges);
705
706 /// Emit range list header.
707 uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
708
709 /// Emit range list fragment.
710 void emitRangeListFragment(const AddressRanges &LinkedRanges,
711 SectionDescriptor &OutRangeSection);
712
713 /// Insert the new line info sequence \p Seq into the current
714 /// set of already linked line info \p Rows. \p SeqIndices carries the
715 /// input Row index that each entry in \p Seq originated from (or the
716 /// invalid-row-index sentinel for manufactured end-of-range rows), and
717 /// is kept in lockstep with \p RowIndices.
718 void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
719 SmallVectorImpl<uint64_t> &SeqIndices,
720 std::vector<DWARFDebugLine::Row> &Rows,
721 SmallVectorImpl<uint64_t> &RowIndices);
722
723 /// Filter \p InputLineTable's rows to those covered by this unit's
724 /// function ranges, relocating addresses in the process, and store the
725 /// result in \p NewRows. \p NewRowIndices is populated in lockstep with
726 /// \p NewRows and carries, for each output row, the index of the input
727 /// row it originated from — or InvalidRowIndex for manufactured
728 /// end-of-range rows.
729 void filterLineTableRows(const DWARFDebugLine::LineTable &InputLineTable,
730 std::vector<DWARFDebugLine::Row> &NewRows,
731 SmallVectorImpl<uint64_t> &NewRowIndices);
732
733 /// Rewrite every DW_AT_LLVM_stmt_sequence DIEValue recorded on this
734 /// unit with the local .debug_line offset of the output sequence
735 /// containing the corresponding input first row.
736 /// \p SeqOffsetToFirstRowIndex maps an input stmt-sequence offset to
737 /// its first-row index (built by buildStmtSeqOffsetToFirstRowIndex so
738 /// that sequences missed by the DWARF parser are recovered from row
739 /// boundaries). \p RowIndexToSeqStartOffset maps an input first-row
740 /// index to the byte offset of the output DW_LNE_set_address that
741 /// opens the matching output sequence.
742 void patchStmtSeqAttributes(
743 const DenseMap<uint64_t, uint64_t> &SeqOffsetToFirstRowIndex,
744 const DenseMap<uint64_t, uint64_t> &RowIndexToSeqStartOffset);
745
746 /// Build a map from input stmt-sequence offset to the first-row index
747 /// of the corresponding sequence in \p InputLineTable. Seeds the map
748 /// from \p InputLineTable.Sequences (the DWARF parser's results), then
749 /// augments it by manually walking row boundaries and realigning them
750 /// against the recorded DW_AT_LLVM_stmt_sequence values so that
751 /// sequences missed by the parser still resolve. Mirrors the
752 /// classic DWARFLinker's constructSeqOffsettoOrigRowMapping.
753 DenseMap<uint64_t, uint64_t> buildStmtSeqOffsetToFirstRowIndex(
754 const DWARFDebugLine::LineTable &InputLineTable) const;
755
756 /// Emits body for both macro sections.
757 void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
758 uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
759
760 /// Creates DIE which would be placed into the "Plain" compile unit.
761 DIE *createPlainDIEandCloneAttributes(
762 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
763 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
764 std::optional<int64_t> &VarAddressAdjustment);
765
766 /// Creates DIE which would be placed into the "Type" compile unit.
767 /// \p SiblingOrdinal is the input DIE's position in its parent's child list.
768 TypeEntry *createTypeDIEandCloneAttributes(
769 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
770 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit,
771 uint32_t SiblingOrdinal);
772
773 /// Create output DIE inside specified \p TypeDescriptor.
774 DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
775 DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
776 bool IsDeclaration, bool IsParentDeclaration);
777
778 /// Enumerate \p DieEntry children and assign names for them.
779 Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
780 SyntheticTypeNameBuilder &NameBuilder);
781
782 /// DWARFFile containing this compile unit.
783 DWARFFile &File;
784
785 /// Pointer to the paired compile unit from the input DWARF.
786 DWARFUnit *OrigUnit = nullptr;
787
788 /// Raw DW_AT_language from the input (not ODR-filtered).
789 std::optional<uint16_t> Language;
790
791 /// Parseable Swift interface entries staged during the parallel analysis
792 /// phase. Merged serially afterwards.
793 struct PendingSwiftInterface {
794 PendingSwiftInterface(StringRef ModuleName, StringRef ResolvedPath)
795 : ModuleName(ModuleName), ResolvedPath(ResolvedPath) {}
796 std::string ModuleName;
797 std::string ResolvedPath;
798 };
799 SmallVector<PendingSwiftInterface> PendingSwiftInterfaces;
800
801 /// Line table for this unit.
802 const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
803
804 /// Cached resolved paths from the line table.
805 /// The key is <UniqueUnitID, FileIdx>.
806 using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
807 ResolvedPathsMap ResolvedFullPaths;
808 StringMap<StringEntry *> ResolvedParentPaths;
809
810 /// Maps an address into the index inside .debug_addr section.
811 IndexedValuesMap<uint64_t> DebugAddrIndexMap;
812
813 std::unique_ptr<DependencyTracker> Dependencies;
814
815 /// \defgroup Data Members accessed asynchronously.
816 ///
817 /// @{
818 OffsetToUnitTy getUnitFromOffset;
819
820 std::optional<uint64_t> LowPc;
821 uint64_t HighPc = 0;
822
823 /// Flag indicating whether type de-duplication is forbidden.
824 bool NoODR = true;
825
826 /// Deterministic priority for type DIE allocation (lower wins).
827 uint64_t Priority = std::numeric_limits<uint64_t>::max();
828
829 /// The ranges in that map are the PC ranges for functions in this unit,
830 /// associated with the PC offset to apply to the addresses to get
831 /// the linked address.
832 RangesTy Ranges;
833 std::mutex RangesMutex;
834
835 /// The DW_AT_low_pc of each DW_TAG_label.
836 using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
837 LabelMapTy Labels;
838
839 /// Recorded DW_AT_LLVM_stmt_sequence attributes for this unit. Each
840 /// entry pairs the DIEValue holding the attribute with the input-side
841 /// byte offset of the referenced line-table sequence. The value is
842 /// rewritten with the matching output offset after the line table has
843 /// been emitted; resolution from input offset to input first-row
844 /// index (including the parser-miss fallback) happens at patch time.
845 struct StmtSeqPatch {
846 DIEValue *Value = nullptr;
847 uint64_t InputStmtSeqOffset = 0;
848 };
849 SmallVector<StmtSeqPatch, 4> StmtSeqListAttributes;
850 std::mutex LabelsMutex;
851
852 /// This field keeps current stage of overall compile unit processing.
853 std::atomic<Stage> Stage;
854
855 /// DIE info indexed by DIE index.
856 SmallVector<DIEInfo> DieInfoArray;
857 SmallVector<uint64_t> OutDieOffsetArray;
858 SmallVector<TypeEntry *> TypeEntries;
859
860 /// The list of accelerator records for this unit.
861 ArrayList<AccelInfo> AcceleratorRecords;
862 /// @}
863};
864
865/// \returns list of attributes referencing type DIEs which might be
866/// deduplicated.
867/// Note: it does not include DW_AT_containing_type attribute to avoid
868/// infinite recursion.
869ArrayRef<dwarf::Attribute> getODRAttributes();
870
871} // end of namespace parallel
872} // end of namespace dwarf_linker
873} // end of namespace llvm
874
875#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
876