Changes in directory llvm/lib/CodeGen:
AsmPrinter.cpp updated: 1.39 -> 1.40 DwarfWriter.cpp updated: 1.17 -> 1.18 MachineDebugInfo.cpp updated: 1.4 -> 1.5 --- Log message: Set up MachineDebugInfo to scan for debug information form "llvm.db"g globals. Global Variable information is now pulled from "llvm.dbg.globals" --- Diffs of the changes: (+289 -16) AsmPrinter.cpp | 5 DwarfWriter.cpp | 31 ++--- MachineDebugInfo.cpp | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 16 deletions(-) Index: llvm/lib/CodeGen/AsmPrinter.cpp diff -u llvm/lib/CodeGen/AsmPrinter.cpp:1.39 llvm/lib/CodeGen/AsmPrinter.cpp:1.40 --- llvm/lib/CodeGen/AsmPrinter.cpp:1.39 Mon Jan 23 22:15:29 2006 +++ llvm/lib/CodeGen/AsmPrinter.cpp Thu Jan 26 14:21:46 2006 @@ -78,6 +78,11 @@ << "\n" << CommentString << " End of file scope inline assembly\n"; SwitchSection("", 0); // Reset back to no section. + + if (MachineDebugInfo *DebugInfo = getAnalysisToUpdate<MachineDebugInfo>()) { + DebugInfo->AnalyzeModule(M); + } + return false; } Index: llvm/lib/CodeGen/DwarfWriter.cpp diff -u llvm/lib/CodeGen/DwarfWriter.cpp:1.17 llvm/lib/CodeGen/DwarfWriter.cpp:1.18 --- llvm/lib/CodeGen/DwarfWriter.cpp:1.17 Wed Jan 25 11:18:50 2006 +++ llvm/lib/CodeGen/DwarfWriter.cpp Thu Jan 26 14:21:46 2006 @@ -18,6 +18,7 @@ #include "llvm/Type.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineDebugInfo.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetMachine.h" @@ -1719,28 +1720,26 @@ /// variables. void DwarfWriter::ConstructGlobalDIEs(Module &M) { const TargetData &TD = Asm->TM.getTargetData(); - - // Iterate throu each of the globals. - for (Module::const_global_iterator GI = M.global_begin(), GE = M.global_end(); - GI != GE; ++GI) { - if (!GI->hasInitializer()) continue; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (GI->hasAppendingLinkage() && (GI->getName() == "llvm.global_ctors" || - GI->getName() == "llvm.global_dtors")) - continue; + + std::vector<GlobalWrapper> GlobalVariables = DebugInfo->getGlobalVariables(M); + + for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) { + GlobalWrapper &GW = GlobalVariables[i]; + GlobalVariable *GV = GW.getGlobalVariable(); - std::string Name = Asm->Mang->getValueName(GI); - Constant *C = GI->getInitializer(); + if (!GV->hasInitializer()) continue; // External global require no code + + // FIXME - Use global info type information when available. + std::string Name = Asm->Mang->getValueName(GV); + Constant *C = GV->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD.getTypeSize(Ty); unsigned Align = TD.getTypeAlignmentShift(Ty); if (C->isNullValue() && /* FIXME: Verify correct */ - (GI->hasInternalLinkage() || GI->hasWeakLinkage() || - GI->hasLinkOnceLinkage())) { + (GV->hasInternalLinkage() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage())) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - } /// FIXME - Get correct compile unit context. @@ -1748,7 +1747,7 @@ DWContext *Context = CompileUnits[0]->getContext(); /// Create new global. - NewGlobalVariable(Context, GI->getName(), Name, Ty, Size, Align); + NewGlobalVariable(Context, GV->getName(), Name, Ty, Size, Align); } } Index: llvm/lib/CodeGen/MachineDebugInfo.cpp diff -u llvm/lib/CodeGen/MachineDebugInfo.cpp:1.4 llvm/lib/CodeGen/MachineDebugInfo.cpp:1.5 --- llvm/lib/CodeGen/MachineDebugInfo.cpp:1.4 Tue Jan 17 11:31:53 2006 +++ llvm/lib/CodeGen/MachineDebugInfo.cpp Thu Jan 26 14:21:46 2006 @@ -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 @@ 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::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; +} + _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits