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