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