//===-- llvm/CodeGen/MachineDebugInfo.cpp -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file was developed by James M. Laskey and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/Constants.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineLocation.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.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 "llvm/Support/Streams.h" using namespace llvm; using namespace llvm::dwarf; // Handle the Pass registration stuff necessary to use TargetData's. namespace { RegisterPass X("machinedebuginfo", "Debug Information"); } //===----------------------------------------------------------------------===// /// 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 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 getGlobalVariablesUsing(C, Result); } } } /// getGlobalVariablesUsing - Return all of the GlobalVariables that use the /// named GlobalVariable. static std::vector getGlobalVariablesUsing(Module &M, const std::string &RootName) { std::vector Result; // GlobalVariables matching criteria. std::vector FieldTypes; FieldTypes.push_back(Type::Int32Ty); FieldTypes.push_back(Type::Int32Ty); // Get the GlobalVariable root. GlobalVariable *UseRoot = M.getGlobalVariable(RootName, StructType::get(FieldTypes)); // If present and linkonce then scan for users. if (UseRoot && UseRoot->hasLinkOnceLinkage()) { getGlobalVariablesUsing(UseRoot, Result); } return Result; } /// 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; } /// getGlobalVariable - Return either a direct or cast Global value. /// static GlobalVariable *getGlobalVariable(Value *V) { if (GlobalVariable *GV = dyn_cast(V)) { return GV; } else if (ConstantExpr *CE = dyn_cast(V)) { if (CE->getOpcode() == Instruction::BitCast) { return dyn_cast(CE->getOperand(0)); } } return NULL; } /// isGlobalVariable - Return true if the given value can be coerced to a /// GlobalVariable. static bool isGlobalVariable(Value *V) { if (isa(V) || isa(V)) { return true; } else if (ConstantExpr *CE = dyn_cast(V)) { if (CE->getOpcode() == Instruction::BitCast) { return isa(CE->getOperand(0)); } } return false; } /// getUIntOperand - Return ith operand if it is an unsigned integer. /// static ConstantInt *getUIntOperand(GlobalVariable *GV, unsigned i) { // Make sure the GlobalVariable has an initializer. if (!GV->hasInitializer()) return NULL; // Get the initializer constant. ConstantStruct *CI = dyn_cast(GV->getInitializer()); if (!CI) return NULL; // Check if there is at least i + 1 operands. unsigned N = CI->getNumOperands(); if (i >= N) return NULL; // Check constant. return dyn_cast(CI->getOperand(i)); } //===----------------------------------------------------------------------===// /// ApplyToFields - Target the visitor to each field of the debug information /// descriptor. void DIVisitor::ApplyToFields(DebugInfoDesc *DD) { DD->ApplyToFields(this); } //===----------------------------------------------------------------------===// /// DICountVisitor - This DIVisitor counts all the fields in the supplied debug /// the supplied DebugInfoDesc. class DICountVisitor : public DIVisitor { private: unsigned Count; // Running count of fields. public: DICountVisitor() : DIVisitor(), Count(0) {} // 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(int64_t &Field) { ++Count; } virtual void Apply(uint64_t &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; } virtual void Apply(std::vector &Field) { ++Count; } }; //===----------------------------------------------------------------------===// /// DIDeserializeVisitor - This DIVisitor deserializes all the fields in the /// supplied DebugInfoDesc. class DIDeserializeVisitor : public DIVisitor { private: DIDeserializer &DR; // Active deserializer. unsigned I; // Current operand index. ConstantStruct *CI; // GlobalVariable constant initializer. public: DIDeserializeVisitor(DIDeserializer &D, GlobalVariable *GV) : DIVisitor() , DR(D) , I(0) , 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)->getSExtValue(); } virtual void Apply(unsigned &Field) { Constant *C = CI->getOperand(I++); Field = cast(C)->getZExtValue(); } virtual void Apply(int64_t &Field) { Constant *C = CI->getOperand(I++); Field = cast(C)->getSExtValue(); } virtual void Apply(uint64_t &Field) { Constant *C = CI->getOperand(I++); Field = cast(C)->getZExtValue(); } virtual void Apply(bool &Field) { Constant *C = CI->getOperand(I++); Field = cast(C)->getZExtValue(); } virtual void Apply(std::string &Field) { Constant *C = CI->getOperand(I++); Field = C->getStringValue(); } 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 = getGlobalVariable(C); } virtual void Apply(std::vector &Field) { Field.resize(0); Constant *C = CI->getOperand(I++); GlobalVariable *GV = getGlobalVariable(C); if (GV->hasInitializer()) { 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); } } else if (GV->getInitializer()->isNullValue()) { if (const ArrayType *T = dyn_cast(GV->getType()->getElementType())) { Field.resize(T->getNumElements()); } } } } }; //===----------------------------------------------------------------------===// /// DISerializeVisitor - This DIVisitor serializes all the fields in /// the supplied DebugInfoDesc. class DISerializeVisitor : public DIVisitor { private: DISerializer &SR; // Active serializer. std::vector &Elements; // Element accumulator. public: DISerializeVisitor(DISerializer &S, std::vector &E) : DIVisitor() , SR(S) , Elements(E) {} /// Apply - Set the value of each of the fields. /// virtual void Apply(int &Field) { Elements.push_back(ConstantInt::get(Type::Int32Ty, int32_t(Field))); } virtual void Apply(unsigned &Field) { Elements.push_back(ConstantInt::get(Type::Int32Ty, uint32_t(Field))); } virtual void Apply(int64_t &Field) { Elements.push_back(ConstantInt::get(Type::Int64Ty, int64_t(Field))); } virtual void Apply(uint64_t &Field) { Elements.push_back(ConstantInt::get(Type::Int64Ty, uint64_t(Field))); } virtual void Apply(bool &Field) { Elements.push_back(ConstantInt::get(Type::Int1Ty, Field)); } virtual void Apply(std::string &Field) { Elements.push_back(SR.getString(Field)); } virtual void Apply(DebugInfoDesc *&Field) { GlobalVariable *GV = NULL; // If non-NULL then 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::getBitCast(GV, EmptyTy)); } else { // Use NULL. Elements.push_back(ConstantPointerNull::get(EmptyTy)); } } virtual void Apply(GlobalVariable *&Field) { const PointerType *EmptyTy = SR.getEmptyStructPtrType(); if (Field) { Elements.push_back(ConstantExpr::getBitCast(Field, EmptyTy)); } else { Elements.push_back(ConstantPointerNull::get(EmptyTy)); } } virtual void Apply(std::vector &Field) { const PointerType *EmptyTy = SR.getEmptyStructPtrType(); unsigned N = Field.size(); ArrayType *AT = ArrayType::get(EmptyTy, N); std::vector ArrayElements; for (unsigned i = 0, N = Field.size(); i < N; ++i) { if (DebugInfoDesc *Element = Field[i]) { GlobalVariable *GVE = SR.Serialize(Element); Constant *CE = ConstantExpr::getBitCast(GVE, EmptyTy); ArrayElements.push_back(cast(CE)); } else { ArrayElements.push_back(ConstantPointerNull::get(EmptyTy)); } } Constant *CA = ConstantArray::get(AT, ArrayElements); GlobalVariable *CAGV = new GlobalVariable(AT, true, GlobalValue::InternalLinkage, CA, "llvm.dbg.array", SR.getModule()); CAGV->setSection("llvm.metadata"); Constant *CAE = ConstantExpr::getBitCast(CAGV, EmptyTy); Elements.push_back(CAE); } }; //===----------------------------------------------------------------------===// /// DIGetTypesVisitor - This DIVisitor gathers all the field types in /// the supplied DebugInfoDesc. class DIGetTypesVisitor : public DIVisitor { private: DISerializer &SR; // Active serializer. std::vector &Fields; // Type accumulator. public: DIGetTypesVisitor(DISerializer &S, std::vector &F) : DIVisitor() , SR(S) , Fields(F) {} /// Apply - Set the value of each of the fields. /// virtual void Apply(int &Field) { Fields.push_back(Type::Int32Ty); } virtual void Apply(unsigned &Field) { Fields.push_back(Type::Int32Ty); } virtual void Apply(int64_t &Field) { Fields.push_back(Type::Int64Ty); } virtual void Apply(uint64_t &Field) { Fields.push_back(Type::Int64Ty); } virtual void Apply(bool &Field) { Fields.push_back(Type::Int1Ty); } 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); } virtual void Apply(std::vector &Field) { const PointerType *EmptyTy = SR.getEmptyStructPtrType(); Fields.push_back(EmptyTy); } }; //===----------------------------------------------------------------------===// /// DIVerifyVisitor - This DIVisitor verifies all the field types against /// a constant initializer. class DIVerifyVisitor : public DIVisitor { private: DIVerifier &VR; // Active verifier. bool IsValid; // Validity status. unsigned I; // Current operand index. ConstantStruct *CI; // GlobalVariable constant initializer. public: DIVerifyVisitor(DIVerifier &V, GlobalVariable *GV) : DIVisitor() , VR(V) , IsValid(true) , I(0) , 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(int64_t &Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && isa(C); } virtual void Apply(uint64_t &Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && isa(C); } virtual void Apply(bool &Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && isa(C) && C->getType() == Type::Int1Ty; } virtual void Apply(std::string &Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && (!C || isStringValue(C) || C->isNullValue()); } virtual void Apply(DebugInfoDesc *&Field) { // FIXME - Prepare the correct descriptor. Constant *C = CI->getOperand(I++); IsValid = IsValid && isGlobalVariable(C); } virtual void Apply(GlobalVariable *&Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && isGlobalVariable(C); } virtual void Apply(std::vector &Field) { Constant *C = CI->getOperand(I++); IsValid = IsValid && isGlobalVariable(C); if (!IsValid) return; GlobalVariable *GV = getGlobalVariable(C); IsValid = IsValid && GV && GV->hasInitializer(); if (!IsValid) return; ConstantArray *CA = dyn_cast(GV->getInitializer()); IsValid = IsValid && CA; if (!IsValid) return; for (unsigned i = 0, N = CA->getNumOperands(); IsValid && i < N; ++i) { IsValid = IsValid && isGlobalVariable(CA->getOperand(i)); if (!IsValid) return; GlobalVariable *GVE = getGlobalVariable(CA->getOperand(i)); VR.Verify(GVE); } } }; //===----------------------------------------------------------------------===// /// 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) { ConstantInt *C = getUIntOperand(GV, 0); return C ? ((unsigned)C->getZExtValue() & ~LLVMDebugVersionMask) : (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) { ConstantInt *C = getUIntOperand(GV, 0); return C ? ((unsigned)C->getZExtValue() & LLVMDebugVersionMask) : (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 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: case DW_TAG_inheritance: return new DerivedTypeDesc(Tag); case DW_TAG_array_type: case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_enumeration_type: case DW_TAG_vector_type: case DW_TAG_subroutine_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; } /// getLinkage - get linkage appropriate for this type of descriptor. /// GlobalValue::LinkageTypes DebugInfoDesc::getLinkage() const { return GlobalValue::InternalLinkage; } /// ApplyToFields - Target the vistor to the fields of the descriptor. /// void DebugInfoDesc::ApplyToFields(DIVisitor *Visitor) { Visitor->Apply(Tag); } //===----------------------------------------------------------------------===// 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 { return GlobalValue::LinkOnceLinkage; } /// ApplyToFields - Target the visitor to the fields of the TransUnitDesc. /// void AnchorDesc::ApplyToFields(DIVisitor *Visitor) { DebugInfoDesc::ApplyToFields(Visitor); Visitor->Apply(AnchorTag); } /// 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 { 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. /// const char *AnchorDesc::getTypeString() const { return "llvm.dbg.anchor.type"; } #ifndef NDEBUG void AnchorDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "AnchorTag(" << AnchorTag << ")\n"; } #endif //===----------------------------------------------------------------------===// AnchoredDesc::AnchoredDesc(unsigned T) : DebugInfoDesc(T) , Anchor(NULL) {} /// ApplyToFields - Target the visitor to the fields of the AnchoredDesc. /// void AnchoredDesc::ApplyToFields(DIVisitor *Visitor) { DebugInfoDesc::ApplyToFields(Visitor); Visitor->Apply(Anchor); } //===----------------------------------------------------------------------===// CompileUnitDesc::CompileUnitDesc() : AnchoredDesc(DW_TAG_compile_unit) , Language(0) , FileName("") , Directory("") , Producer("") {} // 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); // Handle cases out of sync with compiler. if (getVersion() == 0) { unsigned DebugVersion; Visitor->Apply(DebugVersion); } Visitor->Apply(Language); Visitor->Apply(FileName); Visitor->Apply(Directory); Visitor->Apply(Producer); } /// getDescString - Return a string used to compose global names and labels. /// const char *CompileUnitDesc::getDescString() const { return "llvm.dbg.compile_unit"; } /// getTypeString - Return a string used to label this descriptors type. /// const char *CompileUnitDesc::getTypeString() const { return "llvm.dbg.compile_unit.type"; } /// 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 AnchorString; } #ifndef NDEBUG void CompileUnitDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " << "Language(" << Language << "), " << "FileName(\"" << FileName << "\"), " << "Directory(\"" << Directory << "\"), " << "Producer(\"" << Producer << "\")\n"; } #endif //===----------------------------------------------------------------------===// TypeDesc::TypeDesc(unsigned T) : DebugInfoDesc(T) , Context(NULL) , Name("") , File(NULL) , Line(0) , Size(0) , Align(0) , Offset(0) , Flags(0) {} /// ApplyToFields - Target the visitor to the fields of the TypeDesc. /// void TypeDesc::ApplyToFields(DIVisitor *Visitor) { DebugInfoDesc::ApplyToFields(Visitor); Visitor->Apply(Context); Visitor->Apply(Name); Visitor->Apply(File); Visitor->Apply(Line); Visitor->Apply(Size); Visitor->Apply(Align); Visitor->Apply(Offset); if (getVersion() > LLVMDebugVersion4) Visitor->Apply(Flags); } /// getDescString - Return a string used to compose global names and labels. /// const char *TypeDesc::getDescString() const { return "llvm.dbg.type"; } /// getTypeString - Return a string used to label this descriptor's type. /// const char *TypeDesc::getTypeString() const { return "llvm.dbg.type.type"; } #ifndef NDEBUG void TypeDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << Context << "), " << "Name(\"" << Name << "\"), " << "File(" << File << "), " << "Line(" << Line << "), " << "Size(" << Size << "), " << "Align(" << Align << "), " << "Offset(" << Offset << "), " << "Flags(" << Flags << ")\n"; } #endif //===----------------------------------------------------------------------===// BasicTypeDesc::BasicTypeDesc() : 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) { TypeDesc::ApplyToFields(Visitor); Visitor->Apply(Encoding); } /// getDescString - Return a string used to compose global names and labels. /// const char *BasicTypeDesc::getDescString() const { return "llvm.dbg.basictype"; } /// getTypeString - Return a string used to label this descriptor's type. /// const char *BasicTypeDesc::getTypeString() const { return "llvm.dbg.basictype.type"; } #ifndef NDEBUG void BasicTypeDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " << "Size(" << getSize() << "), " << "Encoding(" << Encoding << ")\n"; } #endif //===----------------------------------------------------------------------===// DerivedTypeDesc::DerivedTypeDesc(unsigned T) : TypeDesc(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: case DW_TAG_inheritance: 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(FromType); } /// getDescString - Return a string used to compose global names and labels. /// const char *DerivedTypeDesc::getDescString() const { return "llvm.dbg.derivedtype"; } /// getTypeString - Return a string used to label this descriptor's type. /// const char *DerivedTypeDesc::getTypeString() const { return "llvm.dbg.derivedtype.type"; } #ifndef NDEBUG void DerivedTypeDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " << "Size(" << getSize() << "), " << "File(" << getFile() << "), " << "Line(" << getLine() << "), " << "FromType(" << FromType << ")\n"; } #endif //===----------------------------------------------------------------------===// CompositeTypeDesc::CompositeTypeDesc(unsigned T) : DerivedTypeDesc(T) , 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: case DW_TAG_vector_type: case DW_TAG_subroutine_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(Elements); } /// getDescString - Return a string used to compose global names and labels. /// const char *CompositeTypeDesc::getDescString() const { return "llvm.dbg.compositetype"; } /// getTypeString - Return a string used to label this descriptor's type. /// const char *CompositeTypeDesc::getTypeString() const { return "llvm.dbg.compositetype.type"; } #ifndef NDEBUG void CompositeTypeDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Context(" << getContext() << "), " << "Name(\"" << getName() << "\"), " << "Size(" << getSize() << "), " << "File(" << getFile() << "), " << "Line(" << getLine() << "), " << "FromType(" << getFromType() << "), " << "Elements.size(" << Elements.size() << ")\n"; } #endif //===----------------------------------------------------------------------===// SubrangeDesc::SubrangeDesc() : 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) { DebugInfoDesc::ApplyToFields(Visitor); Visitor->Apply(Lo); Visitor->Apply(Hi); } /// getDescString - Return a string used to compose global names and labels. /// const char *SubrangeDesc::getDescString() const { return "llvm.dbg.subrange"; } /// getTypeString - Return a string used to label this descriptor's type. /// const char *SubrangeDesc::getTypeString() const { return "llvm.dbg.subrange.type"; } #ifndef NDEBUG void SubrangeDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Lo(" << Lo << "), " << "Hi(" << Hi << ")\n"; } #endif //===----------------------------------------------------------------------===// 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() { 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); Visitor->Apply(File); Visitor->Apply(Line); Visitor->Apply(TyDesc); } /// 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() { 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("") , FullName("") , LinkageName("") , File(NULL) , Line(0) , TyDesc(NULL) , IsStatic(false) , IsDefinition(false) {} /// ApplyToFields - Target the visitor to the fields of the global. /// void GlobalDesc::ApplyToFields(DIVisitor *Visitor) { AnchoredDesc::ApplyToFields(Visitor); Visitor->Apply(Context); Visitor->Apply(Name); Visitor->Apply(FullName); Visitor->Apply(LinkageName); Visitor->Apply(File); Visitor->Apply(Line); Visitor->Apply(TyDesc); Visitor->Apply(IsStatic); Visitor->Apply(IsDefinition); } //===----------------------------------------------------------------------===// GlobalVariableDesc::GlobalVariableDesc() : 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); } /// getDescString - Return a string used to compose global names and labels. /// const char *GlobalVariableDesc::getDescString() const { return "llvm.dbg.global_variable"; } /// getTypeString - Return a string used to label this descriptors type. /// const char *GlobalVariableDesc::getTypeString() const { return "llvm.dbg.global_variable.type"; } /// 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 AnchorString; } #ifndef NDEBUG void GlobalVariableDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " << "Name(\"" << getName() << "\"), " << "FullName(\"" << getFullName() << "\"), " << "LinkageName(\"" << getLinkageName() << "\"), " << "File(" << getFile() << ")," << "Line(" << getLine() << ")," << "Type(" << getType() << "), " << "IsStatic(" << (isStatic() ? "true" : "false") << "), " << "IsDefinition(" << (isDefinition() ? "true" : "false") << "), " << "Global(" << Global << ")\n"; } #endif //===----------------------------------------------------------------------===// SubprogramDesc::SubprogramDesc() : 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) { GlobalDesc::ApplyToFields(Visitor); } /// getDescString - Return a string used to compose global names and labels. /// const char *SubprogramDesc::getDescString() const { return "llvm.dbg.subprogram"; } /// getTypeString - Return a string used to label this descriptors type. /// const char *SubprogramDesc::getTypeString() const { return "llvm.dbg.subprogram.type"; } /// getAnchorString - Return a string used to label this descriptor's anchor. /// const char *SubprogramDesc::AnchorString = "llvm.dbg.subprograms"; const char *SubprogramDesc::getAnchorString() const { return AnchorString; } #ifndef NDEBUG void SubprogramDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << "), " << "Anchor(" << getAnchor() << "), " << "Name(\"" << getName() << "\"), " << "FullName(\"" << getFullName() << "\"), " << "LinkageName(\"" << getLinkageName() << "\"), " << "File(" << getFile() << ")," << "Line(" << getLine() << ")," << "Type(" << getType() << "), " << "IsStatic(" << (isStatic() ? "true" : "false") << "), " << "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n"; } #endif //===----------------------------------------------------------------------===// 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() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << ")," << "Context(" << Context << ")\n"; } #endif //===----------------------------------------------------------------------===// DebugInfoDesc *DIDeserializer::Deserialize(Value *V) { return Deserialize(getGlobalVariable(V)); } DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) { // Handle NULL. if (!GV) return NULL; // Check to see if it has been already deserialized. DebugInfoDesc *&Slot = GlobalDescs[GV]; if (Slot) return Slot; // Get the Tag from the global. unsigned Tag = DebugInfoDesc::TagFromGlobal(GV); // Create an empty instance of the correct sort. Slot = DebugInfoDesc::DescFactory(Tag); // If not a user defined descriptor. if (Slot) { // Deserialize the fields. DIDeserializeVisitor DRAM(*this, GV); DRAM.ApplyToFields(Slot); } return Slot; } //===----------------------------------------------------------------------===// /// getStrPtrType - Return a "sbyte *" type. /// const PointerType *DISerializer::getStrPtrType() { // If not already defined. if (!StrPtrTy) { // Construct the pointer to signed bytes. StrPtrTy = PointerType::get(Type::Int8Ty); } return StrPtrTy; } /// getEmptyStructPtrType - Return a "{ }*" type. /// 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; } /// getTagType - Return the type describing the specified descriptor (via tag.) /// const StructType *DISerializer::getTagType(DebugInfoDesc *DD) { // Attempt to get the previously defined type. StructType *&Ty = TagTypes[DD->getTag()]; // If not already defined. if (!Ty) { // Set up fields vector. std::vector Fields; // Get types of fields. DIGetTypesVisitor GTAM(*this, Fields); GTAM.ApplyToFields(DD); // Construct structured type. Ty = StructType::get(Fields); // Register type name with module. M->addTypeName(DD->getTypeString(), Ty); } return Ty; } /// getString - Construct the string as constant string global. /// Constant *DISerializer::getString(const std::string &String) { // Check string cache for previous edition. Constant *&Slot = StringCache[String]; // Return Constant if previously defined. if (Slot) return Slot; // 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::getBitCast(StrGV, getStrPtrType()); } return Slot; } /// 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 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, DD->getLinkage(), NULL, DD->getDescString(), M); GV->setSection("llvm.metadata"); // Insert new GlobalVariable in DescGlobals map. Slot = GV; // Set up elements vector std::vector Elements; // Add fields. DISerializeVisitor SRAM(*this, Elements); SRAM.ApplyToFields(DD); // Set the globals initializer. GV->setInitializer(ConstantStruct::get(Ty, Elements)); return GV; } //===----------------------------------------------------------------------===// /// Verify - Return true if the GlobalVariable appears to be a valid /// serialization of a DebugInfoDesc. bool DIVerifier::Verify(Value *V) { return !V || Verify(getGlobalVariable(V)); } bool DIVerifier::Verify(GlobalVariable *GV) { // 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); // Check for user defined descriptors. if (Tag == DW_TAG_invalid) { ValiditySlot = Valid; return true; } // Get the Version. unsigned Version = DebugInfoDesc::VersionFromGlobal(GV); // Check for version mismatch. if (Version != LLVMDebugVersion) { ValiditySlot = Invalid; return false; } // Construct an empty DebugInfoDesc. DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag); // Allow for user defined descriptors. if (!DD) return true; // Get the initializer constant. ConstantStruct *CI = cast(GV->getInitializer()); // Get the operand count. unsigned N = CI->getNumOperands(); // Get the field count. unsigned &CountSlot = Counts[Tag]; if (!CountSlot) { // Check the operand count to the field count DICountVisitor CTAM; CTAM.ApplyToFields(DD); CountSlot = CTAM.getCount(); } // Field count must be at most equal operand count. if (CountSlot > N) { delete DD; ValiditySlot = Invalid; return false; } // Check each field for valid type. DIVerifyVisitor VRAM(*this, GV); VRAM.ApplyToFields(DD); // Release empty DebugInfoDesc. delete DD; // 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() , LabelIDList() , ScopeMap() , RootScope(NULL) , FrameMoves() {} MachineDebugInfo::~MachineDebugInfo() { } /// doInitialization - Initialize the debug state for a new module. /// bool MachineDebugInfo::doInitialization() { return false; } /// doFinalization - Tear down the debug state after completion of a module. /// 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. FrameMoves.clear(); } /// getDescFor - Convert a Value to a debug information descriptor. /// // FIXME - use new Value type when available. DebugInfoDesc *MachineDebugInfo::getDescFor(Value *V) { return DR.Deserialize(V); } /// Verify - Verify that a Value is debug information descriptor. /// bool MachineDebugInfo::Verify(Value *V) { return VR.Verify(V); } /// AnalyzeModule - Scan the module for global debug information. /// void MachineDebugInfo::AnalyzeModule(Module &M) { SetupCompileUnits(M); } /// SetupCompileUnits - Set up the unique vector of compile units. /// void MachineDebugInfo::SetupCompileUnits(Module &M) { std::vectorCU = getAnchoredDescriptors(M); for (unsigned i = 0, N = CU.size(); i < N; i++) { CompileUnits.insert(CU[i]); } } /// getCompileUnits - Return a vector of debug compile units. /// const UniqueVector MachineDebugInfo::getCompileUnits()const{ return CompileUnits; } /// getGlobalVariablesUsing - Return all of the GlobalVariables that use the /// named GlobalVariable. std::vector 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(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; } //===----------------------------------------------------------------------===// /// DebugLabelFolding pass - This pass prunes out redundant debug labels. This /// allows a debug emitter to determine if the range of two labels is empty, /// by seeing if the labels map to the same reduced label. namespace llvm { struct DebugLabelFolder : public MachineFunctionPass { virtual bool runOnMachineFunction(MachineFunction &MF); virtual const char *getPassName() const { return "Debug Label Folder"; } }; bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) { // Get machine debug info. MachineDebugInfo *MDI = getAnalysisToUpdate(); if (!MDI) return false; // Get target instruction info. const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); if (!TII) return false; // Track if change is made. bool MadeChange = false; // No prior label to begin. unsigned PriorLabel = 0; // Iterate through basic blocks. for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) { // Iterate through instructions. for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { // Is it a debug label. if ((unsigned)I->getOpcode() == TargetInstrInfo::LABEL) { // The label ID # is always operand #0, an immediate. unsigned NextLabel = I->getOperand(0).getImm(); // If there was an immediate prior label. if (PriorLabel) { // Remap the current label to prior label. MDI->RemapLabel(NextLabel, PriorLabel); // Delete the current label. I = BB->erase(I); // Indicate a change has been made. MadeChange = true; continue; } else { // Start a new round. PriorLabel = NextLabel; } } else { // No consecutive labels. PriorLabel = 0; } ++I; } } return MadeChange; } FunctionPass *createDebugLabelFoldingPass() { return new DebugLabelFolder(); } }