[llvm-commits] [llvm-gcc-4.2] r50510 - in /llvm-gcc-4.2/trunk/gcc: llvm-types.cpp llvm.h objc/objc-act.c

Chris Lattner sabre at nondot.org
Wed Apr 30 18:39:53 PDT 2008


Author: lattner
Date: Wed Apr 30 20:39:53 2008
New Revision: 50510

URL: http://llvm.org/viewvc/llvm-project?rev=50510&view=rev
Log:
Fully revert r50276 from the tree and fix the objc bug another way:
When adding a field decl to a struct, if the LLVM type for the field
is larger than the field decl size, try to drop elements from the
llvm type to make it fit.  This fixes cases where the ObjC frontend
is abusing trees, fixing gcc/testsuite/objc.dg/newproperty-retain-3.c

There are other cases where the C++ front-end is violating the sanctity
of trees (see the FIXME and disabled assert) but this patch should not
make those cases any better or worse.


Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
    llvm-gcc-4.2/trunk/gcc/llvm.h
    llvm-gcc-4.2/trunk/gcc/objc/objc-act.c

Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=50510&r1=50509&r2=50510&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Wed Apr 30 20:39:53 2008
@@ -46,10 +46,6 @@
 }
 #include "llvm-abi.h"
 
-void llvm_compute_type(tree X) {
-  ConvertType(X);
-}
-
 //===----------------------------------------------------------------------===//
 //                   Matching LLVM types with GCC trees
 //===----------------------------------------------------------------------===//
@@ -1772,7 +1768,6 @@
   }
 }
 
-
 /// DecodeStructFields - This method decodes the specified field, if it is a
 /// FIELD_DECL, adding or updating the specified StructTypeConversionInfo to
 /// reflect it.  Return true if field is decoded correctly. Otherwise return
@@ -1817,29 +1812,82 @@
   unsigned StartOffsetInBytes = StartOffsetInBits/8;
 
   const Type *Ty = ConvertType(getDeclaredType(Field));
-
+  
   // If this field is packed then the struct may need padding fields
   // before this field.
   if (DECL_PACKED(Field) && !Info.isPacked())
     return false;
+  
   // Pop any previous elements out of the struct if they overlap with this one.
   // This can happen when the C++ front-end overlaps fields with tail padding in
   // C++ classes.
-  else if (!Info.ResizeLastElementIfOverlapsWith(StartOffsetInBytes, Field, Ty)) {
+  if (!Info.ResizeLastElementIfOverlapsWith(StartOffsetInBytes, Field, Ty)) {
     // LLVM disagrees as to where this field should go in the natural field
     // ordering.  Therefore convert to a packed struct and try again.
     return false;
   } 
-  else if (TYPE_USER_ALIGN(TREE_TYPE(Field))
-           && (unsigned)DECL_ALIGN_UNIT(Field) != Info.getTypeAlignment(Ty)
-           && !Info.isPacked()) {
+  
+  if (TYPE_USER_ALIGN(TREE_TYPE(Field)) &&
+      (unsigned)DECL_ALIGN_UNIT(Field) != Info.getTypeAlignment(Ty) &&
+      !Info.isPacked()) {
     // If Field has user defined alignment and it does not match Ty alignment
     // then convert to a packed struct and try again.
     return false;
-  } else
-    // At this point, we know that adding the element will happen at the right
-    // offset.  Add it.
-    Info.addElement(Ty, StartOffsetInBytes, Info.getTypeSize(Ty));
+  }
+  
+  // If the converted LLVM type has a different size than the field decl then we
+  // have a fun case where DECL_SIZE(Field) disagrees with 
+  // TYPE_SIZE(TREE_TYPE(Field)).  In a sane world, this would never happen, but
+  // it can occur in some places in the ObjC front-end for example.  The only
+  // time we support this is when the LLVM type is a struct.  In this case, we
+  // remove entries from the end of the LLVM struct until the size matches what
+  // the RTL backend expects as the size for the field.
+  if (DECL_SIZE(Field) && isInt64(DECL_SIZE(Field), true) &&
+      getInt64(DECL_SIZE(Field), true) != Info.getTypeSize(Ty)*8) {
+    uint64_t LLVMSize = Info.getTypeSize(Ty)*8;
+    uint64_t GCCFieldSize = getInt64(DECL_SIZE(Field), true);
+    tree FieldType = TREE_TYPE(Field);
+    assert(getInt64(TYPE_SIZE(FieldType), true) == LLVMSize &&
+           "LLVM and GCC type layout mismatch?");
+    assert(GCCFieldSize < Info.getTypeSize(Ty)*8 &&
+           "GCC FieldDecl size larger than its type's size?");
+    const StructType *STy = cast<StructType>(Ty);
+    
+    // Copy over elements that start before the GCC Field Size.
+    std::vector<const Type*> NewElements;
+    const StructLayout *Layout = getTargetData().getStructLayout(STy);
+
+    // Copy over all elements from the LLVM structure that start before the end
+    // of the GCC field decl.
+    if (GCCFieldSize) {
+      for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+        assert(i != STy->getNumElements() && "Didn't find any fields to drop?");
+        if (Layout->getElementOffset(i)*8 >= GCCFieldSize)
+          break;
+        NewElements.push_back(STy->getElementType(i));
+      }
+    }
+    
+    // Make a new LLVM struct out of these fields.
+    Ty = StructType::get(NewElements, STy->isPacked());
+    
+    // At this point, the size of the GCC and LLVM types must exactly match
+    // again... except when this is the last field of a C++ struct, in which
+    // case where are crazy tail padding games we have yet to play.  Verify
+    // that we either exactly match or that this is the last field.
+    //
+    // FIXME: Scratch that.  There are other crazy cases in the C++ front-end
+    // that violate this.  If we couldn't fix the type size here, we will
+    // continue on with an unmodified type, which at least won't break anything
+    // worse than it was before.
+    //
+    //assert((Info.getTypeSize(Ty)*8 == GCCFieldSize || isLastFieldDecl(Field))
+    //       && "Could not make GCC and LLVM field size agree!");
+  }
+  
+  // At this point, we know that adding the element will happen at the right
+  // offset.  Add it.
+  Info.addElement(Ty, StartOffsetInBytes, Info.getTypeSize(Ty));
   return true;
 }
 

Modified: llvm-gcc-4.2/trunk/gcc/llvm.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm.h?rev=50510&r1=50509&r2=50510&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm.h Wed Apr 30 20:39:53 2008
@@ -49,12 +49,6 @@
  */
 void reset_type_and_initializer_llvm(union tree_node*);
 
-/* llvm_compute_type - Compute the LLVM type for the specified tree type eagerly
- * instead of letting it happen lazily.
- */
-void llvm_compute_type(union tree_node*);
-
-
 /* reset_initializer_llvm - Change the initializer for a global variable. */
 void reset_initializer_llvm(union tree_node*);
 

Modified: llvm-gcc-4.2/trunk/gcc/objc/objc-act.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/objc/objc-act.c?rev=50510&r1=50509&r2=50510&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/objc/objc-act.c (original)
+++ llvm-gcc-4.2/trunk/gcc/objc/objc-act.c Wed Apr 30 20:39:53 2008
@@ -8619,22 +8619,6 @@
       /* APPLE LOCAL begin ObjC new abi */
       if (flag_objc_abi == 2)
         CLASS_TYPE (class) = record;
-      
-      /* APPLE LOCAL llvm begin */
-#if 0
-#ifdef ENABLE_LLVM
-      /* Synthesized properties will later be added to this RECORD_DECL as they
-       * are found in @implementations.  We don't want the LLVM tree->llvm
-       * converter to see these newly added properties, so we emulate the RTL
-       * backend and analyze the type eagerly in this case.  It would be better
-       * for the ObjC front-end to not add these properties to the RECORD_DECL
-       * but that would be a large/invasive change.  rdar://5812818
-       */
-      if (flag_objc_abi == 2)
-        llvm_compute_type(record);
-#endif
-#endif
-      /* APPLE LOCAL llvm end */
     }
 }
       /* APPLE LOCAL end ObjC new abi */





More information about the llvm-commits mailing list