|  | //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/IR/DebugLoc.h" | 
|  | #include "LLVMContextImpl.h" | 
|  | #include "llvm/Config/llvm-config.h" | 
|  | #include "llvm/IR/DebugInfo.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // DebugLoc Implementation | 
|  | //===----------------------------------------------------------------------===// | 
|  | DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {} | 
|  | DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {} | 
|  |  | 
|  | DILocation *DebugLoc::get() const { | 
|  | return cast_or_null<DILocation>(Loc.get()); | 
|  | } | 
|  |  | 
|  | unsigned DebugLoc::getLine() const { | 
|  | assert(get() && "Expected valid DebugLoc"); | 
|  | return get()->getLine(); | 
|  | } | 
|  |  | 
|  | unsigned DebugLoc::getCol() const { | 
|  | assert(get() && "Expected valid DebugLoc"); | 
|  | return get()->getColumn(); | 
|  | } | 
|  |  | 
|  | MDNode *DebugLoc::getScope() const { | 
|  | assert(get() && "Expected valid DebugLoc"); | 
|  | return get()->getScope(); | 
|  | } | 
|  |  | 
|  | DILocation *DebugLoc::getInlinedAt() const { | 
|  | assert(get() && "Expected valid DebugLoc"); | 
|  | return get()->getInlinedAt(); | 
|  | } | 
|  |  | 
|  | MDNode *DebugLoc::getInlinedAtScope() const { | 
|  | return cast<DILocation>(Loc)->getInlinedAtScope(); | 
|  | } | 
|  |  | 
|  | DebugLoc DebugLoc::getFnDebugLoc() const { | 
|  | // FIXME: Add a method on \a DILocation that does this work. | 
|  | const MDNode *Scope = getInlinedAtScope(); | 
|  | if (auto *SP = getDISubprogram(Scope)) | 
|  | return DebugLoc::get(SP->getScopeLine(), 0, SP); | 
|  |  | 
|  | return DebugLoc(); | 
|  | } | 
|  |  | 
|  | DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope, | 
|  | const MDNode *InlinedAt) { | 
|  | // If no scope is available, this is an unknown location. | 
|  | if (!Scope) | 
|  | return DebugLoc(); | 
|  |  | 
|  | return DILocation::get(Scope->getContext(), Line, Col, | 
|  | const_cast<MDNode *>(Scope), | 
|  | const_cast<MDNode *>(InlinedAt)); | 
|  | } | 
|  |  | 
|  | DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt, | 
|  | LLVMContext &Ctx, | 
|  | DenseMap<const MDNode *, MDNode *> &Cache, | 
|  | bool ReplaceLast) { | 
|  | SmallVector<DILocation *, 3> InlinedAtLocations; | 
|  | DILocation *Last = InlinedAt; | 
|  | DILocation *CurInlinedAt = DL; | 
|  |  | 
|  | // Gather all the inlined-at nodes. | 
|  | while (DILocation *IA = CurInlinedAt->getInlinedAt()) { | 
|  | // Skip any we've already built nodes for. | 
|  | if (auto *Found = Cache[IA]) { | 
|  | Last = cast<DILocation>(Found); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (ReplaceLast && !IA->getInlinedAt()) | 
|  | break; | 
|  | InlinedAtLocations.push_back(IA); | 
|  | CurInlinedAt = IA; | 
|  | } | 
|  |  | 
|  | // Starting from the top, rebuild the nodes to point to the new inlined-at | 
|  | // location (then rebuilding the rest of the chain behind it) and update the | 
|  | // map of already-constructed inlined-at nodes. | 
|  | for (const DILocation *MD : reverse(InlinedAtLocations)) | 
|  | Cache[MD] = Last = DILocation::getDistinct( | 
|  | Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last); | 
|  |  | 
|  | return Last; | 
|  | } | 
|  |  | 
|  | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | 
|  | LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); } | 
|  | #endif | 
|  |  | 
|  | void DebugLoc::print(raw_ostream &OS) const { | 
|  | if (!Loc) | 
|  | return; | 
|  |  | 
|  | // Print source line info. | 
|  | auto *Scope = cast<DIScope>(getScope()); | 
|  | OS << Scope->getFilename(); | 
|  | OS << ':' << getLine(); | 
|  | if (getCol() != 0) | 
|  | OS << ':' << getCol(); | 
|  |  | 
|  | if (DebugLoc InlinedAtDL = getInlinedAt()) { | 
|  | OS << " @[ "; | 
|  | InlinedAtDL.print(OS); | 
|  | OS << " ]"; | 
|  | } | 
|  | } |