diff options
Diffstat (limited to 'gcc/cp/spew.c')
-rw-r--r-- | gcc/cp/spew.c | 303 |
1 files changed, 148 insertions, 155 deletions
diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c index c1aa9543899..d56f6117392 100644 --- a/gcc/cp/spew.c +++ b/gcc/cp/spew.c @@ -50,12 +50,12 @@ Boston, MA 02111-1307, USA. */ backtracking. */ /* fifo of tokens recognized and available to parser. */ -struct token +struct token GTY(()) { /* The values for YYCHAR will fit in a short. */ short yychar; unsigned int lineno; - YYSTYPE yylval; + YYSTYPE GTY ((desc ("%1.yychar"))) yylval; }; /* Since inline methods can refer to text which has not yet been seen, @@ -68,7 +68,14 @@ struct token This function's FUNCTION_DECL will have a bit set in its common so that we know to watch out for it. */ -struct unparsed_text +#define TOKEN_CHUNK_SIZE 20 +struct token_chunk GTY(()) +{ + struct token_chunk *next; + struct token toks[TOKEN_CHUNK_SIZE]; +}; + +struct unparsed_text GTY(()) { struct unparsed_text *next; /* process this one next */ tree decl; /* associated declaration */ @@ -76,26 +83,31 @@ struct unparsed_text int lineno; /* line number we got the text from */ int interface; /* remembering interface_unknown and interface_only */ - struct token *pos; /* current position, when rescanning */ - struct token *limit; /* end of saved text */ + struct token_chunk * tokens; /* Start of the token list. */ + + struct token_chunk *last_chunk; /* End of the token list. */ + short last_pos; /* Number of tokens used in the last chunk of + TOKENS. */ + + short cur_pos; /* Current token in 'cur_chunk', when rescanning. */ + struct token_chunk *cur_chunk; /* Current chunk, when rescanning. */ }; /* Stack of state saved off when we return to an inline method or default argument that has been stored for later parsing. */ -struct feed +struct feed GTY(()) { struct unparsed_text *input; const char *filename; int lineno; int yychar; - YYSTYPE yylval; + YYSTYPE GTY ((desc ("%1.yychar"))) yylval; int first_token; - struct obstack token_obstack; + struct obstack GTY ((skip (""))) token_obstack; struct feed *next; -}; +}; -static struct obstack feed_obstack; -static struct feed *feed; +static GTY(()) struct feed *feed; static SPEW_INLINE void do_aggr PARAMS ((void)); static SPEW_INLINE int identifier_type PARAMS ((tree)); @@ -107,25 +119,32 @@ static int read_token PARAMS ((struct token *)); static SPEW_INLINE int num_tokens PARAMS ((void)); static SPEW_INLINE struct token *nth_token PARAMS ((int)); -static SPEW_INLINE int add_token PARAMS ((struct token *)); +static SPEW_INLINE int next_token PARAMS ((struct token *)); static SPEW_INLINE int shift_token PARAMS ((void)); static SPEW_INLINE void push_token PARAMS ((struct token *)); static SPEW_INLINE void consume_token PARAMS ((void)); static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *)); static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *)); -static SPEW_INLINE void snarf_block PARAMS ((const char *, int)); +static SPEW_INLINE struct token * space_for_token + PARAMS ((struct unparsed_text *t)); +static SPEW_INLINE struct token * remove_last_token + PARAMS ((struct unparsed_text *t)); +static struct unparsed_text * alloc_unparsed_text + PARAMS ((const char *fn, int li, tree decl, int interface)); + +static void snarf_block PARAMS ((struct unparsed_text *t)); static tree snarf_defarg PARAMS ((void)); static int frob_id PARAMS ((int, int, tree *)); /* The list of inline functions being held off until we reach the end of the current class declaration. */ -static struct unparsed_text *pending_inlines; -static struct unparsed_text *pending_inlines_tail; +static GTY(()) struct unparsed_text *pending_inlines; +static GTY(()) struct unparsed_text *pending_inlines_tail; /* The list of previously-deferred inline functions currently being parsed. This exists solely to be a GC root. */ -static struct unparsed_text *processing_these_inlines; +static GTY(()) struct unparsed_text *processing_these_inlines; static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *)); @@ -151,13 +170,8 @@ extern int yychar; /* the lookahead symbol */ extern YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ /* The token fifo lives in this obstack. */ -struct obstack token_obstack; -int first_token; - -/* Sometimes we need to save tokens for later parsing. If so, they are - stored on this obstack. */ -struct obstack inline_text_obstack; -char *inline_text_firstobj; +static struct obstack token_obstack; +static int first_token; /* When we see a default argument in a method declaration, we snarf it as text using snarf_defarg. When we get up to namespace scope, we then go @@ -168,35 +182,21 @@ char *inline_text_firstobj; the TREE_TYPE is the current_class_type, TREE_VALUE is the FUNCTION_DECL, and TREE_PURPOSE is the list unprocessed dependent functions. */ -static tree defarg_fns; /* list of functions with unprocessed defargs */ -static tree defarg_parm; /* current default parameter */ -static tree defarg_depfns; /* list of unprocessed fns met during current fn. */ -static tree defarg_fnsdone; /* list of fns with circular defargs */ +/* list of functions with unprocessed defargs */ +static GTY(()) tree defarg_fns; +/* current default parameter */ +static GTY(()) tree defarg_parm; +/* list of unprocessed fns met during current fn. */ +static GTY(()) tree defarg_depfns; +/* list of fns with circular defargs */ +static GTY(()) tree defarg_fnsdone; /* Initialize obstacks. Called once, from cxx_init. */ void init_spew () { - gcc_obstack_init (&inline_text_obstack); - inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); gcc_obstack_init (&token_obstack); - gcc_obstack_init (&feed_obstack); - ggc_add_tree_root (&defarg_fns, 1); - ggc_add_tree_root (&defarg_parm, 1); - ggc_add_tree_root (&defarg_depfns, 1); - ggc_add_tree_root (&defarg_fnsdone, 1); - - ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *), - mark_pending_inlines); - ggc_add_root (&processing_these_inlines, 1, sizeof (struct unparsed_text *), - mark_pending_inlines); -} - -void -clear_inline_text_obstack () -{ - obstack_free (&inline_text_obstack, inline_text_firstobj); } /* Subroutine of read_token. */ @@ -270,8 +270,6 @@ yylexstring (t) t->yylval.ttype = combine_strings (strings); last_token_id = t->yylval.ttype; - - VARRAY_FREE (strings); } /* We will have always read one token too many. */ @@ -396,10 +394,10 @@ feed_input (input) abort (); #endif - f = obstack_alloc (&feed_obstack, sizeof (struct feed)); + f = ggc_alloc (sizeof (struct feed)); - /* The token list starts just after the struct unparsed_text in memory. */ - input->pos = (struct token *) (input + 1); + input->cur_chunk = input->tokens; + input->cur_pos = 0; #ifdef SPEW_DEBUG if (spew_debug) @@ -439,48 +437,12 @@ end_input () token_obstack = f->token_obstack; feed = f->next; - obstack_free (&feed_obstack, f); - #ifdef SPEW_DEBUG if (spew_debug) fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno); #endif } -/* GC callback to mark memory pointed to by the pending inline queue. */ -void -mark_pending_inlines (pi) - PTR pi; -{ - struct unparsed_text *up = * (struct unparsed_text **)pi; - - while (up) - { - struct token *t = (struct token *) (up + 1); - struct token *l = up->limit; - - while (t < l) - { - /* Some of the possible values for yychar use yylval.code - instead of yylval.ttype. We only have to worry about - yychars that could have been returned by read_token. */ - switch (t->yychar) - { - case '+': case '-': case '*': case '/': - case '%': case '&': case '|': case '^': - case '>': case '<': case LSHIFT: case RSHIFT: - case ASSIGN: case MIN_MAX: case EQCOMPARE: case ARITHCOMPARE: - t++; - continue; - } - if (t->yylval.ttype) - ggc_mark_tree (t->yylval.ttype); - t++; - } - up = up->next; - } -} - /* Token queue management. */ /* Return the number of tokens available on the fifo. */ @@ -510,16 +472,24 @@ static const struct token Tpad = { EMPTY, 0 UNION_INIT_ZERO }; /* Copy the next token into T and return its value. */ static SPEW_INLINE int -add_token (t) +next_token (t) struct token *t; { if (!feed) return read_token (t); - if (feed->input->pos < feed->input->limit) + if (feed->input->cur_chunk != feed->input->last_chunk + || feed->input->cur_pos != feed->input->last_pos) { - memcpy (t, feed->input->pos, sizeof (struct token)); - return (feed->input->pos++)->yychar; + if (feed->input->cur_pos == TOKEN_CHUNK_SIZE) + { + feed->input->cur_chunk = feed->input->cur_chunk->next; + feed->input->cur_pos = 0; + } + memcpy (t, feed->input->cur_chunk->toks + feed->input->cur_pos, + sizeof (struct token)); + feed->input->cur_pos++; + return t->yychar; } memcpy (t, &Teosi, sizeof (struct token)); @@ -532,7 +502,7 @@ shift_token () { size_t point = obstack_object_size (&token_obstack); obstack_blank (&token_obstack, sizeof (struct token)); - return add_token ((struct token *) (obstack_base (&token_obstack) + point)); + return next_token ((struct token *) (obstack_base (&token_obstack) + point)); } /* Consume the next token out of the fifo. */ @@ -1060,22 +1030,73 @@ process_next_inline (i) extract_interface_info (); } } + +/* Create a new token at the end of the token list in T. */ +static SPEW_INLINE struct token * +space_for_token (t) + struct unparsed_text *t; +{ + if (t->last_pos != TOKEN_CHUNK_SIZE) + return t->last_chunk->toks + (t->last_pos++); + t->last_chunk->next = ggc_alloc (sizeof (*t->last_chunk->next)); + t->last_chunk = t->last_chunk->next; + t->last_chunk->next = NULL; + + t->last_pos = 1; + return t->last_chunk->toks; +} + +/* Shrink the token list in T by one token. */ +static SPEW_INLINE struct token * +remove_last_token (t) + struct unparsed_text *t; +{ + struct token *result = t->last_chunk->toks + t->last_pos - 1; + if (t->last_pos == 0) + abort (); + t->last_pos--; + if (t->last_pos == 0 && t->last_chunk != t->tokens) + { + struct token_chunk **tc; + for (tc = &t->tokens; (*tc)->next != NULL; tc = &(*tc)->next) + ; + *tc = NULL; + t->last_pos = sizeof ((*tc)->toks) / sizeof ((*tc)->toks[0]); + } + return result; +} + +/* Allocate an 'unparsed_text' structure, ready to use space_for_token. */ +static struct unparsed_text * +alloc_unparsed_text (fn, li, decl, interface) + const char *fn; + int li; + tree decl; + int interface; +{ + struct unparsed_text *r; + r = ggc_alloc_cleared (sizeof (*r)); + r->decl = decl; + r->filename = fn; + r->lineno = li; + r->interface = interface; + r->tokens = r->last_chunk = ggc_alloc_cleared (sizeof (*r->tokens)); + return r; +} /* Subroutine of snarf_method, deals with actual absorption of the block. */ -static SPEW_INLINE void -snarf_block (starting_file, starting_line) - const char *starting_file; - int starting_line; +static void +snarf_block (t) + struct unparsed_text *t; { int blev = 1; int look_for_semicolon = 0; int look_for_lbrac = 0; int look_for_catch = 0; int yyc; - struct token tmp; - size_t point; + struct token *current; if (yychar == '{') ; @@ -1092,17 +1113,14 @@ snarf_block (starting_file, starting_line) yyerror ("parse error in method specification"); /* The current token is the first one to be recorded. */ - tmp.yychar = yychar; - tmp.yylval = yylval; - tmp.lineno = lineno; - obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token)); + current = space_for_token (t); + current->yychar = yychar; + current->yylval = yylval; + current->lineno = lineno; for (;;) { - point = obstack_object_size (&inline_text_obstack); - obstack_blank (&inline_text_obstack, sizeof (struct token)); - yyc = add_token ((struct token *) - (obstack_base (&inline_text_obstack) + point)); + yyc = next_token (space_for_token (t)); if (yyc == '{') { @@ -1117,27 +1135,29 @@ snarf_block (starting_file, starting_line) if (!look_for_catch) break; - if (add_token (&tmp) != CATCH) + if (next_token (space_for_token (t)) != CATCH) { - push_token (&tmp); + push_token (remove_last_token (t)); break; } look_for_lbrac = 1; - obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token)); } } else if (yyc == ';') { if (look_for_lbrac) { + struct token *fake; + error ("function body for constructor missing"); /* fake a { } to avoid further errors */ - tmp.yylval.ttype = 0; - tmp.yychar = '{'; - obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token)); - tmp.yychar = '}'; - obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token)); + fake = space_for_token (t); + fake->yylval.ttype = 0; + fake->yychar = '{'; + fake = space_for_token (t); + fake->yylval.ttype = 0; + fake->yychar = '}'; break; } else if (look_for_semicolon && blev == 0) @@ -1145,7 +1165,7 @@ snarf_block (starting_file, starting_line) } else if (yyc == 0) { - error_with_file_and_line (starting_file, starting_line, + error_with_file_and_line (t->filename, t->lineno, "end of file read inside definition"); break; } @@ -1160,37 +1180,24 @@ snarf_method (decl) { int starting_lineno = lineno; const char *starting_filename = input_filename; - size_t len; - struct unparsed_text *meth; - /* Leave room for the header, then absorb the block. */ - obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text)); - snarf_block (starting_filename, starting_lineno); + meth = alloc_unparsed_text (starting_filename, starting_lineno, decl, + (interface_unknown ? 1 + : (interface_only ? 0 : 2))); - len = obstack_object_size (&inline_text_obstack); - meth = (struct unparsed_text *) obstack_finish (&inline_text_obstack); + snarf_block (meth); /* Happens when we get two declarations of the same function in the same scope. */ if (decl == void_type_node || (current_class_type && TYPE_REDEFINED (current_class_type))) - { - obstack_free (&inline_text_obstack, (char *)meth); - return; - } - - meth->decl = decl; - meth->filename = starting_filename; - meth->lineno = starting_lineno; - meth->limit = (struct token *) ((char *)meth + len); - meth->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); - meth->next = 0; + return; #ifdef SPEW_DEBUG if (spew_debug) fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n", - meth->limit - (struct token *) (meth + 1), + meth->limit, starting_filename, starting_lineno); #endif @@ -1204,8 +1211,8 @@ snarf_method (decl) pending_inlines_tail = meth; } -/* Consume a no-commas expression - a default argument - and save it - on the inline_text_obstack. */ +/* Consume a no-commas expression - a default argument - and return + a DEFAULT_ARG tree node. */ static tree snarf_defarg () @@ -1214,19 +1221,14 @@ snarf_defarg () const char *starting_filename = input_filename; int yyc; int plev = 0; - size_t point; - size_t len; struct unparsed_text *buf; tree arg; - obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text)); + buf = alloc_unparsed_text (starting_filename, starting_lineno, 0, 0); for (;;) { - point = obstack_object_size (&inline_text_obstack); - obstack_blank (&inline_text_obstack, sizeof (struct token)); - yyc = add_token ((struct token *) - (obstack_base (&inline_text_obstack) + point)); + yyc = next_token (space_for_token (buf)); if (plev <= 0 && (yyc == ')' || yyc == ',')) break; @@ -1243,24 +1245,13 @@ snarf_defarg () } /* Unget the last token. */ - push_token ((struct token *) (obstack_base (&inline_text_obstack) + point)); - /* This is the documented way to shrink a growing obstack block. */ - obstack_blank (&inline_text_obstack, - (int) sizeof (struct token)); + push_token (remove_last_token (buf)); done: - len = obstack_object_size (&inline_text_obstack); - buf = (struct unparsed_text *) obstack_finish (&inline_text_obstack); - - buf->decl = 0; - buf->filename = starting_filename; - buf->lineno = starting_lineno; - buf->limit = (struct token *) ((char *)buf + len); - buf->next = 0; - #ifdef SPEW_DEBUG if (spew_debug) fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n", - buf->limit - (struct token *) (buf + 1), + buf->limit, starting_filename, starting_lineno); #endif @@ -1531,3 +1522,5 @@ yyerror (msgid) else error ("%s before `%s' token", string, NAME (last_token)); } + +#include "gt-cp-spew.h" |