Debugify.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Debugify.h - Check debug info preservation in optimizations --------===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file Interface to the `debugify` synthetic/original debug info testing
  15. /// utility.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  19. #define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  20. #include "llvm/ADT/MapVector.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/Bitcode/BitcodeWriterPass.h"
  23. #include "llvm/IR/IRPrintingPasses.h"
  24. #include "llvm/IR/LegacyPassManager.h"
  25. #include "llvm/IR/PassManager.h"
  26. #include "llvm/IR/ValueHandle.h"
  27. #include "llvm/Pass.h"
  28. using DebugFnMap = llvm::MapVector<llvm::StringRef, const llvm::DISubprogram *>;
  29. using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
  30. using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
  31. using WeakInstValueMap =
  32. llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
  33. /// Used to track the Debug Info Metadata information.
  34. struct DebugInfoPerPass {
  35. // This maps a function name to its associated DISubprogram.
  36. DebugFnMap DIFunctions;
  37. // This maps an instruction and the info about whether it has !dbg attached.
  38. DebugInstMap DILocations;
  39. // This tracks value (instruction) deletion. If an instruction gets deleted,
  40. // WeakVH nulls itself.
  41. WeakInstValueMap InstToDelete;
  42. // Maps variable into dbg users (#dbg values/declares for this variable).
  43. DebugVarMap DIVariables;
  44. };
  45. /// Map pass names to a per-pass DebugInfoPerPass instance.
  46. using DebugInfoPerPassMap = llvm::MapVector<llvm::StringRef, DebugInfoPerPass>;
  47. namespace llvm {
  48. class DIBuilder;
  49. /// Add synthesized debug information to a module.
  50. ///
  51. /// \param M The module to add debug information to.
  52. /// \param Functions A range of functions to add debug information to.
  53. /// \param Banner A prefix string to add to debug/error messages.
  54. /// \param ApplyToMF A call back that will add debug information to the
  55. /// MachineFunction for a Function. If nullptr, then the
  56. /// MachineFunction (if any) will not be modified.
  57. bool applyDebugifyMetadata(
  58. Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
  59. std::function<bool(DIBuilder &, Function &)> ApplyToMF);
  60. /// Strip out all of the metadata and debug info inserted by debugify. If no
  61. /// llvm.debugify module-level named metadata is present, this is a no-op.
  62. /// Returns true if any change was made.
  63. bool stripDebugifyMetadata(Module &M);
  64. /// Collect original debug information before a pass.
  65. ///
  66. /// \param M The module to collect debug information from.
  67. /// \param Functions A range of functions to collect debug information from.
  68. /// \param DIPreservationMap A map to collect the DI metadata.
  69. /// \param Banner A prefix string to add to debug/error messages.
  70. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  71. bool collectDebugInfoMetadata(Module &M,
  72. iterator_range<Module::iterator> Functions,
  73. DebugInfoPerPassMap &DIPreservationMap,
  74. StringRef Banner, StringRef NameOfWrappedPass);
  75. /// Check original debug information after a pass.
  76. ///
  77. /// \param M The module to collect debug information from.
  78. /// \param Functions A range of functions to collect debug information from.
  79. /// \param DIPreservationMap A map used to check collected the DI metadata.
  80. /// \param Banner A prefix string to add to debug/error messages.
  81. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  82. bool checkDebugInfoMetadata(Module &M,
  83. iterator_range<Module::iterator> Functions,
  84. DebugInfoPerPassMap &DIPreservationMap,
  85. StringRef Banner, StringRef NameOfWrappedPass,
  86. StringRef OrigDIVerifyBugsReportFilePath);
  87. } // namespace llvm
  88. /// Used to check whether we track synthetic or original debug info.
  89. enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
  90. llvm::ModulePass *createDebugifyModulePass(
  91. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  92. llvm::StringRef NameOfWrappedPass = "",
  93. DebugInfoPerPassMap *DIPreservationMap = nullptr);
  94. llvm::FunctionPass *createDebugifyFunctionPass(
  95. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  96. llvm::StringRef NameOfWrappedPass = "",
  97. DebugInfoPerPassMap *DIPreservationMap = nullptr);
  98. struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
  99. llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  100. };
  101. /// Track how much `debugify` information (in the `synthetic` mode only)
  102. /// has been lost.
  103. struct DebugifyStatistics {
  104. /// Number of missing dbg.values.
  105. unsigned NumDbgValuesMissing = 0;
  106. /// Number of dbg.values expected.
  107. unsigned NumDbgValuesExpected = 0;
  108. /// Number of instructions with empty debug locations.
  109. unsigned NumDbgLocsMissing = 0;
  110. /// Number of instructions expected to have debug locations.
  111. unsigned NumDbgLocsExpected = 0;
  112. /// Get the ratio of missing/expected dbg.values.
  113. float getMissingValueRatio() const {
  114. return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
  115. }
  116. /// Get the ratio of missing/expected instructions with locations.
  117. float getEmptyLocationRatio() const {
  118. return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
  119. }
  120. };
  121. /// Map pass names to a per-pass DebugifyStatistics instance.
  122. using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
  123. llvm::ModulePass *createCheckDebugifyModulePass(
  124. bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  125. DebugifyStatsMap *StatsMap = nullptr,
  126. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  127. DebugInfoPerPassMap *DIPreservationMap = nullptr,
  128. llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  129. llvm::FunctionPass *createCheckDebugifyFunctionPass(
  130. bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  131. DebugifyStatsMap *StatsMap = nullptr,
  132. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  133. DebugInfoPerPassMap *DIPreservationMap = nullptr,
  134. llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  135. struct NewPMCheckDebugifyPass
  136. : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
  137. llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  138. };
  139. namespace llvm {
  140. void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
  141. struct DebugifyEachInstrumentation {
  142. DebugifyStatsMap StatsMap;
  143. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  144. };
  145. /// DebugifyCustomPassManager wraps each pass with the debugify passes if
  146. /// needed.
  147. /// NOTE: We support legacy custom pass manager only.
  148. /// TODO: Add New PM support for custom pass manager.
  149. class DebugifyCustomPassManager : public legacy::PassManager {
  150. StringRef OrigDIVerifyBugsReportFilePath;
  151. DebugifyStatsMap *DIStatsMap = nullptr;
  152. DebugInfoPerPassMap *DIPreservationMap = nullptr;
  153. enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  154. public:
  155. using super = legacy::PassManager;
  156. void add(Pass *P) override {
  157. // Wrap each pass with (-check)-debugify passes if requested, making
  158. // exceptions for passes which shouldn't see -debugify instrumentation.
  159. bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
  160. !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
  161. !isBitcodeWriterPass(P);
  162. if (!WrapWithDebugify) {
  163. super::add(P);
  164. return;
  165. }
  166. // Either apply -debugify/-check-debugify before/after each pass and collect
  167. // debug info loss statistics, or collect and check original debug info in
  168. // the optimizations.
  169. PassKind Kind = P->getPassKind();
  170. StringRef Name = P->getPassName();
  171. // TODO: Implement Debugify for LoopPass.
  172. switch (Kind) {
  173. case PT_Function:
  174. super::add(createDebugifyFunctionPass(Mode, Name, DIPreservationMap));
  175. super::add(P);
  176. super::add(createCheckDebugifyFunctionPass(
  177. isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DIPreservationMap,
  178. OrigDIVerifyBugsReportFilePath));
  179. break;
  180. case PT_Module:
  181. super::add(createDebugifyModulePass(Mode, Name, DIPreservationMap));
  182. super::add(P);
  183. super::add(createCheckDebugifyModulePass(
  184. isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DIPreservationMap,
  185. OrigDIVerifyBugsReportFilePath));
  186. break;
  187. default:
  188. super::add(P);
  189. break;
  190. }
  191. }
  192. // Used within DebugifyMode::SyntheticDebugInfo mode.
  193. void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
  194. // Used within DebugifyMode::OriginalDebugInfo mode.
  195. void setDIPreservationMap(DebugInfoPerPassMap &PerPassMap) {
  196. DIPreservationMap = &PerPassMap;
  197. }
  198. void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
  199. OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
  200. }
  201. StringRef getOrigDIVerifyBugsReportFilePath() const {
  202. return OrigDIVerifyBugsReportFilePath;
  203. }
  204. void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
  205. bool isSyntheticDebugInfo() const {
  206. return Mode == DebugifyMode::SyntheticDebugInfo;
  207. }
  208. bool isOriginalDebugInfoMode() const {
  209. return Mode == DebugifyMode::OriginalDebugInfo;
  210. }
  211. const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
  212. DebugInfoPerPassMap &getDebugInfoPerPassMap() { return *DIPreservationMap; }
  213. };
  214. } // namespace llvm
  215. #endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  216. #ifdef __GNUC__
  217. #pragma GCC diagnostic pop
  218. #endif