From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30103 invoked by alias); 1 Dec 2003 07:02:29 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 30092 invoked from network); 1 Dec 2003 07:02:28 -0000 Received: from unknown (HELO mta4.rcsntx.swbell.net) (151.164.30.28) by sources.redhat.com with SMTP; 1 Dec 2003 07:02:28 -0000 Received: from bothner.com (adsl-216-102-199-253.dsl.snfc21.pacbell.net [216.102.199.253]) by mta4.rcsntx.swbell.net (8.12.10/8.12.10) with ESMTP id hB172Qm6016780 for ; Mon, 1 Dec 2003 01:02:27 -0600 (CST) Message-ID: <3FCAE78E.2060505@bothner.com> Date: Mon, 01 Dec 2003 07:02:00 -0000 From: Per Bothner User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5) Gecko/20031007 X-Accept-Language: en-us, en MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org Subject: [cs] patch to re-use tag types Content-Type: multipart/mixed; boundary="------------010309060102010905070603" X-SW-Source: 2003-12/txt/msg00019.txt.bz2 This is a multi-part message in MIME format. --------------010309060102010905070603 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1037 I checked the attached patch into the compile server. This patch handle tag types such as 'struct foo'. Suppose some fragment declares or defines 'struct foo', and perhaps uses 'struct foo' in a declaration. Now suppose a new compilation refers to 'struct foo', but we haven't included any old fragments that refer to 'struct foo'. I.e. 'struct foo' was references in a previous compilation unit, but we hav't seen it yet in the current compilation union. In that case we want to re-use the same RECORD_TYPE for 'struct foo' that we already have. This is because if we later re-use the fragment (form the previous complation) that references 'struct foo' we want these to be the same RECORD_TYPE. A cleaner solution might be to use the C_DECL_INVISIBLE flag, attached to the TYPE_STUB_DECL. I might do that if I fix the TYPE_STUB_DECL kludge, as I'm tempted to. The patches also changes some functions to use the newtrack_declarations and track_dependencies globals. -- --Per Bothner per@bothner.com http://per.bothner.com/ --------------010309060102010905070603 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="save-tags.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="save-tags.patch" Content-length: 8563 2003-11-30 Per Bothner Remember a tag type across compilation units. * gcc.c (TYPE_IS_OLD_TAG): New macro. * gcc.c (restore_fragment_bindings): Chain new decl after old one. When restoring a tag, reuse old tag type, and clear TYPE_IS_OLD_TAG. (poplevel): If popping a global tag, keep the IDNTEFIER_TAG_VALUE, but hide it using TYPE_IS_OLD_TAG. (lookup_tag, shadow_tag_warned, xref_tag, start_struct, start_enum, finish_enum): Handle TYPE_IS_OLD_TAG. * c-decl.c (pushdecl, lookup_name, finish_enum): Use new track_declarations global. Index: c-decl.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v retrieving revision 1.417.2.7 diff -u -p -r1.417.2.7 c-decl.c --- c-decl.c 7 Nov 2003 21:06:22 -0000 1.417.2.7 +++ c-decl.c 1 Dec 2003 06:51:45 -0000 @@ -158,6 +158,11 @@ static int warn_about_return_type; /* Nonzero when starting a function declared `extern inline'. */ static int current_extern_inline; + +/* For a RECORD_TYPE, UNION_TYPE or ENUM_TYPE means we haven't seen + a mention of it this compilation unit. + An alternative solution: use C_DECL_INVISIBLE on the TYPE_STUB_DECL. */ +#define TYPE_IS_OLD_TAG(TYPE) TYPE_STRING_FLAG (TYPE) /* Each c_scope structure describes the complete contents of one scope. Three scopes are distinguished specially: the innermost or current @@ -396,9 +401,23 @@ restore_fragment_bindings (tree bindings { tree n = DECL_NAME (x); if (n != NULL_TREE) - IDENTIFIER_SYMBOL_VALUE (n) = x; - TREE_CHAIN (x) = b->names; - b->names = x; + { + tree old = IDENTIFIER_SYMBOL_VALUE (n); + if (old != NULL_TREE) + { + TREE_CHAIN (x) = TREE_CHAIN (old); + TREE_CHAIN (old) = x; + if (b->names_last == old) + b->names_last = x; + } + else + { + SCOPE_LIST_APPEND (b, names, x); + TREE_CHAIN (x) = NULL_TREE; + } + IDENTIFIER_SYMBOL_VALUE (n) = x; + TREE_USED (x) = 0; + } i++; } #if 0 @@ -426,20 +445,27 @@ restore_fragment_bindings (tree bindings { /* lookup_tag/pushtag/finish_struct */ tree type = x; tree name = TYPE_NAME (type); + tree fields = TREE_VEC_ELT (bindings, i + 1); + tree size = TREE_VEC_ELT (bindings, i + 2); if (name != NULL_TREE) { - if (IDENTIFIER_TAG_VALUE (name) == NULL) + if (IDENTIFIER_TAG_VALUE (name) == NULL_TREE + || TYPE_IS_OLD_TAG (IDENTIFIER_TAG_VALUE (name))) { IDENTIFIER_TAG_VALUE (name) = type; + TYPE_IS_OLD_TAG (type) = 0; b->tags = tree_cons (name, x, b->tags); TYPE_SIZE (type) = NULL_TREE; TYPE_FIELDS (type) = NULL_TREE; } } - if (TYPE_SIZE (type) == NULL_TREE) + if (fields != NULL) { - TYPE_FIELDS (type) = TREE_VEC_ELT (bindings, i + 1); - TYPE_SIZE (type) = TREE_VEC_ELT (bindings, i + 2); + for (x = TYPE_MAIN_VARIANT (type); x; x = TYPE_NEXT_VARIANT (x)) + { + TYPE_FIELDS (x) = fields; + TYPE_SIZE (x) = size; + } } i += 3; } @@ -455,11 +481,21 @@ lang_clear_identifier (pfile, node, v) void *v ATTRIBUTE_UNUSED; { tree tnode = HT_IDENT_TO_GCC_IDENT (node); + tree t; if (TREE_CODE (tnode) != IDENTIFIER_NODE) abort(); IDENTIFIER_SYMBOL_VALUE (tnode) = NULL_TREE; - IDENTIFIER_TAG_VALUE (tnode) = NULL_TREE; + t = IDENTIFIER_TAG_VALUE (tnode); + if (t != NULL) + { + /* We want to re-use the same type for subsequent compiles. */ + TYPE_IS_OLD_TAG (t) = 1; + TYPE_SIZE (t) = NULL_TREE; + TYPE_FIELDS (t) = NULL_TREE; + } IDENTIFIER_LABEL_VALUE (tnode) = NULL_TREE; + TREE_USED (tnode) = 0; + TREE_PUBLIC (tnode) = 0; reset_hashnode (node); return 1; @@ -758,8 +794,15 @@ poplevel (int keep, int dummy ATTRIBUTE_ decl = scope->function_body ? current_function_decl : block; for (p = scope->tags; p; p = TREE_CHAIN (p)) { - if (TREE_PURPOSE (p)) - IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0; + tree tag; + if (TREE_PURPOSE (p) + && (tag = IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p))) != NULL_TREE) + { + if (current_scope == global_scope) + TYPE_IS_OLD_TAG (tag) = 1; + else + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0; + } if (decl) TYPE_CONTEXT (TREE_VALUE (p)) = decl; } @@ -835,15 +878,18 @@ pushtag (tree name, tree type) if (TYPE_NAME (type) == 0) TYPE_NAME (type) = name; - if (IDENTIFIER_TAG_VALUE (name)) + if (IDENTIFIER_TAG_VALUE (name) + && ! TYPE_IS_OLD_TAG (IDENTIFIER_TAG_VALUE (name))) b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name), b->shadowed_tags); IDENTIFIER_TAG_VALUE (name) = type; } + TYPE_IS_OLD_TAG (type) = 0; b->tags = tree_cons (name, type, b->tags); #if 0 + if (track_declarations) /*server_mode >= 0 && server_mode != 1*/ if (b == global_scope && server_mode >= 0 && server_mode != 1) { note_fragment_binding_1 (b->tags); @@ -1812,8 +1858,7 @@ pushdecl (tree x) return old; } - if (server_mode >= 0 && server_mode != 1 - && scope == global_scope) + if (track_declarations && scope == global_scope) { SET_DECL_FRAGMENT (x, current_c_fragment); note_fragment_binding_1 (x); @@ -1858,8 +1903,7 @@ pushdecl (tree x) } /* Install the new declaration in the requested scope. */ - if (server_mode >= 0 && server_mode != 1 - && scope == global_scope) + if (track_declarations && scope == global_scope) { SET_DECL_FRAGMENT (x, current_c_fragment); note_fragment_binding_1 (x); @@ -2267,7 +2311,7 @@ lookup_tag (enum tree_code code, tree na tree tag = IDENTIFIER_TAG_VALUE (name); int thislevel = 0; - if (!tag) + if (!tag || TYPE_IS_OLD_TAG (tag)) return 0; /* We only care about whether it's in this level if @@ -2328,9 +2372,7 @@ lookup_name (tree name) if (C_DECL_INVISIBLE (decl)) return 0; /* FIXME also need to do this for C++ !*/ - if (decl != NULL_TREE - && (server_mode > 1 - || server_mode == 0 /* ??? */)) + if (decl != NULL_TREE && track_dependencies) register_decl_dependency (decl); return decl; } @@ -2509,8 +2551,6 @@ shadow_tag (tree declspecs) void shadow_tag_warned (tree declspecs, int warned) - - /* 1 => we have done a pedwarn. 2 => we have done a warning, but no pedwarn. */ { @@ -2553,7 +2593,10 @@ shadow_tag_warned (tree declspecs, int w if (t == 0) { - t = make_node (code); + if ((t = IDENTIFIER_TAG_VALUE (name)) == NULL + || ! TYPE_IS_OLD_TAG (t) + || TREE_CODE (t) != code) + t = make_node (code); pushtag (name, t); } note_tag (t); @@ -4804,7 +4847,11 @@ xref_tag (enum tree_code code, tree name When a real declaration of this type is found, the forward-reference will be altered into a real type. */ - ref = make_node (code); + if (name == NULL_TREE + || (ref = IDENTIFIER_TAG_VALUE (name)) == NULL + || ! TYPE_IS_OLD_TAG (ref) + || TREE_CODE (ref) != code) + ref = make_node (code); if (code == ENUMERAL_TYPE) { /* Give the type a default layout like unsigned int @@ -4852,7 +4899,11 @@ start_struct (enum tree_code code, tree { /* Otherwise create a forward-reference just so the tag is in scope. */ - ref = make_node (code); + if (name == NULL_TREE + || (ref = IDENTIFIER_TAG_VALUE (name)) == NULL_TREE + || ! TYPE_IS_OLD_TAG (ref) + || TREE_CODE (ref) != code) + ref = make_node (code); pushtag (name, ref); } @@ -5187,7 +5238,7 @@ finish_struct (tree t, tree fieldlist, t layout_type (t); - if (server_mode >= 0 && server_mode != 1) + if (track_declarations) /*server_mode >= 0 && server_mode != 1*/ { note_fragment_binding_3 (t, fieldlist, TYPE_SIZE (t)); } @@ -5366,7 +5417,11 @@ start_enum (tree name) if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE) { - enumtype = make_node (ENUMERAL_TYPE); + if (name == NULL_TREE + || (enumtype = IDENTIFIER_TAG_VALUE (name)) == NULL_TREE + || ! TYPE_IS_OLD_TAG (enumtype) + || TREE_CODE (enumtype) != ENUMERAL_TYPE) + enumtype = make_node (ENUMERAL_TYPE); pushtag (name, enumtype); } note_tag (enumtype); @@ -5499,7 +5554,7 @@ finish_enum (tree enumtype, tree values, TYPE_VALUES (enumtype) = values; } - if (server_mode >= 0 && server_mode != 1) + if (track_declarations) { note_fragment_binding_3 (enumtype, values, TYPE_SIZE (enumtype)); } --------------010309060102010905070603--