Index: include/llvm/IR/Debugify.h =================================================================== --- /dev/null +++ include/llvm/IR/Debugify.h @@ -0,0 +1,119 @@ +//===- Debugify.h - Passes to attach synthetic debug info to IR constructs ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines passes to attach synthetic debug info to the IR in +/// various granularities. It can be used to create targeted tests for debug +/// info preservation. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGIFY_H +#define LLVM_IR_DEBUGIFY_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { +class Function; +class FunctionPass; +class Module; +class ModulePass; +class PreservedAnalyses; +template class AnalysisManager; + +/// Create and return a pass that attaches synthetic debug info to the module. +ModulePass *createDebugifyModulePass(); + +/// Create and return a pass that attaches synthetic debug info to the function. +FunctionPass *createDebugifyFunctionPass(); + +/// Create and return a pass that verifies the debug info inserted by the above +/// DebugifyModulePass. +ModulePass *createCheckDebugifyModulePass(bool Strip = false, + StringRef NameOfWrappedPass = ""); + +/// Create and return a pass that verifies the debug info inserted by the above +/// DebugifyFunctionPass. +FunctionPass *createCheckDebugifyFunctionPass(bool Strip = false, + StringRef NameOfWrappedPass = ""); + +/// Pass for attaching synthetic debug info to the module. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class DebugifyModulePass { + bool Result = false; + +public: + PreservedAnalyses run(Module &M, AnalysisManager &AM); + + static StringRef name() { return "Debugify Module IR"; } + + bool getResult() const { return Result; } +}; + +/// Pass for attaching synthetic debug info to instructions within a single +/// function. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class DebugifyFunctionPass { + bool Result = false; + +public: + PreservedAnalyses run(Function &F, AnalysisManager &AM); + + static StringRef name() { return "Debugify Function IR"; } + + bool getResult() const { return Result; } +}; + +/// Pass for checking debug info inserted by DebugifyModulePass. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class CheckDebugifyModulePass { + bool Result = false; + bool Strip; + StringRef NameOfWrappedPass; + +public: + CheckDebugifyModulePass(bool Strip = false, + StringRef NamedOfWrappedPass = ""); + + PreservedAnalyses run(Module &F, AnalysisManager &AM); + + static StringRef name() { return "Check Debugify Module IR"; } + + bool getResult() const { return Result; } +}; + +/// Pass for checking debug info inserted by DebugifyFunctionPass. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class CheckDebugifyFunctionPass { + bool Result = false; + bool Strip; + StringRef NameOfWrappedPass; + +public: + CheckDebugifyFunctionPass(bool Strip = false, + StringRef NamedOfWrappedPass = ""); + + PreservedAnalyses run(Function &F, AnalysisManager &AM); + + static StringRef name() { return "Check Debugify Function IR"; } + + bool getResult() const { return Result; } +}; + +} // End llvm namespace + +#endif Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -316,6 +316,10 @@ void initializePrintBasicBlockPassPass(PassRegistry&); void initializePrintFunctionPassWrapperPass(PassRegistry&); void initializePrintModulePassWrapperPass(PassRegistry&); +void initializeDebugifyModulePassWrapperPass(PassRegistry&); +void initializeCheckDebugifyModulePassWrapperPass(PassRegistry&); +void initializeDebugifyFunctionPassWrapperPass(PassRegistry&); +void initializeCheckDebugifyFunctionPassWrapperPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&); void initializePromoteLegacyPassPass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -36,6 +36,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Debugify.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Support/Valgrind.h" @@ -196,6 +197,10 @@ (void) llvm::createPrintModulePass(os); (void) llvm::createPrintFunctionPass(os); (void) llvm::createPrintBasicBlockPass(os); + (void) llvm::createDebugifyModulePass(); + (void) llvm::createDebugifyFunctionPass(); + (void) llvm::createCheckDebugifyModulePass(); + (void) llvm::createCheckDebugifyFunctionPass(); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); (void) llvm::createLintPass(); Index: include/llvm/Pass.h =================================================================== --- include/llvm/Pass.h +++ include/llvm/Pass.h @@ -119,6 +119,15 @@ void dump() const; // dump - Print to stderr. + /// createDebugifyPass - Create a Pass appropriate to attach the synthetic + /// debug information to the IR that this pass operates on (Module or + /// Function). + Pass *createDebugifyPass(); + + /// createCheckDebugifyPass - Create a Pass appropriate to verify the debug + /// info inserted by one of the above Debugify passes. + Pass *createCheckDebugifyPass(bool Strip, StringRef NameOfWrappedPass); + /// createPrinterPass - Get a Pass appropriate to print the IR this /// pass operates on (Module, Function or MachineFunction). virtual Pass *createPrinterPass(raw_ostream &OS, Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -17,6 +17,7 @@ DebugInfo.cpp DebugInfoMetadata.cpp DebugLoc.cpp + Debugify.cpp DiagnosticHandler.cpp DiagnosticInfo.cpp DiagnosticPrinter.cpp Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -49,6 +49,10 @@ initializePrintModulePassWrapperPass(Registry); initializePrintFunctionPassWrapperPass(Registry); initializePrintBasicBlockPassPass(Registry); + initializeDebugifyModulePassWrapperPass(Registry); + initializeCheckDebugifyModulePassWrapperPass(Registry); + initializeDebugifyFunctionPassWrapperPass(Registry); + initializeCheckDebugifyFunctionPassWrapperPass(Registry); initializeSafepointIRVerifierPass(Registry); initializeVerifierLegacyPassPass(Registry); } Index: lib/IR/Debugify.cpp =================================================================== --- /dev/null +++ lib/IR/Debugify.cpp @@ -0,0 +1,477 @@ +//===- Debugify.cpp - Attach synthetic debug info to everything -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// (Check)DebugifyModulePass and (Check)DebugifyFunctionPass implementations. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Debugify.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO.h" + +using namespace llvm; + +namespace { + +cl::opt Quiet("debugify-quiet", + cl::desc("Suppress verbose debugify output")); + +raw_ostream &dbg() { return Quiet ? nulls() : errs(); } + +uint64_t getAllocSizeInBits(Module &M, Type *Ty) { + return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; +} + +bool isFunctionSkipped(Function &F) { + return F.isDeclaration() || !F.hasExactDefinition(); +} + +/// Find the basic block's terminating instruction. +/// +/// Special care is needed to handle musttail and deopt calls, as these behave +/// like (but are in fact not) terminators. +Instruction *findTerminatingInstruction(BasicBlock &BB) { + if (auto *I = BB.getTerminatingMustTailCall()) + return I; + if (auto *I = BB.getTerminatingDeoptimizeCall()) + return I; + return BB.getTerminator(); +} + +bool applyDebugifyMetadata(Module &M, + iterator_range Functions, + StringRef Banner) { + // Skip modules with debug info. + if (M.getNamedMetadata("llvm.dbg.cu")) { + dbg() << Banner << "Skipping module with debug info\n"; + return false; + } + + DIBuilder DIB(M); + LLVMContext &Ctx = M.getContext(); + + // Get a DIType which corresponds to Ty. + DenseMap TypeCache; + auto getCachedDIType = [&](Type *Ty) -> DIType * { + uint64_t Size = getAllocSizeInBits(M, Ty); + DIType *&DTy = TypeCache[Size]; + if (!DTy) { + std::string Name = "ty" + utostr(Size); + DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned); + } + return DTy; + }; + + unsigned NextLine = 1; + unsigned NextVar = 1; + auto File = DIB.createFile(M.getName(), "/"); + auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify", + /*isOptimized=*/true, "", 0); + + // Visit each instruction. + for (Function &F : Functions) { + if (isFunctionSkipped(F)) + continue; + + auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); + bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage(); + auto SP = + DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType, + IsLocalToUnit, /*isDefinition=*/true, NextLine, + DINode::FlagZero, /*isOptimized=*/true); + F.setSubprogram(SP); + for (BasicBlock &BB : F) { + // Attach debug locations. + for (Instruction &I : BB) + I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); + + // Inserting debug values into EH pads can break IR invariants. + if (BB.isEHPad()) + continue; + + // Find the terminating instruction, after which no debug values are + // attached. + Instruction *LastInst = findTerminatingInstruction(BB); + assert(LastInst && "Expected basic block with a terminator"); + + // Maintain an insertion point which can't be invalidated when updates + // are made. + BasicBlock::iterator InsertPt = BB.getFirstInsertionPt(); + assert(InsertPt != BB.end() && "Expected to find an insertion point"); + Instruction *InsertBefore = &*InsertPt; + + // Attach debug values. + for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) { + // Skip void-valued instructions. + if (I->getType()->isVoidTy()) + continue; + + // Phis and EH pads must be grouped at the beginning of the block. + // Only advance the insertion point when we finish visiting these. + if (!isa(I) && !I->isEHPad()) + InsertBefore = I->getNextNode(); + + std::string Name = utostr(NextVar++); + const DILocation *Loc = I->getDebugLoc().get(); + auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), + getCachedDIType(I->getType()), + /*AlwaysPreserve=*/true); + DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc, + InsertBefore); + } + } + DIB.finalizeSubprogram(SP); + } + DIB.finalize(); + + // Track the number of distinct lines and variables. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify"); + auto *IntTy = Type::getInt32Ty(Ctx); + auto addDebugifyOperand = [&](unsigned N) { + NMD->addOperand(MDNode::get( + Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N)))); + }; + addDebugifyOperand(NextLine - 1); // Original number of lines. + addDebugifyOperand(NextVar - 1); // Original number of variables. + assert(NMD->getNumOperands() == 2 && + "llvm.debugify should have exactly 2 operands!"); + + // Claim that this synthetic debug info is valid. + StringRef DIVersionKey = "Debug Info Version"; + if (!M.getModuleFlag(DIVersionKey)) + M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION); + + return true; +} + +/// Return true if a mis-sized diagnostic is issued for \p DVI. +bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) { + // The size of a dbg.value's value operand should match the size of the + // variable it corresponds to. + // + // TODO: This, along with a check for non-null value operands, should be + // promoted to verifier failures. + Value *V = DVI->getValue(); + if (!V) + return false; + + // For now, don't try to interpret anything more complicated than an empty + // DIExpression. Eventually we should try to handle OP_deref and fragments. + if (DVI->getExpression()->getNumElements()) + return false; + + Type *Ty = V->getType(); + uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty); + Optional DbgVarSize = DVI->getFragmentSizeInBits(); + if (!ValueOperandSize || !DbgVarSize) + return false; + + bool HasBadSize = Ty->isIntegerTy() ? (ValueOperandSize < *DbgVarSize) + : (ValueOperandSize != *DbgVarSize); + if (HasBadSize) { + dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize + << ", but its variable has size " << *DbgVarSize << ": "; + DVI->print(dbg()); + dbg() << "\n"; + } + return HasBadSize; +} + +bool checkDebugifyMetadata(Module &M, + iterator_range Functions, + StringRef NameOfWrappedPass, StringRef Banner, + bool Strip) { + // Skip modules without debugify metadata. + NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); + if (!NMD) { + dbg() << Banner << "Skipping module without debugify metadata\n"; + return false; + } + + auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { + return mdconst::extract(NMD->getOperand(Idx)->getOperand(0)) + ->getZExtValue(); + }; + assert(NMD->getNumOperands() == 2 && + "llvm.debugify should have exactly 2 operands!"); + unsigned OriginalNumLines = getDebugifyOperand(0); + unsigned OriginalNumVars = getDebugifyOperand(1); + bool HasErrors = false; + + BitVector MissingLines{OriginalNumLines, true}; + BitVector MissingVars{OriginalNumVars, true}; + for (Function &F : Functions) { + if (isFunctionSkipped(F)) + continue; + + // Find missing lines. + for (Instruction &I : instructions(F)) { + if (isa(&I)) + continue; + + auto DL = I.getDebugLoc(); + if (DL && DL.getLine() != 0) { + MissingLines.reset(DL.getLine() - 1); + continue; + } + + if (!DL) { + dbg() << "ERROR: Instruction with empty DebugLoc in function "; + dbg() << F.getName() << " --"; + I.print(dbg()); + dbg() << "\n"; + HasErrors = true; + } + } + + // Find missing variables and mis-sized debug values. + for (Instruction &I : instructions(F)) { + auto *DVI = dyn_cast(&I); + if (!DVI) + continue; + + unsigned Var = ~0U; + (void)to_integer(DVI->getVariable()->getName(), Var, 10); + assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable"); + bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI); + if (!HasBadSize) + MissingVars.reset(Var - 1); + HasErrors |= HasBadSize; + } + } + + // Print the results. + for (unsigned Idx : MissingLines.set_bits()) + dbg() << "WARNING: Missing line " << Idx + 1 << "\n"; + + for (unsigned Idx : MissingVars.set_bits()) + dbg() << "WARNING: Missing variable " << Idx + 1 << "\n"; + + dbg() << Banner; + if (!NameOfWrappedPass.empty()) + dbg() << " [" << NameOfWrappedPass << "]"; + dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n'; + + // Strip the Debugify Metadata if required. + if (Strip) { + StripDebugInfo(M); + M.eraseNamedMetadata(NMD); + return true; + } + + return false; +} + +/// Wrapper pass for attaching synthetic debug info to the module, to be used +/// with the legacy module pass manager. +class DebugifyModulePassWrapper : public ModulePass { + DebugifyModulePass P; + +public: + static char ID; + + DebugifyModulePassWrapper() : ModulePass(ID) { + initializeDebugifyModulePassWrapperPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + ModuleAnalysisManager DummyMAM; + P.run(M, DummyMAM); + return P.getResult(); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + StringRef getPassName() const override { return P.name(); } +}; + +/// Wrapper pass for attaching synthetic debug info to a function, to be used +/// with the legacy function pass manager. +class DebugifyFunctionPassWrapper : public FunctionPass { + DebugifyFunctionPass P; + +public: + static char ID; + + DebugifyFunctionPassWrapper() : FunctionPass(ID) { + initializeDebugifyFunctionPassWrapperPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + FunctionAnalysisManager DummyFAM; + P.run(F, DummyFAM); + return P.getResult(); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + StringRef getPassName() const override { return P.name(); } +}; + +/// Pass for checking debug info inserted by DebugifyModulePass, to be used +/// with the legacy module pass manager. +class CheckDebugifyModulePassWrapper : public ModulePass { + CheckDebugifyModulePass P; + +public: + static char ID; + + CheckDebugifyModulePassWrapper() : ModulePass(ID) { + initializeCheckDebugifyModulePassWrapperPass( + *PassRegistry::getPassRegistry()); + } + CheckDebugifyModulePassWrapper(bool Strip, StringRef NameOfWrappedPass) + : ModulePass(ID), P(Strip, NameOfWrappedPass) { + initializeCheckDebugifyModulePassWrapperPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + ModuleAnalysisManager DummyMAM; + P.run(M, DummyMAM); + return P.getResult(); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + StringRef getPassName() const override { return P.name(); } +}; + +/// Pass for checking debug info inserted by DebugifyFunctionPass, to be used +/// with the legacy function pass manager. +struct CheckDebugifyFunctionPassWrapper : public FunctionPass { + CheckDebugifyFunctionPass P; + +public: + static char ID; + + CheckDebugifyFunctionPassWrapper() : FunctionPass(ID) { + initializeCheckDebugifyFunctionPassWrapperPass( + *PassRegistry::getPassRegistry()); + } + CheckDebugifyFunctionPassWrapper(bool Strip, StringRef NameOfWrappedPass) + : FunctionPass(ID), P(Strip, NameOfWrappedPass) { + initializeCheckDebugifyFunctionPassWrapperPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + FunctionAnalysisManager DummyFAM; + P.run(F, DummyFAM); + return P.getResult(); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + StringRef getPassName() const override { return P.name(); } +}; + +} // end anonymous namespace + +// Debugify passes for new pass manager. +PreservedAnalyses DebugifyModulePass::run(Module &M, ModuleAnalysisManager &) { + Result = applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: "); + return PreservedAnalyses::all(); +} + +PreservedAnalyses DebugifyFunctionPass::run(Function &F, + FunctionAnalysisManager &) { + Module &M = *F.getParent(); + auto FuncIt = F.getIterator(); + Result = applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), + "FunctionDebugify: "); + return PreservedAnalyses::all(); +} + +CheckDebugifyModulePass::CheckDebugifyModulePass(bool Strip, + StringRef NameOfWrappedPass) + : Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {} + +PreservedAnalyses CheckDebugifyModulePass::run(Module &M, + ModuleAnalysisManager &) { + Result = checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass, + "CheckModuleDebugify", Strip); + return PreservedAnalyses::all(); +} + +CheckDebugifyFunctionPass::CheckDebugifyFunctionPass(bool Strip, + StringRef NameOfWrappedPass) + : Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {} + +PreservedAnalyses CheckDebugifyFunctionPass::run(Function &F, + FunctionAnalysisManager &) { + Module &M = *F.getParent(); + auto FuncIt = F.getIterator(); + Result = checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), + NameOfWrappedPass, "CheckFunctionDebugify", + Strip); + return PreservedAnalyses::all(); +} + +// Register the pass wrappers to the legacy pass manager. +char DebugifyModulePassWrapper::ID = 0; +INITIALIZE_PASS(DebugifyModulePassWrapper, "debugify", + "Attach debug info to the module", false, false) + +char CheckDebugifyModulePassWrapper::ID = 0; +INITIALIZE_PASS(CheckDebugifyModulePassWrapper, "check-debugify", + "Check debug info inserted by DebugifyModulePass", false, + false) + +char DebugifyFunctionPassWrapper::ID = 0; +INITIALIZE_PASS(DebugifyFunctionPassWrapper, "debugify-function", + "Attach debug info to a function", false, false) + +char CheckDebugifyFunctionPassWrapper::ID = 0; +INITIALIZE_PASS(CheckDebugifyFunctionPassWrapper, "check-debugify-function", + "Check debug info inserted by DebugifyFunctionPass", false, + false) + +// API for use with the legacy pass manager. +ModulePass *llvm::createDebugifyModulePass() { + return new DebugifyModulePassWrapper(); +} + +FunctionPass *llvm::createDebugifyFunctionPass() { + return new DebugifyFunctionPassWrapper(); +} + +ModulePass *llvm::createCheckDebugifyModulePass(bool Strip, + StringRef NameOfWrappedPass) { + return new CheckDebugifyModulePassWrapper(Strip, NameOfWrappedPass); +} + +FunctionPass *llvm::createCheckDebugifyFunctionPass(bool Strip, + StringRef NameOfWrappedPass) { + return new CheckDebugifyFunctionPassWrapper(Strip, NameOfWrappedPass); +} + Index: lib/IR/LegacyPassManager.cpp =================================================================== --- lib/IR/LegacyPassManager.cpp +++ lib/IR/LegacyPassManager.cpp @@ -14,6 +14,7 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/IR/Debugify.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" @@ -84,6 +85,11 @@ cl::init(false), cl::Hidden); static cl::opt + DebugifyEach("debugify-each", + cl::desc("Start each pass with debugify and end it with check-debugify"), + cl::init(false), cl::Hidden); + +static cl::opt PrintModuleScope("print-module-scope", cl::desc("When printing IR for print-[before|after]{-all} " "always print a module IR"), @@ -753,12 +759,22 @@ return; } + // We do not want to debugify Verifier, since it verifies in doFinalization() + // if + bool shouldInsertDebugifyPasses = DebugifyEach && PI && !PI->isAnalysis(); + if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) { Pass *PP = P->createPrinterPass( dbgs(), ("*** IR Dump Before " + P->getPassName() + " ***").str()); PP->assignPassManager(activeStack, getTopLevelPassManagerType()); } + if (shouldInsertDebugifyPasses) { + if (Pass *DP = P->createDebugifyPass()) { + DP->assignPassManager(activeStack, getTopLevelPassManagerType()); + } + } + // Add the requested pass to the best available pass manager. P->assignPassManager(activeStack, getTopLevelPassManagerType()); @@ -767,6 +783,12 @@ dbgs(), ("*** IR Dump After " + P->getPassName() + " ***").str()); PP->assignPassManager(activeStack, getTopLevelPassManagerType()); } + if (shouldInsertDebugifyPasses) { + if (Pass *DP = P->createCheckDebugifyPass(true, P->getPassName())) { + DP->assignPassManager(activeStack, getTopLevelPassManagerType()); + } + } + } /// Find the pass that implements Analysis AID. Search immutable Index: lib/IR/Pass.cpp =================================================================== --- lib/IR/Pass.cpp +++ lib/IR/Pass.cpp @@ -17,6 +17,7 @@ #include "llvm/Config/llvm-config.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Debugify.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" @@ -44,22 +45,6 @@ delete Resolver; } -// Force out-of-line virtual method. -ModulePass::~ModulePass() = default; - -Pass *ModulePass::createPrinterPass(raw_ostream &OS, - const std::string &Banner) const { - return createPrintModulePass(OS, Banner); -} - -PassManagerType ModulePass::getPotentialPassManagerType() const { - return PMT_ModulePassManager; -} - -bool ModulePass::skipModule(Module &M) const { - return !M.getContext().getOptPassGate().shouldRunPass(this, M); -} - bool Pass::mustPreserveAnalysisID(char &AID) const { return Resolver->getAnalysisIfAvailable(&AID, true) != nullptr; } @@ -132,6 +117,28 @@ } #endif +Pass *Pass::createDebugifyPass() { + switch (Kind) { + case PT_Module: + return createDebugifyModulePass(); + case PT_Function: + return createDebugifyFunctionPass(); + default: + return nullptr; + } +} + +Pass *Pass::createCheckDebugifyPass(bool Strip, StringRef NameOfWrappedPass) { + switch (Kind) { + case PT_Module: + return createCheckDebugifyModulePass(Strip, NameOfWrappedPass); + case PT_Function: + return createCheckDebugifyFunctionPass(Strip, NameOfWrappedPass); + default: + return nullptr; + } +} + //===----------------------------------------------------------------------===// // ImmutablePass Implementation // @@ -143,6 +150,25 @@ } //===----------------------------------------------------------------------===// +// ModulePass Implementation +// +// Force out-of-line virtual method. +ModulePass::~ModulePass() = default; + +Pass *ModulePass::createPrinterPass(raw_ostream &OS, + const std::string &Banner) const { + return createPrintModulePass(OS, Banner); +} + +PassManagerType ModulePass::getPotentialPassManagerType() const { + return PMT_ModulePassManager; +} + +bool ModulePass::skipModule(Module &M) const { + return !M.getContext().getOptPassGate().shouldRunPass(this, M); +} + +//===----------------------------------------------------------------------===// // FunctionPass Implementation // Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1067,7 +1067,10 @@ AssertDI(Op && isa(Op), "invalid macro ref", &N, Op); } } - CUVisited.insert(&N); + // We only want to verify real debug information, not synthetic inserted by + // Debugify. + if (N.getProducer() != "debugify") + CUVisited.insert(&N); } void Verifier::visitDISubprogram(const DISubprogram &N) { Index: test/DebugInfo/debugify-each.c =================================================================== --- /dev/null +++ test/DebugInfo/debugify-each.c @@ -0,0 +1,17 @@ +// RUN: clang -mllvm -debugify-each -emit-llvm -S -O1 -o - %s 2>&1 | \ +// RUN: FileCheck %s + +int main() +{ + int a = 3; + int b = 4; + return a + b; +} + +// CHECK: CheckModuleDebugify [{{.*}}]: PASS +// CHECK: CheckModuleDebugify [{{.*}}]: PASS + +// CHECK: CheckFunctionDebugify [{{.*}}]: PASS +// CHECK: CheckFunctionDebugify [{{.*}}]: PASS +// CHECK: CheckFunctionDebugify [{{.*}}]: PASS +// CHECK: CheckFunctionDebugify [{{.*}}]: PASS Index: tools/opt/CMakeLists.txt =================================================================== --- tools/opt/CMakeLists.txt +++ tools/opt/CMakeLists.txt @@ -26,7 +26,6 @@ add_llvm_tool(opt AnalysisWrappers.cpp BreakpointPrinter.cpp - Debugify.cpp GraphPrinters.cpp NewPMDriver.cpp PassPrinters.cpp Index: tools/opt/Debugify.cpp =================================================================== --- tools/opt/Debugify.cpp +++ /dev/null @@ -1,420 +0,0 @@ -//===- Debugify.cpp - Attach synthetic debug info to everything -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file This pass attaches synthetic debug info to everything. It can be used -/// to create targeted tests for debug info preservation. -/// -//===----------------------------------------------------------------------===// - -#include "PassPrinters.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/Pass.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO.h" - -using namespace llvm; - -namespace { - -cl::opt Quiet("debugify-quiet", - cl::desc("Suppress verbose debugify output")); - -raw_ostream &dbg() { return Quiet ? nulls() : errs(); } - -uint64_t getAllocSizeInBits(Module &M, Type *Ty) { - return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; -} - -bool isFunctionSkipped(Function &F) { - return F.isDeclaration() || !F.hasExactDefinition(); -} - -/// Find the basic block's terminating instruction. -/// -/// Special care is needed to handle musttail and deopt calls, as these behave -/// like (but are in fact not) terminators. -Instruction *findTerminatingInstruction(BasicBlock &BB) { - if (auto *I = BB.getTerminatingMustTailCall()) - return I; - if (auto *I = BB.getTerminatingDeoptimizeCall()) - return I; - return BB.getTerminator(); -} - -bool applyDebugifyMetadata(Module &M, - iterator_range Functions, - StringRef Banner) { - // Skip modules with debug info. - if (M.getNamedMetadata("llvm.dbg.cu")) { - dbg() << Banner << "Skipping module with debug info\n"; - return false; - } - - DIBuilder DIB(M); - LLVMContext &Ctx = M.getContext(); - - // Get a DIType which corresponds to Ty. - DenseMap TypeCache; - auto getCachedDIType = [&](Type *Ty) -> DIType * { - uint64_t Size = getAllocSizeInBits(M, Ty); - DIType *&DTy = TypeCache[Size]; - if (!DTy) { - std::string Name = "ty" + utostr(Size); - DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned); - } - return DTy; - }; - - unsigned NextLine = 1; - unsigned NextVar = 1; - auto File = DIB.createFile(M.getName(), "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify", - /*isOptimized=*/true, "", 0); - - // Visit each instruction. - for (Function &F : Functions) { - if (isFunctionSkipped(F)) - continue; - - auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); - bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage(); - auto SP = - DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType, - IsLocalToUnit, /*isDefinition=*/true, NextLine, - DINode::FlagZero, /*isOptimized=*/true); - F.setSubprogram(SP); - for (BasicBlock &BB : F) { - // Attach debug locations. - for (Instruction &I : BB) - I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); - - // Inserting debug values into EH pads can break IR invariants. - if (BB.isEHPad()) - continue; - - // Find the terminating instruction, after which no debug values are - // attached. - Instruction *LastInst = findTerminatingInstruction(BB); - assert(LastInst && "Expected basic block with a terminator"); - - // Maintain an insertion point which can't be invalidated when updates - // are made. - BasicBlock::iterator InsertPt = BB.getFirstInsertionPt(); - assert(InsertPt != BB.end() && "Expected to find an insertion point"); - Instruction *InsertBefore = &*InsertPt; - - // Attach debug values. - for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) { - // Skip void-valued instructions. - if (I->getType()->isVoidTy()) - continue; - - // Phis and EH pads must be grouped at the beginning of the block. - // Only advance the insertion point when we finish visiting these. - if (!isa(I) && !I->isEHPad()) - InsertBefore = I->getNextNode(); - - std::string Name = utostr(NextVar++); - const DILocation *Loc = I->getDebugLoc().get(); - auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), - getCachedDIType(I->getType()), - /*AlwaysPreserve=*/true); - DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc, - InsertBefore); - } - } - DIB.finalizeSubprogram(SP); - } - DIB.finalize(); - - // Track the number of distinct lines and variables. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify"); - auto *IntTy = Type::getInt32Ty(Ctx); - auto addDebugifyOperand = [&](unsigned N) { - NMD->addOperand(MDNode::get( - Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N)))); - }; - addDebugifyOperand(NextLine - 1); // Original number of lines. - addDebugifyOperand(NextVar - 1); // Original number of variables. - assert(NMD->getNumOperands() == 2 && - "llvm.debugify should have exactly 2 operands!"); - - // Claim that this synthetic debug info is valid. - StringRef DIVersionKey = "Debug Info Version"; - if (!M.getModuleFlag(DIVersionKey)) - M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION); - - return true; -} - -/// Return true if a mis-sized diagnostic is issued for \p DVI. -bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) { - // The size of a dbg.value's value operand should match the size of the - // variable it corresponds to. - // - // TODO: This, along with a check for non-null value operands, should be - // promoted to verifier failures. - Value *V = DVI->getValue(); - if (!V) - return false; - - // For now, don't try to interpret anything more complicated than an empty - // DIExpression. Eventually we should try to handle OP_deref and fragments. - if (DVI->getExpression()->getNumElements()) - return false; - - Type *Ty = V->getType(); - uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty); - Optional DbgVarSize = DVI->getFragmentSizeInBits(); - if (!ValueOperandSize || !DbgVarSize) - return false; - - bool HasBadSize = false; - if (Ty->isIntegerTy()) { - auto Signedness = DVI->getVariable()->getSignedness(); - if (Signedness && *Signedness == DIBasicType::Signedness::Signed) - HasBadSize = ValueOperandSize < *DbgVarSize; - } else { - HasBadSize = ValueOperandSize != *DbgVarSize; - } - - if (HasBadSize) { - dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize - << ", but its variable has size " << *DbgVarSize << ": "; - DVI->print(dbg()); - dbg() << "\n"; - } - return HasBadSize; -} - -bool checkDebugifyMetadata(Module &M, - iterator_range Functions, - StringRef NameOfWrappedPass, StringRef Banner, - bool Strip) { - // Skip modules without debugify metadata. - NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); - if (!NMD) { - dbg() << Banner << "Skipping module without debugify metadata\n"; - return false; - } - - auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { - return mdconst::extract(NMD->getOperand(Idx)->getOperand(0)) - ->getZExtValue(); - }; - assert(NMD->getNumOperands() == 2 && - "llvm.debugify should have exactly 2 operands!"); - unsigned OriginalNumLines = getDebugifyOperand(0); - unsigned OriginalNumVars = getDebugifyOperand(1); - bool HasErrors = false; - - BitVector MissingLines{OriginalNumLines, true}; - BitVector MissingVars{OriginalNumVars, true}; - for (Function &F : Functions) { - if (isFunctionSkipped(F)) - continue; - - // Find missing lines. - for (Instruction &I : instructions(F)) { - if (isa(&I)) - continue; - - auto DL = I.getDebugLoc(); - if (DL && DL.getLine() != 0) { - MissingLines.reset(DL.getLine() - 1); - continue; - } - - if (!DL) { - dbg() << "ERROR: Instruction with empty DebugLoc in function "; - dbg() << F.getName() << " --"; - I.print(dbg()); - dbg() << "\n"; - HasErrors = true; - } - } - - // Find missing variables and mis-sized debug values. - for (Instruction &I : instructions(F)) { - auto *DVI = dyn_cast(&I); - if (!DVI) - continue; - - unsigned Var = ~0U; - (void)to_integer(DVI->getVariable()->getName(), Var, 10); - assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable"); - bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI); - if (!HasBadSize) - MissingVars.reset(Var - 1); - HasErrors |= HasBadSize; - } - } - - // Print the results. - for (unsigned Idx : MissingLines.set_bits()) - dbg() << "WARNING: Missing line " << Idx + 1 << "\n"; - - for (unsigned Idx : MissingVars.set_bits()) - dbg() << "WARNING: Missing variable " << Idx + 1 << "\n"; - - dbg() << Banner; - if (!NameOfWrappedPass.empty()) - dbg() << " [" << NameOfWrappedPass << "]"; - dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n'; - - // Strip the Debugify Metadata if required. - if (Strip) { - StripDebugInfo(M); - M.eraseNamedMetadata(NMD); - return true; - } - - return false; -} - -/// 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 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: "); - } - - DebugifyModulePass() : ModulePass(ID) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - static char ID; // Pass identification. -}; - -/// 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 { - Module &M = *F.getParent(); - auto FuncIt = F.getIterator(); - return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), - "FunctionDebugify: "); - } - - DebugifyFunctionPass() : FunctionPass(ID) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - static char ID; // Pass identification. -}; - -/// ModulePass for checking debug info inserted by -debugify, used with the -/// legacy module pass manager. -struct CheckDebugifyModulePass : public ModulePass { - bool runOnModule(Module &M) override { - return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass, - "CheckModuleDebugify", Strip); - } - - CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "") - : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - static char ID; // Pass identification. - -private: - bool Strip; - StringRef NameOfWrappedPass; -}; - -/// FunctionPass for checking debug info inserted by -debugify-function, used -/// with the legacy module pass manager. -struct CheckDebugifyFunctionPass : public FunctionPass { - bool runOnFunction(Function &F) override { - Module &M = *F.getParent(); - auto FuncIt = F.getIterator(); - return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), - NameOfWrappedPass, "CheckFunctionDebugify", - Strip); - } - - CheckDebugifyFunctionPass(bool Strip = false, - StringRef NameOfWrappedPass = "") - : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - static char ID; // Pass identification. - -private: - bool Strip; - StringRef NameOfWrappedPass; -}; - -} // end anonymous namespace - -ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); } - -FunctionPass *createDebugifyFunctionPass() { - return new DebugifyFunctionPass(); -} - -PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) { - applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: "); - return PreservedAnalyses::all(); -} - -ModulePass *createCheckDebugifyModulePass(bool Strip, - StringRef NameOfWrappedPass) { - return new CheckDebugifyModulePass(Strip, NameOfWrappedPass); -} - -FunctionPass *createCheckDebugifyFunctionPass(bool Strip, - StringRef NameOfWrappedPass) { - return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass); -} - -PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M, - ModuleAnalysisManager &) { - checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false); - return PreservedAnalyses::all(); -} - -char DebugifyModulePass::ID = 0; -static RegisterPass DM("debugify", - "Attach debug info to everything"); - -char CheckDebugifyModulePass::ID = 0; -static RegisterPass - CDM("check-debugify", "Check debug info from -debugify"); - -char DebugifyFunctionPass::ID = 0; -static RegisterPass DF("debugify-function", - "Attach debug info to a function"); - -char CheckDebugifyFunctionPass::ID = 0; -static RegisterPass - CDF("check-debugify-function", "Check debug info from -debugify-function"); Index: tools/opt/NewPMDriver.cpp =================================================================== --- tools/opt/NewPMDriver.cpp +++ tools/opt/NewPMDriver.cpp @@ -14,12 +14,12 @@ //===----------------------------------------------------------------------===// #include "NewPMDriver.h" -#include "PassPrinters.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/Config/llvm-config.h" +#include "llvm/IR/Debugify.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" @@ -232,10 +232,10 @@ [](StringRef Name, ModulePassManager &MPM, ArrayRef) { if (Name == "debugify") { - MPM.addPass(NewPMDebugifyPass()); + MPM.addPass(DebugifyModulePass()); return true; } else if (Name == "check-debugify") { - MPM.addPass(NewPMCheckDebugifyPass()); + MPM.addPass(CheckDebugifyModulePass()); return true; } return false; @@ -272,7 +272,7 @@ if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); if (EnableDebugify) - MPM.addPass(NewPMDebugifyPass()); + MPM.addPass(DebugifyModulePass()); if (!PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) { errs() << Arg0 << ": unable to parse pass pipeline description.\n"; @@ -282,7 +282,7 @@ if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); if (EnableDebugify) - MPM.addPass(NewPMCheckDebugifyPass()); + MPM.addPass(CheckDebugifyModulePass()); // Add any relevant output pass at the end of the pipeline. switch (OK) { Index: tools/opt/PassPrinters.h =================================================================== --- tools/opt/PassPrinters.h +++ tools/opt/PassPrinters.h @@ -49,24 +49,4 @@ } // end namespace llvm -llvm::ModulePass *createDebugifyModulePass(); -llvm::FunctionPass *createDebugifyFunctionPass(); - -struct NewPMDebugifyPass : public llvm::PassInfoMixin { - llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); -}; - -llvm::ModulePass * -createCheckDebugifyModulePass(bool Strip = false, - llvm::StringRef NameOfWrappedPass = ""); - -llvm::FunctionPass * -createCheckDebugifyFunctionPass(bool Strip = false, - llvm::StringRef NameOfWrappedPass = ""); - -struct NewPMCheckDebugifyPass - : public llvm::PassInfoMixin { - llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); -}; - #endif // LLVM_TOOLS_OPT_PASSPRINTERS_H Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -28,6 +28,7 @@ #include "llvm/Config/llvm-config.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Debugify.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" @@ -211,11 +212,6 @@ cl::desc( "Start the pipeline with debugify and end it with check-debugify")); -static cl::opt DebugifyEach( - "debugify-each", - cl::desc( - "Start each pass with debugify and end it with check-debugify")); - static cl::opt PrintBreakpoints("print-breakpoints-for-testing", cl::desc("Print select breakpoints location for testing")); @@ -265,37 +261,6 @@ cl::desc("YAML output filename for pass remarks"), cl::value_desc("filename")); -class OptCustomPassManager : public legacy::PassManager { -public: - using super = legacy::PassManager; - - void add(Pass *P) override { - bool WrapWithDebugify = DebugifyEach && !P->getAsImmutablePass() && - !isIRPrintingPass(P) && !isBitcodeWriterPass(P); - if (!WrapWithDebugify) { - super::add(P); - return; - } - PassKind Kind = P->getPassKind(); - // TODO: Implement Debugify for BasicBlockPass, LoopPass. - switch (Kind) { - case PT_Function: - super::add(createDebugifyFunctionPass()); - super::add(P); - super::add(createCheckDebugifyFunctionPass(true, P->getPassName())); - break; - case PT_Module: - super::add(createDebugifyModulePass()); - super::add(P); - super::add(createCheckDebugifyModulePass(true, P->getPassName())); - break; - default: - super::add(P); - break; - } - } -}; - static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { // Add the pass to the pass manager... PM.add(P); @@ -605,8 +570,7 @@ // Create a PassManager to hold and optimize the collection of passes we are // about to build. - OptCustomPassManager Passes; - bool AddOneTimeDebugifyPasses = EnableDebugify && !DebugifyEach; + legacy::PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(ModuleTriple); @@ -620,7 +584,7 @@ Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); - if (AddOneTimeDebugifyPasses) + if (EnableDebugify) Passes.add(createDebugifyModulePass()); std::unique_ptr FPasses; @@ -768,7 +732,7 @@ if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); - if (AddOneTimeDebugifyPasses) + if (EnableDebugify) Passes.add(createCheckDebugifyModulePass(false)); // In run twice mode, we want to make sure the output is bit-by-bit