diff options
author | Jim Laskey <jlaskey@mac.com> | 2006-01-26 20:21:46 +0000 |
---|---|---|
committer | Jim Laskey <jlaskey@mac.com> | 2006-01-26 20:21:46 +0000 |
commit | b3e789ac2548a4382d0db03b573fd8a127617f8f (patch) | |
tree | a521e43b703e2c7efefa89d933b62982913c5b54 /lib/CodeGen/MachineDebugInfo.cpp | |
parent | e4a359e43b7af7db24482f1da3303c0bb7c9f425 (diff) | |
download | external_llvm-b3e789ac2548a4382d0db03b573fd8a127617f8f.zip external_llvm-b3e789ac2548a4382d0db03b573fd8a127617f8f.tar.gz external_llvm-b3e789ac2548a4382d0db03b573fd8a127617f8f.tar.bz2 |
Set up MachineDebugInfo to scan for debug information form "llvm.db"g globals.
Global Variable information is now pulled from "llvm.dbg.globals"
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25655 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/MachineDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/MachineDebugInfo.cpp | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/lib/CodeGen/MachineDebugInfo.cpp b/lib/CodeGen/MachineDebugInfo.cpp index 5464686..bfcd981 100644 --- a/lib/CodeGen/MachineDebugInfo.cpp +++ b/lib/CodeGen/MachineDebugInfo.cpp @@ -9,6 +9,13 @@ #include "llvm/CodeGen/MachineDebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Intrinsics.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Support/Dwarf.h" + using namespace llvm; // Handle the Pass registration stuff necessary to use TargetData's. @@ -16,8 +23,220 @@ namespace { RegisterPass<MachineDebugInfo> X("machinedebuginfo", "Debug Information"); } +//===----------------------------------------------------------------------===// + +/// getGlobalVariablesUsing - Return all of the global variables which have the +/// specified value in their initializer somewhere. +static void +getGlobalVariablesUsing(Value *V, std::vector<GlobalVariable*> &Result) { + // Scan though value users. + for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) { + // If the user is a global variable then add to result. + Result.push_back(GV); + } else if (Constant *C = dyn_cast<Constant>(*I)) { + // If the user is a constant variable then scan its users + getGlobalVariablesUsing(C, Result); + } + } +} + +/// getGlobalVariablesUsing - Return all of the global variables that use the +/// named global variable. +static std::vector<GlobalVariable*> +getGlobalVariablesUsing(Module &M, const std::string &RootName) { + std::vector<GlobalVariable*> Result; // Global variables matching criteria. + + // Get the global variable root. + GlobalVariable *UseRoot = M.getGlobalVariable(RootName, + StructType::get(std::vector<const Type*>())); + + // If present and linkonce then scan for users. + if (UseRoot && UseRoot->hasLinkOnceLinkage()) { + getGlobalVariablesUsing(UseRoot, Result); + } + + return Result; +} + +/// 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. +/// +const 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 ""; +} + +//===----------------------------------------------------------------------===// + +DebugInfoWrapper::DebugInfoWrapper(GlobalVariable *G) +: GV(G) +, IC(dyn_cast<ConstantStruct>(GV->getInitializer())) { + assert(IC && "llvm.db.global is missing structured constant"); +} + +//===----------------------------------------------------------------------===// + +CompileUnitWrapper::CompileUnitWrapper(GlobalVariable *G) +: DebugInfoWrapper(G) +{ + // FIXME - should probably ease up on the number of operands (version.) + assert(IC->getNumOperands() == 7 && + "Compile unit does not have correct number of operands"); +} + +/// getTag - Return the compile unit's tag number. Currently should be +/// DW_TAG_variable. +unsigned CompileUnitWrapper::getTag() const { + ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(0)); + assert(CI && "Compile unit tag not an unsigned integer"); + return CI->getValue(); +} + +/// isCorrectDebugVersion - Return true if is the correct llvm debug version. +/// Currently the value is 0 (zero.) If the value is is not correct then +/// ignore all debug information. +bool CompileUnitWrapper::isCorrectDebugVersion() const { + ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(1)); + assert(CI && "Compile unit debug version not an unsigned integer"); + return CI->getValue() == 0; +} + +/// getLanguage - Return the compile unit's language number (ex. DW_LANG_C89.) +/// +unsigned CompileUnitWrapper::getLanguage() const { + ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(2)); + assert(CI && "Compile unit language number not an unsigned integer"); + return CI->getValue(); +} + +/// getFileName - Return the compile unit's file name. +/// +const std::string CompileUnitWrapper::getFileName() const { + return getStringValue(IC->getOperand(3)); +} + +/// getDirectory - Return the compile unit's file directory. +/// +const std::string CompileUnitWrapper::getDirectory() const { + return getStringValue(IC->getOperand(4)); +} +/// getProducer - Return the compile unit's generator name. +/// +const std::string CompileUnitWrapper::getProducer() const { + return getStringValue(IC->getOperand(5)); +} + //===----------------------------------------------------------------------===// + +GlobalWrapper::GlobalWrapper(GlobalVariable *G) +: DebugInfoWrapper(G) +{ + // FIXME - should probably ease up on the number of operands (version.) + assert(IC->getNumOperands() == 8 && + "Global does not have correct number of operands"); +} + +/// getTag - Return the global's tag number. Currently should be +/// DW_TAG_variable or DW_TAG_subprogram. +unsigned GlobalWrapper::getTag() const { + ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(0)); + assert(CI && "Global tag not an unsigned integer"); + return CI->getValue(); +} + +/// getContext - Return the "lldb.compile_unit" context global. +/// +GlobalVariable *GlobalWrapper::getContext() const { + return dyn_cast<GlobalVariable>(IC->getOperand(1)); +} + +/// getName - Return the name of the global. +/// +const std::string GlobalWrapper::getName() const { + return getStringValue(IC->getOperand(2)); +} + +/// getType - Return the type of the global. +/// +const GlobalVariable *GlobalWrapper::getType() const { + return dyn_cast<GlobalVariable>(IC->getOperand(4)); +} + +/// isStatic - Return true if the global is static. +/// +bool GlobalWrapper::isStatic() const { + ConstantBool *CB = dyn_cast<ConstantBool>(IC->getOperand(5)); + assert(CB && "Global static flag is not boolean"); + return CB->getValue(); +} + +/// isDefinition - Return true if the global is a definition. +/// +bool GlobalWrapper::isDefinition() const { + ConstantBool *CB = dyn_cast<ConstantBool>(IC->getOperand(6)); + assert(CB && "Global definition flag is not boolean"); + return CB->getValue(); +} + +/// getGlobalVariable - Return the global variable (tag == DW_TAG_variable.) +/// +GlobalVariable *GlobalWrapper::getGlobalVariable() const { + ConstantExpr *CE = dyn_cast<ConstantExpr>(IC->getOperand(7)); + assert(CE && CE->getOpcode() == Instruction::Cast && + "Global location is not a cast of GlobalVariable"); + GlobalVariable *GV = dyn_cast<GlobalVariable>(CE->getOperand(0)); + assert(GV && "Global location is not a cast of GlobalVariable"); + return GV; +} + +//===----------------------------------------------------------------------===// + + +MachineDebugInfo::MachineDebugInfo() +: CompileUnits() +, Directories() +, SourceFiles() +, Lines() +{ + +} +MachineDebugInfo::~MachineDebugInfo() { + +} + /// doInitialization - Initialize the debug state for a new module. /// bool MachineDebugInfo::doInitialization() { @@ -29,3 +248,53 @@ bool MachineDebugInfo::doInitialization() { bool MachineDebugInfo::doFinalization() { return false; } + +/// AnalyzeModule - Scan the module for global debug information. +/// +void MachineDebugInfo::AnalyzeModule(Module &M) { + SetupCompileUnits(M); +} + +/// SetupCompileUnits - Set up the unique vector of compile units. +/// +void MachineDebugInfo::SetupCompileUnits(Module &M) { + // Get vector of all debug compile units. + std::vector<GlobalVariable*> Globals = + getGlobalVariablesUsing(M, "llvm.dbg.translation_units"); + + // Scan all compile unit globals. + for (unsigned i = 0, N = Globals.size(); i < N; ++i) { + // Create wrapper for compile unit. + CompileUnitWrapper CUI(Globals[i]); + // Add to result. + if (CUI.isCorrectDebugVersion()) CompileUnits.insert(CUI); + } + + // If there any bad compile units then suppress debug information + if (CompileUnits.size() != Globals.size()) CompileUnits.reset(); +} + +/// getGlobalVariables - Return a vector of debug global variables. +/// +std::vector<GlobalWrapper> MachineDebugInfo::getGlobalVariables(Module &M) { + // Get vector of all debug global objects. + std::vector<GlobalVariable*> Globals = + getGlobalVariablesUsing(M, "llvm.dbg.globals"); + + // Accumulation of global variables. + std::vector<GlobalWrapper> GlobalVariables; + +// FIXME - skip until globals have new format +#if 0 + // Scan all globals. + for (unsigned i = 0, N = Globals.size(); i < N; ++i) { + // Create wrapper for global. + GlobalWrapper GW(Globals[i]); + // If the global is a variable then add to result. + if (GW.getTag() == DW_TAG_variable) GlobalVariables.push_back(GW); + } +#endif + + return GlobalVariables; +} + |