13namespace dwarflinker_parallel {
28#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
35 while (!Worklist.
empty()) {
51 CU.getDIEInfo(Child.getDebugInfoEntry());
55 if (!ParentPlainDieIsKept && ChildPlainDieIsKept)
57 "Found invalid link in keep chain");
59 if (Child.getTag() == dwarf::DW_TAG_subprogram) {
61 &
CU, Child.getDebugInfoEntry()))) {
63 "Live subprogram is not marked as kept");
67 if (!ChildInfo.getODRAvailable()) {
68 assert(!ChildTypeDieIsKept);
72 if (!ParentTypeDieIsKept && ChildTypeDieIsKept)
74 "Found invalid link in keep chain");
76 if (CurrentInfo.getIsInAnonNamespaceScope() &&
79 "Found invalid placement marking for member "
80 "of anonymous namespace");
85 if (!BrokenLinks.
empty()) {
87 errs() <<
"\n=================================\n";
89 Link.Parent.getOffset(),
90 Link.Child.getOffset());
92 errs() <<
"\nParent:";
93 Link.Parent.dump(
errs(), 0, {});
95 CU.getDIEInfo(Link.Parent).dump();
98 Link.Child.dump(
errs(), 2, {});
100 CU.getDIEInfo(Link.Child).dump();
108 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
115 std::nullopt,
false);
119 HasNewInterconnectedCUs);
124 std::optional<UnitEntryPairTy> ReferencedBy) {
134 const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
137 Entry.CU->getFirstChildEntry(Entry.DieEntry);
138 CurChild && CurChild->getAbbreviationDeclarationPtr();
139 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
143 bool IsLiveChild =
false;
145 switch (CurChild->getTag()) {
146 case dwarf::DW_TAG_label: {
151 if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
157 case dwarf::DW_TAG_subprogram: {
165 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
172 case dwarf::DW_TAG_constant:
173 case dwarf::DW_TAG_variable: {
182 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
189 case dwarf::DW_TAG_base_type: {
195 case dwarf::DW_TAG_imported_module:
196 case dwarf::DW_TAG_imported_declaration:
197 case dwarf::DW_TAG_imported_unit: {
199 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
210 case dwarf::DW_TAG_type_unit:
211 case dwarf::DW_TAG_partial_unit:
212 case dwarf::DW_TAG_compile_unit: {
225 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
234 HasNewInterconnectedCUs)) {
245 bool HasNewDependency =
false;
247 assert(Root.hasReferencedByOtherEntry() &&
248 "Root entry without dependency inside the dependencies list");
260 HasNewDependency =
true;
268 return HasNewDependency;
275 !
Info.getKeepTypeChildren())
279 Info.unsetKeepTypeChildren();
283 Entry.CU->getFirstChildEntry(Entry.DieEntry);
284 CurChild && CurChild->getAbbreviationDeclarationPtr();
285 CurChild = Entry.CU->getSiblingEntry(CurChild))
290 switch (Entry->getTag()) {
291 case dwarf::DW_TAG_compile_unit:
292 case dwarf::DW_TAG_module:
293 case dwarf::DW_TAG_namespace:
306 switch (NewPlacement) {
308 return Info.needToPlaceInTypeTable();
311 return Info.needToKeepInPlainDwarf();
314 return Info.needToPlaceInTypeTable() &&
Info.needToKeepInPlainDwarf();
325 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
330 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
334 bool NeedKeepTypeChildren =
Info.needToPlaceInTypeTable();
335 bool NeedKeepPlainChildren =
Info.needToKeepInPlainDwarf();
337 bool AreTypeParentsDone = !NeedKeepTypeChildren;
338 bool ArePlainParentsDone = !NeedKeepPlainChildren;
341 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
344 Entry.CU->getDebugInfoEntry(*ParentIdx);
347 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
348 if (ParentInfo.getKeepTypeChildren())
349 AreTypeParentsDone =
true;
353 ParentInfo.setKeepTypeChildren();
362 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
363 if (ParentInfo.getKeepPlainChildren())
364 ArePlainParentsDone =
true;
368 ParentInfo.setKeepPlainChildren();
377 if (AreTypeParentsDone && ArePlainParentsDone)
395 if (!EntryInfo.getODRAvailable())
398 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
430 std::atomic<bool> &HasNewInterconnectedCUs) {
431 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
442 "Wrong kind of placement for ODR unavailable entry");
456 Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
461 InterCUProcessingStarted,
462 HasNewInterconnectedCUs))
471 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
472 Info.getODRAvailable()) {
483 Entry.CU->getFirstChildEntry(Entry.DieEntry);
484 CurChild && CurChild->getAbbreviationDeclarationPtr();
485 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
488 switch (CurChild->getTag()) {
489 case dwarf::DW_TAG_variable:
490 case dwarf::DW_TAG_constant:
491 case dwarf::DW_TAG_subprogram:
492 case dwarf::DW_TAG_label: {
493 if (ChildInfo.getHasAnAddress())
498 case dwarf::DW_TAG_lexical_block:
499 case dwarf::DW_TAG_friend:
500 case dwarf::DW_TAG_inheritance:
501 case dwarf::DW_TAG_formal_parameter:
502 case dwarf::DW_TAG_unspecified_parameters:
503 case dwarf::DW_TAG_template_type_parameter:
504 case dwarf::DW_TAG_template_value_parameter:
505 case dwarf::DW_TAG_GNU_template_parameter_pack:
506 case dwarf::DW_TAG_GNU_formal_parameter_pack:
507 case dwarf::DW_TAG_GNU_template_template_param:
508 case dwarf::DW_TAG_thrown_type: {
529 InterCUProcessingStarted, HasNewInterconnectedCUs))
538 Entry.CU->getFirstChildEntry(Entry.DieEntry);
539 CurChild && CurChild->getAbbreviationDeclarationPtr();
540 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
542 switch (CurChild->getTag()) {
543 case dwarf::DW_TAG_variable:
544 case dwarf::DW_TAG_constant:
545 case dwarf::DW_TAG_subprogram:
546 case dwarf::DW_TAG_label: {
547 if (ChildInfo.getHasAnAddress())
556 InterCUProcessingStarted, HasNewInterconnectedCUs))
569 case dwarf::DW_TAG_imported_module:
570 case dwarf::DW_TAG_imported_declaration:
571 case dwarf::DW_TAG_imported_unit:
572 case dwarf::DW_TAG_array_type:
573 case dwarf::DW_TAG_class_type:
574 case dwarf::DW_TAG_enumeration_type:
575 case dwarf::DW_TAG_pointer_type:
576 case dwarf::DW_TAG_reference_type:
577 case dwarf::DW_TAG_string_type:
578 case dwarf::DW_TAG_structure_type:
579 case dwarf::DW_TAG_subroutine_type:
580 case dwarf::DW_TAG_typedef:
581 case dwarf::DW_TAG_union_type:
582 case dwarf::DW_TAG_variant:
583 case dwarf::DW_TAG_module:
584 case dwarf::DW_TAG_ptr_to_member_type:
585 case dwarf::DW_TAG_set_type:
586 case dwarf::DW_TAG_subrange_type:
587 case dwarf::DW_TAG_base_type:
588 case dwarf::DW_TAG_const_type:
589 case dwarf::DW_TAG_enumerator:
590 case dwarf::DW_TAG_file_type:
591 case dwarf::DW_TAG_packed_type:
592 case dwarf::DW_TAG_thrown_type:
593 case dwarf::DW_TAG_volatile_type:
594 case dwarf::DW_TAG_dwarf_procedure:
595 case dwarf::DW_TAG_restrict_type:
596 case dwarf::DW_TAG_interface_type:
597 case dwarf::DW_TAG_namespace:
598 case dwarf::DW_TAG_unspecified_type:
599 case dwarf::DW_TAG_shared_type:
600 case dwarf::DW_TAG_rvalue_reference_type:
601 case dwarf::DW_TAG_coarray_type:
602 case dwarf::DW_TAG_dynamic_type:
603 case dwarf::DW_TAG_atomic_type:
604 case dwarf::DW_TAG_immutable_type:
605 case dwarf::DW_TAG_function_template:
606 case dwarf::DW_TAG_class_template:
614 std::atomic<bool> &HasNewInterconnectedCUs) {
615 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
616 if (Abbrev ==
nullptr)
619 DWARFUnit &Unit = Entry.CU->getOrigUnit();
625 for (
const auto &AttrSpec : Abbrev->attributes()) {
628 AttrSpec.Attr == dwarf::DW_AT_sibling) {
630 Unit.getFormParams());
636 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
637 Val, InterCUProcessingStarted
641 Entry.CU->warn(
"cann't find referenced DIE", Entry.DieEntry);
645 if (!RefDie->DieEntry) {
647 RefDie->CU->setInterconnectedCU();
648 Entry.CU->setInterconnectedCU();
649 HasNewInterconnectedCUs =
true;
653 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
654 InterCUProcessingStarted) &&
655 "Inter-CU reference while inter-CU processing is not started");
658 if (!RefInfo.getODRAvailable())
660 else if (RefInfo.getODRAvailable() &&
671 if (AttrSpec.Attr == dwarf::DW_AT_import) {
697 switch (Entry.DieEntry->getTag()) {
698 case dwarf::DW_TAG_subprogram:
699 case dwarf::DW_TAG_label:
700 case dwarf::DW_TAG_variable:
701 case dwarf::DW_TAG_constant: {
710 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
715 Result.CU->getDebugInfoEntry(*ParentIdx);
718 Result.DieEntry = ParentEntry;
729 if (
Info.getTrackLiveness()) {
730 const auto *Abbrev =
DIE.getAbbreviationDeclarationPtr();
732 if (!
Info.getIsInFunctionScope() &&
733 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
741 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
742 Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
745 if (LocExprAddrAndRelocAdjustment.first)
746 Info.setHasAnAddress();
748 if (!LocExprAddrAndRelocAdjustment.second)
751 if (!IsLiveParent &&
Info.getIsInFunctionScope() &&
752 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
756 Info.setHasAnAddress();
758 if (Entry.CU->getGlobalData().getOptions().Verbose) {
759 outs() <<
"Keeping variable DIE:";
762 DumpOpts.
Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
772 std::optional<DWARFFormValue> LowPCVal =
DIE.find(dwarf::DW_AT_low_pc);
774 std::optional<uint64_t> LowPc;
775 std::optional<uint64_t> HighPc;
776 std::optional<int64_t> RelocAdjustment;
777 if (
Info.getTrackLiveness()) {
782 Info.setHasAnAddress();
785 Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
787 if (!RelocAdjustment)
790 if (
DIE.
getTag() == dwarf::DW_TAG_subprogram) {
793 HighPc =
DIE.getHighPC(*LowPc);
795 Entry.CU->warn(
"function without high_pc. Range will be discarded.",
800 if (*LowPc > *HighPc) {
801 Entry.CU->warn(
"low_pc greater than high_pc. Range will be discarded.",
805 }
else if (
DIE.
getTag() == dwarf::DW_TAG_label) {
806 if (Entry.CU->hasLabelAt(*LowPc))
818 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
821 Info.setHasAnAddress();
823 if (Entry.CU->getGlobalData().getOptions().Verbose) {
824 outs() <<
"Keeping subprogram DIE:";
827 DumpOpts.
Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
831 if (!
Info.getTrackLiveness() ||
DIE.
getTag() == dwarf::DW_TAG_label)
834 Entry.CU->addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
Analysis containing CSE Info
Branch Probability Basic Block Placement
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A pointer to another debug information entry.
A structured debug information entry.
dwarf::Tag getTag() const
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
iterator_range< iterator > children() const
const DWARFDebugInfoEntry * getDebugInfoEntry() const
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
DieOutputPlacement
Kinds of placement for the output die.
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
@ Both
Corresponding DIE goes to type table and to plain dwarf.
Class keeping live worklist item data.
LiveRootWorklistActionTy getAction() const
UnitEntryPairTy getRootEntry() const
bool hasReferencedByOtherEntry() const
RootEntriesListTy RootEntriesWorkList
List of entries which are 'root DIE's.
bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Examine worklist and mark all 'root DIE's as kept and set "Placement" property.
bool updateDependenciesCompleteness()
Check if dependencies have incompatible placement.
bool isChildrenAction(LiveRootWorklistActionTy Action)
static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry)
Returns true if specified subprogram references live code section.
bool maybeAddReferencedRoots(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Check referenced DIEs and add them into the worklist.
bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Mark whole DIE tree as kept recursively.
void markParentsAsKeepingChildren(const UnitEntryPairTy &Entry)
Mark parents as keeping children.
void setPlainDwarfPlacementRec(const UnitEntryPairTy &Entry)
Mark whole DIE tree as placed in "PlainDwarf".
bool isLiveAction(LiveRootWorklistActionTy Action)
void verifyKeepChain()
Recursively walk the DIE tree and check "keepness" and "placement" information.
void collectRootsToKeep(const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy, bool IsLiveParent)
This function navigates DIEs tree starting from specified Entry.
UnitEntryPairTy getRootForSpecifiedEntry(UnitEntryPairTy Entry)
static bool isLiveVariableEntry(const UnitEntryPairTy &Entry, bool IsLiveParent)
Returns true if specified variable references live code section.
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Recursively walk the DIE tree and look for DIEs to keep.
RootEntriesListTy Dependencies
List of entries dependencies.
bool isSingleAction(LiveRootWorklistActionTy Action)
bool isTypeTableCandidate(const DWARFDebugInfoEntry *DIEEntry)
void addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy)
Add action item to the work list.
bool isTypeAction(LiveRootWorklistActionTy Action)
@ MarkSingleTypeEntry
Mark current item as type entry.
@ MarkSingleLiveEntry
Mark current item as live entry.
@ 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.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry)
static CompileUnit::DieOutputPlacement getFinalPlacementForEntry(const UnitEntryPairTy &Entry, CompileUnit::DieOutputPlacement Placement)
ArrayRef< dwarf::Attribute > getODRAttributes()
bool isAlreadyMarked(const CompileUnit::DIEInfo &Info, CompileUnit::DieOutputPlacement NewPlacement)
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto reverse(ContainerTy &&C)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Container for dump options that control which debug information will be dumped.
unsigned ChildRecurseDepth
A broken link in the keep chain.
BrokenLink(DWARFDie Parent, DWARFDie Child, const char *Message)
Information gathered about source DIEs.
bool needToKeepInPlainDwarf() const
DieOutputPlacement getPlacement() const
void setPlacement(DieOutputPlacement Placement)
Sets Placement kind for the corresponding die.
bool needToPlaceInTypeTable() const
This is a helper structure which keeps a debug info entry with it's containing compilation unit.
const DWARFDebugInfoEntry * DieEntry