mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
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 llvm-svn: 295749
This commit is contained in:
parent
0599d58aba
commit
458ca95045
@ -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();
|
||||
@ -1946,6 +1950,8 @@ void Verifier::verifySiblingFuncletUnwinds() {
|
||||
// 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(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) {
|
||||
@ -4416,6 +4424,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;
|
||||
|
26
test/Verifier/fnarg-debuginfo.ll
Normal file
26
test/Verifier/fnarg-debuginfo.ll
Normal file
@ -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}
|
Loading…
Reference in New Issue
Block a user