diff options
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 38 | ||||
-rw-r--r-- | llvm/test/Verifier/fnarg-debuginfo.ll | 26 |
2 files changed, 64 insertions, 0 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 90017354631..deba84dbb96 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -297,6 +297,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { // 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(); @@ -1947,6 +1951,8 @@ void Verifier::verifySiblingFuncletUnwinds() { // visitFunction - Verify that a function is ok. // void Verifier::visitFunction(const Function &F) { + DebugFnArgs.clear(); + visitGlobalValue(F); // Check function arguments. @@ -4349,6 +4355,8 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { " variable and !dbg attachment", &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc, Loc->getScope()->getSubprogram()); + + verifyFnArgs(DII); } static uint64_t getVariableSize(const DILocalVariable &V) { @@ -4417,6 +4425,36 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { 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; diff --git a/llvm/test/Verifier/fnarg-debuginfo.ll b/llvm/test/Verifier/fnarg-debuginfo.ll new file mode 100644 index 00000000000..7cbe9ce93b9 --- /dev/null +++ b/llvm/test/Verifier/fnarg-debuginfo.ll @@ -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} |