From b5b04b5b7ad009488a07a945e28001edaf5809b5 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 10 May 2012 20:04:00 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 12 +++ gdb/block.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++-- gdb/block.h | 22 +++++ gdb/symtab.h | 17 ++++ 4 files changed, 284 insertions(+), 7 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9e04f3493e..d3ec55a6ac 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +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. + 2012-05-10 Tom Tromey * jv-lang.c (get_java_class_symtab): Use allocate_global_block, diff --git a/gdb/block.c b/gdb/block.c index d3bc5ea959..38b64b33af 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -393,15 +393,138 @@ set_block_symtab (struct block *block, struct symtab *symtab) 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 @@ block_iterator_first (const struct block *block, 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 @@ block_iter_name_first (const struct block *block, 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 @@ block_iter_name_first (const struct block *block, 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 @@ block_iter_match_first (const struct block *block, 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 @@ block_iter_match_next (const char *name, 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); } diff --git a/gdb/block.h b/gdb/block.h index de674a8665..b4f92f3eb6 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -186,6 +186,28 @@ extern void set_block_symtab (struct block *, struct symtab *); 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; diff --git a/gdb/symtab.h b/gdb/symtab.h index 61e7c0fdb9..526fe5a91b 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -833,6 +833,23 @@ struct symtab /* 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