From 743aa7e5bbedfbccb953e324ef22af2fac01f1d7 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Sat, 17 Apr 2010 08:14:08 +0000 Subject: [PATCH] * 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) : 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) : 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) : Fold double negation. (gnat_to_gnu) : 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158461 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ada/ChangeLog | 25 ++++++++++++++ gcc/ada/gcc-interface/decl.c | 72 ++++++++++++++++----------------------- gcc/ada/gcc-interface/gigi.h | 10 +++++- gcc/ada/gcc-interface/misc.c | 2 ++ gcc/ada/gcc-interface/trans.c | 16 ++------- gcc/ada/gcc-interface/utils.c | 5 ++- gcc/ada/gcc-interface/utils2.c | 76 ++++++++++++++++++++---------------------- 7 files changed, 105 insertions(+), 101 deletions(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 261263592e9..21800d82dc7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,28 @@ +2010-04-17 Eric Botcazou + + * 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) : 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) : 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) : Fold + double negation. + (gnat_to_gnu) : 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 * gcc-interface/gigi.h (gnat_init_decl_processing): Delete. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 02d729621bc..b7fd3318cee 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -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); diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 61baf34d26f..224abe8e80f 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -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] diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 1b31890f32c..52fe65a560d 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -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); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 7f35bc2ca57..4b7946c865e 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -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 diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index e110ef51e32..668226bd906 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -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)) diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index 33f3a613f60..ca35cc7458a 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -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) { -- 2.11.0