1198892Srdivacky//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===//
2198892Srdivacky//
3198892Srdivacky//                     The LLVM Compiler Infrastructure
4198892Srdivacky//
5198892Srdivacky// This file is distributed under the University of Illinois Open Source
6198892Srdivacky// License. See LICENSE.TXT for details.
7198892Srdivacky//
8198892Srdivacky//===----------------------------------------------------------------------===//
9198892Srdivacky//
10198892Srdivacky// This family of functions identifies calls to builtin functions that allocate
11249423Sdim// or free memory.
12198892Srdivacky//
13198892Srdivacky//===----------------------------------------------------------------------===//
14198892Srdivacky
15239462Sdim#define DEBUG_TYPE "memory-builtins"
16249423Sdim#include "llvm/Analysis/MemoryBuiltins.h"
17249423Sdim#include "llvm/ADT/STLExtras.h"
18239462Sdim#include "llvm/ADT/Statistic.h"
19199481Srdivacky#include "llvm/Analysis/ValueTracking.h"
20249423Sdim#include "llvm/IR/DataLayout.h"
21249423Sdim#include "llvm/IR/GlobalVariable.h"
22249423Sdim#include "llvm/IR/Instructions.h"
23249423Sdim#include "llvm/IR/Intrinsics.h"
24249423Sdim#include "llvm/IR/Metadata.h"
25249423Sdim#include "llvm/IR/Module.h"
26239462Sdim#include "llvm/Support/Debug.h"
27239462Sdim#include "llvm/Support/MathExtras.h"
28239462Sdim#include "llvm/Support/raw_ostream.h"
29243830Sdim#include "llvm/Target/TargetLibraryInfo.h"
30239462Sdim#include "llvm/Transforms/Utils/Local.h"
31198892Srdivackyusing namespace llvm;
32198892Srdivacky
33239462Sdimenum AllocType {
34239462Sdim  MallocLike         = 1<<0, // allocates
35239462Sdim  CallocLike         = 1<<1, // allocates + bzero
36239462Sdim  ReallocLike        = 1<<2, // reallocates
37239462Sdim  StrDupLike         = 1<<3,
38239462Sdim  AllocLike          = MallocLike | CallocLike | StrDupLike,
39239462Sdim  AnyAlloc           = MallocLike | CallocLike | ReallocLike | StrDupLike
40239462Sdim};
41198892Srdivacky
42239462Sdimstruct AllocFnsTy {
43243830Sdim  LibFunc::Func Func;
44239462Sdim  AllocType AllocTy;
45239462Sdim  unsigned char NumParams;
46239462Sdim  // First and Second size parameters (or -1 if unused)
47239462Sdim  signed char FstParam, SndParam;
48239462Sdim};
49239462Sdim
50239462Sdim// FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
51239462Sdim// know which functions are nounwind, noalias, nocapture parameters, etc.
52239462Sdimstatic const AllocFnsTy AllocationFnData[] = {
53243830Sdim  {LibFunc::malloc,              MallocLike,  1, 0,  -1},
54243830Sdim  {LibFunc::valloc,              MallocLike,  1, 0,  -1},
55243830Sdim  {LibFunc::Znwj,                MallocLike,  1, 0,  -1}, // new(unsigned int)
56243830Sdim  {LibFunc::ZnwjRKSt9nothrow_t,  MallocLike,  2, 0,  -1}, // new(unsigned int, nothrow)
57243830Sdim  {LibFunc::Znwm,                MallocLike,  1, 0,  -1}, // new(unsigned long)
58243830Sdim  {LibFunc::ZnwmRKSt9nothrow_t,  MallocLike,  2, 0,  -1}, // new(unsigned long, nothrow)
59243830Sdim  {LibFunc::Znaj,                MallocLike,  1, 0,  -1}, // new[](unsigned int)
60243830Sdim  {LibFunc::ZnajRKSt9nothrow_t,  MallocLike,  2, 0,  -1}, // new[](unsigned int, nothrow)
61243830Sdim  {LibFunc::Znam,                MallocLike,  1, 0,  -1}, // new[](unsigned long)
62243830Sdim  {LibFunc::ZnamRKSt9nothrow_t,  MallocLike,  2, 0,  -1}, // new[](unsigned long, nothrow)
63243830Sdim  {LibFunc::posix_memalign,      MallocLike,  3, 2,  -1},
64243830Sdim  {LibFunc::calloc,              CallocLike,  2, 0,   1},
65243830Sdim  {LibFunc::realloc,             ReallocLike, 2, 1,  -1},
66243830Sdim  {LibFunc::reallocf,            ReallocLike, 2, 1,  -1},
67243830Sdim  {LibFunc::strdup,              StrDupLike,  1, -1, -1},
68243830Sdim  {LibFunc::strndup,             StrDupLike,  2, 1,  -1}
69239462Sdim};
70239462Sdim
71239462Sdim
72239462Sdimstatic Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
73239462Sdim  if (LookThroughBitCast)
74239462Sdim    V = V->stripPointerCasts();
75239462Sdim
76239462Sdim  CallSite CS(const_cast<Value*>(V));
77239462Sdim  if (!CS.getInstruction())
78239462Sdim    return 0;
79239462Sdim
80239462Sdim  Function *Callee = CS.getCalledFunction();
81239462Sdim  if (!Callee || !Callee->isDeclaration())
82239462Sdim    return 0;
83239462Sdim  return Callee;
84198892Srdivacky}
85198892Srdivacky
86239462Sdim/// \brief Returns the allocation data for the given value if it is a call to a
87239462Sdim/// known allocation function, and NULL otherwise.
88239462Sdimstatic const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy,
89243830Sdim                                           const TargetLibraryInfo *TLI,
90239462Sdim                                           bool LookThroughBitCast = false) {
91249423Sdim  // Skip intrinsics
92249423Sdim  if (isa<IntrinsicInst>(V))
93249423Sdim    return 0;
94249423Sdim
95239462Sdim  Function *Callee = getCalledFunction(V, LookThroughBitCast);
96239462Sdim  if (!Callee)
97239462Sdim    return 0;
98198892Srdivacky
99243830Sdim  // Make sure that the function is available.
100243830Sdim  StringRef FnName = Callee->getName();
101243830Sdim  LibFunc::Func TLIFn;
102243830Sdim  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
103243830Sdim    return 0;
104243830Sdim
105239462Sdim  unsigned i = 0;
106239462Sdim  bool found = false;
107239462Sdim  for ( ; i < array_lengthof(AllocationFnData); ++i) {
108243830Sdim    if (AllocationFnData[i].Func == TLIFn) {
109239462Sdim      found = true;
110239462Sdim      break;
111239462Sdim    }
112239462Sdim  }
113239462Sdim  if (!found)
114239462Sdim    return 0;
115198892Srdivacky
116239462Sdim  const AllocFnsTy *FnData = &AllocationFnData[i];
117239462Sdim  if ((FnData->AllocTy & AllocTy) == 0)
118239462Sdim    return 0;
119239462Sdim
120239462Sdim  // Check function prototype.
121239462Sdim  int FstParam = FnData->FstParam;
122239462Sdim  int SndParam = FnData->SndParam;
123226633Sdim  FunctionType *FTy = Callee->getFunctionType();
124239462Sdim
125239462Sdim  if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
126239462Sdim      FTy->getNumParams() == FnData->NumParams &&
127239462Sdim      (FstParam < 0 ||
128239462Sdim       (FTy->getParamType(FstParam)->isIntegerTy(32) ||
129239462Sdim        FTy->getParamType(FstParam)->isIntegerTy(64))) &&
130239462Sdim      (SndParam < 0 ||
131239462Sdim       FTy->getParamType(SndParam)->isIntegerTy(32) ||
132239462Sdim       FTy->getParamType(SndParam)->isIntegerTy(64)))
133239462Sdim    return FnData;
134239462Sdim  return 0;
135198892Srdivacky}
136198892Srdivacky
137239462Sdimstatic bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) {
138239462Sdim  ImmutableCallSite CS(LookThroughBitCast ? V->stripPointerCasts() : V);
139249423Sdim  return CS && CS.hasFnAttr(Attribute::NoAlias);
140198892Srdivacky}
141198892Srdivacky
142239462Sdim
143239462Sdim/// \brief Tests if a value is a call or invoke to a library function that
144239462Sdim/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
145239462Sdim/// like).
146243830Sdimbool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
147243830Sdim                          bool LookThroughBitCast) {
148243830Sdim  return getAllocationData(V, AnyAlloc, TLI, LookThroughBitCast);
149198892Srdivacky}
150198892Srdivacky
151239462Sdim/// \brief Tests if a value is a call or invoke to a function that returns a
152239462Sdim/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
153243830Sdimbool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
154243830Sdim                       bool LookThroughBitCast) {
155239462Sdim  // it's safe to consider realloc as noalias since accessing the original
156239462Sdim  // pointer is undefined behavior
157243830Sdim  return isAllocationFn(V, TLI, LookThroughBitCast) ||
158239462Sdim         hasNoAliasAttr(V, LookThroughBitCast);
159198892Srdivacky}
160198892Srdivacky
161239462Sdim/// \brief Tests if a value is a call or invoke to a library function that
162239462Sdim/// allocates uninitialized memory (such as malloc).
163243830Sdimbool llvm::isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
164243830Sdim                          bool LookThroughBitCast) {
165243830Sdim  return getAllocationData(V, MallocLike, TLI, LookThroughBitCast);
166198892Srdivacky}
167198892Srdivacky
168239462Sdim/// \brief Tests if a value is a call or invoke to a library function that
169239462Sdim/// allocates zero-filled memory (such as calloc).
170243830Sdimbool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
171243830Sdim                          bool LookThroughBitCast) {
172243830Sdim  return getAllocationData(V, CallocLike, TLI, LookThroughBitCast);
173198892Srdivacky}
174198892Srdivacky
175239462Sdim/// \brief Tests if a value is a call or invoke to a library function that
176239462Sdim/// allocates memory (either malloc, calloc, or strdup like).
177243830Sdimbool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
178243830Sdim                         bool LookThroughBitCast) {
179243830Sdim  return getAllocationData(V, AllocLike, TLI, LookThroughBitCast);
180239462Sdim}
181239462Sdim
182239462Sdim/// \brief Tests if a value is a call or invoke to a library function that
183239462Sdim/// reallocates memory (such as realloc).
184243830Sdimbool llvm::isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
185243830Sdim                           bool LookThroughBitCast) {
186243830Sdim  return getAllocationData(V, ReallocLike, TLI, LookThroughBitCast);
187239462Sdim}
188239462Sdim
189239462Sdim/// extractMallocCall - Returns the corresponding CallInst if the instruction
190239462Sdim/// is a malloc call.  Since CallInst::CreateMalloc() only creates calls, we
191239462Sdim/// ignore InvokeInst here.
192243830Sdimconst CallInst *llvm::extractMallocCall(const Value *I,
193243830Sdim                                        const TargetLibraryInfo *TLI) {
194243830Sdim  return isMallocLikeFn(I, TLI) ? dyn_cast<CallInst>(I) : 0;
195239462Sdim}
196239462Sdim
197243830Sdimstatic Value *computeArraySize(const CallInst *CI, const DataLayout *TD,
198243830Sdim                               const TargetLibraryInfo *TLI,
199199481Srdivacky                               bool LookThroughSExt = false) {
200198892Srdivacky  if (!CI)
201249423Sdim    return 0;
202198892Srdivacky
203198953Srdivacky  // The size of the malloc's result type must be known to determine array size.
204243830Sdim  Type *T = getMallocAllocatedType(CI, TLI);
205198953Srdivacky  if (!T || !T->isSized() || !TD)
206249423Sdim    return 0;
207198892Srdivacky
208199481Srdivacky  unsigned ElementSize = TD->getTypeAllocSize(T);
209226633Sdim  if (StructType *ST = dyn_cast<StructType>(T))
210199481Srdivacky    ElementSize = TD->getStructLayout(ST)->getSizeInBytes();
211198892Srdivacky
212210299Sed  // If malloc call's arg can be determined to be a multiple of ElementSize,
213199481Srdivacky  // return the multiple.  Otherwise, return NULL.
214210299Sed  Value *MallocArg = CI->getArgOperand(0);
215249423Sdim  Value *Multiple = 0;
216199481Srdivacky  if (ComputeMultiple(MallocArg, ElementSize, Multiple,
217199481Srdivacky                      LookThroughSExt))
218199481Srdivacky    return Multiple;
219198892Srdivacky
220249423Sdim  return 0;
221198892Srdivacky}
222198892Srdivacky
223249423Sdim/// isArrayMalloc - Returns the corresponding CallInst if the instruction
224198892Srdivacky/// is a call to malloc whose array size can be determined and the array size
225198892Srdivacky/// is not constant 1.  Otherwise, return NULL.
226243830Sdimconst CallInst *llvm::isArrayMalloc(const Value *I,
227243830Sdim                                    const DataLayout *TD,
228243830Sdim                                    const TargetLibraryInfo *TLI) {
229243830Sdim  const CallInst *CI = extractMallocCall(I, TLI);
230243830Sdim  Value *ArraySize = computeArraySize(CI, TD, TLI);
231198892Srdivacky
232249423Sdim  if (ConstantInt *ConstSize = dyn_cast_or_null<ConstantInt>(ArraySize))
233249423Sdim    if (ConstSize->isOne())
234249423Sdim      return CI;
235198892Srdivacky
236198892Srdivacky  // CI is a non-array malloc or we can't figure out that it is an array malloc.
237249423Sdim  return 0;
238198892Srdivacky}
239198892Srdivacky
240198892Srdivacky/// getMallocType - Returns the PointerType resulting from the malloc call.
241198953Srdivacky/// The PointerType depends on the number of bitcast uses of the malloc call:
242198953Srdivacky///   0: PointerType is the calls' return type.
243198953Srdivacky///   1: PointerType is the bitcast's result type.
244198953Srdivacky///  >1: Unique PointerType cannot be determined, return NULL.
245243830SdimPointerType *llvm::getMallocType(const CallInst *CI,
246243830Sdim                                 const TargetLibraryInfo *TLI) {
247243830Sdim  assert(isMallocLikeFn(CI, TLI) && "getMallocType and not malloc call");
248249423Sdim
249249423Sdim  PointerType *MallocType = 0;
250198953Srdivacky  unsigned NumOfBitCastUses = 0;
251198953Srdivacky
252198892Srdivacky  // Determine if CallInst has a bitcast use.
253206083Srdivacky  for (Value::const_use_iterator UI = CI->use_begin(), E = CI->use_end();
254198892Srdivacky       UI != E; )
255198953Srdivacky    if (const BitCastInst *BCI = dyn_cast<BitCastInst>(*UI++)) {
256198953Srdivacky      MallocType = cast<PointerType>(BCI->getDestTy());
257198953Srdivacky      NumOfBitCastUses++;
258198953Srdivacky    }
259198892Srdivacky
260198953Srdivacky  // Malloc call has 1 bitcast use, so type is the bitcast's destination type.
261198953Srdivacky  if (NumOfBitCastUses == 1)
262198953Srdivacky    return MallocType;
263198892Srdivacky
264198892Srdivacky  // Malloc call was not bitcast, so type is the malloc function's return type.
265198953Srdivacky  if (NumOfBitCastUses == 0)
266198892Srdivacky    return cast<PointerType>(CI->getType());
267198892Srdivacky
268198892Srdivacky  // Type could not be determined.
269249423Sdim  return 0;
270198892Srdivacky}
271198892Srdivacky
272198953Srdivacky/// getMallocAllocatedType - Returns the Type allocated by malloc call.
273198953Srdivacky/// The Type depends on the number of bitcast uses of the malloc call:
274198953Srdivacky///   0: PointerType is the malloc calls' return type.
275198953Srdivacky///   1: PointerType is the bitcast's result type.
276198953Srdivacky///  >1: Unique PointerType cannot be determined, return NULL.
277243830SdimType *llvm::getMallocAllocatedType(const CallInst *CI,
278243830Sdim                                   const TargetLibraryInfo *TLI) {
279243830Sdim  PointerType *PT = getMallocType(CI, TLI);
280249423Sdim  return PT ? PT->getElementType() : 0;
281198892Srdivacky}
282198892Srdivacky
283249423Sdim/// getMallocArraySize - Returns the array size of a malloc call.  If the
284198892Srdivacky/// argument passed to malloc is a multiple of the size of the malloced type,
285198892Srdivacky/// then return that multiple.  For non-array mallocs, the multiple is
286198892Srdivacky/// constant 1.  Otherwise, return NULL for mallocs whose array size cannot be
287198892Srdivacky/// determined.
288243830SdimValue *llvm::getMallocArraySize(CallInst *CI, const DataLayout *TD,
289243830Sdim                                const TargetLibraryInfo *TLI,
290199481Srdivacky                                bool LookThroughSExt) {
291243830Sdim  assert(isMallocLikeFn(CI, TLI) && "getMallocArraySize and not malloc call");
292243830Sdim  return computeArraySize(CI, TD, TLI, LookThroughSExt);
293198892Srdivacky}
294198892Srdivacky
295198892Srdivacky
296239462Sdim/// extractCallocCall - Returns the corresponding CallInst if the instruction
297239462Sdim/// is a calloc call.
298243830Sdimconst CallInst *llvm::extractCallocCall(const Value *I,
299243830Sdim                                        const TargetLibraryInfo *TLI) {
300243830Sdim  return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : 0;
301239462Sdim}
302239462Sdim
303239462Sdim
304210299Sed/// isFreeCall - Returns non-null if the value is a call to the builtin free()
305243830Sdimconst CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
306198892Srdivacky  const CallInst *CI = dyn_cast<CallInst>(I);
307249423Sdim  if (!CI || isa<IntrinsicInst>(CI))
308210299Sed    return 0;
309198892Srdivacky  Function *Callee = CI->getCalledFunction();
310221345Sdim  if (Callee == 0 || !Callee->isDeclaration())
311210299Sed    return 0;
312198892Srdivacky
313243830Sdim  StringRef FnName = Callee->getName();
314243830Sdim  LibFunc::Func TLIFn;
315243830Sdim  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
316221345Sdim    return 0;
317221345Sdim
318243830Sdim  if (TLIFn != LibFunc::free &&
319243830Sdim      TLIFn != LibFunc::ZdlPv && // operator delete(void*)
320243830Sdim      TLIFn != LibFunc::ZdaPv)   // operator delete[](void*)
321243830Sdim    return 0;
322243830Sdim
323198892Srdivacky  // Check free prototype.
324249423Sdim  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
325198892Srdivacky  // attribute will exist.
326226633Sdim  FunctionType *FTy = Callee->getFunctionType();
327198892Srdivacky  if (!FTy->getReturnType()->isVoidTy())
328210299Sed    return 0;
329198892Srdivacky  if (FTy->getNumParams() != 1)
330210299Sed    return 0;
331224145Sdim  if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
332210299Sed    return 0;
333198892Srdivacky
334210299Sed  return CI;
335198892Srdivacky}
336239462Sdim
337239462Sdim
338239462Sdim
339239462Sdim//===----------------------------------------------------------------------===//
340239462Sdim//  Utility functions to compute size of objects.
341239462Sdim//
342239462Sdim
343239462Sdim
344239462Sdim/// \brief Compute the size of the object pointed by Ptr. Returns true and the
345239462Sdim/// object size in Size if successful, and false otherwise.
346239462Sdim/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
347239462Sdim/// byval arguments, and global variables.
348243830Sdimbool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD,
349243830Sdim                         const TargetLibraryInfo *TLI, bool RoundToAlign) {
350239462Sdim  if (!TD)
351239462Sdim    return false;
352239462Sdim
353243830Sdim  ObjectSizeOffsetVisitor Visitor(TD, TLI, Ptr->getContext(), RoundToAlign);
354239462Sdim  SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
355239462Sdim  if (!Visitor.bothKnown(Data))
356239462Sdim    return false;
357239462Sdim
358239462Sdim  APInt ObjSize = Data.first, Offset = Data.second;
359239462Sdim  // check for overflow
360239462Sdim  if (Offset.slt(0) || ObjSize.ult(Offset))
361239462Sdim    Size = 0;
362239462Sdim  else
363239462Sdim    Size = (ObjSize - Offset).getZExtValue();
364239462Sdim  return true;
365239462Sdim}
366239462Sdim
367239462Sdim
368239462SdimSTATISTIC(ObjectVisitorArgument,
369239462Sdim          "Number of arguments with unsolved size and offset");
370239462SdimSTATISTIC(ObjectVisitorLoad,
371239462Sdim          "Number of load instructions with unsolved size and offset");
372239462Sdim
373239462Sdim
374239462SdimAPInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
375239462Sdim  if (RoundToAlign && Align)
376239462Sdim    return APInt(IntTyBits, RoundUpToAlignment(Size.getZExtValue(), Align));
377239462Sdim  return Size;
378239462Sdim}
379239462Sdim
380243830SdimObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout *TD,
381243830Sdim                                                 const TargetLibraryInfo *TLI,
382239462Sdim                                                 LLVMContext &Context,
383239462Sdim                                                 bool RoundToAlign)
384243830Sdim: TD(TD), TLI(TLI), RoundToAlign(RoundToAlign) {
385239462Sdim  IntegerType *IntTy = TD->getIntPtrType(Context);
386239462Sdim  IntTyBits = IntTy->getBitWidth();
387239462Sdim  Zero = APInt::getNullValue(IntTyBits);
388239462Sdim}
389239462Sdim
390239462SdimSizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
391239462Sdim  V = V->stripPointerCasts();
392251662Sdim  if (Instruction *I = dyn_cast<Instruction>(V)) {
393251662Sdim    // If we have already seen this instruction, bail out. Cycles can happen in
394251662Sdim    // unreachable code after constant propagation.
395251662Sdim    if (!SeenInsts.insert(I))
396251662Sdim      return unknown();
397239462Sdim
398243830Sdim    if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
399251662Sdim      return visitGEPOperator(*GEP);
400251662Sdim    return visit(*I);
401243830Sdim  }
402239462Sdim  if (Argument *A = dyn_cast<Argument>(V))
403239462Sdim    return visitArgument(*A);
404239462Sdim  if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
405239462Sdim    return visitConstantPointerNull(*P);
406249423Sdim  if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
407249423Sdim    return visitGlobalAlias(*GA);
408239462Sdim  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
409239462Sdim    return visitGlobalVariable(*GV);
410239462Sdim  if (UndefValue *UV = dyn_cast<UndefValue>(V))
411239462Sdim    return visitUndefValue(*UV);
412243830Sdim  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
413239462Sdim    if (CE->getOpcode() == Instruction::IntToPtr)
414239462Sdim      return unknown(); // clueless
415251662Sdim    if (CE->getOpcode() == Instruction::GetElementPtr)
416251662Sdim      return visitGEPOperator(cast<GEPOperator>(*CE));
417243830Sdim  }
418239462Sdim
419239462Sdim  DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V
420239462Sdim        << '\n');
421239462Sdim  return unknown();
422239462Sdim}
423239462Sdim
424239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
425239462Sdim  if (!I.getAllocatedType()->isSized())
426239462Sdim    return unknown();
427239462Sdim
428239462Sdim  APInt Size(IntTyBits, TD->getTypeAllocSize(I.getAllocatedType()));
429239462Sdim  if (!I.isArrayAllocation())
430239462Sdim    return std::make_pair(align(Size, I.getAlignment()), Zero);
431239462Sdim
432239462Sdim  Value *ArraySize = I.getArraySize();
433239462Sdim  if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
434239462Sdim    Size *= C->getValue().zextOrSelf(IntTyBits);
435239462Sdim    return std::make_pair(align(Size, I.getAlignment()), Zero);
436239462Sdim  }
437239462Sdim  return unknown();
438239462Sdim}
439239462Sdim
440239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
441239462Sdim  // no interprocedural analysis is done at the moment
442239462Sdim  if (!A.hasByValAttr()) {
443239462Sdim    ++ObjectVisitorArgument;
444239462Sdim    return unknown();
445239462Sdim  }
446239462Sdim  PointerType *PT = cast<PointerType>(A.getType());
447239462Sdim  APInt Size(IntTyBits, TD->getTypeAllocSize(PT->getElementType()));
448239462Sdim  return std::make_pair(align(Size, A.getParamAlignment()), Zero);
449239462Sdim}
450239462Sdim
451239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
452243830Sdim  const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(), AnyAlloc,
453243830Sdim                                               TLI);
454239462Sdim  if (!FnData)
455239462Sdim    return unknown();
456239462Sdim
457239462Sdim  // handle strdup-like functions separately
458239462Sdim  if (FnData->AllocTy == StrDupLike) {
459239462Sdim    APInt Size(IntTyBits, GetStringLength(CS.getArgument(0)));
460239462Sdim    if (!Size)
461239462Sdim      return unknown();
462239462Sdim
463239462Sdim    // strndup limits strlen
464239462Sdim    if (FnData->FstParam > 0) {
465239462Sdim      ConstantInt *Arg= dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
466239462Sdim      if (!Arg)
467239462Sdim        return unknown();
468239462Sdim
469239462Sdim      APInt MaxSize = Arg->getValue().zextOrSelf(IntTyBits);
470239462Sdim      if (Size.ugt(MaxSize))
471239462Sdim        Size = MaxSize + 1;
472239462Sdim    }
473239462Sdim    return std::make_pair(Size, Zero);
474239462Sdim  }
475239462Sdim
476239462Sdim  ConstantInt *Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
477239462Sdim  if (!Arg)
478239462Sdim    return unknown();
479239462Sdim
480239462Sdim  APInt Size = Arg->getValue().zextOrSelf(IntTyBits);
481239462Sdim  // size determined by just 1 parameter
482239462Sdim  if (FnData->SndParam < 0)
483239462Sdim    return std::make_pair(Size, Zero);
484239462Sdim
485239462Sdim  Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->SndParam));
486239462Sdim  if (!Arg)
487239462Sdim    return unknown();
488239462Sdim
489239462Sdim  Size *= Arg->getValue().zextOrSelf(IntTyBits);
490239462Sdim  return std::make_pair(Size, Zero);
491239462Sdim
492239462Sdim  // TODO: handle more standard functions (+ wchar cousins):
493239462Sdim  // - strdup / strndup
494239462Sdim  // - strcpy / strncpy
495239462Sdim  // - strcat / strncat
496239462Sdim  // - memcpy / memmove
497239462Sdim  // - strcat / strncat
498239462Sdim  // - memset
499239462Sdim}
500239462Sdim
501239462SdimSizeOffsetType
502239462SdimObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&) {
503239462Sdim  return std::make_pair(Zero, Zero);
504239462Sdim}
505239462Sdim
506239462SdimSizeOffsetType
507239462SdimObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst&) {
508239462Sdim  return unknown();
509239462Sdim}
510239462Sdim
511239462SdimSizeOffsetType
512239462SdimObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) {
513239462Sdim  // Easy cases were already folded by previous passes.
514239462Sdim  return unknown();
515239462Sdim}
516239462Sdim
517239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) {
518239462Sdim  SizeOffsetType PtrData = compute(GEP.getPointerOperand());
519249423Sdim  APInt Offset(IntTyBits, 0);
520249423Sdim  if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(*TD, Offset))
521239462Sdim    return unknown();
522239462Sdim
523239462Sdim  return std::make_pair(PtrData.first, PtrData.second + Offset);
524239462Sdim}
525239462Sdim
526249423SdimSizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) {
527249423Sdim  if (GA.mayBeOverridden())
528249423Sdim    return unknown();
529249423Sdim  return compute(GA.getAliasee());
530249423Sdim}
531249423Sdim
532239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV){
533239462Sdim  if (!GV.hasDefinitiveInitializer())
534239462Sdim    return unknown();
535239462Sdim
536239462Sdim  APInt Size(IntTyBits, TD->getTypeAllocSize(GV.getType()->getElementType()));
537239462Sdim  return std::make_pair(align(Size, GV.getAlignment()), Zero);
538239462Sdim}
539239462Sdim
540239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) {
541239462Sdim  // clueless
542239462Sdim  return unknown();
543239462Sdim}
544239462Sdim
545239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
546239462Sdim  ++ObjectVisitorLoad;
547239462Sdim  return unknown();
548239462Sdim}
549239462Sdim
550251662SdimSizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
551251662Sdim  // too complex to analyze statically.
552251662Sdim  return unknown();
553239462Sdim}
554239462Sdim
555239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
556239462Sdim  SizeOffsetType TrueSide  = compute(I.getTrueValue());
557239462Sdim  SizeOffsetType FalseSide = compute(I.getFalseValue());
558239462Sdim  if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide == FalseSide)
559239462Sdim    return TrueSide;
560239462Sdim  return unknown();
561239462Sdim}
562239462Sdim
563239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {
564239462Sdim  return std::make_pair(Zero, Zero);
565239462Sdim}
566239462Sdim
567239462SdimSizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
568239462Sdim  DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n');
569239462Sdim  return unknown();
570239462Sdim}
571239462Sdim
572239462Sdim
573243830SdimObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const DataLayout *TD,
574243830Sdim                                                   const TargetLibraryInfo *TLI,
575239462Sdim                                                     LLVMContext &Context)
576243830Sdim: TD(TD), TLI(TLI), Context(Context), Builder(Context, TargetFolder(TD)) {
577239462Sdim  IntTy = TD->getIntPtrType(Context);
578239462Sdim  Zero = ConstantInt::get(IntTy, 0);
579239462Sdim}
580239462Sdim
581239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
582239462Sdim  SizeOffsetEvalType Result = compute_(V);
583239462Sdim
584239462Sdim  if (!bothKnown(Result)) {
585239462Sdim    // erase everything that was computed in this iteration from the cache, so
586239462Sdim    // that no dangling references are left behind. We could be a bit smarter if
587239462Sdim    // we kept a dependency graph. It's probably not worth the complexity.
588239462Sdim    for (PtrSetTy::iterator I=SeenVals.begin(), E=SeenVals.end(); I != E; ++I) {
589239462Sdim      CacheMapTy::iterator CacheIt = CacheMap.find(*I);
590239462Sdim      // non-computable results can be safely cached
591239462Sdim      if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
592239462Sdim        CacheMap.erase(CacheIt);
593239462Sdim    }
594239462Sdim  }
595239462Sdim
596239462Sdim  SeenVals.clear();
597239462Sdim  return Result;
598239462Sdim}
599239462Sdim
600239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
601243830Sdim  ObjectSizeOffsetVisitor Visitor(TD, TLI, Context);
602239462Sdim  SizeOffsetType Const = Visitor.compute(V);
603239462Sdim  if (Visitor.bothKnown(Const))
604239462Sdim    return std::make_pair(ConstantInt::get(Context, Const.first),
605239462Sdim                          ConstantInt::get(Context, Const.second));
606239462Sdim
607239462Sdim  V = V->stripPointerCasts();
608239462Sdim
609239462Sdim  // check cache
610239462Sdim  CacheMapTy::iterator CacheIt = CacheMap.find(V);
611239462Sdim  if (CacheIt != CacheMap.end())
612239462Sdim    return CacheIt->second;
613239462Sdim
614239462Sdim  // always generate code immediately before the instruction being
615239462Sdim  // processed, so that the generated code dominates the same BBs
616239462Sdim  Instruction *PrevInsertPoint = Builder.GetInsertPoint();
617239462Sdim  if (Instruction *I = dyn_cast<Instruction>(V))
618239462Sdim    Builder.SetInsertPoint(I);
619239462Sdim
620239462Sdim  // record the pointers that were handled in this run, so that they can be
621239462Sdim  // cleaned later if something fails
622239462Sdim  SeenVals.insert(V);
623239462Sdim
624239462Sdim  // now compute the size and offset
625239462Sdim  SizeOffsetEvalType Result;
626239462Sdim  if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
627239462Sdim    Result = visitGEPOperator(*GEP);
628239462Sdim  } else if (Instruction *I = dyn_cast<Instruction>(V)) {
629239462Sdim    Result = visit(*I);
630239462Sdim  } else if (isa<Argument>(V) ||
631239462Sdim             (isa<ConstantExpr>(V) &&
632239462Sdim              cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
633249423Sdim             isa<GlobalAlias>(V) ||
634239462Sdim             isa<GlobalVariable>(V)) {
635239462Sdim    // ignore values where we cannot do more than what ObjectSizeVisitor can
636239462Sdim    Result = unknown();
637239462Sdim  } else {
638239462Sdim    DEBUG(dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: "
639239462Sdim          << *V << '\n');
640239462Sdim    Result = unknown();
641239462Sdim  }
642239462Sdim
643239462Sdim  if (PrevInsertPoint)
644239462Sdim    Builder.SetInsertPoint(PrevInsertPoint);
645239462Sdim
646239462Sdim  // Don't reuse CacheIt since it may be invalid at this point.
647239462Sdim  CacheMap[V] = Result;
648239462Sdim  return Result;
649239462Sdim}
650239462Sdim
651239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) {
652239462Sdim  if (!I.getAllocatedType()->isSized())
653239462Sdim    return unknown();
654239462Sdim
655239462Sdim  // must be a VLA
656239462Sdim  assert(I.isArrayAllocation());
657239462Sdim  Value *ArraySize = I.getArraySize();
658239462Sdim  Value *Size = ConstantInt::get(ArraySize->getType(),
659239462Sdim                                 TD->getTypeAllocSize(I.getAllocatedType()));
660239462Sdim  Size = Builder.CreateMul(Size, ArraySize);
661239462Sdim  return std::make_pair(Size, Zero);
662239462Sdim}
663239462Sdim
664239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitCallSite(CallSite CS) {
665243830Sdim  const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(), AnyAlloc,
666243830Sdim                                               TLI);
667239462Sdim  if (!FnData)
668239462Sdim    return unknown();
669239462Sdim
670239462Sdim  // handle strdup-like functions separately
671239462Sdim  if (FnData->AllocTy == StrDupLike) {
672239462Sdim    // TODO
673239462Sdim    return unknown();
674239462Sdim  }
675239462Sdim
676239462Sdim  Value *FirstArg = CS.getArgument(FnData->FstParam);
677239462Sdim  FirstArg = Builder.CreateZExt(FirstArg, IntTy);
678239462Sdim  if (FnData->SndParam < 0)
679239462Sdim    return std::make_pair(FirstArg, Zero);
680239462Sdim
681239462Sdim  Value *SecondArg = CS.getArgument(FnData->SndParam);
682239462Sdim  SecondArg = Builder.CreateZExt(SecondArg, IntTy);
683239462Sdim  Value *Size = Builder.CreateMul(FirstArg, SecondArg);
684239462Sdim  return std::make_pair(Size, Zero);
685239462Sdim
686239462Sdim  // TODO: handle more standard functions (+ wchar cousins):
687239462Sdim  // - strdup / strndup
688239462Sdim  // - strcpy / strncpy
689239462Sdim  // - strcat / strncat
690239462Sdim  // - memcpy / memmove
691239462Sdim  // - strcat / strncat
692239462Sdim  // - memset
693239462Sdim}
694239462Sdim
695239462SdimSizeOffsetEvalType
696239462SdimObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst&) {
697239462Sdim  return unknown();
698239462Sdim}
699239462Sdim
700239462SdimSizeOffsetEvalType
701239462SdimObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst&) {
702239462Sdim  return unknown();
703239462Sdim}
704239462Sdim
705239462SdimSizeOffsetEvalType
706239462SdimObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) {
707239462Sdim  SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand());
708239462Sdim  if (!bothKnown(PtrData))
709239462Sdim    return unknown();
710239462Sdim
711239462Sdim  Value *Offset = EmitGEPOffset(&Builder, *TD, &GEP, /*NoAssumptions=*/true);
712239462Sdim  Offset = Builder.CreateAdd(PtrData.second, Offset);
713239462Sdim  return std::make_pair(PtrData.first, Offset);
714239462Sdim}
715239462Sdim
716239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst&) {
717239462Sdim  // clueless
718239462Sdim  return unknown();
719239462Sdim}
720239462Sdim
721239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst&) {
722239462Sdim  return unknown();
723239462Sdim}
724239462Sdim
725239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) {
726239462Sdim  // create 2 PHIs: one for size and another for offset
727239462Sdim  PHINode *SizePHI   = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
728239462Sdim  PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
729239462Sdim
730239462Sdim  // insert right away in the cache to handle recursive PHIs
731239462Sdim  CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
732239462Sdim
733239462Sdim  // compute offset/size for each PHI incoming pointer
734239462Sdim  for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
735239462Sdim    Builder.SetInsertPoint(PHI.getIncomingBlock(i)->getFirstInsertionPt());
736239462Sdim    SizeOffsetEvalType EdgeData = compute_(PHI.getIncomingValue(i));
737239462Sdim
738239462Sdim    if (!bothKnown(EdgeData)) {
739239462Sdim      OffsetPHI->replaceAllUsesWith(UndefValue::get(IntTy));
740239462Sdim      OffsetPHI->eraseFromParent();
741239462Sdim      SizePHI->replaceAllUsesWith(UndefValue::get(IntTy));
742239462Sdim      SizePHI->eraseFromParent();
743239462Sdim      return unknown();
744239462Sdim    }
745239462Sdim    SizePHI->addIncoming(EdgeData.first, PHI.getIncomingBlock(i));
746239462Sdim    OffsetPHI->addIncoming(EdgeData.second, PHI.getIncomingBlock(i));
747239462Sdim  }
748239462Sdim
749239462Sdim  Value *Size = SizePHI, *Offset = OffsetPHI, *Tmp;
750239462Sdim  if ((Tmp = SizePHI->hasConstantValue())) {
751239462Sdim    Size = Tmp;
752239462Sdim    SizePHI->replaceAllUsesWith(Size);
753239462Sdim    SizePHI->eraseFromParent();
754239462Sdim  }
755239462Sdim  if ((Tmp = OffsetPHI->hasConstantValue())) {
756239462Sdim    Offset = Tmp;
757239462Sdim    OffsetPHI->replaceAllUsesWith(Offset);
758239462Sdim    OffsetPHI->eraseFromParent();
759239462Sdim  }
760239462Sdim  return std::make_pair(Size, Offset);
761239462Sdim}
762239462Sdim
763239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) {
764239462Sdim  SizeOffsetEvalType TrueSide  = compute_(I.getTrueValue());
765239462Sdim  SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());
766239462Sdim
767239462Sdim  if (!bothKnown(TrueSide) || !bothKnown(FalseSide))
768239462Sdim    return unknown();
769239462Sdim  if (TrueSide == FalseSide)
770239462Sdim    return TrueSide;
771239462Sdim
772239462Sdim  Value *Size = Builder.CreateSelect(I.getCondition(), TrueSide.first,
773239462Sdim                                     FalseSide.first);
774239462Sdim  Value *Offset = Builder.CreateSelect(I.getCondition(), TrueSide.second,
775239462Sdim                                       FalseSide.second);
776239462Sdim  return std::make_pair(Size, Offset);
777239462Sdim}
778239462Sdim
779239462SdimSizeOffsetEvalType ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) {
780239462Sdim  DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I <<'\n');
781239462Sdim  return unknown();
782239462Sdim}
783