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