X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FIR%2FDebugInfo.cpp;h=70a6722568591129b69b732595f2ea3baa994c3a;hp=4e36a8df3e1efd4314c21538995c39672d8ea421;hb=8d8c981a1f20a5454a4abeffa64942aa0e94d0c5;hpb=076fd5dfc1f0600183bbc7db974dc7b39086136d diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 4e36a8df3e1..70a67225685 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/GVMaterializer.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" @@ -32,713 +33,69 @@ using namespace llvm; using namespace llvm::dwarf; -//===----------------------------------------------------------------------===// -// DIDescriptor -//===----------------------------------------------------------------------===// - -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() || - DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify()); -} - -static Value *getField(const MDNode *DbgNode, unsigned Elt) { - if (!DbgNode || Elt >= DbgNode->getNumOperands()) - return nullptr; - return DbgNode->getOperand(Elt); -} - -static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { - return dyn_cast_or_null(getField(DbgNode, Elt)); -} - -static StringRef getStringField(const MDNode *DbgNode, unsigned Elt) { - if (MDString *MDS = dyn_cast_or_null(getField(DbgNode, Elt))) - return MDS->getString(); - return StringRef(); -} - -StringRef DIDescriptor::getStringField(unsigned Elt) const { - return ::getStringField(DbgNode, Elt); -} - -uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { - if (!DbgNode) - 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) - 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 { - MDNode *Field = getNodeField(DbgNode, Elt); - return DIDescriptor(Field); -} - -GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); - return nullptr; -} - -Constant *DIDescriptor::getConstantField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); - return nullptr; -} - -Function *DIDescriptor::getFunctionField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); - return nullptr; -} - -void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { - if (!DbgNode) - return; - - if (Elt < DbgNode->getNumOperands()) { - MDNode *Node = const_cast(DbgNode); - Node->replaceOperandWith(Elt, F); - } -} - -/// getInlinedAt - If this variable is inlined then return inline location. -MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); } - -/// Return the size reported by the variable's type. +/// \brief Return the size reported by the variable's type. unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) { DIType Ty = getType().resolve(Map); // Follow derived types until we reach a type that // reports back a size. - while (Ty.isDerivedType() && !Ty.getSizeInBits()) { - DIDerivedType DT(&*Ty); + while (isa(Ty) && !Ty.getSizeInBits()) { + DIDerivedType DT = cast(Ty); Ty = DT.getTypeDerivedFrom().resolve(Map); } assert(Ty.getSizeInBits() && "type with size 0"); return Ty.getSizeInBits(); } -uint64_t DIExpression::getElement(unsigned Idx) const { - unsigned I = Idx + 1; - if (I < DbgNode->getNumOperands()) - if (auto *CI = dyn_cast_or_null(DbgNode->getOperand(I))) - return CI->getZExtValue(); - - assert(false && "non-existing complex address element requested"); - return 0; -} - -bool DIExpression::isVariablePiece() const { - return getNumElements() && getElement(0) == dwarf::DW_OP_piece; -} - -uint64_t DIExpression::getPieceOffset() const { - assert(isVariablePiece()); - return getElement(1); -} - -uint64_t DIExpression::getPieceSize() const { - assert(isVariablePiece()); - return getElement(2); -} - -//===----------------------------------------------------------------------===// -// Predicates -//===----------------------------------------------------------------------===// - -bool DIDescriptor::isSubroutineType() const { - return isCompositeType() && getTag() == dwarf::DW_TAG_subroutine_type; -} - -/// 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_ptr_to_member_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_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: - 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); -} - -/// 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: - case dwarf::DW_TAG_file_type: - return true; - default: - break; - } - return isType(); -} - -/// 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 || - getTag() == dwarf::DW_TAG_GNU_template_template_param || - getTag() == dwarf::DW_TAG_GNU_template_parameter_pack); -} - -/// 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() == 4); -} - -/// 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_APPLE_property. -bool DIDescriptor::isObjCProperty() const { - return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; -} - -/// \brief Return true if the specified tag is DW_TAG_imported_module or -/// DW_TAG_imported_declaration. -bool DIDescriptor::isImportedEntity() const { - return DbgNode && (getTag() == dwarf::DW_TAG_imported_module || - getTag() == dwarf::DW_TAG_imported_declaration); -} - -/// \brief Return true if the specified tag is DW_TAG_imported_module or -/// DW_TAG_imported_declaration. -bool DIDescriptor::isExpression() const { - return DbgNode && (getTag() == dwarf::DW_TAG_expression); -} - //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in the passed descriptor. -void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { - +void DIDescriptor::replaceAllUsesWith(LLVMContext &, DIDescriptor D) { assert(DbgNode && "Trying to replace an unverified type!"); + assert(DbgNode->isTemporary() && "Expected temporary node"); + TempMDNode Temp(get()); // 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. - const MDNode *DN = D; - if (DbgNode == DN) { - SmallVector Ops(DbgNode->getNumOperands()); - for (size_t i = 0; i != Ops.size(); ++i) - Ops[i] = DbgNode->getOperand(i); - DN = MDNode::get(VMContext, Ops); + if (Temp.get() == D.get()) { + DbgNode = MDNode::replaceWithUniqued(std::move(Temp)); + return; } - MDNode *Node = const_cast(DbgNode); - const Value *V = cast_or_null(DN); - Node->replaceAllUsesWith(const_cast(V)); - MDNode::deleteTemporary(Node); - DbgNode = DN; + Temp->replaceAllUsesWith(D.get()); + DbgNode = D.get(); } -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in D. void DIDescriptor::replaceAllUsesWith(MDNode *D) { - assert(DbgNode && "Trying to replace an unverified type!"); assert(DbgNode != D && "This replacement should always happen"); - MDNode *Node = const_cast(DbgNode); - const MDNode *DN = D; - const Value *V = cast_or_null(DN); - Node->replaceAllUsesWith(const_cast(V)); - MDNode::deleteTemporary(Node); -} - -/// Verify - Verify that a compile unit is well formed. -bool DICompileUnit::Verify() const { - if (!isCompileUnit()) - return false; - - // Don't bother verifying the compilation directory or producer string - // as those could be empty. - if (getFilename().empty()) - return false; - - return DbgNode->getNumOperands() == 14; -} - -/// Verify - Verify that an ObjC property is well formed. -bool DIObjCProperty::Verify() const { - if (!isObjCProperty()) - return false; - - // Don't worry about the rest of the strings for now. - return DbgNode->getNumOperands() == 8; -} - -/// Check if a field at position Elt of a MDNode is a MDNode. -/// We currently allow an empty string and an integer. -/// But we don't allow a non-empty string in a MDNode field. -static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) { - // FIXME: This function should return true, if the field is null or the field - // is indeed a MDNode: return !Fld || isa(Fld). - Value *Fld = getField(DbgNode, Elt); - if (Fld && isa(Fld) && !cast(Fld)->getString().empty()) - return false; - return true; -} - -/// Check if a field at position Elt of a MDNode is a MDString. -static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return !Fld || isa(Fld); -} - -/// Check if a value can be a reference to a type. -static bool isTypeRef(const Value *Val) { - return !Val || - (isa(Val) && !cast(Val)->getString().empty()) || - (isa(Val) && DIType(cast(Val)).isType()); -} - -/// Check if a field at position Elt of a MDNode can be a reference to a type. -static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isTypeRef(Fld); -} - -/// Check if a value can be a ScopeRef. -static bool isScopeRef(const Value *Val) { - return !Val || - (isa(Val) && !cast(Val)->getString().empty()) || - // Not checking for Val->isScope() here, because it would work - // only for lexical scopes and not all subclasses of DIScope. - isa(Val); -} - -/// Check if a field at position Elt of a MDNode can be a ScopeRef. -static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isScopeRef(Fld); -} - -/// Verify - Verify that a type descriptor is well formed. -bool DIType::Verify() const { - if (!isType()) - return false; - // Make sure Context @ field 2 is MDNode. - if (!fieldIsScopeRef(DbgNode, 2)) - return false; - - // FIXME: Sink this into the various subclass verifies. - uint16_t 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_array_type && - Tag != dwarf::DW_TAG_enumeration_type && - Tag != dwarf::DW_TAG_subroutine_type && - Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend && - getFilename().empty()) - return false; - - // DIType is abstract, it should be a BasicType, a DerivedType or - // a CompositeType. - if (isBasicType()) - return DIBasicType(DbgNode).Verify(); - else if (isCompositeType()) - return DICompositeType(DbgNode).Verify(); - else if (isDerivedType()) - return DIDerivedType(DbgNode).Verify(); - else - return false; -} - -/// Verify - Verify that a basic type descriptor is well formed. -bool DIBasicType::Verify() const { - return isBasicType() && DbgNode->getNumOperands() == 10; -} - -/// Verify - Verify that a derived type descriptor is well formed. -bool DIDerivedType::Verify() const { - // Make sure DerivedFrom @ field 9 is TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) - return false; - if (getTag() == dwarf::DW_TAG_ptr_to_member_type) - // Make sure ClassType @ field 10 is a TypeRef. - if (!fieldIsTypeRef(DbgNode, 10)) - return false; - - return isDerivedType() && DbgNode->getNumOperands() >= 10 && - DbgNode->getNumOperands() <= 14; -} - -/// Verify - Verify that a composite type descriptor is well formed. -bool DICompositeType::Verify() const { - if (!isCompositeType()) - return false; - - // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) - return false; - if (!fieldIsTypeRef(DbgNode, 12)) - return false; - - // Make sure the type identifier at field 14 is MDString, it can be null. - if (!fieldIsMDString(DbgNode, 14)) - return false; - - // A subroutine type can't be both & and &&. - if (isLValueReference() && isRValueReference()) - return false; - - return DbgNode->getNumOperands() == 15; -} - -/// Verify - Verify that a subprogram descriptor is well formed. -bool DISubprogram::Verify() const { - if (!isSubprogram()) - return false; - - // Make sure context @ field 2 is a ScopeRef and type @ field 7 is a MDNode. - if (!fieldIsScopeRef(DbgNode, 2)) - return false; - if (!fieldIsMDNode(DbgNode, 7)) - return false; - // Containing type @ field 12. - if (!fieldIsTypeRef(DbgNode, 12)) - return false; - - // A subprogram can't be both & and &&. - if (isLValueReference() && isRValueReference()) - return false; - - return DbgNode->getNumOperands() == 20; -} - -/// Verify - Verify that a global variable descriptor is well formed. -bool DIGlobalVariable::Verify() const { - if (!isGlobalVariable()) - return false; - - if (getDisplayName().empty()) - return false; - // Make sure context @ field 2 is an MDNode. - if (!fieldIsMDNode(DbgNode, 2)) - return false; - // Make sure that type @ field 8 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 8)) - return false; - // Make sure StaticDataMemberDeclaration @ field 12 is MDNode. - if (!fieldIsMDNode(DbgNode, 12)) - return false; - - return DbgNode->getNumOperands() == 13; -} - -/// Verify - Verify that a variable descriptor is well formed. -bool DIVariable::Verify() const { - if (!isVariable()) - return false; - - // Make sure context @ field 1 is an MDNode. - if (!fieldIsMDNode(DbgNode, 1)) - return false; - // Make sure that type @ field 5 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 5)) - return false; - - // Variable without an inline location. - if (DbgNode->getNumOperands() == 7) - return true; - - return DbgNode->getNumOperands() == 8; -} - -/// Verify - Verify that a variable descriptor is well formed. -bool DIExpression::Verify() const { return isExpression(); } - -/// 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 (!isNameSpace()) - return false; - return DbgNode->getNumOperands() == 5; -} - -/// \brief Retrieve the MDNode for the directory/file pair. -MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); } - -/// \brief Verify that the file descriptor is well formed. -bool DIFile::Verify() const { - return isFile() && DbgNode->getNumOperands() == 2; -} - -/// \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() == 4; -} - -/// \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; -} - -/// \brief Verify that the imported module descriptor is well formed. -bool DIImportedEntity::Verify() const { - return isImportedEntity() && - (DbgNode->getNumOperands() == 4 || DbgNode->getNumOperands() == 5); -} - -/// getObjCProperty - Return property node, if this ivar is associated with one. -MDNode *DIDerivedType::getObjCProperty() const { - return getNodeField(DbgNode, 10); -} - -MDString *DICompositeType::getIdentifier() const { - return cast_or_null(getField(DbgNode, 14)); -} - -#ifndef NDEBUG -static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) { - for (unsigned i = 0; i != LHS->getNumOperands(); ++i) { - // Skip the 'empty' list (that's a single i32 0, rather than truly empty). - if (i == 0 && isa(LHS->getOperand(i))) - continue; - const MDNode *E = cast(LHS->getOperand(i)); - bool found = false; - for (unsigned j = 0; !found && j != RHS->getNumOperands(); ++j) - found = E == RHS->getOperand(j); - assert(found && "Losing a member during member list replacement"); - } -} -#endif - -/// \brief Set the array of member DITypes. -void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) { - TrackingVH N(*this); - if (Elements) { -#ifndef NDEBUG - // Check that the new list of members contains all the old members as well. - if (const MDNode *El = cast_or_null(N->getOperand(10))) - VerifySubsetOf(El, Elements); -#endif - N->replaceOperandWith(10, Elements); - } - if (TParams) - N->replaceOperandWith(13, TParams); - DbgNode = N; -} - -/// Generate a reference to this DIType. Uses the type identifier instead -/// of the actual MDNode if possible, to help type uniquing. -DIScopeRef DIScope::getRef() const { - if (!isCompositeType()) - return DIScopeRef(*this); - DICompositeType DTy(DbgNode); - if (!DTy.getIdentifier()) - return DIScopeRef(*this); - return DIScopeRef(DTy.getIdentifier()); + assert(DbgNode->isTemporary() && "Expected temporary node"); + TempMDNode Node(get()); + Node->replaceAllUsesWith(D); } -/// \brief Set the containing type. -void DICompositeType::setContainingType(DICompositeType ContainingType) { - TrackingVH N(*this); - N->replaceOperandWith(12, ContainingType.getRef()); - DbgNode = N; -} +DIScopeRef DIScope::getRef() const { return MDScopeRef::get(get()); } -/// 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()) + DISubprogram SP = dyn_cast(getContext()); + if (!SP) return false; // This variable is not inlined function argument if its scope // does not describe current function. - return !DISubprogram(getContext()).describes(CurFn); + return !SP.describes(CurFn); +} + +Function *DISubprogram::getFunction() const { + if (auto *N = get()) + if (auto *C = dyn_cast_or_null(N->getFunction())) + return dyn_cast(C->getValue()); + return nullptr; } -/// 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()) @@ -751,239 +108,136 @@ bool DISubprogram::describes(const Function *F) { return false; } -unsigned DISubprogram::isOptimized() const { - assert(DbgNode && "Invalid subprogram descriptor!"); - if (DbgNode->getNumOperands() == 15) - return getUnsignedField(14); - return 0; -} - -MDNode *DISubprogram::getVariablesNodes() const { - return getNodeField(DbgNode, 18); -} - -DIArray DISubprogram::getVariables() const { - return DIArray(getNodeField(DbgNode, 18)); +GlobalVariable *DIGlobalVariable::getGlobal() const { + return dyn_cast_or_null(getConstant()); } -Value *DITemplateValueParameter::getValue() const { - return getField(DbgNode, 4); -} - -// If the current node has a parent scope then return that, -// else return an empty scope. DIScopeRef DIScope::getContext() const { + if (DIType T = dyn_cast(*this)) + return T.getContext(); - if (isType()) - return DIType(DbgNode).getContext(); - - if (isSubprogram()) - return DIScopeRef(DISubprogram(DbgNode).getContext()); + if (DISubprogram SP = dyn_cast(*this)) + return MDScopeRef(SP.getContext()); - if (isLexicalBlock()) - return DIScopeRef(DILexicalBlock(DbgNode).getContext()); + if (DILexicalBlock LB = dyn_cast(*this)) + return MDScopeRef(LB.getContext()); - if (isLexicalBlockFile()) - return DIScopeRef(DILexicalBlockFile(DbgNode).getContext()); + if (DINameSpace NS = dyn_cast(*this)) + return MDScopeRef(NS.getContext()); - if (isNameSpace()) - return DIScopeRef(DINameSpace(DbgNode).getContext()); - - assert((isFile() || isCompileUnit()) && "Unhandled type of scope."); - return DIScopeRef(nullptr); + assert((isa(*this) || isa(*this)) && + "Unhandled type of scope."); + return MDScopeRef(); } -// If the scope node has a name, return that, else return an empty string. StringRef DIScope::getName() const { - if (isType()) - return DIType(DbgNode).getName(); - if (isSubprogram()) - return DISubprogram(DbgNode).getName(); - if (isNameSpace()) - return DINameSpace(DbgNode).getName(); - assert((isLexicalBlock() || isLexicalBlockFile() || isFile() || - isCompileUnit()) && + if (DIType T = dyn_cast(*this)) + return T.getName(); + if (DISubprogram SP = dyn_cast(*this)) + return SP.getName(); + if (DINameSpace NS = dyn_cast(*this)) + return NS.getName(); + assert((isa(*this) || isa(*this) || + isa(*this)) && "Unhandled type of scope."); return StringRef(); } StringRef DIScope::getFilename() const { - if (!DbgNode) - return StringRef(); - return ::getStringField(getNodeField(DbgNode, 1), 0); + if (auto *N = get()) + if (auto *F = N->getFile()) + return F->getFilename(); + return ""; } StringRef DIScope::getDirectory() const { - if (!DbgNode) - return StringRef(); - return ::getStringField(getNodeField(DbgNode, 1), 1); -} - -DIArray DICompileUnit::getEnumTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 7)); + if (auto *N = get()) + if (auto *F = N->getFile()) + return F->getDirectory(); + return ""; } -DIArray DICompileUnit::getRetainedTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 8)); -} - -DIArray DICompileUnit::getSubprograms() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 9)); +void DICompileUnit::replaceSubprograms(DIArray Subprograms) { + get()->replaceSubprograms(MDSubprogramArray(Subprograms)); } -DIArray DICompileUnit::getGlobalVariables() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 10)); +void DICompileUnit::replaceGlobalVariables(DIArray GlobalVariables) { + get()->replaceGlobalVariables(MDGlobalVariableArray(GlobalVariables)); } -DIArray DICompileUnit::getImportedEntities() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 11)); -} - -/// copyWithNewScope - Return a copy of this location, replacing the -/// current scope with the given one. DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope) { - SmallVector Elts; - assert(Verify()); - for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) { - if (I != 2) - Elts.push_back(DbgNode->getOperand(I)); - else - Elts.push_back(NewScope); - } - MDNode *NewDIL = MDNode::get(Ctx, Elts); - return DILocation(NewDIL); + assert(NewScope && "Expected valid scope"); + + const auto *Old = cast(DbgNode); + return DILocation(MDLocation::get(Ctx, Old->getLine(), Old->getColumn(), + NewScope, Old->getInlinedAt())); } -/// computeNewDiscriminator - Generate a new discriminator value for this -/// file and line location. unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { std::pair Key(getFilename().data(), getLineNumber()); return ++Ctx.pImpl->DiscriminatorTable[Key]; } -/// fixupSubprogramName - Replace contains special characters used -/// in a typical Objective-C names with '.' in a given string. -static void fixupSubprogramName(DISubprogram Fn, SmallVectorImpl &Out) { - StringRef FName = - Fn.getFunction() ? Fn.getFunction()->getName() : Fn.getName(); - FName = Function::getRealLinkageName(FName); - - StringRef Prefix("llvm.dbg.lv."); - Out.reserve(FName.size() + Prefix.size()); - Out.append(Prefix.begin(), Prefix.end()); - - bool isObjCLike = false; - for (size_t i = 0, e = FName.size(); i < e; ++i) { - char C = FName[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; - fixupSubprogramName(Fn, 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; - fixupSubprogramName(Fn, 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)); + return cast(DV) + ->withInline(cast_or_null(InlinedScope)); } -/// 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)); + return cast(DV)->withoutInline(); } -/// 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 (auto *LocalScope = dyn_cast_or_null(Scope)) + return LocalScope->getSubprogram(); + return nullptr; +} - if (D.isLexicalBlock()) - return getDISubprogram(DILexicalBlock(Scope).getContext()); +DISubprogram llvm::getDISubprogram(const Function *F) { + // We look for the first instr that has a debug annotation leading back to F. + for (auto &BB : *F) { + auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) { + return Inst.getDebugLoc(); + }); + if (Inst == BB.end()) + continue; + DebugLoc DLoc = Inst->getDebugLoc(); + const MDNode *Scope = DLoc.getInlinedAtScope(); + DISubprogram Subprogram = getDISubprogram(Scope); + return Subprogram.describes(F) ? Subprogram : DISubprogram(); + } return DISubprogram(); } -/// getDICompositeType - Find underlying composite type. DICompositeType llvm::getDICompositeType(DIType T) { - if (T.isCompositeType()) - return DICompositeType(T); + if (auto *C = dyn_cast_or_null(T)) + return C; - if (T.isDerivedType()) { + if (auto *D = dyn_cast_or_null(T)) { // This function is currently used by dragonegg and dragonegg does // not generate identifier for types, so using an empty map to resolve // DerivedFrom should be fine. DITypeIdentifierMap EmptyMap; return getDICompositeType( - DIDerivedType(T).getTypeDerivedFrom().resolve(EmptyMap)); + DIDerivedType(D).getTypeDerivedFrom().resolve(EmptyMap)); } - return DICompositeType(); + return nullptr; } -/// Update DITypeIdentifierMap by going through retained types of each CU. DITypeIdentifierMap llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) { DITypeIdentifierMap Map; for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) { - DICompileUnit CU(CU_Nodes->getOperand(CUi)); + DICompileUnit CU = cast(CU_Nodes->getOperand(CUi)); DIArray Retain = CU.getRetainedTypes(); - for (unsigned Ti = 0, Te = Retain.getNumElements(); Ti != Te; ++Ti) { - if (!Retain.getElement(Ti).isCompositeType()) + for (unsigned Ti = 0, Te = Retain.size(); Ti != Te; ++Ti) { + if (!isa(Retain[Ti])) continue; - DICompositeType Ty(Retain.getElement(Ti)); + DICompositeType Ty = cast(Retain[Ti]); if (MDString *TypeId = Ty.getIdentifier()) { // Definition has priority over declaration. // Try to insert (TypeId, Ty) to Map. @@ -1022,46 +276,37 @@ void DebugInfoFinder::InitializeTypeMap(const Module &M) { } } -/// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(const Module &M) { InitializeTypeMap(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)); + DICompileUnit CU = cast(CU_Nodes->getOperand(i)); addCompileUnit(CU); - DIArray GVs = CU.getGlobalVariables(); - for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { - DIGlobalVariable DIG(GVs.getElement(i)); + for (DIGlobalVariable DIG : CU->getGlobalVariables()) { if (addGlobalVariable(DIG)) { processScope(DIG.getContext()); processType(DIG.getType().resolve(TypeIdentifierMap)); } } - 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))); - DIArray Imports = CU.getImportedEntities(); - for (unsigned i = 0, e = Imports.getNumElements(); i != e; ++i) { - DIImportedEntity Import = DIImportedEntity(Imports.getElement(i)); + for (auto *SP : CU->getSubprograms()) + processSubprogram(SP); + for (auto *ET : CU->getEnumTypes()) + processType(ET); + for (auto *RT : CU->getRetainedTypes()) + processType(RT); + for (DIImportedEntity Import : CU->getImportedEntities()) { DIDescriptor Entity = Import.getEntity().resolve(TypeIdentifierMap); - if (Entity.isType()) - processType(DIType(Entity)); - else if (Entity.isSubprogram()) - processSubprogram(DISubprogram(Entity)); - else if (Entity.isNameSpace()) - processScope(DINameSpace(Entity).getContext()); + if (auto *T = dyn_cast(Entity)) + processType(T); + else if (auto *SP = dyn_cast(Entity)) + processSubprogram(SP); + else if (auto *NS = dyn_cast(Entity)) + processScope(NS->getScope()); } } } } -/// processLocation - Process DILocation. void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { if (!Loc) return; @@ -1070,84 +315,68 @@ void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { processLocation(M, Loc.getOrigLocation()); } -/// processType - Process DIType. void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; processScope(DT.getContext().resolve(TypeIdentifierMap)); - if (DT.isCompositeType()) { - DICompositeType DCT(DT); + if (DICompositeType DCT = dyn_cast(DT)) { processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); - if (DT.isSubroutineType()) { - DITypeArray DTA = DISubroutineType(DT).getTypeArray(); - for (unsigned i = 0, e = DTA.getNumElements(); i != e; ++i) - processType(DTA.getElement(i).resolve(TypeIdentifierMap)); + if (DISubroutineType ST = dyn_cast(DCT)) { + for (MDTypeRef Ref : ST->getTypeArray()) + processType(Ref.resolve(TypeIdentifierMap)); return; } - DIArray DA = DCT.getElements(); - 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)); + for (Metadata *D : DCT->getElements()->operands()) { + if (DIType T = dyn_cast(D)) + processType(T); + else if (DISubprogram SP = dyn_cast(D)) + processSubprogram(SP); } - } else if (DT.isDerivedType()) { - DIDerivedType DDT(DT); + } else if (DIDerivedType DDT = dyn_cast(DT)) { processType(DDT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); } } void DebugInfoFinder::processScope(DIScope Scope) { - if (Scope.isType()) { - DIType Ty(Scope); + if (!Scope) + return; + if (DIType Ty = dyn_cast(Scope)) { processType(Ty); return; } - if (Scope.isCompileUnit()) { - addCompileUnit(DICompileUnit(Scope)); + if (DICompileUnit CU = dyn_cast(Scope)) { + addCompileUnit(CU); return; } - if (Scope.isSubprogram()) { - processSubprogram(DISubprogram(Scope)); + if (DISubprogram SP = dyn_cast(Scope)) { + processSubprogram(SP); return; } if (!addScope(Scope)) return; - if (Scope.isLexicalBlock()) { - DILexicalBlock LB(Scope); + if (DILexicalBlock LB = dyn_cast(Scope)) { processScope(LB.getContext()); - } else if (Scope.isLexicalBlockFile()) { - DILexicalBlockFile LBF = DILexicalBlockFile(Scope); - processScope(LBF.getScope()); - } else if (Scope.isNameSpace()) { - DINameSpace NS(Scope); + } else if (DINameSpace NS = dyn_cast(Scope)) { processScope(NS.getContext()); } } -/// processSubprogram - Process DISubprogram. void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; processScope(SP.getContext().resolve(TypeIdentifierMap)); processType(SP.getType()); - DIArray TParams = SP.getTemplateParams(); - for (unsigned I = 0, E = TParams.getNumElements(); I != E; ++I) { - DIDescriptor Element = TParams.getElement(I); - if (Element.isTemplateTypeParameter()) { - DITemplateTypeParameter TType(Element); - processScope(TType.getContext().resolve(TypeIdentifierMap)); + for (auto *Element : SP.getTemplateParams()) { + if (DITemplateTypeParameter TType = + dyn_cast(Element)) { processType(TType.getType().resolve(TypeIdentifierMap)); - } else if (Element.isTemplateValueParameter()) { - DITemplateValueParameter TVal(Element); - processScope(TVal.getContext().resolve(TypeIdentifierMap)); + } else if (DITemplateValueParameter TVal = + dyn_cast(Element)) { processType(TVal.getType().resolve(TypeIdentifierMap)); } } } -/// processDeclare - Process DbgDeclareInst. void DebugInfoFinder::processDeclare(const Module &M, const DbgDeclareInst *DDI) { MDNode *N = dyn_cast(DDI->getVariable()); @@ -1155,14 +384,14 @@ void DebugInfoFinder::processDeclare(const Module &M, return; InitializeTypeMap(M); - DIDescriptor DV(N); - if (!DV.isVariable()) + DIVariable DV = dyn_cast(N); + if (!DV) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; - processScope(DIVariable(N).getContext()); - processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); + processScope(DV.getContext()); + processType(DV.getType().resolve(TypeIdentifierMap)); } void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) { @@ -1171,57 +400,53 @@ void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) { return; InitializeTypeMap(M); - DIDescriptor DV(N); - if (!DV.isVariable()) + DIVariable DV = dyn_cast(N); + if (!DV) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; - processScope(DIVariable(N).getContext()); - processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); + processScope(DV.getContext()); + processType(DV.getType().resolve(TypeIdentifierMap)); } -/// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { if (!DT) return false; - if (!NodesSeen.insert(DT)) + if (!NodesSeen.insert(DT).second) return false; TYs.push_back(DT); return true; } -/// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { if (!CU) return false; - if (!NodesSeen.insert(CU)) + if (!NodesSeen.insert(CU).second) return false; CUs.push_back(CU); return true; } -/// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { if (!DIG) return false; - if (!NodesSeen.insert(DIG)) + if (!NodesSeen.insert(DIG).second) return false; GVs.push_back(DIG); return true; } -// addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { if (!SP) return false; - if (!NodesSeen.insert(SP)) + if (!NodesSeen.insert(SP).second) return false; SPs.push_back(SP); @@ -1235,7 +460,7 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // as null for now. if (Scope->getNumOperands() == 0) return false; - if (!NodesSeen.insert(Scope)) + if (!NodesSeen.insert(Scope).second) return false; Scopes.push_back(Scope); return true; @@ -1245,247 +470,36 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // 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) + if (!get()) 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->isNameSpace()) { - DINameSpace(DbgNode).printInternal(OS); - } else if (this->isScope()) { - DIScope(DbgNode).printInternal(OS); - } else if (this->isExpression()) { - DIExpression(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); - OS << " ["; - unsigned Lang = getLanguage(); - if (const char *LangStr = dwarf::LanguageString(Lang)) - OS << LangStr; - else - (OS << "lang 0x").write_hex(Lang); - OS << ']'; + get()->print(OS); } -void DIEnumerator::printInternal(raw_ostream &OS) const { - OS << " [" << getName() << " :: " << getEnumValue() << ']'; -} - -void DIType::printInternal(raw_ostream &OS) const { - if (!DbgNode) +static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, + const LLVMContext &Ctx) { + if (!DL) 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]"; - else if (isPublic()) - OS << " [public]"; - - if (isArtificial()) - OS << " [artificial]"; - - if (isForwardDecl()) - OS << " [decl]"; - else if (getTag() == dwarf::DW_TAG_structure_type || - getTag() == dwarf::DW_TAG_union_type || - getTag() == dwarf::DW_TAG_enumeration_type || - getTag() == dwarf::DW_TAG_class_type) - OS << " [def]"; - if (isVector()) - OS << " [vector]"; - if (isStaticMember()) - OS << " [static]"; - - if (isLValueReference()) - OS << " [reference]"; - - if (isRValueReference()) - OS << " [rvalue reference]"; -} - -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 = getElements(); - OS << " [" << A.getNumElements() << " elements]"; -} - -void DINameSpace::printInternal(raw_ostream &OS) const { - StringRef Name = getName(); - if (!Name.empty()) - OS << " [" << Name << ']'; - - OS << " [line " << getLineNumber() << ']'; -} - -void DISubprogram::printInternal(raw_ostream &OS) const { - // TODO : Print context - OS << " [line " << getLineNumber() << ']'; - - if (isLocalToUnit()) - OS << " [local]"; - - if (isDefinition()) - OS << " [def]"; + DIScope Scope = cast(DL.getScope()); + // Omit the directory, because it's likely to be long and uninteresting. + CommentOS << Scope.getFilename(); + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); - if (getScopeLineNumber() != getLineNumber()) - OS << " [scope " << getScopeLineNumber() << "]"; - - if (isPrivate()) - OS << " [private]"; - else if (isProtected()) - OS << " [protected]"; - else if (isPublic()) - OS << " [public]"; - - if (isLValueReference()) - OS << " [reference]"; - - if (isRValueReference()) - OS << " [rvalue reference]"; - - 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 DIExpression::printInternal(raw_ostream &OS) const { - for (unsigned I = 0; I < getNumElements(); ++I) { - uint64_t OpCode = getElement(I); - OS << " [" << OperationEncodingString(OpCode); - switch (OpCode) { - case DW_OP_plus: { - OS << " " << getElement(++I); - break; - } - case DW_OP_piece: { - unsigned Offset = getElement(++I); - unsigned Size = getElement(++I); - OS << " offset=" << Offset << ", size= " << Size; - break; - } - default: - break; - } - OS << "]"; - } -} - -void DIObjCProperty::printInternal(raw_ostream &OS) const { - StringRef Name = getObjCPropertyName(); - if (!Name.empty()) - OS << " [" << Name << ']'; + DebugLoc InlinedAtDL = DL.getInlinedAt(); + if (!InlinedAtDL) + return; - 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)); - assert(Scope.isScope() && "Scope of a DebugLoc should be a DIScope."); - // Omit the directory, because it's likely to be long and uninteresting. - CommentOS << Scope.getFilename(); - 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 << " ]"; - } - } + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, CommentOS, Ctx); + CommentOS << " ]"; } void DIVariable::printExtendedName(raw_ostream &OS) const { @@ -1493,9 +507,8 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { StringRef Res = getName(); if (!Res.empty()) OS << Res << "," << getLineNumber(); - if (MDNode *InlinedAt = getInlinedAt()) { - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); - if (!InlinedAtDL.isUnknown()) { + if (auto *InlinedAt = get()->getInlinedAt()) { + if (DebugLoc InlinedAtDL = InlinedAt) { OS << " @["; printDebugLoc(InlinedAtDL, OS, Ctx); OS << "]"; @@ -1503,30 +516,34 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { } } -/// Specialize constructor to make sure it has the correct type. -template <> DIRef::DIRef(const Value *V) : Val(V) { - assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); +template <> +DIDescriptor +DIRef::resolve(const DITypeIdentifierMap &Map) const { + return DIDescriptor(DebugNodeRef(Val).resolve(Map)); } -template <> DIRef::DIRef(const Value *V) : Val(V) { - assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode"); +template <> +DIScope DIRef::resolve(const DITypeIdentifierMap &Map) const { + return MDScopeRef(Val).resolve(Map); } - -/// Specialize getFieldAs to handle fields that are references to DIScopes. template <> -DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const { - return DIScopeRef(getField(DbgNode, Elt)); +DIType DIRef::resolve(const DITypeIdentifierMap &Map) const { + return MDTypeRef(Val).resolve(Map); } -/// Specialize getFieldAs to handle fields that are references to DITypes. -template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const { - return DITypeRef(getField(DbgNode, Elt)); + +bool llvm::stripDebugInfo(Function &F) { + bool Changed = false; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (I.getDebugLoc()) { + Changed = true; + I.setDebugLoc(DebugLoc()); + } + } + } + return Changed; } -/// Strip debug info in the module if it exists. -/// To do this, we remove all calls to the debugger intrinsics and any named -/// metadata for debugging. We also remove debug locations for instructions. -/// Return true if module is modified. bool llvm::StripDebugInfo(Module &M) { - bool Changed = false; // Remove all of the calls to the debugger intrinsics, and remove them from @@ -1559,26 +576,20 @@ bool llvm::StripDebugInfo(Module &M) { } } - for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) - for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; - ++FI) - for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; - ++BI) { - if (!BI->getDebugLoc().isUnknown()) { - Changed = true; - BI->setDebugLoc(DebugLoc()); - } - } + for (Function &F : M) + Changed |= stripDebugInfo(F); + + if (GVMaterializer *Materializer = M.getMaterializer()) + Materializer->setStripDebugInfo(); return Changed; } -/// Return Debug Info Metadata Version by checking module flags. unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { - Value *Val = M.getModuleFlag("Debug Info Version"); - if (!Val) - return 0; - return cast(Val)->getZExtValue(); + if (auto *Val = mdconst::dyn_extract_or_null( + M.getModuleFlag("Debug Info Version"))) + return Val->getZExtValue(); + return 0; } llvm::DenseMap @@ -1590,10 +601,8 @@ llvm::makeSubprogramMap(const Module &M) { return R; for (MDNode *N : CU_Nodes->operands()) { - DICompileUnit CUNode(N); - DIArray SPs = CUNode.getSubprograms(); - for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { - DISubprogram SP(SPs.getElement(i)); + DICompileUnit CUNode = cast(N); + for (DISubprogram SP : CUNode->getSubprograms()) { if (Function *F = SP.getFunction()) R.insert(std::make_pair(F, SP)); }