File indexing completed on 2026-05-10 08:43:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
0015 #define LLVM_ANALYSIS_MEMORYBUILTINS_H
0016
0017 #include "llvm/ADT/APInt.h"
0018 #include "llvm/ADT/DenseMap.h"
0019 #include "llvm/ADT/SmallPtrSet.h"
0020 #include "llvm/Analysis/TargetFolder.h"
0021 #include "llvm/IR/IRBuilder.h"
0022 #include "llvm/IR/InstVisitor.h"
0023 #include "llvm/IR/ValueHandle.h"
0024 #include <cstdint>
0025 #include <optional>
0026 #include <utility>
0027
0028 namespace llvm {
0029
0030 class AllocaInst;
0031 class AAResults;
0032 class Argument;
0033 class ConstantPointerNull;
0034 class DataLayout;
0035 class ExtractElementInst;
0036 class ExtractValueInst;
0037 class GEPOperator;
0038 class GlobalAlias;
0039 class GlobalVariable;
0040 class Instruction;
0041 class IntegerType;
0042 class IntrinsicInst;
0043 class IntToPtrInst;
0044 class LLVMContext;
0045 class LoadInst;
0046 class PHINode;
0047 class SelectInst;
0048 class Type;
0049 class UndefValue;
0050 class Value;
0051
0052
0053
0054
0055 bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI);
0056 bool isAllocationFn(const Value *V,
0057 function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
0058
0059
0060
0061 bool isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI);
0062
0063
0064
0065 bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
0066
0067
0068
0069 bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
0070
0071
0072
0073 bool isReallocLikeFn(const Function *F);
0074
0075
0076 Value *getReallocatedOperand(const CallBase *CB);
0077
0078
0079
0080
0081
0082
0083 bool isLibFreeFunction(const Function *F, const LibFunc TLIFn);
0084
0085
0086 Value *getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI);
0102
0103
0104
0105
0106
0107 Value *getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI);
0108
0109
0110
0111
0112
0113
0114 std::optional<APInt> getAllocSize(
0115 const CallBase *CB, const TargetLibraryInfo *TLI,
0116 function_ref<const Value *(const Value *)> Mapper = [](const Value *V) {
0117 return V;
0118 });
0119
0120
0121
0122
0123 Constant *getInitialValueOfAllocation(const Value *V,
0124 const TargetLibraryInfo *TLI,
0125 Type *Ty);
0126
0127
0128
0129
0130 std::optional<StringRef> getAllocationFamily(const Value *I,
0131 const TargetLibraryInfo *TLI);
0132
0133
0134
0135
0136
0137
0138 struct ObjectSizeOpts {
0139
0140 enum class Mode : uint8_t {
0141
0142
0143 ExactSizeFromOffset,
0144
0145
0146 ExactUnderlyingSizeAndOffset,
0147
0148
0149 Min,
0150
0151 Max,
0152 };
0153
0154
0155 Mode EvalMode = Mode::ExactSizeFromOffset;
0156
0157
0158 bool RoundToAlign = false;
0159
0160
0161
0162 bool NullIsUnknownSize = false;
0163
0164 AAResults *AA = nullptr;
0165 };
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
0176 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
0177
0178
0179
0180
0181
0182 Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL,
0183 const TargetLibraryInfo *TLI, bool MustSucceed);
0184 Value *lowerObjectSizeCall(
0185 IntrinsicInst *ObjectSize, const DataLayout &DL,
0186 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
0187 SmallVectorImpl<Instruction *> *InsertedInstructions = nullptr);
0188
0189
0190
0191
0192 template <typename T, class C> struct SizeOffsetType {
0193 public:
0194 T Size;
0195 T Offset;
0196
0197 SizeOffsetType() = default;
0198 SizeOffsetType(T Size, T Offset)
0199 : Size(std::move(Size)), Offset(std::move(Offset)) {}
0200
0201 bool knownSize() const { return C::known(Size); }
0202 bool knownOffset() const { return C::known(Offset); }
0203 bool anyKnown() const { return knownSize() || knownOffset(); }
0204 bool bothKnown() const { return knownSize() && knownOffset(); }
0205
0206 bool operator==(const SizeOffsetType<T, C> &RHS) const {
0207 return Size == RHS.Size && Offset == RHS.Offset;
0208 }
0209 bool operator!=(const SizeOffsetType<T, C> &RHS) const {
0210 return !(*this == RHS);
0211 }
0212 };
0213
0214
0215
0216 struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
0217 SizeOffsetAPInt() = default;
0218 SizeOffsetAPInt(APInt Size, APInt Offset)
0219 : SizeOffsetType(std::move(Size), std::move(Offset)) {}
0220
0221 static bool known(const APInt &V) { return V.getBitWidth() > 1; }
0222 };
0223
0224
0225
0226
0227
0228
0229
0230 struct OffsetSpan {
0231 APInt Before;
0232 APInt After;
0233
0234 OffsetSpan() = default;
0235 OffsetSpan(APInt Before, APInt After) : Before(Before), After(After) {}
0236
0237 bool knownBefore() const { return known(Before); }
0238 bool knownAfter() const { return known(After); }
0239 bool anyKnown() const { return knownBefore() || knownAfter(); }
0240 bool bothKnown() const { return knownBefore() && knownAfter(); }
0241
0242 bool operator==(const OffsetSpan &RHS) const {
0243 return Before == RHS.Before && After == RHS.After;
0244 }
0245 bool operator!=(const OffsetSpan &RHS) const { return !(*this == RHS); }
0246
0247 static bool known(const APInt &V) { return V.getBitWidth() > 1; }
0248 };
0249
0250
0251
0252 class ObjectSizeOffsetVisitor
0253 : public InstVisitor<ObjectSizeOffsetVisitor, OffsetSpan> {
0254 const DataLayout &DL;
0255 const TargetLibraryInfo *TLI;
0256 ObjectSizeOpts Options;
0257 unsigned IntTyBits;
0258 APInt Zero;
0259 SmallDenseMap<Instruction *, OffsetSpan, 8> SeenInsts;
0260 unsigned InstructionsVisited;
0261
0262 APInt align(APInt Size, MaybeAlign Align);
0263
0264 static OffsetSpan unknown() { return OffsetSpan(); }
0265
0266 public:
0267 ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
0268 LLVMContext &Context, ObjectSizeOpts Options = {});
0269
0270 SizeOffsetAPInt compute(Value *V);
0271
0272
0273
0274 OffsetSpan visitAllocaInst(AllocaInst &I);
0275 OffsetSpan visitArgument(Argument &A);
0276 OffsetSpan visitCallBase(CallBase &CB);
0277 OffsetSpan visitConstantPointerNull(ConstantPointerNull &);
0278 OffsetSpan visitExtractElementInst(ExtractElementInst &I);
0279 OffsetSpan visitExtractValueInst(ExtractValueInst &I);
0280 OffsetSpan visitGlobalAlias(GlobalAlias &GA);
0281 OffsetSpan visitGlobalVariable(GlobalVariable &GV);
0282 OffsetSpan visitIntToPtrInst(IntToPtrInst &);
0283 OffsetSpan visitLoadInst(LoadInst &I);
0284 OffsetSpan visitPHINode(PHINode &);
0285 OffsetSpan visitSelectInst(SelectInst &I);
0286 OffsetSpan visitUndefValue(UndefValue &);
0287 OffsetSpan visitInstruction(Instruction &I);
0288
0289 private:
0290 OffsetSpan
0291 findLoadOffsetRange(LoadInst &LoadFrom, BasicBlock &BB,
0292 BasicBlock::iterator From,
0293 SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks,
0294 unsigned &ScannedInstCount);
0295 OffsetSpan combineOffsetRange(OffsetSpan LHS, OffsetSpan RHS);
0296 OffsetSpan computeImpl(Value *V);
0297 OffsetSpan computeValue(Value *V);
0298 bool CheckedZextOrTrunc(APInt &I);
0299 };
0300
0301
0302
0303 struct SizeOffsetWeakTrackingVH;
0304 struct SizeOffsetValue : public SizeOffsetType<Value *, SizeOffsetValue> {
0305 SizeOffsetValue() : SizeOffsetType(nullptr, nullptr) {}
0306 SizeOffsetValue(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {}
0307 SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT);
0308
0309 static bool known(Value *V) { return V != nullptr; }
0310 };
0311
0312
0313
0314 struct SizeOffsetWeakTrackingVH
0315 : public SizeOffsetType<WeakTrackingVH, SizeOffsetWeakTrackingVH> {
0316 SizeOffsetWeakTrackingVH() : SizeOffsetType(nullptr, nullptr) {}
0317 SizeOffsetWeakTrackingVH(Value *Size, Value *Offset)
0318 : SizeOffsetType(Size, Offset) {}
0319 SizeOffsetWeakTrackingVH(const SizeOffsetValue &SOV)
0320 : SizeOffsetType(SOV.Size, SOV.Offset) {}
0321
0322 static bool known(WeakTrackingVH V) { return V.pointsToAliveValue(); }
0323 };
0324
0325
0326
0327 class ObjectSizeOffsetEvaluator
0328 : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetValue> {
0329 using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
0330 using WeakEvalType = SizeOffsetWeakTrackingVH;
0331 using CacheMapTy = DenseMap<const Value *, WeakEvalType>;
0332 using PtrSetTy = SmallPtrSet<const Value *, 8>;
0333
0334 const DataLayout &DL;
0335 const TargetLibraryInfo *TLI;
0336 LLVMContext &Context;
0337 BuilderTy Builder;
0338 IntegerType *IntTy;
0339 Value *Zero;
0340 CacheMapTy CacheMap;
0341 PtrSetTy SeenVals;
0342 ObjectSizeOpts EvalOpts;
0343 SmallPtrSet<Instruction *, 8> InsertedInstructions;
0344
0345 SizeOffsetValue compute_(Value *V);
0346
0347 public:
0348 ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
0349 LLVMContext &Context, ObjectSizeOpts EvalOpts = {});
0350
0351 static SizeOffsetValue unknown() { return SizeOffsetValue(); }
0352
0353 SizeOffsetValue compute(Value *V);
0354
0355
0356 SizeOffsetValue visitAllocaInst(AllocaInst &I);
0357 SizeOffsetValue visitCallBase(CallBase &CB);
0358 SizeOffsetValue visitExtractElementInst(ExtractElementInst &I);
0359 SizeOffsetValue visitExtractValueInst(ExtractValueInst &I);
0360 SizeOffsetValue visitGEPOperator(GEPOperator &GEP);
0361 SizeOffsetValue visitIntToPtrInst(IntToPtrInst &);
0362 SizeOffsetValue visitLoadInst(LoadInst &I);
0363 SizeOffsetValue visitPHINode(PHINode &PHI);
0364 SizeOffsetValue visitSelectInst(SelectInst &I);
0365 SizeOffsetValue visitInstruction(Instruction &I);
0366 };
0367
0368 }
0369
0370 #endif