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: {
226 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
235 HasNewInterconnectedCUs)) {
246 bool HasNewDependency =
false;
248 assert(Root.hasReferencedByOtherEntry() &&
249 "Root entry without dependency inside the dependencies list");
261 HasNewDependency =
true;
269 return HasNewDependency;
276 !Info.getKeepTypeChildren())
280 Info.unsetKeepTypeChildren();
284 Entry.CU->getFirstChildEntry(Entry.DieEntry);
286 CurChild = Entry.CU->getSiblingEntry(CurChild))
291 switch (Entry->getTag()) {
292 case dwarf::DW_TAG_compile_unit:
293 case dwarf::DW_TAG_module:
294 case dwarf::DW_TAG_namespace:
307 switch (NewPlacement) {
309 return Info.needToPlaceInTypeTable();
312 return Info.needToKeepInPlainDwarf();
315 return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
326 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
331 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
336 bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
338 bool AreTypeParentsDone = !NeedKeepTypeChildren;
339 bool ArePlainParentsDone = !NeedKeepPlainChildren;
342 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
345 Entry.CU->getDebugInfoEntry(*ParentIdx);
348 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
349 if (ParentInfo.getKeepTypeChildren())
350 AreTypeParentsDone =
true;
354 ParentInfo.setKeepTypeChildren();
363 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
364 if (ParentInfo.getKeepPlainChildren())
365 ArePlainParentsDone =
true;
369 ParentInfo.setKeepPlainChildren();
378 if (AreTypeParentsDone && ArePlainParentsDone)
396 if (!EntryInfo.getODRAvailable())
399 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
409 Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_declaration), 0);
410 bool ParentIsType =
false;
412 if (std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx()) {
414 Entry.CU->getDebugInfoEntry(*ParentIdx)->getTag();
415 ParentIsType = ParentTag == dwarf::DW_TAG_class_type ||
416 ParentTag == dwarf::DW_TAG_structure_type ||
417 ParentTag == dwarf::DW_TAG_union_type;
420 if (IsDeclaration && ParentIsType) {
436 switch (EntryInfo.getPlacement()) {
457 std::atomic<bool> &HasNewInterconnectedCUs) {
458 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
469 "Wrong kind of placement for ODR unavailable entry");
483 Entry.
DieEntry->
getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
488 InterCUProcessingStarted,
489 HasNewInterconnectedCUs))
493 if (isSingleAction(Action))
498 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
499 Info.getODRAvailable()) {
510 Entry.CU->getFirstChildEntry(Entry.DieEntry);
512 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
515 switch (CurChild->getTag()) {
516 case dwarf::DW_TAG_variable:
517 case dwarf::DW_TAG_constant:
518 case dwarf::DW_TAG_subprogram:
519 case dwarf::DW_TAG_label: {
520 if (ChildInfo.getHasAnAddress())
525 case dwarf::DW_TAG_lexical_block:
526 case dwarf::DW_TAG_friend:
527 case dwarf::DW_TAG_inheritance:
528 case dwarf::DW_TAG_formal_parameter:
529 case dwarf::DW_TAG_unspecified_parameters:
530 case dwarf::DW_TAG_template_type_parameter:
531 case dwarf::DW_TAG_template_value_parameter:
532 case dwarf::DW_TAG_GNU_template_parameter_pack:
533 case dwarf::DW_TAG_GNU_formal_parameter_pack:
534 case dwarf::DW_TAG_GNU_template_template_param:
535 case dwarf::DW_TAG_thrown_type: {
556 InterCUProcessingStarted, HasNewInterconnectedCUs))
565 Entry.CU->getFirstChildEntry(Entry.DieEntry);
567 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
569 switch (CurChild->getTag()) {
570 case dwarf::DW_TAG_variable:
571 case dwarf::DW_TAG_constant:
572 case dwarf::DW_TAG_subprogram:
573 case dwarf::DW_TAG_label: {
574 if (ChildInfo.getHasAnAddress())
583 InterCUProcessingStarted, HasNewInterconnectedCUs))
596 case dwarf::DW_TAG_imported_module:
597 case dwarf::DW_TAG_imported_declaration:
598 case dwarf::DW_TAG_imported_unit:
599 case dwarf::DW_TAG_array_type:
600 case dwarf::DW_TAG_class_type:
601 case dwarf::DW_TAG_enumeration_type:
602 case dwarf::DW_TAG_pointer_type:
603 case dwarf::DW_TAG_reference_type:
604 case dwarf::DW_TAG_string_type:
605 case dwarf::DW_TAG_structure_type:
606 case dwarf::DW_TAG_subroutine_type:
607 case dwarf::DW_TAG_typedef:
608 case dwarf::DW_TAG_union_type:
609 case dwarf::DW_TAG_variant:
610 case dwarf::DW_TAG_module:
611 case dwarf::DW_TAG_ptr_to_member_type:
612 case dwarf::DW_TAG_set_type:
613 case dwarf::DW_TAG_subrange_type:
614 case dwarf::DW_TAG_base_type:
615 case dwarf::DW_TAG_const_type:
616 case dwarf::DW_TAG_enumerator:
617 case dwarf::DW_TAG_file_type:
618 case dwarf::DW_TAG_packed_type:
619 case dwarf::DW_TAG_thrown_type:
620 case dwarf::DW_TAG_volatile_type:
621 case dwarf::DW_TAG_dwarf_procedure:
622 case dwarf::DW_TAG_restrict_type:
623 case dwarf::DW_TAG_interface_type:
624 case dwarf::DW_TAG_namespace:
625 case dwarf::DW_TAG_unspecified_type:
626 case dwarf::DW_TAG_shared_type:
627 case dwarf::DW_TAG_rvalue_reference_type:
628 case dwarf::DW_TAG_coarray_type:
629 case dwarf::DW_TAG_dynamic_type:
630 case dwarf::DW_TAG_atomic_type:
631 case dwarf::DW_TAG_immutable_type:
632 case dwarf::DW_TAG_function_template:
633 case dwarf::DW_TAG_class_template:
641 std::atomic<bool> &HasNewInterconnectedCUs) {
642 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
643 if (Abbrev ==
nullptr)
646 DWARFUnit &Unit = Entry.CU->getOrigUnit();
652 for (
const auto &AttrSpec : Abbrev->attributes()) {
655 AttrSpec.Attr == dwarf::DW_AT_sibling) {
657 Unit.getFormParams());
663 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
664 Val, InterCUProcessingStarted
668 Entry.CU->warn(
"could not find referenced DIE", Entry.DieEntry);
672 if (!RefDie->DieEntry) {
674 RefDie->CU->setInterconnectedCU();
675 Entry.CU->setInterconnectedCU();
676 HasNewInterconnectedCUs =
true;
680 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
681 InterCUProcessingStarted) &&
682 "Inter-CU reference while inter-CU processing is not started");
685 if (!RefInfo.getODRAvailable())
687 else if (RefInfo.getODRAvailable() &&
698 if (AttrSpec.Attr == dwarf::DW_AT_import) {
724 switch (Entry.DieEntry->getTag()) {
725 case dwarf::DW_TAG_subprogram:
726 case dwarf::DW_TAG_label:
727 case dwarf::DW_TAG_variable:
728 case dwarf::DW_TAG_constant: {
737 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
742 Result.CU->getDebugInfoEntry(*ParentIdx);
745 Result.DieEntry = ParentEntry;
754 outs() <<
"Keeping " << Kind <<
" DIE:";
766 if (Info.getTrackLiveness()) {
767 const auto *Abbrev =
DIE.getAbbreviationDeclarationPtr();
769 if (!Info.getIsInFunctionScope() &&
770 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
778 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
779 Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
780 DIE, Entry.CU->getGlobalData().getOptions().Verbose);
782 if (LocExprAddrAndRelocAdjustment.first)
783 Info.setHasAnAddress();
785 if (!LocExprAddrAndRelocAdjustment.second)
788 if (!IsLiveParent && Info.getIsInFunctionScope() &&
789 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
793 Info.setHasAnAddress();
795 dumpKeptDIE(
DIE,
"variable", Entry.CU->getGlobalData().getOptions().Verbose);
803 std::optional<DWARFFormValue> LowPCVal =
DIE.find(dwarf::DW_AT_low_pc);
805 const bool Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
806 std::optional<uint64_t> LowPc;
807 std::optional<uint64_t> HighPc;
808 std::optional<int64_t> RelocAdjustment;
809 if (Info.getTrackLiveness()) {
814 Info.setHasAnAddress();
817 Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
819 if (!RelocAdjustment)
822 if (
DIE.
getTag() == dwarf::DW_TAG_subprogram) {
825 HighPc =
DIE.getHighPC(*LowPc);
827 Entry.CU->warn(
"function without high_pc. Range will be discarded.",
832 if (*LowPc > *HighPc) {
833 Entry.CU->warn(
"low_pc greater than high_pc. Range will be discarded.",
837 }
else if (
DIE.
getTag() == dwarf::DW_TAG_label) {
838 if (Entry.CU->hasLabelAt(*LowPc))
855 Entry.CU->getOrigUnit().getUnitDIE().find(dwarf::DW_AT_language), 0);
856 if (Language == dwarf::DW_LANG_Mips_Assembler ||
857 Language == dwarf::DW_LANG_Assembly) {
858 if (
auto Range = Entry.CU->getContaingFile()
859 .Addresses->getAssemblyRangeForAddress(*LowPc))
860 Entry.CU->addFunctionRange(
Range->LowPC,
Range->HighPC,
864 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
867 Info.setHasAnAddress();
871 if (!Info.getTrackLiveness() ||
DIE.
getTag() == dwarf::DW_TAG_label)
874 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