//===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements DebugInfoProbe. This probe can be used by a pass // manager to analyze how optimizer is treating debugging information. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "debuginfoprobe" #include "llvm/DebugInfoProbe.h" #include "llvm/Function.h" #include "llvm/IntrinsicInst.h" #include "llvm/Metadata.h" #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringRef.h" #include #include using namespace llvm; static cl::opt EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden, cl::desc("Enable debug info probe")); // CreateInfoOutputFile - Return a file stream to print our output on. namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } //===----------------------------------------------------------------------===// // DebugInfoProbeImpl - This class implements a interface to monitor // how an optimization pass is preserving debugging information. namespace llvm { class DebugInfoProbeImpl { public: DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {} void initialize(StringRef PName, Function &F); void finalize(Function &F); void report(); private: unsigned NumDbgLineLost, NumDbgValueLost; std::string PassName; Function *TheFn; std::set DbgVariables; std::set MissingDebugLoc; }; } //===----------------------------------------------------------------------===// // DebugInfoProbeImpl /// initialize - Collect information before running an optimization pass. void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) { if (!EnableDebugInfoProbe) return; PassName = PName; DbgVariables.clear(); MissingDebugLoc.clear(); TheFn = &F; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { if (!isa(BI) && BI->getDebugLoc().isUnknown()) MissingDebugLoc.insert(BI); if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; if (DbgDeclareInst *DDI = dyn_cast(BI)) { Addr = DDI->getAddress(); Node = DDI->getVariable(); } else if (DbgValueInst *DVI = dyn_cast(BI)) { Addr = DVI->getValue(); Node = DVI->getVariable(); } if (Addr) DbgVariables.insert(Node); } } /// report - Report findings. This should be invoked after finalize. void DebugInfoProbeImpl::report() { if (!EnableDebugInfoProbe) return; if (NumDbgLineLost || NumDbgValueLost) { raw_ostream *OutStream = CreateInfoOutputFile(); if (NumDbgLineLost) *OutStream << NumDbgLineLost << "\t times line number info lost by " << PassName << "\n"; if (NumDbgValueLost) *OutStream << NumDbgValueLost << "\t times variable info lost by " << PassName << "\n"; delete OutStream; } NumDbgLineLost = 0; NumDbgValueLost = 0; } /// finalize - Collect information after running an optimization pass. This /// must be used after initialization. void DebugInfoProbeImpl::finalize(Function &F) { if (!EnableDebugInfoProbe) return; assert (TheFn == &F && "Invalid function to measure!"); std::setDbgVariables2; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { if (!isa(BI) && BI->getDebugLoc().isUnknown() && MissingDebugLoc.count(BI) == 0) { ++NumDbgLineLost; DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- "); DEBUG(BI->print(dbgs())); DEBUG(dbgs() << "\n"); } if (!isa(BI)) continue; Value *Addr = NULL; MDNode *Node = NULL; if (DbgDeclareInst *DDI = dyn_cast(BI)) { Addr = DDI->getAddress(); Node = DDI->getVariable(); } else if (DbgValueInst *DVI = dyn_cast(BI)) { Addr = DVI->getValue(); Node = DVI->getVariable(); } if (Addr) DbgVariables2.insert(Node); } for (std::set::iterator I = DbgVariables.begin(), E = DbgVariables.end(); I != E; ++I) { if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) { DEBUG(dbgs() << "DebugInfoProbe(" << PassName << "): Losing dbg info for variable: "; if (MDString *MDS = dyn_cast_or_null( (*I)->getOperand(2))) dbgs() << MDS->getString(); else dbgs() << "..."; dbgs() << "\n"); ++NumDbgValueLost; } } } //===----------------------------------------------------------------------===// // DebugInfoProbe DebugInfoProbe::DebugInfoProbe() { pImpl = new DebugInfoProbeImpl(); } DebugInfoProbe::~DebugInfoProbe() { delete pImpl; } /// initialize - Collect information before running an optimization pass. void DebugInfoProbe::initialize(StringRef PName, Function &F) { pImpl->initialize(PName, F); } /// finalize - Collect information after running an optimization pass. This /// must be used after initialization. void DebugInfoProbe::finalize(Function &F) { pImpl->finalize(F); } /// report - Report findings. This should be invoked after finalize. void DebugInfoProbe::report() { pImpl->report(); } //===----------------------------------------------------------------------===// // DebugInfoProbeInfo /// ~DebugInfoProbeInfo - Report data collected by all probes before deleting /// them. DebugInfoProbeInfo::~DebugInfoProbeInfo() { if (!EnableDebugInfoProbe) return; for (StringMap::iterator I = Probes.begin(), E = Probes.end(); I != E; ++I) { I->second->report(); delete I->second; } } /// initialize - Collect information before running an optimization pass. void DebugInfoProbeInfo::initialize(Pass *P, Function &F) { if (!EnableDebugInfoProbe) return; if (P->getAsPMDataManager()) return; StringMapEntry &Entry = Probes.GetOrCreateValue(P->getPassName()); DebugInfoProbe *&Probe = Entry.getValue(); if (!Probe) Probe = new DebugInfoProbe(); Probe->initialize(P->getPassName(), F); } /// finalize - Collect information after running an optimization pass. This /// must be used after initialization. void DebugInfoProbeInfo::finalize(Pass *P, Function &F) { if (!EnableDebugInfoProbe) return; if (P->getAsPMDataManager()) return; StringMapEntry &Entry = Probes.GetOrCreateValue(P->getPassName()); DebugInfoProbe *&Probe = Entry.getValue(); assert (Probe && "DebugInfoProbe is not initialized!"); Probe->finalize(F); }