* symtab.h (struct symtab) <includes, user>: New fields.

* block.h (struct block_iterator) <d, idx, which>: 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.
This commit is contained in:
Tom Tromey 2012-05-10 20:04:00 +00:00
parent 84a146c9d3
commit b5b04b5b7a
4 changed files with 284 additions and 7 deletions

View File

@ -1,3 +1,15 @@
2012-05-10 Tom Tromey <tromey@redhat.com>
* symtab.h (struct symtab) <includes, user>: New fields.
* block.h (struct block_iterator) <d, idx, which>: 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 <tromey@redhat.com>
* jv-lang.c (get_java_class_symtab): Use allocate_global_block,

View File

@ -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);
}

View File

@ -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;

View File

@ -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