[cfe-commits] r79464 - in /cfe/trunk/lib/CodeGen: CGCXX.cpp CodeGenFunction.h

Fariborz Jahanian fjahanian at apple.com
Wed Aug 19 13:55:17 PDT 2009


Author: fjahanian
Date: Wed Aug 19 15:55:16 2009
New Revision: 79464

URL: http://llvm.org/viewvc/llvm-project?rev=79464&view=rev
Log:
ir-gen for constructing arrays as non-static data members. WIP.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Wed Aug 19 15:55:16 2009
@@ -332,6 +332,83 @@
   return BaseValue;
 }
 
+/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
+/// for-loop to call the default constructor on individual members of the
+/// array. 'Array' is the array type, 'This' is llvm pointer of the start
+/// of the array and 'D' is the default costructor Decl for elements of the
+/// array. It is assumed that all relevant checks have been made by the
+/// caller.
+void
+CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+                                            const ArrayType *Array,
+                                            llvm::Value *This) {
+  const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
+  assert(CA && "Do we support VLA for construction ?");
+  
+  // Create a temporary for the loop index and initialize it with 0.
+  llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt32Ty(VMContext),
+                                           "loop.index");
+  llvm::Value* zeroConstant = 
+    llvm::Constant::getNullValue(llvm::Type::getInt32Ty(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 = CA->getSize().getZExtValue();
+  llvm::Value * NumElementsPtr = 
+  llvm::ConstantInt::get(llvm::Type::getInt32Ty(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");
+  
+  // Store the blocks to use for break and continue.
+  // FIXME. Is this needed?
+  BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock));
+  
+  // Inside the loop body, emit the constructor call on the array element.
+  Counter = Builder.CreateLoad(IndexPtr);
+  llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
+  if (const ConstantArrayType *CAT = 
+      dyn_cast<ConstantArrayType>(Array->getElementType())) {
+    // Need to call this routine again.
+    EmitCXXAggrConstructorCall(D, CAT, Address);
+  } 
+  else
+    EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0);
+  
+  // FIXME. Do we need this?
+  BreakContinueStack.pop_back();
+  
+  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);
+  
+}
+
 void
 CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, 
                                         CXXCtorType Type, 
@@ -1231,6 +1308,14 @@
          FieldEnd = ClassDecl->field_end();
          Field != FieldEnd; ++Field) {
       QualType FieldType = getContext().getCanonicalType((*Field)->getType());
+      const ConstantArrayType *Array = 
+        getContext().getAsConstantArrayType(FieldType);
+      if (Array) {
+        FieldType = Array->getElementType();
+        while (const ConstantArrayType *AT = 
+                getContext().getAsConstantArrayType(FieldType))
+          FieldType = AT->getElementType();
+      }
       if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion())
         continue;
       const RecordType *ClassRec = FieldType->getAs<RecordType>();
@@ -1242,7 +1327,16 @@
             MemberClassDecl->getDefaultConstructor(getContext())) {
         LoadOfThis = LoadCXXThis();
         LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
-        EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 0, 0);
+        if (Array) {
+          const llvm::Type *BasePtr = ConvertType(FieldType);
+          BasePtr = llvm::PointerType::getUnqual(BasePtr);
+          llvm::Value *BaseAddrPtr = 
+            Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+          EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr);
+        }
+        else
+          EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 
+                                 0, 0);
       }
     }
   }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Aug 19 15:55:16 2009
@@ -582,6 +582,10 @@
                               llvm::Value *This,
                               CallExpr::const_arg_iterator ArgBeg,
                               CallExpr::const_arg_iterator ArgEnd);
+  
+  void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+                                  const ArrayType *Array,
+                                  llvm::Value *This);
 
   void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
                              llvm::Value *This);





More information about the cfe-commits mailing list