[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / Transforms / Utils / DebugifyTest.cpp
blob089830967e642e469d7fd2a785b3db5e0b13efa8
1 //===- DebugifyTest.cpp - Debugify unit tests -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/SmallVector.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/DebugInfoMetadata.h"
12 #include "llvm/IR/IntrinsicInst.h"
13 #include "llvm/IR/LegacyPassManager.h"
14 #include "llvm/Support/SourceMgr.h"
15 #include "llvm/Transforms/Utils/Debugify.h"
16 #include "gtest/gtest.h"
18 using namespace llvm;
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("DebugifyTest", errs());
25 return Mod;
28 namespace llvm {
29 void initializeDebugInfoDropPass(PassRegistry &);
30 void initializeDebugInfoDummyAnalysisPass(PassRegistry &);
32 namespace {
33 struct DebugInfoDrop : public FunctionPass {
34 static char ID;
35 bool runOnFunction(Function &F) override {
36 // Drop DISubprogram.
37 F.setSubprogram(nullptr);
38 for (BasicBlock &BB : F) {
39 // Remove debug locations.
40 for (Instruction &I : BB)
41 I.setDebugLoc(DebugLoc());
44 return false;
47 void getAnalysisUsage(AnalysisUsage &AU) const override {
48 AU.setPreservesCFG();
51 DebugInfoDrop() : FunctionPass(ID) {}
54 struct DebugValueDrop : public FunctionPass {
55 static char ID;
56 bool runOnFunction(Function &F) override {
57 SmallVector<DbgVariableIntrinsic *, 4> Dbgs;
58 for (BasicBlock &BB : F) {
59 // Remove dbg var intrinsics.
60 for (Instruction &I : BB) {
61 if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I))
62 Dbgs.push_back(DVI);
66 for (auto &I : Dbgs)
67 I->eraseFromParent();
69 return true;
72 void getAnalysisUsage(AnalysisUsage &AU) const override {
73 AU.setPreservesCFG();
76 DebugValueDrop() : FunctionPass(ID) {}
79 struct DebugInfoDummyAnalysis : public FunctionPass {
80 static char ID;
81 bool runOnFunction(Function &F) override {
82 // Do nothing, so debug info stays untouched.
83 return false;
85 void getAnalysisUsage(AnalysisUsage &AU) const override {
86 AU.setPreservesAll();
89 DebugInfoDummyAnalysis() : FunctionPass(ID) {}
93 char DebugInfoDrop::ID = 0;
94 char DebugValueDrop::ID = 0;
95 char DebugInfoDummyAnalysis::ID = 0;
97 TEST(DebugInfoDrop, DropOriginalDebugInfo) {
98 LLVMContext C;
99 std::unique_ptr<Module> M = parseIR(C, R"(
100 define i16 @f(i16 %a) !dbg !6 {
101 %b = add i16 %a, 1, !dbg !11
102 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
103 ret i16 0, !dbg !11
105 declare void @llvm.dbg.value(metadata, metadata, metadata)
107 !llvm.dbg.cu = !{!0}
108 !llvm.module.flags = !{!5}
110 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
111 !1 = !DIFile(filename: "t.ll", directory: "/")
112 !2 = !{}
113 !5 = !{i32 2, !"Debug Info Version", i32 3}
114 !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
115 !7 = !DISubroutineType(types: !2)
116 !8 = !{!9}
117 !9 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 1, type: !10)
118 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
119 !11 = !DILocation(line: 1, column: 1, scope: !6)
120 )");
122 DebugInfoDrop *P = new DebugInfoDrop();
124 DebugInfoPerPass DIBeforePass;
125 DebugifyCustomPassManager Passes;
126 Passes.setDebugInfoBeforePass(DIBeforePass);
127 Passes.add(createDebugifyModulePass(DebugifyMode::OriginalDebugInfo, "",
128 &(Passes.getDebugInfoPerPass())));
129 Passes.add(P);
130 Passes.add(createCheckDebugifyModulePass(false, "", nullptr,
131 DebugifyMode::OriginalDebugInfo,
132 &(Passes.getDebugInfoPerPass())));
134 testing::internal::CaptureStderr();
135 Passes.run(*M);
137 std::string StdOut = testing::internal::GetCapturedStderr();
139 std::string ErrorForSP = "ERROR: dropped DISubprogram of";
140 std::string WarningForLoc = "WARNING: dropped DILocation of";
141 std::string FinalResult = "CheckModuleDebugify (original debuginfo): FAIL";
143 EXPECT_TRUE(StdOut.find(ErrorForSP) != std::string::npos);
144 EXPECT_TRUE(StdOut.find(WarningForLoc) != std::string::npos);
145 EXPECT_TRUE(StdOut.find(FinalResult) != std::string::npos);
148 TEST(DebugValueDrop, DropOriginalDebugValues) {
149 LLVMContext C;
150 std::unique_ptr<Module> M = parseIR(C, R"(
151 define i16 @f(i16 %a) !dbg !6 {
152 %b = add i16 %a, 1, !dbg !11
153 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
154 ret i16 0, !dbg !11
156 declare void @llvm.dbg.value(metadata, metadata, metadata)
158 !llvm.dbg.cu = !{!0}
159 !llvm.module.flags = !{!5}
161 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
162 !1 = !DIFile(filename: "t.ll", directory: "/")
163 !2 = !{}
164 !5 = !{i32 2, !"Debug Info Version", i32 3}
165 !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
166 !7 = !DISubroutineType(types: !2)
167 !8 = !{!9}
168 !9 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 1, type: !10)
169 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
170 !11 = !DILocation(line: 1, column: 1, scope: !6)
171 )");
173 DebugValueDrop *P = new DebugValueDrop();
175 DebugInfoPerPass DIBeforePass;
176 DebugifyCustomPassManager Passes;
177 Passes.setDebugInfoBeforePass(DIBeforePass);
178 Passes.add(createDebugifyModulePass(DebugifyMode::OriginalDebugInfo, "",
179 &(Passes.getDebugInfoPerPass())));
180 Passes.add(P);
181 Passes.add(createCheckDebugifyModulePass(false, "", nullptr,
182 DebugifyMode::OriginalDebugInfo,
183 &(Passes.getDebugInfoPerPass())));
185 testing::internal::CaptureStderr();
186 Passes.run(*M);
188 std::string StdOut = testing::internal::GetCapturedStderr();
190 std::string ErrorForSP = "ERROR: dropped DISubprogram of";
191 std::string WarningForLoc = "WARNING: dropped DILocation of";
192 std::string WarningForVars = "WARNING: drops dbg.value()/dbg.declare() for";
193 std::string FinalResult = "CheckModuleDebugify (original debuginfo): FAIL";
195 EXPECT_TRUE(StdOut.find(ErrorForSP) == std::string::npos);
196 EXPECT_TRUE(StdOut.find(WarningForLoc) == std::string::npos);
197 EXPECT_TRUE(StdOut.find(WarningForVars) != std::string::npos);
198 EXPECT_TRUE(StdOut.find(FinalResult) != std::string::npos);
201 TEST(DebugInfoDummyAnalysis, PreserveOriginalDebugInfo) {
202 LLVMContext C;
203 std::unique_ptr<Module> M = parseIR(C, R"(
204 define i32 @g(i32 %b) !dbg !6 {
205 %c = add i32 %b, 1, !dbg !11
206 call void @llvm.dbg.value(metadata i32 %c, metadata !9, metadata !DIExpression()), !dbg !11
207 ret i32 1, !dbg !11
209 declare void @llvm.dbg.value(metadata, metadata, metadata)
211 !llvm.dbg.cu = !{!0}
212 !llvm.module.flags = !{!5}
214 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
215 !1 = !DIFile(filename: "test.ll", directory: "/")
216 !2 = !{}
217 !5 = !{i32 2, !"Debug Info Version", i32 3}
218 !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
219 !7 = !DISubroutineType(types: !2)
220 !8 = !{!9}
221 !9 = !DILocalVariable(name: "c", scope: !6, file: !1, line: 1, type: !10)
222 !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
223 !11 = !DILocation(line: 1, column: 1, scope: !6)
224 )");
226 DebugInfoDummyAnalysis *P = new DebugInfoDummyAnalysis();
228 DebugInfoPerPass DIBeforePass;
229 DebugifyCustomPassManager Passes;
230 Passes.setDebugInfoBeforePass(DIBeforePass);
231 Passes.add(createDebugifyModulePass(DebugifyMode::OriginalDebugInfo, "",
232 &(Passes.getDebugInfoPerPass())));
233 Passes.add(P);
234 Passes.add(createCheckDebugifyModulePass(false, "", nullptr,
235 DebugifyMode::OriginalDebugInfo,
236 &(Passes.getDebugInfoPerPass())));
238 testing::internal::CaptureStderr();
239 Passes.run(*M);
241 std::string StdOut = testing::internal::GetCapturedStderr();
243 std::string ErrorForSP = "ERROR: dropped DISubprogram of";
244 std::string WarningForLoc = "WARNING: dropped DILocation of";
245 std::string WarningForVars = "WARNING: drops dbg.value()/dbg.declare() for";
246 std::string FinalResult = "CheckModuleDebugify (original debuginfo): PASS";
248 EXPECT_TRUE(StdOut.find(ErrorForSP) == std::string::npos);
249 EXPECT_TRUE(StdOut.find(WarningForLoc) == std::string::npos);
250 EXPECT_TRUE(StdOut.find(WarningForVars) == std::string::npos);
251 EXPECT_TRUE(StdOut.find(FinalResult) != std::string::npos);
254 } // end namespace llvm
256 INITIALIZE_PASS_BEGIN(DebugInfoDrop, "debuginfodroppass", "debuginfodroppass",
257 false, false)
258 INITIALIZE_PASS_END(DebugInfoDrop, "debuginfodroppass", "debuginfodroppass", false,
259 false)
261 INITIALIZE_PASS_BEGIN(DebugInfoDummyAnalysis, "debuginfodummyanalysispass",
262 "debuginfodummyanalysispass", false, false)
263 INITIALIZE_PASS_END(DebugInfoDummyAnalysis, "debuginfodummyanalysispass",
264 "debuginfodummyanalysispass", false, false)