From 86cbdba5228a3cb043a73c630e8d93e1a943cbe3 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 6 Feb 2006 15:33:21 +0000 Subject: [PATCH] Changing model for the construction of debug information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26016 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/DwarfWriter.h | 4 +- include/llvm/CodeGen/MachineDebugInfo.h | 427 ++++++++++---- lib/CodeGen/DwarfWriter.cpp | 22 +- lib/CodeGen/MachineDebugInfo.cpp | 702 +++++++++++++++++++++--- 4 files changed, 953 insertions(+), 202 deletions(-) diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index c98dbbce396..841a029d60b 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -33,7 +33,7 @@ namespace llvm { // Forward declarations. // class AsmPrinter; - class CompileUnitWrapper; + class CompileUnitDesc; class DIE; class DwarfWriter; class DWContext; @@ -657,7 +657,7 @@ private: /// NewCompileUnit - Create new compile unit information. /// - DIE *NewCompileUnit(const CompileUnitWrapper &CompileUnit); + DIE *NewCompileUnit(const CompileUnitDesc *CompileUnit); /// EmitInitial - Emit initial Dwarf declarations. /// diff --git a/include/llvm/CodeGen/MachineDebugInfo.h b/include/llvm/CodeGen/MachineDebugInfo.h index fe12802dcde..a04f778c16f 100644 --- a/include/llvm/CodeGen/MachineDebugInfo.h +++ b/include/llvm/CodeGen/MachineDebugInfo.h @@ -17,160 +17,385 @@ // The following information can be retrieved from the MachineDebugInfo. // // -- Source directories - Directories are uniqued based on their canonical -// string and assigned a sequential numeric ID (base 1.) A directory ID - 1 -// provides the index of directory information in a queried directory list. +// string and assigned a sequential numeric ID (base 1.) // -- Source files - Files are also uniqued based on their name and directory -// ID. A file ID is sequential number (base 1.) A file ID - 1 provides the -// index of source information in a queried file list. +// ID. A file ID is sequential number (base 1.) // -- Source line coorespondence - A vector of file ID, line#, column# triples. // A DEBUG_LOCATION instruction is generated by the DAG Legalizer // corresponding to each entry in the source line list. This allows a debug -// information emitter to generate labels to map code addressed to debug -// tables. +// emitter to generate labels referenced by degug information tables. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_MACHINEDEBUGINFO_H #define LLVM_CODEGEN_MACHINEDEBUGINFO_H -#include "llvm/Pass.h" +#include "llvm/Support/Dwarf.h" #include "llvm/ADT/UniqueVector.h" +#include "llvm/Pass.h" +#include "llvm/User.h" + #include +#include namespace llvm { +//===----------------------------------------------------------------------===// // Forward declarations. -class ConstantStruct; +class DebugInfoDesc; class GlobalVariable; class Module; +class PointerType; +class StructType; //===----------------------------------------------------------------------===// -/// DebugInfoWrapper - This class is the base class for debug info wrappers. +// Debug info constants. +enum { + LLVMDebugVersion = 1, // Current version of debug information. + DIInvalid = ~0U, // Invalid result indicator. + + // DebugInfoDesc type identifying tags. + // FIXME - Change over with gcc4. +#if 1 + DI_TAG_compile_unit = DW_TAG_compile_unit, + DI_TAG_global_variable = DW_TAG_variable, + DI_TAG_subprogram = DW_TAG_subprogram +#else + DI_TAG_compile_unit = 1, + DI_TAG_global_variable, + DI_TAG_subprogram +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIApplyManager - Subclasses of this class apply steps to each of the fields +/// in the supplied DebugInfoDesc. +class DIApplyManager { +public: + DIApplyManager() {} + virtual ~DIApplyManager() {} + + + /// ApplyToFields - Target the manager to each field of the debug information + /// descriptor. + void ApplyToFields(DebugInfoDesc *DD); + + /// Apply - Subclasses override each of these methods to perform the + /// appropriate action for the type of field. + virtual void Apply(int &Field) = 0; + virtual void Apply(unsigned &Field) = 0; + virtual void Apply(bool &Field) = 0; + virtual void Apply(std::string &Field) = 0; + virtual void Apply(DebugInfoDesc *&Field) = 0; + virtual void Apply(GlobalVariable *&Field) = 0; +}; + +//===----------------------------------------------------------------------===// +/// DebugInfoDesc - This class is the base class for debug info descriptors. /// -class DebugInfoWrapper { +class DebugInfoDesc { +private: + unsigned Tag; // Content indicator. Dwarf values are + // used but that does not limit use to + // Dwarf writers. + protected: - GlobalVariable *GV; // "llvm.db" global - ConstantStruct *IC; // Initializer constant. + DebugInfoDesc(unsigned T) : Tag(T) {} public: - DebugInfoWrapper(GlobalVariable *G); + virtual ~DebugInfoDesc() {} + + // Accessors + unsigned getTag() const { return Tag; } - /// getGlobal - Return the "llvm.db" global. - /// - GlobalVariable *getGlobal() const { return GV; } + /// TagFromGlobal - Returns the Tag number from a debug info descriptor + /// GlobalVariable. + static unsigned TagFromGlobal(GlobalVariable *GV, bool Checking = false); - /// operator== - Used by Uniquevector to locate entry. + /// DescFactory - Create an instance of debug info descriptor based on Tag. + /// Return NULL if not a recognized Tag. + static DebugInfoDesc *DescFactory(unsigned Tag); + + //===--------------------------------------------------------------------===// + // Subclasses should supply the following static methods. + + // Implement isa/cast/dyncast. + static bool classof(const DebugInfoDesc *) { return true; } + + //===--------------------------------------------------------------------===// + // Subclasses should supply the following virtual methods. + + /// ApplyToFields - Target the apply manager to the fields of the descriptor. /// - bool operator==(const DebugInfoWrapper &DI) const { return IC == DI.IC; } + virtual void ApplyToFields(DIApplyManager *Mgr) = 0; - /// operator< - Used by Uniquevector to locate entry. + /// TypeString - Return a string used to compose globalnames and labels. /// - bool operator<(const DebugInfoWrapper &DI) const { return IC < DI.IC; } + virtual const char *TypeString() const = 0; + +#ifndef NDEBUG + virtual void dump() = 0; +#endif }; //===----------------------------------------------------------------------===// -/// CompileUnitWrapper - This class wraps a "lldb.compile_unit" global to -/// provide easy access to its attributes. -class CompileUnitWrapper : public DebugInfoWrapper { -private: - // Operand indices. - enum { - Tag_op, - Version_op, - Language_op, - FileName_op, - Directory_op, - Producer_op, - Anchor_op, // ignored - N_op - }; +/// CompileUnitDesc - This class packages debug information associated with a +/// source/header file. +class CompileUnitDesc : public DebugInfoDesc { +private: + unsigned DebugVersion; // LLVM debug version when produced. + unsigned Language; // Language number (ex. DW_LANG_C89.) + std::string FileName; // Source file name. + std::string Directory; // Source file directory. + std::string Producer; // Compiler string. + GlobalVariable *TransUnit; // Translation unit - ignored. public: - CompileUnitWrapper(GlobalVariable *G); + CompileUnitDesc() + : DebugInfoDesc(DI_TAG_compile_unit) + , DebugVersion(LLVMDebugVersion) + , Language(0) + , FileName("") + , Directory("") + , Producer("") + , TransUnit(NULL) + {} - /// getGlobal - Return the "lldb.compile_unit" global. - /// - GlobalVariable *getGlobal() const { return GV; } - - /// getTag - Return the compile unit's tag number. Currently DW_TAG_variable, - /// DW_TAG_subprogram or DW_TAG_compile_unit. - unsigned getTag() const; + // Accessors + unsigned getDebugVersion() const { return DebugVersion; } + unsigned getLanguage() const { return Language; } + const std::string &getFileName() const { return FileName; } + const std::string &getDirectory() const { return Directory; } + const std::string &getProducer() const { return Producer; } + void setLanguage(unsigned L) { Language = L; } + void setFileName(const std::string &FN) { FileName = FN; } + void setDirectory(const std::string &D) { Directory = D; } + void setProducer(const std::string &P) { Producer = P; } + // FIXME - Need translation unit getter/setter. - /// 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 isCorrectDebugVersion() const; + // Implement isa/cast/dyncast. + static bool classof(const CompileUnitDesc *) { return true; } + static bool classof(const DebugInfoDesc *D) { + return D->getTag() == DI_TAG_compile_unit; + } - /// getLanguage - Return the compile unit's language number (ex. DW_LANG_C89.) - /// - unsigned getLanguage() const; + /// DebugVersionFromGlobal - Returns the version number from a compile unit + /// GlobalVariable. + static unsigned DebugVersionFromGlobal(GlobalVariable *GV, + bool Checking = false); - /// getFileName - Return the compile unit's file name. + /// ApplyToFields - Target the apply manager to the fields of the + /// CompileUnitDesc. + virtual void ApplyToFields(DIApplyManager *Mgr); + + /// TypeString - Return a string used to compose globalnames and labels. /// - const std::string getFileName() const; + virtual const char *TypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// GlobalVariableDesc - This class packages debug information associated with a +/// GlobalVariable. +class GlobalVariableDesc : public DebugInfoDesc { +private: + DebugInfoDesc *Context; // Context debug descriptor. + std::string Name; // Global name. + GlobalVariable *TransUnit; // Translation unit - ignored. + // FIXME - Use a descriptor. + GlobalVariable *TyDesc; // Type debug descriptor. + bool IsStatic; // Is the global a static. + bool IsDefinition; // Is the global defined in context. + GlobalVariable *Global; // llvm global. - /// getDirectory - Return the compile unit's file directory. - /// - const std::string getDirectory() const; +public: + GlobalVariableDesc() + : DebugInfoDesc(DI_TAG_global_variable) + , Context(0) + , Name("") + , TransUnit(NULL) + , TyDesc(NULL) + , IsStatic(false) + , IsDefinition(false) + , Global(NULL) + {} - /// getProducer - Return the compile unit's generator name. + // Accessors + DebugInfoDesc *getContext() const { return Context; } + const std::string &getName() const { return Name; } + bool isStatic() const { return IsStatic; } + bool isDefinition() const { return IsDefinition; } + GlobalVariable *getGlobalVariable() const { return Global; } + void setName(const std::string &N) { Name = N; } + void setIsStatic(bool IS) { IsStatic = IS; } + void setIsDefinition(bool ID) { IsDefinition = ID; } + void setGlobalVariable(GlobalVariable *GV) { Global = GV; } + // FIXME - Other getters/setters. + + // Implement isa/cast/dyncast. + static bool classof(const GlobalVariableDesc *) { return true; } + static bool classof(const DebugInfoDesc *D) { + return D->getTag() == DI_TAG_global_variable; + } + + /// ApplyToFields - Target the apply manager to the fields of the + /// GlobalVariableDesc. + virtual void ApplyToFields(DIApplyManager *Mgr); + + /// TypeString - Return a string used to compose globalnames and labels. /// - const std::string getProducer() const; + virtual const char *TypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif }; //===----------------------------------------------------------------------===// -/// GlobalWrapper - This class wraps a "lldb.global" global to provide easy -/// access to its attributes. -class GlobalWrapper : public DebugInfoWrapper { +/// SubprogramDesc - This class packages debug information associated with a +/// subprogram/function. +class SubprogramDesc : public DebugInfoDesc { private: - // Operand indices. - enum { - Tag_op, - Context_op, - Name_op, - Anchor_op, // ignored - Type_op, - Static_op, - Definition_op, - GlobalVariable_op, - N_op - }; + DebugInfoDesc *Context; // Context debug descriptor. + std::string Name; // Subprogram name. + GlobalVariable *TransUnit; // Translation unit - ignored. + // FIXME - Use a descriptor. + GlobalVariable *TyDesc; // Type debug descriptor. + bool IsStatic; // Is the subprogram a static. + bool IsDefinition; // Is the subprogram defined in context. public: - GlobalWrapper(GlobalVariable *G); + SubprogramDesc() + : DebugInfoDesc(DI_TAG_subprogram) + , Context(0) + , Name("") + , TransUnit(NULL) + , TyDesc(NULL) + , IsStatic(false) + , IsDefinition(false) + {} - /// getGlobal - Return the "lldb.global" global. - /// - GlobalVariable *getGlobal() const { return GV; } + // Accessors + DebugInfoDesc *getContext() const { return Context; } + const std::string &getName() const { return Name; } + bool isStatic() const { return IsStatic; } + bool isDefinition() const { return IsDefinition; } + void setName(const std::string &N) { Name = N; } + void setIsStatic(bool IS) { IsStatic = IS; } + void setIsDefinition(bool ID) { IsDefinition = ID; } + // FIXME - Other getters/setters. + + // Implement isa/cast/dyncast. + static bool classof(const SubprogramDesc *) { return true; } + static bool classof(const DebugInfoDesc *D) { + return D->getTag() == DI_TAG_subprogram; + } + + /// ApplyToFields - Target the apply manager to the fields of the + /// SubprogramDesc. + virtual void ApplyToFields(DIApplyManager *Mgr); - /// getContext - Return the "lldb.compile_unit" context global. + /// TypeString - Return a string used to compose globalnames and labels. /// - GlobalVariable *getContext() const; + virtual const char *TypeString() const; - /// getTag - Return the global's tag number. Currently should be - /// DW_TAG_variable or DW_TAG_subprogram. - unsigned getTag() const; +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIDeserializer - This class is responsible for casting GlobalVariables +/// into DebugInfoDesc objects. +class DIDeserializer { +private: + Module *M; // Definition space module. + unsigned DebugVersion; // Version of debug information in use. + std::map GlobalDescs; + // Previously defined gloabls. + +public: + DIDeserializer() : M(NULL), DebugVersion(LLVMDebugVersion) {} + ~DIDeserializer() {} + + // Accessors + Module *getModule() const { return M; }; + void setModule(Module *module) { M = module; } + unsigned getDebugVersion() const { return DebugVersion; } - /// getName - Return the name of the global. + /// Deserialize - Reconstitute a GlobalVariable into it's component + /// DebugInfoDesc objects. + DebugInfoDesc *Deserialize(Value *V); + DebugInfoDesc *Deserialize(GlobalVariable *GV); +}; + +//===----------------------------------------------------------------------===// +/// DISerializer - This class is responsible for casting DebugInfoDesc objects +/// into GlobalVariables. +class DISerializer { +private: + Module *M; // Definition space module. + PointerType *StrPtrTy; // A "sbyte *" type. Created lazily. + PointerType *EmptyStructPtrTy; // A "{ }*" type. Created lazily. + std::map TagTypes; + // Types per Tag. Created lazily. + std::map DescGlobals; + // Previously defined descriptors. + std::map StringCache; + // Previously defined strings. +public: + DISerializer() : M(NULL) {} + ~DISerializer() {} + + // Accessors + Module *getModule() const { return M; }; + void setModule(Module *module) { M = module; } + + /// getStrPtrType - Return a "sbyte *" type. /// - const std::string getName() const; + const PointerType *getStrPtrType(); - /// getType - Return the type of the global. + /// getEmptyStructPtrType - Return a "{ }*" type. /// - const GlobalVariable *getType() const; - - /// isStatic - Return true if the global is static. + const PointerType *getEmptyStructPtrType(); + + /// getTagType - Return the type describing the specified descriptor (via + /// tag.) + const StructType *getTagType(DebugInfoDesc *DD); + + /// getString - Construct the string as constant string global. /// - bool isStatic() const; + GlobalVariable *getString(const std::string &String); + + /// Serialize - Recursively cast the specified descriptor into a + /// GlobalVariable so that it can be serialized to a .bc or .ll file. + GlobalVariable *Serialize(DebugInfoDesc *DD); +}; - /// isDefinition - Return true if the global is a definition. - /// - bool isDefinition() const; +//===----------------------------------------------------------------------===// +/// DIVerifier - This class is responsible for verifying the given network of +/// GlobalVariables are valid as DebugInfoDesc objects. +class DIVerifier { +private: + unsigned DebugVersion; // Version of debug information in use. + std::set Visited; // Tracks visits during recursion. + std::map Counts; // Count of fields per Tag type. + + /// markVisited - Return true if the GlobalVariable hase been "seen" before. + /// Mark markVisited otherwise. + bool markVisited(GlobalVariable *GV); - /// getGlobalVariable - Return the global variable (tag == DW_TAG_variable.) - /// - GlobalVariable *getGlobalVariable() const; +public: + DIVerifier() : DebugVersion(LLVMDebugVersion) {} + ~DIVerifier() {} + + /// Verify - Return true if the GlobalVariable appears to be a valid + /// serialization of a DebugInfoDesc. + bool Verify(GlobalVariable *GV); }; //===----------------------------------------------------------------------===// @@ -228,8 +453,14 @@ public: /// class MachineDebugInfo : public ImmutablePass { private: + // Debug indforma + // Use the same serializer/deserializer/verifier for the module. + DISerializer SR; + DIDeserializer DR; + DIVerifier VR; + // CompileUnits - Uniquing vector for compile units. - UniqueVector CompileUnits; + UniqueVector CompileUnits; // Directories - Uniquing vector for directories. UniqueVector Directories; @@ -300,11 +531,11 @@ public: /// getCompileUnits - Return a vector of debug compile units. /// - const UniqueVector getCompileUnits() const; + const UniqueVector getCompileUnits() const; - /// getGlobalVariables - Return a vector of debug global variables. + /// getGlobalVariables - Return a vector of debug GlobalVariables. /// - static std::vector getGlobalVariables(Module &M); + std::vector getGlobalVariables(Module &M); }; // End class MachineDebugInfo diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index 4de5dcfc2a0..f7bb0923bba 100644 --- a/lib/CodeGen/DwarfWriter.cpp +++ b/lib/CodeGen/DwarfWriter.cpp @@ -1269,16 +1269,16 @@ void DwarfWriter::NewGlobalVariable(DWContext *Context, /// NewCompileUnit - Create new compile unit information. /// -DIE *DwarfWriter::NewCompileUnit(const CompileUnitWrapper &CompileUnit) { +DIE *DwarfWriter::NewCompileUnit(const CompileUnitDesc *CompileUnit) { DIE *Unit = new DIE(DW_TAG_compile_unit, DW_CHILDREN_yes); // FIXME - use the correct line set. Unit->AddLabel (DW_AT_stmt_list, DW_FORM_data4, DWLabel("line", 0)); Unit->AddLabel (DW_AT_high_pc, DW_FORM_addr, DWLabel("text_end", 0)); Unit->AddLabel (DW_AT_low_pc, DW_FORM_addr, DWLabel("text_begin", 0)); - Unit->AddString(DW_AT_producer, DW_FORM_string, CompileUnit.getProducer()); - Unit->AddUInt (DW_AT_language, DW_FORM_data1, CompileUnit.getLanguage()); - Unit->AddString(DW_AT_name, DW_FORM_string, CompileUnit.getFileName()); - Unit->AddString(DW_AT_comp_dir, DW_FORM_string, CompileUnit.getDirectory()); + Unit->AddString(DW_AT_producer, DW_FORM_string, CompileUnit->getProducer()); + Unit->AddUInt (DW_AT_language, DW_FORM_data1, CompileUnit->getLanguage()); + Unit->AddString(DW_AT_name, DW_FORM_string, CompileUnit->getFileName()); + Unit->AddString(DW_AT_comp_dir, DW_FORM_string, CompileUnit->getDirectory()); Unit->Complete(*this); return Unit; @@ -1723,11 +1723,10 @@ void DwarfWriter::EmitDebugMacInfo() { /// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and /// header file. void DwarfWriter::ConstructCompileUnitDIEs() { - const UniqueVector CUW = DebugInfo->getCompileUnits(); + const UniqueVector CUW = DebugInfo->getCompileUnits(); for (unsigned i = 1, N = CUW.size(); i <= N; ++i) { - const CompileUnitWrapper &CompileUnit = CUW[i]; - DIE *Unit = NewCompileUnit(CompileUnit); + DIE *Unit = NewCompileUnit(CUW[i]); DWContext *Context = new DWContext(*this, NULL, Unit); CompileUnits.push_back(Unit); } @@ -1738,11 +1737,12 @@ void DwarfWriter::ConstructCompileUnitDIEs() { void DwarfWriter::ConstructGlobalDIEs(Module &M) { const TargetData &TD = Asm->TM.getTargetData(); - std::vector GlobalVariables = DebugInfo->getGlobalVariables(M); + std::vector GlobalVariables = + DebugInfo->getGlobalVariables(M); for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) { - GlobalWrapper &GW = GlobalVariables[i]; - GlobalVariable *GV = GW.getGlobalVariable(); + GlobalVariableDesc *GVD = GlobalVariables[i]; + GlobalVariable *GV = GVD->getGlobalVariable(); if (!GV->hasInitializer()) continue; // External global require no code diff --git a/lib/CodeGen/MachineDebugInfo.cpp b/lib/CodeGen/MachineDebugInfo.cpp index ab42886cb48..e3b24ab03b5 100644 --- a/lib/CodeGen/MachineDebugInfo.cpp +++ b/lib/CodeGen/MachineDebugInfo.cpp @@ -11,11 +11,14 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Support/Dwarf.h" +#include + using namespace llvm; // Handle the Pass registration stuff necessary to use TargetData's. @@ -25,14 +28,14 @@ namespace { //===----------------------------------------------------------------------===// -/// getGlobalVariablesUsing - Return all of the global variables which have the +/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the /// specified value in their initializer somewhere. static void getGlobalVariablesUsing(Value *V, std::vector &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(*I)) { - // If the user is a global variable then add to result. + // If the user is a GlobalVariable then add to result. Result.push_back(GV); } else if (Constant *C = dyn_cast(*I)) { // If the user is a constant variable then scan its users @@ -41,13 +44,13 @@ getGlobalVariablesUsing(Value *V, std::vector &Result) { } } -/// getGlobalVariablesUsing - Return all of the global variables that use the -/// named global variable. +/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the +/// named GlobalVariable. static std::vector getGlobalVariablesUsing(Module &M, const std::string &RootName) { - std::vector Result; // Global variables matching criteria. + std::vector Result; // GlobalVariables matching criteria. - // Get the global variable root. + // Get the GlobalVariable root. GlobalVariable *UseRoot = M.getGlobalVariable(RootName, StructType::get(std::vector())); @@ -98,131 +101,646 @@ static const std::string getStringValue(Value *V, unsigned Offset = 0) { return ""; } +/// isStringValue - Return true if the given value can be coerced to a string. +/// +static bool isStringValue(Value *V) { + if (GlobalVariable *GV = dyn_cast(V)) { + if (GV->hasInitializer() && isa(GV->getInitializer())) { + ConstantArray *Init = cast(GV->getInitializer()); + return Init->isString(); + } + } else if (Constant *C = dyn_cast(V)) { + if (GlobalValue *GV = dyn_cast(C)) + return isStringValue(GV); + else if (ConstantExpr *CE = dyn_cast(C)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + if (CE->getNumOperands() == 3 && + cast(CE->getOperand(1))->isNullValue() && + isa(CE->getOperand(2))) { + return isStringValue(CE->getOperand(0)); + } + } + } + } + return false; +} + /// getGlobalValue - Return either a direct or cast Global value. /// static GlobalVariable *getGlobalValue(Value *V) { if (GlobalVariable *GV = dyn_cast(V)) { return GV; } else if (ConstantExpr *CE = dyn_cast(V)) { - return CE->getOpcode() == Instruction::Cast ? dyn_cast(V) - : NULL; + if (CE->getOpcode() == Instruction::Cast) { + return dyn_cast(CE->getOperand(0)); + } } return NULL; } +/// isGlobalValue - Return true if the given value can be coerced to a +/// GlobalVariable. +static bool isGlobalValue(Value *V) { + if (isa(V) || isa(V)) { + return true; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() == Instruction::Cast) { + return isa(CE->getOperand(0)); + } + } + return false; +} + +/// isUIntOperand - Return true if the ith operand is an unsigned integer. +/// +static bool isUIntOperand(GlobalVariable *GV, unsigned i) { + // Make sure the GlobalVariable has an initializer. + if (!GV->hasInitializer()) return false; + + // Get the initializer constant. + ConstantStruct *CI = dyn_cast(GV->getInitializer()); + if (!CI) return false; + // Check if there is at least i + 1 operands. + unsigned N = CI->getNumOperands(); + if (i >= N) return false; + + // Check constant. + return isa(CI->getOperand(i)); +} + //===----------------------------------------------------------------------===// -DebugInfoWrapper::DebugInfoWrapper(GlobalVariable *G) -: GV(G) -, IC(dyn_cast(GV->getInitializer())) { - assert(IC && "llvm.db.global is missing structured constant"); +/// TagFromGlobal - Returns the Tag number from a debug info descriptor +/// GlobalVariable. +unsigned DebugInfoDesc::TagFromGlobal(GlobalVariable *GV, bool Checking) { + if (Checking && !isUIntOperand(GV, 0)) return DIInvalid; + ConstantStruct *CI = cast(GV->getInitializer()); + Constant *C = CI->getOperand(0); + return cast(C)->getValue(); } + +/// DescFactory - Create an instance of debug info descriptor based on Tag. +/// Return NULL if not a recognized Tag. +DebugInfoDesc *DebugInfoDesc::DescFactory(unsigned Tag) { + switch (Tag) { + case DI_TAG_compile_unit: return new CompileUnitDesc(); + case DI_TAG_global_variable: return new GlobalVariableDesc(); + case DI_TAG_subprogram: return new SubprogramDesc(); + default: break; + } + return NULL; +} + +//===----------------------------------------------------------------------===// + +/// ApplyToFields - Target the manager to each field of the debug information +/// descriptor. +void DIApplyManager::ApplyToFields(DebugInfoDesc *DD) { + DD->ApplyToFields(this); +} + +//===----------------------------------------------------------------------===// +/// DICountAppMgr - This DIApplyManager counts all the fields in the supplied +/// debug the supplied DebugInfoDesc. +class DICountAppMgr : public DIApplyManager { +private: + unsigned Count; // Running count of fields. + +public: + DICountAppMgr() : DIApplyManager(), Count(1) {} + // Accessors. + unsigned getCount() const { return Count; } + + /// Apply - Count each of the fields. + /// + virtual void Apply(int &Field) { ++Count; } + virtual void Apply(unsigned &Field) { ++Count; } + virtual void Apply(bool &Field) { ++Count; } + virtual void Apply(std::string &Field) { ++Count; } + virtual void Apply(DebugInfoDesc *&Field) { ++Count; } + virtual void Apply(GlobalVariable *&Field) { ++Count; } +}; + //===----------------------------------------------------------------------===// +/// DIDeserializeAppMgr - This DIApplyManager deserializes all the fields in +/// the supplied DebugInfoDesc. +class DIDeserializeAppMgr : public DIApplyManager { +private: + DIDeserializer &DR; // Active deserializer. + unsigned I; // Current operand index. + ConstantStruct *CI; // GlobalVariable constant initializer. + +public: + DIDeserializeAppMgr(DIDeserializer &D, GlobalVariable *GV) + : DIApplyManager() + , DR(D) + , I(1) + , CI(cast(GV->getInitializer())) + {} + + /// Apply - Set the value of each of the fields. + /// + virtual void Apply(int &Field) { + Constant *C = CI->getOperand(I++); + Field = cast(C)->getValue(); + } + virtual void Apply(unsigned &Field) { + Constant *C = CI->getOperand(I++); + Field = cast(C)->getValue(); + } + virtual void Apply(bool &Field) { + Constant *C = CI->getOperand(I++); + Field = cast(C)->getValue(); + } + virtual void Apply(std::string &Field) { + Constant *C = CI->getOperand(I++); + Field = getStringValue(C); + } + virtual void Apply(DebugInfoDesc *&Field) { + Constant *C = CI->getOperand(I++); + Field = DR.Deserialize(C); + } + virtual void Apply(GlobalVariable *&Field) { + Constant *C = CI->getOperand(I++); + Field = getGlobalValue(C); + } +}; -CompileUnitWrapper::CompileUnitWrapper(GlobalVariable *G) -: DebugInfoWrapper(G) -{ - // FIXME - should probably ease up on the number of operands (version.) - assert(IC->getNumOperands() == N_op && - "Compile unit does not have correct number of operands"); +//===----------------------------------------------------------------------===// +/// DISerializeAppMgr - This DIApplyManager serializes all the fields in +/// the supplied DebugInfoDesc. +class DISerializeAppMgr : public DIApplyManager { +private: + DISerializer &SR; // Active serializer. + std::vector &Elements; // Element accumulator. + +public: + DISerializeAppMgr(DISerializer &S, std::vector &E) + : DIApplyManager() + , SR(S) + , Elements(E) + {} + + /// Apply - Set the value of each of the fields. + /// + virtual void Apply(int &Field) { + Elements.push_back(ConstantUInt::get(Type::IntTy, Field)); + } + virtual void Apply(unsigned &Field) { + Elements.push_back(ConstantUInt::get(Type::UIntTy, Field)); + } + virtual void Apply(bool &Field) { + Elements.push_back(ConstantBool::get(Field)); + } + virtual void Apply(std::string &Field) { + Elements.push_back(SR.getString(Field)); + } + virtual void Apply(DebugInfoDesc *&Field) { + GlobalVariable *GV = NULL; + + // If non-NULL the convert to global. + if (Field) GV = SR.Serialize(Field); + + // FIXME - At some point should use specific type. + const PointerType *EmptyTy = SR.getEmptyStructPtrType(); + + if (GV) { + // Set to pointer to global. + Elements.push_back(ConstantExpr::getCast(GV, EmptyTy)); + } else { + // Use NULL. + Elements.push_back(ConstantPointerNull::get(EmptyTy)); + } + } + virtual void Apply(GlobalVariable *&Field) { + const PointerType *EmptyTy = SR.getEmptyStructPtrType(); + Elements.push_back(ConstantExpr::getCast(Field, EmptyTy)); + } +}; + +//===----------------------------------------------------------------------===// +/// DIGetTypesAppMgr - This DIApplyManager gathers all the field types in +/// the supplied DebugInfoDesc. +class DIGetTypesAppMgr : public DIApplyManager { +private: + DISerializer &SR; // Active serializer. + std::vector &Fields; // Type accumulator. + +public: + DIGetTypesAppMgr(DISerializer &S, std::vector &F) + : DIApplyManager() + , SR(S) + , Fields(F) + {} + + /// Apply - Set the value of each of the fields. + /// + virtual void Apply(int &Field) { + Fields.push_back(Type::IntTy); + } + virtual void Apply(unsigned &Field) { + Fields.push_back(Type::UIntTy); + } + virtual void Apply(bool &Field) { + Fields.push_back(Type::BoolTy); + } + virtual void Apply(std::string &Field) { + Fields.push_back(SR.getStrPtrType()); + } + virtual void Apply(DebugInfoDesc *&Field) { + // FIXME - At some point should use specific type. + const PointerType *EmptyTy = SR.getEmptyStructPtrType(); + Fields.push_back(EmptyTy); + } + virtual void Apply(GlobalVariable *&Field) { + const PointerType *EmptyTy = SR.getEmptyStructPtrType(); + Fields.push_back(EmptyTy); + } +}; + +//===----------------------------------------------------------------------===// +/// DIVerifyAppMgr - This DIApplyManager verifies all the field types against +/// a constant initializer. +class DIVerifyAppMgr : public DIApplyManager { +private: + DIVerifier &VR; // Active verifier. + bool IsValid; // Validity status. + unsigned I; // Current operand index. + ConstantStruct *CI; // GlobalVariable constant initializer. + +public: + DIVerifyAppMgr(DIVerifier &V, GlobalVariable *GV) + : DIApplyManager() + , VR(V) + , IsValid(true) + , I(1) + , CI(cast(GV->getInitializer())) + { + } + + // Accessors. + bool isValid() const { return IsValid; } + + /// Apply - Set the value of each of the fields. + /// + virtual void Apply(int &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isa(C); + } + virtual void Apply(unsigned &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isa(C); + } + virtual void Apply(bool &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isa(C); + } + virtual void Apply(std::string &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isStringValue(C); + } + virtual void Apply(DebugInfoDesc *&Field) { + // FIXME - Prepare the correct descriptor. + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isGlobalValue(C); + } + virtual void Apply(GlobalVariable *&Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isGlobalValue(C); + } +}; + +//===----------------------------------------------------------------------===// + +/// DebugVersionFromGlobal - Returns the version number from a compile unit +/// GlobalVariable. +unsigned CompileUnitDesc::DebugVersionFromGlobal(GlobalVariable *GV, + bool Checking) { + if (Checking && !isUIntOperand(GV, 1)) return DIInvalid; + ConstantStruct *CI = cast(GV->getInitializer()); + Constant *C = CI->getOperand(1); + return cast(C)->getValue(); +} + +/// ApplyToFields - Target the apply manager to the fields of the +/// CompileUnitDesc. +void CompileUnitDesc::ApplyToFields(DIApplyManager *Mgr) { + Mgr->Apply(DebugVersion); + Mgr->Apply(Language); + Mgr->Apply(FileName); + Mgr->Apply(Directory); + Mgr->Apply(Producer); + Mgr->Apply(TransUnit); } -/// getTag - Return the compile unit's tag number. Currently should be -/// DW_TAG_variable. -unsigned CompileUnitWrapper::getTag() const { - return cast(IC->getOperand(Tag_op))->getValue(); +/// TypeString - Return a string used to compose globalnames and labels. +/// +const char *CompileUnitDesc::TypeString() const { + return "compile_unit"; } -/// 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 { - return cast(IC->getOperand(Version_op))->getValue() == 0; +#ifndef NDEBUG +void CompileUnitDesc::dump() { + std::cerr << TypeString() << " " + << "Tag(" << getTag() << "), " + << "Language(" << Language << "), " + << "FileName(\"" << FileName << "\"), " + << "Directory(\"" << Directory << "\"), " + << "Producer(\"" << Producer << "\")\n"; } +#endif -/// getLanguage - Return the compile unit's language number (ex. DW_LANG_C89.) -/// -unsigned CompileUnitWrapper::getLanguage() const { - return cast(IC->getOperand(Language_op))->getValue(); +//===----------------------------------------------------------------------===// + +/// ApplyToFields - Target the apply manager to the fields of the +/// GlobalVariableDesc. +void GlobalVariableDesc::ApplyToFields(DIApplyManager *Mgr) { + Mgr->Apply(Context); + Mgr->Apply(Name); + Mgr->Apply(TransUnit); + Mgr->Apply(TyDesc); + Mgr->Apply(IsStatic); + Mgr->Apply(IsDefinition); + Mgr->Apply(Global); } -/// getFileName - Return the compile unit's file name. +/// TypeString - Return a string used to compose globalnames and labels. /// -const std::string CompileUnitWrapper::getFileName() const { - return getStringValue(IC->getOperand(FileName_op)); +const char *GlobalVariableDesc::TypeString() const { + return "global_variable"; } -/// getDirectory - Return the compile unit's file directory. -/// -const std::string CompileUnitWrapper::getDirectory() const { - return getStringValue(IC->getOperand(Directory_op)); +#ifndef NDEBUG +void GlobalVariableDesc::dump() { + std::cerr << TypeString() << " " + << "Tag(" << getTag() << "), " + << "Name(\"" << Name << "\"), " + << "Type(" << TyDesc << "), " + << "IsStatic(" << (IsStatic ? "true" : "false") << "), " + << "IsDefinition(" << (IsDefinition ? "true" : "false") << "), " + << "Global(" << Global << ")\n"; } +#endif + +//===----------------------------------------------------------------------===// + +/// ApplyToFields - Target the apply manager to the fields of the +/// SubprogramDesc. +void SubprogramDesc::ApplyToFields(DIApplyManager *Mgr) { + Mgr->Apply(Context); + Mgr->Apply(Name); + Mgr->Apply(TransUnit); + Mgr->Apply(TyDesc); + Mgr->Apply(IsStatic); + Mgr->Apply(IsDefinition); -/// getProducer - Return the compile unit's generator name. + // FIXME - Temp variable until restructured. + GlobalVariable *Tmp; + Mgr->Apply(Tmp); +} + +/// TypeString - Return a string used to compose globalnames and labels. /// -const std::string CompileUnitWrapper::getProducer() const { - return getStringValue(IC->getOperand(Producer_op)); +const char *SubprogramDesc::TypeString() const { + return "subprogram"; } +#ifndef NDEBUG +void SubprogramDesc::dump() { + std::cerr << TypeString() << " " + << "Tag(" << getTag() << "), " + << "Name(\"" << Name << "\"), " + << "Type(" << TyDesc << "), " + << "IsStatic(" << (IsStatic ? "true" : "false") << "), " + << "IsDefinition(" << (IsDefinition ? "true" : "false") << ")\n"; +} +#endif + //===----------------------------------------------------------------------===// -GlobalWrapper::GlobalWrapper(GlobalVariable *G) -: DebugInfoWrapper(G) -{ - // FIXME - should probably ease up on the number of operands (version.) - assert(IC->getNumOperands() == N_op && - "Global does not have correct number of operands"); +DebugInfoDesc *DIDeserializer::Deserialize(Value *V) { + return Deserialize(cast(V)); } +DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) { + // Check to see if it has been already deserialized. + DebugInfoDesc *&Slot = GlobalDescs[GV]; + if (Slot) return Slot; -/// getTag - Return the global's tag number. Currently should be -/// DW_TAG_variable or DW_TAG_subprogram. -unsigned GlobalWrapper::getTag() const { - return cast(IC->getOperand(Tag_op))->getValue(); + // Get the Tag from the global. + unsigned Tag = DebugInfoDesc::TagFromGlobal(GV); + + // Get the debug version if a compile unit. + if (Tag == DI_TAG_compile_unit) { + DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV); + } + + // Create an empty instance of the correct sort. + Slot = DebugInfoDesc::DescFactory(Tag); + assert(Slot && "Unknown Tag"); + + // Deserialize the fields. + DIDeserializeAppMgr DRAM(*this, GV); + DRAM.ApplyToFields(Slot); + + return Slot; } -/// getContext - Return the "lldb.compile_unit" context global. +//===----------------------------------------------------------------------===// + +/// getStrPtrType - Return a "sbyte *" type. /// -GlobalVariable *GlobalWrapper::getContext() const { - return getGlobalValue(IC->getOperand(Context_op)); +const PointerType *DISerializer::getStrPtrType() { + // If not already defined. + if (!StrPtrTy) { + // Construct the pointer to signed bytes. + StrPtrTy = PointerType::get(Type::SByteTy); + } + + return StrPtrTy; } -/// getName - Return the name of the global. +/// getEmptyStructPtrType - Return a "{ }*" type. /// -const std::string GlobalWrapper::getName() const { - return getStringValue(IC->getOperand(Name_op)); +const PointerType *DISerializer::getEmptyStructPtrType() { + // If not already defined. + if (!EmptyStructPtrTy) { + // Construct the empty structure type. + const StructType *EmptyStructTy = + StructType::get(std::vector()); + // Construct the pointer to empty structure type. + EmptyStructPtrTy = PointerType::get(EmptyStructTy); + } + + return EmptyStructPtrTy; } -/// getType - Return the type of the global. +/// getTagType - Return the type describing the specified descriptor (via tag.) /// -const GlobalVariable *GlobalWrapper::getType() const { - return getGlobalValue(IC->getOperand(Type_op)); +const StructType *DISerializer::getTagType(DebugInfoDesc *DD) { + // Attempt to get the previously defined type. + StructType *&Ty = TagTypes[DD->getTag()]; + + // If not already defined. + if (!Ty) { + // Get descriptor type name. + const char *TS = DD->TypeString(); + + // Set up fields vector. + std::vector Fields; + // Add tag field. + Fields.push_back(Type::UIntTy); + // Get types of remaining fields. + DIGetTypesAppMgr GTAM(*this, Fields); + GTAM.ApplyToFields(DD); + + // Construct structured type. + Ty = StructType::get(Fields); + + // Construct a name for the type. + const std::string Name = std::string("lldb.") + DD->TypeString() + ".type"; + + // Register type name with module. + M->addTypeName(Name, Ty); + } + + return Ty; } -/// isStatic - Return true if the global is static. +/// getString - Construct the string as constant string global. /// -bool GlobalWrapper::isStatic() const { - return cast(IC->getOperand(Static_op))->getValue(); +GlobalVariable *DISerializer::getString(const std::string &String) { + // Check string cache for previous edition. + GlobalVariable *&Slot = StringCache[String]; + // return GlobalVariable if previously defined. + if (Slot) return Slot; + // Construct strings as an llvm constant. + Constant *ConstStr = ConstantArray::get(String); + // Otherwise create and return a new string global. + return Slot = new GlobalVariable(ConstStr->getType(), true, + GlobalVariable::InternalLinkage, + ConstStr, "str", M); } -/// isDefinition - Return true if the global is a definition. -/// -bool GlobalWrapper::isDefinition() const { - return dyn_cast(IC->getOperand(Definition_op))->getValue(); +/// Serialize - Recursively cast the specified descriptor into a GlobalVariable +/// so that it can be serialized to a .bc or .ll file. +GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) { + // Check if the DebugInfoDesc is already in the map. + GlobalVariable *&Slot = DescGlobals[DD]; + + // See if DebugInfoDesc exists, if so return prior GlobalVariable. + if (Slot) return Slot; + + // Get DebugInfoDesc type Tag. + unsigned Tag = DD->getTag(); + + // Construct name. + const std::string Name = std::string("lldb.") + + DD->TypeString(); + + // Get the type associated with the Tag. + const StructType *Ty = getTagType(DD); + + // Create the GlobalVariable early to prevent infinite recursion. + GlobalVariable *GV = new GlobalVariable(Ty, true, + GlobalValue::InternalLinkage, + NULL, Name, M); + + // Insert new GlobalVariable in DescGlobals map. + Slot = GV; + + // Set up elements vector + std::vector Elements; + // Add Tag value. + Elements.push_back(ConstantUInt::get(Type::UIntTy, Tag)); + // Add remaining fields. + DISerializeAppMgr SRAM(*this, Elements); + SRAM.ApplyToFields(DD); + + // Set the globals initializer. + GV->setInitializer(ConstantStruct::get(Ty, Elements)); + + return GV; } -/// getGlobalVariable - Return the global variable (tag == DW_TAG_variable.) -/// -GlobalVariable *GlobalWrapper::getGlobalVariable() const { - return getGlobalValue(IC->getOperand(GlobalVariable_op)); +//===----------------------------------------------------------------------===// + +/// markVisited - Return true if the GlobalVariable hase been "seen" before. +/// Mark visited otherwise. +bool DIVerifier::markVisited(GlobalVariable *GV) { + // Check if the GlobalVariable is already in the Visited set. + std::set::iterator VI = Visited.lower_bound(GV); + + // See if GlobalVariable exists. + bool Exists = VI != Visited.end() && *VI == GV; + + // Insert in set. + if (!Exists) Visited.insert(VI, GV); + + return Exists; +} + +/// Verify - Return true if the GlobalVariable appears to be a valid +/// serialization of a DebugInfoDesc. +bool DIVerifier::Verify(GlobalVariable *GV) { + // Check if seen before. + if (markVisited(GV)) return true; + + // Get the Tag + unsigned Tag = DebugInfoDesc::TagFromGlobal(GV, true); + if (Tag == DIInvalid) return false; + + // If a compile unit we need the debug version. + if (Tag == DI_TAG_compile_unit) { + DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV, true); + if (DebugVersion == DIInvalid) return false; + } + + // Construct an empty DebugInfoDesc. + DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag); + if (!DD) return false; + + // Get the initializer constant. + ConstantStruct *CI = cast(GV->getInitializer()); + + // Get the operand count. + unsigned N = CI->getNumOperands(); + + // Get the field count. + unsigned &Slot = Counts[Tag]; + if (!Slot) { + // Check the operand count to the field count + DICountAppMgr CTAM; + CTAM.ApplyToFields(DD); + Slot = CTAM.getCount(); + } + + // Field count must equal operand count. + if (Slot != N) { + delete DD; + return false; + } + + // Check each field for valid type. + DIVerifyAppMgr VRAM(*this, GV); + VRAM.ApplyToFields(DD); + + // Release empty DebugInfoDesc. + delete DD; + + // Return result of field tests. + return VRAM.isValid(); } //===----------------------------------------------------------------------===// MachineDebugInfo::MachineDebugInfo() -: CompileUnits() +: SR() +, DR() +, VR() +, CompileUnits() , Directories() , SourceFiles() , Lines() @@ -248,54 +766,56 @@ bool MachineDebugInfo::doFinalization() { /// AnalyzeModule - Scan the module for global debug information. /// void MachineDebugInfo::AnalyzeModule(Module &M) { + SR.setModule(&M); + DR.setModule(&M); SetupCompileUnits(M); } /// SetupCompileUnits - Set up the unique vector of compile units. /// void MachineDebugInfo::SetupCompileUnits(Module &M) { + SR.setModule(&M); + DR.setModule(&M); // Get vector of all debug compile units. std::vector 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); + // Add compile unit to result. + CompileUnits.insert( + static_cast(DR.Deserialize(Globals[i]))); } - - // If there any bad compile units then suppress debug information - if (CompileUnits.size() != Globals.size()) CompileUnits.reset(); } /// getCompileUnits - Return a vector of debug compile units. /// -const UniqueVector MachineDebugInfo::getCompileUnits()const{ +const UniqueVector MachineDebugInfo::getCompileUnits()const{ return CompileUnits; } -/// getGlobalVariables - Return a vector of debug global variables. +/// getGlobalVariables - Return a vector of debug GlobalVariables. /// -std::vector MachineDebugInfo::getGlobalVariables(Module &M) { +std::vector +MachineDebugInfo::getGlobalVariables(Module &M) { + SR.setModule(&M); + DR.setModule(&M); // Get vector of all debug global objects. std::vector Globals = getGlobalVariablesUsing(M, "llvm.dbg.globals"); - // Accumulation of global variables. - std::vector GlobalVariables; + // Accumulation of GlobalVariables. + std::vector 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); + GlobalVariable *GV = Globals[i]; + if (DebugInfoDesc::TagFromGlobal(GV, true) == DI_TAG_global_variable) { + GlobalVariableDesc *GVD = + static_cast(DR.Deserialize(GV)); + GlobalVariables.push_back(GVD); + } } -#endif return GlobalVariables; } -- 2.34.1