LLVM 18.0.0git
MemoryBuiltins.cpp
Go to the documentation of this file.
1//===- MemoryBuiltins.cpp - Identify calls to memory builtins -------------===//
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
15#include "llvm/ADT/APInt.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Statistic.h"
23#include "llvm/IR/Argument.h"
24#include "llvm/IR/Attributes.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/DataLayout.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/GlobalAlias.h"
31#include "llvm/IR/Instruction.h"
34#include "llvm/IR/Operator.h"
35#include "llvm/IR/Type.h"
36#include "llvm/IR/Value.h"
39#include "llvm/Support/Debug.h"
42#include <cassert>
43#include <cstdint>
44#include <iterator>
45#include <numeric>
46#include <optional>
47#include <type_traits>
48#include <utility>
49
50using namespace llvm;
51
52#define DEBUG_TYPE "memory-builtins"
53
55 "object-size-offset-visitor-max-visit-instructions",
56 cl::desc("Maximum number of instructions for ObjectSizeOffsetVisitor to "
57 "look at"),
58 cl::init(100));
59
60enum AllocType : uint8_t {
61 OpNewLike = 1<<0, // allocates; never returns null
62 MallocLike = 1<<1, // allocates; may return null
63 StrDupLike = 1<<2,
67};
68
69enum class MallocFamily {
70 Malloc,
71 CPPNew, // new(unsigned int)
72 CPPNewAligned, // new(unsigned int, align_val_t)
73 CPPNewArray, // new[](unsigned int)
74 CPPNewArrayAligned, // new[](unsigned long, align_val_t)
75 MSVCNew, // new(unsigned int)
76 MSVCArrayNew, // new[](unsigned int)
79};
80
82 switch (Family) {
84 return "malloc";
86 return "_Znwm";
88 return "_ZnwmSt11align_val_t";
90 return "_Znam";
92 return "_ZnamSt11align_val_t";
94 return "??2@YAPAXI@Z";
96 return "??_U@YAPAXI@Z";
98 return "vec_malloc";
100 return "__kmpc_alloc_shared";
101 }
102 llvm_unreachable("missing an alloc family");
103}
104
107 unsigned NumParams;
108 // First and Second size parameters (or -1 if unused)
110 // Alignment parameter for aligned_alloc and aligned new
112 // Name of default allocator function to group malloc/free calls by family
114};
115
116// clang-format off
117// FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
118// know which functions are nounwind, noalias, nocapture parameters, etc.
119static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
120 {LibFunc_Znwj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int)
121 {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int, nothrow)
122 {LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t)
123 {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t, nothrow)
124 {LibFunc_Znwm, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long)
125 {LibFunc_Znwm12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, __hot_cold_t)
126 {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow)
127 {LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow, __hot_cold_t)
128 {LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t)
129 {LibFunc_ZnwmSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, __hot_cold_t)
130 {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow)
131 {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow, __hot_cold_t)
132 {LibFunc_Znaj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int)
133 {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int, nothrow)
134 {LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t)
135 {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t, nothrow)
136 {LibFunc_Znam, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long)
137 {LibFunc_Znam12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, __hot_cold_t)
138 {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long, nothrow)
139 {LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, nothrow, __hot_cold_t)
140 {LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t)
141 {LibFunc_ZnamSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, __hot_cold_t)
142 {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t, nothrow)
143 {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, nothrow, __hot_cold_t)
144 {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int)
145 {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int, nothrow)
146 {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long)
147 {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long, nothrow)
148 {LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int)
149 {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int, nothrow)
150 {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long)
151 {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long, nothrow)
152 {LibFunc_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
153 {LibFunc_dunder_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
154 {LibFunc_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
155 {LibFunc_dunder_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
156 {LibFunc___kmpc_alloc_shared, {MallocLike, 1, 0, -1, -1, MallocFamily::KmpcAllocShared}},
157};
158// clang-format on
159
160static const Function *getCalledFunction(const Value *V,
161 bool &IsNoBuiltin) {
162 // Don't care about intrinsics in this case.
163 if (isa<IntrinsicInst>(V))
164 return nullptr;
165
166 const auto *CB = dyn_cast<CallBase>(V);
167 if (!CB)
168 return nullptr;
169
170 IsNoBuiltin = CB->isNoBuiltin();
171
172 if (const Function *Callee = CB->getCalledFunction())
173 return Callee;
174 return nullptr;
175}
176
177/// Returns the allocation data for the given value if it's a call to a known
178/// allocation function.
179static std::optional<AllocFnsTy>
181 const TargetLibraryInfo *TLI) {
182 // Don't perform a slow TLI lookup, if this function doesn't return a pointer
183 // and thus can't be an allocation function.
184 if (!Callee->getReturnType()->isPointerTy())
185 return std::nullopt;
186
187 // Make sure that the function is available.
188 LibFunc TLIFn;
189 if (!TLI || !TLI->getLibFunc(*Callee, TLIFn) || !TLI->has(TLIFn))
190 return std::nullopt;
191
192 const auto *Iter = find_if(
193 AllocationFnData, [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) {
194 return P.first == TLIFn;
195 });
196
197 if (Iter == std::end(AllocationFnData))
198 return std::nullopt;
199
200 const AllocFnsTy *FnData = &Iter->second;
201 if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
202 return std::nullopt;
203
204 // Check function prototype.
205 int FstParam = FnData->FstParam;
206 int SndParam = FnData->SndParam;
207 FunctionType *FTy = Callee->getFunctionType();
208
209 if (FTy->getReturnType()->isPointerTy() &&
210 FTy->getNumParams() == FnData->NumParams &&
211 (FstParam < 0 ||
212 (FTy->getParamType(FstParam)->isIntegerTy(32) ||
213 FTy->getParamType(FstParam)->isIntegerTy(64))) &&
214 (SndParam < 0 ||
215 FTy->getParamType(SndParam)->isIntegerTy(32) ||
216 FTy->getParamType(SndParam)->isIntegerTy(64)))
217 return *FnData;
218 return std::nullopt;
219}
220
221static std::optional<AllocFnsTy>
223 const TargetLibraryInfo *TLI) {
224 bool IsNoBuiltinCall;
225 if (const Function *Callee = getCalledFunction(V, IsNoBuiltinCall))
226 if (!IsNoBuiltinCall)
227 return getAllocationDataForFunction(Callee, AllocTy, TLI);
228 return std::nullopt;
229}
230
231static std::optional<AllocFnsTy>
233 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
234 bool IsNoBuiltinCall;
235 if (const Function *Callee = getCalledFunction(V, IsNoBuiltinCall))
236 if (!IsNoBuiltinCall)
238 Callee, AllocTy, &GetTLI(const_cast<Function &>(*Callee)));
239 return std::nullopt;
240}
241
242static std::optional<AllocFnsTy>
244 bool IsNoBuiltinCall;
245 const Function *Callee =
246 getCalledFunction(V, IsNoBuiltinCall);
247 if (!Callee)
248 return std::nullopt;
249
250 // Prefer to use existing information over allocsize. This will give us an
251 // accurate AllocTy.
252 if (!IsNoBuiltinCall)
253 if (std::optional<AllocFnsTy> Data =
255 return Data;
256
257 Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize);
258 if (Attr == Attribute())
259 return std::nullopt;
260
261 std::pair<unsigned, std::optional<unsigned>> Args = Attr.getAllocSizeArgs();
262
263 AllocFnsTy Result;
264 // Because allocsize only tells us how many bytes are allocated, we're not
265 // really allowed to assume anything, so we use MallocLike.
266 Result.AllocTy = MallocLike;
267 Result.NumParams = Callee->getNumOperands();
268 Result.FstParam = Args.first;
269 Result.SndParam = Args.second.value_or(-1);
270 // Allocsize has no way to specify an alignment argument
271 Result.AlignParam = -1;
272 return Result;
273}
274
276 if (const auto *CB = dyn_cast<CallBase>(V)) {
277 Attribute Attr = CB->getFnAttr(Attribute::AllocKind);
278 if (Attr.isValid())
279 return AllocFnKind(Attr.getValueAsInt());
280 }
281 return AllocFnKind::Unknown;
282}
283
285 return F->getAttributes().getAllocKind();
286}
287
288static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted) {
289 return (getAllocFnKind(V) & Wanted) != AllocFnKind::Unknown;
290}
291
292static bool checkFnAllocKind(const Function *F, AllocFnKind Wanted) {
293 return (getAllocFnKind(F) & Wanted) != AllocFnKind::Unknown;
294}
295
296/// Tests if a value is a call or invoke to a library function that
297/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
298/// like).
299bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI) {
300 return getAllocationData(V, AnyAlloc, TLI).has_value() ||
301 checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
302}
304 const Value *V,
305 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
306 return getAllocationData(V, AnyAlloc, GetTLI).has_value() ||
307 checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
308}
309
310/// Tests if a value is a call or invoke to a library function that
311/// allocates memory via new.
312bool llvm::isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
313 return getAllocationData(V, OpNewLike, TLI).has_value();
314}
315
316/// Tests if a value is a call or invoke to a library function that
317/// allocates memory similar to malloc or calloc.
319 // TODO: Function behavior does not match name.
320 return getAllocationData(V, MallocOrOpNewLike, TLI).has_value();
321}
322
323/// Tests if a value is a call or invoke to a library function that
324/// allocates memory (either malloc, calloc, or strdup like).
325bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
326 return getAllocationData(V, AllocLike, TLI).has_value() ||
327 checkFnAllocKind(V, AllocFnKind::Alloc);
328}
329
330/// Tests if a functions is a call or invoke to a library function that
331/// reallocates memory (e.g., realloc).
333 return checkFnAllocKind(F, AllocFnKind::Realloc);
334}
335
337 if (checkFnAllocKind(CB, AllocFnKind::Realloc))
338 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
339 return nullptr;
340}
341
343 // Note: Removability is highly dependent on the source language. For
344 // example, recent C++ requires direct calls to the global allocation
345 // [basic.stc.dynamic.allocation] to be observable unless part of a new
346 // expression [expr.new paragraph 13].
347
348 // Historically we've treated the C family allocation routines and operator
349 // new as removable
350 return isAllocLikeFn(CB, TLI);
351}
352
354 const TargetLibraryInfo *TLI) {
355 const std::optional<AllocFnsTy> FnData = getAllocationData(V, AnyAlloc, TLI);
356 if (FnData && FnData->AlignParam >= 0) {
357 return V->getOperand(FnData->AlignParam);
358 }
359 return V->getArgOperandWithAttribute(Attribute::AllocAlign);
360}
361
362/// When we're compiling N-bit code, and the user uses parameters that are
363/// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
364/// trouble with APInt size issues. This function handles resizing + overflow
365/// checks for us. Check and zext or trunc \p I depending on IntTyBits and
366/// I's value.
367static bool CheckedZextOrTrunc(APInt &I, unsigned IntTyBits) {
368 // More bits than we can handle. Checking the bit width isn't necessary, but
369 // it's faster than checking active bits, and should give `false` in the
370 // vast majority of cases.
371 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
372 return false;
373 if (I.getBitWidth() != IntTyBits)
374 I = I.zextOrTrunc(IntTyBits);
375 return true;
376}
377
378std::optional<APInt>
380 function_ref<const Value *(const Value *)> Mapper) {
381 // Note: This handles both explicitly listed allocation functions and
382 // allocsize. The code structure could stand to be cleaned up a bit.
383 std::optional<AllocFnsTy> FnData = getAllocationSize(CB, TLI);
384 if (!FnData)
385 return std::nullopt;
386
387 // Get the index type for this address space, results and intermediate
388 // computations are performed at that width.
389 auto &DL = CB->getModule()->getDataLayout();
390 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType());
391
392 // Handle strdup-like functions separately.
393 if (FnData->AllocTy == StrDupLike) {
394 APInt Size(IntTyBits, GetStringLength(Mapper(CB->getArgOperand(0))));
395 if (!Size)
396 return std::nullopt;
397
398 // Strndup limits strlen.
399 if (FnData->FstParam > 0) {
400 const ConstantInt *Arg =
401 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
402 if (!Arg)
403 return std::nullopt;
404
405 APInt MaxSize = Arg->getValue().zext(IntTyBits);
406 if (Size.ugt(MaxSize))
407 Size = MaxSize + 1;
408 }
409 return Size;
410 }
411
412 const ConstantInt *Arg =
413 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
414 if (!Arg)
415 return std::nullopt;
416
417 APInt Size = Arg->getValue();
418 if (!CheckedZextOrTrunc(Size, IntTyBits))
419 return std::nullopt;
420
421 // Size is determined by just 1 parameter.
422 if (FnData->SndParam < 0)
423 return Size;
424
425 Arg = dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->SndParam)));
426 if (!Arg)
427 return std::nullopt;
428
429 APInt NumElems = Arg->getValue();
430 if (!CheckedZextOrTrunc(NumElems, IntTyBits))
431 return std::nullopt;
432
433 bool Overflow;
434 Size = Size.umul_ov(NumElems, Overflow);
435 if (Overflow)
436 return std::nullopt;
437 return Size;
438}
439
441 const TargetLibraryInfo *TLI,
442 Type *Ty) {
443 auto *Alloc = dyn_cast<CallBase>(V);
444 if (!Alloc)
445 return nullptr;
446
447 // malloc are uninitialized (undef)
448 if (getAllocationData(Alloc, MallocOrOpNewLike, TLI).has_value())
449 return UndefValue::get(Ty);
450
451 AllocFnKind AK = getAllocFnKind(Alloc);
452 if ((AK & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
453 return UndefValue::get(Ty);
454 if ((AK & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
455 return Constant::getNullValue(Ty);
456
457 return nullptr;
458}
459
460struct FreeFnsTy {
461 unsigned NumParams;
462 // Name of default allocator function to group malloc/free calls by family
464};
465
466// clang-format off
467static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
468 {LibFunc_ZdlPv, {1, MallocFamily::CPPNew}}, // operator delete(void*)
469 {LibFunc_ZdaPv, {1, MallocFamily::CPPNewArray}}, // operator delete[](void*)
470 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
471 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
472 {LibFunc_msvc_delete_array_ptr32, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
473 {LibFunc_msvc_delete_array_ptr64, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
474 {LibFunc_ZdlPvj, {2, MallocFamily::CPPNew}}, // delete(void*, uint)
475 {LibFunc_ZdlPvm, {2, MallocFamily::CPPNew}}, // delete(void*, ulong)
476 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}}, // delete(void*, nothrow)
477 {LibFunc_ZdlPvSt11align_val_t, {2, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t)
478 {LibFunc_ZdaPvj, {2, MallocFamily::CPPNewArray}}, // delete[](void*, uint)
479 {LibFunc_ZdaPvm, {2, MallocFamily::CPPNewArray}}, // delete[](void*, ulong)
480 {LibFunc_ZdaPvRKSt9nothrow_t, {2, MallocFamily::CPPNewArray}}, // delete[](void*, nothrow)
481 {LibFunc_ZdaPvSt11align_val_t, {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
482 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}}, // delete(void*, uint)
483 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}}, // delete(void*, ulonglong)
484 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
485 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
486 {LibFunc_msvc_delete_array_ptr32_int, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, uint)
487 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, ulonglong)
488 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
489 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
490 {LibFunc___kmpc_free_shared, {2, MallocFamily::KmpcAllocShared}}, // OpenMP Offloading RTL free
491 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t, nothrow)
492 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
493 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned int, align_val_t)
494 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned long, align_val_t)
495 {LibFunc_ZdaPvjSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
496 {LibFunc_ZdaPvmSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
497};
498// clang-format on
499
500std::optional<FreeFnsTy> getFreeFunctionDataForFunction(const Function *Callee,
501 const LibFunc TLIFn) {
502 const auto *Iter =
503 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
504 return P.first == TLIFn;
505 });
506 if (Iter == std::end(FreeFnData))
507 return std::nullopt;
508 return Iter->second;
509}
510
511std::optional<StringRef>
513 bool IsNoBuiltin;
514 const Function *Callee = getCalledFunction(I, IsNoBuiltin);
515 if (Callee == nullptr || IsNoBuiltin)
516 return std::nullopt;
517 LibFunc TLIFn;
518
519 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) {
520 // Callee is some known library function.
521 const auto AllocData = getAllocationDataForFunction(Callee, AnyAlloc, TLI);
522 if (AllocData)
523 return mangledNameForMallocFamily(AllocData->Family);
524 const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
525 if (FreeData)
526 return mangledNameForMallocFamily(FreeData->Family);
527 }
528 // Callee isn't a known library function, still check attributes.
529 if (checkFnAllocKind(I, AllocFnKind::Free | AllocFnKind::Alloc |
530 AllocFnKind::Realloc)) {
531 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
532 if (Attr.isValid())
533 return Attr.getValueAsString();
534 }
535 return std::nullopt;
536}
537
538/// isLibFreeFunction - Returns true if the function is a builtin free()
539bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
540 std::optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
541 if (!FnData)
542 return checkFnAllocKind(F, AllocFnKind::Free);
543
544 // Check free prototype.
545 // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
546 // attribute will exist.
547 FunctionType *FTy = F->getFunctionType();
548 if (!FTy->getReturnType()->isVoidTy())
549 return false;
550 if (FTy->getNumParams() != FnData->NumParams)
551 return false;
552 if (!FTy->getParamType(0)->isPointerTy())
553 return false;
554
555 return true;
556}
557
559 bool IsNoBuiltinCall;
560 const Function *Callee = getCalledFunction(CB, IsNoBuiltinCall);
561 if (Callee == nullptr || IsNoBuiltinCall)
562 return nullptr;
563
564 LibFunc TLIFn;
565 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) &&
566 isLibFreeFunction(Callee, TLIFn)) {
567 // All currently supported free functions free the first argument.
568 return CB->getArgOperand(0);
569 }
570
571 if (checkFnAllocKind(CB, AllocFnKind::Free))
572 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
573
574 return nullptr;
575}
576
577//===----------------------------------------------------------------------===//
578// Utility functions to compute size of objects.
579//
581 if (Data.second.isNegative() || Data.first.ult(Data.second))
582 return APInt(Data.first.getBitWidth(), 0);
583 return Data.first - Data.second;
584}
585
586/// Compute the size of the object pointed by Ptr. Returns true and the
587/// object size in Size if successful, and false otherwise.
588/// If RoundToAlign is true, then Size is rounded up to the alignment of
589/// allocas, byval arguments, and global variables.
591 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) {
592 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts);
593 SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
594 if (!Visitor.bothKnown(Data))
595 return false;
596
598 return true;
599}
600
602 const DataLayout &DL,
603 const TargetLibraryInfo *TLI,
604 bool MustSucceed) {
605 return lowerObjectSizeCall(ObjectSize, DL, TLI, /*AAResults=*/nullptr,
606 MustSucceed);
607}
608
610 IntrinsicInst *ObjectSize, const DataLayout &DL,
611 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
612 SmallVectorImpl<Instruction *> *InsertedInstructions) {
613 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
614 "ObjectSize must be a call to llvm.objectsize!");
615
616 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
617 ObjectSizeOpts EvalOptions;
618 EvalOptions.AA = AA;
619
620 // Unless we have to fold this to something, try to be as accurate as
621 // possible.
622 if (MustSucceed)
623 EvalOptions.EvalMode =
624 MaxVal ? ObjectSizeOpts::Mode::Max : ObjectSizeOpts::Mode::Min;
625 else
626 EvalOptions.EvalMode = ObjectSizeOpts::Mode::ExactSizeFromOffset;
627
628 EvalOptions.NullIsUnknownSize =
629 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
630
631 auto *ResultType = cast<IntegerType>(ObjectSize->getType());
632 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
633 if (StaticOnly) {
634 // FIXME: Does it make sense to just return a failure value if the size won't
635 // fit in the output and `!MustSucceed`?
637 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) &&
638 isUIntN(ResultType->getBitWidth(), Size))
639 return ConstantInt::get(ResultType, Size);
640 } else {
641 LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
642 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
643 SizeOffsetEvalType SizeOffsetPair =
644 Eval.compute(ObjectSize->getArgOperand(0));
645
646 if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
649 if (InsertedInstructions)
650 InsertedInstructions->push_back(I);
651 }));
652 Builder.SetInsertPoint(ObjectSize);
653
654 // If we've outside the end of the object, then we can always access
655 // exactly 0 bytes.
656 Value *ResultSize =
657 Builder.CreateSub(SizeOffsetPair.first, SizeOffsetPair.second);
658 Value *UseZero =
659 Builder.CreateICmpULT(SizeOffsetPair.first, SizeOffsetPair.second);
660 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
661 Value *Ret = Builder.CreateSelect(
662 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
663
664 // The non-constant size expression cannot evaluate to -1.
665 if (!isa<Constant>(SizeOffsetPair.first) ||
666 !isa<Constant>(SizeOffsetPair.second))
667 Builder.CreateAssumption(
668 Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1)));
669
670 return Ret;
671 }
672 }
673
674 if (!MustSucceed)
675 return nullptr;
676
677 return ConstantInt::get(ResultType, MaxVal ? -1ULL : 0);
678}
679
680STATISTIC(ObjectVisitorArgument,
681 "Number of arguments with unsolved size and offset");
682STATISTIC(ObjectVisitorLoad,
683 "Number of load instructions with unsolved size and offset");
684
685APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) {
686 if (Options.RoundToAlign && Alignment)
687 return APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
688 return Size;
689}
690
692 const TargetLibraryInfo *TLI,
693 LLVMContext &Context,
695 : DL(DL), TLI(TLI), Options(Options) {
696 // Pointer size must be rechecked for each object visited since it could have
697 // a different address space.
698}
699
701 InstructionsVisited = 0;
702 return computeImpl(V);
703}
704
705SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) {
706 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
707
708 // Stripping pointer casts can strip address space casts which can change the
709 // index type size. The invariant is that we use the value type to determine
710 // the index type size and if we stripped address space casts we have to
711 // readjust the APInt as we pass it upwards in order for the APInt to match
712 // the type the caller passed in.
713 APInt Offset(InitialIntTyBits, 0);
714 V = V->stripAndAccumulateConstantOffsets(
715 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
716
717 // Later we use the index type size and zero but it will match the type of the
718 // value that is passed to computeImpl.
719 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
720 Zero = APInt::getZero(IntTyBits);
721
722 SizeOffsetType SOT = computeValue(V);
723
724 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
725 if (!IndexTypeSizeChanged && Offset.isZero())
726 return SOT;
727
728 // We stripped an address space cast that changed the index type size or we
729 // accumulated some constant offset (or both). Readjust the bit width to match
730 // the argument index type size and apply the offset, as required.
731 if (IndexTypeSizeChanged) {
732 if (knownSize(SOT) && !::CheckedZextOrTrunc(SOT.first, InitialIntTyBits))
733 SOT.first = APInt();
734 if (knownOffset(SOT) && !::CheckedZextOrTrunc(SOT.second, InitialIntTyBits))
735 SOT.second = APInt();
736 }
737 // If the computed offset is "unknown" we cannot add the stripped offset.
738 return {SOT.first,
739 SOT.second.getBitWidth() > 1 ? SOT.second + Offset : SOT.second};
740}
741
742SizeOffsetType ObjectSizeOffsetVisitor::computeValue(Value *V) {
743 if (Instruction *I = dyn_cast<Instruction>(V)) {
744 // If we have already seen this instruction, bail out. Cycles can happen in
745 // unreachable code after constant propagation.
746 auto P = SeenInsts.try_emplace(I, unknown());
747 if (!P.second)
748 return P.first->second;
749 ++InstructionsVisited;
750 if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions)
751 return unknown();
752 SizeOffsetType Res = visit(*I);
753 // Cache the result for later visits. If we happened to visit this during
754 // the above recursion, we would consider it unknown until now.
755 SeenInsts[I] = Res;
756 return Res;
757 }
758 if (Argument *A = dyn_cast<Argument>(V))
759 return visitArgument(*A);
760 if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
762 if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
763 return visitGlobalAlias(*GA);
764 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
765 return visitGlobalVariable(*GV);
766 if (UndefValue *UV = dyn_cast<UndefValue>(V))
767 return visitUndefValue(*UV);
768
769 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
770 << *V << '\n');
771 return unknown();
772}
773
774bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
775 return ::CheckedZextOrTrunc(I, IntTyBits);
776}
777
779 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
780 if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
781 return unknown();
782 APInt Size(IntTyBits, ElemSize.getKnownMinValue());
783 if (!I.isArrayAllocation())
784 return std::make_pair(align(Size, I.getAlign()), Zero);
785
786 Value *ArraySize = I.getArraySize();
787 if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
788 APInt NumElems = C->getValue();
789 if (!CheckedZextOrTrunc(NumElems))
790 return unknown();
791
792 bool Overflow;
793 Size = Size.umul_ov(NumElems, Overflow);
794 return Overflow ? unknown()
795 : std::make_pair(align(Size, I.getAlign()), Zero);
796 }
797 return unknown();
798}
799
801 Type *MemoryTy = A.getPointeeInMemoryValueType();
802 // No interprocedural analysis is done at the moment.
803 if (!MemoryTy|| !MemoryTy->isSized()) {
804 ++ObjectVisitorArgument;
805 return unknown();
806 }
807
808 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
809 return std::make_pair(align(Size, A.getParamAlign()), Zero);
810}
811
813 if (std::optional<APInt> Size = getAllocSize(&CB, TLI))
814 return std::make_pair(*Size, Zero);
815 return unknown();
816}
817
820 // If null is unknown, there's nothing we can do. Additionally, non-zero
821 // address spaces can make use of null, so we don't presume to know anything
822 // about that.
823 //
824 // TODO: How should this work with address space casts? We currently just drop
825 // them on the floor, but it's unclear what we should do when a NULL from
826 // addrspace(1) gets casted to addrspace(0) (or vice-versa).
827 if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace())
828 return unknown();
829 return std::make_pair(Zero, Zero);
830}
831
834 return unknown();
835}
836
839 // Easy cases were already folded by previous passes.
840 return unknown();
841}
842
844 if (GA.isInterposable())
845 return unknown();
846 return computeImpl(GA.getAliasee());
847}
848
850 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() ||
851 ((!GV.hasInitializer() || GV.isInterposable()) &&
853 return unknown();
854
855 APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType()));
856 return std::make_pair(align(Size, GV.getAlign()), Zero);
857}
858
860 // clueless
861 return unknown();
862}
863
864SizeOffsetType ObjectSizeOffsetVisitor::findLoadSizeOffset(
867 unsigned &ScannedInstCount) {
868 constexpr unsigned MaxInstsToScan = 128;
869
870 auto Where = VisitedBlocks.find(&BB);
871 if (Where != VisitedBlocks.end())
872 return Where->second;
873
874 auto Unknown = [this, &BB, &VisitedBlocks]() {
875 return VisitedBlocks[&BB] = unknown();
876 };
877 auto Known = [&BB, &VisitedBlocks](SizeOffsetType SO) {
878 return VisitedBlocks[&BB] = SO;
879 };
880
881 do {
882 Instruction &I = *From;
883
884 if (I.isDebugOrPseudoInst())
885 continue;
886
887 if (++ScannedInstCount > MaxInstsToScan)
888 return Unknown();
889
890 if (!I.mayWriteToMemory())
891 continue;
892
893 if (auto *SI = dyn_cast<StoreInst>(&I)) {
894 AliasResult AR =
895 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
896 switch ((AliasResult::Kind)AR) {
898 continue;
900 if (SI->getValueOperand()->getType()->isPointerTy())
901 return Known(computeImpl(SI->getValueOperand()));
902 else
903 return Unknown(); // No handling of non-pointer values by `compute`.
904 default:
905 return Unknown();
906 }
907 }
908
909 if (auto *CB = dyn_cast<CallBase>(&I)) {
911 // Bail out on indirect call.
912 if (!Callee)
913 return Unknown();
914
915 LibFunc TLIFn;
916 if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) ||
917 !TLI->has(TLIFn))
918 return Unknown();
919
920 // TODO: There's probably more interesting case to support here.
921 if (TLIFn != LibFunc_posix_memalign)
922 return Unknown();
923
924 AliasResult AR =
925 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
926 switch ((AliasResult::Kind)AR) {
928 continue;
930 break;
931 default:
932 return Unknown();
933 }
934
935 // Is the error status of posix_memalign correctly checked? If not it
936 // would be incorrect to assume it succeeds and load doesn't see the
937 // previous value.
938 std::optional<bool> Checked = isImpliedByDomCondition(
939 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL);
940 if (!Checked || !*Checked)
941 return Unknown();
942
943 Value *Size = CB->getOperand(2);
944 auto *C = dyn_cast<ConstantInt>(Size);
945 if (!C)
946 return Unknown();
947
948 return Known({C->getValue(), APInt(C->getValue().getBitWidth(), 0)});
949 }
950
951 return Unknown();
952 } while (From-- != BB.begin());
953
954 SmallVector<SizeOffsetType> PredecessorSizeOffsets;
955 for (auto *PredBB : predecessors(&BB)) {
956 PredecessorSizeOffsets.push_back(findLoadSizeOffset(
957 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()),
958 VisitedBlocks, ScannedInstCount));
959 if (!bothKnown(PredecessorSizeOffsets.back()))
960 return Unknown();
961 }
962
963 if (PredecessorSizeOffsets.empty())
964 return Unknown();
965
966 return Known(std::accumulate(PredecessorSizeOffsets.begin() + 1,
967 PredecessorSizeOffsets.end(),
968 PredecessorSizeOffsets.front(),
969 [this](SizeOffsetType LHS, SizeOffsetType RHS) {
970 return combineSizeOffset(LHS, RHS);
971 }));
972}
973
975 if (!Options.AA) {
976 ++ObjectVisitorLoad;
977 return unknown();
978 }
979
981 unsigned ScannedInstCount = 0;
982 SizeOffsetType SO =
983 findLoadSizeOffset(LI, *LI.getParent(), BasicBlock::iterator(LI),
984 VisitedBlocks, ScannedInstCount);
985 if (!bothKnown(SO))
986 ++ObjectVisitorLoad;
987 return SO;
988}
989
990SizeOffsetType ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetType LHS,
991 SizeOffsetType RHS) {
992 if (!bothKnown(LHS) || !bothKnown(RHS))
993 return unknown();
994
995 switch (Options.EvalMode) {
997 return (getSizeWithOverflow(LHS).slt(getSizeWithOverflow(RHS))) ? LHS : RHS;
999 return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS;
1001 return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) ? LHS
1002 : unknown();
1004 return LHS == RHS ? LHS : unknown();
1005 }
1006 llvm_unreachable("missing an eval mode");
1007}
1008
1010 if (PN.getNumIncomingValues() == 0)
1011 return unknown();
1012 auto IncomingValues = PN.incoming_values();
1013 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1014 computeImpl(*IncomingValues.begin()),
1015 [this](SizeOffsetType LHS, Value *VRHS) {
1016 return combineSizeOffset(LHS, computeImpl(VRHS));
1017 });
1018}
1019
1021 return combineSizeOffset(computeImpl(I.getTrueValue()),
1022 computeImpl(I.getFalseValue()));
1023}
1024
1026 return std::make_pair(Zero, Zero);
1027}
1028
1030 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1031 << '\n');
1032 return unknown();
1033}
1034
1036 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
1037 ObjectSizeOpts EvalOpts)
1038 : DL(DL), TLI(TLI), Context(Context),
1039 Builder(Context, TargetFolder(DL),
1041 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1042 EvalOpts(EvalOpts) {
1043 // IntTy and Zero must be set for each compute() since the address space may
1044 // be different for later objects.
1045}
1046
1048 // XXX - Are vectors of pointers possible here?
1049 IntTy = cast<IntegerType>(DL.getIndexType(V->getType()));
1050 Zero = ConstantInt::get(IntTy, 0);
1051
1052 SizeOffsetEvalType Result = compute_(V);
1053
1054 if (!bothKnown(Result)) {
1055 // Erase everything that was computed in this iteration from the cache, so
1056 // that no dangling references are left behind. We could be a bit smarter if
1057 // we kept a dependency graph. It's probably not worth the complexity.
1058 for (const Value *SeenVal : SeenVals) {
1059 CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
1060 // non-computable results can be safely cached
1061 if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
1062 CacheMap.erase(CacheIt);
1063 }
1064
1065 // Erase any instructions we inserted as part of the traversal.
1066 for (Instruction *I : InsertedInstructions) {
1067 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
1068 I->eraseFromParent();
1069 }
1070 }
1071
1072 SeenVals.clear();
1073 InsertedInstructions.clear();
1074 return Result;
1075}
1076
1077SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
1078 ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, EvalOpts);
1079 SizeOffsetType Const = Visitor.compute(V);
1080 if (Visitor.bothKnown(Const))
1081 return std::make_pair(ConstantInt::get(Context, Const.first),
1082 ConstantInt::get(Context, Const.second));
1083
1084 V = V->stripPointerCasts();
1085
1086 // Check cache.
1087 CacheMapTy::iterator CacheIt = CacheMap.find(V);
1088 if (CacheIt != CacheMap.end())
1089 return CacheIt->second;
1090
1091 // Always generate code immediately before the instruction being
1092 // processed, so that the generated code dominates the same BBs.
1093 BuilderTy::InsertPointGuard Guard(Builder);
1094 if (Instruction *I = dyn_cast<Instruction>(V))
1095 Builder.SetInsertPoint(I);
1096
1097 // Now compute the size and offset.
1098 SizeOffsetEvalType Result;
1099
1100 // Record the pointers that were handled in this run, so that they can be
1101 // cleaned later if something fails. We also use this set to break cycles that
1102 // can occur in dead code.
1103 if (!SeenVals.insert(V).second) {
1104 Result = unknown();
1105 } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
1106 Result = visitGEPOperator(*GEP);
1107 } else if (Instruction *I = dyn_cast<Instruction>(V)) {
1108 Result = visit(*I);
1109 } else if (isa<Argument>(V) ||
1110 (isa<ConstantExpr>(V) &&
1111 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
1112 isa<GlobalAlias>(V) ||
1113 isa<GlobalVariable>(V)) {
1114 // Ignore values where we cannot do more than ObjectSizeVisitor.
1115 Result = unknown();
1116 } else {
1117 LLVM_DEBUG(
1118 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1119 << '\n');
1120 Result = unknown();
1121 }
1122
1123 // Don't reuse CacheIt since it may be invalid at this point.
1124 CacheMap[V] = Result;
1125 return Result;
1126}
1127
1129 if (!I.getAllocatedType()->isSized())
1130 return unknown();
1131
1132 // must be a VLA
1133 assert(I.isArrayAllocation());
1134
1135 // If needed, adjust the alloca's operand size to match the pointer indexing
1136 // size. Subsequent math operations expect the types to match.
1137 Value *ArraySize = Builder.CreateZExtOrTrunc(
1138 I.getArraySize(),
1139 DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace()));
1140 assert(ArraySize->getType() == Zero->getType() &&
1141 "Expected zero constant to have pointer index type");
1142
1143 Value *Size = ConstantInt::get(ArraySize->getType(),
1144 DL.getTypeAllocSize(I.getAllocatedType()));
1145 Size = Builder.CreateMul(Size, ArraySize);
1146 return std::make_pair(Size, Zero);
1147}
1148
1150 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI);
1151 if (!FnData)
1152 return unknown();
1153
1154 // Handle strdup-like functions separately.
1155 if (FnData->AllocTy == StrDupLike) {
1156 // TODO: implement evaluation of strdup/strndup
1157 return unknown();
1158 }
1159
1160 Value *FirstArg = CB.getArgOperand(FnData->FstParam);
1161 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1162 if (FnData->SndParam < 0)
1163 return std::make_pair(FirstArg, Zero);
1164
1165 Value *SecondArg = CB.getArgOperand(FnData->SndParam);
1166 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1167 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1168 return std::make_pair(Size, Zero);
1169}
1170
1173 return unknown();
1174}
1175
1178 return unknown();
1179}
1180
1183 SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand());
1184 if (!bothKnown(PtrData))
1185 return unknown();
1186
1187 Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1188 Offset = Builder.CreateAdd(PtrData.second, Offset);
1189 return std::make_pair(PtrData.first, Offset);
1190}
1191
1193 // clueless
1194 return unknown();
1195}
1196
1198 return unknown();
1199}
1200
1202 // Create 2 PHIs: one for size and another for offset.
1203 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1204 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1205
1206 // Insert right away in the cache to handle recursive PHIs.
1207 CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
1208
1209 // Compute offset/size for each PHI incoming pointer.
1210 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1211 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1212 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1213 SizeOffsetEvalType EdgeData = compute_(PHI.getIncomingValue(i));
1214
1215 if (!bothKnown(EdgeData)) {
1216 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1217 OffsetPHI->eraseFromParent();
1218 InsertedInstructions.erase(OffsetPHI);
1219 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1220 SizePHI->eraseFromParent();
1221 InsertedInstructions.erase(SizePHI);
1222 return unknown();
1223 }
1224 SizePHI->addIncoming(EdgeData.first, IncomingBlock);
1225 OffsetPHI->addIncoming(EdgeData.second, IncomingBlock);
1226 }
1227
1228 Value *Size = SizePHI, *Offset = OffsetPHI;
1229 if (Value *Tmp = SizePHI->hasConstantValue()) {
1230 Size = Tmp;
1231 SizePHI->replaceAllUsesWith(Size);
1232 SizePHI->eraseFromParent();
1233 InsertedInstructions.erase(SizePHI);
1234 }
1235 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
1236 Offset = Tmp;
1237 OffsetPHI->replaceAllUsesWith(Offset);
1238 OffsetPHI->eraseFromParent();
1239 InsertedInstructions.erase(OffsetPHI);
1240 }
1241 return std::make_pair(Size, Offset);
1242}
1243
1245 SizeOffsetEvalType TrueSide = compute_(I.getTrueValue());
1246 SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());
1247
1248 if (!bothKnown(TrueSide) || !bothKnown(FalseSide))
1249 return unknown();
1250 if (TrueSide == FalseSide)
1251 return TrueSide;
1252
1253 Value *Size = Builder.CreateSelect(I.getCondition(), TrueSide.first,
1254 FalseSide.first);
1255 Value *Offset = Builder.CreateSelect(I.getCondition(), TrueSide.second,
1256 FalseSide.second);
1257 return std::make_pair(Size, Offset);
1258}
1259
1261 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1262 << '\n');
1263 return unknown();
1264}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Rewrite undef for PHI
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the simple types necessary to represent the attributes associated with functions a...
BlockVerifier::State From
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
Hexagon Common GEP
static LVOptions Options
Definition: LVOptions.cpp:25
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
MallocFamily
static AllocFnKind getAllocFnKind(const Value *V)
static APInt getSizeWithOverflow(const SizeOffsetType &Data)
static std::optional< AllocFnsTy > getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, const TargetLibraryInfo *TLI)
Returns the allocation data for the given value if it's a call to a known allocation function.
static std::optional< AllocFnsTy > getAllocationData(const Value *V, AllocType AllocTy, const TargetLibraryInfo *TLI)
std::optional< FreeFnsTy > getFreeFunctionDataForFunction(const Function *Callee, const LibFunc TLIFn)
static std::optional< AllocFnsTy > getAllocationSize(const Value *V, const TargetLibraryInfo *TLI)
static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted)
StringRef mangledNameForMallocFamily(const MallocFamily &Family)
static bool CheckedZextOrTrunc(APInt &I, unsigned IntTyBits)
When we're compiling N-bit code, and the user uses parameters that are greater than N bits (e....
static const std::pair< LibFunc, FreeFnsTy > FreeFnData[]
static cl::opt< unsigned > ObjectSizeOffsetVisitorMaxVisitInstructions("object-size-offset-visitor-max-visit-instructions", cl::desc("Maximum number of instructions for ObjectSizeOffsetVisitor to " "look at"), cl::init(100))
static const std::pair< LibFunc, AllocFnsTy > AllocationFnData[]
AllocType
@ MallocLike
@ AnyAlloc
@ AllocLike
@ StrDupLike
@ OpNewLike
@ MallocOrOpNewLike
static const Function * getCalledFunction(const Value *V, bool &IsNoBuiltin)
LLVMContext & Context
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition: VPlanSLP.cpp:191
Value * RHS
Value * LHS
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
The main low level interface to the alias analysis implementation.
Class for arbitrary precision integers.
Definition: APInt.h:76
APInt zext(unsigned width) const
Zero extend to a new width.
Definition: APInt.cpp:981
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1485
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:178
The possible results of an alias query.
Definition: AliasAnalysis.h:82
@ NoAlias
The two locations do not alias at all.
@ MustAlias
The two locations precisely alias each other.
an instruction to allocate memory on the stack
Definition: Instructions.h:58
This class represents an incoming formal argument to a Function.
Definition: Argument.h:28
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:297
std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:369
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:318
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:184
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:437
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
Definition: BasicBlock.cpp:446
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:173
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1227
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1449
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1394
Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
@ ICMP_EQ
equal
Definition: InstrTypes.h:769
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:136
A constant pointer value that points to null.
Definition: Constants.h:533
PointerType * getType() const
Specialize the getType() method to always return an PointerType, which reduces the amount of casting ...
Definition: Constants.h:549
This is an important base class in LLVM.
Definition: Constant.h:41
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:356
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
unsigned getIndexTypeSizeInBits(Type *Ty) const
Layout size of the index used in GEP calculation.
Definition: DataLayout.cpp:774
unsigned getAllocaAddrSpace() const
Definition: DataLayout.h:276
IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
Definition: DataLayout.cpp:905
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:504
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
bool erase(const KeyT &Val)
Definition: DenseMap.h:329
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition: DenseMap.h:71
iterator end()
Definition: DenseMap.h:84
This instruction extracts a single (scalar) element from a VectorType value.
This instruction extracts a struct member or array element value from an aggregate value.
Class to represent function types.
Definition: DerivedTypes.h:103
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Definition: DerivedTypes.h:142
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
Type * getReturnType() const
Definition: DerivedTypes.h:124
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:341
const Constant * getAliasee() const
Definition: GlobalAlias.h:84
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:79
bool hasExternalWeakLinkage() const
Definition: GlobalValue.h:524
bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition: Globals.cpp:100
Type * getValueType() const
Definition: GlobalValue.h:292
bool hasInitializer() const
Definitions have initializers, declarations don't.
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2230
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Definition: IRBuilder.h:2018
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition: IRBuilder.cpp:1108
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2218
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition: IRBuilder.h:2370
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1338
CallInst * CreateAssumption(Value *Cond, ArrayRef< OperandBundleDef > OpBundles=std::nullopt)
Create an assume intrinsic call that allows the optimizer to assume that the provided condition will ...
Definition: IRBuilder.cpp:551
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1321
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:180
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1355
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
Definition: IRBuilder.h:76
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2639
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Definition: Instruction.cpp:71
const BasicBlock * getParent() const
Definition: Instruction.h:139
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:93
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:75
This class represents a cast from an integer to a pointer.
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:47
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
Definition: IntrinsicInst.h:54
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
An instruction for reading from memory.
Definition: Instructions.h:177
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.h:275
Evaluate the size and offset of an object pointed to by a Value*.
SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I)
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I)
SizeOffsetEvalType visitPHINode(PHINode &PHI)
SizeOffsetEvalType visitSelectInst(SelectInst &I)
static SizeOffsetEvalType unknown()
SizeOffsetEvalType compute(Value *V)
bool anyKnown(SizeOffsetEvalType SizeOffset)
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts={})
SizeOffsetEvalType visitCallBase(CallBase &CB)
SizeOffsetEvalType visitInstruction(Instruction &I)
SizeOffsetEvalType visitAllocaInst(AllocaInst &I)
bool bothKnown(SizeOffsetEvalType SizeOffset)
SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst &)
SizeOffsetEvalType visitLoadInst(LoadInst &I)
SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP)
Evaluate the size and offset of an object pointed to by a Value* statically.
SizeOffsetType visitAllocaInst(AllocaInst &I)
SizeOffsetType visitArgument(Argument &A)
SizeOffsetType visitGlobalVariable(GlobalVariable &GV)
SizeOffsetType visitSelectInst(SelectInst &I)
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts Options={})
SizeOffsetType visitCallBase(CallBase &CB)
SizeOffsetType visitExtractValueInst(ExtractValueInst &I)
SizeOffsetType visitConstantPointerNull(ConstantPointerNull &)
SizeOffsetType visitExtractElementInst(ExtractElementInst &I)
static bool bothKnown(const SizeOffsetType &SizeOffset)
SizeOffsetType visitUndefValue(UndefValue &)
SizeOffsetType visitGlobalAlias(GlobalAlias &GA)
SizeOffsetType visitIntToPtrInst(IntToPtrInst &)
static bool knownSize(const SizeOffsetType &SizeOffset)
SizeOffsetType visitLoadInst(LoadInst &I)
static bool knownOffset(const SizeOffsetType &SizeOffset)
SizeOffsetType visitInstruction(Instruction &I)
SizeOffsetType compute(Value *V)
SizeOffsetType visitPHINode(PHINode &)
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
Value * hasConstantValue() const
If the specified PHI node always merges together the same value, return the value,...
unsigned getNumIncomingValues() const
Return the number of incoming edges.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:693
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1743
This class represents the LLVM 'select' instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:366
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetFolder - Create constants with target dependent folding.
Definition: TargetFolder.h:34
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:255
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:302
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
'undef' values are things that do not have specified contents.
Definition: Constants.h:1330
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1724
Value * getOperand(unsigned i) const
Definition: User.h:169
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition: TypeSize.h:172
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition: TypeSize.h:169
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:228
std::pair< APInt, APInt > SizeOffsetType
AllocFnKind
Definition: Attributes.h:47
bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
std::optional< StringRef > getAllocationFamily(const Value *I, const TargetLibraryInfo *TLI)
If a function is part of an allocation family (e.g.
Value * lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL, const TargetLibraryInfo *TLI, bool MustSucceed)
Try to turn a call to @llvm.objectsize into an integer value of the given Type.
Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
std::pair< Value *, Value * > SizeOffsetEvalType
bool isLibFreeFunction(const Function *F, const LibFunc TLIFn)
isLibFreeFunction - Returns true if the function is a builtin free()
Value * getReallocatedOperand(const CallBase *CB)
If this is a call to a realloc function, return the reallocated operand.
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory (either malloc,...
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
Value * emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL, User *GEP, bool NoAssumptions=false)
Given a getelementptr instruction/constantexpr, emit the code necessary to compute the offset from th...
Definition: Local.cpp:22
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
uint64_t GetStringLength(const Value *V, unsigned CharSize=8)
If we can compute the length of the string pointed to by the specified pointer, return 'len+1'.
bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory similar to malloc or...
bool isReallocLikeFn(const Function *F)
Tests if a function is a call or invoke to a library function that reallocates memory (e....
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1753
auto predecessors(const MachineBasicBlock *BB)
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
std::optional< bool > isImpliedByDomCondition(const Value *Cond, const Instruction *ContextI, const DataLayout &DL)
Return the boolean condition value in the context of the given instruction if it is known based on do...
bool isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory via new.
MallocFamily Family
unsigned NumParams
AllocType AllocTy
MallocFamily Family
unsigned NumParams
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117
Various options to control the behavior of getObjectSize.
bool NullIsUnknownSize
If this is true, null pointers in address space 0 will be treated as though they can't be evaluated.
Mode EvalMode
How we want to evaluate this object's size.
AAResults * AA
If set, used for more accurate evaluation.
bool RoundToAlign
Whether to round the result up to the alignment of allocas, byval arguments, and global variables.
@ ExactUnderlyingSizeAndOffset
All branches must be known and have the same underlying size and offset to be merged.
@ Max
Same as Min, except we pick the maximum size of all of the branches.
@ Min
Evaluate all branches of an unknown condition.
@ ExactSizeFromOffset
All branches must be known and have the same size, starting from the offset, to be merged.