From d8044160b7047642e312fb5f713fe0db46171dd8 Mon Sep 17 00:00:00 2001 From: Geoffrey Keating Date: Wed, 9 Jun 2004 20:10:13 +0000 Subject: [PATCH] Index: gcc/ChangeLog 2004-06-09 Geoffrey Keating * Makefile.in (CPPLIB_H): Put files in order of inclusion. (CPP_ID_DATA_H): New. (gtype-desc.o): Update dependencies. (GTFILES): Use CPP_ID_DATA_H. Index: gcc/testsuite/ChangeLog 2004-06-09 Geoffrey Keating * gcc.dg/pch/macro-4.c: New. * gcc.dg/pch/macro-4.hs: New. Index: libcpp/ChangeLog 2004-06-09 Geoffrey Keating * traditional.c (push_replacement_text): Set macro->traditional. (save_replacement_text): Likewise. * pch.c (cpp_write_pch_state): Don't write list of defined macros. (struct save_macro_item): Delete. (struct save_macro_data): Use a character array not the previous structured format. (save_macros): Save macro as text not as internal structures. (cpp_prepare_state): Update for changes to save_macro_data. (cpp_read_state): Don't read macros defined in PCH. Restore -D macros as text. * macro.c (create_iso_definition): Honour alloc_subobject. Clear traditional flag. (_cpp_create_definition): Honour alloc_subobject. * lex.c (cpp_token_val_index): New. * internal.h: Include cpp-id-data.h. (uchar): Move definition to cpp-id-data.h. (U): Likewise. (cpp_macro): Likewise. * directives.c (struct answer): Move to cpp-id-data.h. (do_assert): Honour alloc_subobject. Index: libcpp/include/ChangeLog 2004-06-09 Geoffrey Keating * symtab.h (struct ht): Add field 'alloc_subobject'. * cpplib.h (struct cpp_string): Add GTY marker. (enum cpp_token_fld_kind): New. (struct cpp_token): Add GTY markers. (cpp_token_val_index): Prototype. (CPP_HASHNODE_VALUE_IDX): New. (struct cpp_hashnode): Don't skip fields of 'value' when marking. * cpp-id-data.h: New file. From-SVN: r82851 --- gcc/ChangeLog | 7 ++ gcc/Makefile.in | 16 +-- gcc/gengtype.c | 53 ++++++---- gcc/stringpool.c | 49 ++------- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/pch/macro-4.c | 8 ++ gcc/testsuite/gcc.dg/pch/macro-4.hs | 1 + libcpp/ChangeLog | 24 +++++ libcpp/directives.c | 25 +++-- libcpp/include/ChangeLog | 11 ++ libcpp/include/cpp-id-data.h | 77 ++++++++++++++ libcpp/include/cpplib.h | 68 +++++++++--- libcpp/include/symtab.h | 5 +- libcpp/internal.h | 44 +------- libcpp/lex.c | 22 ++++ libcpp/macro.c | 30 +++++- libcpp/pch.c | 157 +++++++++++----------------- libcpp/traditional.c | 3 + 18 files changed, 372 insertions(+), 233 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pch/macro-4.c create mode 100644 gcc/testsuite/gcc.dg/pch/macro-4.hs create mode 100644 libcpp/include/cpp-id-data.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1184df74999..7f5e57d0efd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-06-09 Geoffrey Keating + + * Makefile.in (CPPLIB_H): Put files in order of inclusion. + (CPP_ID_DATA_H): New. + (gtype-desc.o): Update dependencies. + (GTFILES): Use CPP_ID_DATA_H. + 2004-06-09 Mark Mitchell Revert: diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2fa566aeea1..fc878543323 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -712,10 +712,11 @@ C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H) C_TREE_H = c-tree.h $(C_COMMON_H) SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h PREDICT_H = predict.h predict.def -CPPLIB_H = $(srcdir)/../libcpp/include/cpplib.h \ - $(srcdir)/../libcpp/include/line-map.h +CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \ + $(srcdir)/../libcpp/include/cpplib.h MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h +CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) TREE_GIMPLE_H = tree-gimple.h tree-iterator.h TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \ @@ -1522,10 +1523,11 @@ dumpvers: dumpvers.c version.o: version.c version.h -gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h \ - $(HASHTAB_H) $(TREE_H) $(RTL_H) function.h insn-config.h $(EXPR_H) $(OPTABS_H) \ - libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \ - cselib.h insn-addr.h $(TREE_FLOW_H) +gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ + varray.h $(HASHTAB_H) $(SPLAY_TREE_H) bitmap.h $(TREE_H) $(RTL_H) \ + function.h insn-config.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \ + cselib.h insn-addr.h $(OPTABS_H) libfuncs.h debug.h $(GGC_H) \ + cgraph.h tree-alias-type.h $(TREE_FLOW_H) reload.h $(CPP_ID_DATA_H) ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \ $(HASHTAB_H) toplev.h $(PARAMS_H) hosthooks.h @@ -2289,7 +2291,7 @@ s-preds: genpreds$(build_exeext) $(STAMP) s-preds GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \ - $(srcdir)/../libcpp/include/cpplib.h $(host_xm_file_list) \ + $(CPP_ID_DATA_H) $(host_xm_file_list) \ $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \ $(srcdir)/coverage.c $(srcdir)/function.h $(srcdir)/rtl.h \ $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/libfuncs.h $(SYMTAB_H) \ diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 804ef70320a..5d7082437b0 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -875,7 +875,7 @@ note_yacc_type (options_p o, pair_p fields, pair_p typeinfo, } static void process_gc_options (options_p, enum gc_used_enum, - int *, int *, int *); + int *, int *, int *, type_p *); static void set_gc_used_type (type_p, enum gc_used_enum, type_p *); static void set_gc_used (pair_p); @@ -883,7 +883,7 @@ static void set_gc_used (pair_p); static void process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, - int *pass_param, int *length) + int *pass_param, int *length, type_p *nested_ptr) { options_p o; for (o = opt; o; o = o->next) @@ -895,6 +895,8 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, *pass_param = 1; else if (strcmp (o->name, "length") == 0) *length = 1; + else if (strcmp (o->name, "nested_ptr") == 0) + *nested_ptr = ((const struct nested_ptr_data *) o->info)->type; } /* Set the gc_used field of T to LEVEL, and handle the types it references. */ @@ -914,18 +916,24 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM]) { pair_p f; int dummy; + type_p dummy2; - process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy); + process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, + &dummy2); for (f = t->u.s.fields; f; f = f->next) { int maybe_undef = 0; int pass_param = 0; int length = 0; + type_p nested_ptr = NULL; process_gc_options (f->opt, level, &maybe_undef, &pass_param, - &length); + &length, &nested_ptr); - if (length && f->type->kind == TYPE_POINTER) + if (nested_ptr && f->type->kind == TYPE_POINTER) + set_gc_used_type (nested_ptr, GC_POINTED_TO, + pass_param ? param : NULL); + else if (length && f->type->kind == TYPE_POINTER) set_gc_used_type (f->type->u.p, GC_USED, NULL); else if (maybe_undef && f->type->kind == TYPE_POINTER) set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL); @@ -1015,7 +1023,7 @@ static outf_p create_file (const char *name, const char *oname) { static const char *const hdr[] = { - " Copyright (C) 2003 Free Software Foundation, Inc.\n", + " Copyright (C) 2004 Free Software Foundation, Inc.\n", "\n", "This file is part of GCC.\n", "\n", @@ -1101,6 +1109,7 @@ open_base_files (void) "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h", "tree-alias-type.h", "tree-flow.h", "reload.h", + "cpp-id-data.h", NULL }; const char *const *ifp; @@ -1408,7 +1417,8 @@ struct walk_type_data int used_length; type_p orig_s; const char *reorder_fn; - int needs_cast_p; + bool needs_cast_p; + bool fn_wants_lvalue; }; /* Print a mangled name representing T to OF. */ @@ -1511,7 +1521,7 @@ walk_type (type_p t, struct walk_type_data *d) options_p oo; const struct nested_ptr_data *nested_ptr_d = NULL; - d->needs_cast_p = 0; + d->needs_cast_p = false; for (oo = d->opt; oo; oo = oo->next) if (strcmp (oo->name, "length") == 0) length = (const char *)oo->info; @@ -1525,7 +1535,7 @@ walk_type (type_p t, struct walk_type_data *d) 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 ; + nested_ptr_d = (const struct nested_ptr_data *) oo->info; else if (strcmp (oo->name, "dot") == 0) ; else if (strcmp (oo->name, "tag") == 0) @@ -1643,10 +1653,12 @@ walk_type (type_p t, struct walk_type_data *d) 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, "", + oprintf (d->of, "%*s%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); + nested_ptr_d->type->u.s.tag, + d->fn_wants_lvalue ? "" : "const ", + d->val); oprintf (d->of, "%*s", d->indent + 2, ""); output_escaped_param (d, nested_ptr_d->convert_from, "nested_ptr"); @@ -1654,12 +1666,15 @@ walk_type (type_p t, struct walk_type_data *d) 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"); + if (d->fn_wants_lvalue) + { + 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, ""); @@ -1839,6 +1854,7 @@ walk_type (type_p t, struct walk_type_data *d) d->line = &f->line; d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name); d->opt = f->opt; + d->used_length = false; if (union_p && use_param_p && d->param == NULL) oprintf (d->of, "%*sabort();\n", d->indent, ""); @@ -2231,7 +2247,7 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d) /* For S, a structure that's part of ORIG_S, and using parameters PARAM, write out a routine that: - Is of type gt_note_pointers - - If calls PROCESS_FIELD on each field of S or its substructures. + - Calls PROCESS_FIELD on each field of S or its substructures. */ static void @@ -2259,6 +2275,7 @@ write_local_func_for_structure (type_p orig_s, type_p s, type_p *param) d.prev_val[1] = "not valid postage"; /* Guarantee an error. */ d.prev_val[3] = "x"; d.val = "(*x)"; + d.fn_wants_lvalue = true; oprintf (d.of, "\n"); oprintf (d.of, "void\n"); diff --git a/gcc/stringpool.c b/gcc/stringpool.c index d17f31decdd..0227688f6e1 100644 --- a/gcc/stringpool.c +++ b/gcc/stringpool.c @@ -51,7 +51,12 @@ static struct obstack string_stack; static hashnode alloc_node (hash_table *); static int mark_ident (struct cpp_reader *, hashnode, const void *); -static int ht_copy_and_clear (struct cpp_reader *, hashnode, const void *); + +static void * +stringpool_ggc_alloc (size_t x) +{ + return ggc_alloc (x); +} /* Initialize the string pool. */ void @@ -60,6 +65,7 @@ init_stringpool (void) /* Create with 16K (2^14) entries. */ ident_hash = ht_create (14); ident_hash->alloc_node = alloc_node; + ident_hash->alloc_subobject = stringpool_ggc_alloc; gcc_obstack_init (&string_stack); } @@ -212,39 +218,7 @@ struct string_pool_data GTY(()) static GTY(()) struct string_pool_data * spd; -/* Copy HP into the corresponding entry in HT2, and then clear - the cpplib parts of HP. */ - -static int -ht_copy_and_clear (cpp_reader *r ATTRIBUTE_UNUSED, hashnode hp, const void *ht2_p) -{ - cpp_hashnode *h = CPP_HASHNODE (hp); - struct ht *ht2 = (struct ht *) ht2_p; - - if (h->type != NT_VOID - && (h->flags & NODE_BUILTIN) == 0) - { - cpp_hashnode *h2 = CPP_HASHNODE (ht_lookup (ht2, - NODE_NAME (h), - NODE_LEN (h), - HT_ALLOC)); - h2->type = h->type; - memcpy (&h2->value, &h->value, sizeof (h->value)); - - h->type = NT_VOID; - memset (&h->value, 0, sizeof (h->value)); - } - return 1; -} - -/* The hash table as it was before gt_pch_save_stringpool was called. */ - -static struct ht *saved_ident_hash; - -/* 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. */ +/* Save the stringpool data in SPD. */ void gt_pch_save_stringpool (void) @@ -255,10 +229,6 @@ gt_pch_save_stringpool (void) 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; - ht_forall (ident_hash, ht_copy_and_clear, saved_ident_hash); } /* Return the stringpool to its state before gt_pch_save_stringpool @@ -267,9 +237,6 @@ gt_pch_save_stringpool (void) void gt_pch_fixup_stringpool (void) { - ht_forall (saved_ident_hash, ht_copy_and_clear, ident_hash); - ht_destroy (saved_ident_hash); - saved_ident_hash = 0; } /* A PCH file has been restored, which loaded SPD; fill the real hash table diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 332e3f0628b..c9565dd8949 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-06-09 Geoffrey Keating + + * gcc.dg/pch/macro-4.c: New. + * gcc.dg/pch/macro-4.hs: New. + 2004-06-09 Tobias Schlueter PR fortran/13249 diff --git a/gcc/testsuite/gcc.dg/pch/macro-4.c b/gcc/testsuite/gcc.dg/pch/macro-4.c new file mode 100644 index 00000000000..1c199fa6eb0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pch/macro-4.c @@ -0,0 +1,8 @@ +#define DEFN aa + bb + +#include "macro-4.h" + +int foo(int aa, int bb) +{ + return DEFN; +} diff --git a/gcc/testsuite/gcc.dg/pch/macro-4.hs b/gcc/testsuite/gcc.dg/pch/macro-4.hs new file mode 100644 index 00000000000..5af162d63d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pch/macro-4.hs @@ -0,0 +1 @@ +/* No content! */ diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index d81a049e646..cc2b9316887 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,27 @@ +2004-06-09 Geoffrey Keating + + * traditional.c (push_replacement_text): Set macro->traditional. + (save_replacement_text): Likewise. + * pch.c (cpp_write_pch_state): Don't write list of defined macros. + (struct save_macro_item): Delete. + (struct save_macro_data): Use a character array not the previous + structured format. + (save_macros): Save macro as text not as internal structures. + (cpp_prepare_state): Update for changes to save_macro_data. + (cpp_read_state): Don't read macros defined in PCH. Restore + -D macros as text. + * macro.c (create_iso_definition): Honour alloc_subobject. + Clear traditional flag. + (_cpp_create_definition): Honour alloc_subobject. + * lex.c (cpp_token_val_index): New. + * internal.h: Include cpp-id-data.h. + (uchar): Move definition to cpp-id-data.h. + (U): Likewise. + (cpp_macro): Likewise. + * directives.c (struct answer): Move to cpp-id-data.h. + (do_assert): Honour alloc_subobject. + + 2004-06-09 Paolo Bonzini * Makefile.am (all-local): New. diff --git a/libcpp/directives.c b/libcpp/directives.c index 5a6a342bea5..16873dadecf 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -26,14 +26,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "mkdeps.h" #include "obstack.h" -/* Chained list of answers to an assertion. */ -struct answer -{ - struct answer *next; - unsigned int count; - cpp_token first[1]; -}; - /* Stack of conditionals currently in progress (including both successful and failing conditionals). */ struct if_stack @@ -1727,6 +1719,8 @@ do_assert (cpp_reader *pfile) node = parse_assertion (pfile, &new_answer, T_ASSERT); if (node) { + size_t answer_size; + /* Place the new answer in the answer list. First check there is not a duplicate. */ new_answer->next = 0; @@ -1741,11 +1735,20 @@ do_assert (cpp_reader *pfile) new_answer->next = node->value.answers; } + answer_size = sizeof (struct answer) + ((new_answer->count - 1) + * sizeof (cpp_token)); + /* Commit or allocate storage for the object. */ + if (pfile->hash_table->alloc_subobject) + { + struct answer *temp_answer = new_answer; + new_answer = pfile->hash_table->alloc_subobject (answer_size); + memcpy (new_answer, temp_answer, answer_size); + } + else + BUFF_FRONT (pfile->a_buff) += answer_size; + node->type = NT_ASSERTION; node->value.answers = new_answer; - BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer) - + (new_answer->count - 1) - * sizeof (cpp_token)); check_eol (pfile); } } diff --git a/libcpp/include/ChangeLog b/libcpp/include/ChangeLog index a2f4bc5e3ef..0dbd0c33474 100644 --- a/libcpp/include/ChangeLog +++ b/libcpp/include/ChangeLog @@ -1,3 +1,14 @@ +2004-06-09 Geoffrey Keating + + * symtab.h (struct ht): Add field 'alloc_subobject'. + * cpplib.h (struct cpp_string): Add GTY marker. + (enum cpp_token_fld_kind): New. + (struct cpp_token): Add GTY markers. + (cpp_token_val_index): Prototype. + (CPP_HASHNODE_VALUE_IDX): New. + (struct cpp_hashnode): Don't skip fields of 'value' when marking. + * cpp-id-data.h: New file. + 2004-05-29 Geoffrey Keating * symtab.h (struct ht): New field 'entries_owned' diff --git a/libcpp/include/cpp-id-data.h b/libcpp/include/cpp-id-data.h new file mode 100644 index 00000000000..bdeaeba5182 --- /dev/null +++ b/libcpp/include/cpp-id-data.h @@ -0,0 +1,77 @@ +/* Structures that hang off cpp_identifier, for PCH. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 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 +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "cpplib.h" + +#ifndef HAVE_UCHAR +typedef unsigned char uchar; +#endif +#define U (const uchar *) /* Intended use: U"string" */ + +/* Chained list of answers to an assertion. */ +struct answer GTY(()) +{ + struct answer *next; + unsigned int count; + cpp_token GTY ((length ("%h.count"))) first[1]; +}; + +/* Each macro definition is recorded in a cpp_macro structure. + Variadic macros cannot occur with traditional cpp. */ +struct cpp_macro GTY(()) +{ + /* Parameters, if any. */ + cpp_hashnode ** GTY ((nested_ptr (union tree_node, + "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL", + "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"), + length ("%h.paramc"))) + params; + + /* Replacement tokens (ISO) or replacement text (traditional). See + comment at top of cpptrad.c for how traditional function-like + macros are encoded. */ + union cpp_macro_u + { + cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens; + const uchar * GTY ((tag ("1"))) text; + } GTY ((desc ("%1.traditional"))) exp; + + /* Definition line number. */ + source_location line; + + /* Number of tokens in expansion, or bytes for traditional macros. */ + unsigned int count; + + /* Number of parameters. */ + unsigned short paramc; + + /* If a function-like macro. */ + unsigned int fun_like : 1; + + /* If a variadic macro. */ + unsigned int variadic : 1; + + /* If macro defined in system header. */ + unsigned int syshdr : 1; + + /* Nonzero if it has been expanded or had its existence tested. */ + unsigned int used : 1; + + /* Indicate which field of 'exp' is in use. */ + unsigned int traditional : 1; +}; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index cf701b5e861..dab315714df 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -156,7 +156,7 @@ enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_STDC89, CLK_STDC94, CLK_STDC99, CLK_GNUCXX, CLK_CXX98, CLK_ASM}; /* Payload of a NUMBER, STRING, CHAR or COMMENT token. */ -struct cpp_string +struct cpp_string GTY(()) { unsigned int len; const unsigned char *text; @@ -171,23 +171,48 @@ struct cpp_string #define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */ #define BOL (1 << 6) /* Token at beginning of line. */ +/* Specify which field, if any, of the cpp_token union is used. */ + +enum cpp_token_fld_kind { + CPP_TOKEN_FLD_NODE, + CPP_TOKEN_FLD_SOURCE, + CPP_TOKEN_FLD_STR, + CPP_TOKEN_FLD_ARG_NO, + CPP_TOKEN_FLD_NONE +}; + /* A preprocessing token. This has been carefully packed and should occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */ -struct cpp_token +struct cpp_token GTY(()) { source_location src_loc; /* Location of first char of token. */ ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */ unsigned char flags; /* flags - see above */ - union + union cpp_token_u { - cpp_hashnode *node; /* An identifier. */ - const cpp_token *source; /* Inherit padding from this token. */ - struct cpp_string str; /* A string, or number. */ - unsigned int arg_no; /* Argument no. for a CPP_MACRO_ARG. */ - } val; + /* An identifier. */ + cpp_hashnode * + GTY ((nested_ptr (union tree_node, + "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL", + "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"), + tag ("CPP_TOKEN_FLD_NODE"))) + node; + + /* Inherit padding from this token. */ + cpp_token * GTY ((tag ("CPP_TOKEN_FLD_SOURCE"))) source; + + /* A string, or number. */ + struct cpp_string GTY ((tag ("CPP_TOKEN_FLD_STR"))) str; + + /* Argument no. for a CPP_MACRO_ARG. */ + unsigned int GTY ((tag ("CPP_TOKEN_FLD_ARG_NO"))) arg_no; + } GTY ((desc ("cpp_token_val_index (&%1)"))) val; }; +/* Say which field is in use. */ +extern enum cpp_token_fld_kind cpp_token_val_index (cpp_token *tok); + /* A type wide enough to hold any multibyte source character. cpplib's character constant interpreter requires an unsigned type. Also, a typedef for the signed equivalent. @@ -498,6 +523,23 @@ enum builtin_type #define NODE_LEN(NODE) HT_LEN (&(NODE)->ident) #define NODE_NAME(NODE) HT_STR (&(NODE)->ident) +/* Specify which field, if any, of the union is used. */ + +enum { + NTV_MACRO, + NTV_ANSWER, + NTV_BUILTIN, + NTV_ARGUMENT, + NTV_NONE +}; + +#define CPP_HASHNODE_VALUE_IDX(HNODE) \ + ((HNODE.flags & NODE_MACRO_ARG) ? NTV_ARGUMENT \ + : HNODE.type == NT_MACRO ? ((HNODE.flags & NODE_BUILTIN) \ + ? NTV_BUILTIN : NTV_MACRO) \ + : HNODE.type == NT_ASSERTION ? NTV_ANSWER \ + : NTV_NONE) + /* The common part of an identifier node shared amongst all 3 C front ends. Also used to store CPP identifiers, which are a superset of identifiers in the grammatical sense. */ @@ -515,14 +557,14 @@ struct cpp_hashnode GTY(()) union _cpp_hashnode_value { /* If a macro. */ - cpp_macro * GTY((skip)) macro; + cpp_macro * GTY((tag ("NTV_MACRO"))) macro; /* Answers to an assertion. */ - struct answer * GTY ((skip)) answers; + struct answer * GTY ((tag ("NTV_ANSWER"))) answers; /* Code for a builtin macro. */ - enum builtin_type GTY ((tag ("1"))) builtin; + enum builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin; /* Macro argument index. */ - unsigned short GTY ((tag ("0"))) arg_index; - } GTY ((desc ("0"))) value; + unsigned short GTY ((tag ("NTV_ARGUMENT"))) arg_index; + } GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value; }; /* Call this first to get a handle to pass to other functions. diff --git a/libcpp/include/symtab.h b/libcpp/include/symtab.h index d11e4efe6dc..0b2a848739e 100644 --- a/libcpp/include/symtab.h +++ b/libcpp/include/symtab.h @@ -46,8 +46,11 @@ struct ht struct obstack stack; hashnode *entries; - /* Call back. */ + /* Call back, allocate a node. */ hashnode (*alloc_node) (hash_table *); + /* Call back, allocate something that hangs off a node like a cpp_macro. + NULL means use the usual allocator. */ + void * (*alloc_subobject) (size_t); unsigned int nslots; /* Total slots in the entries array. */ unsigned int nelements; /* Number of live elements. */ diff --git a/libcpp/internal.h b/libcpp/internal.h index 3608201d560..fd3facf6136 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define LIBCPP_INTERNAL_H #include "symtab.h" +#include "cpp-id-data.h" #if defined HAVE_ICONV_H && defined HAVE_ICONV #include @@ -45,11 +46,6 @@ struct cset_converter iconv_t cd; }; -#ifndef HAVE_UCHAR -typedef unsigned char uchar; -#endif -#define U (const uchar *) /* Intended use: U"string" */ - #define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t)) /* Test if a sign is valid within a preprocessing number. */ @@ -90,44 +86,6 @@ struct dummy #define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1)) #define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT) -/* Each macro definition is recorded in a cpp_macro structure. - Variadic macros cannot occur with traditional cpp. */ -struct cpp_macro -{ - /* Parameters, if any. */ - cpp_hashnode **params; - - /* Replacement tokens (ISO) or replacement text (traditional). See - comment at top of cpptrad.c for how traditional function-like - macros are encoded. */ - union - { - cpp_token *tokens; - const uchar *text; - } exp; - - /* Definition line number. */ - fileline line; - - /* Number of tokens in expansion, or bytes for traditional macros. */ - unsigned int count; - - /* Number of parameters. */ - unsigned short paramc; - - /* If a function-like macro. */ - unsigned int fun_like : 1; - - /* If a variadic macro. */ - unsigned int variadic : 1; - - /* If macro defined in system header. */ - unsigned int syshdr : 1; - - /* Nonzero if it has been expanded or had its existence tested. */ - unsigned int used : 1; -}; - #define _cpp_mark_macro_used(NODE) do { \ if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \ (NODE)->value.macro->used = 1; } while (0) diff --git a/libcpp/lex.c b/libcpp/lex.c index 37df6efc0b7..7eafb13d3b4 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1556,3 +1556,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len) buff->cur = result + len; return result; } + +/* Say which field of TOK is in use. */ + +enum cpp_token_fld_kind +cpp_token_val_index (cpp_token *tok) +{ + switch (TOKEN_SPELL (tok)) + { + case SPELL_IDENT: + return CPP_TOKEN_FLD_NODE; + case SPELL_LITERAL: + return CPP_TOKEN_FLD_STR; + case SPELL_NONE: + if (tok->type == CPP_MACRO_ARG) + return CPP_TOKEN_FLD_ARG_NO; + else if (tok->type == CPP_PADDING) + return CPP_TOKEN_FLD_SOURCE; + /* else fall through */ + default: + return CPP_TOKEN_FLD_NONE; + } +} diff --git a/libcpp/macro.c b/libcpp/macro.c index cfc42b4050f..dc58b3180f1 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -1408,8 +1408,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (!ok) return false; - /* Success. Commit the parameter array. */ - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; + /* Success. Commit or allocate the parameter array. */ + if (pfile->hash_table->alloc_subobject) + { + cpp_token *tokns = pfile->hash_table->alloc_subobject + (sizeof (cpp_token) * macro->paramc); + memcpy (tokns, macro->params, sizeof (cpp_token) * macro->paramc); + macro->params = tokns; + } + else + BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; macro->fun_like = 1; } else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) @@ -1472,6 +1480,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) } macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); + macro->traditional = 0; /* Don't count the CPP_EOF. */ macro->count--; @@ -1480,8 +1489,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (macro->count) macro->exp.tokens[0].flags &= ~PREV_WHITE; - /* Commit the memory. */ - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; + /* Commit or allocate the memory. */ + if (pfile->hash_table->alloc_subobject) + { + cpp_token *tokns = pfile->hash_table->alloc_subobject (sizeof (cpp_token) + * macro->count); + memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); + macro->exp.tokens = tokns; + } + else + BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; return true; } @@ -1494,7 +1511,10 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) unsigned int i; bool ok; - macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); + if (pfile->hash_table->alloc_subobject) + macro = pfile->hash_table->alloc_subobject (sizeof (cpp_macro)); + else + macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); macro->line = pfile->directive_line; macro->params = 0; macro->paramc = 0; diff --git a/libcpp/pch.c b/libcpp/pch.c index 51175a9a67b..a9d139a30b7 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -347,15 +347,6 @@ cpp_write_pch_state (cpp_reader *r, FILE *f) { struct macrodef_struct z; - /* Write out the list of defined identifiers. */ - cpp_forall_identifiers (r, write_macdef, f); - memset (&z, 0, sizeof (z)); - if (fwrite (&z, sizeof (z), 1, f) != 1) - { - cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header"); - return -1; - } - if (!r->deps) r->deps = deps_init (); @@ -544,46 +535,64 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd) return 1; } -/* Save all the existing macros and assertions. - This code assumes that there might be hundreds, but not thousands of - existing definitions. */ - -struct save_macro_item { - struct save_macro_item *next; - struct cpp_hashnode macs[64]; -}; +/* Save all the existing macros. */ struct save_macro_data { - struct save_macro_item *macros; + uchar **defns; size_t count; + size_t array_size; char **saved_pragmas; }; -/* Save the definition of a single macro, so that it will persist across - a PCH restore. */ +/* Save the definition of a single macro, so that it will persist + across a PCH restore. Because macro data is in GCed memory, which + will be blown away by PCH, it must be temporarily copied to + malloced memory. (The macros will refer to identifier nodes which + are also GCed and so on, so the copying is done by turning them + into self-contained strings.) The assumption is that most macro + definitions will come from the PCH file, not from the compilation + before the PCH file is loaded, so it doesn't matter that this is + a little expensive. + + It would reduce the cost even further if macros defined in the PCH + file were not saved in this way, but this is not done (yet), except + for builtins, and for #assert by default. */ static int -save_macros (cpp_reader *r ATTRIBUTE_UNUSED, cpp_hashnode *h, void *data_p) +save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) { struct save_macro_data *data = (struct save_macro_data *)data_p; if (h->type != NT_VOID && (h->flags & NODE_BUILTIN) == 0) { - cpp_hashnode *save; - if (data->count == ARRAY_SIZE (data->macros->macs)) + if (data->count == data->array_size) + { + data->array_size *= 2; + data->defns = xrealloc (data->defns, (data->array_size + * sizeof (uchar *))); + } + + switch (h->type) { - struct save_macro_item *d = data->macros; - data->macros = xmalloc (sizeof (struct save_macro_item)); - data->macros->next = d; - data->count = 0; + case NT_ASSERTION: + /* Not currently implemented. */ + return 1; + + case NT_MACRO: + { + const uchar * defn = cpp_macro_definition (r, h); + size_t defnlen = ustrlen (defn); + + data->defns[data->count] = xmemdup (defn, defnlen, defnlen + 2); + data->defns[data->count][defnlen] = '\n'; + } + break; + + default: + abort (); } - save = data->macros->macs + data->count; data->count++; - memcpy (save, h, sizeof (struct cpp_hashnode)); - HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)), - HT_LEN (HT_NODE (save)), - HT_LEN (HT_NODE (save)) + 1); } return 1; } @@ -596,8 +605,9 @@ cpp_prepare_state (cpp_reader *r, struct save_macro_data **data) { struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data)); - d->macros = NULL; - d->count = ARRAY_SIZE (d->macros->macs); + d->array_size = 512; + d->defns = xmalloc (d->array_size * sizeof (d->defns[0])); + d->count = 0; cpp_forall_identifiers (r, save_macros, d); d->saved_pragmas = _cpp_save_pragma_names (r); *data = d; @@ -612,11 +622,9 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f, struct save_macro_data *data) { struct macrodef_struct m; - size_t defnlen = 256; - unsigned char *defn = xmalloc (defnlen); - struct lexer_state old_state; struct save_macro_item *d; size_t i, mac_count; + struct lexer_state old_state; /* Restore spec_nodes, which will be full of references to the old hashtable entries and so will now be invalid. */ @@ -628,70 +636,28 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f, s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__")); } - /* Run through the carefully-saved macros, insert them. */ - d = data->macros; - mac_count = data->count; - while (d) - { - struct save_macro_item *nextd; - for (i = 0; i < mac_count; i++) - { - cpp_hashnode *h; - - h = cpp_lookup (r, HT_STR (HT_NODE (&d->macs[i])), - HT_LEN (HT_NODE (&d->macs[i]))); - h->type = d->macs[i].type; - h->flags = d->macs[i].flags; - h->value = d->macs[i].value; - free ((void *)HT_STR (HT_NODE (&d->macs[i]))); - } - nextd = d->next; - free (d); - d = nextd; - mac_count = ARRAY_SIZE (d->macs); - } - - _cpp_restore_pragma_names (r, data->saved_pragmas); - - free (data); - old_state = r->state; - r->state.in_directive = 1; r->state.prevent_expansion = 1; r->state.angled_headers = 0; - /* Read in the identifiers that must be defined. */ - for (;;) + /* Run through the carefully-saved macros, insert them. */ + for (i = 0; i < data->count; i++) { cpp_hashnode *h; - - if (fread (&m, sizeof (m), 1, f) != 1) - goto error; - - if (m.name_length == 0) - break; - - if (defnlen < m.definition_length + 1) - { - defnlen = m.definition_length + 256; - defn = xrealloc (defn, defnlen); - } + size_t namelen; + uchar *defn; - if (fread (defn, 1, m.definition_length, f) != m.definition_length) - goto error; - defn[m.definition_length] = '\n'; - - h = cpp_lookup (r, defn, m.name_length); + namelen = strcspn (data->defns[i], "( \n"); + h = cpp_lookup (r, data->defns[i], namelen); + defn = data->defns[i] + namelen; - if (h->type == NT_MACRO) - _cpp_free_definition (h); - if (m.flags & NODE_POISONED) - h->flags |= NODE_POISONED | NODE_DIAGNOSTIC; - else if (m.name_length != m.definition_length) + /* The PCH file is valid, so we know that if there is a definition + from the PCH file it must be the same as the one we had + originally, and so do not need to restore it. */ + if (h->type == NT_VOID) { - if (cpp_push_buffer (r, defn + m.name_length, - m.definition_length - m.name_length, true) + if (cpp_push_buffer (r, defn, ustrchr (defn, '\n') - defn, true) != NULL) { _cpp_clean_line (r); @@ -702,11 +668,14 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f, else abort (); } - } + free (data->defns[i]); + } r->state = old_state; - free (defn); - defn = NULL; + + _cpp_restore_pragma_names (r, data->saved_pragmas); + + free (data); if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL) != 0) diff --git a/libcpp/traditional.c b/libcpp/traditional.c index f4ce9f66e47..38e301c43ff 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -701,6 +701,7 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) cpp_macro *macro = node->value.macro; macro->used = 1; text = macro->exp.text; + macro->traditional = 1; len = macro->count; } @@ -934,6 +935,7 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, memcpy (exp, pfile->out.base, len); exp[len] = '\n'; macro->exp.text = exp; + macro->traditional = 1; macro->count = len; } else @@ -949,6 +951,7 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, exp = BUFF_FRONT (pfile->a_buff); block = (struct block *) (exp + macro->count); macro->exp.text = exp; + macro->traditional = 1; /* Write out the block information. */ block->text_len = len; -- 2.30.2