32 #define DEBUG_TYPE "memory-builtins"
57 {LibFunc::ZnwjRKSt9nothrow_t, {
MallocLike, 2, 0, -1}},
59 {LibFunc::ZnwmRKSt9nothrow_t, {
MallocLike, 2, 0, -1}},
61 {LibFunc::ZnajRKSt9nothrow_t, {
MallocLike, 2, 0, -1}},
63 {LibFunc::ZnamRKSt9nothrow_t, {
MallocLike, 2, 0, -1}},
64 {LibFunc::msvc_new_int, {
OpNewLike, 1, 0, -1}},
65 {LibFunc::msvc_new_int_nothrow, {
MallocLike, 2, 0, -1}},
66 {LibFunc::msvc_new_longlong, {
OpNewLike, 1, 0, -1}},
67 {LibFunc::msvc_new_longlong_nothrow, {
MallocLike, 2, 0, -1}},
68 {LibFunc::msvc_new_array_int, {
OpNewLike, 1, 0, -1}},
69 {LibFunc::msvc_new_array_int_nothrow, {
MallocLike, 2, 0, -1}},
70 {LibFunc::msvc_new_array_longlong, {
OpNewLike, 1, 0, -1}},
71 {LibFunc::msvc_new_array_longlong_nothrow, {
MallocLike, 2, 0, -1}},
83 if (isa<IntrinsicInst>(V))
86 if (LookThroughBitCast)
110 if (!TLI || !TLI->
getLibFunc(FnName, TLIFn) || !TLI->
has(TLIFn))
115 return P.first == TLIFn;
144 bool LookThroughBitCast =
false) {
145 bool IsNoBuiltinCall;
148 if (!IsNoBuiltinCall)
155 bool IsNoBuiltinCall;
163 if (!IsNoBuiltinCall)
180 Result.
SndParam = Args.second.getValueOr(-1);
194 bool LookThroughBitCast) {
201 bool LookThroughBitCast) {
211 bool LookThroughBitCast) {
218 bool LookThroughBitCast) {
225 bool LookThroughBitCast) {
239 bool LookThroughSExt =
false) {
255 Value *Multiple =
nullptr;
256 if (
ComputeMultiple(MallocArg, ElementSize, Multiple, LookThroughSExt))
272 unsigned NumOfBitCastUses = 0;
277 if (
const BitCastInst *BCI = dyn_cast<BitCastInst>(*UI++)) {
278 MallocType = cast<PointerType>(BCI->getDestTy());
283 if (NumOfBitCastUses == 1)
287 if (NumOfBitCastUses == 0)
288 return cast<PointerType>(CI->
getType());
312 bool LookThroughSExt) {
329 if (!CI || isa<IntrinsicInst>(CI))
332 if (Callee ==
nullptr)
337 if (!TLI || !TLI->
getLibFunc(FnName, TLIFn) || !TLI->
has(TLIFn))
340 unsigned ExpectedNumParams;
341 if (TLIFn == LibFunc::free ||
342 TLIFn == LibFunc::ZdlPv ||
343 TLIFn == LibFunc::ZdaPv ||
344 TLIFn == LibFunc::msvc_delete_ptr32 ||
345 TLIFn == LibFunc::msvc_delete_ptr64 ||
346 TLIFn == LibFunc::msvc_delete_array_ptr32 ||
347 TLIFn == LibFunc::msvc_delete_array_ptr64)
348 ExpectedNumParams = 1;
349 else if (TLIFn == LibFunc::ZdlPvj ||
350 TLIFn == LibFunc::ZdlPvm ||
351 TLIFn == LibFunc::ZdlPvRKSt9nothrow_t ||
352 TLIFn == LibFunc::ZdaPvj ||
353 TLIFn == LibFunc::ZdaPvm ||
354 TLIFn == LibFunc::ZdaPvRKSt9nothrow_t ||
355 TLIFn == LibFunc::msvc_delete_ptr32_int ||
356 TLIFn == LibFunc::msvc_delete_ptr64_longlong ||
357 TLIFn == LibFunc::msvc_delete_ptr32_nothrow ||
358 TLIFn == LibFunc::msvc_delete_ptr64_nothrow ||
359 TLIFn == LibFunc::msvc_delete_array_ptr32_int ||
360 TLIFn == LibFunc::msvc_delete_array_ptr64_longlong ||
361 TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow ||
362 TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow)
363 ExpectedNumParams = 2;
387 if (Data.second.isNegative() || Data.first.ult(Data.second))
388 return APInt(Data.first.getBitWidth(), 0);
389 return Data.first - Data.second;
402 if (!Visitor.bothKnown(Data))
414 "ObjectSize must be a call to llvm.objectsize!");
428 auto *ResultType = cast<IntegerType>(ObjectSize->
getType());
430 isUIntN(ResultType->getBitWidth(), Size))
440 "Number of arguments with unsolved size and offset");
442 "Number of load instructions with unsolved size and offset");
445 APInt ObjectSizeOffsetVisitor::align(
APInt Size, uint64_t Align) {
446 if (RoundToAlign && Align)
456 : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign), Mode(Mode) {
469 if (!SeenInsts.
insert(
I).second)
487 if (CE->getOpcode() == Instruction::IntToPtr)
489 if (CE->getOpcode() == Instruction::GetElementPtr)
493 DEBUG(
dbgs() <<
"ObjectSizeOffsetVisitor::compute() unhandled value: " << *V
504 return std::make_pair(align(Size, I.
getAlignment()), Zero);
507 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(ArraySize)) {
508 Size *=
C->getValue().zextOrSelf(IntTyBits);
509 return std::make_pair(align(Size, I.
getAlignment()), Zero);
517 ++ObjectVisitorArgument;
544 if (Size.
ugt(MaxSize))
547 return std::make_pair(Size, Zero);
558 auto CheckedZextOrTrunc = [&](
APInt &
I) {
562 if (
I.getBitWidth() > IntTyBits &&
I.getActiveBits() > IntTyBits)
564 if (
I.getBitWidth() != IntTyBits)
565 I =
I.zextOrTrunc(IntTyBits);
570 if (!CheckedZextOrTrunc(Size))
575 return std::make_pair(Size, Zero);
582 if (!CheckedZextOrTrunc(NumElems))
586 Size = Size.
umul_ov(NumElems, Overflow);
587 return Overflow ? unknown() : std::make_pair(Size, Zero);
600 return std::make_pair(Zero, Zero);
620 return std::make_pair(PtrData.first, PtrData.second + Offset);
634 return std::make_pair(align(Size, GV.
getAlignment()), Zero);
656 if (TrueSide == FalseSide) {
663 if (TrueResult == FalseResult) {
667 if (TrueResult.
slt(FalseResult))
672 if (TrueResult.
sgt(FalseResult))
681 return std::make_pair(Zero, Zero);
685 DEBUG(
dbgs() <<
"ObjectSizeOffsetVisitor unknown instruction:" << I <<
'\n');
692 : DL(DL), TLI(TLI), Context(Context), Builder(Context,
TargetFolder(DL)),
693 RoundToAlign(RoundToAlign) {
709 for (
const Value *SeenVal : SeenVals) {
712 if (CacheIt != CacheMap.
end() &&
anyKnown(CacheIt->second))
713 CacheMap.
erase(CacheIt);
724 if (Visitor.bothKnown(Const))
732 if (CacheIt != CacheMap.
end())
733 return CacheIt->second;
747 if (!SeenVals.
insert(V).second) {
753 }
else if (isa<Argument>(V) ||
754 (isa<ConstantExpr>(V) &&
755 cast<ConstantExpr>(V)->getOpcode() == Instruction::IntToPtr) ||
756 isa<GlobalAlias>(V) ||
757 isa<GlobalVariable>(V)) {
761 DEBUG(
dbgs() <<
"ObjectSizeOffsetEvaluator::compute() unhandled value: "
767 CacheMap[V] = Result;
780 Size = Builder.
CreateMul(Size, ArraySize);
781 return std::make_pair(Size, Zero);
796 FirstArg = Builder.
CreateZExt(FirstArg, IntTy);
798 return std::make_pair(FirstArg, Zero);
801 SecondArg = Builder.
CreateZExt(SecondArg, IntTy);
803 return std::make_pair(Size, Zero);
831 Offset = Builder.
CreateAdd(PtrData.second, Offset);
832 return std::make_pair(PtrData.first, Offset);
850 CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
879 return std::make_pair(Size, Offset);
888 if (TrueSide == FalseSide)
895 return std::make_pair(Size, Offset);
899 DEBUG(
dbgs() <<
"ObjectSizeOffsetEvaluator unknown instruction:" << I <<
'\n');
Value * EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, bool NoAssumptions=false)
Given a getelementptr instruction/constantexpr, emit the code necessary to compute the offset from th...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
A parsed version of the target data layout string in and methods for querying it. ...
const_iterator end(StringRef path)
Get end iterator over path.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
uint64_t getZExtValue() const
Get zero extended value.
STATISTIC(NumFunctions,"Total number of functions")
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
const CallInst * extractCallocCall(const Value *I, const TargetLibraryInfo *TLI)
extractCallocCall - Returns the corresponding CallInst if the instruction is a calloc call...
uint64_t GetStringLength(const Value *V)
If we can compute the length of the string pointed to by the specified pointer, return 'len+1'...
bool hasByValOrInAllocaAttr() const
Return true if this argument has the byval attribute or inalloca attribute on it in its containing fu...
unsigned getNumOperands() const
unsigned getPointerTypeSizeInBits(Type *) const
Layout pointer size, in bits, based on the type.
This class represents a function call, abstracting a target machine's calling convention.
static Optional< AllocFnsTy > getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, const TargetLibraryInfo *TLI)
Returns the allocation data for the given value if it's either a call to a known allocation function...
SizeOffsetType visitAllocaInst(AllocaInst &I)
The two locations do not alias at all.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
An instruction for reading from memory.
SizeOffsetType visitArgument(Argument &A)
Type * getElementType() const
const Constant * getAliasee() const
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
const CallInst * isFreeCall(const Value *I, const TargetLibraryInfo *TLI)
isFreeCall - Returns non-null if the value is a call to the builtin free()
StringRef getName() const
Return a constant reference to the value's name.
bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1...
This class represents the LLVM 'select' instruction.
SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP)
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
SizeOffsetType visitExtractValueInst(ExtractValueInst &I)
SizeOffsetType visitGEPOperator(GEPOperator &GEP)
const APInt & getValue() const
Return the constant as an APInt value reference.
'undef' values are things that do not have specified contents.
std::pair< unsigned, Optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute (or pair(0, 0) if not known).
bool has(LibFunc::Func F) const
Tests whether a library function is available.
static Optional< AllocFnsTy > getAllocationSize(const Value *V, const TargetLibraryInfo *TLI)
Class to represent struct types.
SizeOffsetEvalType visitCallSite(CallSite CS)
SizeOffsetType visitIntToPtrInst(IntToPtrInst &)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign=false)
void visit(Iterator Start, Iterator End)
bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a function that returns a NoAlias pointer (including malloc/c...
A constant value that is initialized with an expression using other constant values.
Class to represent function types.
APInt zextOrSelf(unsigned width) const
Zero extend or truncate to width.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const
Accumulate the constant address offset of this GEP if possible.
unsigned getAlignment() const
bool sgt(const APInt &RHS) const
Signed greather than comparison.
This class represents a no-op cast from one type to another.
TargetFolder - Create constants with target dependent folding.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign=false, ObjSizeMode Mode=ObjSizeMode::Exact)
Compute the size of the object pointed by Ptr.
std::pair< APInt, APInt > SizeOffsetType
bool hasDefinitiveInitializer() const
hasDefinitiveInitializer - Whether the global variable has an initializer, and any other instances of...
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
APInt umul_ov(const APInt &RHS, bool &Overflow) const
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="")
SizeOffsetType visitInstruction(Instruction &I)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Class to represent pointers.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Value * getMallocArraySize(CallInst *CI, const DataLayout &DL, const TargetLibraryInfo *TLI, bool LookThroughSExt=false)
getMallocArraySize - Returns the array size of a malloc call.
SizeOffsetType visitGlobalVariable(GlobalVariable &GV)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const
Searches for a particular function name.
Type * getParamType(unsigned i) const
Parameter type accessors.
bool erase(const KeyT &Val)
SizeOffsetEvalType visitSelectInst(SelectInst &I)
ConstantInt * lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL, const TargetLibraryInfo *TLI, bool MustSucceed)
Try to turn a call to .objectsize into an integer value of the given Type.
Value * hasConstantValue() const
If the specified PHI node always merges together the same value, return the value, otherwise return null.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
const CallInst * extractMallocCall(const Value *I, const TargetLibraryInfo *TLI)
extractMallocCall - Returns the corresponding CallInst if the instruction is a malloc call...
const Value * getCondition() const
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
unsigned getAlignment() const
Return the alignment of the memory that is being allocated by the instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
unsigned getParamAlignment() const
If this is a byval or inalloca argument, return its alignment.
static Value * computeArraySize(const CallInst *CI, const DataLayout &DL, const TargetLibraryInfo *TLI, bool LookThroughSExt=false)
static APInt getSizeWithOverflow(const SizeOffsetType &Data)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getPointerOperand()
static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast)
static Optional< AllocFnsTy > getAllocationData(const Value *V, AllocType AllocTy, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
This class represents a cast from an integer to a pointer.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
SizeOffsetType visitCallSite(CallSite CS)
LLVMContext & getContext() const
All values hold a context through their type.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
const Value * getTrueValue() const
PointerType * getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI)
getMallocType - Returns the PointerType resulting from the malloc call.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
SizeOffsetType visitSelectInst(SelectInst &I)
SizeOffsetType visitExtractElementInst(ExtractElementInst &I)
SizeOffsetType visitGlobalAlias(GlobalAlias &GA)
bool ugt(const APInt &RHS) const
Unsigned greather than comparison.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
SizeOffsetEvalType visitInstruction(Instruction &I)
This is the shared class of boolean and integer constants.
InstrTy * getInstruction() const
bool slt(const APInt &RHS) const
Signed less than comparison.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Evaluate the size and offset of an object pointed to by a Value* statically.
ValTy * getArgument(unsigned ArgNo) const
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
SizeOffsetType visitPHINode(PHINode &)
A constant pointer value that points to null.
uint64_t getSizeInBytes() const
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
SizeOffsetType visitUndefValue(UndefValue &)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SizeOffsetType compute(Value *V)
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
Class for arbitrary precision integers.
std::pair< Value *, Value * > SizeOffsetEvalType
SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst &)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI)
getMallocAllocatedType - Returns the Type allocated by malloc call.
SizeOffsetEvalType visitPHINode(PHINode &PHI)
bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates uninitialized memory (such ...
SizeOffsetEvalType compute(Value *V)
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
PointerType * getType() const
Global values are always pointers.
user_iterator_impl< const User > const_user_iterator
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
SizeOffsetEvalType visitLoadInst(LoadInst &I)
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign=false, ObjSizeMode Mode=ObjSizeMode::Exact)
ImmutableCallSite - establish a view to a call site for examination.
bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates zero-filled memory (such as...
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates memory (either malloc...
bool ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, bool LookThroughSExt=false, unsigned Depth=0)
This function computes the integer multiple of Base that equals V.
iterator find(const KeyT &Val)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static const std::pair< LibFunc::Func, AllocFnsTy > AllocationFnData[]
bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time...
bool anyKnown(SizeOffsetEvalType SizeOffset)
static Function * getCalledFunction(const Value *V, bool LookThroughBitCast, bool &IsNoBuiltin)
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
static bool bothKnown(const SizeOffsetType &SizeOffset)
FunTy * getCalledFunction() const
getCalledFunction - Return the function being called if this is a direct call, otherwise return null ...
LLVM Value Representation.
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I)
const Value * getArraySize() const
Get the number of elements allocated.
const Value * getFalseValue() const
StringRef - Represent a constant reference to a string, i.e.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static APInt getNullValue(unsigned numBits)
Get the '0' value.
auto find_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
bool isUIntN(unsigned N, uint64_t x)
isUIntN - Checks if an unsigned integer fits into the given (dynamic) bit width.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
SizeOffsetType visitLoadInst(LoadInst &I)
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
SizeOffsetEvalType visitAllocaInst(AllocaInst &I)
bool bothKnown(SizeOffsetEvalType SizeOffset)
SizeOffsetType visitConstantPointerNull(ConstantPointerNull &)
SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I)
A wrapper class for inspecting calls to intrinsic functions.
bool isVoidTy() const
Return true if this is 'void'.
an instruction to allocate memory on the stack