This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][RFC] Init sizetypes based on target defs
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 1 Jun 2011 17:32:47 +0200 (CEST)
- Subject: Re: [PATCH][RFC] Init sizetypes based on target defs
- References: <alpine.LNX.2.00.1105311335430.810@zhemvz.fhfr.qr>
On Tue, 31 May 2011, Richard Guenther wrote:
>
> 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)
And this one, ontop of the previously posted patch to defer things
to the middle-end, passed bootstrap and regtest for all languages
on x86_64-unknown-linux-gnu.
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.orig 2011-06-01 15:41:56.000000000 +0200
--- gcc/stor-layout.c 2011-06-01 16:14:03.000000000 +0200
*************** make_accum_type (int precision, int unsi
*** 2189,2216 ****
return type;
}
! /* Initialize sizetype and bitsizetype to a reasonable and temporary
! value to enable integer types to be created. */
void
initialize_sizetypes (void)
{
! tree t = make_node (INTEGER_TYPE);
! int precision = GET_MODE_BITSIZE (SImode);
! SET_TYPE_MODE (t, SImode);
! TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode);
! TYPE_IS_SIZETYPE (t) = 1;
! TYPE_UNSIGNED (t) = 1;
! TYPE_SIZE (t) = build_int_cst (t, precision);
! TYPE_SIZE_UNIT (t) = build_int_cst (t, GET_MODE_SIZE (SImode));
! TYPE_PRECISION (t) = precision;
! set_min_and_max_values_for_integral_type (t, precision,
/*is_unsigned=*/true);
! sizetype = t;
! bitsizetype = build_distinct_type_copy (t);
}
/* Make sizetype a version of TYPE, and initialize *sizetype accordingly.
--- 2189,2258 ----
return type;
}
! /* Initialize sizetypes so layout_type can use them. */
void
initialize_sizetypes (void)
{
! int precision, bprecision;
! /* Get sizetypes precision from the SIZE_TYPE target macro. */
! 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 ();
!
! bprecision
! = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
! bprecision
! = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
! if (bprecision > HOST_BITS_PER_WIDE_INT * 2)
! bprecision = HOST_BITS_PER_WIDE_INT * 2;
!
! /* Create stubs for sizetype and bitsizetype so we can create constants. */
! sizetype = make_node (INTEGER_TYPE);
! /* ??? We can't set a name for sizetype because it appears in C diagnostics
! and pp_c_type_specifier doesn't deal with IDENTIFIER_NODE TYPE_NAMEs. */
! TYPE_PRECISION (sizetype) = precision;
! TYPE_UNSIGNED (sizetype) = 1;
! TYPE_IS_SIZETYPE (sizetype) = 1;
! bitsizetype = make_node (INTEGER_TYPE);
! TYPE_NAME (bitsizetype) = get_identifier ("bitsizetype");
! TYPE_PRECISION (bitsizetype) = bprecision;
! TYPE_UNSIGNED (bitsizetype) = 1;
! TYPE_IS_SIZETYPE (bitsizetype) = 1;
!
! /* Now layout both types manually. */
! SET_TYPE_MODE (sizetype, smallest_mode_for_size (precision, MODE_INT));
! TYPE_ALIGN (sizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (sizetype));
! TYPE_SIZE (sizetype) = bitsize_int (precision);
! TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
! set_min_and_max_values_for_integral_type (sizetype, 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 (sizetype)
! = double_int_to_tree (sizetype,
! tree_to_double_int (TYPE_MAX_VALUE (sizetype)));
! SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
! TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
! TYPE_SIZE (bitsizetype) = bitsize_int (bprecision);
! TYPE_SIZE_UNIT (bitsizetype)
! = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
! set_min_and_max_values_for_integral_type (bitsizetype, bprecision,
/*is_unsigned=*/true);
+ /* ??? TYPE_MAX_VALUE is not properly sign-extended. */
! /* Create the signed variants of *sizetype. */
! ssizetype = make_signed_type (TYPE_PRECISION (sizetype));
! TYPE_IS_SIZETYPE (ssizetype) = 1;
! sbitsizetype = make_signed_type (TYPE_PRECISION (bitsizetype));
! TYPE_IS_SIZETYPE (sbitsizetype) = 1;
}
/* Make sizetype a version of TYPE, and initialize *sizetype accordingly.
*************** initialize_sizetypes (void)
*** 2222,2282 ****
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
! = 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_PRECISION (t) = precision;
! TYPE_UID (t) = TYPE_UID (bitsizetype);
! TYPE_IS_SIZETYPE (t) = 1;
!
! /* 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);
! TYPE_IS_SIZETYPE (ssizetype) = 1;
! sbitsizetype = make_signed_type (precision);
! TYPE_IS_SIZETYPE (sbitsizetype) = 1;
}
/* TYPE is an integral type, i.e., an INTEGRAL_TYPE, ENUMERAL_TYPE
--- 2264,2270 ----
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