LLVM 23.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
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#define SINGLE_FLAG_METHODS_SET(Name, Value) \
224 bool get##Name() const { return Flags & Value; } \
225 void set##Name() { \
226 auto InputData = Flags.load(); \
227 while (!Flags.compare_exchange_weak(InputData, InputData | Value)) { \
228 } \
229 } \
230 void unset##Name() { \
231 auto InputData = Flags.load(); \
232 while (!Flags.compare_exchange_weak(InputData, InputData & ~Value)) { \
233 } \
234 }
235
236 /// DIE is a part of the linked output.
238
239 /// DIE has children which are part of the linked output.
240 SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10)
241
242 /// DIE has children which are part of the type table.
243 SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20)
244
245 /// DIE is in module scope.
246 SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40)
247
248 /// DIE is in function scope.
249 SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80)
250
251 /// DIE is in anonymous namespace scope.
252 SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100)
253
254 /// DIE is available for ODR type deduplication.
255 SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200)
256
257 /// Track liveness for the DIE.
258 SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400)
259
260 /// Track liveness for the DIE.
261 SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800)
262
264 auto InputData = Flags.load();
265 while (!Flags.compare_exchange_weak(
266 InputData, InputData & ~(0x7 | 0x8 | 0x10 | 0x20))) {
267 }
268 }
269
270 /// Erase all flags.
271 void eraseData() { Flags = 0; }
272
273#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
274 LLVM_DUMP_METHOD void dump();
275#endif
276
278 return (getKeep() && (getPlacement() == CompileUnit::TypeTable ||
280 getKeepTypeChildren();
281 }
282
284 return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf ||
286 getKeepPlainChildren();
287 }
288 };
289
290 /// \defgroup Group of functions returning DIE info.
291 ///
292 /// @{
293
294 /// \p Idx index of the DIE.
295 /// \returns DieInfo descriptor.
296 DIEInfo &getDIEInfo(unsigned Idx) { return DieInfoArray[Idx]; }
297
298 /// \p Idx index of the DIE.
299 /// \returns DieInfo descriptor.
300 const DIEInfo &getDIEInfo(unsigned Idx) const { return DieInfoArray[Idx]; }
301
302 /// \p Idx index of the DIE.
303 /// \returns DieInfo descriptor.
305 return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
306 }
307
308 /// \p Idx index of the DIE.
309 /// \returns DieInfo descriptor.
310 const DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) const {
311 return DieInfoArray[getOrigUnit().getDIEIndex(Entry)];
312 }
313
314 /// \p Die
315 /// \returns PlainDieInfo descriptor.
317 return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
318 }
319
320 /// \p Die
321 /// \returns PlainDieInfo descriptor.
322 const DIEInfo &getDIEInfo(const DWARFDie &Die) const {
323 return DieInfoArray[getOrigUnit().getDIEIndex(Die)];
324 }
325
326 /// \p Idx index of the DIE.
327 /// \returns DieInfo descriptor.
329 return reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
330 ->load();
331 }
332
333 /// \p Idx index of the DIE.
334 /// \returns type entry.
336 return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
337 ->load();
338 }
339
340 /// \p InputDieEntry debug info entry.
341 /// \returns DieInfo descriptor.
343 return reinterpret_cast<std::atomic<uint64_t> *>(
344 &OutDieOffsetArray[getOrigUnit().getDIEIndex(InputDieEntry)])
345 ->load();
346 }
347
348 /// \p InputDieEntry debug info entry.
349 /// \returns type entry.
351 return reinterpret_cast<std::atomic<TypeEntry *> *>(
352 &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
353 ->load();
354 }
355
356 /// \p Idx index of the DIE.
357 /// \returns DieInfo descriptor.
359 reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx])
360 ->store(Offset);
361 }
362
363 /// \p Idx index of the DIE.
364 /// \p Type entry.
366 reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
367 ->store(Entry);
368 }
369
370 /// \p InputDieEntry debug info entry.
371 /// \p Type entry.
372 void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry,
373 TypeEntry *Entry) {
374 reinterpret_cast<std::atomic<TypeEntry *> *>(
375 &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
376 ->store(Entry);
377 }
378
379 /// @}
380
381 /// Returns value of DW_AT_low_pc attribute.
382 std::optional<uint64_t> getLowPc() const { return LowPc; }
383
384 /// Returns value of DW_AT_high_pc attribute.
385 uint64_t getHighPc() const { return HighPc; }
386
387 /// Returns true if there is a label corresponding to the specified \p Addr.
388 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
389
390 /// Add the low_pc of a label that is relocated by applying
391 /// offset \p PCOffset.
392 void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
393
394 /// Resolve the DIE attribute reference that has been extracted in \p
395 /// RefValue. The resulting DIE might be in another CompileUnit.
396 /// \returns referenced die and corresponding compilation unit.
397 /// compilation unit is null if reference could not be resolved.
398 std::optional<UnitEntryPairTy>
399 resolveDIEReference(const DWARFFormValue &RefValue,
400 ResolveInterCUReferencesMode CanResolveInterCUReferences);
401
402 std::optional<UnitEntryPairTy>
404 dwarf::Attribute Attr,
405 ResolveInterCUReferencesMode CanResolveInterCUReferences);
406
407 /// @}
408
409 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
410 /// offset \p PCOffset.
411 void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
412
413 /// Returns function ranges of this unit.
414 const RangesTy &getFunctionRanges() const { return Ranges; }
415
416 /// Record that a DW_AT_LLVM_stmt_sequence attribute on this unit
417 /// references the input line-table sequence whose header sits at
418 /// \p InputStmtSeqOffset. Resolution of that offset to an input
419 /// first-row index (via parser results plus a manual boundary-based
420 /// fallback) happens in a post-cloning pass, before \p V is rewritten
421 /// to the byte offset of the matching output sequence. Keying on row
422 /// index rather than address avoids collisions when two input
423 /// sequences would relocate to the same output address (e.g. ICF).
424 void noteStmtSeqListAttribute(DIEValue *V, uint64_t InputStmtSeqOffset) {
425 StmtSeqListAttributes.push_back({V, InputStmtSeqOffset});
426 }
427
428 /// Clone and emit this compilation unit.
429 Error
430 cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,
431 TypeUnit *ArtificialTypeUnit);
432
433 /// Clone and emit debug locations(.debug_loc/.debug_loclists).
435
436 /// Clone and emit ranges.
438
439 /// Clone and emit debug macros(.debug_macinfo/.debug_macro).
441
442 // Clone input DIE entry. \p SiblingOrdinal is this DIE's position in its
443 // parent's child list, or UINT32_MAX for the unit DIE.
444 std::pair<DIE *, TypeEntry *>
445 cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
446 TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
447 std::optional<int64_t> FuncAddressAdjustment,
448 std::optional<int64_t> VarAddressAdjustment,
449 BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit,
450 uint32_t SiblingOrdinal = std::numeric_limits<uint32_t>::max());
451
452 // Clone and emit line table.
453 Error cloneAndEmitLineTable(const Triple &TargetTriple);
454
455 /// Clone attribute location axpression.
456 void cloneDieAttrExpression(const DWARFExpression &InputExpression,
457 SmallVectorImpl<uint8_t> &OutputExpression,
458 SectionDescriptor &Section,
459 std::optional<int64_t> VarAddressAdjustment,
460 OffsetsPtrVector &PatchesOffsets);
461
462 /// Returns index(inside .debug_addr) of an address.
464 return DebugAddrIndexMap.getValueIndex(Addr);
465 }
466
467 /// Returns directory and file from the line table by index.
468 std::optional<std::pair<StringRef, StringRef>>
470
471 /// Returns directory and file from the line table by index.
472 std::optional<std::pair<StringRef, StringRef>>
474
475 /// \defgroup Helper methods to access OrigUnit.
476 ///
477 /// @{
478
479 /// Returns paired compile unit from input DWARF.
481 assert(OrigUnit != nullptr);
482 return *OrigUnit;
483 }
484
485 const DWARFDebugInfoEntry *
487 assert(OrigUnit != nullptr);
488 return OrigUnit->getFirstChildEntry(Die);
489 }
490
491 const DWARFDebugInfoEntry *
493 assert(OrigUnit != nullptr);
494 return OrigUnit->getSiblingEntry(Die);
495 }
496
498 assert(OrigUnit != nullptr);
499 return OrigUnit->getParent(Die);
500 }
501
502 DWARFDie getDIEAtIndex(unsigned Index) {
503 assert(OrigUnit != nullptr);
504 return OrigUnit->getDIEAtIndex(Index);
505 }
506
507 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
508 assert(OrigUnit != nullptr);
509 return OrigUnit->getDebugInfoEntry(Index);
510 }
511
512 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
513 assert(OrigUnit != nullptr);
514 return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
515 }
516
518 assert(OrigUnit != nullptr);
519 return DWARFDie(OrigUnit, Die);
520 }
521
523 assert(OrigUnit != nullptr);
524 return OrigUnit->getDIEIndex(Die);
525 }
526
527 uint32_t getDIEIndex(const DWARFDie &Die) const {
528 assert(OrigUnit != nullptr);
529 return OrigUnit->getDIEIndex(Die);
530 }
531
532 std::optional<DWARFFormValue> find(uint32_t DieIdx,
533 ArrayRef<dwarf::Attribute> Attrs) const {
534 assert(OrigUnit != nullptr);
535 return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs);
536 }
537
538 std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
539 ArrayRef<dwarf::Attribute> Attrs) const {
540 if (!Die)
541 return std::nullopt;
542 auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
543 if (AbbrevDecl) {
544 for (auto Attr : Attrs) {
545 if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr,
546 *OrigUnit))
547 return Value;
548 }
549 }
550 return std::nullopt;
551 }
552
553 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
554 return OrigUnit->getDIEIndexForOffset(Offset);
555 }
556
557 /// @}
558
559 /// \defgroup Methods used for reporting warnings and errors:
560 ///
561 /// @{
562
563 void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
565 }
566
567 void warn(Error Warning, const DWARFDie *DIE = nullptr) {
568 handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
569 GlobalData.warn(Info.message(), getUnitName(), DIE);
570 });
571 }
572
573 void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
574 if (DieEntry != nullptr) {
575 DWARFDie DIE(&getOrigUnit(), DieEntry);
577 return;
578 }
579
581 }
582
583 void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
584 GlobalData.warn(Err, getUnitName(), DIE);
585 }
586
587 void error(Error Err, const DWARFDie *DIE = nullptr) {
588 handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
589 GlobalData.error(Info.message(), getUnitName(), DIE);
590 });
591 }
592
593 /// @}
594
595 /// Save specified accelerator info \p Info.
597 AcceleratorRecords.add(Info);
598 }
599
600 /// Enumerates all units accelerator records.
601 void
603 AcceleratorRecords.forEach(Handler);
604 }
605
606 /// Output unit selector.
608 public:
611
612 /// Accessor for common functionality.
614
615 bool isCompileUnit();
616
617 bool isTypeUnit();
618
619 /// Returns CompileUnit if applicable.
621
622 /// Returns TypeUnit if applicable.
624
625 protected:
627 };
628
629private:
630 /// Navigate DWARF tree recursively and set die properties.
631 void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
632 bool IsODRUnavailableFunctionScope);
633
634 struct LinkedLocationExpressionsWithOffsetPatches {
636 OffsetsPtrVector Patches;
637 };
638 using LinkedLocationExpressionsVector =
640
641 /// Emit debug locations.
642 void emitLocations(DebugSectionKind LocationSectionKind);
643
644 /// Emit location list header.
645 uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
646
647 /// Emit location list fragment.
648 uint64_t emitLocListFragment(
649 const LinkedLocationExpressionsVector &LinkedLocationExpression,
650 SectionDescriptor &OutLocationSection);
651
652 /// Emit the .debug_addr section fragment for current unit.
653 Error emitDebugAddrSection();
654
655 /// Emit .debug_aranges.
656 void emitAranges(AddressRanges &LinkedFunctionRanges);
657
658 /// Clone and emit .debug_ranges/.debug_rnglists.
659 void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
660 AddressRanges &LinkedFunctionRanges);
661
662 /// Emit range list header.
663 uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
664
665 /// Emit range list fragment.
666 void emitRangeListFragment(const AddressRanges &LinkedRanges,
667 SectionDescriptor &OutRangeSection);
668
669 /// Insert the new line info sequence \p Seq into the current
670 /// set of already linked line info \p Rows. \p SeqIndices carries the
671 /// input Row index that each entry in \p Seq originated from (or the
672 /// invalid-row-index sentinel for manufactured end-of-range rows), and
673 /// is kept in lockstep with \p RowIndices.
674 void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
675 SmallVectorImpl<uint64_t> &SeqIndices,
676 std::vector<DWARFDebugLine::Row> &Rows,
677 SmallVectorImpl<uint64_t> &RowIndices);
678
679 /// Filter \p InputLineTable's rows to those covered by this unit's
680 /// function ranges, relocating addresses in the process, and store the
681 /// result in \p NewRows. \p NewRowIndices is populated in lockstep with
682 /// \p NewRows and carries, for each output row, the index of the input
683 /// row it originated from — or InvalidRowIndex for manufactured
684 /// end-of-range rows.
685 void filterLineTableRows(const DWARFDebugLine::LineTable &InputLineTable,
686 std::vector<DWARFDebugLine::Row> &NewRows,
687 SmallVectorImpl<uint64_t> &NewRowIndices);
688
689 /// Rewrite every DW_AT_LLVM_stmt_sequence DIEValue recorded on this
690 /// unit with the local .debug_line offset of the output sequence
691 /// containing the corresponding input first row.
692 /// \p SeqOffsetToFirstRowIndex maps an input stmt-sequence offset to
693 /// its first-row index (built by buildStmtSeqOffsetToFirstRowIndex so
694 /// that sequences missed by the DWARF parser are recovered from row
695 /// boundaries). \p RowIndexToSeqStartOffset maps an input first-row
696 /// index to the byte offset of the output DW_LNE_set_address that
697 /// opens the matching output sequence.
698 void patchStmtSeqAttributes(
699 const DenseMap<uint64_t, uint64_t> &SeqOffsetToFirstRowIndex,
700 const DenseMap<uint64_t, uint64_t> &RowIndexToSeqStartOffset);
701
702 /// Build a map from input stmt-sequence offset to the first-row index
703 /// of the corresponding sequence in \p InputLineTable. Seeds the map
704 /// from \p InputLineTable.Sequences (the DWARF parser's results), then
705 /// augments it by manually walking row boundaries and realigning them
706 /// against the recorded DW_AT_LLVM_stmt_sequence values so that
707 /// sequences missed by the parser still resolve. Mirrors the
708 /// classic DWARFLinker's constructSeqOffsettoOrigRowMapping.
710 const DWARFDebugLine::LineTable &InputLineTable) const;
711
712 /// Emits body for both macro sections.
713 void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
714 uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
715
716 /// Creates DIE which would be placed into the "Plain" compile unit.
717 DIE *createPlainDIEandCloneAttributes(
718 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
719 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
720 std::optional<int64_t> &VarAddressAdjustment);
721
722 /// Creates DIE which would be placed into the "Type" compile unit.
723 /// \p SiblingOrdinal is the input DIE's position in its parent's child list.
724 TypeEntry *createTypeDIEandCloneAttributes(
725 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
726 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit,
727 uint32_t SiblingOrdinal);
728
729 /// Create output DIE inside specified \p TypeDescriptor.
730 DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
731 DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
732 bool IsDeclaration, bool IsParentDeclaration);
733
734 /// Enumerate \p DieEntry children and assign names for them.
735 Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
736 SyntheticTypeNameBuilder &NameBuilder);
737
738 /// DWARFFile containing this compile unit.
739 DWARFFile &File;
740
741 /// Pointer to the paired compile unit from the input DWARF.
742 DWARFUnit *OrigUnit = nullptr;
743
744 /// Raw DW_AT_language from the input (not ODR-filtered).
745 std::optional<uint16_t> Language;
746
747 /// Parseable Swift interface entries staged during the parallel analysis
748 /// phase. Merged serially afterwards.
749 struct PendingSwiftInterface {
750 PendingSwiftInterface(StringRef ModuleName, StringRef ResolvedPath)
751 : ModuleName(ModuleName), ResolvedPath(ResolvedPath) {}
752 std::string ModuleName;
753 std::string ResolvedPath;
754 };
755 SmallVector<PendingSwiftInterface> PendingSwiftInterfaces;
756
757 /// Line table for this unit.
758 const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
759
760 /// Cached resolved paths from the line table.
761 /// The key is <UniqueUnitID, FileIdx>.
762 using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
763 ResolvedPathsMap ResolvedFullPaths;
764 StringMap<StringEntry *> ResolvedParentPaths;
765
766 /// Maps an address into the index inside .debug_addr section.
767 IndexedValuesMap<uint64_t> DebugAddrIndexMap;
768
769 std::unique_ptr<DependencyTracker> Dependencies;
770
771 /// \defgroup Data Members accessed asynchronously.
772 ///
773 /// @{
774 OffsetToUnitTy getUnitFromOffset;
775
776 std::optional<uint64_t> LowPc;
777 uint64_t HighPc = 0;
778
779 /// Flag indicating whether type de-duplication is forbidden.
780 bool NoODR = true;
781
782 /// Deterministic priority for type DIE allocation (lower wins).
783 uint64_t Priority = std::numeric_limits<uint64_t>::max();
784
785 /// The ranges in that map are the PC ranges for functions in this unit,
786 /// associated with the PC offset to apply to the addresses to get
787 /// the linked address.
788 RangesTy Ranges;
789 std::mutex RangesMutex;
790
791 /// The DW_AT_low_pc of each DW_TAG_label.
792 using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
793 LabelMapTy Labels;
794
795 /// Recorded DW_AT_LLVM_stmt_sequence attributes for this unit. Each
796 /// entry pairs the DIEValue holding the attribute with the input-side
797 /// byte offset of the referenced line-table sequence. The value is
798 /// rewritten with the matching output offset after the line table has
799 /// been emitted; resolution from input offset to input first-row
800 /// index (including the parser-miss fallback) happens at patch time.
801 struct StmtSeqPatch {
802 DIEValue *Value = nullptr;
803 uint64_t InputStmtSeqOffset = 0;
804 };
805 SmallVector<StmtSeqPatch, 4> StmtSeqListAttributes;
806 std::mutex LabelsMutex;
807
808 /// This field keeps current stage of overall compile unit processing.
809 std::atomic<Stage> Stage;
810
811 /// DIE info indexed by DIE index.
812 SmallVector<DIEInfo> DieInfoArray;
813 SmallVector<uint64_t> OutDieOffsetArray;
814 SmallVector<TypeEntry *> TypeEntries;
815
816 /// The list of accelerator records for this unit.
817 ArrayList<AccelInfo> AcceleratorRecords;
818 /// @}
819};
820
821/// \returns list of attributes referencing type DIEs which might be
822/// deduplicated.
823/// Note: it does not include DW_AT_containing_type attribute to avoid
824/// infinite recursion.
826
827} // end of namespace parallel
828} // end of namespace dwarf_linker
829} // end of namespace llvm
830
831#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:661
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:828
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:133
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:47
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)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
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.
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:557
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:383
endianness
Definition bit.h:71
@ Keep
No function return thunk.
Definition CodeGen.h:162
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:1114
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 unsetPlacement()
Unsets Placement kind for the corresponding die.
bool setPlacementIfUnset(DieOutputPlacement Placement)
Sets Placement kind for the corresponding die.
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)