diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 67f526fe91464..676ab15c563b4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1680,8 +1680,34 @@ void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, void DwarfCompileUnit::applyCommonDbgVariableAttributes(const DbgVariable &Var, DIE &VariableDie) { StringRef Name = Var.getName(); + DIE *CurrentDie = &VariableDie; + std::string FullName = ""; + unsigned lexicalBlockCount = 0; + // while(true) { + // DIE* ParentDIE = CurrentDie->getParent(); + // if (ParentDIE == nullptr) + // break; + // auto ParentName = ParentDIE->findAttribute(dwarf::DW_AT_linkage_name); + // if (ParentName.getAttribute() == 0) { + // auto PName = ParentDIE->findAttribute(dwarf::DW_AT_name); + // if (PName.getAttribute() == 0) { + // if (ParentDIE->getTag() == dwarf::DW_TAG_lexical_block) + // FullName.insert(0, "_" + + // std::string(std::to_string(++lexicalBlockCount))); + // goto label; + // } + // FullName.insert(0, PName.getDIEString().getString()); + // goto label; + // } + // FullName.insert(0, ParentName.getDIEString().getString()); + // label: + // CurrentDie = ParentDIE; + // if (ParentDIE->getTag() == dwarf::DW_TAG_compile_unit) + // break; + // } + std::string FinalName = FullName + Name.str(); if (!Name.empty()) - addString(VariableDie, dwarf::DW_AT_name, Name); + addString(VariableDie, dwarf::DW_AT_name, FinalName); const auto *DIVar = Var.getVariable(); if (DIVar) { if (uint32_t AlignInBytes = DIVar->getAlignInBytes()) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 3ce7829207cb6..1d55b86a7ba45 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -10590,6 +10590,9 @@ describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg, Register DestReg = DestSrc->Destination->getReg(); Register SrcReg = DestSrc->Source->getReg(); + if (!DestReg.isValid() || !SrcReg.isValid()) + return std::nullopt; + auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {}); // If the described register is the destination, just return the source. diff --git a/llvm/test/DebugInfo/AArch64/callsite.mir b/llvm/test/DebugInfo/AArch64/callsite.mir new file mode 100644 index 0000000000000..e3bd764db430b --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/callsite.mir @@ -0,0 +1,68 @@ +# This test should not crash when generating call-site information. +# It was created to make sure that if isCopyLikeInstr in TargetInstrInfo.h +# returns an undef Dest Reg or Src Reg, we don't try to get a SubReg for it. + +# RUN: llc --mtriple=arm64e-apple-ios -start-before=aarch64-asm-printer %s -filetype=obj -o /dev/null --emit-call-site-info +--- | + %struct.rtyuio = type { i8 } + define noundef i32 @aserty(ptr noundef %0, ptr noundef %1) local_unnamed_addr #0 !dbg !23 { + ret i32 0 + } + define void @asdfgh(ptr noundef %0, ptr noundef %1, i8 noundef zeroext %2) local_unnamed_addr #0 !dbg !53 { + %4 = alloca ptr + %5 = call ptr @llvm.stackguard() + %6 = alloca %struct.rtyuio + %7 = icmp eq ptr %1, null + br i1 %7, label %10, label %8 + %9 = tail call i8 @polkiokl(ptr noundef %0) #6 + br label %10 + ret void + } + declare i8 @polkiokl(ptr noundef) local_unnamed_addr #2 + !llvm.module.flags = !{!2, !8} + !llvm.dbg.cu = !{!9} + !2 = !{i32 2, !"Debug Info Version", i32 3} + !8 = !{i32 7, !"frame-pointer", i32 1} + !9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !10, emissionKind: FullDebug, sysroot: "/") + !10 = !DIFile(filename: "a.cpp", directory: "/") + !23 = distinct !DISubprogram(type: !27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, unit: !9, retainedNodes: !46) + !24 = distinct !DICompositeType(tag: DW_TAG_class_type, identifier: "yshscbshhdvcm") + !27 = !DISubroutineType(types: !28) + !28 = !{} + !30 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !33) + !33 = distinct !DICompositeType(tag: DW_TAG_structure_type, identifier: "tyruwyeuiwiybabd") + !36 = !DISubroutineType(types: !37) + !37 = !{} + !46 = !{} + !47 = !DILocalVariable(scope: !23, type: !48, flags: DIFlagArtificial | DIFlagObjectPointer) + !48 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64) + !49 = !DILocalVariable(scope: !23, type: !30) + !50 = !DILocation(scope: !23) + !51 = !DILocation(scope: !23) + !53 = distinct !DISubprogram(type: !36, unit: !9, retainedNodes: !54) + !54 = !{} +name: aserty +stack: + - { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: + - { bb: 0, offset: 9, fwdArgRegs: + - { arg: 2, reg: '$w2' } } +body: | + bb.0 (%ir-block.2): + DBG_VALUE $x0, $noreg, !47, !DIExpression(), debug-location !50 + DBG_VALUE $x1, $noreg, !49, !DIExpression(), debug-location !50 + frame-setup PACIBSP implicit-def $lr, implicit killed $lr, implicit $sp + early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.1), (store (s64) into %stack.0) + $fp = frame-setup ADDXri $sp, 0, 0 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + frame-setup CFI_INSTRUCTION offset $w30, -8 + frame-setup CFI_INSTRUCTION offset $w29, -16 + $x2 = ORRXrs $xzr, undef $noreg, 0, implicit $wzr, debug-location !51 + BL @asdfgh, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $x0, implicit killed $x1, implicit killed $w2, implicit-def $sp, debug-location !51 +... +name: asdfgh +body: | + bb.2 (%ir-block.10): diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp index a705e7d51d874..b13d2790d52ef 100644 --- a/llvm/tools/llvm-dwarfdump/Statistics.cpp +++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -275,7 +275,8 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix, StringMap &FnStatMap, GlobalStats &GlobalStats, LocationStats &LocStats, - AbstractOriginVarsTy *AbstractOriginVariables) { + AbstractOriginVarsTy *AbstractOriginVariables, + std::string Prefix) { const dwarf::Tag Tag = Die.getTag(); // Skip CU node. if (Tag == dwarf::DW_TAG_compile_unit) @@ -366,6 +367,23 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix, consumeError(Loc.takeError()); } else { HasLoc = true; + auto Name = Die.find(dwarf::DW_AT_name); + auto StringName = Name->getAsCString(); + if (!StringName) { + consumeError(StringName.takeError()); + auto AbsOrigin = Die.find(dwarf::DW_AT_abstract_origin); + if (AbsOrigin != std::nullopt) { + if (const char *Name = + Die.getAttributeValueAsReferencedDie(*AbsOrigin) + .getName(DINameKind::LinkageName)) { + llvm::outs() << "\nvariable name: " << Prefix << " " << Name + << "\n"; + } + } + } else { + std::string S(*StringName); + llvm::outs() << "\nvariable name: " << Prefix << " " << S << "\n"; + } // Get PC coverage. auto Default = find_if( *Loc, [](const DWARFLocationExpression &L) { return !L.Range; }); @@ -500,7 +518,7 @@ static void collectStatsRecursive( AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo, AbstractOriginVarsTyMap &LocalAbstractOriginFnInfo, FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed, - AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) { + std::string Prefix, AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) { // Skip NULL nodes. if (Die.isNULL()) return; @@ -609,7 +627,8 @@ static void collectStatsRecursive( } else { // Not a scope, visit the Die itself. It could be a variable. collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth, - FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr); + FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr, + Prefix); } // Set InlineDepth correctly for child recursion @@ -623,6 +642,65 @@ static void collectStatsRecursive( unsigned FormalParameterIndex = 0; DWARFDie Child = Die.getFirstChild(); while (Child) { + std::string PreName = ""; + if (Child.getTag() != dwarf::DW_TAG_formal_parameter && + Child.getTag() != dwarf::DW_TAG_variable) { + if (Child.getTag() == dwarf::DW_TAG_lexical_block) { + PreName = " LinkageName: _" + std::to_string(LexicalBlockIndex); + } else if (Child.getTag() == dwarf::DW_TAG_subprogram) { + if (auto AbsOrig = Child.find(dwarf::DW_AT_abstract_origin)) { + if (const char *Name = + Child.getAttributeValueAsReferencedDie(*AbsOrig).getName( + DINameKind::LinkageName)) { + PreName = " Subprogram: " + std::string(Name) + ", "; + } + } + if (auto LinkName = Child.find(dwarf::DW_AT_linkage_name)) { + if (auto CString = LinkName->getAsCString()) { + PreName = " Subprogram: " + std::string(*CString) + ", "; + } + } + } else if (auto AbsOrig = Child.find(dwarf::DW_AT_abstract_origin)) { + if (const char *Name = + Child.getAttributeValueAsReferencedDie(*AbsOrig).getName( + DINameKind::LinkageName)) { + if (Child.getTag() == dwarf::DW_TAG_namespace) + PreName = " Namespace: " + std::to_string(Child.getTag()) + " " + + std::string(Name) + ", "; + else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine) + PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) + + " " + std::string(Name) + ", "; + else + PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " + + std::string(Name) + ", "; + } + } else if (auto LinkName = Child.find(dwarf::DW_AT_linkage_name)) { + if (auto CString = LinkName->getAsCString()) { + if (Child.getTag() == dwarf::DW_TAG_namespace) + PreName = " Namespace: " + std::to_string(Child.getTag()) + " " + + std::string(*CString) + ", "; + else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine) + PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) + + " " + std::string(*CString) + ", "; + else + PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " + + std::string(*CString) + ", "; + } + } else if (auto Name = Child.find(dwarf::DW_AT_name)) { + if (auto CString = Name->getAsCString()) { + if (Child.getTag() == dwarf::DW_TAG_namespace) + PreName = " Namespace: " + std::to_string(Child.getTag()) + " " + + std::string(*CString) + ", "; + else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine) + PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) + + " " + std::string(*CString) + ", "; + else + PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " + + std::string(*CString) + ", "; + } + } + } + std::string ChildVarPrefix = VarPrefix; if (Child.getTag() == dwarf::DW_TAG_lexical_block) ChildVarPrefix += toHex(LexicalBlockIndex++) + '.'; @@ -633,7 +711,7 @@ static void collectStatsRecursive( Child, FnPrefix, ChildVarPrefix, BytesInScope, InlineDepth, FnStatMap, GlobalStats, LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo, LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed, - AbstractOriginVarsPtr); + Prefix + PreName, AbstractOriginVarsPtr); Child = Child.getSibling(); } @@ -885,10 +963,18 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, AbstractOriginVarsTyMap LocalAbstractOriginFnInfo; FunctionsWithAbstractOriginTy FnsWithAbstractOriginToBeProcessed; + auto CUName = CUDie.find(dwarf::DW_AT_name); + std::string name = ""; + if (CUName != std::nullopt) { + auto Sname = CUName->getAsCString(); + if (!Sname) + name.insert(0, *Sname); + } + collectStatsRecursive( CUDie, "/", "g", 0, 0, Statistics, GlobalStats, LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo, - LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed); + LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed, name); // collectZeroLocCovForVarsWithAbstractOrigin will filter out all // out-of-order DWARF functions that have been processed within it,