llvm.org GIT mirror llvm / 97e1656
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307754 91177308-0d34-0410-b5e6-96231b3b80d8 Mikael Holmen 3 years ago
2 changed file(s) with 27 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
223223 SizeOffsetType visitSelectInst(SelectInst &I);
224224 SizeOffsetType visitUndefValue(UndefValue&);
225225 SizeOffsetType visitInstruction(Instruction &I);
226
227 private:
228 bool CheckedZextOrTrunc(APInt &I);
226229 };
227230
228231 typedef std::pair SizeOffsetEvalType;
504504 return unknown();
505505 }
506506
507 /// When we're compiling N-bit code, and the user uses parameters that are
508 /// greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
509 /// trouble with APInt size issues. This function handles resizing + overflow
510 /// checks for us. Check and zext or trunc \p I depending on IntTyBits and
511 /// I's value.
512 bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
513 // More bits than we can handle. Checking the bit width isn't necessary, but
514 // it's faster than checking active bits, and should give `false` in the
515 // vast majority of cases.
516 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
517 return false;
518 if (I.getBitWidth() != IntTyBits)
519 I = I.zextOrTrunc(IntTyBits);
520 return true;
521 }
522
507523 SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
508524 if (!I.getAllocatedType()->isSized())
509525 return unknown();
514530
515531 Value *ArraySize = I.getArraySize();
516532 if (const ConstantInt *C = dyn_cast(ArraySize)) {
517 Size *= C->getValue().zextOrSelf(IntTyBits);
518 return std::make_pair(align(Size, I.getAlignment()), Zero);
533 APInt NumElems = C->getValue();
534 if (!CheckedZextOrTrunc(NumElems))
535 return unknown();
536
537 bool Overflow;
538 Size = Size.umul_ov(NumElems, Overflow);
539 return Overflow ? unknown() : std::make_pair(align(Size, I.getAlignment()),
540 Zero);
519541 }
520542 return unknown();
521543 }
559581 ConstantInt *Arg = dyn_cast(CS.getArgument(FnData->FstParam));
560582 if (!Arg)
561583 return unknown();
562
563 // When we're compiling N-bit code, and the user uses parameters that are
564 // greater than N bits (e.g. uint64_t on a 32-bit build), we can run into
565 // trouble with APInt size issues. This function handles resizing + overflow
566 // checks for us.
567 auto CheckedZextOrTrunc = [&](APInt &I) {
568 // More bits than we can handle. Checking the bit width isn't necessary, but
569 // it's faster than checking active bits, and should give `false` in the
570 // vast majority of cases.
571 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
572 return false;
573 if (I.getBitWidth() != IntTyBits)
574 I = I.zextOrTrunc(IntTyBits);
575 return true;
576 };
577584
578585 APInt Size = Arg->getValue();
579586 if (!CheckedZextOrTrunc(Size))