LLVM 22.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 {
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 }
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() ||
290}
292 const Value *V,
293 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
294 return getAllocationData(V, AnyAlloc, GetTLI).has_value() ||
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() ||
316}
317
318/// Tests if a functions is a call or invoke to a library function that
319/// reallocates memory (e.g., realloc).
323
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 if (isa<AllocaInst>(V))
432 return UndefValue::get(Ty);
433
434 auto *Alloc = dyn_cast<CallBase>(V);
435 if (!Alloc)
436 return nullptr;
437
438 // malloc are uninitialized (undef)
439 if (getAllocationData(Alloc, MallocOrOpNewLike, TLI).has_value())
440 return UndefValue::get(Ty);
441
444 return UndefValue::get(Ty);
446 return Constant::getNullValue(Ty);
447
448 return nullptr;
449}
450
451struct FreeFnsTy {
452 unsigned NumParams;
453 // Name of default allocator function to group malloc/free calls by family
455};
456
457// clang-format off
458static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
459 {LibFunc_ZdlPv, {1, MallocFamily::CPPNew}}, // operator delete(void*)
460 {LibFunc_ZdaPv, {1, MallocFamily::CPPNewArray}}, // operator delete[](void*)
461 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
462 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
463 {LibFunc_msvc_delete_array_ptr32, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
464 {LibFunc_msvc_delete_array_ptr64, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
465 {LibFunc_ZdlPvj, {2, MallocFamily::CPPNew}}, // delete(void*, uint)
466 {LibFunc_ZdlPvm, {2, MallocFamily::CPPNew}}, // delete(void*, ulong)
467 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}}, // delete(void*, nothrow)
468 {LibFunc_ZdlPvSt11align_val_t, {2, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t)
469 {LibFunc_ZdaPvj, {2, MallocFamily::CPPNewArray}}, // delete[](void*, uint)
470 {LibFunc_ZdaPvm, {2, MallocFamily::CPPNewArray}}, // delete[](void*, ulong)
471 {LibFunc_ZdaPvRKSt9nothrow_t, {2, MallocFamily::CPPNewArray}}, // delete[](void*, nothrow)
472 {LibFunc_ZdaPvSt11align_val_t, {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
473 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}}, // delete(void*, uint)
474 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}}, // delete(void*, ulonglong)
475 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
476 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
477 {LibFunc_msvc_delete_array_ptr32_int, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, uint)
478 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, ulonglong)
479 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
480 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
481 {LibFunc___kmpc_free_shared, {2, MallocFamily::KmpcAllocShared}}, // OpenMP Offloading RTL free
482 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t, nothrow)
483 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
484 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned int, align_val_t)
485 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned long, align_val_t)
486 {LibFunc_ZdaPvjSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
487 {LibFunc_ZdaPvmSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
488};
489// clang-format on
490
491std::optional<FreeFnsTy> getFreeFunctionDataForFunction(const Function *Callee,
492 const LibFunc TLIFn) {
493 const auto *Iter =
494 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
495 return P.first == TLIFn;
496 });
497 if (Iter == std::end(FreeFnData))
498 return std::nullopt;
499 return Iter->second;
500}
501
502std::optional<StringRef>
504 if (const Function *Callee = getCalledFunction(I)) {
505 LibFunc TLIFn;
506 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) {
507 // Callee is some known library function.
508 const auto AllocData =
510 if (AllocData)
511 return mangledNameForMallocFamily(AllocData->Family);
512 const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
513 if (FreeData)
514 return mangledNameForMallocFamily(FreeData->Family);
515 }
516 }
517
518 // Callee isn't a known library function, still check attributes.
521 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
522 if (Attr.isValid())
523 return Attr.getValueAsString();
524 }
525 return std::nullopt;
526}
527
528/// isLibFreeFunction - Returns true if the function is a builtin free()
529bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
530 std::optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
531 if (!FnData)
533
534 // Check free prototype.
535 // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
536 // attribute will exist.
537 FunctionType *FTy = F->getFunctionType();
538 if (!FTy->getReturnType()->isVoidTy())
539 return false;
540 if (FTy->getNumParams() != FnData->NumParams)
541 return false;
542 if (!FTy->getParamType(0)->isPointerTy())
543 return false;
544
545 return true;
546}
547
549 if (const Function *Callee = getCalledFunction(CB)) {
550 LibFunc TLIFn;
551 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) &&
552 isLibFreeFunction(Callee, TLIFn)) {
553 // All currently supported free functions free the first argument.
554 return CB->getArgOperand(0);
555 }
556 }
557
559 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
560
561 return nullptr;
562}
563
564//===----------------------------------------------------------------------===//
565// Utility functions to compute size of objects.
566//
568 APInt Size = Data.Size;
569 APInt Offset = Data.Offset;
570
571 if (Offset.isNegative() || Size.ult(Offset))
572 return APInt::getZero(Size.getBitWidth());
573
574 return Size - Offset;
575}
576
577/// Compute the size of the object pointed by Ptr. Returns true and the
578/// object size in Size if successful, and false otherwise.
579/// If RoundToAlign is true, then Size is rounded up to the alignment of
580/// allocas, byval arguments, and global variables.
582 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) {
583 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts);
584 SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr));
585 if (!Data.bothKnown())
586 return false;
587
589 return true;
590}
591
592std::optional<TypeSize> llvm::getBaseObjectSize(const Value *Ptr,
593 const DataLayout &DL,
594 const TargetLibraryInfo *TLI,
595 ObjectSizeOpts Opts) {
597 "Other modes are currently not supported");
598
599 auto Align = [&](TypeSize Size, MaybeAlign Alignment) {
600 if (Opts.RoundToAlign && Alignment && !Size.isScalable())
601 return TypeSize::getFixed(alignTo(Size.getFixedValue(), *Alignment));
602 return Size;
603 };
604
605 if (isa<UndefValue>(Ptr))
606 return TypeSize::getZero();
607
608 if (isa<ConstantPointerNull>(Ptr)) {
610 return std::nullopt;
611 return TypeSize::getZero();
612 }
613
614 if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
615 if (!GV->getValueType()->isSized() || GV->hasExternalWeakLinkage() ||
616 !GV->hasInitializer() || GV->isInterposable())
617 return std::nullopt;
618 return Align(DL.getTypeAllocSize(GV->getValueType()), GV->getAlign());
619 }
620
621 if (auto *A = dyn_cast<Argument>(Ptr)) {
622 Type *MemoryTy = A->getPointeeInMemoryValueType();
623 if (!MemoryTy || !MemoryTy->isSized())
624 return std::nullopt;
625 return Align(DL.getTypeAllocSize(MemoryTy), A->getParamAlign());
626 }
627
628 if (auto *AI = dyn_cast<AllocaInst>(Ptr)) {
629 if (std::optional<TypeSize> Size = AI->getAllocationSize(DL))
630 return Align(*Size, AI->getAlign());
631 return std::nullopt;
632 }
633
634 if (auto *CB = dyn_cast<CallBase>(Ptr)) {
635 if (std::optional<APInt> Size = getAllocSize(CB, TLI)) {
636 if (std::optional<uint64_t> ZExtSize = Size->tryZExtValue())
637 return TypeSize::getFixed(*ZExtSize);
638 }
639 return std::nullopt;
640 }
641
642 return std::nullopt;
643}
644
646 const DataLayout &DL,
647 const TargetLibraryInfo *TLI,
648 bool MustSucceed) {
649 return lowerObjectSizeCall(ObjectSize, DL, TLI, /*AAResults=*/nullptr,
650 MustSucceed);
651}
652
654 IntrinsicInst *ObjectSize, const DataLayout &DL,
655 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
656 SmallVectorImpl<Instruction *> *InsertedInstructions) {
657 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
658 "ObjectSize must be a call to llvm.objectsize!");
659
660 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
661 ObjectSizeOpts EvalOptions;
662 EvalOptions.AA = AA;
663
664 // Unless we have to fold this to something, try to be as accurate as
665 // possible.
666 if (MustSucceed)
667 EvalOptions.EvalMode =
669 else
671
672 EvalOptions.NullIsUnknownSize =
673 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
674
675 auto *ResultType = cast<IntegerType>(ObjectSize->getType());
676 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
677 if (StaticOnly) {
678 // FIXME: Does it make sense to just return a failure value if the size won't
679 // fit in the output and `!MustSucceed`?
681 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) &&
682 isUIntN(ResultType->getBitWidth(), Size))
683 return ConstantInt::get(ResultType, Size);
684 } else {
685 LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
686 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
687 SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0));
688
689 if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
692 if (InsertedInstructions)
693 InsertedInstructions->push_back(I);
694 }));
695 Builder.SetInsertPoint(ObjectSize);
696
697 Value *Size = SizeOffsetPair.Size;
698 Value *Offset = SizeOffsetPair.Offset;
699
700 // If we've outside the end of the object, then we can always access
701 // exactly 0 bytes.
702 Value *ResultSize = Builder.CreateSub(Size, Offset);
703 Value *UseZero = Builder.CreateICmpULT(Size, Offset);
704 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
705 Value *Ret = Builder.CreateSelect(
706 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
707
708 // The non-constant size expression cannot evaluate to -1.
710 Builder.CreateAssumption(Builder.CreateICmpNE(
711 Ret, ConstantInt::getAllOnesValue(ResultType)));
712
713 return Ret;
714 }
715 }
716
717 if (!MustSucceed)
718 return nullptr;
719
720 return MaxVal ? Constant::getAllOnesValue(ResultType)
721 : Constant::getNullValue(ResultType);
722}
723
724STATISTIC(ObjectVisitorArgument,
725 "Number of arguments with unsolved size and offset");
726STATISTIC(ObjectVisitorLoad,
727 "Number of load instructions with unsolved size and offset");
728
729static std::optional<APInt>
731 std::optional<APInt> RHS,
732 ObjectSizeOpts::Mode EvalMode) {
733 if (!LHS || !RHS)
734 return std::nullopt;
735 if (EvalMode == ObjectSizeOpts::Mode::Max)
736 return LHS->sge(*RHS) ? *LHS : *RHS;
737 else
738 return LHS->sle(*RHS) ? *LHS : *RHS;
739}
740
741static std::optional<APInt> aggregatePossibleConstantValuesImpl(
742 const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth,
743 unsigned recursionDepth) {
744 constexpr unsigned maxRecursionDepth = 4;
745 if (recursionDepth == maxRecursionDepth)
746 return std::nullopt;
747
748 if (const auto *CI = dyn_cast<ConstantInt>(V)) {
749 return CI->getValue().sextOrTrunc(BitWidth);
750 } else if (const auto *SI = dyn_cast<SelectInst>(V)) {
752 aggregatePossibleConstantValuesImpl(SI->getTrueValue(), EvalMode,
753 BitWidth, recursionDepth + 1),
754 aggregatePossibleConstantValuesImpl(SI->getFalseValue(), EvalMode,
755 BitWidth, recursionDepth + 1),
756 EvalMode);
757 } else if (const auto *PN = dyn_cast<PHINode>(V)) {
758 unsigned Count = PN->getNumIncomingValues();
759 if (Count == 0)
760 return std::nullopt;
762 PN->getIncomingValue(0), EvalMode, BitWidth, recursionDepth + 1);
763 for (unsigned I = 1; Acc && I < Count; ++I) {
765 PN->getIncomingValue(I), EvalMode, BitWidth, recursionDepth + 1);
766 Acc = combinePossibleConstantValues(Acc, Tmp, EvalMode);
767 }
768 return Acc;
769 }
770
771 return std::nullopt;
772}
773
774static std::optional<APInt>
776 unsigned BitWidth) {
777 if (auto *CI = dyn_cast<ConstantInt>(V))
778 return CI->getValue().sextOrTrunc(BitWidth);
779
780 if (EvalMode != ObjectSizeOpts::Mode::Min &&
781 EvalMode != ObjectSizeOpts::Mode::Max)
782 return std::nullopt;
783
784 // Not using computeConstantRange here because we cannot guarantee it's not
785 // doing optimization based on UB which we want to avoid when expanding
786 // __builtin_object_size.
787 return aggregatePossibleConstantValuesImpl(V, EvalMode, BitWidth, 0u);
788}
789
790/// Align \p Size according to \p Alignment. If \p Size is greater than
791/// getSignedMaxValue(), set it as unknown as we can only represent signed value
792/// in OffsetSpan.
793APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) {
794 if (Options.RoundToAlign && Alignment)
795 Size = APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
796
797 return Size.isNegative() ? APInt() : Size;
798}
799
801 const TargetLibraryInfo *TLI,
802 LLVMContext &Context,
803 ObjectSizeOpts Options)
804 : DL(DL), TLI(TLI), Options(Options) {
805 // Pointer size must be rechecked for each object visited since it could have
806 // a different address space.
807}
808
810 InstructionsVisited = 0;
811 OffsetSpan Span = computeImpl(V);
812
813 // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow
814 // us to overwrite it if needs be.
815 if (Span.knownAfter() && !Span.knownBefore() &&
817 Span.Before = APInt::getZero(Span.After.getBitWidth());
818
819 if (!Span.bothKnown())
820 return {};
821
822 return {Span.Before + Span.After, Span.Before};
823}
824
825OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
826 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
827
828 // Stripping pointer casts can strip address space casts which can change the
829 // index type size. The invariant is that we use the value type to determine
830 // the index type size and if we stripped address space casts we have to
831 // readjust the APInt as we pass it upwards in order for the APInt to match
832 // the type the caller passed in.
833 APInt Offset(InitialIntTyBits, 0);
834 V = V->stripAndAccumulateConstantOffsets(
835 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
836
837 // Give it another try with approximated analysis. We don't start with this
838 // one because stripAndAccumulateConstantOffsets behaves differently wrt.
839 // overflows if we provide an external Analysis.
840 if ((Options.EvalMode == ObjectSizeOpts::Mode::Min ||
841 Options.EvalMode == ObjectSizeOpts::Mode::Max) &&
842 isa<GEPOperator>(V)) {
843 // External Analysis used to compute the Min/Max value of individual Offsets
844 // within a GEP.
845 ObjectSizeOpts::Mode EvalMode =
849 // For a GEPOperator the indices are first converted to offsets in the
850 // pointer’s index type, so we need to provide the index type to make sure
851 // the min/max operations are performed in correct type.
852 unsigned IdxTyBits = DL.getIndexTypeSizeInBits(V->getType());
853 auto OffsetRangeAnalysis = [EvalMode, IdxTyBits](Value &VOffset,
854 APInt &Offset) {
855 if (auto PossibleOffset =
856 aggregatePossibleConstantValues(&VOffset, EvalMode, IdxTyBits)) {
857 Offset = *PossibleOffset;
858 return true;
859 }
860 return false;
861 };
862
863 V = V->stripAndAccumulateConstantOffsets(
864 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true,
865 /*ExternalAnalysis=*/OffsetRangeAnalysis);
866 }
867
868 // Later we use the index type size and zero but it will match the type of the
869 // value that is passed to computeImpl.
870 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
871 Zero = APInt::getZero(IntTyBits);
872 OffsetSpan ORT = computeValue(V);
873
874 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
875 if (!IndexTypeSizeChanged && Offset.isZero())
876 return ORT;
877
878 // We stripped an address space cast that changed the index type size or we
879 // accumulated some constant offset (or both). Readjust the bit width to match
880 // the argument index type size and apply the offset, as required.
881 if (IndexTypeSizeChanged) {
882 if (ORT.knownBefore() &&
883 !::CheckedZextOrTrunc(ORT.Before, InitialIntTyBits))
884 ORT.Before = APInt();
885 if (ORT.knownAfter() && !::CheckedZextOrTrunc(ORT.After, InitialIntTyBits))
886 ORT.After = APInt();
887 }
888 // If the computed bound is "unknown" we cannot add the stripped offset.
889 if (ORT.knownBefore()) {
890 bool Overflow;
891 ORT.Before = ORT.Before.sadd_ov(Offset, Overflow);
892 if (Overflow)
893 ORT.Before = APInt();
894 }
895 if (ORT.knownAfter()) {
896 bool Overflow;
897 ORT.After = ORT.After.ssub_ov(Offset, Overflow);
898 if (Overflow)
899 ORT.After = APInt();
900 }
901
902 // We end up pointing on a location that's outside of the original object.
903 if (ORT.knownBefore() && ORT.Before.isNegative()) {
904 // This means that we *may* be accessing memory before the allocation.
905 // Conservatively return an unknown size.
906 //
907 // TODO: working with ranges instead of value would make it possible to take
908 // a better decision.
909 if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
910 Options.EvalMode == ObjectSizeOpts::Mode::Max) {
911 return ObjectSizeOffsetVisitor::unknown();
912 }
913 // Otherwise it's fine, caller can handle negative offset.
914 }
915 return ORT;
916}
917
918OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) {
919 if (Instruction *I = dyn_cast<Instruction>(V)) {
920 // If we have already seen this instruction, bail out. Cycles can happen in
921 // unreachable code after constant propagation.
922 auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown());
923 if (!P.second)
924 return P.first->second;
925 ++InstructionsVisited;
926 if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions)
927 return ObjectSizeOffsetVisitor::unknown();
928 OffsetSpan Res = visit(*I);
929 // Cache the result for later visits. If we happened to visit this during
930 // the above recursion, we would consider it unknown until now.
931 SeenInsts[I] = Res;
932 return Res;
933 }
934 if (Argument *A = dyn_cast<Argument>(V))
935 return visitArgument(*A);
936 if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
938 if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
939 return visitGlobalAlias(*GA);
940 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
941 return visitGlobalVariable(*GV);
942 if (UndefValue *UV = dyn_cast<UndefValue>(V))
943 return visitUndefValue(*UV);
944
945 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
946 << *V << '\n');
947 return ObjectSizeOffsetVisitor::unknown();
948}
949
950bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
951 return ::CheckedZextOrTrunc(I, IntTyBits);
952}
953
955 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
956 if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
957 return ObjectSizeOffsetVisitor::unknown();
958 if (!isUIntN(IntTyBits, ElemSize.getKnownMinValue()))
959 return ObjectSizeOffsetVisitor::unknown();
960 APInt Size(IntTyBits, ElemSize.getKnownMinValue());
961
962 if (!I.isArrayAllocation())
963 return OffsetSpan(Zero, align(Size, I.getAlign()));
964
965 Value *ArraySize = I.getArraySize();
966 if (auto PossibleSize = aggregatePossibleConstantValues(
967 ArraySize, Options.EvalMode,
968 ArraySize->getType()->getScalarSizeInBits())) {
969 APInt NumElems = *PossibleSize;
970 if (!CheckedZextOrTrunc(NumElems))
971 return ObjectSizeOffsetVisitor::unknown();
972
973 bool Overflow;
974 Size = Size.umul_ov(NumElems, Overflow);
975
976 return Overflow ? ObjectSizeOffsetVisitor::unknown()
977 : OffsetSpan(Zero, align(Size, I.getAlign()));
978 }
979 return ObjectSizeOffsetVisitor::unknown();
980}
981
983 Type *MemoryTy = A.getPointeeInMemoryValueType();
984 // No interprocedural analysis is done at the moment.
985 if (!MemoryTy|| !MemoryTy->isSized()) {
986 ++ObjectVisitorArgument;
987 return ObjectSizeOffsetVisitor::unknown();
988 }
989
990 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
991 return OffsetSpan(Zero, align(Size, A.getParamAlign()));
992}
993
995 auto Mapper = [this](const Value *V) -> const Value * {
996 if (!V->getType()->isIntegerTy())
997 return V;
998
999 if (auto PossibleBound = aggregatePossibleConstantValues(
1000 V, Options.EvalMode, V->getType()->getScalarSizeInBits()))
1001 return ConstantInt::get(V->getType(), *PossibleBound);
1002
1003 return V;
1004 };
1005
1006 if (std::optional<APInt> Size = getAllocSize(&CB, TLI, Mapper)) {
1007 // Very large unsigned value cannot be represented as OffsetSpan.
1008 if (Size->isNegative())
1009 return ObjectSizeOffsetVisitor::unknown();
1010 return OffsetSpan(Zero, *Size);
1011 }
1012 return ObjectSizeOffsetVisitor::unknown();
1013}
1014
1017 // If null is unknown, there's nothing we can do. Additionally, non-zero
1018 // address spaces can make use of null, so we don't presume to know anything
1019 // about that.
1020 //
1021 // TODO: How should this work with address space casts? We currently just drop
1022 // them on the floor, but it's unclear what we should do when a NULL from
1023 // addrspace(1) gets casted to addrspace(0) (or vice-versa).
1024 if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace())
1025 return ObjectSizeOffsetVisitor::unknown();
1026 return OffsetSpan(Zero, Zero);
1027}
1028
1031 return ObjectSizeOffsetVisitor::unknown();
1032}
1033
1035 // Easy cases were already folded by previous passes.
1036 return ObjectSizeOffsetVisitor::unknown();
1037}
1038
1040 if (GA.isInterposable())
1041 return ObjectSizeOffsetVisitor::unknown();
1042 return computeImpl(GA.getAliasee());
1043}
1044
1046 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() ||
1047 ((!GV.hasInitializer() || GV.isInterposable()) &&
1048 Options.EvalMode != ObjectSizeOpts::Mode::Min))
1049 return ObjectSizeOffsetVisitor::unknown();
1050
1051 APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType()));
1052 return OffsetSpan(Zero, align(Size, GV.getAlign()));
1053}
1054
1056 // clueless
1057 return ObjectSizeOffsetVisitor::unknown();
1058}
1059
1060OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange(
1061 LoadInst &Load, BasicBlock &BB, BasicBlock::iterator From,
1063 unsigned &ScannedInstCount) {
1064 constexpr unsigned MaxInstsToScan = 128;
1065
1066 auto Where = VisitedBlocks.find(&BB);
1067 if (Where != VisitedBlocks.end())
1068 return Where->second;
1069
1070 auto Unknown = [&BB, &VisitedBlocks]() {
1071 return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown();
1072 };
1073 auto Known = [&BB, &VisitedBlocks](OffsetSpan SO) {
1074 return VisitedBlocks[&BB] = SO;
1075 };
1076
1077 do {
1078 Instruction &I = *From;
1079
1080 if (I.isDebugOrPseudoInst())
1081 continue;
1082
1083 if (++ScannedInstCount > MaxInstsToScan)
1084 return Unknown();
1085
1086 if (!I.mayWriteToMemory())
1087 continue;
1088
1089 if (auto *SI = dyn_cast<StoreInst>(&I)) {
1090 AliasResult AR =
1091 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
1092 switch ((AliasResult::Kind)AR) {
1094 continue;
1096 if (SI->getValueOperand()->getType()->isPointerTy())
1097 return Known(computeImpl(SI->getValueOperand()));
1098 else
1099 return Unknown(); // No handling of non-pointer values by `compute`.
1100 default:
1101 return Unknown();
1102 }
1103 }
1104
1105 if (auto *CB = dyn_cast<CallBase>(&I)) {
1107 // Bail out on indirect call.
1108 if (!Callee)
1109 return Unknown();
1110
1111 LibFunc TLIFn;
1112 if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) ||
1113 !TLI->has(TLIFn))
1114 return Unknown();
1115
1116 // TODO: There's probably more interesting case to support here.
1117 if (TLIFn != LibFunc_posix_memalign)
1118 return Unknown();
1119
1120 AliasResult AR =
1121 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
1122 switch ((AliasResult::Kind)AR) {
1124 continue;
1126 break;
1127 default:
1128 return Unknown();
1129 }
1130
1131 // Is the error status of posix_memalign correctly checked? If not it
1132 // would be incorrect to assume it succeeds and load doesn't see the
1133 // previous value.
1134 std::optional<bool> Checked = isImpliedByDomCondition(
1135 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL);
1136 if (!Checked || !*Checked)
1137 return Unknown();
1138
1139 Value *Size = CB->getOperand(2);
1140 auto *C = dyn_cast<ConstantInt>(Size);
1141 if (!C)
1142 return Unknown();
1143
1144 APInt CSize = C->getValue();
1145 if (CSize.isNegative())
1146 return Unknown();
1147
1148 return Known({APInt(CSize.getBitWidth(), 0), CSize});
1149 }
1150
1151 return Unknown();
1152 } while (From-- != BB.begin());
1153
1154 SmallVector<OffsetSpan> PredecessorSizeOffsets;
1155 for (auto *PredBB : predecessors(&BB)) {
1156 PredecessorSizeOffsets.push_back(findLoadOffsetRange(
1157 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()),
1158 VisitedBlocks, ScannedInstCount));
1159 if (!PredecessorSizeOffsets.back().bothKnown())
1160 return Unknown();
1161 }
1162
1163 if (PredecessorSizeOffsets.empty())
1164 return Unknown();
1165
1166 return Known(std::accumulate(
1167 PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(),
1168 PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) {
1169 return combineOffsetRange(LHS, RHS);
1170 }));
1171}
1172
1174 if (!Options.AA) {
1175 ++ObjectVisitorLoad;
1176 return ObjectSizeOffsetVisitor::unknown();
1177 }
1178
1180 unsigned ScannedInstCount = 0;
1181 OffsetSpan SO =
1182 findLoadOffsetRange(LI, *LI.getParent(), BasicBlock::iterator(LI),
1183 VisitedBlocks, ScannedInstCount);
1184 if (!SO.bothKnown())
1185 ++ObjectVisitorLoad;
1186 return SO;
1187}
1188
1189OffsetSpan ObjectSizeOffsetVisitor::combineOffsetRange(OffsetSpan LHS,
1190 OffsetSpan RHS) {
1191 if (!LHS.bothKnown() || !RHS.bothKnown())
1192 return ObjectSizeOffsetVisitor::unknown();
1193
1194 switch (Options.EvalMode) {
1196 return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before,
1197 LHS.After.slt(RHS.After) ? LHS.After : RHS.After};
1199 return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before,
1200 LHS.After.sgt(RHS.After) ? LHS.After : RHS.After};
1201 }
1203 return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(),
1204 LHS.After.eq(RHS.After) ? LHS.After : APInt()};
1206 return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown();
1207 }
1208 llvm_unreachable("missing an eval mode");
1209}
1210
1212 if (PN.getNumIncomingValues() == 0)
1213 return ObjectSizeOffsetVisitor::unknown();
1214 auto IncomingValues = PN.incoming_values();
1215 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1216 computeImpl(*IncomingValues.begin()),
1217 [this](OffsetSpan LHS, Value *VRHS) {
1218 return combineOffsetRange(LHS, computeImpl(VRHS));
1219 });
1220}
1221
1223 return combineOffsetRange(computeImpl(I.getTrueValue()),
1224 computeImpl(I.getFalseValue()));
1225}
1226
1230
1232 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1233 << '\n');
1234 return ObjectSizeOffsetVisitor::unknown();
1235}
1236
1237// Just set these right here...
1240
1242 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
1243 ObjectSizeOpts EvalOpts)
1244 : DL(DL), TLI(TLI), Context(Context),
1245 Builder(Context, TargetFolder(DL),
1247 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1248 EvalOpts(EvalOpts) {
1249 // IntTy and Zero must be set for each compute() since the address space may
1250 // be different for later objects.
1251}
1252
1254 // XXX - Are vectors of pointers possible here?
1255 IntTy = cast<IntegerType>(DL.getIndexType(V->getType()));
1256 Zero = ConstantInt::get(IntTy, 0);
1257
1258 SizeOffsetValue Result = compute_(V);
1259
1260 if (!Result.bothKnown()) {
1261 // Erase everything that was computed in this iteration from the cache, so
1262 // that no dangling references are left behind. We could be a bit smarter if
1263 // we kept a dependency graph. It's probably not worth the complexity.
1264 for (const Value *SeenVal : SeenVals) {
1265 CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
1266 // non-computable results can be safely cached
1267 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown())
1268 CacheMap.erase(CacheIt);
1269 }
1270
1271 // Erase any instructions we inserted as part of the traversal.
1272 for (Instruction *I : InsertedInstructions) {
1273 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
1274 I->eraseFromParent();
1275 }
1276 }
1277
1278 SeenVals.clear();
1279 InsertedInstructions.clear();
1280 return Result;
1281}
1282
1283SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) {
1284
1285 // Only trust ObjectSizeOffsetVisitor in exact mode, otherwise fallback on
1286 // dynamic computation.
1287 ObjectSizeOpts VisitorEvalOpts(EvalOpts);
1288 VisitorEvalOpts.EvalMode = ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset;
1289 ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, VisitorEvalOpts);
1290
1291 SizeOffsetAPInt Const = Visitor.compute(V);
1292 if (Const.bothKnown())
1293 return SizeOffsetValue(ConstantInt::get(Context, Const.Size),
1294 ConstantInt::get(Context, Const.Offset));
1295
1296 V = V->stripPointerCasts();
1297
1298 // Check cache.
1299 CacheMapTy::iterator CacheIt = CacheMap.find(V);
1300 if (CacheIt != CacheMap.end())
1301 return CacheIt->second;
1302
1303 // Always generate code immediately before the instruction being
1304 // processed, so that the generated code dominates the same BBs.
1305 BuilderTy::InsertPointGuard Guard(Builder);
1307 Builder.SetInsertPoint(I);
1308
1309 // Now compute the size and offset.
1310 SizeOffsetValue Result;
1311
1312 // Record the pointers that were handled in this run, so that they can be
1313 // cleaned later if something fails. We also use this set to break cycles that
1314 // can occur in dead code.
1315 if (!SeenVals.insert(V).second) {
1317 } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
1318 Result = visitGEPOperator(*GEP);
1319 } else if (Instruction *I = dyn_cast<Instruction>(V)) {
1320 Result = visit(*I);
1321 } else if (isa<Argument>(V) ||
1322 (isa<ConstantExpr>(V) &&
1323 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
1324 isa<GlobalAlias>(V) ||
1326 // Ignore values where we cannot do more than ObjectSizeVisitor.
1328 } else {
1329 LLVM_DEBUG(
1330 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1331 << '\n');
1333 }
1334
1335 // Don't reuse CacheIt since it may be invalid at this point.
1336 CacheMap[V] = SizeOffsetWeakTrackingVH(Result);
1337 return Result;
1338}
1339
1341 if (!I.getAllocatedType()->isSized())
1343
1344 // must be a VLA or vscale.
1345 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
1346
1347 // If needed, adjust the alloca's operand size to match the pointer indexing
1348 // size. Subsequent math operations expect the types to match.
1349 Value *ArraySize = Builder.CreateZExtOrTrunc(
1350 I.getArraySize(),
1351 DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace()));
1352 assert(ArraySize->getType() == Zero->getType() &&
1353 "Expected zero constant to have pointer index type");
1354
1355 Value *Size = Builder.CreateTypeSize(
1356 ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType()));
1357 Size = Builder.CreateMul(Size, ArraySize);
1358 return SizeOffsetValue(Size, Zero);
1359}
1360
1362 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI);
1363 if (!FnData)
1365
1366 // Handle strdup-like functions separately.
1367 if (FnData->AllocTy == StrDupLike) {
1368 // TODO: implement evaluation of strdup/strndup
1370 }
1371
1372 Value *FirstArg = CB.getArgOperand(FnData->FstParam);
1373 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1374 if (FnData->SndParam < 0)
1375 return SizeOffsetValue(FirstArg, Zero);
1376
1377 Value *SecondArg = CB.getArgOperand(FnData->SndParam);
1378 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1379 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1380 return SizeOffsetValue(Size, Zero);
1381}
1382
1387
1392
1394 SizeOffsetValue PtrData = compute_(GEP.getPointerOperand());
1395 if (!PtrData.bothKnown())
1397
1398 Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1399 Offset = Builder.CreateAdd(PtrData.Offset, Offset);
1400 return SizeOffsetValue(PtrData.Size, Offset);
1401}
1402
1407
1411
1413 // Create 2 PHIs: one for size and another for offset.
1414 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1415 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1416
1417 // Insert right away in the cache to handle recursive PHIs.
1418 CacheMap[&PHI] = SizeOffsetWeakTrackingVH(SizePHI, OffsetPHI);
1419
1420 // Compute offset/size for each PHI incoming pointer.
1421 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1422 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1423 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1424 SizeOffsetValue EdgeData = compute_(PHI.getIncomingValue(i));
1425
1426 if (!EdgeData.bothKnown()) {
1427 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1428 OffsetPHI->eraseFromParent();
1429 InsertedInstructions.erase(OffsetPHI);
1430 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1431 SizePHI->eraseFromParent();
1432 InsertedInstructions.erase(SizePHI);
1434 }
1435 SizePHI->addIncoming(EdgeData.Size, IncomingBlock);
1436 OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock);
1437 }
1438
1439 Value *Size = SizePHI, *Offset = OffsetPHI;
1440 if (Value *Tmp = SizePHI->hasConstantValue()) {
1441 Size = Tmp;
1442 SizePHI->replaceAllUsesWith(Size);
1443 SizePHI->eraseFromParent();
1444 InsertedInstructions.erase(SizePHI);
1445 }
1446 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
1447 Offset = Tmp;
1448 OffsetPHI->replaceAllUsesWith(Offset);
1449 OffsetPHI->eraseFromParent();
1450 InsertedInstructions.erase(OffsetPHI);
1451 }
1452 return SizeOffsetValue(Size, Offset);
1453}
1454
1456 SizeOffsetValue TrueSide = compute_(I.getTrueValue());
1457 SizeOffsetValue FalseSide = compute_(I.getFalseValue());
1458
1459 if (!TrueSide.bothKnown() || !FalseSide.bothKnown())
1461 if (TrueSide == FalseSide)
1462 return TrueSide;
1463
1464 Value *Size =
1465 Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size);
1466 Value *Offset =
1467 Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset);
1468 return SizeOffsetValue(Size, Offset);
1469}
1470
1472 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1473 << '\n');
1475}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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...
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...
SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks
Hexagon Common GEP
static LVOptions Options
Definition LVOptions.cpp:25
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
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 std::optional< APInt > aggregatePossibleConstantValuesImpl(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth, unsigned recursionDepth)
static const std::pair< LibFunc, FreeFnsTy > FreeFnData[]
static const Function * getCalledFunction(const Value *V)
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 APInt getSizeWithOverflow(const SizeOffsetAPInt &Data)
static std::optional< APInt > aggregatePossibleConstantValues(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth)
#define P(N)
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:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1012
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1541
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1489
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1928
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1941
@ 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
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:69
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:223
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:459
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
Value * getArgOperand(unsigned i) const
LLVM_ABI Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
unsigned arg_size() const
This is the shared class of boolean and integer constants.
Definition Constants.h:87
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
A constant pointer value that points to null.
Definition Constants.h:563
PointerType * getType() const
Specialize the getType() method to always return an PointerType, which reduces the amount of casting ...
Definition Constants.h:579
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:74
iterator end()
Definition DenseMap.h:81
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.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
const Constant * getAliasee() const
Definition GlobalAlias.h:87
bool hasExternalWeakLinkage() const
LLVM_ABI bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition Globals.cpp:107
Type * getValueType() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:207
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
Definition IRBuilder.h:75
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This class represents a cast from an integer to a pointer.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
Evaluate the size and offset of an object pointed to by a Value*.
LLVM_ABI SizeOffsetValue visitExtractValueInst(ExtractValueInst &I)
LLVM_ABI SizeOffsetValue visitExtractElementInst(ExtractElementInst &I)
LLVM_ABI SizeOffsetValue compute(Value *V)
LLVM_ABI SizeOffsetValue visitInstruction(Instruction &I)
LLVM_ABI ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts={})
LLVM_ABI SizeOffsetValue visitLoadInst(LoadInst &I)
LLVM_ABI SizeOffsetValue visitGEPOperator(GEPOperator &GEP)
LLVM_ABI SizeOffsetValue visitIntToPtrInst(IntToPtrInst &)
LLVM_ABI SizeOffsetValue visitPHINode(PHINode &PHI)
LLVM_ABI SizeOffsetValue visitCallBase(CallBase &CB)
LLVM_ABI SizeOffsetValue visitSelectInst(SelectInst &I)
LLVM_ABI SizeOffsetValue visitAllocaInst(AllocaInst &I)
static SizeOffsetValue unknown()
Evaluate the size and offset of an object pointed to by a Value* statically.
LLVM_ABI OffsetSpan visitSelectInst(SelectInst &I)
LLVM_ABI OffsetSpan visitExtractValueInst(ExtractValueInst &I)
LLVM_ABI OffsetSpan visitConstantPointerNull(ConstantPointerNull &)
LLVM_ABI OffsetSpan visitExtractElementInst(ExtractElementInst &I)
LLVM_ABI OffsetSpan visitGlobalVariable(GlobalVariable &GV)
LLVM_ABI OffsetSpan visitCallBase(CallBase &CB)
LLVM_ABI OffsetSpan visitIntToPtrInst(IntToPtrInst &)
LLVM_ABI OffsetSpan visitAllocaInst(AllocaInst &I)
LLVM_ABI ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts Options={})
LLVM_ABI OffsetSpan visitLoadInst(LoadInst &I)
LLVM_ABI OffsetSpan visitPHINode(PHINode &)
LLVM_ABI OffsetSpan visitGlobalAlias(GlobalAlias &GA)
LLVM_ABI OffsetSpan visitInstruction(Instruction &I)
LLVM_ABI SizeOffsetAPInt compute(Value *V)
LLVM_ABI OffsetSpan visitUndefValue(UndefValue &)
LLVM_ABI 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()
LLVM_ABI 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.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
TargetFolder - Create constants with target dependent folding.
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.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getZero()
Definition TypeSize.h:349
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:267
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition Type.h:311
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:230
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:1430
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
Definition User.h:232
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.cpp:1099
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI 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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
AllocFnKind
Definition Attributes.h:51
LLVM_ABI 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...
LLVM_ABI std::optional< StringRef > getAllocationFamily(const Value *I, const TargetLibraryInfo *TLI)
If a function is part of an allocation family (e.g.
LLVM_ABI 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.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:243
LLVM_ABI bool isLibFreeFunction(const Function *F, const LibFunc TLIFn)
isLibFreeFunction - Returns true if the function is a builtin free()
LLVM_ABI Value * getReallocatedOperand(const CallBase *CB)
If this is a call to a realloc function, return the reallocated operand.
LLVM_ABI std::optional< TypeSize > getBaseObjectSize(const Value *Ptr, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Like getObjectSize(), but only returns the size of base objects (like allocas, global variables and a...
LLVM_ABI 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,...
LLVM_ABI 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.
LLVM_ABI 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
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
LLVM_ABI 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'.
LLVM_ABI 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...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI bool isReallocLikeFn(const Function *F)
Tests if a function is a call or invoke to a library function that reallocates memory (e....
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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:1770
auto predecessors(const MachineBasicBlock *BB)
LLVM_ABI 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...
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI 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 (non-zero power of two) alignment.
Definition Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
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.
SizeOffsetWeakTrackingVH - Used by ObjectSizeOffsetEvaluator in a DenseMap.