aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/ada/ChangeLog44
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h82
-rw-r--r--gcc/ada/gcc-interface/decl.c200
-rw-r--r--gcc/ada/gcc-interface/gigi.h4
-rw-r--r--gcc/ada/gcc-interface/misc.c21
-rw-r--r--gcc/ada/gcc-interface/trans.c33
-rw-r--r--gcc/ada/gcc-interface/utils.c115
-rw-r--r--gcc/ada/gcc-interface/utils2.c7
-rw-r--r--gcc/dbxout.c70
-rw-r--r--gcc/dwarf2out.c84
-rw-r--r--gcc/fold-const.c54
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h3
-rw-r--r--gcc/tree-chrec.c23
-rw-r--r--gcc/tree-ssa.c10
-rw-r--r--gcc/tree-vrp.c25
-rw-r--r--gcc/tree.c51
-rw-r--r--gcc/tree.h1
19 files changed, 500 insertions, 361 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b089b1d..8caac7e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 99806dd..0548b21 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -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
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 19c9fa5..38bc862 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -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.
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 6feadbd..46215da 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -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));
-
- /* 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));
-
- /* Set the precision to the Esize except for bit-packed arrays and
- subtypes of Standard.Boolean. */
+ /* 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));
- else if (Is_Boolean_Type (gnat_entity))
- esize = 1;
-
- 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)));
+ /* 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. */
+ 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));
- 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_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_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)));
-
- 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_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_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)))
+
+ /* 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_MIN_VALUE (t), f, r);
- tree high = SUBSTITUTE_IN_EXPR (TYPE_MAX_VALUE (t), f, r);
+ 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_MIN_VALUE (t) && high == TYPE_MAX_VALUE (t))
+ 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:
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 8ccb39c..4d19b42 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -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. */
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 5ccf134..bd6b51a 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -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. */
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index ee65c81..2c471f1 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -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);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index e3cf975..6dbd1e7 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -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);
}
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index e5001ab..3fe8585 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -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)))
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index dd05076..eb0fcee 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -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))
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0d308c9..157bdaf 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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))
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index fb59049..32de681 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 4b6ce27..506b527 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -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 \
}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 0694189..06ad6c1 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -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
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index 82c1fbe..495f95a 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -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);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 10f8482..13a79dc 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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;
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 3a86b82..a0f4c3d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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
diff --git a/gcc/tree.c b/gcc/tree.c
index 5ed55c1..92f16e7 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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). */
diff --git a/gcc/tree.h b/gcc/tree.h
index eaa8e2e..52c4fdf 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);