Patchwork rewrite Ada's build_variant_list to build a VEC

login
register
mail settings
Submitter Nathan Froyd
Date July 16, 2010, 2:08 a.m.
Message ID <20100716020846.GY12333@codesourcery.com>
Download mbox | patch
Permalink /patch/59062/
State New
Headers show

Comments

Nathan Froyd - July 16, 2010, 2:08 a.m.
The patch does just what $SUBJECT suggests.  It's so much nicer to have
a proper data structure than an ad-hoc collection of TREE_LIST and
TREE_VEC, and it'll be a good bit smaller and more cache-friendly, too.

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.

Tested on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

	* 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.
Eric Botcazou - Aug. 4, 2010, 3:38 p.m.
> 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.

> 	* 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?

Patch

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 54d0222..69683ed 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -113,6 +113,23 @@  static VEC (tree,heap) *defer_finalize_list;
 static GTY ((if_marked ("tree_int_map_marked_p"),
 	     param_is (struct tree_int_map))) htab_t annotate_value_cache;
 
+typedef struct GTY(()) rec_variant_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;
+} rec_variant;
+
+DEF_VEC_O(rec_variant);
+DEF_VEC_ALLOC_O(rec_variant,heap);
+
 enum alias_set_op
 {
   ALIAS_SET_COPY,
@@ -147,7 +164,8 @@  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 tree build_subst_list (Entity_Id, Entity_Id, bool);
-static tree build_variant_list (tree, tree, tree);
+static void build_variant_list_1 (tree, tree, VEC(rec_variant,heap) **);
+static VEC(rec_variant,heap) *build_variant_list (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);
@@ -157,7 +175,8 @@  static void check_ok_for_atomic (tree, Entity_Id, bool);
 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 tree create_variant_part_from (tree, VEC(rec_variant,heap) *,
+				      tree, tree, tree);
 static void copy_and_substitute_in_size (tree, tree, tree);
 static void rest_of_type_decl_compilation_no_defer (tree);
 
@@ -3041,9 +3060,10 @@  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_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(rec_variant,heap) *gnu_variant_list;
 
 	      gnu_type = make_node (RECORD_TYPE);
 	      TYPE_NAME (gnu_type) = gnu_entity_name;
@@ -3071,15 +3091,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)
 		{
+		  rec_variant *v;
+		  unsigned ix;
+
 		  gnu_variant_list
 		    = build_variant_list (TREE_TYPE (gnu_variant_part),
-					  gnu_subst_list, NULL_TREE);
+					  gnu_subst_list);
 
 		  /* 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 (rec_variant, gnu_variant_list,
+					    ix, v)
+		    if (!integer_onep (v->qual))
 		      {
 			selected_variant = false;
 			break;
@@ -3087,20 +3111,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 (rec_variant, 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;
 		}
 
@@ -3183,13 +3208,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);
+			rec_variant *v;
+			unsigned ix;
+
+			t = NULL_TREE;
+			FOR_EACH_VEC_ELT_REVERSE (rec_variant,
+						  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
@@ -3315,6 +3350,8 @@  gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 					 gnat_entity);
 		}
 
+	      VEC_free (rec_variant, heap, gnu_variant_list);
+
 	      /* Now we can finalize it.  */
 	      rest_of_record_type_compilation (gnu_type);
 	    }
@@ -7541,15 +7578,13 @@  build_subst_list (Entity_Id gnat_subtype, Entity_Id gnat_type, bool definition)
   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.  */
+/* 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.  */
 
-static tree
-build_variant_list (tree qual_union_type, tree subst_list, tree gnu_list)
+static void
+build_variant_list_1 (tree qual_union_type, tree subst_list,
+		      VEC(rec_variant,heap) **variant_list)
 {
   tree gnu_field;
 
@@ -7566,18 +7601,20 @@  build_variant_list (tree qual_union_type, tree subst_list, tree gnu_list)
 	 still be accessed.  */
       if (!integer_zerop (qual))
 	{
+	  rec_variant *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 (rec_variant, 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);
+	    build_variant_list_1 (TREE_TYPE (variant_subpart),
+				  subst_list, variant_list);
 
 	  /* If the new qualifier is unconditionally true, the subsequent
 	     variants cannot be accessed.  */
@@ -7585,8 +7622,16 @@  build_variant_list (tree qual_union_type, tree subst_list, tree gnu_list)
 	    break;
 	}
     }
+}
 
-  return gnu_list;
+static VEC(rec_variant,heap) *
+build_variant_list (tree qual_union_type, tree subst_list)
+{
+  VEC(rec_variant,heap) *variant_list = NULL;
+
+  build_variant_list_1 (qual_union_type, subst_list, &variant_list);
+
+  return variant_list;
 }
 
 /* UINT_SIZE is a Uint giving the specified size for an object of GNU_TYPE
@@ -8307,13 +8352,16 @@  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(rec_variant,heap) *variant_list,
 			  tree record_type, tree pos_list, tree 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;
+  rec_variant *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);
@@ -8341,9 +8389,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 (rec_variant, 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.  */
@@ -8351,12 +8399,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)
 	{
@@ -8378,7 +8426,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;