Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:42

0001 //===- Debugify.h - Check debug info preservation in optimizations --------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file Interface to the `debugify` synthetic/original debug info testing
0010 /// utility.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
0015 #define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
0016 
0017 #include "llvm/ADT/MapVector.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/Bitcode/BitcodeWriterPass.h"
0020 #include "llvm/IR/IRPrintingPasses.h"
0021 #include "llvm/IR/LegacyPassManager.h"
0022 #include "llvm/IR/Module.h"
0023 #include "llvm/IR/PassInstrumentation.h"
0024 #include "llvm/IR/PassManager.h"
0025 #include "llvm/IR/ValueHandle.h"
0026 #include "llvm/Pass.h"
0027 
0028 using DebugFnMap =
0029     llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
0030 using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
0031 using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
0032 using WeakInstValueMap =
0033     llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
0034 
0035 /// Used to track the Debug Info Metadata information.
0036 struct DebugInfoPerPass {
0037   // This maps a function name to its associated DISubprogram.
0038   DebugFnMap DIFunctions;
0039   // This maps an instruction and the info about whether it has !dbg attached.
0040   DebugInstMap DILocations;
0041   // This tracks value (instruction) deletion. If an instruction gets deleted,
0042   // WeakVH nulls itself.
0043   WeakInstValueMap InstToDelete;
0044   // Maps variable into dbg users (#dbg values/declares for this variable).
0045   DebugVarMap DIVariables;
0046 };
0047 
0048 namespace llvm {
0049 class DIBuilder;
0050 
0051 /// Add synthesized debug information to a module.
0052 ///
0053 /// \param M The module to add debug information to.
0054 /// \param Functions A range of functions to add debug information to.
0055 /// \param Banner A prefix string to add to debug/error messages.
0056 /// \param ApplyToMF A call back that will add debug information to the
0057 ///                  MachineFunction for a Function. If nullptr, then the
0058 ///                  MachineFunction (if any) will not be modified.
0059 bool applyDebugifyMetadata(
0060     Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
0061     std::function<bool(DIBuilder &, Function &)> ApplyToMF);
0062 
0063 /// Strip out all of the metadata and debug info inserted by debugify. If no
0064 /// llvm.debugify module-level named metadata is present, this is a no-op.
0065 /// Returns true if any change was made.
0066 bool stripDebugifyMetadata(Module &M);
0067 
0068 /// Collect original debug information before a pass.
0069 ///
0070 /// \param M The module to collect debug information from.
0071 /// \param Functions A range of functions to collect debug information from.
0072 /// \param DebugInfoBeforePass DI metadata before a pass.
0073 /// \param Banner A prefix string to add to debug/error messages.
0074 /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
0075 bool collectDebugInfoMetadata(Module &M,
0076                               iterator_range<Module::iterator> Functions,
0077                               DebugInfoPerPass &DebugInfoBeforePass,
0078                               StringRef Banner, StringRef NameOfWrappedPass);
0079 
0080 /// Check original debug information after a pass.
0081 ///
0082 /// \param M The module to collect debug information from.
0083 /// \param Functions A range of functions to collect debug information from.
0084 /// \param DebugInfoBeforePass DI metadata before a pass.
0085 /// \param Banner A prefix string to add to debug/error messages.
0086 /// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
0087 bool checkDebugInfoMetadata(Module &M,
0088                             iterator_range<Module::iterator> Functions,
0089                             DebugInfoPerPass &DebugInfoBeforePass,
0090                             StringRef Banner, StringRef NameOfWrappedPass,
0091                             StringRef OrigDIVerifyBugsReportFilePath);
0092 } // namespace llvm
0093 
0094 /// Used to check whether we track synthetic or original debug info.
0095 enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
0096 
0097 llvm::ModulePass *createDebugifyModulePass(
0098     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0099     llvm::StringRef NameOfWrappedPass = "",
0100     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
0101 llvm::FunctionPass *createDebugifyFunctionPass(
0102     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0103     llvm::StringRef NameOfWrappedPass = "",
0104     DebugInfoPerPass *DebugInfoBeforePass = nullptr);
0105 
0106 class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
0107   llvm::StringRef NameOfWrappedPass;
0108   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
0109   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
0110 public:
0111   NewPMDebugifyPass(
0112       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0113       llvm::StringRef NameOfWrappedPass = "",
0114       DebugInfoPerPass *DebugInfoBeforePass = nullptr)
0115       : NameOfWrappedPass(NameOfWrappedPass),
0116         DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
0117 
0118   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
0119 };
0120 
0121 /// Track how much `debugify` information (in the `synthetic` mode only)
0122 /// has been lost.
0123 struct DebugifyStatistics {
0124   /// Number of missing dbg.values.
0125   unsigned NumDbgValuesMissing = 0;
0126 
0127   /// Number of dbg.values expected.
0128   unsigned NumDbgValuesExpected = 0;
0129 
0130   /// Number of instructions with empty debug locations.
0131   unsigned NumDbgLocsMissing = 0;
0132 
0133   /// Number of instructions expected to have debug locations.
0134   unsigned NumDbgLocsExpected = 0;
0135 
0136   /// Get the ratio of missing/expected dbg.values.
0137   float getMissingValueRatio() const {
0138     return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
0139   }
0140 
0141   /// Get the ratio of missing/expected instructions with locations.
0142   float getEmptyLocationRatio() const {
0143     return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
0144   }
0145 };
0146 
0147 /// Map pass names to a per-pass DebugifyStatistics instance.
0148 using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
0149 
0150 llvm::ModulePass *createCheckDebugifyModulePass(
0151     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
0152     DebugifyStatsMap *StatsMap = nullptr,
0153     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0154     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
0155     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
0156 
0157 llvm::FunctionPass *createCheckDebugifyFunctionPass(
0158     bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
0159     DebugifyStatsMap *StatsMap = nullptr,
0160     enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0161     DebugInfoPerPass *DebugInfoBeforePass = nullptr,
0162     llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
0163 
0164 class NewPMCheckDebugifyPass
0165     : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
0166   llvm::StringRef NameOfWrappedPass;
0167   llvm::StringRef OrigDIVerifyBugsReportFilePath;
0168   DebugifyStatsMap *StatsMap;
0169   DebugInfoPerPass *DebugInfoBeforePass;
0170   enum DebugifyMode Mode;
0171   bool Strip;
0172 public:
0173   NewPMCheckDebugifyPass(
0174       bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
0175       DebugifyStatsMap *StatsMap = nullptr,
0176       enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
0177       DebugInfoPerPass *DebugInfoBeforePass = nullptr,
0178       llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
0179       : NameOfWrappedPass(NameOfWrappedPass),
0180         OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
0181         StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
0182         Strip(Strip) {}
0183 
0184   llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
0185 };
0186 
0187 namespace llvm {
0188 void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
0189 
0190 class DebugifyEachInstrumentation {
0191   llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
0192   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
0193   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
0194   DebugifyStatsMap *DIStatsMap = nullptr;
0195 
0196 public:
0197   void registerCallbacks(PassInstrumentationCallbacks &PIC,
0198                          ModuleAnalysisManager &MAM);
0199   // Used within DebugifyMode::SyntheticDebugInfo mode.
0200   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
0201   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
0202   // Used within DebugifyMode::OriginalDebugInfo mode.
0203   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
0204     DebugInfoBeforePass = &PerPassMap;
0205   }
0206   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
0207 
0208   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
0209     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
0210   }
0211   StringRef getOrigDIVerifyBugsReportFilePath() const {
0212     return OrigDIVerifyBugsReportFilePath;
0213   }
0214 
0215   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
0216 
0217   bool isSyntheticDebugInfo() const {
0218     return Mode == DebugifyMode::SyntheticDebugInfo;
0219   }
0220   bool isOriginalDebugInfoMode() const {
0221     return Mode == DebugifyMode::OriginalDebugInfo;
0222   }
0223 };
0224 
0225 /// DebugifyCustomPassManager wraps each pass with the debugify passes if
0226 /// needed.
0227 /// NOTE: We support legacy custom pass manager only.
0228 /// TODO: Add New PM support for custom pass manager.
0229 class DebugifyCustomPassManager : public legacy::PassManager {
0230   StringRef OrigDIVerifyBugsReportFilePath;
0231   DebugifyStatsMap *DIStatsMap = nullptr;
0232   DebugInfoPerPass *DebugInfoBeforePass = nullptr;
0233   enum DebugifyMode Mode = DebugifyMode::NoDebugify;
0234 
0235 public:
0236   using super = legacy::PassManager;
0237 
0238   void add(Pass *P) override {
0239     // Wrap each pass with (-check)-debugify passes if requested, making
0240     // exceptions for passes which shouldn't see -debugify instrumentation.
0241     bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
0242                             !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
0243                             !isBitcodeWriterPass(P);
0244     if (!WrapWithDebugify) {
0245       super::add(P);
0246       return;
0247     }
0248 
0249     // Either apply -debugify/-check-debugify before/after each pass and collect
0250     // debug info loss statistics, or collect and check original debug info in
0251     // the optimizations.
0252     PassKind Kind = P->getPassKind();
0253     StringRef Name = P->getPassName();
0254 
0255     // TODO: Implement Debugify for LoopPass.
0256     switch (Kind) {
0257     case PT_Function:
0258       super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
0259       super::add(P);
0260       super::add(createCheckDebugifyFunctionPass(
0261           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
0262           OrigDIVerifyBugsReportFilePath));
0263       break;
0264     case PT_Module:
0265       super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
0266       super::add(P);
0267       super::add(createCheckDebugifyModulePass(
0268           isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
0269           OrigDIVerifyBugsReportFilePath));
0270       break;
0271     default:
0272       super::add(P);
0273       break;
0274     }
0275   }
0276 
0277   // Used within DebugifyMode::SyntheticDebugInfo mode.
0278   void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
0279   // Used within DebugifyMode::OriginalDebugInfo mode.
0280   void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
0281     DebugInfoBeforePass = &PerPassDI;
0282   }
0283   void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
0284     OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
0285   }
0286   StringRef getOrigDIVerifyBugsReportFilePath() const {
0287     return OrigDIVerifyBugsReportFilePath;
0288   }
0289 
0290   void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
0291 
0292   bool isSyntheticDebugInfo() const {
0293     return Mode == DebugifyMode::SyntheticDebugInfo;
0294   }
0295   bool isOriginalDebugInfoMode() const {
0296     return Mode == DebugifyMode::OriginalDebugInfo;
0297   }
0298 
0299   const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
0300   DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
0301 };
0302 } // namespace llvm
0303 
0304 #endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H