[llvm] r295749 - Teach the IR verifier to reject conflicting debug info for function arguments.

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 21 11:03:15 PST 2017


Author: adrian
Date: Tue Feb 21 13:03:15 2017
New Revision: 295749

URL: http://llvm.org/viewvc/llvm-project?rev=295749&view=rev
Log:
Teach the IR verifier to reject conflicting debug info for function arguments.

Conflicting debug info for function arguments causes hard-to-debug
assertions in the DWARF backend, so the Verifier should reject it.
For performance reasons this only checks function arguments from
non-inlined debug intrinsics for now.

rdar://problem/30520286

Added:
    llvm/trunk/test/Verifier/fnarg-debuginfo.ll
Modified:
    llvm/trunk/lib/IR/Verifier.cpp

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=295749&r1=295748&r2=295749&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Tue Feb 21 13:03:15 2017
@@ -297,6 +297,9 @@ class Verifier : public InstVisitor<Veri
   // constant expressions, we can arrive at a particular user many times.
   SmallPtrSet<const Value *, 32> GlobalValueVisited;
 
+  // Keeps track of duplicate function argument debug info.
+  SmallVector<const DILocalVariable *, 16> DebugFnArgs;
+
   TBAAVerifier TBAAVerifyHelper;
 
   void checkAtomicMemAccessSize(Type *Ty, const Instruction *I);
@@ -498,6 +501,7 @@ private:
   void verifySiblingFuncletUnwinds();
 
   void verifyFragmentExpression(const DbgInfoIntrinsic &I);
+  void verifyFnArgs(const DbgInfoIntrinsic &I);
 
   /// Module-level debug info verification...
   void verifyCompileUnits();
@@ -1946,6 +1950,8 @@ void Verifier::verifySiblingFuncletUnwin
 // visitFunction - Verify that a function is ok.
 //
 void Verifier::visitFunction(const Function &F) {
+  DebugFnArgs.clear();
+
   visitGlobalValue(F);
 
   // Check function arguments.
@@ -4348,6 +4354,8 @@ void Verifier::visitDbgIntrinsic(StringR
                                " variable and !dbg attachment",
            &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
            Loc->getScope()->getSubprogram());
+
+  verifyFnArgs(DII);
 }
 
 static uint64_t getVariableSize(const DILocalVariable &V) {
@@ -4416,6 +4424,36 @@ void Verifier::verifyFragmentExpression(
   AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E);
 }
 
+void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) {
+  DILocalVariable *Var;
+  if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
+    // For performance reasons only check non-inlined ones.
+    if (DV->getDebugLoc()->getInlinedAt())
+      return;
+    Var = DV->getVariable();
+  } else {
+    auto *DD = cast<DbgDeclareInst>(&I);
+    if (DD->getDebugLoc()->getInlinedAt())
+      return;
+    Var = DD->getVariable();
+  }
+  AssertDI(Var, "dbg intrinsic without variable");
+
+  unsigned ArgNo = Var->getArg();
+  if (!ArgNo)
+    return;
+
+  // Verify there are no duplicate function argument debug info entries.
+  // These will cause hard-to-debug assertions in the DWARF backend.
+  if (DebugFnArgs.size() < ArgNo)
+    DebugFnArgs.resize(ArgNo, nullptr);
+
+  auto *Prev = DebugFnArgs[ArgNo - 1];
+  DebugFnArgs[ArgNo - 1] = Var;
+  AssertDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,
+           Prev, Var);
+}
+
 void Verifier::verifyCompileUnits() {
   auto *CUs = M.getNamedMetadata("llvm.dbg.cu");
   SmallPtrSet<const Metadata *, 2> Listed;

Added: llvm/trunk/test/Verifier/fnarg-debuginfo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/fnarg-debuginfo.ll?rev=295749&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/fnarg-debuginfo.ll (added)
+++ llvm/trunk/test/Verifier/fnarg-debuginfo.ll Tue Feb 21 13:03:15 2017
@@ -0,0 +1,26 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) 
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
+
+define void @foo() !dbg !2 {
+entry:
+  %a = alloca i32
+  ; CHECK: conflicting debug info for argument
+  call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !3, metadata !DIExpression()), !dbg !6
+  call void @llvm.dbg.declare(metadata i32* %a, metadata !4, metadata !DIExpression()), !dbg !6
+  ret void, !dbg !6
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", emissionKind: FullDebug)
+!1 = !DIFile(filename: "x.c", directory: "/")
+!2 = distinct !DISubprogram(name: "foo", scope: !0, isDefinition: true, unit: !0)
+!3 = !DILocalVariable(name: "a", arg: 1, scope: !2, file: !1, line: 1, type: !5)
+!4 = !DILocalVariable(name: "b", arg: 1, scope: !2, file: !1, line: 1, type: !5)
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!6 = !DILocation(line: 1, scope: !2)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 1, !"Debug Info Version", i32 3}




More information about the llvm-commits mailing list