[DebugInfo][RemoveDIs] Add conversion utilities for new-debug-info format
This patch plumbs the command line --experimental-debuginfo-iterators flag in to the pass managers, so that modules can be converted to the new format, passes run, then converted back to the old format. That allows developers to test-out the new debuginfo representation across some part of LLVM with no further work, and from the command line. It also installs flag-catchers at the various points that bitcode and textual IR can egress from a process, and temporarily convert the module to dbg.value format when doing so. No tests alas as it's designed to be transparent. Differential Revision: https://reviews.llvm.org/D154372
This commit is contained in:
1 parent
1d1fede493
commit
10a9e7442c
8 files changed
+244
-1
No files matched your search
@@ -46,6 +46,7 @@
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassInstrumentation.h"
|
||||
#include "llvm/IR/PassManagerInternal.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/TypeName.h"
|
||||
#include <cassert>
|
||||
@@ -58,8 +59,27 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// RemoveDIs: Provide facilities for converting debug-info from one form to
|
||||
// another, which are no-ops for everything but modules.
|
||||
template <class IRUnitT> inline bool shouldConvertDbgInfo(IRUnitT &IR) {
|
||||
return false;
|
||||
}
|
||||
template <> inline bool shouldConvertDbgInfo(Module &IR) {
|
||||
return !IR.IsNewDbgInfoFormat && UseNewDbgInfoFormat;
|
||||
}
|
||||
template <class IRUnitT> inline void doConvertDbgInfoToNew(IRUnitT &IR) {}
|
||||
template <> inline void doConvertDbgInfoToNew(Module &IR) {
|
||||
IR.convertToNewDbgValues();
|
||||
}
|
||||
template <class IRUnitT> inline void doConvertDebugInfoToOld(IRUnitT &IR) {}
|
||||
template <> inline void doConvertDebugInfoToOld(Module &IR) {
|
||||
IR.convertFromNewDbgValues();
|
||||
}
|
||||
|
||||
/// A special type used by analysis passes to provide an address that
|
||||
/// identifies that particular analysis pass type.
|
||||
///
|
||||
@@ -507,6 +527,12 @@ public:
|
||||
detail::getAnalysisResult<PassInstrumentationAnalysis>(
|
||||
AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...));
|
||||
|
||||
// RemoveDIs: if requested, convert debug-info to DPValue representation
|
||||
// for duration of these passes.
|
||||
bool ShouldConvertDbgInfo = shouldConvertDbgInfo(IR);
|
||||
if (ShouldConvertDbgInfo)
|
||||
doConvertDbgInfoToNew(IR);
|
||||
|
||||
for (auto &Pass : Passes) {
|
||||
// Check the PassInstrumentation's BeforePass callbacks before running the
|
||||
// pass, skip its execution completely if asked to (callback returns
|
||||
@@ -529,6 +555,9 @@ public:
|
||||
PA.intersect(std::move(PassPA));
|
||||
}
|
||||
|
||||
if (ShouldConvertDbgInfo)
|
||||
doConvertDebugInfoToOld(IR);
|
||||
|
||||
// Invalidation was handled after each pass in the above loop for the
|
||||
// current unit of IR. Therefore, the remaining analysis results in the
|
||||
// AnalysisManager are preserved. We mark this with a set so that we don't
|
||||
|
||||
@@ -19,10 +19,20 @@
|
||||
using namespace llvm;
|
||||
|
||||
PreservedAnalyses BitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) {
|
||||
// RemoveDIs: there's no bitcode representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertFromNewDbgValues();
|
||||
|
||||
const ModuleSummaryIndex *Index =
|
||||
EmitSummaryIndex ? &(AM.getResult<ModuleSummaryIndexAnalysis>(M))
|
||||
: nullptr;
|
||||
WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, Index, EmitModuleHash);
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertToNewDbgValues();
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
@@ -54,8 +64,17 @@ namespace {
|
||||
EmitSummaryIndex
|
||||
? &(getAnalysis<ModuleSummaryIndexWrapperPass>().getIndex())
|
||||
: nullptr;
|
||||
// RemoveDIs: there's no bitcode representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertFromNewDbgValues();
|
||||
|
||||
WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, Index,
|
||||
EmitModuleHash);
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertToNewDbgValues();
|
||||
return false;
|
||||
}
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
|
||||
@@ -981,11 +981,29 @@ void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V,
|
||||
}
|
||||
|
||||
void llvm::printMIR(raw_ostream &OS, const Module &M) {
|
||||
// RemoveDIs: as there's no textual form for DPValues yet, print debug-info
|
||||
// in dbg.value format.
|
||||
bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
const_cast<Module &>(M).convertFromNewDbgValues();
|
||||
|
||||
yaml::Output Out(OS);
|
||||
Out << const_cast<Module &>(M);
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
const_cast<Module &>(M).convertToNewDbgValues();
|
||||
}
|
||||
|
||||
void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
|
||||
// RemoveDIs: as there's no textual form for DPValues yet, print debug-info
|
||||
// in dbg.value format.
|
||||
bool IsNewDbgInfoFormat = MF.getFunction().IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
const_cast<Function &>(MF.getFunction()).convertFromNewDbgValues();
|
||||
|
||||
MIRPrinter Printer(OS);
|
||||
Printer.print(MF);
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
const_cast<Function &>(MF.getFunction()).convertToNewDbgValues();
|
||||
}
|
||||
+119
-1
@@ -39,6 +39,7 @@
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/DebugProgramInstruction.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
@@ -285,6 +286,16 @@ static const Module *getModuleFromVal(const Value *V) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const Module *getModuleFromDPI(const DPMarker *Marker) {
|
||||
const Function *M =
|
||||
Marker->getParent() ? Marker->getParent()->getParent() : nullptr;
|
||||
return M ? M->getParent() : nullptr;
|
||||
}
|
||||
|
||||
static const Module *getModuleFromDPI(const DPValue *DPV) {
|
||||
return getModuleFromDPI(DPV->getMarker());
|
||||
}
|
||||
|
||||
static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
|
||||
switch (cc) {
|
||||
default: Out << "cc" << cc; break;
|
||||
@@ -2612,6 +2623,8 @@ public:
|
||||
void printBasicBlock(const BasicBlock *BB);
|
||||
void printInstructionLine(const Instruction &I);
|
||||
void printInstruction(const Instruction &I);
|
||||
void printDPMarker(const DPMarker &DPI);
|
||||
void printDPValue(const DPValue &DPI);
|
||||
|
||||
void printUseListOrder(const Value *V, const std::vector<unsigned> &Shuffle);
|
||||
void printUseLists(const Function *F);
|
||||
@@ -3771,6 +3784,9 @@ void AssemblyWriter::printTypeIdentities() {
|
||||
|
||||
/// printFunction - Print all aspects of a function.
|
||||
void AssemblyWriter::printFunction(const Function *F) {
|
||||
bool ConvertBack = F->IsNewDbgInfoFormat;
|
||||
if (ConvertBack)
|
||||
const_cast<Function *>(F)->convertFromNewDbgValues();
|
||||
if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out);
|
||||
|
||||
if (F->isMaterializable())
|
||||
@@ -3913,6 +3929,8 @@ void AssemblyWriter::printFunction(const Function *F) {
|
||||
Out << "}\n";
|
||||
}
|
||||
|
||||
if (ConvertBack)
|
||||
const_cast<Function *>(F)->convertToNewDbgValues();
|
||||
Machine.purgeFunction();
|
||||
}
|
||||
|
||||
@@ -4007,8 +4025,15 @@ void AssemblyWriter::printInfoComment(const Value &V) {
|
||||
if (const auto *Relocate = dyn_cast<GCRelocateInst>(&V))
|
||||
printGCRelocateComment(*Relocate);
|
||||
|
||||
if (AnnotationWriter)
|
||||
if (AnnotationWriter) {
|
||||
AnnotationWriter->printInfoComment(V, Out);
|
||||
} else if (const Instruction *I = dyn_cast<Instruction>(&V)) {
|
||||
if (I->DbgMarker) {
|
||||
// In the new, experimental DPValue representation of debug-info, print
|
||||
// out which instructions have DPMarkers and where they are.
|
||||
Out << "; dbgmarker @ " << I->DbgMarker;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I,
|
||||
@@ -4468,6 +4493,36 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||
printInfoComment(I);
|
||||
}
|
||||
|
||||
void AssemblyWriter::printDPMarker(const DPMarker &Marker) {
|
||||
// There's no formal representation of a DPMarker -- print purely as a
|
||||
// debugging aid.
|
||||
for (const DPValue &DPI2 : Marker.StoredDPValues) {
|
||||
printDPValue(DPI2);
|
||||
Out << "\n";
|
||||
}
|
||||
|
||||
Out << " DPMarker -> { ";
|
||||
printInstruction(*Marker.MarkedInstr);
|
||||
Out << " }";
|
||||
return;
|
||||
}
|
||||
|
||||
void AssemblyWriter::printDPValue(const DPValue &Value) {
|
||||
// There's no formal representation of a DPValue -- print purely as a
|
||||
// debugging aid.
|
||||
Out << " DPValue { ";
|
||||
auto WriterCtx = getContext();
|
||||
WriteAsOperandInternal(Out, Value.getRawLocation(), WriterCtx, true);
|
||||
Out << ", ";
|
||||
WriteAsOperandInternal(Out, Value.getVariable(), WriterCtx, true);
|
||||
Out << ", ";
|
||||
WriteAsOperandInternal(Out, Value.getExpression(), WriterCtx, true);
|
||||
Out << ", ";
|
||||
WriteAsOperandInternal(Out, Value.getDebugLoc().get(), WriterCtx, true);
|
||||
Out << " marker @" << Value.getMarker();
|
||||
Out << " }";
|
||||
}
|
||||
|
||||
void AssemblyWriter::printMetadataAttachments(
|
||||
const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
|
||||
StringRef Separator) {
|
||||
@@ -4613,11 +4668,19 @@ void BasicBlock::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
|
||||
|
||||
void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
|
||||
bool ShouldPreserveUseListOrder, bool IsForDebug) const {
|
||||
// RemoveDIs: always print with debug-info in intrinsic format.
|
||||
bool ConvertAfter = IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
const_cast<Module *>(this)->convertFromNewDbgValues();
|
||||
|
||||
SlotTracker SlotTable(this);
|
||||
formatted_raw_ostream OS(ROS);
|
||||
AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
|
||||
ShouldPreserveUseListOrder);
|
||||
W.printModule(this);
|
||||
|
||||
if (ConvertAfter)
|
||||
const_cast<Module *>(this)->convertToNewDbgValues();
|
||||
}
|
||||
|
||||
void NamedMDNode::print(raw_ostream &ROS, bool IsForDebug) const {
|
||||
@@ -4694,6 +4757,53 @@ static bool isReferencingMDNode(const Instruction &I) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DPMarker::print(raw_ostream &ROS, bool IsForDebug) const {
|
||||
|
||||
ModuleSlotTracker MST(getModuleFromDPI(this), true);
|
||||
print(ROS, MST, IsForDebug);
|
||||
}
|
||||
|
||||
void DPValue::print(raw_ostream &ROS, bool IsForDebug) const {
|
||||
|
||||
ModuleSlotTracker MST(getModuleFromDPI(this), true);
|
||||
print(ROS, MST, IsForDebug);
|
||||
}
|
||||
|
||||
void DPMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST,
|
||||
bool IsForDebug) const {
|
||||
// There's no formal representation of a DPMarker -- print purely as a
|
||||
// debugging aid.
|
||||
formatted_raw_ostream OS(ROS);
|
||||
SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr));
|
||||
SlotTracker &SlotTable =
|
||||
MST.getMachine() ? *MST.getMachine() : EmptySlotTable;
|
||||
auto incorporateFunction = [&](const Function *F) {
|
||||
if (F)
|
||||
MST.incorporateFunction(*F);
|
||||
};
|
||||
incorporateFunction(getParent() ? getParent()->getParent() : nullptr);
|
||||
AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug);
|
||||
W.printDPMarker(*this);
|
||||
}
|
||||
|
||||
void DPValue::print(raw_ostream &ROS, ModuleSlotTracker &MST,
|
||||
bool IsForDebug) const {
|
||||
// There's no formal representation of a DPValue -- print purely as a
|
||||
// debugging aid.
|
||||
formatted_raw_ostream OS(ROS);
|
||||
SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr));
|
||||
SlotTracker &SlotTable =
|
||||
MST.getMachine() ? *MST.getMachine() : EmptySlotTable;
|
||||
auto incorporateFunction = [&](const Function *F) {
|
||||
if (F)
|
||||
MST.incorporateFunction(*F);
|
||||
};
|
||||
incorporateFunction(Marker->getParent() ? Marker->getParent()->getParent()
|
||||
: nullptr);
|
||||
AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug);
|
||||
W.printDPValue(*this);
|
||||
}
|
||||
|
||||
void Value::print(raw_ostream &ROS, bool IsForDebug) const {
|
||||
bool ShouldInitializeAllMetadata = false;
|
||||
if (auto *I = dyn_cast<Instruction>(this))
|
||||
@@ -4939,6 +5049,14 @@ void ModuleSlotTracker::collectMDNodes(MachineMDNodeListType &L, unsigned LB,
|
||||
LLVM_DUMP_METHOD
|
||||
void Value::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
||||
|
||||
// Value::dump - allow easy printing of Values from the debugger.
|
||||
LLVM_DUMP_METHOD
|
||||
void DPMarker::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
||||
|
||||
// Value::dump - allow easy printing of Values from the debugger.
|
||||
LLVM_DUMP_METHOD
|
||||
void DPValue::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
||||
|
||||
// Type::dump - allow easy printing of Types from the debugger.
|
||||
LLVM_DUMP_METHOD
|
||||
void Type::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
||||
|
||||
@@ -179,6 +179,18 @@ bool BasicBlock::validateDbgValues(bool Assert, bool Msg, raw_ostream *OS) {
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void BasicBlock::dumpDbgValues() const {
|
||||
for (auto &Inst : *this) {
|
||||
if (!Inst.DbgMarker)
|
||||
continue;
|
||||
|
||||
dbgs() << "@ " << Inst.DbgMarker << " ";
|
||||
Inst.DbgMarker->dump();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
void BasicBlock::setIsNewDbgInfoFormat(bool NewFlag) {
|
||||
if (NewFlag && !IsNewDbgInfoFormat)
|
||||
convertToNewDbgValues();
|
||||
|
||||
@@ -39,6 +39,12 @@ public:
|
||||
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
|
||||
|
||||
bool runOnModule(Module &M) override {
|
||||
// RemoveDIs: there's no textual representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertFromNewDbgValues();
|
||||
|
||||
if (llvm::isFunctionInPrintList("*")) {
|
||||
if (!Banner.empty())
|
||||
OS << Banner << "\n";
|
||||
@@ -55,6 +61,10 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
M.convertToNewDbgValues();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,6 +87,12 @@ public:
|
||||
|
||||
// This pass just prints a banner followed by the function as it's processed.
|
||||
bool runOnFunction(Function &F) override {
|
||||
// RemoveDIs: there's no textual representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool IsNewDbgInfoFormat = F.IsNewDbgInfoFormat;
|
||||
if (IsNewDbgInfoFormat)
|
||||
F.convertFromNewDbgValues();
|
||||
|
||||
if (isFunctionInPrintList(F.getName())) {
|
||||
if (forcePrintModuleIR())
|
||||
OS << Banner << " (function: " << F.getName() << ")\n"
|
||||
@@ -84,6 +100,10 @@ public:
|
||||
else
|
||||
OS << Banner << '\n' << static_cast<Value &>(F);
|
||||
}
|
||||
|
||||
if (IsNewDbgInfoFormat)
|
||||
F.convertToNewDbgValues();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern cl::opt<bool> UseNewDbgInfoFormat;
|
||||
// See PassManagers.h for Pass Manager infrastructure overview.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -527,6 +528,11 @@ bool PassManagerImpl::run(Module &M) {
|
||||
dumpArguments();
|
||||
dumpPasses();
|
||||
|
||||
// RemoveDIs: if a command line flag is given, convert to the DPValue
|
||||
// representation of debug-info for the duration of these passes.
|
||||
if (UseNewDbgInfoFormat)
|
||||
M.convertToNewDbgValues();
|
||||
|
||||
for (ImmutablePass *ImPass : getImmutablePasses())
|
||||
Changed |= ImPass->doInitialization(M);
|
||||
|
||||
@@ -539,6 +545,8 @@ bool PassManagerImpl::run(Module &M) {
|
||||
for (ImmutablePass *ImPass : getImmutablePasses())
|
||||
Changed |= ImPass->doFinalization(M);
|
||||
|
||||
M.convertFromNewDbgValues();
|
||||
|
||||
return Changed;
|
||||
}
|
||||
} // namespace legacy
|
||||
|
||||
@@ -31,6 +31,12 @@ PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner,
|
||||
EmitSummaryIndex(EmitSummaryIndex) {}
|
||||
|
||||
PreservedAnalyses PrintModulePass::run(Module &M, ModuleAnalysisManager &AM) {
|
||||
// RemoveDIs: there's no textual representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool ShouldConvert = M.IsNewDbgInfoFormat;
|
||||
if (ShouldConvert)
|
||||
M.convertFromNewDbgValues();
|
||||
|
||||
if (llvm::isFunctionInPrintList("*")) {
|
||||
if (!Banner.empty())
|
||||
OS << Banner << "\n";
|
||||
@@ -57,6 +63,9 @@ PreservedAnalyses PrintModulePass::run(Module &M, ModuleAnalysisManager &AM) {
|
||||
Index->print(OS);
|
||||
}
|
||||
|
||||
if (ShouldConvert)
|
||||
M.convertToNewDbgValues();
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
@@ -66,11 +75,21 @@ PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner)
|
||||
|
||||
PreservedAnalyses PrintFunctionPass::run(Function &F,
|
||||
FunctionAnalysisManager &) {
|
||||
// RemoveDIs: there's no textual representation of the DPValue debug-info,
|
||||
// convert to dbg.values before writing out.
|
||||
bool ShouldConvert = F.IsNewDbgInfoFormat;
|
||||
if (ShouldConvert)
|
||||
F.convertFromNewDbgValues();
|
||||
|
||||
if (isFunctionInPrintList(F.getName())) {
|
||||
if (forcePrintModuleIR())
|
||||
OS << Banner << " (function: " << F.getName() << ")\n" << *F.getParent();
|
||||
else
|
||||
OS << Banner << '\n' << static_cast<Value &>(F);
|
||||
}
|
||||
|
||||
if (ShouldConvert)
|
||||
F.convertToNewDbgValues();
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
Reference in new issue
Block a user