This reverts rG8ee7c7e02953.
One test is failing, I'll reland this as soon as possible.
mutated to test debug info handling within that transformation. This is a
simple way to test for proper debug info handling.
-The ``debugify`` utility pass
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The ``debugify`` utility
+^^^^^^^^^^^^^^^^^^^^^^^^
The ``debugify`` testing utility is just a pair of passes: ``debugify`` and
``check-debugify``.
.. _MIRDebugify:
-Test original debug info preservation in optimizations
-------------------------------------------------------
-
-In addition to automatically generating debug info, the checks provided by
-the ``debugify`` utility pass can also be used to test the preservation of
-pre-existing debug info metadata. It could be run as follows:
-
-.. code-block:: bash
-
- # Run the pass by checking original Debug Info preservation.
- $ opt -verify-debuginfo-preserve -pass-to-test sample.ll
-
- # Check the preservation of original Debug Info after each pass.
- $ opt -verify-each-debuginfo-preserve -O2 sample.ll
-
Mutation testing for MIR-level transformations
----------------------------------------------
-//===- Debugify.h - Check debug info preservation in optimizations --------===//
+//===- Debugify.h - Attach synthetic debug info to everything -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//
///
-/// \file Interface to the `debugify` synthetic/original debug info testing
-/// utility.
+/// \file Interface to the `debugify` synthetic debug info testing utility.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
#define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
-#include "llvm/ADT/DenseMap.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"
-
-using DebugFnMap = llvm::DenseMap<llvm::StringRef, const llvm::DISubprogram *>;
-using DebugInstMap = llvm::DenseMap<const llvm::Instruction *, bool>;
-using WeakInstValueMap =
- llvm::DenseMap<const llvm::Instruction *, llvm::WeakVH>;
-
-/// Used to track the Debug Info Metadata information.
-struct DebugInfoPerPass {
- // This maps a function name to its associated DISubprogram.
- DebugFnMap DIFunctions;
- // This maps an instruction and the info about whether it has !dbg attached.
- DebugInstMap DILocations;
- // This tracks value (instruction) deletion. If an instruction gets deleted,
- // WeakVH nulls itself.
- WeakInstValueMap InstToDelete;
-};
-
-/// Map pass names to a per-pass DebugInfoPerPass instance.
-using DebugInfoPerPassMap = llvm::MapVector<llvm::StringRef, DebugInfoPerPass>;
namespace llvm {
class DIBuilder;
/// Returns true if any change was made.
bool stripDebugifyMetadata(Module &M);
-/// Collect original debug information before a pass.
-///
-/// \param M The module to collect debug information from.
-/// \param Functions A range of functions to collect debug information from.
-/// \param DIPreservationMap A map to collect the DI metadata.
-/// \param Banner A prefix string to add to debug/error messages.
-/// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
-bool collectDebugInfoMetadata(Module &M,
- iterator_range<Module::iterator> Functions,
- DebugInfoPerPassMap &DIPreservationMap,
- StringRef Banner, StringRef NameOfWrappedPass);
-
-/// Check original debug information after a pass.
-///
-/// \param M The module to collect debug information from.
-/// \param Functions A range of functions to collect debug information from.
-/// \param DIPreservationMap A map used to check collected the DI metadata.
-/// \param Banner A prefix string to add to debug/error messages.
-/// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
-bool checkDebugInfoMetadata(Module &M,
- iterator_range<Module::iterator> Functions,
- DebugInfoPerPassMap &DIPreservationMap,
- StringRef Banner, StringRef NameOfWrappedPass);
-} // namespace llvm
-
-/// Used to check whether we track synthetic or original debug info.
-enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
-
-llvm::ModulePass *createDebugifyModulePass(
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- llvm::StringRef NameOfWrappedPass = "",
- DebugInfoPerPassMap *DIPreservationMap = nullptr);
-llvm::FunctionPass *createDebugifyFunctionPass(
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- llvm::StringRef NameOfWrappedPass = "",
- DebugInfoPerPassMap *DIPreservationMap = nullptr);
+llvm::ModulePass *createDebugifyModulePass();
+llvm::FunctionPass *createDebugifyFunctionPass();
struct NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
};
-/// Track how much `debugify` information (in the `synthetic` mode only)
-/// has been lost.
+/// Track how much `debugify` information has been lost.
struct DebugifyStatistics {
/// Number of missing dbg.values.
unsigned NumDbgValuesMissing = 0;
/// Map pass names to a per-pass DebugifyStatistics instance.
using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
-llvm::ModulePass *createCheckDebugifyModulePass(
- bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr);
+void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
+
+llvm::ModulePass *
+createCheckDebugifyModulePass(bool Strip = false,
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
-llvm::FunctionPass *createCheckDebugifyFunctionPass(
- bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr);
+llvm::FunctionPass *
+createCheckDebugifyFunctionPass(bool Strip = false,
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
struct NewPMCheckDebugifyPass
: public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
};
-namespace llvm {
-void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
-
struct DebugifyEachInstrumentation {
DebugifyStatsMap StatsMap;
/// NOTE: We support legacy custom pass manager only.
/// TODO: Add New PM support for custom pass manager.
class DebugifyCustomPassManager : public legacy::PassManager {
- DebugifyStatsMap *DIStatsMap = nullptr;
- DebugInfoPerPassMap *DIPreservationMap = nullptr;
- enum DebugifyMode Mode = DebugifyMode::NoDebugify;
+ DebugifyStatsMap DIStatsMap;
+ bool EnableDebugifyEach = false;
public:
using super = legacy::PassManager;
void add(Pass *P) override {
// Wrap each pass with (-check)-debugify passes if requested, making
// exceptions for passes which shouldn't see -debugify instrumentation.
- bool WrapWithDebugify =
- Mode != DebugifyMode::NoDebugify &&
- !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
- !isBitcodeWriterPass(P);
+ bool WrapWithDebugify = EnableDebugifyEach && !P->getAsImmutablePass() &&
+ !isIRPrintingPass(P) && !isBitcodeWriterPass(P);
if (!WrapWithDebugify) {
super::add(P);
return;
}
- // Either apply -debugify/-check-debugify before/after each pass and collect
- // debug info loss statistics, or collect and check original debug info in
- // the optimizations.
+ // Apply -debugify/-check-debugify before/after each pass and collect
+ // debug info loss statistics.
PassKind Kind = P->getPassKind();
StringRef Name = P->getPassName();
// TODO: Implement Debugify for LoopPass.
switch (Kind) {
case PT_Function:
- super::add(createDebugifyFunctionPass(Mode, Name, DIPreservationMap));
+ super::add(createDebugifyFunctionPass());
super::add(P);
- super::add(createCheckDebugifyFunctionPass(
- isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DIPreservationMap));
+ super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
break;
case PT_Module:
- super::add(createDebugifyModulePass(Mode, Name, DIPreservationMap));
+ super::add(createDebugifyModulePass());
super::add(P);
- super::add(createCheckDebugifyModulePass(
- isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DIPreservationMap));
+ super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
break;
default:
super::add(P);
}
}
- // Used within DebugifyMode::SyntheticDebugInfo mode.
- void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
- // Used within DebugifyMode::OriginalDebugInfo mode.
- void setDIPreservationMap(DebugInfoPerPassMap &PerPassMap) {
- DIPreservationMap = &PerPassMap;
- }
- void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
-
- bool isSyntheticDebugInfo() const {
- return Mode == DebugifyMode::SyntheticDebugInfo;
- }
- bool isOriginalDebugInfoMode() const {
- return Mode == DebugifyMode::OriginalDebugInfo;
- }
+ void enableDebugifyEach() { EnableDebugifyEach = true; }
- const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
- DebugInfoPerPassMap &getDebugInfoPerPassMap() { return *DIPreservationMap; }
+ const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
};
} // namespace llvm
-//===- Debugify.cpp - Check debug info preservation in optimizations ------===//
+//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//
///
-/// \file In the `synthetic` mode, the `-debugify` attaches synthetic debug info
-/// to everything. It can be used to create targeted tests for debug info
-/// preservation. In addition, when using the `original` mode, it can check
-/// original debug info preservation. The `synthetic` mode is default one.
+/// \file This pass attaches synthetic debug info to everything. It can be used
+/// to create targeted tests for debug info preservation.
///
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
-#define DEBUG_TYPE "debugify"
-
using namespace llvm;
namespace {
Locations,
LocationsAndVariables
};
-
-// Used for the synthetic mode only.
cl::opt<Level> DebugifyLevel(
"debugify-level", cl::desc("Kind of debug info to add"),
cl::values(clEnumValN(Level::Locations, "locations", "Locations only"),
return true;
}
-static bool
-applyDebugify(Function &F,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr,
- StringRef NameOfWrappedPass = "") {
+static bool applyDebugify(Function &F) {
Module &M = *F.getParent();
auto FuncIt = F.getIterator();
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
- "FunctionDebugify: ", /*ApplyToMF*/ nullptr);
- assert(DIPreservationMap);
- return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap,
- "FunctionDebugify (original debuginfo)",
- NameOfWrappedPass);
+ return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ "FunctionDebugify: ", /*ApplyToMF=*/nullptr);
}
-static bool
-applyDebugify(Module &M,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr,
- StringRef NameOfWrappedPass = "") {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return applyDebugifyMetadata(M, M.functions(),
- "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
- return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap,
- "ModuleDebugify (original debuginfo)",
- NameOfWrappedPass);
+static bool applyDebugify(Module &M) {
+ return applyDebugifyMetadata(M, M.functions(),
+ "ModuleDebugify: ", /*ApplyToMF=*/nullptr);
}
bool llvm::stripDebugifyMetadata(Module &M) {
return Changed;
}
-bool llvm::collectDebugInfoMetadata(Module &M,
- iterator_range<Module::iterator> Functions,
- DebugInfoPerPassMap &DIPreservationMap,
- StringRef Banner,
- StringRef NameOfWrappedPass) {
- LLVM_DEBUG(dbgs() << Banner << ": (before) " << NameOfWrappedPass << '\n');
-
- // Clear the map with the debug info before every single pass.
- DIPreservationMap.clear();
-
- if (!M.getNamedMetadata("llvm.dbg.cu")) {
- dbg() << Banner << ": Skipping module without debug info\n";
- return false;
- }
-
- // Visit each instruction.
- for (Function &F : Functions) {
- if (isFunctionSkipped(F))
- continue;
-
- // Collect the DISubprogram.
- auto *SP = F.getSubprogram();
- DIPreservationMap[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP});
- if (SP)
- LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
-
- for (BasicBlock &BB : F) {
- // Collect debug locations (!dbg).
- // TODO: Collect dbg.values.
- for (Instruction &I : BB) {
- // Skip PHIs.
- if (isa<PHINode>(I))
- continue;
-
- // Skip debug instructions.
- if (isa<DbgInfoIntrinsic>(&I))
- continue;
-
- LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
- DIPreservationMap[NameOfWrappedPass].InstToDelete.insert({&I, &I});
-
- const DILocation *Loc = I.getDebugLoc().get();
- bool HasLoc = Loc != nullptr;
- DIPreservationMap[NameOfWrappedPass].DILocations.insert({&I, HasLoc});
- }
- }
- }
-
- return true;
-}
-
-// This checks the preservation of original debug info attached to functions.
-static bool checkFunctions(const DebugFnMap &DIFunctionsBefore,
- const DebugFnMap &DIFunctionsAfter,
- StringRef NameOfWrappedPass,
- StringRef FileNameFromCU) {
- bool Preserved = true;
- for (const auto &F : DIFunctionsAfter) {
- if (F.second)
- continue;
- auto SPIt = DIFunctionsBefore.find(F.first);
- if (SPIt == DIFunctionsBefore.end()) {
- dbg() << "ERROR: " << NameOfWrappedPass
- << " did not generate DISubprogram for " << F.first << " from "
- << FileNameFromCU << '\n';
- Preserved = false;
- } else {
- auto SP = SPIt->second;
- if (!SP)
- continue;
- // If the function had the SP attached before the pass, consider it as
- // a debug info bug.
- dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of "
- << F.first << " from " << FileNameFromCU << '\n';
- Preserved = false;
- }
- }
-
- return Preserved;
-}
-
-// This checks the preservation of the original debug info attached to
-// instructions.
-static bool checkInstructions(const DebugInstMap &DILocsBefore,
- const DebugInstMap &DILocsAfter,
- const WeakInstValueMap &InstToDelete,
- StringRef NameOfWrappedPass,
- StringRef FileNameFromCU) {
- bool Preserved = true;
- for (const auto &L : DILocsAfter) {
- if (L.second)
- continue;
- auto Instr = L.first;
-
- // In order to avoid pointer reuse/recycling, skip the values that might
- // have been deleted during a pass.
- auto WeakInstrPtr = InstToDelete.find(Instr);
- if (WeakInstrPtr != InstToDelete.end() && !WeakInstrPtr->second)
- continue;
-
- auto FnName = Instr->getFunction()->getName();
- auto BB = Instr->getParent();
- auto BBName = BB->hasName() ? BB->getName() : "no-name";
-
- auto InstrIt = DILocsBefore.find(Instr);
- if (InstrIt == DILocsBefore.end()) {
- dbg() << "WARNING: " << NameOfWrappedPass
- << " did not generate DILocation for " << *Instr
- << " (BB: " << BBName << ", Fn: " << FnName
- << ", File: " << FileNameFromCU << ")\n";
- Preserved = false;
- } else {
- if (!InstrIt->second)
- continue;
- // If the instr had the !dbg attached before the pass, consider it as
- // a debug info issue.
- dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of "
- << *Instr << " (BB: " << BBName << ", Fn: " << FnName
- << ", File: " << FileNameFromCU << ")\n";
- Preserved = false;
- }
- }
-
- return Preserved;
-}
-
-bool llvm::checkDebugInfoMetadata(Module &M,
- iterator_range<Module::iterator> Functions,
- DebugInfoPerPassMap &DIPreservationMap,
- StringRef Banner,
- StringRef NameOfWrappedPass) {
- LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n');
-
- if (!M.getNamedMetadata("llvm.dbg.cu")) {
- dbg() << Banner << ": Skipping module without debug info\n";
- return false;
- }
-
- // Map the debug info holding DIs after a pass.
- DebugInfoPerPassMap DIPreservationAfter;
-
- // Visit each instruction.
- for (Function &F : Functions) {
- if (isFunctionSkipped(F))
- continue;
-
- // TODO: Collect metadata other than DISubprograms.
- // Collect the DISubprogram.
- auto *SP = F.getSubprogram();
- DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP});
- if (SP)
- LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
-
- for (BasicBlock &BB : F) {
- // Collect debug locations (!dbg attachments).
- // TODO: Collect dbg.values.
- for (Instruction &I : BB) {
- // Skip PHIs.
- if (isa<PHINode>(I))
- continue;
-
- // Skip debug instructions.
- if (isa<DbgInfoIntrinsic>(&I))
- continue;
-
- LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
-
- const DILocation *Loc = I.getDebugLoc().get();
- bool HasLoc = Loc != nullptr;
-
- DIPreservationAfter[NameOfWrappedPass].DILocations.insert({&I, HasLoc});
- }
- }
- }
-
- // TODO: The name of the module could be read better?
- StringRef FileNameFromCU =
- (cast<DICompileUnit>(M.getNamedMetadata("llvm.dbg.cu")->getOperand(0)))
- ->getFilename();
-
- auto DIFunctionsBefore = DIPreservationMap[NameOfWrappedPass].DIFunctions;
- auto DIFunctionsAfter = DIPreservationAfter[NameOfWrappedPass].DIFunctions;
-
- auto DILocsBefore = DIPreservationMap[NameOfWrappedPass].DILocations;
- auto DILocsAfter = DIPreservationAfter[NameOfWrappedPass].DILocations;
-
- auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete;
-
- bool ResultForFunc = checkFunctions(DIFunctionsBefore, DIFunctionsAfter,
- NameOfWrappedPass, FileNameFromCU);
- bool ResultForInsts =
- checkInstructions(DILocsBefore, DILocsAfter, InstToDelete,
- NameOfWrappedPass, FileNameFromCU);
- bool Result = ResultForFunc && ResultForInsts;
-
- StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner;
- if (Result)
- dbg() << ResultBanner << ": PASS\n";
- else
- dbg() << ResultBanner << ": FAIL\n";
-
- LLVM_DEBUG(dbgs() << "\n\n");
- return Result;
-}
-
namespace {
/// Return true if a mis-sized diagnostic is issued for \p DVI.
bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
/// ModulePass for attaching synthetic debug info to everything, used with the
/// legacy module pass manager.
struct DebugifyModulePass : public ModulePass {
- bool runOnModule(Module &M) override {
- return applyDebugify(M, Mode, DIPreservationMap, NameOfWrappedPass);
- }
+ bool runOnModule(Module &M) override { return applyDebugify(M); }
- DebugifyModulePass(enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- StringRef NameOfWrappedPass = "",
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
- : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
- DIPreservationMap(DIPreservationMap), Mode(Mode) {}
+ DebugifyModulePass() : ModulePass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
-
-private:
- StringRef NameOfWrappedPass;
- DebugInfoPerPassMap *DIPreservationMap;
- enum DebugifyMode Mode;
};
/// FunctionPass for attaching synthetic debug info to instructions within a
/// single function, used with the legacy module pass manager.
struct DebugifyFunctionPass : public FunctionPass {
- bool runOnFunction(Function &F) override {
- return applyDebugify(F, Mode, DIPreservationMap, NameOfWrappedPass);
- }
+ bool runOnFunction(Function &F) override { return applyDebugify(F); }
- DebugifyFunctionPass(
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- StringRef NameOfWrappedPass = "",
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
- : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
- DIPreservationMap(DIPreservationMap), Mode(Mode) {}
+ DebugifyFunctionPass() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
-
-private:
- StringRef NameOfWrappedPass;
- DebugInfoPerPassMap *DIPreservationMap;
- enum DebugifyMode Mode;
};
/// ModulePass for checking debug info inserted by -debugify, used with the
/// legacy module pass manager.
struct CheckDebugifyModulePass : public ModulePass {
bool runOnModule(Module &M) override {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
- "CheckModuleDebugify", Strip, StatsMap);
- return checkDebugInfoMetadata(
- M, M.functions(), *DIPreservationMap,
- "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass);
+ return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
+ "CheckModuleDebugify", Strip, StatsMap);
}
- CheckDebugifyModulePass(
- bool Strip = false, StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
- : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
- StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
- Strip(Strip) {}
+ CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
static char ID; // Pass identification.
private:
+ bool Strip;
StringRef NameOfWrappedPass;
DebugifyStatsMap *StatsMap;
- DebugInfoPerPassMap *DIPreservationMap;
- enum DebugifyMode Mode;
- bool Strip;
};
/// FunctionPass for checking debug info inserted by -debugify-function, used
bool runOnFunction(Function &F) override {
Module &M = *F.getParent();
auto FuncIt = F.getIterator();
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
- NameOfWrappedPass, "CheckFunctionDebugify",
- Strip, StatsMap);
- return checkDebugInfoMetadata(
- M, make_range(FuncIt, std::next(FuncIt)), *DIPreservationMap,
- "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass);
+ return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ NameOfWrappedPass, "CheckFunctionDebugify",
+ Strip, StatsMap);
}
- CheckDebugifyFunctionPass(
- bool Strip = false, StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr,
- enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
- : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
- StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
- Strip(Strip) {}
+ CheckDebugifyFunctionPass(bool Strip = false,
+ StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
static char ID; // Pass identification.
private:
+ bool Strip;
StringRef NameOfWrappedPass;
DebugifyStatsMap *StatsMap;
- DebugInfoPerPassMap *DIPreservationMap;
- enum DebugifyMode Mode;
- bool Strip;
};
} // end anonymous namespace
}
}
-ModulePass *createDebugifyModulePass(enum DebugifyMode Mode,
- llvm::StringRef NameOfWrappedPass,
- DebugInfoPerPassMap *DIPreservationMap) {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return new DebugifyModulePass();
- assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
- return new DebugifyModulePass(Mode, NameOfWrappedPass, DIPreservationMap);
+ModulePass *llvm::createDebugifyModulePass() {
+ return new DebugifyModulePass();
}
-FunctionPass *
-createDebugifyFunctionPass(enum DebugifyMode Mode,
- llvm::StringRef NameOfWrappedPass,
- DebugInfoPerPassMap *DIPreservationMap) {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return new DebugifyFunctionPass();
- assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
- return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DIPreservationMap);
+FunctionPass *llvm::createDebugifyFunctionPass() {
+ return new DebugifyFunctionPass();
}
PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
return PreservedAnalyses::all();
}
-ModulePass *createCheckDebugifyModulePass(
- bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
- enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
- assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
- return new CheckDebugifyModulePass(false, NameOfWrappedPass, nullptr, Mode,
- DIPreservationMap);
+ModulePass *llvm::createCheckDebugifyModulePass(bool Strip,
+ StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
}
-FunctionPass *createCheckDebugifyFunctionPass(
- bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
- enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) {
- if (Mode == DebugifyMode::SyntheticDebugInfo)
- return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
- assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
- return new CheckDebugifyFunctionPass(false, NameOfWrappedPass, nullptr, Mode,
- DIPreservationMap);
+FunctionPass *
+llvm::createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
}
PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
+++ /dev/null
-; RUN: opt -verify-debuginfo-preserve -instcombine -S -o - < %s 2>&1 | FileCheck %s
-
-; CHECK: ModuleDebugify (original debuginfo): Skipping module without debug info
-; CHECK-NEXT: CheckModuleDebugify (original debuginfo): Skipping module without debug info
-
-; ModuleID = 'no-dbg-info.c'
-source_filename = "no-dbg-info.c"
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-; Function Attrs: nounwind uwtable
-define dso_local i32 @fn() {
- %1 = call i32 (...) @fn2()
- ret i32 %1
-}
-
-declare dso_local i32 @fn2(...)
-
-!llvm.module.flags = !{!0}
-!llvm.ident = !{!1}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{!"clang version 11.0.0"}
cl::desc(
"Start the pipeline with debugify and end it with check-debugify"));
-static cl::opt<bool> VerifyDebugInfoPreserve(
- "verify-debuginfo-preserve",
- cl::desc("Start the pipeline with collecting and end it with checking of "
- "debug info preservation."));
-
-static cl::opt<bool> VerifyEachDebugInfoPreserve(
- "verify-each-debuginfo-preserve",
- cl::desc("Start each pass with collecting and end it with checking of "
- "debug info preservation."));
-
static cl::opt<bool>
PrintBreakpoints("print-breakpoints-for-testing",
cl::desc("Print select breakpoints location for testing"));
// about to build. If the -debugify-each option is set, wrap each pass with
// the (-check)-debugify passes.
DebugifyCustomPassManager Passes;
- DebugifyStatsMap DIStatsMap;
- DebugInfoPerPassMap DIPreservationMap;
- if (DebugifyEach) {
- Passes.setDebugifyMode(DebugifyMode::SyntheticDebugInfo);
- Passes.setDIStatsMap(DIStatsMap);
- } else if (VerifyEachDebugInfoPreserve) {
- Passes.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
- Passes.setDIPreservationMap(DIPreservationMap);
- }
+ if (DebugifyEach)
+ Passes.enableDebugifyEach();
- bool AddOneTimeDebugifyPasses =
- (EnableDebugify && !DebugifyEach) ||
- (VerifyDebugInfoPreserve && !VerifyEachDebugInfoPreserve);
+ bool AddOneTimeDebugifyPasses = EnableDebugify && !DebugifyEach;
Passes.add(new TargetLibraryInfoWrapperPass(TLII));
Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis()
: TargetIRAnalysis()));
- if (AddOneTimeDebugifyPasses) {
- if (EnableDebugify) {
- Passes.setDIStatsMap(DIStatsMap);
- Passes.add(createDebugifyModulePass());
- } else if (VerifyDebugInfoPreserve) {
- Passes.setDIPreservationMap(DIPreservationMap);
- Passes.add(createDebugifyModulePass(
- DebugifyMode::OriginalDebugInfo, "",
- &(Passes.getDebugInfoPerPassMap())));
- }
- }
+ if (AddOneTimeDebugifyPasses)
+ Passes.add(createDebugifyModulePass());
std::unique_ptr<legacy::FunctionPassManager> FPasses;
if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
- if (AddOneTimeDebugifyPasses) {
- if (EnableDebugify)
- Passes.add(createCheckDebugifyModulePass(false));
- else if (VerifyDebugInfoPreserve)
- Passes.add(createCheckDebugifyModulePass(
- false, "", nullptr, DebugifyMode::OriginalDebugInfo,
- &(Passes.getDebugInfoPerPassMap())));
- }
+ if (AddOneTimeDebugifyPasses)
+ Passes.add(createCheckDebugifyModulePass(false));
// In run twice mode, we want to make sure the output is bit-by-bit
// equivalent if we run the pass manager again, so setup two buffers and
set(LLVM_LINK_COMPONENTS
Analysis
AsmParser
- BitWriter
Core
Support
TransformUtils
CloningTest.cpp
CodeExtractorTest.cpp
CodeMoverUtilsTest.cpp
- DebugifyTest.cpp
FunctionComparatorTest.cpp
IntegerDivisionTest.cpp
LocalTest.cpp
+++ /dev/null
-//===- DebugifyTest.cpp - Debugify unit tests -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/AsmParser/Parser.h"
-#include "llvm/IR/DebugInfoMetadata.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Transforms/Utils/Debugify.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-
-static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
- SMDiagnostic Err;
- std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
- if (!Mod)
- Err.print("DebugifyTest", errs());
- return Mod;
-}
-
-namespace llvm {
-void initializeDebugInfoDropPass(PassRegistry &);
-void initializeDebugInfoDummyAnalysisPass(PassRegistry &);
-
-namespace {
-struct DebugInfoDrop : public FunctionPass {
- static char ID;
- bool runOnFunction(Function &F) override {
- // Drop DISubprogram.
- F.setSubprogram(nullptr);
- for (BasicBlock &BB : F) {
- // Remove debug locations.
- for (Instruction &I : BB)
- I.setDebugLoc(DebugLoc());
- }
-
- return false;
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- }
-
- DebugInfoDrop() : FunctionPass(ID) {}
-};
-
-struct DebugInfoDummyAnalysis : public FunctionPass {
- static char ID;
- bool runOnFunction(Function &F) override {
- // Do nothing, so debug info stays untouched.
- return false;
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-
- DebugInfoDummyAnalysis() : FunctionPass(ID) {}
-};
-}
-
-char DebugInfoDrop::ID = 0;
-char DebugInfoDummyAnalysis::ID = 0;
-
-TEST(DebugInfoDrop, DropOriginalDebugInfo) {
- LLVMContext C;
- std::unique_ptr<Module> M = parseIR(C, R"(
- define i16 @f(i16 %a) !dbg !6 {
- %b = add i16 %a, 1, !dbg !11
- call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
- ret i16 0, !dbg !11
- }
- declare void @llvm.dbg.value(metadata, metadata, metadata)
-
- !llvm.dbg.cu = !{!0}
- !llvm.module.flags = !{!5}
-
- !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
- !1 = !DIFile(filename: "t.ll", directory: "/")
- !2 = !{}
- !5 = !{i32 2, !"Debug Info Version", i32 3}
- !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
- !7 = !DISubroutineType(types: !2)
- !8 = !{!9}
- !9 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 1, type: !10)
- !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
- !11 = !DILocation(line: 1, column: 1, scope: !6)
- )");
-
- DebugInfoDrop *P = new DebugInfoDrop();
-
- DebugInfoPerPassMap DIPreservationMap;
- DebugifyCustomPassManager Passes;
- Passes.setDIPreservationMap(DIPreservationMap);
- Passes.add(createDebugifyModulePass(DebugifyMode::OriginalDebugInfo, "",
- &(Passes.getDebugInfoPerPassMap())));
- Passes.add(P);
- Passes.add(createCheckDebugifyModulePass(false, "", nullptr,
- DebugifyMode::OriginalDebugInfo,
- &(Passes.getDebugInfoPerPassMap())));
-
- testing::internal::CaptureStderr();
- Passes.run(*M);
-
- std::string StdOut = testing::internal::GetCapturedStderr();
-
- std::string ErrorForSP = "ERROR: dropped DISubprogram of";
- std::string WarningForLoc = "WARNING: dropped DILocation of";
- std::string FinalResult = "CheckModuleDebugify (original debuginfo): FAIL";
-
- EXPECT_TRUE(StdOut.find(ErrorForSP) != std::string::npos);
- EXPECT_TRUE(StdOut.find(WarningForLoc) != std::string::npos);
- EXPECT_TRUE(StdOut.find(FinalResult) != std::string::npos);
-}
-
-TEST(DebugInfoDummyAnalysis, PreserveOriginalDebugInfo) {
- LLVMContext C;
- std::unique_ptr<Module> M = parseIR(C, R"(
- define i32 @g(i32 %b) !dbg !6 {
- %c = add i32 %b, 1, !dbg !11
- call void @llvm.dbg.value(metadata i32 %c, metadata !9, metadata !DIExpression()), !dbg !11
- ret i32 1, !dbg !11
- }
- declare void @llvm.dbg.value(metadata, metadata, metadata)
-
- !llvm.dbg.cu = !{!0}
- !llvm.module.flags = !{!5}
-
- !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
- !1 = !DIFile(filename: "test.ll", directory: "/")
- !2 = !{}
- !5 = !{i32 2, !"Debug Info Version", i32 3}
- !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
- !7 = !DISubroutineType(types: !2)
- !8 = !{!9}
- !9 = !DILocalVariable(name: "c", scope: !6, file: !1, line: 1, type: !10)
- !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
- !11 = !DILocation(line: 1, column: 1, scope: !6)
- )");
-
- DebugInfoDummyAnalysis *P = new DebugInfoDummyAnalysis();
-
- DebugInfoPerPassMap DIPreservationMap;
- DebugifyCustomPassManager Passes;
- Passes.setDIPreservationMap(DIPreservationMap);
- Passes.add(createDebugifyModulePass(DebugifyMode::OriginalDebugInfo, "",
- &(Passes.getDebugInfoPerPassMap())));
- Passes.add(P);
- Passes.add(createCheckDebugifyModulePass(false, "", nullptr,
- DebugifyMode::OriginalDebugInfo,
- &(Passes.getDebugInfoPerPassMap())));
-
- testing::internal::CaptureStderr();
- Passes.run(*M);
-
- std::string StdOut = testing::internal::GetCapturedStderr();
-
- std::string ErrorForSP = "ERROR: dropped DISubprogram of";
- std::string WarningForLoc = "WARNING: dropped DILocation of";
- std::string FinalResult = "CheckModuleDebugify (original debuginfo): PASS";
-
- EXPECT_TRUE(StdOut.find(ErrorForSP) == std::string::npos);
- EXPECT_TRUE(StdOut.find(WarningForLoc) == std::string::npos);
- EXPECT_TRUE(StdOut.find(FinalResult) != std::string::npos);
-}
-
-} // end namespace llvm
-
-INITIALIZE_PASS_BEGIN(DebugInfoDrop, "debuginfodroppass", "debuginfodroppass",
- false, false)
-INITIALIZE_PASS_END(DebugInfoDrop, "debuginfodroppass", "debuginfodroppass", false,
- false)
-
-INITIALIZE_PASS_BEGIN(DebugInfoDummyAnalysis, "debuginfodummyanalysispass",
- "debuginfodummyanalysispass", false, false)
-INITIALIZE_PASS_END(DebugInfoDummyAnalysis, "debuginfodummyanalysispass",
- "debuginfodummyanalysispass", false, false)