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 (either malloc, calloc, or strdup like).
299bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
300 return getAllocationData(V, AllocLike, TLI).has_value() ||
302}
303
304/// Tests if a functions is a call or invoke to a library function that
305/// reallocates memory (e.g., realloc).
309
312 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
313 return nullptr;
314}
315
317 // Note: Removability is highly dependent on the source language. For
318 // example, recent C++ requires direct calls to the global allocation
319 // [basic.stc.dynamic.allocation] to be observable unless part of a new
320 // expression [expr.new paragraph 13].
321
322 // Historically we've treated the C family allocation routines and operator
323 // new as removable
324 return isAllocLikeFn(CB, TLI);
325}
326
328 const TargetLibraryInfo *TLI) {
329 const std::optional<AllocFnsTy> FnData = getAllocationData(V, AnyAlloc, TLI);
330 if (FnData && FnData->AlignParam >= 0) {
331 return V->getOperand(FnData->AlignParam);
332 }
333 return V->getArgOperandWithAttribute(Attribute::AllocAlign);
334}
335
336/// When we're compiling N-bit code, and the user uses parameters that are
337/// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
338/// trouble with APInt size issues. This function handles resizing + overflow
339/// checks for us. Check and zext or trunc \p I depending on IntTyBits and
340/// I's value.
341static bool checkedZextOrTrunc(APInt &I, unsigned IntTyBits) {
342 // More bits than we can handle. Checking the bit width isn't necessary, but
343 // it's faster than checking active bits, and should give `false` in the
344 // vast majority of cases.
345 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
346 return false;
347 if (I.getBitWidth() != IntTyBits)
348 I = I.zextOrTrunc(IntTyBits);
349 return true;
350}
351
352std::optional<APInt>
354 function_ref<const Value *(const Value *)> Mapper) {
355 // Note: This handles both explicitly listed allocation functions and
356 // allocsize. The code structure could stand to be cleaned up a bit.
357 std::optional<AllocFnsTy> FnData = getAllocationSize(CB, TLI);
358 if (!FnData)
359 return std::nullopt;
360
361 // Get the index type for this address space, results and intermediate
362 // computations are performed at that width.
363 auto &DL = CB->getDataLayout();
364 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType());
365
366 // Handle strdup-like functions separately.
367 if (FnData->AllocTy == StrDupLike) {
368 APInt Size(IntTyBits, GetStringLength(Mapper(CB->getArgOperand(0))));
369 if (!Size)
370 return std::nullopt;
371
372 // Strndup limits strlen.
373 if (FnData->FstParam > 0) {
374 const ConstantInt *Arg =
375 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
376 if (!Arg)
377 return std::nullopt;
378
379 APInt MaxSize = Arg->getValue().zext(IntTyBits);
380 if (Size.ugt(MaxSize))
381 Size = MaxSize + 1;
382 }
383 return Size;
384 }
385
386 const ConstantInt *Arg =
387 dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->FstParam)));
388 if (!Arg)
389 return std::nullopt;
390
391 APInt Size = Arg->getValue();
392 if (!checkedZextOrTrunc(Size, IntTyBits))
393 return std::nullopt;
394
395 // Size is determined by just 1 parameter.
396 if (FnData->SndParam < 0)
397 return Size;
398
399 Arg = dyn_cast<ConstantInt>(Mapper(CB->getArgOperand(FnData->SndParam)));
400 if (!Arg)
401 return std::nullopt;
402
403 APInt NumElems = Arg->getValue();
404 if (!checkedZextOrTrunc(NumElems, IntTyBits))
405 return std::nullopt;
406
407 bool Overflow;
408 Size = Size.umul_ov(NumElems, Overflow);
409 if (Overflow)
410 return std::nullopt;
411 return Size;
412}
413
415 const TargetLibraryInfo *TLI,
416 Type *Ty) {
417 if (isa<AllocaInst>(V))
418 return UndefValue::get(Ty);
419
420 auto *Alloc = dyn_cast<CallBase>(V);
421 if (!Alloc)
422 return nullptr;
423
424 // malloc are uninitialized (undef)
425 if (getAllocationData(Alloc, MallocOrOpNewLike, TLI).has_value())
426 return UndefValue::get(Ty);
427
430 return UndefValue::get(Ty);
432 return Constant::getNullValue(Ty);
433
434 return nullptr;
435}
436
437struct FreeFnsTy {
438 unsigned NumParams;
439 // Name of default allocator function to group malloc/free calls by family
441};
442
443// clang-format off
444static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
445 {LibFunc_ZdlPv, {1, MallocFamily::CPPNew}}, // operator delete(void*)
446 {LibFunc_ZdaPv, {1, MallocFamily::CPPNewArray}}, // operator delete[](void*)
447 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
448 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}}, // operator delete(void*)
449 {LibFunc_msvc_delete_array_ptr32, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
450 {LibFunc_msvc_delete_array_ptr64, {1, MallocFamily::MSVCArrayNew}}, // operator delete[](void*)
451 {LibFunc_ZdlPvj, {2, MallocFamily::CPPNew}}, // delete(void*, uint)
452 {LibFunc_ZdlPvm, {2, MallocFamily::CPPNew}}, // delete(void*, ulong)
453 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}}, // delete(void*, nothrow)
454 {LibFunc_ZdlPvSt11align_val_t, {2, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t)
455 {LibFunc_ZdaPvj, {2, MallocFamily::CPPNewArray}}, // delete[](void*, uint)
456 {LibFunc_ZdaPvm, {2, MallocFamily::CPPNewArray}}, // delete[](void*, ulong)
457 {LibFunc_ZdaPvRKSt9nothrow_t, {2, MallocFamily::CPPNewArray}}, // delete[](void*, nothrow)
458 {LibFunc_ZdaPvSt11align_val_t, {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
459 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}}, // delete(void*, uint)
460 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}}, // delete(void*, ulonglong)
461 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
462 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}}, // delete(void*, nothrow)
463 {LibFunc_msvc_delete_array_ptr32_int, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, uint)
464 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, ulonglong)
465 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
466 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}}, // delete[](void*, nothrow)
467 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, align_val_t, nothrow)
468 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
469 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned int, align_val_t)
470 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}}, // delete(void*, unsigned long, align_val_t)
471 {LibFunc_ZdaPvjSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
472 {LibFunc_ZdaPvmSt11align_val_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
473};
474// clang-format on
475
476static std::optional<FreeFnsTy>
477getFreeFunctionDataForFunction(const Function *Callee, const LibFunc TLIFn) {
478 const auto *Iter =
479 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
480 return P.first == TLIFn;
481 });
482 if (Iter == std::end(FreeFnData))
483 return std::nullopt;
484 return Iter->second;
485}
486
487std::optional<StringRef>
489 if (const Function *Callee = getCalledFunction(I)) {
490 LibFunc TLIFn = TLI ? TLI->getLibFunc(*Callee) : NotLibFunc;
491 if (TLIFn != NotLibFunc && TLI->has(TLIFn)) {
492 // Callee is some known library function.
493 const auto AllocData =
495 if (AllocData)
496 return mangledNameForMallocFamily(AllocData->Family);
497 const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
498 if (FreeData)
499 return mangledNameForMallocFamily(FreeData->Family);
500 }
501 }
502
503 // Callee isn't a known library function, still check attributes.
506 Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
507 if (Attr.isValid())
508 return Attr.getValueAsString();
509 }
510 return std::nullopt;
511}
512
513/// isLibFreeFunction - Returns true if the function is a builtin free()
514bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
515 std::optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
516 if (!FnData)
518
519 // Check free prototype.
520 // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
521 // attribute will exist.
522 FunctionType *FTy = F->getFunctionType();
523 if (!FTy->getReturnType()->isVoidTy())
524 return false;
525 if (FTy->getNumParams() != FnData->NumParams)
526 return false;
527 if (!FTy->getParamType(0)->isPointerTy())
528 return false;
529
530 return true;
531}
532
534 if (const Function *Callee = getCalledFunction(CB)) {
535 LibFunc TLIFn = TLI ? TLI->getLibFunc(*Callee) : NotLibFunc;
536 if (TLIFn != NotLibFunc && TLI->has(TLIFn) &&
537 isLibFreeFunction(Callee, TLIFn)) {
538 // All currently supported free functions free the first argument.
539 return CB->getArgOperand(0);
540 }
541 }
542
544 return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
545
546 return nullptr;
547}
548
549//===----------------------------------------------------------------------===//
550// Utility functions to compute size of objects.
551//
553 APInt Size = Data.Size;
554 APInt Offset = Data.Offset;
555
556 if (Offset.isNegative() || Size.ult(Offset))
557 return APInt::getZero(Size.getBitWidth());
558
559 return Size - Offset;
560}
561
562/// Compute the size of the object pointed by Ptr. Returns true and the
563/// object size in Size if successful, and false otherwise.
564/// If RoundToAlign is true, then Size is rounded up to the alignment of
565/// allocas, byval arguments, and global variables.
566bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
567 const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) {
568 ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts);
569 SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr));
570 if (!Data.bothKnown())
571 return false;
572
574 return true;
575}
576
577std::optional<TypeSize> llvm::getBaseObjectSize(const Value *Ptr,
578 const DataLayout &DL,
579 const TargetLibraryInfo *TLI,
580 ObjectSizeOpts Opts) {
582 "Other modes are currently not supported");
583
584 auto Align = [&](TypeSize Size, MaybeAlign Alignment) {
585 if (Opts.RoundToAlign && Alignment && !Size.isScalable())
586 return TypeSize::getFixed(alignTo(Size.getFixedValue(), *Alignment));
587 return Size;
588 };
589
590 if (isa<UndefValue>(Ptr))
591 return TypeSize::getZero();
592
593 if (isa<ConstantPointerNull>(Ptr)) {
595 return std::nullopt;
596 return TypeSize::getZero();
597 }
598
599 if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
600 if (!GV->getValueType()->isSized() || GV->hasExternalWeakLinkage() ||
601 !GV->hasInitializer() || GV->isInterposable())
602 return std::nullopt;
603 return Align(TypeSize::getFixed(GV->getGlobalSize(DL)), GV->getAlign());
604 }
605
606 if (auto *A = dyn_cast<Argument>(Ptr)) {
607 Type *MemoryTy = A->getPointeeInMemoryValueType();
608 if (!MemoryTy || !MemoryTy->isSized())
609 return std::nullopt;
610 return Align(DL.getTypeAllocSize(MemoryTy), A->getParamAlign());
611 }
612
613 if (auto *AI = dyn_cast<AllocaInst>(Ptr)) {
614 if (std::optional<TypeSize> Size = AI->getAllocationSize(DL))
615 return Align(*Size, AI->getAlign());
616 return std::nullopt;
617 }
618
619 if (auto *CB = dyn_cast<CallBase>(Ptr)) {
620 if (std::optional<APInt> Size = getAllocSize(CB, TLI)) {
621 if (std::optional<uint64_t> ZExtSize = Size->tryZExtValue())
622 return TypeSize::getFixed(*ZExtSize);
623 }
624 return std::nullopt;
625 }
626
627 return std::nullopt;
628}
629
631 const DataLayout &DL,
632 const TargetLibraryInfo *TLI,
633 bool MustSucceed) {
634 return lowerObjectSizeCall(ObjectSize, DL, TLI, /*AAResults=*/nullptr,
635 MustSucceed);
636}
637
639 IntrinsicInst *ObjectSize, const DataLayout &DL,
640 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
641 SmallVectorImpl<Instruction *> *InsertedInstructions) {
642 assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
643 "ObjectSize must be a call to llvm.objectsize!");
644
645 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
646 ObjectSizeOpts EvalOptions;
647 EvalOptions.AA = AA;
648
649 // Unless we have to fold this to something, try to be as accurate as
650 // possible.
651 if (MustSucceed)
652 EvalOptions.EvalMode =
654 else
656
657 EvalOptions.NullIsUnknownSize =
658 cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
659
660 auto *ResultType = cast<IntegerType>(ObjectSize->getType());
661 bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
662 if (StaticOnly) {
663 // FIXME: Does it make sense to just return a failure value if the size
664 // won't fit in the output and `!MustSucceed`?
665 uint64_t Size;
666 if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI,
667 EvalOptions) &&
668 isUIntN(ResultType->getBitWidth(), Size))
669 return ConstantInt::get(ResultType, Size);
670 } else {
671 LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
672 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
673 SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0));
674
675 if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
678 if (InsertedInstructions)
679 InsertedInstructions->push_back(I);
680 }));
681 Builder.SetInsertPoint(ObjectSize);
682
683 Value *Size = SizeOffsetPair.Size;
684 Value *Offset = SizeOffsetPair.Offset;
685
686 // If we've outside the end of the object, then we can always access
687 // exactly 0 bytes.
688 Value *ResultSize = Builder.CreateSub(Size, Offset);
689 Value *UseZero = Builder.CreateICmpULT(Size, Offset);
690 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
691 Value *Ret = Builder.CreateSelect(
692 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
693
694 // The non-constant size expression cannot evaluate to -1.
696 Builder.CreateAssumption(Builder.CreateICmpNE(
697 Ret, ConstantInt::getAllOnesValue(ResultType)));
698
699 return Ret;
700 }
701 }
702
703 if (!MustSucceed)
704 return nullptr;
705
706 return MaxVal ? Constant::getAllOnesValue(ResultType)
707 : Constant::getNullValue(ResultType);
708}
709
710STATISTIC(ObjectVisitorArgument,
711 "Number of arguments with unsolved size and offset");
712STATISTIC(ObjectVisitorLoad,
713 "Number of load instructions with unsolved size and offset");
714
715static std::optional<APInt>
717 std::optional<APInt> RHS,
718 ObjectSizeOpts::Mode EvalMode) {
719 if (!LHS || !RHS)
720 return std::nullopt;
721 if (EvalMode == ObjectSizeOpts::Mode::Max)
722 return LHS->sge(*RHS) ? *LHS : *RHS;
723 return LHS->sle(*RHS) ? *LHS : *RHS;
724}
725
726static std::optional<APInt> aggregatePossibleConstantValuesImpl(
727 const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth,
728 unsigned RecursionDepth) {
729 constexpr unsigned MaxRecursionDepth = 4;
730 if (RecursionDepth == MaxRecursionDepth)
731 return std::nullopt;
732
733 if (const auto *CI = dyn_cast<ConstantInt>(V)) {
734 return CI->getValue().sextOrTrunc(BitWidth);
735 } else if (const auto *SI = dyn_cast<SelectInst>(V)) {
737 aggregatePossibleConstantValuesImpl(SI->getTrueValue(), EvalMode,
738 BitWidth, RecursionDepth + 1),
739 aggregatePossibleConstantValuesImpl(SI->getFalseValue(), EvalMode,
740 BitWidth, RecursionDepth + 1),
741 EvalMode);
742 } else if (const auto *PN = dyn_cast<PHINode>(V)) {
743 unsigned Count = PN->getNumIncomingValues();
744 if (Count == 0)
745 return std::nullopt;
747 PN->getIncomingValue(0), EvalMode, BitWidth, RecursionDepth + 1);
748 for (unsigned I = 1; Acc && I < Count; ++I) {
750 PN->getIncomingValue(I), EvalMode, BitWidth, RecursionDepth + 1);
751 Acc = combinePossibleConstantValues(Acc, Tmp, EvalMode);
752 }
753 return Acc;
754 }
755
756 return std::nullopt;
757}
758
759static std::optional<APInt>
761 unsigned BitWidth) {
762 if (auto *CI = dyn_cast<ConstantInt>(V))
763 return CI->getValue().sextOrTrunc(BitWidth);
764
765 if (EvalMode != ObjectSizeOpts::Mode::Min &&
766 EvalMode != ObjectSizeOpts::Mode::Max)
767 return std::nullopt;
768
769 // Not using computeConstantRange here because we cannot guarantee it's not
770 // doing optimization based on UB which we want to avoid when expanding
771 // __builtin_object_size.
772 return aggregatePossibleConstantValuesImpl(V, EvalMode, BitWidth, 0u);
773}
774
775/// Align \p Size according to \p Alignment. If \p Size is greater than
776/// getSignedMaxValue(), set it as unknown as we can only represent signed value
777/// in OffsetSpan.
778APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) {
779 if (Options.RoundToAlign && Alignment)
780 Size = APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
781
782 return Size.isNegative() ? APInt() : Size;
783}
784
786 const TargetLibraryInfo *TLI,
787 LLVMContext &Context,
788 ObjectSizeOpts Options)
789 : DL(DL), TLI(TLI), Options(Options) {
790 // Pointer size must be rechecked for each object visited since it could have
791 // a different address space.
792}
793
795 InstructionsVisited = 0;
796 OffsetSpan Span = computeImpl(V);
797
798 // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow
799 // us to overwrite it if needs be.
800 if (Span.knownAfter() && !Span.knownBefore() &&
802 Span.Before = APInt::getZero(Span.After.getBitWidth());
803
804 if (!Span.bothKnown())
805 return {};
806
807 return {Span.Before + Span.After, Span.Before};
808}
809
810OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
811 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
812
813 // Stripping pointer casts can strip address space casts which can change the
814 // index type size. The invariant is that we use the value type to determine
815 // the index type size and if we stripped address space casts we have to
816 // readjust the APInt as we pass it upwards in order for the APInt to match
817 // the type the caller passed in.
818 APInt Offset(InitialIntTyBits, 0);
819 V = V->stripAndAccumulateConstantOffsets(
820 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
821
822 // Give it another try with approximated analysis. We don't start with this
823 // one because stripAndAccumulateConstantOffsets behaves differently wrt.
824 // overflows if we provide an external Analysis.
825 if ((Options.EvalMode == ObjectSizeOpts::Mode::Min ||
826 Options.EvalMode == ObjectSizeOpts::Mode::Max) &&
827 isa<GEPOperator>(V)) {
828 // External Analysis used to compute the Min/Max value of individual Offsets
829 // within a GEP.
830 ObjectSizeOpts::Mode EvalMode =
834 // For a GEPOperator the indices are first converted to offsets in the
835 // pointer’s index type, so we need to provide the index type to make sure
836 // the min/max operations are performed in correct type.
837 unsigned IdxTyBits = DL.getIndexTypeSizeInBits(V->getType());
838 auto OffsetRangeAnalysis = [EvalMode, IdxTyBits](Value &VOffset,
839 APInt &Offset) {
840 if (auto PossibleOffset =
841 aggregatePossibleConstantValues(&VOffset, EvalMode, IdxTyBits)) {
842 Offset = *PossibleOffset;
843 return true;
844 }
845 return false;
846 };
847
848 V = V->stripAndAccumulateConstantOffsets(
849 DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true,
850 /*ExternalAnalysis=*/OffsetRangeAnalysis);
851 }
852
853 // Later we use the index type size and zero but it will match the type of the
854 // value that is passed to computeImpl.
855 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
856 Zero = APInt::getZero(IntTyBits);
857 OffsetSpan ORT = computeValue(V);
858
859 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
860 if (!IndexTypeSizeChanged && Offset.isZero())
861 return ORT;
862
863 // We stripped an address space cast that changed the index type size or we
864 // accumulated some constant offset (or both). Readjust the bit width to match
865 // the argument index type size and apply the offset, as required.
866 if (IndexTypeSizeChanged) {
867 if (ORT.knownBefore() &&
868 !::checkedZextOrTrunc(ORT.Before, InitialIntTyBits))
869 ORT.Before = APInt();
870 if (ORT.knownAfter() && !::checkedZextOrTrunc(ORT.After, InitialIntTyBits))
871 ORT.After = APInt();
872 }
873 // If the computed bound is "unknown" we cannot add the stripped offset.
874 if (ORT.knownBefore()) {
875 bool Overflow;
876 ORT.Before = ORT.Before.sadd_ov(Offset, Overflow);
877 if (Overflow)
878 ORT.Before = APInt();
879 }
880 if (ORT.knownAfter()) {
881 bool Overflow;
882 ORT.After = ORT.After.ssub_ov(Offset, Overflow);
883 if (Overflow)
884 ORT.After = APInt();
885 }
886
887 // We end up pointing on a location that's outside of the original object.
888 if (ORT.knownBefore() && ORT.Before.isNegative()) {
889 // This means that we *may* be accessing memory before the allocation.
890 // Conservatively return an unknown size.
891 //
892 // TODO: working with ranges instead of value would make it possible to take
893 // a better decision.
894 if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
895 Options.EvalMode == ObjectSizeOpts::Mode::Max) {
896 return ObjectSizeOffsetVisitor::unknown();
897 }
898 // Otherwise it's fine, caller can handle negative offset.
899 }
900 return ORT;
901}
902
903OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) {
904 if (Instruction *I = dyn_cast<Instruction>(V)) {
905 // If we have already seen this instruction, bail out. Cycles can happen in
906 // unreachable code after constant propagation.
907 auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown());
908 if (!P.second)
909 return P.first->second;
910 ++InstructionsVisited;
911 if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions)
912 return ObjectSizeOffsetVisitor::unknown();
913 OffsetSpan Res = visit(*I);
914 // Cache the result for later visits. If we happened to visit this during
915 // the above recursion, we would consider it unknown until now.
916 SeenInsts[I] = Res;
917 return Res;
918 }
919 if (Argument *A = dyn_cast<Argument>(V))
920 return visitArgument(*A);
921 if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
923 if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
924 return visitGlobalAlias(*GA);
925 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
926 return visitGlobalVariable(*GV);
927 if (UndefValue *UV = dyn_cast<UndefValue>(V))
928 return visitUndefValue(*UV);
929
930 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
931 << *V << '\n');
932 return ObjectSizeOffsetVisitor::unknown();
933}
934
935bool ObjectSizeOffsetVisitor::checkedZextOrTrunc(APInt &I) {
936 return ::checkedZextOrTrunc(I, IntTyBits);
937}
938
940 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
941 if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
942 return ObjectSizeOffsetVisitor::unknown();
943 if (!isUIntN(IntTyBits, ElemSize.getKnownMinValue()))
944 return ObjectSizeOffsetVisitor::unknown();
945 APInt Size(IntTyBits, ElemSize.getKnownMinValue());
946
947 if (!I.isArrayAllocation())
948 return OffsetSpan(Zero, align(Size, I.getAlign()));
949
950 Value *ArraySize = I.getArraySize();
951 if (auto PossibleSize = aggregatePossibleConstantValues(
952 ArraySize, Options.EvalMode,
953 ArraySize->getType()->getScalarSizeInBits())) {
954 APInt NumElems = *PossibleSize;
955 if (!checkedZextOrTrunc(NumElems))
956 return ObjectSizeOffsetVisitor::unknown();
957
958 bool Overflow;
959 Size = Size.umul_ov(NumElems, Overflow);
960
961 return Overflow ? ObjectSizeOffsetVisitor::unknown()
962 : OffsetSpan(Zero, align(Size, I.getAlign()));
963 }
964 return ObjectSizeOffsetVisitor::unknown();
965}
966
968 Type *MemoryTy = A.getPointeeInMemoryValueType();
969 // No interprocedural analysis is done at the moment.
970 if (!MemoryTy || !MemoryTy->isSized()) {
971 ++ObjectVisitorArgument;
972 return ObjectSizeOffsetVisitor::unknown();
973 }
974
975 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
976 return OffsetSpan(Zero, align(Size, A.getParamAlign()));
977}
978
980 auto Mapper = [this](const Value *V) -> const Value * {
981 if (!V->getType()->isIntegerTy())
982 return V;
983
984 if (auto PossibleBound = aggregatePossibleConstantValues(
985 V, Options.EvalMode, V->getType()->getScalarSizeInBits()))
986 return ConstantInt::get(V->getType(), *PossibleBound);
987
988 return V;
989 };
990
991 if (std::optional<APInt> Size = getAllocSize(&CB, TLI, Mapper)) {
992 // Very large unsigned value cannot be represented as OffsetSpan.
993 if (Size->isNegative())
994 return ObjectSizeOffsetVisitor::unknown();
995 return OffsetSpan(Zero, *Size);
996 }
997 return ObjectSizeOffsetVisitor::unknown();
998}
999
1002 // If null is unknown, there's nothing we can do. Additionally, non-zero
1003 // address spaces can make use of null, so we don't presume to know anything
1004 // about that.
1005 //
1006 // TODO: How should this work with address space casts? We currently just drop
1007 // them on the floor, but it's unclear what we should do when a NULL from
1008 // addrspace(1) gets casted to addrspace(0) (or vice-versa).
1009 if (Options.NullIsUnknownSize || CPN.getPointerType()->getAddressSpace())
1010 return ObjectSizeOffsetVisitor::unknown();
1011 return OffsetSpan(Zero, Zero);
1012}
1013
1016 return ObjectSizeOffsetVisitor::unknown();
1017}
1018
1020 // Easy cases were already folded by previous passes.
1021 return ObjectSizeOffsetVisitor::unknown();
1022}
1023
1025 if (GA.isInterposable())
1026 return ObjectSizeOffsetVisitor::unknown();
1027 return computeImpl(GA.getAliasee());
1028}
1029
1031 if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() ||
1032 ((!GV.hasInitializer() || GV.isInterposable()) &&
1033 Options.EvalMode != ObjectSizeOpts::Mode::Min))
1034 return ObjectSizeOffsetVisitor::unknown();
1035
1036 APInt Size(IntTyBits, GV.getGlobalSize(DL));
1037 return OffsetSpan(Zero, align(Size, GV.getAlign()));
1038}
1039
1041 // clueless
1042 return ObjectSizeOffsetVisitor::unknown();
1043}
1044
1045OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange(
1048 unsigned &ScannedInstCount) {
1049 constexpr unsigned MaxInstsToScan = 128;
1050
1051 auto Where = VisitedBlocks.find(&BB);
1052 if (Where != VisitedBlocks.end())
1053 return Where->second;
1054
1055 auto Unknown = [&BB, &VisitedBlocks]() {
1056 return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown();
1057 };
1058 auto Known = [&BB, &VisitedBlocks](OffsetSpan SO) {
1059 return VisitedBlocks[&BB] = SO;
1060 };
1061
1062 do {
1063 Instruction &I = *From;
1064
1065 if (I.isDebugOrPseudoInst())
1066 continue;
1067
1068 if (++ScannedInstCount > MaxInstsToScan)
1069 return Unknown();
1070
1071 if (!I.mayWriteToMemory())
1072 continue;
1073
1074 if (auto *SI = dyn_cast<StoreInst>(&I)) {
1075 AliasResult AR =
1076 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
1077 switch ((AliasResult::Kind)AR) {
1079 continue;
1081 if (SI->getValueOperand()->getType()->isPointerTy())
1082 return Known(computeImpl(SI->getValueOperand()));
1083 else
1084 return Unknown(); // No handling of non-pointer values by `compute`.
1085 default:
1086 return Unknown();
1087 }
1088 }
1089
1090 if (auto *CB = dyn_cast<CallBase>(&I)) {
1092 // Bail out on indirect call.
1093 if (!Callee)
1094 return Unknown();
1095
1096 if (!TLI)
1097 return Unknown();
1098
1099 LibFunc TLIFn = TLI->getLibFunc(*CB->getCalledFunction());
1100 if (!TLI->has(TLIFn))
1101 return Unknown();
1102
1103 // TODO: There's probably more interesting case to support here.
1104 if (TLIFn != LibFunc_posix_memalign)
1105 return Unknown();
1106
1107 AliasResult AR =
1108 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
1109 switch ((AliasResult::Kind)AR) {
1111 continue;
1113 break;
1114 default:
1115 return Unknown();
1116 }
1117
1118 // Is the error status of posix_memalign correctly checked? If not it
1119 // would be incorrect to assume it succeeds and load doesn't see the
1120 // previous value.
1121 std::optional<bool> Checked = isImpliedByDomCondition(
1122 ICmpInst::ICMP_EQ, CB, ConstantInt::get(CB->getType(), 0), &Load, DL);
1123 if (!Checked || !*Checked)
1124 return Unknown();
1125
1126 Value *Size = CB->getOperand(2);
1127 auto *C = dyn_cast<ConstantInt>(Size);
1128 if (!C)
1129 return Unknown();
1130
1131 APInt CSize = C->getValue();
1132 if (CSize.isNegative())
1133 return Unknown();
1134
1135 return Known({APInt(CSize.getBitWidth(), 0), CSize});
1136 }
1137
1138 return Unknown();
1139 } while (From-- != BB.begin());
1140
1141 SmallVector<OffsetSpan> PredecessorSizeOffsets;
1142 for (auto *PredBB : predecessors(&BB)) {
1143 PredecessorSizeOffsets.push_back(findLoadOffsetRange(
1144 Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()),
1145 VisitedBlocks, ScannedInstCount));
1146 if (!PredecessorSizeOffsets.back().bothKnown())
1147 return Unknown();
1148 }
1149
1150 if (PredecessorSizeOffsets.empty())
1151 return Unknown();
1152
1153 return Known(std::accumulate(
1154 PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(),
1155 PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) {
1156 return combineOffsetRange(LHS, RHS);
1157 }));
1158}
1159
1161 if (!Options.AA) {
1162 ++ObjectVisitorLoad;
1163 return ObjectSizeOffsetVisitor::unknown();
1164 }
1165
1167 unsigned ScannedInstCount = 0;
1168 OffsetSpan SO =
1169 findLoadOffsetRange(LI, *LI.getParent(), BasicBlock::iterator(LI),
1170 VisitedBlocks, ScannedInstCount);
1171 if (!SO.bothKnown())
1172 ++ObjectVisitorLoad;
1173 return SO;
1174}
1175
1176OffsetSpan ObjectSizeOffsetVisitor::combineOffsetRange(OffsetSpan LHS,
1177 OffsetSpan RHS) {
1178 if (!LHS.bothKnown() || !RHS.bothKnown())
1179 return ObjectSizeOffsetVisitor::unknown();
1180
1181 switch (Options.EvalMode) {
1183 return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before,
1184 LHS.After.slt(RHS.After) ? LHS.After : RHS.After};
1186 return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before,
1187 LHS.After.sgt(RHS.After) ? LHS.After : RHS.After};
1188 }
1190 return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(),
1191 LHS.After.eq(RHS.After) ? LHS.After : APInt()};
1193 return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown();
1194 }
1195 llvm_unreachable("missing an eval mode");
1196}
1197
1199 if (PN.getNumIncomingValues() == 0)
1200 return ObjectSizeOffsetVisitor::unknown();
1201 auto IncomingValues = PN.incoming_values();
1202 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1203 computeImpl(*IncomingValues.begin()),
1204 [this](OffsetSpan LHS, Value *VRHS) {
1205 return combineOffsetRange(LHS, computeImpl(VRHS));
1206 });
1207}
1208
1210 return combineOffsetRange(computeImpl(I.getTrueValue()),
1211 computeImpl(I.getFalseValue()));
1212}
1213
1217
1219 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1220 << '\n');
1221 return ObjectSizeOffsetVisitor::unknown();
1222}
1223
1224// Just set these right here...
1227
1229 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
1230 ObjectSizeOpts EvalOpts)
1231 : DL(DL), TLI(TLI), Context(Context),
1232 Builder(Context, TargetFolder(DL),
1234 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1235 EvalOpts(EvalOpts) {
1236 // IntTy and Zero must be set for each compute() since the address space may
1237 // be different for later objects.
1238}
1239
1241 // XXX - Are vectors of pointers possible here?
1242 IntTy = cast<IntegerType>(DL.getIndexType(V->getType()));
1243 Zero = ConstantInt::get(IntTy, 0);
1244
1245 SizeOffsetValue Result = compute_(V);
1246
1247 if (!Result.bothKnown()) {
1248 // Erase everything that was computed in this iteration from the cache, so
1249 // that no dangling references are left behind. We could be a bit smarter if
1250 // we kept a dependency graph. It's probably not worth the complexity.
1251 for (const Value *SeenVal : SeenVals) {
1252 CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
1253 // non-computable results can be safely cached
1254 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown())
1255 CacheMap.erase(CacheIt);
1256 }
1257
1258 // Erase any instructions we inserted as part of the traversal.
1259 for (Instruction *I : InsertedInstructions) {
1260 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
1261 I->eraseFromParent();
1262 }
1263 }
1264
1265 SeenVals.clear();
1266 InsertedInstructions.clear();
1267 return Result;
1268}
1269
1270SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) {
1271
1272 // Only trust ObjectSizeOffsetVisitor in exact mode, otherwise fallback on
1273 // dynamic computation.
1274 ObjectSizeOpts VisitorEvalOpts(EvalOpts);
1275 VisitorEvalOpts.EvalMode = ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset;
1276 ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, VisitorEvalOpts);
1277
1278 SizeOffsetAPInt Const = Visitor.compute(V);
1279 if (Const.bothKnown())
1280 return SizeOffsetValue(ConstantInt::get(Context, Const.Size),
1281 ConstantInt::get(Context, Const.Offset));
1282
1283 V = V->stripPointerCasts();
1284
1285 // Check cache.
1286 CacheMapTy::iterator CacheIt = CacheMap.find(V);
1287 if (CacheIt != CacheMap.end())
1288 return CacheIt->second;
1289
1290 // Always generate code immediately before the instruction being
1291 // processed, so that the generated code dominates the same BBs.
1292 BuilderTy::InsertPointGuard Guard(Builder);
1294 Builder.SetInsertPoint(I);
1295
1296 // Now compute the size and offset.
1297 SizeOffsetValue Result;
1298
1299 // Record the pointers that were handled in this run, so that they can be
1300 // cleaned later if something fails. We also use this set to break cycles that
1301 // can occur in dead code.
1302 if (!SeenVals.insert(V).second) {
1304 } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
1305 Result = visitGEPOperator(*GEP);
1306 } else if (Instruction *I = dyn_cast<Instruction>(V)) {
1307 Result = visit(*I);
1308 } else if (isa<Argument>(V) ||
1309 (isa<ConstantExpr>(V) &&
1310 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
1312 // Ignore values where we cannot do more than ObjectSizeVisitor.
1314 } else {
1315 LLVM_DEBUG(
1316 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1317 << '\n');
1319 }
1320
1321 // Don't reuse CacheIt since it may be invalid at this point.
1322 CacheMap[V] = SizeOffsetWeakTrackingVH(Result);
1323 return Result;
1324}
1325
1327 if (!I.getAllocatedType()->isSized())
1329
1330 // must be a VLA or vscale.
1331 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
1332
1333 // If needed, adjust the alloca's operand size to match the pointer indexing
1334 // size. Subsequent math operations expect the types to match.
1335 Type *IndexTy = DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace());
1336 assert(IndexTy == Zero->getType() &&
1337 "Expected zero constant to have pointer index type");
1338
1339 Value *Size = Builder.CreateAllocationSize(IndexTy, &I);
1340 return SizeOffsetValue(Size, Zero);
1341}
1342
1344 std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI);
1345 if (!FnData)
1347
1348 // Handle strdup-like functions separately.
1349 if (FnData->AllocTy == StrDupLike) {
1350 // TODO: implement evaluation of strdup/strndup
1352 }
1353
1354 Value *FirstArg = CB.getArgOperand(FnData->FstParam);
1355 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1356 if (FnData->SndParam < 0)
1357 return SizeOffsetValue(FirstArg, Zero);
1358
1359 Value *SecondArg = CB.getArgOperand(FnData->SndParam);
1360 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1361 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1362 return SizeOffsetValue(Size, Zero);
1363}
1364
1369
1374
1376 SizeOffsetValue PtrData = compute_(GEP.getPointerOperand());
1377 if (!PtrData.bothKnown())
1379
1380 Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1381 Offset = Builder.CreateAdd(PtrData.Offset, Offset);
1382 return SizeOffsetValue(PtrData.Size, Offset);
1383}
1384
1389
1393
1395 // Create 2 PHIs: one for size and another for offset.
1396 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1397 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1398
1399 // Insert right away in the cache to handle recursive PHIs.
1400 CacheMap[&PHI] = SizeOffsetWeakTrackingVH(SizePHI, OffsetPHI);
1401
1402 // Compute offset/size for each PHI incoming pointer.
1403 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1404 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1405 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1406 SizeOffsetValue EdgeData = compute_(PHI.getIncomingValue(i));
1407
1408 if (!EdgeData.bothKnown()) {
1409 OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1410 OffsetPHI->eraseFromParent();
1411 InsertedInstructions.erase(OffsetPHI);
1412 SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy));
1413 SizePHI->eraseFromParent();
1414 InsertedInstructions.erase(SizePHI);
1416 }
1417 SizePHI->addIncoming(EdgeData.Size, IncomingBlock);
1418 OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock);
1419 }
1420
1421 Value *Size = SizePHI, *Offset = OffsetPHI;
1422 if (Value *Tmp = SizePHI->hasConstantValue()) {
1423 Size = Tmp;
1424 SizePHI->replaceAllUsesWith(Size);
1425 SizePHI->eraseFromParent();
1426 InsertedInstructions.erase(SizePHI);
1427 }
1428 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
1429 Offset = Tmp;
1430 OffsetPHI->replaceAllUsesWith(Offset);
1431 OffsetPHI->eraseFromParent();
1432 InsertedInstructions.erase(OffsetPHI);
1433 }
1434 return SizeOffsetValue(Size, Offset);
1435}
1436
1438 SizeOffsetValue TrueSide = compute_(I.getTrueValue());
1439 SizeOffsetValue FalseSide = compute_(I.getFalseValue());
1440
1441 if (!TrueSide.bothKnown() || !FalseSide.bothKnown())
1443 if (TrueSide == FalseSide)
1444 return TrueSide;
1445
1446 Value *Size =
1447 Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size);
1448 Value *Offset =
1449 Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset);
1450 return SizeOffsetValue(Size, Offset);
1451}
1452
1454 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1455 << '\n');
1457}
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:1056
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:1964
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:1977
@ 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:2903
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'.
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.