dbxout.c (dbxout_range_type): Add LOW and HIGH parameters.

* dbxout.c (dbxout_range_type): Add LOW and HIGH parameters.  Use them
	for bounds.
	(print_int_cst_bounds_in_octal_p): Likewise.
	(dbxout_type): Adjust calls to above functions.  Be prepared to deal
	with subtypes.
	* dwarf2out.c (base_type_die): Likewise.
	(is_subrange_type): Delete.
	(subrange_type_die): Add LOW and HIGH parameters.  Use them for bounds.
	(modified_type_die): Call subrange_type_for_debug_p on subtypes.
	* fold-const.c (fold_truth_not_expr) <CONVERT_EXPR>: Do not strip it if
	the destination type is boolean.
	(build_range_check): Do not special-case subtypes.
	(fold_sign_changed_comparison): Likewise.
	(fold_unary): Likewise.
	* langhooks-def.h (LANG_HOOKS_GET_SUBRANGE_BOUNDS): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add LANG_HOOKS_GET_SUBRANGE_BOUNDS.
	* langhooks.h (lang_hooks_for_types): Add get_subrange_bounds.
	* tree.c (subrange_type_for_debug_p): New predicate based on the former
	is_subrange_type.
	* tree.h (subrange_type_for_debug_p): Declare.
	* tree-chrec.c (avoid_arithmetics_in_type_p): Delete.
	(convert_affine_scev): Remove call to above function.
	(chrec_convert_aggressive): Likewise.
	* tree-ssa.c (useless_type_conversion_p_1): Do not specifically return
	false for conversions involving subtypes.
	* tree-vrp.c (vrp_val_max): Do not special-case subtypes.
	(vrp_val_min): Likewise.
	(needs_overflow_infinity): Likewise.
	(extract_range_from_unary_expr): Likewise.
ada/
	* gcc-interface/ada-tree.h (TYPE_GCC_MIN_VALUE, TYPE_GCC_MAX_VALUE):
	New macros.
	(TYPE_RM_VALUES): Likewise.
	(TYPE_RM_SIZE): Rewrite in terms of TYPE_RM_VALUES.
	(SET_TYPE_RM_SIZE): New macro.
	(TYPE_RM_MIN_VALUE, TYPE_RM_MAX_VALUE): Likewise.
	(SET_TYPE_RM_SIZE, SET_TYPE_RM_MAX_VALUE): Likewise.
	(TYPE_MIN_VALUE, TYPE_MAX_VALUE): Redefine.
	* gcc-interface/gigi.h (create_range_type): Declare.
	* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Modular_Integer_Type>
	Use SET_TYPE_RM_MAX_VALUE to set the upper bound on the UMT type.
	<E_Signed_Integer_Subtype>: Build a regular integer type first and
	then set the RM bounds.  Use SET_TYPE_RM_SIZE to set the RM size.
	<E_Floating_Point_Subtype>: Build a regular floating-point type first
	and then set the RM bounds.
	<E_Array_Type>: Use create_range_type instead of build_range_type.
	<E_Array_Subtype>: Build a regular integer type first and then set
	the RM bounds for the extra subtype.
	<E_String_Literal_Subtype>: Use create_range_type instead of
	build_range_type.
	<all>: Set the RM bounds for enumeration types and the GCC bounds for
	floating-point types.
	(set_rm_size): Use SET_TYPE_RM_SIZE to set the RM size.
	(make_type_from_size) <INTEGER_TYPE>: Use SET_TYPE_RM_{MIN,MAX}_VALUE
	to set the bounds.  Use SET_TYPE_RM_SIZE to set the RM size.
	(substitute_in_type) <INTEGER_TYPE>: Deal with GCC bounds for domain
	types and with RM bounds for subtypes.
	* gcc-interface/misc.c (LANG_HOOKS_GET_SUBRANGE_BOUNDS): Define.
	(gnat_print_type) <REAL_TYPE>: New case.
	<ENUMERAL_TYPE>: Fall through to above case.
	(gnat_get_subrange_bounds): New function.
	* gcc-interface/trans.c (add_decl_expr): Mark the trees rooted as
	TYPE_RM_MIN_VALUE and TYPE_RM_MAX_VALUE, if any.
	* gcc-interface/utils.c (gnat_init_decl_processing): Use precision 8
	for booleans.  Adjust and use SET_TYPE_RM_SIZE to set the RM size.
	(create_range_type): New function.
	(create_param_decl): Build a regular integer type first and then set
	the RM bounds for the extra subtype.
	(unchecked_convert): Remove kludge for 'Valid.
	* gcc-interface/utils2.c (build_binary_op) <ARRAY_RANGE_REF>: Convert
	the index to sizetype instead of TYPE_DOMAIN.

From-SVN: r147563
This commit is contained in:
Eric Botcazou 2009-05-15 09:11:40 +00:00 committed by Eric Botcazou
parent 331d918689
commit 84fb43a1a4
19 changed files with 499 additions and 360 deletions

View File

@ -1,3 +1,35 @@
2009-05-15 Eric Botcazou <ebotcazou@adacore.com>
* dbxout.c (dbxout_range_type): Add LOW and HIGH parameters. Use them
for bounds.
(print_int_cst_bounds_in_octal_p): Likewise.
(dbxout_type): Adjust calls to above functions. Be prepared to deal
with subtypes.
* dwarf2out.c (base_type_die): Likewise.
(is_subrange_type): Delete.
(subrange_type_die): Add LOW and HIGH parameters. Use them for bounds.
(modified_type_die): Call subrange_type_for_debug_p on subtypes.
* fold-const.c (fold_truth_not_expr) <CONVERT_EXPR>: Do not strip it if
the destination type is boolean.
(build_range_check): Do not special-case subtypes.
(fold_sign_changed_comparison): Likewise.
(fold_unary): Likewise.
* langhooks-def.h (LANG_HOOKS_GET_SUBRANGE_BOUNDS): Define.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add LANG_HOOKS_GET_SUBRANGE_BOUNDS.
* langhooks.h (lang_hooks_for_types): Add get_subrange_bounds.
* tree.c (subrange_type_for_debug_p): New predicate based on the former
is_subrange_type.
* tree.h (subrange_type_for_debug_p): Declare.
* tree-chrec.c (avoid_arithmetics_in_type_p): Delete.
(convert_affine_scev): Remove call to above function.
(chrec_convert_aggressive): Likewise.
* tree-ssa.c (useless_type_conversion_p_1): Do not specifically return
false for conversions involving subtypes.
* tree-vrp.c (vrp_val_max): Do not special-case subtypes.
(vrp_val_min): Likewise.
(needs_overflow_infinity): Likewise.
(extract_range_from_unary_expr): Likewise.
2009-05-15 Paolo Bonzini <bonzini@gnu.org>
* config/frv/frv.h: Clean up references to GO_IF_LEGITIMATE_ADDRESS.

View File

@ -1,3 +1,47 @@
2009-05-15 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (TYPE_GCC_MIN_VALUE, TYPE_GCC_MAX_VALUE):
New macros.
(TYPE_RM_VALUES): Likewise.
(TYPE_RM_SIZE): Rewrite in terms of TYPE_RM_VALUES.
(SET_TYPE_RM_SIZE): New macro.
(TYPE_RM_MIN_VALUE, TYPE_RM_MAX_VALUE): Likewise.
(SET_TYPE_RM_SIZE, SET_TYPE_RM_MAX_VALUE): Likewise.
(TYPE_MIN_VALUE, TYPE_MAX_VALUE): Redefine.
* gcc-interface/gigi.h (create_range_type): Declare.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Modular_Integer_Type>
Use SET_TYPE_RM_MAX_VALUE to set the upper bound on the UMT type.
<E_Signed_Integer_Subtype>: Build a regular integer type first and
then set the RM bounds. Use SET_TYPE_RM_SIZE to set the RM size.
<E_Floating_Point_Subtype>: Build a regular floating-point type first
and then set the RM bounds.
<E_Array_Type>: Use create_range_type instead of build_range_type.
<E_Array_Subtype>: Build a regular integer type first and then set
the RM bounds for the extra subtype.
<E_String_Literal_Subtype>: Use create_range_type instead of
build_range_type.
<all>: Set the RM bounds for enumeration types and the GCC bounds for
floating-point types.
(set_rm_size): Use SET_TYPE_RM_SIZE to set the RM size.
(make_type_from_size) <INTEGER_TYPE>: Use SET_TYPE_RM_{MIN,MAX}_VALUE
to set the bounds. Use SET_TYPE_RM_SIZE to set the RM size.
(substitute_in_type) <INTEGER_TYPE>: Deal with GCC bounds for domain
types and with RM bounds for subtypes.
* gcc-interface/misc.c (LANG_HOOKS_GET_SUBRANGE_BOUNDS): Define.
(gnat_print_type) <REAL_TYPE>: New case.
<ENUMERAL_TYPE>: Fall through to above case.
(gnat_get_subrange_bounds): New function.
* gcc-interface/trans.c (add_decl_expr): Mark the trees rooted as
TYPE_RM_MIN_VALUE and TYPE_RM_MAX_VALUE, if any.
* gcc-interface/utils.c (gnat_init_decl_processing): Use precision 8
for booleans. Adjust and use SET_TYPE_RM_SIZE to set the RM size.
(create_range_type): New function.
(create_param_decl): Build a regular integer type first and then set
the RM bounds for the extra subtype.
(unchecked_convert): Remove kludge for 'Valid.
* gcc-interface/utils2.c (build_binary_op) <ARRAY_RANGE_REF>: Convert
the index to sizetype instead of TYPE_DOMAIN.
2009-05-14 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (elaborate_expression_1): Remove GNAT_EXPR

View File

@ -167,9 +167,87 @@ struct GTY(()) lang_decl { tree t; };
mechanism refer to the routine gnat_to_gnu_entity. */
#define TYPE_CI_CO_LIST(NODE) TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE))
/* For integral types, this is the RM size of the type. */
/* For numerical types, this is the GCC lower bound of the type. The GCC
type system is based on the invariant that an object X of a given type
cannot hold at run time a value smaller than its lower bound; otherwise
the behavior is undefined. The optimizer takes advantage of this and
considers that the assertion X >= LB is always true. */
#define TYPE_GCC_MIN_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.minval)
/* For numerical types, this is the GCC upper bound of the type. The GCC
type system is based on the invariant that an object X of a given type
cannot hold at run time a value larger than its upper bound; otherwise
the behavior is undefined. The optimizer takes advantage of this and
considers that the assertion X <= UB is always true. */
#define TYPE_GCC_MAX_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.maxval)
/* For numerical types, this holds various RM-defined values. */
#define TYPE_RM_VALUES(NODE) TYPE_LANG_SLOT_1 (NUMERICAL_TYPE_CHECK (NODE))
/* For numerical types, this is the RM size of the type, aka its precision.
There is a discrepancy between what is called precision here (and more
generally throughout gigi) and what is called precision in the GCC type
system: in the former case it's TYPE_RM_SIZE whereas it's TYPE_PRECISION
in the latter case. They are not identical because of the need to support
invalid values.
These values can be outside the range of values allowed by the RM size
but they must nevertheless be valid in the GCC type system, otherwise
the optimizer can pretend that they simply don't exist. Therefore they
must be within the range of values allowed by the precision in the GCC
sense, hence TYPE_PRECISION be set to the Esize, not the RM size. */
#define TYPE_RM_SIZE(NODE) \
TYPE_LANG_SLOT_1 (TREE_CHECK3 (NODE, ENUMERAL_TYPE, BOOLEAN_TYPE, INTEGER_TYPE))
(TYPE_RM_VALUES (NODE) ? TREE_VEC_ELT (TYPE_RM_VALUES (NODE), 0) : NULL_TREE)
#define SET_TYPE_RM_SIZE(NODE, X) \
TREE_VEC_ELT ((TYPE_RM_VALUES (NODE) \
= (TYPE_RM_VALUES (NODE) \
? TYPE_RM_VALUES (NODE) : make_tree_vec (3))), 0) = (X)
/* For numerical types, this is the RM lower bound of the type. There is
again a discrepancy between this lower bound and the GCC lower bound,
again because of the need to support invalid values.
These values can be outside the range of values allowed by the RM lower
bound but they must nevertheless be valid in the GCC type system, otherwise
the optimizer can pretend that they simply don't exist. Therefore they
must be within the range of values allowed by the lower bound in the GCC
sense, hence the GCC lower bound be set to that of the base type. */
#define TYPE_RM_MIN_VALUE(NODE) \
(TYPE_RM_VALUES (NODE) ? TREE_VEC_ELT (TYPE_RM_VALUES (NODE), 1) : NULL_TREE)
#define SET_TYPE_RM_MIN_VALUE(NODE, X) \
TREE_VEC_ELT ((TYPE_RM_VALUES (NODE) \
= (TYPE_RM_VALUES (NODE) \
? TYPE_RM_VALUES (NODE) : make_tree_vec (3))), 1) = (X)
/* For numerical types, this is the RM upper bound of the type. There is
again a discrepancy between this upper bound and the GCC upper bound,
again because of the need to support invalid values.
These values can be outside the range of values allowed by the RM upper
bound but they must nevertheless be valid in the GCC type system, otherwise
the optimizer can pretend that they simply don't exist. Therefore they
must be within the range of values allowed by the upper bound in the GCC
sense, hence the GCC upper bound be set to that of the base type. */
#define TYPE_RM_MAX_VALUE(NODE) \
(TYPE_RM_VALUES (NODE) ? TREE_VEC_ELT (TYPE_RM_VALUES (NODE), 2) : NULL_TREE)
#define SET_TYPE_RM_MAX_VALUE(NODE, X) \
TREE_VEC_ELT ((TYPE_RM_VALUES (NODE) \
= (TYPE_RM_VALUES (NODE) \
? TYPE_RM_VALUES (NODE) : make_tree_vec (3))), 2) = (X)
/* For numerical types, this is the lower bound of the type, i.e. the RM lower
bound for language-defined types and the GCC lower bound for others. */
#undef TYPE_MIN_VALUE
#define TYPE_MIN_VALUE(NODE) \
(TYPE_RM_MIN_VALUE (NODE) \
? TYPE_RM_MIN_VALUE (NODE) : TYPE_GCC_MIN_VALUE (NODE))
/* For numerical types, this is the upper bound of the type, i.e. the RM upper
bound for language-defined types and the GCC upper bound for others. */
#undef TYPE_MAX_VALUE
#define TYPE_MAX_VALUE(NODE) \
(TYPE_RM_MAX_VALUE (NODE) \
? TYPE_RM_MAX_VALUE (NODE) : TYPE_GCC_MAX_VALUE (NODE))
/* In an UNCONSTRAINED_ARRAY_TYPE, points to the record containing both
the template and object.

View File

@ -1503,7 +1503,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
&& !tree_int_cst_equal (gnu_high, TYPE_MAX_VALUE (gnu_type)))
{
tree gnu_subtype = make_unsigned_type (esize);
TYPE_MAX_VALUE (gnu_subtype) = gnu_high;
SET_TYPE_RM_MAX_VALUE (gnu_subtype, gnu_high);
TREE_TYPE (gnu_subtype) = gnu_type;
TYPE_EXTRA_SUBTYPE_P (gnu_subtype) = 1;
TYPE_NAME (gnu_type) = create_concat_name (gnat_entity, "UMT");
@ -1519,7 +1519,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
case E_Decimal_Fixed_Point_Subtype:
/* For integral subtypes, we make a new INTEGER_TYPE. Note that we do
not want to call build_range_type since we would like each subtype
not want to call create_range_type since we would like each subtype
node to be distinct. ??? Historically this was in preparation for
when memory aliasing is implemented, but that's obsolete now given
the call to relate_alias_sets below.
@ -1539,39 +1539,37 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|| !Compile_Time_Known_Value (Type_High_Bound (gnat_entity))))
gnat_to_gnu_entity (Ancestor_Subtype (gnat_entity), gnu_expr, 0);
gnu_type = make_node (INTEGER_TYPE);
TREE_TYPE (gnu_type) = get_unpadded_type (Etype (gnat_entity));
/* Set the precision to the Esize except for bit-packed arrays. */
if (Is_Packed_Array_Type (gnat_entity)
&& Is_Bit_Packed_Array (Original_Array_Type (gnat_entity)))
esize = UI_To_Int (RM_Size (gnat_entity));
/* This should be an unsigned type if the base type is unsigned or
if the lower bound is constant and non-negative or if the type
is biased. */
TYPE_UNSIGNED (gnu_type) = (Is_Unsigned_Type (Etype (gnat_entity))
|| Is_Unsigned_Type (gnat_entity)
|| Has_Biased_Representation (gnat_entity));
if (Is_Unsigned_Type (Etype (gnat_entity))
|| Is_Unsigned_Type (gnat_entity)
|| Has_Biased_Representation (gnat_entity))
gnu_type = make_unsigned_type (esize);
else
gnu_type = make_signed_type (esize);
TREE_TYPE (gnu_type) = get_unpadded_type (Etype (gnat_entity));
/* Set the precision to the Esize except for bit-packed arrays and
subtypes of Standard.Boolean. */
if (Is_Packed_Array_Type (gnat_entity)
&& Is_Bit_Packed_Array (Original_Array_Type (gnat_entity)))
esize = UI_To_Int (RM_Size (gnat_entity));
else if (Is_Boolean_Type (gnat_entity))
esize = 1;
SET_TYPE_RM_MIN_VALUE
(gnu_type,
convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_Low_Bound (gnat_entity),
gnat_entity, get_identifier ("L"),
definition, true,
Needs_Debug_Info (gnat_entity))));
TYPE_PRECISION (gnu_type) = esize;
TYPE_MIN_VALUE (gnu_type)
= convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_Low_Bound (gnat_entity),
gnat_entity, get_identifier ("L"),
definition, true,
Needs_Debug_Info (gnat_entity)));
TYPE_MAX_VALUE (gnu_type)
= convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_High_Bound (gnat_entity),
gnat_entity, get_identifier ("U"),
definition, true,
Needs_Debug_Info (gnat_entity)));
SET_TYPE_RM_MAX_VALUE
(gnu_type,
convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_High_Bound (gnat_entity),
gnat_entity, get_identifier ("U"),
definition, true,
Needs_Debug_Info (gnat_entity))));
/* One of the above calls might have caused us to be elaborated,
so don't blow up if so. */
@ -1584,8 +1582,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_BIASED_REPRESENTATION_P (gnu_type)
= Has_Biased_Representation (gnat_entity);
layout_type (gnu_type);
/* Attach the TYPE_STUB_DECL in case we have a parallel type. */
TYPE_STUB_DECL (gnu_type)
= create_type_stub_decl (gnu_entity_name, gnu_type);
@ -1616,8 +1612,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree gnu_field_type, gnu_field;
/* Set the RM size before wrapping up the type. */
TYPE_RM_SIZE (gnu_type)
= UI_To_gnu (RM_Size (gnat_entity), bitsizetype);
SET_TYPE_RM_SIZE (gnu_type,
UI_To_gnu (RM_Size (gnat_entity), bitsizetype));
TYPE_PACKED_ARRAY_TYPE_P (gnu_type) = 1;
gnu_field_type = gnu_type;
@ -1669,8 +1665,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree gnu_field_type, gnu_field;
/* Set the RM size before wrapping up the type. */
TYPE_RM_SIZE (gnu_type)
= UI_To_gnu (RM_Size (gnat_entity), bitsizetype);
SET_TYPE_RM_SIZE (gnu_type,
UI_To_gnu (RM_Size (gnat_entity), bitsizetype));
gnu_field_type = gnu_type;
gnu_type = make_node (RECORD_TYPE);
@ -1741,20 +1737,27 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (REAL_TYPE);
TREE_TYPE (gnu_type) = get_unpadded_type (Etype (gnat_entity));
TYPE_PRECISION (gnu_type) = fp_size_to_prec (esize);
TYPE_GCC_MIN_VALUE (gnu_type)
= TYPE_GCC_MIN_VALUE (TREE_TYPE (gnu_type));
TYPE_GCC_MAX_VALUE (gnu_type)
= TYPE_GCC_MAX_VALUE (TREE_TYPE (gnu_type));
layout_type (gnu_type);
TYPE_MIN_VALUE (gnu_type)
= convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_Low_Bound (gnat_entity),
gnat_entity, get_identifier ("L"),
definition, true,
Needs_Debug_Info (gnat_entity)));
SET_TYPE_RM_MIN_VALUE
(gnu_type,
convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_Low_Bound (gnat_entity),
gnat_entity, get_identifier ("L"),
definition, true,
Needs_Debug_Info (gnat_entity))));
TYPE_MAX_VALUE (gnu_type)
= convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_High_Bound (gnat_entity),
gnat_entity, get_identifier ("U"),
definition, true,
Needs_Debug_Info (gnat_entity)));
SET_TYPE_RM_MAX_VALUE
(gnu_type,
convert (TREE_TYPE (gnu_type),
elaborate_expression (Type_High_Bound (gnat_entity),
gnat_entity, get_identifier ("U"),
definition, true,
Needs_Debug_Info (gnat_entity))));
/* One of the above calls might have caused us to be elaborated,
so don't blow up if so. */
@ -1764,8 +1767,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
break;
}
layout_type (gnu_type);
/* Inherit our alias set from what we're a subtype of, as for
integer subtypes. */
relate_alias_sets (gnu_type, TREE_TYPE (gnu_type), ALIAS_SET_COPY);
@ -1899,8 +1900,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_index_types[index]
= create_index_type (convert (sizetype, gnu_min),
convert (sizetype, gnu_max),
build_range_type (gnu_ind_subtype,
gnu_min, gnu_max),
create_range_type (gnu_ind_subtype,
gnu_min, gnu_max),
gnat_entity);
/* Update the maximum size of the array, in elements. */
gnu_max_size
@ -2585,19 +2586,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
subtype if necessary. */
if (TYPE_MODULAR_P (gnu_inner_type))
{
tree gnu_subtype = make_node (INTEGER_TYPE);
tree gnu_subtype
= make_unsigned_type (TYPE_PRECISION (gnu_inner_type));
TREE_TYPE (gnu_subtype) = gnu_inner_type;
TYPE_EXTRA_SUBTYPE_P (gnu_subtype) = 1;
TYPE_UNSIGNED (gnu_subtype) = 1;
TYPE_PRECISION (gnu_subtype)
= TYPE_PRECISION (gnu_inner_type);
TYPE_MIN_VALUE (gnu_subtype)
= TYPE_MIN_VALUE (gnu_inner_type);
TYPE_MAX_VALUE (gnu_subtype)
= TYPE_MAX_VALUE (gnu_inner_type);
layout_type (gnu_subtype);
SET_TYPE_RM_MIN_VALUE (gnu_subtype,
TYPE_MIN_VALUE (gnu_inner_type));
SET_TYPE_RM_MAX_VALUE (gnu_subtype,
TYPE_MAX_VALUE (gnu_inner_type));
gnu_inner_type = gnu_subtype;
}
@ -2665,9 +2661,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree gnu_index_type
= create_index_type (convert (sizetype, gnu_lower_bound),
convert (sizetype, gnu_upper_bound),
build_range_type (gnu_string_index_type,
gnu_lower_bound,
gnu_upper_bound),
create_range_type (gnu_string_index_type,
gnu_lower_bound,
gnu_upper_bound),
gnat_entity);
gnu_type
@ -4743,6 +4739,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|| (kind == E_Floating_Point_Type && !Vax_Float (gnat_entity)))
{
tree gnu_scalar_type = gnu_type;
tree gnu_low_bound, gnu_high_bound;
/* If this is a padded type, we need to use the underlying type. */
if (TREE_CODE (gnu_scalar_type) == RECORD_TYPE
@ -4754,19 +4751,27 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
if (!longest_float_type_node && kind == E_Floating_Point_Type)
longest_float_type_node = gnu_scalar_type;
TYPE_MIN_VALUE (gnu_scalar_type)
= gnat_to_gnu (Type_Low_Bound (gnat_entity));
TYPE_MAX_VALUE (gnu_scalar_type)
= gnat_to_gnu (Type_High_Bound (gnat_entity));
gnu_low_bound = gnat_to_gnu (Type_Low_Bound (gnat_entity));
gnu_high_bound = gnat_to_gnu (Type_High_Bound (gnat_entity));
/* For enumeration types, write full debugging information. */
if (kind == E_Enumeration_Type)
{
/* Since this has both a typedef and a tag, avoid outputting
the name twice. */
/* Enumeration types have specific RM bounds. */
SET_TYPE_RM_MIN_VALUE (gnu_scalar_type, gnu_low_bound);
SET_TYPE_RM_MAX_VALUE (gnu_scalar_type, gnu_high_bound);
/* Write full debugging information. Since this has both a
typedef and a tag, avoid outputting the name twice. */
DECL_ARTIFICIAL (gnu_decl) = 1;
rest_of_type_decl_compilation (gnu_decl);
}
else
{
/* Floating-point types don't have specific RM bounds. */
TYPE_GCC_MIN_VALUE (gnu_scalar_type) = gnu_low_bound;
TYPE_GCC_MAX_VALUE (gnu_scalar_type) = gnu_high_bound;
}
}
/* If we deferred processing of incomplete types, re-enable it. If there
@ -7391,7 +7396,7 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity)
&& Is_Discrete_Or_Fixed_Point_Type (gnat_entity))
|| (TREE_CODE (gnu_type) == ENUMERAL_TYPE
|| TREE_CODE (gnu_type) == BOOLEAN_TYPE))
TYPE_RM_SIZE (gnu_type) = size;
SET_TYPE_RM_SIZE (gnu_type, size);
/* ...or the Ada size for record and union types. */
else if ((TREE_CODE (gnu_type) == RECORD_TYPE
@ -7443,10 +7448,12 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
else
new_type = make_signed_type (size);
TREE_TYPE (new_type) = TREE_TYPE (type) ? TREE_TYPE (type) : type;
TYPE_MIN_VALUE (new_type)
= convert (TREE_TYPE (new_type), TYPE_MIN_VALUE (type));
TYPE_MAX_VALUE (new_type)
= convert (TREE_TYPE (new_type), TYPE_MAX_VALUE (type));
SET_TYPE_RM_MIN_VALUE (new_type,
convert (TREE_TYPE (new_type),
TYPE_MIN_VALUE (type)));
SET_TYPE_RM_MAX_VALUE (new_type,
convert (TREE_TYPE (new_type),
TYPE_MAX_VALUE (type)));
/* Propagate the name to avoid creating a fake subrange type. */
if (TYPE_NAME (type))
{
@ -7456,7 +7463,7 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
TYPE_NAME (new_type) = TYPE_NAME (type);
}
TYPE_BIASED_REPRESENTATION_P (new_type) = biased_p;
TYPE_RM_SIZE (new_type) = bitsize_int (size);
SET_TYPE_RM_SIZE (new_type, bitsize_int (size));
return new_type;
case RECORD_TYPE:
@ -7703,18 +7710,20 @@ substitute_in_type (tree t, tree f, tree r)
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
case REAL_TYPE:
if (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (t))
|| CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (t)))
{
tree low = SUBSTITUTE_IN_EXPR (TYPE_MIN_VALUE (t), f, r);
tree high = SUBSTITUTE_IN_EXPR (TYPE_MAX_VALUE (t), f, r);
if (low == TYPE_MIN_VALUE (t) && high == TYPE_MAX_VALUE (t))
/* First the domain types of arrays. */
if (CONTAINS_PLACEHOLDER_P (TYPE_GCC_MIN_VALUE (t))
|| CONTAINS_PLACEHOLDER_P (TYPE_GCC_MAX_VALUE (t)))
{
tree low = SUBSTITUTE_IN_EXPR (TYPE_GCC_MIN_VALUE (t), f, r);
tree high = SUBSTITUTE_IN_EXPR (TYPE_GCC_MAX_VALUE (t), f, r);
if (low == TYPE_GCC_MIN_VALUE (t) && high == TYPE_GCC_MAX_VALUE (t))
return t;
new = copy_type (t);
TYPE_MIN_VALUE (new) = low;
TYPE_MAX_VALUE (new) = high;
TYPE_GCC_MIN_VALUE (new) = low;
TYPE_GCC_MAX_VALUE (new) = high;
if (TREE_CODE (t) == INTEGER_TYPE && TYPE_INDEX_TYPE (t))
SET_TYPE_INDEX_TYPE
@ -7723,6 +7732,23 @@ substitute_in_type (tree t, tree f, tree r)
return new;
}
/* Then the subtypes. */
if (CONTAINS_PLACEHOLDER_P (TYPE_RM_MIN_VALUE (t))
|| CONTAINS_PLACEHOLDER_P (TYPE_RM_MAX_VALUE (t)))
{
tree low = SUBSTITUTE_IN_EXPR (TYPE_RM_MIN_VALUE (t), f, r);
tree high = SUBSTITUTE_IN_EXPR (TYPE_RM_MAX_VALUE (t), f, r);
if (low == TYPE_RM_MIN_VALUE (t) && high == TYPE_RM_MAX_VALUE (t))
return t;
new = copy_type (t);
SET_TYPE_RM_MIN_VALUE (new, low);
SET_TYPE_RM_MAX_VALUE (new, high);
return new;
}
return t;
case COMPLEX_TYPE:

View File

@ -558,6 +558,10 @@ extern tree copy_type (tree type);
extern tree create_index_type (tree min, tree max, tree index,
Node_Id gnat_node);
/* Return a subtype of TYPE with range MIN to MAX. If TYPE is NULL,
sizetype is used. */
extern tree create_range_type (tree type, tree min, tree max);
/* Return a TYPE_DECL node suitable for the TYPE_STUB_DECL field of a type.
TYPE_NAME gives the name of the type and TYPE is a ..._TYPE node giving
its data type. */

View File

@ -78,6 +78,7 @@ static int gnat_eh_type_covers (tree, tree);
static void gnat_parse_file (int);
static void internal_error_function (const char *, va_list *);
static tree gnat_type_max_size (const_tree);
static void gnat_get_subrange_bounds (const_tree, tree *, tree *);
/* Definitions for our language-specific hooks. */
@ -125,6 +126,8 @@ static tree gnat_type_max_size (const_tree);
#define LANG_HOOKS_TYPE_FOR_SIZE gnat_type_for_size
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
#define LANG_HOOKS_TYPES_COMPATIBLE_P gnat_types_compatible_p
#undef LANG_HOOKS_GET_SUBRANGE_BOUNDS
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS gnat_get_subrange_bounds
#undef LANG_HOOKS_ATTRIBUTE_TABLE
#define LANG_HOOKS_ATTRIBUTE_TABLE gnat_internal_attribute_table
#undef LANG_HOOKS_BUILTIN_FUNCTION
@ -513,6 +516,12 @@ gnat_print_type (FILE *file, tree node, int indent)
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
print_node_brief (file, "RM size", TYPE_RM_SIZE (node), indent + 4);
/* ... fall through ... */
case REAL_TYPE:
print_node_brief (file, "RM min", TYPE_RM_MIN_VALUE (node), indent + 4);
print_node_brief (file, "RM max", TYPE_RM_MAX_VALUE (node), indent + 4);
break;
case ARRAY_TYPE:
@ -644,6 +653,18 @@ gnat_type_max_size (const_tree gnu_type)
return max_unitsize;
}
/* GNU_TYPE is a subtype of an integral type. Set LOWVAL to the low bound
and HIGHVAL to the high bound, respectively. */
static void
gnat_get_subrange_bounds (const_tree gnu_type, tree *lowval, tree *highval)
{
tree min = TYPE_MIN_VALUE (gnu_type);
tree max = TYPE_MAX_VALUE (gnu_type);
*lowval = TREE_CONSTANT (min) ? min : TYPE_GCC_MIN_VALUE (gnu_type);
*highval = TREE_CONSTANT (max) ? max : TYPE_GCC_MAX_VALUE (gnu_type);
}
/* GNU_TYPE is a type. Determine if it should be passed by reference by
default. */

View File

@ -5562,6 +5562,7 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
Note that walk_tree knows how to deal with TYPE_DECL, but neither
VAR_DECL nor CONST_DECL. This appears to be somewhat arbitrary. */
mark_visited (&gnu_stmt);
if (TREE_CODE (gnu_decl) == VAR_DECL
|| TREE_CODE (gnu_decl) == CONST_DECL)
{
@ -5569,13 +5570,31 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
mark_visited (&DECL_SIZE_UNIT (gnu_decl));
mark_visited (&DECL_INITIAL (gnu_decl));
}
/* In any case, we have to deal with our own TYPE_ADA_SIZE field. */
if (TREE_CODE (gnu_decl) == TYPE_DECL
&& (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
&& (t = TYPE_ADA_SIZE (type)))
mark_visited (&t);
/* In any case, we have to deal with our own fields. */
else if (TREE_CODE (gnu_decl) == TYPE_DECL)
switch (TREE_CODE (type))
{
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
if ((t = TYPE_ADA_SIZE (type)))
mark_visited (&t);
break;
case INTEGER_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
case REAL_TYPE:
if ((t = TYPE_RM_MIN_VALUE (type)))
mark_visited (&t);
if ((t = TYPE_RM_MAX_VALUE (type)))
mark_visited (&t);
break;
default:
break;
}
}
else
add_stmt_with_node (gnu_stmt, gnat_entity);

View File

@ -530,12 +530,14 @@ gnat_init_decl_processing (void)
set_sizetype (size_type_node);
/* In Ada, we use an unsigned 8-bit type for the default boolean type. */
boolean_type_node = make_node (BOOLEAN_TYPE);
TYPE_PRECISION (boolean_type_node) = 1;
fixup_unsigned_type (boolean_type_node);
TYPE_RM_SIZE (boolean_type_node) = bitsize_int (1);
boolean_type_node = make_unsigned_type (8);
TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
SET_TYPE_RM_MAX_VALUE (boolean_type_node,
build_int_cst (boolean_type_node, 1));
SET_TYPE_RM_SIZE (boolean_type_node, bitsize_int (1));
build_common_tree_nodes_2 (0);
boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
ptr_void_type_node = build_pointer_type (void_type_node);
}
@ -1195,6 +1197,42 @@ create_index_type (tree min, tree max, tree index, Node_Id gnat_node)
return type;
}
/* Return a subtype of TYPE with range MIN to MAX. If TYPE is NULL,
sizetype is used. */
tree
create_range_type (tree type, tree min, tree max)
{
tree range_type;
if (type == NULL_TREE)
type = sizetype;
/* First build a type with the base range. */
range_type
= build_range_type (type, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type));
min = convert (type, min);
max = convert (type, max);
/* If this type has the TYPE_RM_{MIN,MAX}_VALUE we want, return it. */
if (TYPE_RM_MIN_VALUE (range_type)
&& TYPE_RM_MAX_VALUE (range_type)
&& operand_equal_p (TYPE_RM_MIN_VALUE (range_type), min, 0)
&& operand_equal_p (TYPE_RM_MAX_VALUE (range_type), max, 0))
return range_type;
/* Otherwise, if TYPE_RM_{MIN,MAX}_VALUE is set, make a copy. */
if (TYPE_RM_MIN_VALUE (range_type) || TYPE_RM_MAX_VALUE (range_type))
range_type = copy_type (range_type);
/* Then set the actual range. */
SET_TYPE_RM_MIN_VALUE (range_type, min);
SET_TYPE_RM_MAX_VALUE (range_type, max);
return range_type;
}
/* Return a TYPE_DECL node suitable for the TYPE_STUB_DECL field of a type.
TYPE_NAME gives the name of the type and TYPE is a ..._TYPE node giving
@ -1581,16 +1619,12 @@ create_param_decl (tree param_name, tree param_type, bool readonly)
if (TREE_CODE (param_type) == INTEGER_TYPE
&& TYPE_BIASED_REPRESENTATION_P (param_type))
{
tree subtype = make_node (INTEGER_TYPE);
tree subtype
= make_unsigned_type (TYPE_PRECISION (integer_type_node));
TREE_TYPE (subtype) = integer_type_node;
TYPE_BIASED_REPRESENTATION_P (subtype) = 1;
TYPE_UNSIGNED (subtype) = 1;
TYPE_PRECISION (subtype) = TYPE_PRECISION (integer_type_node);
TYPE_MIN_VALUE (subtype) = TYPE_MIN_VALUE (param_type);
TYPE_MAX_VALUE (subtype) = TYPE_MAX_VALUE (param_type);
layout_type (subtype);
SET_TYPE_RM_MIN_VALUE (subtype, TYPE_MIN_VALUE (param_type));
SET_TYPE_RM_MAX_VALUE (subtype, TYPE_MAX_VALUE (param_type));
param_type = subtype;
}
else
@ -4288,8 +4322,7 @@ maybe_unconstrained_array (tree exp)
}
/* Return true if EXPR is an expression that can be folded as an operand
of a VIEW_CONVERT_EXPR. See the head comment of unchecked_convert for
the rationale. */
of a VIEW_CONVERT_EXPR. See ada-tree.h for a complete rationale. */
static bool
can_fold_for_view_convert_p (tree expr)
@ -4337,22 +4370,7 @@ can_fold_for_view_convert_p (tree expr)
we expect the 8 bits at Vbits'Address to always contain Value, while
their original location depends on the endianness, at Value'Address
on a little-endian architecture but not on a big-endian one.
??? There is a problematic discrepancy between what is called precision
here (and more generally throughout gigi) for integral types and what is
called precision in the middle-end. In the former case it's the RM size
as given by TYPE_RM_SIZE (or rm_size) whereas it's TYPE_PRECISION in the
latter case, the hitch being that they are not equal when they matter,
that is when the number of value bits is not equal to the type's size:
TYPE_RM_SIZE does give the number of value bits but TYPE_PRECISION is set
to the size. The sole exception are BOOLEAN_TYPEs for which both are 1.
The consequence is that gigi must duplicate code bridging the gap between
the type's size and its precision that exists for TYPE_PRECISION in the
middle-end, because the latter knows nothing about TYPE_RM_SIZE, and be
wary of transformations applied in the middle-end based on TYPE_PRECISION
because this value doesn't reflect the actual precision for Ada. */
on a little-endian architecture but not on a big-endian one. */
tree
unchecked_convert (tree type, tree expr, bool notrunc_p)
@ -4397,43 +4415,6 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
expr = convert (rtype, expr);
expr = build1 (NOP_EXPR, type, expr);
}
/* We have another special case: if we are unchecked converting either
a subtype or a type with limited range into a base type, we need to
ensure that VRP doesn't propagate range information because this
conversion may be done precisely to validate that the object is
within the range it is supposed to have. */
else if (TREE_CODE (expr) != INTEGER_CST
&& TREE_CODE (type) == INTEGER_TYPE && !TREE_TYPE (type)
&& ((TREE_CODE (etype) == INTEGER_TYPE && TREE_TYPE (etype))
|| TREE_CODE (etype) == ENUMERAL_TYPE
|| TREE_CODE (etype) == BOOLEAN_TYPE))
{
/* The optimization barrier is a VIEW_CONVERT_EXPR node; moreover,
in order not to be deemed an useless type conversion, it must
be from subtype to base type.
Therefore we first do the bulk of the conversion to a subtype of
the final type. And this conversion must itself not be deemed
useless if the source type is not a subtype because, otherwise,
the final VIEW_CONVERT_EXPR will be deemed so as well. That's
why we toggle the unsigned flag in this conversion, which is
harmless since the final conversion is only a reinterpretation
of the bit pattern.
??? This may raise addressability and/or aliasing issues because
VIEW_CONVERT_EXPR gets gimplified as an lvalue, thus causing the
address of its operand to be taken if it is deemed addressable
and not already in GIMPLE form. */
tree rtype
= gnat_type_for_mode (TYPE_MODE (type), !TYPE_UNSIGNED (etype));
rtype = copy_type (rtype);
TYPE_MAIN_VARIANT (rtype) = rtype;
TREE_TYPE (rtype) = type;
expr = convert (rtype, expr);
expr = build1 (VIEW_CONVERT_EXPR, type, expr);
}
else
expr = convert (type, expr);
}

View File

@ -802,11 +802,10 @@ build_binary_op (enum tree_code op_code, tree result_type,
left_type = TREE_TYPE (left_operand);
}
/* Then convert the right operand to its base type. This will
prevent unneeded signedness conversions when sizetype is wider than
integer. */
/* Then convert the right operand to its base type. This will prevent
unneeded sign conversions when sizetype is wider than integer. */
right_operand = convert (right_base_type, right_operand);
right_operand = convert (TYPE_DOMAIN (left_type), right_operand);
right_operand = convert (sizetype, right_operand);
if (!TREE_CONSTANT (right_operand)
|| !TREE_CONSTANT (TYPE_MIN_VALUE (right_type)))

View File

@ -318,9 +318,9 @@ static void dbxout_args (tree);
static void dbxout_type_fields (tree);
static void dbxout_type_method_1 (tree);
static void dbxout_type_methods (tree);
static void dbxout_range_type (tree);
static void dbxout_range_type (tree, tree, tree);
static void dbxout_type (tree, int);
static bool print_int_cst_bounds_in_octal_p (tree);
static bool print_int_cst_bounds_in_octal_p (tree, tree, tree);
static bool is_fortran (void);
static void dbxout_type_name (tree);
static void dbxout_class_name_qualifiers (tree);
@ -1593,10 +1593,10 @@ dbxout_type_methods (tree type)
/* Emit a "range" type specification, which has the form:
"r<index type>;<lower bound>;<upper bound>;".
TYPE is an INTEGER_TYPE. */
TYPE is an INTEGER_TYPE, LOW and HIGH are the bounds. */
static void
dbxout_range_type (tree type)
dbxout_range_type (tree type, tree low, tree high)
{
stabstr_C ('r');
if (TREE_TYPE (type))
@ -1624,25 +1624,23 @@ dbxout_range_type (tree type)
}
stabstr_C (';');
if (TYPE_MIN_VALUE (type) != 0
&& host_integerp (TYPE_MIN_VALUE (type), 0))
if (low && host_integerp (low, 0))
{
if (print_int_cst_bounds_in_octal_p (type))
stabstr_O (TYPE_MIN_VALUE (type));
if (print_int_cst_bounds_in_octal_p (type, low, high))
stabstr_O (low);
else
stabstr_D (tree_low_cst (TYPE_MIN_VALUE (type), 0));
stabstr_D (tree_low_cst (low, 0));
}
else
stabstr_C ('0');
stabstr_C (';');
if (TYPE_MAX_VALUE (type) != 0
&& host_integerp (TYPE_MAX_VALUE (type), 0))
if (high && host_integerp (high, 0))
{
if (print_int_cst_bounds_in_octal_p (type))
stabstr_O (TYPE_MAX_VALUE (type));
if (print_int_cst_bounds_in_octal_p (type, low, high))
stabstr_O (high);
else
stabstr_D (tree_low_cst (TYPE_MAX_VALUE (type), 0));
stabstr_D (tree_low_cst (high, 0));
stabstr_C (';');
}
else
@ -1663,10 +1661,9 @@ dbxout_range_type (tree type)
static void
dbxout_type (tree type, int full)
{
tree tem;
tree main_variant;
static int anonymous_type_number = 0;
bool vector_type = false;
tree tem, main_variant, low, high;
if (TREE_CODE (type) == VECTOR_TYPE)
{
@ -1676,6 +1673,27 @@ dbxout_type (tree type, int full)
vector_type = true;
}
if (TREE_CODE (type) == INTEGER_TYPE)
{
if (TREE_TYPE (type) == 0)
{
low = TYPE_MIN_VALUE (type);
high = TYPE_MAX_VALUE (type);
}
else if (subrange_type_for_debug_p (type, &low, &high))
;
/* If this is a subtype that should not be emitted as a subrange type,
use the base type. */
else
{
type = TREE_TYPE (type);
low = TYPE_MIN_VALUE (type);
high = TYPE_MAX_VALUE (type);
}
}
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
by assuming `int'. */
@ -1877,7 +1895,7 @@ dbxout_type (tree type, int full)
stabstr_C (';');
}
dbxout_range_type (type);
dbxout_range_type (type, low, high);
}
else
@ -1893,7 +1911,7 @@ dbxout_type (tree type, int full)
stabstr_C (';');
}
if (print_int_cst_bounds_in_octal_p (type))
if (print_int_cst_bounds_in_octal_p (type, low, high))
{
stabstr_C ('r');
@ -1908,15 +1926,15 @@ dbxout_type (tree type, int full)
dbxout_type_index (type);
stabstr_C (';');
stabstr_O (TYPE_MIN_VALUE (type));
stabstr_O (low);
stabstr_C (';');
stabstr_O (TYPE_MAX_VALUE (type));
stabstr_O (high);
stabstr_C (';');
}
else
/* Output other integer types as subranges of `int'. */
dbxout_range_type (type);
dbxout_range_type (type, low, high);
}
break;
@ -2010,7 +2028,7 @@ dbxout_type (tree type, int full)
else
{
stabstr_C ('a');
dbxout_range_type (tem);
dbxout_range_type (tem, TYPE_MIN_VALUE (tem), TYPE_MAX_VALUE (tem));
}
dbxout_type (TREE_TYPE (type), 0);
@ -2258,7 +2276,7 @@ dbxout_type (tree type, int full)
should be printed in octal format. */
static bool
print_int_cst_bounds_in_octal_p (tree type)
print_int_cst_bounds_in_octal_p (tree type, tree low, tree high)
{
/* If we can use GDB extensions and the size is wider than a long
(the size used by GDB to read them) or we may have trouble writing
@ -2272,10 +2290,8 @@ print_int_cst_bounds_in_octal_p (tree type)
can't span same size unsigned types. */
if (use_gnu_debug_info_extensions
&& TYPE_MIN_VALUE (type) != 0
&& TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& TYPE_MAX_VALUE (type) != 0
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
&& low && TREE_CODE (low) == INTEGER_CST
&& high && TREE_CODE (high) == INTEGER_CST
&& (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
|| ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
&& TYPE_UNSIGNED (type))

View File

@ -5095,8 +5095,7 @@ static void output_line_info (void);
static void output_file_names (void);
static dw_die_ref base_type_die (tree);
static int is_base_type (tree);
static bool is_subrange_type (const_tree);
static dw_die_ref subrange_type_die (tree, dw_die_ref);
static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
static int type_is_enum (const_tree);
static unsigned int dbx_reg_number (const_rtx);
@ -9273,6 +9272,11 @@ base_type_die (tree type)
if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE)
return 0;
/* If this is a subtype that should not be emitted as a subrange type,
use the base type. See subrange_type_for_debug_p. */
if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE)
type = TREE_TYPE (type);
switch (TREE_CODE (type))
{
case INTEGER_TYPE:
@ -9392,67 +9396,11 @@ simple_type_size_in_bits (const_tree type)
return TYPE_ALIGN (type);
}
/* Return true if the debug information for the given type should be
emitted as a subrange type. */
static inline bool
is_subrange_type (const_tree type)
{
tree subtype = TREE_TYPE (type);
/* Subrange types are identified by the fact that they are integer
types, and that they have a subtype which is either an integer type
or an enumeral type. */
if (TREE_CODE (type) != INTEGER_TYPE
|| subtype == NULL_TREE)
return false;
if (TREE_CODE (subtype) != INTEGER_TYPE
&& TREE_CODE (subtype) != ENUMERAL_TYPE
&& TREE_CODE (subtype) != BOOLEAN_TYPE)
return false;
if (TREE_CODE (type) == TREE_CODE (subtype)
&& int_size_in_bytes (type) == int_size_in_bytes (subtype)
&& TYPE_MIN_VALUE (type) != NULL
&& TYPE_MIN_VALUE (subtype) != NULL
&& tree_int_cst_equal (TYPE_MIN_VALUE (type), TYPE_MIN_VALUE (subtype))
&& TYPE_MAX_VALUE (type) != NULL
&& TYPE_MAX_VALUE (subtype) != NULL
&& tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
{
/* The type and its subtype have the same representation. If in
addition the two types also have the same name, then the given
type is not a subrange type, but rather a plain base type. */
/* FIXME: brobecker/2004-03-22:
Sizetype INTEGER_CSTs nodes are canonicalized. It should
therefore be sufficient to check the TYPE_SIZE node pointers
rather than checking the actual size. Unfortunately, we have
found some cases, such as in the Ada "integer" type, where
this is not the case. Until this problem is solved, we need to
keep checking the actual size. */
tree type_name = TYPE_NAME (type);
tree subtype_name = TYPE_NAME (subtype);
if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
type_name = DECL_NAME (type_name);
if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
subtype_name = DECL_NAME (subtype_name);
if (type_name == subtype_name)
return false;
}
return true;
}
/* Given a pointer to a tree node for a subrange type, return a pointer
to a DIE that describes the given type. */
static dw_die_ref
subrange_type_die (tree type, dw_die_ref context_die)
subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
{
dw_die_ref subrange_die;
const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
@ -9469,12 +9417,10 @@ subrange_type_die (tree type, dw_die_ref context_die)
add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
}
if (TYPE_MIN_VALUE (type) != NULL)
add_bound_info (subrange_die, DW_AT_lower_bound,
TYPE_MIN_VALUE (type));
if (TYPE_MAX_VALUE (type) != NULL)
add_bound_info (subrange_die, DW_AT_upper_bound,
TYPE_MAX_VALUE (type));
if (low)
add_bound_info (subrange_die, DW_AT_lower_bound, low);
if (high)
add_bound_info (subrange_die, DW_AT_upper_bound, high);
return subrange_die;
}
@ -9491,7 +9437,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
dw_die_ref sub_die = NULL;
tree item_type = NULL;
tree qualified_type;
tree name;
tree name, low, high;
if (code == ERROR_MARK)
return NULL;
@ -9561,9 +9507,11 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
simple_type_size_in_bits (type) / BITS_PER_UNIT);
item_type = TREE_TYPE (type);
}
else if (is_subrange_type (type))
else if (code == INTEGER_TYPE
&& TREE_TYPE (type) != NULL_TREE
&& subrange_type_for_debug_p (type, &low, &high))
{
mod_type_die = subrange_type_die (type, context_die);
mod_type_die = subrange_type_die (type, low, high, context_die);
item_type = TREE_TYPE (type);
}
else if (is_base_type (type))

View File

@ -3741,7 +3741,7 @@ fold_truth_not_expr (tree arg)
case NON_LVALUE_EXPR:
return invert_truthvalue (TREE_OPERAND (arg, 0));
case NOP_EXPR:
CASE_CONVERT:
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
{
t = build1 (TRUTH_NOT_EXPR, type, arg);
@ -3750,7 +3750,6 @@ fold_truth_not_expr (tree arg)
/* ... fall through ... */
case CONVERT_EXPR:
case FLOAT_EXPR:
t = build1 (TREE_CODE (arg), type,
invert_truthvalue (TREE_OPERAND (arg, 0)));
@ -4694,7 +4693,6 @@ static tree
build_range_check (tree type, tree exp, int in_p, tree low, tree high)
{
tree etype = TREE_TYPE (exp), value;
enum tree_code code;
#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization for function pointer expressions
@ -4777,35 +4775,14 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
}
/* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
This requires wrap-around arithmetics for the type of the expression. */
code = TREE_CODE (etype);
switch (code)
{
case INTEGER_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
/* There is no requirement that LOW be within the range of ETYPE
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */
if (code == INTEGER_TYPE && TREE_TYPE (etype))
{
etype = TREE_TYPE (etype);
/* But not in an enumeral or boolean type though. */
code = TREE_CODE (etype);
}
This requires wrap-around arithmetics for the type of the expression.
First make sure that arithmetics in this type is valid, then make sure
that it wraps around. */
if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
TYPE_UNSIGNED (etype));
if (code != INTEGER_TYPE)
etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
TYPE_UNSIGNED (etype));
break;
default:
break;
}
/* If we don't have wrap-around arithmetics upfront, try to force it. */
if (TREE_CODE (etype) == INTEGER_TYPE
&& !TYPE_OVERFLOW_WRAPS (etype))
if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
{
tree utype, minv, maxv;
@ -7229,11 +7206,6 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
return NULL_TREE;
/* If the conversion is from an integral subtype to its basetype
leave it alone. */
if (TREE_TYPE (inner_type) == outer_type)
return NULL_TREE;
if (TREE_CODE (arg1) != INTEGER_CST
&& !(CONVERT_EXPR_P (arg1)
&& TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
@ -8291,9 +8263,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
transformation effectively doesn't preserve non-maximal ranges. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (op0) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST
/* Not if the conversion is to the sub-type. */
&& TREE_TYPE (type) != TREE_TYPE (op0))
&& TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
{
tree and = op0;
tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
@ -8410,11 +8380,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
|| POINTER_TYPE_P (type))
&& (INTEGRAL_TYPE_P (TREE_TYPE (op0))
|| POINTER_TYPE_P (TREE_TYPE (op0)))
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0))
/* Do not muck with VIEW_CONVERT_EXPRs that convert from
a sub-type to its base type as generated by the Ada FE. */
&& !(INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& TREE_TYPE (TREE_TYPE (op0))))
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
return fold_convert (type, op0);
/* Strip inner integral conversions that do not change the precision. */

View File

@ -161,6 +161,7 @@ extern tree lhd_make_node (enum tree_code);
lhd_omp_firstprivatize_type_sizes
#define LANG_HOOKS_TYPE_HASH_EQ NULL
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type
#define LANG_HOOKS_HASH_TYPES true
@ -177,6 +178,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
LANG_HOOKS_TYPE_HASH_EQ, \
LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
LANG_HOOKS_HASH_TYPES \
}

View File

@ -130,6 +130,9 @@ struct lang_hooks_for_types
for the debugger about the array bounds, strides, etc. */
bool (*get_array_descr_info) (const_tree, struct array_descr_info *);
/* Fill in information for the debugger about the bounds of TYPE. */
void (*get_subrange_bounds) (const_tree, tree *, tree *);
/* If we requested a pointer to a vector, build up the pointers that
we stripped off while looking for the inner type. Similarly for
return values from functions. The argument TYPE is the top of the

View File

@ -1100,21 +1100,6 @@ nb_vars_in_chrec (tree chrec)
}
}
/* Returns true if TYPE is a type in that we cannot directly perform
arithmetics, even though it is a scalar type. */
static bool
avoid_arithmetics_in_type_p (const_tree type)
{
/* Ada frontend uses subtypes -- an arithmetic cannot be directly performed
in the subtype, but a base type must be used, and the result then can
be casted to the subtype. */
if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE)
return true;
return false;
}
static tree chrec_convert_1 (tree, tree, gimple, bool);
/* Converts BASE and STEP of affine scev to TYPE. LOOP is the loop whose iv
@ -1136,10 +1121,6 @@ convert_affine_scev (struct loop *loop, tree type,
tree new_base, new_step;
tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
/* If we cannot perform arithmetic in TYPE, avoid creating an scev. */
if (avoid_arithmetics_in_type_p (type))
return false;
/* In general,
(TYPE) (BASE + STEP * i) = (TYPE) BASE + (TYPE -- sign extend) STEP * i,
but we must check some assumptions.
@ -1342,10 +1323,6 @@ chrec_convert_aggressive (tree type, tree chrec)
if (TYPE_PRECISION (type) > TYPE_PRECISION (inner_type))
return NULL_TREE;
/* If we cannot perform arithmetic in TYPE, avoid creating an scev. */
if (avoid_arithmetics_in_type_p (type))
return NULL_TREE;
rtype = POINTER_TYPE_P (type) ? sizetype : type;
left = CHREC_LEFT (chrec);

View File

@ -923,19 +923,9 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
|| TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
return false;
/* Conversions from a non-base to a base type are not useless.
This way we preserve the invariant to do arithmetic in
base types only. */
if (TREE_TYPE (inner_type)
&& TREE_TYPE (inner_type) != inner_type
&& (TREE_TYPE (outer_type) == outer_type
|| TREE_TYPE (outer_type) == NULL_TREE))
return false;
/* We don't need to preserve changes in the types minimum or
maximum value in general as these do not generate code
unless the types precisions are different. */
return true;
}

View File

@ -121,7 +121,7 @@ DEF_VEC_ALLOC_O(switch_update, heap);
static VEC (switch_update, heap) *to_update_switch_stmts;
/* Return the maximum value for TYPEs base type. */
/* Return the maximum value for TYPE. */
static inline tree
vrp_val_max (const_tree type)
@ -129,14 +129,10 @@ vrp_val_max (const_tree type)
if (!INTEGRAL_TYPE_P (type))
return NULL_TREE;
/* For integer sub-types the values for the base type are relevant. */
if (TREE_TYPE (type))
type = TREE_TYPE (type);
return TYPE_MAX_VALUE (type);
}
/* Return the minimum value for TYPEs base type. */
/* Return the minimum value for TYPE. */
static inline tree
vrp_val_min (const_tree type)
@ -144,10 +140,6 @@ vrp_val_min (const_tree type)
if (!INTEGRAL_TYPE_P (type))
return NULL_TREE;
/* For integer sub-types the values for the base type are relevant. */
if (TREE_TYPE (type))
type = TREE_TYPE (type);
return TYPE_MIN_VALUE (type);
}
@ -188,11 +180,7 @@ vrp_val_is_min (const_tree val)
static inline bool
needs_overflow_infinity (const_tree type)
{
return (INTEGRAL_TYPE_P (type)
&& !TYPE_OVERFLOW_WRAPS (type)
/* Integer sub-types never overflow as they are never
operands of arithmetic operators. */
&& !(TREE_TYPE (type) && TREE_TYPE (type) != type));
return INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type);
}
/* Return whether TYPE can support our overflow infinity
@ -2702,13 +2690,6 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
tree inner_type = TREE_TYPE (op0);
tree outer_type = type;
/* Always use base-types here. This is important for the
correct signedness. */
if (TREE_TYPE (inner_type))
inner_type = TREE_TYPE (inner_type);
if (TREE_TYPE (outer_type))
outer_type = TREE_TYPE (outer_type);
/* If VR0 is varying and we increase the type precision, assume
a full range for the following transformation. */
if (vr0.type == VR_VARYING

View File

@ -5696,6 +5696,57 @@ build_range_type (tree type, tree lowval, tree highval)
return itype;
}
/* Return true if the debug information for TYPE, a subtype, should be emitted
as a subrange type. If so, set LOWVAL to the low bound and HIGHVAL to the
high bound, respectively. Sometimes doing so unnecessarily obfuscates the
debug info and doesn't reflect the source code. */
bool
subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval)
{
tree base_type = TREE_TYPE (type), low, high;
/* Subrange types have a base type which is an integral type. */
if (!INTEGRAL_TYPE_P (base_type))
return false;
/* Get the real bounds of the subtype. */
if (lang_hooks.types.get_subrange_bounds)
lang_hooks.types.get_subrange_bounds (type, &low, &high);
else
{
low = TYPE_MIN_VALUE (type);
high = TYPE_MAX_VALUE (type);
}
/* If the type and its base type have the same representation and the same
name, then the type is not a subrange but a copy of the base type. */
if ((TREE_CODE (base_type) == INTEGER_TYPE
|| TREE_CODE (base_type) == BOOLEAN_TYPE)
&& int_size_in_bytes (type) == int_size_in_bytes (base_type)
&& tree_int_cst_equal (low, TYPE_MIN_VALUE (base_type))
&& tree_int_cst_equal (high, TYPE_MAX_VALUE (base_type)))
{
tree type_name = TYPE_NAME (type);
tree base_type_name = TYPE_NAME (base_type);
if (type_name && TREE_CODE (type_name) == TYPE_DECL)
type_name = DECL_NAME (type_name);
if (base_type_name && TREE_CODE (base_type_name) == TYPE_DECL)
base_type_name = DECL_NAME (base_type_name);
if (type_name == base_type_name)
return false;
}
if (lowval)
*lowval = low;
if (highval)
*highval = high;
return true;
}
/* Just like build_index_type, but takes lowval and highval instead
of just highval (maxval). */

View File

@ -4860,6 +4860,7 @@ extern void build_common_tree_nodes_2 (int);
extern void build_common_builtin_nodes (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_range_type (tree, tree, tree);
extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);
extern HOST_WIDE_INT int_cst_value (const_tree);
extern bool fields_compatible_p (const_tree, const_tree);