Home | History | Annotate | Line # | Download | only in IR
      1 //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/IR/DebugLoc.h"
     10 #include "LLVMContextImpl.h"
     11 #include "llvm/Config/llvm-config.h"
     12 #include "llvm/IR/DebugInfo.h"
     13 using namespace llvm;
     14 
     15 //===----------------------------------------------------------------------===//
     16 // DebugLoc Implementation
     17 //===----------------------------------------------------------------------===//
     18 DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}
     19 DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}
     20 
     21 DILocation *DebugLoc::get() const {
     22   return cast_or_null<DILocation>(Loc.get());
     23 }
     24 
     25 unsigned DebugLoc::getLine() const {
     26   assert(get() && "Expected valid DebugLoc");
     27   return get()->getLine();
     28 }
     29 
     30 unsigned DebugLoc::getCol() const {
     31   assert(get() && "Expected valid DebugLoc");
     32   return get()->getColumn();
     33 }
     34 
     35 MDNode *DebugLoc::getScope() const {
     36   assert(get() && "Expected valid DebugLoc");
     37   return get()->getScope();
     38 }
     39 
     40 DILocation *DebugLoc::getInlinedAt() const {
     41   assert(get() && "Expected valid DebugLoc");
     42   return get()->getInlinedAt();
     43 }
     44 
     45 MDNode *DebugLoc::getInlinedAtScope() const {
     46   return cast<DILocation>(Loc)->getInlinedAtScope();
     47 }
     48 
     49 DebugLoc DebugLoc::getFnDebugLoc() const {
     50   // FIXME: Add a method on \a DILocation that does this work.
     51   const MDNode *Scope = getInlinedAtScope();
     52   if (auto *SP = getDISubprogram(Scope))
     53     return DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
     54 
     55   return DebugLoc();
     56 }
     57 
     58 bool DebugLoc::isImplicitCode() const {
     59   if (DILocation *Loc = get()) {
     60     return Loc->isImplicitCode();
     61   }
     62   return true;
     63 }
     64 
     65 void DebugLoc::setImplicitCode(bool ImplicitCode) {
     66   if (DILocation *Loc = get()) {
     67     Loc->setImplicitCode(ImplicitCode);
     68   }
     69 }
     70 
     71 DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt,
     72                                    LLVMContext &Ctx,
     73                                    DenseMap<const MDNode *, MDNode *> &Cache) {
     74   SmallVector<DILocation *, 3> InlinedAtLocations;
     75   DILocation *Last = InlinedAt;
     76   DILocation *CurInlinedAt = DL;
     77 
     78   // Gather all the inlined-at nodes.
     79   while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
     80     // Skip any we've already built nodes for.
     81     if (auto *Found = Cache[IA]) {
     82       Last = cast<DILocation>(Found);
     83       break;
     84     }
     85 
     86     InlinedAtLocations.push_back(IA);
     87     CurInlinedAt = IA;
     88   }
     89 
     90   // Starting from the top, rebuild the nodes to point to the new inlined-at
     91   // location (then rebuilding the rest of the chain behind it) and update the
     92   // map of already-constructed inlined-at nodes.
     93   for (const DILocation *MD : reverse(InlinedAtLocations))
     94     Cache[MD] = Last = DILocation::getDistinct(
     95         Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
     96 
     97   return Last;
     98 }
     99 
    100 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    101 LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }
    102 #endif
    103 
    104 void DebugLoc::print(raw_ostream &OS) const {
    105   if (!Loc)
    106     return;
    107 
    108   // Print source line info.
    109   auto *Scope = cast<DIScope>(getScope());
    110   OS << Scope->getFilename();
    111   OS << ':' << getLine();
    112   if (getCol() != 0)
    113     OS << ':' << getCol();
    114 
    115   if (DebugLoc InlinedAtDL = getInlinedAt()) {
    116     OS << " @[ ";
    117     InlinedAtDL.print(OS);
    118     OS << " ]";
    119   }
    120 }
    121