Migrate over to the record layout builder.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76338 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f7b913c..680ec24 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -24,6 +24,8 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "RecordLayoutBuilder.h"
+
 using namespace clang;
 
 enum FloatingRank {
@@ -726,102 +728,6 @@
   return ABIAlign;
 }
 
-
-/// LayoutField - Field layout.
-void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
-                                  bool IsUnion, unsigned StructPacking,
-                                  ASTContext &Context) {
-  unsigned FieldPacking = StructPacking;
-  uint64_t FieldOffset = IsUnion ? 0 : Size;
-  uint64_t FieldSize;
-  unsigned FieldAlign;
-
-  // FIXME: Should this override struct packing? Probably we want to
-  // take the minimum?
-  if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
-    FieldPacking = PA->getAlignment();
-  
-  if (const Expr *BitWidthExpr = FD->getBitWidth()) {
-    // TODO: Need to check this algorithm on other targets!
-    //       (tested on Linux-X86)
-    FieldSize = BitWidthExpr->EvaluateAsInt(Context).getZExtValue();
-    
-    std::pair<uint64_t, unsigned> FieldInfo = 
-      Context.getTypeInfo(FD->getType());
-    uint64_t TypeSize = FieldInfo.first;
-    
-    // Determine the alignment of this bitfield. The packing
-    // attributes define a maximum and the alignment attribute defines
-    // a minimum.
-    // FIXME: What is the right behavior when the specified alignment
-    // is smaller than the specified packing?
-    FieldAlign = FieldInfo.second;
-    if (FieldPacking)
-      FieldAlign = std::min(FieldAlign, FieldPacking);
-    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()->isIncompleteArrayType()) {
-      // This is 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 = Context.getAsArrayType(FD->getType());
-      FieldAlign = Context.getTypeAlign(ATy->getElementType());
-    } else if (const ReferenceType *RT = FD->getType()->getAsReferenceType()) {
-      unsigned AS = RT->getPointeeType().getAddressSpace();
-      FieldSize = Context.Target.getPointerWidth(AS);
-      FieldAlign = Context.Target.getPointerAlign(AS);
-    } else {
-      std::pair<uint64_t, unsigned> FieldInfo = 
-        Context.getTypeInfo(FD->getType());
-      FieldSize = FieldInfo.first;
-      FieldAlign = FieldInfo.second;
-    }
-    
-    // Determine the alignment of this bitfield. The packing
-    // attributes define a maximum and the alignment attribute defines
-    // a minimum. Additionally, the packing alignment must be at least
-    // a byte for non-bitfields.
-    //
-    // FIXME: What is the right behavior when the specified alignment
-    // is smaller than the specified packing?
-    if (FieldPacking)
-      FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
-    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 the next available offset.
-  NextOffset = Size;
-
-  // Remember max struct/class alignment.
-  Alignment = std::max(Alignment, FieldAlign);
-}
-
 static void CollectLocalObjCIvars(ASTContext *Ctx,
                                   const ObjCInterfaceDecl *OI,
                                   llvm::SmallVectorImpl<FieldDecl*> &Fields) {
@@ -934,9 +840,9 @@
   if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
     return *Entry;
 
-  unsigned FieldCount = D->ivar_size();
   // Add in synthesized ivar count if laying out an implementation.
   if (Impl) {
+    unsigned FieldCount = D->ivar_size();
     unsigned SynthCount = CountSynthesizedIvars(D);
     FieldCount += SynthCount;
     // If there aren't any sythesized ivars then reuse the interface
@@ -947,40 +853,10 @@
       return getObjCLayout(D, 0);
   }
 
-  ASTRecordLayout *NewEntry = NULL;
-  if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
-    const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD);
-    unsigned Alignment = SL.getAlignment();
-
-    // We start laying out ivars not at the end of the superclass
-    // structure, but at the next byte following the last field.
-    uint64_t Size = llvm::RoundUpToAlignment(SL.NextOffset, 8);
-
-    ObjCLayouts[Key] = NewEntry = new ASTRecordLayout(Size, Alignment);
-    NewEntry->InitializeLayout(FieldCount);
-  } else {
-    ObjCLayouts[Key] = NewEntry = new ASTRecordLayout();
-    NewEntry->InitializeLayout(FieldCount);
-  }
-
-  unsigned StructPacking = 0;
-  if (const PackedAttr *PA = D->getAttr<PackedAttr>())
-    StructPacking = PA->getAlignment();
-
-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), 
-                                    AA->getAlignment()));
-
-  // Layout each ivar sequentially.
-  unsigned i = 0;
-  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
-  ShallowCollectObjCIvars(D, Ivars, Impl);
-  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
-       NewEntry->LayoutField(Ivars[k], i++, false, StructPacking, *this);
- 
-  // Finally, round the size of the total struct up to the alignment of the
-  // struct itself.
-  NewEntry->FinalizeLayout();
+  const ASTRecordLayout *NewEntry = 
+    ASTRecordLayoutBuilder::ComputeLayout(*this, D, Impl);
+  ObjCLayouts[Key] = NewEntry;
+  
   return *NewEntry;
 }
 
@@ -1005,34 +881,10 @@
   const ASTRecordLayout *&Entry = ASTRecordLayouts[D];
   if (Entry) return *Entry;
 
-  // Allocate and assign into ASTRecordLayouts here.  The "Entry" reference can
-  // be invalidated (dangle) if the ASTRecordLayouts hashtable is inserted into.
-  ASTRecordLayout *NewEntry = new ASTRecordLayout();
+  const ASTRecordLayout *NewEntry = 
+    ASTRecordLayoutBuilder::ComputeLayout(*this, D);
   Entry = NewEntry;
-
-  // FIXME: Avoid linear walk through the fields, if possible.
-  NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));
-  bool IsUnion = D->isUnion();
-
-  unsigned StructPacking = 0;
-  if (const PackedAttr *PA = D->getAttr<PackedAttr>())
-    StructPacking = PA->getAlignment();
-
-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    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.
-  unsigned FieldIdx = 0;
-  for (RecordDecl::field_iterator Field = D->field_begin(),
-                               FieldEnd = D->field_end();
-       Field != FieldEnd; (void)++Field, ++FieldIdx)
-    NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);
-
-  // Finally, round the size of the total struct up to the alignment of the
-  // struct itself.
-  NewEntry->FinalizeLayout(getLangOptions().CPlusPlus);
+  
   return *NewEntry;
 }