[cfe-commits] r76338 - in /cfe/trunk: include/clang/AST/RecordLayout.h lib/AST/ASTContext.cpp lib/AST/RecordLayoutBuilder.h

Anders Carlsson andersca at mac.com
Sat Jul 18 14:19:52 PDT 2009


Author: andersca
Date: Sat Jul 18 16:19:52 2009
New Revision: 76338

URL: http://llvm.org/viewvc/llvm-project?rev=76338&view=rev
Log:
Migrate over to the record layout builder.

Modified:
    cfe/trunk/include/clang/AST/RecordLayout.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h

Modified: cfe/trunk/include/clang/AST/RecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=76338&r1=76337&r2=76338&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Sat Jul 18 16:19:52 2009
@@ -37,12 +37,6 @@
   friend class ASTContext;
   friend class ASTRecordLayoutBuilder;
 
-  ASTRecordLayout(uint64_t S = 0, unsigned A = 8) 
-    : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
-  ~ASTRecordLayout() {
-    delete [] FieldOffsets;
-  }
-
   ASTRecordLayout(uint64_t Size, unsigned Alignment,
                   unsigned nextoffset,
                   const uint64_t *fieldoffsets, unsigned fieldcount) 
@@ -54,37 +48,10 @@
         FieldOffsets[i] = fieldoffsets[i];
     }
   }
-
-  /// Initialize record layout. N is the number of fields in this record.
-  void InitializeLayout(unsigned N) {
-    FieldCount = N;
-    FieldOffsets = new uint64_t[N];
-  }
-
-  /// Finalize record layout. Adjust record size based on the alignment.
-  void FinalizeLayout(bool ForceNonEmpty = false) {
-    // In C++, records cannot be of size 0.
-    if (ForceNonEmpty && Size == 0)
-      Size = 8;
-    // Finally, round the size of the record up to the alignment of the
-    // record itself.
-    Size = (Size + (Alignment-1)) & ~(Alignment-1);
-  }
-
-  void SetFieldOffset(unsigned FieldNo, uint64_t Offset) {
-    assert (FieldNo < FieldCount && "Invalid Field No");
-    FieldOffsets[FieldNo] = Offset;
+  ~ASTRecordLayout() {
+    delete [] FieldOffsets;
   }
 
-  void SetAlignment(unsigned A) {  Alignment = A; }
-
-  /// LayoutField - Field layout. StructPacking is the specified
-  /// packing alignment (maximum alignment) in bits to use for the
-  /// structure, or 0 if no packing alignment is specified.
-  void LayoutField(const FieldDecl *FD, unsigned FieldNo,
-                   bool IsUnion, unsigned StructPacking,
-                   ASTContext &Context);
-  
   ASTRecordLayout(const ASTRecordLayout&);   // DO NOT IMPLEMENT
   void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
 public:

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=76338&r1=76337&r2=76338&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Jul 18 16:19:52 2009
@@ -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;
 }
 

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=76338&r1=76337&r2=76338&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Sat Jul 18 16:19:52 2009
@@ -38,6 +38,9 @@
               const ObjCImplementationDecl *Impl);
 
   void LayoutField(const FieldDecl *D);
+
+  /// FinishLayout - Finalize record layout. Adjust record size based on the
+  /// alignment.
   void FinishLayout();
   
   void UpdateAlignment(unsigned NewAlignment);





More information about the cfe-commits mailing list