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