Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DependencyTracker.h
35292 views
//===- "DependencyTracker.h" ------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H9#define LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H1011#include "DWARFLinkerCompileUnit.h"12#include "llvm/ADT/PointerIntPair.h"13#include "llvm/ADT/SmallVector.h"1415namespace llvm {16class DWARFDebugInfoEntry;17class DWARFDie;1819namespace dwarf_linker {20namespace parallel {2122/// This class discovers DIEs dependencies: marks "live" DIEs, marks DIE23/// locations (whether DIE should be cloned as regular DIE or it should be put24/// into the artificial type unit).25class DependencyTracker {26public:27DependencyTracker(CompileUnit &CU) : CU(CU) {}2829/// Recursively walk the \p DIE tree and look for DIEs to keep. Store that30/// information in \p CU's DIEInfo.31///32/// This function is the entry point of the DIE selection algorithm. It is33/// expected to walk the DIE tree and(through the mediation of34/// Context.File.Addresses) ask for relocation adjustment value on each35/// DIE that might be a 'root DIE'(f.e. subprograms, variables).36///37/// Returns true if all dependencies are correctly discovered. Inter-CU38/// dependencies cannot be discovered if referenced CU is not analyzed yet.39/// If that is the case this method returns false.40bool resolveDependenciesAndMarkLiveness(41bool InterCUProcessingStarted,42std::atomic<bool> &HasNewInterconnectedCUs);4344/// Check if dependencies have incompatible placement.45/// If that is the case modify placement to be compatible.46/// \returns true if any placement was updated, otherwise returns false.47/// This method should be called as a followup processing after48/// resolveDependenciesAndMarkLiveness().49bool updateDependenciesCompleteness();5051/// Recursively walk the \p DIE tree and check "keepness" and "placement"52/// information. It is an error if parent node does not have "keep" flag,53/// while child has one. It is an error if parent node has "TypeTable"54/// placement while child has "PlainDwarf" placement. This function dump error55/// at stderr in that case.56void verifyKeepChain();5758protected:59enum class LiveRootWorklistActionTy : uint8_t {60/// Mark current item as live entry.61MarkSingleLiveEntry = 0,6263/// Mark current item as type entry.64MarkSingleTypeEntry,6566/// Mark current item and all its children as live entry.67MarkLiveEntryRec,6869/// Mark current item and all its children as type entry.70MarkTypeEntryRec,7172/// Mark all children of current item as live entry.73MarkLiveChildrenRec,7475/// Mark all children of current item as type entry.76MarkTypeChildrenRec,77};7879/// \returns true if the specified action is for the "PlainDwarf".80bool isLiveAction(LiveRootWorklistActionTy Action) {81switch (Action) {82default:83return false;8485case LiveRootWorklistActionTy::MarkSingleLiveEntry:86case LiveRootWorklistActionTy::MarkLiveEntryRec:87case LiveRootWorklistActionTy::MarkLiveChildrenRec:88return true;89}90}9192/// \returns true if the specified action is for the "TypeTable".93bool isTypeAction(LiveRootWorklistActionTy Action) {94switch (Action) {95default:96return false;9798case LiveRootWorklistActionTy::MarkSingleTypeEntry:99case LiveRootWorklistActionTy::MarkTypeEntryRec:100case LiveRootWorklistActionTy::MarkTypeChildrenRec:101return true;102}103}104105/// \returns true if the specified action affects only Root entry106/// itself and does not affect it`s children.107bool isSingleAction(LiveRootWorklistActionTy Action) {108switch (Action) {109default:110return false;111112case LiveRootWorklistActionTy::MarkSingleLiveEntry:113case LiveRootWorklistActionTy::MarkSingleTypeEntry:114return true;115}116}117118/// \returns true if the specified action affects only Root entry119/// itself and does not affect it`s children.120bool isChildrenAction(LiveRootWorklistActionTy Action) {121switch (Action) {122default:123return false;124125case LiveRootWorklistActionTy::MarkLiveChildrenRec:126case LiveRootWorklistActionTy::MarkTypeChildrenRec:127return true;128}129}130131/// Class keeping live worklist item data.132class LiveRootWorklistItemTy {133public:134LiveRootWorklistItemTy() = default;135LiveRootWorklistItemTy(const LiveRootWorklistItemTy &) = default;136LiveRootWorklistItemTy(LiveRootWorklistActionTy Action,137UnitEntryPairTy RootEntry) {138RootCU.setInt(Action);139RootCU.setPointer(RootEntry.CU);140141RootDieEntry = RootEntry.DieEntry;142}143LiveRootWorklistItemTy(LiveRootWorklistActionTy Action,144UnitEntryPairTy RootEntry,145UnitEntryPairTy ReferencedBy) {146RootCU.setPointer(RootEntry.CU);147RootCU.setInt(Action);148RootDieEntry = RootEntry.DieEntry;149150ReferencedByCU = ReferencedBy.CU;151ReferencedByDieEntry = ReferencedBy.DieEntry;152}153154UnitEntryPairTy getRootEntry() const {155return UnitEntryPairTy{RootCU.getPointer(), RootDieEntry};156}157158CompileUnit::DieOutputPlacement getPlacement() const {159return static_cast<CompileUnit::DieOutputPlacement>(RootCU.getInt());160}161162bool hasReferencedByOtherEntry() const { return ReferencedByCU != nullptr; }163164UnitEntryPairTy getReferencedByEntry() const {165assert(ReferencedByCU);166assert(ReferencedByDieEntry);167return UnitEntryPairTy{ReferencedByCU, ReferencedByDieEntry};168}169170LiveRootWorklistActionTy getAction() const {171return static_cast<LiveRootWorklistActionTy>(RootCU.getInt());172}173174protected:175/// Root entry.176/// ASSUMPTION: 3 bits are used to store LiveRootWorklistActionTy value.177/// Thus LiveRootWorklistActionTy should have no more eight elements.178179/// Pointer traits for CompileUnit.180struct CompileUnitPointerTraits {181static inline void *getAsVoidPointer(CompileUnit *P) { return P; }182static inline CompileUnit *getFromVoidPointer(void *P) {183return (CompileUnit *)P;184}185static constexpr int NumLowBitsAvailable = 3;186static_assert(187alignof(CompileUnit) >= (1 << NumLowBitsAvailable),188"CompileUnit insufficiently aligned to have enough low bits.");189};190191PointerIntPair<CompileUnit *, 3, LiveRootWorklistActionTy,192CompileUnitPointerTraits>193RootCU;194const DWARFDebugInfoEntry *RootDieEntry = nullptr;195196/// Another root entry which references this RootDieEntry.197/// ReferencedByDieEntry is kept to update placement.198/// if RootDieEntry has placement incompatible with placement199/// of ReferencedByDieEntry then it should be updated.200CompileUnit *ReferencedByCU = nullptr;201const DWARFDebugInfoEntry *ReferencedByDieEntry = nullptr;202};203204using RootEntriesListTy = SmallVector<LiveRootWorklistItemTy>;205206/// This function navigates DIEs tree starting from specified \p Entry.207/// It puts found 'root DIE' into the worklist. The \p CollectLiveEntries208/// instructs to collect either live roots(like subprograms having live209/// DW_AT_low_pc) or otherwise roots which is not live(they need to be210/// collected if they are imported f.e. by DW_TAG_imported_module).211void collectRootsToKeep(const UnitEntryPairTy &Entry,212std::optional<UnitEntryPairTy> ReferencedBy,213bool IsLiveParent);214215/// Returns true if specified variable references live code section.216static bool isLiveVariableEntry(const UnitEntryPairTy &Entry,217bool IsLiveParent);218219/// Returns true if specified subprogram references live code section.220static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry);221222/// Examine worklist and mark all 'root DIE's as kept and set "Placement"223/// property.224bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted,225std::atomic<bool> &HasNewInterconnectedCUs);226227/// Mark whole DIE tree as kept recursively.228bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action,229const UnitEntryPairTy &RootEntry,230const UnitEntryPairTy &Entry,231bool InterCUProcessingStarted,232std::atomic<bool> &HasNewInterconnectedCUs);233234/// Mark parents as keeping children.235void markParentsAsKeepingChildren(const UnitEntryPairTy &Entry);236237/// Mark whole DIE tree as placed in "PlainDwarf".238void setPlainDwarfPlacementRec(const UnitEntryPairTy &Entry);239240/// Check referenced DIEs and add them into the worklist.241bool maybeAddReferencedRoots(LiveRootWorklistActionTy Action,242const UnitEntryPairTy &RootEntry,243const UnitEntryPairTy &Entry,244bool InterCUProcessingStarted,245std::atomic<bool> &HasNewInterconnectedCUs);246247/// \returns true if \p DIEEntry can possibly be put into the artificial type248/// unit.249bool isTypeTableCandidate(const DWARFDebugInfoEntry *DIEEntry);250251/// \returns root for the specified \p Entry.252UnitEntryPairTy getRootForSpecifiedEntry(UnitEntryPairTy Entry);253254/// Add action item to the work list.255void256addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action,257const UnitEntryPairTy &Entry,258std::optional<UnitEntryPairTy> ReferencedBy);259260CompileUnit &CU;261262/// List of entries which are 'root DIE's.263RootEntriesListTy RootEntriesWorkList;264265/// List of entries dependencies.266RootEntriesListTy Dependencies;267};268269} // end of namespace parallel270} // end of namespace dwarf_linker271} // end of namespace llvm272273#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H274275276