|  | //===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file implements a pass that prints instructions, and associated debug | 
|  | // info: | 
|  | // | 
|  | //   - source/line/col information | 
|  | //   - original variable name | 
|  | //   - original type name | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/Pass.h" | 
|  | #include "llvm/Function.h" | 
|  | #include "llvm/IntrinsicInst.h" | 
|  | #include "llvm/Metadata.h" | 
|  | #include "llvm/Module.h" | 
|  | #include "llvm/Assembly/Writer.h" | 
|  | #include "llvm/Analysis/DebugInfo.h" | 
|  | #include "llvm/Analysis/Passes.h" | 
|  | #include "llvm/Support/CFG.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | static cl::opt<bool> | 
|  | PrintDirectory("print-fullpath", | 
|  | cl::desc("Print fullpath when printing debug info"), | 
|  | cl::Hidden); | 
|  |  | 
|  | namespace { | 
|  | class PrintDbgInfo : public FunctionPass { | 
|  | raw_ostream &Out; | 
|  | void printVariableDeclaration(const Value *V); | 
|  | public: | 
|  | static char ID; // Pass identification | 
|  | PrintDbgInfo() : FunctionPass(ID), Out(errs()) { | 
|  | initializePrintDbgInfoPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | virtual bool runOnFunction(Function &F); | 
|  | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | AU.setPreservesAll(); | 
|  | } | 
|  | }; | 
|  | char PrintDbgInfo::ID = 0; | 
|  | } | 
|  |  | 
|  | INITIALIZE_PASS(PrintDbgInfo, "print-dbginfo", | 
|  | "Print debug info in human readable form", false, false) | 
|  |  | 
|  | FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); } | 
|  |  | 
|  | /// Find the debug info descriptor corresponding to this global variable. | 
|  | static Value *findDbgGlobalDeclare(GlobalVariable *V) { | 
|  | const Module *M = V->getParent(); | 
|  | NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); | 
|  | if (!NMD) | 
|  | return 0; | 
|  |  | 
|  | for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { | 
|  | DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); | 
|  | if (!DIG.isGlobalVariable()) | 
|  | continue; | 
|  | if (DIGlobalVariable(DIG).getGlobal() == V) | 
|  | return DIG; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /// Find the debug info descriptor corresponding to this function. | 
|  | static Value *findDbgSubprogramDeclare(Function *V) { | 
|  | const Module *M = V->getParent(); | 
|  | NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"); | 
|  | if (!NMD) | 
|  | return 0; | 
|  |  | 
|  | for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { | 
|  | DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); | 
|  | if (!DIG.isSubprogram()) | 
|  | continue; | 
|  | if (DISubprogram(DIG).getFunction() == V) | 
|  | return DIG; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. | 
|  | /// It looks through pointer casts too. | 
|  | static const DbgDeclareInst *findDbgDeclare(const Value *V) { | 
|  | V = V->stripPointerCasts(); | 
|  |  | 
|  | if (!isa<Instruction>(V) && !isa<Argument>(V)) | 
|  | return 0; | 
|  |  | 
|  | const Function *F = NULL; | 
|  | if (const Instruction *I = dyn_cast<Instruction>(V)) | 
|  | F = I->getParent()->getParent(); | 
|  | else if (const Argument *A = dyn_cast<Argument>(V)) | 
|  | F = A->getParent(); | 
|  |  | 
|  | for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) | 
|  | for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); | 
|  | BI != BE; ++BI) | 
|  | if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) | 
|  | if (DDI->getAddress() == V) | 
|  | return DDI; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static bool getLocationInfo(const Value *V, std::string &DisplayName, | 
|  | std::string &Type, unsigned &LineNo, | 
|  | std::string &File, std::string &Dir) { | 
|  | DICompileUnit Unit; | 
|  | DIType TypeD; | 
|  |  | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) { | 
|  | Value *DIGV = findDbgGlobalDeclare(GV); | 
|  | if (!DIGV) return false; | 
|  | DIGlobalVariable Var(cast<MDNode>(DIGV)); | 
|  |  | 
|  | StringRef D = Var.getDisplayName(); | 
|  | if (!D.empty()) | 
|  | DisplayName = D; | 
|  | LineNo = Var.getLineNumber(); | 
|  | Unit = Var.getCompileUnit(); | 
|  | TypeD = Var.getType(); | 
|  | } else if (Function *F = dyn_cast<Function>(const_cast<Value*>(V))){ | 
|  | Value *DIF = findDbgSubprogramDeclare(F); | 
|  | if (!DIF) return false; | 
|  | DISubprogram Var(cast<MDNode>(DIF)); | 
|  |  | 
|  | StringRef D = Var.getDisplayName(); | 
|  | if (!D.empty()) | 
|  | DisplayName = D; | 
|  | LineNo = Var.getLineNumber(); | 
|  | Unit = Var.getCompileUnit(); | 
|  | TypeD = Var.getType(); | 
|  | } else { | 
|  | const DbgDeclareInst *DDI = findDbgDeclare(V); | 
|  | if (!DDI) return false; | 
|  | DIVariable Var(cast<MDNode>(DDI->getVariable())); | 
|  |  | 
|  | StringRef D = Var.getName(); | 
|  | if (!D.empty()) | 
|  | DisplayName = D; | 
|  | LineNo = Var.getLineNumber(); | 
|  | Unit = Var.getCompileUnit(); | 
|  | TypeD = Var.getType(); | 
|  | } | 
|  |  | 
|  | StringRef T = TypeD.getName(); | 
|  | if (!T.empty()) | 
|  | Type = T; | 
|  | StringRef F = Unit.getFilename(); | 
|  | if (!F.empty()) | 
|  | File = F; | 
|  | StringRef D = Unit.getDirectory(); | 
|  | if (!D.empty()) | 
|  | Dir = D; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void PrintDbgInfo::printVariableDeclaration(const Value *V) { | 
|  | std::string DisplayName, File, Directory, Type; | 
|  | unsigned LineNo = 0; | 
|  |  | 
|  | if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory)) | 
|  | return; | 
|  |  | 
|  | Out << "; "; | 
|  | WriteAsOperand(Out, V, false, 0); | 
|  | if (isa<Function>(V)) | 
|  | Out << " is function " << DisplayName | 
|  | << " of type " << Type << " declared at "; | 
|  | else | 
|  | Out << " is variable " << DisplayName | 
|  | << " of type " << Type << " declared at "; | 
|  |  | 
|  | if (PrintDirectory) | 
|  | Out << Directory << "/"; | 
|  |  | 
|  | Out << File << ":" << LineNo << "\n"; | 
|  | } | 
|  |  | 
|  | bool PrintDbgInfo::runOnFunction(Function &F) { | 
|  | if (F.isDeclaration()) | 
|  | return false; | 
|  |  | 
|  | Out << "function " << F.getName() << "\n\n"; | 
|  |  | 
|  | for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { | 
|  | BasicBlock *BB = I; | 
|  |  | 
|  | if (I != F.begin() && (pred_begin(BB) == pred_end(BB))) | 
|  | // Skip dead blocks. | 
|  | continue; | 
|  |  | 
|  | Out << BB->getName(); | 
|  | Out << ":"; | 
|  |  | 
|  | Out << "\n"; | 
|  |  | 
|  | for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); | 
|  | i != e; ++i) { | 
|  |  | 
|  | printVariableDeclaration(i); | 
|  |  | 
|  | if (const User *U = dyn_cast<User>(i)) { | 
|  | for(unsigned i=0;i<U->getNumOperands();i++) | 
|  | printVariableDeclaration(U->getOperand(i)); | 
|  | } | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } |