• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //==- llvm/Analysis/MemoryBuiltins.h - Calls to memory builtins --*- 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 family of functions identifies calls to builtin functions that allocate
10 // or free memory.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
15 #define LLVM_ANALYSIS_MEMORYBUILTINS_H
16 
17 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/Analysis/TargetFolder.h"
21 #include "llvm/Analysis/TargetLibraryInfo.h"
22 #include "llvm/IR/IRBuilder.h"
23 #include "llvm/IR/InstVisitor.h"
24 #include "llvm/IR/ValueHandle.h"
25 #include <cstdint>
26 #include <optional>
27 #include <utility>
28 
29 namespace llvm {
30 
31 class AllocaInst;
32 class AAResults;
33 class Argument;
34 class ConstantPointerNull;
35 class DataLayout;
36 class ExtractElementInst;
37 class ExtractValueInst;
38 class GEPOperator;
39 class GlobalAlias;
40 class GlobalVariable;
41 class Instruction;
42 class IntegerType;
43 class IntrinsicInst;
44 class IntToPtrInst;
45 class LLVMContext;
46 class LoadInst;
47 class PHINode;
48 class SelectInst;
49 class Type;
50 class UndefValue;
51 class Value;
52 
53 /// Tests if a value is a call or invoke to a library function that
54 /// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
55 /// like).
56 bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI);
57 bool isAllocationFn(const Value *V,
58                     function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
59 
60 /// Tests if a value is a call or invoke to a library function that
61 /// allocates memory via new.
62 bool isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI);
63 
64 /// Tests if a value is a call or invoke to a library function that
65 /// allocates memory similar to malloc or calloc.
66 bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
67 
68 /// Tests if a value is a call or invoke to a library function that
69 /// allocates memory (either malloc, calloc, or strdup like).
70 bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
71 
72 /// Tests if a function is a call or invoke to a library function that
73 /// reallocates memory (e.g., realloc).
74 bool isReallocLikeFn(const Function *F);
75 
76 /// If this is a call to a realloc function, return the reallocated operand.
77 Value *getReallocatedOperand(const CallBase *CB);
78 
79 //===----------------------------------------------------------------------===//
80 //  free Call Utility Functions.
81 //
82 
83 /// isLibFreeFunction - Returns true if the function is a builtin free()
84 bool isLibFreeFunction(const Function *F, const LibFunc TLIFn);
85 
86 /// If this if a call to a free function, return the freed operand.
87 Value *getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
88 
89 //===----------------------------------------------------------------------===//
90 //  Properties of allocation functions
91 //
92 
93 /// Return true if this is a call to an allocation function that does not have
94 /// side effects that we are required to preserve beyond the effect of
95 /// allocating a new object.
96 /// Ex: If our allocation routine has a counter for the number of objects
97 /// allocated, and the program prints it on exit, can the value change due
98 /// to optimization? Answer is highly language dependent.
99 /// Note: *Removable* really does mean removable; it does not mean observable.
100 /// A language (e.g. C++) can allow removing allocations without allowing
101 /// insertion or speculative execution of allocation routines.
102 bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI);
103 
104 /// Gets the alignment argument for an aligned_alloc-like function, using either
105 /// built-in knowledge based on fuction names/signatures or allocalign
106 /// attributes. Note: the Value returned may not indicate a valid alignment, per
107 /// the definition of the allocalign attribute.
108 Value *getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI);
109 
110 /// Return the size of the requested allocation. With a trivial mapper, this is
111 /// similar to calling getObjectSize(..., Exact), but without looking through
112 /// calls that return their argument. A mapper function can be used to replace
113 /// one Value* (operand to the allocation) with another. This is useful when
114 /// doing abstract interpretation.
115 std::optional<APInt> getAllocSize(
116     const CallBase *CB, const TargetLibraryInfo *TLI,
117     function_ref<const Value *(const Value *)> Mapper = [](const Value *V) {
118       return V;
119     });
120 
121 /// If this is a call to an allocation function that initializes memory to a
122 /// fixed value, return said value in the requested type.  Otherwise, return
123 /// nullptr.
124 Constant *getInitialValueOfAllocation(const Value *V,
125                                       const TargetLibraryInfo *TLI,
126                                       Type *Ty);
127 
128 /// If a function is part of an allocation family (e.g.
129 /// malloc/realloc/calloc/free), return the identifier for its family
130 /// of functions.
131 std::optional<StringRef> getAllocationFamily(const Value *I,
132                                              const TargetLibraryInfo *TLI);
133 
134 //===----------------------------------------------------------------------===//
135 //  Utility functions to compute size of objects.
136 //
137 
138 /// Various options to control the behavior of getObjectSize.
139 struct ObjectSizeOpts {
140   /// Controls how we handle conditional statements with unknown conditions.
141   enum class Mode : uint8_t {
142     /// All branches must be known and have the same size, starting from the
143     /// offset, to be merged.
144     ExactSizeFromOffset,
145     /// All branches must be known and have the same underlying size and offset
146     /// to be merged.
147     ExactUnderlyingSizeAndOffset,
148     /// Evaluate all branches of an unknown condition. If all evaluations
149     /// succeed, pick the minimum size.
150     Min,
151     /// Same as Min, except we pick the maximum size of all of the branches.
152     Max,
153   };
154 
155   /// How we want to evaluate this object's size.
156   Mode EvalMode = Mode::ExactSizeFromOffset;
157   /// Whether to round the result up to the alignment of allocas, byval
158   /// arguments, and global variables.
159   bool RoundToAlign = false;
160   /// If this is true, null pointers in address space 0 will be treated as
161   /// though they can't be evaluated. Otherwise, null is always considered to
162   /// point to a 0 byte region of memory.
163   bool NullIsUnknownSize = false;
164   /// If set, used for more accurate evaluation
165   AAResults *AA = nullptr;
166 };
167 
168 /// Compute the size of the object pointed by Ptr. Returns true and the
169 /// object size in Size if successful, and false otherwise. In this context, by
170 /// object we mean the region of memory starting at Ptr to the end of the
171 /// underlying object pointed to by Ptr.
172 ///
173 /// WARNING: The object size returned is the allocation size.  This does not
174 /// imply dereferenceability at site of use since the object may be freeed in
175 /// between.
176 bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
177                    const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
178 
179 /// Try to turn a call to \@llvm.objectsize into an integer value of the given
180 /// Type. Returns null on failure. If MustSucceed is true, this function will
181 /// not return null, and may return conservative values governed by the second
182 /// argument of the call to objectsize.
183 Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL,
184                            const TargetLibraryInfo *TLI, bool MustSucceed);
185 Value *lowerObjectSizeCall(
186     IntrinsicInst *ObjectSize, const DataLayout &DL,
187     const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
188     SmallVectorImpl<Instruction *> *InsertedInstructions = nullptr);
189 
190 using SizeOffsetType = std::pair<APInt, APInt>;
191 
192 /// Evaluate the size and offset of an object pointed to by a Value*
193 /// statically. Fails if size or offset are not known at compile time.
194 class ObjectSizeOffsetVisitor
195   : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
196   const DataLayout &DL;
197   const TargetLibraryInfo *TLI;
198   ObjectSizeOpts Options;
199   unsigned IntTyBits;
200   APInt Zero;
201   SmallDenseMap<Instruction *, SizeOffsetType, 8> SeenInsts;
202   unsigned InstructionsVisited;
203 
204   APInt align(APInt Size, MaybeAlign Align);
205 
unknown()206   SizeOffsetType unknown() {
207     return std::make_pair(APInt(), APInt());
208   }
209 
210 public:
211   ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
212                           LLVMContext &Context, ObjectSizeOpts Options = {});
213 
214   SizeOffsetType compute(Value *V);
215 
knownSize(const SizeOffsetType & SizeOffset)216   static bool knownSize(const SizeOffsetType &SizeOffset) {
217     return SizeOffset.first.getBitWidth() > 1;
218   }
219 
knownOffset(const SizeOffsetType & SizeOffset)220   static bool knownOffset(const SizeOffsetType &SizeOffset) {
221     return SizeOffset.second.getBitWidth() > 1;
222   }
223 
bothKnown(const SizeOffsetType & SizeOffset)224   static bool bothKnown(const SizeOffsetType &SizeOffset) {
225     return knownSize(SizeOffset) && knownOffset(SizeOffset);
226   }
227 
228   // These are "private", except they can't actually be made private. Only
229   // compute() should be used by external users.
230   SizeOffsetType visitAllocaInst(AllocaInst &I);
231   SizeOffsetType visitArgument(Argument &A);
232   SizeOffsetType visitCallBase(CallBase &CB);
233   SizeOffsetType visitConstantPointerNull(ConstantPointerNull&);
234   SizeOffsetType visitExtractElementInst(ExtractElementInst &I);
235   SizeOffsetType visitExtractValueInst(ExtractValueInst &I);
236   SizeOffsetType visitGlobalAlias(GlobalAlias &GA);
237   SizeOffsetType visitGlobalVariable(GlobalVariable &GV);
238   SizeOffsetType visitIntToPtrInst(IntToPtrInst&);
239   SizeOffsetType visitLoadInst(LoadInst &I);
240   SizeOffsetType visitPHINode(PHINode&);
241   SizeOffsetType visitSelectInst(SelectInst &I);
242   SizeOffsetType visitUndefValue(UndefValue&);
243   SizeOffsetType visitInstruction(Instruction &I);
244 
245 private:
246   SizeOffsetType findLoadSizeOffset(
247       LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From,
248       SmallDenseMap<BasicBlock *, SizeOffsetType, 8> &VisitedBlocks,
249       unsigned &ScannedInstCount);
250   SizeOffsetType combineSizeOffset(SizeOffsetType LHS, SizeOffsetType RHS);
251   SizeOffsetType computeImpl(Value *V);
252   SizeOffsetType computeValue(Value *V);
253   bool CheckedZextOrTrunc(APInt &I);
254 };
255 
256 using SizeOffsetEvalType = std::pair<Value *, Value *>;
257 
258 /// Evaluate the size and offset of an object pointed to by a Value*.
259 /// May create code to compute the result at run-time.
260 class ObjectSizeOffsetEvaluator
261   : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
262   using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
263   using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>;
264   using CacheMapTy = DenseMap<const Value *, WeakEvalType>;
265   using PtrSetTy = SmallPtrSet<const Value *, 8>;
266 
267   const DataLayout &DL;
268   const TargetLibraryInfo *TLI;
269   LLVMContext &Context;
270   BuilderTy Builder;
271   IntegerType *IntTy;
272   Value *Zero;
273   CacheMapTy CacheMap;
274   PtrSetTy SeenVals;
275   ObjectSizeOpts EvalOpts;
276   SmallPtrSet<Instruction *, 8> InsertedInstructions;
277 
278   SizeOffsetEvalType compute_(Value *V);
279 
280 public:
unknown()281   static SizeOffsetEvalType unknown() {
282     return std::make_pair(nullptr, nullptr);
283   }
284 
285   ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
286                             LLVMContext &Context, ObjectSizeOpts EvalOpts = {});
287 
288   SizeOffsetEvalType compute(Value *V);
289 
knownSize(SizeOffsetEvalType SizeOffset)290   bool knownSize(SizeOffsetEvalType SizeOffset) {
291     return SizeOffset.first;
292   }
293 
knownOffset(SizeOffsetEvalType SizeOffset)294   bool knownOffset(SizeOffsetEvalType SizeOffset) {
295     return SizeOffset.second;
296   }
297 
anyKnown(SizeOffsetEvalType SizeOffset)298   bool anyKnown(SizeOffsetEvalType SizeOffset) {
299     return knownSize(SizeOffset) || knownOffset(SizeOffset);
300   }
301 
bothKnown(SizeOffsetEvalType SizeOffset)302   bool bothKnown(SizeOffsetEvalType SizeOffset) {
303     return knownSize(SizeOffset) && knownOffset(SizeOffset);
304   }
305 
306   // The individual instruction visitors should be treated as private.
307   SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
308   SizeOffsetEvalType visitCallBase(CallBase &CB);
309   SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I);
310   SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I);
311   SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP);
312   SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&);
313   SizeOffsetEvalType visitLoadInst(LoadInst &I);
314   SizeOffsetEvalType visitPHINode(PHINode &PHI);
315   SizeOffsetEvalType visitSelectInst(SelectInst &I);
316   SizeOffsetEvalType visitInstruction(Instruction &I);
317 };
318 
319 } // end namespace llvm
320 
321 #endif // LLVM_ANALYSIS_MEMORYBUILTINS_H
322