| //===-- ProgramInfo.cpp - Compute and cache info about a program ----------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file was developed by the LLVM research group and is distributed under | 
 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements the ProgramInfo and related classes, by sorting through | 
 | // the loaded Module. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/Debugger/ProgramInfo.h" | 
 | #include "llvm/Constants.h" | 
 | #include "llvm/DerivedTypes.h" | 
 | #include "llvm/Intrinsics.h" | 
 | #include "llvm/Instructions.h" | 
 | #include "llvm/Module.h" | 
 | #include "llvm/Debugger/SourceFile.h" | 
 | #include "llvm/Debugger/SourceLanguage.h" | 
 | #include "llvm/Support/SlowOperationInformer.h" | 
 | #include "llvm/ADT/STLExtras.h" | 
 | #include <iostream> | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | /// getGlobalVariablesUsing - Return all of the global variables which have the | 
 | /// specified value in their initializer somewhere. | 
 | static void getGlobalVariablesUsing(Value *V, | 
 |                                     std::vector<GlobalVariable*> &Found) { | 
 |   for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { | 
 |     if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) | 
 |       Found.push_back(GV); | 
 |     else if (Constant *C = dyn_cast<Constant>(*I)) | 
 |       getGlobalVariablesUsing(C, Found); | 
 |   } | 
 | } | 
 |  | 
 | /// getStringValue - Turn an LLVM constant pointer that eventually points to a | 
 | /// global into a string value.  Return an empty string if we can't do it. | 
 | /// | 
 | static std::string getStringValue(Value *V, unsigned Offset = 0) { | 
 |   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { | 
 |     if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) { | 
 |       ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); | 
 |       if (Init->isString()) { | 
 |         std::string Result = Init->getAsString(); | 
 |         if (Offset < Result.size()) { | 
 |           // If we are pointing INTO The string, erase the beginning... | 
 |           Result.erase(Result.begin(), Result.begin()+Offset); | 
 |  | 
 |           // Take off the null terminator, and any string fragments after it. | 
 |           std::string::size_type NullPos = Result.find_first_of((char)0); | 
 |           if (NullPos != std::string::npos) | 
 |             Result.erase(Result.begin()+NullPos, Result.end()); | 
 |           return Result; | 
 |         } | 
 |       } | 
 |     } | 
 |   } else if (Constant *C = dyn_cast<Constant>(V)) { | 
 |     if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) | 
 |       return getStringValue(GV, Offset); | 
 |     else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { | 
 |       if (CE->getOpcode() == Instruction::GetElementPtr) { | 
 |         // Turn a gep into the specified offset. | 
 |         if (CE->getNumOperands() == 3 && | 
 |             cast<Constant>(CE->getOperand(1))->isNullValue() && | 
 |             isa<ConstantInt>(CE->getOperand(2))) { | 
 |           return getStringValue(CE->getOperand(0), | 
 |                    Offset+cast<ConstantInt>(CE->getOperand(2))->getRawValue()); | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |   return ""; | 
 | } | 
 |  | 
 | /// getNextStopPoint - Follow the def-use chains of the specified LLVM value, | 
 | /// traversing the use chains until we get to a stoppoint.  When we do, return | 
 | /// the source location of the stoppoint.  If we don't find a stoppoint, return | 
 | /// null. | 
 | static const GlobalVariable *getNextStopPoint(const Value *V, unsigned &LineNo, | 
 |                                               unsigned &ColNo) { | 
 |   // The use-def chains can fork.  As such, we pick the lowest numbered one we | 
 |   // find. | 
 |   const GlobalVariable *LastDesc = 0; | 
 |   unsigned LastLineNo = ~0; | 
 |   unsigned LastColNo = ~0; | 
 |  | 
 |   for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end(); | 
 |        UI != E; ++UI) { | 
 |     bool ShouldRecurse = true; | 
 |     if (cast<Instruction>(*UI)->getOpcode() == Instruction::PHI) { | 
 |       // Infinite loops == bad, ignore PHI nodes. | 
 |       ShouldRecurse = false; | 
 |     } else if (const CallInst *CI = dyn_cast<CallInst>(*UI)) { | 
 |       // If we found a stop point, check to see if it is earlier than what we | 
 |       // already have.  If so, remember it. | 
 |       if (const Function *F = CI->getCalledFunction()) | 
 |         if (F->getIntrinsicID() == Intrinsic::dbg_stoppoint) { | 
 |           unsigned CurLineNo = ~0, CurColNo = ~0; | 
 |           const GlobalVariable *CurDesc = 0; | 
 |           if (const ConstantInt *C = dyn_cast<ConstantInt>(CI->getOperand(2))) | 
 |             CurLineNo = C->getRawValue(); | 
 |           if (const ConstantInt *C = dyn_cast<ConstantInt>(CI->getOperand(3))) | 
 |             CurColNo = C->getRawValue(); | 
 |           const Value *Op = CI->getOperand(4); | 
 |  | 
 |           if ((CurDesc = dyn_cast<GlobalVariable>(Op)) && | 
 |               (LineNo < LastLineNo || | 
 |                (LineNo == LastLineNo && ColNo < LastColNo))) { | 
 |             LastDesc = CurDesc; | 
 |             LastLineNo = CurLineNo; | 
 |             LastColNo = CurColNo; | 
 |           } | 
 |           ShouldRecurse = false; | 
 |         } | 
 |  | 
 |     } | 
 |  | 
 |     // If this is not a phi node or a stopping point, recursively scan the users | 
 |     // of this instruction to skip over region.begin's and the like. | 
 |     if (ShouldRecurse) { | 
 |       unsigned CurLineNo, CurColNo; | 
 |       if (const GlobalVariable *GV = getNextStopPoint(*UI, CurLineNo,CurColNo)){ | 
 |         if (LineNo < LastLineNo || (LineNo == LastLineNo && ColNo < LastColNo)){ | 
 |           LastDesc = GV; | 
 |           LastLineNo = CurLineNo; | 
 |           LastColNo = CurColNo; | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   if (LastDesc) { | 
 |     LineNo = LastLineNo != ~0U ? LastLineNo : 0; | 
 |     ColNo  = LastColNo  != ~0U ? LastColNo : 0; | 
 |   } | 
 |   return LastDesc; | 
 | } | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // SourceFileInfo implementation | 
 | // | 
 |  | 
 | SourceFileInfo::SourceFileInfo(const GlobalVariable *Desc, | 
 |                                const SourceLanguage &Lang) | 
 |   : Language(&Lang), Descriptor(Desc) { | 
 |   Version = 0; | 
 |   SourceText = 0; | 
 |  | 
 |   if (Desc && Desc->hasInitializer()) | 
 |     if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer())) | 
 |       if (CS->getNumOperands() > 4) { | 
 |         if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(CS->getOperand(1))) | 
 |           Version = CUI->getValue(); | 
 |  | 
 |         BaseName  = getStringValue(CS->getOperand(3)); | 
 |         Directory = getStringValue(CS->getOperand(4)); | 
 |       } | 
 | } | 
 |  | 
 | SourceFileInfo::~SourceFileInfo() { | 
 |   delete SourceText; | 
 | } | 
 |  | 
 | SourceFile &SourceFileInfo::getSourceText() const { | 
 |   // FIXME: this should take into account the source search directories! | 
 |   if (SourceText == 0) { // Read the file in if we haven't already. | 
 |     sys::Path tmpPath; | 
 |     if (!Directory.empty()) | 
 |       tmpPath.setDirectory(Directory); | 
 |     tmpPath.appendFile(BaseName); | 
 |     if (tmpPath.readable()) | 
 |       SourceText = new SourceFile(tmpPath.toString(), Descriptor); | 
 |     else | 
 |       SourceText = new SourceFile(BaseName, Descriptor); | 
 |   } | 
 |   return *SourceText; | 
 | } | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // SourceFunctionInfo implementation | 
 | // | 
 | SourceFunctionInfo::SourceFunctionInfo(ProgramInfo &PI, | 
 |                                        const GlobalVariable *Desc) | 
 |   : Descriptor(Desc) { | 
 |   LineNo = ColNo = 0; | 
 |   if (Desc && Desc->hasInitializer()) | 
 |     if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer())) | 
 |       if (CS->getNumOperands() > 2) { | 
 |         // Entry #1 is the file descriptor. | 
 |         if (const GlobalVariable *GV = | 
 |             dyn_cast<GlobalVariable>(CS->getOperand(1))) | 
 |           SourceFile = &PI.getSourceFile(GV); | 
 |  | 
 |         // Entry #2 is the function name. | 
 |         Name = getStringValue(CS->getOperand(2)); | 
 |       } | 
 | } | 
 |  | 
 | /// getSourceLocation - This method returns the location of the first stopping | 
 | /// point in the function. | 
 | void SourceFunctionInfo::getSourceLocation(unsigned &RetLineNo, | 
 |                                            unsigned &RetColNo) const { | 
 |   // If we haven't computed this yet... | 
 |   if (!LineNo) { | 
 |     // Look at all of the users of the function descriptor, looking for calls to | 
 |     // %llvm.dbg.func.start. | 
 |     for (Value::use_const_iterator UI = Descriptor->use_begin(), | 
 |            E = Descriptor->use_end(); UI != E; ++UI) | 
 |       if (const CallInst *CI = dyn_cast<CallInst>(*UI)) | 
 |         if (const Function *F = CI->getCalledFunction()) | 
 |           if (F->getIntrinsicID() == Intrinsic::dbg_func_start) { | 
 |             // We found the start of the function.  Check to see if there are | 
 |             // any stop points on the use-list of the function start. | 
 |             const GlobalVariable *SD = getNextStopPoint(CI, LineNo, ColNo); | 
 |             if (SD) {             // We found the first stop point! | 
 |               // This is just a sanity check. | 
 |               if (getSourceFile().getDescriptor() != SD) | 
 |                 std::cout << "WARNING: first line of function is not in the" | 
 |                   " file that the function descriptor claims it is in.\n"; | 
 |               break; | 
 |             } | 
 |           } | 
 |   } | 
 |   RetLineNo = LineNo; RetColNo = ColNo; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // ProgramInfo implementation | 
 | // | 
 |  | 
 | ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) { | 
 |   assert(M && "Cannot create program information with a null module!"); | 
 |   sys::Path modulePath(M->getModuleIdentifier()); | 
 |   ProgramTimeStamp = modulePath.getTimestamp(); | 
 |  | 
 |   SourceFilesIsComplete = false; | 
 |   SourceFunctionsIsComplete = false; | 
 | } | 
 |  | 
 | ProgramInfo::~ProgramInfo() { | 
 |   // Delete cached information about source program objects... | 
 |   for (std::map<const GlobalVariable*, SourceFileInfo*>::iterator | 
 |          I = SourceFiles.begin(), E = SourceFiles.end(); I != E; ++I) | 
 |     delete I->second; | 
 |   for (std::map<const GlobalVariable*, SourceFunctionInfo*>::iterator | 
 |          I = SourceFunctions.begin(), E = SourceFunctions.end(); I != E; ++I) | 
 |     delete I->second; | 
 |  | 
 |   // Delete the source language caches. | 
 |   for (unsigned i = 0, e = LanguageCaches.size(); i != e; ++i) | 
 |     delete LanguageCaches[i].second; | 
 | } | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // SourceFileInfo tracking... | 
 | // | 
 |  | 
 | /// getSourceFile - Return source file information for the specified source file | 
 | /// descriptor object, adding it to the collection as needed.  This method | 
 | /// always succeeds (is unambiguous), and is always efficient. | 
 | /// | 
 | const SourceFileInfo & | 
 | ProgramInfo::getSourceFile(const GlobalVariable *Desc) { | 
 |   SourceFileInfo *&Result = SourceFiles[Desc]; | 
 |   if (Result) return *Result; | 
 |  | 
 |   // Figure out what language this source file comes from... | 
 |   unsigned LangID = 0;   // Zero is unknown language | 
 |   if (Desc && Desc->hasInitializer()) | 
 |     if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer())) | 
 |       if (CS->getNumOperands() > 2) | 
 |         if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(CS->getOperand(2))) | 
 |           LangID = CUI->getValue(); | 
 |  | 
 |   const SourceLanguage &Lang = SourceLanguage::get(LangID); | 
 |   SourceFileInfo *New = Lang.createSourceFileInfo(Desc, *this); | 
 |  | 
 |   // FIXME: this should check to see if there is already a Filename/WorkingDir | 
 |   // pair that matches this one.  If so, we shouldn't create the duplicate! | 
 |   // | 
 |   SourceFileIndex.insert(std::make_pair(New->getBaseName(), New)); | 
 |   return *(Result = New); | 
 | } | 
 |  | 
 |  | 
 | /// getSourceFiles - Index all of the source files in the program and return | 
 | /// a mapping of it.  This information is lazily computed the first time | 
 | /// that it is requested.  Since this information can take a long time to | 
 | /// compute, the user is given a chance to cancel it.  If this occurs, an | 
 | /// exception is thrown. | 
 | const std::map<const GlobalVariable*, SourceFileInfo*> & | 
 | ProgramInfo::getSourceFiles(bool RequiresCompleteMap) { | 
 |   // If we have a fully populated map, or if the client doesn't need one, just | 
 |   // return what we have. | 
 |   if (SourceFilesIsComplete || !RequiresCompleteMap) | 
 |     return SourceFiles; | 
 |  | 
 |   // Ok, all of the source file descriptors (compile_unit in dwarf terms), | 
 |   // should be on the use list of the llvm.dbg.translation_units global. | 
 |   // | 
 |   GlobalVariable *Units = | 
 |     M->getGlobalVariable("llvm.dbg.translation_units", | 
 |                          StructType::get(std::vector<const Type*>())); | 
 |   if (Units == 0) | 
 |     throw "Program contains no debugging information!"; | 
 |  | 
 |   std::vector<GlobalVariable*> TranslationUnits; | 
 |   getGlobalVariablesUsing(Units, TranslationUnits); | 
 |  | 
 |   SlowOperationInformer SOI("building source files index"); | 
 |  | 
 |   // Loop over all of the translation units found, building the SourceFiles | 
 |   // mapping. | 
 |   for (unsigned i = 0, e = TranslationUnits.size(); i != e; ++i) { | 
 |     getSourceFile(TranslationUnits[i]); | 
 |     SOI.progress(i+1, e); | 
 |   } | 
 |  | 
 |   // Ok, if we got this far, then we indexed the whole program. | 
 |   SourceFilesIsComplete = true; | 
 |   return SourceFiles; | 
 | } | 
 |  | 
 | /// getSourceFile - Look up the file with the specified name.  If there is | 
 | /// more than one match for the specified filename, prompt the user to pick | 
 | /// one.  If there is no source file that matches the specified name, throw | 
 | /// an exception indicating that we can't find the file.  Otherwise, return | 
 | /// the file information for that file. | 
 | const SourceFileInfo &ProgramInfo::getSourceFile(const std::string &Filename) { | 
 |   std::multimap<std::string, SourceFileInfo*>::const_iterator Start, End; | 
 |   getSourceFiles(); | 
 |   tie(Start, End) = SourceFileIndex.equal_range(Filename); | 
 |  | 
 |   if (Start == End) throw "Could not find source file '" + Filename + "'!"; | 
 |   const SourceFileInfo &SFI = *Start->second; | 
 |   ++Start; | 
 |   if (Start == End) return SFI; | 
 |  | 
 |   throw "FIXME: Multiple source files with the same name not implemented!"; | 
 | } | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // SourceFunctionInfo tracking... | 
 | // | 
 |  | 
 |  | 
 | /// getFunction - Return function information for the specified function | 
 | /// descriptor object, adding it to the collection as needed.  This method | 
 | /// always succeeds (is unambiguous), and is always efficient. | 
 | /// | 
 | const SourceFunctionInfo & | 
 | ProgramInfo::getFunction(const GlobalVariable *Desc) { | 
 |   SourceFunctionInfo *&Result = SourceFunctions[Desc]; | 
 |   if (Result) return *Result; | 
 |  | 
 |   // Figure out what language this function comes from... | 
 |   const GlobalVariable *SourceFileDesc = 0; | 
 |   if (Desc && Desc->hasInitializer()) | 
 |     if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer())) | 
 |       if (CS->getNumOperands() > 0) | 
 |         if (const GlobalVariable *GV = | 
 |             dyn_cast<GlobalVariable>(CS->getOperand(1))) | 
 |           SourceFileDesc = GV; | 
 |  | 
 |   const SourceLanguage &Lang = getSourceFile(SourceFileDesc).getLanguage(); | 
 |   return *(Result = Lang.createSourceFunctionInfo(Desc, *this)); | 
 | } | 
 |  | 
 |  | 
 | // getSourceFunctions - Index all of the functions in the program and return | 
 | // them.  This information is lazily computed the first time that it is | 
 | // requested.  Since this information can take a long time to compute, the user | 
 | // is given a chance to cancel it.  If this occurs, an exception is thrown. | 
 | const std::map<const GlobalVariable*, SourceFunctionInfo*> & | 
 | ProgramInfo::getSourceFunctions(bool RequiresCompleteMap) { | 
 |   if (SourceFunctionsIsComplete || !RequiresCompleteMap) | 
 |     return SourceFunctions; | 
 |  | 
 |   // Ok, all of the source function descriptors (subprogram in dwarf terms), | 
 |   // should be on the use list of the llvm.dbg.translation_units global. | 
 |   // | 
 |   GlobalVariable *Units = | 
 |     M->getGlobalVariable("llvm.dbg.globals", | 
 |                          StructType::get(std::vector<const Type*>())); | 
 |   if (Units == 0) | 
 |     throw "Program contains no debugging information!"; | 
 |  | 
 |   std::vector<GlobalVariable*> Functions; | 
 |   getGlobalVariablesUsing(Units, Functions); | 
 |  | 
 |   SlowOperationInformer SOI("building functions index"); | 
 |  | 
 |   // Loop over all of the functions found, building the SourceFunctions mapping. | 
 |   for (unsigned i = 0, e = Functions.size(); i != e; ++i) { | 
 |     getFunction(Functions[i]); | 
 |     SOI.progress(i+1, e); | 
 |   } | 
 |  | 
 |   // Ok, if we got this far, then we indexed the whole program. | 
 |   SourceFunctionsIsComplete = true; | 
 |   return SourceFunctions; | 
 | } |