diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index c29d5bf12d8..ffcc07d902c 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,11 +22,15 @@ namespace llvm { class LLVMContext; class raw_ostream; - class MDNode; + class MDLocation; - /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, - /// and MachineInstr to compactly encode file/line/scope information for an - /// operation. + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a MDLocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a MDLocation API with a + /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -43,66 +47,89 @@ namespace llvm { return *this; } + /// \brief Construct from an \a MDLocation. + DebugLoc(MDLocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a MDLocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(MDNode *N); + + MDLocation *get() const; + operator MDLocation *() const { return get(); } + MDLocation *operator->() const { return get(); } + MDLocation &operator*() const { return *get(); } + /// \brief Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - /// get - Get a new DebugLoc that corresponds to the specified line/col - /// scope/inline location. + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a MDLocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use MDLocation::get(). static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, MDNode *InlinedAt = nullptr); - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. + /// \brief Translate the DILexicalBlock into a DebugLoc. + /// + /// FIXME: Remove this. It has only one user, and the user just wants to + /// pass an \a MDScope around. static DebugLoc getFromDILexicalBlock(MDNode *N); - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return !Loc; } - unsigned getLine() const; unsigned getCol() const; - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. MDNode *getScope() const; + MDLocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use MDLocation/MDLocalScope API to + /// find the subprogram, and then MDLocation::get(). + DebugLoc getFnDebugLoc() const; + + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } + + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } + + void dump() const; + + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] + void print(raw_ostream &OS) const; + + // FIXME: Remove this old API once callers have been updated. + static DebugLoc getFromDILocation(MDNode *N) { return DebugLoc(N); } + bool isUnknown() const { return !Loc; } MDNode *getScope(const LLVMContext &) const { return getScope(); } - - /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or - /// null if invalid or not present. - MDNode *getInlinedAt() const; - MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } - - /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + MDNode *getInlinedAt(const LLVMContext &) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, const LLVMContext &) const { return getScopeAndInlinedAt(Scope, IA); } - - /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode() const; + MDNode *getScopeNode() const { return getInlinedAtScope(); } MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } - - // getFnDebugLoc - Walk up the scope chain of given debug loc and find line - // number info for the function. - DebugLoc getFnDebugLoc() const; DebugLoc getFnDebugLoc(const LLVMContext &) const { return getFnDebugLoc(); } - - /// getAsMDNode - This method converts the compressed DebugLoc node into a - /// DILocation compatible MDNode. - MDNode *getAsMDNode() const; MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - - bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - - void dump() const; void dump(const LLVMContext &) const { dump(); } - /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(raw_ostream &OS) const; }; } // end namespace llvm diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index 6b2a5395930..515e0a2b716 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -16,28 +16,40 @@ using namespace llvm; //===----------------------------------------------------------------------===// // DebugLoc Implementation //===----------------------------------------------------------------------===// +DebugLoc::DebugLoc(MDLocation *L) : Loc(L) {} +DebugLoc::DebugLoc(MDNode *L) : Loc(L) {} -unsigned DebugLoc::getLine() const { return DILocation(Loc).getLineNumber(); } -unsigned DebugLoc::getCol() const { return DILocation(Loc).getColumnNumber(); } - -MDNode *DebugLoc::getScope() const { return DILocation(Loc).getScope(); } - -MDNode *DebugLoc::getInlinedAt() const { - return DILocation(Loc).getOrigLocation(); +MDLocation *DebugLoc::get() const { + return cast_or_null(Loc.get()); } -/// Return both the Scope and the InlinedAt values. -void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const { - Scope = getScope(); - IA = getInlinedAt(); +unsigned DebugLoc::getLine() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getLine(); } -MDNode *DebugLoc::getScopeNode() const { +unsigned DebugLoc::getCol() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getColumn(); +} + +MDNode *DebugLoc::getScope() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getScope(); +} + +MDLocation *DebugLoc::getInlinedAt() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getInlinedAt(); +} + +MDNode *DebugLoc::getInlinedAtScope() const { return cast(Loc)->getInlinedAtScope(); } DebugLoc DebugLoc::getFnDebugLoc() const { - const MDNode *Scope = getScopeNode(); + // FIXME: Add a method on \a MDLocation that does this work. + const MDNode *Scope = getInlinedAtScope(); DISubprogram SP = getDISubprogram(Scope); if (SP.isSubprogram()) return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); @@ -51,19 +63,7 @@ DebugLoc DebugLoc::get(unsigned Line, unsigned Col, if (!Scope) return DebugLoc(); - return getFromDILocation( - MDLocation::get(Scope->getContext(), Line, Col, Scope, InlinedAt)); -} - -/// getAsMDNode - This method converts the compressed DebugLoc node into a -/// DILocation-compatible MDNode. -MDNode *DebugLoc::getAsMDNode() const { return Loc; } - -/// getFromDILocation - Translate the DILocation quad into a DebugLoc. -DebugLoc DebugLoc::getFromDILocation(MDNode *N) { - DebugLoc Loc; - Loc.Loc.reset(N); - return Loc; + return MDLocation::get(Scope->getContext(), Line, Col, Scope, InlinedAt); } /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. @@ -77,38 +77,48 @@ DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) { void DebugLoc::dump() const { #ifndef NDEBUG - if (!isUnknown()) { - dbgs() << getLine(); - if (getCol() != 0) - dbgs() << ',' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); - if (!InlinedAtDL.isUnknown()) { - dbgs() << " @ "; - InlinedAtDL.dump(); - } else - dbgs() << "\n"; - } + if (!Loc) + return; + + dbgs() << getLine(); + if (getCol() != 0) + dbgs() << ',' << getCol(); + if (DebugLoc InlinedAtDL = DebugLoc(getInlinedAt())) { + dbgs() << " @ "; + InlinedAtDL.dump(); + } else + dbgs() << "\n"; #endif } void DebugLoc::print(raw_ostream &OS) const { - if (!isUnknown()) { - // Print source line info. - DIScope Scope(getScope()); - assert((!Scope || Scope.isScope()) && - "Scope of a DebugLoc should be null or a DIScope."); - if (Scope) - OS << Scope.getFilename(); - else - OS << ""; - OS << ':' << getLine(); - if (getCol() != 0) - OS << ':' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); - if (!InlinedAtDL.isUnknown()) { - OS << " @[ "; - InlinedAtDL.print(OS); - OS << " ]"; - } + if (!Loc) + return; + + // Print source line info. + DIScope Scope(getScope()); + assert((!Scope || Scope.isScope()) && + "Scope of a DebugLoc should be null or a DIScope."); + if (Scope) + OS << Scope.getFilename(); + else + OS << ""; + OS << ':' << getLine(); + if (getCol() != 0) + OS << ':' << getCol(); + + if (DebugLoc InlinedAtDL = getInlinedAt()) { + OS << " @[ "; + InlinedAtDL.print(OS); + OS << " ]"; } } + +// FIXME: Remove this old API once callers have been updated. +MDNode *DebugLoc::getInlinedAt(const LLVMContext &) const { + return getInlinedAt(); +} +void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const { + Scope = getScope(); + IA = getInlinedAt(); +}