1 //===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===// 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 // This file defines a number of light weight data structures used 10 // to describe and track debug location information. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_IR_DEBUGLOC_H 15 #define LLVM_IR_DEBUGLOC_H 16 17 #include "llvm/Config/llvm-config.h" 18 #include "llvm/IR/TrackingMDRef.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/DataTypes.h" 21 22 namespace llvm { 23 24 class LLVMContext; 25 class raw_ostream; 26 class DILocation; 27 class Function; 28 29 #if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 30 #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN 31 struct DbgLocOrigin { 32 static constexpr unsigned long MaxDepth = 16; 33 using StackTracesTy = 34 SmallVector<std::pair<int, std::array<void *, MaxDepth>>, 0>; 35 StackTracesTy StackTraces; 36 DbgLocOrigin(bool ShouldCollectTrace); 37 void addTrace(); getOriginStackTracesDbgLocOrigin38 const StackTracesTy &getOriginStackTraces() const { return StackTraces; }; 39 }; 40 #else 41 struct DbgLocOrigin { DbgLocOriginDbgLocOrigin42 DbgLocOrigin(bool) {} 43 }; 44 #endif 45 // Used to represent different "kinds" of DebugLoc, expressing that the 46 // instruction it is part of is either normal and should contain a valid 47 // DILocation, or otherwise describing the reason why the instruction does 48 // not contain a valid DILocation. 49 enum class DebugLocKind : uint8_t { 50 // The instruction is expected to contain a valid DILocation. 51 Normal, 52 // The instruction is compiler-generated, i.e. it is not associated with any 53 // line in the original source. 54 CompilerGenerated, 55 // The instruction has intentionally had its source location removed, 56 // typically because it was moved outside of its original control-flow and 57 // presenting the prior source location would be misleading for debuggers 58 // or profilers. 59 Dropped, 60 // The instruction does not have a known or currently knowable source 61 // location, e.g. the attribution is ambiguous in a way that can't be 62 // represented, or determining the correct location is complicated and 63 // requires future developer effort. 64 Unknown, 65 // DebugLoc is attached to an instruction that we don't expect to be 66 // emitted, and so can omit a valid DILocation; we don't expect to ever try 67 // and emit these into the line table, and trying to do so is a sign that 68 // something has gone wrong (most likely a DebugLoc leaking from a transient 69 // compiler-generated instruction). 70 Temporary 71 }; 72 73 // Extends TrackingMDNodeRef to also store a DebugLocKind and Origin, 74 // allowing Debugify to ignore intentionally-empty DebugLocs and display the 75 // code responsible for generating unintentionally-empty DebugLocs. 76 // Currently we only need to track the Origin of this DILoc when using a 77 // DebugLoc that is not annotated (i.e. has DebugLocKind::Normal) and has a 78 // null DILocation, so only collect the origin stacktrace in those cases. 79 class DILocAndCoverageTracking : public TrackingMDNodeRef, 80 public DbgLocOrigin { 81 public: 82 DebugLocKind Kind; 83 // Default constructor for empty DebugLocs. DILocAndCoverageTracking()84 DILocAndCoverageTracking() 85 : TrackingMDNodeRef(nullptr), DbgLocOrigin(true), 86 Kind(DebugLocKind::Normal) {} 87 // Valid or nullptr MDNode*, no annotative DebugLocKind. DILocAndCoverageTracking(const MDNode * Loc)88 DILocAndCoverageTracking(const MDNode *Loc) 89 : TrackingMDNodeRef(const_cast<MDNode *>(Loc)), DbgLocOrigin(!Loc), 90 Kind(DebugLocKind::Normal) {} 91 LLVM_ABI DILocAndCoverageTracking(const DILocation *Loc); 92 // Explicit DebugLocKind, which always means a nullptr MDNode*. DILocAndCoverageTracking(DebugLocKind Kind)93 DILocAndCoverageTracking(DebugLocKind Kind) 94 : TrackingMDNodeRef(nullptr), 95 DbgLocOrigin(Kind == DebugLocKind::Normal), Kind(Kind) {} 96 }; 97 template <> struct simplify_type<DILocAndCoverageTracking> { 98 using SimpleType = MDNode *; 99 100 static MDNode *getSimplifiedValue(DILocAndCoverageTracking &MD) { 101 return MD.get(); 102 } 103 }; 104 template <> struct simplify_type<const DILocAndCoverageTracking> { 105 using SimpleType = MDNode *; 106 107 static MDNode *getSimplifiedValue(const DILocAndCoverageTracking &MD) { 108 return MD.get(); 109 } 110 }; 111 112 using DebugLocTrackingRef = DILocAndCoverageTracking; 113 #else 114 using DebugLocTrackingRef = TrackingMDNodeRef; 115 #endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 116 117 /// A debug info location. 118 /// 119 /// This class is a wrapper around a tracking reference to an \a DILocation 120 /// pointer. 121 /// 122 /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a 123 /// one based on relatively opaque \a MDNode pointers. 124 class DebugLoc { 125 126 DebugLocTrackingRef Loc; 127 128 public: 129 DebugLoc() = default; 130 131 /// Construct from an \a DILocation. 132 LLVM_ABI DebugLoc(const DILocation *L); 133 134 /// Construct from an \a MDNode. 135 /// 136 /// Note: if \c N is not an \a DILocation, a verifier check will fail, and 137 /// accessors will crash. However, construction from other nodes is 138 /// supported in order to handle forward references when reading textual 139 /// IR. 140 LLVM_ABI explicit DebugLoc(const MDNode *N); 141 142 #if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 143 DebugLoc(DebugLocKind Kind) : Loc(Kind) {} 144 DebugLocKind getKind() const { return Loc.Kind; } 145 #endif 146 147 #if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 148 static inline DebugLoc getTemporary() { 149 return DebugLoc(DebugLocKind::Temporary); 150 } 151 static inline DebugLoc getUnknown() { 152 return DebugLoc(DebugLocKind::Unknown); 153 } 154 static inline DebugLoc getCompilerGenerated() { 155 return DebugLoc(DebugLocKind::CompilerGenerated); 156 } 157 static inline DebugLoc getDropped() { 158 return DebugLoc(DebugLocKind::Dropped); 159 } 160 #else 161 static inline DebugLoc getTemporary() { return DebugLoc(); } 162 static inline DebugLoc getUnknown() { return DebugLoc(); } 163 static inline DebugLoc getCompilerGenerated() { return DebugLoc(); } 164 static inline DebugLoc getDropped() { return DebugLoc(); } 165 #endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 166 167 /// When two instructions are combined into a single instruction we also 168 /// need to combine the original locations into a single location. 169 /// When the locations are the same we can use either location. 170 /// When they differ, we need a third location which is distinct from 171 /// either. If they share a common scope, use this scope and compare the 172 /// line/column pair of the locations with the common scope: 173 /// * if both match, keep the line and column; 174 /// * if only the line number matches, keep the line and set the column as 175 /// 0; 176 /// * otherwise set line and column as 0. 177 /// If they do not share a common scope the location is ambiguous and can't 178 /// be represented in a line entry. In this case, set line and column as 0 179 /// and use the scope of any location. 180 /// 181 /// \p LocA \p LocB: The locations to be merged. 182 LLVM_ABI static DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB); 183 184 /// Try to combine the vector of locations passed as input in a single one. 185 /// This function applies getMergedLocation() repeatedly left-to-right. 186 /// 187 /// \p Locs: The locations to be merged. 188 LLVM_ABI static DebugLoc getMergedLocations(ArrayRef<DebugLoc> Locs); 189 190 /// If this DebugLoc is non-empty, returns this DebugLoc; otherwise, selects 191 /// \p Other. 192 /// In coverage-tracking builds, this also accounts for whether this or 193 /// \p Other have an annotative DebugLocKind applied, such that if both are 194 /// empty but exactly one has an annotation, we prefer that annotated 195 /// location. 196 DebugLoc orElse(DebugLoc Other) const { 197 if (*this) 198 return *this; 199 #if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 200 if (Other) 201 return Other; 202 if (getKind() != DebugLocKind::Normal) 203 return *this; 204 if (Other.getKind() != DebugLocKind::Normal) 205 return Other; 206 return *this; 207 #else 208 return Other; 209 #endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE 210 } 211 212 #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN 213 const DbgLocOrigin::StackTracesTy &getOriginStackTraces() const { 214 return Loc.getOriginStackTraces(); 215 } 216 DebugLoc getCopied() const { 217 DebugLoc NewDL = *this; 218 NewDL.Loc.addTrace(); 219 return NewDL; 220 } 221 #else 222 DebugLoc getCopied() const { return *this; } 223 #endif 224 225 /// Get the underlying \a DILocation. 226 /// 227 /// \pre !*this or \c isa<DILocation>(getAsMDNode()). 228 /// @{ 229 LLVM_ABI DILocation *get() const; 230 operator DILocation *() const { return get(); } 231 DILocation *operator->() const { return get(); } 232 DILocation &operator*() const { return *get(); } 233 /// @} 234 235 /// Check for null. 236 /// 237 /// Check for null in a way that is safe with broken debug info. Unlike 238 /// the conversion to \c DILocation, this doesn't require that \c Loc is of 239 /// the right type. Important for cases like \a llvm::StripDebugInfo() and 240 /// \a Instruction::hasMetadata(). 241 explicit operator bool() const { return Loc; } 242 243 /// Check whether this has a trivial destructor. 244 bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } 245 246 enum { ReplaceLastInlinedAt = true }; 247 /// Rebuild the entire inlined-at chain for this instruction so that the top of 248 /// the chain now is inlined-at the new call site. 249 /// \param InlinedAt The new outermost inlined-at in the chain. 250 LLVM_ABI static DebugLoc 251 appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt, LLVMContext &Ctx, 252 DenseMap<const MDNode *, MDNode *> &Cache); 253 254 /// Return true if the source locations match, ignoring isImplicitCode and 255 /// source atom info. 256 bool isSameSourceLocation(const DebugLoc &Other) const { 257 if (get() == Other.get()) 258 return true; 259 return ((bool)*this == (bool)Other) && getLine() == Other.getLine() && 260 getCol() == Other.getCol() && getScope() == Other.getScope() && 261 getInlinedAt() == Other.getInlinedAt(); 262 } 263 264 LLVM_ABI unsigned getLine() const; 265 LLVM_ABI unsigned getCol() const; 266 LLVM_ABI MDNode *getScope() const; 267 LLVM_ABI DILocation *getInlinedAt() const; 268 269 /// Get the fully inlined-at scope for a DebugLoc. 270 /// 271 /// Gets the inlined-at scope for a DebugLoc. 272 LLVM_ABI MDNode *getInlinedAtScope() const; 273 274 /// Rebuild the entire inline-at chain by replacing the subprogram at the 275 /// end of the chain with NewSP. 276 LLVM_ABI static DebugLoc 277 replaceInlinedAtSubprogram(const DebugLoc &DL, DISubprogram &NewSP, 278 LLVMContext &Ctx, 279 DenseMap<const MDNode *, MDNode *> &Cache); 280 281 /// Find the debug info location for the start of the function. 282 /// 283 /// Walk up the scope chain of given debug loc and find line number info 284 /// for the function. 285 /// 286 /// FIXME: Remove this. Users should use DILocation/DILocalScope API to 287 /// find the subprogram, and then DILocation::get(). 288 LLVM_ABI DebugLoc getFnDebugLoc() const; 289 290 /// Return \c this as a bar \a MDNode. 291 MDNode *getAsMDNode() const { return Loc; } 292 293 /// Check if the DebugLoc corresponds to an implicit code. 294 LLVM_ABI bool isImplicitCode() const; 295 LLVM_ABI void setImplicitCode(bool ImplicitCode); 296 297 bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } 298 bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } 299 300 LLVM_ABI void dump() const; 301 302 /// prints source location /path/to/file.exe:line:col @[inlined at] 303 LLVM_ABI void print(raw_ostream &OS) const; 304 }; 305 306 } // end namespace llvm 307 308 #endif // LLVM_IR_DEBUGLOC_H 309