[cfe-commits] r76330 - in /cfe/trunk: clang.xcodeproj/project.pbxproj include/clang/AST/RecordLayout.h lib/AST/RecordLayoutBuilder.cpp lib/AST/RecordLayoutBuilder.h

Anders Carlsson andersca at mac.com
Sat Jul 18 13:20:49 PDT 2009


Author: andersca
Date: Sat Jul 18 15:20:21 2009
New Revision: 76330

URL: http://llvm.org/viewvc/llvm-project?rev=76330&view=rev
Log:
Add a new ASTRecordLayoutBuilder class. Not used yet.

Added:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h
Modified:
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/AST/RecordLayout.h

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=76330&r1=76329&r2=76330&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Sat Jul 18 15:20:21 2009
@@ -39,6 +39,7 @@
 		1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; };
 		1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
 		1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
+		1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
 		1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
 		1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
 		1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
@@ -188,7 +189,6 @@
 		DEB076CF0F3A222200F5A2BE /* DeclTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB076CE0F3A222200F5A2BE /* DeclTemplate.cpp */; };
 		DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */; };
 		DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */; };
-		DEC63B1A0C7B940200DBF169 /* CFG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEC63B190C7B940200DBF169 /* CFG.cpp */; };
 		DEC63B1C0C7B940600DBF169 /* CFG.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC63B1B0C7B940600DBF169 /* CFG.h */; };
 		DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9900A9433CD00353FCA /* Decl.h */; };
 		DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9A30A94346E00353FCA /* AST.h */; };
@@ -363,6 +363,8 @@
 		1A7342470C7B57D500122F56 /* CGObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjC.cpp; path = lib/CodeGen/CGObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
 		1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
+		1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
+		1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
 		1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
@@ -603,7 +605,6 @@
 		DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TokenConcatenation.cpp; sourceTree = "<group>"; };
 		DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaAttr.cpp; path = lib/Sema/SemaAttr.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		DEB089EE0F12F1D900522C07 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; };
-		DEC63B190C7B940200DBF169 /* CFG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CFG.cpp; path = lib/AST/CFG.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		DEC63B1B0C7B940600DBF169 /* CFG.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CFG.h; path = clang/AST/CFG.h; sourceTree = "<group>"; tabWidth = 2; };
 		DEC8D9900A9433CD00353FCA /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/AST/Decl.h; sourceTree = "<group>"; tabWidth = 2; };
 		DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = "<group>"; tabWidth = 2; };
@@ -1182,7 +1183,6 @@
 				DE8823CA0ED0046600CBC30A /* APValue.cpp */,
 				35BB2D7E0D19954000944DB5 /* ASTConsumer.cpp */,
 				DE1732FF0B068B700080B521 /* ASTContext.cpp */,
-				DEC63B190C7B940200DBF169 /* CFG.cpp */,
 				35FE6BCE0DF6EE1F00739712 /* DeclBase.cpp */,
 				DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */,
 				3538FDB70ED24A4E005EC283 /* DeclarationName.cpp */,
@@ -1197,6 +1197,8 @@
 				3557D1A80EB136B100C59739 /* InheritViz.cpp */,
 				DEDFE5CE0F7206E40035BD10 /* NestedNameSpecifier.cpp */,
 				35EE48B00E0C4CCA00715C54 /* ParentMap.cpp */,
+				1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */,
+				1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */,
 				DE3452400AEF1A2D00DBC861 /* Stmt.cpp */,
 				DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */,
 				DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */,
@@ -1545,7 +1547,6 @@
 				1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */,
 				DE224FF80C7AA98800D370A5 /* CGExprComplex.cpp in Sources */,
 				1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */,
-				DEC63B1A0C7B940200DBF169 /* CFG.cpp in Sources */,
 				DE2252700C7E82D000D370A5 /* CGExprScalar.cpp in Sources */,
 				35260CA50C7F75C000D66CE9 /* ExprCXX.cpp in Sources */,
 				DE2255FC0C8004E600D370A5 /* ParseDeclCXX.cpp in Sources */,
@@ -1695,6 +1696,7 @@
 				BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */,
 				1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
 				DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
+				1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

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

==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Sat Jul 18 15:20:21 2009
@@ -18,6 +18,7 @@
 
 namespace clang {
   class ASTContext;
+  class FieldDecl;
   class RecordDecl;
 
 /// ASTRecordLayout - 
@@ -34,6 +35,7 @@
   unsigned Alignment;   // Alignment of record in bits.
   unsigned FieldCount;  // Number of fields
   friend class ASTContext;
+  friend class ASTRecordLayoutBuilder;
 
   ASTRecordLayout(uint64_t S = 0, unsigned A = 8) 
     : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
@@ -41,6 +43,16 @@
     delete [] FieldOffsets;
   }
 
+  ASTRecordLayout(uint64_t Size, unsigned Alignment,
+                  const uint64_t *fieldoffsets, unsigned fieldcount) 
+  : Size(Size), FieldOffsets(0), Alignment(Alignment), FieldCount(fieldcount) {
+    if (FieldCount > 0)  {
+      FieldOffsets = new uint64_t[FieldCount];
+      for (unsigned i = 0; i < FieldCount; ++i)
+        FieldOffsets[i] = fieldoffsets[i];
+    }
+  }
+
   /// Initialize record layout. N is the number of fields in this record.
   void InitializeLayout(unsigned N) {
     FieldCount = N;

Added: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=76330&view=auto

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (added)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Jul 18 15:20:21 2009
@@ -0,0 +1,162 @@
+//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RecordLayoutBuilder.h"
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/TargetInfo.h"
+#include <llvm/Support/MathExtras.h>
+
+using namespace clang;
+
+ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) 
+  : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0), 
+  IsUnion(false) {}
+
+void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
+  IsUnion = D->isUnion();
+  
+  if (const PackedAttr* PA = D->getAttr<PackedAttr>())
+    StructPacking = PA->getAlignment();
+  
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+    UpdateAlignment(AA->getAlignment());
+  
+  // Layout each field, for now, just sequentially, respecting alignment.  In
+  // the future, this will need to be tweakable by targets.
+  for (RecordDecl::field_iterator Field = D->field_begin(), 
+       FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
+    LayoutField(*Field);
+  
+  // Finally, round the size of the total struct up to the alignment of the
+  // struct itself.
+  FinishLayout();
+}
+
+void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
+  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 = D->getAttr<PackedAttr>())
+    FieldPacking = PA->getAlignment();
+  
+  if (const Expr *BitWidthExpr = D->getBitWidth()) {
+    // TODO: Need to check this algorithm on other targets!
+    //       (tested on Linux-X86)
+    FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue();
+    
+    std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->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 = D->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 (!D->getIdentifier())
+      FieldAlign = 1;
+  } else {
+    if (D->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 = Ctx.getAsArrayType(D->getType());
+      FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
+    } else if (const ReferenceType *RT = D->getType()->getAsReferenceType()) {
+      unsigned AS = RT->getPointeeType().getAddressSpace();
+      FieldSize = Ctx.Target.getPointerWidth(AS);
+      FieldAlign = Ctx.Target.getPointerAlign(AS);
+    } else {
+      std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->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 = D->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.push_back(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.
+  UpdateAlignment(FieldAlign);
+}
+
+void ASTRecordLayoutBuilder::FinishLayout() {
+  // In C++, records cannot be of size 0.
+  if (Ctx.getLangOptions().CPlusPlus && 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 ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
+  if (NewAlignment <= Alignment)
+    return;
+  
+  assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
+  
+  Alignment = NewAlignment;
+}
+         
+const ASTRecordLayout *
+ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, 
+                                      const RecordDecl *D) {
+  ASTRecordLayoutBuilder Builder(Ctx);
+
+  Builder.Layout(D);
+
+  return new ASTRecordLayout(Builder.Size, Builder.Alignment,
+                             Builder.FieldOffsets.data(), 
+                             Builder.FieldOffsets.size());
+}

Added: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=76330&view=auto

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (added)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Sat Jul 18 15:20:21 2009
@@ -0,0 +1,51 @@
+//===- ASTRecordLayoutBuilder.h - Helper class for building record layouts ===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
+#define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+  class ASTContext;
+  class ASTRecordLayout;
+  class FieldDecl;
+  class RecordDecl;
+  
+class ASTRecordLayoutBuilder {
+  ASTContext &Ctx;
+
+  uint64_t Size;
+  uint64_t Alignment;
+  llvm::SmallVector<uint64_t, 16> FieldOffsets;
+  
+  unsigned StructPacking;
+  unsigned NextOffset;
+  bool IsUnion;
+  
+  ASTRecordLayoutBuilder(ASTContext &Ctx);
+  
+  void Layout(const RecordDecl *D);
+  void LayoutField(const FieldDecl *D);
+  void FinishLayout();
+  
+  void UpdateAlignment(unsigned NewAlignment);
+
+  ASTRecordLayoutBuilder(const ASTRecordLayoutBuilder&);   // DO NOT IMPLEMENT
+  void operator=(const ASTRecordLayoutBuilder&); // DO NOT IMPLEMENT
+public:
+  static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx, 
+                                              const RecordDecl *RD);
+  
+};
+  
+} // end namespace clang
+
+#endif
+





More information about the cfe-commits mailing list