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) {
135 const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
138 Entry.CU->getFirstChildEntry(Entry.DieEntry);
140 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
144 bool IsLiveChild =
false;
146 switch (CurChild->getTag()) {
147 case dwarf::DW_TAG_label: {
152 if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
158 case dwarf::DW_TAG_subprogram: {
166 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
173 case dwarf::DW_TAG_constant:
174 case dwarf::DW_TAG_variable: {
183 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
190 case dwarf::DW_TAG_base_type: {
196 case dwarf::DW_TAG_imported_module:
197 case dwarf::DW_TAG_imported_declaration:
198 case dwarf::DW_TAG_imported_unit: {
200 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
211 case dwarf::DW_TAG_type_unit:
212 case dwarf::DW_TAG_partial_unit:
213 case dwarf::DW_TAG_compile_unit: {
225 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_module &&
241 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
250 HasNewInterconnectedCUs)) {
261 bool HasNewDependency =
false;
263 assert(Root.hasReferencedByOtherEntry() &&
264 "Root entry without dependency inside the dependencies list");
276 HasNewDependency =
true;
284 return HasNewDependency;
291 !Info.getKeepTypeChildren())
295 Info.unsetKeepTypeChildren();
299 Entry.CU->getFirstChildEntry(Entry.DieEntry);
301 CurChild = Entry.CU->getSiblingEntry(CurChild))
306 switch (Entry->getTag()) {
307 case dwarf::DW_TAG_compile_unit:
308 case dwarf::DW_TAG_module:
309 case dwarf::DW_TAG_namespace:
322 switch (NewPlacement) {
324 return Info.needToPlaceInTypeTable();
327 return Info.needToKeepInPlainDwarf();
330 return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
341 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
346 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
351 bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
353 bool AreTypeParentsDone = !NeedKeepTypeChildren;
354 bool ArePlainParentsDone = !NeedKeepPlainChildren;
357 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
360 Entry.CU->getDebugInfoEntry(*ParentIdx);
363 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
364 if (ParentInfo.getKeepTypeChildren())
365 AreTypeParentsDone =
true;
369 ParentInfo.setKeepTypeChildren();
378 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
379 if (ParentInfo.getKeepPlainChildren())
380 ArePlainParentsDone =
true;
384 ParentInfo.setKeepPlainChildren();
393 if (AreTypeParentsDone && ArePlainParentsDone)
411 if (!EntryInfo.getODRAvailable())
414 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
424 Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_declaration), 0);
425 bool ParentIsType =
false;
427 if (std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx()) {
429 Entry.CU->getDebugInfoEntry(*ParentIdx)->getTag();
430 ParentIsType = ParentTag == dwarf::DW_TAG_class_type ||
431 ParentTag == dwarf::DW_TAG_structure_type ||
432 ParentTag == dwarf::DW_TAG_union_type;
435 if (IsDeclaration && ParentIsType) {
451 switch (EntryInfo.getPlacement()) {
472 std::atomic<bool> &HasNewInterconnectedCUs) {
473 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
484 "Wrong kind of placement for ODR unavailable entry");
498 Entry.
DieEntry->
getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
503 InterCUProcessingStarted,
504 HasNewInterconnectedCUs))
508 if (isSingleAction(Action))
513 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
514 Info.getODRAvailable()) {
525 Entry.CU->getFirstChildEntry(Entry.DieEntry);
527 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
530 switch (CurChild->getTag()) {
531 case dwarf::DW_TAG_variable:
532 case dwarf::DW_TAG_constant:
533 case dwarf::DW_TAG_subprogram:
534 case dwarf::DW_TAG_label: {
535 if (ChildInfo.getHasAnAddress())
540 case dwarf::DW_TAG_lexical_block:
541 case dwarf::DW_TAG_friend:
542 case dwarf::DW_TAG_inheritance:
543 case dwarf::DW_TAG_formal_parameter:
544 case dwarf::DW_TAG_unspecified_parameters:
545 case dwarf::DW_TAG_template_type_parameter:
546 case dwarf::DW_TAG_template_value_parameter:
547 case dwarf::DW_TAG_GNU_template_parameter_pack:
548 case dwarf::DW_TAG_GNU_formal_parameter_pack:
549 case dwarf::DW_TAG_GNU_template_template_param:
550 case dwarf::DW_TAG_thrown_type: {
571 InterCUProcessingStarted, HasNewInterconnectedCUs))
580 Entry.CU->getFirstChildEntry(Entry.DieEntry);
582 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
584 switch (CurChild->getTag()) {
585 case dwarf::DW_TAG_variable:
586 case dwarf::DW_TAG_constant:
587 case dwarf::DW_TAG_subprogram:
588 case dwarf::DW_TAG_label: {
589 if (ChildInfo.getHasAnAddress())
598 InterCUProcessingStarted, HasNewInterconnectedCUs))
611 case dwarf::DW_TAG_imported_module:
612 case dwarf::DW_TAG_imported_declaration:
613 case dwarf::DW_TAG_imported_unit:
614 case dwarf::DW_TAG_array_type:
615 case dwarf::DW_TAG_class_type:
616 case dwarf::DW_TAG_enumeration_type:
617 case dwarf::DW_TAG_pointer_type:
618 case dwarf::DW_TAG_reference_type:
619 case dwarf::DW_TAG_string_type:
620 case dwarf::DW_TAG_structure_type:
621 case dwarf::DW_TAG_subroutine_type:
622 case dwarf::DW_TAG_typedef:
623 case dwarf::DW_TAG_union_type:
624 case dwarf::DW_TAG_variant:
625 case dwarf::DW_TAG_module:
626 case dwarf::DW_TAG_ptr_to_member_type:
627 case dwarf::DW_TAG_set_type:
628 case dwarf::DW_TAG_subrange_type:
629 case dwarf::DW_TAG_base_type:
630 case dwarf::DW_TAG_const_type:
631 case dwarf::DW_TAG_enumerator:
632 case dwarf::DW_TAG_file_type:
633 case dwarf::DW_TAG_packed_type:
634 case dwarf::DW_TAG_thrown_type:
635 case dwarf::DW_TAG_volatile_type:
636 case dwarf::DW_TAG_dwarf_procedure:
637 case dwarf::DW_TAG_restrict_type:
638 case dwarf::DW_TAG_interface_type:
639 case dwarf::DW_TAG_namespace:
640 case dwarf::DW_TAG_unspecified_type:
641 case dwarf::DW_TAG_shared_type:
642 case dwarf::DW_TAG_rvalue_reference_type:
643 case dwarf::DW_TAG_coarray_type:
644 case dwarf::DW_TAG_dynamic_type:
645 case dwarf::DW_TAG_atomic_type:
646 case dwarf::DW_TAG_immutable_type:
647 case dwarf::DW_TAG_function_template:
648 case dwarf::DW_TAG_class_template:
656 std::atomic<bool> &HasNewInterconnectedCUs) {
657 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
658 if (Abbrev ==
nullptr)
661 DWARFUnit &Unit = Entry.CU->getOrigUnit();
667 for (
const auto &AttrSpec : Abbrev->attributes()) {
670 AttrSpec.Attr == dwarf::DW_AT_sibling) {
672 Unit.getFormParams());
678 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
679 Val, InterCUProcessingStarted
683 Entry.CU->warn(
"could not find referenced DIE", Entry.DieEntry);
687 if (!RefDie->DieEntry) {
689 RefDie->CU->setInterconnectedCU();
690 Entry.CU->setInterconnectedCU();
691 HasNewInterconnectedCUs =
true;
695 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
696 InterCUProcessingStarted) &&
697 "Inter-CU reference while inter-CU processing is not started");
700 if (!RefInfo.getODRAvailable())
702 else if (RefInfo.getODRAvailable() &&
713 if (AttrSpec.Attr == dwarf::DW_AT_import) {
739 switch (Entry.DieEntry->getTag()) {
740 case dwarf::DW_TAG_subprogram:
741 case dwarf::DW_TAG_label:
742 case dwarf::DW_TAG_variable:
743 case dwarf::DW_TAG_constant: {
752 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
757 Result.CU->getDebugInfoEntry(*ParentIdx);
760 Result.DieEntry = ParentEntry;
769 outs() <<
"Keeping " << Kind <<
" DIE:";
781 if (Info.getTrackLiveness()) {
782 const auto *Abbrev =
DIE.getAbbreviationDeclarationPtr();
784 if (!Info.getIsInFunctionScope() &&
785 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
793 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
794 Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
795 DIE, Entry.CU->getGlobalData().getOptions().Verbose);
797 if (LocExprAddrAndRelocAdjustment.first)
798 Info.setHasAnAddress();
800 if (!LocExprAddrAndRelocAdjustment.second)
803 if (!IsLiveParent && Info.getIsInFunctionScope() &&
804 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
808 Info.setHasAnAddress();
810 dumpKeptDIE(
DIE,
"variable", Entry.CU->getGlobalData().getOptions().Verbose);
818 std::optional<DWARFFormValue> LowPCVal =
DIE.find(dwarf::DW_AT_low_pc);
820 const bool Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
821 std::optional<uint64_t> LowPc;
822 std::optional<uint64_t> HighPc;
823 std::optional<int64_t> RelocAdjustment;
824 if (Info.getTrackLiveness()) {
829 Info.setHasAnAddress();
832 Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
834 if (!RelocAdjustment)
837 if (
DIE.
getTag() == dwarf::DW_TAG_subprogram) {
840 HighPc =
DIE.getHighPC(*LowPc);
842 Entry.CU->warn(
"function without high_pc. Range will be discarded.",
847 if (*LowPc > *HighPc) {
848 Entry.CU->warn(
"low_pc greater than high_pc. Range will be discarded.",
852 }
else if (
DIE.
getTag() == dwarf::DW_TAG_label) {
853 if (Entry.CU->hasLabelAt(*LowPc))
870 Entry.CU->getOrigUnit().getUnitDIE().find(dwarf::DW_AT_language), 0);
871 if (Language == dwarf::DW_LANG_Mips_Assembler ||
872 Language == dwarf::DW_LANG_Assembly) {
873 if (
auto Range = Entry.CU->getContaingFile()
874 .Addresses->getAssemblyRangeForAddress(*LowPc))
875 Entry.CU->addFunctionRange(
Range->LowPC,
Range->HighPC,
879 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
882 Info.setHasAnAddress();
886 if (!Info.getTrackLiveness() ||
DIE.
getTag() == dwarf::DW_TAG_label)
889 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 bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry)
static CompileUnit::DieOutputPlacement getFinalPlacementForEntry(const UnitEntryPairTy &Entry, CompileUnit::DieOutputPlacement Placement)
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
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 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 isLiveAction(LiveRootWorklistActionTy Action)
bool isChildrenAction(LiveRootWorklistActionTy Action)
bool isTypeAction(LiveRootWorklistActionTy Action)
bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry, const UnitEntryPairTy &Entry, bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Mark whole DIE tree as kept recursively.
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.
void addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry, std::optional< UnitEntryPairTy > ReferencedBy)
Add action item to the work list.
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.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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