diff options
-rw-r--r-- | include/llvm/CodeGen/DwarfWriter.h | 4 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineDebugInfo.h | 427 | ||||
-rw-r--r-- | lib/CodeGen/DwarfWriter.cpp | 22 | ||||
-rw-r--r-- | 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 c98dbbce39..841a029d60 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 fe12802dcd..a04f778c16 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 <string> +#include <set> 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<GlobalVariable *, DebugInfoDesc *> 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<unsigned, StructType *> TagTypes; + // Types per Tag. Created lazily. + std::map<DebugInfoDesc *, GlobalVariable *> DescGlobals; + // Previously defined descriptors. + std::map<const std::string, GlobalVariable*> 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<GlobalVariable *> Visited; // Tracks visits during recursion. + std::map<unsigned, unsigned> 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<CompileUnitWrapper> CompileUnits; + UniqueVector<CompileUnitDesc *> CompileUnits; // Directories - Uniquing vector for directories. UniqueVector<std::string> Directories; @@ -300,11 +531,11 @@ public: /// getCompileUnits - Return a vector of debug compile units. /// - const UniqueVector<CompileUnitWrapper> getCompileUnits() const; + const UniqueVector<CompileUnitDesc *> getCompileUnits() const; - /// getGlobalVariables - Return a vector of debug global variables. + /// getGlobalVariables - Return a vector of debug GlobalVariables. /// - static std::vector<GlobalWrapper> getGlobalVariables(Module &M); + std::vector<GlobalVariableDesc *> getGlobalVariables(Module &M); }; // End class MachineDebugInfo diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index 4de5dcfc2a..f7bb0923bb 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<CompileUnitWrapper> CUW = DebugInfo->getCompileUnits(); + const UniqueVector<CompileUnitDesc *> 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<GlobalWrapper> GlobalVariables = DebugInfo->getGlobalVariables(M); + std::vector<GlobalVariableDesc *> 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 ab42886cb4..e3b24ab03b 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 <iostream> + 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<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. + // If the user is a GlobalVariable 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 @@ -41,13 +44,13 @@ getGlobalVariablesUsing(Value *V, std::vector<GlobalVariable*> &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<GlobalVariable*> getGlobalVariablesUsing(Module &M, const std::string &RootName) { - std::vector<GlobalVariable*> Result; // Global variables matching criteria. + std::vector<GlobalVariable*> Result; // GlobalVariables matching criteria. - // Get the global variable root. + // Get the GlobalVariable root. GlobalVariable *UseRoot = M.getGlobalVariable(RootName, StructType::get(std::vector<const Type*>())); @@ -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<GlobalVariable>(V)) { + if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) { + ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); + return Init->isString(); + } + } else if (Constant *C = dyn_cast<Constant>(V)) { + if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) + return isStringValue(GV); + else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + if (CE->getNumOperands() == 3 && + cast<Constant>(CE->getOperand(1))->isNullValue() && + isa<ConstantInt>(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<GlobalVariable>(V)) { return GV; } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { - return CE->getOpcode() == Instruction::Cast ? dyn_cast<GlobalVariable>(V) - : NULL; + if (CE->getOpcode() == Instruction::Cast) { + return dyn_cast<GlobalVariable>(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<GlobalVariable>(V) || isa<ConstantPointerNull>(V)) { + return true; + } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { + if (CE->getOpcode() == Instruction::Cast) { + return isa<GlobalVariable>(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<ConstantStruct>(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<ConstantUInt>(CI->getOperand(i)); +} + //===----------------------------------------------------------------------===// -DebugInfoWrapper::DebugInfoWrapper(GlobalVariable *G) -: GV(G) -, IC(dyn_cast<ConstantStruct>(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<ConstantStruct>(GV->getInitializer()); + Constant *C = CI->getOperand(0); + return cast<ConstantUInt>(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<ConstantStruct>(GV->getInitializer())) + {} + + /// Apply - Set the value of each of the fields. + /// + virtual void Apply(int &Field) { + Constant *C = CI->getOperand(I++); + Field = cast<ConstantSInt>(C)->getValue(); + } + virtual void Apply(unsigned &Field) { + Constant *C = CI->getOperand(I++); + Field = cast<ConstantUInt>(C)->getValue(); + } + virtual void Apply(bool &Field) { + Constant *C = CI->getOperand(I++); + Field = cast<ConstantBool>(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<Constant*> &Elements; // Element accumulator. + +public: + DISerializeAppMgr(DISerializer &S, std::vector<Constant*> &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<const Type*> &Fields; // Type accumulator. + +public: + DIGetTypesAppMgr(DISerializer &S, std::vector<const Type*> &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<ConstantStruct>(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<ConstantInt>(C); + } + virtual void Apply(unsigned &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isa<ConstantInt>(C); + } + virtual void Apply(bool &Field) { + Constant *C = CI->getOperand(I++); + IsValid = IsValid && isa<ConstantBoo |