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