forked from OSchip/llvm-project
CodeGen for array new list initializers. Doesn't correctly clean up in the face of exceptions yet.
llvm-svn: 151171
This commit is contained in:
parent
2837aa2932
commit
f862eb6a9f
|
@ -508,6 +508,7 @@ static CharUnits CalculateCookiePadding(CodeGenFunction &CGF,
|
|||
|
||||
static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
||||
const CXXNewExpr *e,
|
||||
unsigned minElements,
|
||||
llvm::Value *&numElements,
|
||||
llvm::Value *&sizeWithoutCookie) {
|
||||
QualType type = e->getAllocatedType();
|
||||
|
@ -581,6 +582,11 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
// Okay, compute a count at the right width.
|
||||
llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);
|
||||
|
||||
// If there is a brace-initializer, we cannot allocate fewer elements than
|
||||
// there are initializers. If we do, that's treated like an overflow.
|
||||
if (adjustedCount.ult(minElements))
|
||||
hasAnyOverflow = true;
|
||||
|
||||
// Scale numElements by that. This might overflow, but we don't
|
||||
// care because it only overflows if allocationSize does, too, and
|
||||
// if that overflows then we shouldn't use this.
|
||||
|
@ -612,14 +618,16 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
|
||||
// Otherwise, we might need to use the overflow intrinsics.
|
||||
} else {
|
||||
// There are up to four conditions we need to test for:
|
||||
// There are up to five conditions we need to test for:
|
||||
// 1) if isSigned, we need to check whether numElements is negative;
|
||||
// 2) if numElementsWidth > sizeWidth, we need to check whether
|
||||
// numElements is larger than something representable in size_t;
|
||||
// 3) we need to compute
|
||||
// 3) if minElements > 0, we need to check whether numElements is smaller
|
||||
// than that.
|
||||
// 4) we need to compute
|
||||
// sizeWithoutCookie := numElements * typeSizeMultiplier
|
||||
// and check whether it overflows; and
|
||||
// 4) if we need a cookie, we need to compute
|
||||
// 5) if we need a cookie, we need to compute
|
||||
// size := sizeWithoutCookie + cookieSize
|
||||
// and check whether it overflows.
|
||||
|
||||
|
@ -646,10 +654,11 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
// If there's a non-1 type size multiplier, then we can do the
|
||||
// signedness check at the same time as we do the multiply
|
||||
// because a negative number times anything will cause an
|
||||
// unsigned overflow. Otherwise, we have to do it here.
|
||||
// unsigned overflow. Otherwise, we have to do it here. But at least
|
||||
// in this case, we can subsume the >= minElements check.
|
||||
if (typeSizeMultiplier == 1)
|
||||
hasOverflow = CGF.Builder.CreateICmpSLT(numElements,
|
||||
llvm::ConstantInt::get(CGF.SizeTy, 0));
|
||||
llvm::ConstantInt::get(CGF.SizeTy, minElements));
|
||||
|
||||
// Otherwise, zext up to size_t if necessary.
|
||||
} else if (numElementsWidth < sizeWidth) {
|
||||
|
@ -658,6 +667,21 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
|
||||
assert(numElements->getType() == CGF.SizeTy);
|
||||
|
||||
if (minElements) {
|
||||
// Don't allow allocation of fewer elements than we have initializers.
|
||||
if (!hasOverflow) {
|
||||
hasOverflow = CGF.Builder.CreateICmpULT(numElements,
|
||||
llvm::ConstantInt::get(CGF.SizeTy, minElements));
|
||||
} else if (numElementsWidth > sizeWidth) {
|
||||
// The other existing overflow subsumes this check.
|
||||
// We do an unsigned comparison, since any signed value < -1 is
|
||||
// taken care of either above or below.
|
||||
hasOverflow = CGF.Builder.CreateOr(hasOverflow,
|
||||
CGF.Builder.CreateICmpULT(numElements,
|
||||
llvm::ConstantInt::get(CGF.SizeTy, minElements)));
|
||||
}
|
||||
}
|
||||
|
||||
size = numElements;
|
||||
|
||||
// Multiply by the type size if necessary. This multiplier
|
||||
|
@ -741,11 +765,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
return size;
|
||||
}
|
||||
|
||||
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
|
||||
llvm::Value *NewPtr) {
|
||||
|
||||
const Expr *Init = E->getInitializer();
|
||||
QualType AllocType = E->getAllocatedType();
|
||||
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
|
||||
QualType AllocType, llvm::Value *NewPtr) {
|
||||
|
||||
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
|
||||
if (!CGF.hasAggregateLLVMType(AllocType))
|
||||
|
@ -775,26 +796,39 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
|
|||
if (!E->hasInitializer())
|
||||
return; // We have a POD type.
|
||||
|
||||
// Check if the number of elements is constant.
|
||||
bool checkZero = true;
|
||||
if (llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements)) {
|
||||
// If it's constant zero, skip the whole loop.
|
||||
if (constNum->isZero()) return;
|
||||
|
||||
checkZero = false;
|
||||
}
|
||||
|
||||
llvm::Value *explicitPtr = beginPtr;
|
||||
// Find the end of the array, hoisted out of the loop.
|
||||
llvm::Value *endPtr =
|
||||
Builder.CreateInBoundsGEP(beginPtr, numElements, "array.end");
|
||||
|
||||
unsigned initializerElements = 0;
|
||||
|
||||
const Expr *Init = E->getInitializer();
|
||||
// If the initializer is an initializer list, first do the explicit elements.
|
||||
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
|
||||
initializerElements = ILE->getNumInits();
|
||||
QualType elementType = E->getAllocatedType();
|
||||
// FIXME: exception-safety for the explicit initializers
|
||||
for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) {
|
||||
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), elementType, explicitPtr);
|
||||
explicitPtr =Builder.CreateConstGEP1_32(explicitPtr, 1, "array.exp.next");
|
||||
}
|
||||
|
||||
// The remaining elements are filled with the array filler expression.
|
||||
Init = ILE->getArrayFiller();
|
||||
}
|
||||
|
||||
// Create the continuation block.
|
||||
llvm::BasicBlock *contBB = createBasicBlock("new.loop.end");
|
||||
|
||||
// If we need to check for zero, do so now.
|
||||
if (checkZero) {
|
||||
// If the number of elements isn't constant, we have to now check if there is
|
||||
// anything left to initialize.
|
||||
if (llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements)) {
|
||||
// If all elements have already been initialized, skip the whole loop.
|
||||
if (constNum->getZExtValue() <= initializerElements) return;
|
||||
} else {
|
||||
llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty");
|
||||
llvm::Value *isEmpty = Builder.CreateICmpEQ(beginPtr, endPtr,
|
||||
llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr,
|
||||
"array.isempty");
|
||||
Builder.CreateCondBr(isEmpty, contBB, nonEmptyBB);
|
||||
EmitBlock(nonEmptyBB);
|
||||
|
@ -808,8 +842,8 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
|
|||
|
||||
// Set up the current-element phi.
|
||||
llvm::PHINode *curPtr =
|
||||
Builder.CreatePHI(beginPtr->getType(), 2, "array.cur");
|
||||
curPtr->addIncoming(beginPtr, entryBB);
|
||||
Builder.CreatePHI(explicitPtr->getType(), 2, "array.cur");
|
||||
curPtr->addIncoming(explicitPtr, entryBB);
|
||||
|
||||
// Enter a partial-destruction cleanup if necessary.
|
||||
QualType::DestructionKind dtorKind = elementType.isDestructedType();
|
||||
|
@ -823,7 +857,7 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
|
|||
}
|
||||
|
||||
// Emit the initializer into this element.
|
||||
StoreAnyExprIntoOneUnit(*this, E, curPtr);
|
||||
StoreAnyExprIntoOneUnit(*this, Init, E->getAllocatedType(), curPtr);
|
||||
|
||||
// Leave the cleanup if we entered one.
|
||||
if (cleanupDominator) {
|
||||
|
@ -895,7 +929,7 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
|
|||
if (!Init)
|
||||
return;
|
||||
|
||||
StoreAnyExprIntoOneUnit(CGF, E, NewPtr);
|
||||
StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -1069,10 +1103,18 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||
// The allocation size is the first argument.
|
||||
QualType sizeType = getContext().getSizeType();
|
||||
|
||||
// If there is a brace-initializer, cannot allocate fewer elements than inits.
|
||||
unsigned minElements = 0;
|
||||
if (E->isArray() && E->hasInitializer()) {
|
||||
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer()))
|
||||
minElements = ILE->getNumInits();
|
||||
}
|
||||
|
||||
llvm::Value *numElements = 0;
|
||||
llvm::Value *allocSizeWithoutCookie = 0;
|
||||
llvm::Value *allocSize =
|
||||
EmitCXXNewAllocSize(*this, E, numElements, allocSizeWithoutCookie);
|
||||
EmitCXXNewAllocSize(*this, E, minElements, numElements,
|
||||
allocSizeWithoutCookie);
|
||||
|
||||
allocatorArgs.add(RValue::get(allocSize), sizeType);
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: define void @_Z2fni
|
||||
void fn(int n) {
|
||||
// CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
||||
// CHECK: store i32 1
|
||||
// CHECK: store i32 2
|
||||
// CHECK: store i32 3
|
||||
// CHECK: icmp eq i32*
|
||||
// CHECK-NEXT: br i1
|
||||
new int[n] { 1, 2, 3 };
|
||||
}
|
||||
|
||||
// CHECK: define void @_Z15const_underflowv
|
||||
void const_underflow() {
|
||||
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
||||
// CHECK: call noalias i8* @_Zna{{.}}(i{{32|64}} -1)
|
||||
new int[2] { 1, 2, 3 };
|
||||
}
|
||||
|
||||
// CHECK: define void @_Z11const_exactv
|
||||
void const_exact() {
|
||||
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
||||
// CHECK-NOT: icmp eq i32*
|
||||
new int[3] { 1, 2, 3 };
|
||||
}
|
||||
|
||||
// CHECK: define void @_Z16const_sufficientv
|
||||
void const_sufficient() {
|
||||
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
||||
new int[4] { 1, 2, 3 };
|
||||
// CHECK: ret void
|
||||
}
|
Loading…
Reference in New Issue