From patchwork Fri Jul 16 02:08:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 59062 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A6A72B6F06 for ; Fri, 16 Jul 2010 12:08:59 +1000 (EST) Received: (qmail 27349 invoked by alias); 16 Jul 2010 02:08:56 -0000 Received: (qmail 27014 invoked by uid 22791); 16 Jul 2010 02:08:54 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 16 Jul 2010 02:08:48 +0000 Received: (qmail 17323 invoked from network); 16 Jul 2010 02:08:46 -0000 Received: from unknown (HELO localhost) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 16 Jul 2010 02:08:46 -0000 Date: Thu, 15 Jul 2010 19:08:46 -0700 From: Nathan Froyd To: gcc-patches@gcc.gnu.org Subject: [PATCH] rewrite Ada's build_variant_list to build a VEC Message-ID: <20100716020846.GY12333@codesourcery.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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. 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;