From c2c50cdcdc19a1bca993c06d13d8cdca87083ce4 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 2 Jan 2013 09:10:48 +0000 Subject: Rename VMCore directory to IR. Aside from moving the actual files, this patch only updates the build system and the source file comments under lib/... that are relevant. I'll be updating other docs and other files in smaller subsequnet commits. While I've tried to test this, but it is entirely possible that there will still be some build system fallout. Also, note that I've not changed the library name itself: libLLVMCore.a is still the library name. I'd be interested in others' opinions about whether we should rename this as well (I think we should, just not sure what it might break) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171359 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 1197 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1197 insertions(+) create mode 100644 lib/IR/DebugInfo.cpp (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp new file mode 100644 index 0000000000..07508c879e --- /dev/null +++ b/lib/IR/DebugInfo.cpp @@ -0,0 +1,1197 @@ +//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper classes used to build and interpret debug +// information in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::dwarf; + +//===----------------------------------------------------------------------===// +// DIDescriptor +//===----------------------------------------------------------------------===// + +DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { +} + +StringRef +DIDescriptor::getStringField(unsigned Elt) const { + if (DbgNode == 0) + return StringRef(); + + if (Elt < DbgNode->getNumOperands()) + if (MDString *MDS = dyn_cast_or_null(DbgNode->getOperand(Elt))) + return MDS->getString(); + + return StringRef(); +} + +uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + if (ConstantInt *CI + = dyn_cast_or_null(DbgNode->getOperand(Elt))) + return CI->getZExtValue(); + + return 0; +} + +int64_t DIDescriptor::getInt64Field(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + if (ConstantInt *CI + = dyn_cast_or_null(DbgNode->getOperand(Elt))) + return CI->getSExtValue(); + + return 0; +} + +DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { + if (DbgNode == 0) + return DIDescriptor(); + + if (Elt < DbgNode->getNumOperands()) + return + DIDescriptor(dyn_cast_or_null(DbgNode->getOperand(Elt))); + return DIDescriptor(); +} + +GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + 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; +} + +void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { + if (DbgNode == 0) + return; + + if (Elt < DbgNode->getNumOperands()) { + MDNode *Node = const_cast(DbgNode); + Node->replaceOperandWith(Elt, F); + } +} + +unsigned DIVariable::getNumAddrElements() const { + if (getVersion() <= LLVMDebugVersion8) + return DbgNode->getNumOperands()-6; + if (getVersion() == 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() <= LLVMDebugVersion9) + return NULL; + return dyn_cast_or_null(DbgNode->getOperand(7)); +} + +//===----------------------------------------------------------------------===// +// Predicates +//===----------------------------------------------------------------------===// + +/// isBasicType - Return true if the specified tag is legal for +/// DIBasicType. +bool DIDescriptor::isBasicType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_unspecified_type: + return true; + default: + return false; + } +} + +/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. +bool DIDescriptor::isDerivedType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_reference_type: + case dwarf::DW_TAG_rvalue_reference_type: + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_volatile_type: + 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. + return isCompositeType(); + } +} + +/// isCompositeType - Return true if the specified tag is legal for +/// DICompositeType. +bool DIDescriptor::isCompositeType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_array_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_subroutine_type: + case dwarf::DW_TAG_class_type: + return true; + default: + return false; + } +} + +/// isVariable - Return true if the specified tag is legal for DIVariable. +bool DIDescriptor::isVariable() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_auto_variable: + case dwarf::DW_TAG_arg_variable: + case dwarf::DW_TAG_return_variable: + return true; + default: + return false; + } +} + +/// isType - Return true if the specified tag is legal for DIType. +bool DIDescriptor::isType() const { + return isBasicType() || isCompositeType() || isDerivedType(); +} + +/// isSubprogram - Return true if the specified tag is legal for +/// DISubprogram. +bool DIDescriptor::isSubprogram() const { + return DbgNode && getTag() == dwarf::DW_TAG_subprogram; +} + +/// isGlobalVariable - Return true if the specified tag is legal for +/// DIGlobalVariable. +bool DIDescriptor::isGlobalVariable() const { + return DbgNode && (getTag() == dwarf::DW_TAG_variable || + getTag() == dwarf::DW_TAG_constant); +} + +/// isGlobal - Return true if the specified tag is legal for DIGlobal. +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 { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_compile_unit: + case dwarf::DW_TAG_lexical_block: + case dwarf::DW_TAG_subprogram: + case dwarf::DW_TAG_namespace: + return true; + default: + break; + } + 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 { + 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 { + return DbgNode && getTag() == dwarf::DW_TAG_namespace; +} + +/// isLexicalBlockFile - Return true if the specified descriptor is a +/// lexical block with an extra file. +bool DIDescriptor::isLexicalBlockFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() == 3); +} + +/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. +bool DIDescriptor::isLexicalBlock() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() > 3); +} + +/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. +bool DIDescriptor::isSubrange() const { + return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; +} + +/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. +bool DIDescriptor::isEnumerator() const { + return DbgNode && getTag() == dwarf::DW_TAG_enumerator; +} + +/// isObjCProperty - Return true if the specified tag is DW_TAG +bool DIDescriptor::isObjCProperty() const { + return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; +} +//===----------------------------------------------------------------------===// +// Simple Descriptor Constructors and other Methods +//===----------------------------------------------------------------------===// + +DIType::DIType(const MDNode *N) : DIScope(N) { + if (!N) return; + if (!isBasicType() && !isDerivedType() && !isCompositeType()) { + DbgNode = 0; + } +} + +unsigned DIArray::getNumElements() const { + if (!DbgNode) + return 0; + return DbgNode->getNumOperands(); +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(DIDescriptor &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 (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 (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 (!DbgNode) + return false; + StringRef N = getFilename(); + if (N.empty()) + return false; + // It is possible that directory and produce string is empty. + return true; +} + +/// Verify - Verify that an ObjC property is well formed. +bool DIObjCProperty::Verify() const { + if (!DbgNode) + return false; + unsigned Tag = getTag(); + if (Tag != dwarf::DW_TAG_APPLE_property) return false; + DIType Ty = getType(); + if (!Ty.Verify()) return false; + + // Don't worry about the rest of the strings for now. + return true; +} + +/// Verify - Verify that a type descriptor is well formed. +bool DIType::Verify() const { + if (!DbgNode) + return false; + if (getContext() && !getContext().Verify()) + return false; + 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_rvalue_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 && + Tag != dwarf::DW_TAG_subroutine_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 (!DbgNode) + return false; + if (getContext() && !getContext().Verify()) + return false; + + return true; +} + +/// Verify - Verify that a subprogram descriptor is well formed. +bool DISubprogram::Verify() const { + if (!DbgNode) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DICompositeType Ty = getType(); + if (!Ty.Verify()) + return false; + return true; +} + +/// Verify - Verify that a global variable descriptor is well formed. +bool DIGlobalVariable::Verify() const { + if (!DbgNode) + return false; + + if (getDisplayName().empty()) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + if (!getGlobal() && !getConstant()) + return false; + + return true; +} + +/// Verify - Verify that a variable descriptor is well formed. +bool DIVariable::Verify() const { + if (!DbgNode) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + 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 { + unsigned Tag = getTag(); + + if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && + Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + return getSizeInBits(); + + DIType BaseType = getTypeDerivedFrom(); + + // If this type is not derived from any type then take conservative approach. + if (!BaseType.isValid()) + return getSizeInBits(); + + // If this is a derived type, go ahead and get the base type, unless it's a + // reference then it's just the size of the field. Pointer types have no need + // of this since they're a different type of qualification on the type. + if (BaseType.getTag() == dwarf::DW_TAG_reference_type || + BaseType.getTag() == dwarf::DW_TAG_rvalue_reference_type) + return getSizeInBits(); + + if (BaseType.isDerivedType()) + return DIDerivedType(BaseType).getOriginalTypeSize(); + + return BaseType.getSizeInBits(); +} + +/// getObjCProperty - Return property node, if this ivar is associated with one. +MDNode *DIDerivedType::getObjCProperty() const { + if (getVersion() <= LLVMDebugVersion11 || DbgNode->getNumOperands() <= 10) + return NULL; + return dyn_cast_or_null(DbgNode->getOperand(10)); +} + +/// 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(); + if (F->getName() == Name) + return true; + return false; +} + +unsigned DISubprogram::isOptimized() const { + assert (DbgNode && "Invalid subprogram descriptor!"); + if (DbgNode->getNumOperands() == 16) + return getUnsignedField(15); + return 0; +} + +MDNode *DISubprogram::getVariablesNodes() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return NULL; + if (MDNode *Temp = dyn_cast_or_null(DbgNode->getOperand(19))) + return dyn_cast_or_null(Temp->getOperand(0)); + return NULL; +} + +DIArray DISubprogram::getVariables() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return DIArray(); + if (MDNode *T = dyn_cast_or_null(DbgNode->getOperand(19))) + if (MDNode *A = dyn_cast_or_null(T->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +StringRef DIScope::getFilename() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getFilename(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getFilename(); + if (isSubprogram()) + return DISubprogram(DbgNode).getFilename(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getFilename(); + if (isNameSpace()) + return DINameSpace(DbgNode).getFilename(); + if (isType()) + return DIType(DbgNode).getFilename(); + if (isFile()) + return DIFile(DbgNode).getFilename(); + llvm_unreachable("Invalid DIScope!"); +} + +StringRef DIScope::getDirectory() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getDirectory(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getDirectory(); + if (isSubprogram()) + return DISubprogram(DbgNode).getDirectory(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getDirectory(); + if (isNameSpace()) + return DINameSpace(DbgNode).getDirectory(); + if (isType()) + return DIType(DbgNode).getDirectory(); + if (isFile()) + return DIFile(DbgNode).getDirectory(); + llvm_unreachable("Invalid DIScope!"); +} + +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 (N->getNumOperands() > 0) + 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(); +} + +/// 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; + + if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' || + C == '+' || C == '(' || C == ')')) + Out.push_back('.'); + else + Out.push_back(C); + } +} + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); + return M.getNamedMetadata(Name.str()); +} + +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); + + 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(Constant::getNullValue(Type::getInt32Ty(VMContext))): + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// getDISubprogram - Find subprogram that is enclosing this scope. +DISubprogram llvm::getDISubprogram(const MDNode *Scope) { + DIDescriptor D(Scope); + if (D.isSubprogram()) + return DISubprogram(Scope); + + if (D.isLexicalBlockFile()) + return getDISubprogram(DILexicalBlockFile(Scope).getContext()); + + if (D.isLexicalBlock()) + return getDISubprogram(DILexicalBlock(Scope).getContext()); + + return DISubprogram(); +} + +/// getDICompositeType - Find underlying composite type. +DICompositeType llvm::getDICompositeType(DIType T) { + if (T.isCompositeType()) + return DICompositeType(T); + + if (T.isDerivedType()) + 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; +} + +//===----------------------------------------------------------------------===// +// DebugInfoFinder implementations. +//===----------------------------------------------------------------------===// + +/// processModule - Process entire module and collect debug info. +void DebugInfoFinder::processModule(const Module &M) { + if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { + DICompileUnit CU(CU_Nodes->getOperand(i)); + addCompileUnit(CU); + if (CU.getVersion() > LLVMDebugVersion10) { + DIArray GVs = CU.getGlobalVariables(); + for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { + DIGlobalVariable DIG(GVs.getElement(i)); + if (addGlobalVariable(DIG)) + processType(DIG.getType()); + } + DIArray SPs = CU.getSubprograms(); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) + processSubprogram(DISubprogram(SPs.getElement(i))); + DIArray EnumTypes = CU.getEnumTypes(); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) + processType(DIType(EnumTypes.getElement(i))); + DIArray RetainedTypes = CU.getRetainedTypes(); + for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) + processType(DIType(RetainedTypes.getElement(i))); + return; + } + } + } + + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) + for (Function::const_iterator FI = (*I).begin(), FE = (*I).end(); + FI != FE; ++FI) + for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); + BI != BE; ++BI) { + if (const DbgDeclareInst *DDI = dyn_cast(BI)) + processDeclare(DDI); + + DebugLoc Loc = BI->getDebugLoc(); + if (Loc.isUnknown()) + continue; + + LLVMContext &Ctx = BI->getContext(); + DIDescriptor Scope(Loc.getScope(Ctx)); + + if (Scope.isCompileUnit()) + addCompileUnit(DICompileUnit(Scope)); + else if (Scope.isSubprogram()) + processSubprogram(DISubprogram(Scope)); + else if (Scope.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Scope); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + 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)) { + if (DIG.getVersion() <= LLVMDebugVersion10) + 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.Verify()) return; + DIDescriptor S(Loc.getScope()); + if (S.isCompileUnit()) + addCompileUnit(DICompileUnit(S)); + else if (S.isSubprogram()) + processSubprogram(DISubprogram(S)); + else if (S.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(S)); + else if (S.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(S); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + processLocation(Loc.getOrigLocation()); +} + +/// processType - Process DIType. +void DebugInfoFinder::processType(DIType DT) { + if (!addType(DT)) + return; + if (DT.getVersion() <= LLVMDebugVersion10) + addCompileUnit(DT.getCompileUnit()); + if (DT.isCompositeType()) { + DICompositeType DCT(DT); + processType(DCT.getTypeDerivedFrom()); + DIArray DA = DCT.getTypeArray(); + 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); + processType(DDT.getTypeDerivedFrom()); + } +} + +/// processLexicalBlock +void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { + DIScope Context = LB.getContext(); + if (Context.isLexicalBlock()) + return processLexicalBlock(DILexicalBlock(Context)); + else if (Context.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Context); + return processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + else + return processSubprogram(DISubprogram(Context)); +} + +/// processSubprogram - Process DISubprogram. +void DebugInfoFinder::processSubprogram(DISubprogram SP) { + if (!addSubprogram(SP)) + return; + if (SP.getVersion() <= LLVMDebugVersion10) + addCompileUnit(SP.getCompileUnit()); + processType(SP.getType()); +} + +/// processDeclare - Process DbgDeclareInst. +void DebugInfoFinder::processDeclare(const DbgDeclareInst *DDI) { + MDNode *N = dyn_cast(DDI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) + return; + + if (!NodesSeen.insert(DV)) + return; + if (DIVariable(N).getVersion() <= LLVMDebugVersion10) + addCompileUnit(DIVariable(N).getCompileUnit()); + processType(DIVariable(N).getType()); +} + +/// addType - Add type into Tys. +bool DebugInfoFinder::addType(DIType DT) { + if (!DT.isValid()) + return false; + + if (!NodesSeen.insert(DT)) + return false; + + TYs.push_back(DT); + return true; +} + +/// addCompileUnit - Add compile unit into CUs. +bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { + if (!CU.Verify()) + return false; + + if (!NodesSeen.insert(CU)) + return false; + + CUs.push_back(CU); + return true; +} + +/// addGlobalVariable - Add global variable into GVs. +bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { + if (!DIDescriptor(DIG).isGlobalVariable()) + return false; + + if (!NodesSeen.insert(DIG)) + return false; + + GVs.push_back(DIG); + return true; +} + +// addSubprogram - Add subprgoram into SPs. +bool DebugInfoFinder::addSubprogram(DISubprogram SP) { + if (!DIDescriptor(SP).isSubprogram()) + return false; + + if (!NodesSeen.insert(SP)) + return false; + + SPs.push_back(SP); + return true; +} + +//===----------------------------------------------------------------------===// +// DIDescriptor: dump routines for all descriptors. +//===----------------------------------------------------------------------===// + +/// dump - Print descriptor to dbgs() with a newline. +void DIDescriptor::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// print - Print descriptor. +void DIDescriptor::print(raw_ostream &OS) const { + if (!DbgNode) return; + + if (const char *Tag = dwarf::TagString(getTag())) + OS << "[ " << Tag << " ]"; + + if (this->isSubrange()) { + DISubrange(DbgNode).printInternal(OS); + } else if (this->isCompileUnit()) { + DICompileUnit(DbgNode).printInternal(OS); + } else if (this->isFile()) { + DIFile(DbgNode).printInternal(OS); + } else if (this->isEnumerator()) { + DIEnumerator(DbgNode).printInternal(OS); + } else if (this->isBasicType()) { + DIType(DbgNode).printInternal(OS); + } else if (this->isDerivedType()) { + DIDerivedType(DbgNode).printInternal(OS); + } else if (this->isCompositeType()) { + DICompositeType(DbgNode).printInternal(OS); + } else if (this->isSubprogram()) { + DISubprogram(DbgNode).printInternal(OS); + } else if (this->isGlobalVariable()) { + DIGlobalVariable(DbgNode).printInternal(OS); + } else if (this->isVariable()) { + DIVariable(DbgNode).printInternal(OS); + } else if (this->isObjCProperty()) { + DIObjCProperty(DbgNode).printInternal(OS); + } else if (this->isScope()) { + DIScope(DbgNode).printInternal(OS); + } +} + +void DISubrange::printInternal(raw_ostream &OS) const { + int64_t Count = getCount(); + if (Count != -1) + OS << " [" << getLo() << ", " << Count - 1 << ']'; + else + OS << " [unbounded]"; +} + +void DIScope::printInternal(raw_ostream &OS) const { + OS << " [" << getDirectory() << "/" << getFilename() << ']'; +} + +void DICompileUnit::printInternal(raw_ostream &OS) const { + DIScope::printInternal(OS); + if (unsigned Lang = getLanguage()) + OS << " [" << dwarf::LanguageString(Lang) << ']'; +} + +void DIEnumerator::printInternal(raw_ostream &OS) const { + OS << " [" << getName() << " :: " << getEnumValue() << ']'; +} + +void DIType::printInternal(raw_ostream &OS) const { + if (!DbgNode) return; + + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "]"; + + // TODO: Print context? + + OS << " [line " << getLineNumber() + << ", size " << getSizeInBits() + << ", align " << getAlignInBits() + << ", offset " << getOffsetInBits(); + if (isBasicType()) + if (const char *Enc = + dwarf::AttributeEncodingString(DIBasicType(DbgNode).getEncoding())) + OS << ", enc " << Enc; + OS << "]"; + + if (isPrivate()) + OS << " [private]"; + else if (isProtected()) + OS << " [protected]"; + + if (isForwardDecl()) + OS << " [fwd]"; +} + +void DIDerivedType::printInternal(raw_ostream &OS) const { + DIType::printInternal(OS); + OS << " [from " << getTypeDerivedFrom().getName() << ']'; +} + +void DICompositeType::printInternal(raw_ostream &OS) const { + DIType::printInternal(OS); + DIArray A = getTypeArray(); + OS << " [" << A.getNumElements() << " elements]"; +} + +void DISubprogram::printInternal(raw_ostream &OS) const { + // TODO : Print context + OS << " [line " << getLineNumber() << ']'; + + if (isLocalToUnit()) + OS << " [local]"; + + if (isDefinition()) + OS << " [def]"; + + if (getScopeLineNumber() != getLineNumber()) + OS << " [scope " << getScopeLineNumber() << "]"; + + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; +} + +void DIGlobalVariable::printInternal(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; + + OS << " [line " << getLineNumber() << ']'; + + // TODO : Print context + + if (isLocalToUnit()) + OS << " [local]"; + + if (isDefinition()) + OS << " [def]"; +} + +void DIVariable::printInternal(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; + + OS << " [line " << getLineNumber() << ']'; +} + +void DIObjCProperty::printInternal(raw_ostream &OS) const { + StringRef Name = getObjCPropertyName(); + if (!Name.empty()) + OS << " [" << Name << ']'; + + OS << " [line " << getLineNumber() + << ", properties " << getUnsignedField(6) << ']'; +} + +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 << " ]"; + } + } +} + +void DIVariable::printExtendedName(raw_ostream &OS) const { + const LLVMContext &Ctx = DbgNode->getContext(); + StringRef Res = getName(); + if (!Res.empty()) + OS << Res << "," << getLineNumber(); + if (MDNode *InlinedAt = getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} -- cgit v1.2.3-18-g5258 From 0b8c9a80f20772c3793201ab5b251d3520b9cea3 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 2 Jan 2013 11:36:10 +0000 Subject: Move all of the header files which are involved in modelling the LLVM IR into their new header subdirectory: include/llvm/IR. This matches the directory structure of lib, and begins to correct a long standing point of file layout clutter in LLVM. There are still more header files to move here, but I wanted to handle them in separate commits to make tracking what files make sense at each layer easier. The only really questionable files here are the target intrinsic tablegen files. But that's a battle I'd rather not fight today. I've updated both CMake and Makefile build systems (I think, and my tests think, but I may have missed something). I've also re-sorted the includes throughout the project. I'll be committing updates to Clang, DragonEgg, and Polly momentarily. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171366 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 07508c879e..bec941afda 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -17,12 +17,12 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/ValueTracking.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Intrinsics.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" -- cgit v1.2.3-18-g5258 From e302b6cb69e96b948101e1ab6c0476187c92ee84 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 5 Jan 2013 21:39:33 +0000 Subject: Include access modifiers in subprogram metadata IR comment. Based on code review feedback in r171604 from Chandler Carruth & Eric Christopher. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index bec941afda..5dd9dd1c9d 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -1122,6 +1122,11 @@ void DISubprogram::printInternal(raw_ostream &OS) const { if (getScopeLineNumber() != getLineNumber()) OS << " [scope " << getScopeLineNumber() << "]"; + if (isPrivate()) + OS << " [private]"; + else if (isProtected()) + OS << " [protected]"; + StringRef Res = getName(); if (!Res.empty()) OS << " [" << Res << ']'; -- cgit v1.2.3-18-g5258 From 62fdfb5fa7efdfd61339e4abe6fd87e60e939e58 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 7 Jan 2013 05:51:15 +0000 Subject: PR14759: Debug info support for C++ member pointers. This works fine with GDB for member variable pointers, but GDB's support for member function pointers seems to be quite unrelated to DW_TAG_ptr_to_member_type. (see GDB bug 14998 for details) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171698 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 5dd9dd1c9d..b5e1d177df 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -172,6 +172,7 @@ bool DIDescriptor::isDerivedType() const { switch (getTag()) { case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_ptr_to_member_type: case dwarf::DW_TAG_reference_type: case dwarf::DW_TAG_rvalue_reference_type: case dwarf::DW_TAG_const_type: @@ -423,6 +424,7 @@ bool DIType::Verify() const { 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_ptr_to_member_type && Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_rvalue_reference_type && Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_vector_type && -- cgit v1.2.3-18-g5258 From 72a81be37452983f9960a376c19682034ef7db35 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Tue, 8 Jan 2013 00:16:33 +0000 Subject: Remove what appears to be a dead llvm-specific debug tag. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171821 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index b5e1d177df..6ca692e274 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -212,7 +212,6 @@ bool DIDescriptor::isVariable() const { switch (getTag()) { case dwarf::DW_TAG_auto_variable: case dwarf::DW_TAG_arg_variable: - case dwarf::DW_TAG_return_variable: return true; default: return false; -- cgit v1.2.3-18-g5258 From 0fecdfb7c44aee85e78e0ba6e9547b702bc64c4a Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 8 Jan 2013 00:31:02 +0000 Subject: Mark artificial types as such in the annotated debug output. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171826 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 6ca692e274..d288308097 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -1095,6 +1095,9 @@ void DIType::printInternal(raw_ostream &OS) const { else if (isProtected()) OS << " [protected]"; + if (isArtificial()) + OS << " [artificial]"; + if (isForwardDecl()) OS << " [fwd]"; } -- cgit v1.2.3-18-g5258 From 9a1e0e252a7ede548acaac98cf304d4bb135fb97 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Tue, 8 Jan 2013 01:53:52 +0000 Subject: Remove the llvm-local DW_TAG_vector_type tag and add a test to make sure that vector types do work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171833 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index d288308097..7083495c72 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -197,7 +197,6 @@ bool DIDescriptor::isCompositeType() const { case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_enumeration_type: - case dwarf::DW_TAG_vector_type: case dwarf::DW_TAG_subroutine_type: case dwarf::DW_TAG_class_type: return true; @@ -426,7 +425,7 @@ bool DIType::Verify() const { Tag != dwarf::DW_TAG_ptr_to_member_type && Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_rvalue_reference_type && - Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_vector_type && + Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_array_type && Tag != dwarf::DW_TAG_enumeration_type && Tag != dwarf::DW_TAG_subroutine_type && @@ -1100,6 +1099,8 @@ void DIType::printInternal(raw_ostream &OS) const { if (isForwardDecl()) OS << " [fwd]"; + if (isVector()) + OS << " [vector]"; } void DIDerivedType::printInternal(raw_ostream &OS) const { -- cgit v1.2.3-18-g5258 From 6b6061f01171bd3d4e32022efa45428d4f9941ee Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 16 Jan 2013 01:22:23 +0000 Subject: Define metadata interfaces for describing a static data member of a class. Emit static data member declarations and definitions through correctly. Part of PR14471. Patch by Paul Robinson! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172590 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 7083495c72..876aff8575 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -1101,6 +1101,8 @@ void DIType::printInternal(raw_ostream &OS) const { OS << " [fwd]"; if (isVector()) OS << " [vector]"; + if (isStaticMember()) + OS << " [static]"; } void DIDerivedType::printInternal(raw_ostream &OS) const { -- cgit v1.2.3-18-g5258 From fe07db323b2b403236375af0a54b0ed2294cd0e6 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 19 Jan 2013 23:00:25 +0000 Subject: Fix a latent bug exposed by recent static member debug info changes. We weren't encoding boolean constants correctly due to modeling boolean as a signed type & then sign extending an i1 up to a byte & getting 255. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172926 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 876aff8575..b431184829 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -383,7 +383,8 @@ bool DIType::isUnsignedDIType() { if (BTy.Verify()) { unsigned Encoding = BTy.getEncoding(); if (Encoding == dwarf::DW_ATE_unsigned || - Encoding == dwarf::DW_ATE_unsigned_char) + Encoding == dwarf::DW_ATE_unsigned_char || + Encoding == dwarf::DW_ATE_boolean) return true; } return false; -- cgit v1.2.3-18-g5258 From a8eefc7cc7c6e8be06d570fff76dc42b43a23392 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 2 Feb 2013 05:56:24 +0000 Subject: Remove the (apparently) unnecessary debug info metadata indirection. The main lists of debug info metadata attached to the compile_unit had an extra layer of metadata nodes they went through for no apparent reason. This patch removes that (& still passes just as much of the GDB 7.5 test suite). If anyone can show evidence as to why these extra metadata nodes are there I'm open to reverting this patch & documenting why they're there. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174266 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index b431184829..c983787712 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -652,8 +652,7 @@ DIArray DICompileUnit::getEnumTypes() const { 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(N); return DIArray(); } @@ -662,8 +661,7 @@ DIArray DICompileUnit::getRetainedTypes() const { 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(N); return DIArray(); } @@ -672,9 +670,7 @@ DIArray DICompileUnit::getSubprograms() const { return DIArray(); if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(12))) - if (N->getNumOperands() > 0) - if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) - return DIArray(A); + return DIArray(N); return DIArray(); } @@ -684,8 +680,7 @@ DIArray DICompileUnit::getGlobalVariables() const { 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(N); return DIArray(); } -- cgit v1.2.3-18-g5258 From a9b1317443990533f56a8420c0fbfb8868dad566 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 4 Feb 2013 05:31:37 +0000 Subject: PR15149: crash when printing debug info metadata containing an invalid language spec git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174304 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index c983787712..ecaab1fd65 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -1058,8 +1058,8 @@ void DIScope::printInternal(raw_ostream &OS) const { void DICompileUnit::printInternal(raw_ostream &OS) const { DIScope::printInternal(OS); - if (unsigned Lang = getLanguage()) - OS << " [" << dwarf::LanguageString(Lang) << ']'; + if (const char *Lang = dwarf::LanguageString(getLanguage())) + OS << " [" << Lang << ']'; } void DIEnumerator::printInternal(raw_ostream &OS) const { -- cgit v1.2.3-18-g5258 From f839eed5ea2bfd395256d60e15d1e31dbad6ca8b Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 4 Feb 2013 05:56:36 +0000 Subject: [DebugInfo] remove more node indirection (this time from the subprogram's variable lists) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174305 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index ecaab1fd65..a59fdcd4de 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -593,17 +593,14 @@ unsigned DISubprogram::isOptimized() const { MDNode *DISubprogram::getVariablesNodes() const { if (!DbgNode || DbgNode->getNumOperands() <= 19) return NULL; - if (MDNode *Temp = dyn_cast_or_null(DbgNode->getOperand(19))) - return dyn_cast_or_null(Temp->getOperand(0)); - return NULL; + return dyn_cast_or_null(DbgNode->getOperand(19)); } DIArray DISubprogram::getVariables() const { if (!DbgNode || DbgNode->getNumOperands() <= 19) return DIArray(); if (MDNode *T = dyn_cast_or_null(DbgNode->getOperand(19))) - if (MDNode *A = dyn_cast_or_null(T->getOperand(0))) - return DIArray(A); + return DIArray(T); return DIArray(); } -- cgit v1.2.3-18-g5258 From 6643868498043d373384e0befaff3b5a8a8574f7 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 11 Mar 2013 23:21:19 +0000 Subject: Add asserts to DIBuilder & fix DINameSpace::Verify to allow unnamed namespaces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176837 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index a59fdcd4de..9a5e47318a 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -517,8 +517,6 @@ bool DILocation::Verify() const { bool DINameSpace::Verify() const { if (!DbgNode) return false; - if (getName().empty()) - return false; return true; } -- cgit v1.2.3-18-g5258 From c0ec8a4f4db3c579dfc8c219dc39014f34260b42 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 11 Mar 2013 23:39:23 +0000 Subject: Remove support for versioned debug info. Versioned debug info support has been a burden to maintain & also compromised current debug info verification by causing test cases testing old debug info to remain rather than being updated to the latest. It also makes it hard to add or change the metadata schema by requiring various backwards-compatibility in the DI* hierarchy. So it's being removed in preparation for new changes to the schema to tidy up old/unnecessary fields and add new fields needed for new debug info (well, new to LLVM at least). The more surprising part of this is the changes to DI*::Verify - this became necessary due to the changes to AsmWriter. AsmWriter was relying on the version test to decide which bits of metadata were actually debug info when printing the comment annotations. Without the version information the tag numbers were too common & it would print debug info on random metadata that happened to start with an integer that matched a tag number. Instead this change makes the Verify functions more precise (just adding "number of operands" checks - not type checking those operands yet) & relies on that to decide which metadata is debug info metadata. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176838 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/DebugInfo.cpp | 180 ++++++++++++++++++++++++--------------------------- 1 file changed, 86 insertions(+), 94 deletions(-) (limited to 'lib/IR/DebugInfo.cpp') diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 9a5e47318a..e85d4adf77 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -51,6 +51,21 @@ DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { } +bool DIDescriptor::Verify() const { + return DbgNode && + (DIDerivedType(DbgNode).Verify() || + DICompositeType(DbgNode).Verify() || DIBasicType(DbgNode).Verify() || + DIVariable(DbgNode).Verify() || DISubprogram(DbgNode).Verify() || + DIGlobalVariable(DbgNode).Verify() || DIFile(DbgNode).Verify() || + DICompileUnit(DbgNode).Verify() || DINameSpace(DbgNode).Verify() || + DILexicalBlock(DbgNode).Verify() || + DILexicalBlockFile(DbgNode).Verify() || + DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() || + DIObjCProperty(DbgNode).Verify() || + DITemplateTypeParameter(DbgNode).Verify() || + DITemplateValueParameter(DbgNode).Verify()); +} + StringRef DIDescriptor::getStringField(unsigned Elt) const { if (DbgNode == 0) @@ -135,17 +150,11 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { } unsigned DIVariable::getNumAddrElements() const { - if (getVersion() <= LLVMDebugVersion8) - return DbgNode->getNumOperands()-6; - if (getVersion() == 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() <= LLVMDebugVersion9) - return NULL; return dyn_cast_or_null(DbgNode->getOperand(7)); } @@ -392,31 +401,30 @@ bool DIType::isUnsignedDIType() { /// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { - if (!DbgNode) + if (!isCompileUnit()) return false; StringRef N = getFilename(); if (N.empty()) return false; // It is possible that directory and produce string is empty. - return true; + return DbgNode->getNumOperands() == 15; } /// Verify - Verify that an ObjC property is well formed. bool DIObjCProperty::Verify() const { - if (!DbgNode) + if (!isObjCProperty()) return false; - unsigned Tag = getTag(); - if (Tag != dwarf::DW_TAG_APPLE_property) return false; + DIType Ty = getType(); if (!Ty.Verify()) return false; // Don't worry about the rest of the strings for now. - return true; + return DbgNode->getNumOperands() == 8; } /// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { - if (!DbgNode) + if (!isType()) return false; if (getContext() && !getContext().Verify()) return false; @@ -437,27 +445,28 @@ bool DIType::Verify() const { /// Verify - Verify that a basic type descriptor is well formed. bool DIBasicType::Verify() const { - return isBasicType(); + return isBasicType() && DbgNode->getNumOperands() == 10; } /// Verify - Verify that a derived type descriptor is well formed. bool DIDerivedType::Verify() const { - return isDerivedType(); + return isDerivedType() && DbgNode->getNumOperands() >= 10 && + DbgNode->getNumOperands() <= 14; } /// Verify - Verify that a composite type descriptor is well formed. bool DICompositeType::Verify() const { - if (!DbgNode) + if (!isCompositeType()) return false; if (getContext() && !getContext().Verify()) return false; - return true; + return DbgNode->getNumOperands() >= 10 && DbgNode->getNumOperands() <= 14; } /// Verify - Verify that a subprogram descriptor is well formed. bool DISubprogram::Verify() const { - if (!DbgNode) + if (!isSubprogram()) return false; if (getContext() && !getContext().Verify()) @@ -466,12 +475,12 @@ bool DISubprogram::Verify() const { DICompositeType Ty = getType(); if (!Ty.Verify()) return false; - return true; + return DbgNode->getNumOperands() == 21; } /// Verify - Verify that a global variable descriptor is well formed. bool DIGlobalVariable::Verify() const { - if (!DbgNode) + if (!isGlobalVariable()) return false; if (getDisplayName().empty()) @@ -487,12 +496,12 @@ bool DIGlobalVariable::Verify() const { if (!getGlobal() && !getConstant()) return false; - return true; + return DbgNode->getNumOperands() == 13; } /// Verify - Verify that a variable descriptor is well formed. bool DIVariable::Verify() const { - if (!DbgNode) + if (!isVariable()) return false; if (getContext() && !getContext().Verify()) @@ -502,7 +511,7 @@ bool DIVariable::Verify() const { if (!Ty.Verify()) return false; - return true; + return DbgNode->getNumOperands() >= 8; } /// Verify - Verify that a location descriptor is well formed. @@ -515,9 +524,44 @@ bool DILocation::Verify() const { /// Verify - Verify that a namespace descriptor is well formed. bool DINameSpace::Verify() const { - if (!DbgNode) + if (!isNameSpace()) return false; - return true; + return DbgNode->getNumOperands() == 5; +} + +/// \brief Verify that the file descriptor is well formed. +bool DIFile::Verify() const { + return isFile() && DbgNode->getNumOperands() == 4; +} + +/// \brief Verify that the enumerator descriptor is well formed. +bool DIEnumerator::Verify() const { + return isEnumerator() && DbgNode->getNumOperands() == 3; +} + +/// \brief Verify that the subrange descriptor is well formed. +bool DISubrange::Verify() const { + return isSubrange() && DbgNode->getNumOperands() == 3; +} + +/// \brief Verify that the lexical block descriptor is well formed. +bool DILexicalBlock::Verify() const { + return isLexicalBlock() && DbgNode->getNumOperands() == 6; +} + +/// \brief Verify that the file-scoped lexical block descriptor is well formed. +bool DILexicalBlockFile::Verify() const { + return isLexicalBlockFile() && DbgNode->getNumOperands() == 3; +} + +/// \brief Verify that the template type parameter descriptor is well formed. +bool DITemplateTypeParameter::Verify() const { + return isTemplateTypeParameter() && DbgNode->getNumOperands() == 7; +} + +/// \brief Verify that the template value parameter descriptor is well formed. +bool DITemplateValueParameter::Verify() const { + return isTemplateValueParameter() && DbgNode->getNumOperands() == 8; } /// getOriginalTypeSize - If this type is derived from a base type then @@ -551,7 +595,7 @@ uint64_t DIDerivedType::getOriginalTypeSize() const { /// getObjCProperty - Return property node, if this ivar is associated with one. MDNode *DIDerivedType::getObjCProperty() const { - if (getVersion() <= LLVMDebugVersion11 || DbgNode->getNumOperands() <= 10) + if (DbgNode->getNumOperands() <= 10) return NULL; return dyn_cast_or_null(DbgNode->getOperand(10)); } @@ -803,71 +847,25 @@ void DebugInfoFinder::processModule(const Module &M) { for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit CU(CU_Nodes->getOperand(i)); addCompileUnit(CU); - if (CU.getVersion() > LLVMDebugVersion10) { - DIArray GVs = CU.getGlobalVariables(); - for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { - DIGlobalVariable DIG(GVs.getElement(i)); - if (addGlobalVariable(DIG)) - processType(DIG.getType()); - } - DIArray SPs = CU.getSubprograms(); - for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) - processSubprogram(DISubprogram(SPs.getElement(i))); - DIArray EnumTypes = CU.getEnumTypes(); - for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - processType(DIType(EnumTypes.getElement(i))); - DIArray RetainedTypes = CU.getRetainedTypes(); - for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) - processType(DIType(RetainedTypes.getElement(i))); - return; - } - } - } - - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - for (Function::const_iterator FI = (*I).begin(), FE = (*I).end(); - FI != FE; ++FI) - for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); - BI != BE; ++BI) { - if (const DbgDeclareInst *DDI = dyn_cast(BI)) - processDeclare(DDI); - - DebugLoc Loc = BI->getDebugLoc(); - if (Loc.isUnknown()) - continue; - - LLVMContext &Ctx = BI->getContext(); - DIDescriptor Scope(Loc.getScope(Ctx)); - - if (Scope.isCompileUnit()) - addCompileUnit(DICompileUnit(Scope)); - else if (Scope.isSubprogram()) - processSubprogram(DISubprogram(Scope)); - else if (Scope.isLexicalBlockFile()) { - DILexicalBlockFile DBF = DILexicalBlockFile(Scope); - processLexicalBlock(DILexicalBlock(DBF.getScope())); - } - 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)) { - if (DIG.getVersion() <= LLVMDebugVersion10) - addCompileUnit(DIG.getCompileUnit()); - processType(DIG.getType()); + DIArray GVs = CU.getGlobalVariables(); + for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { + DIGlobalVariable DIG(GVs.getElement(i)); + if (addGlobalVariable(DIG)) + processType(DIG.getType()); } + DIArray SPs = CU.getSubprograms(); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) + processSubprogram(DISubprogram(SPs.getElement(i))); + DIArray EnumTypes = CU.getEnumTypes(); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) + processType(DIType(EnumTypes.getElement(i))); + DIArray RetainedTypes = CU.getRetainedTypes(); + for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) + processType(DIType(RetainedTypes.getElement(i))); + // FIXME: We really shouldn't be bailing out after visiting just one CU + return; } } - - 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. @@ -891,8 +889,6 @@ void DebugInfoFinder::processLocation(DILocation Loc) { void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; - if (DT.getVersion() <= LLVMDebugVersion10) - addCompileUnit(DT.getCompileUnit()); if (DT.isCompositeType()) { DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom()); @@ -927,8 +923,6 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; - if (SP.getVersion() <= LLVMDebugVersion10) - addCompileUnit(SP.getCompileUnit()); processType(SP.getType()); } @@ -943,8 +937,6 @@ void DebugInfoFinder::processDeclare(const DbgDeclareInst *DDI) { if (!NodesSeen.insert(DV)) return; - if (DIVariable(N).getVersion() <= LLVMDebugVersion10) - addCompileUnit(DIVariable(N).getCompileUnit()); processType(DIVariable(N).getType()); } -- cgit v1.2.3-18-g5258