1*9880d681SAndroid Build Coastguard Worker //===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This family of functions identifies calls to builtin functions that allocate
11*9880d681SAndroid Build Coastguard Worker // or free memory.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/MemoryBuiltins.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/TargetLibraryInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Metadata.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Local.h"
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "memory-builtins"
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker enum AllocType : uint8_t {
35*9880d681SAndroid Build Coastguard Worker OpNewLike = 1<<0, // allocates; never returns null
36*9880d681SAndroid Build Coastguard Worker MallocLike = 1<<1 | OpNewLike, // allocates; may return null
37*9880d681SAndroid Build Coastguard Worker CallocLike = 1<<2, // allocates + bzero
38*9880d681SAndroid Build Coastguard Worker ReallocLike = 1<<3, // reallocates
39*9880d681SAndroid Build Coastguard Worker StrDupLike = 1<<4,
40*9880d681SAndroid Build Coastguard Worker AllocLike = MallocLike | CallocLike | StrDupLike,
41*9880d681SAndroid Build Coastguard Worker AnyAlloc = AllocLike | ReallocLike
42*9880d681SAndroid Build Coastguard Worker };
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker struct AllocFnsTy {
45*9880d681SAndroid Build Coastguard Worker AllocType AllocTy;
46*9880d681SAndroid Build Coastguard Worker unsigned NumParams;
47*9880d681SAndroid Build Coastguard Worker // First and Second size parameters (or -1 if unused)
48*9880d681SAndroid Build Coastguard Worker int FstParam, SndParam;
49*9880d681SAndroid Build Coastguard Worker };
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker // FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
52*9880d681SAndroid Build Coastguard Worker // know which functions are nounwind, noalias, nocapture parameters, etc.
53*9880d681SAndroid Build Coastguard Worker static const std::pair<LibFunc::Func, AllocFnsTy> AllocationFnData[] = {
54*9880d681SAndroid Build Coastguard Worker {LibFunc::malloc, {MallocLike, 1, 0, -1}},
55*9880d681SAndroid Build Coastguard Worker {LibFunc::valloc, {MallocLike, 1, 0, -1}},
56*9880d681SAndroid Build Coastguard Worker {LibFunc::Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int)
57*9880d681SAndroid Build Coastguard Worker {LibFunc::ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow)
58*9880d681SAndroid Build Coastguard Worker {LibFunc::Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long)
59*9880d681SAndroid Build Coastguard Worker {LibFunc::ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow)
60*9880d681SAndroid Build Coastguard Worker {LibFunc::Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int)
61*9880d681SAndroid Build Coastguard Worker {LibFunc::ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow)
62*9880d681SAndroid Build Coastguard Worker {LibFunc::Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long)
63*9880d681SAndroid Build Coastguard Worker {LibFunc::ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow)
64*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_int, {OpNewLike, 1, 0, -1}}, // new(unsigned int)
65*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_int_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow)
66*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_longlong, {OpNewLike, 1, 0, -1}}, // new(unsigned long long)
67*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned long long, nothrow)
68*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_array_int, {OpNewLike, 1, 0, -1}}, // new[](unsigned int)
69*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow)
70*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long)
71*9880d681SAndroid Build Coastguard Worker {LibFunc::msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow)
72*9880d681SAndroid Build Coastguard Worker {LibFunc::calloc, {CallocLike, 2, 0, 1}},
73*9880d681SAndroid Build Coastguard Worker {LibFunc::realloc, {ReallocLike, 2, 1, -1}},
74*9880d681SAndroid Build Coastguard Worker {LibFunc::reallocf, {ReallocLike, 2, 1, -1}},
75*9880d681SAndroid Build Coastguard Worker {LibFunc::strdup, {StrDupLike, 1, -1, -1}},
76*9880d681SAndroid Build Coastguard Worker {LibFunc::strndup, {StrDupLike, 2, 1, -1}}
77*9880d681SAndroid Build Coastguard Worker // TODO: Handle "int posix_memalign(void **, size_t, size_t)"
78*9880d681SAndroid Build Coastguard Worker };
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker
getCalledFunction(const Value * V,bool LookThroughBitCast)81*9880d681SAndroid Build Coastguard Worker static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
82*9880d681SAndroid Build Coastguard Worker if (LookThroughBitCast)
83*9880d681SAndroid Build Coastguard Worker V = V->stripPointerCasts();
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker CallSite CS(const_cast<Value*>(V));
86*9880d681SAndroid Build Coastguard Worker if (!CS.getInstruction())
87*9880d681SAndroid Build Coastguard Worker return nullptr;
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker if (CS.isNoBuiltin())
90*9880d681SAndroid Build Coastguard Worker return nullptr;
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker Function *Callee = CS.getCalledFunction();
93*9880d681SAndroid Build Coastguard Worker if (!Callee || !Callee->isDeclaration())
94*9880d681SAndroid Build Coastguard Worker return nullptr;
95*9880d681SAndroid Build Coastguard Worker return Callee;
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker /// Returns the allocation data for the given value if it's either a call to a
99*9880d681SAndroid Build Coastguard Worker /// known allocation function, or a call to a function with the allocsize
100*9880d681SAndroid Build Coastguard Worker /// attribute.
getAllocationData(const Value * V,AllocType AllocTy,const TargetLibraryInfo * TLI,bool LookThroughBitCast=false)101*9880d681SAndroid Build Coastguard Worker static Optional<AllocFnsTy> getAllocationData(const Value *V, AllocType AllocTy,
102*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI,
103*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast = false) {
104*9880d681SAndroid Build Coastguard Worker // Skip intrinsics
105*9880d681SAndroid Build Coastguard Worker if (isa<IntrinsicInst>(V))
106*9880d681SAndroid Build Coastguard Worker return None;
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Worker const Function *Callee = getCalledFunction(V, LookThroughBitCast);
109*9880d681SAndroid Build Coastguard Worker if (!Callee)
110*9880d681SAndroid Build Coastguard Worker return None;
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker // If it has allocsize, we can skip checking if it's a known function.
113*9880d681SAndroid Build Coastguard Worker //
114*9880d681SAndroid Build Coastguard Worker // MallocLike is chosen here because allocsize makes no guarantees about the
115*9880d681SAndroid Build Coastguard Worker // nullness of the result of the function, nor does it deal with strings, nor
116*9880d681SAndroid Build Coastguard Worker // does it require that the memory returned is zeroed out.
117*9880d681SAndroid Build Coastguard Worker LLVM_CONSTEXPR auto AllocSizeAllocTy = MallocLike;
118*9880d681SAndroid Build Coastguard Worker if ((AllocTy & AllocSizeAllocTy) == AllocSizeAllocTy &&
119*9880d681SAndroid Build Coastguard Worker Callee->hasFnAttribute(Attribute::AllocSize)) {
120*9880d681SAndroid Build Coastguard Worker Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize);
121*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, Optional<unsigned>> Args = Attr.getAllocSizeArgs();
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker AllocFnsTy Result;
124*9880d681SAndroid Build Coastguard Worker Result.AllocTy = AllocSizeAllocTy;
125*9880d681SAndroid Build Coastguard Worker Result.NumParams = Callee->getNumOperands();
126*9880d681SAndroid Build Coastguard Worker Result.FstParam = Args.first;
127*9880d681SAndroid Build Coastguard Worker Result.SndParam = Args.second.getValueOr(-1);
128*9880d681SAndroid Build Coastguard Worker return Result;
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker // Make sure that the function is available.
132*9880d681SAndroid Build Coastguard Worker StringRef FnName = Callee->getName();
133*9880d681SAndroid Build Coastguard Worker LibFunc::Func TLIFn;
134*9880d681SAndroid Build Coastguard Worker if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
135*9880d681SAndroid Build Coastguard Worker return None;
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker const auto *Iter =
138*9880d681SAndroid Build Coastguard Worker std::find_if(std::begin(AllocationFnData), std::end(AllocationFnData),
139*9880d681SAndroid Build Coastguard Worker [TLIFn](const std::pair<LibFunc::Func, AllocFnsTy> &P) {
140*9880d681SAndroid Build Coastguard Worker return P.first == TLIFn;
141*9880d681SAndroid Build Coastguard Worker });
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker if (Iter == std::end(AllocationFnData))
144*9880d681SAndroid Build Coastguard Worker return None;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker const AllocFnsTy *FnData = &Iter->second;
147*9880d681SAndroid Build Coastguard Worker if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
148*9880d681SAndroid Build Coastguard Worker return None;
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker // Check function prototype.
151*9880d681SAndroid Build Coastguard Worker int FstParam = FnData->FstParam;
152*9880d681SAndroid Build Coastguard Worker int SndParam = FnData->SndParam;
153*9880d681SAndroid Build Coastguard Worker FunctionType *FTy = Callee->getFunctionType();
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
156*9880d681SAndroid Build Coastguard Worker FTy->getNumParams() == FnData->NumParams &&
157*9880d681SAndroid Build Coastguard Worker (FstParam < 0 ||
158*9880d681SAndroid Build Coastguard Worker (FTy->getParamType(FstParam)->isIntegerTy(32) ||
159*9880d681SAndroid Build Coastguard Worker FTy->getParamType(FstParam)->isIntegerTy(64))) &&
160*9880d681SAndroid Build Coastguard Worker (SndParam < 0 ||
161*9880d681SAndroid Build Coastguard Worker FTy->getParamType(SndParam)->isIntegerTy(32) ||
162*9880d681SAndroid Build Coastguard Worker FTy->getParamType(SndParam)->isIntegerTy(64)))
163*9880d681SAndroid Build Coastguard Worker return *FnData;
164*9880d681SAndroid Build Coastguard Worker return None;
165*9880d681SAndroid Build Coastguard Worker }
166*9880d681SAndroid Build Coastguard Worker
hasNoAliasAttr(const Value * V,bool LookThroughBitCast)167*9880d681SAndroid Build Coastguard Worker static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) {
168*9880d681SAndroid Build Coastguard Worker ImmutableCallSite CS(LookThroughBitCast ? V->stripPointerCasts() : V);
169*9880d681SAndroid Build Coastguard Worker return CS && CS.paramHasAttr(AttributeSet::ReturnIndex, Attribute::NoAlias);
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker /// \brief Tests if a value is a call or invoke to a library function that
174*9880d681SAndroid Build Coastguard Worker /// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
175*9880d681SAndroid Build Coastguard Worker /// like).
isAllocationFn(const Value * V,const TargetLibraryInfo * TLI,bool LookThroughBitCast)176*9880d681SAndroid Build Coastguard Worker bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
177*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast) {
178*9880d681SAndroid Build Coastguard Worker return getAllocationData(V, AnyAlloc, TLI, LookThroughBitCast).hasValue();
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Worker /// \brief Tests if a value is a call or invoke to a function that returns a
182*9880d681SAndroid Build Coastguard Worker /// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
isNoAliasFn(const Value * V,const TargetLibraryInfo * TLI,bool LookThroughBitCast)183*9880d681SAndroid Build Coastguard Worker bool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
184*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast) {
185*9880d681SAndroid Build Coastguard Worker // it's safe to consider realloc as noalias since accessing the original
186*9880d681SAndroid Build Coastguard Worker // pointer is undefined behavior
187*9880d681SAndroid Build Coastguard Worker return isAllocationFn(V, TLI, LookThroughBitCast) ||
188*9880d681SAndroid Build Coastguard Worker hasNoAliasAttr(V, LookThroughBitCast);
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker /// \brief Tests if a value is a call or invoke to a library function that
192*9880d681SAndroid Build Coastguard Worker /// allocates uninitialized memory (such as malloc).
isMallocLikeFn(const Value * V,const TargetLibraryInfo * TLI,bool LookThroughBitCast)193*9880d681SAndroid Build Coastguard Worker bool llvm::isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
194*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast) {
195*9880d681SAndroid Build Coastguard Worker return getAllocationData(V, MallocLike, TLI, LookThroughBitCast).hasValue();
196*9880d681SAndroid Build Coastguard Worker }
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker /// \brief Tests if a value is a call or invoke to a library function that
199*9880d681SAndroid Build Coastguard Worker /// allocates zero-filled memory (such as calloc).
isCallocLikeFn(const Value * V,const TargetLibraryInfo * TLI,bool LookThroughBitCast)200*9880d681SAndroid Build Coastguard Worker bool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
201*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast) {
202*9880d681SAndroid Build Coastguard Worker return getAllocationData(V, CallocLike, TLI, LookThroughBitCast).hasValue();
203*9880d681SAndroid Build Coastguard Worker }
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker /// \brief Tests if a value is a call or invoke to a library function that
206*9880d681SAndroid Build Coastguard Worker /// allocates memory (either malloc, calloc, or strdup like).
isAllocLikeFn(const Value * V,const TargetLibraryInfo * TLI,bool LookThroughBitCast)207*9880d681SAndroid Build Coastguard Worker bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
208*9880d681SAndroid Build Coastguard Worker bool LookThroughBitCast) {
209*9880d681SAndroid Build Coastguard Worker return getAllocationData(V, AllocLike, TLI, LookThroughBitCast).hasValue();
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker /// extractMallocCall - Returns the corresponding CallInst if the instruction
213*9880d681SAndroid Build Coastguard Worker /// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we
214*9880d681SAndroid Build Coastguard Worker /// ignore InvokeInst here.
extractMallocCall(const Value * I,const TargetLibraryInfo * TLI)215*9880d681SAndroid Build Coastguard Worker const CallInst *llvm::extractMallocCall(const Value *I,
216*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI) {
217*9880d681SAndroid Build Coastguard Worker return isMallocLikeFn(I, TLI) ? dyn_cast<CallInst>(I) : nullptr;
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
computeArraySize(const CallInst * CI,const DataLayout & DL,const TargetLibraryInfo * TLI,bool LookThroughSExt=false)220*9880d681SAndroid Build Coastguard Worker static Value *computeArraySize(const CallInst *CI, const DataLayout &DL,
221*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI,
222*9880d681SAndroid Build Coastguard Worker bool LookThroughSExt = false) {
223*9880d681SAndroid Build Coastguard Worker if (!CI)
224*9880d681SAndroid Build Coastguard Worker return nullptr;
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker // The size of the malloc's result type must be known to determine array size.
227*9880d681SAndroid Build Coastguard Worker Type *T = getMallocAllocatedType(CI, TLI);
228*9880d681SAndroid Build Coastguard Worker if (!T || !T->isSized())
229*9880d681SAndroid Build Coastguard Worker return nullptr;
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker unsigned ElementSize = DL.getTypeAllocSize(T);
232*9880d681SAndroid Build Coastguard Worker if (StructType *ST = dyn_cast<StructType>(T))
233*9880d681SAndroid Build Coastguard Worker ElementSize = DL.getStructLayout(ST)->getSizeInBytes();
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker // If malloc call's arg can be determined to be a multiple of ElementSize,
236*9880d681SAndroid Build Coastguard Worker // return the multiple. Otherwise, return NULL.
237*9880d681SAndroid Build Coastguard Worker Value *MallocArg = CI->getArgOperand(0);
238*9880d681SAndroid Build Coastguard Worker Value *Multiple = nullptr;
239*9880d681SAndroid Build Coastguard Worker if (ComputeMultiple(MallocArg, ElementSize, Multiple, LookThroughSExt))
240*9880d681SAndroid Build Coastguard Worker return Multiple;
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker return nullptr;
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker /// getMallocType - Returns the PointerType resulting from the malloc call.
246*9880d681SAndroid Build Coastguard Worker /// The PointerType depends on the number of bitcast uses of the malloc call:
247*9880d681SAndroid Build Coastguard Worker /// 0: PointerType is the calls' return type.
248*9880d681SAndroid Build Coastguard Worker /// 1: PointerType is the bitcast's result type.
249*9880d681SAndroid Build Coastguard Worker /// >1: Unique PointerType cannot be determined, return NULL.
getMallocType(const CallInst * CI,const TargetLibraryInfo * TLI)250*9880d681SAndroid Build Coastguard Worker PointerType *llvm::getMallocType(const CallInst *CI,
251*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI) {
252*9880d681SAndroid Build Coastguard Worker assert(isMallocLikeFn(CI, TLI) && "getMallocType and not malloc call");
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Worker PointerType *MallocType = nullptr;
255*9880d681SAndroid Build Coastguard Worker unsigned NumOfBitCastUses = 0;
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker // Determine if CallInst has a bitcast use.
258*9880d681SAndroid Build Coastguard Worker for (Value::const_user_iterator UI = CI->user_begin(), E = CI->user_end();
259*9880d681SAndroid Build Coastguard Worker UI != E;)
260*9880d681SAndroid Build Coastguard Worker if (const BitCastInst *BCI = dyn_cast<BitCastInst>(*UI++)) {
261*9880d681SAndroid Build Coastguard Worker MallocType = cast<PointerType>(BCI->getDestTy());
262*9880d681SAndroid Build Coastguard Worker NumOfBitCastUses++;
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker // Malloc call has 1 bitcast use, so type is the bitcast's destination type.
266*9880d681SAndroid Build Coastguard Worker if (NumOfBitCastUses == 1)
267*9880d681SAndroid Build Coastguard Worker return MallocType;
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker // Malloc call was not bitcast, so type is the malloc function's return type.
270*9880d681SAndroid Build Coastguard Worker if (NumOfBitCastUses == 0)
271*9880d681SAndroid Build Coastguard Worker return cast<PointerType>(CI->getType());
272*9880d681SAndroid Build Coastguard Worker
273*9880d681SAndroid Build Coastguard Worker // Type could not be determined.
274*9880d681SAndroid Build Coastguard Worker return nullptr;
275*9880d681SAndroid Build Coastguard Worker }
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker /// getMallocAllocatedType - Returns the Type allocated by malloc call.
278*9880d681SAndroid Build Coastguard Worker /// The Type depends on the number of bitcast uses of the malloc call:
279*9880d681SAndroid Build Coastguard Worker /// 0: PointerType is the malloc calls' return type.
280*9880d681SAndroid Build Coastguard Worker /// 1: PointerType is the bitcast's result type.
281*9880d681SAndroid Build Coastguard Worker /// >1: Unique PointerType cannot be determined, return NULL.
getMallocAllocatedType(const CallInst * CI,const TargetLibraryInfo * TLI)282*9880d681SAndroid Build Coastguard Worker Type *llvm::getMallocAllocatedType(const CallInst *CI,
283*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI) {
284*9880d681SAndroid Build Coastguard Worker PointerType *PT = getMallocType(CI, TLI);
285*9880d681SAndroid Build Coastguard Worker return PT ? PT->getElementType() : nullptr;
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker
288*9880d681SAndroid Build Coastguard Worker /// getMallocArraySize - Returns the array size of a malloc call. If the
289*9880d681SAndroid Build Coastguard Worker /// argument passed to malloc is a multiple of the size of the malloced type,
290*9880d681SAndroid Build Coastguard Worker /// then return that multiple. For non-array mallocs, the multiple is
291*9880d681SAndroid Build Coastguard Worker /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
292*9880d681SAndroid Build Coastguard Worker /// determined.
getMallocArraySize(CallInst * CI,const DataLayout & DL,const TargetLibraryInfo * TLI,bool LookThroughSExt)293*9880d681SAndroid Build Coastguard Worker Value *llvm::getMallocArraySize(CallInst *CI, const DataLayout &DL,
294*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI,
295*9880d681SAndroid Build Coastguard Worker bool LookThroughSExt) {
296*9880d681SAndroid Build Coastguard Worker assert(isMallocLikeFn(CI, TLI) && "getMallocArraySize and not malloc call");
297*9880d681SAndroid Build Coastguard Worker return computeArraySize(CI, DL, TLI, LookThroughSExt);
298*9880d681SAndroid Build Coastguard Worker }
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard Worker /// extractCallocCall - Returns the corresponding CallInst if the instruction
302*9880d681SAndroid Build Coastguard Worker /// is a calloc call.
extractCallocCall(const Value * I,const TargetLibraryInfo * TLI)303*9880d681SAndroid Build Coastguard Worker const CallInst *llvm::extractCallocCall(const Value *I,
304*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI) {
305*9880d681SAndroid Build Coastguard Worker return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : nullptr;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker /// isFreeCall - Returns non-null if the value is a call to the builtin free()
isFreeCall(const Value * I,const TargetLibraryInfo * TLI)310*9880d681SAndroid Build Coastguard Worker const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
311*9880d681SAndroid Build Coastguard Worker const CallInst *CI = dyn_cast<CallInst>(I);
312*9880d681SAndroid Build Coastguard Worker if (!CI || isa<IntrinsicInst>(CI))
313*9880d681SAndroid Build Coastguard Worker return nullptr;
314*9880d681SAndroid Build Coastguard Worker Function *Callee = CI->getCalledFunction();
315*9880d681SAndroid Build Coastguard Worker if (Callee == nullptr)
316*9880d681SAndroid Build Coastguard Worker return nullptr;
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard Worker StringRef FnName = Callee->getName();
319*9880d681SAndroid Build Coastguard Worker LibFunc::Func TLIFn;
320*9880d681SAndroid Build Coastguard Worker if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
321*9880d681SAndroid Build Coastguard Worker return nullptr;
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker unsigned ExpectedNumParams;
324*9880d681SAndroid Build Coastguard Worker if (TLIFn == LibFunc::free ||
325*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdlPv || // operator delete(void*)
326*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdaPv || // operator delete[](void*)
327*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*)
328*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*)
329*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*)
330*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr64) // operator delete[](void*)
331*9880d681SAndroid Build Coastguard Worker ExpectedNumParams = 1;
332*9880d681SAndroid Build Coastguard Worker else if (TLIFn == LibFunc::ZdlPvj || // delete(void*, uint)
333*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdlPvm || // delete(void*, ulong)
334*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow)
335*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdaPvj || // delete[](void*, uint)
336*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong)
337*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow)
338*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr32_int || // delete(void*, uint)
339*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong)
340*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow)
341*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow)
342*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr32_int || // delete[](void*, uint)
343*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong)
344*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow)
345*9880d681SAndroid Build Coastguard Worker TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow)
346*9880d681SAndroid Build Coastguard Worker ExpectedNumParams = 2;
347*9880d681SAndroid Build Coastguard Worker else
348*9880d681SAndroid Build Coastguard Worker return nullptr;
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker // Check free prototype.
351*9880d681SAndroid Build Coastguard Worker // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
352*9880d681SAndroid Build Coastguard Worker // attribute will exist.
353*9880d681SAndroid Build Coastguard Worker FunctionType *FTy = Callee->getFunctionType();
354*9880d681SAndroid Build Coastguard Worker if (!FTy->getReturnType()->isVoidTy())
355*9880d681SAndroid Build Coastguard Worker return nullptr;
356*9880d681SAndroid Build Coastguard Worker if (FTy->getNumParams() != ExpectedNumParams)
357*9880d681SAndroid Build Coastguard Worker return nullptr;
358*9880d681SAndroid Build Coastguard Worker if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
359*9880d681SAndroid Build Coastguard Worker return nullptr;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker return CI;
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
367*9880d681SAndroid Build Coastguard Worker // Utility functions to compute size of objects.
368*9880d681SAndroid Build Coastguard Worker //
getSizeWithOverflow(const SizeOffsetType & Data)369*9880d681SAndroid Build Coastguard Worker static APInt getSizeWithOverflow(const SizeOffsetType &Data) {
370*9880d681SAndroid Build Coastguard Worker if (Data.second.isNegative() || Data.first.ult(Data.second))
371*9880d681SAndroid Build Coastguard Worker return APInt(Data.first.getBitWidth(), 0);
372*9880d681SAndroid Build Coastguard Worker return Data.first - Data.second;
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker
375*9880d681SAndroid Build Coastguard Worker /// \brief Compute the size of the object pointed by Ptr. Returns true and the
376*9880d681SAndroid Build Coastguard Worker /// object size in Size if successful, and false otherwise.
377*9880d681SAndroid Build Coastguard Worker /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
378*9880d681SAndroid Build Coastguard Worker /// byval arguments, and global variables.
getObjectSize(const Value * Ptr,uint64_t & Size,const DataLayout & DL,const TargetLibraryInfo * TLI,bool RoundToAlign,llvm::ObjSizeMode Mode)379*9880d681SAndroid Build Coastguard Worker bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
380*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI, bool RoundToAlign,
381*9880d681SAndroid Build Coastguard Worker llvm::ObjSizeMode Mode) {
382*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(),
383*9880d681SAndroid Build Coastguard Worker RoundToAlign, Mode);
384*9880d681SAndroid Build Coastguard Worker SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
385*9880d681SAndroid Build Coastguard Worker if (!Visitor.bothKnown(Data))
386*9880d681SAndroid Build Coastguard Worker return false;
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker Size = getSizeWithOverflow(Data).getZExtValue();
389*9880d681SAndroid Build Coastguard Worker return true;
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Worker STATISTIC(ObjectVisitorArgument,
393*9880d681SAndroid Build Coastguard Worker "Number of arguments with unsolved size and offset");
394*9880d681SAndroid Build Coastguard Worker STATISTIC(ObjectVisitorLoad,
395*9880d681SAndroid Build Coastguard Worker "Number of load instructions with unsolved size and offset");
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker
align(APInt Size,uint64_t Align)398*9880d681SAndroid Build Coastguard Worker APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
399*9880d681SAndroid Build Coastguard Worker if (RoundToAlign && Align)
400*9880d681SAndroid Build Coastguard Worker return APInt(IntTyBits, alignTo(Size.getZExtValue(), Align));
401*9880d681SAndroid Build Coastguard Worker return Size;
402*9880d681SAndroid Build Coastguard Worker }
403*9880d681SAndroid Build Coastguard Worker
ObjectSizeOffsetVisitor(const DataLayout & DL,const TargetLibraryInfo * TLI,LLVMContext & Context,bool RoundToAlign,ObjSizeMode Mode)404*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL,
405*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *TLI,
406*9880d681SAndroid Build Coastguard Worker LLVMContext &Context,
407*9880d681SAndroid Build Coastguard Worker bool RoundToAlign,
408*9880d681SAndroid Build Coastguard Worker ObjSizeMode Mode)
409*9880d681SAndroid Build Coastguard Worker : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign), Mode(Mode) {
410*9880d681SAndroid Build Coastguard Worker // Pointer size must be rechecked for each object visited since it could have
411*9880d681SAndroid Build Coastguard Worker // a different address space.
412*9880d681SAndroid Build Coastguard Worker }
413*9880d681SAndroid Build Coastguard Worker
compute(Value * V)414*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
415*9880d681SAndroid Build Coastguard Worker IntTyBits = DL.getPointerTypeSizeInBits(V->getType());
416*9880d681SAndroid Build Coastguard Worker Zero = APInt::getNullValue(IntTyBits);
417*9880d681SAndroid Build Coastguard Worker
418*9880d681SAndroid Build Coastguard Worker V = V->stripPointerCasts();
419*9880d681SAndroid Build Coastguard Worker if (Instruction *I = dyn_cast<Instruction>(V)) {
420*9880d681SAndroid Build Coastguard Worker // If we have already seen this instruction, bail out. Cycles can happen in
421*9880d681SAndroid Build Coastguard Worker // unreachable code after constant propagation.
422*9880d681SAndroid Build Coastguard Worker if (!SeenInsts.insert(I).second)
423*9880d681SAndroid Build Coastguard Worker return unknown();
424*9880d681SAndroid Build Coastguard Worker
425*9880d681SAndroid Build Coastguard Worker if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
426*9880d681SAndroid Build Coastguard Worker return visitGEPOperator(*GEP);
427*9880d681SAndroid Build Coastguard Worker return visit(*I);
428*9880d681SAndroid Build Coastguard Worker }
429*9880d681SAndroid Build Coastguard Worker if (Argument *A = dyn_cast<Argument>(V))
430*9880d681SAndroid Build Coastguard Worker return visitArgument(*A);
431*9880d681SAndroid Build Coastguard Worker if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
432*9880d681SAndroid Build Coastguard Worker return visitConstantPointerNull(*P);
433*9880d681SAndroid Build Coastguard Worker if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
434*9880d681SAndroid Build Coastguard Worker return visitGlobalAlias(*GA);
435*9880d681SAndroid Build Coastguard Worker if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
436*9880d681SAndroid Build Coastguard Worker return visitGlobalVariable(*GV);
437*9880d681SAndroid Build Coastguard Worker if (UndefValue *UV = dyn_cast<UndefValue>(V))
438*9880d681SAndroid Build Coastguard Worker return visitUndefValue(*UV);
439*9880d681SAndroid Build Coastguard Worker if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
440*9880d681SAndroid Build Coastguard Worker if (CE->getOpcode() == Instruction::IntToPtr)
441*9880d681SAndroid Build Coastguard Worker return unknown(); // clueless
442*9880d681SAndroid Build Coastguard Worker if (CE->getOpcode() == Instruction::GetElementPtr)
443*9880d681SAndroid Build Coastguard Worker return visitGEPOperator(cast<GEPOperator>(*CE));
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker
446*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V
447*9880d681SAndroid Build Coastguard Worker << '\n');
448*9880d681SAndroid Build Coastguard Worker return unknown();
449*9880d681SAndroid Build Coastguard Worker }
450*9880d681SAndroid Build Coastguard Worker
visitAllocaInst(AllocaInst & I)451*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
452*9880d681SAndroid Build Coastguard Worker if (!I.getAllocatedType()->isSized())
453*9880d681SAndroid Build Coastguard Worker return unknown();
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker APInt Size(IntTyBits, DL.getTypeAllocSize(I.getAllocatedType()));
456*9880d681SAndroid Build Coastguard Worker if (!I.isArrayAllocation())
457*9880d681SAndroid Build Coastguard Worker return std::make_pair(align(Size, I.getAlignment()), Zero);
458*9880d681SAndroid Build Coastguard Worker
459*9880d681SAndroid Build Coastguard Worker Value *ArraySize = I.getArraySize();
460*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
461*9880d681SAndroid Build Coastguard Worker Size *= C->getValue().zextOrSelf(IntTyBits);
462*9880d681SAndroid Build Coastguard Worker return std::make_pair(align(Size, I.getAlignment()), Zero);
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker return unknown();
465*9880d681SAndroid Build Coastguard Worker }
466*9880d681SAndroid Build Coastguard Worker
visitArgument(Argument & A)467*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
468*9880d681SAndroid Build Coastguard Worker // No interprocedural analysis is done at the moment.
469*9880d681SAndroid Build Coastguard Worker if (!A.hasByValOrInAllocaAttr()) {
470*9880d681SAndroid Build Coastguard Worker ++ObjectVisitorArgument;
471*9880d681SAndroid Build Coastguard Worker return unknown();
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker PointerType *PT = cast<PointerType>(A.getType());
474*9880d681SAndroid Build Coastguard Worker APInt Size(IntTyBits, DL.getTypeAllocSize(PT->getElementType()));
475*9880d681SAndroid Build Coastguard Worker return std::make_pair(align(Size, A.getParamAlignment()), Zero);
476*9880d681SAndroid Build Coastguard Worker }
477*9880d681SAndroid Build Coastguard Worker
visitCallSite(CallSite CS)478*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
479*9880d681SAndroid Build Coastguard Worker Optional<AllocFnsTy> FnData =
480*9880d681SAndroid Build Coastguard Worker getAllocationData(CS.getInstruction(), AnyAlloc, TLI);
481*9880d681SAndroid Build Coastguard Worker if (!FnData)
482*9880d681SAndroid Build Coastguard Worker return unknown();
483*9880d681SAndroid Build Coastguard Worker
484*9880d681SAndroid Build Coastguard Worker // Handle strdup-like functions separately.
485*9880d681SAndroid Build Coastguard Worker if (FnData->AllocTy == StrDupLike) {
486*9880d681SAndroid Build Coastguard Worker APInt Size(IntTyBits, GetStringLength(CS.getArgument(0)));
487*9880d681SAndroid Build Coastguard Worker if (!Size)
488*9880d681SAndroid Build Coastguard Worker return unknown();
489*9880d681SAndroid Build Coastguard Worker
490*9880d681SAndroid Build Coastguard Worker // Strndup limits strlen.
491*9880d681SAndroid Build Coastguard Worker if (FnData->FstParam > 0) {
492*9880d681SAndroid Build Coastguard Worker ConstantInt *Arg =
493*9880d681SAndroid Build Coastguard Worker dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
494*9880d681SAndroid Build Coastguard Worker if (!Arg)
495*9880d681SAndroid Build Coastguard Worker return unknown();
496*9880d681SAndroid Build Coastguard Worker
497*9880d681SAndroid Build Coastguard Worker APInt MaxSize = Arg->getValue().zextOrSelf(IntTyBits);
498*9880d681SAndroid Build Coastguard Worker if (Size.ugt(MaxSize))
499*9880d681SAndroid Build Coastguard Worker Size = MaxSize + 1;
500*9880d681SAndroid Build Coastguard Worker }
501*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Zero);
502*9880d681SAndroid Build Coastguard Worker }
503*9880d681SAndroid Build Coastguard Worker
504*9880d681SAndroid Build Coastguard Worker ConstantInt *Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
505*9880d681SAndroid Build Coastguard Worker if (!Arg)
506*9880d681SAndroid Build Coastguard Worker return unknown();
507*9880d681SAndroid Build Coastguard Worker
508*9880d681SAndroid Build Coastguard Worker // When we're compiling N-bit code, and the user uses parameters that are
509*9880d681SAndroid Build Coastguard Worker // greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
510*9880d681SAndroid Build Coastguard Worker // trouble with APInt size issues. This function handles resizing + overflow
511*9880d681SAndroid Build Coastguard Worker // checks for us.
512*9880d681SAndroid Build Coastguard Worker auto CheckedZextOrTrunc = [&](APInt &I) {
513*9880d681SAndroid Build Coastguard Worker // More bits than we can handle. Checking the bit width isn't necessary, but
514*9880d681SAndroid Build Coastguard Worker // it's faster than checking active bits, and should give `false` in the
515*9880d681SAndroid Build Coastguard Worker // vast majority of cases.
516*9880d681SAndroid Build Coastguard Worker if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
517*9880d681SAndroid Build Coastguard Worker return false;
518*9880d681SAndroid Build Coastguard Worker if (I.getBitWidth() != IntTyBits)
519*9880d681SAndroid Build Coastguard Worker I = I.zextOrTrunc(IntTyBits);
520*9880d681SAndroid Build Coastguard Worker return true;
521*9880d681SAndroid Build Coastguard Worker };
522*9880d681SAndroid Build Coastguard Worker
523*9880d681SAndroid Build Coastguard Worker APInt Size = Arg->getValue();
524*9880d681SAndroid Build Coastguard Worker if (!CheckedZextOrTrunc(Size))
525*9880d681SAndroid Build Coastguard Worker return unknown();
526*9880d681SAndroid Build Coastguard Worker
527*9880d681SAndroid Build Coastguard Worker // Size is determined by just 1 parameter.
528*9880d681SAndroid Build Coastguard Worker if (FnData->SndParam < 0)
529*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Zero);
530*9880d681SAndroid Build Coastguard Worker
531*9880d681SAndroid Build Coastguard Worker Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->SndParam));
532*9880d681SAndroid Build Coastguard Worker if (!Arg)
533*9880d681SAndroid Build Coastguard Worker return unknown();
534*9880d681SAndroid Build Coastguard Worker
535*9880d681SAndroid Build Coastguard Worker APInt NumElems = Arg->getValue();
536*9880d681SAndroid Build Coastguard Worker if (!CheckedZextOrTrunc(NumElems))
537*9880d681SAndroid Build Coastguard Worker return unknown();
538*9880d681SAndroid Build Coastguard Worker
539*9880d681SAndroid Build Coastguard Worker bool Overflow;
540*9880d681SAndroid Build Coastguard Worker Size = Size.umul_ov(NumElems, Overflow);
541*9880d681SAndroid Build Coastguard Worker return Overflow ? unknown() : std::make_pair(Size, Zero);
542*9880d681SAndroid Build Coastguard Worker
543*9880d681SAndroid Build Coastguard Worker // TODO: handle more standard functions (+ wchar cousins):
544*9880d681SAndroid Build Coastguard Worker // - strdup / strndup
545*9880d681SAndroid Build Coastguard Worker // - strcpy / strncpy
546*9880d681SAndroid Build Coastguard Worker // - strcat / strncat
547*9880d681SAndroid Build Coastguard Worker // - memcpy / memmove
548*9880d681SAndroid Build Coastguard Worker // - strcat / strncat
549*9880d681SAndroid Build Coastguard Worker // - memset
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker
552*9880d681SAndroid Build Coastguard Worker SizeOffsetType
visitConstantPointerNull(ConstantPointerNull &)553*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&) {
554*9880d681SAndroid Build Coastguard Worker return std::make_pair(Zero, Zero);
555*9880d681SAndroid Build Coastguard Worker }
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker SizeOffsetType
visitExtractElementInst(ExtractElementInst &)558*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst&) {
559*9880d681SAndroid Build Coastguard Worker return unknown();
560*9880d681SAndroid Build Coastguard Worker }
561*9880d681SAndroid Build Coastguard Worker
562*9880d681SAndroid Build Coastguard Worker SizeOffsetType
visitExtractValueInst(ExtractValueInst &)563*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) {
564*9880d681SAndroid Build Coastguard Worker // Easy cases were already folded by previous passes.
565*9880d681SAndroid Build Coastguard Worker return unknown();
566*9880d681SAndroid Build Coastguard Worker }
567*9880d681SAndroid Build Coastguard Worker
visitGEPOperator(GEPOperator & GEP)568*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) {
569*9880d681SAndroid Build Coastguard Worker SizeOffsetType PtrData = compute(GEP.getPointerOperand());
570*9880d681SAndroid Build Coastguard Worker APInt Offset(IntTyBits, 0);
571*9880d681SAndroid Build Coastguard Worker if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(DL, Offset))
572*9880d681SAndroid Build Coastguard Worker return unknown();
573*9880d681SAndroid Build Coastguard Worker
574*9880d681SAndroid Build Coastguard Worker return std::make_pair(PtrData.first, PtrData.second + Offset);
575*9880d681SAndroid Build Coastguard Worker }
576*9880d681SAndroid Build Coastguard Worker
visitGlobalAlias(GlobalAlias & GA)577*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) {
578*9880d681SAndroid Build Coastguard Worker if (GA.isInterposable())
579*9880d681SAndroid Build Coastguard Worker return unknown();
580*9880d681SAndroid Build Coastguard Worker return compute(GA.getAliasee());
581*9880d681SAndroid Build Coastguard Worker }
582*9880d681SAndroid Build Coastguard Worker
visitGlobalVariable(GlobalVariable & GV)583*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV){
584*9880d681SAndroid Build Coastguard Worker if (!GV.hasDefinitiveInitializer())
585*9880d681SAndroid Build Coastguard Worker return unknown();
586*9880d681SAndroid Build Coastguard Worker
587*9880d681SAndroid Build Coastguard Worker APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getType()->getElementType()));
588*9880d681SAndroid Build Coastguard Worker return std::make_pair(align(Size, GV.getAlignment()), Zero);
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker
visitIntToPtrInst(IntToPtrInst &)591*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) {
592*9880d681SAndroid Build Coastguard Worker // clueless
593*9880d681SAndroid Build Coastguard Worker return unknown();
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker
visitLoadInst(LoadInst &)596*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
597*9880d681SAndroid Build Coastguard Worker ++ObjectVisitorLoad;
598*9880d681SAndroid Build Coastguard Worker return unknown();
599*9880d681SAndroid Build Coastguard Worker }
600*9880d681SAndroid Build Coastguard Worker
visitPHINode(PHINode &)601*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
602*9880d681SAndroid Build Coastguard Worker // too complex to analyze statically.
603*9880d681SAndroid Build Coastguard Worker return unknown();
604*9880d681SAndroid Build Coastguard Worker }
605*9880d681SAndroid Build Coastguard Worker
visitSelectInst(SelectInst & I)606*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
607*9880d681SAndroid Build Coastguard Worker SizeOffsetType TrueSide = compute(I.getTrueValue());
608*9880d681SAndroid Build Coastguard Worker SizeOffsetType FalseSide = compute(I.getFalseValue());
609*9880d681SAndroid Build Coastguard Worker if (bothKnown(TrueSide) && bothKnown(FalseSide)) {
610*9880d681SAndroid Build Coastguard Worker if (TrueSide == FalseSide) {
611*9880d681SAndroid Build Coastguard Worker return TrueSide;
612*9880d681SAndroid Build Coastguard Worker }
613*9880d681SAndroid Build Coastguard Worker
614*9880d681SAndroid Build Coastguard Worker APInt TrueResult = getSizeWithOverflow(TrueSide);
615*9880d681SAndroid Build Coastguard Worker APInt FalseResult = getSizeWithOverflow(FalseSide);
616*9880d681SAndroid Build Coastguard Worker
617*9880d681SAndroid Build Coastguard Worker if (TrueResult == FalseResult) {
618*9880d681SAndroid Build Coastguard Worker return TrueSide;
619*9880d681SAndroid Build Coastguard Worker }
620*9880d681SAndroid Build Coastguard Worker if (Mode == ObjSizeMode::Min) {
621*9880d681SAndroid Build Coastguard Worker if (TrueResult.slt(FalseResult))
622*9880d681SAndroid Build Coastguard Worker return TrueSide;
623*9880d681SAndroid Build Coastguard Worker return FalseSide;
624*9880d681SAndroid Build Coastguard Worker }
625*9880d681SAndroid Build Coastguard Worker if (Mode == ObjSizeMode::Max) {
626*9880d681SAndroid Build Coastguard Worker if (TrueResult.sgt(FalseResult))
627*9880d681SAndroid Build Coastguard Worker return TrueSide;
628*9880d681SAndroid Build Coastguard Worker return FalseSide;
629*9880d681SAndroid Build Coastguard Worker }
630*9880d681SAndroid Build Coastguard Worker }
631*9880d681SAndroid Build Coastguard Worker return unknown();
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
visitUndefValue(UndefValue &)634*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {
635*9880d681SAndroid Build Coastguard Worker return std::make_pair(Zero, Zero);
636*9880d681SAndroid Build Coastguard Worker }
637*9880d681SAndroid Build Coastguard Worker
visitInstruction(Instruction & I)638*9880d681SAndroid Build Coastguard Worker SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
639*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n');
640*9880d681SAndroid Build Coastguard Worker return unknown();
641*9880d681SAndroid Build Coastguard Worker }
642*9880d681SAndroid Build Coastguard Worker
ObjectSizeOffsetEvaluator(const DataLayout & DL,const TargetLibraryInfo * TLI,LLVMContext & Context,bool RoundToAlign)643*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(
644*9880d681SAndroid Build Coastguard Worker const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
645*9880d681SAndroid Build Coastguard Worker bool RoundToAlign)
646*9880d681SAndroid Build Coastguard Worker : DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)),
647*9880d681SAndroid Build Coastguard Worker RoundToAlign(RoundToAlign) {
648*9880d681SAndroid Build Coastguard Worker // IntTy and Zero must be set for each compute() since the address space may
649*9880d681SAndroid Build Coastguard Worker // be different for later objects.
650*9880d681SAndroid Build Coastguard Worker }
651*9880d681SAndroid Build Coastguard Worker
compute(Value * V)652*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
653*9880d681SAndroid Build Coastguard Worker // XXX - Are vectors of pointers possible here?
654*9880d681SAndroid Build Coastguard Worker IntTy = cast<IntegerType>(DL.getIntPtrType(V->getType()));
655*9880d681SAndroid Build Coastguard Worker Zero = ConstantInt::get(IntTy, 0);
656*9880d681SAndroid Build Coastguard Worker
657*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType Result = compute_(V);
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker if (!bothKnown(Result)) {
660*9880d681SAndroid Build Coastguard Worker // Erase everything that was computed in this iteration from the cache, so
661*9880d681SAndroid Build Coastguard Worker // that no dangling references are left behind. We could be a bit smarter if
662*9880d681SAndroid Build Coastguard Worker // we kept a dependency graph. It's probably not worth the complexity.
663*9880d681SAndroid Build Coastguard Worker for (const Value *SeenVal : SeenVals) {
664*9880d681SAndroid Build Coastguard Worker CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal);
665*9880d681SAndroid Build Coastguard Worker // non-computable results can be safely cached
666*9880d681SAndroid Build Coastguard Worker if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
667*9880d681SAndroid Build Coastguard Worker CacheMap.erase(CacheIt);
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker }
670*9880d681SAndroid Build Coastguard Worker
671*9880d681SAndroid Build Coastguard Worker SeenVals.clear();
672*9880d681SAndroid Build Coastguard Worker return Result;
673*9880d681SAndroid Build Coastguard Worker }
674*9880d681SAndroid Build Coastguard Worker
compute_(Value * V)675*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
676*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign);
677*9880d681SAndroid Build Coastguard Worker SizeOffsetType Const = Visitor.compute(V);
678*9880d681SAndroid Build Coastguard Worker if (Visitor.bothKnown(Const))
679*9880d681SAndroid Build Coastguard Worker return std::make_pair(ConstantInt::get(Context, Const.first),
680*9880d681SAndroid Build Coastguard Worker ConstantInt::get(Context, Const.second));
681*9880d681SAndroid Build Coastguard Worker
682*9880d681SAndroid Build Coastguard Worker V = V->stripPointerCasts();
683*9880d681SAndroid Build Coastguard Worker
684*9880d681SAndroid Build Coastguard Worker // Check cache.
685*9880d681SAndroid Build Coastguard Worker CacheMapTy::iterator CacheIt = CacheMap.find(V);
686*9880d681SAndroid Build Coastguard Worker if (CacheIt != CacheMap.end())
687*9880d681SAndroid Build Coastguard Worker return CacheIt->second;
688*9880d681SAndroid Build Coastguard Worker
689*9880d681SAndroid Build Coastguard Worker // Always generate code immediately before the instruction being
690*9880d681SAndroid Build Coastguard Worker // processed, so that the generated code dominates the same BBs.
691*9880d681SAndroid Build Coastguard Worker BuilderTy::InsertPointGuard Guard(Builder);
692*9880d681SAndroid Build Coastguard Worker if (Instruction *I = dyn_cast<Instruction>(V))
693*9880d681SAndroid Build Coastguard Worker Builder.SetInsertPoint(I);
694*9880d681SAndroid Build Coastguard Worker
695*9880d681SAndroid Build Coastguard Worker // Now compute the size and offset.
696*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType Result;
697*9880d681SAndroid Build Coastguard Worker
698*9880d681SAndroid Build Coastguard Worker // Record the pointers that were handled in this run, so that they can be
699*9880d681SAndroid Build Coastguard Worker // cleaned later if something fails. We also use this set to break cycles that
700*9880d681SAndroid Build Coastguard Worker // can occur in dead code.
701*9880d681SAndroid Build Coastguard Worker if (!SeenVals.insert(V).second) {
702*9880d681SAndroid Build Coastguard Worker Result = unknown();
703*9880d681SAndroid Build Coastguard Worker } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
704*9880d681SAndroid Build Coastguard Worker Result = visitGEPOperator(*GEP);
705*9880d681SAndroid Build Coastguard Worker } else if (Instruction *I = dyn_cast<Instruction>(V)) {
706*9880d681SAndroid Build Coastguard Worker Result = visit(*I);
707*9880d681SAndroid Build Coastguard Worker } else if (isa<Argument>(V) ||
708*9880d681SAndroid Build Coastguard Worker (isa<ConstantExpr>(V) &&
709*9880d681SAndroid Build Coastguard Worker cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
710*9880d681SAndroid Build Coastguard Worker isa<GlobalAlias>(V) ||
711*9880d681SAndroid Build Coastguard Worker isa<GlobalVariable>(V)) {
712*9880d681SAndroid Build Coastguard Worker // Ignore values where we cannot do more than ObjectSizeVisitor.
713*9880d681SAndroid Build Coastguard Worker Result = unknown();
714*9880d681SAndroid Build Coastguard Worker } else {
715*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: "
716*9880d681SAndroid Build Coastguard Worker << *V << '\n');
717*9880d681SAndroid Build Coastguard Worker Result = unknown();
718*9880d681SAndroid Build Coastguard Worker }
719*9880d681SAndroid Build Coastguard Worker
720*9880d681SAndroid Build Coastguard Worker // Don't reuse CacheIt since it may be invalid at this point.
721*9880d681SAndroid Build Coastguard Worker CacheMap[V] = Result;
722*9880d681SAndroid Build Coastguard Worker return Result;
723*9880d681SAndroid Build Coastguard Worker }
724*9880d681SAndroid Build Coastguard Worker
visitAllocaInst(AllocaInst & I)725*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) {
726*9880d681SAndroid Build Coastguard Worker if (!I.getAllocatedType()->isSized())
727*9880d681SAndroid Build Coastguard Worker return unknown();
728*9880d681SAndroid Build Coastguard Worker
729*9880d681SAndroid Build Coastguard Worker // must be a VLA
730*9880d681SAndroid Build Coastguard Worker assert(I.isArrayAllocation());
731*9880d681SAndroid Build Coastguard Worker Value *ArraySize = I.getArraySize();
732*9880d681SAndroid Build Coastguard Worker Value *Size = ConstantInt::get(ArraySize->getType(),
733*9880d681SAndroid Build Coastguard Worker DL.getTypeAllocSize(I.getAllocatedType()));
734*9880d681SAndroid Build Coastguard Worker Size = Builder.CreateMul(Size, ArraySize);
735*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Zero);
736*9880d681SAndroid Build Coastguard Worker }
737*9880d681SAndroid Build Coastguard Worker
visitCallSite(CallSite CS)738*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitCallSite(CallSite CS) {
739*9880d681SAndroid Build Coastguard Worker Optional<AllocFnsTy> FnData =
740*9880d681SAndroid Build Coastguard Worker getAllocationData(CS.getInstruction(), AnyAlloc, TLI);
741*9880d681SAndroid Build Coastguard Worker if (!FnData)
742*9880d681SAndroid Build Coastguard Worker return unknown();
743*9880d681SAndroid Build Coastguard Worker
744*9880d681SAndroid Build Coastguard Worker // Handle strdup-like functions separately.
745*9880d681SAndroid Build Coastguard Worker if (FnData->AllocTy == StrDupLike) {
746*9880d681SAndroid Build Coastguard Worker // TODO
747*9880d681SAndroid Build Coastguard Worker return unknown();
748*9880d681SAndroid Build Coastguard Worker }
749*9880d681SAndroid Build Coastguard Worker
750*9880d681SAndroid Build Coastguard Worker Value *FirstArg = CS.getArgument(FnData->FstParam);
751*9880d681SAndroid Build Coastguard Worker FirstArg = Builder.CreateZExt(FirstArg, IntTy);
752*9880d681SAndroid Build Coastguard Worker if (FnData->SndParam < 0)
753*9880d681SAndroid Build Coastguard Worker return std::make_pair(FirstArg, Zero);
754*9880d681SAndroid Build Coastguard Worker
755*9880d681SAndroid Build Coastguard Worker Value *SecondArg = CS.getArgument(FnData->SndParam);
756*9880d681SAndroid Build Coastguard Worker SecondArg = Builder.CreateZExt(SecondArg, IntTy);
757*9880d681SAndroid Build Coastguard Worker Value *Size = Builder.CreateMul(FirstArg, SecondArg);
758*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Zero);
759*9880d681SAndroid Build Coastguard Worker
760*9880d681SAndroid Build Coastguard Worker // TODO: handle more standard functions (+ wchar cousins):
761*9880d681SAndroid Build Coastguard Worker // - strdup / strndup
762*9880d681SAndroid Build Coastguard Worker // - strcpy / strncpy
763*9880d681SAndroid Build Coastguard Worker // - strcat / strncat
764*9880d681SAndroid Build Coastguard Worker // - memcpy / memmove
765*9880d681SAndroid Build Coastguard Worker // - strcat / strncat
766*9880d681SAndroid Build Coastguard Worker // - memset
767*9880d681SAndroid Build Coastguard Worker }
768*9880d681SAndroid Build Coastguard Worker
769*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType
visitExtractElementInst(ExtractElementInst &)770*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst&) {
771*9880d681SAndroid Build Coastguard Worker return unknown();
772*9880d681SAndroid Build Coastguard Worker }
773*9880d681SAndroid Build Coastguard Worker
774*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType
visitExtractValueInst(ExtractValueInst &)775*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst&) {
776*9880d681SAndroid Build Coastguard Worker return unknown();
777*9880d681SAndroid Build Coastguard Worker }
778*9880d681SAndroid Build Coastguard Worker
779*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType
visitGEPOperator(GEPOperator & GEP)780*9880d681SAndroid Build Coastguard Worker ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) {
781*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand());
782*9880d681SAndroid Build Coastguard Worker if (!bothKnown(PtrData))
783*9880d681SAndroid Build Coastguard Worker return unknown();
784*9880d681SAndroid Build Coastguard Worker
785*9880d681SAndroid Build Coastguard Worker Value *Offset = EmitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
786*9880d681SAndroid Build Coastguard Worker Offset = Builder.CreateAdd(PtrData.second, Offset);
787*9880d681SAndroid Build Coastguard Worker return std::make_pair(PtrData.first, Offset);
788*9880d681SAndroid Build Coastguard Worker }
789*9880d681SAndroid Build Coastguard Worker
visitIntToPtrInst(IntToPtrInst &)790*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst&) {
791*9880d681SAndroid Build Coastguard Worker // clueless
792*9880d681SAndroid Build Coastguard Worker return unknown();
793*9880d681SAndroid Build Coastguard Worker }
794*9880d681SAndroid Build Coastguard Worker
visitLoadInst(LoadInst &)795*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst&) {
796*9880d681SAndroid Build Coastguard Worker return unknown();
797*9880d681SAndroid Build Coastguard Worker }
798*9880d681SAndroid Build Coastguard Worker
visitPHINode(PHINode & PHI)799*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) {
800*9880d681SAndroid Build Coastguard Worker // Create 2 PHIs: one for size and another for offset.
801*9880d681SAndroid Build Coastguard Worker PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
802*9880d681SAndroid Build Coastguard Worker PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
803*9880d681SAndroid Build Coastguard Worker
804*9880d681SAndroid Build Coastguard Worker // Insert right away in the cache to handle recursive PHIs.
805*9880d681SAndroid Build Coastguard Worker CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
806*9880d681SAndroid Build Coastguard Worker
807*9880d681SAndroid Build Coastguard Worker // Compute offset/size for each PHI incoming pointer.
808*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
809*9880d681SAndroid Build Coastguard Worker Builder.SetInsertPoint(&*PHI.getIncomingBlock(i)->getFirstInsertionPt());
810*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType EdgeData = compute_(PHI.getIncomingValue(i));
811*9880d681SAndroid Build Coastguard Worker
812*9880d681SAndroid Build Coastguard Worker if (!bothKnown(EdgeData)) {
813*9880d681SAndroid Build Coastguard Worker OffsetPHI->replaceAllUsesWith(UndefValue::get(IntTy));
814*9880d681SAndroid Build Coastguard Worker OffsetPHI->eraseFromParent();
815*9880d681SAndroid Build Coastguard Worker SizePHI->replaceAllUsesWith(UndefValue::get(IntTy));
816*9880d681SAndroid Build Coastguard Worker SizePHI->eraseFromParent();
817*9880d681SAndroid Build Coastguard Worker return unknown();
818*9880d681SAndroid Build Coastguard Worker }
819*9880d681SAndroid Build Coastguard Worker SizePHI->addIncoming(EdgeData.first, PHI.getIncomingBlock(i));
820*9880d681SAndroid Build Coastguard Worker OffsetPHI->addIncoming(EdgeData.second, PHI.getIncomingBlock(i));
821*9880d681SAndroid Build Coastguard Worker }
822*9880d681SAndroid Build Coastguard Worker
823*9880d681SAndroid Build Coastguard Worker Value *Size = SizePHI, *Offset = OffsetPHI, *Tmp;
824*9880d681SAndroid Build Coastguard Worker if ((Tmp = SizePHI->hasConstantValue())) {
825*9880d681SAndroid Build Coastguard Worker Size = Tmp;
826*9880d681SAndroid Build Coastguard Worker SizePHI->replaceAllUsesWith(Size);
827*9880d681SAndroid Build Coastguard Worker SizePHI->eraseFromParent();
828*9880d681SAndroid Build Coastguard Worker }
829*9880d681SAndroid Build Coastguard Worker if ((Tmp = OffsetPHI->hasConstantValue())) {
830*9880d681SAndroid Build Coastguard Worker Offset = Tmp;
831*9880d681SAndroid Build Coastguard Worker OffsetPHI->replaceAllUsesWith(Offset);
832*9880d681SAndroid Build Coastguard Worker OffsetPHI->eraseFromParent();
833*9880d681SAndroid Build Coastguard Worker }
834*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Offset);
835*9880d681SAndroid Build Coastguard Worker }
836*9880d681SAndroid Build Coastguard Worker
visitSelectInst(SelectInst & I)837*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) {
838*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType TrueSide = compute_(I.getTrueValue());
839*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());
840*9880d681SAndroid Build Coastguard Worker
841*9880d681SAndroid Build Coastguard Worker if (!bothKnown(TrueSide) || !bothKnown(FalseSide))
842*9880d681SAndroid Build Coastguard Worker return unknown();
843*9880d681SAndroid Build Coastguard Worker if (TrueSide == FalseSide)
844*9880d681SAndroid Build Coastguard Worker return TrueSide;
845*9880d681SAndroid Build Coastguard Worker
846*9880d681SAndroid Build Coastguard Worker Value *Size = Builder.CreateSelect(I.getCondition(), TrueSide.first,
847*9880d681SAndroid Build Coastguard Worker FalseSide.first);
848*9880d681SAndroid Build Coastguard Worker Value *Offset = Builder.CreateSelect(I.getCondition(), TrueSide.second,
849*9880d681SAndroid Build Coastguard Worker FalseSide.second);
850*9880d681SAndroid Build Coastguard Worker return std::make_pair(Size, Offset);
851*9880d681SAndroid Build Coastguard Worker }
852*9880d681SAndroid Build Coastguard Worker
visitInstruction(Instruction & I)853*9880d681SAndroid Build Coastguard Worker SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) {
854*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I <<'\n');
855*9880d681SAndroid Build Coastguard Worker return unknown();
856*9880d681SAndroid Build Coastguard Worker }
857