OSDN Git Service

* decl.c (maybe_pad_type): Try to get a form of the type with integral
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 May 2008 19:35:01 +0000 (19:35 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 May 2008 19:35:01 +0000 (19:35 +0000)
mode even if the alignment is not a factor of the original size.  But
make sure to create the inner field with the original size.  Reorder.
* trans.c (addressable_p) <COMPONENT_REF>: Treat the field of a padding
record as always addressable.
* utils.c (convert): Deal specially with conversions between original
and packable versions of a record type.
* utils2.c (build_binary_op) <MODIFY_EXPR>: Be more restrictive when
recognizing an assignment between padded objects.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@134916 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/ada/trans.c
gcc/ada/utils.c
gcc/ada/utils2.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/alignment4.adb
gcc/testsuite/gnat.dg/alignment5.adb
gcc/testsuite/gnat.dg/alignment6.adb

index b1f1a6c..6da64b6 100644 (file)
@@ -1,3 +1,15 @@
+2008-05-03  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * decl.c (maybe_pad_type): Try to get a form of the type with integral
+       mode even if the alignment is not a factor of the original size.  But
+       make sure to create the inner field with the original size.  Reorder.
+       * trans.c (addressable_p) <COMPONENT_REF>: Treat the field of a padding
+       record as always addressable.
+       * utils.c (convert): Deal specially with conversions between original
+       and packable versions of a record type.
+       * utils2.c (build_binary_op) <MODIFY_EXPR>: Be more restrictive when
+       recognizing an assignment between padded objects.
+
 2008-05-01  Eric Botcazou  <ebotcazou@adacore.com>
 
        * decl.c (make_packable_type): Resize the last component to its RM size
index 8dec1be..9d933b7 100644 (file)
@@ -5448,9 +5448,9 @@ make_packable_type (tree type, bool in_record)
 
   new_type = make_node (TREE_CODE (type));
 
-  /* Copy the name and flags from the old type to that of the new.  Note
-     that we rely on the pointer equality created here for TYPE_NAME at
-     the end of gnat_to_gnu.  */
+  /* Copy the name and flags from the old type to that of the new.
+     Note that we rely on the pointer equality created here for
+     TYPE_NAME to look through conversions in various places.  */
   TYPE_NAME (new_type) = TYPE_NAME (type);
   TYPE_JUSTIFIED_MODULAR_P (new_type) = TYPE_JUSTIFIED_MODULAR_P (type);
   TYPE_CONTAINS_TEMPLATE_P (new_type) = TYPE_CONTAINS_TEMPLATE_P (type);
@@ -5576,7 +5576,7 @@ make_packable_type (tree type, bool in_record)
    GNAT_ENTITY and NAME_TRAILER are used to name the resulting record and
    to issue a warning.
 
-   IS_USER_TYPE is true if we must be sure we complete the original type.
+   IS_USER_TYPE is true if we must complete the original type.
 
    DEFINITION is true if this type is being defined.
 
@@ -5634,59 +5634,65 @@ maybe_pad_type (tree type, tree size, unsigned int align,
   if (align == 0 && !size)
     return type;
 
+  /* If requested, complete the original type and give it a name.  */
+  if (is_user_type)
+    create_type_decl (get_entity_name (gnat_entity), type,
+                     NULL, !Comes_From_Source (gnat_entity),
+                     !(TYPE_NAME (type)
+                       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+                       && DECL_IGNORED_P (TYPE_NAME (type))),
+                     gnat_entity);
+
   /* We used to modify the record in place in some cases, but that could
      generate incorrect debugging information.  So make a new record
      type and name.  */
   record = make_node (RECORD_TYPE);
+  TYPE_IS_PADDING_P (record) = 1;
 
   if (Present (gnat_entity))
     TYPE_NAME (record) = create_concat_name (gnat_entity, name_trailer);
 
-  /* If we were making a type, complete the original type and give it a
-     name.  */
-  if (is_user_type)
-    create_type_decl (get_entity_name (gnat_entity), type,
-                     NULL, !Comes_From_Source (gnat_entity),
-                     !(TYPE_NAME (type)
-                       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-                       && DECL_IGNORED_P (TYPE_NAME (type))),
-                     gnat_entity);
+  TYPE_VOLATILE (record)
+    = Present (gnat_entity) && Treat_As_Volatile (gnat_entity);
+
+  TYPE_ALIGN (record) = align;
+  if (orig_align)
+    TYPE_USER_ALIGN (record) = align;
+
+  TYPE_SIZE (record) = size ? size : orig_size;
+  TYPE_SIZE_UNIT (record)
+    = convert (sizetype,
+              size_binop (CEIL_DIV_EXPR, TYPE_SIZE (record),
+                          bitsize_unit_node));
 
   /* If we are changing the alignment and the input type is a record with
      BLKmode and a small constant size, try to make a form that has an
-     integral mode.  That might allow this record to have an integral mode,
-     which will be much more efficient.  There is no point in doing this if a
-     size is specified unless it is also smaller than the maximum mode size
-     and it is incorrect to do this if the size of the original type is not a
-     multiple of the alignment.  */
+     integral mode.  This might allow the padding record to also have an
+     integral mode, which will be much more efficient.  There is no point
+     in doing so if a size is specified unless it is also a small constant
+     size and it is incorrect to do so if we cannot guarantee that the mode
+     will be naturally aligned since the field must always be addressable.  */
   if (align != 0
       && TREE_CODE (type) == RECORD_TYPE
       && TYPE_MODE (type) == BLKmode
       && TREE_CODE (orig_size) == INTEGER_CST
+      && !TREE_CONSTANT_OVERFLOW (orig_size)
       && compare_tree_int (orig_size, MAX_FIXED_MODE_SIZE) <= 0
       && (!size
          || (TREE_CODE (size) == INTEGER_CST
-             && compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0))
-      && value_factor_p (orig_size, align))
-    type = make_packable_type (type, true);
+             && compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0)))
+    {
+      tree packable_type = make_packable_type (type, true);
+      if (TYPE_MODE (packable_type) != BLKmode
+         && align >= TYPE_ALIGN (packable_type))
+        type = packable_type;
+    }
 
+  /* Now create the field with the original size.  */
   field  = create_field_decl (get_identifier ("F"), type, record, 0,
-                             NULL_TREE, bitsize_zero_node, 1);
-
+                             orig_size, bitsize_zero_node, 1);
   DECL_INTERNAL_P (field) = 1;
-  TYPE_SIZE (record) = size ? size : orig_size;
-  TYPE_SIZE_UNIT (record)
-    = (size ? convert (sizetype,
-                      size_binop (CEIL_DIV_EXPR, size, bitsize_unit_node))
-       : TYPE_SIZE_UNIT (type));
 
-  TYPE_ALIGN (record) = align;
-  if (orig_align)
-    TYPE_USER_ALIGN (record) = align;
-
-  TYPE_IS_PADDING_P (record) = 1;
-  TYPE_VOLATILE (record)
-    = Present (gnat_entity) && Treat_As_Volatile (gnat_entity);
   /* Do not finalize it until after the auxiliary record is built.  */
   finish_record_type (record, field, 1, true);
 
index 404b42f..5ec3ecd 100644 (file)
@@ -202,7 +202,7 @@ static tree emit_range_check (tree, Node_Id);
 static tree emit_index_check (tree, tree, tree, tree);
 static tree emit_check (tree, tree, int);
 static tree convert_with_check (Entity_Id, tree, bool, bool, bool);
-static bool larger_record_type_p (tree, tree);
+static bool smaller_packable_type_p (tree, tree);
 static bool addressable_p (tree, tree);
 static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
 static tree extract_values (tree, tree);
@@ -2204,11 +2204,11 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
             of the object if they are distinct, because the expectations
             of the callee would otherwise not be met:
               - if it's a justified modular type,
-              - if the actual type is a packable version of it.  */
+              - if the actual type is a smaller packable version of it.  */
          else if (TREE_CODE (gnu_name_type) == RECORD_TYPE
                   && (TYPE_JUSTIFIED_MODULAR_P (gnu_name_type)
-                      || larger_record_type_p (gnu_name_type,
-                                               TREE_TYPE (gnu_name))))
+                      || smaller_packable_type_p (TREE_TYPE (gnu_name),
+                                                gnu_name_type)))
            gnu_name = convert (gnu_name_type, gnu_name);
 
          /* Make a SAVE_EXPR to both properly account for potential side
@@ -6120,21 +6120,25 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
   return convert (gnu_type, gnu_result);
 }
 \f
-/* Return true if RECORD_TYPE, a record type, is larger than TYPE.  */
+/* Return true if TYPE is a smaller packable version of RECORD_TYPE.  */
 
 static bool
-larger_record_type_p (tree record_type, tree type)
+smaller_packable_type_p (tree type, tree record_type)
 {
-  tree rsize, size;
+  tree size, rsize;
 
-  /* Padding types are not considered larger on their own.  */
-  if (TYPE_IS_PADDING_P (record_type))
+  /* We're not interested in variants here.  */
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (record_type))
+    return false;
+
+  /* Like a variant, a packable version keeps the original TYPE_NAME.  */
+  if (TYPE_NAME (type) != TYPE_NAME (record_type))
     return false;
 
-  rsize = TYPE_SIZE (record_type);
   size = TYPE_SIZE (type);
+  rsize = TYPE_SIZE (record_type);
 
-  if (!(TREE_CODE (rsize) == INTEGER_CST && TREE_CODE (size) == INTEGER_CST))
+  if (!(TREE_CODE (size) == INTEGER_CST && TREE_CODE (rsize) == INTEGER_CST))
     return false;
 
   return tree_int_cst_lt (size, rsize) != 0;
@@ -6208,7 +6212,7 @@ addressable_p (tree gnu_expr, tree gnu_type)
      to be considered in practice.  */
   if (gnu_type
       && TREE_CODE (gnu_type) == RECORD_TYPE
-      && larger_record_type_p (gnu_type, TREE_TYPE (gnu_expr)))
+      && smaller_packable_type_p (TREE_TYPE (gnu_expr), gnu_type))
     return false;
 
   switch (TREE_CODE (gnu_expr))
@@ -6238,16 +6242,18 @@ addressable_p (tree gnu_expr, tree gnu_type)
              && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE));
 
     case COMPONENT_REF:
-      return (!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
-             && (!STRICT_ALIGNMENT
-                 /* Even with DECL_BIT_FIELD cleared, we have to ensure that
-                    the field is sufficiently aligned, in case it is subject
-                    to a pragma Component_Alignment.  But we don't need to
-                    check the alignment of the containing record, as it is
-                    guaranteed to be not smaller than that of its most
-                    aligned field that is not a bit-field.  */
-                 || DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
-                      >= TYPE_ALIGN (TREE_TYPE (gnu_expr)))
+      return (((!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
+               /* Even with DECL_BIT_FIELD cleared, we have to ensure that
+                  the field is sufficiently aligned, in case it is subject
+                  to a pragma Component_Alignment.  But we don't need to
+                  check the alignment of the containing record, as it is
+                  guaranteed to be not smaller than that of its most
+                  aligned field that is not a bit-field.  */
+               && (!STRICT_ALIGNMENT
+                   || DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
+                      >= TYPE_ALIGN (TREE_TYPE (gnu_expr))))
+              /* The field of a padding record is always addressable.  */
+              || TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))
              && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
 
     case ARRAY_REF:  case ARRAY_RANGE_REF:
index d6a2234..8d3df68 100644 (file)
@@ -3396,7 +3396,9 @@ convert (tree type, tree expr)
           && TYPE_IS_PADDING_P (type) && TYPE_IS_PADDING_P (etype)
           && (!TREE_CONSTANT (TYPE_SIZE (type))
               || !TREE_CONSTANT (TYPE_SIZE (etype))
-              || gnat_types_compatible_p (type, etype)))
+              || gnat_types_compatible_p (type, etype)
+              || TYPE_NAME (TREE_TYPE (TYPE_FIELDS (type)))
+                 == TYPE_NAME (TREE_TYPE (TYPE_FIELDS (etype)))))
     ;
 
   /* If the output type has padding, convert to the inner type and
@@ -3405,9 +3407,13 @@ convert (tree type, tree expr)
     {
       /* If we previously converted from another type and our type is
         of variable size, remove the conversion to avoid the need for
-        variable-size temporaries.  */
+        variable-size temporaries.  Likewise for a conversion between
+        original and packable version.  */
       if (TREE_CODE (expr) == VIEW_CONVERT_EXPR
-         && !TREE_CONSTANT (TYPE_SIZE (type)))
+         && (!TREE_CONSTANT (TYPE_SIZE (type))
+             || (ecode == RECORD_TYPE
+                 && TYPE_NAME (etype)
+                    == TYPE_NAME (TREE_TYPE (TREE_OPERAND (expr, 0))))))
        expr = TREE_OPERAND (expr, 0);
 
       /* If we are just removing the padding from expr, convert the original
@@ -3419,7 +3425,10 @@ convert (tree type, tree expr)
          && TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
          && (!TREE_CONSTANT (TYPE_SIZE (type))
              || gnat_types_compatible_p (type,
-                                         TREE_TYPE (TREE_OPERAND (expr, 0)))))
+                                         TREE_TYPE (TREE_OPERAND (expr, 0)))
+             || (ecode == RECORD_TYPE
+                 && TYPE_NAME (etype)
+                    == TYPE_NAME (TREE_TYPE (TYPE_FIELDS (type))))))
        return convert (type, TREE_OPERAND (expr, 0));
 
       /* If the result type is a padded type with a self-referentially-sized
@@ -3534,8 +3543,12 @@ convert (tree type, tree expr)
 
     case CONSTRUCTOR:
       /* If we are converting a CONSTRUCTOR to a mere variant type, just make
-        a new one in the proper type.  */
-      if (gnat_types_compatible_p (type, etype))
+        a new one in the proper type.  Likewise for a conversion between
+        original and packable version.  */
+      if (code == ecode
+         && (gnat_types_compatible_p (type, etype)
+             || (code == RECORD_TYPE
+                 && TYPE_NAME (type) == TYPE_NAME (etype))))
        {
          expr = copy_node (expr);
          TREE_TYPE (expr) = type;
@@ -3617,7 +3630,8 @@ convert (tree type, tree expr)
 
   /* If we're converting between two aggregate types that are mere
      variants, just make a VIEW_CONVERT_EXPR.  */
-  else if (AGGREGATE_TYPE_P (type)
+  else if (code == ecode
+          && AGGREGATE_TYPE_P (type)
           && gnat_types_compatible_p (type, etype))
     return build1 (VIEW_CONVERT_EXPR, type, expr);
 
index f2eaf5e..b45c7ac 100644 (file)
@@ -693,21 +693,24 @@ build_binary_op (enum tree_code op_code, tree result_type,
          && TYPE_ALIGN_OK (right_type))
        operation_type = right_type;
 
-      /* If we are copying between padded objects of the same underlying
-        type with a non-zero size, use the padded view of the type, this
-        is very likely more efficient; but gnat_to_gnu will have removed
-        the padding on the RHS so we have to make sure that we can safely
-        put it back.  */
+      /* If we are copying between padded objects with compatible types, use
+        the padded view of the objects, this is very likely more efficient.
+        Likewise for a padded that is assigned a constructor, in order to
+        avoid putting a VIEW_CONVERT_EXPR on the LHS.  But don't do this if
+        we wouldn't have actually copied anything.  */
       else if (TREE_CODE (left_type) == RECORD_TYPE
               && TYPE_IS_PADDING_P (left_type)
-              && TREE_TYPE (TYPE_FIELDS (left_type)) == right_type
-              && !integer_zerop (TYPE_SIZE (right_type))
+              && TREE_CONSTANT (TYPE_SIZE (left_type))
               && ((TREE_CODE (right_operand) == COMPONENT_REF
                    && TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
                       == RECORD_TYPE
                    && TYPE_IS_PADDING_P
-                      (TREE_TYPE (TREE_OPERAND (right_operand, 0))))
-                  || TREE_CODE (right_operand) == CONSTRUCTOR))
+                      (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
+                   && gnat_types_compatible_p
+                       (left_type,
+                        TREE_TYPE (TREE_OPERAND (right_operand, 0))))
+                  || TREE_CODE (right_operand) == CONSTRUCTOR)
+              && !integer_zerop (TYPE_SIZE (right_type)))
        operation_type = left_type;
 
       /* Find the best type to use for copying between aggregate types.  */
index 1eea848..53a4fc0 100644 (file)
@@ -1,3 +1,9 @@
+2008-05-03  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/alignment4.adb: Adjust.
+       * gnat.dg/alignment5.adb: Likewise.
+       * gnat.dg/alignment6.adb: XFAIL.
+
 2008-05-03  Richard Guenther  <rguenther@suse.de>
 
        * gcc.dg/tree-ssa/loop-36.c: Cleanup the dump file.
index ebc1053..c23bcfe 100644 (file)
@@ -11,5 +11,5 @@ begin
   S1 := S2;
 end;
 
--- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
+-- { dg-final { scan-tree-dump-not ".\F" "gimple" } }
 -- { dg-final { cleanup-tree-dump "gimple" } }
index 4cc2d18..8a89f5e 100644 (file)
@@ -27,5 +27,5 @@ begin
    A_REC := B_REC;
 end;
 
--- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
+-- { dg-final { scan-tree-dump-not "\.F" "gimple" } }
 -- { dg-final { cleanup-tree-dump "gimple" } }
index f2889a5..548574f 100644 (file)
@@ -28,5 +28,5 @@ begin
    B_REC := A_REC;
 end;
 
--- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
+-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" { xfail *-*-* } } }
 -- { dg-final { cleanup-tree-dump "gimple" } }