From c513ed117f5cdef6598ac6b5b589b43c19d66173 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Fri, 13 Mar 2026 14:51:41 +0100 Subject: [PATCH] [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: https://github.com/llvm/llvm-project/blob/5d7a502a9d923784abe4382ec479ee1c0667d743/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. --- llvm/lib/IR/Verifier.cpp | 13 +++++++++++++ .../MIR/X86/live-debug-values-reg-copy.mir | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index b35ccd3d6e78..3cdc75ca9869 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1630,6 +1630,8 @@ void Verifier::visitDISubprogram(const DISubprogram &N) { if (auto *RawNode = N.getRawRetainedNodes()) { auto *Node = dyn_cast(RawNode); CheckDI(Node, "invalid retained nodes list", &N, RawNode); + + DenseMap 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(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()), diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir index 1f9cc7542fd9..abd50477f3d0 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir @@ -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}