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