aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/IR/DebugInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/DebugInfo.h')
-rw-r--r--include/llvm/IR/DebugInfo.h293
1 files changed, 190 insertions, 103 deletions
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h
index 22a2138..d2e5975 100644
--- a/include/llvm/IR/DebugInfo.h
+++ b/include/llvm/IR/DebugInfo.h
@@ -18,11 +18,11 @@
#define LLVM_IR_DEBUGINFO_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/IR/Metadata.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
@@ -66,10 +66,10 @@ class DIHeaderFieldIterator
public:
DIHeaderFieldIterator() {}
- DIHeaderFieldIterator(StringRef Header)
+ explicit DIHeaderFieldIterator(StringRef Header)
: Header(Header), Current(Header.slice(0, Header.find('\0'))) {}
StringRef operator*() const { return Current; }
- const StringRef * operator->() const { return &Current; }
+ const StringRef *operator->() const { return &Current; }
DIHeaderFieldIterator &operator++() {
increment();
return *this;
@@ -99,6 +99,16 @@ public:
return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos);
}
+ /// \brief Get the current field as a number.
+ ///
+ /// Convert the current field into a number. Return \c 0 on error.
+ template <class T> T getNumber() const {
+ T Int;
+ if (getCurrent().getAsInteger(0, Int))
+ return 0;
+ return Int;
+ }
+
private:
void increment() {
assert(Current.data() != nullptr && "Cannot increment past the end");
@@ -122,27 +132,21 @@ public:
/// The three accessibility flags are mutually exclusive and rolled together
/// in the first two bits.
enum {
- FlagAccessibility = 1 << 0 | 1 << 1,
- FlagPrivate = 1,
- FlagProtected = 2,
- FlagPublic = 3,
-
- FlagFwdDecl = 1 << 2,
- FlagAppleBlock = 1 << 3,
- FlagBlockByrefStruct = 1 << 4,
- FlagVirtual = 1 << 5,
- FlagArtificial = 1 << 6,
- FlagExplicit = 1 << 7,
- FlagPrototyped = 1 << 8,
- FlagObjcClassComplete = 1 << 9,
- FlagObjectPointer = 1 << 10,
- FlagVector = 1 << 11,
- FlagStaticMember = 1 << 12,
- FlagIndirectVariable = 1 << 13,
- FlagLValueReference = 1 << 14,
- FlagRValueReference = 1 << 15
+#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID,
+#include "llvm/IR/DebugInfoFlags.def"
+ FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic
};
+ static unsigned getFlag(StringRef Flag);
+ static const char *getFlagString(unsigned Flag);
+
+ /// \brief Split up a flags bitfield.
+ ///
+ /// Split \c Flags into \c SplitFlags, a vector of its components. Returns
+ /// any remaining (unrecognized) bits.
+ static unsigned splitFlags(unsigned Flags,
+ SmallVectorImpl<unsigned> &SplitFlags);
+
protected:
const MDNode *DbgNode;
@@ -168,42 +172,47 @@ public:
bool Verify() const;
- operator MDNode *() const { return const_cast<MDNode *>(DbgNode); }
- MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); }
+ MDNode *get() const { return const_cast<MDNode *>(DbgNode); }
+ operator MDNode *() const { return get(); }
+ MDNode *operator->() const { return get(); }
// An explicit operator bool so that we can do testing of DI values
// easily.
// FIXME: This operator bool isn't actually protecting anything at the
// moment due to the conversion operator above making DIDescriptor nodes
// implicitly convertable to bool.
- LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; }
+ explicit operator bool() const { return DbgNode != nullptr; }
bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; }
bool operator!=(DIDescriptor Other) const { return !operator==(Other); }
- StringRef getHeader() const {
- return getStringField(0);
- }
+ StringRef getHeader() const { return getStringField(0); }
size_t getNumHeaderFields() const {
return std::distance(DIHeaderFieldIterator(getHeader()),
DIHeaderFieldIterator());
}
- StringRef getHeaderField(unsigned Index) const {
+ DIHeaderFieldIterator header_begin() const {
+ return DIHeaderFieldIterator(getHeader());
+ }
+ DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); }
+
+ DIHeaderFieldIterator getHeaderIterator(unsigned Index) const {
// Since callers expect an empty string for out-of-range accesses, we can't
// use std::advance() here.
- for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index)
+ for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index)
if (!Index)
- return *I;
- return StringRef();
+ return I;
+ return header_end();
+ }
+
+ StringRef getHeaderField(unsigned Index) const {
+ return *getHeaderIterator(Index);
}
template <class T> T getHeaderFieldAs(unsigned Index) const {
- T Int;
- if (getHeaderField(Index).getAsInteger(0, Int))
- return 0;
- return Int;
+ return getHeaderIterator(Index).getNumber<T>();
}
uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); }
@@ -238,6 +247,19 @@ public:
void replaceAllUsesWith(MDNode *D);
};
+#define RETURN_FROM_RAW(VALID, DEFAULT) \
+ do { \
+ if (auto *N = getRaw()) \
+ return VALID; \
+ return DEFAULT; \
+ } while (false)
+#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \
+ do { \
+ if (auto *N = getRaw()) \
+ return DESC(dyn_cast_or_null<MDNode>(VALID)); \
+ return DESC(static_cast<const MDNode *>(nullptr)); \
+ } while (false)
+
/// \brief This is used to represent ranges, for array bounds.
class DISubrange : public DIDescriptor {
friend class DIDescriptor;
@@ -258,9 +280,7 @@ public:
unsigned getNumElements() const {
return DbgNode ? DbgNode->getNumOperands() : 0;
}
- T getElement(unsigned Idx) const {
- return getFieldAs<T>(Idx);
- }
+ T getElement(unsigned Idx) const { return getFieldAs<T>(Idx); }
};
typedef DITypedArray<DIDescriptor> DIArray;
@@ -282,6 +302,7 @@ public:
};
template <typename T> class DIRef;
+typedef DIRef<DIDescriptor> DIDescriptorRef;
typedef DIRef<DIScope> DIScopeRef;
typedef DIRef<DIType> DITypeRef;
typedef DITypedArray<DITypeRef> DITypeArray;
@@ -371,6 +392,12 @@ template <typename T> StringRef DIRef<T>::getName() const {
return MS->getString();
}
+/// \brief Handle fields that are references to DIDescriptors.
+template <>
+DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const;
+/// \brief Specialize DIRef constructor for DIDescriptorRef.
+template <> DIRef<DIDescriptor>::DIRef(const Metadata *V);
+
/// \brief Handle fields that are references to DIScopes.
template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
/// \brief Specialize DIRef constructor for DIScopeRef.
@@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
/// \brief Specialize DIRef constructor for DITypeRef.
template <> DIRef<DIType>::DIRef(const Metadata *V);
-/// \briefThis is a wrapper for a type.
+/// \brief This is a wrapper for a type.
///
/// FIXME: Types should be factored much better so that CV qualifiers and
/// others do not require a huge and empty descriptor full of zeros.
@@ -392,7 +419,7 @@ protected:
public:
explicit DIType(const MDNode *N = nullptr) : DIScope(N) {}
- operator DITypeRef () const {
+ operator DITypeRef() const {
assert(isType() &&
"constructing DITypeRef from an MDNode that is not a type");
return DITypeRef(&*getRef());
@@ -402,20 +429,12 @@ public:
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
StringRef getName() const { return getHeaderField(1); }
- unsigned getLineNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
- uint64_t getSizeInBits() const {
- return getHeaderFieldAs<unsigned>(3);
- }
- uint64_t getAlignInBits() const {
- return getHeaderFieldAs<unsigned>(4);
- }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ uint64_t getSizeInBits() const { return getHeaderFieldAs<unsigned>(3); }
+ uint64_t getAlignInBits() const { return getHeaderFieldAs<unsigned>(4); }
// FIXME: Offset is only used for DW_TAG_member nodes. Making every type
// carry this is just plain insane.
- uint64_t getOffsetInBits() const {
- return getHeaderFieldAs<unsigned>(5);
- }
+ uint64_t getOffsetInBits() const { return getHeaderFieldAs<unsigned>(5); }
unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); }
bool isPrivate() const {
return (getFlags() & FlagAccessibility) == FlagPrivate;
@@ -499,6 +518,7 @@ public:
// FIXME: Make this derive from DIType directly & just store the
// base type in a single DIType field.
class DICompositeType : public DIDerivedType {
+ friend class DIBuilder;
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -512,20 +532,26 @@ public:
assert(!isSubroutineType() && "no elements for DISubroutineType");
return getFieldAs<DIArray>(4);
}
+
+private:
template <typename T>
void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) {
- assert((!TParams || DbgNode->getNumOperands() == 8) &&
- "If you're setting the template parameters this should include a slot "
- "for that!");
+ assert(
+ (!TParams || DbgNode->getNumOperands() == 8) &&
+ "If you're setting the template parameters this should include a slot "
+ "for that!");
setArraysHelper(Elements, TParams);
}
- unsigned getRunTimeLang() const {
- return getHeaderFieldAs<unsigned>(7);
- }
+
+public:
+ unsigned getRunTimeLang() const { return getHeaderFieldAs<unsigned>(7); }
DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); }
+private:
/// \brief Set the containing type.
void setContainingType(DICompositeType ContainingType);
+
+public:
DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
MDString *getIdentifier() const;
@@ -663,7 +689,6 @@ public:
unsigned isRValueReference() const {
return (getFlags() & FlagRValueReference) != 0;
}
-
};
/// \brief This is a wrapper for a lexical block.
@@ -671,12 +696,8 @@ class DILexicalBlock : public DIScope {
public:
explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(2); }
- unsigned getLineNumber() const {
- return getHeaderFieldAs<unsigned>(1);
- }
- unsigned getColumnNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(2); }
bool Verify() const;
};
@@ -685,6 +706,8 @@ class DILexicalBlockFile : public DIScope {
public:
explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {}
DIScope getContext() const {
+ // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but
+ // then we check if it's a subprogram? WHAT?!?
if (getScope().isSubprogram())
return getScope();
return getScope().getContext();
@@ -713,18 +736,11 @@ public:
class DITemplateTypeParameter : public DIDescriptor {
public:
explicit DITemplateTypeParameter(const MDNode *N = nullptr)
- : DIDescriptor(N) {}
+ : DIDescriptor(N) {}
StringRef getName() const { return getHeaderField(1); }
- unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
- unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(3).getDirectory();
- }
bool Verify() const;
};
@@ -732,19 +748,12 @@ public:
class DITemplateValueParameter : public DIDescriptor {
public:
explicit DITemplateValueParameter(const MDNode *N = nullptr)
- : DIDescriptor(N) {}
+ : DIDescriptor(N) {}
StringRef getName() const { return getHeaderField(1); }
- unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
- unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- Value *getValue() const;
- StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(4).getDirectory();
- }
+ Metadata *getValue() const;
bool Verify() const;
};
@@ -763,7 +772,7 @@ public:
unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); }
unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); }
StringRef getDirectory() const {
return getFieldAs<DIFile>(2).getDirectory();
@@ -807,11 +816,6 @@ public:
return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0;
}
- /// \brief Return true if this variable is represented as a pointer.
- bool isIndirect() const {
- return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0;
- }
-
/// \brief If this variable is inlined then return inline location.
MDNode *getInlinedAt() const;
@@ -831,7 +835,13 @@ public:
void printExtendedName(raw_ostream &OS) const;
};
-/// \brief A complex location expression.
+/// \brief A complex location expression in postfix notation.
+///
+/// This is (almost) a DWARF expression that modifies the location of a
+/// variable or (or the location of a single piece of a variable).
+///
+/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
+/// and have DW_OP_plus consume the topmost elements on the stack.
class DIExpression : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -854,24 +864,91 @@ public:
uint64_t getElement(unsigned Idx) const;
/// \brief Return whether this is a piece of an aggregate variable.
- bool isVariablePiece() const;
- /// \brief Return the offset of this piece in bytes.
- uint64_t getPieceOffset() const;
- /// \brief Return the size of this piece in bytes.
- uint64_t getPieceSize() const;
+ bool isBitPiece() const;
+ /// \brief Return the offset of this piece in bits.
+ uint64_t getBitPieceOffset() const;
+ /// \brief Return the size of this piece in bits.
+ uint64_t getBitPieceSize() const;
+
+ class iterator;
+ /// \brief A lightweight wrapper around an element of a DIExpression.
+ class Operand {
+ friend class iterator;
+ DIHeaderFieldIterator I;
+ Operand() {}
+ Operand(DIHeaderFieldIterator I) : I(I) {}
+ public:
+ /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments.
+ /// Argument 0 is the operand itself.
+ uint64_t getArg(unsigned N) const {
+ DIHeaderFieldIterator In = I;
+ std::advance(In, N);
+ return In.getNumber<uint64_t>();
+ }
+ operator uint64_t () const { return I.getNumber<uint64_t>(); }
+ /// \brief Returns underlying DIHeaderFieldIterator.
+ const DIHeaderFieldIterator &getBase() const { return I; }
+ /// \brief Returns the next operand.
+ Operand getNext() const;
+ };
+
+ /// \brief An iterator for DIExpression elements.
+ class iterator : public std::iterator<std::input_iterator_tag, StringRef,
+ unsigned, const Operand*, Operand> {
+ friend class Operand;
+ DIHeaderFieldIterator I;
+ Operand Tmp;
+ iterator(DIHeaderFieldIterator I) : I(I) {}
+ public:
+ iterator() {}
+ iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {}
+ const Operand &operator*() { return Tmp = Operand(I); }
+ const Operand *operator->() { return &(Tmp = Operand(I)); }
+ iterator &operator++() {
+ increment();
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator X(*this);
+ increment();
+ return X;
+ }
+ bool operator==(const iterator &X) const { return I == X.I; }
+ bool operator!=(const iterator &X) const { return !(*this == X); }
+
+ private:
+ void increment() {
+ switch (**this) {
+ case dwarf::DW_OP_bit_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:
+ llvm_unreachable("unsupported operand");
+ }
+ }
+ };
+
+ iterator begin() const;
+ iterator end() const;
};
/// \brief This object holds location information.
///
/// This object is not associated with any DWARF tag.
class DILocation : public DIDescriptor {
+ MDLocation *getRaw() const { return dyn_cast_or_null<MDLocation>(get()); }
+
public:
explicit DILocation(const MDNode *N) : DIDescriptor(N) {}
- unsigned getLineNumber() const { return getUnsignedField(0); }
- unsigned getColumnNumber() const { return getUnsignedField(1); }
- DIScope getScope() const { return getFieldAs<DIScope>(2); }
- DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); }
+ unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); }
+ unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); }
+ DIScope getScope() const {
+ RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope());
+ }
+ DILocation getOrigLocation() const {
+ RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt());
+ }
StringRef getFilename() const { return getScope().getFilename(); }
StringRef getDirectory() const { return getScope().getDirectory(); }
bool Verify() const;
@@ -892,7 +969,9 @@ public:
// sure this location is a lexical block before retrieving its
// value.
return getScope().isLexicalBlockFile()
- ? getFieldAs<DILexicalBlockFile>(2).getDiscriminator()
+ ? DILexicalBlockFile(
+ cast<MDNode>(cast<MDLocation>(DbgNode)->getScope()))
+ .getDiscriminator()
: 0;
}
@@ -951,14 +1030,18 @@ class DIImportedEntity : public DIDescriptor {
void printInternal(raw_ostream &OS) const;
public:
+ DIImportedEntity() = default;
explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
- DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
+ DIDescriptorRef getEntity() const { return getFieldAs<DIDescriptorRef>(2); }
unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
StringRef getName() const { return getHeaderField(2); }
bool Verify() const;
};
+#undef RETURN_FROM_RAW
+#undef RETURN_DESCRIPTOR_FROM_RAW
+
/// \brief Find subprogram that is enclosing this scope.
DISubprogram getDISubprogram(const MDNode *Scope);
@@ -1015,6 +1098,9 @@ public:
/// \brief Process DILocation.
void processLocation(const Module &M, DILocation Loc);
+ /// \brief Process DIExpression.
+ void processExpression(DIExpression Expr);
+
/// \brief Clear all lists.
void reset();
@@ -1033,7 +1119,8 @@ private:
public:
typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator;
typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator;
- typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator;
+ typedef SmallVectorImpl<DIGlobalVariable>::const_iterator
+ global_variable_iterator;
typedef SmallVectorImpl<DIType>::const_iterator type_iterator;
typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator;