mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-30 16:34:03 +00:00
0f03782d16
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133822 91177308-0d34-0410-b5e6-96231b3b80d8
226 lines
7.2 KiB
C++
226 lines
7.2 KiB
C++
//===-- 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 <set>
|
|
#include <string>
|
|
|
|
using namespace llvm;
|
|
|
|
static cl::opt<bool>
|
|
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<MDNode *> DbgVariables;
|
|
std::set<Instruction *> 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<PHINode>(BI) && BI->getDebugLoc().isUnknown())
|
|
MissingDebugLoc.insert(BI);
|
|
if (!isa<DbgInfoIntrinsic>(BI)) continue;
|
|
Value *Addr = NULL;
|
|
MDNode *Node = NULL;
|
|
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
|
|
Addr = DDI->getAddress();
|
|
Node = DDI->getVariable();
|
|
} else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(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::set<MDNode *>DbgVariables2;
|
|
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<PHINode>(BI) && BI->getDebugLoc().isUnknown() &&
|
|
MissingDebugLoc.count(BI) == 0) {
|
|
++NumDbgLineLost;
|
|
DEBUG(dbgs() << "DebugInfoProbe (" << PassName << "): --- ");
|
|
DEBUG(BI->print(dbgs()));
|
|
DEBUG(dbgs() << "\n");
|
|
}
|
|
if (!isa<DbgInfoIntrinsic>(BI)) continue;
|
|
Value *Addr = NULL;
|
|
MDNode *Node = NULL;
|
|
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
|
|
Addr = DDI->getAddress();
|
|
Node = DDI->getVariable();
|
|
} else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
|
|
Addr = DVI->getValue();
|
|
Node = DVI->getVariable();
|
|
}
|
|
if (Addr)
|
|
DbgVariables2.insert(Node);
|
|
}
|
|
|
|
for (std::set<MDNode *>::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<MDString>(
|
|
(*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<DebugInfoProbe*>::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<DebugInfoProbe *> &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<DebugInfoProbe *> &Entry =
|
|
Probes.GetOrCreateValue(P->getPassName());
|
|
DebugInfoProbe *&Probe = Entry.getValue();
|
|
assert (Probe && "DebugInfoProbe is not initialized!");
|
|
Probe->finalize(F);
|
|
}
|