[DWARFv5] Verify all-or-nothing constraint on DIFile source

Update IR verifier to check the constraint that DIFile source is present on all
files or no files.

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

llvm-svn: 348022
This commit is contained in:
Scott Linder 2018-11-30 19:13:38 +00:00
parent d1c9751657
commit 4ed5195712
3 changed files with 86 additions and 0 deletions

View File

@ -281,6 +281,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// Whether the current function has a DISubprogram attached to it.
bool HasDebugInfo = false;
/// Whether source was present on the first DIFile encountered in each CU.
DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo;
/// Stores the count of how many objects were passed to llvm.localescape for a
/// given function and the largest index passed to llvm.localrecover.
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
@ -519,6 +522,9 @@ private:
/// Module-level verification that all @llvm.experimental.deoptimize
/// declarations share the same calling convention.
void verifyDeoptimizeCallingConvs();
/// Verify all-or-nothing property of DIFile source attribute within a CU.
void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F);
};
} // end anonymous namespace
@ -1032,6 +1038,8 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,
N.getFile());
verifySourceDebugInfo(N, *N.getFile());
AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),
"invalid emission kind", &N);
@ -1109,6 +1117,8 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
AssertDI(N.isDistinct(), "subprogram definitions must be distinct", &N);
AssertDI(Unit, "subprogram definitions must have a compile unit", &N);
AssertDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit);
if (N.getFile())
verifySourceDebugInfo(*N.getUnit(), *N.getFile());
} else {
// Subprogram declarations (part of the type hierarchy).
AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N);
@ -4744,6 +4754,14 @@ void Verifier::verifyDeoptimizeCallingConvs() {
}
}
void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) {
bool HasSource = F.getSource().hasValue();
if (!HasSourceDebugInfo.count(&U))
HasSourceDebugInfo[&U] = HasSource;
AssertDI(HasSource == HasSourceDebugInfo[&U],
"inconsistent use of embedded source");
}
//===----------------------------------------------------------------------===//
// Implement the public interfaces to this file...
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,27 @@
; RUN: llvm-as < %s 2>&1 >/dev/null | FileCheck %s
; Ensure we reject debug info where the DIFiles of a DICompileUnit mix source
; and no-source.
define dso_local void @foo() !dbg !5 {
ret void
}
define dso_local void @bar() !dbg !6 {
ret void
}
!llvm.dbg.cu = !{!4}
!llvm.module.flags = !{!0, !1}
!0 = !{i32 2, !"Dwarf Version", i32 5}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
; CHECK: inconsistent use of embedded source
; CHECK: warning: ignoring invalid debug info
!3 = !DIFile(filename: "bar.h", directory: "dir")
!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2)
!5 = distinct !DISubprogram(name: "foo", file: !2, unit: !4)
!6 = distinct !DISubprogram(name: "bar", file: !3, unit: !4)

View File

@ -0,0 +1,41 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s
; Ensure we accept debug info where DIFiles within a DICompileUnit either all
; have source, or none have source.
define dso_local void @foo() !dbg !6 {
ret void
}
define dso_local void @bar() !dbg !7 {
ret void
}
define dso_local void @baz() !dbg !9 {
ret void
}
define dso_local void @qux() !dbg !11 {
ret void
}
!llvm.dbg.cu = !{!0, !2}
!llvm.module.flags = !{!4, !5}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
; CHECK: !1 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
!1 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
; CHECK: !3 = !DIFile(filename: "qux.h", directory: "dir")
!3 = !DIFile(filename: "qux.h", directory: "dir")
!4 = !{i32 2, !"Dwarf Version", i32 5}
!5 = !{i32 2, !"Debug Info Version", i32 3}
!6 = distinct !DISubprogram(name: "foo", file: !1, unit: !0)
!7 = distinct !DISubprogram(name: "bar", file: !8, unit: !0)
; CHECK: !8 = !DIFile(filename: "bar.h", directory: "dir", source: "void bar() { }\0A")
!8 = !DIFile(filename: "bar.h", directory: "dir", source: "void bar() { }\0A")
!9 = distinct !DISubprogram(name: "baz", file: !10, unit: !2)
; CHECK: !10 = !DIFile(filename: "baz.c", directory: "dir")
!10 = !DIFile(filename: "baz.c", directory: "dir")
!11 = distinct !DISubprogram(name: "qux", file: !3, unit: !2)