diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 145 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 42 |
2 files changed, 103 insertions, 84 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 222d87b44c..47d4fcbae3 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1033,73 +1033,68 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, } } -/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) -/// for-loop to call the default constructor on individual members of the -/// array. -/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the -/// array type and 'ArrayPtr' points to the beginning fo the array. -/// It is assumed that all relevant checks have been made by the caller. +/// EmitCXXAggrConstructorCall - Emit a loop to call a particular +/// constructor for each of several members of an array. /// -/// \param ZeroInitialization True if each element should be zero-initialized -/// before it is constructed. +/// \param ctor the constructor to call for each element +/// \param argBegin,argEnd the arguments to evaluate and pass to the +/// constructor +/// \param arrayType the type of the array to initialize +/// \param arrayBegin an arrayType* +/// \param zeroInitialize true if each element should be +/// zero-initialized before it is constructed void -CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - const ConstantArrayType *ArrayTy, - llvm::Value *ArrayPtr, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, - bool ZeroInitialization) { - - const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); - llvm::Value * NumElements = - llvm::ConstantInt::get(SizeTy, - getContext().getConstantArrayElementCount(ArrayTy)); - - EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd, - ZeroInitialization); +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, + const ConstantArrayType *arrayType, + llvm::Value *arrayBegin, + CallExpr::const_arg_iterator argBegin, + CallExpr::const_arg_iterator argEnd, + bool zeroInitialize) { + QualType elementType; + llvm::Value *numElements = + emitArrayLength(arrayType, elementType, arrayBegin); + + EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, + argBegin, argEnd, zeroInitialize); } +/// EmitCXXAggrConstructorCall - Emit a loop to call a particular +/// constructor for each of several members of an array. +/// +/// \param ctor the constructor to call for each element +/// \param numElements the number of elements in the array; +/// assumed to be non-zero +/// \param argBegin,argEnd the arguments to evaluate and pass to the +/// constructor +/// \param arrayBegin a T*, where T is the type constructed by ctor +/// \param zeroInitialize true if each element should be +/// zero-initialized before it is constructed void -CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - llvm::Value *NumElements, - llvm::Value *ArrayPtr, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, - bool ZeroInitialization) { - const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); - - // Create a temporary for the loop index and initialize it with 0. - llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index"); - llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); - Builder.CreateStore(Zero, IndexPtr); - - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); - - EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - - // Generate: if (loop-index < number-of-elements fall to the loop body, - // otherwise, go to the block after the for-loop. - llvm::Value *Counter = Builder.CreateLoad(IndexPtr); - llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless"); - // If the condition is true, execute the body. - Builder.CreateCondBr(IsLess, ForBody, AfterFor); +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, + llvm::Value *numElements, + llvm::Value *arrayBegin, + CallExpr::const_arg_iterator argBegin, + CallExpr::const_arg_iterator argEnd, + bool zeroInitialize) { + // Find the end of the array. + llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements, + "arrayctor.end"); + + // Enter the loop, setting up a phi for the current location to initialize. + llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); + llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop"); + EmitBlock(loopBB); + llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2, + "arrayctor.cur"); + cur->addIncoming(arrayBegin, entryBB); - EmitBlock(ForBody); - - llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); // Inside the loop body, emit the constructor call on the array element. - Counter = Builder.CreateLoad(IndexPtr); - llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, - "arrayidx"); + + QualType type = getContext().getTypeDeclType(ctor->getParent()); // Zero initialize the storage, if requested. - if (ZeroInitialization) - EmitNullInitialization(Address, - getContext().getTypeDeclType(D->getParent())); + if (zeroInitialize) + EmitNullInitialization(cur, type); // C++ [class.temporary]p4: // There are two contexts in which temporaries are destroyed at a different @@ -1109,27 +1104,33 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, // every temporary created in a default argument expression is sequenced // before the construction of the next array element, if any. - // Keep track of the current number of live temporaries. { RunCleanupsScope Scope(*this); - EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address, - ArgBeg, ArgEnd); - } + // Evaluate the constructor and its arguments in a regular + // partial-destroy cleanup. + if (getLangOptions().Exceptions && + !ctor->getParent()->hasTrivialDestructor()) { + Destroyer *destroyer = destroyCXXObject; + pushRegularPartialArrayCleanup(arrayBegin, cur, type, *destroyer); + } - EmitBlock(ContinueBlock); + EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/ false, + cur, argBegin, argEnd); + } - // Emit the increment of the loop counter. - llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1); - Counter = Builder.CreateLoad(IndexPtr); - NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); - Builder.CreateStore(NextVal, IndexPtr); + // Go to the next element. + llvm::Value *next = + Builder.CreateInBoundsGEP(cur, llvm::ConstantInt::get(SizeTy, 1), + "arrayctor.next"); + cur->addIncoming(next, Builder.GetInsertBlock()); - // Finally, branch back up to the condition for the next iteration. - EmitBranch(CondBlock); + // Check whether that's the end of the loop. + llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done"); + llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont"); + Builder.CreateCondBr(done, contBB, loopBB); - // Emit the fall-through block. - EmitBlock(AfterFor, true); + EmitBlock(contBB); } void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 07997e4391..49aab66268 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -379,19 +379,11 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, } } - const ConstantArrayType *Array - = getContext().getAsConstantArrayType(E->getType()); - if (Array) { - QualType BaseElementTy = getContext().getBaseElementType(Array); - const llvm::Type *BasePtr = ConvertType(BaseElementTy); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(Dest.getAddr(), BasePtr); - - EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, + if (const ConstantArrayType *arrayType + = getContext().getAsConstantArrayType(E->getType())) { + EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddr(), E->arg_begin(), E->arg_end()); - } - else { + } else { CXXCtorType Type = Ctor_Complete; bool ForVirtualBase = false; @@ -805,11 +797,37 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, RequiresZeroInitialization = true; } + + // It's legal for NumElements to be zero, but + // EmitCXXAggrConstructorCall doesn't handle that, so we need to. + llvm::BranchInst *br = 0; + + // Optimize for a constant count. + llvm::ConstantInt *constantCount + = dyn_cast<llvm::ConstantInt>(NumElements); + if (constantCount) { + // Just skip out if the constant count is zero. + if (constantCount->isZero()) return; + + // Otherwise, emit the check. + } else { + llvm::BasicBlock *loopBB = CGF.createBasicBlock("new.ctorloop"); + llvm::Value *iszero = CGF.Builder.CreateIsNull(NumElements, "isempty"); + br = CGF.Builder.CreateCondBr(iszero, loopBB, loopBB); + CGF.EmitBlock(loopBB); + } CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, E->constructor_arg_begin(), E->constructor_arg_end(), RequiresZeroInitialization); + + // Patch the earlier check to skip over the loop. + if (br) { + assert(CGF.Builder.GetInsertBlock()->empty()); + br->setSuccessor(0, CGF.Builder.GetInsertBlock()); + } + return; } else if (E->getNumConstructorArgs() == 1 && isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) { |