[DebugInfo] Add Verifier check for duplicate arg indices in SP's retainedNodes list (#186225)

DwarfFile asserts if two arguments of the same subprogram with the same
index are present in a DISubprogram scope:
5d7a502a9d/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp (L110)

This patch adds a check to the Verifier to detect such invalid IR
earlier. It can be helpful for finding reproducers for bugs like
https://issues.chromium.org/issues/40288032.

The incorrect args field of DILocalVariable in
llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir is fixed.
This commit is contained in:
Vladislav Dzhidzhoev 2026-03-13 14:51:41 +01:00 committed by GitHub
parent 991fd93780
commit c513ed117f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 14 additions and 1 deletions

View File

@ -1630,6 +1630,8 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
if (auto *RawNode = N.getRawRetainedNodes()) {
auto *Node = dyn_cast<MDTuple>(RawNode);
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
DenseMap<unsigned, DILocalVariable *> Args;
for (Metadata *Op : Node->operands()) {
CheckDI(Op, "nullptr in retained nodes", &N, Node);
@ -1657,6 +1659,17 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
"invalid retained nodes, retained node does not belong to subprogram",
&N, Node, RetainedNode, RetainedNodeScope, RetainedNodeSP,
RetainedNodeUnit);
auto *DV = dyn_cast<DILocalVariable>(RetainedNode);
if (!DV)
continue;
if (unsigned ArgNum = DV->getArg()) {
auto [ArgI, Inserted] = Args.insert({ArgNum, DV});
CheckDI(Inserted || DV == ArgI->second,
"invalid retained nodes, more than one local variable with the "
"same argument index",
&N, N.getUnit(), Node, RetainedNode, Args[ArgNum]);
}
}
}
CheckDI(!hasConflictingReferenceFlags(N.getFlags()),

View File

@ -95,7 +95,7 @@
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12, !13}
!12 = !DILocalVariable(name: "arg1", arg: 1, scope: !7, file: !1, line: 6, type: !10)
!13 = !DILocalVariable(name: "var1", arg: 1, scope: !7, file: !1, line: 6, type: !10)
!13 = !DILocalVariable(name: "var1", scope: !7, file: !1, line: 6, type: !10)
!15 = !DILocation(line: 6, column: 13, scope: !7)
!20 = !{!21, !21, i64 0}
!21 = !{!"int", !22, i64 0}