This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] Init sizetypes based on target defs


This initializes sizetypes correctly from the start, using target
definitions available.  All Frontends initialize sizetypes from
size_type_node for which there is a target macro SIZE_TYPE which
tells what type to use for this (C runtime ABI) type.

Now, there are two frontends who do not honor SIZE_TYPE but
have an idea on its own.  That's Java (probably by accident) and
Ada (of course).  Java does

  /* This is not a java type, however tree-dfa requires a definition for
     size_type_node.  */
  size_type_node = make_unsigned_type (POINTER_SIZE);
  set_sizetype (size_type_node);

so the FE itself doesn't care and POINTER_SIZE for almost all targets
yields the same result as following the SIZE_TYPE advice.  Ada has
its own idea and thinks it can choose size_t freely,

  /* In Ada, we use the unsigned type corresponding to the width of Pmode 
as
     SIZETYPE.  In most cases when ptr_mode and Pmode differ, C will use 
the
     width of ptr_mode for SIZETYPE, but we get better code using the 
width
     of Pmode.  Note that, although we manipulate negative offsets for 
some
     internal constructs and rely on compile time overflow detection in 
size
     computations, using unsigned types for SIZETYPEs is fine since they 
are
     treated specially by the middle-end, in particular sign-extended.  */
  size_type_node = gnat_type_for_mode (Pmode, 1);
  set_sizetype (size_type_node);
  TYPE_NAME (sizetype) = get_identifier ("size_type");

hmm, yes.  Again practically for most targets size_t will be following
its SIZE_TYPE advice, but surely not for all.  OTOH while the above
clearly doesn't look "accidential", it certainly looks wrong.  If
not for sizetype then at least for size_type_node.  The comment hints
that the patch at most will no longer "get better code", but if
Pmode gets better code when used for sizetype(!) then we should do
so unconditionally and could get rid of the size_t reverse-engineering
in initialize_sizetypes completely (m32c might disagree here).

Not yet bootstrapped or tested (but I don't expect any issues other
than eventual typos on the targets I have access to).

Now, any objections?  (Patch to be adjusted to really remove
all set_sizetype calls)

Thanks,
Richard.

2011-05-31  Richard Guenther  <rguenther@suse.de>

	* stor-layout.c (initialize_sizetypes): Initialize all
	sizetypes based on target definitions.
	(set_sizetype): Remove.

Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 174469)
+++ gcc/stor-layout.c	(working copy)
@@ -2189,95 +2189,83 @@ make_accum_type (int precision, int unsi
   return type;
 }
 
-/* Initialize sizetype and bitsizetype to a reasonable and temporary
-   value to enable integer types to be created.  */
+/* Initialize sizetypes so layout_type can use them.  */
 
 void
 initialize_sizetypes (void)
 {
-  tree t = make_node (INTEGER_TYPE);
-  int precision = GET_MODE_BITSIZE (SImode);
+  tree t;
+  int precision;
 
-  SET_TYPE_MODE (t, SImode);
-  TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode);
-  TYPE_IS_SIZETYPE (t) = 1;
+  if (strcmp (SIZE_TYPE, "unsigned int") == 0)
+    precision = INT_TYPE_SIZE;
+  else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
+    precision = LONG_TYPE_SIZE;
+  else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
+    precision = LONG_LONG_TYPE_SIZE;
+  else
+    gcc_unreachable ();
+
+  t = make_node (INTEGER_TYPE);
+  TYPE_NAME (t) = get_identifier ("sizetype");
+  TYPE_PRECISION (t) = precision;
   TYPE_UNSIGNED (t) = 1;
+  TYPE_IS_SIZETYPE (t) = 1;
+  /* Layout sizetype manually.  */
+  SET_TYPE_MODE (t, smallest_mode_for_size (TYPE_PRECISION (t), MODE_INT));
+  TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (TYPE_MODE (t));
   TYPE_SIZE (t) = build_int_cst (t, precision);
-  TYPE_SIZE_UNIT (t) = build_int_cst (t, GET_MODE_SIZE (SImode));
-  TYPE_PRECISION (t) = precision;
-
+  TYPE_SIZE_UNIT (t) = build_int_cst (t, GET_MODE_SIZE (TYPE_MODE (t)));
   set_min_and_max_values_for_integral_type (t, precision,
 					    /*is_unsigned=*/true);
-
+  /* sizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
+     sign-extended in a way consistent with force_fit_type.  */
+  TYPE_MAX_VALUE (t)
+    = double_int_to_tree (t, tree_to_double_int (TYPE_MAX_VALUE (t)));
   sizetype = t;
-  bitsizetype = build_distinct_type_copy (t);
-}
 
-/* Make sizetype a version of TYPE, and initialize *sizetype accordingly.
-   We do this by overwriting the stub sizetype and bitsizetype nodes created
-   by initialize_sizetypes.  This makes sure that (a) anything stubby about
-   them no longer exists and (b) any INTEGER_CSTs created with such a type,
-   remain valid.  */
 
-void
-set_sizetype (tree type)
-{
-  tree t, max;
-  int oprecision = TYPE_PRECISION (type);
-  /* The *bitsizetype types use a precision that avoids overflows when
-     calculating signed sizes / offsets in bits.  However, when
-     cross-compiling from a 32 bit to a 64 bit host, we are limited to 64 bit
-     precision.  */
-  int precision
-    = MIN (oprecision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+  precision
+    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
   precision
     = GET_MODE_PRECISION (smallest_mode_for_size (precision, MODE_INT));
   if (precision > HOST_BITS_PER_WIDE_INT * 2)
     precision = HOST_BITS_PER_WIDE_INT * 2;
 
-  /* sizetype must be an unsigned type.  */
-  gcc_assert (TYPE_UNSIGNED (type));
-
-  t = build_distinct_type_copy (type);
-  /* We want to use sizetype's cache, as we will be replacing that type.  */
-  TYPE_CACHED_VALUES (t) = TYPE_CACHED_VALUES (sizetype);
-  TYPE_CACHED_VALUES_P (t) = TYPE_CACHED_VALUES_P (sizetype);
-  TYPE_UID (t) = TYPE_UID (sizetype);
-  TYPE_IS_SIZETYPE (t) = 1;
-
-  /* Replace our original stub sizetype.  */
-  memcpy (sizetype, t, tree_size (sizetype));
-  TYPE_MAIN_VARIANT (sizetype) = sizetype;
-  TYPE_CANONICAL (sizetype) = sizetype;
-
-  /* sizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
-     sign-extended in a way consistent with force_fit_type.  */
-  max = TYPE_MAX_VALUE (sizetype);
-  TYPE_MAX_VALUE (sizetype)
-    = double_int_to_tree (sizetype, tree_to_double_int (max));
-
   t = make_node (INTEGER_TYPE);
-  TYPE_NAME (t) = get_identifier ("bit_size_type");
-  /* We want to use bitsizetype's cache, as we will be replacing that type.  */
-  TYPE_CACHED_VALUES (t) = TYPE_CACHED_VALUES (bitsizetype);
-  TYPE_CACHED_VALUES_P (t) = TYPE_CACHED_VALUES_P (bitsizetype);
+  TYPE_NAME (t) = get_identifier ("bitsizetype");
   TYPE_PRECISION (t) = precision;
-  TYPE_UID (t) = TYPE_UID (bitsizetype);
+  TYPE_UNSIGNED (t) = 1;
   TYPE_IS_SIZETYPE (t) = 1;
+  /* Layout bitsizetype manually.  */
+  SET_TYPE_MODE (t, smallest_mode_for_size (TYPE_PRECISION (t), MODE_INT));
+  TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (TYPE_MODE (t));
+  TYPE_SIZE (t) = build_int_cst (t, precision);
+  TYPE_SIZE_UNIT (t) = build_int_cst (t, GET_MODE_SIZE (TYPE_MODE (t)));
+  set_min_and_max_values_for_integral_type (t, precision,
+					    /*is_unsigned=*/true);
+  /* ???  TYPE_MAX_VALUE is not properly sign-extended.  */
+  bitsizetype = t;
 
-  /* Replace our original stub bitsizetype.  */
-  memcpy (bitsizetype, t, tree_size (bitsizetype));
-  TYPE_MAIN_VARIANT (bitsizetype) = bitsizetype;
-  TYPE_CANONICAL (bitsizetype) = bitsizetype;
-
-  fixup_unsigned_type (bitsizetype);
 
   /* Create the signed variants of *sizetype.  */
-  ssizetype = make_signed_type (oprecision);
+  ssizetype = make_signed_type (TYPE_PRECISION (sizetype));
   TYPE_IS_SIZETYPE (ssizetype) = 1;
-  sbitsizetype = make_signed_type (precision);
+  sbitsizetype = make_signed_type (TYPE_PRECISION (bitsizetype));
   TYPE_IS_SIZETYPE (sbitsizetype) = 1;
 }
+
+/* Make sizetype a version of TYPE, and initialize *sizetype accordingly.
+   We do this by overwriting the stub sizetype and bitsizetype nodes created
+   by initialize_sizetypes.  This makes sure that (a) anything stubby about
+   them no longer exists and (b) any INTEGER_CSTs created with such a type,
+   remain valid.  */
+
+void
+set_sizetype (tree type)
+{
+  gcc_assert (TYPE_PRECISION (sizetype) == TYPE_PRECISION (type));
+}
 
 /* TYPE is an integral type, i.e., an INTEGRAL_TYPE, ENUMERAL_TYPE
    or BOOLEAN_TYPE.  Set TYPE_MIN_VALUE and TYPE_MAX_VALUE


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]