diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Analysis/MemoryBuiltins.cpp | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) |
Notes
Diffstat (limited to 'lib/Analysis/MemoryBuiltins.cpp')
-rw-r--r-- | lib/Analysis/MemoryBuiltins.cpp | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index 24fedfed772c..686ad294378c 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetFolder.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" @@ -40,7 +41,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/Local.h" #include <cassert> #include <cstdint> #include <iterator> @@ -75,12 +75,24 @@ static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = { {LibFunc_valloc, {MallocLike, 1, 0, -1}}, {LibFunc_Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int) {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) + {LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1}}, // new(unsigned int, align_val_t) + {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, // new(unsigned int, align_val_t, nothrow) + {MallocLike, 3, 0, -1}}, {LibFunc_Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long) {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow) + {LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1}}, // new(unsigned long, align_val_t) + {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, // new(unsigned long, align_val_t, nothrow) + {MallocLike, 3, 0, -1}}, {LibFunc_Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) + {LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1}}, // new[](unsigned int, align_val_t) + {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, // new[](unsigned int, align_val_t, nothrow) + {MallocLike, 3, 0, -1}}, {LibFunc_Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long) {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow) + {LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1}}, // new[](unsigned long, align_val_t) + {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, // new[](unsigned long, align_val_t, nothrow) + {MallocLike, 3, 0, -1}}, {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) @@ -112,10 +124,9 @@ static const Function *getCalledFunction(const Value *V, bool LookThroughBitCast IsNoBuiltin = CS.isNoBuiltin(); - const Function *Callee = CS.getCalledFunction(); - if (!Callee || !Callee->isDeclaration()) - return nullptr; - return Callee; + if (const Function *Callee = CS.getCalledFunction()) + return Callee; + return nullptr; } /// Returns the allocation data for the given value if it's either a call to a @@ -206,7 +217,7 @@ static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) { return CS && CS.hasRetAttr(Attribute::NoAlias); } -/// \brief Tests if a value is a call or invoke to a library function that +/// 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). bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, @@ -214,7 +225,7 @@ bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, return getAllocationData(V, AnyAlloc, TLI, LookThroughBitCast).hasValue(); } -/// \brief Tests if a value is a call or invoke to a function that returns a +/// Tests if a value is a call or invoke to a function that returns a /// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions). bool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { @@ -224,29 +235,29 @@ bool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI, hasNoAliasAttr(V, LookThroughBitCast); } -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates uninitialized memory (such as malloc). bool llvm::isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { return getAllocationData(V, MallocLike, TLI, LookThroughBitCast).hasValue(); } -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates zero-filled memory (such as calloc). bool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { return getAllocationData(V, CallocLike, TLI, LookThroughBitCast).hasValue(); } -/// \brief Tests if a value is a call or invoke to a library function that -/// allocates memory similiar to malloc or calloc. +/// Tests if a value is a call or invoke to a library function that +/// allocates memory similar to malloc or calloc. bool llvm::isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { return getAllocationData(V, MallocOrCallocLike, TLI, LookThroughBitCast).hasValue(); } -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates memory (either malloc, calloc, or strdup like). bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { @@ -350,11 +361,10 @@ const CallInst *llvm::extractCallocCall(const Value *I, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { - const CallInst *CI = dyn_cast<CallInst>(I); - if (!CI || isa<IntrinsicInst>(CI)) - return nullptr; - Function *Callee = CI->getCalledFunction(); - if (Callee == nullptr) + bool IsNoBuiltinCall; + const Function *Callee = + getCalledFunction(I, /*LookThroughBitCast=*/false, IsNoBuiltinCall); + if (Callee == nullptr || IsNoBuiltinCall) return nullptr; StringRef FnName = Callee->getName(); @@ -374,9 +384,11 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { else if (TLIFn == LibFunc_ZdlPvj || // delete(void*, uint) TLIFn == LibFunc_ZdlPvm || // delete(void*, ulong) TLIFn == LibFunc_ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) + TLIFn == LibFunc_ZdlPvSt11align_val_t || // delete(void*, align_val_t) TLIFn == LibFunc_ZdaPvj || // delete[](void*, uint) TLIFn == LibFunc_ZdaPvm || // delete[](void*, ulong) TLIFn == LibFunc_ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) + TLIFn == LibFunc_ZdaPvSt11align_val_t || // delete[](void*, align_val_t) 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) @@ -386,6 +398,9 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { TLIFn == LibFunc_msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ExpectedNumParams = 2; + else if (TLIFn == LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t || // delete(void*, align_val_t, nothrow) + TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t) // delete[](void*, align_val_t, nothrow) + ExpectedNumParams = 3; else return nullptr; @@ -400,7 +415,7 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext())) return nullptr; - return CI; + return dyn_cast<CallInst>(I); } //===----------------------------------------------------------------------===// @@ -412,7 +427,7 @@ static APInt getSizeWithOverflow(const SizeOffsetType &Data) { return Data.first - Data.second; } -/// \brief Compute the size of the object pointed by Ptr. Returns true and the +/// 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 alignment of /// allocas, byval arguments, and global variables. @@ -513,8 +528,8 @@ SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { return visitGEPOperator(cast<GEPOperator>(*CE)); } - DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V - << '\n'); + LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " + << *V << '\n'); return unknown(); } @@ -627,7 +642,14 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) { SizeOffsetType ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull& CPN) { - if (Options.NullIsUnknownSize && CPN.getType()->getAddressSpace() == 0) + // If null is unknown, there's nothing we can do. Additionally, non-zero + // address spaces can make use of null, so we don't presume to know anything + // about that. + // + // TODO: How should this work with address space casts? We currently just drop + // them on the floor, but it's unclear what we should do when a NULL from + // addrspace(1) gets casted to addrspace(0) (or vice-versa). + if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) return unknown(); return std::make_pair(Zero, Zero); } @@ -714,7 +736,8 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) { } SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { - DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n'); + LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I + << '\n'); return unknown(); } @@ -793,8 +816,9 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { // Ignore values where we cannot do more than ObjectSizeVisitor. Result = unknown(); } else { - DEBUG(dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " - << *V << '\n'); + LLVM_DEBUG( + dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V + << '\n'); Result = unknown(); } @@ -931,6 +955,7 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { } SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) { - DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I <<'\n'); + LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I + << '\n'); return unknown(); } |