brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · bfba6e0 Raw
219 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/DebugLoc.h"10#include "llvm/Config/llvm-config.h"11#include "llvm/IR/DebugInfo.h"12 13using namespace llvm;14 15#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN16#include "llvm/Support/Signals.h"17 18DbgLocOrigin::DbgLocOrigin(bool ShouldCollectTrace) {19  if (!ShouldCollectTrace)20    return;21  auto &[Depth, StackTrace] = StackTraces.emplace_back();22  Depth = sys::getStackTrace(StackTrace);23}24void DbgLocOrigin::addTrace() {25  // We only want to add new stacktraces if we already have one: addTrace exists26  // to provide more context to how missing DebugLocs have propagated through27  // the program, but by design if there is no existing stacktrace then we have28  // decided not to track this DebugLoc as being "missing".29  if (StackTraces.empty())30    return;31  auto &[Depth, StackTrace] = StackTraces.emplace_back();32  Depth = sys::getStackTrace(StackTrace);33}34#endif35 36#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE37DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L)38    : TrackingMDNodeRef(const_cast<DILocation *>(L)), DbgLocOrigin(!L),39      Kind(DebugLocKind::Normal) {}40#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE41 42//===----------------------------------------------------------------------===//43// DebugLoc Implementation44//===----------------------------------------------------------------------===//45DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}46DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}47 48DILocation *DebugLoc::get() const {49  return cast_or_null<DILocation>(Loc.get());50}51 52unsigned DebugLoc::getLine() const {53  assert(get() && "Expected valid DebugLoc");54  return get()->getLine();55}56 57unsigned DebugLoc::getCol() const {58  assert(get() && "Expected valid DebugLoc");59  return get()->getColumn();60}61 62MDNode *DebugLoc::getScope() const {63  assert(get() && "Expected valid DebugLoc");64  return get()->getScope();65}66 67DILocation *DebugLoc::getInlinedAt() const {68  assert(get() && "Expected valid DebugLoc");69  return get()->getInlinedAt();70}71 72MDNode *DebugLoc::getInlinedAtScope() const {73  return cast<DILocation>(Loc)->getInlinedAtScope();74}75 76DebugLoc DebugLoc::getFnDebugLoc() const {77  // FIXME: Add a method on \a DILocation that does this work.78  const MDNode *Scope = getInlinedAtScope();79  if (auto *SP = getDISubprogram(Scope))80    return DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);81 82  return DebugLoc();83}84 85bool DebugLoc::isImplicitCode() const {86  if (DILocation *Loc = get()) {87    return Loc->isImplicitCode();88  }89  return true;90}91 92void DebugLoc::setImplicitCode(bool ImplicitCode) {93  if (DILocation *Loc = get()) {94    Loc->setImplicitCode(ImplicitCode);95  }96}97 98DebugLoc DebugLoc::replaceInlinedAtSubprogram(99    const DebugLoc &RootLoc, DISubprogram &NewSP, LLVMContext &Ctx,100    DenseMap<const MDNode *, MDNode *> &Cache) {101  SmallVector<DILocation *> LocChain;102  DILocation *CachedResult = nullptr;103 104  // Collect the inline chain, stopping if we find a location that has already105  // been processed.106  for (DILocation *Loc = RootLoc; Loc; Loc = Loc->getInlinedAt()) {107    if (auto It = Cache.find(Loc); It != Cache.end()) {108      CachedResult = cast<DILocation>(It->second);109      break;110    }111    LocChain.push_back(Loc);112  }113 114  DILocation *UpdatedLoc = CachedResult;115  if (!UpdatedLoc) {116    // If no cache hits, then back() is the end of the inline chain, that is,117    // the DILocation whose scope ends in the Subprogram to be replaced.118    DILocation *LocToUpdate = LocChain.pop_back_val();119    DIScope *NewScope = DILocalScope::cloneScopeForSubprogram(120        *LocToUpdate->getScope(), NewSP, Ctx, Cache);121    UpdatedLoc = DILocation::get(Ctx, LocToUpdate->getLine(),122                                 LocToUpdate->getColumn(), NewScope);123    Cache[LocToUpdate] = UpdatedLoc;124  }125 126  // Recreate the location chain, bottom-up, starting at the new scope (or a127  // cached result).128  for (const DILocation *LocToUpdate : reverse(LocChain)) {129    UpdatedLoc =130        DILocation::get(Ctx, LocToUpdate->getLine(), LocToUpdate->getColumn(),131                        LocToUpdate->getScope(), UpdatedLoc);132    Cache[LocToUpdate] = UpdatedLoc;133  }134 135  return UpdatedLoc;136}137 138DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt,139                                   LLVMContext &Ctx,140                                   DenseMap<const MDNode *, MDNode *> &Cache) {141  SmallVector<DILocation *, 3> InlinedAtLocations;142  DILocation *Last = InlinedAt;143  DILocation *CurInlinedAt = DL;144 145  // Gather all the inlined-at nodes.146  while (DILocation *IA = CurInlinedAt->getInlinedAt()) {147    // Skip any we've already built nodes for.148    if (auto *Found = Cache[IA]) {149      Last = cast<DILocation>(Found);150      break;151    }152 153    InlinedAtLocations.push_back(IA);154    CurInlinedAt = IA;155  }156 157  // Starting from the top, rebuild the nodes to point to the new inlined-at158  // location (then rebuilding the rest of the chain behind it) and update the159  // map of already-constructed inlined-at nodes.160  // Key Instructions: InlinedAt fields don't need atom info.161  for (const DILocation *MD : reverse(InlinedAtLocations))162    Cache[MD] = Last = DILocation::getDistinct(163        Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);164 165  return Last;166}167 168DebugLoc DebugLoc::getMergedLocations(ArrayRef<DebugLoc> Locs) {169  if (Locs.empty())170    return DebugLoc();171  if (Locs.size() == 1)172    return Locs[0];173  DebugLoc Merged = Locs[0];174  for (const DebugLoc &DL : llvm::drop_begin(Locs)) {175    Merged = getMergedLocation(Merged, DL);176    if (!Merged)177      break;178  }179  return Merged;180}181DebugLoc DebugLoc::getMergedLocation(DebugLoc LocA, DebugLoc LocB) {182  if (!LocA || !LocB) {183    // If coverage tracking is enabled, prioritize returning empty non-annotated184    // locations to empty annotated locations.185#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE186    if (!LocA && LocA.getKind() == DebugLocKind::Normal)187      return LocA;188    if (!LocB && LocB.getKind() == DebugLocKind::Normal)189      return LocB;190#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE191    if (!LocA)192      return LocA;193    return LocB;194  }195  return DILocation::getMergedLocation(LocA, LocB);196}197 198#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)199LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }200#endif201 202void DebugLoc::print(raw_ostream &OS) const {203  if (!Loc)204    return;205 206  // Print source line info.207  auto *Scope = cast<DIScope>(getScope());208  OS << Scope->getFilename();209  OS << ':' << getLine();210  if (getCol() != 0)211    OS << ':' << getCol();212 213  if (DebugLoc InlinedAtDL = getInlinedAt()) {214    OS << " @[ ";215    InlinedAtDL.print(OS);216    OS << " ]";217  }218}219