Skip to content

Commit

Permalink
Add debug location verification for !llvm.loop attachments.
Browse files Browse the repository at this point in the history
This patch teaches the Verifier how to detect broken !llvm.loop
attachments as discussed in https://reviews.llvm.org/D60831. This
allows LLVM to warn and strip out the broken debug info before
attempting an LTO compilation with input generated by LLVM predating
https://reviews.llvm.org/rL361149.

rdar://problem/51631158

Differential Revision: https://reviews.llvm.org/D63499

llvm-svn: 363725
  • Loading branch information
adrian-prantl committed Jun 18, 2019
1 parent a702f07 commit 8ff822d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 26 deletions.
60 changes: 34 additions & 26 deletions llvm/lib/IR/Verifier.cpp
Expand Up @@ -2342,36 +2342,44 @@ void Verifier::visitFunction(const Function &F) {
// FIXME: Check this incrementally while visiting !dbg attachments.
// FIXME: Only check when N is the canonical subprogram for F.
SmallPtrSet<const MDNode *, 32> Seen;
for (auto &BB : F)
for (auto &I : BB) {
// Be careful about using DILocation here since we might be dealing with
// broken code (this is the Verifier after all).
DILocation *DL =
dyn_cast_or_null<DILocation>(I.getDebugLoc().getAsMDNode());
if (!DL)
continue;
if (!Seen.insert(DL).second)
continue;
auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) {
// Be careful about using DILocation here since we might be dealing with
// broken code (this is the Verifier after all).
const DILocation *DL = dyn_cast_or_null<DILocation>(Node);
if (!DL)
return;
if (!Seen.insert(DL).second)
return;

Metadata *Parent = DL->getRawScope();
AssertDI(Parent && isa<DILocalScope>(Parent),
"DILocation's scope must be a DILocalScope", N, &F, &I, DL,
Parent);
DILocalScope *Scope = DL->getInlinedAtScope();
if (Scope && !Seen.insert(Scope).second)
continue;
Metadata *Parent = DL->getRawScope();
AssertDI(Parent && isa<DILocalScope>(Parent),
"DILocation's scope must be a DILocalScope", N, &F, &I, DL,
Parent);
DILocalScope *Scope = DL->getInlinedAtScope();
if (Scope && !Seen.insert(Scope).second)
return;

DISubprogram *SP = Scope ? Scope->getSubprogram() : nullptr;
DISubprogram *SP = Scope ? Scope->getSubprogram() : nullptr;

// Scope and SP could be the same MDNode and we don't want to skip
// validation in that case
if (SP && ((Scope != SP) && !Seen.insert(SP).second))
continue;
// Scope and SP could be the same MDNode and we don't want to skip
// validation in that case
if (SP && ((Scope != SP) && !Seen.insert(SP).second))
return;

// FIXME: Once N is canonical, check "SP == &N".
AssertDI(SP->describes(&F),
"!dbg attachment points at wrong subprogram for function", N, &F,
&I, DL, Scope, SP);
// FIXME: Once N is canonical, check "SP == &N".
AssertDI(SP->describes(&F),
"!dbg attachment points at wrong subprogram for function", N, &F,
&I, DL, Scope, SP);
};
for (auto &BB : F)
for (auto &I : BB) {
VisitDebugLoc(I, I.getDebugLoc().getAsMDNode());
// The llvm.loop annotations also contain two DILocations.
if (auto MD = I.getMetadata(LLVMContext::MD_loop))
for (unsigned i = 1; i < MD->getNumOperands(); ++i)
VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i)));
if (BrokenDebugInfo)
return;
}
}

Expand Down
28 changes: 28 additions & 0 deletions llvm/test/Verifier/llvm.loop.ll
@@ -0,0 +1,28 @@
; RUN: llvm-as -disable-output < %s -o /dev/null 2>&1 | FileCheck %s

define i32 @foo() !dbg !4 {
entry:
ret i32 0, !dbg !6
}

define i32 @bar() !dbg !5 {
entry:
; CHECK: !dbg attachment points at wrong subprogram for function
ret i32 0, !dbg !10, !llvm.loop !9
}

; CHECK: warning: ignoring invalid debug info
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!7, !8}

!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
!1 = !DIFile(filename: "dwarf-test.c", directory: "test")
!2 = !{}
!4 = distinct !DISubprogram(name: "foo", scope: !0, isDefinition: true, unit: !0)
!5 = distinct !DISubprogram(name: "bar", scope: !0, isDefinition: true, unit: !0)
!6 = !DILocation(line: 7, scope: !4)
!7 = !{i32 2, !"Dwarf Version", i32 3}
!8 = !{i32 1, !"Debug Info Version", i32 3}
!9 = !{!9, !10, !11}
!10 = !DILocation(line: 1, scope: !5)
!11 = !DILocation(line: 1, scope: !4)

0 comments on commit 8ff822d

Please sign in to comment.