|
18 | 18 |
|
19 | 19 | #include "llvm/ADT/STLExtras.h"
|
20 | 20 | #include "llvm/ADT/SmallPtrSet.h"
|
| 21 | +#include "llvm/ADT/SmallSet.h" |
21 | 22 | #include "llvm/ADT/SmallVector.h"
|
22 | 23 | #include "llvm/ADT/TinyPtrVector.h"
|
23 | 24 | #include "llvm/ADT/iterator_range.h"
|
| 25 | +#include "llvm/IR/DataLayout.h" |
24 | 26 | #include "llvm/IR/IntrinsicInst.h"
|
| 27 | +#include "llvm/IR/PassManager.h" |
25 | 28 |
|
26 | 29 | namespace llvm {
|
27 | 30 |
|
@@ -225,8 +228,75 @@ void RAUW(DIAssignID *Old, DIAssignID *New);
|
225 | 228 | /// Remove all Assignment Tracking related intrinsics and metadata from \p F.
|
226 | 229 | void deleteAll(Function *F);
|
227 | 230 |
|
| 231 | +/// Helper struct for trackAssignments, below. We don't use the similar |
| 232 | +/// DebugVariable class because trackAssignments doesn't (yet?) understand |
| 233 | +/// partial variables (fragment info) as input and want to make that clear and |
| 234 | +/// explicit using types. In addition, eventually we will want to understand |
| 235 | +/// expressions that modify the base address too, which a DebugVariable doesn't |
| 236 | +/// capture. |
| 237 | +struct VarRecord { |
| 238 | + DILocalVariable *Var; |
| 239 | + DILocation *DL; |
| 240 | + |
| 241 | + VarRecord(DbgVariableIntrinsic *DVI) |
| 242 | + : Var(DVI->getVariable()), DL(getDebugValueLoc(DVI)) {} |
| 243 | + VarRecord(DILocalVariable *Var, DILocation *DL) : Var(Var), DL(DL) {} |
| 244 | + friend bool operator<(const VarRecord &LHS, const VarRecord &RHS) { |
| 245 | + return std::tie(LHS.Var, LHS.DL) < std::tie(RHS.Var, RHS.DL); |
| 246 | + } |
| 247 | + friend bool operator==(const VarRecord &LHS, const VarRecord &RHS) { |
| 248 | + return std::tie(LHS.Var, LHS.DL) == std::tie(RHS.Var, RHS.DL); |
| 249 | + } |
| 250 | +}; |
| 251 | + |
| 252 | +/// Map of backing storage to a set of variables that are stored to it. |
| 253 | +/// TODO: Backing storage shouldn't be limited to allocas only. Some local |
| 254 | +/// variables have their storage allocated by the calling function (addresses |
| 255 | +/// passed in with sret & byval parameters). |
| 256 | +using StorageToVarsMap = DenseMap<const AllocaInst *, SmallSet<VarRecord, 2>>; |
| 257 | + |
| 258 | +/// Track assignments to \p Vars between \p Start and \p End. |
| 259 | + |
| 260 | +void trackAssignments(Function::iterator Start, Function::iterator End, |
| 261 | + const StorageToVarsMap &Vars, const DataLayout &DL, |
| 262 | + bool DebugPrints = false); |
| 263 | + |
| 264 | +/// Describes properties of a store that has a static size and offset into a |
| 265 | +/// some base storage. Used by the getAssignmentInfo functions. |
| 266 | +struct AssignmentInfo { |
| 267 | + AllocaInst const *Base; ///< Base storage. |
| 268 | + uint64_t OffsetInBits; ///< Offset into Base. |
| 269 | + uint64_t SizeInBits; ///< Number of bits stored. |
| 270 | + bool StoreToWholeAlloca; ///< SizeInBits equals the size of the base storage. |
| 271 | + |
| 272 | + AssignmentInfo(const DataLayout &DL, AllocaInst const *Base, |
| 273 | + uint64_t OffsetInBits, uint64_t SizeInBits) |
| 274 | + : Base(Base), OffsetInBits(OffsetInBits), SizeInBits(SizeInBits), |
| 275 | + StoreToWholeAlloca( |
| 276 | + OffsetInBits == 0 && |
| 277 | + SizeInBits == DL.getTypeSizeInBits(Base->getAllocatedType())) {} |
| 278 | +}; |
| 279 | + |
| 280 | +Optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, |
| 281 | + const MemIntrinsic *I); |
| 282 | +Optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, |
| 283 | + const StoreInst *SI); |
| 284 | +Optional<AssignmentInfo> getAssignmentInfo(const DataLayout &DL, |
| 285 | + const AllocaInst *AI); |
| 286 | + |
228 | 287 | } // end namespace at
|
229 | 288 |
|
| 289 | +/// Convert @llvm.dbg.declare intrinsics into sets of @llvm.dbg.assign |
| 290 | +/// intrinsics by treating stores to the dbg.declare'd address as assignments |
| 291 | +/// to the variable. Not all kinds of variables are supported yet; those will |
| 292 | +/// be left with their dbg.declare intrinsics. |
| 293 | +class AssignmentTrackingPass : public PassInfoMixin<AssignmentTrackingPass> { |
| 294 | +public: |
| 295 | + void runOnFunction(Function &F); |
| 296 | + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
| 297 | + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); |
| 298 | +}; |
| 299 | + |
230 | 300 | /// Return true if assignment tracking is enabled.
|
231 | 301 | bool getEnableAssignmentTracking();
|
232 | 302 | } // end namespace llvm
|
|
0 commit comments