mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Revert "[Debugify] Make the debugify aware of the original (-g) Debug Info"
This reverts rG8ee7c7e02953. One test is failing, I'll reland this as soon as possible.
This commit is contained in:
parent
60a660675e
commit
78cda129f4
@ -229,8 +229,8 @@ An IR test case for a transformation can, in many cases, be automatically
|
||||
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``.
|
||||
@ -346,21 +346,6 @@ tests. Changes to this pass are not allowed to break existing tests.
|
||||
|
||||
.. _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
|
||||
----------------------------------------------
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- 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.
|
||||
@ -6,41 +6,19 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \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;
|
||||
@ -62,49 +40,14 @@ bool applyDebugifyMetadata(
|
||||
/// 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;
|
||||
@ -132,26 +75,23 @@ struct DebugifyStatistics {
|
||||
/// 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::FunctionPass *createCheckDebugifyFunctionPass(
|
||||
bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
|
||||
DebugifyStatsMap *StatsMap = nullptr,
|
||||
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
|
||||
DebugInfoPerPassMap *DIPreservationMap = nullptr);
|
||||
llvm::ModulePass *
|
||||
createCheckDebugifyModulePass(bool Strip = false,
|
||||
llvm::StringRef NameOfWrappedPass = "",
|
||||
DebugifyStatsMap *StatsMap = 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;
|
||||
|
||||
@ -163,9 +103,8 @@ struct DebugifyEachInstrumentation {
|
||||
/// 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;
|
||||
@ -173,34 +112,29 @@ public:
|
||||
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);
|
||||
@ -208,23 +142,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// 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; }
|
||||
void enableDebugifyEach() { EnableDebugifyEach = true; }
|
||||
|
||||
bool isSyntheticDebugInfo() const {
|
||||
return Mode == DebugifyMode::SyntheticDebugInfo;
|
||||
}
|
||||
bool isOriginalDebugInfoMode() const {
|
||||
return Mode == DebugifyMode::OriginalDebugInfo;
|
||||
}
|
||||
|
||||
const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
|
||||
DebugInfoPerPassMap &getDebugInfoPerPassMap() { return *DIPreservationMap; }
|
||||
const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- 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.
|
||||
@ -6,10 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \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.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -26,8 +24,6 @@
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
#define DEBUG_TYPE "debugify"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
@ -39,8 +35,6 @@ enum class Level {
|
||||
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"),
|
||||
@ -205,33 +199,16 @@ bool llvm::applyDebugifyMetadata(
|
||||
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) {
|
||||
@ -279,211 +256,6 @@ 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) {
|
||||
@ -622,74 +394,43 @@ bool checkDebugifyMetadata(Module &M,
|
||||
/// 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();
|
||||
@ -698,11 +439,9 @@ struct CheckDebugifyModulePass : public ModulePass {
|
||||
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
|
||||
@ -711,23 +450,16 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
|
||||
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();
|
||||
@ -736,11 +468,9 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
|
||||
static char ID; // Pass identification.
|
||||
|
||||
private:
|
||||
bool Strip;
|
||||
StringRef NameOfWrappedPass;
|
||||
DebugifyStatsMap *StatsMap;
|
||||
DebugInfoPerPassMap *DIPreservationMap;
|
||||
enum DebugifyMode Mode;
|
||||
bool Strip;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@ -766,23 +496,12 @@ void llvm::exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map) {
|
||||
}
|
||||
}
|
||||
|
||||
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 &) {
|
||||
@ -791,24 +510,16 @@ 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,
|
||||
|
@ -1,23 +0,0 @@
|
||||
; 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"}
|
@ -219,16 +219,6 @@ static cl::opt<bool> EnableDebugify(
|
||||
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"));
|
||||
@ -823,19 +813,10 @@ int main(int argc, char **argv) {
|
||||
// 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));
|
||||
|
||||
@ -843,17 +824,8 @@ int main(int argc, char **argv) {
|
||||
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 ||
|
||||
@ -997,14 +969,8 @@ int main(int argc, char **argv) {
|
||||
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
|
||||
|
@ -1,7 +1,6 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Analysis
|
||||
AsmParser
|
||||
BitWriter
|
||||
Core
|
||||
Support
|
||||
TransformUtils
|
||||
@ -14,7 +13,6 @@ add_llvm_unittest(UtilsTests
|
||||
CloningTest.cpp
|
||||
CodeExtractorTest.cpp
|
||||
CodeMoverUtilsTest.cpp
|
||||
DebugifyTest.cpp
|
||||
FunctionComparatorTest.cpp
|
||||
IntegerDivisionTest.cpp
|
||||
LocalTest.cpp
|
||||
|
@ -1,180 +0,0 @@
|
||||
//===- 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)
|
Loading…
Reference in New Issue
Block a user