From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15472 invoked by alias); 10 May 2012 20:04:17 -0000 Received: (qmail 15450 invoked by uid 22791); 10 May 2012 20:04:12 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 May 2012 20:03:42 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4AK3fBf026873 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 10 May 2012 16:03:41 -0400 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q4AK3dPP023380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 10 May 2012 16:03:40 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Subject: Re: [5/10] add notion of included symtabs References: <878vhjbqrq.fsf@fleche.redhat.com> Date: Thu, 10 May 2012 20:04:00 -0000 In-Reply-To: <878vhjbqrq.fsf@fleche.redhat.com> (Tom Tromey's message of "Wed, 25 Apr 2012 12:38:49 -0600") Message-ID: <87wr4jajms.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.95 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00383.txt.bz2 >>>>> "Tom" == Tom Tromey writes: Tom> This patch changes symtabs to have a notion of "included" symtabs. Here is the version I am checking in. This takes Jan's comment into account, and it also adds get_block_symtab, which was removed from the previous patch. Tom 2012-05-10 Tom Tromey * symtab.h (struct symtab) : New fields. * block.h (struct block_iterator) : New fields. * block.c (initialize_block_iterator, find_iterator_symtab) (block_iterator_step, block_iter_name_step) (block_iter_match_step): New functions. (block_iterator_first, block_iterator_next) (block_iter_name_first, block_iter_name_next) (block_iter_match_first, block_iter_match_next): Rewrite. (get_block_symtab): New function. Index: block.c =================================================================== RCS file: /cvs/src/src/gdb/block.c,v retrieving revision 1.29 diff -u -r1.29 block.c --- block.c 10 May 2012 19:59:12 -0000 1.29 +++ block.c 10 May 2012 20:02:50 -0000 @@ -393,15 +393,138 @@ gb->symtab = symtab; } +/* Return the symtab of the global block. */ + +static struct symtab * +get_block_symtab (const struct block *block) +{ + struct global_block *gb; + + gdb_assert (BLOCK_SUPERBLOCK (block) == NULL); + gb = (struct global_block *) block; + gdb_assert (gb->symtab != NULL); + return gb->symtab; +} + +/* Initialize a block iterator, either to iterate over a single block, + or, for static and global blocks, all the included symtabs as + well. */ + +static void +initialize_block_iterator (const struct block *block, + struct block_iterator *iter) +{ + enum block_enum which; + struct symtab *symtab; + + iter->idx = -1; + + if (BLOCK_SUPERBLOCK (block) == NULL) + { + which = GLOBAL_BLOCK; + symtab = get_block_symtab (block); + } + else if (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL) + { + which = STATIC_BLOCK; + symtab = get_block_symtab (BLOCK_SUPERBLOCK (block)); + } + else + { + iter->d.block = block; + /* A signal value meaning that we're iterating over a single + block. */ + iter->which = FIRST_LOCAL_BLOCK; + return; + } + + /* If this is an included symtab, find the canonical includer and + use it instead. */ + while (symtab->user != NULL) + symtab = symtab->user; + + /* Putting this check here simplifies the logic of the iterator + functions. If there are no included symtabs, we only need to + search a single block, so we might as well just do that + directly. */ + if (symtab->includes == NULL) + { + iter->d.block = block; + /* A signal value meaning that we're iterating over a single + block. */ + iter->which = FIRST_LOCAL_BLOCK; + } + else + { + iter->d.symtab = symtab; + iter->which = which; + } +} + +/* A helper function that finds the current symtab over whose static + or global block we should iterate. */ + +static struct symtab * +find_iterator_symtab (struct block_iterator *iterator) +{ + if (iterator->idx == -1) + return iterator->d.symtab; + return iterator->d.symtab->includes[iterator->idx]; +} + +/* Perform a single step for a plain block iterator, iterating across + symbol tables as needed. Returns the next symbol, or NULL when + iteration is complete. */ + +static struct symbol * +block_iterator_step (struct block_iterator *iterator, int first) +{ + struct symbol *sym; + + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK); + + while (1) + { + if (first) + { + struct symtab *symtab = find_iterator_symtab (iterator); + const struct block *block; + + /* Iteration is complete. */ + if (symtab == NULL) + return NULL; + + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which); + sym = dict_iterator_first (BLOCK_DICT (block), &iterator->dict_iter); + } + else + sym = dict_iterator_next (&iterator->dict_iter); + + if (sym != NULL) + return sym; + + /* We have finished iterating the appropriate block of one + symtab. Now advance to the next symtab and begin iteration + there. */ + ++iterator->idx; + first = 1; + } +} + /* See block.h. */ struct symbol * block_iterator_first (const struct block *block, struct block_iterator *iterator) { - return dict_iterator_first (block->dict, &iterator->dict_iter); + initialize_block_iterator (block, iterator); + + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iterator_first (block->dict, &iterator->dict_iter); + + return block_iterator_step (iterator, 1); } /* See block.h. */ @@ -409,7 +532,51 @@ struct symbol * block_iterator_next (struct block_iterator *iterator) { - return dict_iterator_next (&iterator->dict_iter); + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iterator_next (&iterator->dict_iter); + + return block_iterator_step (iterator, 0); +} + +/* Perform a single step for a "name" block iterator, iterating across + symbol tables as needed. Returns the next symbol, or NULL when + iteration is complete. */ + +static struct symbol * +block_iter_name_step (struct block_iterator *iterator, const char *name, + int first) +{ + struct symbol *sym; + + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK); + + while (1) + { + if (first) + { + struct symtab *symtab = find_iterator_symtab (iterator); + const struct block *block; + + /* Iteration is complete. */ + if (symtab == NULL) + return NULL; + + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which); + sym = dict_iter_name_first (BLOCK_DICT (block), name, + &iterator->dict_iter); + } + else + sym = dict_iter_name_next (name, &iterator->dict_iter); + + if (sym != NULL) + return sym; + + /* We have finished iterating the appropriate block of one + symtab. Now advance to the next symtab and begin iteration + there. */ + ++iterator->idx; + first = 1; + } } /* See block.h. */ @@ -419,7 +586,12 @@ const char *name, struct block_iterator *iterator) { - return dict_iter_name_first (block->dict, name, &iterator->dict_iter); + initialize_block_iterator (block, iterator); + + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iter_name_first (block->dict, name, &iterator->dict_iter); + + return block_iter_name_step (iterator, name, 1); } /* See block.h. */ @@ -427,7 +599,53 @@ struct symbol * block_iter_name_next (const char *name, struct block_iterator *iterator) { - return dict_iter_name_next (name, &iterator->dict_iter); + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iter_name_next (name, &iterator->dict_iter); + + return block_iter_name_step (iterator, name, 0); +} + +/* Perform a single step for a "match" block iterator, iterating + across symbol tables as needed. Returns the next symbol, or NULL + when iteration is complete. */ + +static struct symbol * +block_iter_match_step (struct block_iterator *iterator, + const char *name, + symbol_compare_ftype *compare, + int first) +{ + struct symbol *sym; + + gdb_assert (iterator->which != FIRST_LOCAL_BLOCK); + + while (1) + { + if (first) + { + struct symtab *symtab = find_iterator_symtab (iterator); + const struct block *block; + + /* Iteration is complete. */ + if (symtab == NULL) + return NULL; + + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), iterator->which); + sym = dict_iter_match_first (BLOCK_DICT (block), name, + compare, &iterator->dict_iter); + } + else + sym = dict_iter_match_next (name, compare, &iterator->dict_iter); + + if (sym != NULL) + return sym; + + /* We have finished iterating the appropriate block of one + symtab. Now advance to the next symtab and begin iteration + there. */ + ++iterator->idx; + first = 1; + } } /* See block.h. */ @@ -438,8 +656,13 @@ symbol_compare_ftype *compare, struct block_iterator *iterator) { - return dict_iter_match_first (block->dict, name, compare, - &iterator->dict_iter); + initialize_block_iterator (block, iterator); + + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iter_match_first (block->dict, name, compare, + &iterator->dict_iter); + + return block_iter_match_step (iterator, name, compare, 1); } /* See block.h. */ @@ -449,5 +672,8 @@ symbol_compare_ftype *compare, struct block_iterator *iterator) { - return dict_iter_match_next (name, compare, &iterator->dict_iter); + if (iterator->which == FIRST_LOCAL_BLOCK) + return dict_iter_match_next (name, compare, &iterator->dict_iter); + + return block_iter_match_step (iterator, name, compare, 0); } Index: block.h =================================================================== RCS file: /cvs/src/src/gdb/block.h,v retrieving revision 1.28 diff -u -r1.28 block.h --- block.h 10 May 2012 19:59:12 -0000 1.28 +++ block.h 10 May 2012 20:02:50 -0000 @@ -186,6 +186,28 @@ struct block_iterator { + /* If we're iterating over a single block, this holds the block. + Otherwise, it holds the canonical symtab. */ + + union + { + struct symtab *symtab; + const struct block *block; + } d; + + /* If we're iterating over a single block, this is always -1. + Otherwise, it holds the index of the current "included" symtab in + the canonical symtab (that is, d.symtab->includes[idx]), with -1 + meaning the canonical symtab itself. */ + + int idx; + + /* Which block, either static or global, to iterate over. If this + is FIRST_LOCAL_BLOCK, then we are iterating over a single block. + This is used to select which field of 'd' is in use. */ + + enum block_enum which; + /* The underlying dictionary iterator. */ struct dict_iterator dict_iter; Index: symtab.h =================================================================== RCS file: /cvs/src/src/gdb/symtab.h,v retrieving revision 1.205 diff -u -r1.205 symtab.h --- symtab.h 27 Apr 2012 20:47:56 -0000 1.205 +++ symtab.h 10 May 2012 20:02:51 -0000 @@ -833,6 +833,23 @@ /* struct call_site entries for this compilation unit or NULL. */ htab_t call_site_htab; + + /* If non-NULL, then this points to a NULL-terminated vector of + included symbol tables. When searching the static or global + block of this symbol table, the corresponding block of all + included symbol tables will also be searched. Note that this + list must be flattened -- the symbol reader is responsible for + ensuring that this vector contains the transitive closure of all + included symbol tables. */ + + struct symtab **includes; + + /* If this is an included symbol table, this points to one includer + of the table. This user is considered the canonical symbol table + containing this one. An included symbol table may itself be + included by another. */ + + struct symtab *user; }; #define BLOCKVECTOR(symtab) (symtab)->blockvector