1 //===- Debugify.h - Attach synthetic debug info to everything -------------===//
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 debug info testing utility.
10 ///
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_TRANSFORM_UTILS_DEBUGIFY_H
14 #define LLVM_TRANSFORM_UTILS_DEBUGIFY_H
15 
16 #include "llvm/ADT/MapVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Bitcode/BitcodeWriterPass.h"
19 #include "llvm/IR/IRPrintingPasses.h"
20 #include "llvm/IR/LegacyPassManager.h"
21 #include "llvm/IR/PassManager.h"
22 
23 namespace llvm {
24 class DIBuilder;
25 
26 /// Add synthesized debug information to a module.
27 ///
28 /// \param M The module to add debug information to.
29 /// \param Functions A range of functions to add debug information to.
30 /// \param Banner A prefix string to add to debug/error messages.
31 /// \param ApplyToMF A call back that will add debug information to the
32 ///                  MachineFunction for a Function. If nullptr, then the
33 ///                  MachineFunction (if any) will not be modified.
34 bool applyDebugifyMetadata(
35     Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
36     std::function<bool(DIBuilder &, Function &)> ApplyToMF);
37 
38 /// Strip out all of the metadata and debug info inserted by debugify. If no
39 /// llvm.debugify module-level named metadata is present, this is a no-op.
40 /// Returns true if any change was made.
41 bool stripDebugifyMetadata(Module &M);
42 
43 llvm::ModulePass *createDebugifyModulePass();
44 llvm::FunctionPass *createDebugifyFunctionPass();
45 
46 struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
47   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
48 };
49 
50 /// Track how much `debugify` information has been lost.
51 struct DebugifyStatistics {
52   /// Number of missing dbg.values.
53   unsigned NumDbgValuesMissing = 0;
54 
55   /// Number of dbg.values expected.
56   unsigned NumDbgValuesExpected = 0;
57 
58   /// Number of instructions with empty debug locations.
59   unsigned NumDbgLocsMissing = 0;
60 
61   /// Number of instructions expected to have debug locations.
62   unsigned NumDbgLocsExpected = 0;
63 
64   /// Get the ratio of missing/expected dbg.values.
65   float getMissingValueRatio() const {
66     return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
67   }
68 
69   /// Get the ratio of missing/expected instructions with locations.
70   float getEmptyLocationRatio() const {
71     return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
72   }
73 };
74 
75 /// Map pass names to a per-pass DebugifyStatistics instance.
76 using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
77 
78 void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
79 
80 llvm::ModulePass *
81 createCheckDebugifyModulePass(bool Strip = false,
82                               llvm::StringRef NameOfWrappedPass = "",
83                               DebugifyStatsMap *StatsMap = nullptr);
84 
85 llvm::FunctionPass *
86 createCheckDebugifyFunctionPass(bool Strip = false,
87                                 llvm::StringRef NameOfWrappedPass = "",
88                                 DebugifyStatsMap *StatsMap = nullptr);
89 
90 struct NewPMCheckDebugifyPass
91     : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
92   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
93 };
94 
95 /// DebugifyCustomPassManager wraps each pass with the debugify passes if
96 /// needed.
97 /// NOTE: We support legacy custom pass manager only.
98 /// TODO: Add New PM support for custom pass manager.
99 class DebugifyCustomPassManager : public legacy::PassManager {
100   DebugifyStatsMap DIStatsMap;
101   bool EnableDebugifyEach = false;
102 
103 public:
104   using super = legacy::PassManager;
105 
106   void add(Pass *P) override {
107     // Wrap each pass with (-check)-debugify passes if requested, making
108     // exceptions for passes which shouldn't see -debugify instrumentation.
109     bool WrapWithDebugify = EnableDebugifyEach && !P->getAsImmutablePass() &&
110                             !isIRPrintingPass(P) && !isBitcodeWriterPass(P);
111     if (!WrapWithDebugify) {
112       super::add(P);
113       return;
114     }
115 
116     // Apply -debugify/-check-debugify before/after each pass and collect
117     // debug info loss statistics.
118     PassKind Kind = P->getPassKind();
119     StringRef Name = P->getPassName();
120 
121     // TODO: Implement Debugify for LoopPass.
122     switch (Kind) {
123     case PT_Function:
124       super::add(createDebugifyFunctionPass());
125       super::add(P);
126       super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
127       break;
128     case PT_Module:
129       super::add(createDebugifyModulePass());
130       super::add(P);
131       super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
132       break;
133     default:
134       super::add(P);
135       break;
136     }
137   }
138 
139   void enableDebugifyEach() { EnableDebugifyEach = true; }
140 
141   const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
142 };
143 } // namespace llvm
144 
145 #endif // LLVM_TRANSFORM_UTILS_DEBUGIFY_H
146