[cfe-commits] r46736 - in /cfe/trunk: CodeGen/CGExprConstant.cpp CodeGen/CodeGenTypes.cpp CodeGen/CodeGenTypes.h test/CodeGen/struct.c

Devang Patel dpatel at apple.com
Mon Feb 4 18:39:51 PST 2008


Author: dpatel
Date: Mon Feb  4 20:39:50 2008
New Revision: 46736

URL: http://llvm.org/viewvc/llvm-project?rev=46736&view=rev
Log:
Cleanup InitListExpr code generation code.
Handle padding fields while initializing struct (fix PR 1962)


Modified:
    cfe/trunk/CodeGen/CGExprConstant.cpp
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/CodeGen/CodeGenTypes.h
    cfe/trunk/test/CodeGen/struct.c

Modified: cfe/trunk/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExprConstant.cpp?rev=46736&r1=46735&r2=46736&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/CodeGen/CGExprConstant.cpp Mon Feb  4 20:39:50 2008
@@ -66,75 +66,136 @@
     
     return EmitConversion(C, E->getSubExpr()->getType(), E->getType());    
   }
-  
-  llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
-    const llvm::CompositeType *CType = 
-      dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType()));
 
-    if (!CType) {
-        // We have a scalar in braces. Just use the first element.
-        return Visit(ILE->getInit(0));
-    }
-      
-    unsigned NumInitElements = ILE->getNumInits();
-    unsigned NumInitableElts = NumInitElements;
+  llvm::Constant *EmitArrayInitialization(InitListExpr *ILE,
+                                          const llvm::ArrayType *AType) {
+    
     std::vector<llvm::Constant*> Elts;    
-      
-    // Initialising an array or structure requires us to automatically 
+    unsigned NumInitElements = ILE->getNumInits();      
+    const llvm::Type *ElemTy = AType->getElementType();
+    unsigned NumElements = AType->getNumElements();
+
+    // Initialising an array requires us to automatically 
     // initialise any elements that have not been initialised explicitly
-    const llvm::ArrayType *AType = 0; 
-    const llvm::StructType *SType = 0; 
-    const llvm::Type *ElemTy = 0;
-    unsigned NumElements = 0;
-    
-    // If this is an array, we may have to truncate the initializer
-    if ((AType = dyn_cast<llvm::ArrayType>(CType))) {
-      NumElements = AType->getNumElements();
-      ElemTy = AType->getElementType();
-      NumInitableElts = std::min(NumInitableElts, NumElements);
-    }
-
-    // If this is a structure, we may have to truncate the initializer
-    if ((SType = dyn_cast<llvm::StructType>(CType))) {
-      NumElements = SType->getNumElements();
-      NumInitableElts = std::min(NumInitableElts, NumElements);
-    }
+    unsigned NumInitableElts = std::min(NumInitElements, NumElements);
 
     // Copy initializer elements.
     unsigned i = 0;
-    for (i = 0; i < NumInitableElts; ++i) {
+    for (; i < NumInitableElts; ++i) {
+        
       llvm::Constant *C = Visit(ILE->getInit(i));
       // FIXME: Remove this when sema of initializers is finished (and the code
       // above).
       if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) {
         if (ILE->getType()->isVoidType()) return 0;
-        return llvm::UndefValue::get(CType);
+        return llvm::UndefValue::get(AType);
       }
       assert (C && "Failed to create initializer expression");
       Elts.push_back(C);
     }
     
-    if (SType) {
-      // Initialize remaining structure elements.
-      for (; i < NumElements; ++i) {
-        ElemTy = SType->getElementType(i);
-        Elts.push_back(llvm::Constant::getNullValue(ElemTy));
-      }
-      return llvm::ConstantStruct::get(SType, Elts);
-    }
-    
-    if (ILE->getType()->isVectorType())
-      return llvm::ConstantVector::get(cast<llvm::VectorType>(CType), Elts);
-    
-    // Make sure we have an array at this point
-    assert(AType);
-
     // Initialize remaining array elements.
     for (; i < NumElements; ++i)
       Elts.push_back(llvm::Constant::getNullValue(ElemTy));
 
     return llvm::ConstantArray::get(AType, Elts);    
   }
+
+  llvm::Constant *EmitStructInitialization(InitListExpr *ILE,
+                                           const llvm::StructType *SType) {
+
+    std::vector<llvm::Constant*> Elts;
+    const CGRecordLayout *CGR = CGM.getTypes().getCGRecordLayout(SType);
+    unsigned NumInitElements = ILE->getNumInits();
+    unsigned NumElements = SType->getNumElements();
+      
+    // Initialising an structure requires us to automatically 
+    // initialise any elements that have not been initialised explicitly
+    unsigned NumInitableElts = std::min(NumInitElements, NumElements);
+
+    // Copy initializer elements. Skip padding fields.
+    unsigned EltNo = 0;  // Element no in ILE
+    unsigned FieldNo = 0; // Field no in  SType
+    while (EltNo < NumInitableElts) {
+      
+      // Zero initialize padding field.
+      if (CGR->isPaddingField(FieldNo)) {
+        const llvm::Type *FieldTy = SType->getElementType(FieldNo);
+        Elts.push_back(llvm::Constant::getNullValue(FieldTy));
+        FieldNo++;
+        continue;
+      }
+        
+      llvm::Constant *C = Visit(ILE->getInit(EltNo));
+      // FIXME: Remove this when sema of initializers is finished (and the code
+      // above).
+      if (C == 0 && ILE->getInit(EltNo)->getType()->isVoidType()) {
+        if (ILE->getType()->isVoidType()) return 0;
+        return llvm::UndefValue::get(SType);
+      }
+      assert (C && "Failed to create initializer expression");
+      Elts.push_back(C);
+      EltNo++;
+      FieldNo++;
+    }
+    
+    // Initialize remaining structure elements.
+    for (unsigned i = Elts.size(); i < NumElements; ++i) {
+      const llvm::Type *FieldTy = SType->getElementType(i);
+      Elts.push_back(llvm::Constant::getNullValue(FieldTy));
+    }
+     
+    return llvm::ConstantStruct::get(SType, Elts);
+  }
+
+  llvm::Constant *EmitVectorInitialization(InitListExpr *ILE,
+                                           const llvm::VectorType *VType) {
+
+    std::vector<llvm::Constant*> Elts;    
+    unsigned NumInitElements = ILE->getNumInits();      
+    unsigned NumElements = VType->getNumElements();
+
+    assert (NumInitElements == NumElements 
+            && "Unsufficient vector init elelments");
+    // Copy initializer elements.
+    unsigned i = 0;
+    for (; i < NumElements; ++i) {
+        
+      llvm::Constant *C = Visit(ILE->getInit(i));
+      // FIXME: Remove this when sema of initializers is finished (and the code
+      // above).
+      if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) {
+        if (ILE->getType()->isVoidType()) return 0;
+        return llvm::UndefValue::get(VType);
+      }
+      assert (C && "Failed to create initializer expression");
+      Elts.push_back(C);
+    }
+
+    return llvm::ConstantVector::get(VType, Elts);    
+  }
+                                          
+  llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
+    const llvm::CompositeType *CType = 
+      dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType()));
+
+    if (!CType) {
+        // We have a scalar in braces. Just use the first element.
+        return Visit(ILE->getInit(0));
+    }
+      
+    if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(CType))
+      return EmitArrayInitialization(ILE, AType);
+
+    if (const llvm::StructType *SType = dyn_cast<llvm::StructType>(CType))
+      return EmitStructInitialization(ILE, SType);
+
+    if (const llvm::VectorType *VType = dyn_cast<llvm::VectorType>(CType))
+      return EmitVectorInitialization(ILE, VType);
+    
+    // Make sure we have an array at this point
+    assert(0 && "Unable to handle InitListExpr");
+  }
   
   llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) {
     // If this is due to array->pointer conversion, emit the array expression as

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=46736&r1=46735&r2=46736&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Mon Feb  4 20:39:50 2008
@@ -66,7 +66,7 @@
     /// placeBitField - Find a place for FD, which is a bit-field. 
     void placeBitField(const FieldDecl *FD);
 
-    llvm::SmallVector<unsigned, 8> &getPaddingFields() {
+    llvm::SmallSet<unsigned, 8> &getPaddingFields() {
       return PaddingFields;
     }
 
@@ -79,7 +79,7 @@
     llvm::SmallVector<const FieldDecl *, 8> FieldDecls;
     std::vector<const llvm::Type*> LLVMFields;
     llvm::SmallVector<uint64_t, 8> Offsets;
-    llvm::SmallVector<unsigned, 8> PaddingFields;
+    llvm::SmallSet<unsigned, 8> PaddingFields;
   };
 }
 
@@ -334,7 +334,8 @@
       RO.layoutStructFields(RL);
 
       // Get llvm::StructType.
-      CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType());
+      CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(), 
+                                               RO.getPaddingFields());
       ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
       CGRecordLayouts[ResultType] = RLI;
 
@@ -357,7 +358,8 @@
         RO.layoutUnionFields();
 
         // Get llvm::StructType.
-        CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType());
+        CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
+                                                 RO.getPaddingFields());
         ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
         CGRecordLayouts[ResultType] = RLI;
       } else {       
@@ -520,7 +522,7 @@
   Offsets.push_back(llvmSize);
   llvmSize += TySize;
   if (isPaddingField)
-    PaddingFields.push_back(llvmFieldNo);
+    PaddingFields.insert(llvmFieldNo);
   LLVMFields.push_back(Ty);
   ++llvmFieldNo;
 }

Modified: cfe/trunk/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.h?rev=46736&r1=46735&r2=46736&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.h Mon Feb  4 20:39:50 2008
@@ -15,6 +15,7 @@
 #define CODEGEN_CODEGENTYPES_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
 #include <vector>
 
 namespace llvm {
@@ -42,7 +43,8 @@
   class CGRecordLayout {
     CGRecordLayout(); // DO NOT IMPLEMENT
   public:
-    CGRecordLayout(llvm::Type *T) : STy(T) {
+    CGRecordLayout(llvm::Type *T, llvm::SmallSet<unsigned, 8> &PF) 
+      : STy(T), PaddingFields(PF) {
       // FIXME : Collect info about fields that requires adjustments 
       // (i.e. fields that do not directly map to llvm struct fields.)
     }
@@ -52,8 +54,17 @@
       return STy;
     }
 
+    bool isPaddingField(unsigned No) const {
+      return PaddingFields.count(No) != 0;
+    }
+
+    unsigned getNumPaddingFields() {
+      return PaddingFields.size();
+    }
+
   private:
     llvm::Type *STy;
+    llvm::SmallSet<unsigned, 8> PaddingFields;
   };
   
 /// CodeGenTypes - This class organizes the cross-module state that is used

Modified: cfe/trunk/test/CodeGen/struct.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/struct.c?rev=46736&r1=46735&r2=46736&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/struct.c (original)
+++ cfe/trunk/test/CodeGen/struct.c Mon Feb  4 20:39:50 2008
@@ -140,3 +140,4 @@
 /* struct initialization */
 struct a13 {int b; int c};
 struct a13 c13 = {5};
+struct a14 { short a; int b; } x = {1, 1};





More information about the cfe-commits mailing list