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 struct DebugifyEachInstrumentation {
96   DebugifyStatsMap StatsMap;
97 
98   void registerCallbacks(PassInstrumentationCallbacks &PIC);
99 };
100 
101 /// DebugifyCustomPassManager wraps each pass with the debugify passes if
102 /// needed.
103 /// NOTE: We support legacy custom pass manager only.
104 /// TODO: Add New PM support for custom pass manager.
105 class DebugifyCustomPassManager : public legacy::PassManager {
106   DebugifyStatsMap DIStatsMap;
107   bool EnableDebugifyEach = false;
108 
109 public:
110   using super = legacy::PassManager;
111 
112   void add(Pass *P) override {
113     // Wrap each pass with (-check)-debugify passes if requested, making
114     // exceptions for passes which shouldn't see -debugify instrumentation.
115     bool WrapWithDebugify = EnableDebugifyEach && !P->getAsImmutablePass() &&
116                             !isIRPrintingPass(P) && !isBitcodeWriterPass(P);
117     if (!WrapWithDebugify) {
118       super::add(P);
119       return;
120     }
121 
122     // Apply -debugify/-check-debugify before/after each pass and collect
123     // debug info loss statistics.
124     PassKind Kind = P->getPassKind();
125     StringRef Name = P->getPassName();
126 
127     // TODO: Implement Debugify for LoopPass.
128     switch (Kind) {
129     case PT_Function:
130       super::add(createDebugifyFunctionPass());
131       super::add(P);
132       super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
133       break;
134     case PT_Module:
135       super::add(createDebugifyModulePass());
136       super::add(P);
137       super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
138       break;
139     default:
140       super::add(P);
141       break;
142     }
143   }
144 
145   void enableDebugifyEach() { EnableDebugifyEach = true; }
146 
147   const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
148 };
149 } // namespace llvm
150 
151 #endif // LLVM_TRANSFORM_UTILS_DEBUGIFY_H
152