[DebugInfo] Add Verifier check for incorrectly-scoped retainedNodes#166855
[DebugInfo] Add Verifier check for incorrectly-scoped retainedNodes#166855dzhidzhoev merged 2 commits intollvm:mainfrom
Conversation
These checks ensure that retained nodes of a DISubprogram belong to the subprogram. This was helpful to find issues with https://reviews.llvm.org/D144004, llvm#75385, llvm#165032. Also, interface for accessing DISubprogram's retained nodes is slightly refactored. `DISubprogram::visitRetainedNodes` and `DISubprogram::forEachRetainedNode` are added to avoid repeating checks like ``` if (const auto *LV = dyn_cast<DILocalVariable>(N)) ... else if (const auto *L = dyn_cast<DILabel>(N)) ... else if (const auto *IE = dyn_cast<DIImportedEntity>(N)) ... ``` Tests with wrongly scoped retained nodes are fixed.
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-ir Author: Vladislav Dzhidzhoev (dzhidzhoev) ChangesThese checks ensure that retained nodes of a DISubprogram belong to the subprogram. They were helpful to investigate issues with https://reviews.llvm.org/D144004, #75385, #165032. Also, interface for accessing DISubprogram's retained nodes is slightly refactored. Tests with incorrectly-scoped retained nodes are fixed. Patch is 39.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/166855.diff 24 Files Affected:
diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index 33e6df0ecb873..862293c9666a7 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -108,7 +108,7 @@ class DebugInfoFinder {
LLVM_ABI void processInstruction(const Module &M, const Instruction &I);
/// Process a DILocalVariable.
- LLVM_ABI void processVariable(DILocalVariable *DVI);
+ LLVM_ABI void processVariable(const DILocalVariable *DVI);
/// Process debug info location.
LLVM_ABI void processLocation(const Module &M, const DILocation *Loc);
/// Process a DbgRecord.
@@ -124,7 +124,7 @@ class DebugInfoFinder {
void processCompileUnit(DICompileUnit *CU);
void processScope(DIScope *Scope);
void processType(DIType *DT);
- void processImportedEntity(DIImportedEntity *Import);
+ void processImportedEntity(const DIImportedEntity *Import);
bool addCompileUnit(DICompileUnit *CU);
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
bool addScope(DIScope *Scope);
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 7ade6b8e13308..e6dfa008e808e 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2554,6 +2554,40 @@ class DISubprogram : public DILocalScope {
replaceOperandWith(7, N.get());
}
+ /// For the given retained node of DISubprogram, applies one of the
+ /// given functions depending on the type of the node.
+ template <typename T, typename FuncLVT, typename FuncLabelT,
+ typename FuncImportedEntityT, typename FuncUnknownT>
+ static T
+ visitRetainedNode(const Metadata *N, FuncLVT &&FuncLV, FuncLabelT &&FuncLabel,
+ FuncImportedEntityT &&FuncIE, FuncUnknownT &&FuncUnknown) {
+ if (const auto *LV = dyn_cast<DILocalVariable>(N))
+ return FuncLV(LV);
+ else if (const auto *L = dyn_cast<DILabel>(N))
+ return FuncLabel(L);
+ else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
+ return FuncIE(IE);
+ else
+ return FuncUnknown(N);
+ }
+
+ /// Returns the scope of subprogram's retainedNodes.
+ static const DILocalScope *getRetainedNodeScope(const MDNode *N);
+ // For use in Verifier.
+ static const DIScope *getRawRetainedNodeScope(const MDNode *N);
+
+ /// For each retained node, applies one of the given functions depending
+ /// on the type of a node.
+ template <typename FuncLVT, typename FuncLabelT, typename FuncImportedEntityT>
+ void forEachRetainedNode(FuncLVT &&FuncLV, FuncLabelT &&FuncLabel,
+ FuncImportedEntityT &&FuncIE) const {
+ for (MDNode *N : getRetainedNodes())
+ visitRetainedNode<void>(N, FuncLV, FuncLabel, FuncIE,
+ [](const Metadata *N) {
+ llvm_unreachable("Unexpected retained node!");
+ });
+ }
+
/// Check if this subprogram describes the given function.
///
/// FIXME: Should this be looking through bitcasts?
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 567acf75d1b8d..fde48a30a8203 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1544,18 +1544,8 @@ void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
}
static const DILocalScope *getRetainedNodeScope(const MDNode *N) {
- const DIScope *S;
- if (const auto *LV = dyn_cast<DILocalVariable>(N))
- S = LV->getScope();
- else if (const auto *L = dyn_cast<DILabel>(N))
- S = L->getScope();
- else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
- S = IE->getScope();
- else
- llvm_unreachable("Unexpected retained node!");
-
// Ensure the scope is not a DILexicalBlockFile.
- return cast<DILocalScope>(S)->getNonLexicalBlockFileScope();
+ return DISubprogram::getRetainedNodeScope(N)->getNonLexicalBlockFileScope();
}
// Collect variable information from side table maintained by MF.
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 58836068a4929..4c5fb742aa3eb 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -247,7 +247,7 @@ void DebugInfoFinder::processType(DIType *DT) {
}
}
-void DebugInfoFinder::processImportedEntity(DIImportedEntity *Import) {
+void DebugInfoFinder::processImportedEntity(const DIImportedEntity *Import) {
auto *Entity = Import->getEntity();
if (auto *T = dyn_cast<DIType>(Entity))
processType(T);
@@ -307,15 +307,13 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
}
}
- for (auto *N : SP->getRetainedNodes()) {
- if (auto *Var = dyn_cast_or_null<DILocalVariable>(N))
- processVariable(Var);
- else if (auto *Import = dyn_cast_or_null<DIImportedEntity>(N))
- processImportedEntity(Import);
- }
+ SP->forEachRetainedNode(
+ [this](const DILocalVariable *LV) { processVariable(LV); },
+ [](const DILabel *L) {},
+ [this](const DIImportedEntity *IE) { processImportedEntity(IE); });
}
-void DebugInfoFinder::processVariable(DILocalVariable *DV) {
+void DebugInfoFinder::processVariable(const DILocalVariable *DV) {
if (!NodesSeen.insert(DV).second)
return;
processScope(DV->getScope());
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index a98e925b6f1d8..1a6a25e161803 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1441,6 +1441,19 @@ bool DISubprogram::describes(const Function *F) const {
assert(F && "Invalid function");
return F->getSubprogram() == this;
}
+
+const DIScope *DISubprogram::getRawRetainedNodeScope(const MDNode *N) {
+ return visitRetainedNode<DIScope *>(
+ N, [](const DILocalVariable *LV) { return LV->getScope(); },
+ [](const DILabel *L) { return L->getScope(); },
+ [](const DIImportedEntity *IE) { return IE->getScope(); },
+ [](const Metadata *N) { return nullptr; });
+}
+
+const DILocalScope *DISubprogram::getRetainedNodeScope(const MDNode *N) {
+ return cast<DILocalScope>(getRawRetainedNodeScope(N));
+}
+
DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID,
StorageType Storage,
ArrayRef<Metadata *> Ops)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f1e473a78e3ac..b1632246c5f39 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1559,11 +1559,27 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
auto *Node = dyn_cast<MDTuple>(RawNode);
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
for (Metadata *Op : Node->operands()) {
- CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) ||
- isa<DIImportedEntity>(Op)),
+ CheckDI(Op, "nullptr in retained nodes", &N, Node);
+
+ auto True = [](const Metadata *) { return true; };
+ auto False = [](const Metadata *) { return false; };
+ bool IsTypeCorrect =
+ DISubprogram::visitRetainedNode<bool>(Op, True, True, True, False);
+ CheckDI(IsTypeCorrect,
"invalid retained nodes, expected DILocalVariable, DILabel or "
"DIImportedEntity",
&N, Node, Op);
+
+ auto *RetainedNode = cast<DINode>(Op);
+ auto *RetainedNodeScope = dyn_cast_or_null<DILocalScope>(
+ DISubprogram::getRawRetainedNodeScope(RetainedNode));
+ CheckDI(RetainedNodeScope,
+ "invalid retained nodes, retained node is not local", &N, Node,
+ RetainedNode);
+ CheckDI(
+ RetainedNodeScope->getSubprogram() == &N,
+ "invalid retained nodes, retained node does not belong to subprogram",
+ &N, Node, RetainedNode, RetainedNodeScope);
}
}
CheckDI(!hasConflictingReferenceFlags(N.getFlags()),
diff --git a/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir b/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
index 348a2901ff6a4..24453066f2583 100644
--- a/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
+++ b/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
@@ -55,7 +55,7 @@
!9 = !DILocalVariable(name: "4", scope: !5, file: !1, line: 4, type: !10)
!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
!11 = !DILocation(line: 4, column: 1, scope: !5)
- !12 = distinct !DISubprogram(name: "test_2", linkageName: "test_2", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+ !12 = distinct !DISubprogram(name: "test_2", linkageName: "test_2", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
...
---
diff --git a/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir b/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
index a334e99b9cade..ea01835cae1e5 100644
--- a/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
+++ b/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
@@ -85,10 +85,11 @@
!15 = !DISubrange(count: 3)
!16 = !DILocation(line: 8, scope: !8)
!17 = !DILocation(line: 9, scope: !8)
- !18 = distinct !DISubprogram(name: "test2", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !11)
+ !18 = distinct !DISubprogram(name: "test2", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !22)
!19 = !DILocalVariable(name: "local", scope: !18, file: !2, line: 8, type: !13)
!20 = !DILocation(line: 15, scope: !18)
!21 = !DILocation(line: 16, scope: !18)
+ !22 = !{!19}
...
---
diff --git a/llvm/test/DebugInfo/MIR/X86/machine-cse.mir b/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
index c38c0a1a79f75..63dc44fb705fe 100644
--- a/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
+++ b/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
@@ -73,13 +73,14 @@
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug)
!2 = !DIFile(filename: "bees.cpp", directory: "")
- !3 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
- !33 = distinct !DISubprogram(name: "alsonope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
+ !3 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !9)
+ !33 = distinct !DISubprogram(name: "alsonope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !9)
!4 = !DILocalVariable(name: "bees", scope: !3, type: !5)
!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!7 = !DILocation(line: 0, scope: !3)
!8 = !{!4}
+ !9 = !{}
; CHECK: ![[METAVAR:[0-9]+]] = !DILocalVariable(name: "bees",
diff --git a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
index 06ce18d8edaa7..28fc044e606b5 100644
--- a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
+++ b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
@@ -139,15 +139,15 @@
!23 = !DISubprogram(name: "bar", scope: !1, file: !1, line: 1, type: !24, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
!24 = !DISubroutineType(types: !25)
!25 = !{null, !11}
- !26 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !26 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!27 = !DILocation(line: 0, scope: !26)
- !28 = distinct !DISubprogram(name: "foo3", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !28 = distinct !DISubprogram(name: "foo3", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!29 = !DILocation(line: 0, scope: !28)
- !30 = distinct !DISubprogram(name: "foo4", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !30 = distinct !DISubprogram(name: "foo4", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!31 = !DILocation(line: 0, scope: !30)
- !32 = distinct !DISubprogram(name: "foo5", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !32 = distinct !DISubprogram(name: "foo5", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!33 = !DILocation(line: 0, scope: !32)
- !34 = distinct !DISubprogram(name: "foo6", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !34 = distinct !DISubprogram(name: "foo6", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!35 = !DILocation(line: 0, scope: !34)
...
diff --git a/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
index dbbef2b39587d..594607c6e95d8 100644
--- a/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
+++ b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
@@ -281,15 +281,19 @@ lala:
!11 = !{!13}
!13 = !DILocalVariable(name: "baz", scope: !7, file: !1, line: 6, type: !10)
!14 = !DILocation(line: 1, scope: !7)
-!20 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!20 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !23)
!21 = !DILocalVariable(name: "xyzzy", scope: !20, file: !1, line: 6, type: !10)
!22 = !DILocation(line: 1, scope: !20)
-!30 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!23 = !{!21}
+!30 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !33)
!31 = !DILocalVariable(name: "xyzzy", scope: !30, file: !1, line: 6, type: !10)
!32 = !DILocation(line: 1, scope: !30)
-!40 = distinct !DISubprogram(name: "qux", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!33 = !{!31}
+!40 = distinct !DISubprogram(name: "qux", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !46)
!41 = !DILocalVariable(name: "socks", scope: !40, file: !1, line: 6, type: !10)
!42 = !DILocation(line: 1, scope: !40)
-!43 = distinct !DISubprogram(name: "inlined", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!43 = distinct !DISubprogram(name: "inlined", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !47)
!44 = !DILocation(line: 0, scope: !43, inlinedAt: !42)
!45 = !DILocalVariable(name: "knees", scope: !43, file: !1, line: 6, type: !10)
+!46 = !{!41}
+!47 = !{!45}
diff --git a/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir b/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
index 8a0537658c9c0..2900f0bdcf864 100644
--- a/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
+++ b/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
@@ -82,15 +82,18 @@
!14 = !DISubroutineType(types: !15)
!15 = !{!16}
!16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
- !40 = distinct !DISubprogram(name: "bar", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !40 = distinct !DISubprogram(name: "bar", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !43, type: !14, isDefinition: true)
!41 = !DILocalVariable(name: "towel", scope: !40, file: !2, line: 1, type: !16)
!42 = !DILocation(line: 40, scope: !40)
- !80 = distinct !DISubprogram(name: "baz", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !43 = !{!41}
+ !80 = distinct !DISubprogram(name: "baz", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !83, type: !14, isDefinition: true)
!81 = !DILocalVariable(name: "socks", scope: !80, file: !2, line: 1, type: !16)
!82 = !DILocation(line: 40, scope: !80)
- !120 = distinct !DISubprogram(name: "qux", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !83 = !{!81}
+ !120 = distinct !DISubprogram(name: "qux", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !123, type: !14, isDefinition: true)
!121 = !DILocalVariable(name: "shoes", scope: !120, file: !2, line: 1, type: !16)
!122 = !DILocation(line: 40, scope: !120)
+ !123 = !{!121}
...
---
diff --git a/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll b/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
index e656c6237c068..145b5045687cf 100644
--- a/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
+++ b/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
@@ -108,6 +108,6 @@ exit:
!106 = !DILocation(line: 1, scope: !104)
!113 = !{!103}
!203 = !DILocalVariable(name: "teacake", scope: !204, file: !2, line: 1, type: !16)
-!204 = distinct !DISubprogram(name: "toad", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !113, type: !14, isDefinition: true)
+!204 = distinct !DISubprogram(name: "toad", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !213, type: !14, isDefinition: true)
!206 = !DILocation(line: 1, scope: !204)
!213 = !{!203}
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
index 3beaf8996e4f0..ab57a9612702f 100644
--- a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
+++ b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
@@ -91,7 +91,7 @@
!10 = !{!11}
!11 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 3, type: !9)
!12 = !DILocation(line: 3, column: 12, scope: !6)
- !13 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+ !13 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimize...
[truncated]
|
|
@llvm/pr-subscribers-backend-x86 Author: Vladislav Dzhidzhoev (dzhidzhoev) ChangesThese checks ensure that retained nodes of a DISubprogram belong to the subprogram. They were helpful to investigate issues with https://reviews.llvm.org/D144004, #75385, #165032. Also, interface for accessing DISubprogram's retained nodes is slightly refactored. Tests with incorrectly-scoped retained nodes are fixed. Patch is 39.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/166855.diff 24 Files Affected:
diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index 33e6df0ecb873..862293c9666a7 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -108,7 +108,7 @@ class DebugInfoFinder {
LLVM_ABI void processInstruction(const Module &M, const Instruction &I);
/// Process a DILocalVariable.
- LLVM_ABI void processVariable(DILocalVariable *DVI);
+ LLVM_ABI void processVariable(const DILocalVariable *DVI);
/// Process debug info location.
LLVM_ABI void processLocation(const Module &M, const DILocation *Loc);
/// Process a DbgRecord.
@@ -124,7 +124,7 @@ class DebugInfoFinder {
void processCompileUnit(DICompileUnit *CU);
void processScope(DIScope *Scope);
void processType(DIType *DT);
- void processImportedEntity(DIImportedEntity *Import);
+ void processImportedEntity(const DIImportedEntity *Import);
bool addCompileUnit(DICompileUnit *CU);
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
bool addScope(DIScope *Scope);
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 7ade6b8e13308..e6dfa008e808e 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2554,6 +2554,40 @@ class DISubprogram : public DILocalScope {
replaceOperandWith(7, N.get());
}
+ /// For the given retained node of DISubprogram, applies one of the
+ /// given functions depending on the type of the node.
+ template <typename T, typename FuncLVT, typename FuncLabelT,
+ typename FuncImportedEntityT, typename FuncUnknownT>
+ static T
+ visitRetainedNode(const Metadata *N, FuncLVT &&FuncLV, FuncLabelT &&FuncLabel,
+ FuncImportedEntityT &&FuncIE, FuncUnknownT &&FuncUnknown) {
+ if (const auto *LV = dyn_cast<DILocalVariable>(N))
+ return FuncLV(LV);
+ else if (const auto *L = dyn_cast<DILabel>(N))
+ return FuncLabel(L);
+ else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
+ return FuncIE(IE);
+ else
+ return FuncUnknown(N);
+ }
+
+ /// Returns the scope of subprogram's retainedNodes.
+ static const DILocalScope *getRetainedNodeScope(const MDNode *N);
+ // For use in Verifier.
+ static const DIScope *getRawRetainedNodeScope(const MDNode *N);
+
+ /// For each retained node, applies one of the given functions depending
+ /// on the type of a node.
+ template <typename FuncLVT, typename FuncLabelT, typename FuncImportedEntityT>
+ void forEachRetainedNode(FuncLVT &&FuncLV, FuncLabelT &&FuncLabel,
+ FuncImportedEntityT &&FuncIE) const {
+ for (MDNode *N : getRetainedNodes())
+ visitRetainedNode<void>(N, FuncLV, FuncLabel, FuncIE,
+ [](const Metadata *N) {
+ llvm_unreachable("Unexpected retained node!");
+ });
+ }
+
/// Check if this subprogram describes the given function.
///
/// FIXME: Should this be looking through bitcasts?
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 567acf75d1b8d..fde48a30a8203 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1544,18 +1544,8 @@ void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
}
static const DILocalScope *getRetainedNodeScope(const MDNode *N) {
- const DIScope *S;
- if (const auto *LV = dyn_cast<DILocalVariable>(N))
- S = LV->getScope();
- else if (const auto *L = dyn_cast<DILabel>(N))
- S = L->getScope();
- else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
- S = IE->getScope();
- else
- llvm_unreachable("Unexpected retained node!");
-
// Ensure the scope is not a DILexicalBlockFile.
- return cast<DILocalScope>(S)->getNonLexicalBlockFileScope();
+ return DISubprogram::getRetainedNodeScope(N)->getNonLexicalBlockFileScope();
}
// Collect variable information from side table maintained by MF.
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 58836068a4929..4c5fb742aa3eb 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -247,7 +247,7 @@ void DebugInfoFinder::processType(DIType *DT) {
}
}
-void DebugInfoFinder::processImportedEntity(DIImportedEntity *Import) {
+void DebugInfoFinder::processImportedEntity(const DIImportedEntity *Import) {
auto *Entity = Import->getEntity();
if (auto *T = dyn_cast<DIType>(Entity))
processType(T);
@@ -307,15 +307,13 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
}
}
- for (auto *N : SP->getRetainedNodes()) {
- if (auto *Var = dyn_cast_or_null<DILocalVariable>(N))
- processVariable(Var);
- else if (auto *Import = dyn_cast_or_null<DIImportedEntity>(N))
- processImportedEntity(Import);
- }
+ SP->forEachRetainedNode(
+ [this](const DILocalVariable *LV) { processVariable(LV); },
+ [](const DILabel *L) {},
+ [this](const DIImportedEntity *IE) { processImportedEntity(IE); });
}
-void DebugInfoFinder::processVariable(DILocalVariable *DV) {
+void DebugInfoFinder::processVariable(const DILocalVariable *DV) {
if (!NodesSeen.insert(DV).second)
return;
processScope(DV->getScope());
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index a98e925b6f1d8..1a6a25e161803 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1441,6 +1441,19 @@ bool DISubprogram::describes(const Function *F) const {
assert(F && "Invalid function");
return F->getSubprogram() == this;
}
+
+const DIScope *DISubprogram::getRawRetainedNodeScope(const MDNode *N) {
+ return visitRetainedNode<DIScope *>(
+ N, [](const DILocalVariable *LV) { return LV->getScope(); },
+ [](const DILabel *L) { return L->getScope(); },
+ [](const DIImportedEntity *IE) { return IE->getScope(); },
+ [](const Metadata *N) { return nullptr; });
+}
+
+const DILocalScope *DISubprogram::getRetainedNodeScope(const MDNode *N) {
+ return cast<DILocalScope>(getRawRetainedNodeScope(N));
+}
+
DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID,
StorageType Storage,
ArrayRef<Metadata *> Ops)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f1e473a78e3ac..b1632246c5f39 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1559,11 +1559,27 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
auto *Node = dyn_cast<MDTuple>(RawNode);
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
for (Metadata *Op : Node->operands()) {
- CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) ||
- isa<DIImportedEntity>(Op)),
+ CheckDI(Op, "nullptr in retained nodes", &N, Node);
+
+ auto True = [](const Metadata *) { return true; };
+ auto False = [](const Metadata *) { return false; };
+ bool IsTypeCorrect =
+ DISubprogram::visitRetainedNode<bool>(Op, True, True, True, False);
+ CheckDI(IsTypeCorrect,
"invalid retained nodes, expected DILocalVariable, DILabel or "
"DIImportedEntity",
&N, Node, Op);
+
+ auto *RetainedNode = cast<DINode>(Op);
+ auto *RetainedNodeScope = dyn_cast_or_null<DILocalScope>(
+ DISubprogram::getRawRetainedNodeScope(RetainedNode));
+ CheckDI(RetainedNodeScope,
+ "invalid retained nodes, retained node is not local", &N, Node,
+ RetainedNode);
+ CheckDI(
+ RetainedNodeScope->getSubprogram() == &N,
+ "invalid retained nodes, retained node does not belong to subprogram",
+ &N, Node, RetainedNode, RetainedNodeScope);
}
}
CheckDI(!hasConflictingReferenceFlags(N.getFlags()),
diff --git a/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir b/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
index 348a2901ff6a4..24453066f2583 100644
--- a/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
+++ b/llvm/test/CodeGen/X86/StackColoring-dbg-invariance.mir
@@ -55,7 +55,7 @@
!9 = !DILocalVariable(name: "4", scope: !5, file: !1, line: 4, type: !10)
!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
!11 = !DILocation(line: 4, column: 1, scope: !5)
- !12 = distinct !DISubprogram(name: "test_2", linkageName: "test_2", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+ !12 = distinct !DISubprogram(name: "test_2", linkageName: "test_2", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
...
---
diff --git a/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir b/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
index a334e99b9cade..ea01835cae1e5 100644
--- a/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
+++ b/llvm/test/DebugInfo/MIR/X86/clobbered-fragments.mir
@@ -85,10 +85,11 @@
!15 = !DISubrange(count: 3)
!16 = !DILocation(line: 8, scope: !8)
!17 = !DILocation(line: 9, scope: !8)
- !18 = distinct !DISubprogram(name: "test2", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !11)
+ !18 = distinct !DISubprogram(name: "test2", scope: !2, file: !2, line: 7, type: !9, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !22)
!19 = !DILocalVariable(name: "local", scope: !18, file: !2, line: 8, type: !13)
!20 = !DILocation(line: 15, scope: !18)
!21 = !DILocation(line: 16, scope: !18)
+ !22 = !{!19}
...
---
diff --git a/llvm/test/DebugInfo/MIR/X86/machine-cse.mir b/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
index c38c0a1a79f75..63dc44fb705fe 100644
--- a/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
+++ b/llvm/test/DebugInfo/MIR/X86/machine-cse.mir
@@ -73,13 +73,14 @@
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug)
!2 = !DIFile(filename: "bees.cpp", directory: "")
- !3 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
- !33 = distinct !DISubprogram(name: "alsonope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
+ !3 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !9)
+ !33 = distinct !DISubprogram(name: "alsonope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !9)
!4 = !DILocalVariable(name: "bees", scope: !3, type: !5)
!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!7 = !DILocation(line: 0, scope: !3)
!8 = !{!4}
+ !9 = !{}
; CHECK: ![[METAVAR:[0-9]+]] = !DILocalVariable(name: "bees",
diff --git a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
index 06ce18d8edaa7..28fc044e606b5 100644
--- a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
+++ b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
@@ -139,15 +139,15 @@
!23 = !DISubprogram(name: "bar", scope: !1, file: !1, line: 1, type: !24, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
!24 = !DISubroutineType(types: !25)
!25 = !{null, !11}
- !26 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !26 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!27 = !DILocation(line: 0, scope: !26)
- !28 = distinct !DISubprogram(name: "foo3", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !28 = distinct !DISubprogram(name: "foo3", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!29 = !DILocation(line: 0, scope: !28)
- !30 = distinct !DISubprogram(name: "foo4", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !30 = distinct !DISubprogram(name: "foo4", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!31 = !DILocation(line: 0, scope: !30)
- !32 = distinct !DISubprogram(name: "foo5", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !32 = distinct !DISubprogram(name: "foo5", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!33 = !DILocation(line: 0, scope: !32)
- !34 = distinct !DISubprogram(name: "foo6", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !34 = distinct !DISubprogram(name: "foo6", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!35 = !DILocation(line: 0, scope: !34)
...
diff --git a/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
index dbbef2b39587d..594607c6e95d8 100644
--- a/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
+++ b/llvm/test/DebugInfo/X86/instr-ref-selectiondag.ll
@@ -281,15 +281,19 @@ lala:
!11 = !{!13}
!13 = !DILocalVariable(name: "baz", scope: !7, file: !1, line: 6, type: !10)
!14 = !DILocation(line: 1, scope: !7)
-!20 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!20 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !23)
!21 = !DILocalVariable(name: "xyzzy", scope: !20, file: !1, line: 6, type: !10)
!22 = !DILocation(line: 1, scope: !20)
-!30 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!23 = !{!21}
+!30 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !33)
!31 = !DILocalVariable(name: "xyzzy", scope: !30, file: !1, line: 6, type: !10)
!32 = !DILocation(line: 1, scope: !30)
-!40 = distinct !DISubprogram(name: "qux", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!33 = !{!31}
+!40 = distinct !DISubprogram(name: "qux", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !46)
!41 = !DILocalVariable(name: "socks", scope: !40, file: !1, line: 6, type: !10)
!42 = !DILocation(line: 1, scope: !40)
-!43 = distinct !DISubprogram(name: "inlined", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!43 = distinct !DISubprogram(name: "inlined", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !47)
!44 = !DILocation(line: 0, scope: !43, inlinedAt: !42)
!45 = !DILocalVariable(name: "knees", scope: !43, file: !1, line: 6, type: !10)
+!46 = !{!41}
+!47 = !{!45}
diff --git a/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir b/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
index 8a0537658c9c0..2900f0bdcf864 100644
--- a/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
+++ b/llvm/test/DebugInfo/X86/live-debug-values-constprop.mir
@@ -82,15 +82,18 @@
!14 = !DISubroutineType(types: !15)
!15 = !{!16}
!16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
- !40 = distinct !DISubprogram(name: "bar", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !40 = distinct !DISubprogram(name: "bar", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !43, type: !14, isDefinition: true)
!41 = !DILocalVariable(name: "towel", scope: !40, file: !2, line: 1, type: !16)
!42 = !DILocation(line: 40, scope: !40)
- !80 = distinct !DISubprogram(name: "baz", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !43 = !{!41}
+ !80 = distinct !DISubprogram(name: "baz", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !83, type: !14, isDefinition: true)
!81 = !DILocalVariable(name: "socks", scope: !80, file: !2, line: 1, type: !16)
!82 = !DILocation(line: 40, scope: !80)
- !120 = distinct !DISubprogram(name: "qux", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !13, type: !14, isDefinition: true)
+ !83 = !{!81}
+ !120 = distinct !DISubprogram(name: "qux", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !123, type: !14, isDefinition: true)
!121 = !DILocalVariable(name: "shoes", scope: !120, file: !2, line: 1, type: !16)
!122 = !DILocation(line: 40, scope: !120)
+ !123 = !{!121}
...
---
diff --git a/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll b/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
index e656c6237c068..145b5045687cf 100644
--- a/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
+++ b/llvm/test/DebugInfo/X86/live-debug-values-remove-range.ll
@@ -108,6 +108,6 @@ exit:
!106 = !DILocation(line: 1, scope: !104)
!113 = !{!103}
!203 = !DILocalVariable(name: "teacake", scope: !204, file: !2, line: 1, type: !16)
-!204 = distinct !DISubprogram(name: "toad", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !113, type: !14, isDefinition: true)
+!204 = distinct !DISubprogram(name: "toad", scope: !2, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !213, type: !14, isDefinition: true)
!206 = !DILocation(line: 1, scope: !204)
!213 = !{!203}
diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
index 3beaf8996e4f0..ab57a9612702f 100644
--- a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
+++ b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir
@@ -91,7 +91,7 @@
!10 = !{!11}
!11 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 3, type: !9)
!12 = !DILocation(line: 3, column: 12, scope: !6)
- !13 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+ !13 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimize...
[truncated]
|
| FuncImportedEntityT &&FuncIE, FuncUnknownT &&FuncUnknown) { | ||
| if (const auto *LV = dyn_cast<DILocalVariable>(N)) | ||
| return FuncLV(LV); | ||
| else if (const auto *L = dyn_cast<DILabel>(N)) |
jmorse
left a comment
There was a problem hiding this comment.
LGTM with an inline question. Are the test changes manual updates to fix the output of previous (faulty) LLVMs? (Thanks for the maintenance if so!)
| "invalid retained nodes, retained node is not local", &N, Node, | ||
| RetainedNode); | ||
| CheckDI( | ||
| RetainedNodeScope->getSubprogram() == &N, |
There was a problem hiding this comment.
Do we need to early-exit (or continue) if RetainedNodeScope is null?
There was a problem hiding this comment.
CheckDI(RetainedNodeScope, ...) macro invocation from above exits current function if the check fails.
Thank you! |
|
Very good; it's worth putting that in the commit message, so that future code-archeologists discovering strange test patterns can work out that it was manual editing that shaped the IR inputs, not a version of LLVM that they need to support. |
Added that. |
* main: (1028 commits) [clang][DebugInfo] Attach `DISubprogram` to additional call variants (llvm#166202) [C2y] Claim nonconformance to WG14 N3348 (llvm#166966) [X86] 2012-01-10-UndefExceptionEdge.ll - regenerate test checks (llvm#167307) Remove unused standard headers: <string>, <optional>, <numeric>, <tuple> (llvm#167232) [DebugInfo] Add Verifier check for incorrectly-scoped retainedNodes (llvm#166855) [VPlan] Don't apply predication discount to non-originally-predicated blocks (llvm#160449) [libc++] Avoid overloaded `operator,` for (`T`, `Iter`) cases (llvm#161049) [tools][llc] Make save-stats.ll test target independent (llvm#167238) [AArch64] Fallback to PRFUM for PRFM with negative or unaligned offset (llvm#166756) [X86] ldexp-avx512.ll - add v8f16/v16f16/v32f16 test coverage for llvm#165694 (llvm#167294) [DropAssumes] Drop dereferenceable assumptions after vectorization. (llvm#166947) [VPlan] Simplify branch-cond with getVectorTripCount (llvm#155604) Remove unused <algorithm> inclusion (llvm#166942) [AArch64] Combine subtract with borrow to SBC. (llvm#165271) [AArch64][SVE] Avoid redundant extend of unsigned i8/i16 extracts. (llvm#165863) [SPIRV] Fix failing assertion in SPIRVAsmPrinter (llvm#166909) [libc++] Merge insert/emplace(const_iterator, Args...) implementations (llvm#166470) [libc++] Replace __libcpp_is_final with a variable template (llvm#167137) [gn build] Port 152bda7 [libc++] Replace the last uses of __tuple_types with __type_list (llvm#167214) ...
|
This change triggered a failure for RISCV. Reproducer is attached: |
I think the problem occurs before LTO stage, when Could you please check whether it is a clang frontend issue, or LLVM backend issue? And, if possible, provide a C++ or LLVM IR reproducer, correspondingly. |
|
Hmmm, apparently, we are stumbling across a known side-effect of https://reviews.llvm.org/D39396 when generating some sort of trunks in clang:
This comment from the PR description is partially true. Let's consider the case when a subprogram is cloned together with a function. If we are at -O0 level, DISubprograms do not preserve local variables in retain nodes (in DIBuilder), therefore, the cloned function does not have wrongly-scoped local variable in retained nodes. But at non-O0 levels, we preserve local variables in the original DISubprogram's retainedNodes. Therefore, as It is said in https://reviews.llvm.org/D39396 that DISubprograms may have unresolved metadata node references at the moment of |
…bprogram This fixes an issue reported in llvm#166855 (comment), that had been revealed after llvm#166855 was merged. `CodeGenFunction::GenerateVarArgsThunk` creates thunks for vararg functions by cloning and modifying the function. It is different from `CodeGenFunction::generateThunk`, which is used for Itanium ABI. According to https://reviews.llvm.org/D39396, `CodeGenFunction::GenerateVarArgsThunk` may be called before metadata nodes are resolved. So, it tries to avoid remapping DISubprogram and all metadata nodes it references inside `CloneFunction()` by manually cloning DISubprogram. When optimization level is not OptNone, all local variables are saved in DISubprogram's retainedNodes field. When `CodeGenFunction::GenerateVarArgsThunk` clones such DISubprogram without remapping, it produces a subprogram with incorrectly-scoped retained nodes. It triggers Verifier checks added in llvm#166855. To solve that, retained nodes list of a cloned DISubprogram is cleared.
A (possible) fix for that #167758. |
…rogram (#167758) This fixes the issue reported in #166855 (comment) that had been revealed after #166855 was merged. `CodeGenFunction::GenerateVarArgsThunk` creates thunks for vararg functions by cloning and modifying them. It is different from `CodeGenFunction::generateThunk`, which is used for Itanium ABI. According to https://reviews.llvm.org/D39396, `CodeGenFunction::GenerateVarArgsThunk` may be called before metadata nodes are resolved. So, it tries to avoid remapping DISubprogram and all metadata nodes it references inside `CloneFunction()` by manually cloning DISubprogram. If optimization level is not OptNone, DILocalVariables for a function are saved in DISubprogram's retainedNodes field. When `CodeGenFunction::GenerateVarArgsThunk` clones such DISubprogram without remapping, it produces a subprogram with incorrectly-scoped retained nodes. It triggers Verifier checks added in #166855. To solve that, retained nodes list of a cloned DISubprogram is cleared.
…nk's DISubprogram (#167758) This fixes the issue reported in llvm/llvm-project#166855 (comment) that had been revealed after llvm/llvm-project#166855 was merged. `CodeGenFunction::GenerateVarArgsThunk` creates thunks for vararg functions by cloning and modifying them. It is different from `CodeGenFunction::generateThunk`, which is used for Itanium ABI. According to https://reviews.llvm.org/D39396, `CodeGenFunction::GenerateVarArgsThunk` may be called before metadata nodes are resolved. So, it tries to avoid remapping DISubprogram and all metadata nodes it references inside `CloneFunction()` by manually cloning DISubprogram. If optimization level is not OptNone, DILocalVariables for a function are saved in DISubprogram's retainedNodes field. When `CodeGenFunction::GenerateVarArgsThunk` clones such DISubprogram without remapping, it produces a subprogram with incorrectly-scoped retained nodes. It triggers Verifier checks added in llvm/llvm-project#166855. To solve that, retained nodes list of a cloned DISubprogram is cleared.
…rogram (#167758) This fixes the issue reported in llvm/llvm-project#166855 (comment) that had been revealed after llvm/llvm-project#166855 was merged. `CodeGenFunction::GenerateVarArgsThunk` creates thunks for vararg functions by cloning and modifying them. It is different from `CodeGenFunction::generateThunk`, which is used for Itanium ABI. According to https://reviews.llvm.org/D39396, `CodeGenFunction::GenerateVarArgsThunk` may be called before metadata nodes are resolved. So, it tries to avoid remapping DISubprogram and all metadata nodes it references inside `CloneFunction()` by manually cloning DISubprogram. If optimization level is not OptNone, DILocalVariables for a function are saved in DISubprogram's retainedNodes field. When `CodeGenFunction::GenerateVarArgsThunk` clones such DISubprogram without remapping, it produces a subprogram with incorrectly-scoped retained nodes. It triggers Verifier checks added in llvm/llvm-project#166855. To solve that, retained nodes list of a cloned DISubprogram is cleared. Signed-off-by: Hafidz Muzakky <[email protected]>
…rogram (llvm#167758) This fixes the issue reported in llvm#166855 (comment) that had been revealed after llvm#166855 was merged. `CodeGenFunction::GenerateVarArgsThunk` creates thunks for vararg functions by cloning and modifying them. It is different from `CodeGenFunction::generateThunk`, which is used for Itanium ABI. According to https://reviews.llvm.org/D39396, `CodeGenFunction::GenerateVarArgsThunk` may be called before metadata nodes are resolved. So, it tries to avoid remapping DISubprogram and all metadata nodes it references inside `CloneFunction()` by manually cloning DISubprogram. If optimization level is not OptNone, DILocalVariables for a function are saved in DISubprogram's retainedNodes field. When `CodeGenFunction::GenerateVarArgsThunk` clones such DISubprogram without remapping, it produces a subprogram with incorrectly-scoped retained nodes. It triggers Verifier checks added in llvm#166855. To solve that, retained nodes list of a cloned DISubprogram is cleared.
These checks ensure that retained nodes of a DISubprogram belong to the subprogram.
They were helpful to investigate issues with https://reviews.llvm.org/D144004, #75385, #165032.
Also, interface for accessing DISubprogram's retained nodes is slightly refactored.
DISubprogram::visitRetainedNodesandDISubprogram::forEachRetainedNodeare added to avoid repeating checks likeTests with incorrectly-scoped retained nodes are fixed.