LLVM 24.0.0git
DependencyTracker.h
Go to the documentation of this file.
1//===- "DependencyTracker.h" ------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H
10#define LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H
11
15
16namespace llvm {
18class DWARFDie;
19
20namespace dwarf_linker {
21namespace parallel {
22
23/// This class discovers DIEs dependencies: marks "live" DIEs, marks DIE
24/// locations (whether DIE should be cloned as regular DIE or it should be put
25/// into the artificial type unit).
27public:
29
30 /// Recursively walk the \p DIE tree and look for DIEs to keep. Store that
31 /// information in \p CU's DIEInfo.
32 ///
33 /// This function is the entry point of the DIE selection algorithm. It is
34 /// expected to walk the DIE tree and(through the mediation of
35 /// Context.File.Addresses) ask for relocation adjustment value on each
36 /// DIE that might be a 'root DIE'(f.e. subprograms, variables).
37 ///
38 /// Returns true if all dependencies are correctly discovered. Inter-CU
39 /// dependencies cannot be discovered if referenced CU is not analyzed yet.
40 /// If that is the case this method returns false.
42 bool InterCUProcessingStarted,
43 std::atomic<bool> &HasNewInterconnectedCUs);
44
45 /// Check if dependencies have incompatible placement.
46 /// If that is the case modify placement to be compatible.
47 /// \returns true if any placement was updated, otherwise returns false.
48 /// This method should be called as a followup processing after
49 /// resolveDependenciesAndMarkLiveness().
51
52 /// Recursively walk the \p DIE tree and check "keepness" and "placement"
53 /// information. It is an error if parent node does not have "keep" flag,
54 /// while child has one. It is an error if parent node has "TypeTable"
55 /// placement while child has "PlainDwarf" placement. This function dump error
56 /// at stderr in that case.
57 void verifyKeepChain();
58
59protected:
61 /// Mark current item as live entry.
63
64 /// Mark current item as type entry.
66
67 /// Mark current item and all its children as live entry.
69
70 /// Mark current item and all its children as type entry.
72
73 /// Mark all children of current item as live entry.
75
76 /// Mark all children of current item as type entry.
78 };
79
80 /// \returns true if the specified action is for the "PlainDwarf".
82 switch (Action) {
83 default:
84 return false;
85
89 return true;
90 }
91 }
92
93 /// \returns true if the specified action is for the "TypeTable".
95 switch (Action) {
96 default:
97 return false;
98
102 return true;
103 }
104 }
105
106 /// \returns true if the specified action affects only Root entry
107 /// itself and does not affect it`s children.
108 bool isSingleAction(LiveRootWorklistActionTy Action) {
109 switch (Action) {
110 default:
111 return false;
112
115 return true;
116 }
117 }
118
119 /// \returns true if the specified action affects only Root entry
120 /// itself and does not affect it`s children.
122 switch (Action) {
123 default:
124 return false;
125
128 return true;
129 }
130 }
131
132 /// Class keeping live worklist item data.
134 public:
138 UnitEntryPairTy RootEntry) {
139 RootCU.setInt(Action);
140 RootCU.setPointer(RootEntry.CU);
141
142 RootDieEntry = RootEntry.DieEntry;
143 }
146 UnitEntryPairTy ReferencedBy,
148 RootCU.setPointer(RootEntry.CU);
149 RootCU.setInt(Action);
150 RootDieEntry = RootEntry.DieEntry;
151
152 ReferencedByCU = ReferencedBy.CU;
153 ReferencedByDieEntry = ReferencedBy.DieEntry;
154
156 }
157
159 return UnitEntryPairTy{RootCU.getPointer(), RootDieEntry};
160 }
161
163 return static_cast<CompileUnit::DieOutputPlacement>(RootCU.getInt());
164 }
165
166 bool hasReferencedByOtherEntry() const { return ReferencedByCU != nullptr; }
167
173
174 /// \returns the DIE actually referenced by ReferencedByDieEntry, whose
175 /// placement (rather than the enclosing RootDieEntry's) determines whether
176 /// ReferencedByDieEntry may remain in the type table. Null when the
177 /// referenced DIE is RootDieEntry itself, in which case RootDieEntry's
178 /// placement is used instead.
182
184 return static_cast<LiveRootWorklistActionTy>(RootCU.getInt());
185 }
186
187 protected:
188 /// Root entry.
189 /// ASSUMPTION: 3 bits are used to store LiveRootWorklistActionTy value.
190 /// Thus LiveRootWorklistActionTy should have no more eight elements.
191
192 /// Pointer traits for CompileUnit.
194 static inline void *getAsVoidPointer(CompileUnit *P) { return P; }
195 static inline CompileUnit *getFromVoidPointer(void *P) {
196 return (CompileUnit *)P;
197 }
198 static constexpr int NumLowBitsAvailable = 3;
199 static_assert(
200 alignof(CompileUnit) >= (1 << NumLowBitsAvailable),
201 "CompileUnit insufficiently aligned to have enough low bits.");
202 };
203
208
209 /// Another root entry which references this RootDieEntry.
210 /// ReferencedByDieEntry is kept to update placement.
211 /// if RootDieEntry has placement incompatible with placement
212 /// of ReferencedByDieEntry then it should be updated.
215
216 /// The DIE actually referenced by ReferencedByDieEntry. It lives in the
217 /// same CU as RootDieEntry, but its placement can differ: RootDieEntry is
218 /// the enclosing root that is marked as kept, whereas this DIE may be a
219 /// nested type demoted independently. That placement, not RootDieEntry's,
220 /// determines whether ReferencedByDieEntry may remain in the type table.
221 /// Null when RootDieEntry is the referenced DIE itself.
223 };
224
226
227 /// This function navigates DIEs tree starting from specified \p Entry.
228 /// It puts found 'root DIE' into the worklist. The \p CollectLiveEntries
229 /// instructs to collect either live roots(like subprograms having live
230 /// DW_AT_low_pc) or otherwise roots which is not live(they need to be
231 /// collected if they are imported f.e. by DW_TAG_imported_module).
232 void collectRootsToKeep(const UnitEntryPairTy &Entry,
233 std::optional<UnitEntryPairTy> ReferencedBy,
234 bool IsLiveParent);
235
236 /// Returns true if specified variable references live code section.
237 static bool isLiveVariableEntry(const UnitEntryPairTy &Entry,
238 bool IsLiveParent);
239
240 /// Returns true if specified subprogram references live code section.
241 static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry);
242
243 /// Examine worklist and mark all 'root DIE's as kept and set "Placement"
244 /// property.
245 bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted,
246 std::atomic<bool> &HasNewInterconnectedCUs);
247
248 /// Mark whole DIE tree as kept recursively. When \p RecordDepsOnly is set the
249 /// tree is not marked. Instead its completeness dependencies are recorded
250 /// (see maybeAddReferencedRoots). This is used to re-walk an already-marked
251 /// subtree so a racing referencing root still contributes its dependencies.
253 const UnitEntryPairTy &RootEntry,
254 const UnitEntryPairTy &Entry,
255 bool InterCUProcessingStarted,
256 std::atomic<bool> &HasNewInterconnectedCUs,
257 bool RecordDepsOnly = false);
258
259 /// Mark parents as keeping children.
261
262 /// Mark whole DIE tree as placed in "PlainDwarf".
264
265 /// Check referenced DIEs and add them into the worklist. When \p
266 /// RecordDepsOnly is set, the referenced roots are not scheduled for marking
267 /// (no new worklist items, hence no reference-following recursion). Instead
268 /// each completeness dependency is appended directly to \c Dependencies. This
269 /// is used when \p Entry was already marked by a racing CU/root: the marking
270 /// and subtree are handled elsewhere, but this referencing root's
271 /// dependencies must still be recorded so the completeness fixpoint sees a
272 /// complete, order-independent dependency set.
274 const UnitEntryPairTy &RootEntry,
275 const UnitEntryPairTy &Entry,
276 bool InterCUProcessingStarted,
277 std::atomic<bool> &HasNewInterconnectedCUs,
278 bool RecordDepsOnly = false);
279
280 /// \returns true if \p DIEEntry can possibly be put into the artificial type
281 /// unit.
283
284 /// \returns root for the specified \p Entry.
286
287 /// Add action item to the work list.
289 LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry,
290 std::optional<UnitEntryPairTy> ReferencedBy,
291 const DWARFDebugInfoEntry *ReferencedTypeDieEntry = nullptr);
292
294
295 /// List of entries which are 'root DIE's.
297
298 /// List of entries dependencies.
300};
301
302} // end of namespace parallel
303} // end of namespace dwarf_linker
304} // end of namespace llvm
305
306#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEPENDENCYTRACKER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define P(N)
This file defines the PointerIntPair class.
This file defines the SmallVector class.
A pointer to another debug information entry.
Definition DIE.h:325
DWARFDebugInfoEntry - A DIE with only the minimum required data.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
PointerIntPair - This class implements a pair of a pointer and small integer.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Stores all information related to a compile unit, be it in its original instance of the object file o...
DieOutputPlacement
Kinds of placement for the output die.
LiveRootWorklistItemTy(LiveRootWorklistActionTy Action, UnitEntryPairTy RootEntry, UnitEntryPairTy ReferencedBy, const DWARFDebugInfoEntry *ReferencedTypeDieEntry=nullptr)
LiveRootWorklistItemTy(LiveRootWorklistActionTy Action, UnitEntryPairTy RootEntry)
PointerIntPair< CompileUnit *, 3, LiveRootWorklistActionTy, CompileUnitPointerTraits > RootCU
const DWARFDebugInfoEntry * ReferencedTypeDieEntry
The DIE actually referenced by ReferencedByDieEntry.
CompileUnit * ReferencedByCU
Another root entry which references this RootDieEntry.
bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs, bool RecordDepsOnly=false)
Mark whole DIE tree as kept recursively.
void verifyKeepChain()
Recursively walk the DIE tree and check "keepness" and "placement" information.
RootEntriesListTy Dependencies
List of entries dependencies.
void markParentsAsKeepingChildren(const UnitEntryPairTy &Entry)
Mark parents as keeping children.
UnitEntryPairTy getRootForSpecifiedEntry(UnitEntryPairTy Entry)
bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Examine worklist and mark all 'root DIE's as kept and set "Placement" property.
bool isLiveAction(LiveRootWorklistActionTy Action)
bool isChildrenAction(LiveRootWorklistActionTy Action)
bool isTypeAction(LiveRootWorklistActionTy Action)
void addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy, const DWARFDebugInfoEntry *ReferencedTypeDieEntry=nullptr)
Add action item to the work list.
bool isTypeTableCandidate(const DWARFDebugInfoEntry *DIEEntry)
SmallVector< LiveRootWorklistItemTy > RootEntriesListTy
void setPlainDwarfPlacementRec(const UnitEntryPairTy &Entry)
Mark whole DIE tree as placed in "PlainDwarf".
RootEntriesListTy RootEntriesWorkList
List of entries which are 'root DIE's.
static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry)
Returns true if specified subprogram references live code section.
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Recursively walk the DIE tree and look for DIEs to keep.
static bool isLiveVariableEntry(const UnitEntryPairTy &Entry, bool IsLiveParent)
Returns true if specified variable references live code section.
@ MarkTypeEntryRec
Mark current item and all its children as type entry.
@ MarkLiveChildrenRec
Mark all children of current item as live entry.
@ MarkLiveEntryRec
Mark current item and all its children as live entry.
@ MarkTypeChildrenRec
Mark all children of current item as type entry.
bool maybeAddReferencedRoots(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs, bool RecordDepsOnly=false)
Check referenced DIEs and add them into the worklist.
void collectRootsToKeep(const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy, bool IsLiveParent)
This function navigates DIEs tree starting from specified Entry.
bool updateDependenciesCompleteness()
Check if dependencies have incompatible placement.
This is an optimization pass for GlobalISel generic memory operations.
This is a helper structure which keeps a debug info entry with it's containing compilation unit.