|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
| 9 | +#include "llvm/IR/DebugInfo.h" |
| 10 | +#include "llvm/AsmParser/Parser.h" |
9 | 11 | #include "llvm/IR/DebugInfoMetadata.h"
|
| 12 | +#include "llvm/IR/LLVMContext.h" |
| 13 | +#include "llvm/IR/Module.h" |
| 14 | +#include "llvm/IR/Verifier.h" |
| 15 | +#include "llvm/Support/SourceMgr.h" |
10 | 16 | #include "gtest/gtest.h"
|
11 | 17 |
|
12 | 18 | using namespace llvm;
|
13 | 19 |
|
| 20 | +static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { |
| 21 | + SMDiagnostic Err; |
| 22 | + std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); |
| 23 | + if (!Mod) |
| 24 | + Err.print("DebugInfoTest", errs()); |
| 25 | + return Mod; |
| 26 | +} |
| 27 | + |
14 | 28 | namespace {
|
15 | 29 |
|
16 | 30 | TEST(DINodeTest, getFlag) {
|
@@ -79,4 +93,56 @@ TEST(DINodeTest, splitFlags) {
|
79 | 93 | #undef CHECK_SPLIT
|
80 | 94 | }
|
81 | 95 |
|
| 96 | +TEST(StripTest, LoopMetadata) { |
| 97 | + LLVMContext C; |
| 98 | + std::unique_ptr<Module> M = parseIR(C, R"( |
| 99 | + define void @f() !dbg !5 { |
| 100 | + ret void, !dbg !10, !llvm.loop !11 |
| 101 | + } |
| 102 | +
|
| 103 | + !llvm.dbg.cu = !{!0} |
| 104 | + !llvm.debugify = !{!3, !3} |
| 105 | + !llvm.module.flags = !{!4} |
| 106 | +
|
| 107 | + !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) |
| 108 | + !1 = !DIFile(filename: "loop.ll", directory: "/") |
| 109 | + !2 = !{} |
| 110 | + !3 = !{i32 1} |
| 111 | + !4 = !{i32 2, !"Debug Info Version", i32 3} |
| 112 | + !5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7) |
| 113 | + !6 = !DISubroutineType(types: !2) |
| 114 | + !7 = !{!8} |
| 115 | + !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9) |
| 116 | + !9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) |
| 117 | + !10 = !DILocation(line: 1, column: 1, scope: !5) |
| 118 | + !11 = distinct !{!11, !10, !10} |
| 119 | +)"); |
| 120 | + |
| 121 | + // Look up the debug info emission kind for the CU via the loop metadata |
| 122 | + // attached to the terminator. If, when stripping non-line table debug info, |
| 123 | + // we update the terminator's metadata correctly, we should be able to |
| 124 | + // observe the change in emission kind for the CU. |
| 125 | + auto getEmissionKind = [&]() { |
| 126 | + Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); |
| 127 | + MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop); |
| 128 | + return cast<DILocation>(LoopMD->getOperand(1)) |
| 129 | + ->getScope() |
| 130 | + ->getSubprogram() |
| 131 | + ->getUnit() |
| 132 | + ->getEmissionKind(); |
| 133 | + }; |
| 134 | + |
| 135 | + EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug); |
| 136 | + |
| 137 | + bool Changed = stripNonLineTableDebugInfo(*M); |
| 138 | + EXPECT_TRUE(Changed); |
| 139 | + |
| 140 | + EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly); |
| 141 | + |
| 142 | + bool BrokenDebugInfo = false; |
| 143 | + bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo); |
| 144 | + EXPECT_FALSE(HardError); |
| 145 | + EXPECT_FALSE(BrokenDebugInfo); |
| 146 | +} |
| 147 | + |
82 | 148 | } // end namespace
|
0 commit comments