]> granicus.if.org Git - clang/commitdiff
initial layout support for structures and unions. This isn't actually
authorChris Lattner <sabre@nondot.org>
Wed, 18 Jul 2007 17:52:12 +0000 (17:52 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 18 Jul 2007 17:52:12 +0000 (17:52 +0000)
hooked up to anything, so it's not very useful yet.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40006 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
clang.xcodeproj/project.pbxproj
include/clang/AST/ASTContext.h
include/clang/AST/RecordLayout.h [new file with mode: 0644]

index f7ae1a0e3acfda5e46b1122e0cd2b2bdfa9bb5f8..e2447b972a93623150f74e719c4e27256d1dfea2 100644 (file)
@@ -145,6 +145,9 @@ void ASTContext::InitBuiltinTypes() {
   LongDoubleComplexTy = getComplexType(LongDoubleTy);
 }
 
+//===----------------------------------------------------------------------===//
+//                         Type Sizing and Analysis
+//===----------------------------------------------------------------------===//
 
 /// getTypeSize - Return the size of the specified type, in bits.  This method
 /// does not work on incomplete types.
@@ -197,9 +200,76 @@ ASTContext::getTypeInfo(QualType T, SourceLocation L) {
     return getTypeInfo(cast<ReferenceType>(T)->getReferenceeType(), L);
   }
   
+  assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
   return std::make_pair(Size, Align);
 }
 
+/// getRecordLayout - Get or compute information about the layout of the
+/// specified record (struct/union/class), which indicates its size and field
+/// position information.
+const RecordLayout &ASTContext::getRecordLayout(const RecordDecl *D,
+                                                SourceLocation L) {
+  assert(D->isDefinition() && "Cannot get layout of forward declarations!");
+  
+  // Look up this layout, if already laid out, return what we have.
+  const RecordLayout *&Entry = RecordLayoutInfo[D];
+  if (Entry) return *Entry;
+  
+  // Allocate and assign into RecordLayoutInfo here.  The "Entry" reference can
+  // be invalidated (dangle) if the RecordLayoutInfo hashtable is inserted into.
+  RecordLayout *NewEntry = new RecordLayout();
+  Entry = NewEntry;
+  
+  uint64_t *FieldOffsets = new uint64_t[D->getNumMembers()];
+  uint64_t RecordSize = 0;
+  unsigned RecordAlign = 8;  // Default alignment = 1 byte = 8 bits.
+
+  if (D->getKind() != Decl::Union) {
+    // 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);
+      std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType(), L);
+      uint64_t FieldSize = FieldInfo.first;
+      unsigned FieldAlign = FieldInfo.second;
+      
+      // Round up the current record size to the field's alignment boundary.
+      RecordSize = (RecordSize+FieldAlign-1) & ~(FieldAlign-1);
+      
+      // Place this field at the current location.
+      FieldOffsets[i] = RecordSize;
+      
+      // Reserve space for this field.
+      RecordSize += FieldSize;
+      
+      // Remember max struct/class alignment.
+      RecordAlign = std::max(RecordAlign, FieldAlign);
+    }
+    
+    // Finally, round the size of the total struct up to the alignment of the
+    // struct itself.
+    RecordSize = (RecordSize+RecordAlign-1) & ~(RecordAlign-1);
+  } else {
+    // Union layout just puts each member at the start of the record.
+    for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
+      const FieldDecl *FD = D->getMember(i);
+      std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType(), L);
+      uint64_t FieldSize = FieldInfo.first;
+      unsigned FieldAlign = FieldInfo.second;
+      
+      // Round up the current record size to the field's alignment boundary.
+      RecordSize = std::max(RecordSize, FieldSize);
+      
+      // Place this field at the start of the record.
+      FieldOffsets[i] = 0;
+      
+      // Remember max struct/class alignment.
+      RecordAlign = std::max(RecordAlign, FieldAlign);
+    }
+  }
+}
+
+
 //===----------------------------------------------------------------------===//
 //                   Type creation/memoization methods
 //===----------------------------------------------------------------------===//
index 560076196ae1d974557e7afbc5b596fea14a62a5..fe2507f9f6c05b6409c244f585664810120c4968 100644 (file)
@@ -58,6 +58,7 @@
                DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7160C020EE400F66BC5 /* Sema.cpp */; };
                DE67E71A0C020F4F00F66BC5 /* ASTStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */; };
                DE67E7280C02109800F66BC5 /* ASTStreamer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE67E7270C02109800F66BC5 /* ASTStreamer.h */; };
+               DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6951C60C4D1F5D00A5826B /* RecordLayout.h */; };
                DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE75ED280B044DC90020CF81 /* ASTContext.h */; };
                DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE75EDF00B06880E0020CF81 /* Type.cpp */; };
                DE927FFD0C055DE900231DA4 /* LLVMCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE927FFC0C055DE900231DA4 /* LLVMCodegen.cpp */; };
                                DEB0AEB90C2087A700718A22 /* TextDiagnostics.h in CopyFiles */,
                                DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */,
                                DEEBCBE30C33702C00A9FE82 /* TextDiagnosticBuffer.h in CopyFiles */,
+                               DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */,
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
                DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = Sema/Sema.cpp; sourceTree = "<group>"; };
                DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = Sema/ASTStreamer.cpp; sourceTree = "<group>"; };
                DE67E7270C02109800F66BC5 /* ASTStreamer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTStreamer.h; path = clang/Sema/ASTStreamer.h; sourceTree = "<group>"; };
+               DE6951C60C4D1F5D00A5826B /* RecordLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = RecordLayout.h; path = clang/AST/RecordLayout.h; sourceTree = "<group>"; };
                DE75ED280B044DC90020CF81 /* ASTContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTContext.h; path = clang/AST/ASTContext.h; sourceTree = "<group>"; };
                DE75EDF00B06880E0020CF81 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = AST/Type.cpp; sourceTree = "<group>"; };
                DE927FFC0C055DE900231DA4 /* LLVMCodegen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMCodegen.cpp; path = Driver/LLVMCodegen.cpp; sourceTree = "<group>"; };
                                DEC8D9900A9433CD00353FCA /* Decl.h */,
                                DE0FCA620A95859D00248FD5 /* Expr.h */,
                                1A30A9E80B93A4C800201A91 /* ExprCXX.h */,
+                               DE6951C60C4D1F5D00A5826B /* RecordLayout.h */,
                                DE3452800AEF1B1800DBC861 /* Stmt.h */,
                                DE345F210AFD347900DBC861 /* StmtNodes.def */,
                                DE345C190AFC658B00DBC861 /* StmtVisitor.h */,
index 9010a854168c2de65d94aecb63c64719eba6016b..fc599b51f7f581cf0c3ff6353b8c9e2e659f2dd9 100644 (file)
 #define LLVM_CLANG_AST_ASTCONTEXT_H
 
 #include "clang/AST/Builtins.h"
-#include "clang/AST/Type.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
 #include <vector>
 
 namespace clang {
@@ -33,6 +35,7 @@ class ASTContext {
   llvm::FoldingSet<VectorType> VectorTypes;
   llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
   llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
+  llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
 public:
   TargetInfo &Target;
   Builtin::Context BuiltinInfo;
@@ -55,21 +58,9 @@ public:
   
   void PrintStats() const;
 
-  /// getTypeInfo - Get the size and alignment of the specified complete type in
-  /// bits.
-  std::pair<uint64_t, unsigned> getTypeInfo(QualType T, SourceLocation L);
-
-  /// getTypeSize - Return the size of the specified type, in bits.  This method
-  /// does not work on incomplete types.
-  uint64_t getTypeSize(QualType T, SourceLocation L) {
-    return getTypeInfo(T, L).first;
-  }
-  
-  /// getTypeAlign - Return the alignment of the specified type, in bits.  This
-  /// method does not work on incomplete types.
-  unsigned getTypeAlign(QualType T, SourceLocation L) {
-    return getTypeInfo(T, L).second;
-  }    
+  //===--------------------------------------------------------------------===//
+  //                           Type Constructors
+  //===--------------------------------------------------------------------===//
   
   /// getComplexType - Return the uniqued reference to the type for a complex
   /// number with the specified element type.
@@ -118,21 +109,50 @@ public:
   /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
   QualType getPointerDiffType() const;
   
+  //===--------------------------------------------------------------------===//
+  //                         Type Sizing and Analysis
+  //===--------------------------------------------------------------------===//
+  
+  /// getTypeInfo - Get the size and alignment of the specified complete type in
+  /// bits.
+  std::pair<uint64_t, unsigned> getTypeInfo(QualType T, SourceLocation L);
+  
+  /// getTypeSize - Return the size of the specified type, in bits.  This method
+  /// does not work on incomplete types.
+  uint64_t getTypeSize(QualType T, SourceLocation L) {
+    return getTypeInfo(T, L).first;
+  }
+  
+  /// getTypeAlign - Return the alignment of the specified type, in bits.  This
+  /// method does not work on incomplete types.
+  unsigned getTypeAlign(QualType T, SourceLocation L) {
+    return getTypeInfo(T, L).second;
+  }
+  
+  /// getRecordLayout - Get or compute information about the layout of the
+  /// specified record (struct/union/class), which indicates its size and field
+  /// position information.
+  const RecordLayout &getRecordLayout(const RecordDecl *D, SourceLocation L);
+  
+  //===--------------------------------------------------------------------===//
+  //                            Type Operators
+  //===--------------------------------------------------------------------===//
+  
   /// getIntegerBitwidth - Return the bitwidth of the specified integer type
   /// according to the target.  'Loc' specifies the source location that
   /// requires evaluation of this property.
   unsigned getIntegerBitwidth(QualType T, SourceLocation Loc);
-
-  // maxIntegerType - Returns the highest ranked integer type. Handles 3
-  // different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
+  
+  /// maxIntegerType - Returns the highest ranked integer type. Handles 3
+  /// different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
   static QualType maxIntegerType(QualType lhs, QualType rhs);
   
-  // maxFloatingType - Returns the highest ranked float type. Both input 
-  // types are required to be floats.
+  /// maxFloatingType - Returns the highest ranked float type. Both input 
+  /// types are required to be floats.
   static QualType maxFloatingType(QualType lt, QualType rt);
 
-  // maxComplexType - Returns the highest ranked complex type. Handles 3
-  // different type combos: complex/complex, complex/float, float/complex. 
+  /// maxComplexType - Returns the highest ranked complex type. Handles 3
+  /// different type combos: complex/complex, complex/float, float/complex. 
   QualType maxComplexType(QualType lt, QualType rt) const;
   
 private:
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
new file mode 100644 (file)
index 0000000..5169737
--- /dev/null
@@ -0,0 +1,57 @@
+//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the RecordLayout interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
+#define LLVM_CLANG_AST_LAYOUTINFO_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+  class ASTContext;
+  class RecordDecl;
+
+/// RecordLayout - This class contains layout information for one RecordDecl,
+/// which is a struct/union/class.  The decl represented must be a definition,
+/// not a forward declaration.  These objects are managed by ASTContext.
+class RecordLayout {
+  uint64_t Size;        // Size of record in bits.
+  unsigned Alignment;   // Alignment of record in bits.
+  uint64_t *FieldOffsets;
+  friend class ASTContext;
+  
+  RecordLayout() {}
+  ~RecordLayout() {
+    delete [] FieldOffsets;
+  }
+  
+  void SetLayout(uint64_t size, unsigned alignment, uint64_t *fieldOffsets) {
+    Size = Size; Alignment = alignment;
+    FieldOffsets = fieldOffsets;
+  }
+  
+  RecordLayout(const RecordLayout&);   // DO NOT IMPLEMENT
+  void operator=(const RecordLayout&); // DO NOT IMPLEMENT
+public:
+  
+  unsigned getAlignment() const { return Alignment; }
+  uint64_t getSize() const { return Size; }
+  
+  uint64_t getFieldOffset(unsigned FieldNo) const {
+    return FieldOffsets[FieldNo];
+  }
+    
+};
+
+}  // end namespace clang
+
+#endif