xref: /llvm-project/llvm/lib/DWARFLinker/Parallel/DependencyTracker.cpp (revision 0ed8194256c6c96875ed9dd102d15ee8a9260fec)
12357e899Savl-llvm //=== DependencyTracker.cpp -----------------------------------------------===//
22357e899Savl-llvm //
32357e899Savl-llvm // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42357e899Savl-llvm // See https://llvm.org/LICENSE.txt for license information.
52357e899Savl-llvm // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62357e899Savl-llvm //
72357e899Savl-llvm //===----------------------------------------------------------------------===//
82357e899Savl-llvm 
92357e899Savl-llvm #include "DependencyTracker.h"
102357e899Savl-llvm #include "llvm/Support/FormatVariadic.h"
112357e899Savl-llvm 
122357e899Savl-llvm using namespace llvm;
132357e899Savl-llvm using namespace dwarf_linker;
142357e899Savl-llvm using namespace dwarf_linker::parallel;
152357e899Savl-llvm 
162357e899Savl-llvm /// A broken link in the keep chain. By recording both the parent and the child
172357e899Savl-llvm /// we can show only broken links for DIEs with multiple children.
182357e899Savl-llvm struct BrokenLink {
BrokenLinkBrokenLink192357e899Savl-llvm   BrokenLink(DWARFDie Parent, DWARFDie Child, const char *Message)
202357e899Savl-llvm       : Parent(Parent), Child(Child), Message(Message) {}
212357e899Savl-llvm   DWARFDie Parent;
222357e899Savl-llvm   DWARFDie Child;
232357e899Savl-llvm   std::string Message;
242357e899Savl-llvm };
252357e899Savl-llvm 
262357e899Savl-llvm /// Verify the keep chain by looking for DIEs that are kept but who's parent
272357e899Savl-llvm /// isn't.
verifyKeepChain()282357e899Savl-llvm void DependencyTracker::verifyKeepChain() {
292357e899Savl-llvm #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
302357e899Savl-llvm   SmallVector<DWARFDie> Worklist;
312357e899Savl-llvm   Worklist.push_back(CU.getOrigUnit().getUnitDIE());
322357e899Savl-llvm 
332357e899Savl-llvm   // List of broken links.
342357e899Savl-llvm   SmallVector<BrokenLink> BrokenLinks;
352357e899Savl-llvm 
362357e899Savl-llvm   while (!Worklist.empty()) {
372357e899Savl-llvm     const DWARFDie Current = Worklist.back();
382357e899Savl-llvm     Worklist.pop_back();
392357e899Savl-llvm 
402357e899Savl-llvm     if (!Current.isValid())
412357e899Savl-llvm       continue;
422357e899Savl-llvm 
432357e899Savl-llvm     CompileUnit::DIEInfo &CurrentInfo =
442357e899Savl-llvm         CU.getDIEInfo(Current.getDebugInfoEntry());
452357e899Savl-llvm     const bool ParentPlainDieIsKept = CurrentInfo.needToKeepInPlainDwarf();
462357e899Savl-llvm     const bool ParentTypeDieIsKept = CurrentInfo.needToPlaceInTypeTable();
472357e899Savl-llvm 
482357e899Savl-llvm     for (DWARFDie Child : reverse(Current.children())) {
492357e899Savl-llvm       Worklist.push_back(Child);
502357e899Savl-llvm 
512357e899Savl-llvm       CompileUnit::DIEInfo &ChildInfo =
522357e899Savl-llvm           CU.getDIEInfo(Child.getDebugInfoEntry());
532357e899Savl-llvm       const bool ChildPlainDieIsKept = ChildInfo.needToKeepInPlainDwarf();
542357e899Savl-llvm       const bool ChildTypeDieIsKept = ChildInfo.needToPlaceInTypeTable();
552357e899Savl-llvm 
562357e899Savl-llvm       if (!ParentPlainDieIsKept && ChildPlainDieIsKept)
572357e899Savl-llvm         BrokenLinks.emplace_back(Current, Child,
582357e899Savl-llvm                                  "Found invalid link in keep chain");
592357e899Savl-llvm 
602357e899Savl-llvm       if (Child.getTag() == dwarf::DW_TAG_subprogram) {
612357e899Savl-llvm         if (!ChildInfo.getKeep() && isLiveSubprogramEntry(UnitEntryPairTy(
622357e899Savl-llvm                                         &CU, Child.getDebugInfoEntry()))) {
632357e899Savl-llvm           BrokenLinks.emplace_back(Current, Child,
642357e899Savl-llvm                                    "Live subprogram is not marked as kept");
652357e899Savl-llvm         }
662357e899Savl-llvm       }
672357e899Savl-llvm 
682357e899Savl-llvm       if (!ChildInfo.getODRAvailable()) {
692357e899Savl-llvm         assert(!ChildTypeDieIsKept);
702357e899Savl-llvm         continue;
712357e899Savl-llvm       }
722357e899Savl-llvm 
732357e899Savl-llvm       if (!ParentTypeDieIsKept && ChildTypeDieIsKept)
742357e899Savl-llvm         BrokenLinks.emplace_back(Current, Child,
752357e899Savl-llvm                                  "Found invalid link in keep chain");
762357e899Savl-llvm 
772357e899Savl-llvm       if (CurrentInfo.getIsInAnonNamespaceScope() &&
782357e899Savl-llvm           ChildInfo.needToPlaceInTypeTable()) {
792357e899Savl-llvm         BrokenLinks.emplace_back(Current, Child,
802357e899Savl-llvm                                  "Found invalid placement marking for member "
812357e899Savl-llvm                                  "of anonymous namespace");
822357e899Savl-llvm       }
832357e899Savl-llvm     }
842357e899Savl-llvm   }
852357e899Savl-llvm 
862357e899Savl-llvm   if (!BrokenLinks.empty()) {
872357e899Savl-llvm     for (BrokenLink Link : BrokenLinks) {
882357e899Savl-llvm       errs() << "\n=================================\n";
892357e899Savl-llvm       WithColor::error() << formatv("{0} between {1:x} and {2:x}", Link.Message,
902357e899Savl-llvm                                     Link.Parent.getOffset(),
912357e899Savl-llvm                                     Link.Child.getOffset());
922357e899Savl-llvm 
932357e899Savl-llvm       errs() << "\nParent:";
942357e899Savl-llvm       Link.Parent.dump(errs(), 0, {});
952357e899Savl-llvm       errs() << "\n";
962357e899Savl-llvm       CU.getDIEInfo(Link.Parent).dump();
972357e899Savl-llvm 
982357e899Savl-llvm       errs() << "\nChild:";
992357e899Savl-llvm       Link.Child.dump(errs(), 2, {});
1002357e899Savl-llvm       errs() << "\n";
1012357e899Savl-llvm       CU.getDIEInfo(Link.Child).dump();
1022357e899Savl-llvm     }
1032357e899Savl-llvm     report_fatal_error("invalid keep chain");
1042357e899Savl-llvm   }
1052357e899Savl-llvm #endif
1062357e899Savl-llvm }
1072357e899Savl-llvm 
resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)1082357e899Savl-llvm bool DependencyTracker::resolveDependenciesAndMarkLiveness(
1092357e899Savl-llvm     bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
1102357e899Savl-llvm   RootEntriesWorkList.clear();
1112357e899Savl-llvm 
1122357e899Savl-llvm   // Search for live root DIEs.
1132357e899Savl-llvm   CompileUnit::DIEInfo &CUInfo = CU.getDIEInfo(CU.getDebugInfoEntry(0));
1142357e899Savl-llvm   CUInfo.setPlacement(CompileUnit::PlainDwarf);
1152357e899Savl-llvm   collectRootsToKeep(UnitEntryPairTy{&CU, CU.getDebugInfoEntry(0)},
1162357e899Savl-llvm                      std::nullopt, false);
1172357e899Savl-llvm 
1182357e899Savl-llvm   // Mark live DIEs as kept.
1192357e899Savl-llvm   return markCollectedLiveRootsAsKept(InterCUProcessingStarted,
1202357e899Savl-llvm                                       HasNewInterconnectedCUs);
1212357e899Savl-llvm }
1222357e899Savl-llvm 
addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action,const UnitEntryPairTy & Entry,std::optional<UnitEntryPairTy> ReferencedBy)1232357e899Savl-llvm void DependencyTracker::addActionToRootEntriesWorkList(
1242357e899Savl-llvm     LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry,
1252357e899Savl-llvm     std::optional<UnitEntryPairTy> ReferencedBy) {
1262357e899Savl-llvm   if (ReferencedBy) {
1272357e899Savl-llvm     RootEntriesWorkList.emplace_back(Action, Entry, *ReferencedBy);
1282357e899Savl-llvm     return;
1292357e899Savl-llvm   }
1302357e899Savl-llvm 
1312357e899Savl-llvm   RootEntriesWorkList.emplace_back(Action, Entry);
1322357e899Savl-llvm }
1332357e899Savl-llvm 
collectRootsToKeep(const UnitEntryPairTy & Entry,std::optional<UnitEntryPairTy> ReferencedBy,bool IsLiveParent)1342357e899Savl-llvm void DependencyTracker::collectRootsToKeep(
1352357e899Savl-llvm     const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
1362357e899Savl-llvm     bool IsLiveParent) {
1372357e899Savl-llvm   for (const DWARFDebugInfoEntry *CurChild =
1382357e899Savl-llvm            Entry.CU->getFirstChildEntry(Entry.DieEntry);
1392357e899Savl-llvm        CurChild && CurChild->getAbbreviationDeclarationPtr();
1402357e899Savl-llvm        CurChild = Entry.CU->getSiblingEntry(CurChild)) {
1412357e899Savl-llvm     UnitEntryPairTy ChildEntry(Entry.CU, CurChild);
1422357e899Savl-llvm     CompileUnit::DIEInfo &ChildInfo = Entry.CU->getDIEInfo(CurChild);
1432357e899Savl-llvm 
1442357e899Savl-llvm     bool IsLiveChild = false;
1452357e899Savl-llvm 
1462357e899Savl-llvm     switch (CurChild->getTag()) {
1472357e899Savl-llvm     case dwarf::DW_TAG_label: {
1482357e899Savl-llvm       IsLiveChild = isLiveSubprogramEntry(ChildEntry);
1492357e899Savl-llvm 
1502357e899Savl-llvm       // Keep label referencing live address.
1512357e899Savl-llvm       // Keep label which is child of live parent entry.
1522357e899Savl-llvm       if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
1532357e899Savl-llvm         addActionToRootEntriesWorkList(
1542357e899Savl-llvm             LiveRootWorklistActionTy::MarkLiveEntryRec, ChildEntry,
1552357e899Savl-llvm             ReferencedBy);
1562357e899Savl-llvm       }
1572357e899Savl-llvm     } break;
1582357e899Savl-llvm     case dwarf::DW_TAG_subprogram: {
1592357e899Savl-llvm       IsLiveChild = isLiveSubprogramEntry(ChildEntry);
1602357e899Savl-llvm 
1612357e899Savl-llvm       // Keep subprogram referencing live address.
1622357e899Savl-llvm       if (IsLiveChild) {
1632357e899Savl-llvm         // If subprogram is in module scope and this module allows ODR
1642357e899Savl-llvm         // deduplication set "TypeTable" placement, otherwise set "" placement
1652357e899Savl-llvm         LiveRootWorklistActionTy Action =
1662357e899Savl-llvm             (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
1672357e899Savl-llvm                 ? LiveRootWorklistActionTy::MarkTypeEntryRec
1682357e899Savl-llvm                 : LiveRootWorklistActionTy::MarkLiveEntryRec;
1692357e899Savl-llvm 
1702357e899Savl-llvm         addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
1712357e899Savl-llvm       }
1722357e899Savl-llvm     } break;
1732357e899Savl-llvm     case dwarf::DW_TAG_constant:
1742357e899Savl-llvm     case dwarf::DW_TAG_variable: {
1752357e899Savl-llvm       IsLiveChild = isLiveVariableEntry(ChildEntry, IsLiveParent);
1762357e899Savl-llvm 
1772357e899Savl-llvm       // Keep variable referencing live address.
1782357e899Savl-llvm       if (IsLiveChild) {
1792357e899Savl-llvm         // If variable is in module scope and this module allows ODR
1802357e899Savl-llvm         // deduplication set "TypeTable" placement, otherwise set "" placement
1812357e899Savl-llvm 
1822357e899Savl-llvm         LiveRootWorklistActionTy Action =
1832357e899Savl-llvm             (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
1842357e899Savl-llvm                 ? LiveRootWorklistActionTy::MarkTypeEntryRec
1852357e899Savl-llvm                 : LiveRootWorklistActionTy::MarkLiveEntryRec;
1862357e899Savl-llvm 
1872357e899Savl-llvm         addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
1882357e899Savl-llvm       }
1892357e899Savl-llvm     } break;
1902357e899Savl-llvm     case dwarf::DW_TAG_base_type: {
1912357e899Savl-llvm       // Always keep base types.
1922357e899Savl-llvm       addActionToRootEntriesWorkList(
1932357e899Savl-llvm           LiveRootWorklistActionTy::MarkSingleLiveEntry, ChildEntry,
1942357e899Savl-llvm           ReferencedBy);
1952357e899Savl-llvm     } break;
1962357e899Savl-llvm     case dwarf::DW_TAG_imported_module:
1972357e899Savl-llvm     case dwarf::DW_TAG_imported_declaration:
1982357e899Savl-llvm     case dwarf::DW_TAG_imported_unit: {
1992357e899Savl-llvm       // Always keep DIEs having DW_AT_import attribute.
2002357e899Savl-llvm       if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
2012357e899Savl-llvm         addActionToRootEntriesWorkList(
2022357e899Savl-llvm             LiveRootWorklistActionTy::MarkSingleLiveEntry, ChildEntry,
2032357e899Savl-llvm             ReferencedBy);
2042357e899Savl-llvm         break;
2052357e899Savl-llvm       }
2062357e899Savl-llvm 
2072357e899Savl-llvm       addActionToRootEntriesWorkList(
2082357e899Savl-llvm           LiveRootWorklistActionTy::MarkSingleTypeEntry, ChildEntry,
2092357e899Savl-llvm           ReferencedBy);
2102357e899Savl-llvm     } break;
2112357e899Savl-llvm     case dwarf::DW_TAG_type_unit:
2122357e899Savl-llvm     case dwarf::DW_TAG_partial_unit:
2132357e899Savl-llvm     case dwarf::DW_TAG_compile_unit: {
2142357e899Savl-llvm       llvm_unreachable("Called for incorrect DIE");
2152357e899Savl-llvm     } break;
2162357e899Savl-llvm     default:
2172357e899Savl-llvm       // Nothing to do.
2182357e899Savl-llvm       break;
2192357e899Savl-llvm     }
2202357e899Savl-llvm 
2212357e899Savl-llvm     collectRootsToKeep(ChildEntry, ReferencedBy, IsLiveChild || IsLiveParent);
2222357e899Savl-llvm   }
2232357e899Savl-llvm }
2242357e899Savl-llvm 
markCollectedLiveRootsAsKept(bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)2252357e899Savl-llvm bool DependencyTracker::markCollectedLiveRootsAsKept(
2262357e899Savl-llvm     bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
2272357e899Savl-llvm   bool Res = true;
2282357e899Savl-llvm 
2292357e899Savl-llvm   // Mark roots as kept.
2302357e899Savl-llvm   while (!RootEntriesWorkList.empty()) {
2312357e899Savl-llvm     LiveRootWorklistItemTy Root = RootEntriesWorkList.pop_back_val();
2322357e899Savl-llvm 
2332357e899Savl-llvm     if (markDIEEntryAsKeptRec(Root.getAction(), Root.getRootEntry(),
2342357e899Savl-llvm                               Root.getRootEntry(), InterCUProcessingStarted,
2352357e899Savl-llvm                               HasNewInterconnectedCUs)) {
2362357e899Savl-llvm       if (Root.hasReferencedByOtherEntry())
2372357e899Savl-llvm         Dependencies.push_back(Root);
2382357e899Savl-llvm     } else
2392357e899Savl-llvm       Res = false;
2402357e899Savl-llvm   }
2412357e899Savl-llvm 
2422357e899Savl-llvm   return Res;
2432357e899Savl-llvm }
2442357e899Savl-llvm 
updateDependenciesCompleteness()2452357e899Savl-llvm bool DependencyTracker::updateDependenciesCompleteness() {
2462357e899Savl-llvm   bool HasNewDependency = false;
2472357e899Savl-llvm   for (LiveRootWorklistItemTy &Root : Dependencies) {
2482357e899Savl-llvm     assert(Root.hasReferencedByOtherEntry() &&
2492357e899Savl-llvm            "Root entry without dependency inside the dependencies list");
2502357e899Savl-llvm 
2512357e899Savl-llvm     UnitEntryPairTy RootEntry = Root.getRootEntry();
2522357e899Savl-llvm     CompileUnit::DIEInfo &RootInfo =
2532357e899Savl-llvm         RootEntry.CU->getDIEInfo(RootEntry.DieEntry);
2542357e899Savl-llvm 
2552357e899Savl-llvm     UnitEntryPairTy ReferencedByEntry = Root.getReferencedByEntry();
2562357e899Savl-llvm     CompileUnit::DIEInfo &ReferencedByInfo =
2572357e899Savl-llvm         ReferencedByEntry.CU->getDIEInfo(ReferencedByEntry.DieEntry);
2582357e899Savl-llvm 
2592357e899Savl-llvm     if (!RootInfo.needToPlaceInTypeTable() &&
2602357e899Savl-llvm         ReferencedByInfo.needToPlaceInTypeTable()) {
2612357e899Savl-llvm       HasNewDependency = true;
2622357e899Savl-llvm       setPlainDwarfPlacementRec(ReferencedByEntry);
2632357e899Savl-llvm 
2642357e899Savl-llvm       // FIXME: we probably need to update getKeepTypeChildren status for
2652357e899Savl-llvm       // parents of *Root.ReferencedBy.
2662357e899Savl-llvm     }
2672357e899Savl-llvm   }
2682357e899Savl-llvm 
2692357e899Savl-llvm   return HasNewDependency;
2702357e899Savl-llvm }
2712357e899Savl-llvm 
setPlainDwarfPlacementRec(const UnitEntryPairTy & Entry)2722357e899Savl-llvm void DependencyTracker::setPlainDwarfPlacementRec(
2732357e899Savl-llvm     const UnitEntryPairTy &Entry) {
2742357e899Savl-llvm   CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
2752357e899Savl-llvm   if (Info.getPlacement() == CompileUnit::PlainDwarf &&
2762357e899Savl-llvm       !Info.getKeepTypeChildren())
2772357e899Savl-llvm     return;
2782357e899Savl-llvm 
2792357e899Savl-llvm   Info.setPlacement(CompileUnit::PlainDwarf);
2802357e899Savl-llvm   Info.unsetKeepTypeChildren();
2812357e899Savl-llvm   markParentsAsKeepingChildren(Entry);
2822357e899Savl-llvm 
2832357e899Savl-llvm   for (const DWARFDebugInfoEntry *CurChild =
2842357e899Savl-llvm            Entry.CU->getFirstChildEntry(Entry.DieEntry);
2852357e899Savl-llvm        CurChild && CurChild->getAbbreviationDeclarationPtr();
2862357e899Savl-llvm        CurChild = Entry.CU->getSiblingEntry(CurChild))
2872357e899Savl-llvm     setPlainDwarfPlacementRec(UnitEntryPairTy{Entry.CU, CurChild});
2882357e899Savl-llvm }
2892357e899Savl-llvm 
isNamespaceLikeEntry(const DWARFDebugInfoEntry * Entry)2902357e899Savl-llvm static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry) {
2912357e899Savl-llvm   switch (Entry->getTag()) {
2922357e899Savl-llvm   case dwarf::DW_TAG_compile_unit:
2932357e899Savl-llvm   case dwarf::DW_TAG_module:
2942357e899Savl-llvm   case dwarf::DW_TAG_namespace:
2952357e899Savl-llvm     return true;
2962357e899Savl-llvm 
2972357e899Savl-llvm   default:
2982357e899Savl-llvm     return false;
2992357e899Savl-llvm   }
3002357e899Savl-llvm }
3012357e899Savl-llvm 
isAlreadyMarked(const CompileUnit::DIEInfo & Info,CompileUnit::DieOutputPlacement NewPlacement)3022357e899Savl-llvm bool isAlreadyMarked(const CompileUnit::DIEInfo &Info,
3032357e899Savl-llvm                      CompileUnit::DieOutputPlacement NewPlacement) {
3042357e899Savl-llvm   if (!Info.getKeep())
3052357e899Savl-llvm     return false;
3062357e899Savl-llvm 
3072357e899Savl-llvm   switch (NewPlacement) {
3082357e899Savl-llvm   case CompileUnit::TypeTable:
3092357e899Savl-llvm     return Info.needToPlaceInTypeTable();
3102357e899Savl-llvm 
3112357e899Savl-llvm   case CompileUnit::PlainDwarf:
3122357e899Savl-llvm     return Info.needToKeepInPlainDwarf();
3132357e899Savl-llvm 
3142357e899Savl-llvm   case CompileUnit::Both:
3152357e899Savl-llvm     return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
3162357e899Savl-llvm 
3172357e899Savl-llvm   case CompileUnit::NotSet:
3182357e899Savl-llvm     llvm_unreachable("Unset placement type is specified.");
3192357e899Savl-llvm   };
3202357e899Savl-llvm 
3212357e899Savl-llvm   llvm_unreachable("Unknown CompileUnit::DieOutputPlacement enum");
3222357e899Savl-llvm }
3232357e899Savl-llvm 
isAlreadyMarked(const UnitEntryPairTy & Entry,CompileUnit::DieOutputPlacement NewPlacement)3242357e899Savl-llvm bool isAlreadyMarked(const UnitEntryPairTy &Entry,
3252357e899Savl-llvm                      CompileUnit::DieOutputPlacement NewPlacement) {
3262357e899Savl-llvm   return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
3272357e899Savl-llvm }
3282357e899Savl-llvm 
markParentsAsKeepingChildren(const UnitEntryPairTy & Entry)3292357e899Savl-llvm void DependencyTracker::markParentsAsKeepingChildren(
3302357e899Savl-llvm     const UnitEntryPairTy &Entry) {
3312357e899Savl-llvm   if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
3322357e899Savl-llvm     return;
3332357e899Savl-llvm 
3342357e899Savl-llvm   CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
3352357e899Savl-llvm   bool NeedKeepTypeChildren = Info.needToPlaceInTypeTable();
3362357e899Savl-llvm   bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
3372357e899Savl-llvm 
3382357e899Savl-llvm   bool AreTypeParentsDone = !NeedKeepTypeChildren;
3392357e899Savl-llvm   bool ArePlainParentsDone = !NeedKeepPlainChildren;
3402357e899Savl-llvm 
3412357e899Savl-llvm   // Mark parents as 'Keep*Children'.
3422357e899Savl-llvm   std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
3432357e899Savl-llvm   while (ParentIdx) {
3442357e899Savl-llvm     const DWARFDebugInfoEntry *ParentEntry =
3452357e899Savl-llvm         Entry.CU->getDebugInfoEntry(*ParentIdx);
3462357e899Savl-llvm     CompileUnit::DIEInfo &ParentInfo = Entry.CU->getDIEInfo(*ParentIdx);
3472357e899Savl-llvm 
3482357e899Savl-llvm     if (!AreTypeParentsDone && NeedKeepTypeChildren) {
3492357e899Savl-llvm       if (ParentInfo.getKeepTypeChildren())
3502357e899Savl-llvm         AreTypeParentsDone = true;
3512357e899Savl-llvm       else {
3522357e899Savl-llvm         bool AddToWorklist = !isAlreadyMarked(
3532357e899Savl-llvm             ParentInfo, CompileUnit::DieOutputPlacement::TypeTable);
3542357e899Savl-llvm         ParentInfo.setKeepTypeChildren();
3552357e899Savl-llvm         if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
3562357e899Savl-llvm           addActionToRootEntriesWorkList(
3572357e899Savl-llvm               LiveRootWorklistActionTy::MarkTypeChildrenRec,
3582357e899Savl-llvm               UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
3592357e899Savl-llvm         }
3602357e899Savl-llvm       }
3612357e899Savl-llvm     }
3622357e899Savl-llvm 
3632357e899Savl-llvm     if (!ArePlainParentsDone && NeedKeepPlainChildren) {
3642357e899Savl-llvm       if (ParentInfo.getKeepPlainChildren())
3652357e899Savl-llvm         ArePlainParentsDone = true;
3662357e899Savl-llvm       else {
3672357e899Savl-llvm         bool AddToWorklist = !isAlreadyMarked(
3682357e899Savl-llvm             ParentInfo, CompileUnit::DieOutputPlacement::PlainDwarf);
3692357e899Savl-llvm         ParentInfo.setKeepPlainChildren();
3702357e899Savl-llvm         if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
3712357e899Savl-llvm           addActionToRootEntriesWorkList(
3722357e899Savl-llvm               LiveRootWorklistActionTy::MarkLiveChildrenRec,
3732357e899Savl-llvm               UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
3742357e899Savl-llvm         }
3752357e899Savl-llvm       }
3762357e899Savl-llvm     }
3772357e899Savl-llvm 
3782357e899Savl-llvm     if (AreTypeParentsDone && ArePlainParentsDone)
3792357e899Savl-llvm       break;
3802357e899Savl-llvm 
3812357e899Savl-llvm     ParentIdx = ParentEntry->getParentIdx();
3822357e899Savl-llvm   }
3832357e899Savl-llvm }
3842357e899Savl-llvm 
3852357e899Savl-llvm // This function tries to set specified \p Placement for the \p Entry.
3862357e899Savl-llvm // Depending on the concrete entry, the placement could be:
3872357e899Savl-llvm //  a) changed to another.
3882357e899Savl-llvm //  b) joined with current entry placement.
3892357e899Savl-llvm //  c) set as requested.
3902357e899Savl-llvm static CompileUnit::DieOutputPlacement
getFinalPlacementForEntry(const UnitEntryPairTy & Entry,CompileUnit::DieOutputPlacement Placement)3912357e899Savl-llvm getFinalPlacementForEntry(const UnitEntryPairTy &Entry,
3922357e899Savl-llvm                           CompileUnit::DieOutputPlacement Placement) {
3932357e899Savl-llvm   assert((Placement != CompileUnit::NotSet) && "Placement is not set");
3942357e899Savl-llvm   CompileUnit::DIEInfo &EntryInfo = Entry.CU->getDIEInfo(Entry.DieEntry);
3952357e899Savl-llvm 
3962357e899Savl-llvm   if (!EntryInfo.getODRAvailable())
3972357e899Savl-llvm     return CompileUnit::PlainDwarf;
3982357e899Savl-llvm 
3992357e899Savl-llvm   if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
4002357e899Savl-llvm     // Do not put variable into the "TypeTable" and "PlainDwarf" at the same
4012357e899Savl-llvm     // time.
4022357e899Savl-llvm     if (EntryInfo.getPlacement() == CompileUnit::PlainDwarf ||
4032357e899Savl-llvm         EntryInfo.getPlacement() == CompileUnit::Both)
4042357e899Savl-llvm       return CompileUnit::PlainDwarf;
4052357e899Savl-llvm 
4062357e899Savl-llvm     if (Placement == CompileUnit::PlainDwarf || Placement == CompileUnit::Both)
4072357e899Savl-llvm       return CompileUnit::PlainDwarf;
4082357e899Savl-llvm   }
4092357e899Savl-llvm 
4102357e899Savl-llvm   switch (EntryInfo.getPlacement()) {
4112357e899Savl-llvm   case CompileUnit::NotSet:
4122357e899Savl-llvm     return Placement;
4132357e899Savl-llvm 
4142357e899Savl-llvm   case CompileUnit::TypeTable:
4152357e899Savl-llvm     return Placement == CompileUnit::PlainDwarf ? CompileUnit::Both : Placement;
4162357e899Savl-llvm 
4172357e899Savl-llvm   case CompileUnit::PlainDwarf:
4182357e899Savl-llvm     return Placement == CompileUnit::TypeTable ? CompileUnit::Both : Placement;
4192357e899Savl-llvm 
4202357e899Savl-llvm   case CompileUnit::Both:
4212357e899Savl-llvm     return CompileUnit::Both;
4222357e899Savl-llvm   };
4232357e899Savl-llvm 
4242357e899Savl-llvm   llvm_unreachable("Unknown placement type.");
4252357e899Savl-llvm   return Placement;
4262357e899Savl-llvm }
4272357e899Savl-llvm 
markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action,const UnitEntryPairTy & RootEntry,const UnitEntryPairTy & Entry,bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)4282357e899Savl-llvm bool DependencyTracker::markDIEEntryAsKeptRec(
4292357e899Savl-llvm     LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
4302357e899Savl-llvm     const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
4312357e899Savl-llvm     std::atomic<bool> &HasNewInterconnectedCUs) {
4322357e899Savl-llvm   if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
4332357e899Savl-llvm     return true;
4342357e899Savl-llvm 
4352357e899Savl-llvm   CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
4362357e899Savl-llvm 
4372357e899Savl-llvm   // Calculate final placement placement.
4382357e899Savl-llvm   CompileUnit::DieOutputPlacement Placement = getFinalPlacementForEntry(
4392357e899Savl-llvm       Entry,
4402357e899Savl-llvm       isLiveAction(Action) ? CompileUnit::PlainDwarf : CompileUnit::TypeTable);
4412357e899Savl-llvm   assert((Info.getODRAvailable() || isLiveAction(Action) ||
4422357e899Savl-llvm           Placement == CompileUnit::PlainDwarf) &&
4432357e899Savl-llvm          "Wrong kind of placement for ODR unavailable entry");
4442357e899Savl-llvm 
4452357e899Savl-llvm   if (!isChildrenAction(Action))
4462357e899Savl-llvm     if (isAlreadyMarked(Entry, Placement))
4472357e899Savl-llvm       return true;
4482357e899Savl-llvm 
4492357e899Savl-llvm   // Mark current DIE as kept.
4502357e899Savl-llvm   Info.setKeep();
4512357e899Savl-llvm   Info.setPlacement(Placement);
4522357e899Savl-llvm 
4532357e899Savl-llvm   // Set keep children property for parents.
4542357e899Savl-llvm   markParentsAsKeepingChildren(Entry);
4552357e899Savl-llvm 
4562357e899Savl-llvm   UnitEntryPairTy FinalRootEntry =
4572357e899Savl-llvm       Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
4582357e899Savl-llvm 
4592357e899Savl-llvm   // Analyse referenced DIEs.
4602357e899Savl-llvm   bool Res = true;
4612357e899Savl-llvm   if (!maybeAddReferencedRoots(Action, FinalRootEntry, Entry,
4622357e899Savl-llvm                                InterCUProcessingStarted,
4632357e899Savl-llvm                                HasNewInterconnectedCUs))
4642357e899Savl-llvm     Res = false;
4652357e899Savl-llvm 
4662357e899Savl-llvm   // Return if we do not need to process children.
4672357e899Savl-llvm   if (isSingleAction(Action))
4682357e899Savl-llvm     return Res;
4692357e899Savl-llvm 
4702357e899Savl-llvm   // Process children.
4712357e899Savl-llvm   // Check for subprograms special case.
4722357e899Savl-llvm   if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
4732357e899Savl-llvm       Info.getODRAvailable()) {
4742357e899Savl-llvm     // Subprograms is a special case. As it can be root for type DIEs
4752357e899Savl-llvm     // and itself may be subject to move into the artificial type unit.
4762357e899Savl-llvm     //  a) Non removable children(like DW_TAG_formal_parameter) should always
4772357e899Savl-llvm     //     be cloned. They are placed into the "PlainDwarf" and into the
4782357e899Savl-llvm     //     "TypeTable".
4792357e899Savl-llvm     //  b) ODR deduplication candidates(type DIEs) children should not be put
4802357e899Savl-llvm     //  into the "PlainDwarf".
4812357e899Savl-llvm     //  c) Children keeping addresses and locations(like DW_TAG_call_site)
4822357e899Savl-llvm     //  should not be put into the "TypeTable".
4832357e899Savl-llvm     for (const DWARFDebugInfoEntry *CurChild =
4842357e899Savl-llvm              Entry.CU->getFirstChildEntry(Entry.DieEntry);
4852357e899Savl-llvm          CurChild && CurChild->getAbbreviationDeclarationPtr();
4862357e899Savl-llvm          CurChild = Entry.CU->getSiblingEntry(CurChild)) {
4872357e899Savl-llvm       CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
4882357e899Savl-llvm 
4892357e899Savl-llvm       switch (CurChild->getTag()) {
4902357e899Savl-llvm       case dwarf::DW_TAG_variable:
4912357e899Savl-llvm       case dwarf::DW_TAG_constant:
4922357e899Savl-llvm       case dwarf::DW_TAG_subprogram:
4932357e899Savl-llvm       case dwarf::DW_TAG_label: {
4942357e899Savl-llvm         if (ChildInfo.getHasAnAddress())
4952357e899Savl-llvm           continue;
4962357e899Savl-llvm       } break;
4972357e899Savl-llvm 
4982357e899Savl-llvm       // Entries having following tags could not be removed from the subprogram.
4992357e899Savl-llvm       case dwarf::DW_TAG_lexical_block:
5002357e899Savl-llvm       case dwarf::DW_TAG_friend:
5012357e899Savl-llvm       case dwarf::DW_TAG_inheritance:
5022357e899Savl-llvm       case dwarf::DW_TAG_formal_parameter:
5032357e899Savl-llvm       case dwarf::DW_TAG_unspecified_parameters:
5042357e899Savl-llvm       case dwarf::DW_TAG_template_type_parameter:
5052357e899Savl-llvm       case dwarf::DW_TAG_template_value_parameter:
5062357e899Savl-llvm       case dwarf::DW_TAG_GNU_template_parameter_pack:
5072357e899Savl-llvm       case dwarf::DW_TAG_GNU_formal_parameter_pack:
5082357e899Savl-llvm       case dwarf::DW_TAG_GNU_template_template_param:
5092357e899Savl-llvm       case dwarf::DW_TAG_thrown_type: {
5102357e899Savl-llvm         // Go to the default child handling.
5112357e899Savl-llvm       } break;
5122357e899Savl-llvm 
5132357e899Savl-llvm       default: {
5142357e899Savl-llvm         bool ChildIsTypeTableCandidate = isTypeTableCandidate(CurChild);
5152357e899Savl-llvm 
5162357e899Savl-llvm         // Skip child marked to be copied into the artificial type unit.
5172357e899Savl-llvm         if (isLiveAction(Action) && ChildIsTypeTableCandidate)
5182357e899Savl-llvm           continue;
5192357e899Savl-llvm 
5202357e899Savl-llvm         // Skip child marked to be copied into the plain unit.
5212357e899Savl-llvm         if (isTypeAction(Action) && !ChildIsTypeTableCandidate)
5222357e899Savl-llvm           continue;
5232357e899Savl-llvm 
5242357e899Savl-llvm         // Go to the default child handling.
5252357e899Savl-llvm       } break;
5262357e899Savl-llvm       }
5272357e899Savl-llvm 
5282357e899Savl-llvm       if (!markDIEEntryAsKeptRec(
5292357e899Savl-llvm               Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
5302357e899Savl-llvm               InterCUProcessingStarted, HasNewInterconnectedCUs))
5312357e899Savl-llvm         Res = false;
5322357e899Savl-llvm     }
5332357e899Savl-llvm 
5342357e899Savl-llvm     return Res;
5352357e899Savl-llvm   }
5362357e899Savl-llvm 
5372357e899Savl-llvm   // Recursively process children.
5382357e899Savl-llvm   for (const DWARFDebugInfoEntry *CurChild =
5392357e899Savl-llvm            Entry.CU->getFirstChildEntry(Entry.DieEntry);
5402357e899Savl-llvm        CurChild && CurChild->getAbbreviationDeclarationPtr();
5412357e899Savl-llvm        CurChild = Entry.CU->getSiblingEntry(CurChild)) {
5422357e899Savl-llvm     CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
5432357e899Savl-llvm     switch (CurChild->getTag()) {
5442357e899Savl-llvm     case dwarf::DW_TAG_variable:
5452357e899Savl-llvm     case dwarf::DW_TAG_constant:
5462357e899Savl-llvm     case dwarf::DW_TAG_subprogram:
5472357e899Savl-llvm     case dwarf::DW_TAG_label: {
5482357e899Savl-llvm       if (ChildInfo.getHasAnAddress())
5492357e899Savl-llvm         continue;
5502357e899Savl-llvm     } break;
5512357e899Savl-llvm     default:
5522357e899Savl-llvm       break; // Nothing to do.
5532357e899Savl-llvm     };
5542357e899Savl-llvm 
5552357e899Savl-llvm     if (!markDIEEntryAsKeptRec(
5562357e899Savl-llvm             Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
5572357e899Savl-llvm             InterCUProcessingStarted, HasNewInterconnectedCUs))
5582357e899Savl-llvm       Res = false;
5592357e899Savl-llvm   }
5602357e899Savl-llvm 
5612357e899Savl-llvm   return Res;
5622357e899Savl-llvm }
5632357e899Savl-llvm 
isTypeTableCandidate(const DWARFDebugInfoEntry * DIEEntry)5642357e899Savl-llvm bool DependencyTracker::isTypeTableCandidate(
5652357e899Savl-llvm     const DWARFDebugInfoEntry *DIEEntry) {
5662357e899Savl-llvm   switch (DIEEntry->getTag()) {
5672357e899Savl-llvm   default:
5682357e899Savl-llvm     return false;
5692357e899Savl-llvm 
5702357e899Savl-llvm   case dwarf::DW_TAG_imported_module:
5712357e899Savl-llvm   case dwarf::DW_TAG_imported_declaration:
5722357e899Savl-llvm   case dwarf::DW_TAG_imported_unit:
5732357e899Savl-llvm   case dwarf::DW_TAG_array_type:
5742357e899Savl-llvm   case dwarf::DW_TAG_class_type:
5752357e899Savl-llvm   case dwarf::DW_TAG_enumeration_type:
5762357e899Savl-llvm   case dwarf::DW_TAG_pointer_type:
5772357e899Savl-llvm   case dwarf::DW_TAG_reference_type:
5782357e899Savl-llvm   case dwarf::DW_TAG_string_type:
5792357e899Savl-llvm   case dwarf::DW_TAG_structure_type:
5802357e899Savl-llvm   case dwarf::DW_TAG_subroutine_type:
5812357e899Savl-llvm   case dwarf::DW_TAG_typedef:
5822357e899Savl-llvm   case dwarf::DW_TAG_union_type:
5832357e899Savl-llvm   case dwarf::DW_TAG_variant:
5842357e899Savl-llvm   case dwarf::DW_TAG_module:
5852357e899Savl-llvm   case dwarf::DW_TAG_ptr_to_member_type:
5862357e899Savl-llvm   case dwarf::DW_TAG_set_type:
5872357e899Savl-llvm   case dwarf::DW_TAG_subrange_type:
5882357e899Savl-llvm   case dwarf::DW_TAG_base_type:
5892357e899Savl-llvm   case dwarf::DW_TAG_const_type:
5902357e899Savl-llvm   case dwarf::DW_TAG_enumerator:
5912357e899Savl-llvm   case dwarf::DW_TAG_file_type:
5922357e899Savl-llvm   case dwarf::DW_TAG_packed_type:
5932357e899Savl-llvm   case dwarf::DW_TAG_thrown_type:
5942357e899Savl-llvm   case dwarf::DW_TAG_volatile_type:
5952357e899Savl-llvm   case dwarf::DW_TAG_dwarf_procedure:
5962357e899Savl-llvm   case dwarf::DW_TAG_restrict_type:
5972357e899Savl-llvm   case dwarf::DW_TAG_interface_type:
5982357e899Savl-llvm   case dwarf::DW_TAG_namespace:
5992357e899Savl-llvm   case dwarf::DW_TAG_unspecified_type:
6002357e899Savl-llvm   case dwarf::DW_TAG_shared_type:
6012357e899Savl-llvm   case dwarf::DW_TAG_rvalue_reference_type:
6022357e899Savl-llvm   case dwarf::DW_TAG_coarray_type:
6032357e899Savl-llvm   case dwarf::DW_TAG_dynamic_type:
6042357e899Savl-llvm   case dwarf::DW_TAG_atomic_type:
6052357e899Savl-llvm   case dwarf::DW_TAG_immutable_type:
6062357e899Savl-llvm   case dwarf::DW_TAG_function_template:
6072357e899Savl-llvm   case dwarf::DW_TAG_class_template:
6082357e899Savl-llvm     return true;
6092357e899Savl-llvm   }
6102357e899Savl-llvm }
6112357e899Savl-llvm 
maybeAddReferencedRoots(LiveRootWorklistActionTy Action,const UnitEntryPairTy & RootEntry,const UnitEntryPairTy & Entry,bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)6122357e899Savl-llvm bool DependencyTracker::maybeAddReferencedRoots(
6132357e899Savl-llvm     LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
6142357e899Savl-llvm     const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
6152357e899Savl-llvm     std::atomic<bool> &HasNewInterconnectedCUs) {
6162357e899Savl-llvm   const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
6172357e899Savl-llvm   if (Abbrev == nullptr)
6182357e899Savl-llvm     return true;
6192357e899Savl-llvm 
6202357e899Savl-llvm   DWARFUnit &Unit = Entry.CU->getOrigUnit();
6212357e899Savl-llvm   DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
6222357e899Savl-llvm   uint64_t Offset =
6232357e899Savl-llvm       Entry.DieEntry->getOffset() + getULEB128Size(Abbrev->getCode());
6242357e899Savl-llvm 
6252357e899Savl-llvm   // For each DIE attribute...
6262357e899Savl-llvm   for (const auto &AttrSpec : Abbrev->attributes()) {
6272357e899Savl-llvm     DWARFFormValue Val(AttrSpec.Form);
6282357e899Savl-llvm     if (!Val.isFormClass(DWARFFormValue::FC_Reference) ||
6292357e899Savl-llvm         AttrSpec.Attr == dwarf::DW_AT_sibling) {
6302357e899Savl-llvm       DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
6312357e899Savl-llvm                                 Unit.getFormParams());
6322357e899Savl-llvm       continue;
6332357e899Savl-llvm     }
6342357e899Savl-llvm     Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
6352357e899Savl-llvm 
6362357e899Savl-llvm     // Resolve reference.
6372357e899Savl-llvm     std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
6382357e899Savl-llvm         Val, InterCUProcessingStarted
6392357e899Savl-llvm                  ? ResolveInterCUReferencesMode::Resolve
6402357e899Savl-llvm                  : ResolveInterCUReferencesMode::AvoidResolving);
6412357e899Savl-llvm     if (!RefDie) {
6422357e899Savl-llvm       Entry.CU->warn("cann't find referenced DIE", Entry.DieEntry);
6432357e899Savl-llvm       continue;
6442357e899Savl-llvm     }
6452357e899Savl-llvm 
6462357e899Savl-llvm     if (!RefDie->DieEntry) {
6472357e899Savl-llvm       // Delay resolving reference.
6482357e899Savl-llvm       RefDie->CU->setInterconnectedCU();
6492357e899Savl-llvm       Entry.CU->setInterconnectedCU();
6502357e899Savl-llvm       HasNewInterconnectedCUs = true;
6512357e899Savl-llvm       return false;
6522357e899Savl-llvm     }
6532357e899Savl-llvm 
6542357e899Savl-llvm     assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
6552357e899Savl-llvm             InterCUProcessingStarted) &&
6562357e899Savl-llvm            "Inter-CU reference while inter-CU processing is not started");
6572357e899Savl-llvm 
6582357e899Savl-llvm     CompileUnit::DIEInfo &RefInfo = RefDie->CU->getDIEInfo(RefDie->DieEntry);
6592357e899Savl-llvm     if (!RefInfo.getODRAvailable())
6602357e899Savl-llvm       Action = LiveRootWorklistActionTy::MarkLiveEntryRec;
6612357e899Savl-llvm     else if (RefInfo.getODRAvailable() &&
6622357e899Savl-llvm              llvm::is_contained(getODRAttributes(), AttrSpec.Attr))
6632357e899Savl-llvm       // Note: getODRAttributes does not include DW_AT_containing_type.
6642357e899Savl-llvm       // It should be OK as we do getRootForSpecifiedEntry(). So any containing
6652357e899Savl-llvm       // type would be found as the root for the entry.
6662357e899Savl-llvm       Action = LiveRootWorklistActionTy::MarkTypeEntryRec;
6672357e899Savl-llvm     else if (isLiveAction(Action))
6682357e899Savl-llvm       Action = LiveRootWorklistActionTy::MarkLiveEntryRec;
6692357e899Savl-llvm     else
6702357e899Savl-llvm       Action = LiveRootWorklistActionTy::MarkTypeEntryRec;
6712357e899Savl-llvm 
6722357e899Savl-llvm     if (AttrSpec.Attr == dwarf::DW_AT_import) {
6732357e899Savl-llvm       if (isNamespaceLikeEntry(RefDie->DieEntry)) {
6742357e899Savl-llvm         addActionToRootEntriesWorkList(
6752357e899Savl-llvm             isTypeAction(Action)
6762357e899Savl-llvm                 ? LiveRootWorklistActionTy::MarkSingleTypeEntry
6772357e899Savl-llvm                 : LiveRootWorklistActionTy::MarkSingleLiveEntry,
6782357e899Savl-llvm             *RefDie, RootEntry);
6792357e899Savl-llvm         continue;
6802357e899Savl-llvm       }
6812357e899Savl-llvm 
6822357e899Savl-llvm       addActionToRootEntriesWorkList(Action, *RefDie, RootEntry);
6832357e899Savl-llvm       continue;
6842357e899Savl-llvm     }
6852357e899Savl-llvm 
6862357e899Savl-llvm     UnitEntryPairTy RootForReferencedDie = getRootForSpecifiedEntry(*RefDie);
6872357e899Savl-llvm     addActionToRootEntriesWorkList(Action, RootForReferencedDie, RootEntry);
6882357e899Savl-llvm   }
6892357e899Savl-llvm 
6902357e899Savl-llvm   return true;
6912357e899Savl-llvm }
6922357e899Savl-llvm 
6932357e899Savl-llvm UnitEntryPairTy
getRootForSpecifiedEntry(UnitEntryPairTy Entry)6942357e899Savl-llvm DependencyTracker::getRootForSpecifiedEntry(UnitEntryPairTy Entry) {
6952357e899Savl-llvm   UnitEntryPairTy Result = Entry;
6962357e899Savl-llvm 
6972357e899Savl-llvm   do {
6982357e899Savl-llvm     switch (Entry.DieEntry->getTag()) {
6992357e899Savl-llvm     case dwarf::DW_TAG_subprogram:
7002357e899Savl-llvm     case dwarf::DW_TAG_label:
7012357e899Savl-llvm     case dwarf::DW_TAG_variable:
7022357e899Savl-llvm     case dwarf::DW_TAG_constant: {
7032357e899Savl-llvm       return Result;
7042357e899Savl-llvm     } break;
7052357e899Savl-llvm 
7062357e899Savl-llvm     default: {
7072357e899Savl-llvm       // Nothing to do.
7082357e899Savl-llvm     }
7092357e899Savl-llvm     }
7102357e899Savl-llvm 
7112357e899Savl-llvm     std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
7122357e899Savl-llvm     if (!ParentIdx)
7132357e899Savl-llvm       return Result;
7142357e899Savl-llvm 
7152357e899Savl-llvm     const DWARFDebugInfoEntry *ParentEntry =
7162357e899Savl-llvm         Result.CU->getDebugInfoEntry(*ParentIdx);
7172357e899Savl-llvm     if (isNamespaceLikeEntry(ParentEntry))
7182357e899Savl-llvm       break;
7192357e899Savl-llvm     Result.DieEntry = ParentEntry;
7202357e899Savl-llvm   } while (true);
7212357e899Savl-llvm 
7222357e899Savl-llvm   return Result;
7232357e899Savl-llvm }
7242357e899Savl-llvm 
isLiveVariableEntry(const UnitEntryPairTy & Entry,bool IsLiveParent)7252357e899Savl-llvm bool DependencyTracker::isLiveVariableEntry(const UnitEntryPairTy &Entry,
7262357e899Savl-llvm                                             bool IsLiveParent) {
7272357e899Savl-llvm   DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
7282357e899Savl-llvm   CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(DIE);
7292357e899Savl-llvm 
7302357e899Savl-llvm   if (Info.getTrackLiveness()) {
7312357e899Savl-llvm     const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
7322357e899Savl-llvm 
7332357e899Savl-llvm     if (!Info.getIsInFunctionScope() &&
7342357e899Savl-llvm         Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
7352357e899Savl-llvm       // Global variables with constant value can always be kept.
7362357e899Savl-llvm     } else {
7372357e899Savl-llvm       // See if there is a relocation to a valid debug map entry inside this
7382357e899Savl-llvm       // variable's location. The order is important here. We want to always
7392357e899Savl-llvm       // check if the variable has a location expression address. However, we
7402357e899Savl-llvm       // don't want a static variable in a function to force us to keep the
7412357e899Savl-llvm       // enclosing function, unless requested explicitly.
7422357e899Savl-llvm       std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
7432357e899Savl-llvm           Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
744*0ed81942SAlexey Lapshin               DIE, Entry.CU->getGlobalData().getOptions().Verbose);
7452357e899Savl-llvm 
7462357e899Savl-llvm       if (LocExprAddrAndRelocAdjustment.first)
7472357e899Savl-llvm         Info.setHasAnAddress();
7482357e899Savl-llvm 
7492357e899Savl-llvm       if (!LocExprAddrAndRelocAdjustment.second)
7502357e899Savl-llvm         return false;
7512357e899Savl-llvm 
7522357e899Savl-llvm       if (!IsLiveParent && Info.getIsInFunctionScope() &&
7532357e899Savl-llvm           !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
7542357e899Savl-llvm         return false;
7552357e899Savl-llvm     }
7562357e899Savl-llvm   }
7572357e899Savl-llvm   Info.setHasAnAddress();
7582357e899Savl-llvm 
7592357e899Savl-llvm   if (Entry.CU->getGlobalData().getOptions().Verbose) {
7602357e899Savl-llvm     outs() << "Keeping variable DIE:";
7612357e899Savl-llvm     DIDumpOptions DumpOpts;
7622357e899Savl-llvm     DumpOpts.ChildRecurseDepth = 0;
7632357e899Savl-llvm     DumpOpts.Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
7642357e899Savl-llvm     DIE.dump(outs(), 8 /* Indent */, DumpOpts);
7652357e899Savl-llvm   }
7662357e899Savl-llvm 
7672357e899Savl-llvm   return true;
7682357e899Savl-llvm }
7692357e899Savl-llvm 
isLiveSubprogramEntry(const UnitEntryPairTy & Entry)7702357e899Savl-llvm bool DependencyTracker::isLiveSubprogramEntry(const UnitEntryPairTy &Entry) {
7712357e899Savl-llvm   DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
7722357e899Savl-llvm   CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
7732357e899Savl-llvm   std::optional<DWARFFormValue> LowPCVal = DIE.find(dwarf::DW_AT_low_pc);
7742357e899Savl-llvm 
7752357e899Savl-llvm   std::optional<uint64_t> LowPc;
7762357e899Savl-llvm   std::optional<uint64_t> HighPc;
7772357e899Savl-llvm   std::optional<int64_t> RelocAdjustment;
7782357e899Savl-llvm   if (Info.getTrackLiveness()) {
7792357e899Savl-llvm     LowPc = dwarf::toAddress(LowPCVal);
7802357e899Savl-llvm     if (!LowPc)
7812357e899Savl-llvm       return false;
7822357e899Savl-llvm 
7832357e899Savl-llvm     Info.setHasAnAddress();
7842357e899Savl-llvm 
7852357e899Savl-llvm     RelocAdjustment =
7862357e899Savl-llvm         Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
787*0ed81942SAlexey Lapshin             DIE, Entry.CU->getGlobalData().getOptions().Verbose);
7882357e899Savl-llvm     if (!RelocAdjustment)
7892357e899Savl-llvm       return false;
7902357e899Savl-llvm 
7912357e899Savl-llvm     if (DIE.getTag() == dwarf::DW_TAG_subprogram) {
7922357e899Savl-llvm       // Validate subprogram address range.
7932357e899Savl-llvm 
7942357e899Savl-llvm       HighPc = DIE.getHighPC(*LowPc);
7952357e899Savl-llvm       if (!HighPc) {
7962357e899Savl-llvm         Entry.CU->warn("function without high_pc. Range will be discarded.",
7972357e899Savl-llvm                        &DIE);
7982357e899Savl-llvm         return false;
7992357e899Savl-llvm       }
8002357e899Savl-llvm 
8012357e899Savl-llvm       if (*LowPc > *HighPc) {
8022357e899Savl-llvm         Entry.CU->warn("low_pc greater than high_pc. Range will be discarded.",
8032357e899Savl-llvm                        &DIE);
8042357e899Savl-llvm         return false;
8052357e899Savl-llvm       }
8062357e899Savl-llvm     } else if (DIE.getTag() == dwarf::DW_TAG_label) {
8072357e899Savl-llvm       if (Entry.CU->hasLabelAt(*LowPc))
8082357e899Savl-llvm         return false;
8092357e899Savl-llvm 
8102357e899Savl-llvm       // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider
8112357e899Savl-llvm       // labels that don't fall into the CU's aranges. This is wrong IMO. Debug
8122357e899Savl-llvm       // info generation bugs aside, this is really wrong in the case of labels,
8132357e899Savl-llvm       // where a label marking the end of a function will have a PC == CU's
8142357e899Savl-llvm       // high_pc.
8152357e899Savl-llvm       if (dwarf::toAddress(Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_high_pc))
8162357e899Savl-llvm               .value_or(UINT64_MAX) <= LowPc)
8172357e899Savl-llvm         return false;
8182357e899Savl-llvm 
8192357e899Savl-llvm       Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
8202357e899Savl-llvm     }
8212357e899Savl-llvm   } else
8222357e899Savl-llvm     Info.setHasAnAddress();
8232357e899Savl-llvm 
8242357e899Savl-llvm   if (Entry.CU->getGlobalData().getOptions().Verbose) {
8252357e899Savl-llvm     outs() << "Keeping subprogram DIE:";
8262357e899Savl-llvm     DIDumpOptions DumpOpts;
8272357e899Savl-llvm     DumpOpts.ChildRecurseDepth = 0;
8282357e899Savl-llvm     DumpOpts.Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
8292357e899Savl-llvm     DIE.dump(outs(), 8 /* Indent */, DumpOpts);
8302357e899Savl-llvm   }
8312357e899Savl-llvm 
8322357e899Savl-llvm   if (!Info.getTrackLiveness() || DIE.getTag() == dwarf::DW_TAG_label)
8332357e899Savl-llvm     return true;
8342357e899Savl-llvm 
8352357e899Savl-llvm   Entry.CU->addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
8362357e899Savl-llvm   return true;
8372357e899Savl-llvm }
838