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