#ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
#define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
using DebugFnMap =
llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
using WeakInstValueMap =
llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
struct DebugInfoPerPass {
DebugFnMap DIFunctions;
DebugInstMap DILocations;
WeakInstValueMap InstToDelete;
DebugVarMap DIVariables;
};
namespace llvm {
class DIBuilder;
bool applyDebugifyMetadata(
Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
std::function<bool(DIBuilder &, Function &)> ApplyToMF);
bool stripDebugifyMetadata(Module &M);
bool collectDebugInfoMetadata(Module &M,
iterator_range<Module::iterator> Functions,
DebugInfoPerPass &DebugInfoBeforePass,
StringRef Banner, StringRef NameOfWrappedPass);
bool checkDebugInfoMetadata(Module &M,
iterator_range<Module::iterator> Functions,
DebugInfoPerPass &DebugInfoBeforePass,
StringRef Banner, StringRef NameOfWrappedPass,
StringRef OrigDIVerifyBugsReportFilePath);
}
enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
llvm::ModulePass *createDebugifyModulePass(
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
llvm::StringRef NameOfWrappedPass = "",
DebugInfoPerPass *DebugInfoBeforePass = nullptr);
llvm::FunctionPass *createDebugifyFunctionPass(
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
llvm::StringRef NameOfWrappedPass = "",
DebugInfoPerPass *DebugInfoBeforePass = nullptr);
class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
llvm::StringRef NameOfWrappedPass;
DebugInfoPerPass *DebugInfoBeforePass = nullptr;
enum DebugifyMode Mode = DebugifyMode::NoDebugify;
public:
NewPMDebugifyPass(
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
llvm::StringRef NameOfWrappedPass = "",
DebugInfoPerPass *DebugInfoBeforePass = nullptr)
: NameOfWrappedPass(NameOfWrappedPass),
DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
};
struct DebugifyStatistics {
unsigned NumDbgValuesMissing = 0;
unsigned NumDbgValuesExpected = 0;
unsigned NumDbgLocsMissing = 0;
unsigned NumDbgLocsExpected = 0;
float getMissingValueRatio() const {
return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
}
float getEmptyLocationRatio() const {
return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
}
};
using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
llvm::ModulePass *createCheckDebugifyModulePass(
bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
DebugifyStatsMap *StatsMap = nullptr,
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
DebugInfoPerPass *DebugInfoBeforePass = nullptr,
llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
llvm::FunctionPass *createCheckDebugifyFunctionPass(
bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
DebugifyStatsMap *StatsMap = nullptr,
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
DebugInfoPerPass *DebugInfoBeforePass = nullptr,
llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
class NewPMCheckDebugifyPass
: public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
llvm::StringRef NameOfWrappedPass;
llvm::StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *StatsMap;
DebugInfoPerPass *DebugInfoBeforePass;
enum DebugifyMode Mode;
bool Strip;
public:
NewPMCheckDebugifyPass(
bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
DebugifyStatsMap *StatsMap = nullptr,
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
DebugInfoPerPass *DebugInfoBeforePass = nullptr,
llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
: NameOfWrappedPass(NameOfWrappedPass),
OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
Strip(Strip) {}
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
};
namespace llvm {
void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
class DebugifyEachInstrumentation {
llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
DebugInfoPerPass *DebugInfoBeforePass = nullptr;
enum DebugifyMode Mode = DebugifyMode::NoDebugify;
DebugifyStatsMap *DIStatsMap = nullptr;
public:
void registerCallbacks(PassInstrumentationCallbacks &PIC);
void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
DebugInfoBeforePass = &PerPassMap;
}
DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
}
StringRef getOrigDIVerifyBugsReportFilePath() const {
return OrigDIVerifyBugsReportFilePath;
}
void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
bool isSyntheticDebugInfo() const {
return Mode == DebugifyMode::SyntheticDebugInfo;
}
bool isOriginalDebugInfoMode() const {
return Mode == DebugifyMode::OriginalDebugInfo;
}
};
class DebugifyCustomPassManager : public legacy::PassManager {
StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *DIStatsMap = nullptr;
DebugInfoPerPass *DebugInfoBeforePass = nullptr;
enum DebugifyMode Mode = DebugifyMode::NoDebugify;
public:
using super = legacy::PassManager;
void add(Pass *P) override {
bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
!P->getAsImmutablePass() && !isIRPrintingPass(P) &&
!isBitcodeWriterPass(P);
if (!WrapWithDebugify) {
super::add(P);
return;
}
PassKind Kind = P->getPassKind();
StringRef Name = P->getPassName();
switch (Kind) {
case PT_Function:
super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
super::add(P);
super::add(createCheckDebugifyFunctionPass(
isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
OrigDIVerifyBugsReportFilePath));
break;
case PT_Module:
super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
super::add(P);
super::add(createCheckDebugifyModulePass(
isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
OrigDIVerifyBugsReportFilePath));
break;
default:
super::add(P);
break;
}
}
void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
DebugInfoBeforePass = &PerPassDI;
}
void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
}
StringRef getOrigDIVerifyBugsReportFilePath() const {
return OrigDIVerifyBugsReportFilePath;
}
void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
bool isSyntheticDebugInfo() const {
return Mode == DebugifyMode::SyntheticDebugInfo;
}
bool isOriginalDebugInfoMode() const {
return Mode == DebugifyMode::OriginalDebugInfo;
}
const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
};
}
#endif