Patchwork rewrite Ada's build_variant_list to build a VEC

login
register
mail settings
Submitter Nathan Froyd
Date Aug. 7, 2010, 5:40 p.m.
Message ID <20100807174003.GG17362@codesourcery.com>
Download mbox | patch
Permalink /patch/61184/
State New
Headers show

Comments

Nathan Froyd - Aug. 7, 2010, 5:40 p.m.
On Wed, Aug 04, 2010 at 05:38:37PM +0200, Eric Botcazou wrote:
> > I don't know what a good name is for the structure; I was going to call
> > it `variant', but that conflicts with bits in atree.h.  Suggestions for
> > a better name welcome.
> 
> "variant_desc" would be fine.

OK, thanks.

> > 	* gcc-interface/decl.c (rec_variant).  Declare.  Declare a VEC of it.
> > 	(build_variant_list): Return a VEC instead of a tree.  Move most
> > 	of the logic into...
> > 	(build_variant_list_1): ...here.  New function.
> > 	(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.
> 
> Wouldn't it work to make build_variant_list take an existing vector, push 
> elements and return the new vector?

Oh.  Yes, yes it would.  How about this version?  Tested on
x86_64-unknown-linux-gnu.

-Nathan

        * 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.
Eric Botcazou - Aug. 8, 2010, 10:46 p.m.
>         * 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.

OK, thanks.

Patch

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index a9e3358..405c3fe 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -112,6 +112,23 @@  typedef struct GTY(()) subst_pair_d {
 DEF_VEC_O(subst_pair);
 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.  */
 static GTY ((if_marked ("tree_int_map_marked_p"),
 	     param_is (struct tree_int_map))) htab_t annotate_value_cache;
@@ -150,7 +167,9 @@  static Uint annotate_value (tree);
 static void annotate_rep (Entity_Id, 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 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 void set_rm_size (Uint, tree, Entity_Id);
 static tree make_type_from_size (tree, tree, bool);
@@ -161,8 +180,8 @@  static tree create_field_decl_from (tree, tree, tree, tree, tree,
 				    VEC(subst_pair,heap) *);
 static tree get_rep_part (tree);
 static tree get_variant_part (tree);
-static tree create_variant_part_from (tree, tree, tree, tree,
-				      VEC(subst_pair,heap) *);
+static tree create_variant_part_from (tree, VEC(variant_desc,heap) *, 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);
 
@@ -3045,9 +3064,10 @@  gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 	      VEC(subst_pair,heap) *gnu_subst_list
 		= build_subst_list (gnat_entity, gnat_base_type, definition);
 	      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;
 	      Entity_Id gnat_field;
+	      VEC(variant_desc,heap) *gnu_variant_list;
 
 	      gnu_type = make_node (RECORD_TYPE);
 	      TYPE_NAME (gnu_type) = gnu_entity_name;
@@ -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.  */
 	      if (gnu_variant_part)
 		{
+		  variant_desc *v;
+		  unsigned ix;
+
 		  gnu_variant_list
 		    = 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
 		     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)))
+		  FOR_EACH_VEC_ELT_REVERSE (variant_desc, gnu_variant_list,
+					    ix, v)
+		    if (!integer_onep (v->qual))
 		      {
 			selected_variant = false;
 			break;
@@ -3091,20 +3115,21 @@  gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 
 		  /* Otherwise, create the new variants.  */
 		  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);
 			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;
+			v->record = new_variant;
 		      }
 		}
 	      else
 		{
-		  gnu_variant_list = NULL_TREE;
+		  gnu_variant_list = NULL;
 		  selected_variant = false;
 		}
 
@@ -3187,13 +3212,23 @@  gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 		      gnu_cont_type = gnu_type;
 		    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 (selected_variant)
 			      gnu_cont_type = gnu_type;
 			    else
-			      gnu_cont_type = TREE_VEC_ELT (TREE_VALUE (t), 2);
+			      gnu_cont_type = v->record;
 			  }
 			else
 			  /* 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)
 					 gnat_entity);
 		}
 
+	      VEC_free (variant_desc, heap, gnu_variant_list);
 	      VEC_free (subst_pair, heap, gnu_subst_list);
 
 	      /* Now we can finalize it.  */
@@ -7547,16 +7583,15 @@  build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition)
   return gnu_vec;
 }
 
-/* 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.  */
+/* 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 substitutions described in SUBST_LIST.  VARIANT_LIST is a
+   pre-existing VEC onto which newly created entries should be
+   pushed.  */
 
-static tree
+static VEC(variant_desc,heap) *
 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;
 
@@ -7575,18 +7610,20 @@  build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list,
 	 still be accessed.  */
       if (!integer_zerop (qual))
 	{
+	  variant_desc *v;
 	  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);
+
+	  v = VEC_safe_push (variant_desc, heap, variant_list, NULL);
+	  v->type = variant_type;
+	  v->field = gnu_field;
+	  v->qual = qual;
+	  v->record = NULL_TREE;
 
 	  /* 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);
+	    variant_list = build_variant_list (TREE_TYPE (variant_subpart),
+					       subst_list, variant_list);
 
 	  /* If the new qualifier is unconditionally true, the subsequent
 	     variants cannot be accessed.  */
@@ -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
@@ -8319,14 +8356,17 @@  get_variant_part (tree record_type)
    layout.  */
 
 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,
 			  VEC(subst_pair,heap) *subst_list)
 {
   tree offset = DECL_FIELD_OFFSET (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;
+  variant_desc *v;
+  unsigned ix;
 
   /* First create the type of the variant part from that of the old one.  */
   new_union_type = make_node (QUAL_UNION_TYPE);
@@ -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);
 
   /* 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;
 
       /* 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,
 	continue;
 
       /* 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);
 
       /* 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 = v->type;
       old_variant_subpart = get_variant_part (old_variant);
       if (old_variant_subpart)
 	{
@@ -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,
 				  TYPE_SIZE (new_variant),
 				  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_CHAIN (new_field) = union_field_list;
       union_field_list = new_field;