[llvm-commits] [llvm-gcc-4.2] r81399 - in /llvm-gcc-4.2/trunk/gcc: llvm-types.cpp tree.h

Dale Johannesen dalej at apple.com
Wed Sep 9 16:36:05 PDT 2009


Author: johannes
Date: Wed Sep  9 18:36:04 2009
New Revision: 81399

URL: http://llvm.org/viewvc/llvm-project?rev=81399&view=rev
Log:
In the presence of #pragma pack, layouts
can be created where a base class has different alignments
in different derived classes.  The code for dealing with
base classes wasn't handling this correctly, leading to
assertions.  Rewrite the base class remapper to key off
a <type, alignment> pair instead of handling the size and
alignment cases separately.


Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
    llvm-gcc-4.2/trunk/gcc/tree.h

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=81399&r1=81398&r2=81399&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Wed Sep  9 18:36:04 2009
@@ -1685,10 +1685,7 @@
 }
 
 /// Mapping from type to type-used-as-base-class and back.
-static DenseMap<tree, tree> BaseTypesMap;
-
-/// Mapping from type to less-aligned-type-used-within-struct and back.
-static DenseMap<std::pair<tree, unsigned int>, tree> LessAlignedTypesMap;
+static DenseMap<std::pair<tree, unsigned int>, tree > BaseTypesMap;
 
 /// FixBaseClassField - This method is called when we have a field Field
 /// of Record type within a Record, and the size of Field is smaller than the
@@ -1702,7 +1699,9 @@
 
 static tree FixBaseClassField(tree Field) {
   tree oldTy = TREE_TYPE(Field);
-  tree newTy = BaseTypesMap[oldTy];
+  std::pair<tree, unsigned int> p = std::make_pair(oldTy,
+                     std::min(DECL_ALIGN(Field), TYPE_ALIGN(oldTy)));
+  tree newTy = BaseTypesMap[p];
   // If already in table, reuse.
   if (!newTy) {
     newTy = copy_node(oldTy);
@@ -1727,11 +1726,11 @@
     // to the C++ virtual base case to get this far, but these don't have
     // the TYPE_DECL sentinel, nor the virtual base class allocation problem.
     if (!F || TREE_CODE(F) != TYPE_DECL) {
-      BaseTypesMap[oldTy] = oldTy;
+      BaseTypesMap[p] = oldTy;
       return oldTy;
     }
-    BaseTypesMap[oldTy] = newTy;
-    BaseTypesMap[newTy] = oldTy;
+    BaseTypesMap[p] = newTy;
+    BaseTypesMap[std::make_pair(newTy, 0U)] = oldTy;
     // Prevent gcc's garbage collector from destroying newTy.  The
     // GC code doesn't understand DenseMaps:(
     llvm_note_type_used(newTy);
@@ -1750,57 +1749,8 @@
         p = IDENTIFIER_POINTER(TYPE_NAME(oldTy));
       else if (DECL_NAME(TYPE_NAME(oldTy)))
         p = IDENTIFIER_POINTER(DECL_NAME(TYPE_NAME(oldTy)));
-      char *q = (char *)xmalloc(strlen(p)+6);
-      strcpy(q,p);
-      strcat(q,".base");
-      TYPE_NAME(newTy) = get_identifier(q);
-      free(q);
-    }
-  }
-  return newTy;
-}
-
-/// FixLessAlignedClassField - This method is called when we have a field Field
-/// of Record type within a Record, and the alignment of Field is smaller than
-/// alignment of its Record type.  The field may not get as much tail padding
-/// as the type would in other contexts.  Replace Field's original
-/// type with a modified one that has the Field's alignment.
-
-static tree FixLessAlignedClassField(tree Field) {
-  tree oldTy = TREE_TYPE(Field);
-  std::pair<tree, unsigned int> p = std::make_pair(oldTy, DECL_ALIGN(Field));
-  tree newTy = LessAlignedTypesMap[p];
-  // If already in table, reuse.
-  if (!newTy) {
-    newTy = copy_node(oldTy);
-    tree F2 = 0, prevF2 = 0, F;
-    // Copy all the fields.
-    for (F = TYPE_FIELDS(oldTy); F; prevF2 = F2, F = TREE_CHAIN(F)) {
-      F2 = copy_node(F);
-      if (prevF2)
-        TREE_CHAIN(prevF2) = F2;
-      else
-        TYPE_FIELDS(newTy) = F2;
-      TREE_CHAIN(F2) = 0;
-    }
-    LessAlignedTypesMap[p] = newTy;
-    LessAlignedTypesMap[std::make_pair(newTy, 0U)] = oldTy;
-    /* Prevent gcc's garbage collector from destroying newTy.  The
-       GC code doesn't understand DenseMaps:( */
-    llvm_note_type_used(newTy);
-    TYPE_ALIGN(newTy) = DECL_ALIGN(Field);
-    TYPE_MAIN_VARIANT(newTy) = newTy;
-    TYPE_STUB_DECL(newTy) = TYPE_STUB_DECL(oldTy);
-    // Change the name.
-    if (TYPE_NAME(oldTy)) {
-      const char *p = "anon";
-      if (TREE_CODE(TYPE_NAME(oldTy)) ==IDENTIFIER_NODE)
-        p = IDENTIFIER_POINTER(TYPE_NAME(oldTy));
-      else if (DECL_NAME(TYPE_NAME(oldTy)))
-        p = IDENTIFIER_POINTER(DECL_NAME(TYPE_NAME(oldTy)));
-      char *q = (char *)xmalloc(strlen(p)+7);
-      strcpy(q,p);
-      strcat(q,".align");
+      char *q = (char *)xmalloc(strlen(p)+20);
+      sprintf(q, "%s.base.%d", p, TYPE_ALIGN(newTy));
       TYPE_NAME(newTy) = get_identifier(q);
       free(q);
     }
@@ -1822,12 +1772,12 @@
 // node for it, but not when A is a nonvirtual base class.  So we can't
 // use that.)
 //
-// Also alter the types referred to by Field nodes that have greater alignment
-// than the Field does; these might not get the tail padding as a Field that
-// they get elsewhere.
-//
-// Both transformations can be needed for the same type (in different contexts),
-// so we need two mappings.
+// If #pragma pack is involved, different derived classes may use different
+// sizes for the base class.  We also alter the types referred to by Field nodes
+// that have greater alignment than the Field does; these might not get the
+// tail padding as a Field that they get elsewhere. To handle these additional
+// cases the size and alignment of the field are used as parts of the index
+// into the map of base classes already created.
 
 static void FixUpFields(tree type) {
   if (TREE_CODE(type)!=RECORD_TYPE)
@@ -1839,29 +1789,17 @@
         TREE_CODE(TREE_TYPE(Field))==RECORD_TYPE &&
         TYPE_SIZE(TREE_TYPE(Field)) &&
         DECL_SIZE(Field) &&
-        TREE_CODE(DECL_SIZE(Field))==INTEGER_CST &&
-        TREE_CODE(TYPE_SIZE(TREE_TYPE(Field)))==INTEGER_CST &&
-        TREE_INT_CST_LOW(DECL_SIZE(Field)) < 
-              TREE_INT_CST_LOW(TYPE_SIZE(TREE_TYPE(Field)))) {
+        ((TREE_CODE(DECL_SIZE(Field))==INTEGER_CST &&
+          TREE_CODE(TYPE_SIZE(TREE_TYPE(Field)))==INTEGER_CST &&
+          TREE_INT_CST_LOW(DECL_SIZE(Field)) < 
+              TREE_INT_CST_LOW(TYPE_SIZE(TREE_TYPE(Field)))) ||
+         (DECL_ALIGN(Field) < TYPE_ALIGN(TREE_TYPE(Field))))) {
       tree newType = FixBaseClassField(Field);
       if (newType != TREE_TYPE(Field)) {
         TREE_TYPE(Field) = newType;
         DECL_FIELD_BASE_REPLACED(Field) = 1;
       }
     }
-    if (TREE_CODE(Field)==FIELD_DECL && 
-        !DECL_BIT_FIELD_TYPE(Field) &&
-        TREE_CODE(DECL_FIELD_OFFSET(Field))==INTEGER_CST &&
-        TREE_CODE(TREE_TYPE(Field))==RECORD_TYPE &&
-        TYPE_SIZE(TREE_TYPE(Field)) &&
-        DECL_SIZE(Field) &&
-        DECL_ALIGN(Field) < TYPE_ALIGN(TREE_TYPE(Field))) {
-      tree newType = FixLessAlignedClassField(Field);
-      if (newType != TREE_TYPE(Field)) {
-        TREE_TYPE(Field) = newType;
-        DECL_FIELD_ALIGN_REPLACED(Field) = 1;
-      }
-    }
   }
   // Size of the complete type will be a multiple of its alignment.
   // In some cases involving empty C++ classes this is not true coming in.
@@ -1900,17 +1838,11 @@
   for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
     if (TREE_CODE(Field) == FIELD_DECL) {
       if (DECL_FIELD_BASE_REPLACED(Field)) {
-        tree &oldTy = BaseTypesMap[TREE_TYPE(Field)];
+        tree &oldTy = BaseTypesMap[std::make_pair(TREE_TYPE(Field), 0U)];
         assert(oldTy);
         TREE_TYPE(Field) = oldTy;
         DECL_FIELD_BASE_REPLACED(Field) = 0;
       }
-      if (DECL_FIELD_ALIGN_REPLACED(Field)) {
-        tree &oldTy = LessAlignedTypesMap[std::make_pair(TREE_TYPE(Field), 0U)];
-        assert(oldTy);
-        TREE_TYPE(Field) = oldTy;
-        DECL_FIELD_ALIGN_REPLACED(Field) = 0;
-      }
     }
   }
 }
@@ -2111,7 +2043,7 @@
 // class D : public virtual B, public virtual C { public: int i3; };
 //
 // The TYPE nodes gcc builds for classes represent that class as it looks
-// standing alone.  Thus B is size 12 and looks like { vptr; i2; baseclass A; }
+// standing alone.  Thus B is size 12 and looks like { vptr; i1; baseclass A; }
 // However, this is not the layout used when that class is a base class for 
 // some other class, yet the same TYPE node is still used.  D in the above has
 // both a BINFO list entry and a FIELD that reference type B, but the virtual

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

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/tree.h (original)
+++ llvm-gcc-4.2/trunk/gcc/tree.h Wed Sep  9 18:36:04 2009
@@ -2751,10 +2751,6 @@
 /* In a FIELD_DECL, marks that the type is temporarily replaced in ConvertType
    because it is used as a base class of another type. */
 #define DECL_FIELD_BASE_REPLACED(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0)
-/* In a FIELD_DECL, marks that the type is temporarily replaced in ConvertType
-   because it is used as the type of a field with less alignment than the
-   type, which means the type may not get tail padding in this case. */
-#define DECL_FIELD_ALIGN_REPLACED(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.gimple_reg_flag)
 #endif
 /* LLVM LOCAL end */
 





More information about the llvm-commits mailing list