diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-14 02:15:49 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-14 02:15:49 +0000 |
commit | 0bdb5aa1a3384d194b0e14a9ecbe3309ff33daa3 (patch) | |
tree | 5be0823f7af4752d0ca364418e4985f0ed7d7d53 /lib/CodeGen/CGClass.cpp | |
parent | b276bd9cc98247331cac8b290ba278b939e53657 (diff) |
Refactor out new function EmitInitializerForField from EmitMemberInitializer. The new function will be used to initialize the fields of lambda expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150451 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 119 |
1 files changed, 69 insertions, 50 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index a5f92d965d..fbbf9a554d 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -412,11 +412,12 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, static void EmitAggMemberInitializer(CodeGenFunction &CGF, LValue LHS, + Expr *Init, llvm::Value *ArrayIndexVar, - CXXCtorInitializer *MemberInit, QualType T, + ArrayRef<VarDecl *> ArrayIndexes, unsigned Index) { - if (Index == MemberInit->getNumArrayIndices()) { + if (Index == ArrayIndexes.size()) { CodeGenFunction::RunCleanupsScope Cleanups(CGF); LValue LV = LHS; @@ -437,9 +438,9 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, } if (!CGF.hasAggregateLLVMType(T)) { - CGF.EmitScalarInit(MemberInit->getInit(), /*decl*/ 0, LV, false); + CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false); } else if (T->isAnyComplexType()) { - CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LV.getAddress(), + CGF.EmitComplexExprIntoAddr(Init, LV.getAddress(), LV.isVolatileQualified()); } else { AggValueSlot Slot = @@ -448,7 +449,7 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased); - CGF.EmitAggExpr(MemberInit->getInit(), Slot); + CGF.EmitAggExpr(Init, Slot); } return; @@ -457,7 +458,7 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T); assert(Array && "Array initialization without the array type?"); llvm::Value *IndexVar - = CGF.GetAddrOfLocalVar(MemberInit->getArrayIndex(Index)); + = CGF.GetAddrOfLocalVar(ArrayIndexes[Index]); assert(IndexVar && "Array index variable not loaded"); // Initialize this index variable to zero. @@ -493,8 +494,8 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, // Inside the loop body recurse to emit the inner loop or, eventually, the // constructor call. - EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, - Array->getElementType(), Index + 1); + EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar, + Array->getElementType(), ArrayIndexes, Index + 1); } CGF.EmitBlock(ContinueBlock); @@ -514,19 +515,15 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, namespace { struct CallMemberDtor : EHScopeStack::Cleanup { - FieldDecl *Field; + llvm::Value *V; CXXDestructorDecl *Dtor; - CallMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor) - : Field(Field), Dtor(Dtor) {} + CallMemberDtor(llvm::Value *V, CXXDestructorDecl *Dtor) + : V(V), Dtor(Dtor) {} void Emit(CodeGenFunction &CGF, Flags flags) { - // FIXME: Is this OK for C++0x delegating constructors? - llvm::Value *ThisPtr = CGF.LoadCXXThis(); - LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0); - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - LHS.getAddress()); + V); } }; } @@ -536,7 +533,11 @@ static bool hasTrivialCopyOrMoveConstructor(const CXXRecordDecl *Record, return Moving ? Record->hasTrivialMoveConstructor() : Record->hasTrivialCopyConstructor(); } - + +static void EmitInitializerForField(CodeGenFunction &CGF, FieldDecl *Field, + LValue LHS, Expr *Init, + ArrayRef<VarDecl *> ArrayIndexes); + static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *MemberInit, @@ -548,7 +549,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, // non-static data member initializers. FieldDecl *Field = MemberInit->getAnyMember(); - QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); + QualType FieldType = Field->getType(); llvm::Value *ThisPtr = CGF.LoadCXXThis(); LValue LHS; @@ -562,28 +563,63 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0); } - if (!CGF.hasAggregateLLVMType(Field->getType())) { + // Special case: if we are in a copy or move constructor, and we are copying + // an array of PODs or classes with trivial copy constructors, ignore the + // AST and perform the copy we know is equivalent. + // FIXME: This is hacky at best... if we had a bit more explicit information + // in the AST, we could generalize it more easily. + const ConstantArrayType *Array + = CGF.getContext().getAsConstantArrayType(FieldType); + if (Array && Constructor->isImplicitlyDefined() && + Constructor->isCopyOrMoveConstructor()) { + QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); + const CXXRecordDecl *Record = BaseElementTy->getAsCXXRecordDecl(); + if (BaseElementTy.isPODType(CGF.getContext()) || + (Record && hasTrivialCopyOrMoveConstructor(Record, + Constructor->isMoveConstructor()))) { + // Find the source pointer. We knows it's the last argument because + // we know we're in a copy constructor. + unsigned SrcArgIndex = Args.size() - 1; + llvm::Value *SrcPtr + = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex])); + LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0); + + // Copy the aggregate. + CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, + LHS.isVolatileQualified()); + return; + } + } + + ArrayRef<VarDecl *> ArrayIndexes; + if (MemberInit->getNumArrayIndices()) + ArrayIndexes = MemberInit->getArrayIndexes(); + EmitInitializerForField(CGF, Field, LHS, MemberInit->getInit(), ArrayIndexes); +} + +static void EmitInitializerForField(CodeGenFunction &CGF, FieldDecl *Field, + LValue LHS, Expr *Init, + ArrayRef<VarDecl *> ArrayIndexes) { + QualType FieldType = Field->getType(); + if (!CGF.hasAggregateLLVMType(FieldType)) { if (LHS.isSimple()) { - CGF.EmitExprAsInit(MemberInit->getInit(), Field, LHS, false); + CGF.EmitExprAsInit(Init, Field, LHS, false); } else { - RValue RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit())); + RValue RHS = RValue::get(CGF.EmitScalarExpr(Init)); CGF.EmitStoreThroughLValue(RHS, LHS); } - } else if (MemberInit->getInit()->getType()->isAnyComplexType()) { - CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(), + } else if (FieldType->isAnyComplexType()) { + CGF.EmitComplexExprIntoAddr(Init, LHS.getAddress(), LHS.isVolatileQualified()); } else { llvm::Value *ArrayIndexVar = 0; - const ConstantArrayType *Array - = CGF.getContext().getAsConstantArrayType(FieldType); - if (Array && Constructor->isImplicitlyDefined() && - Constructor->isCopyOrMoveConstructor()) { + if (ArrayIndexes.size()) { llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); // The LHS is a pointer to the first object we'll be constructing, as // a flat array. - QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); + QualType BaseElementTy = CGF.getContext().getBaseElementType(FieldType); llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy); BasePtr = llvm::PointerType::getUnqual(BasePtr); llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(), @@ -596,31 +632,14 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); CGF.Builder.CreateStore(Zero, ArrayIndexVar); - // If we are copying an array of PODs or classes with trivial copy - // constructors, perform a single aggregate copy. - const CXXRecordDecl *Record = BaseElementTy->getAsCXXRecordDecl(); - if (BaseElementTy.isPODType(CGF.getContext()) || - (Record && hasTrivialCopyOrMoveConstructor(Record, - Constructor->isMoveConstructor()))) { - // Find the source pointer. We knows it's the last argument because - // we know we're in a copy constructor. - unsigned SrcArgIndex = Args.size() - 1; - llvm::Value *SrcPtr - = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex])); - LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0); - - // Copy the aggregate. - CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, - LHS.isVolatileQualified()); - return; - } // Emit the block variables for the array indices, if any. - for (unsigned I = 0, N = MemberInit->getNumArrayIndices(); I != N; ++I) - CGF.EmitAutoVarDecl(*MemberInit->getArrayIndex(I)); + for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I) + CGF.EmitAutoVarDecl(*ArrayIndexes[I]); } - EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0); + EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar, FieldType, + ArrayIndexes, 0); if (!CGF.CGM.getLangOptions().Exceptions) return; @@ -634,7 +653,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (!RD->hasTrivialDestructor()) - CGF.EHStack.pushCleanup<CallMemberDtor>(EHCleanup, Field, + CGF.EHStack.pushCleanup<CallMemberDtor>(EHCleanup, LHS.getAddress(), RD->getDestructor()); } } |