diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 3e7764c85db..459e1576193 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -59,7 +59,7 @@ class DIObjCProperty; typedef DenseMap DITypeIdentifierMap; class DIHeaderFieldIterator - : public std::iterator { StringRef Header; StringRef Current; @@ -834,6 +834,8 @@ public: void printExtendedName(raw_ostream &OS) const; }; +class DIExpressionIterator; + /// \brief A complex location expression. class DIExpression : public DIDescriptor { friend class DIDescriptor; @@ -862,8 +864,64 @@ public: uint64_t getPieceOffset() const; /// \brief Return the size of this piece in bytes. uint64_t getPieceSize() const; + + DIExpressionIterator begin() const; + DIExpressionIterator end() const; }; +/// \brief An iterator for DIExpression elments. +class DIExpressionIterator + : public std::iterator { + DIHeaderFieldIterator I; + DIExpressionIterator(DIHeaderFieldIterator I) : I(I) {} +public: + DIExpressionIterator() {} + DIExpressionIterator(const DIExpression Expr) + : I(Expr.getHeader()) { ++I; } + uint64_t operator*() const { + uint64_t UInt; + if (I->getAsInteger(0, UInt)) + return 0; + return UInt; + } + DIExpressionIterator &operator++() { + increment(); + return *this; + } + DIExpressionIterator operator++(int) { + DIExpressionIterator X(*this); + increment(); + return X; + } + bool operator==(const DIExpressionIterator &X) const { + return I == X.I; + } + bool operator!=(const DIExpressionIterator &X) const { + return !(*this == X); + } + + uint64_t getArg(unsigned N) const { + auto In = I; + std::advance(In, N); + return *DIExpressionIterator(In); + } + + const DIHeaderFieldIterator& getBase() const { return I; } + +private: + void increment() { + switch (**this) { + case dwarf::DW_OP_piece: std::advance(I, 3); break; + case dwarf::DW_OP_plus: std::advance(I, 2); break; + case dwarf::DW_OP_deref: std::advance(I, 1); break; + default: + assert("unsupported operand"); + } + } +}; + + /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 76836fd9551..f7892dd3497 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -162,6 +162,14 @@ uint64_t DIExpression::getPieceSize() const { return getElement(getNumElements()-1); } +DIExpressionIterator DIExpression::begin() const { + return DIExpressionIterator(*this); +} + +DIExpressionIterator DIExpression::end() const { + return DIExpressionIterator(); +} + //===----------------------------------------------------------------------===// // Predicates //===----------------------------------------------------------------------===// @@ -595,25 +603,25 @@ bool DIExpression::Verify() const { if (!DbgNode) return true; - unsigned N = getNumElements(); - for (unsigned I = 0; I < N; ++I) - switch (getElement(I)) { + if (!(isExpression() && DbgNode->getNumOperands() == 1)) + return false; + + for (auto E = end(), I = begin(); I != E; ++I) + switch (*I) { case DW_OP_piece: - // DW_OP_piece has to be the last element in the expression and take two - // arguments. - if (getElement(I) == DW_OP_piece && !isVariablePiece()) - return false; - I += 2; - break; + // Must be the last element of the expression. + return std::distance(I.getBase(), DIHeaderFieldIterator()) == 3; case DW_OP_plus: - // Takes one argument. - if (I+1 == N) + if (std::distance(I.getBase(), DIHeaderFieldIterator()) < 2) return false; - I += 1; break; - default: break; - } - return isExpression() && DbgNode->getNumOperands() == 1; + case DW_OP_deref: + break; + default: + // Other operators are not yet supported by the backend. + return false; + } + return true; } bool DILocation::Verify() const {