diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index b8e4c6cde5d..4e511ebf9b0 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Dwarf.h" namespace llvm { @@ -609,6 +610,58 @@ namespace llvm { /// isInlinedFnEnd - Return true if REI is ending an inlined function. bool isInlinedFnEnd(DbgRegionEndInst &REI, const Function *CurrentFn); + /// DebugInfoEnumrator - This object collects DebugInfo from + /// the module. + class DebugInfoEnumerator { + + public: + /// EnumerateModule - Enumerate entire module and collect debug info + /// anchors. + void enumerateModule(Module &M); + + private: + /// enumerateType - Enumerate DIType. + /// for a type. + void enumerateType(DIType DT); + + /// enumerateSubprogram - Enumberate DISubprogram. + void enumerateSubprogram(DISubprogram SP); + + /// enumerateStopPoint - Enumerate DbgStopPointInst. + void enumerateStopPoint(DbgStopPointInst *SPI); + + /// enumerateFuncStart - Enumberate DbgFuncStartInst. + void enumerateFuncStart(DbgFuncStartInst *FSI); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprgoram into SPs. + bool addSubprogram(DISubprogram SP); + + public: + typedef SmallVector::iterator iterator; + iterator compile_unit_begin() { return CUs.begin(); } + iterator compile_unit_end() { return CUs.end(); } + iterator subprogram_begin() { return SPs.begin(); } + iterator subprogram_end() { return SPs.end(); } + iterator global_variable_begin() { return GVs.begin(); } + iterator global_variable_end() { return GVs.end(); } + + unsigned compile_unit_count() { return CUs.size(); } + unsigned global_variable_count() { return GVs.size(); } + unsigned subprogram_count() { return SPs.size(); } + + private: + SmallVector CUs; // Compile Units + SmallVector SPs; // Subprograms + SmallVector GVs; // Global Variables; + SmallPtrSet NodesSeen; + + }; } // end namespace llvm #endif diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index ff411a69355..7ecb1ad8d4d 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -105,6 +105,7 @@ DIDescriptor::getStringField(unsigned Elt, std::string &Result) const { uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { if (DbgGV == 0) return 0; + if (!DbgGV->hasInitializer()) return 0; Constant *C = DbgGV->getInitializer(); if (C == 0 || Elt >= C->getNumOperands()) @@ -904,6 +905,122 @@ void DIFactory::InsertDeclare(Value *Storage, DIVariable D, BasicBlock *BB) { CallInst::Create(DeclareFn, Args, Args+2, "", BB); } +//===----------------------------------------------------------------------===// +// DebugInfoEnumerator implementations. +//===----------------------------------------------------------------------===// + +/// enumerateModule - Enumerate entire module and collect debug info. +void DebugInfoEnumerator::enumerateModule(Module &M) { + + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; + ++BI) { + if (DbgStopPointInst *SPI = dyn_cast(BI)) + enumerateStopPoint(SPI); + else if (DbgFuncStartInst *FSI = dyn_cast(BI)) + enumerateFuncStart(FSI); + } + + for (Module::global_iterator GVI = M.global_begin(), GVE = M.global_end(); + GVI != GVE; ++GVI) { + GlobalVariable *GV = GVI; + if (!GV->hasName() || !GV->isConstant() + || strcmp(GV->getName().data(), "llvm.dbg.global_variable") + || !GV->hasInitializer()) + continue; + DIGlobalVariable DIG(GV); + if (addGlobalVariable(DIG)) { + addCompileUnit(DIG.getCompileUnit()); + enumerateType(DIG.getType()); + } + } +} + +/// enumerateType - Enumerate DIType. +void DebugInfoEnumerator::enumerateType(DIType DT) { + if (DT.isNull()) + return; + if (!NodesSeen.insert(DT.getGV())) + return; + + addCompileUnit(DT.getCompileUnit()); + if (DT.isCompositeType(DT.getTag())) { + DICompositeType DCT(DT.getGV()); + enumerateType(DCT.getTypeDerivedFrom()); + DIArray DA = DCT.getTypeArray(); + if (!DA.isNull()) + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + DIType TypeE = DIType(D.getGV()); + if (!TypeE.isNull()) + enumerateType(TypeE); + else + enumerateSubprogram(DISubprogram(D.getGV())); + } + } else if (DT.isDerivedType(DT.getTag())) { + DIDerivedType DDT(DT.getGV()); + if (!DDT.isNull()) + enumerateType(DDT.getTypeDerivedFrom()); + } +} + +/// enumerateSubprogram - Enumberate DISubprogram. +void DebugInfoEnumerator::enumerateSubprogram(DISubprogram SP) { + if (!addSubprogram(SP)) + return; + addCompileUnit(SP.getCompileUnit()); + enumerateType(SP.getType()); +} + +/// enumerateStopPoint - Enumerate DbgStopPointInst. +void DebugInfoEnumerator::enumerateStopPoint(DbgStopPointInst *SPI) { + GlobalVariable *Context = dyn_cast(SPI->getContext()); + addCompileUnit(DICompileUnit(Context)); +} + +/// enumerateFuncStart - Enumberate DbgFuncStartInst. +void DebugInfoEnumerator::enumerateFuncStart(DbgFuncStartInst *FSI) { + GlobalVariable *SP = dyn_cast(FSI->getSubprogram()); + enumerateSubprogram(DISubprogram(SP)); +} + +/// addCompileUnit - Add compile unit into CUs. +bool DebugInfoEnumerator::addCompileUnit(DICompileUnit CU) { + if (CU.isNull()) + return false; + + if (!NodesSeen.insert(CU.getGV())) + return false; + + CUs.push_back(CU.getGV()); + return true; +} + +/// addGlobalVariable - Add global variable into GVs. +bool DebugInfoEnumerator::addGlobalVariable(DIGlobalVariable DIG) { + if (DIG.isNull()) + return false; + + if (!NodesSeen.insert(DIG.getGV())) + return false; + + GVs.push_back(DIG.getGV()); + return true; +} + +// addSubprogram - Add subprgoram into SPs. +bool DebugInfoEnumerator::addSubprogram(DISubprogram SP) { + if (SP.isNull()) + return false; + + if (!NodesSeen.insert(SP.getGV())) + return false; + + SPs.push_back(SP.getGV()); + return true; +} + namespace llvm { /// findStopPoint - Find the stoppoint coressponding to this instruction, that /// is the stoppoint that dominates this instruction.