diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -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 @@ -58,8 +59,27 @@ #include #include +extern llvm::cl::opt UseNewDbgInfoFormat; + namespace llvm { +// RemoveDIs: Provide facilities for converting debug-info from one form to +// another, which are no-ops for everything but modules. +template inline bool shouldConvertDbgInfo(IRUnitT &IR) { + return false; +} +template <> inline bool shouldConvertDbgInfo(Module &IR) { + return !IR.IsNewDbgInfoFormat && UseNewDbgInfoFormat; +} +template inline void doConvertDbgInfoToNew(IRUnitT &IR) {} +template <> inline void doConvertDbgInfoToNew(Module &IR) { + IR.convertToNewDbgValues(); +} +template 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 @@ detail::getAnalysisResult( AM, IR, std::tuple(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 @@ 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 diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -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(M)) : nullptr; WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, Index, EmitModuleHash); + + if (IsNewDbgInfoFormat) + M.convertToNewDbgValues(); + return PreservedAnalyses::all(); } @@ -54,8 +64,17 @@ EmitSummaryIndex ? &(getAnalysis().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 { diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -981,11 +981,29 @@ } 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(M).convertFromNewDbgValues(); + yaml::Output Out(OS); Out << const_cast(M); + + if (IsNewDbgInfoFormat) + const_cast(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(MF.getFunction()).convertFromNewDbgValues(); + MIRPrinter Printer(OS); Printer.print(MF); + + if (IsNewDbgInfoFormat) + const_cast(MF.getFunction()).convertToNewDbgValues(); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -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 @@ 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 @@ 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 &Shuffle); void printUseLists(const Function *F); @@ -3771,6 +3784,9 @@ /// printFunction - Print all aspects of a function. void AssemblyWriter::printFunction(const Function *F) { + bool ConvertBack = F->IsNewDbgInfoFormat; + if (ConvertBack) + const_cast(F)->convertFromNewDbgValues(); if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out); if (F->isMaterializable()) @@ -3913,6 +3929,8 @@ Out << "}\n"; } + if (ConvertBack) + const_cast(F)->convertToNewDbgValues(); Machine.purgeFunction(); } @@ -4007,8 +4025,15 @@ if (const auto *Relocate = dyn_cast(&V)) printGCRelocateComment(*Relocate); - if (AnnotationWriter) + if (AnnotationWriter) { AnnotationWriter->printInfoComment(V, Out); + } else if (const Instruction *I = dyn_cast(&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 @@ 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> &MDs, StringRef Separator) { @@ -4613,11 +4668,19 @@ 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(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(this)->convertToNewDbgValues(); } void NamedMDNode::print(raw_ostream &ROS, bool IsForDebug) const { @@ -4694,6 +4757,53 @@ 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(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(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(this)) @@ -4939,6 +5049,14 @@ 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'; } diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -179,6 +179,18 @@ 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(); diff --git a/llvm/lib/IR/IRPrintingPasses.cpp b/llvm/lib/IR/IRPrintingPasses.cpp --- a/llvm/lib/IR/IRPrintingPasses.cpp +++ b/llvm/lib/IR/IRPrintingPasses.cpp @@ -39,6 +39,12 @@ 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 @@ } } } + + if (IsNewDbgInfoFormat) + M.convertToNewDbgValues(); + return false; } @@ -77,6 +87,12 @@ // 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 @@ else OS << Banner << '\n' << static_cast(F); } + + if (IsNewDbgInfoFormat) + F.convertToNewDbgValues(); + return false; } diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -31,6 +31,7 @@ using namespace llvm; +extern cl::opt UseNewDbgInfoFormat; // See PassManagers.h for Pass Manager infrastructure overview. //===----------------------------------------------------------------------===// @@ -527,6 +528,11 @@ 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 @@ for (ImmutablePass *ImPass : getImmutablePasses()) Changed |= ImPass->doFinalization(M); + M.convertFromNewDbgValues(); + return Changed; } } // namespace legacy diff --git a/llvm/lib/IRPrinter/IRPrintingPasses.cpp b/llvm/lib/IRPrinter/IRPrintingPasses.cpp --- a/llvm/lib/IRPrinter/IRPrintingPasses.cpp +++ b/llvm/lib/IRPrinter/IRPrintingPasses.cpp @@ -31,6 +31,12 @@ 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 @@ Index->print(OS); } + if (ShouldConvert) + M.convertToNewDbgValues(); + return PreservedAnalyses::all(); } @@ -66,11 +75,21 @@ 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(F); } + + if (ShouldConvert) + F.convertToNewDbgValues(); + return PreservedAnalyses::all(); }