Refactoring. 
Move field layout code in a ASTRecordLayout member fn.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51966 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 2fe1f51..6b5eaa1 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -311,6 +311,81 @@
   return std::make_pair(Width, Align);
 }
 
+/// LayoutField - Field layout.
+void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
+                                  bool IsUnion, bool StructIsPacked,
+                                  ASTContext &Context) {
+  bool FieldIsPacked = StructIsPacked || FD->getAttr<PackedAttr>();
+  uint64_t FieldOffset = IsUnion ? 0 : Size;
+  uint64_t FieldSize;
+  unsigned FieldAlign;
+  
+  if (const Expr *BitWidthExpr = FD->getBitWidth()) {
+    // TODO: Need to check this algorithm on other targets!
+    //       (tested on Linux-X86)
+    llvm::APSInt I(32);
+    bool BitWidthIsICE = 
+      BitWidthExpr->isIntegerConstantExpr(I, Context);
+    assert (BitWidthIsICE  && "Invalid BitField size expression");
+    FieldSize = I.getZExtValue();
+    
+    std::pair<uint64_t, unsigned> FieldInfo = 
+      Context.getTypeInfo(FD->getType());
+    uint64_t TypeSize = FieldInfo.first;
+    
+    FieldAlign = FieldInfo.second;
+    if (FieldIsPacked)
+      FieldAlign = 1;
+    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+      FieldAlign = std::max(FieldAlign, AA->getAlignment());
+    
+    // Check if we need to add padding to give the field the correct
+    // alignment.
+    if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
+      FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
+    
+    // Padding members don't affect overall alignment
+    if (!FD->getIdentifier())
+      FieldAlign = 1;
+  } else {
+    if (FD->getType()->isIncompleteType()) {
+      // This must be a flexible array member; we can't directly
+      // query getTypeInfo about these, so we figure it out here.
+      // Flexible array members don't have any size, but they
+      // have to be aligned appropriately for their element type.
+      FieldSize = 0;
+      const ArrayType* ATy = FD->getType()->getAsArrayType();
+      FieldAlign = Context.getTypeAlign(ATy->getElementType());
+    } else {
+      std::pair<uint64_t, unsigned> FieldInfo = 
+        Context.getTypeInfo(FD->getType());
+      FieldSize = FieldInfo.first;
+      FieldAlign = FieldInfo.second;
+    }
+    
+    if (FieldIsPacked)
+      FieldAlign = 8;
+    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+      FieldAlign = std::max(FieldAlign, AA->getAlignment());
+    
+    // Round up the current record size to the field's alignment boundary.
+    FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
+  }
+  
+  // Place this field at the current location.
+  FieldOffsets[FieldNo] = FieldOffset;
+  
+  // Reserve space for this field.
+  if (IsUnion) {
+    Size = std::max(Size, FieldSize);
+  } else {
+    Size = FieldOffset + FieldSize;
+  }
+  
+  // Remember max struct/class alignment.
+  Alignment = std::max(Alignment, FieldAlign);
+}
+
 /// getASTRecordLayout - Get or compute information about the layout of the
 /// specified record (struct/union/class), which indicates its size and field
 /// position information.
@@ -326,93 +401,24 @@
   ASTRecordLayout *NewEntry = new ASTRecordLayout();
   Entry = NewEntry;
 
-  uint64_t *FieldOffsets = new uint64_t[D->getNumMembers()];
-  uint64_t RecordSize = 0;
-  unsigned RecordAlign = 8;  // Default alignment = 1 byte = 8 bits.
+  NewEntry->InitializeLayout(D->getNumMembers());
   bool StructIsPacked = D->getAttr<PackedAttr>();
   bool IsUnion = (D->getKind() == Decl::Union);
 
   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    RecordAlign = std::max(RecordAlign, AA->getAlignment());
+    NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), 
+                                    AA->getAlignment()));
 
   // Layout each field, for now, just sequentially, respecting alignment.  In
   // the future, this will need to be tweakable by targets.
   for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
     const FieldDecl *FD = D->getMember(i);
-    bool FieldIsPacked = StructIsPacked || FD->getAttr<PackedAttr>();
-    uint64_t FieldOffset = IsUnion ? 0 : RecordSize;
-    uint64_t FieldSize;
-    unsigned FieldAlign;
-
-    if (const Expr *BitWidthExpr = FD->getBitWidth()) {
-      // TODO: Need to check this algorithm on other targets!
-      //       (tested on Linux-X86)
-      llvm::APSInt I(32);
-      bool BitWidthIsICE = 
-        BitWidthExpr->isIntegerConstantExpr(I, *this);
-      assert (BitWidthIsICE  && "Invalid BitField size expression");
-      FieldSize = I.getZExtValue();
-
-      std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType());
-      uint64_t TypeSize = FieldInfo.first;
-
-      FieldAlign = FieldInfo.second;
-      if (FieldIsPacked)
-        FieldAlign = 1;
-      if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
-        FieldAlign = std::max(FieldAlign, AA->getAlignment());
-
-      // Check if we need to add padding to give the field the correct
-      // alignment.
-      if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
-        FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
-
-      // Padding members don't affect overall alignment
-      if (!FD->getIdentifier())
-        FieldAlign = 1;
-    } else {
-      if (FD->getType()->isIncompleteType()) {
-        // This must be a flexible array member; we can't directly
-        // query getTypeInfo about these, so we figure it out here.
-        // Flexible array members don't have any size, but they
-        // have to be aligned appropriately for their element type.
-        FieldSize = 0;
-        const ArrayType* ATy = FD->getType()->getAsArrayType();
-        FieldAlign = getTypeAlign(ATy->getElementType());
-      } else {
-        std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType());
-        FieldSize = FieldInfo.first;
-        FieldAlign = FieldInfo.second;
-      }
-
-      if (FieldIsPacked)
-        FieldAlign = 8;
-      if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
-        FieldAlign = std::max(FieldAlign, AA->getAlignment());
-
-      // Round up the current record size to the field's alignment boundary.
-      FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
-    }
-
-    // Place this field at the current location.
-    FieldOffsets[i] = FieldOffset;
-
-    // Reserve space for this field.
-    if (IsUnion) {
-      RecordSize = std::max(RecordSize, FieldSize);
-    } else {
-      RecordSize = FieldOffset + FieldSize;
-    }
-
-    // Remember max struct/class alignment.
-    RecordAlign = std::max(RecordAlign, FieldAlign);
+    NewEntry->LayoutField(FD, i, IsUnion, StructIsPacked, *this);
   }
 
   // Finally, round the size of the total struct up to the alignment of the
   // struct itself.
-  RecordSize = (RecordSize + (RecordAlign-1)) & ~(RecordAlign-1);
-
-  NewEntry->SetLayout(RecordSize, RecordAlign, FieldOffsets);
+  NewEntry->FinalizeLayout();
   return *NewEntry;
 }