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 switch (Entry->getTag()) {
110 case dwarf::DW_TAG_compile_unit:
111 case dwarf::DW_TAG_module:
112 case dwarf::DW_TAG_namespace:
121 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
128 std::nullopt,
false);
132 HasNewInterconnectedCUs);
137 std::optional<UnitEntryPairTy> ReferencedBy,
141 ReferencedTypeDieEntry);
149 const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
152 Entry.CU->getFirstChildEntry(Entry.DieEntry);
154 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
158 bool IsLiveChild =
false;
160 switch (CurChild->getTag()) {
161 case dwarf::DW_TAG_label: {
166 if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
172 case dwarf::DW_TAG_subprogram: {
180 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
187 case dwarf::DW_TAG_constant:
188 case dwarf::DW_TAG_variable: {
197 (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
204 case dwarf::DW_TAG_base_type: {
210 case dwarf::DW_TAG_imported_module:
211 case dwarf::DW_TAG_imported_declaration:
212 case dwarf::DW_TAG_imported_unit: {
214 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
225 case dwarf::DW_TAG_type_unit:
226 case dwarf::DW_TAG_partial_unit:
227 case dwarf::DW_TAG_compile_unit: {
251 if (!Entry.CU->isClangModule() &&
252 Entry.DieEntry->getTag() == dwarf::DW_TAG_module &&
268 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
277 HasNewInterconnectedCUs)) {
288 bool HasNewDependency =
false;
290 assert(Root.hasReferencedByOtherEntry() &&
291 "Root entry without dependency inside the dependencies list");
302 Root.getReferencedTypeDieEntry() ? Root.getReferencedTypeDieEntry()
313 HasNewDependency =
true;
321 return HasNewDependency;
328 !Info.getKeepTypeChildren())
332 Info.unsetKeepTypeChildren();
336 Entry.CU->getFirstChildEntry(Entry.DieEntry);
338 CurChild = Entry.CU->getSiblingEntry(CurChild))
347 switch (NewPlacement) {
349 return Info.needToPlaceInTypeTable();
352 return Info.needToKeepInPlainDwarf();
355 return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
366 return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
371 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
376 bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
378 bool AreTypeParentsDone = !NeedKeepTypeChildren;
379 bool ArePlainParentsDone = !NeedKeepPlainChildren;
382 std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
385 Entry.CU->getDebugInfoEntry(*ParentIdx);
388 if (!AreTypeParentsDone && NeedKeepTypeChildren) {
389 if (ParentInfo.getKeepTypeChildren())
390 AreTypeParentsDone =
true;
394 ParentInfo.setKeepTypeChildren();
403 if (!ArePlainParentsDone && NeedKeepPlainChildren) {
404 if (ParentInfo.getKeepPlainChildren())
405 ArePlainParentsDone =
true;
409 ParentInfo.setKeepPlainChildren();
418 if (AreTypeParentsDone && ArePlainParentsDone)
426struct FinalPlacement {
461 if (!EntryInfo.getODRAvailable())
464 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
474 Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_declaration), 0);
475 bool ParentIsType =
false;
477 if (std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx()) {
479 Entry.CU->getDebugInfoEntry(*ParentIdx)->getTag();
480 ParentIsType = ParentTag == dwarf::DW_TAG_class_type ||
481 ParentTag == dwarf::DW_TAG_structure_type ||
482 ParentTag == dwarf::DW_TAG_union_type;
485 if (IsDeclaration && ParentIsType) {
497 return {
Placement, FinalPlacement::JoinVariable};
500 return {
Placement, FinalPlacement::Join};
506 std::atomic<bool> &HasNewInterconnectedCUs,
bool RecordDepsOnly) {
507 if (Entry.DieEntry->getAbbreviationDeclarationPtr() ==
nullptr)
519 "Wrong kind of placement for ODR unavailable entry");
533 InterCUProcessingStarted,
534 HasNewInterconnectedCUs,
538 if (!RecordDepsOnly) {
544 switch (Final.Mode) {
545 case FinalPlacement::Overwrite:
548 case FinalPlacement::Join:
551 case FinalPlacement::JoinVariable:
561 Entry.
DieEntry->
getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
566 InterCUProcessingStarted,
567 HasNewInterconnectedCUs, RecordDepsOnly))
571 if (isSingleAction(Action))
576 if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
577 Info.getODRAvailable()) {
588 Entry.CU->getFirstChildEntry(Entry.DieEntry);
590 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
593 switch (CurChild->getTag()) {
594 case dwarf::DW_TAG_variable:
595 case dwarf::DW_TAG_constant:
596 case dwarf::DW_TAG_subprogram:
597 case dwarf::DW_TAG_label: {
598 if (ChildInfo.getHasAnAddress())
603 case dwarf::DW_TAG_lexical_block:
604 case dwarf::DW_TAG_friend:
605 case dwarf::DW_TAG_inheritance:
606 case dwarf::DW_TAG_formal_parameter:
607 case dwarf::DW_TAG_unspecified_parameters:
608 case dwarf::DW_TAG_template_type_parameter:
609 case dwarf::DW_TAG_template_value_parameter:
610 case dwarf::DW_TAG_GNU_template_parameter_pack:
611 case dwarf::DW_TAG_GNU_formal_parameter_pack:
612 case dwarf::DW_TAG_GNU_template_template_param:
613 case dwarf::DW_TAG_thrown_type: {
634 InterCUProcessingStarted,
635 HasNewInterconnectedCUs, RecordDepsOnly))
644 Entry.CU->getFirstChildEntry(Entry.DieEntry);
646 CurChild = Entry.CU->getSiblingEntry(CurChild)) {
648 switch (CurChild->getTag()) {
649 case dwarf::DW_TAG_variable:
650 case dwarf::DW_TAG_constant:
651 case dwarf::DW_TAG_subprogram:
652 case dwarf::DW_TAG_label: {
653 if (ChildInfo.getHasAnAddress())
662 InterCUProcessingStarted, HasNewInterconnectedCUs, RecordDepsOnly))
675 case dwarf::DW_TAG_imported_module:
676 case dwarf::DW_TAG_imported_declaration:
677 case dwarf::DW_TAG_imported_unit:
678 case dwarf::DW_TAG_array_type:
679 case dwarf::DW_TAG_class_type:
680 case dwarf::DW_TAG_enumeration_type:
681 case dwarf::DW_TAG_pointer_type:
682 case dwarf::DW_TAG_reference_type:
683 case dwarf::DW_TAG_string_type:
684 case dwarf::DW_TAG_structure_type:
685 case dwarf::DW_TAG_subroutine_type:
686 case dwarf::DW_TAG_typedef:
687 case dwarf::DW_TAG_union_type:
688 case dwarf::DW_TAG_variant:
689 case dwarf::DW_TAG_module:
690 case dwarf::DW_TAG_ptr_to_member_type:
691 case dwarf::DW_TAG_set_type:
692 case dwarf::DW_TAG_subrange_type:
693 case dwarf::DW_TAG_base_type:
694 case dwarf::DW_TAG_const_type:
695 case dwarf::DW_TAG_enumerator:
696 case dwarf::DW_TAG_file_type:
697 case dwarf::DW_TAG_packed_type:
698 case dwarf::DW_TAG_thrown_type:
699 case dwarf::DW_TAG_volatile_type:
700 case dwarf::DW_TAG_dwarf_procedure:
701 case dwarf::DW_TAG_restrict_type:
702 case dwarf::DW_TAG_interface_type:
703 case dwarf::DW_TAG_namespace:
704 case dwarf::DW_TAG_unspecified_type:
705 case dwarf::DW_TAG_shared_type:
706 case dwarf::DW_TAG_rvalue_reference_type:
707 case dwarf::DW_TAG_coarray_type:
708 case dwarf::DW_TAG_dynamic_type:
709 case dwarf::DW_TAG_atomic_type:
710 case dwarf::DW_TAG_immutable_type:
711 case dwarf::DW_TAG_function_template:
712 case dwarf::DW_TAG_class_template:
720 std::atomic<bool> &HasNewInterconnectedCUs,
bool RecordDepsOnly) {
721 const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
722 if (Abbrev ==
nullptr)
731 if (RecordDepsOnly) {
733 ReferencedTypeDieEntry);
737 ReferencedTypeDieEntry);
740 DWARFUnit &Unit = Entry.CU->getOrigUnit();
746 for (
const auto &AttrSpec : Abbrev->attributes()) {
749 AttrSpec.Attr == dwarf::DW_AT_sibling) {
751 Unit.getFormParams());
757 std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
758 Val, InterCUProcessingStarted
762 Entry.CU->warn(
"could not find referenced DIE", Entry.DieEntry);
766 if (!RefDie->DieEntry) {
774 RefDie->CU->setInterconnectedCU();
775 Entry.CU->setInterconnectedCU();
776 HasNewInterconnectedCUs =
true;
780 assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
781 InterCUProcessingStarted) &&
782 "Inter-CU reference while inter-CU processing is not started");
785 if (!RefInfo.getODRAvailable())
787 else if (RefInfo.getODRAvailable() &&
798 if (AttrSpec.Attr == dwarf::DW_AT_import) {
807 AddRoot(Action, *RefDie,
nullptr);
816 AddRoot(Action, RootForReferencedDie, RefDie->DieEntry);
827 switch (Entry.DieEntry->getTag()) {
828 case dwarf::DW_TAG_subprogram:
829 case dwarf::DW_TAG_label:
830 case dwarf::DW_TAG_variable:
831 case dwarf::DW_TAG_constant: {
840 std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
845 Result.CU->getDebugInfoEntry(*ParentIdx);
848 Result.DieEntry = ParentEntry;
857 outs() <<
"Keeping " << Kind <<
" DIE:";
869 if (Info.getTrackLiveness()) {
870 const auto *Abbrev =
DIE.getAbbreviationDeclarationPtr();
872 if (!Info.getIsInFunctionScope() &&
873 Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
881 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
882 Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
883 DIE, Entry.CU->getGlobalData().getOptions().Verbose);
885 if (LocExprAddrAndRelocAdjustment.first)
886 Info.setHasAnAddress();
888 if (!LocExprAddrAndRelocAdjustment.second)
891 if (!IsLiveParent && Info.getIsInFunctionScope() &&
892 !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
896 Info.setHasAnAddress();
898 dumpKeptDIE(
DIE,
"variable", Entry.CU->getGlobalData().getOptions().Verbose);
906 std::optional<DWARFFormValue> LowPCVal =
DIE.find(dwarf::DW_AT_low_pc);
908 const bool Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
909 std::optional<uint64_t> LowPc;
910 std::optional<uint64_t> HighPc;
911 std::optional<int64_t> RelocAdjustment;
912 if (Info.getTrackLiveness()) {
917 Info.setHasAnAddress();
920 Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
922 if (!RelocAdjustment)
925 if (
DIE.
getTag() == dwarf::DW_TAG_subprogram) {
928 HighPc =
DIE.getHighPC(*LowPc);
930 Entry.CU->warn(
"function without high_pc. Range will be discarded.",
935 if (*LowPc > *HighPc) {
936 Entry.CU->warn(
"low_pc greater than high_pc. Range will be discarded.",
940 }
else if (
DIE.
getTag() == dwarf::DW_TAG_label) {
941 if (Entry.CU->hasLabelAt(*LowPc))
958 Entry.CU->getOrigUnit().getUnitDIE().find(dwarf::DW_AT_language), 0);
959 if (Language == dwarf::DW_LANG_Mips_Assembler ||
960 Language == dwarf::DW_LANG_Assembly) {
962 Entry.CU->getContaingFile().Addresses->getSymbolRangeForAddress(
964 Entry.CU->addFunctionRange(
Range->LowPC,
Range->HighPC,
968 Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
971 Info.setHasAnAddress();
975 if (!Info.getTrackLiveness() ||
DIE.
getTag() == dwarf::DW_TAG_label)
978 Entry.CU->addFunctionRange(
980 Entry.CU->getContaingFile().Addresses->constrainCodeRangeHighPC(
981 *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