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