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.
443 std::pair<DIE *, TypeEntry *>
444 cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
445 TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
446 std::optional<int64_t> FuncAddressAdjustment,
447 std::optional<int64_t> VarAddressAdjustment,
448 BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
449
450 // Clone and emit line table.
451 Error cloneAndEmitLineTable(const Triple &TargetTriple);
452
453 /// Clone attribute location axpression.
454 void cloneDieAttrExpression(const DWARFExpression &InputExpression,
455 SmallVectorImpl<uint8_t> &OutputExpression,
456 SectionDescriptor &Section,
457 std::optional<int64_t> VarAddressAdjustment,
458 OffsetsPtrVector &PatchesOffsets);
459
460 /// Returns index(inside .debug_addr) of an address.
462 return DebugAddrIndexMap.getValueIndex(Addr);
463 }
464
465 /// Returns directory and file from the line table by index.
466 std::optional<std::pair<StringRef, StringRef>>
468
469 /// Returns directory and file from the line table by index.
470 std::optional<std::pair<StringRef, StringRef>>
472
473 /// \defgroup Helper methods to access OrigUnit.
474 ///
475 /// @{
476
477 /// Returns paired compile unit from input DWARF.
479 assert(OrigUnit != nullptr);
480 return *OrigUnit;
481 }
482
483 const DWARFDebugInfoEntry *
485 assert(OrigUnit != nullptr);
486 return OrigUnit->getFirstChildEntry(Die);
487 }
488
489 const DWARFDebugInfoEntry *
491 assert(OrigUnit != nullptr);
492 return OrigUnit->getSiblingEntry(Die);
493 }
494
496 assert(OrigUnit != nullptr);
497 return OrigUnit->getParent(Die);
498 }
499
500 DWARFDie getDIEAtIndex(unsigned Index) {
501 assert(OrigUnit != nullptr);
502 return OrigUnit->getDIEAtIndex(Index);
503 }
504
505 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
506 assert(OrigUnit != nullptr);
507 return OrigUnit->getDebugInfoEntry(Index);
508 }
509
510 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
511 assert(OrigUnit != nullptr);
512 return OrigUnit->getUnitDIE(ExtractUnitDIEOnly);
513 }
514
516 assert(OrigUnit != nullptr);
517 return DWARFDie(OrigUnit, Die);
518 }
519
521 assert(OrigUnit != nullptr);
522 return OrigUnit->getDIEIndex(Die);
523 }
524
525 uint32_t getDIEIndex(const DWARFDie &Die) const {
526 assert(OrigUnit != nullptr);
527 return OrigUnit->getDIEIndex(Die);
528 }
529
530 std::optional<DWARFFormValue> find(uint32_t DieIdx,
531 ArrayRef<dwarf::Attribute> Attrs) const {
532 assert(OrigUnit != nullptr);
533 return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs);
534 }
535
536 std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die,
537 ArrayRef<dwarf::Attribute> Attrs) const {
538 if (!Die)
539 return std::nullopt;
540 auto AbbrevDecl = Die->getAbbreviationDeclarationPtr();
541 if (AbbrevDecl) {
542 for (auto Attr : Attrs) {
543 if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr,
544 *OrigUnit))
545 return Value;
546 }
547 }
548 return std::nullopt;
549 }
550
551 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
552 return OrigUnit->getDIEIndexForOffset(Offset);
553 }
554
555 /// @}
556
557 /// \defgroup Methods used for reporting warnings and errors:
558 ///
559 /// @{
560
561 void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) {
563 }
564
565 void warn(Error Warning, const DWARFDie *DIE = nullptr) {
566 handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
567 GlobalData.warn(Info.message(), getUnitName(), DIE);
568 });
569 }
570
571 void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) {
572 if (DieEntry != nullptr) {
573 DWARFDie DIE(&getOrigUnit(), DieEntry);
575 return;
576 }
577
579 }
580
581 void error(const Twine &Err, const DWARFDie *DIE = nullptr) {
582 GlobalData.warn(Err, getUnitName(), DIE);
583 }
584
585 void error(Error Err, const DWARFDie *DIE = nullptr) {
586 handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
587 GlobalData.error(Info.message(), getUnitName(), DIE);
588 });
589 }
590
591 /// @}
592
593 /// Save specified accelerator info \p Info.
595 AcceleratorRecords.add(Info);
596 }
597
598 /// Enumerates all units accelerator records.
599 void
601 AcceleratorRecords.forEach(Handler);
602 }
603
604 /// Output unit selector.
606 public:
609
610 /// Accessor for common functionality.
612
613 bool isCompileUnit();
614
615 bool isTypeUnit();
616
617 /// Returns CompileUnit if applicable.
619
620 /// Returns TypeUnit if applicable.
622
623 protected:
625 };
626
627private:
628 /// Navigate DWARF tree recursively and set die properties.
629 void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
630 bool IsODRUnavailableFunctionScope);
631
632 struct LinkedLocationExpressionsWithOffsetPatches {
634 OffsetsPtrVector Patches;
635 };
636 using LinkedLocationExpressionsVector =
638
639 /// Emit debug locations.
640 void emitLocations(DebugSectionKind LocationSectionKind);
641
642 /// Emit location list header.
643 uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection);
644
645 /// Emit location list fragment.
646 uint64_t emitLocListFragment(
647 const LinkedLocationExpressionsVector &LinkedLocationExpression,
648 SectionDescriptor &OutLocationSection);
649
650 /// Emit the .debug_addr section fragment for current unit.
651 Error emitDebugAddrSection();
652
653 /// Emit .debug_aranges.
654 void emitAranges(AddressRanges &LinkedFunctionRanges);
655
656 /// Clone and emit .debug_ranges/.debug_rnglists.
657 void cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
658 AddressRanges &LinkedFunctionRanges);
659
660 /// Emit range list header.
661 uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection);
662
663 /// Emit range list fragment.
664 void emitRangeListFragment(const AddressRanges &LinkedRanges,
665 SectionDescriptor &OutRangeSection);
666
667 /// Insert the new line info sequence \p Seq into the current
668 /// set of already linked line info \p Rows. \p SeqIndices carries the
669 /// input Row index that each entry in \p Seq originated from (or the
670 /// invalid-row-index sentinel for manufactured end-of-range rows), and
671 /// is kept in lockstep with \p RowIndices.
672 void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
673 SmallVectorImpl<uint64_t> &SeqIndices,
674 std::vector<DWARFDebugLine::Row> &Rows,
675 SmallVectorImpl<uint64_t> &RowIndices);
676
677 /// Filter \p InputLineTable's rows to those covered by this unit's
678 /// function ranges, relocating addresses in the process, and store the
679 /// result in \p NewRows. \p NewRowIndices is populated in lockstep with
680 /// \p NewRows and carries, for each output row, the index of the input
681 /// row it originated from — or InvalidRowIndex for manufactured
682 /// end-of-range rows.
683 void filterLineTableRows(const DWARFDebugLine::LineTable &InputLineTable,
684 std::vector<DWARFDebugLine::Row> &NewRows,
685 SmallVectorImpl<uint64_t> &NewRowIndices);
686
687 /// Rewrite every DW_AT_LLVM_stmt_sequence DIEValue recorded on this
688 /// unit with the local .debug_line offset of the output sequence
689 /// containing the corresponding input first row.
690 /// \p SeqOffsetToFirstRowIndex maps an input stmt-sequence offset to
691 /// its first-row index (built by buildStmtSeqOffsetToFirstRowIndex so
692 /// that sequences missed by the DWARF parser are recovered from row
693 /// boundaries). \p RowIndexToSeqStartOffset maps an input first-row
694 /// index to the byte offset of the output DW_LNE_set_address that
695 /// opens the matching output sequence.
696 void patchStmtSeqAttributes(
697 const DenseMap<uint64_t, uint64_t> &SeqOffsetToFirstRowIndex,
698 const DenseMap<uint64_t, uint64_t> &RowIndexToSeqStartOffset);
699
700 /// Build a map from input stmt-sequence offset to the first-row index
701 /// of the corresponding sequence in \p InputLineTable. Seeds the map
702 /// from \p InputLineTable.Sequences (the DWARF parser's results), then
703 /// augments it by manually walking row boundaries and realigning them
704 /// against the recorded DW_AT_LLVM_stmt_sequence values so that
705 /// sequences missed by the parser still resolve. Mirrors the
706 /// classic DWARFLinker's constructSeqOffsettoOrigRowMapping.
708 const DWARFDebugLine::LineTable &InputLineTable) const;
709
710 /// Emits body for both macro sections.
711 void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
712 uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
713
714 /// Creates DIE which would be placed into the "Plain" compile unit.
715 DIE *createPlainDIEandCloneAttributes(
716 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
717 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
718 std::optional<int64_t> &VarAddressAdjustment);
719
720 /// Creates DIE which would be placed into the "Type" compile unit.
721 TypeEntry *createTypeDIEandCloneAttributes(
722 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
723 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit);
724
725 /// Create output DIE inside specified \p TypeDescriptor.
726 DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
727 DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
728 bool IsDeclaration, bool IsParentDeclaration);
729
730 /// Enumerate \p DieEntry children and assign names for them.
731 Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
732 SyntheticTypeNameBuilder &NameBuilder);
733
734 /// DWARFFile containing this compile unit.
735 DWARFFile &File;
736
737 /// Pointer to the paired compile unit from the input DWARF.
738 DWARFUnit *OrigUnit = nullptr;
739
740 /// Raw DW_AT_language from the input (not ODR-filtered).
741 std::optional<uint16_t> Language;
742
743 /// Parseable Swift interface entries staged during the parallel analysis
744 /// phase. Merged serially afterwards.
745 struct PendingSwiftInterface {
746 PendingSwiftInterface(StringRef ModuleName, StringRef ResolvedPath)
747 : ModuleName(ModuleName), ResolvedPath(ResolvedPath) {}
748 std::string ModuleName;
749 std::string ResolvedPath;
750 };
751 SmallVector<PendingSwiftInterface> PendingSwiftInterfaces;
752
753 /// Line table for this unit.
754 const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
755
756 /// Cached resolved paths from the line table.
757 /// The key is <UniqueUnitID, FileIdx>.
758 using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>;
759 ResolvedPathsMap ResolvedFullPaths;
760 StringMap<StringEntry *> ResolvedParentPaths;
761
762 /// Maps an address into the index inside .debug_addr section.
763 IndexedValuesMap<uint64_t> DebugAddrIndexMap;
764
765 std::unique_ptr<DependencyTracker> Dependencies;
766
767 /// \defgroup Data Members accessed asynchronously.
768 ///
769 /// @{
770 OffsetToUnitTy getUnitFromOffset;
771
772 std::optional<uint64_t> LowPc;
773 uint64_t HighPc = 0;
774
775 /// Flag indicating whether type de-duplication is forbidden.
776 bool NoODR = true;
777
778 /// Deterministic priority for type DIE allocation (lower wins).
779 uint64_t Priority = std::numeric_limits<uint64_t>::max();
780
781 /// The ranges in that map are the PC ranges for functions in this unit,
782 /// associated with the PC offset to apply to the addresses to get
783 /// the linked address.
784 RangesTy Ranges;
785 std::mutex RangesMutex;
786
787 /// The DW_AT_low_pc of each DW_TAG_label.
788 using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
789 LabelMapTy Labels;
790
791 /// Recorded DW_AT_LLVM_stmt_sequence attributes for this unit. Each
792 /// entry pairs the DIEValue holding the attribute with the input-side
793 /// byte offset of the referenced line-table sequence. The value is
794 /// rewritten with the matching output offset after the line table has
795 /// been emitted; resolution from input offset to input first-row
796 /// index (including the parser-miss fallback) happens at patch time.
797 struct StmtSeqPatch {
798 DIEValue *Value = nullptr;
799 uint64_t InputStmtSeqOffset = 0;
800 };
801 SmallVector<StmtSeqPatch, 4> StmtSeqListAttributes;
802 std::mutex LabelsMutex;
803
804 /// This field keeps current stage of overall compile unit processing.
805 std::atomic<Stage> Stage;
806
807 /// DIE info indexed by DIE index.
808 SmallVector<DIEInfo> DieInfoArray;
809 SmallVector<uint64_t> OutDieOffsetArray;
810 SmallVector<TypeEntry *> TypeEntries;
811
812 /// The list of accelerator records for this unit.
813 ArrayList<AccelInfo> AcceleratorRecords;
814 /// @}
815};
816
817/// \returns list of attributes referencing type DIEs which might be
818/// deduplicated.
819/// Note: it does not include DW_AT_containing_type attribute to avoid
820/// infinite recursion.
822
823} // end of namespace parallel
824} // end of namespace dwarf_linker
825} // end of namespace llvm
826
827#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)
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:123
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)