X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FMachineDebugInfo.cpp;h=a3013e9608ec7ad446290e52cbcb9ec1e02ac78c;hb=f8a01a966120a041fe96300271573a8bf5a3e668;hp=98d07d3e2f889796794918d954505d5fa9d56742;hpb=f8913f19ae83927521103b9c84189c8d716e85ad;p=oota-llvm.git diff --git a/lib/CodeGen/MachineDebugInfo.cpp b/lib/CodeGen/MachineDebugInfo.cpp index 98d07d3e2f8..a3013e9608e 100644 --- a/lib/CodeGen/MachineDebugInfo.cpp +++ b/lib/CodeGen/MachineDebugInfo.cpp @@ -10,6 +10,7 @@ #include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/Constants.h" +#include "llvm/CodeGen/MachineLocation.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" @@ -20,6 +21,7 @@ #include using namespace llvm; +using namespace llvm::dwarf; // Handle the Pass registration stuff necessary to use TargetData's. namespace { @@ -52,7 +54,7 @@ getGlobalVariablesUsing(Module &M, const std::string &RootName) { std::vector FieldTypes; FieldTypes.push_back(Type::UIntTy); - FieldTypes.push_back(PointerType::get(Type::SByteTy)); + FieldTypes.push_back(Type::UIntTy); // Get the GlobalVariable root. GlobalVariable *UseRoot = M.getGlobalVariable(RootName, @@ -66,45 +68,6 @@ getGlobalVariablesUsing(Module &M, const std::string &RootName) { 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. -/// -static const std::string getStringValue(Value *V, unsigned Offset = 0) { - if (GlobalVariable *GV = dyn_cast(V)) { - if (GV->hasInitializer() && isa(GV->getInitializer())) { - ConstantArray *Init = cast(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(V)) { - if (GlobalValue *GV = dyn_cast(C)) - return getStringValue(GV, Offset); - else if (ConstantExpr *CE = dyn_cast(C)) { - if (CE->getOpcode() == Instruction::GetElementPtr) { - // Turn a gep into the specified offset. - if (CE->getNumOperands() == 3 && - cast(CE->getOperand(1))->isNullValue() && - isa(CE->getOperand(2))) { - return getStringValue(CE->getOperand(0), - Offset+cast(CE->getOperand(2))->getRawValue()); - } - } - } - } - return ""; -} - /// isStringValue - Return true if the given value can be coerced to a string. /// static bool isStringValue(Value *V) { @@ -249,7 +212,7 @@ public: } virtual void Apply(std::string &Field) { Constant *C = CI->getOperand(I++); - Field = getStringValue(C); + Field = C->getStringValue(); } virtual void Apply(DebugInfoDesc *&Field) { Constant *C = CI->getOperand(I++); @@ -262,12 +225,15 @@ public: virtual void Apply(std::vector &Field) { Constant *C = CI->getOperand(I++); GlobalVariable *GV = getGlobalVariable(C); - ConstantArray *CA = cast(GV->getInitializer()); Field.resize(0); - for (unsigned i = 0, N = CA->getNumOperands(); i < N; ++i) { - GlobalVariable *GVE = getGlobalVariable(CA->getOperand(i)); - DebugInfoDesc *DE = DR.Deserialize(GVE); - Field.push_back(DE); + // Have to be able to deal with the empty array case (zero initializer) + if (!GV->hasInitializer()) return; + if (ConstantArray *CA = dyn_cast(GV->getInitializer())) { + for (unsigned i = 0, N = CA->getNumOperands(); i < N; ++i) { + GlobalVariable *GVE = getGlobalVariable(CA->getOperand(i)); + DebugInfoDesc *DE = DR.Deserialize(GVE); + Field.push_back(DE); + } } } }; @@ -296,21 +262,21 @@ public: Elements.push_back(ConstantUInt::get(Type::UIntTy, Field)); } virtual void Apply(int64_t &Field) { - Elements.push_back(ConstantSInt::get(Type::IntTy, Field)); + Elements.push_back(ConstantSInt::get(Type::LongTy, Field)); } virtual void Apply(uint64_t &Field) { - Elements.push_back(ConstantUInt::get(Type::UIntTy, Field)); + Elements.push_back(ConstantUInt::get(Type::ULongTy, Field)); } virtual void Apply(bool &Field) { Elements.push_back(ConstantBool::get(Field)); } virtual void Apply(std::string &Field) { - Elements.push_back(SR.getString(Field)); + Elements.push_back(SR.getString(Field)); } virtual void Apply(DebugInfoDesc *&Field) { GlobalVariable *GV = NULL; - // If non-NULL the convert to global. + // If non-NULL then convert to global. if (Field) GV = SR.Serialize(Field); // FIXME - At some point should use specific type. @@ -349,6 +315,7 @@ public: GlobalValue::InternalLinkage, CA, "llvm.dbg.array", SR.getModule()); + CAGV->setSection("llvm.metadata"); Constant *CAE = ConstantExpr::getCast(CAGV, EmptyTy); Elements.push_back(CAE); } @@ -378,10 +345,10 @@ public: Fields.push_back(Type::UIntTy); } virtual void Apply(int64_t &Field) { - Fields.push_back(Type::IntTy); + Fields.push_back(Type::LongTy); } virtual void Apply(uint64_t &Field) { - Fields.push_back(Type::UIntTy); + Fields.push_back(Type::ULongTy); } virtual void Apply(bool &Field) { Fields.push_back(Type::BoolTy); @@ -451,7 +418,7 @@ public: } virtual void Apply(std::string &Field) { Constant *C = CI->getOperand(I++); - IsValid = IsValid && isStringValue(C); + IsValid = IsValid && (!C || isStringValue(C)); } virtual void Apply(DebugInfoDesc *&Field) { // FIXME - Prepare the correct descriptor. @@ -488,33 +455,48 @@ public: //===----------------------------------------------------------------------===// -/// TagFromGlobal - Returns the Tag number from a debug info descriptor -/// GlobalVariable. +/// TagFromGlobal - Returns the tag number from a debug info descriptor +/// GlobalVariable. Return DIIValid if operand is not an unsigned int. unsigned DebugInfoDesc::TagFromGlobal(GlobalVariable *GV) { ConstantUInt *C = getUIntOperand(GV, 0); - return C ? (unsigned)C->getValue() : (unsigned)DIInvalid; + return C ? ((unsigned)C->getValue() & tag_mask) : (unsigned)DW_TAG_invalid; +} + +/// VersionFromGlobal - Returns the version number from a debug info +/// descriptor GlobalVariable. Return DIIValid if operand is not an unsigned +/// int. +unsigned DebugInfoDesc::VersionFromGlobal(GlobalVariable *GV) { + ConstantUInt *C = getUIntOperand(GV, 0); + return C ? ((unsigned)C->getValue() >> version_shift) : + (unsigned)DW_TAG_invalid; } /// 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_anchor: return new AnchorDesc(); - case DI_TAG_compile_unit: return new CompileUnitDesc(); - case DI_TAG_global_variable: return new GlobalVariableDesc(); - case DI_TAG_subprogram: return new SubprogramDesc(); - case DI_TAG_basictype: return new BasicTypeDesc(); - case DI_TAG_typedef: - case DI_TAG_pointer: - case DI_TAG_reference: - case DI_TAG_const: - case DI_TAG_volatile: - case DI_TAG_restrict: return new DerivedTypeDesc(Tag); - case DI_TAG_array: - case DI_TAG_struct: - case DI_TAG_union: - case DI_TAG_enum: return new CompositeTypeDesc(Tag); - case DI_TAG_subrange: return new SubrangeDesc(); + case DW_TAG_anchor: return new AnchorDesc(); + case DW_TAG_compile_unit: return new CompileUnitDesc(); + case DW_TAG_variable: return new GlobalVariableDesc(); + case DW_TAG_subprogram: return new SubprogramDesc(); + case DW_TAG_lexical_block: return new BlockDesc(); + case DW_TAG_base_type: return new BasicTypeDesc(); + case DW_TAG_typedef: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_const_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_member: return new DerivedTypeDesc(Tag); + case DW_TAG_array_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: return new CompositeTypeDesc(Tag); + case DW_TAG_subrange_type: return new SubrangeDesc(); + case DW_TAG_enumerator: return new EnumeratorDesc(); + case DW_TAG_return_variable: + case DW_TAG_arg_variable: + case DW_TAG_auto_variable: return new VariableDesc(Tag); default: break; } return NULL; @@ -534,6 +516,20 @@ void DebugInfoDesc::ApplyToFields(DIVisitor *Visitor) { //===----------------------------------------------------------------------===// +AnchorDesc::AnchorDesc() +: DebugInfoDesc(DW_TAG_anchor) +, AnchorTag(0) +{} +AnchorDesc::AnchorDesc(AnchoredDesc *D) +: DebugInfoDesc(DW_TAG_anchor) +, AnchorTag(D->getTag()) +{} + +// Implement isa/cast/dyncast. +bool AnchorDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_anchor; +} + /// getLinkage - get linkage appropriate for this type of descriptor. /// GlobalValue::LinkageTypes AnchorDesc::getLinkage() const { @@ -545,13 +541,26 @@ GlobalValue::LinkageTypes AnchorDesc::getLinkage() const { void AnchorDesc::ApplyToFields(DIVisitor *Visitor) { DebugInfoDesc::ApplyToFields(Visitor); - Visitor->Apply(Name); + Visitor->Apply(AnchorTag); } -/// getDescString - Return a string used to compose global names and labels. -/// +/// getDescString - Return a string used to compose global names and labels. A +/// A global variable name needs to be defined for each debug descriptor that is +/// anchored. NOTE: that each global variable named here also needs to be added +/// to the list of names left external in the internalizer. +/// ExternalNames.insert("llvm.dbg.compile_units"); +/// ExternalNames.insert("llvm.dbg.global_variables"); +/// ExternalNames.insert("llvm.dbg.subprograms"); const char *AnchorDesc::getDescString() const { - return Name.c_str(); + switch (AnchorTag) { + case DW_TAG_compile_unit: return CompileUnitDesc::AnchorString; + case DW_TAG_variable: return GlobalVariableDesc::AnchorString; + case DW_TAG_subprogram: return SubprogramDesc::AnchorString; + default: break; + } + + assert(0 && "Tag does not have a case for anchor string"); + return ""; } /// getTypeString - Return a string used to label this descriptors type. @@ -563,8 +572,9 @@ const char *AnchorDesc::getTypeString() const { #ifndef NDEBUG void AnchorDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " - << "Name(" << Name << ")\n"; + << "AnchorTag(" << AnchorTag << ")\n"; } #endif @@ -580,33 +590,31 @@ AnchoredDesc::AnchoredDesc(unsigned T) void AnchoredDesc::ApplyToFields(DIVisitor *Visitor) { DebugInfoDesc::ApplyToFields(Visitor); - Visitor->Apply((DebugInfoDesc *&)Anchor); + DebugInfoDesc *Tmp = Anchor; + Visitor->Apply(Tmp); + Anchor = (AnchorDesc*)Tmp; } //===----------------------------------------------------------------------===// CompileUnitDesc::CompileUnitDesc() -: AnchoredDesc(DI_TAG_compile_unit) -, DebugVersion(LLVMDebugVersion) +: AnchoredDesc(DW_TAG_compile_unit) , Language(0) , FileName("") , Directory("") , Producer("") {} -/// DebugVersionFromGlobal - Returns the version number from a compile unit -/// GlobalVariable. -unsigned CompileUnitDesc::DebugVersionFromGlobal(GlobalVariable *GV) { - ConstantUInt *C = getUIntOperand(GV, 2); - return C ? (unsigned)C->getValue() : (unsigned)DIInvalid; +// Implement isa/cast/dyncast. +bool CompileUnitDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_compile_unit; } - + /// ApplyToFields - Target the visitor to the fields of the CompileUnitDesc. /// void CompileUnitDesc::ApplyToFields(DIVisitor *Visitor) { AnchoredDesc::ApplyToFields(Visitor); - Visitor->Apply(DebugVersion); Visitor->Apply(Language); Visitor->Apply(FileName); Visitor->Apply(Directory); @@ -627,16 +635,17 @@ const char *CompileUnitDesc::getTypeString() const { /// getAnchorString - Return a string used to label this descriptor's anchor. /// +const char *CompileUnitDesc::AnchorString = "llvm.dbg.compile_units"; const char *CompileUnitDesc::getAnchorString() const { - return "llvm.dbg.compile_units"; + return AnchorString; } #ifndef NDEBUG void CompileUnitDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " - << "DebugVersion(" << DebugVersion << "), " << "Language(" << Language << "), " << "FileName(\"" << FileName << "\"), " << "Directory(\"" << Directory << "\"), " @@ -651,7 +660,10 @@ TypeDesc::TypeDesc(unsigned T) , Context(NULL) , Name("") , File(NULL) +, Line(0) , Size(0) +, Align(0) +, Offset(0) {} /// ApplyToFields - Target the visitor to the fields of the TypeDesc. @@ -661,9 +673,13 @@ void TypeDesc::ApplyToFields(DIVisitor *Visitor) { Visitor->Apply(Context); Visitor->Apply(Name); - Visitor->Apply((DebugInfoDesc *&)File); + DebugInfoDesc* Tmp = File; + Visitor->Apply(Tmp); + File = (CompileUnitDesc*)Tmp; Visitor->Apply(Line); Visitor->Apply(Size); + Visitor->Apply(Align); + Visitor->Apply(Offset); } /// getDescString - Return a string used to compose global names and labels. @@ -681,22 +697,30 @@ const char *TypeDesc::getTypeString() const { #ifndef NDEBUG void TypeDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << Context << "), " << "Name(\"" << Name << "\"), " << "File(" << File << "), " << "Line(" << Line << "), " - << "Size(" << Size << ")\n"; + << "Size(" << Size << "), " + << "Align(" << Align << "), " + << "Offset(" << Offset << ")\n"; } #endif //===----------------------------------------------------------------------===// BasicTypeDesc::BasicTypeDesc() -: TypeDesc(DI_TAG_basictype) +: TypeDesc(DW_TAG_base_type) , Encoding(0) {} +// Implement isa/cast/dyncast. +bool BasicTypeDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_base_type; +} + /// ApplyToFields - Target the visitor to the fields of the BasicTypeDesc. /// void BasicTypeDesc::ApplyToFields(DIVisitor *Visitor) { @@ -720,6 +744,7 @@ const char *BasicTypeDesc::getTypeString() const { #ifndef NDEBUG void BasicTypeDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " @@ -735,12 +760,31 @@ DerivedTypeDesc::DerivedTypeDesc(unsigned T) , FromType(NULL) {} +// Implement isa/cast/dyncast. +bool DerivedTypeDesc::classof(const DebugInfoDesc *D) { + unsigned T = D->getTag(); + switch (T) { + case DW_TAG_typedef: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_const_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_member: + return true; + default: break; + } + return false; +} + /// ApplyToFields - Target the visitor to the fields of the DerivedTypeDesc. /// void DerivedTypeDesc::ApplyToFields(DIVisitor *Visitor) { TypeDesc::ApplyToFields(Visitor); - Visitor->Apply((DebugInfoDesc *&)FromType); + DebugInfoDesc* Tmp = FromType; + Visitor->Apply(Tmp); + FromType = (TypeDesc*)Tmp; } /// getDescString - Return a string used to compose global names and labels. @@ -758,6 +802,7 @@ const char *DerivedTypeDesc::getTypeString() const { #ifndef NDEBUG void DerivedTypeDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " @@ -772,14 +817,30 @@ void DerivedTypeDesc::dump() { CompositeTypeDesc::CompositeTypeDesc(unsigned T) : DerivedTypeDesc(T) +, IsVector(false) , Elements() {} +// Implement isa/cast/dyncast. +bool CompositeTypeDesc::classof(const DebugInfoDesc *D) { + unsigned T = D->getTag(); + switch (T) { + case DW_TAG_array_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + return true; + default: break; + } + return false; +} + /// ApplyToFields - Target the visitor to the fields of the CompositeTypeDesc. /// void CompositeTypeDesc::ApplyToFields(DIVisitor *Visitor) { DerivedTypeDesc::ApplyToFields(Visitor); + Visitor->Apply(IsVector); Visitor->Apply(Elements); } @@ -798,6 +859,7 @@ const char *CompositeTypeDesc::getTypeString() const { #ifndef NDEBUG void CompositeTypeDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " @@ -812,11 +874,16 @@ void CompositeTypeDesc::dump() { //===----------------------------------------------------------------------===// SubrangeDesc::SubrangeDesc() -: DebugInfoDesc(DI_TAG_subrange) +: DebugInfoDesc(DW_TAG_subrange_type) , Lo(0) , Hi(0) {} +// Implement isa/cast/dyncast. +bool SubrangeDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_subrange_type; +} + /// ApplyToFields - Target the visitor to the fields of the SubrangeDesc. /// void SubrangeDesc::ApplyToFields(DIVisitor *Visitor) { @@ -841,6 +908,7 @@ const char *SubrangeDesc::getTypeString() const { #ifndef NDEBUG void SubrangeDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Lo(" << Lo << "), " << "Hi(" << Hi << ")\n"; @@ -849,10 +917,121 @@ void SubrangeDesc::dump() { //===----------------------------------------------------------------------===// +EnumeratorDesc::EnumeratorDesc() +: DebugInfoDesc(DW_TAG_enumerator) +, Name("") +, Value(0) +{} + +// Implement isa/cast/dyncast. +bool EnumeratorDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_enumerator; +} + +/// ApplyToFields - Target the visitor to the fields of the EnumeratorDesc. +/// +void EnumeratorDesc::ApplyToFields(DIVisitor *Visitor) { + DebugInfoDesc::ApplyToFields(Visitor); + + Visitor->Apply(Name); + Visitor->Apply(Value); +} + +/// getDescString - Return a string used to compose global names and labels. +/// +const char *EnumeratorDesc::getDescString() const { + return "llvm.dbg.enumerator"; +} + +/// getTypeString - Return a string used to label this descriptor's type. +/// +const char *EnumeratorDesc::getTypeString() const { + return "llvm.dbg.enumerator.type"; +} + +#ifndef NDEBUG +void EnumeratorDesc::dump() { + std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " + << "Tag(" << getTag() << "), " + << "Name(" << Name << "), " + << "Value(" << Value << ")\n"; +} +#endif + +//===----------------------------------------------------------------------===// + +VariableDesc::VariableDesc(unsigned T) +: DebugInfoDesc(T) +, Context(NULL) +, Name("") +, File(NULL) +, Line(0) +, TyDesc(0) +{} + +// Implement isa/cast/dyncast. +bool VariableDesc::classof(const DebugInfoDesc *D) { + unsigned T = D->getTag(); + switch (T) { + case DW_TAG_auto_variable: + case DW_TAG_arg_variable: + case DW_TAG_return_variable: + return true; + default: break; + } + return false; +} + +/// ApplyToFields - Target the visitor to the fields of the VariableDesc. +/// +void VariableDesc::ApplyToFields(DIVisitor *Visitor) { + DebugInfoDesc::ApplyToFields(Visitor); + + Visitor->Apply(Context); + Visitor->Apply(Name); + DebugInfoDesc* Tmp1 = File; + Visitor->Apply(Tmp1); + File = (CompileUnitDesc*)Tmp1; + Visitor->Apply(Line); + DebugInfoDesc* Tmp2 = TyDesc; + Visitor->Apply(Tmp2); + TyDesc = (TypeDesc*)Tmp2; +} + +/// getDescString - Return a string used to compose global names and labels. +/// +const char *VariableDesc::getDescString() const { + return "llvm.dbg.variable"; +} + +/// getTypeString - Return a string used to label this descriptor's type. +/// +const char *VariableDesc::getTypeString() const { + return "llvm.dbg.variable.type"; +} + +#ifndef NDEBUG +void VariableDesc::dump() { + std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " + << "Tag(" << getTag() << "), " + << "Context(" << Context << "), " + << "Name(\"" << Name << "\"), " + << "File(" << File << "), " + << "Line(" << Line << "), " + << "TyDesc(" << TyDesc << ")\n"; +} +#endif + +//===----------------------------------------------------------------------===// + GlobalDesc::GlobalDesc(unsigned T) : AnchoredDesc(T) , Context(0) , Name("") +, File(NULL) +, Line(0) , TyDesc(NULL) , IsStatic(false) , IsDefinition(false) @@ -865,7 +1044,13 @@ void GlobalDesc::ApplyToFields(DIVisitor *Visitor) { Visitor->Apply(Context); Visitor->Apply(Name); - Visitor->Apply((DebugInfoDesc *&)TyDesc); + DebugInfoDesc* Tmp1 = File; + Visitor->Apply(Tmp1); + File = (CompileUnitDesc*)Tmp1; + Visitor->Apply(Line); + DebugInfoDesc* Tmp2 = TyDesc; + Visitor->Apply(Tmp2); + TyDesc = (TypeDesc*)Tmp2; Visitor->Apply(IsStatic); Visitor->Apply(IsDefinition); } @@ -873,17 +1058,21 @@ void GlobalDesc::ApplyToFields(DIVisitor *Visitor) { //===----------------------------------------------------------------------===// GlobalVariableDesc::GlobalVariableDesc() -: GlobalDesc(DI_TAG_global_variable) +: GlobalDesc(DW_TAG_variable) , Global(NULL) {} +// Implement isa/cast/dyncast. +bool GlobalVariableDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_variable; +} + /// ApplyToFields - Target the visitor to the fields of the GlobalVariableDesc. /// void GlobalVariableDesc::ApplyToFields(DIVisitor *Visitor) { GlobalDesc::ApplyToFields(Visitor); Visitor->Apply(Global); - Visitor->Apply(Line); } /// getDescString - Return a string used to compose global names and labels. @@ -900,30 +1089,38 @@ const char *GlobalVariableDesc::getTypeString() const { /// getAnchorString - Return a string used to label this descriptor's anchor. /// +const char *GlobalVariableDesc::AnchorString = "llvm.dbg.global_variables"; const char *GlobalVariableDesc::getAnchorString() const { - return "llvm.dbg.global_variables"; + return AnchorString; } #ifndef NDEBUG void GlobalVariableDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " << "Name(\"" << getName() << "\"), " - << "Type(\"" << getTypeDesc() << "\"), " + << "File(" << getFile() << ")," + << "Line(" << getLine() << ")," + << "Type(\"" << getType() << "\"), " << "IsStatic(" << (isStatic() ? "true" : "false") << "), " << "IsDefinition(" << (isDefinition() ? "true" : "false") << "), " - << "Global(" << Global << "), " - << "Line(" << Line << ")\n"; + << "Global(" << Global << ")\n"; } #endif //===----------------------------------------------------------------------===// SubprogramDesc::SubprogramDesc() -: GlobalDesc(DI_TAG_subprogram) +: GlobalDesc(DW_TAG_subprogram) {} +// Implement isa/cast/dyncast. +bool SubprogramDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_subprogram; +} + /// ApplyToFields - Target the visitor to the fields of the /// SubprogramDesc. void SubprogramDesc::ApplyToFields(DIVisitor *Visitor) { @@ -944,17 +1141,21 @@ const char *SubprogramDesc::getTypeString() const { /// getAnchorString - Return a string used to label this descriptor's anchor. /// +const char *SubprogramDesc::AnchorString = "llvm.dbg.subprograms"; const char *SubprogramDesc::getAnchorString() const { - return "llvm.dbg.subprograms"; + return AnchorString; } #ifndef NDEBUG void SubprogramDesc::dump() { std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " << "Name(\"" << getName() << "\"), " - << "Type(\"" << getTypeDesc() << "\"), " + << "File(" << getFile() << ")," + << "Line(" << getLine() << ")," + << "Type(\"" << getType() << "\"), " << "IsStatic(" << (isStatic() ? "true" : "false") << "), " << "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n"; } @@ -962,6 +1163,47 @@ void SubprogramDesc::dump() { //===----------------------------------------------------------------------===// +BlockDesc::BlockDesc() +: DebugInfoDesc(DW_TAG_lexical_block) +, Context(NULL) +{} + +// Implement isa/cast/dyncast. +bool BlockDesc::classof(const DebugInfoDesc *D) { + return D->getTag() == DW_TAG_lexical_block; +} + +/// ApplyToFields - Target the visitor to the fields of the BlockDesc. +/// +void BlockDesc::ApplyToFields(DIVisitor *Visitor) { + DebugInfoDesc::ApplyToFields(Visitor); + + Visitor->Apply(Context); +} + +/// getDescString - Return a string used to compose global names and labels. +/// +const char *BlockDesc::getDescString() const { + return "llvm.dbg.block"; +} + +/// getTypeString - Return a string used to label this descriptors type. +/// +const char *BlockDesc::getTypeString() const { + return "llvm.dbg.block.type"; +} + +#ifndef NDEBUG +void BlockDesc::dump() { + std::cerr << getDescString() << " " + << "Version(" << getVersion() << "), " + << "Tag(" << getTag() << ")," + << "Context(" << Context << ")\n"; +} +#endif + +//===----------------------------------------------------------------------===// + DebugInfoDesc *DIDeserializer::Deserialize(Value *V) { return Deserialize(getGlobalVariable(V)); } @@ -976,18 +1218,15 @@ DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) { // 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. - DIDeserializeVisitor DRAM(*this, GV); - DRAM.ApplyToFields(Slot); + // If not a user defined descriptor. + if (Slot) { + // Deserialize the fields. + DIDeserializeVisitor DRAM(*this, GV); + DRAM.ApplyToFields(Slot); + } return Slot; } @@ -1050,16 +1289,22 @@ const StructType *DISerializer::getTagType(DebugInfoDesc *DD) { Constant *DISerializer::getString(const std::string &String) { // Check string cache for previous edition. Constant *&Slot = StringCache[String]; - // return Constant if previously defined. + // Return Constant if previously defined. if (Slot) return Slot; - // Construct string as an llvm constant. - Constant *ConstStr = ConstantArray::get(String); - // Otherwise create and return a new string global. - GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true, - GlobalVariable::InternalLinkage, - ConstStr, "str", M); - // Convert to generic string pointer. - Slot = ConstantExpr::getCast(StrGV, getStrPtrType()); + // If empty string then use a sbyte* null instead. + if (String.empty()) { + Slot = ConstantPointerNull::get(getStrPtrType()); + } else { + // Construct string as an llvm constant. + Constant *ConstStr = ConstantArray::get(String); + // Otherwise create and return a new string global. + GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true, + GlobalVariable::InternalLinkage, + ConstStr, "str", M); + StrGV->setSection("llvm.metadata"); + // Convert to generic string pointer. + Slot = ConstantExpr::getCast(StrGV, getStrPtrType()); + } return Slot; } @@ -1079,6 +1324,7 @@ GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) { // Create the GlobalVariable early to prevent infinite recursion. GlobalVariable *GV = new GlobalVariable(Ty, true, DD->getLinkage(), NULL, DD->getDescString(), M); + GV->setSection("llvm.metadata"); // Insert new GlobalVariable in DescGlobals map. Slot = GV; @@ -1097,43 +1343,42 @@ GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) { //===----------------------------------------------------------------------===// -/// 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(Value *V) { - return Verify(getGlobalVariable(V)); + return !V || Verify(getGlobalVariable(V)); } bool DIVerifier::Verify(GlobalVariable *GV) { - // Check if seen before. - if (markVisited(GV)) return true; + // NULLs are valid. + if (!GV) return true; + + // Check prior validity. + unsigned &ValiditySlot = Validity[GV]; + // If visited before then use old state. + if (ValiditySlot) return ValiditySlot == Valid; + + // Assume validity for the time being (recursion.) + ValiditySlot = Valid; + + // Make sure the global is internal or link once (anchor.) + if (GV->getLinkage() != GlobalValue::InternalLinkage && + GV->getLinkage() != GlobalValue::LinkOnceLinkage) { + ValiditySlot = Invalid; + return false; + } + // Get the Tag unsigned Tag = DebugInfoDesc::TagFromGlobal(GV); - if (Tag == DIInvalid) return false; - - // If a compile unit we need the debug version. - if (Tag == DI_TAG_compile_unit) { - DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV); - if (DebugVersion == DIInvalid) return false; - } + + // Check for user defined descriptors. + if (Tag == DW_TAG_invalid) return true; // Construct an empty DebugInfoDesc. DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag); - if (!DD) return false; + + // Allow for user defined descriptors. + if (!DD) return true; // Get the initializer constant. ConstantStruct *CI = cast(GV->getInitializer()); @@ -1142,17 +1387,18 @@ bool DIVerifier::Verify(GlobalVariable *GV) { unsigned N = CI->getNumOperands(); // Get the field count. - unsigned &Slot = Counts[Tag]; - if (!Slot) { + unsigned &CountSlot = Counts[Tag]; + if (!CountSlot) { // Check the operand count to the field count DICountVisitor CTAM; CTAM.ApplyToFields(DD); - Slot = CTAM.getCount(); + CountSlot = CTAM.getCount(); } - // Field count must equal operand count. - if (Slot != N) { + // Field count must be at most equal operand count. + if (CountSlot > N) { delete DD; + ValiditySlot = Invalid; return false; } @@ -1163,22 +1409,36 @@ bool DIVerifier::Verify(GlobalVariable *GV) { // Release empty DebugInfoDesc. delete DD; - // Return result of field tests. - return VRAM.isValid(); + // If fields are not valid. + if (!VRAM.isValid()) { + ValiditySlot = Invalid; + return false; + } + + return true; } //===----------------------------------------------------------------------===// +DebugScope::~DebugScope() { + for (unsigned i = 0, N = Scopes.size(); i < N; ++i) delete Scopes[i]; + for (unsigned j = 0, M = Variables.size(); j < M; ++j) delete Variables[j]; +} + +//===----------------------------------------------------------------------===// MachineDebugInfo::MachineDebugInfo() : DR() +, VR() , CompileUnits() , Directories() , SourceFiles() , Lines() -{ - -} +, LabelID(0) +, ScopeMap() +, RootScope(NULL) +, FrameMoves() +{} MachineDebugInfo::~MachineDebugInfo() { } @@ -1195,6 +1455,27 @@ bool MachineDebugInfo::doFinalization() { return false; } +/// BeginFunction - Begin gathering function debug information. +/// +void MachineDebugInfo::BeginFunction(MachineFunction *MF) { + // Coming soon. +} + +/// MachineDebugInfo::EndFunction - Discard function debug information. +/// +void MachineDebugInfo::EndFunction() { + // Clean up scope information. + if (RootScope) { + delete RootScope; + ScopeMap.clear(); + RootScope = NULL; + } + + // Clean up frame info. + for (unsigned i = 0, N = FrameMoves.size(); i < N; ++i) delete FrameMoves[i]; + FrameMoves.clear(); +} + /// getDescFor - Convert a Value to a debug information descriptor. /// // FIXME - use new Value type when available. @@ -1205,7 +1486,6 @@ DebugInfoDesc *MachineDebugInfo::getDescFor(Value *V) { /// Verify - Verify that a Value is debug information descriptor. /// bool MachineDebugInfo::Verify(Value *V) { - DIVerifier VR; return VR.Verify(V); } @@ -1238,3 +1518,84 @@ MachineDebugInfo::getGlobalVariablesUsing(Module &M, const std::string &RootName) { return ::getGlobalVariablesUsing(M, RootName); } + +/// RecordLabel - Records location information and associates it with a +/// debug label. Returns a unique label ID used to generate a label and +/// provide correspondence to the source line list. +unsigned MachineDebugInfo::RecordLabel(unsigned Line, unsigned Column, + unsigned Source) { + unsigned ID = NextLabelID(); + Lines.push_back(new SourceLineInfo(Line, Column, Source, ID)); + return ID; +} + +/// RecordSource - Register a source file with debug info. Returns an source +/// ID. +unsigned MachineDebugInfo::RecordSource(const std::string &Directory, + const std::string &Source) { + unsigned DirectoryID = Directories.insert(Directory); + return SourceFiles.insert(SourceFileInfo(DirectoryID, Source)); +} +unsigned MachineDebugInfo::RecordSource(const CompileUnitDesc *CompileUnit) { + return RecordSource(CompileUnit->getDirectory(), + CompileUnit->getFileName()); +} + +/// RecordRegionStart - Indicate the start of a region. +/// +unsigned MachineDebugInfo::RecordRegionStart(Value *V) { + // FIXME - need to be able to handle split scopes because of bb cloning. + DebugInfoDesc *ScopeDesc = DR.Deserialize(V); + DebugScope *Scope = getOrCreateScope(ScopeDesc); + unsigned ID = NextLabelID(); + if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID); + return ID; +} + +/// RecordRegionEnd - Indicate the end of a region. +/// +unsigned MachineDebugInfo::RecordRegionEnd(Value *V) { + // FIXME - need to be able to handle split scopes because of bb cloning. + DebugInfoDesc *ScopeDesc = DR.Deserialize(V); + DebugScope *Scope = getOrCreateScope(ScopeDesc); + unsigned ID = NextLabelID(); + Scope->setEndLabelID(ID); + return ID; +} + +/// RecordVariable - Indicate the declaration of a local variable. +/// +void MachineDebugInfo::RecordVariable(Value *V, unsigned FrameIndex) { + VariableDesc *VD = cast(DR.Deserialize(V)); + DebugScope *Scope = getOrCreateScope(VD->getContext()); + DebugVariable *DV = new DebugVariable(VD, FrameIndex); + Scope->AddVariable(DV); +} + +/// getOrCreateScope - Returns the scope associated with the given descriptor. +/// +DebugScope *MachineDebugInfo::getOrCreateScope(DebugInfoDesc *ScopeDesc) { + DebugScope *&Slot = ScopeMap[ScopeDesc]; + if (!Slot) { + // FIXME - breaks down when the context is an inlined function. + DebugInfoDesc *ParentDesc = NULL; + if (BlockDesc *Block = dyn_cast(ScopeDesc)) { + ParentDesc = Block->getContext(); + } + DebugScope *Parent = ParentDesc ? getOrCreateScope(ParentDesc) : NULL; + Slot = new DebugScope(Parent, ScopeDesc); + if (Parent) { + Parent->AddScope(Slot); + } else if (RootScope) { + // FIXME - Add inlined function scopes to the root so we can delete + // them later. Long term, handle inlined functions properly. + RootScope->AddScope(Slot); + } else { + // First function is top level function. + RootScope = Slot; + } + } + return Slot; +} + +