summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/MemoryBuiltins.cpp
diff options
context:
space:
mode:
authorMikael Holmen <mikael.holmen@ericsson.com>2017-07-12 06:19:10 +0000
committerMikael Holmen <mikael.holmen@ericsson.com>2017-07-12 06:19:10 +0000
commitad7e718307a20c6e31ef2e2b54a69756188e3457 (patch)
tree4b9f0d06aa67c95602c2f1b2144690e630a146e0 /llvm/lib/Analysis/MemoryBuiltins.cpp
parente970c2b706d19af3950beba3fe4eebeceed31feb (diff)
downloadbcm5719-llvm-ad7e718307a20c6e31ef2e2b54a69756188e3457.tar.gz
bcm5719-llvm-ad7e718307a20c6e31ef2e2b54a69756188e3457.zip
[MemoryBuiltins] Allow truncation in visitAllocaInst()
Summary: Solves PR33689. If the pointer size is less than the size of the type used for the array size in an alloca (the <ty> type below) then we could trigger the assert in the PR. In that example we have pointer size i16 and <ty> is i32. <result> = alloca [inalloca] <type> [, <ty> <NumElements>] [, align <alignment>] Handle the situation by allowing truncation as well as zero extension in ObjectSizeOffsetVisitor::visitAllocaInst(). Also, we now detect overflow in visitAllocaInst(), similar to how it was already done in visitCallSite(). Reviewers: craig.topper, rnk, george.burgess.iv Reviewed By: george.burgess.iv Subscribers: davide, llvm-commits Differential Revision: https://reviews.llvm.org/D35003 llvm-svn: 307754
Diffstat (limited to 'llvm/lib/Analysis/MemoryBuiltins.cpp')
-rw-r--r--llvm/lib/Analysis/MemoryBuiltins.cpp41
1 files changed, 24 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index f88d54b21e1..7327c07499b 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -505,6 +505,22 @@ SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
return unknown();
}
+/// When we're compiling N-bit code, and the user uses parameters that are
+/// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
+/// trouble with APInt size issues. This function handles resizing + overflow
+/// checks for us. Check and zext or trunc \p I depending on IntTyBits and
+/// I's value.
+bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
+ // More bits than we can handle. Checking the bit width isn't necessary, but
+ // it's faster than checking active bits, and should give `false` in the
+ // vast majority of cases.
+ if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
+ return false;
+ if (I.getBitWidth() != IntTyBits)
+ I = I.zextOrTrunc(IntTyBits);
+ return true;
+}
+
SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
if (!I.getAllocatedType()->isSized())
return unknown();
@@ -515,8 +531,14 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
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);
+ APInt NumElems = C->getValue();
+ if (!CheckedZextOrTrunc(NumElems))
+ return unknown();
+
+ bool Overflow;
+ Size = Size.umul_ov(NumElems, Overflow);
+ return Overflow ? unknown() : std::make_pair(align(Size, I.getAlignment()),
+ Zero);
}
return unknown();
}
@@ -561,21 +583,6 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
if (!Arg)
return unknown();
- // When we're compiling N-bit code, and the user uses parameters that are
- // greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
- // trouble with APInt size issues. This function handles resizing + overflow
- // checks for us.
- auto CheckedZextOrTrunc = [&](APInt &I) {
- // More bits than we can handle. Checking the bit width isn't necessary, but
- // it's faster than checking active bits, and should give `false` in the
- // vast majority of cases.
- if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
- return false;
- if (I.getBitWidth() != IntTyBits)
- I = I.zextOrTrunc(IntTyBits);
- return true;
- };
-
APInt Size = Arg->getValue();
if (!CheckedZextOrTrunc(Size))
return unknown();
OpenPOWER on IntegriCloud