forked from OSchip/llvm-project
				
			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. llvm-svn: 235048
This commit is contained in:
		
							parent
							
								
									7f5015a9cc
								
							
						
					
					
						commit
						f17f34e42b
					
				| 
						 | 
					@ -1932,10 +1932,12 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Check that a location is valid for this variable.
 | 
					  /// \brief Check that a location is valid for this variable.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// Check that \c DL has the same inlined-at location as this variable,
 | 
					  /// Check that \c DL exists, is in the same subprogram, and has the same
 | 
				
			||||||
  /// making them valid for the same \a DbgInfoIntrinsic.
 | 
					  /// inlined-at location as \c this.  (Otherwise, it's not a valid attachemnt
 | 
				
			||||||
 | 
					  /// to a \a DbgInfoIntrinsic.)
 | 
				
			||||||
  bool isValidLocationForIntrinsic(const MDLocation *DL) const {
 | 
					  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.
 | 
					  /// \brief Get an inlined version of this variable.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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<MDSubprogram>(LocalScope))
 | 
				
			||||||
 | 
					    return SP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (auto *LB = dyn_cast<MDLexicalBlockBase>(LocalScope))
 | 
				
			||||||
 | 
					    return getSubprogram(LB->getRawScope());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Just return null; broken scope chains are checked elsewhere.
 | 
				
			||||||
 | 
					  assert(!isa<MDLocalScope>(LocalScope) && "Unknown type of local scope");
 | 
				
			||||||
 | 
					  return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class DbgIntrinsicTy>
 | 
					template <class DbgIntrinsicTy>
 | 
				
			||||||
void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
 | 
					void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
 | 
				
			||||||
  auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();
 | 
					  auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();
 | 
				
			||||||
| 
						 | 
					@ -3379,14 +3398,29 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
 | 
				
			||||||
    if (!isa<MDLocation>(N))
 | 
					    if (!isa<MDLocation>(N))
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BasicBlock *BB = DII.getParent();
 | 
				
			||||||
 | 
					  Function *F = BB ? BB->getParent() : nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // The inlined-at attachments for variables and !dbg attachments must agree.
 | 
					  // The inlined-at attachments for variables and !dbg attachments must agree.
 | 
				
			||||||
  MDLocalVariable *Var = DII.getVariable();
 | 
					  MDLocalVariable *Var = DII.getVariable();
 | 
				
			||||||
  MDLocation *VarIA = Var->getInlinedAt();
 | 
					  MDLocation *VarIA = Var->getInlinedAt();
 | 
				
			||||||
  MDLocation *Loc = DII.getDebugLoc();
 | 
					  MDLocation *Loc = DII.getDebugLoc();
 | 
				
			||||||
  MDLocation *LocIA = Loc ? Loc->getInlinedAt() : nullptr;
 | 
					  Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
 | 
				
			||||||
  BasicBlock *BB = DII.getParent();
 | 
					         &DII, BB, F);
 | 
				
			||||||
  Assert(VarIA == LocIA, "mismatched variable and !dbg inlined-at", &DII, BB,
 | 
					
 | 
				
			||||||
         BB ? BB->getParent() : nullptr, Var, VarIA, Loc, LocIA);
 | 
					  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 <class MapTy>
 | 
					template <class MapTy>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
define void @foo(i32 %a) {
 | 
					define void @foo(i32 %a) {
 | 
				
			||||||
entry:
 | 
					entry:
 | 
				
			||||||
  %s = alloca i32
 | 
					  %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
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,3 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
!llvm.module.flags = !{!0}
 | 
					!llvm.module.flags = !{!0}
 | 
				
			||||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
 | 
					!0 = !{i32 2, !"Debug Info Version", i32 3}
 | 
				
			||||||
 | 
					!1 = !MDSubprogram()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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")
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
define void @foo(i32 %a) {
 | 
					define void @foo(i32 %a) {
 | 
				
			||||||
entry:
 | 
					entry:
 | 
				
			||||||
  %s = alloca i32
 | 
					  %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
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
define void @foo(i32 %a) {
 | 
					define void @foo(i32 %a) {
 | 
				
			||||||
entry:
 | 
					entry:
 | 
				
			||||||
  %s = alloca i32
 | 
					  %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
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,3 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
!llvm.module.flags = !{!0}
 | 
					!llvm.module.flags = !{!0}
 | 
				
			||||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
 | 
					!0 = !{i32 2, !"Debug Info Version", i32 3}
 | 
				
			||||||
 | 
					!1 = !MDSubprogram()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue