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