diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 662bf28e60f..00d557730ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-05-29 Geoffrey Keating + + * gengtype-yacc.y: Add NESTED_PTR token. + (option): Record `nested_ptr' option. + * gengtype-lex.l: Handle `nested_ptr' keyword. + * gengtype.c (walk_type): Process `nested_ptr' option. + * gengtype.h (struct nested_ptr_data): New. + * doc/gty.texi (GTY Options): Document `nested_ptr' option. + * stringpool.c (struct string_pool_data): Make 'entries' point to + ht_identifier instead of tree. + (gt_pch_save_stringpool): Don't adjust pointers. + (gt_pch_restore_stringpool): Call ht_load. + 2004-05-29 Jason Merrill * gimplify.c (gimplify_expr): Don't build a statement list diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi index d43feca7221..c375e24042d 100644 --- a/gcc/doc/gty.texi +++ b/gcc/doc/gty.texi @@ -291,6 +291,19 @@ this field is always @code{NULL}. This is used to avoid requiring backends to define certain optional structures. It doesn't work with language frontends. +@findex nested_ptr +@item nested_ptr (@var{type}, "@var{to expression}", "@var{from expression}") + +The type machinery expects all pointers to point to the start of an +object. Sometimes for abstraction purposes it's convenient to have +a pointer which points inside an object. So long as it's possible to +convert the original object to and from the pointer, such pointers +can still be used. @var{type} is the type of the original object, +the @var{to expression} returns the pointer given the original object, +and the @var{from expression} returns the original object given +the pointer. The pointer will be available using the @code{%h} +escape. + @findex chain_next @findex chain_prev @item chain_next ("@var{expression}") diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index 19d7691f35e..d7fa27ff3bc 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -1,6 +1,6 @@ /* -*- indented-text -*- */ /* Process source files and output type information. - Copyright (C) 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -235,6 +235,7 @@ ITYPE {IWORD}({WS}{IWORD})* "struct"/[^[:alnum:]_] { return STRUCT; } "enum"/[^[:alnum:]_] { return ENUM; } "ptr_alias"/[^[:alnum:]_] { return ALIAS; } +"nested_ptr"/[^[:alnum:]_] { return NESTED_PTR; } [0-9]+ { return NUM; } "param"[0-9]*"_is"/[^[:alnum:]_] { yylval.s = xmemdup (yytext, yyleng, yyleng+1); diff --git a/gcc/gengtype-yacc.y b/gcc/gengtype-yacc.y index 02136dc0d29..2e7b6a70575 100644 --- a/gcc/gengtype-yacc.y +++ b/gcc/gengtype-yacc.y @@ -1,6 +1,6 @@ /* -*- indented-text -*- */ /* Process source files and output type information. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -44,6 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA %token STRUCT %token ENUM %token ALIAS +%token NESTED_PTR %token PARAM_IS %token NUM %token PERCENTPERCENT "%%" @@ -279,6 +280,13 @@ option: ID { $$ = create_option ($1, (void *)$3); } | type_option '(' type ')' { $$ = create_option ($1, adjust_field_type ($3, NULL)); } + | NESTED_PTR '(' type ',' stringseq ',' stringseq ')' + { + struct nested_ptr_data d = + { adjust_field_type ($3, NULL), $5, $7 }; + $$ = create_option ("nested_ptr", + xmemdup (&d, sizeof (d), sizeof (d))); + } ; optionseq: option diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 95c88efd48b..804ef70320a 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1509,6 +1509,7 @@ walk_type (type_p t, struct walk_type_data *d) int use_param_num = -1; int use_params_p = 0; options_p oo; + const struct nested_ptr_data *nested_ptr_d = NULL; d->needs_cast_p = 0; for (oo = d->opt; oo; oo = oo->next) @@ -1523,6 +1524,8 @@ walk_type (type_p t, struct walk_type_data *d) use_params_p = 1; else if (strcmp (oo->name, "desc") == 0) desc = (const char *)oo->info; + else if (strcmp (oo->name, "nested_ptr") == 0) + nested_ptr_d = (const struct nested_ptr_data *)oo->info ; else if (strcmp (oo->name, "dot") == 0) ; else if (strcmp (oo->name, "tag") == 0) @@ -1623,7 +1626,48 @@ walk_type (type_p t, struct walk_type_data *d) break; } - d->process_field (t->u.p, d); + if (nested_ptr_d) + { + const char *oldprevval2 = d->prev_val[2]; + + if (! UNION_OR_STRUCT_P (nested_ptr_d->type)) + { + error_at_line (d->line, + "field `%s' has invalid " + "option `nested_ptr'\n", + d->val); + return; + } + + d->prev_val[2] = d->val; + oprintf (d->of, "%*s{\n", d->indent, ""); + d->indent += 2; + d->val = xasprintf ("x%d", d->counter++); + oprintf (d->of, "%*s%s %s * %s =\n", d->indent, "", + (nested_ptr_d->type->kind == TYPE_UNION + ? "union" : "struct"), + nested_ptr_d->type->u.s.tag, d->val); + oprintf (d->of, "%*s", d->indent + 2, ""); + output_escaped_param (d, nested_ptr_d->convert_from, + "nested_ptr"); + oprintf (d->of, ";\n"); + + d->process_field (nested_ptr_d->type, d); + + oprintf (d->of, "%*s%s = ", d->indent, "", + d->prev_val[2]); + d->prev_val[2] = d->val; + output_escaped_param (d, nested_ptr_d->convert_to, + "nested_ptr"); + oprintf (d->of, ";\n"); + + d->indent -= 2; + oprintf (d->of, "%*s}\n", d->indent, ""); + d->val = d->prev_val[2]; + d->prev_val[2] = oldprevval2; + } + else + d->process_field (t->u.p, d); } else { diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 55ece115073..bf3c5624ced 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -37,6 +37,17 @@ enum typekind { TYPE_PARAM_STRUCT }; +typedef struct pair *pair_p; +typedef struct type *type_p; +typedef unsigned lang_bitmap; + +/* Option data for the 'nested_ptr' option. */ +struct nested_ptr_data { + type_p type; + const char *convert_to; + const char *convert_from; +}; + /* A way to pass data through to the output end. */ typedef struct options { struct options *next; @@ -44,10 +55,6 @@ typedef struct options { const void *info; } *options_p; -typedef struct pair *pair_p; -typedef struct type *type_p; -typedef unsigned lang_bitmap; - /* A name and a type. */ struct pair { pair_p next; diff --git a/gcc/stringpool.c b/gcc/stringpool.c index 781518b9f7d..d17f31decdd 100644 --- a/gcc/stringpool.c +++ b/gcc/stringpool.c @@ -1,5 +1,5 @@ /* String pool for GCC. - Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -201,7 +201,11 @@ gt_pch_n_S (const void *x) struct string_pool_data GTY(()) { - tree * GTY((length ("%h.nslots"))) entries; + struct ht_identifier * * + GTY((length ("%h.nslots"), + nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL", + "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL"))) + entries; unsigned int nslots; unsigned int nelements; }; @@ -237,25 +241,20 @@ ht_copy_and_clear (cpp_reader *r ATTRIBUTE_UNUSED, hashnode hp, const void *ht2_ static struct ht *saved_ident_hash; -/* The hash table contains pointers to the cpp_hashnode inside the - lang_identifier. The PCH machinery can't handle pointers that refer - to the inside of an object, so to save the hash table for PCH the - pointers are adjusted and stored in the variable SPD. */ +/* Prepare the stringpool to be written (by clearing all the cpp parts + of each entry) and place the data to be saved in SPD. Save the + current state in SAVED_IDENT_HASH so that gt_pch_fixup_stringpool + can restore it. */ void gt_pch_save_stringpool (void) { - unsigned int i; - spd = ggc_alloc (sizeof (*spd)); spd->nslots = ident_hash->nslots; spd->nelements = ident_hash->nelements; - spd->entries = ggc_alloc (sizeof (tree *) * spd->nslots); - for (i = 0; i < spd->nslots; i++) - if (ident_hash->entries[i] != NULL) - spd->entries[i] = HT_IDENT_TO_GCC_IDENT (ident_hash->entries[i]); - else - spd->entries[i] = NULL; + spd->entries = ggc_alloc (sizeof (spd->entries[0]) * spd->nslots); + memcpy (spd->entries, ident_hash->entries, + spd->nslots * sizeof (spd->entries[0])); saved_ident_hash = ht_create (14); saved_ident_hash->alloc_node = alloc_node; @@ -274,23 +273,12 @@ gt_pch_fixup_stringpool (void) } /* A PCH file has been restored, which loaded SPD; fill the real hash table - with adjusted pointers from SPD. */ + from SPD. */ void gt_pch_restore_stringpool (void) { - unsigned int i; - - ident_hash->nslots = spd->nslots; - ident_hash->nelements = spd->nelements; - ident_hash->entries = xrealloc (ident_hash->entries, - sizeof (hashnode) * spd->nslots); - for (i = 0; i < spd->nslots; i++) - if (spd->entries[i] != NULL) - ident_hash->entries[i] = GCC_IDENT_TO_HT_IDENT (spd->entries[i]); - else - ident_hash->entries[i] = NULL; - + ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false); spd = NULL; } diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 8ebe6f52bac..71a449504b0 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,10 @@ +2004-05-29 Geoffrey Keating + + * symtab.c (ht_create): Set entries_owned. + (ht_destroy): Honour entries_owned. + (ht_expand): Likewise. + (ht_load): New. + 2004-05-26 Paolo Bonzini PR bootstrap/15651 diff --git a/libcpp/include/ChangeLog b/libcpp/include/ChangeLog index f6c47fa6daf..a2f4bc5e3ef 100644 --- a/libcpp/include/ChangeLog +++ b/libcpp/include/ChangeLog @@ -1,3 +1,8 @@ +2004-05-29 Geoffrey Keating + + * symtab.h (struct ht): New field 'entries_owned' + (ht_load): New prototype. + 2004-05-23 Paolo Bonzini * cpplib.h: Moved from gcc. Change header guard name. diff --git a/libcpp/include/symtab.h b/libcpp/include/symtab.h index 8b793320b56..85e285b419f 100644 --- a/libcpp/include/symtab.h +++ b/libcpp/include/symtab.h @@ -1,5 +1,5 @@ /* Hash tables. - Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -58,6 +58,9 @@ struct ht /* Table usage statistics. */ unsigned int searches; unsigned int collisions; + + /* Should 'entries' be freed when it is no longer needed? */ + bool entries_owned; }; /* Initialize the hashtable with 2 ^ order entries. */ @@ -75,6 +78,10 @@ extern hashnode ht_lookup (hash_table *, const unsigned char *, typedef int (*ht_cb) (struct cpp_reader *, hashnode, const void *); extern void ht_forall (hash_table *, ht_cb, const void *); +/* Restore the hash table. */ +extern void ht_load (hash_table *ht, hashnode *entries, + unsigned int nslots, unsigned int nelements, bool own); + /* Dump allocation statistics to stderr. */ extern void ht_dump_statistics (hash_table *); diff --git a/libcpp/symtab.c b/libcpp/symtab.c index 39cecedf72f..c80dfa25cc0 100644 --- a/libcpp/symtab.c +++ b/libcpp/symtab.c @@ -1,5 +1,5 @@ /* Hash tables. - Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -68,6 +68,7 @@ ht_create (unsigned int order) obstack_alignment_mask (&table->stack) = 0; table->entries = xcalloc (nslots, sizeof (hashnode)); + table->entries_owned = true; table->nslots = nslots; return table; } @@ -78,7 +79,8 @@ void ht_destroy (hash_table *table) { obstack_free (&table->stack, NULL); - free (table->entries); + if (table->entries_owned) + free (table->entries); free (table); } @@ -199,7 +201,9 @@ ht_expand (hash_table *table) } while (++p < limit); - free (table->entries); + if (table->entries_owned) + free (table->entries); + table->entries_owned = true; table->entries = nentries; table->nslots = size; } @@ -222,6 +226,20 @@ ht_forall (hash_table *table, ht_cb cb, const void *v) while (++p < limit); } +/* Restore the hash table. */ +void +ht_load (hash_table *ht, hashnode *entries, + unsigned int nslots, unsigned int nelements, + bool own) +{ + if (ht->entries_owned) + free (ht->entries); + ht->entries = entries; + ht->nslots = nslots; + ht->nelements = nelements; + ht->entries_owned = own; +} + /* Dump allocation statistics to stderr. */ void