29#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
36 while (!Worklist.
empty()) {
52 CU.getDIEInfo(Child.getDebugInfoEntry());
56 if (!ParentPlainDieIsKept && ChildPlainDieIsKept)
58 "Found invalid link in keep chain");
60 if (Child.getTag() == dwarf::DW_TAG_subprogram) {
62 &
CU, Child.getDebugInfoEntry()))) {
64 "Live subprogram is not marked as kept");
68 if (!ChildInfo.getODRAvailable()) {
69 assert(!ChildTypeDieIsKept);
73 if (!ParentTypeDieIsKept && ChildTypeDieIsKept)
75 "Found invalid link in keep chain");
77 if (CurrentInfo.getIsInAnonNamespaceScope() &&
80 "Found invalid placement marking for member "
81 "of anonymous namespace");
86 if (!BrokenLinks.
empty()) {
88 errs() <<
"\n=================================\n";
90 Link.Parent.getOffset(),
91 Link.Child.getOffset());
93 errs() <<
"\nParent:";
94 Link.Parent.dump(
errs(), 0, {});
96 CU.getDIEInfo(Link.Parent).dump();
99 Link.Child.dump(
errs(), 2, {});
101 CU.getDIEInfo(Link.Child).dump();
109 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
116 std::nullopt,
false);
120 HasNewInterconnectedCUs);
125 std::optional<UnitEntryPairTy> ReferencedBy,
129 ReferencedTypeDieEntry);
137 const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
140 Entry.CU->getFirstChildEntry(Entry.DieEntry);
142 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
146 bool IsLiveChild =
false;
148 switch (CurChild->getTag()) {
149 case dwarf::DW_TAG_label: {
154 if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
160 case dwarf::DW_TAG_subprogram: {
168 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
175 case dwarf::DW_TAG_constant:
176 case dwarf::DW_TAG_variable: {
185 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
192 case dwarf::DW_TAG_base_type: {
198 case dwarf::DW_TAG_imported_module:
199 case dwarf::DW_TAG_imported_declaration:
200 case dwarf::DW_TAG_imported_unit: {
202 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
213 case dwarf::DW_TAG_type_unit:
214 case dwarf::DW_TAG_partial_unit:
215 case dwarf::DW_TAG_compile_unit: {
227 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_module &&
243 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
252 HasNewInterconnectedCUs)) {
263 bool HasNewDependency =
false;
265 assert(Root.hasReferencedByOtherEntry() &&
266 "Root entry without dependency inside the dependencies list");
277 Root.getReferencedTypeDieEntry() ? Root.getReferencedTypeDieEntry()
288 HasNewDependency =
true;
296 return HasNewDependency;
303 !Info.getKeepTypeChildren())
307 Info.unsetKeepTypeChildren();
311 Entry.CU->getFirstChildEntry(Entry.DieEntry);
313 CurChild = Entry.CU->getSiblingEntry(CurChild))
318 switch (Entry->getTag()) {
319 case dwarf::DW_TAG_compile_unit:
320 case dwarf::DW_TAG_module:
321 case dwarf::DW_TAG_namespace:
334 switch (NewPlacement) {
336 return Info.needToPlaceInTypeTable();
339 return Info.needToKeepInPlainDwarf();
342 return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
353 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
358 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
363 bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
365 bool AreTypeParentsDone = !NeedKeepTypeChildren;
366 bool ArePlainParentsDone = !NeedKeepPlainChildren;
369 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
372 Entry.CU->getDebugInfoEntry(*ParentIdx);
375 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
376 if (ParentInfo.getKeepTypeChildren())
377 AreTypeParentsDone =
true;
381 ParentInfo.setKeepTypeChildren();
390 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
391 if (ParentInfo.getKeepPlainChildren())
392 ArePlainParentsDone =
true;
396 ParentInfo.setKeepPlainChildren();
405 if (AreTypeParentsDone && ArePlainParentsDone)
413struct FinalPlacement {
448 if (!EntryInfo.getODRAvailable())
451 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
461 Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_declaration), 0);
462 bool ParentIsType =
false;
464 if (std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx()) {
466 Entry.CU->getDebugInfoEntry(*ParentIdx)->getTag();
467 ParentIsType = ParentTag == dwarf::DW_TAG_class_type ||
468 ParentTag == dwarf::DW_TAG_structure_type ||
469 ParentTag == dwarf::DW_TAG_union_type;
472 if (IsDeclaration && ParentIsType) {
484 return {
Placement, FinalPlacement::JoinVariable};
487 return {
Placement, FinalPlacement::Join};
493 std::atomic<bool> &HasNewInterconnectedCUs,
bool RecordDepsOnly) {
494 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
506 "Wrong kind of placement for ODR unavailable entry");
520 InterCUProcessingStarted,
521 HasNewInterconnectedCUs,
525 if (!RecordDepsOnly) {
531 switch (Final.Mode) {
532 case FinalPlacement::Overwrite:
535 case FinalPlacement::Join:
538 case FinalPlacement::JoinVariable:
548 Entry.
DieEntry->
getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
553 InterCUProcessingStarted,
554 HasNewInterconnectedCUs, RecordDepsOnly))
558 if (isSingleAction(Action))
563 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
564 Info.getODRAvailable()) {
575 Entry.CU->getFirstChildEntry(Entry.DieEntry);
577 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
580 switch (CurChild->getTag()) {
581 case dwarf::DW_TAG_variable:
582 case dwarf::DW_TAG_constant:
583 case dwarf::DW_TAG_subprogram:
584 case dwarf::DW_TAG_label: {
585 if (ChildInfo.getHasAnAddress())
590 case dwarf::DW_TAG_lexical_block:
591 case dwarf::DW_TAG_friend:
592 case dwarf::DW_TAG_inheritance:
593 case dwarf::DW_TAG_formal_parameter:
594 case dwarf::DW_TAG_unspecified_parameters:
595 case dwarf::DW_TAG_template_type_parameter:
596 case dwarf::DW_TAG_template_value_parameter:
597 case dwarf::DW_TAG_GNU_template_parameter_pack:
598 case dwarf::DW_TAG_GNU_formal_parameter_pack:
599 case dwarf::DW_TAG_GNU_template_template_param:
600 case dwarf::DW_TAG_thrown_type: {
621 InterCUProcessingStarted,
622 HasNewInterconnectedCUs, RecordDepsOnly))
631 Entry.CU->getFirstChildEntry(Entry.DieEntry);
633 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
635 switch (CurChild->getTag()) {
636 case dwarf::DW_TAG_variable:
637 case dwarf::DW_TAG_constant:
638 case dwarf::DW_TAG_subprogram:
639 case dwarf::DW_TAG_label: {
640 if (ChildInfo.getHasAnAddress())
649 InterCUProcessingStarted, HasNewInterconnectedCUs, RecordDepsOnly))
662 case dwarf::DW_TAG_imported_module:
663 case dwarf::DW_TAG_imported_declaration:
664 case dwarf::DW_TAG_imported_unit:
665 case dwarf::DW_TAG_array_type:
666 case dwarf::DW_TAG_class_type:
667 case dwarf::DW_TAG_enumeration_type:
668 case dwarf::DW_TAG_pointer_type:
669 case dwarf::DW_TAG_reference_type:
670 case dwarf::DW_TAG_string_type:
671 case dwarf::DW_TAG_structure_type:
672 case dwarf::DW_TAG_subroutine_type:
673 case dwarf::DW_TAG_typedef:
674 case dwarf::DW_TAG_union_type:
675 case dwarf::DW_TAG_variant:
676 case dwarf::DW_TAG_module:
677 case dwarf::DW_TAG_ptr_to_member_type:
678 case dwarf::DW_TAG_set_type:
679 case dwarf::DW_TAG_subrange_type:
680 case dwarf::DW_TAG_base_type:
681 case dwarf::DW_TAG_const_type:
682 case dwarf::DW_TAG_enumerator:
683 case dwarf::DW_TAG_file_type:
684 case dwarf::DW_TAG_packed_type:
685 case dwarf::DW_TAG_thrown_type:
686 case dwarf::DW_TAG_volatile_type:
687 case dwarf::DW_TAG_dwarf_procedure:
688 case dwarf::DW_TAG_restrict_type:
689 case dwarf::DW_TAG_interface_type:
690 case dwarf::DW_TAG_namespace:
691 case dwarf::DW_TAG_unspecified_type:
692 case dwarf::DW_TAG_shared_type:
693 case dwarf::DW_TAG_rvalue_reference_type:
694 case dwarf::DW_TAG_coarray_type:
695 case dwarf::DW_TAG_dynamic_type:
696 case dwarf::DW_TAG_atomic_type:
697 case dwarf::DW_TAG_immutable_type:
698 case dwarf::DW_TAG_function_template:
699 case dwarf::DW_TAG_class_template:
707 std::atomic<bool> &HasNewInterconnectedCUs,
bool RecordDepsOnly) {
708 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
709 if (Abbrev ==
nullptr)
718 if (RecordDepsOnly) {
720 ReferencedTypeDieEntry);
724 ReferencedTypeDieEntry);
727 DWARFUnit &Unit = Entry.CU->getOrigUnit();
733 for (
const auto &AttrSpec : Abbrev->attributes()) {
736 AttrSpec.Attr == dwarf::DW_AT_sibling) {
738 Unit.getFormParams());
744 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
745 Val, InterCUProcessingStarted
749 Entry.CU->warn(
"could not find referenced DIE", Entry.DieEntry);
753 if (!RefDie->DieEntry) {
761 RefDie->CU->setInterconnectedCU();
762 Entry.CU->setInterconnectedCU();
763 HasNewInterconnectedCUs =
true;
767 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
768 InterCUProcessingStarted) &&
769 "Inter-CU reference while inter-CU processing is not started");
772 if (!RefInfo.getODRAvailable())
774 else if (RefInfo.getODRAvailable() &&
785 if (AttrSpec.Attr == dwarf::DW_AT_import) {
794 AddRoot(Action, *RefDie,
nullptr);
803 AddRoot(Action, RootForReferencedDie, RefDie->DieEntry);
814 switch (Entry.DieEntry->getTag()) {
815 case dwarf::DW_TAG_subprogram:
816 case dwarf::DW_TAG_label:
817 case dwarf::DW_TAG_variable:
818 case dwarf::DW_TAG_constant: {
827 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
832 Result.CU->getDebugInfoEntry(*ParentIdx);
835 Result.DieEntry = ParentEntry;
844 outs() <<
"Keeping " << Kind <<
" DIE:";
856 if (Info.getTrackLiveness()) {
857 const auto *Abbrev =
DIE.getAbbreviationDeclarationPtr();
859 if (!Info.getIsInFunctionScope() &&
860 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
868 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
869 Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
870 DIE, Entry.CU->getGlobalData().getOptions().Verbose);
872 if (LocExprAddrAndRelocAdjustment.first)
873 Info.setHasAnAddress();
875 if (!LocExprAddrAndRelocAdjustment.second)
878 if (!IsLiveParent && Info.getIsInFunctionScope() &&
879 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
883 Info.setHasAnAddress();
885 dumpKeptDIE(
DIE,
"variable", Entry.CU->getGlobalData().getOptions().Verbose);
893 std::optional<DWARFFormValue> LowPCVal =
DIE.find(dwarf::DW_AT_low_pc);
895 const bool Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
896 std::optional<uint64_t> LowPc;
897 std::optional<uint64_t> HighPc;
898 std::optional<int64_t> RelocAdjustment;
899 if (Info.getTrackLiveness()) {
904 Info.setHasAnAddress();
907 Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
909 if (!RelocAdjustment)
912 if (
DIE.
getTag() == dwarf::DW_TAG_subprogram) {
915 HighPc =
DIE.getHighPC(*LowPc);
917 Entry.CU->warn(
"function without high_pc. Range will be discarded.",
922 if (*LowPc > *HighPc) {
923 Entry.CU->warn(
"low_pc greater than high_pc. Range will be discarded.",
927 }
else if (
DIE.
getTag() == dwarf::DW_TAG_label) {
928 if (Entry.CU->hasLabelAt(*LowPc))
945 Entry.CU->getOrigUnit().getUnitDIE().find(dwarf::DW_AT_language), 0);
946 if (Language == dwarf::DW_LANG_Mips_Assembler ||
947 Language == dwarf::DW_LANG_Assembly) {
948 if (
auto Range = Entry.CU->getContaingFile()
949 .Addresses->getAssemblyRangeForAddress(*LowPc))
950 Entry.CU->addFunctionRange(
Range->LowPC,
Range->HighPC,
954 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
957 Info.setHasAnAddress();
961 if (!Info.getTrackLiveness() ||
DIE.
getTag() == dwarf::DW_TAG_label)
964 Entry.CU->addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bool isAlreadyMarked(const CompileUnit::DIEInfo &Info, CompileUnit::DieOutputPlacement NewPlacement)
static void dumpKeptDIE(const DWARFDie &DIE, StringRef Kind, bool Verbose)
static FinalPlacement getFinalPlacementForEntry(const UnitEntryPairTy &Entry, CompileUnit::DieOutputPlacement Placement)
static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry)
Branch Probability Basic Block Placement
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
A pointer to another debug information entry.
A structured debug information entry.
dwarf::Tag getTag() const
LLVM_ABI void dump() const
DWARFDebugInfoEntry - A DIE with only the minimum required data.
dwarf::Tag getTag() const
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
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.
Represent a constant reference to a string, i.e.
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
DieOutputPlacement
Kinds of placement for the output die.
@ Both
Corresponding DIE goes to type table and to plain dwarf.
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
Class keeping live worklist item data.
UnitEntryPairTy getRootEntry() const
LiveRootWorklistActionTy getAction() const
bool hasReferencedByOtherEntry() const
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)
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.
@ 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.
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.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ArrayRef< dwarf::Attribute > getODRAttributes()
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI 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.
BrokenLink(DWARFDie Parent, DWARFDie Child, const char *Message)
A broken link in the keep chain.
Container for dump options that control which debug information will be dumped.
unsigned ChildRecurseDepth
Information gathered about a DIE in the object file.
Information gathered about source DIEs.
void setPlacement(DieOutputPlacement Placement)
Sets Placement kind for the corresponding die.
bool needToKeepInPlainDwarf() const
bool needToPlaceInTypeTable() const
This is a helper structure which keeps a debug info entry with it's containing compilation unit.
const DWARFDebugInfoEntry * DieEntry