[cfe-commits] r79653 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/copy-constructor-synthesis.cpp
Fariborz Jahanian
fjahanian at apple.com
Fri Aug 21 11:30:26 PDT 2009
Author: fjahanian
Date: Fri Aug 21 13:30:26 2009
New Revision: 79653
URL: http://llvm.org/viewvc/llvm-project?rev=79653&view=rev
Log:
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.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=79653&r1=79652&r2=79653&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Aug 21 13:30:26 2009
@@ -1093,9 +1093,85 @@
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 @@
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 @@
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);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=79653&r1=79652&r2=79653&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Aug 21 13:30:26 2009
@@ -568,6 +568,12 @@
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,
Modified: cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp?rev=79653&r1=79652&r2=79653&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp Fri Aug 21 13:30:26 2009
@@ -57,6 +57,36 @@
};
};
+static int ix = 1;
+// class with user-defined copy constructor.
+struct S {
+ S() : iS(ix++) { }
+ S(const S& arg) { *this = arg; }
+ int iS;
+};
+
+// class with trivial copy constructor.
+struct I {
+ I() : iI(ix++) { }
+ int iI;
+};
+
+struct XM {
+ XM() { }
+ double dXM;
+ S ARR_S[3][4][2];
+ void pr() {
+ for (unsigned i = 0; i < 3; i++)
+ for (unsigned j = 0; j < 4; j++)
+ for (unsigned k = 0; k < 2; k++)
+ printf("ARR_S[%d][%d][%d] = %d\n", i,j,k, ARR_S[i][j][k].iS);
+ for (unsigned i = 0; i < 3; i++)
+ for (unsigned k = 0; k < 2; k++)
+ printf("ARR_I[%d][%d] = %d\n", i,k, ARR_I[i][k].iI);
+ }
+ I ARR_I[3][2];
+};
+
int main()
{
X a;
@@ -65,6 +95,10 @@
X x;
X c(x);
c.pr();
+
+ XM m0;
+ XM m1 = m0;
+ m1.pr();
}
// CHECK-LP64: .globl __ZN1XC1ERK1X
// CHECK-LP64: .weak_definition __ZN1XC1ERK1X
More information about the cfe-commits
mailing list