gigi.h (enum standard_datatypes): Add new values ADT_sbitsize_one_node and ADT_sbitsize_unit_node.

* gcc-interface/gigi.h (enum standard_datatypes): Add new values
	ADT_sbitsize_one_node and ADT_sbitsize_unit_node.
	(sbitsize_one_node): New macro.
	(sbitsize_unit_node): Likewise.
	* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Fix
	latent bug in the computation of subrange_p.  Fold wider_p predicate.
	(cannot_be_superflat_p): Use an explicitly signed 64-bit type to do
	the final comparison.
	(make_aligning_type): Build real negation and use sizetype throughout
	the offset computation.
	(maybe_pad_type): Do not issue the warning when the new size expression
	is too complex.
	(annotate_value) <INTEGER_CST>: Simplify code handling negative values.
	* gcc-interface/misc.c (gnat_init): Initialize sbitsize_one_node and
	sbitsize_unit_node.
	* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Pool_Address>: Fold
	double negation.
	(gnat_to_gnu) <N_Free_Statement>: Likewise.
	* gcc-interface/utils.c (convert): Use sbitsize_unit_node.
	* gcc-interface/utils2.c (compare_arrays): Compute real lengths and use
	constants in sizetype.  Remove dead code and tweak comments.  Generate
	equality instead of inequality comparisons for zero length tests.

From-SVN: r158461
This commit is contained in:
Eric Botcazou 2010-04-17 08:14:08 +00:00 committed by Eric Botcazou
parent 80d56d040e
commit 1081f5a7c7
7 changed files with 105 additions and 101 deletions

View File

@ -1,3 +1,28 @@
2010-04-17 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (enum standard_datatypes): Add new values
ADT_sbitsize_one_node and ADT_sbitsize_unit_node.
(sbitsize_one_node): New macro.
(sbitsize_unit_node): Likewise.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Fix
latent bug in the computation of subrange_p. Fold wider_p predicate.
(cannot_be_superflat_p): Use an explicitly signed 64-bit type to do
the final comparison.
(make_aligning_type): Build real negation and use sizetype throughout
the offset computation.
(maybe_pad_type): Do not issue the warning when the new size expression
is too complex.
(annotate_value) <INTEGER_CST>: Simplify code handling negative values.
* gcc-interface/misc.c (gnat_init): Initialize sbitsize_one_node and
sbitsize_unit_node.
* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Pool_Address>: Fold
double negation.
(gnat_to_gnu) <N_Free_Statement>: Likewise.
* gcc-interface/utils.c (convert): Use sbitsize_unit_node.
* gcc-interface/utils2.c (compare_arrays): Compute real lengths and use
constants in sizetype. Remove dead code and tweak comments. Generate
equality instead of inequality comparisons for zero length tests.
2010-04-16 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (gnat_init_decl_processing): Delete.

View File

@ -2115,11 +2115,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
const int prec_comp
= compare_tree_int (TYPE_RM_SIZE (gnu_index_type),
TYPE_PRECISION (sizetype));
const bool subrange_p = (prec_comp < 0)
|| (prec_comp == 0
&& TYPE_UNSIGNED (gnu_index_type)
== TYPE_UNSIGNED (sizetype));
const bool wider_p = (prec_comp > 0);
const bool subrange_p = (prec_comp < 0
&& (TYPE_UNSIGNED (gnu_index_type)
|| !TYPE_UNSIGNED (sizetype)))
|| (prec_comp == 0
&& TYPE_UNSIGNED (gnu_index_type)
== TYPE_UNSIGNED (sizetype));
tree gnu_orig_min = TYPE_MIN_VALUE (gnu_index_type);
tree gnu_orig_max = TYPE_MAX_VALUE (gnu_index_type);
tree gnu_min = convert (sizetype, gnu_orig_min);
@ -2298,7 +2299,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
&& TREE_CODE (TREE_TYPE (gnu_index_type))
!= INTEGER_TYPE)
|| TYPE_BIASED_REPRESENTATION_P (gnu_index_type)
|| wider_p)
|| prec_comp > 0)
need_index_type_struct = true;
}
@ -5381,7 +5382,7 @@ cannot_be_superflat_p (Node_Id gnat_range)
{
Node_Id gnat_lb = Low_Bound (gnat_range), gnat_hb = High_Bound (gnat_range);
Node_Id scalar_range;
tree gnu_lb, gnu_hb;
tree gnu_lb, gnu_hb, gnu_lb_minus_one;
/* If the low bound is not constant, try to find an upper bound. */
while (Nkind (gnat_lb) != N_Integer_Literal
@ -5401,19 +5402,23 @@ cannot_be_superflat_p (Node_Id gnat_range)
|| Nkind (scalar_range) == N_Range))
gnat_hb = Low_Bound (scalar_range);
if (!(Nkind (gnat_lb) == N_Integer_Literal
&& Nkind (gnat_hb) == N_Integer_Literal))
/* If we have failed to find constant bounds, punt. */
if (Nkind (gnat_lb) != N_Integer_Literal
|| Nkind (gnat_hb) != N_Integer_Literal)
return false;
gnu_lb = UI_To_gnu (Intval (gnat_lb), bitsizetype);
gnu_hb = UI_To_gnu (Intval (gnat_hb), bitsizetype);
/* We need at least a signed 64-bit type to catch most cases. */
gnu_lb = UI_To_gnu (Intval (gnat_lb), sbitsizetype);
gnu_hb = UI_To_gnu (Intval (gnat_hb), sbitsizetype);
if (TREE_OVERFLOW (gnu_lb) || TREE_OVERFLOW (gnu_hb))
return false;
/* If the low bound is the smallest integer, nothing can be smaller. */
gnu_lb = size_binop (MINUS_EXPR, gnu_lb, bitsize_one_node);
if (TREE_OVERFLOW (gnu_lb))
gnu_lb_minus_one = size_binop (MINUS_EXPR, gnu_lb, sbitsize_one_node);
if (TREE_OVERFLOW (gnu_lb_minus_one))
return true;
return (tree_int_cst_lt (gnu_hb, gnu_lb) == 0);
return !tree_int_cst_lt (gnu_hb, gnu_lb_minus_one);
}
/* Return true if GNU_EXPR is (essentially) the address of a CONSTRUCTOR. */
@ -5876,7 +5881,6 @@ make_aligning_type (tree type, unsigned int align, tree size,
/* We will be crafting a record type with one field at a position set to be
the next multiple of ALIGN past record'address + room bytes. We use a
record placeholder to express record'address. */
tree record_type = make_node (RECORD_TYPE);
tree record = build0 (PLACEHOLDER_EXPR, record_type);
@ -5896,7 +5900,6 @@ make_aligning_type (tree type, unsigned int align, tree size,
Every length is in sizetype bytes there, except "pos" which has to be
set as a bit position in the GCC tree for the record. */
tree room_st = size_int (room);
tree vblock_addr_st = size_binop (PLUS_EXPR, record_addr_st, room_st);
tree voffset_st, pos, field;
@ -5911,13 +5914,11 @@ make_aligning_type (tree type, unsigned int align, tree size,
/* Compute VOFFSET and then POS. The next byte position multiple of some
alignment after some address is obtained by "and"ing the alignment minus
1 with the two's complement of the address. */
voffset_st = size_binop (BIT_AND_EXPR,
size_diffop (size_zero_node, vblock_addr_st),
ssize_int ((align / BITS_PER_UNIT) - 1));
fold_build1 (NEGATE_EXPR, sizetype, vblock_addr_st),
size_int ((align / BITS_PER_UNIT) - 1));
/* POS = (ROOM + VOFFSET) * BIT_PER_UNIT, in bitsizetype. */
pos = size_binop (MULT_EXPR,
convert (bitsizetype,
size_binop (PLUS_EXPR, room_st, voffset_st)),
@ -5936,7 +5937,6 @@ make_aligning_type (tree type, unsigned int align, tree size,
consequences on the alignment computation, and create_field_decl would
make one without this special argument, for instance because of the
complex position expression. */
field = create_field_decl (get_identifier ("F"), type, record_type,
1, size, pos, -1);
TYPE_FIELDS (record_type) = field;
@ -6287,6 +6287,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
if (Present (gnat_entity)
&& size
&& TREE_CODE (size) != MAX_EXPR
&& TREE_CODE (size) != COND_EXPR
&& !operand_equal_p (size, orig_size, 0)
&& !(TREE_CODE (size) == INTEGER_CST
&& TREE_CODE (orig_size) == INTEGER_CST
@ -7123,33 +7124,16 @@ annotate_value (tree gnu_size)
if (TREE_OVERFLOW (gnu_size))
return No_Uint;
/* This may have come from a conversion from some smaller type,
so ensure this is in bitsizetype. */
/* This may come from a conversion from some smaller type, so ensure
this is in bitsizetype. */
gnu_size = convert (bitsizetype, gnu_size);
/* For negative values, use NEGATE_EXPR of the supplied value. */
/* For a negative value, use NEGATE_EXPR of the opposite. Such values
appear in expressions containing aligning patterns. */
if (tree_int_cst_sgn (gnu_size) < 0)
{
/* The ridiculous code below is to handle the case of the largest
negative integer. */
tree negative_size = size_diffop (bitsize_zero_node, gnu_size);
bool adjust = false;
tree temp;
if (TREE_OVERFLOW (negative_size))
{
negative_size
= size_binop (MINUS_EXPR, bitsize_zero_node,
size_binop (PLUS_EXPR, gnu_size,
bitsize_one_node));
adjust = true;
}
temp = build1 (NEGATE_EXPR, bitsizetype, negative_size);
if (adjust)
temp = build2 (MINUS_EXPR, bitsizetype, temp, bitsize_one_node);
return annotate_value (temp);
tree op_size = fold_build1 (NEGATE_EXPR, bitsizetype, gnu_size);
return annotate_value (build1 (NEGATE_EXPR, bitsizetype, op_size));
}
return UI_From_gnu (gnu_size);

View File

@ -356,9 +356,15 @@ enum standard_datatypes
/* Type declaration node <==> typedef virtual void *T() */
ADT_fdesc_type,
/* Null pointer for above type */
/* Null pointer for above type. */
ADT_null_fdesc,
/* Value 1 in signed bitsizetype. */
ADT_sbitsize_one_node,
/* Value BITS_PER_UNIT in signed bitsizetype. */
ADT_sbitsize_unit_node,
/* Function declaration nodes for run-time functions for allocating memory.
Ada allocators cause calls to these functions to be generated. Malloc32
is used only on 64bit systems needing to allocate 32bit memory. */
@ -401,6 +407,8 @@ extern GTY(()) tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
#define ptr_void_ftype gnat_std_decls[(int) ADT_ptr_void_ftype]
#define fdesc_type_node gnat_std_decls[(int) ADT_fdesc_type]
#define null_fdesc_node gnat_std_decls[(int) ADT_null_fdesc]
#define sbitsize_one_node gnat_std_decls[(int) ADT_sbitsize_one_node]
#define sbitsize_unit_node gnat_std_decls[(int) ADT_sbitsize_unit_node]
#define malloc_decl gnat_std_decls[(int) ADT_malloc_decl]
#define malloc32_decl gnat_std_decls[(int) ADT_malloc32_decl]
#define free_decl gnat_std_decls[(int) ADT_free_decl]

View File

@ -407,6 +407,8 @@ gnat_init (void)
SET_TYPE_RM_SIZE (boolean_type_node, bitsize_int (1));
build_common_tree_nodes_2 (0);
sbitsize_one_node = sbitsize_int (1);
sbitsize_unit_node = sbitsize_int (BITS_PER_UNIT);
boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
ptr_void_type_node = build_pointer_type (void_type_node);

View File

@ -1356,15 +1356,9 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
{
tree gnu_char_ptr_type = build_pointer_type (char_type_node);
tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
tree gnu_byte_offset
= convert (sizetype,
size_diffop (size_zero_node, gnu_pos));
gnu_byte_offset
= fold_build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
gnu_ptr, gnu_byte_offset);
gnu_ptr, gnu_pos);
}
gnu_result = convert (gnu_result_type, gnu_ptr);
@ -5399,15 +5393,9 @@ gnat_to_gnu (Node_Id gnat_node)
{
tree gnu_char_ptr_type = build_pointer_type (char_type_node);
tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
tree gnu_byte_offset
= convert (sizetype,
size_diffop (size_zero_node, gnu_pos));
gnu_byte_offset
= fold_build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
gnu_ptr, gnu_byte_offset);
gnu_ptr, gnu_pos);
}
gnu_result

View File

@ -4066,9 +4066,8 @@ convert (tree type, tree expr)
tree bit_diff
= size_diffop (bit_position (TYPE_FIELDS (TREE_TYPE (etype))),
bit_position (TYPE_FIELDS (TREE_TYPE (type))));
tree byte_diff = size_binop (CEIL_DIV_EXPR, bit_diff,
sbitsize_int (BITS_PER_UNIT));
tree byte_diff
= size_binop (CEIL_DIV_EXPR, bit_diff, sbitsize_unit_node);
expr = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (expr) = TREE_CONSTANT (TREE_OPERAND (expr, 0));
if (integer_zerop (byte_diff))

View File

@ -260,28 +260,27 @@ compare_arrays (tree result_type, tree a1, tree a2)
a2 = gnat_protect_expr (a2);
/* Process each dimension separately and compare the lengths. If any
dimension has a size known to be zero, set SIZE_ZERO_P to 1 to
suppress the comparison of the data. */
dimension has a length known to be zero, set LENGTH_ZERO_P to true
in order to suppress the comparison of the data at the end. */
while (TREE_CODE (t1) == ARRAY_TYPE && TREE_CODE (t2) == ARRAY_TYPE)
{
tree lb1 = TYPE_MIN_VALUE (TYPE_DOMAIN (t1));
tree ub1 = TYPE_MAX_VALUE (TYPE_DOMAIN (t1));
tree lb2 = TYPE_MIN_VALUE (TYPE_DOMAIN (t2));
tree ub2 = TYPE_MAX_VALUE (TYPE_DOMAIN (t2));
tree bt = get_base_type (TREE_TYPE (lb1));
tree length1 = fold_build2 (MINUS_EXPR, bt, ub1, lb1);
tree length2 = fold_build2 (MINUS_EXPR, bt, ub2, lb2);
tree length1 = size_binop (PLUS_EXPR, size_binop (MINUS_EXPR, ub1, lb1),
size_one_node);
tree length2 = size_binop (PLUS_EXPR, size_binop (MINUS_EXPR, ub2, lb2),
size_one_node);
tree comparison, this_a1_is_null, this_a2_is_null;
tree nbt, tem;
bool btem;
/* If the length of the first array is a constant, swap our operands
unless the length of the second array is the constant zero.
Note that we have set the `length' values to the length - 1. */
if (TREE_CODE (length1) == INTEGER_CST
&& !integer_zerop (fold_build2 (PLUS_EXPR, bt, length2,
convert (bt, integer_one_node))))
unless the length of the second array is the constant zero. */
if (TREE_CODE (length1) == INTEGER_CST && !integer_zerop (length2))
{
tree tem;
bool btem;
tem = a1, a1 = a2, a2 = tem;
tem = t1, t1 = t2, t2 = tem;
tem = lb1, lb1 = lb2, lb2 = tem;
@ -292,57 +291,56 @@ compare_arrays (tree result_type, tree a1, tree a2)
a2_side_effects_p = btem;
}
/* If the length of this dimension in the second array is the constant
zero, we can just go inside the original bounds for the first
array and see if last < first. */
if (integer_zerop (fold_build2 (PLUS_EXPR, bt, length2,
convert (bt, integer_one_node))))
/* If the length of the second array is the constant zero, we can just
use the original stored bounds for the first array and see whether
last < first holds. */
if (integer_zerop (length2))
{
tree ub = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
tree lb = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
length_zero_p = true;
comparison = build_binary_op (LT_EXPR, result_type, ub, lb);
ub1 = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
lb1 = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
comparison = build_binary_op (LT_EXPR, result_type, ub1, lb1);
comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
if (EXPR_P (comparison))
SET_EXPR_LOCATION (comparison, input_location);
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
length_zero_p = true;
this_a1_is_null = comparison;
this_a2_is_null = convert (result_type, boolean_true_node);
}
/* If the length is some other constant value, we know that the
this dimension in the first array cannot be superflat, so we
can just use its length from the actual stored bounds. */
/* Otherwise, if the length is some other constant value, we know that
this dimension in the second array cannot be superflat, so we can
just use its length computed from the actual stored bounds. */
else if (TREE_CODE (length2) == INTEGER_CST)
{
tree bt;
ub1 = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
lb1 = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
/* Note that we know that UB2 and LB2 are constant and hence
cannot contain a PLACEHOLDER_EXPR. */
ub2 = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t2)));
lb2 = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t2)));
nbt = get_base_type (TREE_TYPE (ub1));
bt = get_base_type (TREE_TYPE (ub1));
comparison
= build_binary_op (EQ_EXPR, result_type,
build_binary_op (MINUS_EXPR, nbt, ub1, lb1),
build_binary_op (MINUS_EXPR, nbt, ub2, lb2));
build_binary_op (MINUS_EXPR, bt, ub1, lb1),
build_binary_op (MINUS_EXPR, bt, ub2, lb2));
comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
if (EXPR_P (comparison))
SET_EXPR_LOCATION (comparison, input_location);
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
this_a1_is_null = build_binary_op (LT_EXPR, result_type, ub1, lb1);
if (EXPR_P (this_a1_is_null))
SET_EXPR_LOCATION (this_a1_is_null, input_location);
this_a2_is_null = convert (result_type, boolean_false_node);
}
/* Otherwise compare the computed lengths. */
/* Otherwise, compare the computed lengths. */
else
{
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
@ -353,24 +351,24 @@ compare_arrays (tree result_type, tree a1, tree a2)
if (EXPR_P (comparison))
SET_EXPR_LOCATION (comparison, input_location);
this_a1_is_null
= build_binary_op (LT_EXPR, result_type, length1,
convert (bt, integer_zero_node));
this_a1_is_null = build_binary_op (EQ_EXPR, result_type, length1,
size_zero_node);
if (EXPR_P (this_a1_is_null))
SET_EXPR_LOCATION (this_a1_is_null, input_location);
this_a2_is_null
= build_binary_op (LT_EXPR, result_type, length2,
convert (bt, integer_zero_node));
this_a2_is_null = build_binary_op (EQ_EXPR, result_type, length2,
size_zero_node);
if (EXPR_P (this_a2_is_null))
SET_EXPR_LOCATION (this_a2_is_null, input_location);
}
/* Append expressions for this dimension to the final expressions. */
result = build_binary_op (TRUTH_ANDIF_EXPR, result_type,
result, comparison);
a1_is_null = build_binary_op (TRUTH_ORIF_EXPR, result_type,
this_a1_is_null, a1_is_null);
a2_is_null = build_binary_op (TRUTH_ORIF_EXPR, result_type,
this_a2_is_null, a2_is_null);
@ -378,7 +376,7 @@ compare_arrays (tree result_type, tree a1, tree a2)
t2 = TREE_TYPE (t2);
}
/* Unless the size of some bound is known to be zero, compare the
/* Unless the length of some dimension is known to be zero, compare the
data in the array. */
if (!length_zero_p)
{