2009-10-28 04:05:49 +08:00
|
|
|
//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===//
|
2009-09-10 12:36:43 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-10-28 04:05:49 +08:00
|
|
|
// This family of functions identifies calls to builtin functions that allocate
|
2013-03-09 05:03:09 +08:00
|
|
|
// or free memory.
|
2009-09-10 12:36:43 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-28 04:05:49 +08:00
|
|
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
2015-01-15 10:16:27 +08:00
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
2012-06-21 23:45:28 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2009-09-10 12:36:43 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:48:03 +08:00
|
|
|
#define DEBUG_TYPE "memory-builtins"
|
|
|
|
|
2015-11-18 03:48:06 +08:00
|
|
|
enum AllocType : uint8_t {
|
2013-09-25 01:34:29 +08:00
|
|
|
OpNewLike = 1<<0, // allocates; never returns null
|
|
|
|
MallocLike = 1<<1 | OpNewLike, // allocates; may return null
|
|
|
|
CallocLike = 1<<2, // allocates + bzero
|
|
|
|
ReallocLike = 1<<3, // reallocates
|
|
|
|
StrDupLike = 1<<4,
|
|
|
|
AllocLike = MallocLike | CallocLike | StrDupLike,
|
2013-09-25 01:15:14 +08:00
|
|
|
AnyAlloc = AllocLike | ReallocLike
|
2012-06-21 23:45:28 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct AllocFnsTy {
|
2012-08-29 23:32:21 +08:00
|
|
|
LibFunc::Func Func;
|
2012-06-21 23:45:28 +08:00
|
|
|
AllocType AllocTy;
|
|
|
|
unsigned char NumParams;
|
|
|
|
// First and Second size parameters (or -1 if unused)
|
2012-06-22 02:38:26 +08:00
|
|
|
signed char FstParam, SndParam;
|
2012-06-21 23:45:28 +08:00
|
|
|
};
|
|
|
|
|
2012-06-29 00:34:03 +08:00
|
|
|
// FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
|
|
|
|
// know which functions are nounwind, noalias, nocapture parameters, etc.
|
2012-06-21 23:45:28 +08:00
|
|
|
static const AllocFnsTy AllocationFnData[] = {
|
2012-08-29 23:32:21 +08:00
|
|
|
{LibFunc::malloc, MallocLike, 1, 0, -1},
|
|
|
|
{LibFunc::valloc, MallocLike, 1, 0, -1},
|
2013-09-25 00:37:51 +08:00
|
|
|
{LibFunc::Znwj, OpNewLike, 1, 0, -1}, // new(unsigned int)
|
2013-04-09 12:43:46 +08:00
|
|
|
{LibFunc::ZnwjRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new(unsigned int, nothrow)
|
2013-09-25 00:37:51 +08:00
|
|
|
{LibFunc::Znwm, OpNewLike, 1, 0, -1}, // new(unsigned long)
|
2013-04-09 12:43:46 +08:00
|
|
|
{LibFunc::ZnwmRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new(unsigned long, nothrow)
|
2013-09-25 00:37:51 +08:00
|
|
|
{LibFunc::Znaj, OpNewLike, 1, 0, -1}, // new[](unsigned int)
|
2013-04-09 12:43:46 +08:00
|
|
|
{LibFunc::ZnajRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new[](unsigned int, nothrow)
|
2013-09-25 00:37:51 +08:00
|
|
|
{LibFunc::Znam, OpNewLike, 1, 0, -1}, // new[](unsigned long)
|
2013-04-09 12:43:46 +08:00
|
|
|
{LibFunc::ZnamRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new[](unsigned long, nothrow)
|
2015-12-04 06:45:19 +08:00
|
|
|
{LibFunc::msvc_new_int, OpNewLike, 1, 0, -1}, // new(unsigned int)
|
|
|
|
{LibFunc::msvc_new_int_nothrow, MallocLike, 2, 0, -1}, // new(unsigned int, nothrow)
|
|
|
|
{LibFunc::msvc_new_longlong, OpNewLike, 1, 0, -1}, // new(unsigned long long)
|
|
|
|
{LibFunc::msvc_new_longlong_nothrow, MallocLike, 2, 0, -1}, // new(unsigned long long, nothrow)
|
|
|
|
{LibFunc::msvc_new_array_int, OpNewLike, 1, 0, -1}, // new[](unsigned int)
|
|
|
|
{LibFunc::msvc_new_array_int_nothrow, MallocLike, 2, 0, -1}, // new[](unsigned int, nothrow)
|
|
|
|
{LibFunc::msvc_new_array_longlong, OpNewLike, 1, 0, -1}, // new[](unsigned long long)
|
|
|
|
{LibFunc::msvc_new_array_longlong_nothrow, MallocLike, 2, 0, -1}, // new[](unsigned long long, nothrow)
|
2012-08-29 23:32:21 +08:00
|
|
|
{LibFunc::calloc, CallocLike, 2, 0, 1},
|
|
|
|
{LibFunc::realloc, ReallocLike, 2, 1, -1},
|
|
|
|
{LibFunc::reallocf, ReallocLike, 2, 1, -1},
|
|
|
|
{LibFunc::strdup, StrDupLike, 1, -1, -1},
|
|
|
|
{LibFunc::strndup, StrDupLike, 2, 1, -1}
|
2013-09-25 01:49:08 +08:00
|
|
|
// TODO: Handle "int posix_memalign(void **, size_t, size_t)"
|
2012-06-21 23:45:28 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
|
|
|
|
if (LookThroughBitCast)
|
|
|
|
V = V->stripPointerCasts();
|
2012-06-22 05:25:05 +08:00
|
|
|
|
2012-06-22 23:50:53 +08:00
|
|
|
CallSite CS(const_cast<Value*>(V));
|
|
|
|
if (!CS.getInstruction())
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2013-06-27 08:25:01 +08:00
|
|
|
if (CS.isNoBuiltin())
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2013-05-16 12:12:04 +08:00
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
Function *Callee = CS.getCalledFunction();
|
2012-06-21 23:45:28 +08:00
|
|
|
if (!Callee || !Callee->isDeclaration())
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2012-06-21 23:45:28 +08:00
|
|
|
return Callee;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
/// \brief Returns the allocation data for the given value if it is a call to a
|
|
|
|
/// known allocation function, and NULL otherwise.
|
|
|
|
static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy,
|
2012-08-29 23:32:21 +08:00
|
|
|
const TargetLibraryInfo *TLI,
|
2012-06-21 23:45:28 +08:00
|
|
|
bool LookThroughBitCast = false) {
|
2013-03-09 05:15:00 +08:00
|
|
|
// Skip intrinsics
|
|
|
|
if (isa<IntrinsicInst>(V))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2013-03-09 05:15:00 +08:00
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
Function *Callee = getCalledFunction(V, LookThroughBitCast);
|
|
|
|
if (!Callee)
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2012-08-29 23:32:21 +08:00
|
|
|
// Make sure that the function is available.
|
|
|
|
StringRef FnName = Callee->getName();
|
|
|
|
LibFunc::Func TLIFn;
|
|
|
|
if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2012-08-29 23:32:21 +08:00
|
|
|
|
2015-10-25 03:03:15 +08:00
|
|
|
const AllocFnsTy *FnData =
|
|
|
|
std::find_if(std::begin(AllocationFnData), std::end(AllocationFnData),
|
|
|
|
[TLIFn](const AllocFnsTy &Fn) { return Fn.Func == TLIFn; });
|
|
|
|
|
|
|
|
if (FnData == std::end(AllocationFnData))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2013-09-25 01:34:29 +08:00
|
|
|
if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2012-06-21 23:45:28 +08:00
|
|
|
|
|
|
|
// Check function prototype.
|
2012-06-22 02:38:26 +08:00
|
|
|
int FstParam = FnData->FstParam;
|
|
|
|
int SndParam = FnData->SndParam;
|
2011-07-18 12:54:35 +08:00
|
|
|
FunctionType *FTy = Callee->getFunctionType();
|
2012-06-21 23:45:28 +08:00
|
|
|
|
|
|
|
if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
|
|
|
|
FTy->getNumParams() == FnData->NumParams &&
|
2012-06-22 02:38:26 +08:00
|
|
|
(FstParam < 0 ||
|
2012-06-21 23:45:28 +08:00
|
|
|
(FTy->getParamType(FstParam)->isIntegerTy(32) ||
|
|
|
|
FTy->getParamType(FstParam)->isIntegerTy(64))) &&
|
2012-06-22 02:38:26 +08:00
|
|
|
(SndParam < 0 ||
|
2012-06-21 23:45:28 +08:00
|
|
|
FTy->getParamType(SndParam)->isIntegerTy(32) ||
|
|
|
|
FTy->getParamType(SndParam)->isIntegerTy(64)))
|
|
|
|
return FnData;
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) {
|
2012-06-26 00:17:54 +08:00
|
|
|
ImmutableCallSite CS(LookThroughBitCast ? V->stripPointerCasts() : V);
|
2012-12-19 15:18:57 +08:00
|
|
|
return CS && CS.hasFnAttr(Attribute::NoAlias);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
/// \brief Tests if a value is a call or invoke to a library function that
|
|
|
|
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
|
|
|
/// like).
|
2012-08-29 23:32:21 +08:00
|
|
|
bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
|
|
|
|
bool LookThroughBitCast) {
|
|
|
|
return getAllocationData(V, AnyAlloc, TLI, LookThroughBitCast);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
/// \brief Tests if a value is a call or invoke to a function that returns a
|
2012-06-29 00:34:03 +08:00
|
|
|
/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
|
2012-08-29 23:32:21 +08:00
|
|
|
bool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
|
|
|
|
bool LookThroughBitCast) {
|
2012-06-29 00:34:03 +08:00
|
|
|
// it's safe to consider realloc as noalias since accessing the original
|
|
|
|
// pointer is undefined behavior
|
2012-08-29 23:32:21 +08:00
|
|
|
return isAllocationFn(V, TLI, LookThroughBitCast) ||
|
2012-06-21 23:45:28 +08:00
|
|
|
hasNoAliasAttr(V, LookThroughBitCast);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
/// \brief Tests if a value is a call or invoke to a library function that
|
|
|
|
/// allocates uninitialized memory (such as malloc).
|
2012-08-29 23:32:21 +08:00
|
|
|
bool llvm::isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
|
|
|
bool LookThroughBitCast) {
|
|
|
|
return getAllocationData(V, MallocLike, TLI, LookThroughBitCast);
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
/// \brief Tests if a value is a call or invoke to a library function that
|
|
|
|
/// allocates zero-filled memory (such as calloc).
|
2012-08-29 23:32:21 +08:00
|
|
|
bool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
|
|
|
bool LookThroughBitCast) {
|
|
|
|
return getAllocationData(V, CallocLike, TLI, LookThroughBitCast);
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
2012-06-22 05:25:05 +08:00
|
|
|
/// \brief Tests if a value is a call or invoke to a library function that
|
|
|
|
/// allocates memory (either malloc, calloc, or strdup like).
|
2012-08-29 23:32:21 +08:00
|
|
|
bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
|
|
|
bool LookThroughBitCast) {
|
|
|
|
return getAllocationData(V, AllocLike, TLI, LookThroughBitCast);
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// extractMallocCall - Returns the corresponding CallInst if the instruction
|
|
|
|
/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we
|
|
|
|
/// ignore InvokeInst here.
|
2012-08-29 23:32:21 +08:00
|
|
|
const CallInst *llvm::extractMallocCall(const Value *I,
|
|
|
|
const TargetLibraryInfo *TLI) {
|
2014-04-15 12:59:12 +08:00
|
|
|
return isMallocLikeFn(I, TLI) ? dyn_cast<CallInst>(I) : nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
static Value *computeArraySize(const CallInst *CI, const DataLayout &DL,
|
2012-08-29 23:32:21 +08:00
|
|
|
const TargetLibraryInfo *TLI,
|
2009-11-10 16:32:25 +08:00
|
|
|
bool LookThroughSExt = false) {
|
2009-09-10 12:36:43 +08:00
|
|
|
if (!CI)
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2009-11-07 08:16:28 +08:00
|
|
|
// The size of the malloc's result type must be known to determine array size.
|
2012-08-29 23:32:21 +08:00
|
|
|
Type *T = getMallocAllocatedType(CI, TLI);
|
2015-03-10 10:37:25 +08:00
|
|
|
if (!T || !T->isSized())
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
unsigned ElementSize = DL.getTypeAllocSize(T);
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *ST = dyn_cast<StructType>(T))
|
2015-03-10 10:37:25 +08:00
|
|
|
ElementSize = DL.getStructLayout(ST)->getSizeInBytes();
|
2009-11-07 08:16:28 +08:00
|
|
|
|
2010-06-24 05:41:47 +08:00
|
|
|
// If malloc call's arg can be determined to be a multiple of ElementSize,
|
2009-11-10 16:32:25 +08:00
|
|
|
// return the multiple. Otherwise, return NULL.
|
2010-06-24 05:41:47 +08:00
|
|
|
Value *MallocArg = CI->getArgOperand(0);
|
2014-04-15 12:59:12 +08:00
|
|
|
Value *Multiple = nullptr;
|
2009-11-10 16:32:25 +08:00
|
|
|
if (ComputeMultiple(MallocArg, ElementSize, Multiple,
|
2009-11-18 08:58:27 +08:00
|
|
|
LookThroughSExt))
|
2009-11-10 16:32:25 +08:00
|
|
|
return Multiple;
|
2009-09-19 03:20:02 +08:00
|
|
|
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getMallocType - Returns the PointerType resulting from the malloc call.
|
2009-11-07 08:16:28 +08:00
|
|
|
/// The PointerType depends on the number of bitcast uses of the malloc call:
|
|
|
|
/// 0: PointerType is the calls' return type.
|
|
|
|
/// 1: PointerType is the bitcast's result type.
|
|
|
|
/// >1: Unique PointerType cannot be determined, return NULL.
|
2012-08-29 23:32:21 +08:00
|
|
|
PointerType *llvm::getMallocType(const CallInst *CI,
|
|
|
|
const TargetLibraryInfo *TLI) {
|
|
|
|
assert(isMallocLikeFn(CI, TLI) && "getMallocType and not malloc call");
|
2013-03-09 05:03:09 +08:00
|
|
|
|
2014-04-15 12:59:12 +08:00
|
|
|
PointerType *MallocType = nullptr;
|
2009-11-07 08:16:28 +08:00
|
|
|
unsigned NumOfBitCastUses = 0;
|
|
|
|
|
2009-09-19 03:20:02 +08:00
|
|
|
// Determine if CallInst has a bitcast use.
|
2014-03-09 11:16:01 +08:00
|
|
|
for (Value::const_user_iterator UI = CI->user_begin(), E = CI->user_end();
|
|
|
|
UI != E;)
|
2009-11-07 08:16:28 +08:00
|
|
|
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(*UI++)) {
|
|
|
|
MallocType = cast<PointerType>(BCI->getDestTy());
|
|
|
|
NumOfBitCastUses++;
|
|
|
|
}
|
2009-09-19 03:20:02 +08:00
|
|
|
|
2009-11-07 08:16:28 +08:00
|
|
|
// Malloc call has 1 bitcast use, so type is the bitcast's destination type.
|
|
|
|
if (NumOfBitCastUses == 1)
|
|
|
|
return MallocType;
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2009-09-23 02:50:03 +08:00
|
|
|
// Malloc call was not bitcast, so type is the malloc function's return type.
|
2009-11-07 08:16:28 +08:00
|
|
|
if (NumOfBitCastUses == 0)
|
2009-09-19 03:20:02 +08:00
|
|
|
return cast<PointerType>(CI->getType());
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2009-09-19 03:20:02 +08:00
|
|
|
// Type could not be determined.
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2009-11-07 08:16:28 +08:00
|
|
|
/// getMallocAllocatedType - Returns the Type allocated by malloc call.
|
|
|
|
/// The Type depends on the number of bitcast uses of the malloc call:
|
|
|
|
/// 0: PointerType is the malloc calls' return type.
|
|
|
|
/// 1: PointerType is the bitcast's result type.
|
|
|
|
/// >1: Unique PointerType cannot be determined, return NULL.
|
2012-08-29 23:32:21 +08:00
|
|
|
Type *llvm::getMallocAllocatedType(const CallInst *CI,
|
|
|
|
const TargetLibraryInfo *TLI) {
|
|
|
|
PointerType *PT = getMallocType(CI, TLI);
|
2014-04-15 12:59:12 +08:00
|
|
|
return PT ? PT->getElementType() : nullptr;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2013-03-09 05:03:09 +08:00
|
|
|
/// getMallocArraySize - Returns the array size of a malloc call. If the
|
2009-10-29 04:18:55 +08:00
|
|
|
/// argument passed to malloc is a multiple of the size of the malloced type,
|
|
|
|
/// then return that multiple. For non-array mallocs, the multiple is
|
|
|
|
/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
|
2009-10-16 04:14:52 +08:00
|
|
|
/// determined.
|
2015-03-10 10:37:25 +08:00
|
|
|
Value *llvm::getMallocArraySize(CallInst *CI, const DataLayout &DL,
|
2012-08-29 23:32:21 +08:00
|
|
|
const TargetLibraryInfo *TLI,
|
2009-11-10 16:32:25 +08:00
|
|
|
bool LookThroughSExt) {
|
2012-08-29 23:32:21 +08:00
|
|
|
assert(isMallocLikeFn(CI, TLI) && "getMallocArraySize and not malloc call");
|
2013-10-04 03:50:01 +08:00
|
|
|
return computeArraySize(CI, DL, TLI, LookThroughSExt);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
2009-10-24 12:23:03 +08:00
|
|
|
|
2012-05-04 05:19:58 +08:00
|
|
|
|
|
|
|
/// extractCallocCall - Returns the corresponding CallInst if the instruction
|
|
|
|
/// is a calloc call.
|
2012-08-29 23:32:21 +08:00
|
|
|
const CallInst *llvm::extractCallocCall(const Value *I,
|
|
|
|
const TargetLibraryInfo *TLI) {
|
2014-04-15 12:59:12 +08:00
|
|
|
return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : nullptr;
|
2012-05-04 05:19:58 +08:00
|
|
|
}
|
|
|
|
|
2009-10-27 07:43:48 +08:00
|
|
|
|
2010-06-24 05:51:12 +08:00
|
|
|
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
2012-08-29 23:32:21 +08:00
|
|
|
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
2009-10-24 12:23:03 +08:00
|
|
|
const CallInst *CI = dyn_cast<CallInst>(I);
|
2013-03-09 05:15:00 +08:00
|
|
|
if (!CI || isa<IntrinsicInst>(CI))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-11-04 04:39:35 +08:00
|
|
|
Function *Callee = CI->getCalledFunction();
|
2015-01-15 09:00:33 +08:00
|
|
|
if (Callee == nullptr)
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2011-03-15 15:31:32 +08:00
|
|
|
|
2012-08-29 23:32:21 +08:00
|
|
|
StringRef FnName = Callee->getName();
|
|
|
|
LibFunc::Func TLIFn;
|
|
|
|
if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2012-08-29 23:32:21 +08:00
|
|
|
|
2013-07-22 07:11:42 +08:00
|
|
|
unsigned ExpectedNumParams;
|
|
|
|
if (TLIFn == LibFunc::free ||
|
|
|
|
TLIFn == LibFunc::ZdlPv || // operator delete(void*)
|
2015-12-04 06:45:19 +08:00
|
|
|
TLIFn == LibFunc::ZdaPv || // operator delete[](void*)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr64) // operator delete[](void*)
|
2013-07-22 07:11:42 +08:00
|
|
|
ExpectedNumParams = 1;
|
2014-10-04 04:17:06 +08:00
|
|
|
else if (TLIFn == LibFunc::ZdlPvj || // delete(void*, uint)
|
|
|
|
TLIFn == LibFunc::ZdlPvm || // delete(void*, ulong)
|
|
|
|
TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow)
|
|
|
|
TLIFn == LibFunc::ZdaPvj || // delete[](void*, uint)
|
|
|
|
TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong)
|
2015-12-04 06:45:19 +08:00
|
|
|
TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr32_int || // delete(void*, uint)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow)
|
|
|
|
TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr32_int || // delete[](void*, uint)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow)
|
|
|
|
TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow)
|
2013-07-22 07:11:42 +08:00
|
|
|
ExpectedNumParams = 2;
|
|
|
|
else
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-10-24 12:23:03 +08:00
|
|
|
|
|
|
|
// Check free prototype.
|
2013-03-09 05:03:09 +08:00
|
|
|
// FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
|
2009-10-24 12:23:03 +08:00
|
|
|
// attribute will exist.
|
2011-07-18 12:54:35 +08:00
|
|
|
FunctionType *FTy = Callee->getFunctionType();
|
2009-11-04 04:39:35 +08:00
|
|
|
if (!FTy->getReturnType()->isVoidTy())
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2013-07-22 07:11:42 +08:00
|
|
|
if (FTy->getNumParams() != ExpectedNumParams)
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2011-06-19 05:46:23 +08:00
|
|
|
if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
|
2014-04-15 12:59:12 +08:00
|
|
|
return nullptr;
|
2009-10-24 12:23:03 +08:00
|
|
|
|
2010-06-24 05:51:12 +08:00
|
|
|
return CI;
|
2009-10-24 12:23:03 +08:00
|
|
|
}
|
2012-06-21 23:45:28 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utility functions to compute size of objects.
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
|
|
|
|
/// object size in Size if successful, and false otherwise.
|
|
|
|
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
|
|
|
|
/// byval arguments, and global variables.
|
2015-03-10 10:37:25 +08:00
|
|
|
bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
|
2012-08-29 23:32:21 +08:00
|
|
|
const TargetLibraryInfo *TLI, bool RoundToAlign) {
|
2013-10-04 03:50:01 +08:00
|
|
|
ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), RoundToAlign);
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
|
|
|
|
if (!Visitor.bothKnown(Data))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
APInt ObjSize = Data.first, Offset = Data.second;
|
|
|
|
// check for overflow
|
|
|
|
if (Offset.slt(0) || ObjSize.ult(Offset))
|
|
|
|
Size = 0;
|
|
|
|
else
|
|
|
|
Size = (ObjSize - Offset).getZExtValue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STATISTIC(ObjectVisitorArgument,
|
|
|
|
"Number of arguments with unsolved size and offset");
|
|
|
|
STATISTIC(ObjectVisitorLoad,
|
|
|
|
"Number of load instructions with unsolved size and offset");
|
|
|
|
|
|
|
|
|
|
|
|
APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
|
|
|
|
if (RoundToAlign && Align)
|
|
|
|
return APInt(IntTyBits, RoundUpToAlignment(Size.getZExtValue(), Align));
|
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL,
|
2012-08-29 23:32:21 +08:00
|
|
|
const TargetLibraryInfo *TLI,
|
2012-06-21 23:45:28 +08:00
|
|
|
LLVMContext &Context,
|
2012-11-01 16:07:29 +08:00
|
|
|
bool RoundToAlign)
|
2015-03-10 10:37:25 +08:00
|
|
|
: DL(DL), TLI(TLI), RoundToAlign(RoundToAlign) {
|
2013-12-14 08:27:48 +08:00
|
|
|
// Pointer size must be rechecked for each object visited since it could have
|
|
|
|
// a different address space.
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
|
2015-03-10 10:37:25 +08:00
|
|
|
IntTyBits = DL.getPointerTypeSizeInBits(V->getType());
|
2013-12-14 08:27:48 +08:00
|
|
|
Zero = APInt::getNullValue(IntTyBits);
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
V = V->stripPointerCasts();
|
2013-04-10 02:16:05 +08:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
|
|
|
// If we have already seen this instruction, bail out. Cycles can happen in
|
|
|
|
// unreachable code after constant propagation.
|
2014-11-19 15:49:26 +08:00
|
|
|
if (!SeenInsts.insert(I).second)
|
2013-04-10 02:16:05 +08:00
|
|
|
return unknown();
|
2013-01-01 04:45:10 +08:00
|
|
|
|
2012-08-18 03:26:41 +08:00
|
|
|
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
|
2013-04-10 02:16:05 +08:00
|
|
|
return visitGEPOperator(*GEP);
|
|
|
|
return visit(*I);
|
2012-08-18 03:26:41 +08:00
|
|
|
}
|
2012-06-21 23:45:28 +08:00
|
|
|
if (Argument *A = dyn_cast<Argument>(V))
|
|
|
|
return visitArgument(*A);
|
|
|
|
if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
|
|
|
|
return visitConstantPointerNull(*P);
|
2013-01-01 00:23:48 +08:00
|
|
|
if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
|
|
|
|
return visitGlobalAlias(*GA);
|
2012-06-21 23:45:28 +08:00
|
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
|
|
|
|
return visitGlobalVariable(*GV);
|
|
|
|
if (UndefValue *UV = dyn_cast<UndefValue>(V))
|
|
|
|
return visitUndefValue(*UV);
|
2012-08-18 03:26:41 +08:00
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
2012-06-21 23:45:28 +08:00
|
|
|
if (CE->getOpcode() == Instruction::IntToPtr)
|
|
|
|
return unknown(); // clueless
|
2013-04-10 02:16:05 +08:00
|
|
|
if (CE->getOpcode() == Instruction::GetElementPtr)
|
|
|
|
return visitGEPOperator(cast<GEPOperator>(*CE));
|
2012-08-18 03:26:41 +08:00
|
|
|
}
|
2012-06-21 23:45:28 +08:00
|
|
|
|
|
|
|
DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V
|
|
|
|
<< '\n');
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
|
|
|
|
if (!I.getAllocatedType()->isSized())
|
|
|
|
return unknown();
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
APInt Size(IntTyBits, DL.getTypeAllocSize(I.getAllocatedType()));
|
2012-06-21 23:45:28 +08:00
|
|
|
if (!I.isArrayAllocation())
|
|
|
|
return std::make_pair(align(Size, I.getAlignment()), Zero);
|
|
|
|
|
|
|
|
Value *ArraySize = I.getArraySize();
|
|
|
|
if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
|
|
|
|
Size *= C->getValue().zextOrSelf(IntTyBits);
|
|
|
|
return std::make_pair(align(Size, I.getAlignment()), Zero);
|
|
|
|
}
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
|
|
|
|
// no interprocedural analysis is done at the moment
|
2014-01-28 10:38:36 +08:00
|
|
|
if (!A.hasByValOrInAllocaAttr()) {
|
2012-06-21 23:45:28 +08:00
|
|
|
++ObjectVisitorArgument;
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
PointerType *PT = cast<PointerType>(A.getType());
|
2015-03-10 10:37:25 +08:00
|
|
|
APInt Size(IntTyBits, DL.getTypeAllocSize(PT->getElementType()));
|
2012-06-21 23:45:28 +08:00
|
|
|
return std::make_pair(align(Size, A.getParamAlignment()), Zero);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
|
2012-08-29 23:32:21 +08:00
|
|
|
const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(), AnyAlloc,
|
|
|
|
TLI);
|
2012-06-21 23:45:28 +08:00
|
|
|
if (!FnData)
|
|
|
|
return unknown();
|
|
|
|
|
|
|
|
// handle strdup-like functions separately
|
|
|
|
if (FnData->AllocTy == StrDupLike) {
|
2012-07-25 00:28:13 +08:00
|
|
|
APInt Size(IntTyBits, GetStringLength(CS.getArgument(0)));
|
|
|
|
if (!Size)
|
|
|
|
return unknown();
|
|
|
|
|
|
|
|
// strndup limits strlen
|
|
|
|
if (FnData->FstParam > 0) {
|
|
|
|
ConstantInt *Arg= dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
|
|
|
|
if (!Arg)
|
|
|
|
return unknown();
|
|
|
|
|
|
|
|
APInt MaxSize = Arg->getValue().zextOrSelf(IntTyBits);
|
|
|
|
if (Size.ugt(MaxSize))
|
|
|
|
Size = MaxSize + 1;
|
|
|
|
}
|
|
|
|
return std::make_pair(Size, Zero);
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ConstantInt *Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
|
|
|
|
if (!Arg)
|
|
|
|
return unknown();
|
|
|
|
|
2012-06-22 00:47:58 +08:00
|
|
|
APInt Size = Arg->getValue().zextOrSelf(IntTyBits);
|
2012-06-21 23:45:28 +08:00
|
|
|
// size determined by just 1 parameter
|
2012-06-22 02:38:26 +08:00
|
|
|
if (FnData->SndParam < 0)
|
2012-06-21 23:45:28 +08:00
|
|
|
return std::make_pair(Size, Zero);
|
|
|
|
|
|
|
|
Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->SndParam));
|
|
|
|
if (!Arg)
|
|
|
|
return unknown();
|
|
|
|
|
2012-06-22 00:47:58 +08:00
|
|
|
Size *= Arg->getValue().zextOrSelf(IntTyBits);
|
2012-06-21 23:45:28 +08:00
|
|
|
return std::make_pair(Size, Zero);
|
|
|
|
|
|
|
|
// TODO: handle more standard functions (+ wchar cousins):
|
2012-07-26 02:49:28 +08:00
|
|
|
// - strdup / strndup
|
2012-06-21 23:45:28 +08:00
|
|
|
// - strcpy / strncpy
|
|
|
|
// - strcat / strncat
|
|
|
|
// - memcpy / memmove
|
2012-07-26 02:49:28 +08:00
|
|
|
// - strcat / strncat
|
2012-06-21 23:45:28 +08:00
|
|
|
// - memset
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType
|
|
|
|
ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&) {
|
|
|
|
return std::make_pair(Zero, Zero);
|
|
|
|
}
|
|
|
|
|
2012-06-29 00:34:03 +08:00
|
|
|
SizeOffsetType
|
|
|
|
ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst&) {
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetType
|
|
|
|
ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) {
|
|
|
|
// Easy cases were already folded by previous passes.
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) {
|
|
|
|
SizeOffsetType PtrData = compute(GEP.getPointerOperand());
|
2012-12-31 00:25:48 +08:00
|
|
|
APInt Offset(IntTyBits, 0);
|
2015-03-10 10:37:25 +08:00
|
|
|
if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(DL, Offset))
|
2012-06-21 23:45:28 +08:00
|
|
|
return unknown();
|
|
|
|
|
|
|
|
return std::make_pair(PtrData.first, PtrData.second + Offset);
|
|
|
|
}
|
|
|
|
|
2013-01-01 00:23:48 +08:00
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) {
|
|
|
|
if (GA.mayBeOverridden())
|
|
|
|
return unknown();
|
|
|
|
return compute(GA.getAliasee());
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV){
|
|
|
|
if (!GV.hasDefinitiveInitializer())
|
|
|
|
return unknown();
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getType()->getElementType()));
|
2012-06-21 23:45:28 +08:00
|
|
|
return std::make_pair(align(Size, GV.getAlignment()), Zero);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) {
|
|
|
|
// clueless
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
|
|
|
|
++ObjectVisitorLoad;
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
2013-04-10 02:16:05 +08:00
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
|
|
|
|
// too complex to analyze statically.
|
|
|
|
return unknown();
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
|
|
|
|
SizeOffsetType TrueSide = compute(I.getTrueValue());
|
|
|
|
SizeOffsetType FalseSide = compute(I.getFalseValue());
|
2013-01-01 02:01:36 +08:00
|
|
|
if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide == FalseSide)
|
2012-06-21 23:45:28 +08:00
|
|
|
return TrueSide;
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {
|
|
|
|
return std::make_pair(Zero, Zero);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
|
|
|
|
DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n');
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(
|
|
|
|
const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
|
|
|
|
bool RoundToAlign)
|
|
|
|
: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)),
|
|
|
|
RoundToAlign(RoundToAlign) {
|
2013-12-14 08:27:48 +08:00
|
|
|
// IntTy and Zero must be set for each compute() since the address space may
|
|
|
|
// be different for later objects.
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
|
2013-12-14 08:27:48 +08:00
|
|
|
// XXX - Are vectors of pointers possible here?
|
2015-03-10 10:37:25 +08:00
|
|
|
IntTy = cast<IntegerType>(DL.getIntPtrType(V->getType()));
|
2013-12-14 08:27:48 +08:00
|
|
|
Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetEvalType Result = compute_(V);
|
|
|
|
|
|
|
|
if (!bothKnown(Result)) {
|
|
|
|
// erase everything that was computed in this iteration from the cache, so
|
|
|
|
// that no dangling references are left behind. We could be a bit smarter if
|
|
|
|
// we kept a dependency graph. It's probably not worth the complexity.
|
|
|
|
for (PtrSetTy::iterator I=SeenVals.begin(), E=SeenVals.end(); I != E; ++I) {
|
|
|
|
CacheMapTy::iterator CacheIt = CacheMap.find(*I);
|
|
|
|
// non-computable results can be safely cached
|
|
|
|
if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
|
|
|
|
CacheMap.erase(CacheIt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SeenVals.clear();
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
|
2013-10-24 17:17:24 +08:00
|
|
|
ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign);
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetType Const = Visitor.compute(V);
|
|
|
|
if (Visitor.bothKnown(Const))
|
|
|
|
return std::make_pair(ConstantInt::get(Context, Const.first),
|
|
|
|
ConstantInt::get(Context, Const.second));
|
|
|
|
|
|
|
|
V = V->stripPointerCasts();
|
|
|
|
|
|
|
|
// check cache
|
|
|
|
CacheMapTy::iterator CacheIt = CacheMap.find(V);
|
|
|
|
if (CacheIt != CacheMap.end())
|
|
|
|
return CacheIt->second;
|
|
|
|
|
|
|
|
// always generate code immediately before the instruction being
|
|
|
|
// processed, so that the generated code dominates the same BBs
|
Analysis: Remove implicit ilist iterator conversions
Remove implicit ilist iterator conversions from LLVMAnalysis.
I came across something really scary in `llvm::isKnownNotFullPoison()`
which relied on `Instruction::getNextNode()` being completely broken
(not surprising, but scary nevertheless). This function is documented
(and coded to) return `nullptr` when it gets to the sentinel, but with
an `ilist_half_node` as a sentinel, the sentinel check looks into some
other memory and we don't recognize we've hit the end.
Rooting out these scary cases is the reason I'm removing the implicit
conversions before doing anything else with `ilist`; I'm not at all
surprised that clients rely on badness.
I found another scary case -- this time, not relying on badness, just
bad (but I guess getting lucky so far) -- in
`ObjectSizeOffsetEvaluator::compute_()`. Here, we save out the
insertion point, do some things, and then restore it. Previously, we
let the iterator auto-convert to `Instruction*`, and then set it back
using the `Instruction*` version:
Instruction *PrevInsertPoint = Builder.GetInsertPoint();
/* Logic that may change insert point */
if (PrevInsertPoint)
Builder.SetInsertPoint(PrevInsertPoint);
The check for `PrevInsertPoint` doesn't protect correctly against bad
accesses. If the insertion point has been set to the end of a basic
block (i.e., `SetInsertPoint(SomeBB)`), then `GetInsertPoint()` returns
an iterator pointing at the list sentinel. The version of
`SetInsertPoint()` that's getting called will then call
`PrevInsertPoint->getParent()`, which explodes horribly. The only
reason this hasn't blown up is that it's fairly unlikely the builder is
adding to the end of the block; usually, we're adding instructions
somewhere before the terminator.
llvm-svn: 249925
2015-10-10 08:53:03 +08:00
|
|
|
BuilderTy::InsertPointGuard Guard(Builder);
|
2012-06-21 23:45:28 +08:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(V))
|
|
|
|
Builder.SetInsertPoint(I);
|
|
|
|
|
|
|
|
// now compute the size and offset
|
|
|
|
SizeOffsetEvalType Result;
|
2013-09-30 03:39:13 +08:00
|
|
|
|
|
|
|
// Record the pointers that were handled in this run, so that they can be
|
|
|
|
// cleaned later if something fails. We also use this set to break cycles that
|
|
|
|
// can occur in dead code.
|
2014-11-19 15:49:26 +08:00
|
|
|
if (!SeenVals.insert(V).second) {
|
2013-09-30 03:39:13 +08:00
|
|
|
Result = unknown();
|
|
|
|
} else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
2012-06-21 23:45:28 +08:00
|
|
|
Result = visitGEPOperator(*GEP);
|
|
|
|
} else if (Instruction *I = dyn_cast<Instruction>(V)) {
|
|
|
|
Result = visit(*I);
|
|
|
|
} else if (isa<Argument>(V) ||
|
|
|
|
(isa<ConstantExpr>(V) &&
|
|
|
|
cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
|
2013-01-01 00:23:48 +08:00
|
|
|
isa<GlobalAlias>(V) ||
|
2012-06-21 23:45:28 +08:00
|
|
|
isa<GlobalVariable>(V)) {
|
|
|
|
// ignore values where we cannot do more than what ObjectSizeVisitor can
|
|
|
|
Result = unknown();
|
|
|
|
} else {
|
|
|
|
DEBUG(dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: "
|
|
|
|
<< *V << '\n');
|
|
|
|
Result = unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't reuse CacheIt since it may be invalid at this point.
|
|
|
|
CacheMap[V] = Result;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) {
|
|
|
|
if (!I.getAllocatedType()->isSized())
|
|
|
|
return unknown();
|
|
|
|
|
|
|
|
// must be a VLA
|
|
|
|
assert(I.isArrayAllocation());
|
|
|
|
Value *ArraySize = I.getArraySize();
|
|
|
|
Value *Size = ConstantInt::get(ArraySize->getType(),
|
2015-03-10 10:37:25 +08:00
|
|
|
DL.getTypeAllocSize(I.getAllocatedType()));
|
2012-06-21 23:45:28 +08:00
|
|
|
Size = Builder.CreateMul(Size, ArraySize);
|
|
|
|
return std::make_pair(Size, Zero);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitCallSite(CallSite CS) {
|
2012-08-29 23:32:21 +08:00
|
|
|
const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(), AnyAlloc,
|
|
|
|
TLI);
|
2012-06-21 23:45:28 +08:00
|
|
|
if (!FnData)
|
|
|
|
return unknown();
|
|
|
|
|
|
|
|
// handle strdup-like functions separately
|
|
|
|
if (FnData->AllocTy == StrDupLike) {
|
2012-07-26 02:49:28 +08:00
|
|
|
// TODO
|
|
|
|
return unknown();
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
2012-06-22 00:47:58 +08:00
|
|
|
Value *FirstArg = CS.getArgument(FnData->FstParam);
|
|
|
|
FirstArg = Builder.CreateZExt(FirstArg, IntTy);
|
2012-06-22 02:38:26 +08:00
|
|
|
if (FnData->SndParam < 0)
|
2012-06-21 23:45:28 +08:00
|
|
|
return std::make_pair(FirstArg, Zero);
|
|
|
|
|
|
|
|
Value *SecondArg = CS.getArgument(FnData->SndParam);
|
2012-06-22 00:47:58 +08:00
|
|
|
SecondArg = Builder.CreateZExt(SecondArg, IntTy);
|
2012-06-21 23:45:28 +08:00
|
|
|
Value *Size = Builder.CreateMul(FirstArg, SecondArg);
|
|
|
|
return std::make_pair(Size, Zero);
|
|
|
|
|
|
|
|
// TODO: handle more standard functions (+ wchar cousins):
|
2012-07-26 02:49:28 +08:00
|
|
|
// - strdup / strndup
|
2012-06-21 23:45:28 +08:00
|
|
|
// - strcpy / strncpy
|
|
|
|
// - strcat / strncat
|
|
|
|
// - memcpy / memmove
|
2012-07-26 02:49:28 +08:00
|
|
|
// - strcat / strncat
|
2012-06-21 23:45:28 +08:00
|
|
|
// - memset
|
|
|
|
}
|
|
|
|
|
2012-06-29 00:34:03 +08:00
|
|
|
SizeOffsetEvalType
|
|
|
|
ObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst&) {
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType
|
|
|
|
ObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst&) {
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetEvalType
|
|
|
|
ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) {
|
|
|
|
SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand());
|
|
|
|
if (!bothKnown(PtrData))
|
|
|
|
return unknown();
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
Value *Offset = EmitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
|
2012-06-21 23:45:28 +08:00
|
|
|
Offset = Builder.CreateAdd(PtrData.second, Offset);
|
|
|
|
return std::make_pair(PtrData.first, Offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst&) {
|
|
|
|
// clueless
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst&) {
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) {
|
|
|
|
// create 2 PHIs: one for size and another for offset
|
|
|
|
PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
|
|
|
|
PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
|
|
|
|
|
|
|
|
// insert right away in the cache to handle recursive PHIs
|
|
|
|
CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
|
|
|
|
|
|
|
|
// compute offset/size for each PHI incoming pointer
|
|
|
|
for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
|
Analysis: Remove implicit ilist iterator conversions
Remove implicit ilist iterator conversions from LLVMAnalysis.
I came across something really scary in `llvm::isKnownNotFullPoison()`
which relied on `Instruction::getNextNode()` being completely broken
(not surprising, but scary nevertheless). This function is documented
(and coded to) return `nullptr` when it gets to the sentinel, but with
an `ilist_half_node` as a sentinel, the sentinel check looks into some
other memory and we don't recognize we've hit the end.
Rooting out these scary cases is the reason I'm removing the implicit
conversions before doing anything else with `ilist`; I'm not at all
surprised that clients rely on badness.
I found another scary case -- this time, not relying on badness, just
bad (but I guess getting lucky so far) -- in
`ObjectSizeOffsetEvaluator::compute_()`. Here, we save out the
insertion point, do some things, and then restore it. Previously, we
let the iterator auto-convert to `Instruction*`, and then set it back
using the `Instruction*` version:
Instruction *PrevInsertPoint = Builder.GetInsertPoint();
/* Logic that may change insert point */
if (PrevInsertPoint)
Builder.SetInsertPoint(PrevInsertPoint);
The check for `PrevInsertPoint` doesn't protect correctly against bad
accesses. If the insertion point has been set to the end of a basic
block (i.e., `SetInsertPoint(SomeBB)`), then `GetInsertPoint()` returns
an iterator pointing at the list sentinel. The version of
`SetInsertPoint()` that's getting called will then call
`PrevInsertPoint->getParent()`, which explodes horribly. The only
reason this hasn't blown up is that it's fairly unlikely the builder is
adding to the end of the block; usually, we're adding instructions
somewhere before the terminator.
llvm-svn: 249925
2015-10-10 08:53:03 +08:00
|
|
|
Builder.SetInsertPoint(&*PHI.getIncomingBlock(i)->getFirstInsertionPt());
|
2012-06-21 23:45:28 +08:00
|
|
|
SizeOffsetEvalType EdgeData = compute_(PHI.getIncomingValue(i));
|
|
|
|
|
|
|
|
if (!bothKnown(EdgeData)) {
|
|
|
|
OffsetPHI->replaceAllUsesWith(UndefValue::get(IntTy));
|
|
|
|
OffsetPHI->eraseFromParent();
|
|
|
|
SizePHI->replaceAllUsesWith(UndefValue::get(IntTy));
|
|
|
|
SizePHI->eraseFromParent();
|
|
|
|
return unknown();
|
|
|
|
}
|
|
|
|
SizePHI->addIncoming(EdgeData.first, PHI.getIncomingBlock(i));
|
|
|
|
OffsetPHI->addIncoming(EdgeData.second, PHI.getIncomingBlock(i));
|
|
|
|
}
|
2012-07-04 01:13:25 +08:00
|
|
|
|
|
|
|
Value *Size = SizePHI, *Offset = OffsetPHI, *Tmp;
|
|
|
|
if ((Tmp = SizePHI->hasConstantValue())) {
|
|
|
|
Size = Tmp;
|
|
|
|
SizePHI->replaceAllUsesWith(Size);
|
|
|
|
SizePHI->eraseFromParent();
|
|
|
|
}
|
|
|
|
if ((Tmp = OffsetPHI->hasConstantValue())) {
|
|
|
|
Offset = Tmp;
|
|
|
|
OffsetPHI->replaceAllUsesWith(Offset);
|
|
|
|
OffsetPHI->eraseFromParent();
|
|
|
|
}
|
|
|
|
return std::make_pair(Size, Offset);
|
2012-06-21 23:45:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) {
|
|
|
|
SizeOffsetEvalType TrueSide = compute_(I.getTrueValue());
|
|
|
|
SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());
|
|
|
|
|
|
|
|
if (!bothKnown(TrueSide) || !bothKnown(FalseSide))
|
|
|
|
return unknown();
|
|
|
|
if (TrueSide == FalseSide)
|
|
|
|
return TrueSide;
|
|
|
|
|
|
|
|
Value *Size = Builder.CreateSelect(I.getCondition(), TrueSide.first,
|
|
|
|
FalseSide.first);
|
|
|
|
Value *Offset = Builder.CreateSelect(I.getCondition(), TrueSide.second,
|
|
|
|
FalseSide.second);
|
|
|
|
return std::make_pair(Size, Offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) {
|
|
|
|
DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I <<'\n');
|
|
|
|
return unknown();
|
|
|
|
}
|