LLVM 24.0.0git
DependencyTracker.cpp
Go to the documentation of this file.
1//=== DependencyTracker.cpp -----------------------------------------------===//
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#include "DependencyTracker.h"
12
13using namespace llvm;
14using namespace dwarf_linker;
15using namespace dwarf_linker::parallel;
16
17/// A broken link in the keep chain. By recording both the parent and the child
18/// we can show only broken links for DIEs with multiple children.
26
27/// Verify the keep chain by looking for DIEs that are kept but who's parent
28/// isn't.
30#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
31 SmallVector<DWARFDie> Worklist;
32 Worklist.push_back(CU.getOrigUnit().getUnitDIE());
33
34 // List of broken links.
35 SmallVector<BrokenLink> BrokenLinks;
36
37 while (!Worklist.empty()) {
38 const DWARFDie Current = Worklist.back();
39 Worklist.pop_back();
40
41 if (!Current.isValid())
42 continue;
43
44 CompileUnit::DIEInfo &CurrentInfo =
45 CU.getDIEInfo(Current.getDebugInfoEntry());
46 const bool ParentPlainDieIsKept = CurrentInfo.needToKeepInPlainDwarf();
47 const bool ParentTypeDieIsKept = CurrentInfo.needToPlaceInTypeTable();
48
49 for (DWARFDie Child : reverse(Current.children())) {
50 Worklist.push_back(Child);
51
52 CompileUnit::DIEInfo &ChildInfo =
53 CU.getDIEInfo(Child.getDebugInfoEntry());
54 const bool ChildPlainDieIsKept = ChildInfo.needToKeepInPlainDwarf();
55 const bool ChildTypeDieIsKept = ChildInfo.needToPlaceInTypeTable();
56
57 if (!ParentPlainDieIsKept && ChildPlainDieIsKept)
58 BrokenLinks.emplace_back(Current, Child,
59 "Found invalid link in keep chain");
60
61 if (Child.getTag() == dwarf::DW_TAG_subprogram) {
62 if (!ChildInfo.getKeep() && isLiveSubprogramEntry(UnitEntryPairTy(
63 &CU, Child.getDebugInfoEntry()))) {
64 BrokenLinks.emplace_back(Current, Child,
65 "Live subprogram is not marked as kept");
66 }
67 }
68
69 if (!ChildInfo.getODRAvailable()) {
70 assert(!ChildTypeDieIsKept);
71 continue;
72 }
73
74 if (!ParentTypeDieIsKept && ChildTypeDieIsKept)
75 BrokenLinks.emplace_back(Current, Child,
76 "Found invalid link in keep chain");
77
78 if (CurrentInfo.getIsInAnonNamespaceScope() &&
79 ChildInfo.needToPlaceInTypeTable()) {
80 BrokenLinks.emplace_back(Current, Child,
81 "Found invalid placement marking for member "
82 "of anonymous namespace");
83 }
84 }
85 }
86
87 if (!BrokenLinks.empty()) {
88 for (BrokenLink Link : BrokenLinks) {
89 errs() << "\n=================================\n";
90 WithColor::error() << formatv("{0} between {1:x} and {2:x}", Link.Message,
91 Link.Parent.getOffset(),
92 Link.Child.getOffset());
93
94 errs() << "\nParent:";
95 Link.Parent.dump(errs(), 0, {});
96 errs() << "\n";
97 CU.getDIEInfo(Link.Parent).dump();
98
99 errs() << "\nChild:";
100 Link.Child.dump(errs(), 2, {});
101 errs() << "\n";
102 CU.getDIEInfo(Link.Child).dump();
103 }
104 report_fatal_error("invalid keep chain");
105 }
106#endif
107}
108
109static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry) {
110 switch (Entry->getTag()) {
111 case dwarf::DW_TAG_compile_unit:
112 case dwarf::DW_TAG_module:
113 case dwarf::DW_TAG_namespace:
114 return true;
115
116 default:
117 return false;
118 }
119}
120
122 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
123 RootEntriesWorkList.clear();
124
125 // The recorded subtrees are walked after marking, and need to resolve
126 // references the same way marking did. A unit whose references could not all
127 // be resolved is reset to its loaded stage and marked again from scratch, so
128 // no reference recorded under one resolution mode survives into another.
129 assert((SubtreeDependencyRefs.empty() ||
130 InterCUProcessingWasStarted == InterCUProcessingStarted) &&
131 "recorded subtrees would be walked in a different resolution mode");
132 InterCUProcessingWasStarted = InterCUProcessingStarted;
133
134 // Search for live root DIEs.
135 CompileUnit::DIEInfo &CUInfo = CU.getDIEInfo(CU.getDebugInfoEntry(0));
137 collectRootsToKeep(UnitEntryPairTy{&CU, CU.getDebugInfoEntry(0)},
138 std::nullopt, false);
139
140 // Mark live DIEs as kept.
141 return markCollectedLiveRootsAsKept(InterCUProcessingStarted,
142 HasNewInterconnectedCUs);
143}
144
146 LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry,
147 std::optional<UnitEntryPairTy> ReferencedBy,
148 const DWARFDebugInfoEntry *ReferencedTypeDieEntry) {
149 if (ReferencedBy) {
150 RootEntriesWorkList.emplace_back(Action, Entry, *ReferencedBy,
151 ReferencedTypeDieEntry);
152 return;
153 }
154
155 RootEntriesWorkList.emplace_back(Action, Entry);
156}
157
159 const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
160 bool IsLiveParent) {
161 for (const DWARFDebugInfoEntry *CurChild =
162 Entry.CU->getFirstChildEntry(Entry.DieEntry);
163 CurChild && CurChild->getAbbreviationDeclarationPtr();
164 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
165 UnitEntryPairTy ChildEntry(Entry.CU, CurChild);
166 CompileUnit::DIEInfo &ChildInfo = Entry.CU->getDIEInfo(CurChild);
167
168 bool IsLiveChild = false;
169
170 switch (CurChild->getTag()) {
171 case dwarf::DW_TAG_label: {
172 IsLiveChild = isLiveSubprogramEntry(ChildEntry);
173
174 // Keep label referencing live address.
175 // Keep label which is child of live parent entry.
176 if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
179 ReferencedBy);
180 }
181 } break;
182 case dwarf::DW_TAG_subprogram: {
183 IsLiveChild = isLiveSubprogramEntry(ChildEntry);
184
185 // Keep subprogram referencing live address.
186 if (IsLiveChild) {
187 // If subprogram is in module scope and this module allows ODR
188 // deduplication set "TypeTable" placement, otherwise set "" placement
190 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
193
194 addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
195 }
196 } break;
197 case dwarf::DW_TAG_constant:
198 case dwarf::DW_TAG_variable: {
199 IsLiveChild = isLiveVariableEntry(ChildEntry, IsLiveParent);
200
201 // Keep variable referencing live address.
202 if (IsLiveChild) {
203 // If variable is in module scope and this module allows ODR
204 // deduplication set "TypeTable" placement, otherwise set "" placement
205
207 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
210
211 addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
212 }
213 } break;
214 case dwarf::DW_TAG_base_type: {
215 // Always keep base types.
218 ReferencedBy);
219 } break;
220 case dwarf::DW_TAG_imported_module:
221 case dwarf::DW_TAG_imported_declaration:
222 case dwarf::DW_TAG_imported_unit: {
223 // Always keep DIEs having DW_AT_import attribute.
224 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
227 ReferencedBy);
228 break;
229 }
230
233 ReferencedBy);
234 } break;
235 case dwarf::DW_TAG_type_unit:
236 case dwarf::DW_TAG_partial_unit:
237 case dwarf::DW_TAG_compile_unit: {
238 llvm_unreachable("Called for incorrect DIE");
239 } break;
240 default:
241 // A module compile unit has no relocations, so liveness analysis never
242 // reaches a type definition that nothing else in the unit references. The
243 // module owns the only copy of those definitions, so keep them.
244 if (Entry.CU->isClangModule() && isNamespaceLikeEntry(Entry.DieEntry) &&
245 dwarf::isType(CurChild->getTag())) {
248 ReferencedBy);
249 break;
250 }
251
252 // An importing unit emits a skeleton of the module it imports, so a
253 // forward-declared type nested in a DW_TAG_module there is the module's
254 // record that the name exists, even when no full definition has been
255 // emitted. Route it through the type pool: when another CU emits a
256 // real definition for the same synthetic name, the existing
257 // decl-vs-def race resolution in allocateTypeDie + getFinalDie keeps
258 // the definition and drops this declaration at emission time. For
259 // non-ODR languages getFinalPlacementForEntry forces PlainDwarf,
260 // so the forward decl is kept in place under its module.
261 if (!Entry.CU->isClangModule() &&
262 Entry.DieEntry->getTag() == dwarf::DW_TAG_module &&
263 dwarf::isType(CurChild->getTag()) &&
264 dwarf::toUnsigned(Entry.CU->find(CurChild, dwarf::DW_AT_declaration),
265 0)) {
268 ReferencedBy);
269 }
270 break;
271 }
272
273 collectRootsToKeep(ChildEntry, ReferencedBy, IsLiveChild || IsLiveParent);
274 }
275}
276
278 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
279 bool Res = true;
280
281 // Mark roots as kept.
282 while (!RootEntriesWorkList.empty()) {
283 LiveRootWorklistItemTy Root = RootEntriesWorkList.pop_back_val();
284
286 Root.getRootEntry(), InterCUProcessingStarted,
287 HasNewInterconnectedCUs)) {
288 if (Root.hasReferencedByOtherEntry())
289 Dependencies.push_back(Root);
290 } else
291 Res = false;
292 }
293
294 return Res;
295}
296
298 LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
299 const UnitEntryPairTy &Entry) {
300 SubtreeDependencyRefs.push_back({Entry, Action, RootEntry});
301}
302
304 // Walking a subtree appends the dependencies that belong to a subprogram
305 // nested inside it, so all walking has to finish before the dependency list
306 // is traversed.
307 for (size_t Idx = MaterializedRefs; Idx != SubtreeDependencyRefs.size();
308 ++Idx) {
309 // Copied rather than referenced so that the loop does not depend on the
310 // walk below leaving the vector alone.
312 SubtreeDependenciesKeyTy Key{Ref.Subtree.CU, Ref.Subtree.DieEntry,
313 Ref.Action};
314 if (SubtreeSummaries.contains(Key))
315 continue;
316
317 // Collected separately so that growing the map cannot invalidate the sink.
318 SubtreeDependenciesTy SubtreeDeps;
319 {
321 &SubtreeDeps);
322
323 // A walk that only records dependencies neither marks nor follows
324 // references, so it cannot discover a new interconnection and cannot
325 // fail.
326 std::atomic<bool> HasNewInterconnectedCUs = false;
327 [[maybe_unused]] bool Res = markDIEEntryAsKeptRec(
328 Ref.Action, Ref.ReferencedBy, Ref.Subtree,
329 InterCUProcessingWasStarted, HasNewInterconnectedCUs,
331 assert(Res && !HasNewInterconnectedCUs && "record-deps-only walk failed");
332 }
333
334 SubtreeSummaries[Key] = std::move(SubtreeDeps);
335 }
336
338}
339
341 const UnitEntryPairTy &Root,
342 const DWARFDebugInfoEntry *ReferencedTypeDieEntry,
343 const UnitEntryPairTy &ReferencedBy) {
344 // Completeness must be checked against the actual referenced DIE, not its
345 // enclosing root. A nested type can be demoted to plain DWARF while its
346 // root stays in the type table, and a type-table DIE may only reference
347 // DIEs that are themselves in the type table. Checking the root instead
348 // leaves such a DIE in the type table, later tripping the type-unit
349 // reference assertion in DIEAttributeCloner::cloneDieRefAttr.
350 const DWARFDebugInfoEntry *ReferencedDieEntry =
351 ReferencedTypeDieEntry ? ReferencedTypeDieEntry : Root.DieEntry;
352 CompileUnit::DIEInfo &RootInfo = Root.CU->getDIEInfo(ReferencedDieEntry);
353 CompileUnit::DIEInfo &ReferencedByInfo =
354 ReferencedBy.CU->getDIEInfo(ReferencedBy.DieEntry);
355
356 if (RootInfo.needToPlaceInTypeTable() ||
357 !ReferencedByInfo.needToPlaceInTypeTable())
358 return false;
359
360 setPlainDwarfPlacementRec(ReferencedBy);
361
362 // FIXME: we probably need to update getKeepTypeChildren status for
363 // parents of ReferencedBy.
364 return true;
365}
366
368 bool HasNewDependency = false;
370 CompileUnit::DIEInfo &ReferencedByInfo =
371 Ref.ReferencedBy.CU->getDIEInfo(Ref.ReferencedBy.DieEntry);
372 if (!ReferencedByInfo.needToPlaceInTypeTable())
373 continue;
374
375 SubtreeDependenciesKeyTy Key{Ref.Subtree.CU, Ref.Subtree.DieEntry,
376 Ref.Action};
377 auto Summary = SubtreeSummaries.find(Key);
378 assert(Summary != SubtreeSummaries.end() && "subtree was not summarized");
379
380 // Demotion takes the root out of the type table, so no further dependency
381 // of the same subtree can demote it again.
382 for (const SubtreeDependencyTy &Dep : Summary->second) {
384 Ref.ReferencedBy)) {
385 HasNewDependency = true;
386 break;
387 }
388 }
389 }
390
391 return HasNewDependency;
392}
393
396
397 bool HasNewDependency = false;
399 assert(Root.hasReferencedByOtherEntry() &&
400 "Root entry without dependency inside the dependencies list");
401
402 if (demoteIfIncomplete(Root.getRootEntry(),
403 Root.getReferencedTypeDieEntry(),
404 Root.getReferencedByEntry()))
405 HasNewDependency = true;
406 }
407
409 HasNewDependency = true;
410
411 return HasNewDependency;
412}
413
415 const UnitEntryPairTy &Entry) {
416 CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
417 if (Info.getPlacement() == CompileUnit::PlainDwarf &&
418 !Info.getKeepTypeChildren())
419 return;
420
422 Info.unsetKeepTypeChildren();
424
425 for (const DWARFDebugInfoEntry *CurChild =
426 Entry.CU->getFirstChildEntry(Entry.DieEntry);
427 CurChild && CurChild->getAbbreviationDeclarationPtr();
428 CurChild = Entry.CU->getSiblingEntry(CurChild))
429 setPlainDwarfPlacementRec(UnitEntryPairTy{Entry.CU, CurChild});
430}
431
433 CompileUnit::DieOutputPlacement NewPlacement) {
434 if (!Info.getKeep())
435 return false;
436
437 switch (NewPlacement) {
439 return Info.needToPlaceInTypeTable();
440
442 return Info.needToKeepInPlainDwarf();
443
445 return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
446
448 llvm_unreachable("Unset placement type is specified.");
449 };
450
451 llvm_unreachable("Unknown CompileUnit::DieOutputPlacement enum");
452}
453
455 CompileUnit::DieOutputPlacement NewPlacement) {
456 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
457}
458
460 const UnitEntryPairTy &Entry) {
461 if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
462 return;
463
464 CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
465 bool NeedKeepTypeChildren = Info.needToPlaceInTypeTable();
466 bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
467
468 bool AreTypeParentsDone = !NeedKeepTypeChildren;
469 bool ArePlainParentsDone = !NeedKeepPlainChildren;
470
471 // Mark parents as 'Keep*Children'.
472 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
473 while (ParentIdx) {
474 const DWARFDebugInfoEntry *ParentEntry =
475 Entry.CU->getDebugInfoEntry(*ParentIdx);
476 CompileUnit::DIEInfo &ParentInfo = Entry.CU->getDIEInfo(*ParentIdx);
477
478 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
479 if (ParentInfo.getKeepTypeChildren())
480 AreTypeParentsDone = true;
481 else {
482 bool AddToWorklist = !isAlreadyMarked(
484 ParentInfo.setKeepTypeChildren();
485 if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
488 UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
489 }
490 }
491 }
492
493 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
494 if (ParentInfo.getKeepPlainChildren())
495 ArePlainParentsDone = true;
496 else {
497 bool AddToWorklist = !isAlreadyMarked(
499 ParentInfo.setKeepPlainChildren();
500 if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
503 UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
504 }
505 }
506 }
507
508 if (AreTypeParentsDone && ArePlainParentsDone)
509 break;
510
511 ParentIdx = ParentEntry->getParentIdx();
512 }
513}
514
515namespace {
516struct FinalPlacement {
518
519 /// How Placement combines with the DIE's current placement when applied.
520 enum ApplyMode {
521 /// Overwrite the current placement. Used for entries whose placement is
522 /// fully determined regardless of how they were reached, so every mark
523 /// agrees on the value (ODR-unavailable entries and static data member
524 /// declarations).
525 Overwrite,
526 /// OR-join into the current placement (the common monotone-lattice case):
527 /// a DIE reached by both a live and a type mark ends up in Both.
528 Join,
529 /// Join for a DW_TAG_variable, which cannot occupy the type table and plain
530 /// DWARF at once: PlainDwarf is absorbing so the variable never lands in
531 /// Both.
532 JoinVariable,
533 } Mode;
534};
535} // namespace
536
537// Computes the placement to apply to \p Entry for a mark requesting \p
538// Placement (PlainDwarf for a live action, TypeTable for a type action), along
539// with how it combines with the DIE's current placement. Most entries join, so
540// a DIE reached by both actions ends up in Both. Entries whose placement is
541// fully determined regardless of how they were reached instead overwrite with
542// an exact placement: ODR-unavailable entries cannot be deduplicated into the
543// type table, and a DW_TAG_variable cannot occupy the type table and plain
544// DWARF at once.
545static FinalPlacement
548 assert((Placement != CompileUnit::NotSet) && "Placement is not set");
549 CompileUnit::DIEInfo &EntryInfo = Entry.CU->getDIEInfo(Entry.DieEntry);
550
551 if (!EntryInfo.getODRAvailable())
552 return {CompileUnit::PlainDwarf, FinalPlacement::Overwrite};
553
554 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
555 // In-class static member declarations (e.g. "static constexpr int x = 1;")
556 // are DW_TAG_variable children of a DW_TAG_class_type /
557 // DW_TAG_structure_type / DW_TAG_union_type with DW_AT_declaration set.
558 // They are part of the class type and belong in the TypeTable together with
559 // the class. Forcing them into PlainDwarf would also drag the parent class
560 // into PlainDwarf (via markParentsAsKeepingChildren), producing a duplicate
561 // empty class declaration DIE alongside the full class definition emitted
562 // in another CU.
563 bool IsDeclaration = dwarf::toUnsigned(
564 Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_declaration), 0);
565 bool ParentIsType = false;
566 if (IsDeclaration) {
567 if (std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx()) {
568 dwarf::Tag ParentTag =
569 Entry.CU->getDebugInfoEntry(*ParentIdx)->getTag();
570 ParentIsType = ParentTag == dwarf::DW_TAG_class_type ||
571 ParentTag == dwarf::DW_TAG_structure_type ||
572 ParentTag == dwarf::DW_TAG_union_type;
573 }
574 }
575 if (IsDeclaration && ParentIsType) {
576 // Pure declarations have no runtime address; they belong with the class
577 // type. Always place in TypeTable regardless of how they were reached.
578 return {CompileUnit::TypeTable, FinalPlacement::Overwrite};
579 }
580
581 // A live (PlainDwarf) mark pins the variable to plain DWARF.
583 return {CompileUnit::PlainDwarf, FinalPlacement::Overwrite};
584
585 // Only a type-table mark reaches here. The variable join keeps a PlainDwarf
586 // mark racing this one from turning the variable into Both.
587 return {Placement, FinalPlacement::JoinVariable};
588 }
589
590 return {Placement, FinalPlacement::Join};
591}
592
594 LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
595 const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
596 std::atomic<bool> &HasNewInterconnectedCUs, TreeWalkKindTy Kind) {
597 if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
598 return true;
599
600 CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
601
602 // Calculate final placement.
603 FinalPlacement Final = getFinalPlacementForEntry(
604 Entry,
607 assert((Info.getODRAvailable() || isLiveAction(Action) ||
609 "Wrong kind of placement for ODR unavailable entry");
610
611 if (!recordsDepsOnly(Kind) && !isChildrenAction(Action) &&
612 isAlreadyMarked(Entry, Placement)) {
613 // Entry (and its subtree) were already marked, possibly by a racing CU or
614 // another referencing root, and which one wins is non-deterministic. Skip
615 // the redundant marking, but still record that this root carries the
616 // dependencies the subtree contributes. Otherwise the recorded dependency
617 // set depends on thread interleaving, the demotion fixpoint misses
618 // demotions, and whole type subtrees are left in the artificial type unit
619 // non-deterministically.
620 recordSubtreeDependencies(Action, RootEntry, Entry);
621 return true;
622 }
623
624 if (!recordsDepsOnly(Kind)) {
625 // Mark current DIE as kept.
626 Info.setKeep();
627 // Marks compose monotonically so no interleaving loses an update: a general
628 // mark only raises the placement in the lattice, and a forced placement is
629 // a value every mark agrees on.
630 switch (Final.Mode) {
631 case FinalPlacement::Overwrite:
632 Info.setPlacement(Placement);
633 break;
634 case FinalPlacement::Join:
635 Info.joinPlacement(Placement);
636 break;
637 case FinalPlacement::JoinVariable:
638 Info.joinVariablePlacement(Placement);
639 break;
640 }
641
642 // Set keep children property for parents.
644 }
645
646 bool IsSubprogram = Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram;
647 UnitEntryPairTy FinalRootEntry = IsSubprogram ? Entry : RootEntry;
648
649 // A subprogram becomes the root of everything found below it, so from here on
650 // the dependencies name the subprogram instead of the root referencing the
651 // walked subtree, and are the same for every such root.
652 TreeWalkKindTy FinalKind =
653 IsSubprogram && Kind == TreeWalkKindTy::RecordSubtreeDeps
655 : Kind;
656
657 // Analyse referenced DIEs.
658 bool Res = true;
659 if (!maybeAddReferencedRoots(Action, FinalRootEntry, Entry,
660 InterCUProcessingStarted,
661 HasNewInterconnectedCUs, FinalKind))
662 Res = false;
663
664 // Return if we do not need to process children.
665 if (isSingleAction(Action))
666 return Res;
667
668 // Process children.
669 // Check for subprograms special case.
670 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
671 Info.getODRAvailable()) {
672 // Subprograms is a special case. As it can be root for type DIEs
673 // and itself may be subject to move into the artificial type unit.
674 // a) Non removable children(like DW_TAG_formal_parameter) should always
675 // be cloned. They are placed into the "PlainDwarf" and into the
676 // "TypeTable".
677 // b) ODR deduplication candidates(type DIEs) children should not be put
678 // into the "PlainDwarf".
679 // c) Children keeping addresses and locations(like DW_TAG_call_site)
680 // should not be put into the "TypeTable".
681 for (const DWARFDebugInfoEntry *CurChild =
682 Entry.CU->getFirstChildEntry(Entry.DieEntry);
683 CurChild && CurChild->getAbbreviationDeclarationPtr();
684 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
685 CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
686
687 switch (CurChild->getTag()) {
688 case dwarf::DW_TAG_variable:
689 case dwarf::DW_TAG_constant:
690 case dwarf::DW_TAG_subprogram:
691 case dwarf::DW_TAG_label: {
692 if (ChildInfo.getHasAnAddress())
693 continue;
694 } break;
695
696 // Entries having following tags could not be removed from the subprogram.
697 case dwarf::DW_TAG_lexical_block:
698 case dwarf::DW_TAG_friend:
699 case dwarf::DW_TAG_inheritance:
700 case dwarf::DW_TAG_formal_parameter:
701 case dwarf::DW_TAG_unspecified_parameters:
702 case dwarf::DW_TAG_template_type_parameter:
703 case dwarf::DW_TAG_template_value_parameter:
704 case dwarf::DW_TAG_GNU_template_parameter_pack:
705 case dwarf::DW_TAG_GNU_formal_parameter_pack:
706 case dwarf::DW_TAG_GNU_template_template_param:
707 case dwarf::DW_TAG_thrown_type: {
708 // Go to the default child handling.
709 } break;
710
711 default: {
712 bool ChildIsTypeTableCandidate = isTypeTableCandidate(CurChild);
713
714 // Skip child marked to be copied into the artificial type unit.
715 if (isLiveAction(Action) && ChildIsTypeTableCandidate)
716 continue;
717
718 // Skip child marked to be copied into the plain unit.
719 if (isTypeAction(Action) && !ChildIsTypeTableCandidate)
720 continue;
721
722 // Go to the default child handling.
723 } break;
724 }
725
727 Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
728 InterCUProcessingStarted, HasNewInterconnectedCUs, FinalKind))
729 Res = false;
730 }
731
732 return Res;
733 }
734
735 // Recursively process children.
736 for (const DWARFDebugInfoEntry *CurChild =
737 Entry.CU->getFirstChildEntry(Entry.DieEntry);
738 CurChild && CurChild->getAbbreviationDeclarationPtr();
739 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
740 CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
741 switch (CurChild->getTag()) {
742 case dwarf::DW_TAG_variable:
743 case dwarf::DW_TAG_constant:
744 case dwarf::DW_TAG_subprogram:
745 case dwarf::DW_TAG_label: {
746 if (ChildInfo.getHasAnAddress())
747 continue;
748 } break;
749 default:
750 break; // Nothing to do.
751 };
752
754 Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
755 InterCUProcessingStarted, HasNewInterconnectedCUs, FinalKind))
756 Res = false;
757 }
758
759 return Res;
760}
761
764 switch (DIEEntry->getTag()) {
765 default:
766 return false;
767
768 case dwarf::DW_TAG_imported_module:
769 case dwarf::DW_TAG_imported_declaration:
770 case dwarf::DW_TAG_imported_unit:
771 case dwarf::DW_TAG_array_type:
772 case dwarf::DW_TAG_class_type:
773 case dwarf::DW_TAG_enumeration_type:
774 case dwarf::DW_TAG_pointer_type:
775 case dwarf::DW_TAG_reference_type:
776 case dwarf::DW_TAG_string_type:
777 case dwarf::DW_TAG_structure_type:
778 case dwarf::DW_TAG_subroutine_type:
779 case dwarf::DW_TAG_typedef:
780 case dwarf::DW_TAG_union_type:
781 case dwarf::DW_TAG_variant:
782 case dwarf::DW_TAG_module:
783 case dwarf::DW_TAG_ptr_to_member_type:
784 case dwarf::DW_TAG_set_type:
785 case dwarf::DW_TAG_subrange_type:
786 case dwarf::DW_TAG_base_type:
787 case dwarf::DW_TAG_const_type:
788 case dwarf::DW_TAG_enumerator:
789 case dwarf::DW_TAG_file_type:
790 case dwarf::DW_TAG_packed_type:
791 case dwarf::DW_TAG_thrown_type:
792 case dwarf::DW_TAG_volatile_type:
793 case dwarf::DW_TAG_dwarf_procedure:
794 case dwarf::DW_TAG_restrict_type:
795 case dwarf::DW_TAG_interface_type:
796 case dwarf::DW_TAG_namespace:
797 case dwarf::DW_TAG_unspecified_type:
798 case dwarf::DW_TAG_shared_type:
799 case dwarf::DW_TAG_rvalue_reference_type:
800 case dwarf::DW_TAG_coarray_type:
801 case dwarf::DW_TAG_dynamic_type:
802 case dwarf::DW_TAG_atomic_type:
803 case dwarf::DW_TAG_immutable_type:
804 case dwarf::DW_TAG_function_template:
805 case dwarf::DW_TAG_class_template:
806 return true;
807 }
808}
809
811 LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
812 const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
813 std::atomic<bool> &HasNewInterconnectedCUs, TreeWalkKindTy Kind) {
814 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
815 if (Abbrev == nullptr)
816 return true;
817
818 // A walk that only records dependencies does not schedule the referenced root
819 // for marking. The completeness dependency is collected instead, so it
820 // participates in the demotion fixpoint without triggering any
821 // reference-following recursion.
822 auto AddRoot = [&](LiveRootWorklistActionTy RootAction,
823 const UnitEntryPairTy &Root,
824 const DWARFDebugInfoEntry *ReferencedTypeDieEntry) {
825 switch (Kind) {
827 addActionToRootEntriesWorkList(RootAction, Root, RootEntry,
828 ReferencedTypeDieEntry);
829 return;
830
832 // The dependency belongs to whichever root references this subtree, so it
833 // is summarized and applied to each of them in turn.
834 assert(CollectedSubtreeDeps && "record-deps-only walk without a sink");
835 CollectedSubtreeDeps->push_back(
836 {RootAction, Root, ReferencedTypeDieEntry});
837 return;
838
840 // The dependency belongs to a subprogram nested inside the subtree, so it
841 // is the same for every referencing root and recording it once is enough.
842 Dependencies.emplace_back(RootAction, Root, RootEntry,
843 ReferencedTypeDieEntry);
844 return;
845 }
846 llvm_unreachable("Unknown TreeWalkKindTy enum");
847 };
848
849 DWARFUnit &Unit = Entry.CU->getOrigUnit();
850 DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
851 uint64_t Offset =
852 Entry.DieEntry->getOffset() + getULEB128Size(Abbrev->getCode());
853
854 // For each DIE attribute...
855 for (const auto &AttrSpec : Abbrev->attributes()) {
856 DWARFFormValue Val(AttrSpec.Form);
858 AttrSpec.Attr == dwarf::DW_AT_sibling) {
859 DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
860 Unit.getFormParams());
861 continue;
862 }
863 Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
864
865 // Resolve reference.
866 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
867 Val, InterCUProcessingStarted
870 if (!RefDie) {
871 Entry.CU->warn("could not find referenced DIE", Entry.DieEntry);
872 continue;
873 }
874
875 if (!RefDie->DieEntry) {
876 // The reference could not be resolved yet. Recording dependencies
877 // happens only after marking has fully resolved interconnections, so skip
878 // it here. The scheduling path below handles the delayed-resolution case.
879 if (recordsDepsOnly(Kind))
880 continue;
881
882 // Delay resolving reference.
883 RefDie->CU->setInterconnectedCU();
884 Entry.CU->setInterconnectedCU();
885 HasNewInterconnectedCUs = true;
886 return false;
887 }
888
889 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
890 InterCUProcessingStarted) &&
891 "Inter-CU reference while inter-CU processing is not started");
892
893 CompileUnit::DIEInfo &RefInfo = RefDie->CU->getDIEInfo(RefDie->DieEntry);
894 if (!RefInfo.getODRAvailable())
896 else if (RefInfo.getODRAvailable() &&
897 llvm::is_contained(getODRAttributes(), AttrSpec.Attr))
898 // Note: getODRAttributes does not include DW_AT_containing_type.
899 // It should be OK as we do getRootForSpecifiedEntry(). So any containing
900 // type would be found as the root for the entry.
902 else if (isLiveAction(Action))
904 else
906
907 if (AttrSpec.Attr == dwarf::DW_AT_import) {
908 if (isNamespaceLikeEntry(RefDie->DieEntry)) {
909 AddRoot(isTypeAction(Action)
912 *RefDie, nullptr);
913 continue;
914 }
915
916 AddRoot(Action, *RefDie, nullptr);
917 continue;
918 }
919
920 // Mark the enclosing root type as kept, but also record the actual
921 // referenced DIE: a nested type can be demoted to plain DWARF independently
922 // of its root, in which case ReferencedBy must be demoted too (see
923 // updateDependenciesCompleteness).
924 UnitEntryPairTy RootForReferencedDie = getRootForSpecifiedEntry(*RefDie);
925 AddRoot(Action, RootForReferencedDie, RefDie->DieEntry);
926 }
927
928 return true;
929}
930
933 UnitEntryPairTy Result = Entry;
934
935 do {
936 switch (Entry.DieEntry->getTag()) {
937 case dwarf::DW_TAG_subprogram:
938 case dwarf::DW_TAG_label:
939 case dwarf::DW_TAG_variable:
940 case dwarf::DW_TAG_constant: {
941 return Result;
942 } break;
943
944 default: {
945 // Nothing to do.
946 }
947 }
948
949 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
950 if (!ParentIdx)
951 return Result;
952
953 const DWARFDebugInfoEntry *ParentEntry =
954 Result.CU->getDebugInfoEntry(*ParentIdx);
955 if (isNamespaceLikeEntry(ParentEntry))
956 break;
957 Result.DieEntry = ParentEntry;
958 } while (true);
959
960 return Result;
961}
962
963static void dumpKeptDIE(const DWARFDie &DIE, StringRef Kind, bool Verbose) {
964 if (!Verbose)
965 return;
966 outs() << "Keeping " << Kind << " DIE:";
967 DIDumpOptions DumpOpts;
968 DumpOpts.ChildRecurseDepth = 0;
969 DumpOpts.Verbose = Verbose;
970 DIE.dump(outs(), /*Indent=*/8, DumpOpts);
971}
972
974 bool IsLiveParent) {
975 DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
976 CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(DIE);
977
978 if (Info.getTrackLiveness()) {
979 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
980
981 if (!Info.getIsInFunctionScope() &&
982 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
983 // Global variables with constant value can always be kept.
984 } else {
985 // See if there is a relocation to a valid debug map entry inside this
986 // variable's location. The order is important here. We want to always
987 // check if the variable has a location expression address. However, we
988 // don't want a static variable in a function to force us to keep the
989 // enclosing function, unless requested explicitly.
990 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
991 Entry.CU->getContainingFile().Addresses->getVariableRelocAdjustment(
992 DIE, Entry.CU->getGlobalData().getOptions().Verbose);
993
994 if (LocExprAddrAndRelocAdjustment.first)
995 Info.setHasAnAddress();
996
997 if (!LocExprAddrAndRelocAdjustment.second)
998 return false;
999
1000 if (!IsLiveParent && Info.getIsInFunctionScope() &&
1001 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
1002 return false;
1003 }
1004 }
1005 Info.setHasAnAddress();
1006
1007 dumpKeptDIE(DIE, "variable", Entry.CU->getGlobalData().getOptions().Verbose);
1008
1009 return true;
1010}
1011
1013 DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
1014 CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
1015 std::optional<DWARFFormValue> LowPCVal = DIE.find(dwarf::DW_AT_low_pc);
1016
1017 const bool Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
1018 std::optional<uint64_t> LowPc;
1019 std::optional<uint64_t> HighPc;
1020 std::optional<int64_t> RelocAdjustment;
1021 if (Info.getTrackLiveness()) {
1022 LowPc = dwarf::toAddress(LowPCVal);
1023 if (!LowPc)
1024 return false;
1025
1026 Info.setHasAnAddress();
1027
1028 RelocAdjustment =
1029 Entry.CU->getContainingFile().Addresses->getSubprogramRelocAdjustment(
1030 DIE, Verbose);
1031 if (!RelocAdjustment)
1032 return false;
1033
1034 if (DIE.getTag() == dwarf::DW_TAG_subprogram) {
1035 // Validate subprogram address range.
1036
1037 HighPc = DIE.getHighPC(*LowPc);
1038 if (!HighPc) {
1039 Entry.CU->warn("function without high_pc. Range will be discarded.",
1040 &DIE);
1041 return false;
1042 }
1043
1044 if (*LowPc > *HighPc) {
1045 Entry.CU->warn("low_pc greater than high_pc. Range will be discarded.",
1046 &DIE);
1047 return false;
1048 }
1049 } else if (DIE.getTag() == dwarf::DW_TAG_label) {
1050 if (Entry.CU->hasLabelAt(*LowPc))
1051 return false;
1052
1053 // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider
1054 // labels that don't fall into the CU's aranges. This is wrong IMO. Debug
1055 // info generation bugs aside, this is really wrong in the case of labels,
1056 // where a label marking the end of a function will have a PC == CU's
1057 // high_pc.
1058 if (dwarf::toAddress(Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_high_pc))
1059 .value_or(UINT64_MAX) <= LowPc)
1060 return false;
1061
1062 // For assembly-language CUs there are typically no DW_TAG_subprogram
1063 // DIEs, so labels are the only addresses we see. Fall back to the
1064 // symbol-range lookup to recover a function range for the line-table
1065 // filter; otherwise the output line table would be empty.
1066 uint16_t Language = dwarf::toUnsigned(
1067 Entry.CU->getOrigUnit().getUnitDIE().find(dwarf::DW_AT_language), 0);
1068 if (Language == dwarf::DW_LANG_Mips_Assembler ||
1069 Language == dwarf::DW_LANG_Assembly) {
1070 if (auto Range = Entry.CU->getContainingFile()
1071 .Addresses->getSymbolRangeForAddress(*LowPc))
1072 Entry.CU->addFunctionRange(Range->LowPC, Range->HighPC,
1073 *RelocAdjustment);
1074 }
1075
1076 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
1077 }
1078 } else
1079 Info.setHasAnAddress();
1080
1081 dumpKeptDIE(DIE, "subprogram", Verbose);
1082
1083 if (!Info.getTrackLiveness() || DIE.getTag() == dwarf::DW_TAG_label)
1084 return true;
1085
1086 Entry.CU->addFunctionRange(
1087 *LowPc,
1088 Entry.CU->getContainingFile().Addresses->constrainCodeRangeHighPC(
1089 *LowPc, *HighPc, *RelocAdjustment),
1090 *RelocAdjustment);
1091 return true;
1092}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bool isAlreadyMarked(const CompileUnit::DIEInfo &Info, CompileUnit::DieOutputPlacement NewPlacement)
static void dumpKeptDIE(const DWARFDie &DIE, StringRef Kind, bool Verbose)
static FinalPlacement getFinalPlacementForEntry(const UnitEntryPairTy &Entry, CompileUnit::DieOutputPlacement Placement)
static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry)
Branch Probability Basic Block Placement
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file provides utility classes that use RAII to save and restore values.
A pointer to another debug information entry.
Definition DIE.h:325
A structured debug information entry.
Definition DIE.h:842
dwarf::Tag getTag() const
Definition DIE.h:878
LLVM_ABI void dump() const
Definition DIE.cpp:261
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
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
iterator_range< iterator > children() const
Definition DWARFDie.h:407
const DWARFDebugInfoEntry * getDebugInfoEntry() const
Definition DWARFDie.h:54
bool isValid() const
Definition DWARFDie.h:52
LLVM_ABI bool isFormClass(FormClass FC) const
LLVM_ABI bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)
Extracts a value in Data at offset *OffsetPtr.
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const
Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition WithColor.cpp:84
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.
bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs, TreeWalkKindTy Kind=TreeWalkKindTy::MarkTree)
Mark whole DIE tree as kept recursively.
void verifyKeepChain()
Recursively walk the DIE tree and check "keepness" and "placement" information.
RootEntriesListTy Dependencies
List of entries dependencies.
void markParentsAsKeepingChildren(const UnitEntryPairTy &Entry)
Mark parents as keeping children.
UnitEntryPairTy getRootForSpecifiedEntry(UnitEntryPairTy Entry)
static bool recordsDepsOnly(TreeWalkKindTy Kind)
bool demoteIfIncomplete(const UnitEntryPairTy &Root, const DWARFDebugInfoEntry *ReferencedTypeDieEntry, const UnitEntryPairTy &ReferencedBy)
Demote ReferencedBy to plain DWARF if it may not stay in the type table while the DIE it references t...
bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Examine worklist and mark all 'root DIE's as kept and set "Placement" property.
bool InterCUProcessingWasStarted
Whether inter-unit references could be resolved during marking.
bool applySubtreeSummaries()
Apply each summarized subtree's dependencies to every root recorded as referencing it.
bool isLiveAction(LiveRootWorklistActionTy Action)
bool isChildrenAction(LiveRootWorklistActionTy Action)
TreeWalkKindTy
What a tree walk does, and for a walk that only records dependencies, which root the dependencies it ...
@ MarkTree
Mark the tree as kept and schedule the roots it references.
bool isTypeAction(LiveRootWorklistActionTy Action)
void addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy, const DWARFDebugInfoEntry *ReferencedTypeDieEntry=nullptr)
Add action item to the work list.
DenseMap< SubtreeDependenciesKeyTy, SubtreeDependenciesTy > SubtreeSummaries
Dependency summaries of already-marked subtrees, keyed by subtree and action.
SubtreeDependenciesTy * CollectedSubtreeDeps
Where the walk in progress collects the dependencies that belong to the root referencing the walked s...
bool isTypeTableCandidate(const DWARFDebugInfoEntry *DIEEntry)
size_t MaterializedRefs
Number of leading SubtreeDependencyRefs whose subtree is summarized.
void setPlainDwarfPlacementRec(const UnitEntryPairTy &Entry)
Mark whole DIE tree as placed in "PlainDwarf".
RootEntriesListTy RootEntriesWorkList
List of entries which are 'root DIE's.
SmallVector< SubtreeDependencyTy > SubtreeDependenciesTy
static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry)
Returns true if specified subprogram references live code section.
std::tuple< CompileUnit *, const DWARFDebugInfoEntry *, LiveRootWorklistActionTy > SubtreeDependenciesKeyTy
A subtree paired with the action it is walked with, which selects both the visited children and the a...
void recordSubtreeDependencies(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry)
Record that RootEntry references the already-marked subtree Entry, and therefore carries the complete...
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Recursively walk the DIE tree and look for DIEs to keep.
static bool isLiveVariableEntry(const UnitEntryPairTy &Entry, bool IsLiveParent)
Returns true if specified variable references live code section.
@ MarkTypeEntryRec
Mark current item and all its children as type entry.
@ MarkLiveChildrenRec
Mark all children of current item as live entry.
@ MarkLiveEntryRec
Mark current item and all its children as live entry.
@ MarkTypeChildrenRec
Mark all children of current item as type entry.
SmallVector< SubtreeDependencyRefTy > SubtreeDependencyRefs
Roots referencing an already-marked subtree.
void collectRootsToKeep(const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy, bool IsLiveParent)
This function navigates DIEs tree starting from specified Entry.
bool maybeAddReferencedRoots(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs, TreeWalkKindTy Kind=TreeWalkKindTy::MarkTree)
Check referenced DIEs and add them into the worklist.
bool updateDependenciesCompleteness()
Check if dependencies have incompatible placement.
void materializeSubtreeSummaries()
Walk every subtree that a recorded reference stands for, once per subtree and action,...
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
#define UINT64_MAX
Definition DataTypes.h:77
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ArrayRef< dwarf::Attribute > getODRAttributes()
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
bool isType(Tag T)
Definition Dwarf.h:113
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition LEB128.cpp:19
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196
unsigned ChildRecurseDepth
Definition DIContext.h:198
A utility class that uses RAII to save and restore the value of a variable.
Information gathered about a DIE in the object file.
void setPlacement(DieOutputPlacement Placement)
Sets Placement kind for the corresponding die.
A root referencing an already-marked subtree, standing in for all of that subtree's dependencies.
A completeness dependency of a subtree that belongs to whichever root references the subtree,...
This is a helper structure which keeps a debug info entry with it's containing compilation unit.