LLVM 24.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
59// clang-format off
61 OpNewLike = 1<<0, // allocates; never returns null
62 MallocLike = 1<<1, // allocates; may return null
63 StrDupLike = 1<<2,
67};
68
69enum class MallocFamily {
71 CPPNew, // new(unsigned int)
72 CPPNewAligned, // new(unsigned int, align_val_t)
73 CPPNewArray, // new[](unsigned int)
74 CPPNewArrayAligned, // new[](unsigned long, align_val_t)
75 MSVCNew, // new(unsigned int)
76 MSVCArrayNew, // new[](unsigned int)
78};
79// clang-format on
80
82 switch (Family) {
84 return "malloc";
86 return "_Znwm";
88 return "_ZnwmSt11align_val_t";
90 return "_Znam";
92 return "_ZnamSt11align_val_t";
94 return "??2@YAPAXI@Z";
96 return "??_U@YAPAXI@Z";
98 return "vec_malloc";
99 }
100 llvm_unreachable("missing an alloc family");
101}
102
105 unsigned NumParams;
106 // First and Second size parameters (or -1 if unused)
108 // Alignment parameter for aligned_alloc and aligned new
110 // Name of default allocator function to group malloc/free calls by family
112};
113
114// clang-format off
115// FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
116// know which functions are nounwind, noalias, nocapture parameters, etc.
117static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
118 {LibFunc_Znwj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int)
119 {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned int, nothrow)
120 {LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t)
121 {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t, nothrow)
122 {LibFunc_Znwm, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long)
123 {LibFunc_Znwm12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, __hot_cold_t)
124 {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow)
125 {LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow, __hot_cold_t)
126 {LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t)
127 {LibFunc_ZnwmSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, __hot_cold_t)
128 {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow)
129 {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)
130 {LibFunc_Znaj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int)
131 {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int, nothrow)
132 {LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t)
133 {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t, nothrow)
134 {LibFunc_Znam, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long)
135 {LibFunc_Znam12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, __hot_cold_t)
136 {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long, nothrow)
137 {LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, nothrow, __hot_cold_t)
138 {LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t)
139 {LibFunc_ZnamSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, __hot_cold_t)
140 {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t, nothrow)
141 {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)
142 {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int)
143 {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int, nothrow)
144 {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long)
145 {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long, nothrow)
146 {LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int)
147 {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned int, nothrow)
148 {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long)
149 {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCArrayNew}}, // new[](unsigned long long, nothrow)
150 {LibFunc_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
151 {LibFunc_dunder_strdup, {StrDupLike, 1, -1, -1, -1, MallocFamily::Malloc}},
152 {LibFunc_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
153 {LibFunc_dunder_strndup, {StrDupLike, 2, 1, -1, -1, MallocFamily::Malloc}},
154};
155// clang-format on
156
157static const Function *getCalledFunction(const Value *V) {
158 // Don't care about intrinsics in this case.
159 if (isa<IntrinsicInst>(V))
160 return nullptr;
161
162 const auto *CB = dyn_cast<CallBase>(V);
163 if (!CB)
164 return nullptr;
165
166 if (CB->isNoBuiltin())
167 return nullptr;
168
169 return CB->getCalledFunction();
170}
171
172/// Returns the allocation data for the given value if it's a call to a known
173/// allocation function.
174static std::optional<AllocFnsTy>
176 const TargetLibraryInfo *TLI) {
177 // Don't perform a slow TLI lookup, if this function doesn't return a pointer
178 // and thus can't be an allocation function.
179 if (!Callee->getReturnType()->isPointerTy())
180 return std::nullopt;
181
182 // Make sure that the function is available.
183 if (!TLI)
184 return std::nullopt;
185
186 LibFunc TLIFn = TLI->getLibFunc(*Callee);
187 if (!TLI->has(TLIFn))
188 return std::nullopt;
189
190 const auto *Iter = find_if(AllocationFnData,
191 [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) {
192 return P.first == TLIFn;
193 });
194
195 if (Iter == std::end(AllocationFnData))
196 return std::nullopt;
197
198 const AllocFnsTy *FnData = &Iter->second;
199 if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
200 return std::nullopt;
201
202 // Check function prototype.
203 int FstParam = FnData->FstParam;
204 int SndParam = FnData->SndParam;
205 FunctionType *FTy = Callee->getFunctionType();
206
207 if (FTy->getReturnType()->isPointerTy() &&
208 FTy->getNumParams() == FnData->NumParams &&
209 (FstParam < 0 || (FTy->getParamType(FstParam)->isIntegerTy(32) ||
210 FTy->getParamType(FstParam)->isIntegerTy(64))) &&
211 (SndParam < 0 || FTy->getParamType(SndParam)->isIntegerTy(32) ||
212 FTy->getParamType(SndParam)->isIntegerTy(64)))
213 return *FnData;
214 return std::nullopt;
215}
216
217static std::optional<AllocFnsTy>
219 const TargetLibraryInfo *TLI) {
220 if (const Function *Callee = getCalledFunction(V))
221 return getAllocationDataForFunction(Callee, AllocTy, TLI);
222 return std::nullopt;
223}
224
225static std::optional<AllocFnsTy>
227 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
228 if (const Function *Callee = getCalledFunction(V))
230 Callee, AllocTy, &GetTLI(const_cast<Function &>(*Callee)));
231 return std::nullopt;
232}
233
234static std::optional<AllocFnsTy>
236 if (const Function *Callee = getCalledFunction(CB)) {
237 // Prefer to use existing information over allocsize. This will give us an
238 // accurate AllocTy.
239 if (std::optional<AllocFnsTy> Data =
241 return Data;
242 }
243
244 Attribute Attr = CB->getFnAttr(Attribute::AllocSize);
245 if (Attr == Attribute())
246 return std::nullopt;
247
248 std::pair<unsigned, std::optional<unsigned>> Args = Attr.getAllocSizeArgs();
249
250 AllocFnsTy Result;
251 // Because allocsize only tells us how many bytes are allocated, we're not
252 // really allowed to assume anything, so we use MallocLike.
253 Result.AllocTy = MallocLike;
254 Result.NumParams = CB->arg_size();
255 Result.FstParam = Args.first;
256 Result.SndParam = Args.second.value_or(-1);
257 // Allocsize has no way to specify an alignment argument
258 Result.AlignParam = -1;
259 return Result;
260}
261
263 if (const auto *CB = dyn_cast<CallBase>(V)) {
264 Attribute Attr = CB->getFnAttr(Attribute::AllocKind);
265 if (Attr.isValid())
266 return AllocFnKind(Attr.getValueAsInt());
267 }
269}
270
272 return F->getAttributes().getAllocKind();
273}
274
275static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted) {
276 return (getAllocFnKind(V) & Wanted) != AllocFnKind::Unknown;
277}
278
279static bool checkFnAllocKind(const Function *F, AllocFnKind Wanted) {
280 return (getAllocFnKind(F) & Wanted) != AllocFnKind::Unknown;
281}
282
283/// Tests if a value is a call or invoke to a library function that
284/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
285/// like).
286bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI) {
287 return getAllocationData(V, AnyAlloc, TLI).has_value() ||
289}
291 const Value *V,
292 function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
293 return getAllocationData(V, AnyAlloc, GetTLI).has_value() ||
295}
296
297/// Tests if a value is a call or invoke to a library function that
298/// allocates memory similar to malloc or calloc.
300 const TargetLibraryInfo *TLI) {
301 // TODO: Function behavior does not match name.
302 return getAllocationData(V, MallocOrOpNewLike, TLI).has_value();
303}
304
305/// Tests if a value is a call or invoke to a library function that
306/// allocates memory (either malloc, calloc, or strdup like).
307bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
308 return getAllocationData(V, AllocLike, TLI).has_value() ||
310}
311
312/// Tests if a functions is a call or invoke to a library function that
313/// reallocates memory (e.g., realloc).
317
320 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
321 return nullptr;
322}
323
325 // Note: Removability is highly dependent on the source language. For
326 // example, recent C++ requires direct calls to the global allocation
327 // [basic.stc.dynamic.allocation] to be observable unless part of a new
328 // expression [expr.new paragraph 13].
329
330 // Historically we've treated the C family allocation routines and operator
331 // new as removable
332 return isAllocLikeFn(CB, TLI);
333}
334
336 const TargetLibraryInfo *TLI) {
337 const std::optional<AllocFnsTy> FnData = getAllocationData(V, AnyAlloc, TLI);
338 if (FnData && FnData->AlignParam >= 0) {
339 return V->getOperand(FnData->AlignParam);
340 }
341 return V->getArgOperandWithAttribute(Attribute::AllocAlign);
342}
343
344/// When we're compiling N-bit code, and the user uses parameters that are
345/// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
346/// trouble with APInt size issues. This function handles resizing + overflow
347/// checks for us. Check and zext or trunc \p I depending on IntTyBits and
348/// I's value.
349static bool checkedZextOrTrunc(APInt &I, unsigned IntTyBits) {
350 // More bits than we can handle. Checking the bit width isn't necessary, but
351 // it's faster than checking active bits, and should give `false` in the
352 // vast majority of cases.
353 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
354 return false;
355 if (I.getBitWidth() != IntTyBits)
356 I = I.zextOrTrunc(IntTyBits);
357 return true;
358}
359
360std::optional<APInt>
362 function_ref<const Value *(const Value *)> Mapper) {
363 // Note: This handles both explicitly listed allocation functions and
364 // allocsize. The code structure could stand to be cleaned up a bit.
365 std::optional<AllocFnsTy> FnData = getAllocationSize(CB, TLI);
366 if (!FnData)
367 return std::nullopt;
368
369 // Get the index type for this address space, results and intermediate
370 // computations are performed at that width.
371 auto &DL = CB->getDataLayout();
372 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType());
373
374 // Handle strdup-like functions separately.
375 if (FnData->AllocTy == StrDupLike) {
376 APInt Size(IntTyBits, GetStringLength(Mapper(CB->getArgOperand(0))));
377 if (!Size)
378 return std::nullopt;
379
380 // Strndup limits strlen.
381 if (FnData->FstParam > 0) {
382 const ConstantInt *Arg =
383 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
384 if (!Arg)
385 return std::nullopt;
386
387 APInt MaxSize = Arg->getValue().zext(IntTyBits);
388 if (Size.ugt(MaxSize))
389 Size = MaxSize + 1;
390 }
391 return Size;
392 }
393
394 const ConstantInt *Arg =
395 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
396 if (!Arg)
397 return std::nullopt;
398
399 APInt Size = Arg->getValue();
400 if (!checkedZextOrTrunc(Size, IntTyBits))
401 return std::nullopt;
402
403 // Size is determined by just 1 parameter.
404 if (FnData->SndParam < 0)
405 return Size;
406
407 Arg = dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->SndParam)));
408 if (!Arg)
409 return std::nullopt;
410
411 APInt NumElems = Arg->getValue();
412 if (!checkedZextOrTrunc(NumElems, IntTyBits))
413 return std::nullopt;
414
415 bool Overflow;
416 Size = Size.umul_ov(NumElems, Overflow);
417 if (Overflow)
418 return std::nullopt;
419 return Size;
420}
421
423 const TargetLibraryInfo *TLI,
424 Type *Ty) {
425 if (isa<AllocaInst>(V))
426 return UndefValue::get(Ty);
427
428 auto *Alloc = dyn_cast<CallBase>(V);
429 if (!Alloc)
430 return nullptr;
431
432 // malloc are uninitialized (undef)
433 if (getAllocationData(Alloc, MallocOrOpNewLike, TLI).has_value())
434 return UndefValue::get(Ty);
435
438 return UndefValue::get(Ty);
440 return Constant::getNullValue(Ty);
441
442 return nullptr;
443}
444
445struct FreeFnsTy {
446 unsigned NumParams;
447 // Name of default allocator function to group malloc/free calls by family
449};
450
451// clang-format off
452static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
453 {LibFunc_ZdlPv, {1, MallocFamily::CPPNew}}, // operator delete(void*)
454 {LibFunc_ZdaPv, {1, MallocFamily::CPPNewArray}}, // operator delete[](void*)
455 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
456 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
457 {LibFunc_msvc_delete_array_ptr32, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
458 {LibFunc_msvc_delete_array_ptr64, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
459 {LibFunc_ZdlPvj, {2, MallocFamily::CPPNew}}, // delete(void*, uint)
460 {LibFunc_ZdlPvm, {2, MallocFamily::CPPNew}}, // delete(void*, ulong)
461 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}}, // delete(void*, nothrow)
462 {LibFunc_ZdlPvSt11align_val_t, {2, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t)
463 {LibFunc_ZdaPvj, {2, MallocFamily::CPPNewArray}}, // delete[](void*, uint)
464 {LibFunc_ZdaPvm, {2, MallocFamily::CPPNewArray}}, // delete[](void*, ulong)
465 {LibFunc_ZdaPvRKSt9nothrow_t, {2, MallocFamily::CPPNewArray}}, // delete[](void*, nothrow)
466 {LibFunc_ZdaPvSt11align_val_t, {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
467 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}}, // delete(void*, uint)
468 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}}, // delete(void*, ulonglong)
469 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
470 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
471 {LibFunc_msvc_delete_array_ptr32_int, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, uint)
472 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, ulonglong)
473 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
474 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
475 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t, nothrow)
476 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
477 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned int, align_val_t)
478 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned long, align_val_t)
479 {LibFunc_ZdaPvjSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
480 {LibFunc_ZdaPvmSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
481};
482// clang-format on
483
484static std::optional<FreeFnsTy>
485getFreeFunctionDataForFunction(const Function *Callee, const LibFunc TLIFn) {
486 const auto *Iter =
487 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
488 return P.first == TLIFn;
489 });
490 if (Iter == std::end(FreeFnData))
491 return std::nullopt;
492 return Iter->second;
493}
494
495std::optional<StringRef>
497 if (const Function *Callee = getCalledFunction(I)) {
498 LibFunc TLIFn = TLI ? TLI->getLibFunc(*Callee) : NotLibFunc;
499 if (TLIFn != NotLibFunc && TLI->has(TLIFn)) {
500 // Callee is some known library function.
501 const auto AllocData =
503 if (AllocData)
504 return mangledNameForMallocFamily(AllocData->Family);
505 const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
506 if (FreeData)
507 return mangledNameForMallocFamily(FreeData->Family);
508 }
509 }
510
511 // Callee isn't a known library function, still check attributes.
514 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
515 if (Attr.isValid())
516 return Attr.getValueAsString();
517 }
518 return std::nullopt;
519}
520
521/// isLibFreeFunction - Returns true if the function is a builtin free()
522bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
523 std::optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
524 if (!FnData)
526
527 // Check free prototype.
528 // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
529 // attribute will exist.
530 FunctionType *FTy = F->getFunctionType();
531 if (!FTy->getReturnType()->isVoidTy())
532 return false;
533 if (FTy->getNumParams() != FnData->NumParams)
534 return false;
535 if (!FTy->getParamType(0)->isPointerTy())
536 return false;
537
538 return true;
539}
540
542 if (const Function *Callee = getCalledFunction(CB)) {
543 LibFunc TLIFn = TLI ? TLI->getLibFunc(*Callee) : NotLibFunc;
544 if (TLIFn != NotLibFunc && TLI->has(TLIFn) &&
545 isLibFreeFunction(Callee, TLIFn)) {
546 // All currently supported free functions free the first argument.
547 return CB->getArgOperand(0);
548 }
549 }
550
552 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
553
554 return nullptr;
555}
556
557//===----------------------------------------------------------------------===//
558// Utility functions to compute size of objects.
559//
561 APInt Size = Data.Size;
562 APInt Offset = Data.Offset;
563
564 if (Offset.isNegative() || Size.ult(Offset))
565 return APInt::getZero(Size.getBitWidth());
566
567 return Size - Offset;
568}
569
570/// Compute the size of the object pointed by Ptr. Returns true and the
571/// object size in Size if successful, and false otherwise.
572/// If RoundToAlign is true, then Size is rounded up to the alignment of
573/// allocas, byval arguments, and global variables.
574bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
575 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) {
576 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts);
577 SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr));
578 if (!Data.bothKnown())
579 return false;
580
582 return true;
583}
584
585std::optional<TypeSize> llvm::getBaseObjectSize(const Value *Ptr,
586 const DataLayout &DL,
587 const TargetLibraryInfo *TLI,
588 ObjectSizeOpts Opts) {
590 "Other modes are currently not supported");
591
592 auto Align = [&](TypeSize Size, MaybeAlign Alignment) {
593 if (Opts.RoundToAlign && Alignment && !Size.isScalable())
594 return TypeSize::getFixed(alignTo(Size.getFixedValue(), *Alignment));
595 return Size;
596 };
597
598 if (isa<UndefValue>(Ptr))
599 return TypeSize::getZero();
600
601 if (isa<ConstantPointerNull>(Ptr)) {
603 return std::nullopt;
604 return TypeSize::getZero();
605 }
606
607 if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
608 if (!GV->getValueType()->isSized() || GV->hasExternalWeakLinkage() ||
609 !GV->hasInitializer() || GV->isInterposable())
610 return std::nullopt;
611 return Align(TypeSize::getFixed(GV->getGlobalSize(DL)), GV->getAlign());
612 }
613
614 if (auto *A = dyn_cast<Argument>(Ptr)) {
615 Type *MemoryTy = A->getPointeeInMemoryValueType();
616 if (!MemoryTy || !MemoryTy->isSized())
617 return std::nullopt;
618 return Align(DL.getTypeAllocSize(MemoryTy), A->getParamAlign());
619 }
620
621 if (auto *AI = dyn_cast<AllocaInst>(Ptr)) {
622 if (std::optional<TypeSize> Size = AI->getAllocationSize(DL))
623 return Align(*Size, AI->getAlign());
624 return std::nullopt;
625 }
626
627 if (auto *CB = dyn_cast<CallBase>(Ptr)) {
628 if (std::optional<APInt> Size = getAllocSize(CB, TLI)) {
629 if (std::optional<uint64_t> ZExtSize = Size->tryZExtValue())
630 return TypeSize::getFixed(*ZExtSize);
631 }
632 return std::nullopt;
633 }
634
635 return std::nullopt;
636}
637
639 const DataLayout &DL,
640 const TargetLibraryInfo *TLI,
641 bool MustSucceed) {
642 return lowerObjectSizeCall(ObjectSize, DL, TLI, /*AAResults=*/nullptr,
643 MustSucceed);
644}
645
647 IntrinsicInst *ObjectSize, const DataLayout &DL,
648 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
649 SmallVectorImpl<Instruction *> *InsertedInstructions) {
650 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
651 "ObjectSize must be a call to llvm.objectsize!");
652
653 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
654 ObjectSizeOpts EvalOptions;
655 EvalOptions.AA = AA;
656
657 // Unless we have to fold this to something, try to be as accurate as
658 // possible.
659 if (MustSucceed)
660 EvalOptions.EvalMode =
662 else
664
665 EvalOptions.NullIsUnknownSize =
666 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
667
668 auto *ResultType = cast<IntegerType>(ObjectSize->getType());
669 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
670 if (StaticOnly) {
671 // FIXME: Does it make sense to just return a failure value if the size
672 // won't fit in the output and `!MustSucceed`?
673 uint64_t Size;
674 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI,
675 EvalOptions) &&
676 isUIntN(ResultType->getBitWidth(), Size))
677 return ConstantInt::get(ResultType, Size);
678 } else {
679 LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
680 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
681 SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0));
682
683 if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
686 if (InsertedInstructions)
687 InsertedInstructions->push_back(I);
688 }));
689 Builder.SetInsertPoint(ObjectSize);
690
691 Value *Size = SizeOffsetPair.Size;
692 Value *Offset = SizeOffsetPair.Offset;
693
694 // If we've outside the end of the object, then we can always access
695 // exactly 0 bytes.
696 Value *ResultSize = Builder.CreateSub(Size, Offset);
697 Value *UseZero = Builder.CreateICmpULT(Size, Offset);
698 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
699 Value *Ret = Builder.CreateSelect(
700 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
701
702 // The non-constant size expression cannot evaluate to -1.
704 Builder.CreateAssumption(Builder.CreateICmpNE(
705 Ret, ConstantInt::getAllOnesValue(ResultType)));
706
707 return Ret;
708 }
709 }
710
711 if (!MustSucceed)
712 return nullptr;
713
714 return MaxVal ? Constant::getAllOnesValue(ResultType)
715 : Constant::getNullValue(ResultType);
716}
717
718STATISTIC(ObjectVisitorArgument,
719 "Number of arguments with unsolved size and offset");
720STATISTIC(ObjectVisitorLoad,
721 "Number of load instructions with unsolved size and offset");
722
723static std::optional<APInt>
725 std::optional<APInt> RHS,
726 ObjectSizeOpts::Mode EvalMode) {
727 if (!LHS || !RHS)
728 return std::nullopt;
729 if (EvalMode == ObjectSizeOpts::Mode::Max)
730 return LHS->sge(*RHS) ? *LHS : *RHS;
731 return LHS->sle(*RHS) ? *LHS : *RHS;
732}
733
734static std::optional<APInt> aggregatePossibleConstantValuesImpl(
735 const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth,
736 unsigned RecursionDepth) {
737 constexpr unsigned MaxRecursionDepth = 4;
738 if (RecursionDepth == MaxRecursionDepth)
739 return std::nullopt;
740
741 if (const auto *CI = dyn_cast<ConstantInt>(V)) {
742 return CI->getValue().sextOrTrunc(BitWidth);
743 } else if (const auto *SI = dyn_cast<SelectInst>(V)) {
745 aggregatePossibleConstantValuesImpl(SI->getTrueValue(), EvalMode,
746 BitWidth, RecursionDepth + 1),
747 aggregatePossibleConstantValuesImpl(SI->getFalseValue(), EvalMode,
748 BitWidth, RecursionDepth + 1),
749 EvalMode);
750 } else if (const auto *PN = dyn_cast<PHINode>(V)) {
751 unsigned Count = PN->getNumIncomingValues();
752 if (Count == 0)
753 return std::nullopt;
755 PN->getIncomingValue(0), EvalMode, BitWidth, RecursionDepth + 1);
756 for (unsigned I = 1; Acc && I < Count; ++I) {
758 PN->getIncomingValue(I), EvalMode, BitWidth, RecursionDepth + 1);
759 Acc = combinePossibleConstantValues(Acc, Tmp, EvalMode);
760 }
761 return Acc;
762 }
763
764 return std::nullopt;
765}
766
767static std::optional<APInt>
769 unsigned BitWidth) {
770 if (auto *CI = dyn_cast<ConstantInt>(V))
771 return CI->getValue().sextOrTrunc(BitWidth);
772
773 if (EvalMode != ObjectSizeOpts::Mode::Min &&
774 EvalMode != ObjectSizeOpts::Mode::Max)
775 return std::nullopt;
776
777 // Not using computeConstantRange here because we cannot guarantee it's not
778 // doing optimization based on UB which we want to avoid when expanding
779 // __builtin_object_size.
780 return aggregatePossibleConstantValuesImpl(V, EvalMode, BitWidth, 0u);
781}
782
783/// Align \p Size according to \p Alignment. If \p Size is greater than
784/// getSignedMaxValue(), set it as unknown as we can only represent signed value
785/// in OffsetSpan.
786APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) {
787 if (Options.RoundToAlign && Alignment)
788 Size = APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
789
790 return Size.isNegative() ? APInt() : Size;
791}
792
794 const TargetLibraryInfo *TLI,
795 LLVMContext &Context,
796 ObjectSizeOpts Options)
797 : DL(DL), TLI(TLI), Options(Options) {
798 // Pointer size must be rechecked for each object visited since it could have
799 // a different address space.
800}
801
803 InstructionsVisited = 0;
804 OffsetSpan Span = computeImpl(V);
805
806 // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow
807 // us to overwrite it if needs be.
808 if (Span.knownAfter() && !Span.knownBefore() &&
810 Span.Before = APInt::getZero(Span.After.getBitWidth());
811
812 if (!Span.bothKnown())
813 return {};
814
815 return {Span.Before + Span.After, Span.Before};
816}
817
818OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
819 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
820
821 // Stripping pointer casts can strip address space casts which can change the
822 // index type size. The invariant is that we use the value type to determine
823 // the index type size and if we stripped address space casts we have to
824 // readjust the APInt as we pass it upwards in order for the APInt to match
825 // the type the caller passed in.
826 APInt Offset(InitialIntTyBits, 0);
827 V = V->stripAndAccumulateConstantOffsets(
828 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
829
830 // Give it another try with approximated analysis. We don't start with this
831 // one because stripAndAccumulateConstantOffsets behaves differently wrt.
832 // overflows if we provide an external Analysis.
833 if ((Options.EvalMode == ObjectSizeOpts::Mode::Min ||
834 Options.EvalMode == ObjectSizeOpts::Mode::Max) &&
835 isa<GEPOperator>(V)) {
836 // External Analysis used to compute the Min/Max value of individual Offsets
837 // within a GEP.
838 ObjectSizeOpts::Mode EvalMode =
842 // For a GEPOperator the indices are first converted to offsets in the
843 // pointer’s index type, so we need to provide the index type to make sure
844 // the min/max operations are performed in correct type.
845 unsigned IdxTyBits = DL.getIndexTypeSizeInBits(V->getType());
846 auto OffsetRangeAnalysis = [EvalMode, IdxTyBits](Value &VOffset,
847 APInt &Offset) {
848 if (auto PossibleOffset =
849 aggregatePossibleConstantValues(&VOffset, EvalMode, IdxTyBits)) {
850 Offset = *PossibleOffset;
851 return true;
852 }
853 return false;
854 };
855
856 V = V->stripAndAccumulateConstantOffsets(
857 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true,
858 /*ExternalAnalysis=*/OffsetRangeAnalysis);
859 }
860
861 // Later we use the index type size and zero but it will match the type of the
862 // value that is passed to computeImpl.
863 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
864 Zero = APInt::getZero(IntTyBits);
865 OffsetSpan ORT = computeValue(V);
866
867 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
868 if (!IndexTypeSizeChanged && Offset.isZero())
869 return ORT;
870
871 // We stripped an address space cast that changed the index type size or we
872 // accumulated some constant offset (or both). Readjust the bit width to match
873 // the argument index type size and apply the offset, as required.
874 if (IndexTypeSizeChanged) {
875 if (ORT.knownBefore() &&
876 !::checkedZextOrTrunc(ORT.Before, InitialIntTyBits))
877 ORT.Before = APInt();
878 if (ORT.knownAfter() && !::checkedZextOrTrunc(ORT.After, InitialIntTyBits))
879 ORT.After = APInt();
880 }
881 // If the computed bound is "unknown" we cannot add the stripped offset.
882 if (ORT.knownBefore()) {
883 bool Overflow;
884 ORT.Before = ORT.Before.sadd_ov(Offset, Overflow);
885 if (Overflow)
886 ORT.Before = APInt();
887 }
888 if (ORT.knownAfter()) {
889 bool Overflow;
890 ORT.After = ORT.After.ssub_ov(Offset, Overflow);
891 if (Overflow)
892 ORT.After = APInt();
893 }
894
895 // We end up pointing on a location that's outside of the original object.
896 if (ORT.knownBefore() && ORT.Before.isNegative()) {
897 // This means that we *may* be accessing memory before the allocation.
898 // Conservatively return an unknown size.
899 //
900 // TODO: working with ranges instead of value would make it possible to take
901 // a better decision.
902 if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
903 Options.EvalMode == ObjectSizeOpts::Mode::Max) {
904 return ObjectSizeOffsetVisitor::unknown();
905 }
906 // Otherwise it's fine, caller can handle negative offset.
907 }
908 return ORT;
909}
910
911OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) {
912 if (Instruction *I = dyn_cast<Instruction>(V)) {
913 // If we have already seen this instruction, bail out. Cycles can happen in
914 // unreachable code after constant propagation.
915 auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown());
916 if (!P.second)
917 return P.first->second;
918 ++InstructionsVisited;
919 if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions)
920 return ObjectSizeOffsetVisitor::unknown();
921 OffsetSpan Res = visit(*I);
922 // Cache the result for later visits. If we happened to visit this during
923 // the above recursion, we would consider it unknown until now.
924 SeenInsts[I] = Res;
925 return Res;
926 }
927 if (Argument *A = dyn_cast<Argument>(V))
928 return visitArgument(*A);
929 if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
931 if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
932 return visitGlobalAlias(*GA);
933 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
934 return visitGlobalVariable(*GV);
935 if (UndefValue *UV = dyn_cast<UndefValue>(V))
936 return visitUndefValue(*UV);
937
938 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
939 << *V << '\n');
940 return ObjectSizeOffsetVisitor::unknown();
941}
942
943bool ObjectSizeOffsetVisitor::checkedZextOrTrunc(APInt &I) {
944 return ::checkedZextOrTrunc(I, IntTyBits);
945}
946
948 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
949 if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
950 return ObjectSizeOffsetVisitor::unknown();
951 if (!isUIntN(IntTyBits, ElemSize.getKnownMinValue()))
952 return ObjectSizeOffsetVisitor::unknown();
953 APInt Size(IntTyBits, ElemSize.getKnownMinValue());
954
955 if (!I.isArrayAllocation())
956 return OffsetSpan(Zero, align(Size, I.getAlign()));
957
958 Value *ArraySize = I.getArraySize();
959 if (auto PossibleSize = aggregatePossibleConstantValues(
960 ArraySize, Options.EvalMode,
961 ArraySize->getType()->getScalarSizeInBits())) {
962 APInt NumElems = *PossibleSize;
963 if (!checkedZextOrTrunc(NumElems))
964 return ObjectSizeOffsetVisitor::unknown();
965
966 bool Overflow;
967 Size = Size.umul_ov(NumElems, Overflow);
968
969 return Overflow ? ObjectSizeOffsetVisitor::unknown()
970 : OffsetSpan(Zero, align(Size, I.getAlign()));
971 }
972 return ObjectSizeOffsetVisitor::unknown();
973}
974
976 Type *MemoryTy = A.getPointeeInMemoryValueType();
977 // No interprocedural analysis is done at the moment.
978 if (!MemoryTy || !MemoryTy->isSized()) {
979 ++ObjectVisitorArgument;
980 return ObjectSizeOffsetVisitor::unknown();
981 }
982
983 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
984 return OffsetSpan(Zero, align(Size, A.getParamAlign()));
985}
986
988 auto Mapper = [this](const Value *V) -> const Value * {
989 if (!V->getType()->isIntegerTy())
990 return V;
991
992 if (auto PossibleBound = aggregatePossibleConstantValues(
993 V, Options.EvalMode, V->getType()->getScalarSizeInBits()))
994 return ConstantInt::get(V->getType(), *PossibleBound);
995
996 return V;
997 };
998
999 if (std::optional<APInt> Size = getAllocSize(&CB, TLI, Mapper)) {
1000 // Very large unsigned value cannot be represented as OffsetSpan.
1001 if (Size->isNegative())
1002 return ObjectSizeOffsetVisitor::unknown();
1003 return OffsetSpan(Zero, *Size);
1004 }
1005 return ObjectSizeOffsetVisitor::unknown();
1006}
1007
1010 // If null is unknown, there's nothing we can do. Additionally, non-zero
1011 // address spaces can make use of null, so we don't presume to know anything
1012 // about that.
1013 //
1014 // TODO: How should this work with address space casts? We currently just drop
1015 // them on the floor, but it's unclear what we should do when a NULL from
1016 // addrspace(1) gets casted to addrspace(0) (or vice-versa).
1017 if (Options.NullIsUnknownSize || CPN.getPointerType()->getAddressSpace())
1018 return ObjectSizeOffsetVisitor::unknown();
1019 return OffsetSpan(Zero, Zero);
1020}
1021
1024 return ObjectSizeOffsetVisitor::unknown();
1025}
1026
1028 // Easy cases were already folded by previous passes.
1029 return ObjectSizeOffsetVisitor::unknown();
1030}
1031
1033 if (GA.isInterposable())
1034 return ObjectSizeOffsetVisitor::unknown();
1035 return computeImpl(GA.getAliasee());
1036}
1037
1039 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() ||
1040 ((!GV.hasInitializer() || GV.isInterposable()) &&
1041 Options.EvalMode != ObjectSizeOpts::Mode::Min))
1042 return ObjectSizeOffsetVisitor::unknown();
1043
1044 APInt Size(IntTyBits, GV.getGlobalSize(DL));
1045 return OffsetSpan(Zero, align(Size, GV.getAlign()));
1046}
1047
1049 // clueless
1050 return ObjectSizeOffsetVisitor::unknown();
1051}
1052
1053OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange(
1056 unsigned &ScannedInstCount) {
1057 constexpr unsigned MaxInstsToScan = 128;
1058
1059 auto Where = VisitedBlocks.find(&BB);
1060 if (Where != VisitedBlocks.end())
1061 return Where->second;
1062
1063 auto Unknown = [&BB, &VisitedBlocks]() {
1064 return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown();
1065 };
1066 auto Known = [&BB, &VisitedBlocks](OffsetSpan SO) {
1067 return VisitedBlocks[&BB] = SO;
1068 };
1069
1070 do {
1071 Instruction &I = *From;
1072
1073 if (I.isDebugOrPseudoInst())
1074 continue;
1075
1076 if (++ScannedInstCount > MaxInstsToScan)
1077 return Unknown();
1078
1079 if (!I.mayWriteToMemory())
1080 continue;
1081
1082 if (auto *SI = dyn_cast<StoreInst>(&I)) {
1083 AliasResult AR =
1084 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
1085 switch ((AliasResult::Kind)AR) {
1087 continue;
1089 if (SI->getValueOperand()->getType()->isPointerTy())
1090 return Known(computeImpl(SI->getValueOperand()));
1091 else
1092 return Unknown(); // No handling of non-pointer values by `compute`.
1093 default:
1094 return Unknown();
1095 }
1096 }
1097
1098 if (auto *CB = dyn_cast<CallBase>(&I)) {
1100 // Bail out on indirect call.
1101 if (!Callee)
1102 return Unknown();
1103
1104 if (!TLI)
1105 return Unknown();
1106
1107 LibFunc TLIFn = TLI->getLibFunc(*CB->getCalledFunction());
1108 if (!TLI->has(TLIFn))
1109 return Unknown();
1110
1111 // TODO: There's probably more interesting case to support here.
1112 if (TLIFn != LibFunc_posix_memalign)
1113 return Unknown();
1114
1115 AliasResult AR =
1116 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
1117 switch ((AliasResult::Kind)AR) {
1119 continue;
1121 break;
1122 default:
1123 return Unknown();
1124 }
1125
1126 // Is the error status of posix_memalign correctly checked? If not it
1127 // would be incorrect to assume it succeeds and load doesn't see the
1128 // previous value.
1129 std::optional<bool> Checked = isImpliedByDomCondition(
1130 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL);
1131 if (!Checked || !*Checked)
1132 return Unknown();
1133
1134 Value *Size = CB->getOperand(2);
1135 auto *C = dyn_cast<ConstantInt>(Size);
1136 if (!C)
1137 return Unknown();
1138
1139 APInt CSize = C->getValue();
1140 if (CSize.isNegative())
1141 return Unknown();
1142
1143 return Known({APInt(CSize.getBitWidth(), 0), CSize});
1144 }
1145
1146 return Unknown();
1147 } while (From-- != BB.begin());
1148
1149 SmallVector<OffsetSpan> PredecessorSizeOffsets;
1150 for (auto *PredBB : predecessors(&BB)) {
1151 PredecessorSizeOffsets.push_back(findLoadOffsetRange(
1152 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()),
1153 VisitedBlocks, ScannedInstCount));
1154 if (!PredecessorSizeOffsets.back().bothKnown())
1155 return Unknown();
1156 }
1157
1158 if (PredecessorSizeOffsets.empty())
1159 return Unknown();
1160
1161 return Known(std::accumulate(
1162 PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(),
1163 PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) {
1164 return combineOffsetRange(LHS, RHS);
1165 }));
1166}
1167
1169 if (!Options.AA) {
1170 ++ObjectVisitorLoad;
1171 return ObjectSizeOffsetVisitor::unknown();
1172 }
1173
1175 unsigned ScannedInstCount = 0;
1176 OffsetSpan SO =
1177 findLoadOffsetRange(LI, *LI.getParent(), BasicBlock::iterator(LI),
1178 VisitedBlocks, ScannedInstCount);
1179 if (!SO.bothKnown())
1180 ++ObjectVisitorLoad;
1181 return SO;
1182}
1183
1184OffsetSpan ObjectSizeOffsetVisitor::combineOffsetRange(OffsetSpan LHS,
1185 OffsetSpan RHS) {
1186 if (!LHS.bothKnown() || !RHS.bothKnown())
1187 return ObjectSizeOffsetVisitor::unknown();
1188
1189 switch (Options.EvalMode) {
1191 return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before,
1192 LHS.After.slt(RHS.After) ? LHS.After : RHS.After};
1194 return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before,
1195 LHS.After.sgt(RHS.After) ? LHS.After : RHS.After};
1196 }
1198 return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(),
1199 LHS.After.eq(RHS.After) ? LHS.After : APInt()};
1201 return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown();
1202 }
1203 llvm_unreachable("missing an eval mode");
1204}
1205
1207 if (PN.getNumIncomingValues() == 0)
1208 return ObjectSizeOffsetVisitor::unknown();
1209 auto IncomingValues = PN.incoming_values();
1210 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1211 computeImpl(*IncomingValues.begin()),
1212 [this](OffsetSpan LHS, Value *VRHS) {
1213 return combineOffsetRange(LHS, computeImpl(VRHS));
1214 });
1215}
1216
1218 return combineOffsetRange(computeImpl(I.getTrueValue()),
1219 computeImpl(I.getFalseValue()));
1220}
1221
1225
1227 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1228 << '\n');
1229 return ObjectSizeOffsetVisitor::unknown();
1230}
1231
1232// Just set these right here...
1235
1237 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
1238 ObjectSizeOpts EvalOpts)
1239 : DL(DL), TLI(TLI), Context(Context),
1240 Builder(Context, TargetFolder(DL),
1242 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1243 EvalOpts(EvalOpts) {
1244 // IntTy and Zero must be set for each compute() since the address space may
1245 // be different for later objects.
1246}
1247
1249 // XXX - Are vectors of pointers possible here?
1250 IntTy = cast<IntegerType>(DL.getIndexType(V->getType()));
1251 Zero = ConstantInt::get(IntTy, 0);
1252
1253 SizeOffsetValue Result = compute_(V);
1254
1255 if (!Result.bothKnown()) {
1256 // Erase everything that was computed in this iteration from the cache, so
1257 // that no dangling references are left behind. We could be a bit smarter if
1258 // we kept a dependency graph. It's probably not worth the complexity.
1259 for (const Value *SeenVal : SeenVals) {
1260 CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
1261 // non-computable results can be safely cached
1262 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown())
1263 CacheMap.erase(CacheIt);
1264 }
1265
1266 // Erase any instructions we inserted as part of the traversal.
1267 for (Instruction *I : InsertedInstructions) {
1268 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
1269 I->eraseFromParent();
1270 }
1271 }
1272
1273 SeenVals.clear();
1274 InsertedInstructions.clear();
1275 return Result;
1276}
1277
1278SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) {
1279
1280 // Only trust ObjectSizeOffsetVisitor in exact mode, otherwise fallback on
1281 // dynamic computation.
1282 ObjectSizeOpts VisitorEvalOpts(EvalOpts);
1283 VisitorEvalOpts.EvalMode = ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset;
1284 ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, VisitorEvalOpts);
1285
1286 SizeOffsetAPInt Const = Visitor.compute(V);
1287 if (Const.bothKnown())
1288 return SizeOffsetValue(ConstantInt::get(Context, Const.Size),
1289 ConstantInt::get(Context, Const.Offset));
1290
1291 V = V->stripPointerCasts();
1292
1293 // Check cache.
1294 CacheMapTy::iterator CacheIt = CacheMap.find(V);
1295 if (CacheIt != CacheMap.end())
1296 return CacheIt->second;
1297
1298 // Always generate code immediately before the instruction being
1299 // processed, so that the generated code dominates the same BBs.
1300 BuilderTy::InsertPointGuard Guard(Builder);
1302 Builder.SetInsertPoint(I);
1303
1304 // Now compute the size and offset.
1305 SizeOffsetValue Result;
1306
1307 // Record the pointers that were handled in this run, so that they can be
1308 // cleaned later if something fails. We also use this set to break cycles that
1309 // can occur in dead code.
1310 if (!SeenVals.insert(V).second) {
1312 } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
1313 Result = visitGEPOperator(*GEP);
1314 } else if (Instruction *I = dyn_cast<Instruction>(V)) {
1315 Result = visit(*I);
1316 } else if (isa<Argument>(V) ||
1317 (isa<ConstantExpr>(V) &&
1318 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
1320 // Ignore values where we cannot do more than ObjectSizeVisitor.
1322 } else {
1323 LLVM_DEBUG(
1324 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1325 << '\n');
1327 }
1328
1329 // Don't reuse CacheIt since it may be invalid at this point.
1330 CacheMap[V] = SizeOffsetWeakTrackingVH(Result);
1331 return Result;
1332}
1333
1335 if (!I.getAllocatedType()->isSized())
1337
1338 // must be a VLA or vscale.
1339 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
1340
1341 // If needed, adjust the alloca's operand size to match the pointer indexing
1342 // size. Subsequent math operations expect the types to match.
1343 Type *IndexTy = DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace());
1344 assert(IndexTy == Zero->getType() &&
1345 "Expected zero constant to have pointer index type");
1346
1347 Value *Size = Builder.CreateAllocationSize(IndexTy, &I);
1348 return SizeOffsetValue(Size, Zero);
1349}
1350
1352 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI);
1353 if (!FnData)
1355
1356 // Handle strdup-like functions separately.
1357 if (FnData->AllocTy == StrDupLike) {
1358 // TODO: implement evaluation of strdup/strndup
1360 }
1361
1362 Value *FirstArg = CB.getArgOperand(FnData->FstParam);
1363 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1364 if (FnData->SndParam < 0)
1365 return SizeOffsetValue(FirstArg, Zero);
1366
1367 Value *SecondArg = CB.getArgOperand(FnData->SndParam);
1368 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1369 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1370 return SizeOffsetValue(Size, Zero);
1371}
1372
1377
1382
1384 SizeOffsetValue PtrData = compute_(GEP.getPointerOperand());
1385 if (!PtrData.bothKnown())
1387
1388 Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1389 Offset = Builder.CreateAdd(PtrData.Offset, Offset);
1390 return SizeOffsetValue(PtrData.Size, Offset);
1391}
1392
1397
1401
1403 // Create 2 PHIs: one for size and another for offset.
1404 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1405 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1406
1407 // Insert right away in the cache to handle recursive PHIs.
1408 CacheMap[&PHI] = SizeOffsetWeakTrackingVH(SizePHI, OffsetPHI);
1409
1410 // Compute offset/size for each PHI incoming pointer.
1411 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1412 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1413 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1414 SizeOffsetValue EdgeData = compute_(PHI.getIncomingValue(i));
1415
1416 if (!EdgeData.bothKnown()) {
1417 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1418 OffsetPHI->eraseFromParent();
1419 InsertedInstructions.erase(OffsetPHI);
1420 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1421 SizePHI->eraseFromParent();
1422 InsertedInstructions.erase(SizePHI);
1424 }
1425 SizePHI->addIncoming(EdgeData.Size, IncomingBlock);
1426 OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock);
1427 }
1428
1429 Value *Size = SizePHI, *Offset = OffsetPHI;
1430 if (Value *Tmp = SizePHI->hasConstantValue()) {
1431 Size = Tmp;
1432 SizePHI->replaceAllUsesWith(Size);
1433 SizePHI->eraseFromParent();
1434 InsertedInstructions.erase(SizePHI);
1435 }
1436 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
1437 Offset = Tmp;
1438 OffsetPHI->replaceAllUsesWith(Offset);
1439 OffsetPHI->eraseFromParent();
1440 InsertedInstructions.erase(OffsetPHI);
1441 }
1442 return SizeOffsetValue(Size, Offset);
1443}
1444
1446 SizeOffsetValue TrueSide = compute_(I.getTrueValue());
1447 SizeOffsetValue FalseSide = compute_(I.getFalseValue());
1448
1449 if (!TrueSide.bothKnown() || !FalseSide.bothKnown())
1451 if (TrueSide == FalseSide)
1452 return TrueSide;
1453
1454 Value *Size =
1455 Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size);
1456 Value *Offset =
1457 Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset);
1458 return SizeOffsetValue(Size, Offset);
1459}
1460
1462 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1463 << '\n');
1465}
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 std::optional< FreeFnsTy > getFreeFunctionDataForFunction(const Function *Callee, const LibFunc TLIFn)
static AllocFnKind getAllocFnKind(const Value *V)
static std::optional< APInt > aggregatePossibleConstantValuesImpl(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth, unsigned RecursionDepth)
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< 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)
static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted)
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
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 StringRef mangledNameForMallocFamily(const MallocFamily &Family)
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:119
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:1050
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:326
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1958
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:197
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1971
@ 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:105
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:261
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:446
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:716
PointerType * getPointerType() const
Return the scalar pointer type for this null value.
Definition Constants.h:736
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:64
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:133
iterator end()
Definition DenseMap.h:141
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:353
const Constant * getAliasee() const
Definition GlobalAlias.h:87
bool hasExternalWeakLinkage() const
Type * getValueType() const
LLVM_ABI bool isInterposable(bool CheckNoIPA=true) const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition Globals.cpp:178
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
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:2893
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)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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.
LibFunc getLibFunc(StringRef funcName) 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:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
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:326
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
'undef' values are things that do not have specified contents.
Definition Constants.h:1631
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:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
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
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
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,...
@ Known
Known to have no common set bits.
@ Unknown
Not known to have no common set bits.
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:53
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.
@ Load
The value being inserted comes from a load (InsertElement only).
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:244
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
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....
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
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:1772
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...
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.