LLVM 20.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 <utility>
48
49using namespace llvm;
50
51#define DEBUG_TYPE "memory-builtins"
52
54 "object-size-offset-visitor-max-visit-instructions",
55 cl::desc("Maximum number of instructions for ObjectSizeOffsetVisitor to "
56 "look at"),
57 cl::init(100));
58
60 OpNewLike = 1<<0, // allocates; never returns null
61 MallocLike = 1<<1, // allocates; may return null
62 StrDupLike = 1<<2,
66};
67
68enum class MallocFamily {
69 Malloc,
70 CPPNew, // new(unsigned int)
71 CPPNewAligned, // new(unsigned int, align_val_t)
72 CPPNewArray, // new[](unsigned int)
73 CPPNewArrayAligned, // new[](unsigned long, align_val_t)
74 MSVCNew, // new(unsigned int)
75 MSVCArrayNew, // new[](unsigned int)
78};
79
81 switch (Family) {
83 return "malloc";
85 return "_Znwm";
87 return "_ZnwmSt11align_val_t";
89 return "_Znam";
91 return "_ZnamSt11align_val_t";
93 return "??2@YAPAXI@Z";
95 return "??_U@YAPAXI@Z";
97 return "vec_malloc";
99 return "__kmpc_alloc_shared";
100 }
101 llvm_unreachable("missing an alloc family");
102}
103
106 unsigned NumParams;
107 // First and Second size parameters (or -1 if unused)
109 // Alignment parameter for aligned_alloc and aligned new
111 // Name of default allocator function to group malloc/free calls by family
113};
114
115// clang-format off
116// FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
117// know which functions are nounwind, noalias, nocapture parameters, etc.
118static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
119 {LibFunc_Znwj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int)
120 {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int, nothrow)
121 {LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t)
122 {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t, nothrow)
123 {LibFunc_Znwm, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long)
124 {LibFunc_Znwm12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, __hot_cold_t)
125 {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow)
126 {LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow, __hot_cold_t)
127 {LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t)
128 {LibFunc_ZnwmSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, __hot_cold_t)
129 {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow)
130 {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)
131 {LibFunc_Znaj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int)
132 {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int, nothrow)
133 {LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t)
134 {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t, nothrow)
135 {LibFunc_Znam, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long)
136 {LibFunc_Znam12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, __hot_cold_t)
137 {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long, nothrow)
138 {LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, nothrow, __hot_cold_t)
139 {LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t)
140 {LibFunc_ZnamSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, __hot_cold_t)
141 {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t, nothrow)
142 {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)
143 {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int)
144 {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int, nothrow)
145 {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long)
146 {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long, nothrow)
147 {LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int)
148 {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int, nothrow)
149 {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long)
150 {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long, nothrow)
151 {LibFunc_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
152 {LibFunc_dunder_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
153 {LibFunc_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
154 {LibFunc_dunder_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
155 {LibFunc___kmpc_alloc_shared, {MallocLike, 1, 0, -1, -1, MallocFamily::KmpcAllocShared}},
156};
157// clang-format on
158
159static const Function *getCalledFunction(const Value *V) {
160 // Don't care about intrinsics in this case.
161 if (isa<IntrinsicInst>(V))
162 return nullptr;
163
164 const auto *CB = dyn_cast<CallBase>(V);
165 if (!CB)
166 return nullptr;
167
168 if (CB->isNoBuiltin())
169 return nullptr;
170
171 return CB->getCalledFunction();
172}
173
174/// Returns the allocation data for the given value if it's a call to a known
175/// allocation function.
176static std::optional<AllocFnsTy>
178 const TargetLibraryInfo *TLI) {
179 // Don't perform a slow TLI lookup, if this function doesn't return a pointer
180 // and thus can't be an allocation function.
181 if (!Callee->getReturnType()->isPointerTy())
182 return std::nullopt;
183
184 // Make sure that the function is available.
185 LibFunc TLIFn;
186 if (!TLI || !TLI->getLibFunc(*Callee, TLIFn) || !TLI->has(TLIFn))
187 return std::nullopt;
188
189 const auto *Iter = find_if(
190 AllocationFnData, [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) {
191 return P.first == TLIFn;
192 });
193
194 if (Iter == std::end(AllocationFnData))
195 return std::nullopt;
196
197 const AllocFnsTy *FnData = &Iter->second;
198 if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
199 return std::nullopt;
200
201 // Check function prototype.
202 int FstParam = FnData->FstParam;
203 int SndParam = FnData->SndParam;
204 FunctionType *FTy = Callee->getFunctionType();
205
206 if (FTy->getReturnType()->isPointerTy() &&
207 FTy->getNumParams() == FnData->NumParams &&
208 (FstParam < 0 ||
209 (FTy->getParamType(FstParam)->isIntegerTy(32) ||
210 FTy->getParamType(FstParam)->isIntegerTy(64))) &&
211 (SndParam < 0 ||
212 FTy->getParamType(SndParam)->isIntegerTy(32) ||
213 FTy->getParamType(SndParam)->isIntegerTy(64)))
214 return *FnData;
215 return std::nullopt;
216}
217
218static std::optional<AllocFnsTy>
220 const TargetLibraryInfo *TLI) {
221 if (const Function *Callee = getCalledFunction(V))
222 return getAllocationDataForFunction(Callee, AllocTy, TLI);
223 return std::nullopt;
224}
225
226static std::optional<AllocFnsTy>
228 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
229 if (const Function *Callee = getCalledFunction(V))
231 Callee, AllocTy, &GetTLI(const_cast<Function &>(*Callee)));
232 return std::nullopt;
233}
234
235static std::optional<AllocFnsTy>
237 if (const Function *Callee = getCalledFunction(CB)) {
238 // Prefer to use existing information over allocsize. This will give us an
239 // accurate AllocTy.
240 if (std::optional<AllocFnsTy> Data =
242 return Data;
243 }
244
245 Attribute Attr = CB->getFnAttr(Attribute::AllocSize);
246 if (Attr == Attribute())
247 return std::nullopt;
248
249 std::pair<unsigned, std::optional<unsigned>> Args = Attr.getAllocSizeArgs();
250
251 AllocFnsTy Result;
252 // Because allocsize only tells us how many bytes are allocated, we're not
253 // really allowed to assume anything, so we use MallocLike.
254 Result.AllocTy = MallocLike;
255 Result.NumParams = CB->arg_size();
256 Result.FstParam = Args.first;
257 Result.SndParam = Args.second.value_or(-1);
258 // Allocsize has no way to specify an alignment argument
259 Result.AlignParam = -1;
260 return Result;
261}
262
264 if (const auto *CB = dyn_cast<CallBase>(V)) {
265 Attribute Attr = CB->getFnAttr(Attribute::AllocKind);
266 if (Attr.isValid())
267 return AllocFnKind(Attr.getValueAsInt());
268 }
269 return AllocFnKind::Unknown;
270}
271
273 return F->getAttributes().getAllocKind();
274}
275
276static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted) {
277 return (getAllocFnKind(V) & Wanted) != AllocFnKind::Unknown;
278}
279
280static bool checkFnAllocKind(const Function *F, AllocFnKind Wanted) {
281 return (getAllocFnKind(F) & Wanted) != AllocFnKind::Unknown;
282}
283
284/// Tests if a value is a call or invoke to a library function that
285/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
286/// like).
287bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI) {
288 return getAllocationData(V, AnyAlloc, TLI).has_value() ||
289 checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
290}
292 const Value *V,
293 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
294 return getAllocationData(V, AnyAlloc, GetTLI).has_value() ||
295 checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
296}
297
298/// Tests if a value is a call or invoke to a library function that
299/// allocates memory via new.
300bool llvm::isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
301 return getAllocationData(V, OpNewLike, TLI).has_value();
302}
303
304/// Tests if a value is a call or invoke to a library function that
305/// allocates memory similar to malloc or calloc.
307 // TODO: Function behavior does not match name.
308 return getAllocationData(V, MallocOrOpNewLike, TLI).has_value();
309}
310
311/// Tests if a value is a call or invoke to a library function that
312/// allocates memory (either malloc, calloc, or strdup like).
313bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
314 return getAllocationData(V, AllocLike, TLI).has_value() ||
315 checkFnAllocKind(V, AllocFnKind::Alloc);
316}
317
318/// Tests if a functions is a call or invoke to a library function that
319/// reallocates memory (e.g., realloc).
321 return checkFnAllocKind(F, AllocFnKind::Realloc);
322}
323
325 if (checkFnAllocKind(CB, AllocFnKind::Realloc))
326 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
327 return nullptr;
328}
329
331 // Note: Removability is highly dependent on the source language. For
332 // example, recent C++ requires direct calls to the global allocation
333 // [basic.stc.dynamic.allocation] to be observable unless part of a new
334 // expression [expr.new paragraph 13].
335
336 // Historically we've treated the C family allocation routines and operator
337 // new as removable
338 return isAllocLikeFn(CB, TLI);
339}
340
342 const TargetLibraryInfo *TLI) {
343 const std::optional<AllocFnsTy> FnData = getAllocationData(V, AnyAlloc, TLI);
344 if (FnData && FnData->AlignParam >= 0) {
345 return V->getOperand(FnData->AlignParam);
346 }
347 return V->getArgOperandWithAttribute(Attribute::AllocAlign);
348}
349
350/// When we're compiling N-bit code, and the user uses parameters that are
351/// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
352/// trouble with APInt size issues. This function handles resizing + overflow
353/// checks for us. Check and zext or trunc \p I depending on IntTyBits and
354/// I's value.
355static bool CheckedZextOrTrunc(APInt &I, unsigned IntTyBits) {
356 // More bits than we can handle. Checking the bit width isn't necessary, but
357 // it's faster than checking active bits, and should give `false` in the
358 // vast majority of cases.
359 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
360 return false;
361 if (I.getBitWidth() != IntTyBits)
362 I = I.zextOrTrunc(IntTyBits);
363 return true;
364}
365
366std::optional<APInt>
368 function_ref<const Value *(const Value *)> Mapper) {
369 // Note: This handles both explicitly listed allocation functions and
370 // allocsize. The code structure could stand to be cleaned up a bit.
371 std::optional<AllocFnsTy> FnData = getAllocationSize(CB, TLI);
372 if (!FnData)
373 return std::nullopt;
374
375 // Get the index type for this address space, results and intermediate
376 // computations are performed at that width.
377 auto &DL = CB->getDataLayout();
378 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType());
379
380 // Handle strdup-like functions separately.
381 if (FnData->AllocTy == StrDupLike) {
382 APInt Size(IntTyBits, GetStringLength(Mapper(CB->getArgOperand(0))));
383 if (!Size)
384 return std::nullopt;
385
386 // Strndup limits strlen.
387 if (FnData->FstParam > 0) {
388 const ConstantInt *Arg =
389 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
390 if (!Arg)
391 return std::nullopt;
392
393 APInt MaxSize = Arg->getValue().zext(IntTyBits);
394 if (Size.ugt(MaxSize))
395 Size = MaxSize + 1;
396 }
397 return Size;
398 }
399
400 const ConstantInt *Arg =
401 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
402 if (!Arg)
403 return std::nullopt;
404
405 APInt Size = Arg->getValue();
406 if (!CheckedZextOrTrunc(Size, IntTyBits))
407 return std::nullopt;
408
409 // Size is determined by just 1 parameter.
410 if (FnData->SndParam < 0)
411 return Size;
412
413 Arg = dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->SndParam)));
414 if (!Arg)
415 return std::nullopt;
416
417 APInt NumElems = Arg->getValue();
418 if (!CheckedZextOrTrunc(NumElems, IntTyBits))
419 return std::nullopt;
420
421 bool Overflow;
422 Size = Size.umul_ov(NumElems, Overflow);
423 if (Overflow)
424 return std::nullopt;
425 return Size;
426}
427
429 const TargetLibraryInfo *TLI,
430 Type *Ty) {
431 auto *Alloc = dyn_cast<CallBase>(V);
432 if (!Alloc)
433 return nullptr;
434
435 // malloc are uninitialized (undef)
436 if (getAllocationData(Alloc, MallocOrOpNewLike, TLI).has_value())
437 return UndefValue::get(Ty);
438
439 AllocFnKind AK = getAllocFnKind(Alloc);
440 if ((AK & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
441 return UndefValue::get(Ty);
442 if ((AK & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
443 return Constant::getNullValue(Ty);
444
445 return nullptr;
446}
447
448struct FreeFnsTy {
449 unsigned NumParams;
450 // Name of default allocator function to group malloc/free calls by family
452};
453
454// clang-format off
455static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
456 {LibFunc_ZdlPv, {1, MallocFamily::CPPNew}}, // operator delete(void*)
457 {LibFunc_ZdaPv, {1, MallocFamily::CPPNewArray}}, // operator delete[](void*)
458 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
459 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
460 {LibFunc_msvc_delete_array_ptr32, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
461 {LibFunc_msvc_delete_array_ptr64, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
462 {LibFunc_ZdlPvj, {2, MallocFamily::CPPNew}}, // delete(void*, uint)
463 {LibFunc_ZdlPvm, {2, MallocFamily::CPPNew}}, // delete(void*, ulong)
464 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}}, // delete(void*, nothrow)
465 {LibFunc_ZdlPvSt11align_val_t, {2, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t)
466 {LibFunc_ZdaPvj, {2, MallocFamily::CPPNewArray}}, // delete[](void*, uint)
467 {LibFunc_ZdaPvm, {2, MallocFamily::CPPNewArray}}, // delete[](void*, ulong)
468 {LibFunc_ZdaPvRKSt9nothrow_t, {2, MallocFamily::CPPNewArray}}, // delete[](void*, nothrow)
469 {LibFunc_ZdaPvSt11align_val_t, {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
470 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}}, // delete(void*, uint)
471 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}}, // delete(void*, ulonglong)
472 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
473 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
474 {LibFunc_msvc_delete_array_ptr32_int, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, uint)
475 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, ulonglong)
476 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
477 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
478 {LibFunc___kmpc_free_shared, {2, MallocFamily::KmpcAllocShared}}, // OpenMP Offloading RTL free
479 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t, nothrow)
480 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
481 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned int, align_val_t)
482 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned long, align_val_t)
483 {LibFunc_ZdaPvjSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
484 {LibFunc_ZdaPvmSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
485};
486// clang-format on
487
488std::optional<FreeFnsTy> getFreeFunctionDataForFunction(const Function *Callee,
489 const LibFunc TLIFn) {
490 const auto *Iter =
491 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
492 return P.first == TLIFn;
493 });
494 if (Iter == std::end(FreeFnData))
495 return std::nullopt;
496 return Iter->second;
497}
498
499std::optional<StringRef>
501 if (const Function *Callee = getCalledFunction(I)) {
502 LibFunc TLIFn;
503 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) {
504 // Callee is some known library function.
505 const auto AllocData =
507 if (AllocData)
508 return mangledNameForMallocFamily(AllocData->Family);
509 const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
510 if (FreeData)
511 return mangledNameForMallocFamily(FreeData->Family);
512 }
513 }
514
515 // Callee isn't a known library function, still check attributes.
516 if (checkFnAllocKind(I, AllocFnKind::Free | AllocFnKind::Alloc |
517 AllocFnKind::Realloc)) {
518 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
519 if (Attr.isValid())
520 return Attr.getValueAsString();
521 }
522 return std::nullopt;
523}
524
525/// isLibFreeFunction - Returns true if the function is a builtin free()
526bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
527 std::optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
528 if (!FnData)
529 return checkFnAllocKind(F, AllocFnKind::Free);
530
531 // Check free prototype.
532 // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
533 // attribute will exist.
534 FunctionType *FTy = F->getFunctionType();
535 if (!FTy->getReturnType()->isVoidTy())
536 return false;
537 if (FTy->getNumParams() != FnData->NumParams)
538 return false;
539 if (!FTy->getParamType(0)->isPointerTy())
540 return false;
541
542 return true;
543}
544
546 if (const Function *Callee = getCalledFunction(CB)) {
547 LibFunc TLIFn;
548 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) &&
549 isLibFreeFunction(Callee, TLIFn)) {
550 // All currently supported free functions free the first argument.
551 return CB->getArgOperand(0);
552 }
553 }
554
555 if (checkFnAllocKind(CB, AllocFnKind::Free))
556 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
557
558 return nullptr;
559}
560
561//===----------------------------------------------------------------------===//
562// Utility functions to compute size of objects.
563//
565 APInt Size = Data.Size;
566 APInt Offset = Data.Offset;
567
568 if (Offset.isNegative() || Size.ult(Offset))
569 return APInt::getZero(Size.getBitWidth());
570
571 return Size - Offset;
572}
573
574/// Compute the size of the object pointed by Ptr. Returns true and the
575/// object size in Size if successful, and false otherwise.
576/// If RoundToAlign is true, then Size is rounded up to the alignment of
577/// allocas, byval arguments, and global variables.
579 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) {
580 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts);
581 SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr));
582 if (!Data.bothKnown())
583 return false;
584
586 return true;
587}
588
590 const DataLayout &DL,
591 const TargetLibraryInfo *TLI,
592 bool MustSucceed) {
593 return lowerObjectSizeCall(ObjectSize, DL, TLI, /*AAResults=*/nullptr,
594 MustSucceed);
595}
596
598 IntrinsicInst *ObjectSize, const DataLayout &DL,
599 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
600 SmallVectorImpl<Instruction *> *InsertedInstructions) {
601 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
602 "ObjectSize must be a call to llvm.objectsize!");
603
604 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
605 ObjectSizeOpts EvalOptions;
606 EvalOptions.AA = AA;
607
608 // Unless we have to fold this to something, try to be as accurate as
609 // possible.
610 if (MustSucceed)
611 EvalOptions.EvalMode =
612 MaxVal ? ObjectSizeOpts::Mode::Max : ObjectSizeOpts::Mode::Min;
613 else
614 EvalOptions.EvalMode = ObjectSizeOpts::Mode::ExactSizeFromOffset;
615
616 EvalOptions.NullIsUnknownSize =
617 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
618
619 auto *ResultType = cast<IntegerType>(ObjectSize->getType());
620 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
621 if (StaticOnly) {
622 // FIXME: Does it make sense to just return a failure value if the size won't
623 // fit in the output and `!MustSucceed`?
625 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) &&
626 isUIntN(ResultType->getBitWidth(), Size))
627 return ConstantInt::get(ResultType, Size);
628 } else {
629 LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
630 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
631 SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0));
632
633 if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
636 if (InsertedInstructions)
637 InsertedInstructions->push_back(I);
638 }));
639 Builder.SetInsertPoint(ObjectSize);
640
641 Value *Size = SizeOffsetPair.Size;
642 Value *Offset = SizeOffsetPair.Offset;
643
644 // If we've outside the end of the object, then we can always access
645 // exactly 0 bytes.
646 Value *ResultSize = Builder.CreateSub(Size, Offset);
647 Value *UseZero = Builder.CreateICmpULT(Size, Offset);
648 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
649 Value *Ret = Builder.CreateSelect(
650 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
651
652 // The non-constant size expression cannot evaluate to -1.
653 if (!isa<Constant>(Size) || !isa<Constant>(Offset))
654 Builder.CreateAssumption(
655 Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1)));
656
657 return Ret;
658 }
659 }
660
661 if (!MustSucceed)
662 return nullptr;
663
664 return MaxVal ? Constant::getAllOnesValue(ResultType)
665 : Constant::getNullValue(ResultType);
666}
667
668STATISTIC(ObjectVisitorArgument,
669 "Number of arguments with unsolved size and offset");
670STATISTIC(ObjectVisitorLoad,
671 "Number of load instructions with unsolved size and offset");
672
673static std::optional<APInt>
674combinePossibleConstantValues(std::optional<APInt> LHS,
675 std::optional<APInt> RHS,
676 ObjectSizeOpts::Mode EvalMode) {
677 if (!LHS || !RHS)
678 return std::nullopt;
679 if (EvalMode == ObjectSizeOpts::Mode::Max)
680 return LHS->sge(*RHS) ? *LHS : *RHS;
681 else
682 return LHS->sle(*RHS) ? *LHS : *RHS;
683}
684
685static std::optional<APInt> aggregatePossibleConstantValuesImpl(
686 const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned recursionDepth) {
687 constexpr unsigned maxRecursionDepth = 4;
688 if (recursionDepth == maxRecursionDepth)
689 return std::nullopt;
690
691 if (const auto *CI = dyn_cast<ConstantInt>(V)) {
692 return CI->getValue();
693 } else if (const auto *SI = dyn_cast<SelectInst>(V)) {
695 aggregatePossibleConstantValuesImpl(SI->getTrueValue(), EvalMode,
696 recursionDepth + 1),
697 aggregatePossibleConstantValuesImpl(SI->getFalseValue(), EvalMode,
698 recursionDepth + 1),
699 EvalMode);
700 } else if (const auto *PN = dyn_cast<PHINode>(V)) {
701 unsigned Count = PN->getNumIncomingValues();
702 if (Count == 0)
703 return std::nullopt;
705 PN->getIncomingValue(0), EvalMode, recursionDepth + 1);
706 for (unsigned I = 1; Acc && I < Count; ++I) {
708 PN->getIncomingValue(I), EvalMode, recursionDepth + 1);
709 Acc = combinePossibleConstantValues(Acc, Tmp, EvalMode);
710 }
711 return Acc;
712 }
713
714 return std::nullopt;
715}
716
717static std::optional<APInt>
719 if (auto *CI = dyn_cast<ConstantInt>(V))
720 return CI->getValue();
721
722 if (EvalMode != ObjectSizeOpts::Mode::Min &&
723 EvalMode != ObjectSizeOpts::Mode::Max)
724 return std::nullopt;
725
726 // Not using computeConstantRange here because we cannot guarantee it's not
727 // doing optimization based on UB which we want to avoid when expanding
728 // __builtin_object_size.
729 return aggregatePossibleConstantValuesImpl(V, EvalMode, 0u);
730}
731
732/// Align \p Size according to \p Alignment. If \p Size is greater than
733/// getSignedMaxValue(), set it as unknown as we can only represent signed value
734/// in OffsetSpan.
735APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) {
736 if (Options.RoundToAlign && Alignment)
737 Size = APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
738
739 return Size.isNegative() ? APInt() : Size;
740}
741
743 const TargetLibraryInfo *TLI,
744 LLVMContext &Context,
746 : DL(DL), TLI(TLI), Options(Options) {
747 // Pointer size must be rechecked for each object visited since it could have
748 // a different address space.
749}
750
752 InstructionsVisited = 0;
753 OffsetSpan Span = computeImpl(V);
754
755 // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow
756 // us to overwrite it if needs be.
757 if (Span.knownAfter() && !Span.knownBefore() &&
759 Span.Before = APInt::getZero(Span.After.getBitWidth());
760
761 if (!Span.bothKnown())
762 return {};
763
764 return {Span.Before + Span.After, Span.Before};
765}
766
767OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
768 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
769
770 // Stripping pointer casts can strip address space casts which can change the
771 // index type size. The invariant is that we use the value type to determine
772 // the index type size and if we stripped address space casts we have to
773 // readjust the APInt as we pass it upwards in order for the APInt to match
774 // the type the caller passed in.
775 APInt Offset(InitialIntTyBits, 0);
776 V = V->stripAndAccumulateConstantOffsets(
777 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
778
779 // Give it another try with approximated analysis. We don't start with this
780 // one because stripAndAccumulateConstantOffsets behaves differently wrt.
781 // overflows if we provide an external Analysis.
782 if ((Options.EvalMode == ObjectSizeOpts::Mode::Min ||
784 isa<GEPOperator>(V)) {
785 // External Analysis used to compute the Min/Max value of individual Offsets
786 // within a GEP.
787 ObjectSizeOpts::Mode EvalMode =
791 auto OffsetRangeAnalysis = [EvalMode](Value &VOffset, APInt &Offset) {
792 if (auto PossibleOffset =
793 aggregatePossibleConstantValues(&VOffset, EvalMode)) {
794 Offset = *PossibleOffset;
795 return true;
796 }
797 return false;
798 };
799
800 V = V->stripAndAccumulateConstantOffsets(
801 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true,
802 /*ExternalAnalysis=*/OffsetRangeAnalysis);
803 }
804
805 // Later we use the index type size and zero but it will match the type of the
806 // value that is passed to computeImpl.
807 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
808 Zero = APInt::getZero(IntTyBits);
809 OffsetSpan ORT = computeValue(V);
810
811 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
812 if (!IndexTypeSizeChanged && Offset.isZero())
813 return ORT;
814
815 // We stripped an address space cast that changed the index type size or we
816 // accumulated some constant offset (or both). Readjust the bit width to match
817 // the argument index type size and apply the offset, as required.
818 if (IndexTypeSizeChanged) {
819 if (ORT.knownBefore() &&
820 !::CheckedZextOrTrunc(ORT.Before, InitialIntTyBits))
821 ORT.Before = APInt();
822 if (ORT.knownAfter() && !::CheckedZextOrTrunc(ORT.After, InitialIntTyBits))
823 ORT.After = APInt();
824 }
825 // If the computed bound is "unknown" we cannot add the stripped offset.
826 if (ORT.knownBefore()) {
827 bool Overflow;
828 ORT.Before = ORT.Before.sadd_ov(Offset, Overflow);
829 if (Overflow)
830 ORT.Before = APInt();
831 }
832 if (ORT.knownAfter()) {
833 bool Overflow;
834 ORT.After = ORT.After.ssub_ov(Offset, Overflow);
835 if (Overflow)
836 ORT.After = APInt();
837 }
838
839 // We end up pointing on a location that's outside of the original object.
840 if (ORT.knownBefore() && ORT.Before.isNegative()) {
841 // This means that we *may* be accessing memory before the allocation.
842 // Conservatively return an unknown size.
843 //
844 // TODO: working with ranges instead of value would make it possible to take
845 // a better decision.
846 if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
848 return ObjectSizeOffsetVisitor::unknown();
849 }
850 // Otherwise it's fine, caller can handle negative offset.
851 }
852 return ORT;
853}
854
855OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) {
856 if (Instruction *I = dyn_cast<Instruction>(V)) {
857 // If we have already seen this instruction, bail out. Cycles can happen in
858 // unreachable code after constant propagation.
859 auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown());
860 if (!P.second)
861 return P.first->second;
862 ++InstructionsVisited;
863 if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions)
864 return ObjectSizeOffsetVisitor::unknown();
865 OffsetSpan Res = visit(*I);
866 // Cache the result for later visits. If we happened to visit this during
867 // the above recursion, we would consider it unknown until now.
868 SeenInsts[I] = Res;
869 return Res;
870 }
871 if (Argument *A = dyn_cast<Argument>(V))
872 return visitArgument(*A);
873 if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
875 if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
876 return visitGlobalAlias(*GA);
877 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
878 return visitGlobalVariable(*GV);
879 if (UndefValue *UV = dyn_cast<UndefValue>(V))
880 return visitUndefValue(*UV);
881
882 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
883 << *V << '\n');
884 return ObjectSizeOffsetVisitor::unknown();
885}
886
887bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
888 return ::CheckedZextOrTrunc(I, IntTyBits);
889}
890
892 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
893 if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
894 return ObjectSizeOffsetVisitor::unknown();
895 if (!isUIntN(IntTyBits, ElemSize.getKnownMinValue()))
896 return ObjectSizeOffsetVisitor::unknown();
897 APInt Size(IntTyBits, ElemSize.getKnownMinValue());
898
899 if (!I.isArrayAllocation())
900 return OffsetSpan(Zero, align(Size, I.getAlign()));
901
902 Value *ArraySize = I.getArraySize();
903 if (auto PossibleSize =
904 aggregatePossibleConstantValues(ArraySize, Options.EvalMode)) {
905 APInt NumElems = *PossibleSize;
906 if (!CheckedZextOrTrunc(NumElems))
907 return ObjectSizeOffsetVisitor::unknown();
908
909 bool Overflow;
910 Size = Size.umul_ov(NumElems, Overflow);
911
912 return Overflow ? ObjectSizeOffsetVisitor::unknown()
913 : OffsetSpan(Zero, align(Size, I.getAlign()));
914 }
915 return ObjectSizeOffsetVisitor::unknown();
916}
917
919 Type *MemoryTy = A.getPointeeInMemoryValueType();
920 // No interprocedural analysis is done at the moment.
921 if (!MemoryTy|| !MemoryTy->isSized()) {
922 ++ObjectVisitorArgument;
923 return ObjectSizeOffsetVisitor::unknown();
924 }
925
926 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
927 return OffsetSpan(Zero, align(Size, A.getParamAlign()));
928}
929
931 auto Mapper = [this](const Value *V) -> const Value * {
932 if (!V->getType()->isIntegerTy())
933 return V;
934
935 if (auto PossibleBound =
937 return ConstantInt::get(V->getType(), *PossibleBound);
938
939 return V;
940 };
941
942 if (std::optional<APInt> Size = getAllocSize(&CB, TLI, Mapper)) {
943 // Very large unsigned value cannot be represented as OffsetSpan.
944 if (Size->isNegative())
945 return ObjectSizeOffsetVisitor::unknown();
946 return OffsetSpan(Zero, *Size);
947 }
948 return ObjectSizeOffsetVisitor::unknown();
949}
950
953 // If null is unknown, there's nothing we can do. Additionally, non-zero
954 // address spaces can make use of null, so we don't presume to know anything
955 // about that.
956 //
957 // TODO: How should this work with address space casts? We currently just drop
958 // them on the floor, but it's unclear what we should do when a NULL from
959 // addrspace(1) gets casted to addrspace(0) (or vice-versa).
960 if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace())
961 return ObjectSizeOffsetVisitor::unknown();
962 return OffsetSpan(Zero, Zero);
963}
964
967 return ObjectSizeOffsetVisitor::unknown();
968}
969
971 // Easy cases were already folded by previous passes.
972 return ObjectSizeOffsetVisitor::unknown();
973}
974
976 if (GA.isInterposable())
977 return ObjectSizeOffsetVisitor::unknown();
978 return computeImpl(GA.getAliasee());
979}
980
982 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() ||
983 ((!GV.hasInitializer() || GV.isInterposable()) &&
985 return ObjectSizeOffsetVisitor::unknown();
986
987 APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType()));
988 return OffsetSpan(Zero, align(Size, GV.getAlign()));
989}
990
992 // clueless
993 return ObjectSizeOffsetVisitor::unknown();
994}
995
996OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange(
999 unsigned &ScannedInstCount) {
1000 constexpr unsigned MaxInstsToScan = 128;
1001
1002 auto Where = VisitedBlocks.find(&BB);
1003 if (Where != VisitedBlocks.end())
1004 return Where->second;
1005
1006 auto Unknown = [&BB, &VisitedBlocks]() {
1007 return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown();
1008 };
1009 auto Known = [&BB, &VisitedBlocks](OffsetSpan SO) {
1010 return VisitedBlocks[&BB] = SO;
1011 };
1012
1013 do {
1014 Instruction &I = *From;
1015
1016 if (I.isDebugOrPseudoInst())
1017 continue;
1018
1019 if (++ScannedInstCount > MaxInstsToScan)
1020 return Unknown();
1021
1022 if (!I.mayWriteToMemory())
1023 continue;
1024
1025 if (auto *SI = dyn_cast<StoreInst>(&I)) {
1026 AliasResult AR =
1027 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
1028 switch ((AliasResult::Kind)AR) {
1030 continue;
1032 if (SI->getValueOperand()->getType()->isPointerTy())
1033 return Known(computeImpl(SI->getValueOperand()));
1034 else
1035 return Unknown(); // No handling of non-pointer values by `compute`.
1036 default:
1037 return Unknown();
1038 }
1039 }
1040
1041 if (auto *CB = dyn_cast<CallBase>(&I)) {
1043 // Bail out on indirect call.
1044 if (!Callee)
1045 return Unknown();
1046
1047 LibFunc TLIFn;
1048 if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) ||
1049 !TLI->has(TLIFn))
1050 return Unknown();
1051
1052 // TODO: There's probably more interesting case to support here.
1053 if (TLIFn != LibFunc_posix_memalign)
1054 return Unknown();
1055
1056 AliasResult AR =
1057 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
1058 switch ((AliasResult::Kind)AR) {
1060 continue;
1062 break;
1063 default:
1064 return Unknown();
1065 }
1066
1067 // Is the error status of posix_memalign correctly checked? If not it
1068 // would be incorrect to assume it succeeds and load doesn't see the
1069 // previous value.
1070 std::optional<bool> Checked = isImpliedByDomCondition(
1071 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL);
1072 if (!Checked || !*Checked)
1073 return Unknown();
1074
1075 Value *Size = CB->getOperand(2);
1076 auto *C = dyn_cast<ConstantInt>(Size);
1077 if (!C)
1078 return Unknown();
1079
1080 APInt CSize = C->getValue();
1081 if (CSize.isNegative())
1082 return Unknown();
1083
1084 return Known({APInt(CSize.getBitWidth(), 0), CSize});
1085 }
1086
1087 return Unknown();
1088 } while (From-- != BB.begin());
1089
1090 SmallVector<OffsetSpan> PredecessorSizeOffsets;
1091 for (auto *PredBB : predecessors(&BB)) {
1092 PredecessorSizeOffsets.push_back(findLoadOffsetRange(
1093 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()),
1094 VisitedBlocks, ScannedInstCount));
1095 if (!PredecessorSizeOffsets.back().bothKnown())
1096 return Unknown();
1097 }
1098
1099 if (PredecessorSizeOffsets.empty())
1100 return Unknown();
1101
1102 return Known(std::accumulate(
1103 PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(),
1104 PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) {
1105 return combineOffsetRange(LHS, RHS);
1106 }));
1107}
1108
1110 if (!Options.AA) {
1111 ++ObjectVisitorLoad;
1112 return ObjectSizeOffsetVisitor::unknown();
1113 }
1114
1116 unsigned ScannedInstCount = 0;
1117 OffsetSpan SO =
1118 findLoadOffsetRange(LI, *LI.getParent(), BasicBlock::iterator(LI),
1119 VisitedBlocks, ScannedInstCount);
1120 if (!SO.bothKnown())
1121 ++ObjectVisitorLoad;
1122 return SO;
1123}
1124
1125OffsetSpan ObjectSizeOffsetVisitor::combineOffsetRange(OffsetSpan LHS,
1126 OffsetSpan RHS) {
1127 if (!LHS.bothKnown() || !RHS.bothKnown())
1128 return ObjectSizeOffsetVisitor::unknown();
1129
1130 switch (Options.EvalMode) {
1132 return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before,
1133 LHS.After.slt(RHS.After) ? LHS.After : RHS.After};
1135 return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before,
1136 LHS.After.sgt(RHS.After) ? LHS.After : RHS.After};
1137 }
1139 return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(),
1140 LHS.After.eq(RHS.After) ? LHS.After : APInt()};
1142 return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown();
1143 }
1144 llvm_unreachable("missing an eval mode");
1145}
1146
1148 if (PN.getNumIncomingValues() == 0)
1149 return ObjectSizeOffsetVisitor::unknown();
1150 auto IncomingValues = PN.incoming_values();
1151 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1152 computeImpl(*IncomingValues.begin()),
1153 [this](OffsetSpan LHS, Value *VRHS) {
1154 return combineOffsetRange(LHS, computeImpl(VRHS));
1155 });
1156}
1157
1159 return combineOffsetRange(computeImpl(I.getTrueValue()),
1160 computeImpl(I.getFalseValue()));
1161}
1162
1164 return OffsetSpan(Zero, Zero);
1165}
1166
1168 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1169 << '\n');
1170 return ObjectSizeOffsetVisitor::unknown();
1171}
1172
1173// Just set these right here...
1175 : SizeOffsetType(SOT.Size, SOT.Offset) {}
1176
1178 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
1179 ObjectSizeOpts EvalOpts)
1180 : DL(DL), TLI(TLI), Context(Context),
1181 Builder(Context, TargetFolder(DL),
1183 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1184 EvalOpts(EvalOpts) {
1185 // IntTy and Zero must be set for each compute() since the address space may
1186 // be different for later objects.
1187}
1188
1190 // XXX - Are vectors of pointers possible here?
1191 IntTy = cast<IntegerType>(DL.getIndexType(V->getType()));
1192 Zero = ConstantInt::get(IntTy, 0);
1193
1194 SizeOffsetValue Result = compute_(V);
1195
1196 if (!Result.bothKnown()) {
1197 // Erase everything that was computed in this iteration from the cache, so
1198 // that no dangling references are left behind. We could be a bit smarter if
1199 // we kept a dependency graph. It's probably not worth the complexity.
1200 for (const Value *SeenVal : SeenVals) {
1201 CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
1202 // non-computable results can be safely cached
1203 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown())
1204 CacheMap.erase(CacheIt);
1205 }
1206
1207 // Erase any instructions we inserted as part of the traversal.
1208 for (Instruction *I : InsertedInstructions) {
1209 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
1210 I->eraseFromParent();
1211 }
1212 }
1213
1214 SeenVals.clear();
1215 InsertedInstructions.clear();
1216 return Result;
1217}
1218
1219SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) {
1220
1221 // Only trust ObjectSizeOffsetVisitor in exact mode, otherwise fallback on
1222 // dynamic computation.
1223 ObjectSizeOpts VisitorEvalOpts(EvalOpts);
1224 VisitorEvalOpts.EvalMode = ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset;
1225 ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, VisitorEvalOpts);
1226
1227 SizeOffsetAPInt Const = Visitor.compute(V);
1228 if (Const.bothKnown())
1229 return SizeOffsetValue(ConstantInt::get(Context, Const.Size),
1230 ConstantInt::get(Context, Const.Offset));
1231
1232 V = V->stripPointerCasts();
1233
1234 // Check cache.
1235 CacheMapTy::iterator CacheIt = CacheMap.find(V);
1236 if (CacheIt != CacheMap.end())
1237 return CacheIt->second;
1238
1239 // Always generate code immediately before the instruction being
1240 // processed, so that the generated code dominates the same BBs.
1241 BuilderTy::InsertPointGuard Guard(Builder);
1242 if (Instruction *I = dyn_cast<Instruction>(V))
1243 Builder.SetInsertPoint(I);
1244
1245 // Now compute the size and offset.
1246 SizeOffsetValue Result;
1247
1248 // Record the pointers that were handled in this run, so that they can be
1249 // cleaned later if something fails. We also use this set to break cycles that
1250 // can occur in dead code.
1251 if (!SeenVals.insert(V).second) {
1253 } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
1254 Result = visitGEPOperator(*GEP);
1255 } else if (Instruction *I = dyn_cast<Instruction>(V)) {
1256 Result = visit(*I);
1257 } else if (isa<Argument>(V) ||
1258 (isa<ConstantExpr>(V) &&
1259 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
1260 isa<GlobalAlias>(V) ||
1261 isa<GlobalVariable>(V)) {
1262 // Ignore values where we cannot do more than ObjectSizeVisitor.
1264 } else {
1265 LLVM_DEBUG(
1266 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1267 << '\n');
1269 }
1270
1271 // Don't reuse CacheIt since it may be invalid at this point.
1272 CacheMap[V] = SizeOffsetWeakTrackingVH(Result);
1273 return Result;
1274}
1275
1277 if (!I.getAllocatedType()->isSized())
1279
1280 // must be a VLA or vscale.
1281 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
1282
1283 // If needed, adjust the alloca's operand size to match the pointer indexing
1284 // size. Subsequent math operations expect the types to match.
1285 Value *ArraySize = Builder.CreateZExtOrTrunc(
1286 I.getArraySize(),
1287 DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace()));
1288 assert(ArraySize->getType() == Zero->getType() &&
1289 "Expected zero constant to have pointer index type");
1290
1291 Value *Size = Builder.CreateTypeSize(
1292 ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType()));
1293 Size = Builder.CreateMul(Size, ArraySize);
1294 return SizeOffsetValue(Size, Zero);
1295}
1296
1298 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI);
1299 if (!FnData)
1301
1302 // Handle strdup-like functions separately.
1303 if (FnData->AllocTy == StrDupLike) {
1304 // TODO: implement evaluation of strdup/strndup
1306 }
1307
1308 Value *FirstArg = CB.getArgOperand(FnData->FstParam);
1309 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1310 if (FnData->SndParam < 0)
1311 return SizeOffsetValue(FirstArg, Zero);
1312
1313 Value *SecondArg = CB.getArgOperand(FnData->SndParam);
1314 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1315 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1316 return SizeOffsetValue(Size, Zero);
1317}
1318
1322}
1323
1327}
1328
1330 SizeOffsetValue PtrData = compute_(GEP.getPointerOperand());
1331 if (!PtrData.bothKnown())
1333
1334 Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1335 Offset = Builder.CreateAdd(PtrData.Offset, Offset);
1336 return SizeOffsetValue(PtrData.Size, Offset);
1337}
1338
1340 // clueless
1342}
1343
1346}
1347
1349 // Create 2 PHIs: one for size and another for offset.
1350 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1351 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1352
1353 // Insert right away in the cache to handle recursive PHIs.
1354 CacheMap[&PHI] = SizeOffsetWeakTrackingVH(SizePHI, OffsetPHI);
1355
1356 // Compute offset/size for each PHI incoming pointer.
1357 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1358 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1359 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1360 SizeOffsetValue EdgeData = compute_(PHI.getIncomingValue(i));
1361
1362 if (!EdgeData.bothKnown()) {
1363 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1364 OffsetPHI->eraseFromParent();
1365 InsertedInstructions.erase(OffsetPHI);
1366 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1367 SizePHI->eraseFromParent();
1368 InsertedInstructions.erase(SizePHI);
1370 }
1371 SizePHI->addIncoming(EdgeData.Size, IncomingBlock);
1372 OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock);
1373 }
1374
1375 Value *Size = SizePHI, *Offset = OffsetPHI;
1376 if (Value *Tmp = SizePHI->hasConstantValue()) {
1377 Size = Tmp;
1378 SizePHI->replaceAllUsesWith(Size);
1379 SizePHI->eraseFromParent();
1380 InsertedInstructions.erase(SizePHI);
1381 }
1382 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
1383 Offset = Tmp;
1384 OffsetPHI->replaceAllUsesWith(Offset);
1385 OffsetPHI->eraseFromParent();
1386 InsertedInstructions.erase(OffsetPHI);
1387 }
1388 return SizeOffsetValue(Size, Offset);
1389}
1390
1392 SizeOffsetValue TrueSide = compute_(I.getTrueValue());
1393 SizeOffsetValue FalseSide = compute_(I.getFalseValue());
1394
1395 if (!TrueSide.bothKnown() || !FalseSide.bothKnown())
1397 if (TrueSide == FalseSide)
1398 return TrueSide;
1399
1400 Value *Size =
1401 Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size);
1402 Value *Offset =
1403 Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset);
1404 return SizeOffsetValue(Size, Offset);
1405}
1406
1408 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1409 << '\n');
1411}
Rewrite undef for PHI
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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(...)
Definition: Debug.h:106
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 std::optional< APInt > combinePossibleConstantValues(std::optional< APInt > LHS, std::optional< APInt > RHS, ObjectSizeOpts::Mode EvalMode)
static AllocFnKind getAllocFnKind(const Value *V)
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 bool checkFnAllocKind(const Value *V, AllocFnKind Wanted)
StringRef mangledNameForMallocFamily(const MallocFamily &Family)
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
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 const Function * getCalledFunction(const Value *V)
static std::optional< APInt > aggregatePossibleConstantValues(const Value *V, ObjectSizeOpts::Mode EvalMode)
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 std::optional< APInt > aggregatePossibleConstantValuesImpl(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned recursionDepth)
static const std::pair< LibFunc, AllocFnsTy > AllocationFnData[]
AllocType
@ MallocLike
@ AnyAlloc
@ AllocLike
@ StrDupLike
@ OpNewLike
@ MallocOrOpNewLike
static APInt getSizeWithOverflow(const SizeOffsetAPInt &Data)
#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:166
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:78
APInt zext(unsigned width) const
Zero extend to a new width.
Definition: APInt.cpp:986
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1520
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1468
bool isNegative() const
Determine sign of this APInt.
Definition: APInt.h:329
APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1902
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:200
APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1915
The possible results of an alias query.
Definition: AliasAnalysis.h:77
@ NoAlias
The two locations do not alias at all.
Definition: AliasAnalysis.h:95
@ MustAlias
The two locations precisely alias each other.
an instruction to allocate memory on the stack
Definition: Instructions.h:63
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:371
std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:454
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:392
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:208
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:448
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:416
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:177
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1120
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1349
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
Definition: InstrTypes.h:1613
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1294
Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
unsigned arg_size() const
Definition: InstrTypes.h:1292
@ ICMP_EQ
equal
Definition: InstrTypes.h:694
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:148
A constant pointer value that points to null.
Definition: Constants.h:552
PointerType * getType() const
Specialize the getType() method to always return an PointerType, which reduces the amount of casting ...
Definition: Constants.h:568
This is an important base class in LLVM.
Definition: Constant.h:42
static Constant * getAllOnesValue(Type *Ty)
Definition: Constants.cpp:420
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:373
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
unsigned getIndexTypeSizeInBits(Type *Ty) const
Layout size of the index used in GEP calculation.
Definition: DataLayout.cpp:754
unsigned getAllocaAddrSpace() const
Definition: DataLayout.h:229
IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
Definition: DataLayout.cpp:878
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:457
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
bool erase(const KeyT &Val)
Definition: DenseMap.h:321
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:105
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Definition: DerivedTypes.h:144
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:137
Type * getReturnType() const
Definition: DerivedTypes.h:126
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
const Constant * getAliasee() const
Definition: GlobalAlias.h:86
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:79
bool hasExternalWeakLinkage() const
Definition: GlobalValue.h:529
bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition: Globals.cpp:105
Type * getValueType() const
Definition: GlobalValue.h:296
bool hasInitializer() const
Definitions have initializers, declarations don't.
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2289
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Definition: IRBuilder.h:2066
CallInst * CreateAssumption(Value *Cond, ArrayRef< OperandBundleDef > OpBundles={})
Create an assume intrinsic call that allows the optimizer to assume that the provided condition will ...
Definition: IRBuilder.cpp:521
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition: IRBuilder.cpp:1048
Value * CreateTypeSize(Type *DstType, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Definition: IRBuilder.cpp:103
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2277
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition: IRBuilder.h:2429
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1367
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1350
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:177
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1384
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
Definition: IRBuilder.h:74
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:94
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:72
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Definition: Instruction.cpp:76
This class represents a cast from an integer to a pointer.
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:48
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
Definition: IntrinsicInst.h:55
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:176
Evaluate the size and offset of an object pointed to by a Value*.
SizeOffsetValue visitExtractValueInst(ExtractValueInst &I)
SizeOffsetValue visitExtractElementInst(ExtractElementInst &I)
SizeOffsetValue compute(Value *V)
SizeOffsetValue visitInstruction(Instruction &I)
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts={})
SizeOffsetValue visitLoadInst(LoadInst &I)
SizeOffsetValue visitGEPOperator(GEPOperator &GEP)
SizeOffsetValue visitIntToPtrInst(IntToPtrInst &)
SizeOffsetValue visitPHINode(PHINode &PHI)
SizeOffsetValue visitCallBase(CallBase &CB)
SizeOffsetValue visitSelectInst(SelectInst &I)
SizeOffsetValue visitAllocaInst(AllocaInst &I)
static SizeOffsetValue unknown()
Evaluate the size and offset of an object pointed to by a Value* statically.
OffsetSpan visitSelectInst(SelectInst &I)
OffsetSpan visitExtractValueInst(ExtractValueInst &I)
OffsetSpan visitConstantPointerNull(ConstantPointerNull &)
OffsetSpan visitExtractElementInst(ExtractElementInst &I)
OffsetSpan visitGlobalVariable(GlobalVariable &GV)
OffsetSpan visitCallBase(CallBase &CB)
OffsetSpan visitIntToPtrInst(IntToPtrInst &)
OffsetSpan visitAllocaInst(AllocaInst &I)
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts Options={})
OffsetSpan visitLoadInst(LoadInst &I)
OffsetSpan visitPHINode(PHINode &)
OffsetSpan visitGlobalAlias(GlobalAlias &GA)
OffsetSpan visitInstruction(Instruction &I)
SizeOffsetAPInt compute(Value *V)
OffsetSpan visitUndefValue(UndefValue &)
OffsetSpan visitArgument(Argument &A)
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:703
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1878
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:384
bool empty() const
Definition: SmallVector.h:81
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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:264
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:310
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
'undef' values are things that do not have specified contents.
Definition: Constants.h:1412
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1859
Value * getOperand(unsigned i) const
Definition: User.h:228
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:171
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition: TypeSize.h:168
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition: ilist_node.h:32
#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:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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:255
AllocFnKind
Definition: Attributes.h:49
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...
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:1766
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.
Mode
Controls how we handle conditional statements with unknown conditions.
@ 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.
OffsetSpan - Used internally by ObjectSizeOffsetVisitor.
bool knownBefore() const
APInt After
Number of allocated bytes before this point.
bool knownAfter() const
bool bothKnown() const
SizeOffsetAPInt - Used by ObjectSizeOffsetVisitor, which works with APInts.
SizeOffsetType - A base template class for the object size visitors.
bool bothKnown() const
SizeOffsetWeakTrackingVH - Used by ObjectSizeOffsetEvaluator in a DenseMap.