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