Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- Debugify.h - Check debug info preservation in optimizations --------===//
  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/original debug info testing
  10. /// utility.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  15. #define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  16.  
  17. #include "llvm/ADT/MapVector.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Bitcode/BitcodeWriterPass.h"
  20. #include "llvm/IR/IRPrintingPasses.h"
  21. #include "llvm/IR/LegacyPassManager.h"
  22. #include "llvm/IR/PassManager.h"
  23. #include "llvm/IR/ValueHandle.h"
  24. #include "llvm/Pass.h"
  25.  
  26. using DebugFnMap =
  27.     llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
  28. using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
  29. using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
  30. using WeakInstValueMap =
  31.     llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
  32.  
  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.  
  46. namespace llvm {
  47. class DIBuilder;
  48.  
  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.  
  61. /// Strip out all of the metadata and debug info inserted by debugify. If no
  62. /// llvm.debugify module-level named metadata is present, this is a no-op.
  63. /// Returns true if any change was made.
  64. bool stripDebugifyMetadata(Module &M);
  65.  
  66. /// Collect original debug information before a pass.
  67. ///
  68. /// \param M The module to collect debug information from.
  69. /// \param Functions A range of functions to collect debug information from.
  70. /// \param DebugInfoBeforePass DI metadata before a pass.
  71. /// \param Banner A prefix string to add to debug/error messages.
  72. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  73. bool collectDebugInfoMetadata(Module &M,
  74.                               iterator_range<Module::iterator> Functions,
  75.                               DebugInfoPerPass &DebugInfoBeforePass,
  76.                               StringRef Banner, StringRef NameOfWrappedPass);
  77.  
  78. /// Check original debug information after a pass.
  79. ///
  80. /// \param M The module to collect debug information from.
  81. /// \param Functions A range of functions to collect debug information from.
  82. /// \param DebugInfoBeforePass DI metadata before a pass.
  83. /// \param Banner A prefix string to add to debug/error messages.
  84. /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
  85. bool checkDebugInfoMetadata(Module &M,
  86.                             iterator_range<Module::iterator> Functions,
  87.                             DebugInfoPerPass &DebugInfoBeforePass,
  88.                             StringRef Banner, StringRef NameOfWrappedPass,
  89.                             StringRef OrigDIVerifyBugsReportFilePath);
  90. } // namespace llvm
  91.  
  92. /// Used to check whether we track synthetic or original debug info.
  93. enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
  94.  
  95. llvm::ModulePass *createDebugifyModulePass(
  96.     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  97.     llvm::StringRef NameOfWrappedPass = "",
  98.     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
  99. llvm::FunctionPass *createDebugifyFunctionPass(
  100.     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  101.     llvm::StringRef NameOfWrappedPass = "",
  102.     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
  103.  
  104. class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
  105.   llvm::StringRef NameOfWrappedPass;
  106.   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  107.   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  108. public:
  109.   NewPMDebugifyPass(
  110.       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  111.       llvm::StringRef NameOfWrappedPass = "",
  112.       DebugInfoPerPass *DebugInfoBeforePass = nullptr)
  113.       : NameOfWrappedPass(NameOfWrappedPass),
  114.         DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
  115.  
  116.   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  117. };
  118.  
  119. /// Track how much `debugify` information (in the `synthetic` mode only)
  120. /// has been lost.
  121. struct DebugifyStatistics {
  122.   /// Number of missing dbg.values.
  123.   unsigned NumDbgValuesMissing = 0;
  124.  
  125.   /// Number of dbg.values expected.
  126.   unsigned NumDbgValuesExpected = 0;
  127.  
  128.   /// Number of instructions with empty debug locations.
  129.   unsigned NumDbgLocsMissing = 0;
  130.  
  131.   /// Number of instructions expected to have debug locations.
  132.   unsigned NumDbgLocsExpected = 0;
  133.  
  134.   /// Get the ratio of missing/expected dbg.values.
  135.   float getMissingValueRatio() const {
  136.     return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
  137.   }
  138.  
  139.   /// Get the ratio of missing/expected instructions with locations.
  140.   float getEmptyLocationRatio() const {
  141.     return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
  142.   }
  143. };
  144.  
  145. /// Map pass names to a per-pass DebugifyStatistics instance.
  146. using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
  147.  
  148. llvm::ModulePass *createCheckDebugifyModulePass(
  149.     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  150.     DebugifyStatsMap *StatsMap = nullptr,
  151.     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  152.     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  153.     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  154.  
  155. llvm::FunctionPass *createCheckDebugifyFunctionPass(
  156.     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  157.     DebugifyStatsMap *StatsMap = nullptr,
  158.     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  159.     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  160.     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
  161.  
  162. class NewPMCheckDebugifyPass
  163.     : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
  164.   llvm::StringRef NameOfWrappedPass;
  165.   llvm::StringRef OrigDIVerifyBugsReportFilePath;
  166.   DebugifyStatsMap *StatsMap;
  167.   DebugInfoPerPass *DebugInfoBeforePass;
  168.   enum DebugifyMode Mode;
  169.   bool Strip;
  170. public:
  171.   NewPMCheckDebugifyPass(
  172.       bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
  173.       DebugifyStatsMap *StatsMap = nullptr,
  174.       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
  175.       DebugInfoPerPass *DebugInfoBeforePass = nullptr,
  176.       llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
  177.       : NameOfWrappedPass(NameOfWrappedPass),
  178.         OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
  179.         StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
  180.         Strip(Strip) {}
  181.  
  182.   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
  183. };
  184.  
  185. namespace llvm {
  186. void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
  187.  
  188. class DebugifyEachInstrumentation {
  189.   llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
  190.   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  191.   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  192.   DebugifyStatsMap *DIStatsMap = nullptr;
  193.  
  194. public:
  195.  
  196.   void registerCallbacks(PassInstrumentationCallbacks &PIC);
  197.   // Used within DebugifyMode::SyntheticDebugInfo mode.
  198.   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
  199.   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
  200.   // Used within DebugifyMode::OriginalDebugInfo mode.
  201.   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
  202.     DebugInfoBeforePass = &PerPassMap;
  203.   }
  204.   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
  205.  
  206.   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
  207.     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
  208.   }
  209.   StringRef getOrigDIVerifyBugsReportFilePath() const {
  210.     return OrigDIVerifyBugsReportFilePath;
  211.   }
  212.  
  213.   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
  214.  
  215.   bool isSyntheticDebugInfo() const {
  216.     return Mode == DebugifyMode::SyntheticDebugInfo;
  217.   }
  218.   bool isOriginalDebugInfoMode() const {
  219.     return Mode == DebugifyMode::OriginalDebugInfo;
  220.   }
  221. };
  222.  
  223. /// DebugifyCustomPassManager wraps each pass with the debugify passes if
  224. /// needed.
  225. /// NOTE: We support legacy custom pass manager only.
  226. /// TODO: Add New PM support for custom pass manager.
  227. class DebugifyCustomPassManager : public legacy::PassManager {
  228.   StringRef OrigDIVerifyBugsReportFilePath;
  229.   DebugifyStatsMap *DIStatsMap = nullptr;
  230.   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
  231.   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
  232.  
  233. public:
  234.   using super = legacy::PassManager;
  235.  
  236.   void add(Pass *P) override {
  237.     // Wrap each pass with (-check)-debugify passes if requested, making
  238.     // exceptions for passes which shouldn't see -debugify instrumentation.
  239.     bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
  240.                             !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
  241.                             !isBitcodeWriterPass(P);
  242.     if (!WrapWithDebugify) {
  243.       super::add(P);
  244.       return;
  245.     }
  246.  
  247.     // Either apply -debugify/-check-debugify before/after each pass and collect
  248.     // debug info loss statistics, or collect and check original debug info in
  249.     // the optimizations.
  250.     PassKind Kind = P->getPassKind();
  251.     StringRef Name = P->getPassName();
  252.  
  253.     // TODO: Implement Debugify for LoopPass.
  254.     switch (Kind) {
  255.     case PT_Function:
  256.       super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
  257.       super::add(P);
  258.       super::add(createCheckDebugifyFunctionPass(
  259.           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
  260.           OrigDIVerifyBugsReportFilePath));
  261.       break;
  262.     case PT_Module:
  263.       super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
  264.       super::add(P);
  265.       super::add(createCheckDebugifyModulePass(
  266.           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
  267.           OrigDIVerifyBugsReportFilePath));
  268.       break;
  269.     default:
  270.       super::add(P);
  271.       break;
  272.     }
  273.   }
  274.  
  275.   // Used within DebugifyMode::SyntheticDebugInfo mode.
  276.   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
  277.   // Used within DebugifyMode::OriginalDebugInfo mode.
  278.   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
  279.     DebugInfoBeforePass = &PerPassDI;
  280.   }
  281.   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
  282.     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
  283.   }
  284.   StringRef getOrigDIVerifyBugsReportFilePath() const {
  285.     return OrigDIVerifyBugsReportFilePath;
  286.   }
  287.  
  288.   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
  289.  
  290.   bool isSyntheticDebugInfo() const {
  291.     return Mode == DebugifyMode::SyntheticDebugInfo;
  292.   }
  293.   bool isOriginalDebugInfoMode() const {
  294.     return Mode == DebugifyMode::OriginalDebugInfo;
  295.   }
  296.  
  297.   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
  298.   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
  299. };
  300. } // namespace llvm
  301.  
  302. #endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
  303.