Skip to content

Commit 4ed5195

Browse files
committed
[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
1 parent d1c9751 commit 4ed5195

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

llvm/lib/IR/Verifier.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
281281
/// Whether the current function has a DISubprogram attached to it.
282282
bool HasDebugInfo = false;
283283

284+
/// Whether source was present on the first DIFile encountered in each CU.
285+
DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo;
286+
284287
/// Stores the count of how many objects were passed to llvm.localescape for a
285288
/// given function and the largest index passed to llvm.localrecover.
286289
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
@@ -519,6 +522,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
519522
/// Module-level verification that all @llvm.experimental.deoptimize
520523
/// declarations share the same calling convention.
521524
void verifyDeoptimizeCallingConvs();
525+
526+
/// Verify all-or-nothing property of DIFile source attribute within a CU.
527+
void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F);
522528
};
523529

524530
} // end anonymous namespace
@@ -1032,6 +1038,8 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
10321038
AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,
10331039
N.getFile());
10341040

1041+
verifySourceDebugInfo(N, *N.getFile());
1042+
10351043
AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),
10361044
"invalid emission kind", &N);
10371045

@@ -1109,6 +1117,8 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
11091117
AssertDI(N.isDistinct(), "subprogram definitions must be distinct", &N);
11101118
AssertDI(Unit, "subprogram definitions must have a compile unit", &N);
11111119
AssertDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit);
1120+
if (N.getFile())
1121+
verifySourceDebugInfo(*N.getUnit(), *N.getFile());
11121122
} else {
11131123
// Subprogram declarations (part of the type hierarchy).
11141124
AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N);
@@ -4744,6 +4754,14 @@ void Verifier::verifyDeoptimizeCallingConvs() {
47444754
}
47454755
}
47464756

4757+
void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) {
4758+
bool HasSource = F.getSource().hasValue();
4759+
if (!HasSourceDebugInfo.count(&U))
4760+
HasSourceDebugInfo[&U] = HasSource;
4761+
AssertDI(HasSource == HasSourceDebugInfo[&U],
4762+
"inconsistent use of embedded source");
4763+
}
4764+
47474765
//===----------------------------------------------------------------------===//
47484766
// Implement the public interfaces to this file...
47494767
//===----------------------------------------------------------------------===//
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; RUN: llvm-as < %s 2>&1 >/dev/null | FileCheck %s
2+
3+
; Ensure we reject debug info where the DIFiles of a DICompileUnit mix source
4+
; and no-source.
5+
6+
define dso_local void @foo() !dbg !5 {
7+
ret void
8+
}
9+
10+
define dso_local void @bar() !dbg !6 {
11+
ret void
12+
}
13+
14+
!llvm.dbg.cu = !{!4}
15+
!llvm.module.flags = !{!0, !1}
16+
17+
!0 = !{i32 2, !"Dwarf Version", i32 5}
18+
!1 = !{i32 2, !"Debug Info Version", i32 3}
19+
20+
!2 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
21+
; CHECK: inconsistent use of embedded source
22+
; CHECK: warning: ignoring invalid debug info
23+
!3 = !DIFile(filename: "bar.h", directory: "dir")
24+
25+
!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2)
26+
!5 = distinct !DISubprogram(name: "foo", file: !2, unit: !4)
27+
!6 = distinct !DISubprogram(name: "bar", file: !3, unit: !4)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
2+
; RUN: verify-uselistorder %s
3+
4+
; Ensure we accept debug info where DIFiles within a DICompileUnit either all
5+
; have source, or none have source.
6+
7+
define dso_local void @foo() !dbg !6 {
8+
ret void
9+
}
10+
11+
define dso_local void @bar() !dbg !7 {
12+
ret void
13+
}
14+
15+
define dso_local void @baz() !dbg !9 {
16+
ret void
17+
}
18+
19+
define dso_local void @qux() !dbg !11 {
20+
ret void
21+
}
22+
23+
!llvm.dbg.cu = !{!0, !2}
24+
!llvm.module.flags = !{!4, !5}
25+
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
27+
; CHECK: !1 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
28+
!1 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
29+
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
30+
; CHECK: !3 = !DIFile(filename: "qux.h", directory: "dir")
31+
!3 = !DIFile(filename: "qux.h", directory: "dir")
32+
!4 = !{i32 2, !"Dwarf Version", i32 5}
33+
!5 = !{i32 2, !"Debug Info Version", i32 3}
34+
!6 = distinct !DISubprogram(name: "foo", file: !1, unit: !0)
35+
!7 = distinct !DISubprogram(name: "bar", file: !8, unit: !0)
36+
; CHECK: !8 = !DIFile(filename: "bar.h", directory: "dir", source: "void bar() { }\0A")
37+
!8 = !DIFile(filename: "bar.h", directory: "dir", source: "void bar() { }\0A")
38+
!9 = distinct !DISubprogram(name: "baz", file: !10, unit: !2)
39+
; CHECK: !10 = !DIFile(filename: "baz.c", directory: "dir")
40+
!10 = !DIFile(filename: "baz.c", directory: "dir")
41+
!11 = distinct !DISubprogram(name: "qux", file: !3, unit: !2)

0 commit comments

Comments
 (0)