diff options
Diffstat (limited to 'lib/IR/DebugInfo.cpp')
-rw-r--r-- | lib/IR/DebugInfo.cpp | 284 |
1 files changed, 171 insertions, 113 deletions
diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index bb5161d..6590661 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DIBuilder.h" @@ -36,6 +37,48 @@ using namespace llvm::dwarf; // DIDescriptor //===----------------------------------------------------------------------===// +unsigned DIDescriptor::getFlag(StringRef Flag) { + return StringSwitch<unsigned>(Flag) +#define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME) +#include "llvm/IR/DebugInfoFlags.def" + .Default(0); +} + +const char *DIDescriptor::getFlagString(unsigned Flag) { + switch (Flag) { + default: + return ""; +#define HANDLE_DI_FLAG(ID, NAME) \ + case Flag##NAME: \ + return "DIFlag" #NAME; +#include "llvm/IR/DebugInfoFlags.def" + } +} + +unsigned DIDescriptor::splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags) { + // Accessibility flags need to be specially handled, since they're packed + // together. + if (unsigned A = Flags & FlagAccessibility) { + if (A == FlagPrivate) + SplitFlags.push_back(FlagPrivate); + else if (A == FlagProtected) + SplitFlags.push_back(FlagProtected); + else + SplitFlags.push_back(FlagPublic); + Flags &= ~A; + } + +#define HANDLE_DI_FLAG(ID, NAME) \ + if (unsigned Bit = Flags & ID) { \ + SplitFlags.push_back(Bit); \ + Flags &= ~Bit; \ + } +#include "llvm/IR/DebugInfoFlags.def" + + return Flags; +} + bool DIDescriptor::Verify() const { return DbgNode && (DIDerivedType(DbgNode).Verify() || @@ -52,7 +95,7 @@ bool DIDescriptor::Verify() const { DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify()); } -static Value *getField(const MDNode *DbgNode, unsigned Elt) { +static Metadata *getField(const MDNode *DbgNode, unsigned Elt) { if (!DbgNode || Elt >= DbgNode->getNumOperands()) return nullptr; return DbgNode->getOperand(Elt); @@ -73,25 +116,17 @@ StringRef DIDescriptor::getStringField(unsigned Elt) const { } uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { - if (!DbgNode) - return 0; - - if (Elt < DbgNode->getNumOperands()) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt))) + if (auto *C = getConstantField(Elt)) + if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) 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<ConstantInt>(DbgNode->getOperand(Elt))) - return CI->getSExtValue(); + if (auto *C = getConstantField(Elt)) + if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) + return CI->getZExtValue(); return 0; } @@ -102,12 +137,7 @@ DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { } GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null<GlobalVariable>(DbgNode->getOperand(Elt)); - return nullptr; + return dyn_cast_or_null<GlobalVariable>(getConstantField(Elt)); } Constant *DIDescriptor::getConstantField(unsigned Elt) const { @@ -115,17 +145,14 @@ Constant *DIDescriptor::getConstantField(unsigned Elt) const { return nullptr; if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null<Constant>(DbgNode->getOperand(Elt)); + if (auto *C = + dyn_cast_or_null<ConstantAsMetadata>(DbgNode->getOperand(Elt))) + return C->getValue(); return nullptr; } Function *DIDescriptor::getFunctionField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null<Function>(DbgNode->getOperand(Elt)); - return nullptr; + return dyn_cast_or_null<Function>(getConstantField(Elt)); } void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { @@ -134,7 +161,7 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { if (Elt < DbgNode->getNumOperands()) { MDNode *Node = const_cast<MDNode *>(DbgNode); - Node->replaceOperandWith(Elt, F); + Node->replaceOperandWith(Elt, F ? ConstantAsMetadata::get(F) : nullptr); } } @@ -163,18 +190,32 @@ uint64_t DIExpression::getElement(unsigned Idx) const { return getHeaderFieldAs<int64_t>(I); } -bool DIExpression::isVariablePiece() const { - return getNumElements() && getElement(0) == dwarf::DW_OP_piece; +bool DIExpression::isBitPiece() const { + unsigned N = getNumElements(); + return N >=3 && getElement(N-3) == dwarf::DW_OP_bit_piece; +} + +uint64_t DIExpression::getBitPieceOffset() const { + assert(isBitPiece() && "not a piece"); + return getElement(getNumElements()-2); +} + +uint64_t DIExpression::getBitPieceSize() const { + assert(isBitPiece() && "not a piece"); + return getElement(getNumElements()-1); } -uint64_t DIExpression::getPieceOffset() const { - assert(isVariablePiece()); - return getElement(1); +DIExpression::iterator DIExpression::begin() const { + return DIExpression::iterator(*this); } -uint64_t DIExpression::getPieceSize() const { - assert(isVariablePiece()); - return getElement(2); +DIExpression::iterator DIExpression::end() const { + return DIExpression::iterator(); +} + +DIExpression::Operand DIExpression::Operand::getNext() const { + iterator it(I); + return *(++it); } //===----------------------------------------------------------------------===// @@ -182,7 +223,7 @@ uint64_t DIExpression::getPieceSize() const { //===----------------------------------------------------------------------===// bool DIDescriptor::isSubroutineType() const { - return isCompositeType() && getTag() == dwarf::DW_TAG_subroutine_type; + return DbgNode && getTag() == dwarf::DW_TAG_subroutine_type; } bool DIDescriptor::isBasicType() const { @@ -256,8 +297,7 @@ bool DIDescriptor::isSubprogram() const { } bool DIDescriptor::isGlobalVariable() const { - return DbgNode && (getTag() == dwarf::DW_TAG_variable || - getTag() == dwarf::DW_TAG_constant); + return DbgNode && getTag() == dwarf::DW_TAG_variable; } bool DIDescriptor::isScope() const { @@ -347,27 +387,23 @@ void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { // itself. const MDNode *DN = D; if (DbgNode == DN) { - SmallVector<Value*, 10> Ops(DbgNode->getNumOperands()); - for (size_t i = 0; i != Ops.size(); ++i) - Ops[i] = DbgNode->getOperand(i); + SmallVector<Metadata *, 10> Ops(DbgNode->op_begin(), DbgNode->op_end()); DN = MDNode::get(VMContext, Ops); } - MDNode *Node = const_cast<MDNode *>(DbgNode); - const Value *V = cast_or_null<Value>(DN); - Node->replaceAllUsesWith(const_cast<Value *>(V)); + assert(DbgNode->isTemporary() && "Expected temporary node"); + auto *Node = const_cast<MDNode *>(DbgNode); + Node->replaceAllUsesWith(const_cast<MDNode *>(DN)); MDNode::deleteTemporary(Node); DbgNode = DN; } 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<MDNode *>(DbgNode); - const MDNode *DN = D; - const Value *V = cast_or_null<Value>(DN); - Node->replaceAllUsesWith(const_cast<Value *>(V)); + assert(DbgNode->isTemporary() && "Expected temporary node"); + auto *Node = const_cast<MDNode *>(DbgNode); + Node->replaceAllUsesWith(D); MDNode::deleteTemporary(Node); } @@ -392,21 +428,14 @@ bool DIObjCProperty::Verify() const { } /// \brief 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<MDNode>(Fld). - Value *Fld = getField(DbgNode, Elt); - if (Fld && isa<MDString>(Fld) && !cast<MDString>(Fld)->getString().empty()) - return false; - return true; + Metadata *Fld = getField(DbgNode, Elt); + return !Fld || isa<MDNode>(Fld); } /// \brief 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); + Metadata *Fld = getField(DbgNode, Elt); return !Fld || isa<MDString>(Fld); } @@ -432,7 +461,9 @@ static bool isScopeRef(const Metadata *MD) { return true; if (auto *S = dyn_cast<MDString>(MD)) return !S->getString().empty(); - return isa<MDNode>(MD); + if (auto *N = dyn_cast<MDNode>(MD)) + return DIScope(N).isScope(); + return false; } /// \brief Check if a field at position Elt of a MDNode can be a ScopeRef. @@ -440,6 +471,17 @@ static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) { return isScopeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt))); } +#ifndef NDEBUG +/// \brief Check if a value can be a DescriptorRef. +static bool isDescriptorRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast<MDString>(MD)) + return !S->getString().empty(); + return isa<MDNode>(MD); +} +#endif + bool DIType::Verify() const { if (!isType()) return false; @@ -533,7 +575,6 @@ bool DISubprogram::Verify() const { // If a DISubprogram has an llvm::Function*, then scope chains from all // instructions within the function should lead to this DISubprogram. if (auto *F = getFunction()) { - LLVMContext &Ctxt = F->getContext(); for (auto &BB : *F) { for (auto &I : BB) { DebugLoc DL = I.getDebugLoc(); @@ -543,15 +584,19 @@ bool DISubprogram::Verify() const { MDNode *Scope = nullptr; MDNode *IA = nullptr; // walk the inlined-at scopes - while (DL.getScopeAndInlinedAt(Scope, IA, F->getContext()), IA) + while ((IA = DL.getInlinedAt())) DL = DebugLoc::getFromDILocation(IA); - DL.getScopeAndInlinedAt(Scope, IA, Ctxt); + DL.getScopeAndInlinedAt(Scope, IA); + if (!Scope) + return false; assert(!IA); while (!DIDescriptor(Scope).isSubprogram()) { DILexicalBlockFile D(Scope); Scope = D.isLexicalBlockFile() ? D.getScope() - : DebugLoc::getFromDILexicalBlock(Scope).getScope(Ctxt); + : DebugLoc::getFromDILexicalBlock(Scope).getScope(); + if (!Scope) + return false; } if (!DISubprogram(Scope).describes(F)) return false; @@ -567,8 +612,8 @@ bool DIGlobalVariable::Verify() const { if (getDisplayName().empty()) return false; - // Make sure context @ field 1 is a ScopeRef. - if (!fieldIsScopeRef(DbgNode, 1)) + // Make sure context @ field 1 is an MDNode. + if (!fieldIsMDNode(DbgNode, 1)) return false; // Make sure that type @ field 3 is a DITypeRef. if (!fieldIsTypeRef(DbgNode, 3)) @@ -609,14 +654,29 @@ bool DIExpression::Verify() const { if (!DbgNode) return true; - return isExpression() && DbgNode->getNumOperands() == 1; + if (!(isExpression() && DbgNode->getNumOperands() == 1)) + return false; + + for (auto Op : *this) + switch (Op) { + case DW_OP_bit_piece: + // Must be the last element of the expression. + return std::distance(Op.getBase(), DIHeaderFieldIterator()) == 3; + case DW_OP_plus: + if (std::distance(Op.getBase(), DIHeaderFieldIterator()) < 2) + return false; + break; + case DW_OP_deref: + break; + default: + // Other operators are not yet supported by the backend. + return false; + } + return true; } bool DILocation::Verify() const { - if (!DbgNode) - return false; - - return DbgNode->getNumOperands() == 4; + return DbgNode && isa<MDLocation>(DbgNode); } bool DINameSpace::Verify() const { @@ -678,19 +738,19 @@ MDString *DICompositeType::getIdentifier() const { 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<ConstantInt>(LHS->getOperand(i))) + if (i == 0 && mdconst::hasa<ConstantInt>(LHS->getOperand(i))) continue; const MDNode *E = cast<MDNode>(LHS->getOperand(i)); bool found = false; for (unsigned j = 0; !found && j != RHS->getNumOperands(); ++j) - found = E == RHS->getOperand(j); + found = (E == cast<MDNode>(RHS->getOperand(j))); assert(found && "Losing a member during member list replacement"); } } #endif void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) { - TrackingVH<MDNode> N(*this); + TrackingMDNodeRef N(*this); if (Elements) { #ifndef NDEBUG // Check that the new list of members contains all the old members as well. @@ -714,7 +774,7 @@ DIScopeRef DIScope::getRef() const { } void DICompositeType::setContainingType(DICompositeType ContainingType) { - TrackingVH<MDNode> N(*this); + TrackingMDNodeRef N(*this); N->replaceOperandWith(5, ContainingType.getRef()); DbgNode = N; } @@ -748,8 +808,8 @@ DIArray DISubprogram::getVariables() const { return DIArray(getNodeField(DbgNode, 8)); } -Value *DITemplateValueParameter::getValue() const { - return getField(DbgNode, 3); +Metadata *DITemplateValueParameter::getValue() const { + return DbgNode->getOperand(3); } DIScopeRef DIScope::getContext() const { @@ -851,16 +911,12 @@ void DICompileUnit::replaceGlobalVariables(DIArray GlobalVariables) { DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope) { - SmallVector<Value *, 10> 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<MDLocation>(DbgNode); + return DILocation(MDLocation::get(Ctx, Old->getLine(), Old->getColumn(), + NewScope, Old->getInlinedAt())); } unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { @@ -875,9 +931,8 @@ DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, return cleanseInlinedVariable(DV, VMContext); // Insert inlined scope. - SmallVector<Value *, 8> Elts; - for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) - Elts.push_back(DV->getOperand(I)); + SmallVector<Metadata *, 8> Elts(DV->op_begin(), + DV->op_begin() + DIVariableInlinedAtIndex); Elts.push_back(InlinedScope); DIVariable Inlined(MDNode::get(VMContext, Elts)); @@ -891,9 +946,8 @@ DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { return DIVariable(DV); // Remove inlined scope. - SmallVector<Value *, 8> Elts; - for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) - Elts.push_back(DV->getOperand(I)); + SmallVector<Metadata *, 8> Elts(DV->op_begin(), + DV->op_begin() + DIVariableInlinedAtIndex); DIVariable Cleansed(MDNode::get(VMContext, Elts)); assert(Cleansed.Verify() && "Expected to create a DIVariable"); @@ -923,7 +977,7 @@ DISubprogram llvm::getDISubprogram(const Function *F) { if (Inst == BB.end()) continue; DebugLoc DLoc = Inst->getDebugLoc(); - const MDNode *Scope = DLoc.getScopeNode(F->getParent()->getContext()); + const MDNode *Scope = DLoc.getScopeNode(); DISubprogram Subprogram = getDISubprogram(Scope); return Subprogram.describes(F) ? Subprogram : DISubprogram(); } @@ -1005,7 +1059,7 @@ void DebugInfoFinder::processModule(const Module &M) { for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { DIGlobalVariable DIG(GVs.getElement(i)); if (addGlobalVariable(DIG)) { - processScope(DIG.getContext().resolve(TypeIdentifierMap)); + processScope(DIG.getContext()); processType(DIG.getType().resolve(TypeIdentifierMap)); } } @@ -1106,11 +1160,9 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) { DIDescriptor Element = TParams.getElement(I); if (Element.isTemplateTypeParameter()) { DITemplateTypeParameter TType(Element); - processScope(TType.getContext().resolve(TypeIdentifierMap)); processType(TType.getType().resolve(TypeIdentifierMap)); } else if (Element.isTemplateValueParameter()) { DITemplateValueParameter TVal(Element); - processScope(TVal.getContext().resolve(TypeIdentifierMap)); processType(TVal.getType().resolve(TypeIdentifierMap)); } } @@ -1401,24 +1453,22 @@ void DIVariable::printInternal(raw_ostream &OS) const { } void DIExpression::printInternal(raw_ostream &OS) const { - for (unsigned I = 0; I < getNumElements(); ++I) { - uint64_t OpCode = getElement(I); - OS << " [" << OperationEncodingString(OpCode); - switch (OpCode) { + for (auto Op : *this) { + OS << " [" << OperationEncodingString(Op); + switch (Op) { case DW_OP_plus: { - OS << " " << getElement(++I); + OS << " " << Op.getArg(1); break; } - case DW_OP_piece: { - unsigned Offset = getElement(++I); - unsigned Size = getElement(++I); - OS << " offset=" << Offset << ", size=" << Size; + case DW_OP_bit_piece: { + OS << " offset=" << Op.getArg(1) << ", size=" << Op.getArg(2); break; } + case DW_OP_deref: + // No arguments. + break; default: - // Else bail out early. This may be a line table entry. - OS << "Unknown]"; - return; + llvm_unreachable("unhandled operation"); } OS << "]"; } @@ -1467,6 +1517,10 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { } } +template <> DIRef<DIDescriptor>::DIRef(const Metadata *V) : Val(V) { + assert(isDescriptorRef(V) && + "DIDescriptorRef should be a MDString or MDNode"); +} template <> DIRef<DIScope>::DIRef(const Metadata *V) : Val(V) { assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); } @@ -1475,6 +1529,10 @@ template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) { } template <> +DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const { + return DIDescriptorRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); +} +template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const { return DIScopeRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); } @@ -1530,10 +1588,10 @@ bool llvm::StripDebugInfo(Module &M) { } unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { - Value *Val = M.getModuleFlag("Debug Info Version"); - if (!Val) - return 0; - return cast<ConstantInt>(Val)->getZExtValue(); + if (auto *Val = mdconst::dyn_extract_or_null<ConstantInt>( + M.getModuleFlag("Debug Info Version"))) + return Val->getZExtValue(); + return 0; } llvm::DenseMap<const llvm::Function *, llvm::DISubprogram> |