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