Debugify.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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 =
  29. llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
  30. using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
  31. using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
  32. using WeakInstValueMap =
  33. llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
  34. /// Used to track the Debug Info Metadata information.
  35. struct DebugInfoPerPass {
  36. // This maps a function name to its associated DISubprogram.
  37. DebugFnMap DIFunctions;
  38. // This maps an instruction and the info about whether it has !dbg attached.
  39. DebugInstMap DILocations;
  40. // This tracks value (instruction) deletion. If an instruction gets deleted,
  41. // WeakVH nulls itself.
  42. WeakInstValueMap InstToDelete;
  43. // Maps variable into dbg users (#dbg values/declares for this variable).
  44. DebugVarMap DIVariables;
  45. };
  46. namespace llvm {
  47. class DIBuilder;
  48. /// Add synthesized debug information to a module.
  49. ///
  50. /// \param M The module to add debug information to.
  51. /// \param Functions A range of functions to add debug information to.
  52. /// \param Banner A prefix string to add to debug/error messages.
  53. /// \param ApplyToMF A call back that will add debug information to the
  54. /// MachineFunction for a Function. If nullptr, then the
  55. /// MachineFunction (if any) will not be modified.
  56. bool applyDebugifyMetadata(
  57. Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
  58. std::function<bool(DIBuilder &, Function &)> ApplyToMF);
  59. /// Strip out all of the metadata and debug info inserted by debugify. If no
  60. /// llvm.debugify module-level named metadata is present, this is a no-op.
  61. /// Returns true if any change was made.
  62. bool stripDebugifyMetadata(Module &M);
  63. /// Collect original debug information before a pass.
  64. ///
  65. /// \param M The module to collect debug information from.
  66. /// \param Functions A range of functions to collect debug information from.
  67. /// \param DebugInfoBeforePass DI metadata before a pass.
  68. /// \param Banner A prefix string to add to debug/error messages.
  69. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  70. bool collectDebugInfoMetadata(Module &M,
  71. iterator_range<Module::iterator> Functions,
  72. DebugInfoPerPass &DebugInfoBeforePass,
  73. StringRef Banner, StringRef NameOfWrappedPass);
  74. /// Check original debug information after a pass.
  75. ///
  76. /// \param M The module to collect debug information from.
  77. /// \param Functions A range of functions to collect debug information from.
  78. /// \param DebugInfoBeforePass DI metadata before a pass.
  79. /// \param Banner A prefix string to add to debug/error messages.
  80. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  81. bool checkDebugInfoMetadata(Module &M,
  82. iterator_range<Module::iterator> Functions,
  83. DebugInfoPerPass &DebugInfoBeforePass,
  84. StringRef Banner, StringRef NameOfWrappedPass,
  85. StringRef OrigDIVerifyBugsReportFilePath);
  86. } // namespace llvm
  87. /// Used to check whether we track synthetic or original debug info.
  88. enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
  89. llvm::ModulePass *createDebugifyModulePass(
  90. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  91. llvm::StringRef NameOfWrappedPass = "",
  92. DebugInfoPerPass *DebugInfoBeforePass = nullptr);
  93. llvm::FunctionPass *createDebugifyFunctionPass(
  94. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  95. llvm::StringRef NameOfWrappedPass = "",
  96. DebugInfoPerPass *DebugInfoBeforePass = nullptr);
  97. class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
  98. llvm::StringRef NameOfWrappedPass;
  99. DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  100. enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  101. public:
  102. NewPMDebugifyPass(
  103. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  104. llvm::StringRef NameOfWrappedPass = "",
  105. DebugInfoPerPass *DebugInfoBeforePass = nullptr)
  106. : NameOfWrappedPass(NameOfWrappedPass),
  107. DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
  108. llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  109. };
  110. /// Track how much `debugify` information (in the `synthetic` mode only)
  111. /// has been lost.
  112. struct DebugifyStatistics {
  113. /// Number of missing dbg.values.
  114. unsigned NumDbgValuesMissing = 0;
  115. /// Number of dbg.values expected.
  116. unsigned NumDbgValuesExpected = 0;
  117. /// Number of instructions with empty debug locations.
  118. unsigned NumDbgLocsMissing = 0;
  119. /// Number of instructions expected to have debug locations.
  120. unsigned NumDbgLocsExpected = 0;
  121. /// Get the ratio of missing/expected dbg.values.
  122. float getMissingValueRatio() const {
  123. return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
  124. }
  125. /// Get the ratio of missing/expected instructions with locations.
  126. float getEmptyLocationRatio() const {
  127. return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
  128. }
  129. };
  130. /// Map pass names to a per-pass DebugifyStatistics instance.
  131. using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
  132. llvm::ModulePass *createCheckDebugifyModulePass(
  133. bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  134. DebugifyStatsMap *StatsMap = nullptr,
  135. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  136. DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  137. llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  138. llvm::FunctionPass *createCheckDebugifyFunctionPass(
  139. bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  140. DebugifyStatsMap *StatsMap = nullptr,
  141. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  142. DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  143. llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  144. class NewPMCheckDebugifyPass
  145. : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
  146. llvm::StringRef NameOfWrappedPass;
  147. llvm::StringRef OrigDIVerifyBugsReportFilePath;
  148. DebugifyStatsMap *StatsMap;
  149. DebugInfoPerPass *DebugInfoBeforePass;
  150. enum DebugifyMode Mode;
  151. bool Strip;
  152. public:
  153. NewPMCheckDebugifyPass(
  154. bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  155. DebugifyStatsMap *StatsMap = nullptr,
  156. enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  157. DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  158. llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
  159. : NameOfWrappedPass(NameOfWrappedPass),
  160. OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
  161. StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
  162. Strip(Strip) {}
  163. llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  164. };
  165. namespace llvm {
  166. void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
  167. class DebugifyEachInstrumentation {
  168. llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
  169. DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  170. enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  171. DebugifyStatsMap *DIStatsMap = nullptr;
  172. public:
  173. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  174. // Used within DebugifyMode::SyntheticDebugInfo mode.
  175. void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
  176. const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
  177. // Used within DebugifyMode::OriginalDebugInfo mode.
  178. void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
  179. DebugInfoBeforePass = &PerPassMap;
  180. }
  181. DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
  182. void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
  183. OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
  184. }
  185. StringRef getOrigDIVerifyBugsReportFilePath() const {
  186. return OrigDIVerifyBugsReportFilePath;
  187. }
  188. void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
  189. bool isSyntheticDebugInfo() const {
  190. return Mode == DebugifyMode::SyntheticDebugInfo;
  191. }
  192. bool isOriginalDebugInfoMode() const {
  193. return Mode == DebugifyMode::OriginalDebugInfo;
  194. }
  195. };
  196. /// DebugifyCustomPassManager wraps each pass with the debugify passes if
  197. /// needed.
  198. /// NOTE: We support legacy custom pass manager only.
  199. /// TODO: Add New PM support for custom pass manager.
  200. class DebugifyCustomPassManager : public legacy::PassManager {
  201. StringRef OrigDIVerifyBugsReportFilePath;
  202. DebugifyStatsMap *DIStatsMap = nullptr;
  203. DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  204. enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  205. public:
  206. using super = legacy::PassManager;
  207. void add(Pass *P) override {
  208. // Wrap each pass with (-check)-debugify passes if requested, making
  209. // exceptions for passes which shouldn't see -debugify instrumentation.
  210. bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
  211. !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
  212. !isBitcodeWriterPass(P);
  213. if (!WrapWithDebugify) {
  214. super::add(P);
  215. return;
  216. }
  217. // Either apply -debugify/-check-debugify before/after each pass and collect
  218. // debug info loss statistics, or collect and check original debug info in
  219. // the optimizations.
  220. PassKind Kind = P->getPassKind();
  221. StringRef Name = P->getPassName();
  222. // TODO: Implement Debugify for LoopPass.
  223. switch (Kind) {
  224. case PT_Function:
  225. super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
  226. super::add(P);
  227. super::add(createCheckDebugifyFunctionPass(
  228. isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
  229. OrigDIVerifyBugsReportFilePath));
  230. break;
  231. case PT_Module:
  232. super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
  233. super::add(P);
  234. super::add(createCheckDebugifyModulePass(
  235. isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
  236. OrigDIVerifyBugsReportFilePath));
  237. break;
  238. default:
  239. super::add(P);
  240. break;
  241. }
  242. }
  243. // Used within DebugifyMode::SyntheticDebugInfo mode.
  244. void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
  245. // Used within DebugifyMode::OriginalDebugInfo mode.
  246. void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
  247. DebugInfoBeforePass = &PerPassDI;
  248. }
  249. void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
  250. OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
  251. }
  252. StringRef getOrigDIVerifyBugsReportFilePath() const {
  253. return OrigDIVerifyBugsReportFilePath;
  254. }
  255. void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
  256. bool isSyntheticDebugInfo() const {
  257. return Mode == DebugifyMode::SyntheticDebugInfo;
  258. }
  259. bool isOriginalDebugInfoMode() const {
  260. return Mode == DebugifyMode::OriginalDebugInfo;
  261. }
  262. const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
  263. DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
  264. };
  265. } // namespace llvm
  266. #endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  267. #ifdef __GNUC__
  268. #pragma GCC diagnostic pop
  269. #endif