File indexing completed on 2026-05-10 08:43:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_IR_DEBUGINFO_H
0017 #define LLVM_IR_DEBUGINFO_H
0018
0019 #include "llvm/ADT/DenseMapInfo.h"
0020 #include "llvm/ADT/STLExtras.h"
0021 #include "llvm/ADT/SetVector.h"
0022 #include "llvm/ADT/SmallPtrSet.h"
0023 #include "llvm/ADT/SmallSet.h"
0024 #include "llvm/ADT/SmallVector.h"
0025 #include "llvm/ADT/TinyPtrVector.h"
0026 #include "llvm/ADT/iterator_range.h"
0027 #include "llvm/IR/DataLayout.h"
0028 #include "llvm/IR/IntrinsicInst.h"
0029 #include "llvm/IR/PassManager.h"
0030 #include <optional>
0031
0032 namespace llvm {
0033
0034 class DbgDeclareInst;
0035 class DbgValueInst;
0036 class DbgVariableIntrinsic;
0037 class DbgVariableRecord;
0038 class Instruction;
0039 class Module;
0040
0041
0042
0043 TinyPtrVector<DbgDeclareInst *> findDbgDeclares(Value *V);
0044
0045 TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V);
0046
0047 TinyPtrVector<DbgVariableRecord *> findDVRValues(Value *V);
0048
0049
0050 void findDbgValues(
0051 SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V,
0052 SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr);
0053
0054
0055 void findDbgUsers(
0056 SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V,
0057 SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr);
0058
0059
0060 DISubprogram *getDISubprogram(const MDNode *Scope);
0061
0062
0063
0064 DebugLoc getDebugValueLoc(DbgVariableIntrinsic *DII);
0065 DebugLoc getDebugValueLoc(DbgVariableRecord *DVR);
0066
0067
0068
0069
0070
0071
0072 bool StripDebugInfo(Module &M);
0073 bool stripDebugInfo(Function &F);
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 bool stripNonLineTableDebugInfo(Module &M);
0086
0087
0088
0089
0090
0091 void updateLoopMetadataDebugLocations(
0092 Instruction &I, function_ref<Metadata *(Metadata *)> Updater);
0093
0094
0095 unsigned getDebugMetadataVersionFromModule(const Module &M);
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 class DebugInfoFinder {
0106 public:
0107
0108 void processModule(const Module &M);
0109
0110 void processInstruction(const Module &M, const Instruction &I);
0111
0112
0113 void processVariable(const Module &M, const DILocalVariable *DVI);
0114
0115 void processLocation(const Module &M, const DILocation *Loc);
0116
0117
0118 void processDbgRecord(const Module &M, const DbgRecord &DR);
0119
0120
0121 void processSubprogram(DISubprogram *SP);
0122
0123
0124 void reset();
0125
0126 private:
0127 void processCompileUnit(DICompileUnit *CU);
0128 void processScope(DIScope *Scope);
0129 void processType(DIType *DT);
0130 bool addCompileUnit(DICompileUnit *CU);
0131 bool addGlobalVariable(DIGlobalVariableExpression *DIG);
0132 bool addScope(DIScope *Scope);
0133 bool addSubprogram(DISubprogram *SP);
0134 bool addType(DIType *DT);
0135
0136 public:
0137 using compile_unit_iterator =
0138 SmallVectorImpl<DICompileUnit *>::const_iterator;
0139 using subprogram_iterator = SmallVectorImpl<DISubprogram *>::const_iterator;
0140 using global_variable_expression_iterator =
0141 SmallVectorImpl<DIGlobalVariableExpression *>::const_iterator;
0142 using type_iterator = SmallVectorImpl<DIType *>::const_iterator;
0143 using scope_iterator = SmallVectorImpl<DIScope *>::const_iterator;
0144
0145 iterator_range<compile_unit_iterator> compile_units() const {
0146 return make_range(CUs.begin(), CUs.end());
0147 }
0148
0149 iterator_range<subprogram_iterator> subprograms() const {
0150 return make_range(SPs.begin(), SPs.end());
0151 }
0152
0153 iterator_range<global_variable_expression_iterator> global_variables() const {
0154 return make_range(GVs.begin(), GVs.end());
0155 }
0156
0157 iterator_range<type_iterator> types() const {
0158 return make_range(TYs.begin(), TYs.end());
0159 }
0160
0161 iterator_range<scope_iterator> scopes() const {
0162 return make_range(Scopes.begin(), Scopes.end());
0163 }
0164
0165 unsigned compile_unit_count() const { return CUs.size(); }
0166 unsigned global_variable_count() const { return GVs.size(); }
0167 unsigned subprogram_count() const { return SPs.size(); }
0168 unsigned type_count() const { return TYs.size(); }
0169 unsigned scope_count() const { return Scopes.size(); }
0170
0171 private:
0172 SmallVector<DICompileUnit *, 8> CUs;
0173 SmallVector<DISubprogram *, 8> SPs;
0174 SmallVector<DIGlobalVariableExpression *, 8> GVs;
0175 SmallVector<DIType *, 8> TYs;
0176 SmallVector<DIScope *, 8> Scopes;
0177 SmallPtrSet<const MDNode *, 32> NodesSeen;
0178 };
0179
0180
0181 namespace at {
0182
0183
0184
0185
0186 using AssignmentInstRange =
0187 iterator_range<SmallVectorImpl<Instruction *>::iterator>;
0188
0189
0190
0191
0192 AssignmentInstRange getAssignmentInsts(DIAssignID *ID);
0193
0194
0195
0196
0197 inline AssignmentInstRange getAssignmentInsts(const DbgAssignIntrinsic *DAI) {
0198 return getAssignmentInsts(DAI->getAssignID());
0199 }
0200
0201 inline AssignmentInstRange getAssignmentInsts(const DbgVariableRecord *DVR) {
0202 assert(DVR->isDbgAssign() &&
0203 "Can't get assignment instructions for non-assign DVR!");
0204 return getAssignmentInsts(DVR->getAssignID());
0205 }
0206
0207
0208
0209
0210
0211
0212
0213 class DbgAssignIt
0214 : public iterator_adaptor_base<DbgAssignIt, Value::user_iterator,
0215 typename std::iterator_traits<
0216 Value::user_iterator>::iterator_category,
0217 DbgAssignIntrinsic *, std::ptrdiff_t,
0218 DbgAssignIntrinsic **,
0219 DbgAssignIntrinsic *&> {
0220 public:
0221 DbgAssignIt(Value::user_iterator It) : iterator_adaptor_base(It) {}
0222 DbgAssignIntrinsic *operator*() const { return cast<DbgAssignIntrinsic>(*I); }
0223 };
0224
0225 using AssignmentMarkerRange = iterator_range<DbgAssignIt>;
0226
0227
0228 AssignmentMarkerRange getAssignmentMarkers(DIAssignID *ID);
0229
0230
0231
0232 inline AssignmentMarkerRange getAssignmentMarkers(const Instruction *Inst) {
0233 if (auto *ID = Inst->getMetadata(LLVMContext::MD_DIAssignID))
0234 return getAssignmentMarkers(cast<DIAssignID>(ID));
0235 else
0236 return make_range(Value::user_iterator(), Value::user_iterator());
0237 }
0238
0239 inline SmallVector<DbgVariableRecord *>
0240 getDVRAssignmentMarkers(const Instruction *Inst) {
0241 if (auto *ID = Inst->getMetadata(LLVMContext::MD_DIAssignID))
0242 return cast<DIAssignID>(ID)->getAllDbgVariableRecordUsers();
0243 return {};
0244 }
0245
0246
0247 void deleteAssignmentMarkers(const Instruction *Inst);
0248
0249
0250 void RAUW(DIAssignID *Old, DIAssignID *New);
0251
0252
0253 void deleteAll(Function *F);
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 bool calculateFragmentIntersect(
0265 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits,
0266 uint64_t SliceSizeInBits, const DbgAssignIntrinsic *DbgAssign,
0267 std::optional<DIExpression::FragmentInfo> &Result);
0268 bool calculateFragmentIntersect(
0269 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits,
0270 uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign,
0271 std::optional<DIExpression::FragmentInfo> &Result);
0272
0273
0274
0275 void remapAssignID(DenseMap<DIAssignID *, DIAssignID *> &Map, Instruction &I);
0276
0277
0278
0279
0280
0281
0282
0283 struct VarRecord {
0284 DILocalVariable *Var;
0285 DILocation *DL;
0286
0287 VarRecord(DbgVariableIntrinsic *DVI)
0288 : Var(DVI->getVariable()), DL(getDebugValueLoc(DVI)) {}
0289 VarRecord(DbgVariableRecord *DVR)
0290 : Var(DVR->getVariable()), DL(getDebugValueLoc(DVR)) {}
0291 VarRecord(DILocalVariable *Var, DILocation *DL) : Var(Var), DL(DL) {}
0292 friend bool operator<(const VarRecord &LHS, const VarRecord &RHS) {
0293 return std::tie(LHS.Var, LHS.DL) < std::tie(RHS.Var, RHS.DL);
0294 }
0295 friend bool operator==(const VarRecord &LHS, const VarRecord &RHS) {
0296 return std::tie(LHS.Var, LHS.DL) == std::tie(RHS.Var, RHS.DL);
0297 }
0298 };
0299
0300 }
0301
0302 template <> struct DenseMapInfo<at::VarRecord> {
0303 static inline at::VarRecord getEmptyKey() {
0304 return at::VarRecord(DenseMapInfo<DILocalVariable *>::getEmptyKey(),
0305 DenseMapInfo<DILocation *>::getEmptyKey());
0306 }
0307
0308 static inline at::VarRecord getTombstoneKey() {
0309 return at::VarRecord(DenseMapInfo<DILocalVariable *>::getTombstoneKey(),
0310 DenseMapInfo<DILocation *>::getTombstoneKey());
0311 }
0312
0313 static unsigned getHashValue(const at::VarRecord &Var) {
0314 return hash_combine(Var.Var, Var.DL);
0315 }
0316
0317 static bool isEqual(const at::VarRecord &A, const at::VarRecord &B) {
0318 return A == B;
0319 }
0320 };
0321
0322 namespace at {
0323
0324
0325
0326
0327 using StorageToVarsMap =
0328 DenseMap<const AllocaInst *, SmallSetVector<VarRecord, 2>>;
0329
0330
0331
0332 void trackAssignments(Function::iterator Start, Function::iterator End,
0333 const StorageToVarsMap &Vars, const DataLayout &DL,
0334 bool DebugPrints = false);
0335
0336
0337
0338 struct AssignmentInfo {
0339 AllocaInst const *Base;
0340 uint64_t OffsetInBits;
0341 uint64_t SizeInBits;
0342 bool StoreToWholeAlloca;
0343
0344 AssignmentInfo(const DataLayout &DL, AllocaInst const *Base,
0345 uint64_t OffsetInBits, uint64_t SizeInBits)
0346 : Base(Base), OffsetInBits(OffsetInBits), SizeInBits(SizeInBits),
0347 StoreToWholeAlloca(
0348 OffsetInBits == 0 &&
0349 SizeInBits == DL.getTypeSizeInBits(Base->getAllocatedType())) {}
0350 };
0351
0352 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL,
0353 const MemIntrinsic *I);
0354 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL,
0355 const StoreInst *SI);
0356 std::optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL,
0357 const AllocaInst *AI);
0358
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 class AssignmentTrackingPass : public PassInfoMixin<AssignmentTrackingPass> {
0368
0369
0370 bool runOnFunction(Function &F);
0371
0372 public:
0373 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0374 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0375 };
0376
0377
0378 bool isAssignmentTrackingEnabled(const Module &M);
0379
0380 }
0381
0382 #endif