[cfe-commits] r79681 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/copy-assign-synthesis-1.cpp

Fariborz Jahanian fjahanian at apple.com
Fri Aug 21 15:34:56 PDT 2009


Author: fjahanian
Date: Fri Aug 21 17:34:55 2009
New Revision: 79681

URL: http://llvm.org/viewvc/llvm-project?rev=79681&view=rev
Log:
Patch to ir-gen copy assigning array members when synthesizing 
a copy assignment operator function.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/copy-assign-synthesis-1.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=79681&r1=79680&r2=79681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Aug 21 17:34:55 2009
@@ -1169,6 +1169,91 @@
   EmitBlock(AfterFor, true);
 }
 
+/// EmitClassAggrCopyAssignment - This routine generates code to assign a class
+/// array of objects from SrcValue to DestValue. Assignment can be either a 
+/// bitwise assignment or via a copy assignment operator function call.
+/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy
+void CodeGenFunction::EmitClassAggrCopyAssignment(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 asssigned");
+  bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment();
+  
+  // 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 assignment operator call on array element.
+  Counter = Builder.CreateLoad(IndexPtr);
+  Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
+  Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
+  const CXXMethodDecl *MD = 0;
+  if (BitwiseAssign)
+    EmitAggregateCopy(Dest, Src, Ty);
+  else {
+    bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(),
+                                                               MD);
+    assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign");
+    (void)hasCopyAssign;
+    const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
+    const llvm::Type *LTy =
+    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+                                   FPT->isVariadic());
+    llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), LTy);
+    
+    CallArgList CallArgs;
+    // Push the this (Dest) ptr.
+    CallArgs.push_back(std::make_pair(RValue::get(Dest),
+                                      MD->getThisType(getContext())));
+    
+    // Push the Src ptr.
+    CallArgs.push_back(std::make_pair(RValue::get(Src),
+                                      MD->getParamDecl(0)->getType()));
+    QualType ResultType =
+    MD->getType()->getAsFunctionType()->getResultType();
+    EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+             Callee, CallArgs, MD);
+  }
+  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
 /// or via a copy constructor call.
@@ -1207,6 +1292,7 @@
 /// EmitClassCopyAssignment - This routine generates code to copy assign a class
 /// object from SrcValue to DestValue. Assignment can be either a bitwise 
 /// assignment of via an assignment operator call.
+// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot.
 void CodeGenFunction::EmitClassCopyAssignment(
                                         llvm::Value *Dest, llvm::Value *Src,
                                         const CXXRecordDecl *ClassDecl, 
@@ -1394,19 +1480,29 @@
        FieldEnd = ClassDecl->field_end();
        Field != FieldEnd; ++Field) {
     QualType FieldType = getContext().getCanonicalType((*Field)->getType());
-    
-    // FIXME. How about copy assignment of  arrays!
-    assert(!getContext().getAsArrayType(FieldType) &&
-           "FIXME. Copy assignment of 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);
-      
-      EmitClassCopyAssignment(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);
+        EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
+                                    FieldClassDecl, FieldType);
+      }
+      else
+        EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), 
+                               0 /*ClassDecl*/, FieldClassDecl, FieldType);
       continue;
     }
     // Do a built-in assignment of scalar data members.

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=79681&r1=79680&r2=79681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Aug 21 17:34:55 2009
@@ -574,6 +574,12 @@
                                    const CXXRecordDecl *BaseClassDecl,
                                    QualType Ty);
 
+  void EmitClassAggrCopyAssignment(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-assign-synthesis-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-assign-synthesis-1.cpp?rev=79681&r1=79680&r2=79681&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/copy-assign-synthesis-1.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/copy-assign-synthesis-1.cpp Fri Aug 21 17:34:55 2009
@@ -41,10 +41,17 @@
   int N2;
   void pr() {
     printf("N1 = %d N2 = %d\n", N1, N2);
+    for (unsigned i = 0; i < 3; i++)
+      for (unsigned j = 0; j < 2; j++)
+	printf("arr_b[%d][%d] = %f\n", i,j,arr_b[i][j].B1);
     B::pr();
   }
   N& operator=(const N& arg) { N1 = arg.N1; N2 = arg.N2; 
+    			       for (unsigned i = 0; i < 3; i++)
+      			         for (unsigned j = 0; j < 2; j++)
+				   arr_b[i][j] = arg.arr_b[i][j];
                                return *this; }
+  B arr_b[3][2];
 };
 
 struct Q  : B {





More information about the cfe-commits mailing list