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