X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FDebugInfo.cpp;h=e6ce9e4e74cdc4ff8d2b217eb96442100948d3f9;hb=2bd6269417960e00962cb7d8ff92e36b183a4910;hp=32e61a1723428080f5c3835f7fc8a1cd0e6544f3;hpb=06203127a7815df8aa63849995536fa467aeba93;p=oota-llvm.git diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 32e61a17234..e6ce9e4e74c 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/DebugInfo.h" -#include "llvm/Target/TargetMachine.h" // FIXME: LAYERING VIOLATION! #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Intrinsics.h" @@ -22,9 +21,10 @@ #include "llvm/Module.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::dwarf; @@ -33,52 +33,22 @@ using namespace llvm::dwarf; // DIDescriptor //===----------------------------------------------------------------------===// -/// ValidDebugInfo - Return true if V represents valid debug info value. -/// FIXME : Add DIDescriptor.isValid() -bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) { - if (!N) - return false; - - DIDescriptor DI(N); - - // Check current version. Allow Version6 for now. - unsigned Version = DI.getVersion(); - if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) - return false; +DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { +} - switch (DI.getTag()) { - case DW_TAG_variable: - assert(DIVariable(N).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_compile_unit: - assert(DICompileUnit(N).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_subprogram: - assert(DISubprogram(N).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_lexical_block: - // FIXME: This interfers with the quality of generated code during - // optimization. - if (OptLevel != CodeGenOpt::None) - return false; - // FALLTHROUGH - default: - break; - } +DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { +} - return true; +DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { } -DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) { - DbgNode = N; +DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { +} - // If this is non-null, check to see if the Tag matches. If not, set to null. - if (N && getTag() != RequiredTag) { - DbgNode = 0; - } +DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { } -StringRef +StringRef DIDescriptor::getStringField(unsigned Elt) const { if (DbgNode == 0) return StringRef(); @@ -105,9 +75,9 @@ DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { if (DbgNode == 0) return DIDescriptor(); - if (Elt < DbgNode->getNumOperands() && DbgNode->getOperand(Elt)) - return DIDescriptor(dyn_cast(DbgNode->getOperand(Elt))); - + if (Elt < DbgNode->getNumOperands()) + return + DIDescriptor(dyn_cast_or_null(DbgNode->getOperand(Elt))); return DIDescriptor(); } @@ -120,10 +90,38 @@ GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { return 0; } +Constant *DIDescriptor::getConstantField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + return 0; +} + +Function *DIDescriptor::getFunctionField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + return 0; +} + unsigned DIVariable::getNumAddrElements() const { - return DbgNode->getNumOperands()-6; + if (getVersion() <= llvm::LLVMDebugVersion8) + return DbgNode->getNumOperands()-6; + if (getVersion() == llvm::LLVMDebugVersion9) + return DbgNode->getNumOperands()-7; + return DbgNode->getNumOperands()-8; } +/// getInlinedAt - If this variable is inlined then return inline location. +MDNode *DIVariable::getInlinedAt() const { + if (getVersion() <= llvm::LLVMDebugVersion9) + return NULL; + return dyn_cast_or_null(DbgNode->getOperand(7)); +} //===----------------------------------------------------------------------===// // Predicates @@ -132,13 +130,12 @@ unsigned DIVariable::getNumAddrElements() const { /// isBasicType - Return true if the specified tag is legal for /// DIBasicType. bool DIDescriptor::isBasicType() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_base_type; + return DbgNode && getTag() == dwarf::DW_TAG_base_type; } /// isDerivedType - Return true if the specified tag is legal for DIDerivedType. bool DIDescriptor::isDerivedType() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_pointer_type: @@ -148,6 +145,7 @@ bool DIDescriptor::isDerivedType() const { case dwarf::DW_TAG_restrict_type: case dwarf::DW_TAG_member: case dwarf::DW_TAG_inheritance: + case dwarf::DW_TAG_friend: return true; default: // CompositeTypes are currently modelled as DerivedTypes. @@ -158,7 +156,7 @@ bool DIDescriptor::isDerivedType() const { /// isCompositeType - Return true if the specified tag is legal for /// DICompositeType. bool DIDescriptor::isCompositeType() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_array_type: case dwarf::DW_TAG_structure_type: @@ -175,7 +173,7 @@ bool DIDescriptor::isCompositeType() const { /// isVariable - Return true if the specified tag is legal for DIVariable. bool DIDescriptor::isVariable() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_auto_variable: case dwarf::DW_TAG_arg_variable: @@ -194,15 +192,14 @@ bool DIDescriptor::isType() const { /// isSubprogram - Return true if the specified tag is legal for /// DISubprogram. bool DIDescriptor::isSubprogram() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_subprogram; + return DbgNode && getTag() == dwarf::DW_TAG_subprogram; } /// isGlobalVariable - Return true if the specified tag is legal for /// DIGlobalVariable. bool DIDescriptor::isGlobalVariable() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_variable; + return DbgNode && (getTag() == dwarf::DW_TAG_variable || + getTag() == dwarf::DW_TAG_constant); } /// isGlobal - Return true if the specified tag is legal for DIGlobal. @@ -210,10 +207,16 @@ bool DIDescriptor::isGlobal() const { return isGlobalVariable(); } +/// isUnspecifiedParmeter - Return true if the specified tag is +/// DW_TAG_unspecified_parameters. +bool DIDescriptor::isUnspecifiedParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters; +} + /// isScope - Return true if the specified tag is one of the scope /// related tag. bool DIDescriptor::isScope() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_compile_unit: case dwarf::DW_TAG_lexical_block: @@ -226,41 +229,53 @@ bool DIDescriptor::isScope() const { return false; } +/// isTemplateTypeParameter - Return true if the specified tag is +/// DW_TAG_template_type_parameter. +bool DIDescriptor::isTemplateTypeParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter; +} + +/// isTemplateValueParameter - Return true if the specified tag is +/// DW_TAG_template_value_parameter. +bool DIDescriptor::isTemplateValueParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_value_parameter; +} + /// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. bool DIDescriptor::isCompileUnit() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_compile_unit; + return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; +} + +/// isFile - Return true if the specified tag is DW_TAG_file_type. +bool DIDescriptor::isFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_file_type; } /// isNameSpace - Return true if the specified tag is DW_TAG_namespace. bool DIDescriptor::isNameSpace() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_namespace; + return DbgNode && getTag() == dwarf::DW_TAG_namespace; } /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_lexical_block; + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block; } /// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. bool DIDescriptor::isSubrange() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_subrange_type; + return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; } /// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. bool DIDescriptor::isEnumerator() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_enumerator; + return DbgNode && getTag() == dwarf::DW_TAG_enumerator; } //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -DIType::DIType(MDNode *N) : DIDescriptor(N) { +DIType::DIType(const MDNode *N) : DIScope(N) { if (!N) return; if (!isBasicType() && !isDerivedType() && !isCompositeType()) { DbgNode = 0; @@ -268,34 +283,70 @@ DIType::DIType(MDNode *N) : DIDescriptor(N) { } unsigned DIArray::getNumElements() const { - assert(DbgNode && "Invalid DIArray"); + if (!DbgNode) + return 0; return DbgNode->getNumOperands(); } /// replaceAllUsesWith - Replace all uses of debug info referenced by -/// this descriptor. After this completes, the current debug info value -/// is erased. -void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { - if (isNull()) +/// this descriptor. +void DIType::replaceAllUsesWith(DIDescriptor &D) { + if (!DbgNode) return; - assert(!D.isNull() && "Can not replace with null"); + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (DbgNode != D) { + MDNode *Node = const_cast(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null(DN); + Node->replaceAllUsesWith(const_cast(V)); + MDNode::deleteTemporary(Node); + } +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(MDNode *D) { + if (!DbgNode) + return; // Since we use a TrackingVH for the node, its easy for clients to manufacture // legitimate situations where they want to replaceAllUsesWith() on something // which, due to uniquing, has merged with the source. We shield clients from // this detail by allowing a value to be replaced with replaceAllUsesWith() // itself. - if (getNode() != D.getNode()) { - MDNode *Node = DbgNode; - Node->replaceAllUsesWith(D.getNode()); - Node->destroy(); + if (DbgNode != D) { + MDNode *Node = const_cast(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null(DN); + Node->replaceAllUsesWith(const_cast(V)); + MDNode::deleteTemporary(Node); } } +/// isUnsignedDIType - Return true if type encoding is unsigned. +bool DIType::isUnsignedDIType() { + DIDerivedType DTy(DbgNode); + if (DTy.Verify()) + return DTy.getTypeDerivedFrom().isUnsignedDIType(); + + DIBasicType BTy(DbgNode); + if (BTy.Verify()) { + unsigned Encoding = BTy.getEncoding(); + if (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char) + return true; + } + return false; +} + /// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { - if (isNull()) + if (!DbgNode) return false; StringRef N = getFilename(); if (N.empty()) @@ -306,68 +357,71 @@ bool DICompileUnit::Verify() const { /// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (getContext() && !getContext().Verify()) return false; - - DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) + unsigned Tag = getTag(); + if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type && + Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_restrict_type + && Tag != dwarf::DW_TAG_vector_type && Tag != dwarf::DW_TAG_array_type + && Tag != dwarf::DW_TAG_enumeration_type + && getFilename().empty()) return false; return true; } +/// Verify - Verify that a basic type descriptor is well formed. +bool DIBasicType::Verify() const { + return isBasicType(); +} + +/// Verify - Verify that a derived type descriptor is well formed. +bool DIDerivedType::Verify() const { + return isDerivedType(); +} + /// Verify - Verify that a composite type descriptor is well formed. bool DICompositeType::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (getContext() && !getContext().Verify()) return false; - DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) - return false; return true; } /// Verify - Verify that a subprogram descriptor is well formed. bool DISubprogram::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) - return false; - - DICompileUnit CU = getCompileUnit(); - if (!CU.Verify()) + if (getContext() && !getContext().Verify()) return false; DICompositeType Ty = getType(); - if (!Ty.isNull() && !Ty.Verify()) + if (!Ty.Verify()) return false; return true; } /// Verify - Verify that a global variable descriptor is well formed. bool DIGlobalVariable::Verify() const { - if (isNull()) + if (!DbgNode) return false; if (getDisplayName().empty()) return false; - if (getContext().isNull()) - return false; - - DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) + if (getContext() && !getContext().Verify()) return false; DIType Ty = getType(); if (!Ty.Verify()) return false; - if (!getGlobal()) + if (!getGlobal() && !getConstant()) return false; return true; @@ -375,10 +429,10 @@ bool DIGlobalVariable::Verify() const { /// Verify - Verify that a variable descriptor is well formed. bool DIVariable::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (getContext() && !getContext().Verify()) return false; DIType Ty = getType(); @@ -388,6 +442,23 @@ bool DIVariable::Verify() const { return true; } +/// Verify - Verify that a location descriptor is well formed. +bool DILocation::Verify() const { + if (!DbgNode) + return false; + + return DbgNode->getNumOperands() == 4; +} + +/// Verify - Verify that a namespace descriptor is well formed. +bool DINameSpace::Verify() const { + if (!DbgNode) + return false; + if (getName().empty()) + return false; + return true; +} + /// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t DIDerivedType::getOriginalTypeSize() const { @@ -396,23 +467,36 @@ uint64_t DIDerivedType::getOriginalTypeSize() const { Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || Tag == dwarf::DW_TAG_restrict_type) { DIType BaseType = getTypeDerivedFrom(); - // If this type is not derived from any type then take conservative + // If this type is not derived from any type then take conservative // approach. - if (BaseType.isNull()) + if (!BaseType.isValid()) return getSizeInBits(); if (BaseType.isDerivedType()) - return DIDerivedType(BaseType.getNode()).getOriginalTypeSize(); + return DIDerivedType(BaseType).getOriginalTypeSize(); else return BaseType.getSizeInBits(); } - + return getSizeInBits(); } +/// isInlinedFnArgument - Return true if this variable provides debugging +/// information for an inlined function arguments. +bool DIVariable::isInlinedFnArgument(const Function *CurFn) { + assert(CurFn && "Invalid function"); + if (!getContext().isSubprogram()) + return false; + // This variable is not inlined function argument if its scope + // does not describe current function. + return !(DISubprogram(getContext()).describes(CurFn)); +} + /// describes - Return true if this subprogram provides debugging /// information for the function F. bool DISubprogram::describes(const Function *F) { assert(F && "Invalid function"); + if (F == getFunction()) + return true; StringRef Name = getLinkageName(); if (Name.empty()) Name = getName(); @@ -421,8 +505,17 @@ bool DISubprogram::describes(const Function *F) { return false; } +unsigned DISubprogram::isOptimized() const { + assert (DbgNode && "Invalid subprogram descriptor!"); + if (DbgNode->getNumOperands() == 16) + return getUnsignedField(15); + return 0; +} + StringRef DIScope::getFilename() const { - if (isLexicalBlock()) + if (!DbgNode) + return StringRef(); + if (isLexicalBlock()) return DILexicalBlock(DbgNode).getFilename(); if (isSubprogram()) return DISubprogram(DbgNode).getFilename(); @@ -430,12 +523,18 @@ StringRef DIScope::getFilename() const { return DICompileUnit(DbgNode).getFilename(); if (isNameSpace()) return DINameSpace(DbgNode).getFilename(); + if (isType()) + return DIType(DbgNode).getFilename(); + if (isFile()) + return DIFile(DbgNode).getFilename(); assert(0 && "Invalid DIScope!"); return StringRef(); } StringRef DIScope::getDirectory() const { - if (isLexicalBlock()) + if (!DbgNode) + return StringRef(); + if (isLexicalBlock()) return DILexicalBlock(DbgNode).getDirectory(); if (isSubprogram()) return DISubprogram(DbgNode).getDirectory(); @@ -443,640 +542,328 @@ StringRef DIScope::getDirectory() const { return DICompileUnit(DbgNode).getDirectory(); if (isNameSpace()) return DINameSpace(DbgNode).getDirectory(); + if (isType()) + return DIType(DbgNode).getDirectory(); + if (isFile()) + return DIFile(DbgNode).getDirectory(); assert(0 && "Invalid DIScope!"); return StringRef(); } +DIArray DICompileUnit::getEnumTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(10))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getRetainedTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(11))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getSubprograms() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(12))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + + +DIArray DICompileUnit::getGlobalVariables() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(13))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + //===----------------------------------------------------------------------===// // DIDescriptor: dump routines for all descriptors. //===----------------------------------------------------------------------===// -/// dump - Print descriptor. -void DIDescriptor::dump() const { - dbgs() << "[" << dwarf::TagString(getTag()) << "] "; - dbgs().write_hex((intptr_t) &*DbgNode) << ']'; +/// print - Print descriptor. +void DIDescriptor::print(raw_ostream &OS) const { + OS << "[" << dwarf::TagString(getTag()) << "] "; + OS.write_hex((intptr_t) &*DbgNode) << ']'; } -/// dump - Print compile unit. -void DICompileUnit::dump() const { +/// print - Print compile unit. +void DICompileUnit::print(raw_ostream &OS) const { if (getLanguage()) - dbgs() << " [" << dwarf::LanguageString(getLanguage()) << "] "; + OS << " [" << dwarf::LanguageString(getLanguage()) << "] "; - dbgs() << " [" << getDirectory() << "/" << getFilename() << " ]"; + OS << " [" << getDirectory() << "/" << getFilename() << "]"; } -/// dump - Print type. -void DIType::dump() const { - if (isNull()) return; +/// print - Print type. +void DIType::print(raw_ostream &OS) const { + if (!DbgNode) return; StringRef Res = getName(); if (!Res.empty()) - dbgs() << " [" << Res << "] "; + OS << " [" << Res << "] "; unsigned Tag = getTag(); - dbgs() << " [" << dwarf::TagString(Tag) << "] "; + OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().dump(); - dbgs() << " [" - << getLineNumber() << ", " - << getSizeInBits() << ", " - << getAlignInBits() << ", " - << getOffsetInBits() + OS << " [" + << "line " << getLineNumber() << ", " + << getSizeInBits() << " bits, " + << getAlignInBits() << " bit alignment, " + << getOffsetInBits() << " bit offset" << "] "; if (isPrivate()) - dbgs() << " [private] "; + OS << " [private] "; else if (isProtected()) - dbgs() << " [protected] "; + OS << " [protected] "; if (isForwardDecl()) - dbgs() << " [fwd] "; + OS << " [fwd] "; if (isBasicType()) - DIBasicType(DbgNode).dump(); + DIBasicType(DbgNode).print(OS); else if (isDerivedType()) - DIDerivedType(DbgNode).dump(); + DIDerivedType(DbgNode).print(OS); else if (isCompositeType()) - DICompositeType(DbgNode).dump(); + DICompositeType(DbgNode).print(OS); else { - dbgs() << "Invalid DIType\n"; + OS << "Invalid DIType\n"; return; } - dbgs() << "\n"; + OS << "\n"; } -/// dump - Print basic type. -void DIBasicType::dump() const { - dbgs() << " [" << dwarf::AttributeEncodingString(getEncoding()) << "] "; +/// print - Print basic type. +void DIBasicType::print(raw_ostream &OS) const { + OS << " [" << dwarf::AttributeEncodingString(getEncoding()) << "] "; } -/// dump - Print derived type. -void DIDerivedType::dump() const { - dbgs() << "\n\t Derived From: "; getTypeDerivedFrom().dump(); +/// print - Print derived type. +void DIDerivedType::print(raw_ostream &OS) const { + OS << "\n\t Derived From: "; getTypeDerivedFrom().print(OS); } -/// dump - Print composite type. -void DICompositeType::dump() const { +/// print - Print composite type. +void DICompositeType::print(raw_ostream &OS) const { DIArray A = getTypeArray(); - if (A.isNull()) - return; - dbgs() << " [" << A.getNumElements() << " elements]"; + OS << " [" << A.getNumElements() << " elements]"; } -/// dump - Print global. -void DIGlobal::dump() const { +/// print - Print subprogram. +void DISubprogram::print(raw_ostream &OS) const { StringRef Res = getName(); if (!Res.empty()) - dbgs() << " [" << Res << "] "; + OS << " [" << Res << "] "; unsigned Tag = getTag(); - dbgs() << " [" << dwarf::TagString(Tag) << "] "; + OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().dump(); - dbgs() << " [" << getLineNumber() << "] "; + OS << " [" << getLineNumber() << "] "; if (isLocalToUnit()) - dbgs() << " [local] "; + OS << " [local] "; if (isDefinition()) - dbgs() << " [def] "; + OS << " [def] "; - if (isGlobalVariable()) - DIGlobalVariable(DbgNode).dump(); - - dbgs() << "\n"; + OS << "\n"; } -/// dump - Print subprogram. -void DISubprogram::dump() const { +/// print - Print global variable. +void DIGlobalVariable::print(raw_ostream &OS) const { + OS << " ["; StringRef Res = getName(); if (!Res.empty()) - dbgs() << " [" << Res << "] "; + OS << " [" << Res << "] "; unsigned Tag = getTag(); - dbgs() << " [" << dwarf::TagString(Tag) << "] "; + OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().dump(); - dbgs() << " [" << getLineNumber() << "] "; + OS << " [" << getLineNumber() << "] "; if (isLocalToUnit()) - dbgs() << " [local] "; + OS << " [local] "; if (isDefinition()) - dbgs() << " [def] "; + OS << " [def] "; - dbgs() << "\n"; + if (isGlobalVariable()) + DIGlobalVariable(DbgNode).print(OS); + OS << "]\n"; } -/// dump - Print global variable. -void DIGlobalVariable::dump() const { - dbgs() << " ["; - getGlobal()->dump(); - dbgs() << "] "; +static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, + const LLVMContext &Ctx) { + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << ""; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, CommentOS, Ctx); + CommentOS << " ]"; + } + } } -/// dump - Print variable. -void DIVariable::dump() const { +void DIVariable::printExtendedName(raw_ostream &OS) const { + const LLVMContext &Ctx = DbgNode->getContext(); StringRef Res = getName(); if (!Res.empty()) - dbgs() << " [" << Res << "] "; + OS << Res << "," << getLineNumber(); + if (MDNode *InlinedAt = getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} + +/// print - Print variable. +void DIVariable::print(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "] "; - getCompileUnit().dump(); - dbgs() << " [" << getLineNumber() << "] "; - getType().dump(); - dbgs() << "\n"; + OS << " [" << getLineNumber() << "] "; + getType().print(OS); + OS << "\n"; // FIXME: Dump complex addresses } -//===----------------------------------------------------------------------===// -// DIFactory: Basic Helpers -//===----------------------------------------------------------------------===// +/// dump - Print descriptor to dbgs() with a newline. +void DIDescriptor::dump() const { + print(dbgs()); dbgs() << '\n'; +} -DIFactory::DIFactory(Module &m) - : M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {} +/// dump - Print compile unit to dbgs() with a newline. +void DICompileUnit::dump() const { + print(dbgs()); dbgs() << '\n'; +} -Constant *DIFactory::GetTagConstant(unsigned TAG) { - assert((TAG & LLVMDebugVersionMask) == 0 && - "Tag too large for debug encoding!"); - return ConstantInt::get(Type::getInt32Ty(VMContext), TAG | LLVMDebugVersion); +/// dump - Print type to dbgs() with a newline. +void DIType::dump() const { + print(dbgs()); dbgs() << '\n'; } -//===----------------------------------------------------------------------===// -// DIFactory: Primary Constructors -//===----------------------------------------------------------------------===// +/// dump - Print basic type to dbgs() with a newline. +void DIBasicType::dump() const { + print(dbgs()); dbgs() << '\n'; +} -/// GetOrCreateArray - Create an descriptor for an array of descriptors. -/// This implicitly uniques the arrays created. -DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) { - SmallVector Elts; +/// dump - Print derived type to dbgs() with a newline. +void DIDerivedType::dump() const { + print(dbgs()); dbgs() << '\n'; +} - if (NumTys == 0) - Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); - else - for (unsigned i = 0; i != NumTys; ++i) - Elts.push_back(Tys[i].getNode()); - - return DIArray(MDNode::get(VMContext,Elts.data(), Elts.size())); -} - -/// GetOrCreateSubrange - Create a descriptor for a value range. This -/// implicitly uniques the values returned. -DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subrange_type), - ConstantInt::get(Type::getInt64Ty(VMContext), Lo), - ConstantInt::get(Type::getInt64Ty(VMContext), Hi) - }; - - return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); -} - - - -/// CreateCompileUnit - Create a new descriptor for the specified compile -/// unit. Note that this does not unique compile units within the module. -DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, - StringRef Filename, - StringRef Directory, - StringRef Producer, - bool isMain, - bool isOptimized, - StringRef Flags, - unsigned RunTimeVer) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_compile_unit), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - ConstantInt::get(Type::getInt32Ty(VMContext), LangID), - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory), - MDString::get(VMContext, Producer), - ConstantInt::get(Type::getInt1Ty(VMContext), isMain), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) - }; - - return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10)); -} - -/// CreateEnumerator - Create a single enumerator value. -DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_enumerator), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt64Ty(VMContext), Val) - }; - return DIEnumerator(MDNode::get(VMContext, &Elts[0], 3)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getNode(), - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getNode(), - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang) { - - Value *Elts[] = { - GetTagConstant(Tag), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getNode(), - Elements.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) - }; - return DICompositeType(MDNode::get(VMContext, &Elts[0], 12)); -} - - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang) { - - Value *Elts[] = { - GetTagConstant(Tag), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getNode(), - Elements.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) - }; - return DICompositeType(MDNode::get(VMContext, &Elts[0], 12)); -} - - -/// CreateSubprogram - Create a new descriptor for the specified subprogram. -/// See comments in DISubprogram for descriptions of these fields. This -/// method does not unique the generated descriptors. -DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, - StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DICompileUnit CompileUnit, - unsigned LineNo, DIType Type, - bool isLocalToUnit, - bool isDefinition, - unsigned VK, unsigned VIndex, - DIType ContainingType) { - - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context.getNode(), - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), - ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), - ContainingType.getNode() - }; - return DISubprogram(MDNode::get(VMContext, &Elts[0], 14)); -} - -/// CreateSubprogramDefinition - Create new subprogram descriptor for the -/// given declaration. -DISubprogram DIFactory::CreateSubprogramDefinition(DISubprogram &SPDeclaration) { - if (SPDeclaration.isDefinition()) - return DISubprogram(SPDeclaration.getNode()); - - MDNode *DeclNode = SPDeclaration.getNode(); - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - DeclNode->getOperand(2), // Context - DeclNode->getOperand(3), // Name - DeclNode->getOperand(4), // DisplayName - DeclNode->getOperand(5), // LinkageName - DeclNode->getOperand(6), // CompileUnit - DeclNode->getOperand(7), // LineNo - DeclNode->getOperand(8), // Type - DeclNode->getOperand(9), // isLocalToUnit - ConstantInt::get(Type::getInt1Ty(VMContext), true), - DeclNode->getOperand(11), // Virtuality - DeclNode->getOperand(12), // VIndex - DeclNode->getOperand(13) // Containting Type - }; - return DISubprogram(MDNode::get(VMContext, &Elts[0], 14)); -} - -/// CreateGlobalVariable - Create a new descriptor for the specified global. -DIGlobalVariable -DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DICompileUnit CompileUnit, - unsigned LineNo, DIType Type,bool isLocalToUnit, - bool isDefinition, llvm::GlobalVariable *Val) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_variable), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context.getNode(), - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - Val - }; - - Value *const *Vs = &Elts[0]; - MDNode *Node = MDNode::get(VMContext,Vs, 12); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); - - return DIGlobalVariable(Node); -} - - -/// CreateVariable - Create a new descriptor for the specified variable. -DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, - DICompileUnit CompileUnit, unsigned LineNo, - DIType Type) { - Value *Elts[] = { - GetTagConstant(Tag), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), - }; - return DIVariable(MDNode::get(VMContext, &Elts[0], 6)); -} - - -/// CreateComplexVariable - Create a new descriptor for the specified variable -/// which has a complex address expression for its address. -DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, - const std::string &Name, - DICompileUnit CompileUnit, - unsigned LineNo, - DIType Type, SmallVector &addr) { - SmallVector Elts; - Elts.push_back(GetTagConstant(Tag)); - Elts.push_back(Context.getNode()); - Elts.push_back(MDString::get(VMContext, Name)); - Elts.push_back(CompileUnit.getNode()); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); - Elts.push_back(Type.getNode()); - Elts.insert(Elts.end(), addr.begin(), addr.end()); - - return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size())); -} - - -/// CreateBlock - This creates a descriptor for a lexical block with the -/// specified parent VMContext. -DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_lexical_block), - Context.getNode() - }; - return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2)); -} - -/// CreateNameSpace - This creates new descriptor for a namespace -/// with the specified parent context. -DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, - unsigned LineNo) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_namespace), - Context.getNode(), - MDString::get(VMContext, Name), - CompileUnit.getNode(), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; - return DINameSpace(MDNode::get(VMContext, &Elts[0], 5)); -} - -/// CreateLocation - Creates a debug info location. -DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, DILocation OrigLoc) { - Value *Elts[] = { - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), - S.getNode(), - OrigLoc.getNode(), - }; - return DILocation(MDNode::get(VMContext, &Elts[0], 4)); -} - -/// CreateLocation - Creates a debug info location. -DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, MDNode *OrigLoc) { - Value *Elts[] = { - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), - S.getNode(), - OrigLoc - }; - return DILocation(MDNode::get(VMContext, &Elts[0], 4)); +/// dump - Print composite type to dbgs() with a newline. +void DICompositeType::dump() const { + print(dbgs()); dbgs() << '\n'; } -//===----------------------------------------------------------------------===// -// DIFactory: Routines for inserting code into a function -//===----------------------------------------------------------------------===// +/// dump - Print subprogram to dbgs() with a newline. +void DISubprogram::dump() const { + print(dbgs()); dbgs() << '\n'; +} -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - Instruction *InsertBefore) { - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); +/// dump - Print global variable. +void DIGlobalVariable::dump() const { + print(dbgs()); dbgs() << '\n'; +} - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D.getNode() }; - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); +/// dump - Print variable. +void DIVariable::dump() const { + print(dbgs()); dbgs() << '\n'; } -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - BasicBlock *InsertAtEnd) { - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); +/// fixupObjcLikeName - Replace contains special characters used +/// in a typical Objective-C names with '.' in a given string. +static void fixupObjcLikeName(StringRef Str, SmallVectorImpl &Out) { + bool isObjCLike = false; + for (size_t i = 0, e = Str.size(); i < e; ++i) { + char C = Str[i]; + if (C == '[') + isObjCLike = true; - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D.getNode() }; - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd); + if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' || + C == '+' || C == '(' || C == ')')) + Out.push_back('.'); + else + Out.push_back(C); + } } -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - Instruction *InsertBefore) { - assert(V && "no value passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, StringRef FuncName) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + fixupObjcLikeName(FuncName, Name); - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D.getNode() }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); + return M.getNamedMetadata(Name.str()); } -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - BasicBlock *InsertAtEnd) { - assert(V && "no value passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + fixupObjcLikeName(FuncName, Name); - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D.getNode() }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); + return M.getOrInsertNamedMetadata(Name.str()); +} + +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext) { + SmallVector Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? Elts.push_back(InlinedScope) : + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { + SmallVector Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? + Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))): + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); } //===----------------------------------------------------------------------===// @@ -1085,42 +872,56 @@ Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, /// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(Module &M) { - unsigned MDDbgKind = M.getMDKindID("dbg"); - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; ++BI) { if (DbgDeclareInst *DDI = dyn_cast(BI)) processDeclare(DDI); - else if (MDNode *L = BI->getMetadata(MDDbgKind)) - processLocation(DILocation(L)); - } - NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv"); - if (!NMD) - return; + DebugLoc Loc = BI->getDebugLoc(); + if (Loc.isUnknown()) + continue; + + LLVMContext &Ctx = BI->getContext(); + DIDescriptor Scope(Loc.getScope(Ctx)); - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIGlobalVariable DIG(cast(NMD->getOperand(i))); - if (addGlobalVariable(DIG)) { - addCompileUnit(DIG.getCompileUnit()); - processType(DIG.getType()); + if (Scope.isCompileUnit()) + addCompileUnit(DICompileUnit(Scope)); + else if (Scope.isSubprogram()) + processSubprogram(DISubprogram(Scope)); + else if (Scope.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(Scope)); + + if (MDNode *IA = Loc.getInlinedAt(Ctx)) + processLocation(DILocation(IA)); + } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv")) { + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIGlobalVariable DIG(cast(NMD->getOperand(i))); + if (addGlobalVariable(DIG)) { + addCompileUnit(DIG.getCompileUnit()); + processType(DIG.getType()); + } } } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + processSubprogram(DISubprogram(NMD->getOperand(i))); } /// processLocation - Process DILocation. void DebugInfoFinder::processLocation(DILocation Loc) { - if (Loc.isNull()) return; - DIScope S(Loc.getScope().getNode()); - if (S.isNull()) return; + if (!Loc.Verify()) return; + DIDescriptor S(Loc.getScope()); if (S.isCompileUnit()) - addCompileUnit(DICompileUnit(S.getNode())); + addCompileUnit(DICompileUnit(S)); else if (S.isSubprogram()) - processSubprogram(DISubprogram(S.getNode())); + processSubprogram(DISubprogram(S)); else if (S.isLexicalBlock()) - processLexicalBlock(DILexicalBlock(S.getNode())); + processLexicalBlock(DILexicalBlock(S)); processLocation(Loc.getOrigLocation()); } @@ -1131,40 +932,33 @@ void DebugInfoFinder::processType(DIType DT) { addCompileUnit(DT.getCompileUnit()); if (DT.isCompositeType()) { - DICompositeType DCT(DT.getNode()); + DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom()); DIArray DA = DCT.getTypeArray(); - if (!DA.isNull()) - for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { - DIDescriptor D = DA.getElement(i); - DIType TypeE = DIType(D.getNode()); - if (!TypeE.isNull()) - processType(TypeE); - else - processSubprogram(DISubprogram(D.getNode())); - } + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + if (D.isType()) + processType(DIType(D)); + else if (D.isSubprogram()) + processSubprogram(DISubprogram(D)); + } } else if (DT.isDerivedType()) { - DIDerivedType DDT(DT.getNode()); - if (!DDT.isNull()) - processType(DDT.getTypeDerivedFrom()); + DIDerivedType DDT(DT); + processType(DDT.getTypeDerivedFrom()); } } /// processLexicalBlock void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { - if (LB.isNull()) - return; DIScope Context = LB.getContext(); if (Context.isLexicalBlock()) - return processLexicalBlock(DILexicalBlock(Context.getNode())); + return processLexicalBlock(DILexicalBlock(Context)); else - return processSubprogram(DISubprogram(Context.getNode())); + return processSubprogram(DISubprogram(Context)); } /// processSubprogram - Process DISubprogram. void DebugInfoFinder::processSubprogram(DISubprogram SP) { - if (SP.isNull()) - return; if (!addSubprogram(SP)) return; addCompileUnit(SP.getCompileUnit()); @@ -1173,193 +967,101 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) { /// processDeclare - Process DbgDeclareInst. void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { - DIVariable DV(cast(DDI->getVariable())); - if (DV.isNull()) + MDNode *N = dyn_cast(DDI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) return; - if (!NodesSeen.insert(DV.getNode())) + if (!NodesSeen.insert(DV)) return; - addCompileUnit(DV.getCompileUnit()); - processType(DV.getType()); + addCompileUnit(DIVariable(N).getCompileUnit()); + processType(DIVariable(N).getType()); } /// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { - if (DT.isNull()) + if (!DT.isValid()) return false; - if (!NodesSeen.insert(DT.getNode())) + if (!NodesSeen.insert(DT)) return false; - TYs.push_back(DT.getNode()); + TYs.push_back(DT); return true; } /// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { - if (CU.isNull()) + if (!CU.Verify()) return false; - if (!NodesSeen.insert(CU.getNode())) + if (!NodesSeen.insert(CU)) return false; - CUs.push_back(CU.getNode()); + CUs.push_back(CU); return true; } /// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { - if (DIG.isNull()) + if (!DIDescriptor(DIG).isGlobalVariable()) return false; - if (!NodesSeen.insert(DIG.getNode())) + if (!NodesSeen.insert(DIG)) return false; - GVs.push_back(DIG.getNode()); + GVs.push_back(DIG); return true; } // addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { - if (SP.isNull()) + if (!DIDescriptor(SP).isSubprogram()) return false; - if (!NodesSeen.insert(SP.getNode())) + if (!NodesSeen.insert(SP)) return false; - SPs.push_back(SP.getNode()); - return true; -} - -/// Find the debug info descriptor corresponding to this global variable. -static Value *findDbgGlobalDeclare(GlobalVariable *V) { - const Module *M = V->getParent(); - NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); - if (!NMD) - return 0; - - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIGlobalVariable DIG(cast_or_null(NMD->getOperand(i))); - if (DIG.isNull()) - continue; - if (DIG.getGlobal() == V) - return DIG.getNode(); - } - return 0; -} - -/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. -/// It looks through pointer casts too. -static const DbgDeclareInst *findDbgDeclare(const Value *V) { - V = V->stripPointerCasts(); - - if (!isa(V) && !isa(V)) - return 0; - - const Function *F = NULL; - if (const Instruction *I = dyn_cast(V)) - F = I->getParent()->getParent(); - else if (const Argument *A = dyn_cast(V)) - F = A->getParent(); - - for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) - for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); - BI != BE; ++BI) - if (const DbgDeclareInst *DDI = dyn_cast(BI)) - if (DDI->getAddress() == V) - return DDI; - - return 0; -} - -bool llvm::getLocationInfo(const Value *V, std::string &DisplayName, - std::string &Type, unsigned &LineNo, - std::string &File, std::string &Dir) { - DICompileUnit Unit; - DIType TypeD; - - if (GlobalVariable *GV = dyn_cast(const_cast(V))) { - Value *DIGV = findDbgGlobalDeclare(GV); - if (!DIGV) return false; - DIGlobalVariable Var(cast(DIGV)); - - StringRef D = Var.getDisplayName(); - if (!D.empty()) - DisplayName = D; - LineNo = Var.getLineNumber(); - Unit = Var.getCompileUnit(); - TypeD = Var.getType(); - } else { - const DbgDeclareInst *DDI = findDbgDeclare(V); - if (!DDI) return false; - DIVariable Var(cast(DDI->getVariable())); - - StringRef D = Var.getName(); - if (!D.empty()) - DisplayName = D; - LineNo = Var.getLineNumber(); - Unit = Var.getCompileUnit(); - TypeD = Var.getType(); - } - - StringRef T = TypeD.getName(); - if (!T.empty()) - Type = T; - StringRef F = Unit.getFilename(); - if (!F.empty()) - File = F; - StringRef D = Unit.getDirectory(); - if (!D.empty()) - Dir = D; + SPs.push_back(SP); return true; } -/// ExtractDebugLocation - Extract debug location information -/// from DILocation. -DebugLoc llvm::ExtractDebugLocation(DILocation &Loc, - DebugLocTracker &DebugLocInfo) { - DenseMap::iterator II - = DebugLocInfo.DebugIdMap.find(Loc.getNode()); - if (II != DebugLocInfo.DebugIdMap.end()) - return DebugLoc::get(II->second); - - // Add a new location entry. - unsigned Id = DebugLocInfo.DebugLocations.size(); - DebugLocInfo.DebugLocations.push_back(Loc.getNode()); - DebugLocInfo.DebugIdMap[Loc.getNode()] = Id; - - return DebugLoc::get(Id); -} - /// getDISubprogram - Find subprogram that is enclosing this scope. -DISubprogram llvm::getDISubprogram(MDNode *Scope) { +DISubprogram llvm::getDISubprogram(const MDNode *Scope) { DIDescriptor D(Scope); - if (D.isNull()) - return DISubprogram(); - - if (D.isCompileUnit()) - return DISubprogram(); - if (D.isSubprogram()) return DISubprogram(Scope); - + if (D.isLexicalBlock()) - return getDISubprogram(DILexicalBlock(Scope).getContext().getNode()); - + return getDISubprogram(DILexicalBlock(Scope).getContext()); + return DISubprogram(); } /// getDICompositeType - Find underlying composite type. DICompositeType llvm::getDICompositeType(DIType T) { - if (T.isNull()) - return DICompositeType(); - if (T.isCompositeType()) - return DICompositeType(T.getNode()); - + return DICompositeType(T); + if (T.isDerivedType()) - return getDICompositeType(DIDerivedType(T.getNode()).getTypeDerivedFrom()); - + return getDICompositeType(DIDerivedType(T).getTypeDerivedFrom()); + return DICompositeType(); } + +/// isSubprogramContext - Return true if Context is either a subprogram +/// or another context nested inside a subprogram. +bool llvm::isSubprogramContext(const MDNode *Context) { + if (!Context) + return false; + DIDescriptor D(Context); + if (D.isSubprogram()) + return true; + if (D.isType()) + return isSubprogramContext(DIType(Context).getContext()); + return false; +} +