diff options
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/MemoryBuiltins.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 0f4bfb8e2fb..eaac506dec4 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -388,6 +388,36 @@ bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, return true; } +ConstantInt *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize, + const DataLayout &DL, + const TargetLibraryInfo *TLI, + bool MustSucceed) { + assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize && + "ObjectSize must be a call to llvm.objectsize!"); + + bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero(); + ObjSizeMode Mode; + // Unless we have to fold this to something, try to be as accurate as + // possible. + if (MustSucceed) + Mode = MaxVal ? ObjSizeMode::Max : ObjSizeMode::Min; + else + Mode = ObjSizeMode::Exact; + + // FIXME: Does it make sense to just return a failure value if the size won't + // fit in the output and `!MustSucceed`? + uint64_t Size; + auto *ResultType = cast<IntegerType>(ObjectSize->getType()); + if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, false, Mode) && + isUIntN(ResultType->getBitWidth(), Size)) + return ConstantInt::get(ResultType, Size); + + if (!MustSucceed) + return nullptr; + + return ConstantInt::get(ResultType, MaxVal ? -1ULL : 0); +} + STATISTIC(ObjectVisitorArgument, "Number of arguments with unsolved size and offset"); STATISTIC(ObjectVisitorLoad, |