summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface
diff options
context:
space:
mode:
authorrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-02 23:25:15 +0000
committerrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-02 23:25:15 +0000
commit611349f0ec42a37591db2cd02974a11a48d10edb (patch)
tree2a5c3eecca5f0b75352af30aad7f366c69281c2c /gcc/ada/gcc-interface
parent0012f4fdae066f73c9f38cb33d3a338c3e356cdf (diff)
downloadgcc-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.in2
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h7
-rw-r--r--gcc/ada/gcc-interface/ada.h6
-rw-r--r--gcc/ada/gcc-interface/decl.c1078
-rw-r--r--gcc/ada/gcc-interface/gigi.h34
-rw-r--r--gcc/ada/gcc-interface/misc.c5
-rw-r--r--gcc/ada/gcc-interface/targtyps.c13
-rw-r--r--gcc/ada/gcc-interface/trans.c214
-rw-r--r--gcc/ada/gcc-interface/utils.c261
-rw-r--r--gcc/ada/gcc-interface/utils2.c68
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: