[cfe-commits] r101155 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp test/CodeGen/decl.c

Chris Lattner sabre at nondot.org
Tue Apr 13 11:16:19 PDT 2010


Author: lattner
Date: Tue Apr 13 13:16:19 2010
New Revision: 101155

URL: http://llvm.org/viewvc/llvm-project?rev=101155&view=rev
Log:
Rework the ConstStructBuilder code to emit missing initializer
elements with explicit zero values instead of with tail padding.
On an example like this:

struct foo { int a; int b; };

struct foo fooarray[] = {
    {1, 2},
    {4},
};

We now lay this out as:

@fooarray = global [2 x %struct.foo] [%struct.foo { i32 1, i32 2 }, %struct.foo { i32 4, i32 0 }]

instead of as:

@fooarray = global %0 <{ %struct.foo { i32 1, i32 2 }, %1 { i32 4, [4 x i8] zeroinitializer } }>

Preserving both the struct type of the second element, but also the array type of the entire thing.


Modified:
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/test/CodeGen/decl.c

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=101155&r1=101154&r2=101155&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Tue Apr 13 13:16:19 2010
@@ -50,10 +50,10 @@
     LLVMStructAlignment(1) { }
 
   bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
-                   const Expr *InitExpr);
+                   llvm::Constant *InitExpr);
 
   bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
-                      const Expr *InitExpr);
+                      llvm::Constant *InitExpr);
 
   void AppendPadding(uint64_t NumBytes);
 
@@ -74,18 +74,18 @@
 };
 
 bool ConstStructBuilder::
-AppendField(const FieldDecl *Field, uint64_t FieldOffset, const Expr *InitExpr){
+AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+            llvm::Constant *InitCst) {
   uint64_t FieldOffsetInBytes = FieldOffset / 8;
 
   assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
          && "Field offset mismatch!");
 
   // Emit the field.
-  llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
-  if (!C)
+  if (!InitCst)
     return false;
 
-  unsigned FieldAlignment = getAlignment(C);
+  unsigned FieldAlignment = getAlignment(InitCst);
 
   // Round up the field offset to the alignment of the field type.
   uint64_t AlignedNextFieldOffsetInBytes =
@@ -111,8 +111,9 @@
   }
 
   // Add the field.
-  Elements.push_back(C);
-  NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
+  Elements.push_back(InitCst);
+  NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes +
+                             getSizeInBytes(InitCst);
   
   if (Packed)
     assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
@@ -124,11 +125,8 @@
 
 bool ConstStructBuilder::
   AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
-                 const Expr *InitExpr) {
-  llvm::ConstantInt *CI =
-    cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr,
-                                                         Field->getType(),
-                                                         CGF));
+                 llvm::Constant *InitCst) {
+  llvm::ConstantInt *CI = cast_or_null<llvm::ConstantInt>(InitCst);
   // FIXME: Can this ever happen?
   if (!CI)
     return false;
@@ -323,26 +321,34 @@
   unsigned FieldNo = 0;
   unsigned ElementNo = 0;
   for (RecordDecl::field_iterator Field = RD->field_begin(),
-       FieldEnd = RD->field_end();
-       ElementNo < ILE->getNumInits() && Field != FieldEnd;
-       ++Field, ++FieldNo) {
+       FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+    
+    // If this is a union, skip all the fields that aren't being initialized.
     if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
       continue;
 
-    if (Field->isBitField()) {
-      if (!Field->getIdentifier())
-        continue;
+    // Don't emit anonymous bitfields, they just affect layout.
+    if (Field->isBitField() && !Field->getIdentifier())
+      continue;
 
-      if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
-                          ILE->getInit(ElementNo)))
+    // Get the initializer.  A struct can include fields without initializers,
+    // we just use explicit null values for them.
+    llvm::Constant *EltInit;
+    if (ElementNo < ILE->getNumInits())
+      EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++),
+                                     Field->getType(), CGF);
+    else
+      EltInit = CGM.EmitNullConstant(Field->getType());
+    
+    if (!Field->isBitField()) {
+      // Handle non-bitfield members.
+      if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
         return false;
     } else {
-      if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
-                       ILE->getInit(ElementNo)))
+      // Otherwise we have a bitfield.
+      if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
         return false;
     }
-
-    ElementNo++;
   }
 
   uint64_t LayoutSizeInBytes = Layout.getSize() / 8;

Modified: cfe/trunk/test/CodeGen/decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/decl.c?rev=101155&r1=101154&r2=101155&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/decl.c (original)
+++ cfe/trunk/test/CodeGen/decl.c Tue Apr 13 13:16:19 2010
@@ -5,7 +5,10 @@
 // CHECK: @test5w = global %0 { i32 2, [4 x i8] zeroinitializer }
 // CHECK: @test5y = global %union.test5u { double 7.300000e+0{{[0]*}}1 }
 
-// CHECK: @test6.x = internal constant %1 { i8 1, i8 2, i32 3, [4 x i8] zeroinitializer }
+// CHECK: @test6.x = internal constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
+
+// CHECK: @test7 = global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]
+
 void test1() {
   // This should codegen as a "@test1.x" global.
   const int x[] = { 1, 2, 3, 4, 6, 8, 9, 10, 123, 231, 123,23 };
@@ -74,3 +77,10 @@
   struct SelectDest x = {1, 2, 3};
   test6f(&x);
 }
+
+// rdar://7657600
+struct test7s { int a; int b; } test7[] = {
+  {1, 2},
+  {4},
+};
+





More information about the cfe-commits mailing list