Commit fb7fb701 by Nathan Froyd Committed by Nathan Froyd

* gcc-interface/decl.c (rec_variant). Declare. Declare a VEC of it.

	(build_variant_list): Return a VEC instead of a tree.  Take a
	VEC instead of a tree.
	(create_variant_part_from): Take a VEC instead of a tree for
	variant_list.  Adjust accordingly.
	(gnat_to_gnu_entity): Adjust for changes to previous functions.

From-SVN: r163025
parent 0ec11839
2010-08-08 Nathan Froyd <froydnj@codesourcery.com>
* gcc-interface/decl.c (rec_variant). Declare. Declare a VEC of it.
(build_variant_list): Return a VEC instead of a tree. Take a
VEC instead of a tree.
(create_variant_part_from): Take a VEC instead of a tree for
variant_list. Adjust accordingly.
(gnat_to_gnu_entity): Adjust for changes to previous functions.
2010-08-07 Nathan Froyd <froydnj@codesourcery.com> 2010-08-07 Nathan Froyd <froydnj@codesourcery.com>
* gcc-interface/decl.c (gnat_to_gnu_entity): Use XALLOCAVEC instead * gcc-interface/decl.c (gnat_to_gnu_entity): Use XALLOCAVEC instead
......
...@@ -112,6 +112,23 @@ typedef struct GTY(()) subst_pair_d { ...@@ -112,6 +112,23 @@ typedef struct GTY(()) subst_pair_d {
DEF_VEC_O(subst_pair); DEF_VEC_O(subst_pair);
DEF_VEC_ALLOC_O(subst_pair,heap); DEF_VEC_ALLOC_O(subst_pair,heap);
typedef struct GTY(()) variant_desc_d {
/* The type of the variant. */
tree type;
/* The associated field. */
tree field;
/* The value of the qualifier. */
tree qual;
/* The record associated with this variant. */
tree record;
} variant_desc;
DEF_VEC_O(variant_desc);
DEF_VEC_ALLOC_O(variant_desc,heap);
/* A hash table used to cache the result of annotate_value. */ /* A hash table used to cache the result of annotate_value. */
static GTY ((if_marked ("tree_int_map_marked_p"), static GTY ((if_marked ("tree_int_map_marked_p"),
param_is (struct tree_int_map))) htab_t annotate_value_cache; param_is (struct tree_int_map))) htab_t annotate_value_cache;
...@@ -150,7 +167,9 @@ static Uint annotate_value (tree); ...@@ -150,7 +167,9 @@ static Uint annotate_value (tree);
static void annotate_rep (Entity_Id, tree); static void annotate_rep (Entity_Id, tree);
static tree build_position_list (tree, bool, tree, tree, unsigned int, tree); static tree build_position_list (tree, bool, tree, tree, unsigned int, tree);
static VEC(subst_pair,heap) *build_subst_list (Entity_Id, Entity_Id, bool); static VEC(subst_pair,heap) *build_subst_list (Entity_Id, Entity_Id, bool);
static tree build_variant_list (tree, VEC(subst_pair,heap) *, tree); static VEC(variant_desc,heap) *build_variant_list (tree,
VEC(subst_pair,heap) *,
VEC(variant_desc,heap) *);
static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool); static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool);
static void set_rm_size (Uint, tree, Entity_Id); static void set_rm_size (Uint, tree, Entity_Id);
static tree make_type_from_size (tree, tree, bool); static tree make_type_from_size (tree, tree, bool);
...@@ -161,8 +180,8 @@ static tree create_field_decl_from (tree, tree, tree, tree, tree, ...@@ -161,8 +180,8 @@ static tree create_field_decl_from (tree, tree, tree, tree, tree,
VEC(subst_pair,heap) *); VEC(subst_pair,heap) *);
static tree get_rep_part (tree); static tree get_rep_part (tree);
static tree get_variant_part (tree); static tree get_variant_part (tree);
static tree create_variant_part_from (tree, tree, tree, tree, static tree create_variant_part_from (tree, VEC(variant_desc,heap) *, tree,
VEC(subst_pair,heap) *); tree, VEC(subst_pair,heap) *);
static void copy_and_substitute_in_size (tree, tree, VEC(subst_pair,heap) *); static void copy_and_substitute_in_size (tree, tree, VEC(subst_pair,heap) *);
static void rest_of_type_decl_compilation_no_defer (tree); static void rest_of_type_decl_compilation_no_defer (tree);
...@@ -3045,9 +3064,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3045,9 +3064,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
VEC(subst_pair,heap) *gnu_subst_list VEC(subst_pair,heap) *gnu_subst_list
= build_subst_list (gnat_entity, gnat_base_type, definition); = build_subst_list (gnat_entity, gnat_base_type, definition);
tree gnu_unpad_base_type, gnu_rep_part, gnu_variant_part, 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; tree gnu_pos_list, gnu_field_list = NULL_TREE;
bool selected_variant = false; bool selected_variant = false;
Entity_Id gnat_field; Entity_Id gnat_field;
VEC(variant_desc,heap) *gnu_variant_list;
gnu_type = make_node (RECORD_TYPE); gnu_type = make_node (RECORD_TYPE);
TYPE_NAME (gnu_type) = gnu_entity_name; TYPE_NAME (gnu_type) = gnu_entity_name;
...@@ -3075,15 +3095,19 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3075,15 +3095,19 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
union for the variants that are still relevant. */ union for the variants that are still relevant. */
if (gnu_variant_part) if (gnu_variant_part)
{ {
variant_desc *v;
unsigned ix;
gnu_variant_list gnu_variant_list
= build_variant_list (TREE_TYPE (gnu_variant_part), = build_variant_list (TREE_TYPE (gnu_variant_part),
gnu_subst_list, NULL_TREE); gnu_subst_list, NULL);
/* If all the qualifiers are unconditionally true, the /* If all the qualifiers are unconditionally true, the
innermost variant is statically selected. */ innermost variant is statically selected. */
selected_variant = true; selected_variant = true;
for (t = gnu_variant_list; t; t = TREE_CHAIN (t)) FOR_EACH_VEC_ELT_REVERSE (variant_desc, gnu_variant_list,
if (!integer_onep (TREE_VEC_ELT (TREE_VALUE (t), 1))) ix, v)
if (!integer_onep (v->qual))
{ {
selected_variant = false; selected_variant = false;
break; break;
...@@ -3091,20 +3115,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3091,20 +3115,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* Otherwise, create the new variants. */ /* Otherwise, create the new variants. */
if (!selected_variant) if (!selected_variant)
for (t = gnu_variant_list; t; t = TREE_CHAIN (t)) FOR_EACH_VEC_ELT_REVERSE (variant_desc, gnu_variant_list,
ix, v)
{ {
tree old_variant = TREE_PURPOSE (t); tree old_variant = v->type;
tree new_variant = make_node (RECORD_TYPE); tree new_variant = make_node (RECORD_TYPE);
TYPE_NAME (new_variant) TYPE_NAME (new_variant)
= DECL_NAME (TYPE_NAME (old_variant)); = DECL_NAME (TYPE_NAME (old_variant));
copy_and_substitute_in_size (new_variant, old_variant, copy_and_substitute_in_size (new_variant, old_variant,
gnu_subst_list); gnu_subst_list);
TREE_VEC_ELT (TREE_VALUE (t), 2) = new_variant; v->record = new_variant;
} }
} }
else else
{ {
gnu_variant_list = NULL_TREE; gnu_variant_list = NULL;
selected_variant = false; selected_variant = false;
} }
...@@ -3187,13 +3212,23 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3187,13 +3212,23 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_cont_type = gnu_type; gnu_cont_type = gnu_type;
else else
{ {
t = purpose_member (gnu_context, gnu_variant_list); variant_desc *v;
unsigned ix;
t = NULL_TREE;
FOR_EACH_VEC_ELT_REVERSE (variant_desc,
gnu_variant_list, ix, v)
if (v->type == gnu_context)
{
t = v->type;
break;
}
if (t) if (t)
{ {
if (selected_variant) if (selected_variant)
gnu_cont_type = gnu_type; gnu_cont_type = gnu_type;
else else
gnu_cont_type = TREE_VEC_ELT (TREE_VALUE (t), 2); gnu_cont_type = v->record;
} }
else else
/* The front-end may pass us "ghost" components if /* The front-end may pass us "ghost" components if
...@@ -3319,6 +3354,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3319,6 +3354,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnat_entity); gnat_entity);
} }
VEC_free (variant_desc, heap, gnu_variant_list);
VEC_free (subst_pair, heap, gnu_subst_list); VEC_free (subst_pair, heap, gnu_subst_list);
/* Now we can finalize it. */ /* Now we can finalize it. */
...@@ -7547,16 +7583,15 @@ build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition) ...@@ -7547,16 +7583,15 @@ build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition)
return gnu_vec; return gnu_vec;
} }
/* Scan all fields in QUAL_UNION_TYPE and return a TREE_LIST describing the /* Scan all fields in QUAL_UNION_TYPE and return a VEC describing the
variants of QUAL_UNION_TYPE that are still relevant after applying the variants of QUAL_UNION_TYPE that are still relevant after applying
substitutions described in SUBST_LIST. TREE_PURPOSE is the type of the the substitutions described in SUBST_LIST. VARIANT_LIST is a
variant and TREE_VALUE is a TREE_VEC containing the field, the new value pre-existing VEC onto which newly created entries should be
of the qualifier and NULL_TREE respectively. GNU_LIST is a pre-existing pushed. */
list to be chained to the newly created entries. */
static tree static VEC(variant_desc,heap) *
build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list, build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list,
tree gnu_list) VEC(variant_desc,heap) *variant_list)
{ {
tree gnu_field; tree gnu_field;
...@@ -7575,18 +7610,20 @@ build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list, ...@@ -7575,18 +7610,20 @@ build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list,
still be accessed. */ still be accessed. */
if (!integer_zerop (qual)) if (!integer_zerop (qual))
{ {
variant_desc *v;
tree variant_type = TREE_TYPE (gnu_field), variant_subpart; tree variant_type = TREE_TYPE (gnu_field), variant_subpart;
tree v = make_tree_vec (3);
TREE_VEC_ELT (v, 0) = gnu_field; v = VEC_safe_push (variant_desc, heap, variant_list, NULL);
TREE_VEC_ELT (v, 1) = qual; v->type = variant_type;
TREE_VEC_ELT (v, 2) = NULL_TREE; v->field = gnu_field;
gnu_list = tree_cons (variant_type, v, gnu_list); v->qual = qual;
v->record = NULL_TREE;
/* Recurse on the variant subpart of the variant, if any. */ /* Recurse on the variant subpart of the variant, if any. */
variant_subpart = get_variant_part (variant_type); variant_subpart = get_variant_part (variant_type);
if (variant_subpart) if (variant_subpart)
gnu_list = build_variant_list (TREE_TYPE (variant_subpart), variant_list = build_variant_list (TREE_TYPE (variant_subpart),
subst_list, gnu_list); subst_list, variant_list);
/* If the new qualifier is unconditionally true, the subsequent /* If the new qualifier is unconditionally true, the subsequent
variants cannot be accessed. */ variants cannot be accessed. */
...@@ -7595,7 +7632,7 @@ build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list, ...@@ -7595,7 +7632,7 @@ build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list,
} }
} }
return gnu_list; return variant_list;
} }
/* UINT_SIZE is a Uint giving the specified size for an object of GNU_TYPE /* UINT_SIZE is a Uint giving the specified size for an object of GNU_TYPE
...@@ -8319,14 +8356,17 @@ get_variant_part (tree record_type) ...@@ -8319,14 +8356,17 @@ get_variant_part (tree record_type)
layout. */ layout. */
static tree static tree
create_variant_part_from (tree old_variant_part, tree variant_list, create_variant_part_from (tree old_variant_part,
VEC(variant_desc,heap) *variant_list,
tree record_type, tree pos_list, tree record_type, tree pos_list,
VEC(subst_pair,heap) *subst_list) VEC(subst_pair,heap) *subst_list)
{ {
tree offset = DECL_FIELD_OFFSET (old_variant_part); tree offset = DECL_FIELD_OFFSET (old_variant_part);
tree old_union_type = TREE_TYPE (old_variant_part); tree old_union_type = TREE_TYPE (old_variant_part);
tree new_union_type, new_variant_part, t; tree new_union_type, new_variant_part;
tree union_field_list = NULL_TREE; tree union_field_list = NULL_TREE;
variant_desc *v;
unsigned ix;
/* First create the type of the variant part from that of the old one. */ /* First create the type of the variant part from that of the old one. */
new_union_type = make_node (QUAL_UNION_TYPE); new_union_type = make_node (QUAL_UNION_TYPE);
...@@ -8354,9 +8394,9 @@ create_variant_part_from (tree old_variant_part, tree variant_list, ...@@ -8354,9 +8394,9 @@ create_variant_part_from (tree old_variant_part, tree variant_list,
copy_and_substitute_in_size (new_union_type, old_union_type, subst_list); copy_and_substitute_in_size (new_union_type, old_union_type, subst_list);
/* Now finish up the new variants and populate the union type. */ /* Now finish up the new variants and populate the union type. */
for (t = variant_list; t; t = TREE_CHAIN (t)) FOR_EACH_VEC_ELT_REVERSE (variant_desc, variant_list, ix, v)
{ {
tree old_field = TREE_VEC_ELT (TREE_VALUE (t), 0), new_field; tree old_field = v->field, new_field;
tree old_variant, old_variant_subpart, new_variant, field_list; tree old_variant, old_variant_subpart, new_variant, field_list;
/* Skip variants that don't belong to this nesting level. */ /* Skip variants that don't belong to this nesting level. */
...@@ -8364,12 +8404,12 @@ create_variant_part_from (tree old_variant_part, tree variant_list, ...@@ -8364,12 +8404,12 @@ create_variant_part_from (tree old_variant_part, tree variant_list,
continue; continue;
/* Retrieve the list of fields already added to the new variant. */ /* Retrieve the list of fields already added to the new variant. */
new_variant = TREE_VEC_ELT (TREE_VALUE (t), 2); new_variant = v->record;
field_list = TYPE_FIELDS (new_variant); field_list = TYPE_FIELDS (new_variant);
/* If the old variant had a variant subpart, we need to create a new /* If the old variant had a variant subpart, we need to create a new
variant subpart and add it to the field list. */ variant subpart and add it to the field list. */
old_variant = TREE_PURPOSE (t); old_variant = v->type;
old_variant_subpart = get_variant_part (old_variant); old_variant_subpart = get_variant_part (old_variant);
if (old_variant_subpart) if (old_variant_subpart)
{ {
...@@ -8391,7 +8431,7 @@ create_variant_part_from (tree old_variant_part, tree variant_list, ...@@ -8391,7 +8431,7 @@ create_variant_part_from (tree old_variant_part, tree variant_list,
= create_field_decl_from (old_field, new_variant, new_union_type, = create_field_decl_from (old_field, new_variant, new_union_type,
TYPE_SIZE (new_variant), TYPE_SIZE (new_variant),
pos_list, subst_list); pos_list, subst_list);
DECL_QUALIFIER (new_field) = TREE_VEC_ELT (TREE_VALUE (t), 1); DECL_QUALIFIER (new_field) = v->qual;
DECL_INTERNAL_P (new_field) = 1; DECL_INTERNAL_P (new_field) = 1;
DECL_CHAIN (new_field) = union_field_list; DECL_CHAIN (new_field) = union_field_list;
union_field_list = new_field; union_field_list = new_field;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment