diff options
author | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-02 23:25:15 +0000 |
---|---|---|
committer | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-02 23:25:15 +0000 |
commit | 611349f0ec42a37591db2cd02974a11a48d10edb (patch) | |
tree | 2a5c3eecca5f0b75352af30aad7f366c69281c2c /gcc/ada/gcc-interface | |
parent | 0012f4fdae066f73c9f38cb33d3a338c3e356cdf (diff) | |
download | gcc-611349f0ec42a37591db2cd02974a11a48d10edb.tar.gz |
merge from trunk
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/profile-stdlib@152425 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r-- | gcc/ada/gcc-interface/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/ada-tree.h | 7 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/ada.h | 6 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 1078 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/gigi.h | 34 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/misc.c | 5 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/targtyps.c | 13 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/trans.c | 214 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 261 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils2.c | 68 |
10 files changed, 1092 insertions, 596 deletions
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in index bc2ad926eff..cf717ac39cd 100644 --- a/gcc/ada/gcc-interface/Makefile.in +++ b/gcc/ada/gcc-interface/Makefile.in @@ -2128,7 +2128,7 @@ endif # These base versions lack Ada 2005 additions which would cause bootstrap # problems if included in the compiler and other basic tools. -ifeq ($(filter-out a-except%,$(LIBGNAT_TARGET_PAIRS)),$(LIBGNAT_TARGET_PAIRS)) +ifeq ($(filter a-except%,$(LIBGNAT_TARGET_PAIRS)),) LIBGNAT_TARGET_PAIRS += \ a-except.ads<a-except-2005.ads \ a-except.adb<a-except-2005.adb diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h index 18eb41657cf..94b18bde6b5 100644 --- a/gcc/ada/gcc-interface/ada-tree.h +++ b/gcc/ada/gcc-interface/ada-tree.h @@ -195,6 +195,10 @@ do { \ refer to the routine gnat_to_gnu_entity. */ #define TYPE_CI_CO_LIST(NODE) TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE)) +/* For a VECTOR_TYPE, this is the representative array type. */ +#define TYPE_REPRESENTATIVE_ARRAY(NODE) \ + TYPE_LANG_SLOT_1 (VECTOR_TYPE_CHECK (NODE)) + /* For numerical types, this holds various RM-defined values. */ #define TYPE_RM_VALUES(NODE) TYPE_LANG_SLOT_1 (NUMERICAL_TYPE_CHECK (NODE)) @@ -210,8 +214,7 @@ do { \ TYPE_RM_VALUES (NODE) = make_tree_vec (3); \ /* ??? The field is not visited by the generic \ code so we need to mark it manually. */ \ - if (!TREE_CONSTANT (tmp)) \ - mark_visited (&tmp); \ + MARK_VISITED (tmp); \ TREE_VEC_ELT (TYPE_RM_VALUES (NODE), (N)) = tmp; \ } while (0) diff --git a/gcc/ada/gcc-interface/ada.h b/gcc/ada/gcc-interface/ada.h index 6c2a1419f53..095dec3d6ad 100644 --- a/gcc/ada/gcc-interface/ada.h +++ b/gcc/ada/gcc-interface/ada.h @@ -62,9 +62,9 @@ enum { CAT (SUBTYPE,__First) = FIRST, \ CAT (SUBTYPE,__Last) = LAST }; -/* The following definitions provide the equivalent of the Ada IN and NOT IN - operators, assuming that the subtype involved has been defined using the - SUBTYPE macro defined above. */ +/* The following definition provides the equivalent of the Ada IN operator, + assuming that the subtype involved has been defined using the SUBTYPE + macro defined above. */ #define IN(VALUE,SUBTYPE) \ (((VALUE) >= (SUBTYPE) CAT (SUBTYPE,__First)) \ diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 58c07a777d7..f2f0f159abd 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -122,7 +122,6 @@ enum alias_set_op static void relate_alias_sets (tree, tree, enum alias_set_op); -static tree build_subst_list (Entity_Id, Entity_Id, bool); static bool allocatable_size_p (tree, bool); static void prepend_one_attribute_to (struct attrib **, enum attr_type, tree, tree, Node_Id); @@ -131,9 +130,10 @@ static tree elaborate_expression (Node_Id, Entity_Id, tree, bool, bool, bool); static bool is_variable_size (tree); static tree elaborate_expression_1 (tree, Entity_Id, tree, bool, bool); static tree make_packable_type (tree, bool); -static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool); +static tree gnat_to_gnu_component_type (Entity_Id, bool, bool); static tree gnat_to_gnu_param (Entity_Id, Mechanism_Type, Entity_Id, bool, bool *); +static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool); static bool same_discriminant_p (Entity_Id, Entity_Id); static bool array_type_has_nonaliased_component (Entity_Id, tree); static bool compile_time_known_address_p (Node_Id); @@ -142,14 +142,21 @@ static void components_to_record (tree, Node_Id, tree, int, bool, tree *, bool, bool, bool, bool, bool); static Uint annotate_value (tree); static void annotate_rep (Entity_Id, tree); -static tree compute_field_positions (tree, tree, tree, tree, unsigned int); +static tree build_position_list (tree, bool, tree, tree, unsigned int, tree); +static tree build_subst_list (Entity_Id, Entity_Id, bool); +static tree build_variant_list (tree, tree, tree); static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool); static void set_rm_size (Uint, tree, Entity_Id); static tree make_type_from_size (tree, tree, bool); static unsigned int validate_alignment (Uint, Entity_Id, unsigned int); static unsigned int ceil_alignment (unsigned HOST_WIDE_INT); static void check_ok_for_atomic (tree, Entity_Id, bool); -static int compatible_signatures_p (tree ftype1, tree ftype2); +static int compatible_signatures_p (tree, tree); +static tree create_field_decl_from (tree, tree, tree, tree, tree, tree); +static tree get_rep_part (tree); +static tree get_variant_part (tree); +static tree create_variant_part_from (tree, tree, tree, tree, tree); +static void copy_and_substitute_in_size (tree, tree, tree); static void rest_of_type_decl_compilation_no_defer (tree); /* Given GNAT_ENTITY, a GNAT defining identifier node, which denotes some Ada @@ -898,11 +905,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) if (stable) { - gnu_decl = maybe_stable_expr; /* ??? No DECL_EXPR is created so we need to mark the expression manually lest it is shared. */ if (global_bindings_p ()) - mark_visited (&gnu_decl); + MARK_VISITED (maybe_stable_expr); + gnu_decl = maybe_stable_expr; save_gnu_tree (gnat_entity, gnu_decl, true); saved = true; annotate_object (gnat_entity, gnu_type, NULL_TREE, @@ -1793,8 +1800,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) tree gnu_fat_type = make_node (RECORD_TYPE); tree *gnu_index_types = (tree *) alloca (ndim * sizeof (tree)); tree *gnu_temp_fields = (tree *) alloca (ndim * sizeof (tree)); - tree gnu_max_size = size_one_node, gnu_max_size_unit; - tree gnu_comp_size, tem; + tree gnu_max_size = size_one_node, gnu_max_size_unit, tem; int index; TYPE_NAME (gnu_template_type) @@ -1852,7 +1858,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) char field_name[16]; tree gnu_index_base_type = get_unpadded_type (Base_Type (Etype (gnat_index))); - tree gnu_low_field, gnu_high_field, gnu_low, gnu_high; + tree gnu_low_field, gnu_high_field, gnu_low, gnu_high, gnu_max; /* Make the FIELD_DECLs for the low and high bounds of this type and then make extractions of these fields from the @@ -1885,11 +1891,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) NULL_TREE); TREE_READONLY (gnu_low) = TREE_READONLY (gnu_high) = 1; + /* Compute the size of this dimension. */ + gnu_max + = build3 (COND_EXPR, gnu_index_base_type, + build2 (GE_EXPR, integer_type_node, gnu_high, gnu_low), + gnu_high, + build2 (MINUS_EXPR, gnu_index_base_type, + gnu_low, fold_convert (gnu_index_base_type, + integer_one_node))); + /* Make a range type with the new range in the Ada base type. - Then make an index type with the new range in sizetype. */ + Then make an index type with the size range in sizetype. */ gnu_index_types[index] = create_index_type (convert (sizetype, gnu_low), - convert (sizetype, gnu_high), + convert (sizetype, gnu_max), create_range_type (gnu_index_base_type, gnu_low, gnu_high), gnat_entity); @@ -1931,73 +1946,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Now make the array of arrays and update the pointer to the array in the fat pointer. Note that it is the first field. */ - tem = gnat_to_gnu_type (Component_Type (gnat_entity)); - - /* Try to get a smaller form of the component if needed. */ - if ((Is_Packed (gnat_entity) - || Has_Component_Size_Clause (gnat_entity)) - && !Is_Bit_Packed_Array (gnat_entity) - && !Has_Aliased_Components (gnat_entity) - && !Strict_Alignment (Component_Type (gnat_entity)) - && TREE_CODE (tem) == RECORD_TYPE - && !TYPE_IS_FAT_POINTER_P (tem) - && host_integerp (TYPE_SIZE (tem), 1)) - tem = make_packable_type (tem, false); - - if (Has_Atomic_Components (gnat_entity)) - check_ok_for_atomic (tem, gnat_entity, true); - - /* Get and validate any specified Component_Size, but if Packed, - ignore it since the front end will have taken care of it. */ - gnu_comp_size - = validate_size (Component_Size (gnat_entity), tem, - gnat_entity, - (Is_Bit_Packed_Array (gnat_entity) - ? TYPE_DECL : VAR_DECL), - true, Has_Component_Size_Clause (gnat_entity)); - - /* If the component type is a RECORD_TYPE that has a self-referential - size, use the maximum size. */ - if (!gnu_comp_size - && TREE_CODE (tem) == RECORD_TYPE - && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (tem))) - gnu_comp_size = max_size (TYPE_SIZE (tem), true); - - if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_entity)) - { - tree orig_tem = tem; - unsigned int max_align; - - /* If an alignment is specified, use it as a cap on the component - type so that it can be honored for the whole type. But ignore - it for the original type of packed array types. */ - if (No (Packed_Array_Type (gnat_entity)) - && Known_Alignment (gnat_entity)) - max_align = validate_alignment (Alignment (gnat_entity), - gnat_entity, 0); - else - max_align = 0; - - tem = make_type_from_size (tem, gnu_comp_size, false); - if (max_align > 0 && TYPE_ALIGN (tem) > max_align) - tem = orig_tem; - else - orig_tem = tem; - - tem = maybe_pad_type (tem, gnu_comp_size, 0, gnat_entity, - "C_PAD", false, definition, true); - - /* If a padding record was made, declare it now since it will - never be declared otherwise. This is necessary to ensure - that its subtrees are properly marked. */ - if (tem != orig_tem && !DECL_P (TYPE_NAME (tem))) - create_type_decl (TYPE_NAME (tem), tem, NULL, true, - debug_info_p, gnat_entity); - } - - if (Has_Volatile_Components (gnat_entity)) - tem = build_qualified_type (tem, - TYPE_QUALS (tem) | TYPE_QUAL_VOLATILE); + tem = gnat_to_gnu_component_type (gnat_entity, definition, + debug_info_p); /* If Component_Size is not already specified, annotate it with the size of the component. */ @@ -2130,12 +2080,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnat_base_index = Next_Index (gnat_base_index)) { tree gnu_index_type = get_unpadded_type (Etype (gnat_index)); - tree prec = TYPE_RM_SIZE (gnu_index_type); - const bool wider_p - = (compare_tree_int (prec, TYPE_PRECISION (sizetype)) > 0 - || (compare_tree_int (prec, TYPE_PRECISION (sizetype)) == 0 - && TYPE_UNSIGNED (gnu_index_type) - != TYPE_UNSIGNED (sizetype))); + 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); 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); @@ -2144,7 +2096,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) = get_unpadded_type (Etype (gnat_base_index)); tree gnu_base_orig_min = TYPE_MIN_VALUE (gnu_base_index_type); tree gnu_base_orig_max = TYPE_MAX_VALUE (gnu_base_index_type); - tree gnu_high; + tree gnu_high, gnu_low; /* See if the base array type is already flat. If it is, we are probably compiling an ACATS test but it will cause the @@ -2160,7 +2112,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Similarly, if one of the values overflows in sizetype and the range is null, use 1..0 for the sizetype bounds. */ - else if (wider_p + else if (!subrange_p && TREE_CODE (gnu_min) == INTEGER_CST && TREE_CODE (gnu_max) == INTEGER_CST && (TREE_OVERFLOW (gnu_min) || TREE_OVERFLOW (gnu_max)) @@ -2174,7 +2126,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* If the minimum and maximum values both overflow in sizetype, but the difference in the original type does not overflow in sizetype, ignore the overflow indication. */ - else if (wider_p + else if (!subrange_p && TREE_CODE (gnu_min) == INTEGER_CST && TREE_CODE (gnu_max) == INTEGER_CST && TREE_OVERFLOW (gnu_min) && TREE_OVERFLOW (gnu_max) @@ -2200,25 +2152,41 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Otherwise, if we can prove that the low bound minus one and the high bound cannot overflow, we can just use the expression - MAX (hb, lb - 1). Otherwise, we have to use the most general - expression (hb >= lb) ? hb : lb - 1. Note that the comparison - must be done in the original index type, to avoid any overflow - during the conversion. */ + MAX (hb, lb - 1). Similarly, if we can prove that the high + bound plus one and the low bound cannot overflow, we can use + the high bound as-is and MIN (hb + 1, lb) for the low bound. + Otherwise, we have to fall back to the most general expression + (hb >= lb) ? hb : lb - 1. Note that the comparison must be + done in the original index type, to avoid any overflow during + the conversion. */ else { gnu_high = size_binop (MINUS_EXPR, gnu_min, size_one_node); - - /* If gnu_high is a constant that has overflowed, the bound - is the smallest integer so cannot be the maximum. */ - if (TREE_CODE (gnu_high) == INTEGER_CST - && TREE_OVERFLOW (gnu_high)) + gnu_low = size_binop (PLUS_EXPR, gnu_max, size_one_node); + + /* If gnu_high is a constant that has overflowed, the low + bound is the smallest integer so cannot be the maximum. + If gnu_low is a constant that has overflowed, the high + bound is the highest integer so cannot be the minimum. */ + if ((TREE_CODE (gnu_high) == INTEGER_CST + && TREE_OVERFLOW (gnu_high)) + || (TREE_CODE (gnu_low) == INTEGER_CST + && TREE_OVERFLOW (gnu_low))) gnu_high = gnu_max; - /* If the index type is not wider and gnu_high is a constant + /* If the index type is a subrange and gnu_high a constant that hasn't overflowed, we can use the maximum. */ - else if (!wider_p && TREE_CODE (gnu_high) == INTEGER_CST) + else if (subrange_p && TREE_CODE (gnu_high) == INTEGER_CST) gnu_high = size_binop (MAX_EXPR, gnu_max, gnu_high); + /* If the index type is a subrange and gnu_low a constant + that hasn't overflowed, we can use the minimum. */ + else if (subrange_p && TREE_CODE (gnu_low) == INTEGER_CST) + { + gnu_high = gnu_max; + gnu_min = size_binop (MIN_EXPR, gnu_min, gnu_low); + } + else gnu_high = build_cond_expr (sizetype, @@ -2298,7 +2266,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) - || compare_tree_int (prec, TYPE_PRECISION (sizetype)) > 0) + || wider_p) need_index_type_struct = true; } @@ -2323,9 +2291,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } else { - tree gnu_comp_size; - - gnu_type = gnat_to_gnu_type (Component_Type (gnat_entity)); + gnu_type = gnat_to_gnu_component_type (gnat_entity, definition, + debug_info_p); /* One of the above calls might have caused us to be elaborated, so don't blow up if so. */ @@ -2334,73 +2301,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) maybe_present = true; break; } - - /* Try to get a smaller form of the component if needed. */ - if ((Is_Packed (gnat_entity) - || Has_Component_Size_Clause (gnat_entity)) - && !Is_Bit_Packed_Array (gnat_entity) - && !Has_Aliased_Components (gnat_entity) - && !Strict_Alignment (Component_Type (gnat_entity)) - && TREE_CODE (gnu_type) == RECORD_TYPE - && !TYPE_IS_FAT_POINTER_P (gnu_type) - && host_integerp (TYPE_SIZE (gnu_type), 1)) - gnu_type = make_packable_type (gnu_type, false); - - /* Get and validate any specified Component_Size, but if Packed, - ignore it since the front end will have taken care of it. */ - gnu_comp_size - = validate_size (Component_Size (gnat_entity), gnu_type, - gnat_entity, - (Is_Bit_Packed_Array (gnat_entity) - ? TYPE_DECL : VAR_DECL), true, - Has_Component_Size_Clause (gnat_entity)); - - /* If the component type is a RECORD_TYPE that has a - self-referential size, use the maximum size. */ - if (!gnu_comp_size - && TREE_CODE (gnu_type) == RECORD_TYPE - && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))) - gnu_comp_size = max_size (TYPE_SIZE (gnu_type), true); - - if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_entity)) - { - tree orig_type = gnu_type; - unsigned int max_align; - - /* If an alignment is specified, use it as a cap on the - component type so that it can be honored for the whole - type. But ignore it for the original type of packed - array types. */ - if (No (Packed_Array_Type (gnat_entity)) - && Known_Alignment (gnat_entity)) - max_align = validate_alignment (Alignment (gnat_entity), - gnat_entity, 0); - else - max_align = 0; - - gnu_type - = make_type_from_size (gnu_type, gnu_comp_size, false); - if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align) - gnu_type = orig_type; - else - orig_type = gnu_type; - - gnu_type = maybe_pad_type (gnu_type, gnu_comp_size, 0, - gnat_entity, "C_PAD", false, - definition, true); - - /* If a padding record was made, declare it now since it - will never be declared otherwise. This is necessary - to ensure that its subtrees are properly marked. */ - if (gnu_type != orig_type && !DECL_P (TYPE_NAME (gnu_type))) - create_type_decl (TYPE_NAME (gnu_type), gnu_type, NULL, - true, debug_info_p, gnat_entity); - } - - if (Has_Volatile_Components (Base_Type (gnat_entity))) - gnu_type = build_qualified_type (gnu_type, - (TYPE_QUALS (gnu_type) - | TYPE_QUAL_VOLATILE)); } /* Compute the maximum size of the array in units and bits. */ @@ -2465,7 +2365,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* ??? create_type_decl is not invoked on the inner types so the MULT_EXPR node built above will never be marked. */ - mark_visited (&TYPE_SIZE_UNIT (gnu_arr_type)); + MARK_VISITED (TYPE_SIZE_UNIT (gnu_arr_type)); } } @@ -3058,9 +2958,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } /* When the subtype has discriminants and these discriminants affect - the initial shape it has inherited, factor them in. But for the - of an Unchecked_Union (it must be an Itype), just return the type. - + the initial shape it has inherited, factor them in. But for an + Unchecked_Union (it must be an Itype), just return the type. We can't just test Is_Constrained because private subtypes without discriminants of types with discriminants with default expressions are Is_Constrained but aren't constrained! */ @@ -3074,43 +2973,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) { tree gnu_subst_list = build_subst_list (gnat_entity, gnat_base_type, definition); - tree gnu_pos_list, gnu_field_list = NULL_TREE; - tree gnu_unpad_base_type, t; + tree gnu_unpad_base_type, gnu_rep_part, gnu_variant_part, t; + tree gnu_variant_list, gnu_pos_list, gnu_field_list = NULL_TREE; + bool selected_variant = false; Entity_Id gnat_field; gnu_type = make_node (RECORD_TYPE); TYPE_NAME (gnu_type) = gnu_entity_name; /* Set the size, alignment and alias set of the new type to - match that of the old one, doing required substitutions. - We do it this early because we need the size of the new - type below to discard old fields if necessary. */ - TYPE_SIZE (gnu_type) = TYPE_SIZE (gnu_base_type); - TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_base_type); - SET_TYPE_ADA_SIZE (gnu_type, TYPE_ADA_SIZE (gnu_base_type)); - TYPE_ALIGN (gnu_type) = TYPE_ALIGN (gnu_base_type); - relate_alias_sets (gnu_type, gnu_base_type, ALIAS_SET_COPY); - - if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))) - for (t = gnu_subst_list; t; t = TREE_CHAIN (t)) - TYPE_SIZE (gnu_type) - = substitute_in_expr (TYPE_SIZE (gnu_type), - TREE_PURPOSE (t), - TREE_VALUE (t)); - - if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (gnu_type))) - for (t = gnu_subst_list; t; t = TREE_CHAIN (t)) - TYPE_SIZE_UNIT (gnu_type) - = substitute_in_expr (TYPE_SIZE_UNIT (gnu_type), - TREE_PURPOSE (t), - TREE_VALUE (t)); - - if (CONTAINS_PLACEHOLDER_P (TYPE_ADA_SIZE (gnu_type))) - for (t = gnu_subst_list; t; t = TREE_CHAIN (t)) - SET_TYPE_ADA_SIZE - (gnu_type, substitute_in_expr (TYPE_ADA_SIZE (gnu_type), - TREE_PURPOSE (t), - TREE_VALUE (t))); + match that of the old one, doing required substitutions. */ + copy_and_substitute_in_size (gnu_type, gnu_base_type, + gnu_subst_list); if (TREE_CODE (gnu_base_type) == RECORD_TYPE && TYPE_IS_PADDING_P (gnu_base_type)) @@ -3118,10 +2992,57 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) else gnu_unpad_base_type = gnu_base_type; + /* Look for a REP part in the base type. */ + gnu_rep_part = get_rep_part (gnu_unpad_base_type); + + /* Look for a variant part in the base type. */ + gnu_variant_part = get_variant_part (gnu_unpad_base_type); + + /* If there is a variant part, we must compute whether the + constraints statically select a particular variant. If + so, we simply drop the qualified union and flatten the + list of fields. Otherwise we'll build a new qualified + union for the variants that are still relevant. */ + if (gnu_variant_part) + { + gnu_variant_list + = build_variant_list (TREE_TYPE (gnu_variant_part), + gnu_subst_list, NULL_TREE); + + /* If all the qualifiers are unconditionally true, the + innermost variant is statically selected. */ + selected_variant = true; + for (t = gnu_variant_list; t; t = TREE_CHAIN (t)) + if (!integer_onep (TREE_VEC_ELT (TREE_VALUE (t), 1))) + { + selected_variant = false; + break; + } + + /* Otherwise, create the new variants. */ + if (!selected_variant) + for (t = gnu_variant_list; t; t = TREE_CHAIN (t)) + { + tree old_variant = TREE_PURPOSE (t); + tree new_variant = make_node (RECORD_TYPE); + TYPE_NAME (new_variant) + = DECL_NAME (TYPE_NAME (old_variant)); + copy_and_substitute_in_size (new_variant, old_variant, + gnu_subst_list); + TREE_VEC_ELT (TREE_VALUE (t), 2) = new_variant; + } + } + else + { + gnu_variant_list = NULL_TREE; + selected_variant = false; + } + gnu_pos_list - = compute_field_positions (gnu_unpad_base_type, NULL_TREE, - size_zero_node, bitsize_zero_node, - BIGGEST_ALIGNMENT); + = build_position_list (gnu_unpad_base_type, + gnu_variant_list && !selected_variant, + size_zero_node, bitsize_zero_node, + BIGGEST_ALIGNMENT, NULL_TREE); for (gnat_field = First_Entity (gnat_entity); Present (gnat_field); @@ -3139,16 +3060,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) = Original_Record_Component (gnat_field); tree gnu_old_field = gnat_to_gnu_field_decl (gnat_old_field); - tree gnu_offset - = TREE_VALUE - (purpose_member (gnu_old_field, gnu_pos_list)); - tree gnu_pos = TREE_PURPOSE (gnu_offset); - tree gnu_bitpos = TREE_VALUE (TREE_VALUE (gnu_offset)); - tree gnu_field, gnu_field_type, gnu_size, gnu_new_pos; - tree gnu_last = NULL_TREE; - unsigned int offset_align - = tree_low_cst - (TREE_PURPOSE (TREE_VALUE (gnu_offset)), 1); + tree gnu_context = DECL_CONTEXT (gnu_old_field); + tree gnu_field, gnu_field_type, gnu_size; + tree gnu_cont_type, gnu_last = NULL_TREE; /* If the type is the same, retrieve the GCC type from the old field to take into account possible adjustments. */ @@ -3192,67 +3106,50 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) else gnu_size = TYPE_SIZE (gnu_field_type); - if (CONTAINS_PLACEHOLDER_P (gnu_pos)) - for (t = gnu_subst_list; t; t = TREE_CHAIN (t)) - gnu_pos = substitute_in_expr (gnu_pos, - TREE_PURPOSE (t), - TREE_VALUE (t)); - - /* If the position is now a constant, we can set it as the - position of the field when we make it. Otherwise, we - need to deal with it specially below. */ - if (TREE_CONSTANT (gnu_pos)) + /* If the context of the old field is the base type or its + REP part (if any), put the field directly in the new + type; otherwise look up the context in the variant list + and put the field either in the new type if there is a + selected variant or in one of the new variants. */ + if (gnu_context == gnu_unpad_base_type + || (gnu_rep_part + && gnu_context == TREE_TYPE (gnu_rep_part))) + gnu_cont_type = gnu_type; + else { - gnu_new_pos = bit_from_pos (gnu_pos, gnu_bitpos); - - /* Discard old fields that are outside the new type. - This avoids confusing code scanning it to decide - how to pass it to functions on some platforms. */ - if (TREE_CODE (gnu_new_pos) == INTEGER_CST - && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST - && !integer_zerop (gnu_size) - && !tree_int_cst_lt (gnu_new_pos, - TYPE_SIZE (gnu_type))) + t = purpose_member (gnu_context, gnu_variant_list); + if (t) + { + if (selected_variant) + gnu_cont_type = gnu_type; + else + gnu_cont_type = TREE_VEC_ELT (TREE_VALUE (t), 2); + } + else + /* The front-end may pass us "ghost" components if + it fails to recognize that a constrained subtype + is statically constrained. Discard them. */ continue; } - else - gnu_new_pos = NULL_TREE; + /* Now create the new field modeled on the old one. */ gnu_field - = create_field_decl - (DECL_NAME (gnu_old_field), gnu_field_type, gnu_type, - DECL_PACKED (gnu_old_field), gnu_size, gnu_new_pos, - !DECL_NONADDRESSABLE_P (gnu_old_field)); + = create_field_decl_from (gnu_old_field, gnu_field_type, + gnu_cont_type, gnu_size, + gnu_pos_list, gnu_subst_list); - if (!TREE_CONSTANT (gnu_pos)) + /* Put it in one of the new variants directly. */ + if (gnu_cont_type != gnu_type) { - normalize_offset (&gnu_pos, &gnu_bitpos, offset_align); - DECL_FIELD_OFFSET (gnu_field) = gnu_pos; - DECL_FIELD_BIT_OFFSET (gnu_field) = gnu_bitpos; - SET_DECL_OFFSET_ALIGN (gnu_field, offset_align); - DECL_SIZE (gnu_field) = gnu_size; - DECL_SIZE_UNIT (gnu_field) - = convert (sizetype, - size_binop (CEIL_DIV_EXPR, gnu_size, - bitsize_unit_node)); - layout_decl (gnu_field, DECL_OFFSET_ALIGN (gnu_field)); + TREE_CHAIN (gnu_field) = TYPE_FIELDS (gnu_cont_type); + TYPE_FIELDS (gnu_cont_type) = gnu_field; } - DECL_INTERNAL_P (gnu_field) - = DECL_INTERNAL_P (gnu_old_field); - SET_DECL_ORIGINAL_FIELD - (gnu_field, (DECL_ORIGINAL_FIELD (gnu_old_field) - ? DECL_ORIGINAL_FIELD (gnu_old_field) - : gnu_old_field)); - DECL_DISCRIMINANT_NUMBER (gnu_field) - = DECL_DISCRIMINANT_NUMBER (gnu_old_field); - TREE_THIS_VOLATILE (gnu_field) - = TREE_THIS_VOLATILE (gnu_old_field); - /* To match the layout crafted in components_to_record, if this is the _Tag or _Parent field, put it before any other fields. */ - if (gnat_name == Name_uTag || gnat_name == Name_uParent) + else if (gnat_name == Name_uTag + || gnat_name == Name_uParent) gnu_field_list = chainon (gnu_field_list, gnu_field); /* Similarly, if this is the _Controller field, put @@ -3277,6 +3174,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) save_gnu_tree (gnat_field, gnu_field, false); } + /* If there is a variant list and no selected variant, we need + to create the nest of variant parts from the old nest. */ + if (gnu_variant_list && !selected_variant) + { + tree new_variant_part + = create_variant_part_from (gnu_variant_part, + gnu_variant_list, gnu_type, + gnu_pos_list, gnu_subst_list); + TREE_CHAIN (new_variant_part) = gnu_field_list; + gnu_field_list = new_variant_part; + } + /* Now go through the entities again looking for Itypes that we have not elaborated but should (e.g., Etypes of fields that have Original_Components). */ @@ -3291,11 +3200,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_field_list = nreverse (gnu_field_list); finish_record_type (gnu_type, gnu_field_list, 2, true); - /* Finalize size and mode. */ - TYPE_SIZE (gnu_type) = variable_size (TYPE_SIZE (gnu_type)); - TYPE_SIZE_UNIT (gnu_type) - = variable_size (TYPE_SIZE_UNIT (gnu_type)); - /* See the E_Record_Type case for the rationale. */ if (Is_Tagged_Type (gnat_entity) || Is_Limited_Record (gnat_entity)) @@ -3308,13 +3212,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Fill in locations of fields. */ annotate_rep (gnat_entity, gnu_type); - /* We've built a new type, make an XVS type to show what this - is a subtype of. Some debuggers require the XVS type to be - output first, so do it in that order. */ + /* If debugging information is being written for the type, write + a record that shows what we are a subtype of and also make a + variable that indicates our size, if still variable. */ if (debug_info_p) { tree gnu_subtype_marker = make_node (RECORD_TYPE); tree gnu_unpad_base_name = TYPE_NAME (gnu_unpad_base_type); + tree gnu_size_unit = TYPE_SIZE_UNIT (gnu_type); if (TREE_CODE (gnu_unpad_base_name) == TYPE_DECL) gnu_unpad_base_name = DECL_NAME (gnu_unpad_base_name); @@ -3332,6 +3237,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) add_parallel_type (TYPE_STUB_DECL (gnu_type), gnu_subtype_marker); + + if (definition + && TREE_CODE (gnu_size_unit) != INTEGER_CST + && !CONTAINS_PLACEHOLDER_P (gnu_size_unit)) + create_var_decl (create_concat_name (gnat_entity, "XVZ"), + NULL_TREE, sizetype, gnu_size_unit, false, + false, false, false, NULL, gnat_entity); } /* Now we can finalize it. */ @@ -4631,7 +4543,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) the MULT_EXPR node built above may not be marked by the call to create_type_decl below. */ if (global_bindings_p ()) - mark_visited (&DECL_FIELD_OFFSET (gnu_field)); + MARK_VISITED (DECL_FIELD_OFFSET (gnu_field)); } } @@ -5054,6 +4966,95 @@ Gigi_Equivalent_Type (Entity_Id gnat_entity) return gnat_equiv; } +/* Return a GCC tree for a type corresponding to the component type of the + array type or subtype GNAT_ARRAY. DEFINITION is true if this component + is for an array being defined. DEBUG_INFO_P is true if we need to write + debug information for other types that we may create in the process. */ + +static tree +gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, + bool debug_info_p) +{ + tree gnu_type = gnat_to_gnu_type (Component_Type (gnat_array)); + tree gnu_comp_size; + + /* Try to get a smaller form of the component if needed. */ + if ((Is_Packed (gnat_array) + || Has_Component_Size_Clause (gnat_array)) + && !Is_Bit_Packed_Array (gnat_array) + && !Has_Aliased_Components (gnat_array) + && !Strict_Alignment (Component_Type (gnat_array)) + && TREE_CODE (gnu_type) == RECORD_TYPE + && !TYPE_IS_FAT_POINTER_P (gnu_type) + && host_integerp (TYPE_SIZE (gnu_type), 1)) + gnu_type = make_packable_type (gnu_type, false); + + if (Has_Atomic_Components (gnat_array)) + check_ok_for_atomic (gnu_type, gnat_array, true); + + /* Get and validate any specified Component_Size. */ + gnu_comp_size + = validate_size (Component_Size (gnat_array), gnu_type, gnat_array, + Is_Bit_Packed_Array (gnat_array) ? TYPE_DECL : VAR_DECL, + true, Has_Component_Size_Clause (gnat_array)); + + /* If the array has aliased components and the component size can be zero, + force at least unit size to ensure that the components have distinct + addresses. */ + if (!gnu_comp_size + && Has_Aliased_Components (gnat_array) + && (integer_zerop (TYPE_SIZE (gnu_type)) + || (TREE_CODE (gnu_type) == ARRAY_TYPE + && !TREE_CONSTANT (TYPE_SIZE (gnu_type))))) + gnu_comp_size + = size_binop (MAX_EXPR, TYPE_SIZE (gnu_type), bitsize_unit_node); + + /* If the component type is a RECORD_TYPE that has a self-referential size, + then use the maximum size for the component size. */ + if (!gnu_comp_size + && TREE_CODE (gnu_type) == RECORD_TYPE + && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))) + gnu_comp_size = max_size (TYPE_SIZE (gnu_type), true); + + /* Honor the component size. This is not needed for bit-packed arrays. */ + if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_array)) + { + tree orig_type = gnu_type; + unsigned int max_align; + + /* If an alignment is specified, use it as a cap on the component type + so that it can be honored for the whole type. But ignore it for the + original type of packed array types. */ + if (No (Packed_Array_Type (gnat_array)) && Known_Alignment (gnat_array)) + max_align = validate_alignment (Alignment (gnat_array), gnat_array, 0); + else + max_align = 0; + + gnu_type = make_type_from_size (gnu_type, gnu_comp_size, false); + if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align) + gnu_type = orig_type; + else + orig_type = gnu_type; + + gnu_type = maybe_pad_type (gnu_type, gnu_comp_size, 0, gnat_array, + "C_PAD", false, definition, true); + + /* If a padding record was made, declare it now since it will never be + declared otherwise. This is necessary to ensure that its subtrees + are properly marked. */ + if (gnu_type != orig_type && !DECL_P (TYPE_NAME (gnu_type))) + create_type_decl (TYPE_NAME (gnu_type), gnu_type, NULL, true, + debug_info_p, gnat_array); + } + + if (Has_Volatile_Components (Base_Type (gnat_array))) + gnu_type + = build_qualified_type (gnu_type, + TYPE_QUALS (gnu_type) | TYPE_QUAL_VOLATILE); + + return gnu_type; +} + /* Return a GCC tree for a parameter corresponding to GNAT_PARAM and using MECH as its passing mechanism, to be placed in the parameter list built for GNAT_SUBPROG. Assume a foreign convention for the @@ -5522,37 +5523,6 @@ relate_alias_sets (tree gnu_new_type, tree gnu_old_type, enum alias_set_op op) record_component_aliases (gnu_new_type); } -/* Return a TREE_LIST describing the substitutions needed to reflect the - discriminant substitutions from GNAT_TYPE to GNAT_SUBTYPE. They can - be in any order. TREE_PURPOSE gives the tree for the discriminant and - TREE_VALUE is the replacement value. They are in the form of operands - to substitute_in_expr. DEFINITION is true if this is for a definition - of GNAT_SUBTYPE. */ - -static tree -build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition) -{ - tree gnu_list = NULL_TREE; - Entity_Id gnat_discrim; - Node_Id gnat_value; - - for (gnat_discrim = First_Stored_Discriminant (gnat_type), - gnat_value = First_Elmt (Stored_Constraint (gnat_subtype)); - Present (gnat_discrim); - gnat_discrim = Next_Stored_Discriminant (gnat_discrim), - gnat_value = Next_Elmt (gnat_value)) - /* Ignore access discriminants. */ - if (!Is_Access_Type (Etype (Node (gnat_value)))) - gnu_list = tree_cons (gnat_to_gnu_field_decl (gnat_discrim), - elaborate_expression - (Node (gnat_value), gnat_subtype, - get_entity_name (gnat_discrim), definition, - true, false), - gnu_list); - - return gnu_list; -} - /* Return true if the size represented by GNU_SIZE can be handled by an allocation. If STATIC_P is true, consider only what can be done with a static allocation. */ @@ -6239,7 +6209,7 @@ maybe_pad_type (tree type, tree size, unsigned int align, add_parallel_type (TYPE_STUB_DECL (record), marker); - if (size && TREE_CODE (size) != INTEGER_CST && definition) + if (definition && size && TREE_CODE (size) != INTEGER_CST) create_var_decl (concat_name (name, "XVZ"), NULL_TREE, sizetype, TYPE_SIZE_UNIT (record), false, false, false, false, NULL, gnat_entity); @@ -6257,7 +6227,9 @@ maybe_pad_type (tree type, tree size, unsigned int align, if (align) orig_size = round_up (orig_size, align); - if (size && Present (gnat_entity) + if (Present (gnat_entity) + && size + && TREE_CODE (size) != MAX_EXPR && !operand_equal_p (size, orig_size, 0) && !(TREE_CODE (size) == INTEGER_CST && TREE_CODE (orig_size) == INTEGER_CST @@ -6278,15 +6250,17 @@ maybe_pad_type (tree type, tree size, unsigned int align, /* Generate message only for entities that come from source, since if we have an entity created by expansion, the message will be generated for some other corresponding source entity. */ - if (Comes_From_Source (gnat_entity) && Present (gnat_error_node)) - post_error_ne_tree ("{^ }bits of & unused?", gnat_error_node, - gnat_entity, - size_diffop (size, orig_size)); - - else if (*name_trailer == 'C' && !Is_Internal (gnat_entity)) - post_error_ne_tree ("component of& padded{ by ^ bits}?", - gnat_entity, gnat_entity, - size_diffop (size, orig_size)); + if (Comes_From_Source (gnat_entity)) + { + if (Present (gnat_error_node)) + post_error_ne_tree ("{^ }bits of & unused?", + gnat_error_node, gnat_entity, + size_diffop (size, orig_size)); + else if (name_trailer[0] == 'C') + post_error_ne_tree ("component of& padded{ by ^ bits}?", + gnat_entity, gnat_entity, + size_diffop (size, orig_size)); + } } return record; @@ -6932,6 +6906,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, otherwise, the union type definition will be lacking the fields associated with these empty variants. */ rest_of_record_type_compilation (gnu_variant_type); + create_type_decl (TYPE_NAME (gnu_variant_type), gnu_variant_type, + NULL, true, debug_info_p, gnat_component_list); gnu_field = create_field_decl (gnu_inner_name, gnu_variant_type, gnu_union_type, field_packed, @@ -6978,6 +6954,9 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, return; } + create_type_decl (TYPE_NAME (gnu_union_type), gnu_union_type, + NULL, true, debug_info_p, gnat_component_list); + /* Deal with packedness like in gnat_to_gnu_field. */ union_field_packed = adjust_packed (gnu_union_type, gnu_record_type, packed); @@ -7271,94 +7250,92 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref) UI_From_Int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT)); } -/* Given GNAT_ENTITY, a record type, and GNU_TYPE, its corresponding - GCC type, set Component_Bit_Offset and Esize to the position and size - used by Gigi. */ +/* Given GNAT_ENTITY, a record type, and GNU_TYPE, its corresponding GCC type, + set Component_Bit_Offset and Esize of the components to the position and + size used by Gigi. */ static void annotate_rep (Entity_Id gnat_entity, tree gnu_type) { - tree gnu_list; - tree gnu_entry; Entity_Id gnat_field; + tree gnu_list; - /* We operate by first making a list of all fields and their positions - (we can get the sizes easily at any time) by a recursive call - and then update all the sizes into the tree. */ - gnu_list = compute_field_positions (gnu_type, NULL_TREE, - size_zero_node, bitsize_zero_node, - BIGGEST_ALIGNMENT); + /* We operate by first making a list of all fields and their position (we + can get the size easily) and then update all the sizes in the tree. */ + gnu_list + = build_position_list (gnu_type, false, size_zero_node, bitsize_zero_node, + BIGGEST_ALIGNMENT, NULL_TREE); - for (gnat_field = First_Entity (gnat_entity); Present (gnat_field); + for (gnat_field = First_Entity (gnat_entity); + Present (gnat_field); gnat_field = Next_Entity (gnat_field)) - if ((Ekind (gnat_field) == E_Component - || (Ekind (gnat_field) == E_Discriminant - && !Is_Unchecked_Union (Scope (gnat_field))))) + if (Ekind (gnat_field) == E_Component + || (Ekind (gnat_field) == E_Discriminant + && !Is_Unchecked_Union (Scope (gnat_field)))) { - tree parent_offset = bitsize_zero_node; - - gnu_entry = purpose_member (gnat_to_gnu_field_decl (gnat_field), - gnu_list); + tree parent_offset, t; - if (gnu_entry) + t = purpose_member (gnat_to_gnu_field_decl (gnat_field), gnu_list); + if (t) { if (type_annotate_only && Is_Tagged_Type (gnat_entity)) { - /* In this mode the tag and parent components have not been + /* In this mode the tag and parent components are not generated, so we add the appropriate offset to each component. For a component appearing in the current extension, the offset is the size of the parent. */ - if (Is_Derived_Type (gnat_entity) - && Original_Record_Component (gnat_field) == gnat_field) - parent_offset - = UI_To_gnu (Esize (Etype (Base_Type (gnat_entity))), - bitsizetype); - else - parent_offset = bitsize_int (POINTER_SIZE); + if (Is_Derived_Type (gnat_entity) + && Original_Record_Component (gnat_field) == gnat_field) + parent_offset + = UI_To_gnu (Esize (Etype (Base_Type (gnat_entity))), + bitsizetype); + else + parent_offset = bitsize_int (POINTER_SIZE); } + else + parent_offset = bitsize_zero_node; - Set_Component_Bit_Offset - (gnat_field, - annotate_value - (size_binop (PLUS_EXPR, - bit_from_pos (TREE_PURPOSE (TREE_VALUE (gnu_entry)), - TREE_VALUE (TREE_VALUE - (TREE_VALUE (gnu_entry)))), - parent_offset))); + Set_Component_Bit_Offset + (gnat_field, + annotate_value + (size_binop (PLUS_EXPR, + bit_from_pos (TREE_VEC_ELT (TREE_VALUE (t), 0), + TREE_VEC_ELT (TREE_VALUE (t), 2)), + parent_offset))); Set_Esize (gnat_field, - annotate_value (DECL_SIZE (TREE_PURPOSE (gnu_entry)))); + annotate_value (DECL_SIZE (TREE_PURPOSE (t)))); } - else if (Is_Tagged_Type (gnat_entity) - && Is_Derived_Type (gnat_entity)) + else if (Is_Tagged_Type (gnat_entity) && Is_Derived_Type (gnat_entity)) { - /* If there is no gnu_entry, this is an inherited component whose + /* If there is no entry, this is an inherited component whose position is the same as in the parent type. */ Set_Component_Bit_Offset (gnat_field, Component_Bit_Offset (Original_Record_Component (gnat_field))); + Set_Esize (gnat_field, Esize (Original_Record_Component (gnat_field))); } } } - -/* Scan all fields in GNU_TYPE and build entries where TREE_PURPOSE is the - FIELD_DECL and TREE_VALUE a TREE_LIST with TREE_PURPOSE being the byte - position and TREE_VALUE being a TREE_LIST with TREE_PURPOSE the value to be - placed into DECL_OFFSET_ALIGN and TREE_VALUE the bit position. GNU_POS is - to be added to the position, GNU_BITPOS to the bit position, OFFSET_ALIGN is - the present value of DECL_OFFSET_ALIGN and GNU_LIST is a list of the entries - so far. */ + +/* Scan all fields in GNU_TYPE and return a TREE_LIST where TREE_PURPOSE is + the FIELD_DECL and TREE_VALUE a TREE_VEC containing the byte position, the + value to be placed into DECL_OFFSET_ALIGN and the bit position. The list + of fields is flattened, except for variant parts if DO_NOT_FLATTEN_VARIANT + is set to true. GNU_POS is to be added to the position, GNU_BITPOS to the + bit position, OFFSET_ALIGN is the present offset alignment. GNU_LIST is a + pre-existing list to be chained to the newly created entries. */ static tree -compute_field_positions (tree gnu_type, tree gnu_list, tree gnu_pos, - tree gnu_bitpos, unsigned int offset_align) +build_position_list (tree gnu_type, bool do_not_flatten_variant, tree gnu_pos, + tree gnu_bitpos, unsigned int offset_align, tree gnu_list) { tree gnu_field; - tree gnu_result = gnu_list; - for (gnu_field = TYPE_FIELDS (gnu_type); gnu_field; + for (gnu_field = TYPE_FIELDS (gnu_type); + gnu_field; gnu_field = TREE_CHAIN (gnu_field)) { tree gnu_our_bitpos = size_binop (PLUS_EXPR, gnu_bitpos, @@ -7367,23 +7344,112 @@ compute_field_positions (tree gnu_type, tree gnu_list, tree gnu_pos, DECL_FIELD_OFFSET (gnu_field)); unsigned int our_offset_align = MIN (offset_align, DECL_OFFSET_ALIGN (gnu_field)); + tree v = make_tree_vec (3); - gnu_result - = tree_cons (gnu_field, - tree_cons (gnu_our_offset, - tree_cons (size_int (our_offset_align), - gnu_our_bitpos, NULL_TREE), - NULL_TREE), - gnu_result); + TREE_VEC_ELT (v, 0) = gnu_our_offset; + TREE_VEC_ELT (v, 1) = size_int (our_offset_align); + TREE_VEC_ELT (v, 2) = gnu_our_bitpos; + gnu_list = tree_cons (gnu_field, v, gnu_list); + /* Recurse on internal fields, flattening the nested fields except for + those in the variant part, if requested. */ if (DECL_INTERNAL_P (gnu_field)) - gnu_result - = compute_field_positions (TREE_TYPE (gnu_field), gnu_result, + { + tree gnu_field_type = TREE_TYPE (gnu_field); + if (do_not_flatten_variant + && TREE_CODE (gnu_field_type) == QUAL_UNION_TYPE) + gnu_list + = build_position_list (gnu_field_type, do_not_flatten_variant, + size_zero_node, bitsize_zero_node, + BIGGEST_ALIGNMENT, gnu_list); + else + gnu_list + = build_position_list (gnu_field_type, do_not_flatten_variant, gnu_our_offset, gnu_our_bitpos, - our_offset_align); + our_offset_align, gnu_list); + } + } + + return gnu_list; +} + +/* Return a TREE_LIST describing the substitutions needed to reflect the + discriminant substitutions from GNAT_TYPE to GNAT_SUBTYPE. They can + be in any order. TREE_PURPOSE gives the tree for the discriminant and + TREE_VALUE is the replacement value. They are in the form of operands + to SUBSTITUTE_IN_EXPR. DEFINITION is true if this is for a definition + of GNAT_SUBTYPE. */ + +static tree +build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition) +{ + tree gnu_list = NULL_TREE; + Entity_Id gnat_discrim; + Node_Id gnat_value; + + for (gnat_discrim = First_Stored_Discriminant (gnat_type), + gnat_value = First_Elmt (Stored_Constraint (gnat_subtype)); + Present (gnat_discrim); + gnat_discrim = Next_Stored_Discriminant (gnat_discrim), + gnat_value = Next_Elmt (gnat_value)) + /* Ignore access discriminants. */ + if (!Is_Access_Type (Etype (Node (gnat_value)))) + gnu_list = tree_cons (gnat_to_gnu_field_decl (gnat_discrim), + elaborate_expression + (Node (gnat_value), gnat_subtype, + get_entity_name (gnat_discrim), definition, + true, false), + gnu_list); + + return gnu_list; +} + +/* Scan all fields in QUAL_UNION_TYPE and return a TREE_LIST describing the + variants of QUAL_UNION_TYPE that are still relevant after applying the + substitutions described in SUBST_LIST. TREE_PURPOSE is the type of the + variant and TREE_VALUE is a TREE_VEC containing the field, the new value + of the qualifier and NULL_TREE respectively. GNU_LIST is a pre-existing + list to be chained to the newly created entries. */ + +static tree +build_variant_list (tree qual_union_type, tree subst_list, tree gnu_list) +{ + tree gnu_field; + + for (gnu_field = TYPE_FIELDS (qual_union_type); + gnu_field; + gnu_field = TREE_CHAIN (gnu_field)) + { + tree t, qual = DECL_QUALIFIER (gnu_field); + + for (t = subst_list; t; t = TREE_CHAIN (t)) + qual = SUBSTITUTE_IN_EXPR (qual, TREE_PURPOSE (t), TREE_VALUE (t)); + + /* If the new qualifier is not unconditionally false, its variant may + still be accessed. */ + if (!integer_zerop (qual)) + { + tree variant_type = TREE_TYPE (gnu_field), variant_subpart; + tree v = make_tree_vec (3); + TREE_VEC_ELT (v, 0) = gnu_field; + TREE_VEC_ELT (v, 1) = qual; + TREE_VEC_ELT (v, 2) = NULL_TREE; + gnu_list = tree_cons (variant_type, v, gnu_list); + + /* Recurse on the variant subpart of the variant, if any. */ + variant_subpart = get_variant_part (variant_type); + if (variant_subpart) + gnu_list = build_variant_list (TREE_TYPE (variant_subpart), + subst_list, gnu_list); + + /* If the new qualifier is unconditionally true, the subsequent + variants cannot be accessed. */ + if (integer_onep (qual)) + break; + } } - return gnu_result; + return gnu_list; } /* UINT_SIZE is a Uint giving the specified size for an object of GNU_TYPE @@ -7810,6 +7876,11 @@ check_ok_for_atomic (tree object, Entity_Id gnat_entity, bool comp_p) OBJECT is either a type or a decl. */ if (TYPE_P (object)) { + /* If this is an anonymous base type, nothing to check. Error will be + reported on the source type. */ + if (!Comes_From_Source (gnat_entity)) + return; + mode = TYPE_MODE (object); align = TYPE_ALIGN (object); size = TYPE_SIZE (object); @@ -7891,6 +7962,253 @@ compatible_signatures_p (tree ftype1, tree ftype2) return 1; } +/* Return a FIELD_DECL node modeled on OLD_FIELD. FIELD_TYPE is its type + and RECORD_TYPE is the type of the parent. If SIZE is nonzero, it is the + specified size for this field. POS_LIST is a position list describing + the layout of OLD_FIELD and SUBST_LIST a substitution list to be applied + to this layout. */ + +static tree +create_field_decl_from (tree old_field, tree field_type, tree record_type, + tree size, tree pos_list, tree subst_list) +{ + tree t = TREE_VALUE (purpose_member (old_field, pos_list)); + tree pos = TREE_VEC_ELT (t, 0), bitpos = TREE_VEC_ELT (t, 2); + unsigned int offset_align = tree_low_cst (TREE_VEC_ELT (t, 1), 1); + tree new_pos, new_field; + + if (CONTAINS_PLACEHOLDER_P (pos)) + for (t = subst_list; t; t = TREE_CHAIN (t)) + pos = SUBSTITUTE_IN_EXPR (pos, TREE_PURPOSE (t), TREE_VALUE (t)); + + /* If the position is now a constant, we can set it as the position of the + field when we make it. Otherwise, we need to deal with it specially. */ + if (TREE_CONSTANT (pos)) + new_pos = bit_from_pos (pos, bitpos); + else + new_pos = NULL_TREE; + + new_field + = create_field_decl (DECL_NAME (old_field), field_type, record_type, + DECL_PACKED (old_field), size, new_pos, + !DECL_NONADDRESSABLE_P (old_field)); + + if (!new_pos) + { + normalize_offset (&pos, &bitpos, offset_align); + DECL_FIELD_OFFSET (new_field) = pos; + DECL_FIELD_BIT_OFFSET (new_field) = bitpos; + SET_DECL_OFFSET_ALIGN (new_field, offset_align); + DECL_SIZE (new_field) = size; + DECL_SIZE_UNIT (new_field) + = convert (sizetype, + size_binop (CEIL_DIV_EXPR, size, bitsize_unit_node)); + layout_decl (new_field, DECL_OFFSET_ALIGN (new_field)); + } + + DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); + t = DECL_ORIGINAL_FIELD (old_field); + SET_DECL_ORIGINAL_FIELD (new_field, t ? t : old_field); + DECL_DISCRIMINANT_NUMBER (new_field) = DECL_DISCRIMINANT_NUMBER (old_field); + TREE_THIS_VOLATILE (new_field) = TREE_THIS_VOLATILE (old_field); + + return new_field; +} + +/* Return the REP part of RECORD_TYPE, if any. Otherwise return NULL. */ + +static tree +get_rep_part (tree record_type) +{ + tree field = TYPE_FIELDS (record_type); + + /* The REP part is the first field, internal, another record, and its name + doesn't start with an underscore (i.e. is not generated by the FE). */ + if (DECL_INTERNAL_P (field) + && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + && IDENTIFIER_POINTER (DECL_NAME (field)) [0] != '_') + return field; + + return NULL_TREE; +} + +/* Return the variant part of RECORD_TYPE, if any. Otherwise return NULL. */ + +static tree +get_variant_part (tree record_type) +{ + tree field; + + /* The variant part is the only internal field that is a qualified union. */ + for (field = TYPE_FIELDS (record_type); field; field = TREE_CHAIN (field)) + if (DECL_INTERNAL_P (field) + && TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE) + return field; + + return NULL_TREE; +} + +/* Return a new variant part modeled on OLD_VARIANT_PART. VARIANT_LIST is + the list of variants to be used and RECORD_TYPE is the type of the parent. + POS_LIST is a position list describing the layout of fields present in + OLD_VARIANT_PART and SUBST_LIST a substitution list to be applied to this + layout. */ + +static tree +create_variant_part_from (tree old_variant_part, tree variant_list, + tree record_type, tree pos_list, tree subst_list) +{ + tree offset = DECL_FIELD_OFFSET (old_variant_part); + tree bitpos = DECL_FIELD_BIT_OFFSET (old_variant_part); + tree old_union_type = TREE_TYPE (old_variant_part); + tree new_union_type, new_variant_part, t; + tree union_field_list = NULL_TREE; + + /* First create the type of the variant part from that of the old one. */ + new_union_type = make_node (QUAL_UNION_TYPE); + TYPE_NAME (new_union_type) = DECL_NAME (TYPE_NAME (old_union_type)); + + /* If the position of the variant part is constant, subtract it from the + size of the type of the parent to get the new size. This manual CSE + reduces the code size when not optimizing. */ + if (TREE_CODE (offset) == INTEGER_CST && TREE_CODE (bitpos) == INTEGER_CST) + { + tree first_bit = bit_from_pos (offset, bitpos); + TYPE_SIZE (new_union_type) + = size_binop (MINUS_EXPR, TYPE_SIZE (record_type), first_bit); + TYPE_SIZE_UNIT (new_union_type) + = size_binop (MINUS_EXPR, TYPE_SIZE_UNIT (record_type), + byte_from_pos (offset, bitpos)); + SET_TYPE_ADA_SIZE (new_union_type, + size_binop (MINUS_EXPR, TYPE_ADA_SIZE (record_type), + first_bit)); + TYPE_ALIGN (new_union_type) = TYPE_ALIGN (old_union_type); + relate_alias_sets (new_union_type, old_union_type, ALIAS_SET_COPY); + } + else + copy_and_substitute_in_size (new_union_type, old_union_type, subst_list); + + /* Now finish up the new variants and populate the union type. */ + for (t = variant_list; t; t = TREE_CHAIN (t)) + { + tree old_field = TREE_VEC_ELT (TREE_VALUE (t), 0), new_field; + tree old_variant, old_variant_subpart, new_variant, field_list; + + /* Skip variants that don't belong to this nesting level. */ + if (DECL_CONTEXT (old_field) != old_union_type) + continue; + + /* Retrieve the list of fields already added to the new variant. */ + new_variant = TREE_VEC_ELT (TREE_VALUE (t), 2); + field_list = TYPE_FIELDS (new_variant); + + /* If the old variant had a variant subpart, we need to create a new + variant subpart and add it to the field list. */ + old_variant = TREE_PURPOSE (t); + old_variant_subpart = get_variant_part (old_variant); + if (old_variant_subpart) + { + tree new_variant_subpart + = create_variant_part_from (old_variant_subpart, variant_list, + new_variant, pos_list, subst_list); + TREE_CHAIN (new_variant_subpart) = field_list; + field_list = new_variant_subpart; + } + + /* Finish up the new variant and create the field. */ + finish_record_type (new_variant, nreverse (field_list), 2, true); + compute_record_mode (new_variant); + rest_of_record_type_compilation (new_variant); + + /* No need for debug info thanks to the XVS type. */ + create_type_decl (TYPE_NAME (new_variant), new_variant, NULL, + true, false, Empty); + + new_field + = create_field_decl_from (old_field, new_variant, new_union_type, + TYPE_SIZE (new_variant), + pos_list, subst_list); + DECL_QUALIFIER (new_field) = TREE_VEC_ELT (TREE_VALUE (t), 1); + DECL_INTERNAL_P (new_field) = 1; + TREE_CHAIN (new_field) = union_field_list; + union_field_list = new_field; + } + + /* Finish up the union type and create the variant part. */ + finish_record_type (new_union_type, union_field_list, 2, true); + compute_record_mode (new_union_type); + rest_of_record_type_compilation (new_union_type); + + /* No need for debug info thanks to the XVS type. */ + create_type_decl (TYPE_NAME (new_union_type), new_union_type, NULL, + true, false, Empty); + + new_variant_part + = create_field_decl_from (old_variant_part, new_union_type, record_type, + TYPE_SIZE (new_union_type), + pos_list, subst_list); + DECL_INTERNAL_P (new_variant_part) = 1; + + /* With multiple discriminants it is possible for an inner variant to be + statically selected while outer ones are not; in this case, the list + of fields of the inner variant is not flattened and we end up with a + qualified union with a single member. Drop the useless container. */ + if (!TREE_CHAIN (union_field_list)) + { + DECL_CONTEXT (union_field_list) = record_type; + DECL_FIELD_OFFSET (union_field_list) + = DECL_FIELD_OFFSET (new_variant_part); + DECL_FIELD_BIT_OFFSET (union_field_list) + = DECL_FIELD_BIT_OFFSET (new_variant_part); + SET_DECL_OFFSET_ALIGN (union_field_list, + DECL_OFFSET_ALIGN (new_variant_part)); + new_variant_part = union_field_list; + } + + return new_variant_part; +} + +/* Copy the size (and alignment and alias set) from OLD_TYPE to NEW_TYPE, + which are both RECORD_TYPE, after applying the substitutions described + in SUBST_LIST. */ + +static void +copy_and_substitute_in_size (tree new_type, tree old_type, tree subst_list) +{ + tree t; + + TYPE_SIZE (new_type) = TYPE_SIZE (old_type); + TYPE_SIZE_UNIT (new_type) = TYPE_SIZE_UNIT (old_type); + SET_TYPE_ADA_SIZE (new_type, TYPE_ADA_SIZE (old_type)); + TYPE_ALIGN (new_type) = TYPE_ALIGN (old_type); + relate_alias_sets (new_type, old_type, ALIAS_SET_COPY); + + if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (new_type))) + for (t = subst_list; t; t = TREE_CHAIN (t)) + TYPE_SIZE (new_type) + = SUBSTITUTE_IN_EXPR (TYPE_SIZE (new_type), + TREE_PURPOSE (t), + TREE_VALUE (t)); + + if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (new_type))) + for (t = subst_list; t; t = TREE_CHAIN (t)) + TYPE_SIZE_UNIT (new_type) + = SUBSTITUTE_IN_EXPR (TYPE_SIZE_UNIT (new_type), + TREE_PURPOSE (t), + TREE_VALUE (t)); + + if (CONTAINS_PLACEHOLDER_P (TYPE_ADA_SIZE (new_type))) + for (t = subst_list; t; t = TREE_CHAIN (t)) + SET_TYPE_ADA_SIZE + (new_type, SUBSTITUTE_IN_EXPR (TYPE_ADA_SIZE (new_type), + TREE_PURPOSE (t), + TREE_VALUE (t))); + + /* Finalize the size. */ + TYPE_SIZE (new_type) = variable_size (TYPE_SIZE (new_type)); + TYPE_SIZE_UNIT (new_type) = variable_size (TYPE_SIZE_UNIT (new_type)); +} + /* Given a type T, a FIELD_DECL F, and a replacement value R, return a type with all size expressions that contain F in a PLACEHOLDER_EXPR updated by replacing F with R. diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index a6171b26578..ea1a65d485b 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -75,10 +75,19 @@ extern void set_block_for_group (tree); Get SLOC from GNAT_ENTITY. */ extern void add_decl_expr (tree gnu_decl, Entity_Id gnat_entity); -/* Mark nodes rooted at *TP with TREE_VISITED and types as having their +/* Mark nodes rooted at T with TREE_VISITED and types as having their sized gimplified. We use this to indicate all variable sizes and positions in global types may not be shared by any subprogram. */ -extern void mark_visited (tree *tp); +extern void mark_visited (tree t); + +/* This macro calls the above function but short-circuits the common + case of a constant to save time and also checks for NULL. */ + +#define MARK_VISITED(EXP) \ +do { \ + if((EXP) && !TREE_CONSTANT (EXP)) \ + mark_visited (EXP); \ +} while (0) /* Finalize any From_With_Type incomplete types. We do this after processing our compilation unit and after processing its spec, if this is a body. */ @@ -741,6 +750,10 @@ extern tree remove_conversions (tree exp, bool true_address); likewise return an expression pointing to the underlying array. */ extern tree maybe_unconstrained_array (tree exp); +/* If EXP's type is a VECTOR_TYPE, return EXP converted to the associated + TYPE_REPRESENTATIVE_ARRAY. */ +extern tree maybe_vector_array (tree exp); + /* Return an expression that does an unchecked conversion of EXPR to TYPE. If NOTRUNC_P is true, truncation operations should be suppressed. */ extern tree unchecked_convert (tree type, tree expr, bool notrunc_p); @@ -767,20 +780,6 @@ extern bool is_double_scalar_or_array (Entity_Id gnat_type, component of an aggregate type. */ extern bool type_for_nonaliased_component_p (tree gnu_type); -/* Prepare expr to be an argument of a TRUTH_NOT_EXPR or other logical - operation. - - This preparation consists of taking the ordinary - representation of an expression EXPR and producing a valid tree - boolean expression describing whether EXPR is nonzero. We could - simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1), - but we optimize comparisons, &&, ||, and !. - - The resulting type should always be the same as the input type. - This function is simpler than the corresponding C version since - the only possible operands will be things of Boolean type. */ -extern tree gnat_truthvalue_conversion (tree expr); - /* Return the base type of TYPE. */ extern tree get_base_type (tree type); @@ -956,3 +955,6 @@ extern Nat get_target_double_scalar_alignment (void); #ifndef TARGET_MALLOC64 #define TARGET_MALLOC64 0 #endif + +/* Convenient shortcuts. */ +#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE) diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 26df68de581..67823789ab3 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -521,6 +521,11 @@ gnat_print_type (FILE *file, tree node, int indent) print_node (file,"actual bounds", TYPE_ACTUAL_BOUNDS (node), indent + 4); break; + case VECTOR_TYPE: + print_node (file,"representative array", + TYPE_REPRESENTATIVE_ARRAY (node), indent + 4); + break; + case RECORD_TYPE: if (TYPE_IS_FAT_POINTER_P (node) || TYPE_CONTAINS_TEMPLATE_P (node)) print_node (file, "unconstrained array", diff --git a/gcc/ada/gcc-interface/targtyps.c b/gcc/ada/gcc-interface/targtyps.c index 716550e397f..9bc8f0e42ec 100644 --- a/gcc/ada/gcc-interface/targtyps.c +++ b/gcc/ada/gcc-interface/targtyps.c @@ -160,10 +160,21 @@ get_target_maximum_default_alignment (void) handy and what alignment it honors). In the meantime, resort to malloc considerations only. */ +/* Account for MALLOC_OBSERVABLE_ALIGNMENTs here. Use this or the ABI + guaranteed alignment if greater. */ + +#ifdef MALLOC_OBSERVABLE_ALIGNMENT +#define MALLOC_ALIGNMENT MALLOC_OBSERVABLE_ALIGNMENT +#else +#define MALLOC_OBSERVABLE_ALIGNMENT (2 * LONG_TYPE_SIZE) +#define MALLOC_ALIGNMENT \ + MAX (MALLOC_ABI_ALIGNMENT, MALLOC_OBSERVABLE_ALIGNMENT) +#endif + Pos get_target_default_allocator_alignment (void) { - return MALLOC_ABI_ALIGNMENT / BITS_PER_UNIT; + return MALLOC_ALIGNMENT / BITS_PER_UNIT; } /* Standard'Maximum_Allowed_Alignment. Maximum alignment that we may diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index a90a7a060bc..d94d1f45bfc 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -217,7 +217,7 @@ static tree maybe_implicit_deref (tree); static tree gnat_stabilize_reference (tree, bool); static tree gnat_stabilize_reference_1 (tree, bool); static void set_expr_location_from_node (tree, Node_Id); -static int lvalue_required_p (Node_Id, tree, int); +static int lvalue_required_p (Node_Id, tree, bool, bool); /* Hooks for debug info back-ends, only supported and used in a restricted set of configurations. */ @@ -659,8 +659,10 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name, /* Return a positive value if an lvalue is required for GNAT_NODE. GNU_TYPE is the type that will be used for GNAT_NODE in the - translated GNU tree. ALIASED indicates whether the underlying - object represented by GNAT_NODE is aliased in the Ada sense. + translated GNU tree. CONSTANT indicates whether the underlying + object represented by GNAT_NODE is constant in the Ada sense, + ALIASED whether it is aliased (but the latter doesn't affect + the outcome if CONSTANT is not true). The function climbs up the GNAT tree starting from the node and returns 1 upon encountering a node that effectively requires an @@ -668,7 +670,8 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name, usage in non purely binary logic contexts. */ static int -lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased) +lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant, + bool aliased) { Node_Id gnat_parent = Parent (gnat_node), gnat_temp; @@ -683,7 +686,12 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased) return id == Attr_Address || id == Attr_Access || id == Attr_Unchecked_Access - || id == Attr_Unrestricted_Access; + || id == Attr_Unrestricted_Access + || id == Attr_Bit_Position + || id == Attr_Position + || id == Attr_First_Bit + || id == Attr_Last_Bit + || id == Attr_Bit; } case N_Parameter_Association: @@ -714,11 +722,11 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased) return 0; aliased |= Has_Aliased_Components (Etype (gnat_node)); - return lvalue_required_p (gnat_parent, gnu_type, aliased); + return lvalue_required_p (gnat_parent, gnu_type, constant, aliased); case N_Selected_Component: aliased |= Is_Aliased (Entity (Selector_Name (gnat_parent))); - return lvalue_required_p (gnat_parent, gnu_type, aliased); + return lvalue_required_p (gnat_parent, gnu_type, constant, aliased); case N_Object_Renaming_Declaration: /* We need to make a real renaming only if the constant object is @@ -726,7 +734,8 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased) optimize and return the rvalue. We make an exception if the object is an identifier since in this case the rvalue can be propagated attached to the CONST_DECL. */ - return (aliased != 0 + return (!constant + || aliased /* This should match the constant case of the renaming code. */ || Is_Composite_Type (Underlying_Type (Etype (Name (gnat_parent)))) @@ -741,8 +750,9 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased) case N_Assignment_Statement: /* We cannot use a constructor if the LHS is an atomic object because the actual assignment might end up being done component-wise. */ - return Is_Composite_Type (Underlying_Type (Etype (gnat_node))) - && Is_Atomic (Entity (Name (gnat_parent))); + return (Name (gnat_parent) == gnat_node + || (Is_Composite_Type (Underlying_Type (Etype (gnat_node))) + && Is_Atomic (Entity (Name (gnat_parent))))); default: return 0; @@ -851,7 +861,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) && !Is_Imported (gnat_temp) && Present (Address_Clause (gnat_temp))) { - require_lvalue = lvalue_required_p (gnat_node, gnu_result_type, + require_lvalue = lvalue_required_p (gnat_node, gnu_result_type, true, Is_Aliased (gnat_temp)); use_constant_initializer = !require_lvalue; } @@ -957,7 +967,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) the CST value if an lvalue is not required. Evaluate this now if we have not already done so. */ if (object && require_lvalue < 0) - require_lvalue = lvalue_required_p (gnat_node, gnu_result_type, + require_lvalue = lvalue_required_p (gnat_node, gnu_result_type, true, Is_Aliased (gnat_temp)); if (!object || !require_lvalue) @@ -2931,6 +2941,12 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) gnu_result = convert (TREE_TYPE (gnu_actual), gnu_result); } + /* Undo wrapping of boolean rvalues. */ + if (TREE_CODE (gnu_actual) == NE_EXPR + && TREE_CODE (get_base_type (TREE_TYPE (gnu_actual))) + == BOOLEAN_TYPE + && integer_zerop (TREE_OPERAND (gnu_actual, 1))) + gnu_actual = TREE_OPERAND (gnu_actual, 0); gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_actual, gnu_result); set_expr_location_from_node (gnu_result, gnat_node); @@ -3454,64 +3470,55 @@ unchecked_conversion_lhs_nop (Node_Id gnat_node) return false; } -/* This function is the driver of the GNAT to GCC tree transformation - process. It is the entry point of the tree transformer. GNAT_NODE is the - root of some GNAT tree. Return the root of the corresponding GCC tree. - If this is an expression, return the GCC equivalent of the expression. If - it is a statement, return the statement. In the case when called for a - statement, it may also add statements to the current statement group, in - which case anything it returns is to be interpreted as occurring after - anything `it already added. */ +/* This function is the driver of the GNAT to GCC tree transformation process. + It is the entry point of the tree transformer. GNAT_NODE is the root of + some GNAT tree. Return the root of the corresponding GCC tree. If this + is an expression, return the GCC equivalent of the expression. If this + is a statement, return the statement or add it to the current statement + group, in which case anything returned is to be interpreted as occurring + after anything added. */ tree gnat_to_gnu (Node_Id gnat_node) { + const Node_Kind kind = Nkind (gnat_node); bool went_into_elab_proc = false; tree gnu_result = error_mark_node; /* Default to no value. */ tree gnu_result_type = void_type_node; - tree gnu_expr; - tree gnu_lhs, gnu_rhs; + tree gnu_expr, gnu_lhs, gnu_rhs; Node_Id gnat_temp; /* Save node number for error message and set location information. */ error_gnat_node = gnat_node; Sloc_to_locus (Sloc (gnat_node), &input_location); - if (type_annotate_only - && IN (Nkind (gnat_node), N_Statement_Other_Than_Procedure_Call)) + /* If this node is a statement and we are only annotating types, return an + empty statement list. */ + if (type_annotate_only && IN (kind, N_Statement_Other_Than_Procedure_Call)) return alloc_stmt_list (); - /* If this node is a non-static subexpression and we are only - annotating types, make this into a NULL_EXPR. */ + /* If this node is a non-static subexpression and we are only annotating + types, make this into a NULL_EXPR. */ if (type_annotate_only - && IN (Nkind (gnat_node), N_Subexpr) - && Nkind (gnat_node) != N_Identifier + && IN (kind, N_Subexpr) + && kind != N_Identifier && !Compile_Time_Known_Value (gnat_node)) return build1 (NULL_EXPR, get_unpadded_type (Etype (gnat_node)), build_call_raise (CE_Range_Check_Failed, gnat_node, N_Raise_Constraint_Error)); - /* If this is a Statement and we are at top level, it must be part of the - elaboration procedure, so mark us as being in that procedure and push our - context. - - If we are in the elaboration procedure, check if we are violating a - No_Elaboration_Code restriction by having a statement there. */ - if ((IN (Nkind (gnat_node), N_Statement_Other_Than_Procedure_Call) - && Nkind (gnat_node) != N_Null_Statement - && Nkind (gnat_node) != N_SCIL_Dispatch_Table_Object_Init - && Nkind (gnat_node) != N_SCIL_Dispatch_Table_Tag_Init - && Nkind (gnat_node) != N_SCIL_Dispatching_Call - && Nkind (gnat_node) != N_SCIL_Tag_Init) - || Nkind (gnat_node) == N_Procedure_Call_Statement - || Nkind (gnat_node) == N_Label - || Nkind (gnat_node) == N_Implicit_Label_Declaration - || Nkind (gnat_node) == N_Handled_Sequence_Of_Statements - || ((Nkind (gnat_node) == N_Raise_Constraint_Error - || Nkind (gnat_node) == N_Raise_Storage_Error - || Nkind (gnat_node) == N_Raise_Program_Error) - && (Ekind (Etype (gnat_node)) == E_Void))) + if ((IN (kind, N_Statement_Other_Than_Procedure_Call) + && !IN (kind, N_SCIL_Node) + && kind != N_Null_Statement) + || kind == N_Procedure_Call_Statement + || kind == N_Label + || kind == N_Implicit_Label_Declaration + || kind == N_Handled_Sequence_Of_Statements + || (IN (kind, N_Raise_xxx_Error) && Ekind (Etype (gnat_node)) == E_Void)) { + /* If this is a statement and we are at top level, it must be part of + the elaboration procedure, so mark us as being in that procedure + and push our context. */ if (!current_function_decl) { current_function_decl = TREE_VALUE (gnu_elab_proc_stack); @@ -3520,18 +3527,19 @@ gnat_to_gnu (Node_Id gnat_node) went_into_elab_proc = true; } - /* Don't check for a possible No_Elaboration_Code restriction violation - on N_Handled_Sequence_Of_Statements, as we want to signal an error on + /* If we are in the elaboration procedure, check if we are violating a + No_Elaboration_Code restriction by having a statement there. Don't + check for a possible No_Elaboration_Code restriction violation on + N_Handled_Sequence_Of_Statements, as we want to signal an error on every nested real statement instead. This also avoids triggering spurious errors on dummy (empty) sequences created by the front-end for package bodies in some cases. */ - if (current_function_decl == TREE_VALUE (gnu_elab_proc_stack) - && Nkind (gnat_node) != N_Handled_Sequence_Of_Statements) + && kind != N_Handled_Sequence_Of_Statements) Check_Elaboration_Code_Allowed (gnat_node); } - switch (Nkind (gnat_node)) + switch (kind) { /********************************/ /* Chapter 2: Lexical Elements */ @@ -3743,8 +3751,7 @@ gnat_to_gnu (Node_Id gnat_node) break; if (Present (Expression (gnat_node)) - && !(Nkind (gnat_node) == N_Object_Declaration - && No_Initialization (gnat_node)) + && !(kind == N_Object_Declaration && No_Initialization (gnat_node)) && (!type_annotate_only || Compile_Time_Known_Value (Expression (gnat_node)))) { @@ -3841,6 +3848,11 @@ gnat_to_gnu (Node_Id gnat_node) Node_Id *gnat_expr_array; gnu_array_object = maybe_implicit_deref (gnu_array_object); + + /* Convert vector inputs to their representative array type, to fit + what the code below expects. */ + gnu_array_object = maybe_vector_array (gnu_array_object); + gnu_array_object = maybe_unconstrained_array (gnu_array_object); /* If we got a padded type, remove it too. */ @@ -4086,6 +4098,8 @@ gnat_to_gnu (Node_Id gnat_node) && TYPE_CONTAINS_TEMPLATE_P (gnu_result_type)) gnu_aggr_type = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_result_type))); + else if (TREE_CODE (gnu_result_type) == VECTOR_TYPE) + gnu_aggr_type = TYPE_REPRESENTATIVE_ARRAY (gnu_result_type); if (Null_Record_Present (gnat_node)) gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE); @@ -4136,7 +4150,7 @@ gnat_to_gnu (Node_Id gnat_node) = convert_with_check (Etype (gnat_node), gnu_result, Do_Overflow_Check (gnat_node), Do_Range_Check (Expression (gnat_node)), - Nkind (gnat_node) == N_Type_Conversion + kind == N_Type_Conversion && Float_Truncate (gnat_node), gnat_node); break; @@ -4224,7 +4238,7 @@ gnat_to_gnu (Node_Id gnat_node) gnu_object, gnu_high)); } - if (Nkind (gnat_node) == N_Not_In) + if (kind == N_Not_In) gnu_result = invert_truthvalue (gnu_result); } break; @@ -4248,8 +4262,8 @@ gnat_to_gnu (Node_Id gnat_node) Modular_Integer_Kind)) { enum tree_code code - = (Nkind (gnat_node) == N_Op_Or ? BIT_IOR_EXPR - : Nkind (gnat_node) == N_Op_And ? BIT_AND_EXPR + = (kind == N_Op_Or ? BIT_IOR_EXPR + : kind == N_Op_And ? BIT_AND_EXPR : BIT_XOR_EXPR); gnu_lhs = gnat_to_gnu (Left_Opnd (gnat_node)); @@ -4273,7 +4287,7 @@ gnat_to_gnu (Node_Id gnat_node) case N_Op_Shift_Right_Arithmetic: case N_And_Then: case N_Or_Else: { - enum tree_code code = gnu_codes[Nkind (gnat_node)]; + enum tree_code code = gnu_codes[kind]; bool ignore_lhs_overflow = false; tree gnu_type; @@ -4281,6 +4295,12 @@ gnat_to_gnu (Node_Id gnat_node) gnu_rhs = gnat_to_gnu (Right_Opnd (gnat_node)); gnu_type = gnu_result_type = get_unpadded_type (Etype (gnat_node)); + /* Pending generic support for efficient vector logical operations in + GCC, convert vectors to their representative array type view and + fallthrough. */ + gnu_lhs = maybe_vector_array (gnu_lhs); + gnu_rhs = maybe_vector_array (gnu_rhs); + /* If this is a comparison operator, convert any references to an unconstrained array value into a reference to the actual array. */ @@ -4299,18 +4319,16 @@ gnat_to_gnu (Node_Id gnat_node) /* If this is a shift whose count is not guaranteed to be correct, we need to adjust the shift count. */ - if (IN (Nkind (gnat_node), N_Op_Shift) - && !Shift_Count_OK (gnat_node)) + if (IN (kind, N_Op_Shift) && !Shift_Count_OK (gnat_node)) { tree gnu_count_type = get_base_type (TREE_TYPE (gnu_rhs)); tree gnu_max_shift = convert (gnu_count_type, TYPE_SIZE (gnu_type)); - if (Nkind (gnat_node) == N_Op_Rotate_Left - || Nkind (gnat_node) == N_Op_Rotate_Right) + if (kind == N_Op_Rotate_Left || kind == N_Op_Rotate_Right) gnu_rhs = build_binary_op (TRUNC_MOD_EXPR, gnu_count_type, gnu_rhs, gnu_max_shift); - else if (Nkind (gnat_node) == N_Op_Shift_Right_Arithmetic) + else if (kind == N_Op_Shift_Right_Arithmetic) gnu_rhs = build_binary_op (MIN_EXPR, gnu_count_type, @@ -4326,13 +4344,12 @@ gnat_to_gnu (Node_Id gnat_node) so we may need to choose a different type. In this case, we have to ignore integer overflow lest it propagates all the way down and causes a CE to be explicitly raised. */ - if (Nkind (gnat_node) == N_Op_Shift_Right - && !TYPE_UNSIGNED (gnu_type)) + if (kind == N_Op_Shift_Right && !TYPE_UNSIGNED (gnu_type)) { gnu_type = gnat_unsigned_type (gnu_type); ignore_lhs_overflow = true; } - else if (Nkind (gnat_node) == N_Op_Shift_Right_Arithmetic + else if (kind == N_Op_Shift_Right_Arithmetic && TYPE_UNSIGNED (gnu_type)) { gnu_type = gnat_signed_type (gnu_type); @@ -4355,9 +4372,9 @@ gnat_to_gnu (Node_Id gnat_node) do overflow checking, do it here. The goal is to push the expansions further into the back end over time. */ if (Do_Overflow_Check (gnat_node) && Backend_Overflow_Checks_On_Target - && (Nkind (gnat_node) == N_Op_Add - || Nkind (gnat_node) == N_Op_Subtract - || Nkind (gnat_node) == N_Op_Multiply) + && (kind == N_Op_Add + || kind == N_Op_Subtract + || kind == N_Op_Multiply) && !TYPE_UNSIGNED (gnu_type) && !FLOAT_TYPE_P (gnu_type)) gnu_result = build_binary_op_trapv (code, gnu_type, @@ -4368,8 +4385,7 @@ gnat_to_gnu (Node_Id gnat_node) /* If this is a logical shift with the shift count not verified, we must return zero if it is too large. We cannot compensate above in this case. */ - if ((Nkind (gnat_node) == N_Op_Shift_Left - || Nkind (gnat_node) == N_Op_Shift_Right) + if ((kind == N_Op_Shift_Left || kind == N_Op_Shift_Right) && !Shift_Count_OK (gnat_node)) gnu_result = build_cond_expr @@ -4391,9 +4407,8 @@ gnat_to_gnu (Node_Id gnat_node) = gnat_to_gnu (Next (Next (First (Expressions (gnat_node))))); gnu_result_type = get_unpadded_type (Etype (gnat_node)); - gnu_result = build_cond_expr (gnu_result_type, - gnat_truthvalue_conversion (gnu_cond), - gnu_true, gnu_false); + gnu_result + = build_cond_expr (gnu_result_type, gnu_cond, gnu_true, gnu_false); } break; @@ -4432,10 +4447,10 @@ gnat_to_gnu (Node_Id gnat_node) && !TYPE_UNSIGNED (gnu_result_type) && !FLOAT_TYPE_P (gnu_result_type)) gnu_result - = build_unary_op_trapv (gnu_codes[Nkind (gnat_node)], + = build_unary_op_trapv (gnu_codes[kind], gnu_result_type, gnu_expr, gnat_node); else - gnu_result = build_unary_op (gnu_codes[Nkind (gnat_node)], + gnu_result = build_unary_op (gnu_codes[kind], gnu_result_type, gnu_expr); break; @@ -5204,8 +5219,7 @@ gnat_to_gnu (Node_Id gnat_node) gnu_result_type = get_unpadded_type (Etype (gnat_node)); gnu_result - = build_call_raise (UI_To_Int (Reason (gnat_node)), gnat_node, - Nkind (gnat_node)); + = build_call_raise (UI_To_Int (Reason (gnat_node)), gnat_node, kind); /* If the type is VOID, this is a statement, so we need to generate the code for the call. Handle a Condition, if there @@ -5564,14 +5578,14 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity) /* Mark everything as used to prevent node sharing with subprograms. 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); + MARK_VISITED (gnu_stmt); if (TREE_CODE (gnu_decl) == VAR_DECL || TREE_CODE (gnu_decl) == CONST_DECL) { - mark_visited (&DECL_SIZE (gnu_decl)); - mark_visited (&DECL_SIZE_UNIT (gnu_decl)); - mark_visited (&DECL_INITIAL (gnu_decl)); + MARK_VISITED (DECL_SIZE (gnu_decl)); + MARK_VISITED (DECL_SIZE_UNIT (gnu_decl)); + MARK_VISITED (DECL_INITIAL (gnu_decl)); } } else @@ -5611,20 +5625,32 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity) static tree mark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) { - if (TREE_VISITED (*tp)) + tree t = *tp; + + if (TREE_VISITED (t)) *walk_subtrees = 0; /* Don't mark a dummy type as visited because we want to mark its sizes and fields once it's filled in. */ - else if (!TYPE_IS_DUMMY_P (*tp)) - TREE_VISITED (*tp) = 1; + else if (!TYPE_IS_DUMMY_P (t)) + TREE_VISITED (t) = 1; - if (TYPE_P (*tp)) - TYPE_SIZES_GIMPLIFIED (*tp) = 1; + if (TYPE_P (t)) + TYPE_SIZES_GIMPLIFIED (t) = 1; return NULL_TREE; } +/* Mark nodes rooted at T with TREE_VISITED and types as having their + sized gimplified. We use this to indicate all variable sizes and + positions in global types may not be shared by any subprogram. */ + +void +mark_visited (tree t) +{ + walk_tree (&t, mark_visited_r, NULL, NULL); +} + /* Utility function to unshare expressions wrapped up in a SAVE_EXPR. */ static tree @@ -5639,16 +5665,6 @@ unshare_save_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, return NULL_TREE; } -/* Mark nodes rooted at *TP with TREE_VISITED and types as having their - sized gimplified. We use this to indicate all variable sizes and - positions in global types may not be shared by any subprogram. */ - -void -mark_visited (tree *tp) -{ - walk_tree (tp, mark_visited_r, NULL, NULL); -} - /* Add GNU_CLEANUP, a cleanup action, to the current code group and set its location to that of GNAT_NODE if present. */ diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 31f24ce0340..7acb2ce2de4 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -23,10 +23,6 @@ * * ****************************************************************************/ -/* We have attribute handlers using C specific format specifiers in warning - messages. Make sure they are properly recognized. */ -#define GCC_DIAG_STYLE __gcc_cdiag__ - #include "config.h" #include "system.h" #include "coretypes.h" @@ -101,6 +97,7 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *); +static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *); /* Fake handler for attributes we don't properly support, typically because they'd require dragging a lot of the common-c front-end circuitry. */ @@ -122,6 +119,7 @@ const struct attribute_spec gnat_internal_attribute_table[] = { "type generic", 0, 0, false, true, true, handle_type_generic_attribute }, { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute }, + { "vector_type", 0, 0, false, true, false, handle_vector_type_attribute }, { "may_alias", 0, 0, false, true, false, NULL }, /* ??? format and format_arg are heavy and not supported, which actually @@ -439,9 +437,12 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) { DECL_CONTEXT (decl) = current_function_decl; - /* Functions imported in another function are not really nested. */ - if (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)) - DECL_NO_STATIC_CHAIN (decl) = 1; + /* Functions imported in another function are not really nested. + For really nested functions mark them initially as needing + a static chain for uses of that flag before unnesting; + lower_nested_functions will then recompute it. */ + if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl)) + DECL_STATIC_CHAIN (decl) = 1; } TREE_NO_WARNING (decl) = (gnat_node == Empty || Warnings_Off (gnat_node)); @@ -2266,6 +2267,14 @@ gnat_types_compatible_p (tree t1, tree t2) if ((code = TREE_CODE (t1)) != TREE_CODE (t2)) return 0; + /* Vector types are also compatible if they have the same number of subparts + and the same form of (scalar) element type. */ + if (code == VECTOR_TYPE + && TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) + && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)) + && TYPE_PRECISION (TREE_TYPE (t1)) == TYPE_PRECISION (TREE_TYPE (t2))) + return 1; + /* Array types are also compatible if they are constrained and have the same component type and the same domain. */ if (code == ARRAY_TYPE @@ -3978,6 +3987,16 @@ convert (tree type, tree expr) } break; + case VECTOR_CST: + /* If we are converting a VECTOR_CST to a mere variant type, just make + a new one in the proper type. */ + if (code == ecode && gnat_types_compatible_p (type, etype)) + { + expr = copy_node (expr); + TREE_TYPE (expr) = type; + return expr; + } + case CONSTRUCTOR: /* If we are converting a CONSTRUCTOR to a mere variant type, just make a new one in the proper type. */ @@ -4040,6 +4059,52 @@ convert (tree type, tree expr) return expr; } } + + /* Likewise for a conversion between array type and vector type with a + compatible representative array. */ + else if (code == VECTOR_TYPE + && ecode == ARRAY_TYPE + && gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type), + etype)) + { + VEC(constructor_elt,gc) *e = CONSTRUCTOR_ELTS (expr); + unsigned HOST_WIDE_INT len = VEC_length (constructor_elt, e); + VEC(constructor_elt,gc) *v; + unsigned HOST_WIDE_INT ix; + tree value; + + /* Build a VECTOR_CST from a *constant* array constructor. */ + if (TREE_CONSTANT (expr)) + { + bool constant_p = true; + + /* Iterate through elements and check if all constructor + elements are *_CSTs. */ + FOR_EACH_CONSTRUCTOR_VALUE (e, ix, value) + if (!CONSTANT_CLASS_P (value)) + { + constant_p = false; + break; + } + + if (constant_p) + return build_vector_from_ctor (type, + CONSTRUCTOR_ELTS (expr)); + } + + /* Otherwise, build a regular vector constructor. */ + v = VEC_alloc (constructor_elt, gc, len); + FOR_EACH_CONSTRUCTOR_VALUE (e, ix, value) + { + constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = NULL_TREE; + elt->value = value; + } + expr = copy_node (expr); + TREE_TYPE (expr) = type; + CONSTRUCTOR_ELTS (expr) = v; + return expr; + } break; case UNCONSTRAINED_ARRAY_REF: @@ -4068,10 +4133,11 @@ convert (tree type, tree expr) if (type == TREE_TYPE (op0)) return op0; - /* Otherwise, if we're converting between two aggregate types, we - might be allowed to substitute the VIEW_CONVERT_EXPR target type - in place or to just convert the inner expression. */ - if (AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype)) + /* Otherwise, if we're converting between two aggregate or vector + types, we might be allowed to substitute the VIEW_CONVERT_EXPR + target type in place or to just convert the inner expression. */ + if ((AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype)) + || (VECTOR_TYPE_P (type) && VECTOR_TYPE_P (etype))) { /* If we are converting between mere variants, we can just substitute the VIEW_CONVERT_EXPR in place. */ @@ -4114,11 +4180,16 @@ convert (tree type, tree expr) if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype)) return convert_to_fat_pointer (type, expr); - /* If we are converting between two aggregate types that are mere - variants, just make a VIEW_CONVERT_EXPR. */ - else if (code == ecode - && AGGREGATE_TYPE_P (type) - && gnat_types_compatible_p (type, etype)) + /* If we are converting between two aggregate or vector types that are mere + variants, just make a VIEW_CONVERT_EXPR. Likewise when we are converting + to a vector type from its representative array type. */ + else if ((code == ecode + && (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)) + && gnat_types_compatible_p (type, etype)) + || (code == VECTOR_TYPE + && ecode == ARRAY_TYPE + && gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type), + etype))) return build1 (VIEW_CONVERT_EXPR, type, expr); /* In all other cases of related types, make a NOP_EXPR. */ @@ -4234,6 +4305,15 @@ convert (tree type, tree expr) return unchecked_convert (type, expr, false); case UNCONSTRAINED_ARRAY_TYPE: + /* If the input is a VECTOR_TYPE, convert to the representative + array type first. */ + if (ecode == VECTOR_TYPE) + { + expr = convert (TYPE_REPRESENTATIVE_ARRAY (etype), expr); + etype = TREE_TYPE (expr); + ecode = TREE_CODE (etype); + } + /* If EXPR is a constrained array, take its address, convert it to a fat pointer, and then dereference it. Likewise if EXPR is a record containing both a template and a constrained array. @@ -4363,6 +4443,20 @@ maybe_unconstrained_array (tree exp) return exp; } + +/* If EXP's type is a VECTOR_TYPE, return EXP converted to the associated + TYPE_REPRESENTATIVE_ARRAY. */ + +tree +maybe_vector_array (tree exp) +{ + tree etype = TREE_TYPE (exp); + + if (VECTOR_TYPE_P (etype)) + exp = convert (TYPE_REPRESENTATIVE_ARRAY (etype), exp); + + return exp; +} /* Return true if EXPR is an expression that can be folded as an operand of a VIEW_CONVERT_EXPR. See ada-tree.h for a complete rationale. */ @@ -4498,15 +4592,24 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) expr = unchecked_convert (type, expr, notrunc_p); } - /* We have a special case when we are converting between two - unconstrained array types. In that case, take the address, - convert the fat pointer types, and dereference. */ + /* We have a special case when we are converting between two unconstrained + array types. In that case, take the address, convert the fat pointer + types, and dereference. */ else if (TREE_CODE (etype) == UNCONSTRAINED_ARRAY_TYPE && TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE) expr = build_unary_op (INDIRECT_REF, NULL_TREE, build1 (VIEW_CONVERT_EXPR, TREE_TYPE (type), build_unary_op (ADDR_EXPR, NULL_TREE, expr))); + + /* Another special case is when we are converting to a vector type from its + representative array type; this a regular conversion. */ + else if (TREE_CODE (type) == VECTOR_TYPE + && TREE_CODE (etype) == ARRAY_TYPE + && gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type), + etype)) + expr = convert (type, expr); + else { expr = maybe_unconstrained_array (expr); @@ -5057,7 +5160,8 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args), /* ??? TODO: Support types. */ else { - warning (OPT_Wattributes, "%qE attribute ignored", name); + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -5172,7 +5276,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args, if (!params) { warning (OPT_Wattributes, - "%qE attribute requires prototypes with named arguments", name); + "%qs attribute requires prototypes with named arguments", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else @@ -5183,7 +5288,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args, if (VOID_TYPE_P (TREE_VALUE (params))) { warning (OPT_Wattributes, - "%qE attribute only applies to variadic functions", name); + "%qs attribute only applies to variadic functions", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } } @@ -5230,7 +5336,8 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), TYPE_READONLY (TREE_TYPE (type)), 1)); else { - warning (OPT_Wattributes, "%qE attribute ignored", name); + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -5249,7 +5356,8 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args), DECL_IS_MALLOC (*node) = 1; else { - warning (OPT_Wattributes, "%qE attribute ignored", name); + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -5308,7 +5416,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args, if (!host_integerp (size, 1)) { - warning (OPT_Wattributes, "%qE attribute ignored", name); + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); return NULL_TREE; } @@ -5342,7 +5451,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args, || !host_integerp (TYPE_SIZE_UNIT (type), 1) || TREE_CODE (type) == BOOLEAN_TYPE) { - error ("invalid vector type for attribute %qE", name); + error ("invalid vector type for attribute %qs", + IDENTIFIER_POINTER (name)); return NULL_TREE; } @@ -5374,6 +5484,103 @@ handle_vector_size_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle a "vector_type" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_vector_type_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + /* Vector representative type and size. */ + tree rep_type = *node; + tree rep_size = TYPE_SIZE_UNIT (rep_type); + tree rep_name; + + /* Vector size in bytes and number of units. */ + unsigned HOST_WIDE_INT vec_bytes, vec_units; + + /* Vector element type and mode. */ + tree elem_type; + enum machine_mode elem_mode; + + *no_add_attrs = true; + + /* Get the representative array type, possibly nested within a + padding record e.g. for alignment purposes. */ + + if (TREE_CODE (rep_type) == RECORD_TYPE && TYPE_IS_PADDING_P (rep_type)) + rep_type = TREE_TYPE (TYPE_FIELDS (rep_type)); + + if (TREE_CODE (rep_type) != ARRAY_TYPE) + { + error ("attribute %qs applies to array types only", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + /* Silently punt on variable sizes. We can't make vector types for them, + need to ignore them on front-end generated subtypes of unconstrained + bases, and this attribute is for binding implementors, not end-users, so + we should never get there from legitimate explicit uses. */ + + if (!host_integerp (rep_size, 1)) + return NULL_TREE; + + /* Get the element type/mode and check this is something we know + how to make vectors of. */ + + elem_type = TREE_TYPE (rep_type); + elem_mode = TYPE_MODE (elem_type); + + if ((!INTEGRAL_TYPE_P (elem_type) + && !SCALAR_FLOAT_TYPE_P (elem_type) + && !FIXED_POINT_TYPE_P (elem_type)) + || (!SCALAR_FLOAT_MODE_P (elem_mode) + && GET_MODE_CLASS (elem_mode) != MODE_INT + && !ALL_SCALAR_FIXED_POINT_MODE_P (elem_mode)) + || !host_integerp (TYPE_SIZE_UNIT (elem_type), 1)) + { + error ("invalid element type for attribute %qs", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + /* Sanity check the vector size and element type consistency. */ + + vec_bytes = tree_low_cst (rep_size, 1); + + if (vec_bytes % tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1)) + { + error ("vector size not an integral multiple of component size"); + return NULL; + } + + if (vec_bytes == 0) + { + error ("zero vector size"); + return NULL; + } + + vec_units = vec_bytes / tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1); + if (vec_units & (vec_units - 1)) + { + error ("number of components of the vector not a power of two"); + return NULL_TREE; + } + + /* Build the vector type and replace. */ + + *node = build_vector_type (elem_type, vec_units); + rep_name = TYPE_NAME (rep_type); + if (TREE_CODE (rep_name) == TYPE_DECL) + rep_name = DECL_NAME (rep_name); + TYPE_NAME (*node) = rep_name; + TYPE_REPRESENTATIVE_ARRAY (*node) = rep_type; + + return NULL_TREE; +} + /* ----------------------------------------------------------------------- * * BUILTIN FUNCTIONS * * ----------------------------------------------------------------------- */ @@ -5455,7 +5662,7 @@ gnat_install_builtins (void) know about internal specificities and control attributes accordingly, for instance __builtin_alloca vs no-throw and -fstack-check. We will ignore the generic definition from builtins.def. */ - build_common_builtin_nodes (false); + build_common_builtin_nodes (); /* Now, install the target specific builtins, such as the AltiVec family on ppc, and the common set as exposed by builtins.def. */ diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index b8ca814b6aa..f8a3dfbd525 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -55,63 +55,6 @@ static tree compare_arrays (tree, tree, tree); static tree nonbinary_modular_operation (enum tree_code, tree, tree, tree); static tree build_simple_component_ref (tree, tree, tree, bool); -/* Prepare expr to be an argument of a TRUTH_NOT_EXPR or other logical - operation. - - This preparation consists of taking the ordinary representation of - an expression expr and producing a valid tree boolean expression - describing whether expr is nonzero. We could simply always do - - build_binary_op (NE_EXPR, expr, integer_zero_node, 1), - - but we optimize comparisons, &&, ||, and !. - - The resulting type should always be the same as the input type. - This function is simpler than the corresponding C version since - the only possible operands will be things of Boolean type. */ - -tree -gnat_truthvalue_conversion (tree expr) -{ - tree type = TREE_TYPE (expr); - - switch (TREE_CODE (expr)) - { - case EQ_EXPR: case NE_EXPR: case LE_EXPR: case GE_EXPR: - case LT_EXPR: case GT_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - case ERROR_MARK: - return expr; - - case INTEGER_CST: - return (integer_zerop (expr) - ? build_int_cst (type, 0) - : build_int_cst (type, 1)); - - case REAL_CST: - return (real_zerop (expr) - ? fold_convert (type, integer_zero_node) - : fold_convert (type, integer_one_node)); - - case COND_EXPR: - /* Distribute the conversion into the arms of a COND_EXPR. */ - { - tree arg1 = gnat_truthvalue_conversion (TREE_OPERAND (expr, 1)); - tree arg2 = gnat_truthvalue_conversion (TREE_OPERAND (expr, 2)); - return fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), - arg1, arg2); - } - - default: - return build_binary_op (NE_EXPR, type, expr, - fold_convert (type, integer_zero_node)); - } -} - /* Return the base type of TYPE. */ tree @@ -970,15 +913,6 @@ build_binary_op (enum tree_code op_code, tree result_type, left_operand = convert (operation_type, left_operand); break; - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - left_operand = gnat_truthvalue_conversion (left_operand); - right_operand = gnat_truthvalue_conversion (right_operand); - goto common; - case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: @@ -1120,7 +1054,7 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand) case TRUTH_NOT_EXPR: gcc_assert (result_type == base_type); - result = invert_truthvalue (gnat_truthvalue_conversion (operand)); + result = invert_truthvalue (operand); break; case ATTR_ADDR_EXPR: |