1 //===- DebugInfo.h - Debug Information Helpers ------------------*- 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 bunch of datatypes that are useful for creating and 10 // walking debug info in LLVM IR form. They essentially provide wrappers around 11 // the information in the global variables that's needed when constructing the 12 // DWARF information. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_IR_DEBUGINFO_H 17 #define LLVM_IR_DEBUGINFO_H 18 19 #include "llvm/ADT/DenseMapInfo.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/ADT/SetVector.h" 22 #include "llvm/ADT/SmallPtrSet.h" 23 #include "llvm/ADT/SmallSet.h" 24 #include "llvm/ADT/SmallVector.h" 25 #include "llvm/ADT/TinyPtrVector.h" 26 #include "llvm/ADT/iterator_range.h" 27 #include "llvm/IR/DataLayout.h" 28 #include "llvm/IR/IntrinsicInst.h" 29 #include "llvm/IR/PassManager.h" 30 #include <optional> 31 32 namespace llvm { 33 34 class DbgDeclareInst; 35 class DbgValueInst; 36 class DbgVariableIntrinsic; 37 class DbgVariableRecord; 38 class Instruction; 39 class Module; 40 41 /// Finds dbg.declare intrinsics declaring local variables as living in the 42 /// memory that 'V' points to. 43 TinyPtrVector<DbgDeclareInst *> findDbgDeclares(Value *V); 44 /// As above, for DVRDeclares. 45 TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V); 46 47 /// Finds the llvm.dbg.value intrinsics describing a value. 48 void findDbgValues( 49 SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V, 50 SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr); 51 52 /// Finds the debug info intrinsics describing a value. 53 void findDbgUsers( 54 SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V, 55 SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr); 56 57 /// Find subprogram that is enclosing this scope. 58 DISubprogram *getDISubprogram(const MDNode *Scope); 59 60 /// Produce a DebugLoc to use for each dbg.declare that is promoted to a 61 /// dbg.value. 62 DebugLoc getDebugValueLoc(DbgVariableIntrinsic *DII); 63 DebugLoc getDebugValueLoc(DbgVariableRecord *DVR); 64 65 /// Strip debug info in the module if it exists. 66 /// 67 /// To do this, we remove all calls to the debugger intrinsics and any named 68 /// metadata for debugging. We also remove debug locations for instructions. 69 /// Return true if module is modified. 70 bool StripDebugInfo(Module &M); 71 bool stripDebugInfo(Function &F); 72 73 /// Downgrade the debug info in a module to contain only line table information. 74 /// 75 /// In order to convert debug info to what -gline-tables-only would have 76 /// created, this does the following: 77 /// 1) Delete all debug intrinsics. 78 /// 2) Delete all non-CU named metadata debug info nodes. 79 /// 3) Create new DebugLocs for each instruction. 80 /// 4) Create a new CU debug info, and similarly for every metadata node 81 /// that's reachable from the CU debug info. 82 /// All debug type metadata nodes are unreachable and garbage collected. 83 bool stripNonLineTableDebugInfo(Module &M); 84 85 /// Update the debug locations contained within the MD_loop metadata attached 86 /// to the instruction \p I, if one exists. \p Updater is applied to Metadata 87 /// operand in the MD_loop metadata: the returned value is included in the 88 /// updated loop metadata node if it is non-null. 89 void updateLoopMetadataDebugLocations( 90 Instruction &I, function_ref<Metadata *(Metadata *)> Updater); 91 92 /// Return Debug Info Metadata Version by checking module flags. 93 unsigned getDebugMetadataVersionFromModule(const Module &M); 94 95 /// Utility to find all debug info in a module. 96 /// 97 /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To 98 /// list debug info MDNodes used by an instruction, DebugInfoFinder uses 99 /// processDeclare, processValue and processLocation to handle DbgDeclareInst, 100 /// DbgValueInst and DbgLoc attached to instructions. processModule will go 101 /// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes 102 /// used by the CUs. 103 class DebugInfoFinder { 104 public: 105 /// Process entire module and collect debug info anchors. 106 void processModule(const Module &M); 107 /// Process a single instruction and collect debug info anchors. 108 void processInstruction(const Module &M, const Instruction &I); 109 110 /// Process a DILocalVariable. 111 void processVariable(const Module &M, const DILocalVariable *DVI); 112 /// Process debug info location. 113 void processLocation(const Module &M, const DILocation *Loc); 114 /// Process a DbgRecord (e.g, treat a DbgVariableRecord like a 115 /// DbgVariableIntrinsic). 116 void processDbgRecord(const Module &M, const DbgRecord &DR); 117 118 /// Process subprogram. 119 void processSubprogram(DISubprogram *SP); 120 121 /// Clear all lists. 122 void reset(); 123 124 private: 125 void processCompileUnit(DICompileUnit *CU); 126 void processScope(DIScope *Scope); 127 void processType(DIType *DT); 128 bool addCompileUnit(DICompileUnit *CU); 129 bool addGlobalVariable(DIGlobalVariableExpression *DIG); 130 bool addScope(DIScope *Scope); 131 bool addSubprogram(DISubprogram *SP); 132 bool addType(DIType *DT); 133 134 public: 135 using compile_unit_iterator = 136 SmallVectorImpl<DICompileUnit *>::const_iterator; 137 using subprogram_iterator = SmallVectorImpl<DISubprogram *>::const_iterator; 138 using global_variable_expression_iterator = 139 SmallVectorImpl<DIGlobalVariableExpression *>::const_iterator; 140 using type_iterator = SmallVectorImpl<DIType *>::const_iterator; 141 using scope_iterator = SmallVectorImpl<DIScope *>::const_iterator; 142 143 iterator_range<compile_unit_iterator> compile_units() const { 144 return make_range(CUs.begin(), CUs.end()); 145 } 146 147 iterator_range<subprogram_iterator> subprograms() const { 148 return make_range(SPs.begin(), SPs.end()); 149 } 150 151 iterator_range<global_variable_expression_iterator> global_variables() const { 152 return make_range(GVs.begin(), GVs.end()); 153 } 154 155 iterator_range<type_iterator> types() const { 156 return make_range(TYs.begin(), TYs.end()); 157 } 158 159 iterator_range<scope_iterator> scopes() const { 160 return make_range(Scopes.begin(), Scopes.end()); 161 } 162 163 unsigned compile_unit_count() const { return CUs.size(); } 164 unsigned global_variable_count() const { return GVs.size(); } 165 unsigned subprogram_count() const { return SPs.size(); } 166 unsigned type_count() const { return TYs.size(); } 167 unsigned scope_count() const { return Scopes.size(); } 168 169 private: 170 SmallVector<DICompileUnit *, 8> CUs; 171 SmallVector<DISubprogram *, 8> SPs; 172 SmallVector<DIGlobalVariableExpression *, 8> GVs; 173 SmallVector<DIType *, 8> TYs; 174 SmallVector<DIScope *, 8> Scopes; 175 SmallPtrSet<const MDNode *, 32> NodesSeen; 176 }; 177 178 /// Assignment Tracking (at). 179 namespace at { 180 // 181 // Utilities for enumerating storing instructions from an assignment ID. 182 // 183 /// A range of instructions. 184 using AssignmentInstRange = 185 iterator_range<SmallVectorImpl<Instruction *>::iterator>; 186 /// Return a range of instructions (typically just one) that have \p ID 187 /// as an attachment. 188 /// Iterators invalidated by adding or removing DIAssignID metadata to/from any 189 /// instruction (including by deleting or cloning instructions). 190 AssignmentInstRange getAssignmentInsts(DIAssignID *ID); 191 /// Return a range of instructions (typically just one) that perform the 192 /// assignment that \p DAI encodes. 193 /// Iterators invalidated by adding or removing DIAssignID metadata to/from any 194 /// instruction (including by deleting or cloning instructions). 195 inline AssignmentInstRange getAssignmentInsts(const DbgAssignIntrinsic *DAI) { 196 return getAssignmentInsts(DAI->getAssignID()); 197 } 198 199 inline AssignmentInstRange getAssignmentInsts(const DbgVariableRecord *DVR) { 200 assert(DVR->isDbgAssign() && 201 "Can't get assignment instructions for non-assign DVR!"); 202 return getAssignmentInsts(DVR->getAssignID()); 203 } 204 205 // 206 // Utilities for enumerating llvm.dbg.assign intrinsic from an assignment ID. 207 // 208 /// High level: this is an iterator for llvm.dbg.assign intrinsics. 209 /// Implementation details: this is a wrapper around Value's User iterator that 210 /// dereferences to a DbgAssignIntrinsic ptr rather than a User ptr. 211 class DbgAssignIt 212 : public iterator_adaptor_base<DbgAssignIt, Value::user_iterator, 213 typename std::iterator_traits< 214 Value::user_iterator>::iterator_category, 215 DbgAssignIntrinsic *, std::ptrdiff_t, 216 DbgAssignIntrinsic **, 217 DbgAssignIntrinsic *&> { 218 public: 219 DbgAssignIt(Value::user_iterator It) : iterator_adaptor_base(It) {} 220 DbgAssignIntrinsic *operator*() const { return cast<DbgAssignIntrinsic>(*I); } 221 }; 222 /// A range of llvm.dbg.assign intrinsics. 223 using AssignmentMarkerRange = iterator_range<DbgAssignIt>; 224 /// Return a range of dbg.assign intrinsics which use \ID as an operand. 225 /// Iterators invalidated by deleting an intrinsic contained in this range. 226 AssignmentMarkerRange getAssignmentMarkers(DIAssignID *ID); 227 /// Return a range of dbg.assign intrinsics for which \p Inst performs the 228 /// assignment they encode. 229 /// Iterators invalidated by deleting an intrinsic contained in this range. 230 inline AssignmentMarkerRange getAssignmentMarkers(const Instruction *Inst) { 231 if (auto *ID = Inst->getMetadata(LLVMContext::MD_DIAssignID)) 232 return getAssignmentMarkers(cast<DIAssignID>(ID)); 233 else 234 return make_range(Value::user_iterator(), Value::user_iterator()); 235 } 236 237 inline SmallVector<DbgVariableRecord *> 238 getDVRAssignmentMarkers(const Instruction *Inst) { 239 if (auto *ID = Inst->getMetadata(LLVMContext::MD_DIAssignID)) 240 return cast<DIAssignID>(ID)->getAllDbgVariableRecordUsers(); 241 return {}; 242 } 243 244 /// Delete the llvm.dbg.assign intrinsics linked to \p Inst. 245 void deleteAssignmentMarkers(const Instruction *Inst); 246 247 /// Replace all uses (and attachments) of \p Old with \p New. 248 void RAUW(DIAssignID *Old, DIAssignID *New); 249 250 /// Remove all Assignment Tracking related intrinsics and metadata from \p F. 251 void deleteAll(Function *F); 252 253 /// Calculate the fragment of the variable in \p DAI covered 254 /// from (Dest + SliceOffsetInBits) to 255 /// to (Dest + SliceOffsetInBits + SliceSizeInBits) 256 /// 257 /// Return false if it can't be calculated for any reason. 258 /// Result is set to nullopt if the intersect equals the variable fragment (or 259 /// variable size) in DAI. 260 /// 261 /// Result contains a zero-sized fragment if there's no intersect. 262 bool calculateFragmentIntersect( 263 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, 264 uint64_t SliceSizeInBits, const DbgAssignIntrinsic *DbgAssign, 265 std::optional<DIExpression::FragmentInfo> &Result); 266 bool calculateFragmentIntersect( 267 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, 268 uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, 269 std::optional<DIExpression::FragmentInfo> &Result); 270 271 /// Replace DIAssignID uses and attachments with IDs from \p Map. 272 /// If an ID is unmapped a new ID is generated and added to \p Map. 273 void remapAssignID(DenseMap<DIAssignID *, DIAssignID *> &Map, Instruction &I); 274 275 /// Helper struct for trackAssignments, below. We don't use the similar 276 /// DebugVariable class because trackAssignments doesn't (yet?) understand 277 /// partial variables (fragment info) as input and want to make that clear and 278 /// explicit using types. In addition, eventually we will want to understand 279 /// expressions that modify the base address too, which a DebugVariable doesn't 280 /// capture. 281 struct VarRecord { 282 DILocalVariable *Var; 283 DILocation *DL; 284 285 VarRecord(DbgVariableIntrinsic *DVI) 286 : Var(DVI->getVariable()), DL(getDebugValueLoc(DVI)) {} 287 VarRecord(DbgVariableRecord *DVR) 288 : Var(DVR->getVariable()), DL(getDebugValueLoc(DVR)) {} 289 VarRecord(DILocalVariable *Var, DILocation *DL) : Var(Var), DL(DL) {} 290 friend bool operator<(const VarRecord &LHS, const VarRecord &RHS) { 291 return std::tie(LHS.Var, LHS.DL) < std::tie(RHS.Var, RHS.DL); 292 } 293 friend bool operator==(const VarRecord &LHS, const VarRecord &RHS) { 294 return std::tie(LHS.Var, LHS.DL) == std::tie(RHS.Var, RHS.DL); 295 } 296 }; 297 298 } // namespace at 299 300 template <> struct DenseMapInfo<at::VarRecord> { 301 static inline at::VarRecord getEmptyKey() { 302 return at::VarRecord(DenseMapInfo<DILocalVariable *>::getEmptyKey(), 303 DenseMapInfo<DILocation *>::getEmptyKey()); 304 } 305 306 static inline at::VarRecord getTombstoneKey() { 307 return at::VarRecord(DenseMapInfo<DILocalVariable *>::getTombstoneKey(), 308 DenseMapInfo<DILocation *>::getTombstoneKey()); 309 } 310 311 static unsigned getHashValue(const at::VarRecord &Var) { 312 return hash_combine(Var.Var, Var.DL); 313 } 314 315 static bool isEqual(const at::VarRecord &A, const at::VarRecord &B) { 316 return A == B; 317 } 318 }; 319 320 namespace at { 321 /// Map of backing storage to a set of variables that are stored to it. 322 /// TODO: Backing storage shouldn't be limited to allocas only. Some local 323 /// variables have their storage allocated by the calling function (addresses 324 /// passed in with sret & byval parameters). 325 using StorageToVarsMap = 326 DenseMap<const AllocaInst *, SmallSetVector<VarRecord, 2>>; 327 328 /// Track assignments to \p Vars between \p Start and \p End. 329 330 void trackAssignments(Function::iterator Start, Function::iterator End, 331 const StorageToVarsMap &Vars, const DataLayout &DL, 332 bool DebugPrints = false); 333 334 /// Describes properties of a store that has a static size and offset into a 335 /// some base storage. Used by the getAssignmentInfo functions. 336 struct AssignmentInfo { 337 AllocaInst const *Base; ///< Base storage. 338 uint64_t OffsetInBits; ///< Offset into Base. 339 uint64_t SizeInBits; ///< Number of bits stored. 340 bool StoreToWholeAlloca; ///< SizeInBits equals the size of the base storage. 341 342 AssignmentInfo(const DataLayout &DL, AllocaInst const *Base, 343 uint64_t OffsetInBits, uint64_t SizeInBits) 344 : Base(Base), OffsetInBits(OffsetInBits), SizeInBits(SizeInBits), 345 StoreToWholeAlloca( 346 OffsetInBits == 0 && 347 SizeInBits == DL.getTypeSizeInBits(Base->getAllocatedType())) {} 348 }; 349 350 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, 351 const MemIntrinsic *I); 352 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, 353 const StoreInst *SI); 354 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, 355 const AllocaInst *AI); 356 357 } // end namespace at 358 359 /// Convert @llvm.dbg.declare intrinsics into sets of @llvm.dbg.assign 360 /// intrinsics by treating stores to the dbg.declare'd address as assignments 361 /// to the variable. Not all kinds of variables are supported yet; those will 362 /// be left with their dbg.declare intrinsics. 363 /// The pass sets the debug-info-assignment-tracking module flag to true to 364 /// indicate assignment tracking has been enabled. 365 class AssignmentTrackingPass : public PassInfoMixin<AssignmentTrackingPass> { 366 /// Note: this method does not set the debug-info-assignment-tracking module 367 /// flag. 368 bool runOnFunction(Function &F); 369 370 public: 371 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 372 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 373 }; 374 375 /// Return true if assignment tracking is enabled for module \p M. 376 bool isAssignmentTrackingEnabled(const Module &M); 377 378 } // end namespace llvm 379 380 #endif // LLVM_IR_DEBUGINFO_H 381