xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Transforms/Utils/Debugify.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- Debugify.h - Check debug info preservation in optimizations --------===//
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 //===----------------------------------------------------------------------===//
8 ///
9 /// \file Interface to the `debugify` synthetic/original debug info testing
10 /// utility.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
15 #define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
16 
17 #include "llvm/ADT/MapVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Bitcode/BitcodeWriterPass.h"
20 #include "llvm/IR/IRPrintingPasses.h"
21 #include "llvm/IR/LegacyPassManager.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/PassInstrumentation.h"
24 #include "llvm/IR/PassManager.h"
25 #include "llvm/IR/ValueHandle.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Support/Compiler.h"
28 
29 using DebugFnMap =
30     llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
31 using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
32 using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
33 using WeakInstValueMap =
34     llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
35 
36 /// Used to track the Debug Info Metadata information.
37 struct DebugInfoPerPass {
38   // This maps a function name to its associated DISubprogram.
39   DebugFnMap DIFunctions;
40   // This maps an instruction and the info about whether it has !dbg attached.
41   DebugInstMap DILocations;
42   // This tracks value (instruction) deletion. If an instruction gets deleted,
43   // WeakVH nulls itself.
44   WeakInstValueMap InstToDelete;
45   // Maps variable into dbg users (#dbg values/declares for this variable).
46   DebugVarMap DIVariables;
47 };
48 
49 namespace llvm {
50 class DIBuilder;
51 
52 /// Add synthesized debug information to a module.
53 ///
54 /// \param M The module to add debug information to.
55 /// \param Functions A range of functions to add debug information to.
56 /// \param Banner A prefix string to add to debug/error messages.
57 /// \param ApplyToMF A call back that will add debug information to the
58 ///                  MachineFunction for a Function. If nullptr, then the
59 ///                  MachineFunction (if any) will not be modified.
60 LLVM_ABI bool
61 applyDebugifyMetadata(Module &M, iterator_range<Module::iterator> Functions,
62                       StringRef Banner,
63                       std::function<bool(DIBuilder &, Function &)> ApplyToMF);
64 
65 /// Strip out all of the metadata and debug info inserted by debugify. If no
66 /// llvm.debugify module-level named metadata is present, this is a no-op.
67 /// Returns true if any change was made.
68 LLVM_ABI bool stripDebugifyMetadata(Module &M);
69 
70 /// Collect original debug information before a pass.
71 ///
72 /// \param M The module to collect debug information from.
73 /// \param Functions A range of functions to collect debug information from.
74 /// \param DebugInfoBeforePass DI metadata before a pass.
75 /// \param Banner A prefix string to add to debug/error messages.
76 /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
77 LLVM_ABI bool
78 collectDebugInfoMetadata(Module &M, iterator_range<Module::iterator> Functions,
79                          DebugInfoPerPass &DebugInfoBeforePass,
80                          StringRef Banner, StringRef NameOfWrappedPass);
81 
82 /// Check original debug information after a pass.
83 ///
84 /// \param M The module to collect debug information from.
85 /// \param Functions A range of functions to collect debug information from.
86 /// \param DebugInfoBeforePass DI metadata before a pass.
87 /// \param Banner A prefix string to add to debug/error messages.
88 /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
89 LLVM_ABI bool checkDebugInfoMetadata(Module &M,
90                                      iterator_range<Module::iterator> Functions,
91                                      DebugInfoPerPass &DebugInfoBeforePass,
92                                      StringRef Banner,
93                                      StringRef NameOfWrappedPass,
94                                      StringRef OrigDIVerifyBugsReportFilePath);
95 } // namespace llvm
96 
97 /// Used to check whether we track synthetic or original debug info.
98 enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
99 
100 LLVM_ABI llvm::ModulePass *createDebugifyModulePass(
101     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
102     llvm::StringRef NameOfWrappedPass = "",
103     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
104 LLVM_ABI llvm::FunctionPass *createDebugifyFunctionPass(
105     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
106     llvm::StringRef NameOfWrappedPass = "",
107     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
108 
109 class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
110   llvm::StringRef NameOfWrappedPass;
111   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
112   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
113 public:
114   NewPMDebugifyPass(
115       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
116       llvm::StringRef NameOfWrappedPass = "",
117       DebugInfoPerPass *DebugInfoBeforePass = nullptr)
NameOfWrappedPass(NameOfWrappedPass)118       : NameOfWrappedPass(NameOfWrappedPass),
119         DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
120 
121   LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M,
122                                        llvm::ModuleAnalysisManager &AM);
123 };
124 
125 /// Track how much `debugify` information (in the `synthetic` mode only)
126 /// has been lost.
127 struct DebugifyStatistics {
128   /// Number of missing dbg.values.
129   unsigned NumDbgValuesMissing = 0;
130 
131   /// Number of dbg.values expected.
132   unsigned NumDbgValuesExpected = 0;
133 
134   /// Number of instructions with empty debug locations.
135   unsigned NumDbgLocsMissing = 0;
136 
137   /// Number of instructions expected to have debug locations.
138   unsigned NumDbgLocsExpected = 0;
139 
140   /// Get the ratio of missing/expected dbg.values.
getMissingValueRatioDebugifyStatistics141   float getMissingValueRatio() const {
142     return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
143   }
144 
145   /// Get the ratio of missing/expected instructions with locations.
getEmptyLocationRatioDebugifyStatistics146   float getEmptyLocationRatio() const {
147     return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
148   }
149 };
150 
151 /// Map pass names to a per-pass DebugifyStatistics instance.
152 using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
153 
154 LLVM_ABI llvm::ModulePass *createCheckDebugifyModulePass(
155     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
156     DebugifyStatsMap *StatsMap = nullptr,
157     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
158     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
159     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
160 
161 LLVM_ABI llvm::FunctionPass *createCheckDebugifyFunctionPass(
162     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
163     DebugifyStatsMap *StatsMap = nullptr,
164     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
165     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
166     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
167 
168 class NewPMCheckDebugifyPass
169     : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
170   llvm::StringRef NameOfWrappedPass;
171   llvm::StringRef OrigDIVerifyBugsReportFilePath;
172   DebugifyStatsMap *StatsMap;
173   DebugInfoPerPass *DebugInfoBeforePass;
174   enum DebugifyMode Mode;
175   bool Strip;
176 public:
177   NewPMCheckDebugifyPass(
178       bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
179       DebugifyStatsMap *StatsMap = nullptr,
180       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
181       DebugInfoPerPass *DebugInfoBeforePass = nullptr,
182       llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
NameOfWrappedPass(NameOfWrappedPass)183       : NameOfWrappedPass(NameOfWrappedPass),
184         OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
185         StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
186         Strip(Strip) {}
187 
188   LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M,
189                                        llvm::ModuleAnalysisManager &AM);
190 };
191 
192 namespace llvm {
193 LLVM_ABI void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
194 
195 class DebugifyEachInstrumentation {
196   llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
197   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
198   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
199   DebugifyStatsMap *DIStatsMap = nullptr;
200 
201 public:
202   LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC,
203                                   ModuleAnalysisManager &MAM);
204   // Used within DebugifyMode::SyntheticDebugInfo mode.
setDIStatsMap(DebugifyStatsMap & StatMap)205   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
getDebugifyStatsMap()206   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
207   // Used within DebugifyMode::OriginalDebugInfo mode.
setDebugInfoBeforePass(DebugInfoPerPass & PerPassMap)208   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
209     DebugInfoBeforePass = &PerPassMap;
210   }
getDebugInfoPerPass()211   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
212 
setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath)213   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
214     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
215   }
getOrigDIVerifyBugsReportFilePath()216   StringRef getOrigDIVerifyBugsReportFilePath() const {
217     return OrigDIVerifyBugsReportFilePath;
218   }
219 
setDebugifyMode(enum DebugifyMode M)220   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
221 
isSyntheticDebugInfo()222   bool isSyntheticDebugInfo() const {
223     return Mode == DebugifyMode::SyntheticDebugInfo;
224   }
isOriginalDebugInfoMode()225   bool isOriginalDebugInfoMode() const {
226     return Mode == DebugifyMode::OriginalDebugInfo;
227   }
228 };
229 
230 /// DebugifyCustomPassManager wraps each pass with the debugify passes if
231 /// needed.
232 /// NOTE: We support legacy custom pass manager only.
233 /// TODO: Add New PM support for custom pass manager.
234 class DebugifyCustomPassManager : public legacy::PassManager {
235   StringRef OrigDIVerifyBugsReportFilePath;
236   DebugifyStatsMap *DIStatsMap = nullptr;
237   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
238   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
239 
240 public:
241   using super = legacy::PassManager;
242 
add(Pass * P)243   void add(Pass *P) override {
244     // Wrap each pass with (-check)-debugify passes if requested, making
245     // exceptions for passes which shouldn't see -debugify instrumentation.
246     bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
247                             !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
248                             !isBitcodeWriterPass(P);
249     if (!WrapWithDebugify) {
250       super::add(P);
251       return;
252     }
253 
254     // Either apply -debugify/-check-debugify before/after each pass and collect
255     // debug info loss statistics, or collect and check original debug info in
256     // the optimizations.
257     PassKind Kind = P->getPassKind();
258     StringRef Name = P->getPassName();
259 
260     // TODO: Implement Debugify for LoopPass.
261     switch (Kind) {
262     case PT_Function:
263       super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
264       super::add(P);
265       super::add(createCheckDebugifyFunctionPass(
266           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
267           OrigDIVerifyBugsReportFilePath));
268       break;
269     case PT_Module:
270       super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
271       super::add(P);
272       super::add(createCheckDebugifyModulePass(
273           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
274           OrigDIVerifyBugsReportFilePath));
275       break;
276     default:
277       super::add(P);
278       break;
279     }
280   }
281 
282   // Used within DebugifyMode::SyntheticDebugInfo mode.
setDIStatsMap(DebugifyStatsMap & StatMap)283   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
284   // Used within DebugifyMode::OriginalDebugInfo mode.
setDebugInfoBeforePass(DebugInfoPerPass & PerPassDI)285   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
286     DebugInfoBeforePass = &PerPassDI;
287   }
setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath)288   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
289     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
290   }
getOrigDIVerifyBugsReportFilePath()291   StringRef getOrigDIVerifyBugsReportFilePath() const {
292     return OrigDIVerifyBugsReportFilePath;
293   }
294 
setDebugifyMode(enum DebugifyMode M)295   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
296 
isSyntheticDebugInfo()297   bool isSyntheticDebugInfo() const {
298     return Mode == DebugifyMode::SyntheticDebugInfo;
299   }
isOriginalDebugInfoMode()300   bool isOriginalDebugInfoMode() const {
301     return Mode == DebugifyMode::OriginalDebugInfo;
302   }
303 
getDebugifyStatsMap()304   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
getDebugInfoPerPass()305   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
306 };
307 } // namespace llvm
308 
309 #endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
310