[cfe-commits] r76846 - in /cfe/trunk/lib/CodeGen: CGRecordLayoutBuilder.cpp CGRecordLayoutBuilder.h

Anders Carlsson andersca at mac.com
Wed Jul 22 20:44:19 PDT 2009


Author: andersca
Date: Wed Jul 22 22:43:54 2009
New Revision: 76846

URL: http://llvm.org/viewvc/llvm-project?rev=76846&view=rev
Log:
Implement union layout support.

Modified:
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=76846&r1=76845&r2=76846&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Wed Jul 22 22:43:54 2009
@@ -27,6 +27,11 @@
 using namespace CodeGen;
 
 void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
+  if (D->isUnion()) {
+    LayoutUnion(D);
+    return;
+  }
+  
   if (const PackedAttr* PA = D->getAttr<PackedAttr>())
     StructPacking = PA->getAlignment();
 
@@ -141,11 +146,49 @@
   return true;
 }
 
+void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
+  assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!");
+  
+  const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
+  
+  const llvm::Type *Ty = 0;
+  uint64_t Size = 0;
+  unsigned Align = 0;
+  
+  unsigned FieldNo = 0;
+  for (RecordDecl::field_iterator Field = D->field_begin(), 
+       FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+    assert(Layout.getFieldOffset(FieldNo) == 0 && 
+          "Union field offset did not start at the beginning of record!");
+    
+    const llvm::Type *FieldTy = 
+      Types.ConvertTypeForMemRecursive(Field->getType());
+    unsigned FieldAlign = Types.getTargetData().getTypeAllocSize(FieldTy);
+    uint64_t FieldSize = Types.getTargetData().getABITypeAlignment(FieldTy);
+    
+    if (FieldAlign < Align)
+      continue;
+    
+    if (FieldAlign > Align || FieldSize > Size) {
+      Ty = FieldTy;
+      Align = FieldAlign;
+      Size = FieldSize;
+    }
+  }
+  
+  // Now add our field.
+  if (Ty)
+    AppendField(0, Size, Ty);
+  
+  // Append tail padding.
+  if (Layout.getSize() / 8 > Size)
+    AppendPadding(Layout.getSize() / 8, Align);
+}
+
 bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
   assert(!D->isUnion() && "Can't call LayoutFields on a union!");
   
-  const ASTRecordLayout &Layout = 
-    Types.getContext().getASTRecordLayout(D);
+  const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
   
   unsigned FieldNo = 0;
   for (RecordDecl::field_iterator Field = D->field_begin(), 
@@ -241,9 +284,6 @@
                                      const RecordDecl *D) {
   CGRecordLayoutBuilder Builder(Types);
   
-  if (D->isUnion())
-    return 0;
-
   Builder.Layout(D);
   
   // FIXME: Once this works well enough, enable it.

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h?rev=76846&r1=76845&r2=76846&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h Wed Jul 22 22:43:54 2009
@@ -83,6 +83,9 @@
   /// Layout - Will layout a RecordDecl.
   void Layout(const RecordDecl *D);
 
+  /// LayoutUnion - Will layout a union RecordDecl.
+  void LayoutUnion(const RecordDecl *D);
+  
   /// LayoutField - try to layout all fields in the record decl.
   /// Returns false if the operation failed because the struct is not packed.
   bool LayoutFields(const RecordDecl *D);





More information about the cfe-commits mailing list