OSDN Git Service

* config/pdp11/pdp11.md (various): Fix conditions on a number of
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index ef9ec59..f366318 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "expr.h"
 #include "output.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "target.h"
@@ -172,6 +173,32 @@ variable_size (tree size)
 /* An array of functions used for self-referential size computation.  */
 static GTY(()) VEC (tree, gc) *size_functions;
 
+/* Look inside EXPR into simple arithmetic operations involving constants.
+   Return the outermost non-arithmetic or non-constant node.  */
+
+static tree
+skip_simple_constant_arithmetic (tree expr)
+{
+  while (true)
+    {
+      if (UNARY_CLASS_P (expr))
+       expr = TREE_OPERAND (expr, 0);
+      else if (BINARY_CLASS_P (expr))
+       {
+         if (TREE_CONSTANT (TREE_OPERAND (expr, 1)))
+           expr = TREE_OPERAND (expr, 0);
+         else if (TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+           expr = TREE_OPERAND (expr, 1);
+         else
+           break;
+       }
+      else
+       break;
+    }
+
+  return expr;
+}
+
 /* Similar to copy_tree_r but do not copy component references involving
    PLACEHOLDER_EXPRs.  These nodes are spotted in find_placeholder_in_expr
    and substituted in substitute_in_expr.  */
@@ -233,13 +260,14 @@ self_referential_size (tree size)
 {
   static unsigned HOST_WIDE_INT fnno = 0;
   VEC (tree, heap) *self_refs = NULL;
-  tree param_type_list = NULL, param_decl_list = NULL, arg_list = NULL;
+  tree param_type_list = NULL, param_decl_list = NULL;
   tree t, ref, return_type, fntype, fnname, fndecl;
   unsigned int i;
   char buf[128];
+  VEC(tree,gc) *args = NULL;
 
   /* Do not factor out simple operations.  */
-  t = skip_simple_arithmetic (size);
+  t = skip_simple_constant_arithmetic (size);
   if (TREE_CODE (t) == CALL_EXPR)
     return size;
 
@@ -255,7 +283,8 @@ self_referential_size (tree size)
 
   /* Build the parameter and argument lists in parallel; also
      substitute the former for the latter in the expression.  */
-  for (i = 0; VEC_iterate (tree, self_refs, i, ref); i++)
+  args = VEC_alloc (tree, gc, VEC_length (tree, self_refs));
+  FOR_EACH_VEC_ELT (tree, self_refs, i, ref)
     {
       tree subst, param_name, param_type, param_decl;
 
@@ -290,7 +319,7 @@ self_referential_size (tree size)
 
       param_type_list = tree_cons (NULL_TREE, param_type, param_type_list);
       param_decl_list = chainon (param_decl, param_decl_list);
-      arg_list = tree_cons (NULL_TREE, ref, arg_list);
+      VEC_quick_push (tree, args, ref);
     }
 
   VEC_free (tree, heap, self_refs);
@@ -301,7 +330,6 @@ self_referential_size (tree size)
   /* The 3 lists have been created in reverse order.  */
   param_type_list = nreverse (param_type_list);
   param_decl_list = nreverse (param_decl_list);
-  arg_list = nreverse (arg_list);
 
   /* Build the function type.  */
   return_type = TREE_TYPE (size);
@@ -311,7 +339,7 @@ self_referential_size (tree size)
   sprintf (buf, "SZ"HOST_WIDE_INT_PRINT_UNSIGNED, fnno++);
   fnname = get_file_function_name (buf);
   fndecl = build_decl (input_location, FUNCTION_DECL, fnname, fntype);
-  for (t = param_decl_list; t; t = TREE_CHAIN (t))
+  for (t = param_decl_list; t; t = DECL_CHAIN (t))
     DECL_CONTEXT (t) = fndecl;
   DECL_ARGUMENTS (fndecl) = param_decl_list;
   DECL_RESULT (fndecl)
@@ -342,7 +370,7 @@ self_referential_size (tree size)
   VEC_safe_push (tree, gc, size_functions, fndecl);
 
   /* Replace the original expression with a call to the size function.  */
-  return build_function_call_expr (input_location, fndecl, arg_list);
+  return build_call_expr_loc_vec (input_location, fndecl, args);
 }
 
 /* Take, queue and compile all the size functions.  It is essential that
@@ -468,6 +496,50 @@ int_mode_for_mode (enum machine_mode mode)
   return mode;
 }
 
+/* Find a mode that is suitable for representing a vector with
+   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
+   is no suitable mode.  */
+
+enum machine_mode
+mode_for_vector (enum machine_mode innermode, unsigned nunits)
+{
+  enum machine_mode mode;
+
+  /* First, look for a supported vector type.  */
+  if (SCALAR_FLOAT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_FLOAT;
+  else if (SCALAR_FRACT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_FRACT;
+  else if (SCALAR_UFRACT_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_UFRACT;
+  else if (SCALAR_ACCUM_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_ACCUM;
+  else if (SCALAR_UACCUM_MODE_P (innermode))
+    mode = MIN_MODE_VECTOR_UACCUM;
+  else
+    mode = MIN_MODE_VECTOR_INT;
+
+  /* Do not check vector_mode_supported_p here.  We'll do that
+     later in vector_type_mode.  */
+  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
+    if (GET_MODE_NUNITS (mode) == nunits
+       && GET_MODE_INNER (mode) == innermode)
+      break;
+
+  /* For integers, try mapping it to a same-sized scalar mode.  */
+  if (mode == VOIDmode
+      && GET_MODE_CLASS (innermode) == MODE_INT)
+    mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
+                         MODE_INT, 0);
+
+  if (mode == VOIDmode
+      || (GET_MODE_CLASS (mode) == MODE_INT
+         && !have_regs_of_mode[mode]))
+    return BLKmode;
+
+  return mode;
+}
+
 /* Return the alignment of MODE. This will be bounded by 1 and
    BIGGEST_ALIGNMENT.  */
 
@@ -673,9 +745,9 @@ layout_decl (tree decl, unsigned int known_align)
          int size_as_int = TREE_INT_CST_LOW (size);
 
          if (compare_tree_int (size, size_as_int) == 0)
-           warning (OPT_Wlarger_than_eq, "size of %q+D is %d bytes", decl, size_as_int);
+           warning (OPT_Wlarger_than_, "size of %q+D is %d bytes", decl, size_as_int);
          else
-           warning (OPT_Wlarger_than_eq, "size of %q+D is larger than %wd bytes",
+           warning (OPT_Wlarger_than_, "size of %q+D is larger than %wd bytes",
                      decl, larger_than_size);
        }
     }
@@ -743,7 +815,7 @@ start_record_layout (tree t)
   rli->offset = size_zero_node;
   rli->bitpos = bitsize_zero_node;
   rli->prev_field = 0;
-  rli->pending_statics = 0;
+  rli->pending_statics = NULL;
   rli->packed_maybe_necessary = 0;
   rli->remaining_in_alignment = 0;
 
@@ -827,10 +899,10 @@ debug_rli (record_layout_info rli)
   if (rli->packed_maybe_necessary)
     fprintf (stderr, "packed may be necessary\n");
 
-  if (rli->pending_statics)
+  if (!VEC_empty (tree, rli->pending_statics))
     {
       fprintf (stderr, "pending statics:\n");
-      debug_tree (rli->pending_statics);
+      debug_vec_tree (rli->pending_statics);
     }
 }
 
@@ -1041,8 +1113,7 @@ place_field (record_layout_info rli, tree field)
      it *after* the record is laid out.  */
   if (TREE_CODE (field) == VAR_DECL)
     {
-      rli->pending_statics = tree_cons (NULL_TREE, field,
-                                       rli->pending_statics);
+      VEC_safe_push (tree, gc, rli->pending_statics, field);
       return;
     }
 
@@ -1428,8 +1499,8 @@ place_field (record_layout_info rli, tree field)
 
       /* If we ended a bitfield before the full length of the type then
         pad the struct out to the full length of the last type.  */
-      if ((TREE_CHAIN (field) == NULL
-          || TREE_CODE (TREE_CHAIN (field)) != FIELD_DECL)
+      if ((DECL_CHAIN (field) == NULL
+          || TREE_CODE (DECL_CHAIN (field)) != FIELD_DECL)
          && DECL_BIT_FIELD_TYPE (field)
          && !integer_zerop (DECL_SIZE (field)))
        rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
@@ -1550,7 +1621,7 @@ compute_record_mode (tree type)
   /* A record which has any BLKmode members must itself be
      BLKmode; it can't go in a register.  Unless the member is
      BLKmode only because it isn't aligned.  */
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+  for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     {
       if (TREE_CODE (field) != FIELD_DECL)
        continue;
@@ -1718,15 +1789,15 @@ finish_record_layout (record_layout_info rli, int free_p)
 
   /* Lay out any static members.  This is done now because their type
      may use the record's type.  */
-  while (rli->pending_statics)
-    {
-      layout_decl (TREE_VALUE (rli->pending_statics), 0);
-      rli->pending_statics = TREE_CHAIN (rli->pending_statics);
-    }
+  while (!VEC_empty (tree, rli->pending_statics))
+    layout_decl (VEC_pop (tree, rli->pending_statics), 0);
 
   /* Clean up.  */
   if (free_p)
-    free (rli);
+    {
+      VEC_free (tree, gc, rli->pending_statics);
+      free (rli);
+    }
 }
 \f
 
@@ -1745,8 +1816,8 @@ finish_builtin_struct (tree type, const char *name, tree fields,
   for (tail = NULL_TREE; fields; tail = fields, fields = next)
     {
       DECL_FIELD_CONTEXT (fields) = type;
-      next = TREE_CHAIN (fields);
-      TREE_CHAIN (fields) = tail;
+      next = DECL_CHAIN (fields);
+      DECL_CHAIN (fields) = tail;
     }
   TYPE_FIELDS (type) = tail;
 
@@ -1847,44 +1918,8 @@ layout_type (tree type)
 
        /* Find an appropriate mode for the vector type.  */
        if (TYPE_MODE (type) == VOIDmode)
-         {
-           enum machine_mode innermode = TYPE_MODE (innertype);
-           enum machine_mode mode;
-
-           /* First, look for a supported vector type.  */
-           if (SCALAR_FLOAT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_FLOAT;
-           else if (SCALAR_FRACT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_FRACT;
-           else if (SCALAR_UFRACT_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_UFRACT;
-           else if (SCALAR_ACCUM_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_ACCUM;
-           else if (SCALAR_UACCUM_MODE_P (innermode))
-             mode = MIN_MODE_VECTOR_UACCUM;
-           else
-             mode = MIN_MODE_VECTOR_INT;
-
-           /* Do not check vector_mode_supported_p here.  We'll do that
-              later in vector_type_mode.  */
-           for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
-             if (GET_MODE_NUNITS (mode) == nunits
-                 && GET_MODE_INNER (mode) == innermode)
-               break;
-
-           /* For integers, try mapping it to a same-sized scalar mode.  */
-           if (mode == VOIDmode
-               && GET_MODE_CLASS (innermode) == MODE_INT)
-             mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
-                                   MODE_INT, 0);
-
-           if (mode == VOIDmode ||
-               (GET_MODE_CLASS (mode) == MODE_INT
-                && !have_regs_of_mode[mode]))
-             SET_TYPE_MODE (type, BLKmode);
-           else
-             SET_TYPE_MODE (type, mode);
-         }
+         SET_TYPE_MODE (type,
+                        mode_for_vector (TYPE_MODE (innertype), nunits));
 
        TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
@@ -2060,7 +2095,7 @@ layout_type (tree type)
          TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
 
        /* Place all the fields.  */
-       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
          place_field (rli, field);
 
        if (TREE_CODE (type) == QUAL_UNION_TYPE)