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 } // namespace llvm 44 45 llvm::ModulePass *createDebugifyModulePass(); 46 llvm::FunctionPass *createDebugifyFunctionPass(); 47 48 struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> { 49 llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); 50 }; 51 52 /// Track how much `debugify` information has been lost. 53 struct DebugifyStatistics { 54 /// Number of missing dbg.values. 55 unsigned NumDbgValuesMissing = 0; 56 57 /// Number of dbg.values expected. 58 unsigned NumDbgValuesExpected = 0; 59 60 /// Number of instructions with empty debug locations. 61 unsigned NumDbgLocsMissing = 0; 62 63 /// Number of instructions expected to have debug locations. 64 unsigned NumDbgLocsExpected = 0; 65 66 /// Get the ratio of missing/expected dbg.values. 67 float getMissingValueRatio() const { 68 return float(NumDbgValuesMissing) / float(NumDbgLocsExpected); 69 } 70 71 /// Get the ratio of missing/expected instructions with locations. 72 float getEmptyLocationRatio() const { 73 return float(NumDbgLocsMissing) / float(NumDbgLocsExpected); 74 } 75 }; 76 77 /// Map pass names to a per-pass DebugifyStatistics instance. 78 using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>; 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 namespace llvm { 96 /// DebugifyCustomPassManager wraps each pass with the debugify passes if 97 /// needed. 98 /// NOTE: We support legacy custom pass manager only. 99 /// TODO: Add New PM support for custom pass manager. 100 class DebugifyCustomPassManager : public legacy::PassManager { 101 DebugifyStatsMap DIStatsMap; 102 bool EnableDebugifyEach = false; 103 104 public: 105 using super = legacy::PassManager; 106 107 void add(Pass *P) override { 108 // Wrap each pass with (-check)-debugify passes if requested, making 109 // exceptions for passes which shouldn't see -debugify instrumentation. 110 bool WrapWithDebugify = EnableDebugifyEach && !P->getAsImmutablePass() && 111 !isIRPrintingPass(P) && !isBitcodeWriterPass(P); 112 if (!WrapWithDebugify) { 113 super::add(P); 114 return; 115 } 116 117 // Apply -debugify/-check-debugify before/after each pass and collect 118 // debug info loss statistics. 119 PassKind Kind = P->getPassKind(); 120 StringRef Name = P->getPassName(); 121 122 // TODO: Implement Debugify for LoopPass. 123 switch (Kind) { 124 case PT_Function: 125 super::add(createDebugifyFunctionPass()); 126 super::add(P); 127 super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap)); 128 break; 129 case PT_Module: 130 super::add(createDebugifyModulePass()); 131 super::add(P); 132 super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap)); 133 break; 134 default: 135 super::add(P); 136 break; 137 } 138 } 139 140 void enableDebugifyEach() { EnableDebugifyEach = true; } 141 142 const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; } 143 }; 144 } // namespace llvm 145 146 #endif // LLVM_TRANSFORM_UTILS_DEBUGIFY_H 147