diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-21 18:30:26 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-21 18:30:26 +0000 |
commit | eb0b6d556ff2b4a5053e89fd084eb34e44cea14c (patch) | |
tree | dd7c01ab6cd422153f3b5ee274b534e4f9fd155a /lib/CodeGen | |
parent | 666a91edc949f5b52eeef481601e2a60de4fdebe (diff) |
Patch to provide ir-gen support in copying array members
when synthesizing a copy constructor. Arrays's base element
may have a trivial or non-trivial copy constructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79653 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 106 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 6 |
2 files changed, 102 insertions, 10 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 5bc8b40c63..9389af62d6 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -1093,9 +1093,85 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { return vtable; } +/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class +/// array of objects from SrcValue to DestValue. Copying can be either a bitwise +/// copy or via a copy constructor call. +void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, + llvm::Value *Src, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "VLA cannot be copied over"); + bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + Builder.CreateStore(zeroConstant, IndexPtr, false); + // 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. + uint64_t NumElements = getContext().getConstantArrayElementCount(CA); + llvm::Value * NumElementsPtr = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); + Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); + if (BitwiseCopy) + EmitAggregateCopy(Dest, Src, Ty); + else if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(getContext(), 0)) { + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, + Ctor_Complete); + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + BaseCopyCtor->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + BaseCopyCtor->getParamDecl(0)->getType())); + QualType ResultType = + BaseCopyCtor->getType()->getAsFunctionType()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, CallArgs, BaseCopyCtor); + } + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + /// EmitClassMemberwiseCopy - This routine generates code to copy a class /// object from SrcValue to DestValue. Copying can be either a bitwise copy -/// of via a copy constructor call. +/// or via a copy constructor call. void CodeGenFunction::EmitClassMemberwiseCopy( llvm::Value *Dest, llvm::Value *Src, const CXXRecordDecl *ClassDecl, @@ -1230,19 +1306,29 @@ void CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *CD, FieldEnd = ClassDecl->field_end(); Field != FieldEnd; ++Field) { QualType FieldType = getContext().getCanonicalType((*Field)->getType()); - - // FIXME. How about copying arrays! - assert(!getContext().getAsArrayType(FieldType) && - "FIXME. Copying arrays NYI"); - + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); - - EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), - 0 /*ClassDecl*/, FieldClassDecl, FieldType); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *DestBaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + llvm::Value *SrcBaseAddrPtr = + Builder.CreateBitCast(RHS.getAddress(), BasePtr); + EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, + FieldClassDecl, FieldType); + } + else + EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), + 0 /*ClassDecl*/, FieldClassDecl, FieldType); continue; } // Do a built-in assignment of scalar data members. @@ -1363,7 +1449,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { FieldDecl *Field = Member->getMember(); QualType FieldType = getContext().getCanonicalType((Field)->getType()); const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); + getContext().getAsConstantArrayType(FieldType); if (Array) FieldType = getContext().getBaseElementType(FieldType); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 71614c451c..583bfe3bfd 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -568,6 +568,12 @@ public: const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl); + void EmitClassAggrMemberwiseCopy(llvm::Value *DestValue, + llvm::Value *SrcValue, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty); + void EmitClassMemberwiseCopy(llvm::Value *DestValue, llvm::Value *SrcValue, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl, |