//===-- llvm/CodeGen/MachineDebugInfoDesc.cpp -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MachineDebugInfoDesc.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Constants.h" #include "llvm/GlobalVariable.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Streams.h" using namespace llvm; using namespace llvm::dwarf; /// getUIntOperand - Return ith operand if it is an unsigned integer. /// static ConstantInt *getUIntOperand(const 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)); } //===----------------------------------------------------------------------===// /// Supply a home for the DebugInfoDesc's v-table. DebugInfoDesc::~DebugInfoDesc() {} /// 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 /// 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: { CompileUnitDesc CUD; return CUD.getAnchorString(); } case DW_TAG_variable: { GlobalVariableDesc GVD; return GVD.getAnchorString(); } case DW_TAG_subprogram: { SubprogramDesc SPD; return SPD.getAnchorString(); } default: break; } assert(0 && "Tag does not have a case for anchor string"); return ""; } #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); } #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); } #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); } #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); } #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); } #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); } #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); } #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); } #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); } #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); } #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); } #ifndef NDEBUG void BlockDesc::dump() { cerr << getDescString() << " " << "Version(" << getVersion() << "), " << "Tag(" << getTag() << ")," << "Context(" << Context << ")\n"; } #endif