From 94255c8eb0bd037ad3f186f15b664ab680771358 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Wed, 15 Apr 2015 22:15:46 +0000 Subject: [PATCH] Verifier: Check that @llvm.dbg.* intrinsics have a !dbg attachment Before we start to rely on valid `!dbg` attachments, add a check to the verifier that `@llvm.dbg.*` intrinsics always have one. Also check that the `scope:` fields point at the same `MDSubprogram`. This is in the context of PR22778. The check that the `inlinedAt:` fields agree has baked for a while (since r234021), so I'll kill [1] the `MDLocalVariable::getInlinedAt()` field soon. [1]: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150330/269387.html Unfortunately, that means it's impossible to keep the current `Verifier` checks, which rely on comparing `inlinedAt:` fields. We'll be able to keep the checks I'm adding here. If this breaks your out-of-tree testcases, the upgrade script (add-dbg-to-intrinsics.sh) attached to PR22778 that I used for r235040 might fix them for you. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235048 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/DebugInfoMetadata.h | 8 ++- lib/IR/Verifier.cpp | 42 +++++++++++-- test/Verifier/llvm.dbg.declare-variable.ll | 3 +- .../llvm.dbg.intrinsic-dbg-attachment.ll | 61 +++++++++++++++++++ test/Verifier/llvm.dbg.value-expression.ll | 2 +- test/Verifier/llvm.dbg.value-variable.ll | 3 +- 6 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index e16e4319aa9..ffaab7e2be4 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1932,10 +1932,12 @@ public: /// \brief Check that a location is valid for this variable. /// - /// Check that \c DL has the same inlined-at location as this variable, - /// making them valid for the same \a DbgInfoIntrinsic. + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) bool isValidLocationForIntrinsic(const MDLocation *DL) const { - return getInlinedAt() == (DL ? DL->getInlinedAt() : nullptr); + return DL && getInlinedAt() == DL->getInlinedAt() && + getScope()->getSubprogram() == DL->getScope()->getSubprogram(); } /// \brief Get an inlined version of this variable. diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 2034f8b54f8..3df885ac8f9 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -3361,6 +3361,25 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { }; } +/// \brief Carefully grab the subprogram from a local scope. +/// +/// This carefully grabs the subprogram from a local scope, avoiding the +/// built-in assertions that would typically fire. +static MDSubprogram *getSubprogram(Metadata *LocalScope) { + if (!LocalScope) + return nullptr; + + if (auto *SP = dyn_cast(LocalScope)) + return SP; + + if (auto *LB = dyn_cast(LocalScope)) + return getSubprogram(LB->getRawScope()); + + // Just return null; broken scope chains are checked elsewhere. + assert(!isa(LocalScope) && "Unknown type of local scope"); + return nullptr; +} + template void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { auto *MD = cast(DII.getArgOperand(0))->getMetadata(); @@ -3379,14 +3398,29 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { if (!isa(N)) return; + BasicBlock *BB = DII.getParent(); + Function *F = BB ? BB->getParent() : nullptr; + // The inlined-at attachments for variables and !dbg attachments must agree. MDLocalVariable *Var = DII.getVariable(); MDLocation *VarIA = Var->getInlinedAt(); MDLocation *Loc = DII.getDebugLoc(); - MDLocation *LocIA = Loc ? Loc->getInlinedAt() : nullptr; - BasicBlock *BB = DII.getParent(); - Assert(VarIA == LocIA, "mismatched variable and !dbg inlined-at", &DII, BB, - BB ? BB->getParent() : nullptr, Var, VarIA, Loc, LocIA); + Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", + &DII, BB, F); + + MDLocation *LocIA = Loc->getInlinedAt(); + Assert(VarIA == LocIA, "mismatched variable and !dbg inlined-at", &DII, BB, F, + Var, VarIA, Loc, LocIA); + + MDSubprogram *VarSP = getSubprogram(Var->getRawScope()); + MDSubprogram *LocSP = getSubprogram(Loc->getRawScope()); + if (!VarSP || !LocSP) + return; // Broken scope chains are checked elsewhere. + + Assert(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + + " variable and !dbg attachment", + &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc, + Loc->getScope()->getSubprogram()); } template diff --git a/test/Verifier/llvm.dbg.declare-variable.ll b/test/Verifier/llvm.dbg.declare-variable.ll index e038243bdd6..763f4637366 100644 --- a/test/Verifier/llvm.dbg.declare-variable.ll +++ b/test/Verifier/llvm.dbg.declare-variable.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.declare(metadata i32* %s, metadata !"", metadata !MDExpression()) + call void @llvm.dbg.declare(metadata i32* %s, metadata !"", metadata !MDExpression()), !dbg !MDLocation(scope: !1) ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram() diff --git a/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll b/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll new file mode 100644 index 00000000000..3615960df63 --- /dev/null +++ b/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll @@ -0,0 +1,61 @@ +; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s +define void @foo() { +entry: + call void @llvm.dbg.value( + metadata i8* undef, + i64 0, + metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !MDExpression()) +; CHECK-LABEL: llvm.dbg.value intrinsic requires a !dbg attachment +; CHECK-NEXT: call void @llvm.dbg.value({{.*}}) +; CHECK-NEXT: label %entry +; CHECK-NEXT: void ()* @foo + + call void @llvm.dbg.declare( + metadata i8* undef, + metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !MDExpression()) +; CHECK-LABEL: llvm.dbg.declare intrinsic requires a !dbg attachment +; CHECK-NEXT: call void @llvm.dbg.declare({{.*}}) +; CHECK-NEXT: label %entry +; CHECK-NEXT: void ()* @foo + + call void @llvm.dbg.value( + metadata i8* undef, + i64 0, + metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !MDExpression()), + !dbg !MDLocation(scope: !2) +; CHECK-LABEL: mismatched subprogram between llvm.dbg.value variable and !dbg attachment +; CHECK-NEXT: call void @llvm.dbg.value({{[^,]+, [^,]+}}, metadata ![[VAR:[0-9]+]], {{[^,]+}}), !dbg ![[LOC:[0-9]+]] +; CHECK-NEXT: label %entry +; CHECK-NEXT: void ()* @foo +; CHECK-NEXT: ![[VAR]] = !MDLocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] +; CHECK-NEXT: ![[VARSP]] = !MDSubprogram( +; CHECK-NEXT: ![[LOC]] = !MDLocation({{.*}}scope: ![[LOCSP:[0-9]+]] +; CHECK-NEXT: ![[LOCSP]] = !MDSubprogram( + + call void @llvm.dbg.declare( + metadata i8* undef, + metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !MDExpression()), + !dbg !MDLocation(scope: !2) +; CHECK-LABEL: mismatched subprogram between llvm.dbg.declare variable and !dbg attachment +; CHECK-NEXT: call void @llvm.dbg.declare({{[^,]+}}, metadata ![[VAR:[0-9]+]], {{.*[^,]+}}), !dbg ![[LOC:[0-9]+]] +; CHECK-NEXT: label %entry +; CHECK-NEXT: void ()* @foo +; CHECK-NEXT: ![[VAR]] = !MDLocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] +; CHECK-NEXT: ![[VARSP]] = !MDSubprogram( +; CHECK-NEXT: ![[LOC]] = !MDLocation({{.*}}scope: ![[LOCSP:[0-9]+]] +; CHECK-NEXT: ![[LOCSP]] = !MDSubprogram( + + ret void +} + +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram(name: "foo") +!2 = !MDSubprogram(name: "bar") diff --git a/test/Verifier/llvm.dbg.value-expression.ll b/test/Verifier/llvm.dbg.value-expression.ll index b60c4722fac..18350a144e6 100644 --- a/test/Verifier/llvm.dbg.value-expression.ll +++ b/test/Verifier/llvm.dbg.value-expression.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !"") + call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !""), !dbg !MDLocation(scope: !1) ret void } diff --git a/test/Verifier/llvm.dbg.value-variable.ll b/test/Verifier/llvm.dbg.value-variable.ll index a87a15cdfa2..ba6a687e0ab 100644 --- a/test/Verifier/llvm.dbg.value-variable.ll +++ b/test/Verifier/llvm.dbg.value-variable.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !"", metadata !MDExpression()) + call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !"", metadata !MDExpression()), !dbg !MDLocation(scope: !1) ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram()