1117395Skan/* Process source files and output type information.
2169689Skan   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3117395Skan
4117395SkanThis file is part of GCC.
5117395Skan
6117395SkanGCC is free software; you can redistribute it and/or modify it under
7117395Skanthe terms of the GNU General Public License as published by the Free
8117395SkanSoftware Foundation; either version 2, or (at your option) any later
9117395Skanversion.
10117395Skan
11117395SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
12117395SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
13117395SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14117395Skanfor more details.
15117395Skan
16117395SkanYou should have received a copy of the GNU General Public License
17117395Skanalong with GCC; see the file COPYING.  If not, write to the Free
18169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19169689Skan02110-1301, USA.  */
20117395Skan
21132718Skan#include "bconfig.h"
22117395Skan#include "system.h"
23132718Skan#include "coretypes.h"
24132718Skan#include "tm.h"
25117395Skan#include "gengtype.h"
26117395Skan#include "gtyp-gen.h"
27169689Skan#include "errors.h"
28117395Skan
29117395Skan/* Nonzero iff an error has occurred.  */
30117395Skanstatic int hit_error = 0;
31117395Skan
32132718Skanstatic void gen_rtx_next (void);
33132718Skanstatic void write_rtx_next (void);
34132718Skanstatic void open_base_files (void);
35132718Skanstatic void close_output_files (void);
36117395Skan
37117395Skan/* Report an error at POS, printing MSG.  */
38117395Skan
39117395Skanvoid
40132718Skanerror_at_line (struct fileloc *pos, const char *msg, ...)
41117395Skan{
42132718Skan  va_list ap;
43117395Skan
44132718Skan  va_start (ap, msg);
45132718Skan
46117395Skan  fprintf (stderr, "%s:%d: ", pos->file, pos->line);
47117395Skan  vfprintf (stderr, msg, ap);
48117395Skan  fputc ('\n', stderr);
49117395Skan  hit_error = 1;
50117395Skan
51132718Skan  va_end (ap);
52117395Skan}
53117395Skan
54117395Skan/* vasprintf, but produces fatal message on out-of-memory.  */
55117395Skanint
56132718Skanxvasprintf (char **result, const char *format, va_list args)
57117395Skan{
58117395Skan  int ret = vasprintf (result, format, args);
59117395Skan  if (*result == NULL || ret < 0)
60117395Skan    {
61117395Skan      fputs ("gengtype: out of memory", stderr);
62117395Skan      xexit (1);
63117395Skan    }
64117395Skan  return ret;
65117395Skan}
66117395Skan
67117395Skan/* Wrapper for xvasprintf.  */
68117395Skanchar *
69132718Skanxasprintf (const char *format, ...)
70117395Skan{
71117395Skan  char *result;
72132718Skan  va_list ap;
73132718Skan
74132718Skan  va_start (ap, format);
75117395Skan  xvasprintf (&result, format, ap);
76132718Skan  va_end (ap);
77117395Skan  return result;
78117395Skan}
79117395Skan
80117395Skan/* The one and only TYPE_STRING.  */
81117395Skan
82117395Skanstruct type string_type = {
83132718Skan  TYPE_STRING, NULL, NULL, GC_USED, {0}
84132718Skan};
85117395Skan
86117395Skan/* Lists of various things.  */
87117395Skan
88117395Skanstatic pair_p typedefs;
89117395Skanstatic type_p structures;
90117395Skanstatic type_p param_structs;
91117395Skanstatic pair_p variables;
92117395Skan
93132718Skanstatic void do_scalar_typedef (const char *, struct fileloc *);
94132718Skanstatic type_p find_param_structure
95132718Skan  (type_p t, type_p param[NUM_PARAM]);
96132718Skanstatic type_p adjust_field_tree_exp (type_p t, options_p opt);
97132718Skanstatic type_p adjust_field_rtx_def (type_p t, options_p opt);
98117395Skan
99117395Skan/* Define S as a typedef to T at POS.  */
100117395Skan
101117395Skanvoid
102132718Skando_typedef (const char *s, type_p t, struct fileloc *pos)
103117395Skan{
104117395Skan  pair_p p;
105117395Skan
106117395Skan  for (p = typedefs; p != NULL; p = p->next)
107117395Skan    if (strcmp (p->name, s) == 0)
108117395Skan      {
109117395Skan	if (p->type != t)
110117395Skan	  {
111117395Skan	    error_at_line (pos, "type `%s' previously defined", s);
112117395Skan	    error_at_line (&p->line, "previously defined here");
113117395Skan	  }
114117395Skan	return;
115117395Skan      }
116117395Skan
117169689Skan  p = XNEW (struct pair);
118117395Skan  p->next = typedefs;
119117395Skan  p->name = s;
120117395Skan  p->type = t;
121117395Skan  p->line = *pos;
122117395Skan  typedefs = p;
123117395Skan}
124117395Skan
125117395Skan/* Define S as a typename of a scalar.  */
126117395Skan
127117395Skanstatic void
128132718Skando_scalar_typedef (const char *s, struct fileloc *pos)
129117395Skan{
130117395Skan  do_typedef (s, create_scalar_type (s, strlen (s)), pos);
131117395Skan}
132117395Skan
133117395Skan/* Return the type previously defined for S.  Use POS to report errors.  */
134117395Skan
135117395Skantype_p
136132718Skanresolve_typedef (const char *s, struct fileloc *pos)
137117395Skan{
138117395Skan  pair_p p;
139117395Skan  for (p = typedefs; p != NULL; p = p->next)
140117395Skan    if (strcmp (p->name, s) == 0)
141117395Skan      return p->type;
142117395Skan  error_at_line (pos, "unidentified type `%s'", s);
143117395Skan  return create_scalar_type ("char", 4);
144117395Skan}
145117395Skan
146169689Skan/* Create and return a new structure with tag NAME (or a union iff
147169689Skan   ISUNION is nonzero), at POS with fields FIELDS and options O.  */
148117395Skan
149169689Skantype_p
150132718Skannew_structure (const char *name, int isunion, struct fileloc *pos,
151132718Skan	       pair_p fields, options_p o)
152117395Skan{
153117395Skan  type_p si;
154117395Skan  type_p s = NULL;
155117395Skan  lang_bitmap bitmap = get_base_file_bitmap (pos->file);
156117395Skan
157117395Skan  for (si = structures; si != NULL; si = si->next)
158132718Skan    if (strcmp (name, si->u.s.tag) == 0
159117395Skan	&& UNION_P (si) == isunion)
160117395Skan      {
161117395Skan	type_p ls = NULL;
162117395Skan	if (si->kind == TYPE_LANG_STRUCT)
163117395Skan	  {
164117395Skan	    ls = si;
165132718Skan
166117395Skan	    for (si = ls->u.s.lang_struct; si != NULL; si = si->next)
167117395Skan	      if (si->u.s.bitmap == bitmap)
168117395Skan		s = si;
169117395Skan	  }
170117395Skan	else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
171117395Skan	  {
172117395Skan	    ls = si;
173169689Skan	    si = XCNEW (struct type);
174117395Skan	    memcpy (si, ls, sizeof (struct type));
175117395Skan	    ls->kind = TYPE_LANG_STRUCT;
176117395Skan	    ls->u.s.lang_struct = si;
177117395Skan	    ls->u.s.fields = NULL;
178117395Skan	    si->next = NULL;
179117395Skan	    si->pointer_to = NULL;
180117395Skan	    si->u.s.lang_struct = ls;
181117395Skan	  }
182117395Skan	else
183117395Skan	  s = si;
184117395Skan
185117395Skan	if (ls != NULL && s == NULL)
186117395Skan	  {
187169689Skan	    s = XCNEW (struct type);
188117395Skan	    s->next = ls->u.s.lang_struct;
189117395Skan	    ls->u.s.lang_struct = s;
190117395Skan	    s->u.s.lang_struct = ls;
191117395Skan	  }
192117395Skan	break;
193117395Skan      }
194132718Skan
195117395Skan  if (s == NULL)
196117395Skan    {
197169689Skan      s = XCNEW (struct type);
198117395Skan      s->next = structures;
199117395Skan      structures = s;
200117395Skan    }
201117395Skan
202117395Skan  if (s->u.s.line.file != NULL
203117395Skan      || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
204117395Skan    {
205117395Skan      error_at_line (pos, "duplicate structure definition");
206117395Skan      error_at_line (&s->u.s.line, "previous definition here");
207117395Skan    }
208117395Skan
209117395Skan  s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
210117395Skan  s->u.s.tag = name;
211117395Skan  s->u.s.line = *pos;
212117395Skan  s->u.s.fields = fields;
213117395Skan  s->u.s.opt = o;
214117395Skan  s->u.s.bitmap = bitmap;
215117395Skan  if (s->u.s.lang_struct)
216117395Skan    s->u.s.lang_struct->u.s.bitmap |= bitmap;
217169689Skan
218169689Skan  return s;
219117395Skan}
220117395Skan
221117395Skan/* Return the previously-defined structure with tag NAME (or a union
222117395Skan   iff ISUNION is nonzero), or a new empty structure or union if none
223117395Skan   was defined previously.  */
224117395Skan
225117395Skantype_p
226132718Skanfind_structure (const char *name, int isunion)
227117395Skan{
228117395Skan  type_p s;
229117395Skan
230117395Skan  for (s = structures; s != NULL; s = s->next)
231132718Skan    if (strcmp (name, s->u.s.tag) == 0
232117395Skan	&& UNION_P (s) == isunion)
233117395Skan      return s;
234117395Skan
235169689Skan  s = XCNEW (struct type);
236117395Skan  s->next = structures;
237117395Skan  structures = s;
238117395Skan  s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
239117395Skan  s->u.s.tag = name;
240117395Skan  structures = s;
241117395Skan  return s;
242117395Skan}
243117395Skan
244132718Skan/* Return the previously-defined parameterized structure for structure
245132718Skan   T and parameters PARAM, or a new parameterized empty structure or
246117395Skan   union if none was defined previously.  */
247117395Skan
248117395Skanstatic type_p
249132718Skanfind_param_structure (type_p t, type_p param[NUM_PARAM])
250117395Skan{
251117395Skan  type_p res;
252132718Skan
253117395Skan  for (res = param_structs; res; res = res->next)
254117395Skan    if (res->u.param_struct.stru == t
255132718Skan	&& memcmp (res->u.param_struct.param, param,
256117395Skan		   sizeof (type_p) * NUM_PARAM) == 0)
257117395Skan      break;
258117395Skan  if (res == NULL)
259117395Skan    {
260169689Skan      res = XCNEW (struct type);
261117395Skan      res->kind = TYPE_PARAM_STRUCT;
262117395Skan      res->next = param_structs;
263117395Skan      param_structs = res;
264117395Skan      res->u.param_struct.stru = t;
265117395Skan      memcpy (res->u.param_struct.param, param, sizeof (type_p) * NUM_PARAM);
266117395Skan    }
267117395Skan  return res;
268117395Skan}
269117395Skan
270117395Skan/* Return a scalar type with name NAME.  */
271117395Skan
272117395Skantype_p
273132718Skancreate_scalar_type (const char *name, size_t name_len)
274117395Skan{
275169689Skan  type_p r = XCNEW (struct type);
276117395Skan  r->kind = TYPE_SCALAR;
277169689Skan  r->u.sc = (char *) xmemdup (name, name_len, name_len + 1);
278117395Skan  return r;
279117395Skan}
280117395Skan
281117395Skan/* Return a pointer to T.  */
282117395Skan
283117395Skantype_p
284132718Skancreate_pointer (type_p t)
285117395Skan{
286117395Skan  if (! t->pointer_to)
287117395Skan    {
288169689Skan      type_p r = XCNEW (struct type);
289117395Skan      r->kind = TYPE_POINTER;
290117395Skan      r->u.p = t;
291117395Skan      t->pointer_to = r;
292117395Skan    }
293117395Skan  return t->pointer_to;
294117395Skan}
295117395Skan
296117395Skan/* Return an array of length LEN.  */
297117395Skan
298117395Skantype_p
299132718Skancreate_array (type_p t, const char *len)
300117395Skan{
301117395Skan  type_p v;
302132718Skan
303169689Skan  v = XCNEW (struct type);
304117395Skan  v->kind = TYPE_ARRAY;
305117395Skan  v->u.a.p = t;
306117395Skan  v->u.a.len = len;
307117395Skan  return v;
308117395Skan}
309117395Skan
310169689Skan/* Return an options structure with name NAME and info INFO.  NEXT is the
311169689Skan   next option in the chain.  */
312169689Skan
313169689Skanoptions_p
314169689Skancreate_option (options_p next, const char *name, const void *info)
315169689Skan{
316169689Skan  options_p o = XNEW (struct options);
317169689Skan  o->next = next;
318169689Skan  o->name = name;
319169689Skan  o->info = (const char*) info;
320169689Skan  return o;
321169689Skan}
322169689Skan
323117395Skan/* Add a variable named S of type T with options O defined at POS,
324117395Skan   to `variables'.  */
325117395Skan
326117395Skanvoid
327132718Skannote_variable (const char *s, type_p t, options_p o, struct fileloc *pos)
328117395Skan{
329117395Skan  pair_p n;
330169689Skan  n = XNEW (struct pair);
331117395Skan  n->name = s;
332117395Skan  n->type = t;
333117395Skan  n->line = *pos;
334117395Skan  n->opt = o;
335117395Skan  n->next = variables;
336117395Skan  variables = n;
337117395Skan}
338117395Skan
339169689Skan/* Create a fake field with the given type and name.  NEXT is the next
340169689Skan   field in the chain.  */
341169689Skan
342169689Skanstatic pair_p
343169689Skancreate_field (pair_p next, type_p type, const char *name)
344169689Skan{
345169689Skan  pair_p field;
346169689Skan
347169689Skan  field = XNEW (struct pair);
348169689Skan  field->next = next;
349169689Skan  field->type = type;
350169689Skan  field->name = name;
351169689Skan  field->opt = NULL;
352169689Skan  field->line.file = __FILE__;
353169689Skan  field->line.line = __LINE__;
354169689Skan  return field;
355169689Skan}
356169689Skan
357169689Skan/* Like create_field, but the field is only valid when condition COND
358169689Skan   is true.  */
359169689Skan
360169689Skanstatic pair_p
361169689Skancreate_optional_field (pair_p next, type_p type, const char *name,
362169689Skan		       const char *cond)
363169689Skan{
364169689Skan  static int id = 1;
365169689Skan  pair_p union_fields, field;
366169689Skan  type_p union_type;
367169689Skan
368169689Skan  /* Create a fake union type with a single nameless field of type TYPE.
369169689Skan     The field has a tag of "1".  This allows us to make the presence
370169689Skan     of a field of type TYPE depend on some boolean "desc" being true.  */
371169689Skan  union_fields = create_field (NULL, type, "");
372169689Skan  union_fields->opt = create_option (union_fields->opt, "dot", "");
373169689Skan  union_fields->opt = create_option (union_fields->opt, "tag", "1");
374169689Skan  union_type = new_structure (xasprintf ("%s_%d", "fake_union", id++), 1,
375169689Skan			      &lexer_line, union_fields, NULL);
376169689Skan
377169689Skan  /* Create the field and give it the new fake union type.  Add a "desc"
378169689Skan     tag that specifies the condition under which the field is valid.  */
379169689Skan  field = create_field (next, union_type, name);
380169689Skan  field->opt = create_option (field->opt, "desc", cond);
381169689Skan  return field;
382169689Skan}
383169689Skan
384169689Skan/* We don't care how long a CONST_DOUBLE is.  */
385117395Skan#define CONST_DOUBLE_FORMAT "ww"
386169689Skan/* We don't want to see codes that are only for generator files.  */
387169689Skan#undef GENERATOR_FILE
388169689Skan
389169689Skanenum rtx_code {
390169689Skan#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) ENUM ,
391169689Skan#include "rtl.def"
392169689Skan#undef DEF_RTL_EXPR
393169689Skan  NUM_RTX_CODE
394169689Skan};
395169689Skan
396169689Skanstatic const char * const rtx_name[NUM_RTX_CODE] = {
397169689Skan#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
398169689Skan#include "rtl.def"
399169689Skan#undef DEF_RTL_EXPR
400169689Skan};
401169689Skan
402169689Skanstatic const char * const rtx_format[NUM_RTX_CODE] = {
403117395Skan#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
404117395Skan#include "rtl.def"
405117395Skan#undef DEF_RTL_EXPR
406117395Skan};
407117395Skan
408132718Skanstatic int rtx_next_new[NUM_RTX_CODE];
409117395Skan
410169689Skan/* We also need codes and names for insn notes (not register notes).
411169689Skan   Note that we do *not* bias the note values here.  */
412169689Skanenum insn_note {
413169689Skan#define DEF_INSN_NOTE(NAME) NAME,
414169689Skan#include "insn-notes.def"
415169689Skan#undef DEF_INSN_NOTE
416169689Skan
417169689Skan  NOTE_INSN_MAX
418169689Skan};
419169689Skan
420169689Skan/* We must allocate one more entry here, as we use NOTE_INSN_MAX as the
421169689Skan   default field for line number notes.  */
422169689Skanstatic const char *const note_insn_name[NOTE_INSN_MAX+1] = {
423169689Skan#define DEF_INSN_NOTE(NAME) #NAME,
424169689Skan#include "insn-notes.def"
425169689Skan#undef DEF_INSN_NOTE
426169689Skan};
427169689Skan
428169689Skan#undef CONST_DOUBLE_FORMAT
429169689Skan#define GENERATOR_FILE
430169689Skan
431117395Skan/* Generate the contents of the rtx_next array.  This really doesn't belong
432117395Skan   in gengtype at all, but it's needed for adjust_field_rtx_def.  */
433117395Skan
434117395Skanstatic void
435132718Skangen_rtx_next (void)
436117395Skan{
437117395Skan  int i;
438117395Skan  for (i = 0; i < NUM_RTX_CODE; i++)
439117395Skan    {
440117395Skan      int k;
441132718Skan
442132718Skan      rtx_next_new[i] = -1;
443117395Skan      if (strncmp (rtx_format[i], "iuu", 3) == 0)
444132718Skan	rtx_next_new[i] = 2;
445117395Skan      else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
446132718Skan	rtx_next_new[i] = 1;
447132718Skan      else
448117395Skan	for (k = strlen (rtx_format[i]) - 1; k >= 0; k--)
449117395Skan	  if (rtx_format[i][k] == 'e' || rtx_format[i][k] == 'u')
450132718Skan	    rtx_next_new[i] = k;
451117395Skan    }
452117395Skan}
453117395Skan
454117395Skan/* Write out the contents of the rtx_next array.  */
455117395Skanstatic void
456132718Skanwrite_rtx_next (void)
457117395Skan{
458117395Skan  outf_p f = get_output_file_with_visibility (NULL);
459117395Skan  int i;
460132718Skan
461117395Skan  oprintf (f, "\n/* Used to implement the RTX_NEXT macro.  */\n");
462117395Skan  oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
463117395Skan  for (i = 0; i < NUM_RTX_CODE; i++)
464132718Skan    if (rtx_next_new[i] == -1)
465117395Skan      oprintf (f, "  0,\n");
466117395Skan    else
467132718Skan      oprintf (f,
468132718Skan	       "  RTX_HDR_SIZE + %d * sizeof (rtunion),\n",
469132718Skan	       rtx_next_new[i]);
470117395Skan  oprintf (f, "};\n");
471117395Skan}
472117395Skan
473117395Skan/* Handle `special("rtx_def")'.  This is a special case for field
474117395Skan   `fld' of struct rtx_def, which is an array of unions whose values
475117395Skan   are based in a complex way on the type of RTL.  */
476117395Skan
477117395Skanstatic type_p
478169689Skanadjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
479117395Skan{
480117395Skan  pair_p flds = NULL;
481117395Skan  options_p nodot;
482117395Skan  int i;
483117395Skan  type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp;
484169689Skan  type_p bitmap_tp, basic_block_tp, reg_attrs_tp, constant_tp, symbol_union_tp;
485117395Skan
486132718Skan  if (t->kind != TYPE_UNION)
487117395Skan    {
488132718Skan      error_at_line (&lexer_line,
489132718Skan		     "special `rtx_def' must be applied to a union");
490117395Skan      return &string_type;
491117395Skan    }
492132718Skan
493169689Skan  nodot = create_option (NULL, "dot", "");
494117395Skan
495117395Skan  rtx_tp = create_pointer (find_structure ("rtx_def", 0));
496117395Skan  rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
497117395Skan  tree_tp = create_pointer (find_structure ("tree_node", 1));
498117395Skan  mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0));
499132718Skan  reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0));
500117395Skan  bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
501117395Skan  basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
502169689Skan  constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0));
503117395Skan  scalar_tp = create_scalar_type ("rtunion scalar", 14);
504117395Skan
505117395Skan  {
506117395Skan    pair_p note_flds = NULL;
507117395Skan    int c;
508132718Skan
509169689Skan    for (c = 0; c <= NOTE_INSN_MAX; c++)
510117395Skan      {
511132718Skan	switch (c)
512132718Skan	  {
513132718Skan	  case NOTE_INSN_MAX:
514169689Skan	    note_flds = create_field (note_flds, &string_type, "rt_str");
515132718Skan	    break;
516132718Skan
517132718Skan	  case NOTE_INSN_BLOCK_BEG:
518132718Skan	  case NOTE_INSN_BLOCK_END:
519169689Skan	    note_flds = create_field (note_flds, tree_tp, "rt_tree");
520132718Skan	    break;
521132718Skan
522132718Skan	  case NOTE_INSN_EXPECTED_VALUE:
523169689Skan	  case NOTE_INSN_VAR_LOCATION:
524169689Skan	    note_flds = create_field (note_flds, rtx_tp, "rt_rtx");
525132718Skan	    break;
526132718Skan
527132718Skan	  default:
528169689Skan	    note_flds = create_field (note_flds, scalar_tp, "rt_int");
529132718Skan	    break;
530132718Skan	  }
531169689Skan	/* NOTE_INSN_MAX is used as the default field for line
532169689Skan	   number notes.  */
533169689Skan	if (c == NOTE_INSN_MAX)
534169689Skan	  note_flds->opt = create_option (nodot, "default", "");
535169689Skan	else
536169689Skan	  note_flds->opt = create_option (nodot, "tag", note_insn_name[c]);
537117395Skan      }
538169689Skan    note_union_tp = new_structure ("rtx_def_note_subunion", 1,
539169689Skan				   &lexer_line, note_flds, NULL);
540117395Skan  }
541169689Skan  /* Create a type to represent the various forms of SYMBOL_REF_DATA.  */
542169689Skan  {
543169689Skan    pair_p sym_flds;
544132718Skan
545169689Skan    sym_flds = create_field (NULL, tree_tp, "rt_tree");
546169689Skan    sym_flds->opt = create_option (nodot, "default", "");
547117395Skan
548169689Skan    sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
549169689Skan    sym_flds->opt = create_option (nodot, "tag", "1");
550169689Skan
551169689Skan    symbol_union_tp = new_structure ("rtx_def_symbol_subunion", 1,
552169689Skan				     &lexer_line, sym_flds, NULL);
553169689Skan  }
554117395Skan  for (i = 0; i < NUM_RTX_CODE; i++)
555117395Skan    {
556117395Skan      pair_p subfields = NULL;
557117395Skan      size_t aindex, nmindex;
558117395Skan      const char *sname;
559169689Skan      type_p substruct;
560117395Skan      char *ftag;
561117395Skan
562117395Skan      for (aindex = 0; aindex < strlen (rtx_format[i]); aindex++)
563117395Skan	{
564117395Skan	  type_p t;
565117395Skan	  const char *subname;
566117395Skan
567117395Skan	  switch (rtx_format[i][aindex])
568117395Skan	    {
569117395Skan	    case '*':
570117395Skan	    case 'i':
571117395Skan	    case 'n':
572117395Skan	    case 'w':
573117395Skan	      t = scalar_tp;
574169689Skan	      subname = "rt_int";
575117395Skan	      break;
576117395Skan
577117395Skan	    case '0':
578117395Skan	      if (i == MEM && aindex == 1)
579169689Skan		t = mem_attrs_tp, subname = "rt_mem";
580117395Skan	      else if (i == JUMP_INSN && aindex == 9)
581169689Skan		t = rtx_tp, subname = "rt_rtx";
582117395Skan	      else if (i == CODE_LABEL && aindex == 4)
583169689Skan		t = scalar_tp, subname = "rt_int";
584117395Skan	      else if (i == CODE_LABEL && aindex == 5)
585169689Skan		t = rtx_tp, subname = "rt_rtx";
586117395Skan	      else if (i == LABEL_REF
587117395Skan		       && (aindex == 1 || aindex == 2))
588169689Skan		t = rtx_tp, subname = "rt_rtx";
589117395Skan	      else if (i == NOTE && aindex == 4)
590117395Skan		t = note_union_tp, subname = "";
591117395Skan	      else if (i == NOTE && aindex >= 7)
592169689Skan		t = scalar_tp, subname = "rt_int";
593117395Skan	      else if (i == ADDR_DIFF_VEC && aindex == 4)
594169689Skan		t = scalar_tp, subname = "rt_int";
595117395Skan	      else if (i == VALUE && aindex == 0)
596169689Skan		t = scalar_tp, subname = "rt_int";
597117395Skan	      else if (i == REG && aindex == 1)
598169689Skan		t = scalar_tp, subname = "rt_int";
599132718Skan	      else if (i == REG && aindex == 2)
600169689Skan		t = reg_attrs_tp, subname = "rt_reg";
601117395Skan	      else if (i == SCRATCH && aindex == 0)
602169689Skan		t = scalar_tp, subname = "rt_int";
603132718Skan	      else if (i == SYMBOL_REF && aindex == 1)
604169689Skan		t = scalar_tp, subname = "rt_int";
605132718Skan	      else if (i == SYMBOL_REF && aindex == 2)
606169689Skan		t = symbol_union_tp, subname = "";
607117395Skan	      else if (i == BARRIER && aindex >= 3)
608169689Skan		t = scalar_tp, subname = "rt_int";
609117395Skan	      else
610117395Skan		{
611132718Skan		  error_at_line (&lexer_line,
612117395Skan			"rtx type `%s' has `0' in position %lu, can't handle",
613117395Skan				 rtx_name[i], (unsigned long) aindex);
614117395Skan		  t = &string_type;
615169689Skan		  subname = "rt_int";
616117395Skan		}
617117395Skan	      break;
618132718Skan
619117395Skan	    case 's':
620117395Skan	    case 'S':
621117395Skan	    case 'T':
622117395Skan	      t = &string_type;
623169689Skan	      subname = "rt_str";
624117395Skan	      break;
625117395Skan
626117395Skan	    case 'e':
627117395Skan	    case 'u':
628117395Skan	      t = rtx_tp;
629169689Skan	      subname = "rt_rtx";
630117395Skan	      break;
631117395Skan
632117395Skan	    case 'E':
633117395Skan	    case 'V':
634117395Skan	      t = rtvec_tp;
635169689Skan	      subname = "rt_rtvec";
636117395Skan	      break;
637117395Skan
638117395Skan	    case 't':
639117395Skan	      t = tree_tp;
640169689Skan	      subname = "rt_tree";
641117395Skan	      break;
642117395Skan
643117395Skan	    case 'b':
644117395Skan	      t = bitmap_tp;
645169689Skan	      subname = "rt_bit";
646117395Skan	      break;
647117395Skan
648117395Skan	    case 'B':
649117395Skan	      t = basic_block_tp;
650169689Skan	      subname = "rt_bb";
651117395Skan	      break;
652117395Skan
653117395Skan	    default:
654132718Skan	      error_at_line (&lexer_line,
655117395Skan		     "rtx type `%s' has `%c' in position %lu, can't handle",
656117395Skan			     rtx_name[i], rtx_format[i][aindex],
657117395Skan			     (unsigned long)aindex);
658117395Skan	      t = &string_type;
659169689Skan	      subname = "rt_int";
660117395Skan	      break;
661117395Skan	    }
662117395Skan
663169689Skan	  subfields = create_field (subfields, t,
664169689Skan				    xasprintf (".fld[%lu].%s",
665169689Skan					       (unsigned long) aindex,
666169689Skan					       subname));
667169689Skan	  subfields->opt = nodot;
668117395Skan	  if (t == note_union_tp)
669169689Skan	    subfields->opt = create_option (subfields->opt, "desc",
670169689Skan					    "NOTE_LINE_NUMBER (&%0)");
671169689Skan	  if (t == symbol_union_tp)
672169689Skan	    subfields->opt = create_option (subfields->opt, "desc",
673169689Skan					    "CONSTANT_POOL_ADDRESS_P (&%0)");
674117395Skan	}
675117395Skan
676169689Skan      if (i == SYMBOL_REF)
677169689Skan	{
678169689Skan	  /* Add the "block_sym" field if SYMBOL_REF_HAS_BLOCK_INFO_P holds.  */
679169689Skan	  type_p field_tp = find_structure ("block_symbol", 0);
680169689Skan	  subfields
681169689Skan	    = create_optional_field (subfields, field_tp, "block_sym",
682169689Skan				     "SYMBOL_REF_HAS_BLOCK_INFO_P (&%0)");
683169689Skan	}
684169689Skan
685117395Skan      sname = xasprintf ("rtx_def_%s", rtx_name[i]);
686169689Skan      substruct = new_structure (sname, 0, &lexer_line, subfields, NULL);
687169689Skan
688117395Skan      ftag = xstrdup (rtx_name[i]);
689117395Skan      for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
690117395Skan	ftag[nmindex] = TOUPPER (ftag[nmindex]);
691169689Skan
692169689Skan      flds = create_field (flds, substruct, "");
693169689Skan      flds->opt = create_option (nodot, "tag", ftag);
694117395Skan    }
695117395Skan
696169689Skan  return new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
697117395Skan}
698117395Skan
699117395Skan/* Handle `special("tree_exp")'.  This is a special case for
700117395Skan   field `operands' of struct tree_exp, which although it claims to contain
701132718Skan   pointers to trees, actually sometimes contains pointers to RTL too.
702117395Skan   Passed T, the old type of the field, and OPT its options.  Returns
703117395Skan   a new type for the field.  */
704117395Skan
705117395Skanstatic type_p
706132718Skanadjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED)
707117395Skan{
708117395Skan  pair_p flds;
709117395Skan  options_p nodot;
710132718Skan
711117395Skan  if (t->kind != TYPE_ARRAY)
712117395Skan    {
713132718Skan      error_at_line (&lexer_line,
714117395Skan		     "special `tree_exp' must be applied to an array");
715117395Skan      return &string_type;
716117395Skan    }
717132718Skan
718169689Skan  nodot = create_option (NULL, "dot", "");
719117395Skan
720169689Skan  flds = create_field (NULL, t, "");
721169689Skan  flds->opt = create_option (nodot, "length",
722169689Skan			     "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))");
723169689Skan  flds->opt = create_option (flds->opt, "default", "");
724132718Skan
725169689Skan  return new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
726117395Skan}
727117395Skan
728117395Skan/* Perform any special processing on a type T, about to become the type
729117395Skan   of a field.  Return the appropriate type for the field.
730117395Skan   At present:
731117395Skan   - Converts pointer-to-char, with no length parameter, to TYPE_STRING;
732117395Skan   - Similarly for arrays of pointer-to-char;
733117395Skan   - Converts structures for which a parameter is provided to
734117395Skan     TYPE_PARAM_STRUCT;
735117395Skan   - Handles "special" options.
736132718Skan*/
737117395Skan
738117395Skantype_p
739132718Skanadjust_field_type (type_p t, options_p opt)
740117395Skan{
741117395Skan  int length_p = 0;
742117395Skan  const int pointer_p = t->kind == TYPE_POINTER;
743117395Skan  type_p params[NUM_PARAM];
744117395Skan  int params_p = 0;
745117395Skan  int i;
746117395Skan
747117395Skan  for (i = 0; i < NUM_PARAM; i++)
748117395Skan    params[i] = NULL;
749132718Skan
750117395Skan  for (; opt; opt = opt->next)
751117395Skan    if (strcmp (opt->name, "length") == 0)
752117395Skan      length_p = 1;
753117395Skan    else if (strcmp (opt->name, "param_is") == 0
754117395Skan	     || (strncmp (opt->name, "param", 5) == 0
755117395Skan		 && ISDIGIT (opt->name[5])
756117395Skan		 && strcmp (opt->name + 6, "_is") == 0))
757117395Skan      {
758117395Skan	int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
759117395Skan
760117395Skan	if (! UNION_OR_STRUCT_P (t)
761117395Skan	    && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
762117395Skan	  {
763132718Skan	    error_at_line (&lexer_line,
764117395Skan   "option `%s' may only be applied to structures or structure pointers",
765117395Skan			   opt->name);
766117395Skan	    return t;
767117395Skan	  }
768117395Skan
769117395Skan	params_p = 1;
770117395Skan	if (params[num] != NULL)
771117395Skan	  error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
772117395Skan	if (! ISDIGIT (opt->name[5]))
773117395Skan	  params[num] = create_pointer ((type_p) opt->info);
774117395Skan	else
775117395Skan	  params[num] = (type_p) opt->info;
776117395Skan      }
777117395Skan    else if (strcmp (opt->name, "special") == 0)
778117395Skan      {
779169689Skan	const char *special_name = opt->info;
780117395Skan	if (strcmp (special_name, "tree_exp") == 0)
781117395Skan	  t = adjust_field_tree_exp (t, opt);
782117395Skan	else if (strcmp (special_name, "rtx_def") == 0)
783117395Skan	  t = adjust_field_rtx_def (t, opt);
784117395Skan	else
785117395Skan	  error_at_line (&lexer_line, "unknown special `%s'", special_name);
786117395Skan      }
787117395Skan
788117395Skan  if (params_p)
789117395Skan    {
790117395Skan      type_p realt;
791132718Skan
792117395Skan      if (pointer_p)
793117395Skan	t = t->u.p;
794117395Skan      realt = find_param_structure (t, params);
795117395Skan      t = pointer_p ? create_pointer (realt) : realt;
796117395Skan    }
797117395Skan
798117395Skan  if (! length_p
799117395Skan      && pointer_p
800117395Skan      && t->u.p->kind == TYPE_SCALAR
801117395Skan      && (strcmp (t->u.p->u.sc, "char") == 0
802117395Skan	  || strcmp (t->u.p->u.sc, "unsigned char") == 0))
803117395Skan    return &string_type;
804117395Skan  if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
805117395Skan      && t->u.a.p->u.p->kind == TYPE_SCALAR
806117395Skan      && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
807117395Skan	  || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
808117395Skan    return create_array (&string_type, t->u.a.len);
809117395Skan
810117395Skan  return t;
811117395Skan}
812117395Skan
813117395Skan/* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
814132718Skan   and information about the correspondence between token types and fields
815117395Skan   in TYPEINFO.  POS is used for error messages.  */
816117395Skan
817117395Skanvoid
818132718Skannote_yacc_type (options_p o, pair_p fields, pair_p typeinfo,
819132718Skan		struct fileloc *pos)
820117395Skan{
821117395Skan  pair_p p;
822117395Skan  pair_p *p_p;
823132718Skan
824117395Skan  for (p = typeinfo; p; p = p->next)
825117395Skan    {
826117395Skan      pair_p m;
827132718Skan
828117395Skan      if (p->name == NULL)
829117395Skan	continue;
830117395Skan
831117395Skan      if (p->type == (type_p) 1)
832117395Skan	{
833117395Skan	  pair_p pp;
834117395Skan	  int ok = 0;
835132718Skan
836117395Skan	  for (pp = typeinfo; pp; pp = pp->next)
837117395Skan	    if (pp->type != (type_p) 1
838117395Skan		&& strcmp (pp->opt->info, p->opt->info) == 0)
839117395Skan	      {
840117395Skan		ok = 1;
841117395Skan		break;
842117395Skan	      }
843117395Skan	  if (! ok)
844117395Skan	    continue;
845117395Skan	}
846117395Skan
847117395Skan      for (m = fields; m; m = m->next)
848117395Skan	if (strcmp (m->name, p->name) == 0)
849117395Skan	  p->type = m->type;
850117395Skan      if (p->type == NULL)
851117395Skan	{
852132718Skan	  error_at_line (&p->line,
853117395Skan			 "couldn't match fieldname `%s'", p->name);
854117395Skan	  p->name = NULL;
855117395Skan	}
856117395Skan    }
857132718Skan
858117395Skan  p_p = &typeinfo;
859117395Skan  while (*p_p)
860117395Skan    {
861117395Skan      pair_p p = *p_p;
862117395Skan
863117395Skan      if (p->name == NULL
864117395Skan	  || p->type == (type_p) 1)
865117395Skan	*p_p = p->next;
866117395Skan      else
867117395Skan	p_p = &p->next;
868117395Skan    }
869117395Skan
870169689Skan  do_typedef ("YYSTYPE", new_structure ("yy_union", 1, pos, typeinfo, o), pos);
871117395Skan}
872117395Skan
873132718Skanstatic void process_gc_options (options_p, enum gc_used_enum,
874169689Skan				int *, int *, int *, type_p *);
875132718Skanstatic void set_gc_used_type (type_p, enum gc_used_enum, type_p *);
876132718Skanstatic void set_gc_used (pair_p);
877117395Skan
878117395Skan/* Handle OPT for set_gc_used_type.  */
879117395Skan
880117395Skanstatic void
881132718Skanprocess_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
882169689Skan		    int *pass_param, int *length, type_p *nested_ptr)
883117395Skan{
884117395Skan  options_p o;
885117395Skan  for (o = opt; o; o = o->next)
886117395Skan    if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
887117395Skan      set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL);
888117395Skan    else if (strcmp (o->name, "maybe_undef") == 0)
889117395Skan      *maybe_undef = 1;
890117395Skan    else if (strcmp (o->name, "use_params") == 0)
891117395Skan      *pass_param = 1;
892117395Skan    else if (strcmp (o->name, "length") == 0)
893117395Skan      *length = 1;
894169689Skan    else if (strcmp (o->name, "nested_ptr") == 0)
895169689Skan      *nested_ptr = ((const struct nested_ptr_data *) o->info)->type;
896117395Skan}
897117395Skan
898117395Skan/* Set the gc_used field of T to LEVEL, and handle the types it references.  */
899117395Skan
900117395Skanstatic void
901132718Skanset_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
902117395Skan{
903117395Skan  if (t->gc_used >= level)
904117395Skan    return;
905132718Skan
906117395Skan  t->gc_used = level;
907117395Skan
908117395Skan  switch (t->kind)
909117395Skan    {
910117395Skan    case TYPE_STRUCT:
911117395Skan    case TYPE_UNION:
912117395Skan      {
913117395Skan	pair_p f;
914117395Skan	int dummy;
915169689Skan	type_p dummy2;
916117395Skan
917169689Skan	process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy,
918169689Skan			    &dummy2);
919117395Skan
920117395Skan	for (f = t->u.s.fields; f; f = f->next)
921117395Skan	  {
922117395Skan	    int maybe_undef = 0;
923117395Skan	    int pass_param = 0;
924117395Skan	    int length = 0;
925169689Skan	    type_p nested_ptr = NULL;
926117395Skan	    process_gc_options (f->opt, level, &maybe_undef, &pass_param,
927169689Skan				&length, &nested_ptr);
928132718Skan
929169689Skan	    if (nested_ptr && f->type->kind == TYPE_POINTER)
930169689Skan	      set_gc_used_type (nested_ptr, GC_POINTED_TO,
931169689Skan				pass_param ? param : NULL);
932169689Skan	    else if (length && f->type->kind == TYPE_POINTER)
933117395Skan	      set_gc_used_type (f->type->u.p, GC_USED, NULL);
934117395Skan	    else if (maybe_undef && f->type->kind == TYPE_POINTER)
935117395Skan	      set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
936117395Skan	    else if (pass_param && f->type->kind == TYPE_POINTER && param)
937117395Skan	      set_gc_used_type (find_param_structure (f->type->u.p, param),
938117395Skan				GC_POINTED_TO, NULL);
939117395Skan	    else
940117395Skan	      set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
941117395Skan	  }
942117395Skan	break;
943117395Skan      }
944117395Skan
945117395Skan    case TYPE_POINTER:
946117395Skan      set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
947117395Skan      break;
948117395Skan
949117395Skan    case TYPE_ARRAY:
950117395Skan      set_gc_used_type (t->u.a.p, GC_USED, param);
951117395Skan      break;
952132718Skan
953117395Skan    case TYPE_LANG_STRUCT:
954117395Skan      for (t = t->u.s.lang_struct; t; t = t->next)
955117395Skan	set_gc_used_type (t, level, param);
956117395Skan      break;
957117395Skan
958117395Skan    case TYPE_PARAM_STRUCT:
959117395Skan      {
960117395Skan	int i;
961117395Skan	for (i = 0; i < NUM_PARAM; i++)
962117395Skan	  if (t->u.param_struct.param[i] != 0)
963117395Skan	    set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
964117395Skan      }
965117395Skan      if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
966117395Skan	level = GC_POINTED_TO;
967117395Skan      else
968117395Skan	level = GC_USED;
969117395Skan      t->u.param_struct.stru->gc_used = GC_UNUSED;
970132718Skan      set_gc_used_type (t->u.param_struct.stru, level,
971117395Skan			t->u.param_struct.param);
972117395Skan      break;
973117395Skan
974117395Skan    default:
975117395Skan      break;
976117395Skan    }
977117395Skan}
978117395Skan
979117395Skan/* Set the gc_used fields of all the types pointed to by VARIABLES.  */
980117395Skan
981117395Skanstatic void
982132718Skanset_gc_used (pair_p variables)
983117395Skan{
984117395Skan  pair_p p;
985117395Skan  for (p = variables; p; p = p->next)
986117395Skan    set_gc_used_type (p->type, GC_USED, NULL);
987117395Skan}
988117395Skan
989117395Skan/* File mapping routines.  For each input file, there is one output .c file
990117395Skan   (but some output files have many input files), and there is one .h file
991117395Skan   for the whole build.  */
992117395Skan
993117395Skan/* The list of output files.  */
994117395Skanstatic outf_p output_files;
995117395Skan
996117395Skan/* The output header file that is included into pretty much every
997117395Skan   source file.  */
998169689Skanstatic outf_p header_file;
999117395Skan
1000117395Skan/* Number of files specified in gtfiles.  */
1001117395Skan#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
1002117395Skan
1003117395Skan/* Number of files in the language files array.  */
1004117395Skan#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
1005117395Skan
1006117395Skan/* Length of srcdir name.  */
1007117395Skanstatic int srcdir_len = 0;
1008117395Skan
1009117395Skan#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
1010117395Skanoutf_p base_files[NUM_BASE_FILES];
1011117395Skan
1012132718Skanstatic outf_p create_file (const char *, const char *);
1013132718Skanstatic const char * get_file_basename (const char *);
1014117395Skan
1015117395Skan/* Create and return an outf_p for a new file for NAME, to be called
1016117395Skan   ONAME.  */
1017117395Skan
1018117395Skanstatic outf_p
1019132718Skancreate_file (const char *name, const char *oname)
1020117395Skan{
1021117395Skan  static const char *const hdr[] = {
1022169689Skan    "   Copyright (C) 2004 Free Software Foundation, Inc.\n",
1023117395Skan    "\n",
1024117395Skan    "This file is part of GCC.\n",
1025117395Skan    "\n",
1026117395Skan    "GCC is free software; you can redistribute it and/or modify it under\n",
1027117395Skan    "the terms of the GNU General Public License as published by the Free\n",
1028117395Skan    "Software Foundation; either version 2, or (at your option) any later\n",
1029117395Skan    "version.\n",
1030117395Skan    "\n",
1031117395Skan    "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
1032117395Skan    "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
1033117395Skan    "FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n",
1034117395Skan    "for more details.\n",
1035117395Skan    "\n",
1036117395Skan    "You should have received a copy of the GNU General Public License\n",
1037117395Skan    "along with GCC; see the file COPYING.  If not, write to the Free\n",
1038169689Skan    "Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA\n",
1039169689Skan    "02110-1301, USA.  */\n",
1040117395Skan    "\n",
1041117395Skan    "/* This file is machine generated.  Do not edit.  */\n"
1042117395Skan  };
1043117395Skan  outf_p f;
1044117395Skan  size_t i;
1045132718Skan
1046169689Skan  f = XCNEW (struct outf);
1047117395Skan  f->next = output_files;
1048117395Skan  f->name = oname;
1049117395Skan  output_files = f;
1050117395Skan
1051117395Skan  oprintf (f, "/* Type information for %s.\n", name);
1052117395Skan  for (i = 0; i < ARRAY_SIZE (hdr); i++)
1053117395Skan    oprintf (f, "%s", hdr[i]);
1054117395Skan  return f;
1055117395Skan}
1056117395Skan
1057117395Skan/* Print, like fprintf, to O.  */
1058132718Skanvoid
1059132718Skanoprintf (outf_p o, const char *format, ...)
1060117395Skan{
1061117395Skan  char *s;
1062117395Skan  size_t slength;
1063132718Skan  va_list ap;
1064132718Skan
1065132718Skan  va_start (ap, format);
1066117395Skan  slength = xvasprintf (&s, format, ap);
1067117395Skan
1068117395Skan  if (o->bufused + slength > o->buflength)
1069117395Skan    {
1070117395Skan      size_t new_len = o->buflength;
1071117395Skan      if (new_len == 0)
1072117395Skan	new_len = 1024;
1073117395Skan      do {
1074117395Skan	new_len *= 2;
1075117395Skan      } while (o->bufused + slength >= new_len);
1076169689Skan      o->buf = XRESIZEVEC (char, o->buf, new_len);
1077117395Skan      o->buflength = new_len;
1078117395Skan    }
1079117395Skan  memcpy (o->buf + o->bufused, s, slength);
1080117395Skan  o->bufused += slength;
1081117395Skan  free (s);
1082132718Skan  va_end (ap);
1083117395Skan}
1084117395Skan
1085117395Skan/* Open the global header file and the language-specific header files.  */
1086117395Skan
1087117395Skanstatic void
1088132718Skanopen_base_files (void)
1089117395Skan{
1090117395Skan  size_t i;
1091132718Skan
1092117395Skan  header_file = create_file ("GCC", "gtype-desc.h");
1093117395Skan
1094117395Skan  for (i = 0; i < NUM_BASE_FILES; i++)
1095132718Skan    base_files[i] = create_file (lang_dir_names[i],
1096117395Skan				 xasprintf ("gtype-%s.h", lang_dir_names[i]));
1097117395Skan
1098117395Skan  /* gtype-desc.c is a little special, so we create it here.  */
1099117395Skan  {
1100117395Skan    /* The order of files here matters very much.  */
1101117395Skan    static const char *const ifiles [] = {
1102169689Skan      "config.h", "system.h", "coretypes.h", "tm.h", "varray.h",
1103169689Skan      "hashtab.h", "splay-tree.h",  "obstack.h", "bitmap.h", "input.h",
1104169689Skan      "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
1105169689Skan      "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
1106169689Skan      "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
1107169689Skan      "tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
1108169689Skan      "except.h", "output.h", NULL
1109117395Skan    };
1110117395Skan    const char *const *ifp;
1111117395Skan    outf_p gtype_desc_c;
1112132718Skan
1113117395Skan    gtype_desc_c = create_file ("GCC", "gtype-desc.c");
1114117395Skan    for (ifp = ifiles; *ifp; ifp++)
1115117395Skan      oprintf (gtype_desc_c, "#include \"%s\"\n", *ifp);
1116117395Skan  }
1117117395Skan}
1118117395Skan
1119117395Skan/* Determine the pathname to F relative to $(srcdir).  */
1120117395Skan
1121117395Skanstatic const char *
1122132718Skanget_file_basename (const char *f)
1123117395Skan{
1124117395Skan  const char *basename;
1125117395Skan  unsigned i;
1126132718Skan
1127117395Skan  basename = strrchr (f, '/');
1128132718Skan
1129117395Skan  if (!basename)
1130117395Skan    return f;
1131132718Skan
1132117395Skan  basename++;
1133132718Skan
1134117395Skan  for (i = 1; i < NUM_BASE_FILES; i++)
1135117395Skan    {
1136117395Skan      const char * s1;
1137117395Skan      const char * s2;
1138117395Skan      int l1;
1139117395Skan      int l2;
1140117395Skan      s1 = basename - strlen (lang_dir_names [i]) - 1;
1141117395Skan      s2 = lang_dir_names [i];
1142117395Skan      l1 = strlen (s1);
1143117395Skan      l2 = strlen (s2);
1144169689Skan      if (l1 >= l2 && IS_DIR_SEPARATOR (s1[-1]) && !memcmp (s1, s2, l2))
1145117395Skan        {
1146117395Skan          basename -= l2 + 1;
1147117395Skan          if ((basename - f - 1) != srcdir_len)
1148169689Skan	    fatal ("filename `%s' should be preceded by $srcdir", f);
1149117395Skan          break;
1150117395Skan        }
1151117395Skan    }
1152132718Skan
1153117395Skan  return basename;
1154117395Skan}
1155117395Skan
1156117395Skan/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
1157132718Skan   INPUT_FILE is used by <lang>.
1158117395Skan
1159117395Skan   This function should be written to assume that a file _is_ used
1160117395Skan   if the situation is unclear.  If it wrongly assumes a file _is_ used,
1161117395Skan   a linker error will result.  If it wrongly assumes a file _is not_ used,
1162117395Skan   some GC roots may be missed, which is a much harder-to-debug problem.  */
1163117395Skan
1164117395Skanunsigned
1165132718Skanget_base_file_bitmap (const char *input_file)
1166117395Skan{
1167117395Skan  const char *basename = get_file_basename (input_file);
1168117395Skan  const char *slashpos = strchr (basename, '/');
1169117395Skan  unsigned j;
1170117395Skan  unsigned k;
1171117395Skan  unsigned bitmap;
1172132718Skan
1173169689Skan  /* If the file resides in a language subdirectory (e.g., 'cp'), assume that
1174169689Skan     it belongs to the corresponding language.  The file may belong to other
1175169689Skan     languages as well (which is checked for below).  */
1176169689Skan
1177117395Skan  if (slashpos)
1178117395Skan    {
1179117395Skan      size_t i;
1180117395Skan      for (i = 1; i < NUM_BASE_FILES; i++)
1181117395Skan	if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
1182117395Skan	    && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
1183117395Skan          {
1184117395Skan            /* It's in a language directory, set that language.  */
1185117395Skan            bitmap = 1 << i;
1186117395Skan          }
1187117395Skan    }
1188117395Skan
1189117395Skan  /* If it's in any config-lang.in, then set for the languages
1190117395Skan     specified.  */
1191117395Skan
1192117395Skan  bitmap = 0;
1193117395Skan
1194117395Skan  for (j = 0; j < NUM_LANG_FILES; j++)
1195117395Skan    {
1196117395Skan      if (!strcmp(input_file, lang_files[j]))
1197117395Skan        {
1198117395Skan          for (k = 0; k < NUM_BASE_FILES; k++)
1199117395Skan            {
1200117395Skan              if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
1201117395Skan                bitmap |= (1 << k);
1202117395Skan            }
1203117395Skan        }
1204117395Skan    }
1205132718Skan
1206117395Skan  /* Otherwise, set all languages.  */
1207117395Skan  if (!bitmap)
1208117395Skan    bitmap = (1 << NUM_BASE_FILES) - 1;
1209117395Skan
1210117395Skan  return bitmap;
1211117395Skan}
1212117395Skan
1213117395Skan/* An output file, suitable for definitions, that can see declarations
1214117395Skan   made in INPUT_FILE and is linked into every language that uses
1215117395Skan   INPUT_FILE.  */
1216117395Skan
1217117395Skanoutf_p
1218132718Skanget_output_file_with_visibility (const char *input_file)
1219117395Skan{
1220117395Skan  outf_p r;
1221117395Skan  size_t len;
1222117395Skan  const char *basename;
1223117395Skan  const char *for_name;
1224117395Skan  const char *output_name;
1225117395Skan
1226117395Skan  /* This can happen when we need a file with visibility on a
1227117395Skan     structure that we've never seen.  We have to just hope that it's
1228117395Skan     globally visible.  */
1229117395Skan  if (input_file == NULL)
1230117395Skan    input_file = "system.h";
1231117395Skan
1232117395Skan  /* Determine the output file name.  */
1233117395Skan  basename = get_file_basename (input_file);
1234117395Skan
1235117395Skan  len = strlen (basename);
1236117395Skan  if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
1237117395Skan      || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
1238117395Skan      || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
1239117395Skan    {
1240117395Skan      char *s;
1241132718Skan
1242117395Skan      output_name = s = xasprintf ("gt-%s", basename);
1243117395Skan      for (; *s != '.'; s++)
1244117395Skan	if (! ISALNUM (*s) && *s != '-')
1245117395Skan	  *s = '-';
1246117395Skan      memcpy (s, ".h", sizeof (".h"));
1247117395Skan      for_name = basename;
1248117395Skan    }
1249169689Skan  /* Some headers get used by more than one front-end; hence, it
1250169689Skan     would be inappropriate to spew them out to a single gtype-<lang>.h
1251169689Skan     (and gengtype doesn't know how to direct spewage into multiple
1252169689Skan     gtype-<lang>.h headers at this time).  Instead, we pair up these
1253169689Skan     headers with source files (and their special purpose gt-*.h headers).  */
1254117395Skan  else if (strcmp (basename, "c-common.h") == 0)
1255117395Skan    output_name = "gt-c-common.h", for_name = "c-common.c";
1256117395Skan  else if (strcmp (basename, "c-tree.h") == 0)
1257117395Skan    output_name = "gt-c-decl.h", for_name = "c-decl.c";
1258169689Skan  else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2])
1259169689Skan	   && strcmp (basename + 3, "cp-tree.h") == 0)
1260169689Skan    output_name = "gt-cp-tree.h", for_name = "cp/tree.c";
1261169689Skan  else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2])
1262169689Skan	   && strcmp (basename + 3, "decl.h") == 0)
1263169689Skan    output_name = "gt-cp-decl.h", for_name = "cp/decl.c";
1264169689Skan  else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2])
1265169689Skan	   && strcmp (basename + 3, "name-lookup.h") == 0)
1266169689Skan    output_name = "gt-cp-name-lookup.h", for_name = "cp/name-lookup.c";
1267169689Skan  else if (strncmp (basename, "objc", 4) == 0 && IS_DIR_SEPARATOR (basename[4])
1268169689Skan	   && strcmp (basename + 5, "objc-act.h") == 0)
1269169689Skan    output_name = "gt-objc-objc-act.h", for_name = "objc/objc-act.c";
1270169689Skan  else
1271117395Skan    {
1272117395Skan      size_t i;
1273132718Skan
1274117395Skan      for (i = 0; i < NUM_BASE_FILES; i++)
1275117395Skan	if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
1276117395Skan	    && basename[strlen(lang_dir_names[i])] == '/')
1277117395Skan	  return base_files[i];
1278117395Skan
1279117395Skan      output_name = "gtype-desc.c";
1280117395Skan      for_name = NULL;
1281117395Skan    }
1282117395Skan
1283117395Skan  /* Look through to see if we've ever seen this output filename before.  */
1284117395Skan  for (r = output_files; r; r = r->next)
1285117395Skan    if (strcmp (r->name, output_name) == 0)
1286117395Skan      return r;
1287117395Skan
1288117395Skan  /* If not, create it.  */
1289117395Skan  r = create_file (for_name, output_name);
1290117395Skan
1291117395Skan  return r;
1292117395Skan}
1293117395Skan
1294117395Skan/* The name of an output file, suitable for definitions, that can see
1295117395Skan   declarations made in INPUT_FILE and is linked into every language
1296117395Skan   that uses INPUT_FILE.  */
1297117395Skan
1298117395Skanconst char *
1299132718Skanget_output_file_name (const char *input_file)
1300117395Skan{
1301117395Skan  return get_output_file_with_visibility (input_file)->name;
1302117395Skan}
1303117395Skan
1304117395Skan/* Copy the output to its final destination,
1305117395Skan   but don't unnecessarily change modification times.  */
1306117395Skan
1307117395Skanstatic void
1308132718Skanclose_output_files (void)
1309117395Skan{
1310117395Skan  outf_p of;
1311132718Skan
1312117395Skan  for (of = output_files; of; of = of->next)
1313117395Skan    {
1314117395Skan      FILE * newfile;
1315117395Skan
1316117395Skan      newfile = fopen (of->name, "r");
1317117395Skan      if (newfile != NULL )
1318117395Skan	{
1319117395Skan	  int no_write_p;
1320117395Skan	  size_t i;
1321117395Skan
1322117395Skan	  for (i = 0; i < of->bufused; i++)
1323117395Skan	    {
1324117395Skan	      int ch;
1325117395Skan	      ch = fgetc (newfile);
1326117395Skan	      if (ch == EOF || ch != (unsigned char) of->buf[i])
1327117395Skan		break;
1328117395Skan	    }
1329117395Skan	  no_write_p = i == of->bufused && fgetc (newfile) == EOF;
1330117395Skan	  fclose (newfile);
1331117395Skan
1332117395Skan	  if (no_write_p)
1333117395Skan	    continue;
1334117395Skan	}
1335117395Skan
1336117395Skan      newfile = fopen (of->name, "w");
1337117395Skan      if (newfile == NULL)
1338117395Skan	{
1339117395Skan	  perror ("opening output file");
1340117395Skan	  exit (1);
1341117395Skan	}
1342117395Skan      if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
1343117395Skan	{
1344117395Skan	  perror ("writing output file");
1345117395Skan	  exit (1);
1346117395Skan	}
1347117395Skan      if (fclose (newfile) != 0)
1348117395Skan	{
1349117395Skan	  perror ("closing output file");
1350117395Skan	  exit (1);
1351117395Skan	}
1352117395Skan    }
1353117395Skan}
1354117395Skan
1355117395Skanstruct flist {
1356117395Skan  struct flist *next;
1357117395Skan  int started_p;
1358117395Skan  const char *name;
1359117395Skan  outf_p f;
1360117395Skan};
1361117395Skan
1362132718Skanstruct walk_type_data;
1363117395Skan
1364132718Skan/* For scalars and strings, given the item in 'val'.
1365132718Skan   For structures, given a pointer to the item in 'val'.
1366132718Skan   For misc. pointers, given the item in 'val'.
1367132718Skan*/
1368132718Skantypedef void (*process_field_fn)
1369132718Skan     (type_p f, const struct walk_type_data *p);
1370132718Skantypedef void (*func_name_fn)
1371132718Skan     (type_p s, const struct walk_type_data *p);
1372117395Skan
1373132718Skan/* Parameters for write_types.  */
1374117395Skan
1375132718Skanstruct write_types_data
1376117395Skan{
1377132718Skan  const char *prefix;
1378132718Skan  const char *param_prefix;
1379132718Skan  const char *subfield_marker_routine;
1380132718Skan  const char *marker_routine;
1381132718Skan  const char *reorder_note_routine;
1382132718Skan  const char *comment;
1383132718Skan};
1384117395Skan
1385132718Skanstatic void output_escaped_param (struct walk_type_data *d,
1386132718Skan				  const char *, const char *);
1387132718Skanstatic void output_mangled_typename (outf_p, type_p);
1388132718Skanstatic void walk_type (type_p t, struct walk_type_data *d);
1389132718Skanstatic void write_func_for_structure
1390132718Skan     (type_p orig_s, type_p s, type_p * param,
1391132718Skan      const struct write_types_data *wtd);
1392132718Skanstatic void write_types_process_field
1393132718Skan     (type_p f, const struct walk_type_data *d);
1394132718Skanstatic void write_types (type_p structures,
1395132718Skan			 type_p param_structs,
1396132718Skan			 const struct write_types_data *wtd);
1397132718Skanstatic void write_types_local_process_field
1398132718Skan     (type_p f, const struct walk_type_data *d);
1399132718Skanstatic void write_local_func_for_structure
1400132718Skan     (type_p orig_s, type_p s, type_p * param);
1401132718Skanstatic void write_local (type_p structures,
1402132718Skan			 type_p param_structs);
1403132718Skanstatic void write_enum_defn (type_p structures, type_p param_structs);
1404132718Skanstatic int contains_scalar_p (type_p t);
1405132718Skanstatic void put_mangled_filename (outf_p , const char *);
1406132718Skanstatic void finish_root_table (struct flist *flp, const char *pfx,
1407132718Skan			       const char *tname, const char *lastname,
1408132718Skan			       const char *name);
1409132718Skanstatic void write_root (outf_p , pair_p, type_p, const char *, int,
1410132718Skan			struct fileloc *, const char *);
1411132718Skanstatic void write_array (outf_p f, pair_p v,
1412132718Skan			 const struct write_types_data *wtd);
1413132718Skanstatic void write_roots (pair_p);
1414132718Skan
1415132718Skan/* Parameters for walk_type.  */
1416132718Skan
1417132718Skanstruct walk_type_data
1418132718Skan{
1419132718Skan  process_field_fn process_field;
1420132718Skan  const void *cookie;
1421132718Skan  outf_p of;
1422132718Skan  options_p opt;
1423132718Skan  const char *val;
1424132718Skan  const char *prev_val[4];
1425132718Skan  int indent;
1426132718Skan  int counter;
1427132718Skan  struct fileloc *line;
1428132718Skan  lang_bitmap bitmap;
1429132718Skan  type_p *param;
1430132718Skan  int used_length;
1431132718Skan  type_p orig_s;
1432132718Skan  const char *reorder_fn;
1433169689Skan  bool needs_cast_p;
1434169689Skan  bool fn_wants_lvalue;
1435132718Skan};
1436132718Skan
1437117395Skan/* Print a mangled name representing T to OF.  */
1438117395Skan
1439117395Skanstatic void
1440132718Skanoutput_mangled_typename (outf_p of, type_p t)
1441117395Skan{
1442117395Skan  if (t == NULL)
1443117395Skan    oprintf (of, "Z");
1444117395Skan  else switch (t->kind)
1445117395Skan    {
1446117395Skan    case TYPE_POINTER:
1447117395Skan      oprintf (of, "P");
1448117395Skan      output_mangled_typename (of, t->u.p);
1449117395Skan      break;
1450117395Skan    case TYPE_SCALAR:
1451117395Skan      oprintf (of, "I");
1452117395Skan      break;
1453117395Skan    case TYPE_STRING:
1454117395Skan      oprintf (of, "S");
1455117395Skan      break;
1456117395Skan    case TYPE_STRUCT:
1457117395Skan    case TYPE_UNION:
1458117395Skan    case TYPE_LANG_STRUCT:
1459117395Skan      oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag);
1460117395Skan      break;
1461117395Skan    case TYPE_PARAM_STRUCT:
1462117395Skan      {
1463117395Skan	int i;
1464117395Skan	for (i = 0; i < NUM_PARAM; i++)
1465117395Skan	  if (t->u.param_struct.param[i] != NULL)
1466117395Skan	    output_mangled_typename (of, t->u.param_struct.param[i]);
1467132718Skan	output_mangled_typename (of, t->u.param_struct.stru);
1468117395Skan      }
1469117395Skan      break;
1470117395Skan    case TYPE_ARRAY:
1471169689Skan      gcc_unreachable ();
1472117395Skan    }
1473117395Skan}
1474117395Skan
1475132718Skan/* Print PARAM to D->OF processing escapes.  D->VAL references the
1476132718Skan   current object, D->PREV_VAL the object containing the current
1477132718Skan   object, ONAME is the name of the option and D->LINE is used to
1478132718Skan   print error messages.  */
1479117395Skan
1480117395Skanstatic void
1481132718Skanoutput_escaped_param (struct walk_type_data *d, const char *param,
1482132718Skan		      const char *oname)
1483117395Skan{
1484132718Skan  const char *p;
1485117395Skan
1486132718Skan  for (p = param; *p; p++)
1487132718Skan    if (*p != '%')
1488132718Skan      oprintf (d->of, "%c", *p);
1489132718Skan    else switch (*++p)
1490132718Skan      {
1491132718Skan      case 'h':
1492132718Skan	oprintf (d->of, "(%s)", d->prev_val[2]);
1493132718Skan	break;
1494132718Skan      case '0':
1495132718Skan	oprintf (d->of, "(%s)", d->prev_val[0]);
1496132718Skan	break;
1497132718Skan      case '1':
1498132718Skan	oprintf (d->of, "(%s)", d->prev_val[1]);
1499132718Skan	break;
1500132718Skan      case 'a':
1501117395Skan	{
1502132718Skan	  const char *pp = d->val + strlen (d->val);
1503132718Skan	  while (pp[-1] == ']')
1504132718Skan	    while (*pp != '[')
1505132718Skan	      pp--;
1506132718Skan	  oprintf (d->of, "%s", pp);
1507117395Skan	}
1508132718Skan	break;
1509132718Skan      default:
1510132718Skan	error_at_line (d->line, "`%s' option contains bad escape %c%c",
1511132718Skan		       oname, '%', *p);
1512132718Skan      }
1513132718Skan}
1514117395Skan
1515132718Skan/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
1516132718Skan   which is of type T.  Write code to D->OF to constrain execution (at
1517132718Skan   the point that D->PROCESS_FIELD is called) to the appropriate
1518132718Skan   cases.  Call D->PROCESS_FIELD on subobjects before calling it on
1519132718Skan   pointers to those objects.  D->PREV_VAL lists the objects
1520132718Skan   containing the current object, D->OPT is a list of options to
1521132718Skan   apply, D->INDENT is the current indentation level, D->LINE is used
1522132718Skan   to print error messages, D->BITMAP indicates which languages to
1523132718Skan   print the structure for, and D->PARAM is the current parameter
1524132718Skan   (from an enclosing param_is option).  */
1525132718Skan
1526132718Skanstatic void
1527132718Skanwalk_type (type_p t, struct walk_type_data *d)
1528132718Skan{
1529132718Skan  const char *length = NULL;
1530132718Skan  const char *desc = NULL;
1531132718Skan  int maybe_undef_p = 0;
1532132718Skan  int use_param_num = -1;
1533132718Skan  int use_params_p = 0;
1534132718Skan  options_p oo;
1535169689Skan  const struct nested_ptr_data *nested_ptr_d = NULL;
1536132718Skan
1537169689Skan  d->needs_cast_p = false;
1538132718Skan  for (oo = d->opt; oo; oo = oo->next)
1539132718Skan    if (strcmp (oo->name, "length") == 0)
1540169689Skan      length = oo->info;
1541132718Skan    else if (strcmp (oo->name, "maybe_undef") == 0)
1542132718Skan      maybe_undef_p = 1;
1543132718Skan    else if (strncmp (oo->name, "use_param", 9) == 0
1544132718Skan	     && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1545132718Skan      use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
1546132718Skan    else if (strcmp (oo->name, "use_params") == 0)
1547132718Skan      use_params_p = 1;
1548132718Skan    else if (strcmp (oo->name, "desc") == 0)
1549169689Skan      desc = oo->info;
1550169689Skan    else if (strcmp (oo->name, "nested_ptr") == 0)
1551169689Skan      nested_ptr_d = (const struct nested_ptr_data *) oo->info;
1552132718Skan    else if (strcmp (oo->name, "dot") == 0)
1553132718Skan      ;
1554132718Skan    else if (strcmp (oo->name, "tag") == 0)
1555132718Skan      ;
1556132718Skan    else if (strcmp (oo->name, "special") == 0)
1557132718Skan      ;
1558132718Skan    else if (strcmp (oo->name, "skip") == 0)
1559132718Skan      ;
1560132718Skan    else if (strcmp (oo->name, "default") == 0)
1561132718Skan      ;
1562132718Skan    else if (strcmp (oo->name, "descbits") == 0)
1563132718Skan      ;
1564132718Skan    else if (strcmp (oo->name, "param_is") == 0)
1565132718Skan      ;
1566132718Skan    else if (strncmp (oo->name, "param", 5) == 0
1567132718Skan	     && ISDIGIT (oo->name[5])
1568132718Skan	     && strcmp (oo->name + 6, "_is") == 0)
1569132718Skan      ;
1570132718Skan    else if (strcmp (oo->name, "chain_next") == 0)
1571132718Skan      ;
1572132718Skan    else if (strcmp (oo->name, "chain_prev") == 0)
1573132718Skan      ;
1574132718Skan    else if (strcmp (oo->name, "reorder") == 0)
1575132718Skan      ;
1576132718Skan    else
1577132718Skan      error_at_line (d->line, "unknown option `%s'\n", oo->name);
1578132718Skan
1579132718Skan  if (d->used_length)
1580132718Skan    length = NULL;
1581132718Skan
1582132718Skan  if (use_params_p)
1583117395Skan    {
1584132718Skan      int pointer_p = t->kind == TYPE_POINTER;
1585117395Skan
1586132718Skan      if (pointer_p)
1587132718Skan	t = t->u.p;
1588132718Skan      if (! UNION_OR_STRUCT_P (t))
1589132718Skan	error_at_line (d->line, "`use_params' option on unimplemented type");
1590132718Skan      else
1591132718Skan	t = find_param_structure (t, d->param);
1592132718Skan      if (pointer_p)
1593132718Skan	t = create_pointer (t);
1594132718Skan    }
1595117395Skan
1596132718Skan  if (use_param_num != -1)
1597132718Skan    {
1598132718Skan      if (d->param != NULL && d->param[use_param_num] != NULL)
1599117395Skan	{
1600132718Skan	  type_p nt = d->param[use_param_num];
1601117395Skan
1602132718Skan	  if (t->kind == TYPE_ARRAY)
1603132718Skan	    nt = create_array (nt, t->u.a.len);
1604132718Skan	  else if (length != NULL && t->kind == TYPE_POINTER)
1605132718Skan	    nt = create_pointer (nt);
1606132718Skan	  d->needs_cast_p = (t->kind != TYPE_POINTER
1607132718Skan			     && (nt->kind == TYPE_POINTER
1608132718Skan				 || nt->kind == TYPE_STRING));
1609132718Skan	  t = nt;
1610117395Skan	}
1611132718Skan      else
1612132718Skan	error_at_line (d->line, "no parameter defined for `%s'",
1613132718Skan		       d->val);
1614132718Skan    }
1615117395Skan
1616132718Skan  if (maybe_undef_p
1617132718Skan      && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
1618132718Skan    {
1619132718Skan      error_at_line (d->line,
1620132718Skan		     "field `%s' has invalid option `maybe_undef_p'\n",
1621132718Skan		     d->val);
1622132718Skan      return;
1623132718Skan    }
1624117395Skan
1625132718Skan  switch (t->kind)
1626132718Skan    {
1627132718Skan    case TYPE_SCALAR:
1628132718Skan    case TYPE_STRING:
1629132718Skan      d->process_field (t, d);
1630132718Skan      break;
1631117395Skan
1632132718Skan    case TYPE_POINTER:
1633132718Skan      {
1634132718Skan	if (maybe_undef_p
1635132718Skan	    && t->u.p->u.s.line.file == NULL)
1636132718Skan	  {
1637169689Skan	    oprintf (d->of, "%*sgcc_assert (!%s);\n", d->indent, "", d->val);
1638132718Skan	    break;
1639132718Skan	  }
1640117395Skan
1641132718Skan	if (! length)
1642117395Skan	  {
1643132718Skan	    if (! UNION_OR_STRUCT_P (t->u.p)
1644132718Skan		&& t->u.p->kind != TYPE_PARAM_STRUCT)
1645117395Skan	      {
1646132718Skan		error_at_line (d->line,
1647132718Skan			       "field `%s' is pointer to unimplemented type",
1648132718Skan			       d->val);
1649117395Skan		break;
1650117395Skan	      }
1651132718Skan
1652169689Skan	    if (nested_ptr_d)
1653169689Skan	      {
1654169689Skan		const char *oldprevval2 = d->prev_val[2];
1655169689Skan
1656169689Skan		if (! UNION_OR_STRUCT_P (nested_ptr_d->type))
1657169689Skan		  {
1658169689Skan		    error_at_line (d->line,
1659169689Skan				   "field `%s' has invalid "
1660169689Skan				   "option `nested_ptr'\n",
1661169689Skan				   d->val);
1662169689Skan		    return;
1663169689Skan		  }
1664169689Skan
1665169689Skan		d->prev_val[2] = d->val;
1666169689Skan		oprintf (d->of, "%*s{\n", d->indent, "");
1667169689Skan		d->indent += 2;
1668169689Skan		d->val = xasprintf ("x%d", d->counter++);
1669169689Skan		oprintf (d->of, "%*s%s %s * %s%s =\n", d->indent, "",
1670169689Skan			 (nested_ptr_d->type->kind == TYPE_UNION
1671169689Skan			  ? "union" : "struct"),
1672169689Skan			 nested_ptr_d->type->u.s.tag,
1673169689Skan			 d->fn_wants_lvalue ? "" : "const ",
1674169689Skan			 d->val);
1675169689Skan		oprintf (d->of, "%*s", d->indent + 2, "");
1676169689Skan		output_escaped_param (d, nested_ptr_d->convert_from,
1677169689Skan				      "nested_ptr");
1678169689Skan		oprintf (d->of, ";\n");
1679169689Skan
1680169689Skan		d->process_field (nested_ptr_d->type, d);
1681169689Skan
1682169689Skan		if (d->fn_wants_lvalue)
1683169689Skan		  {
1684169689Skan		    oprintf (d->of, "%*s%s = ", d->indent, "",
1685169689Skan			     d->prev_val[2]);
1686169689Skan		    d->prev_val[2] = d->val;
1687169689Skan		    output_escaped_param (d, nested_ptr_d->convert_to,
1688169689Skan					  "nested_ptr");
1689169689Skan		    oprintf (d->of, ";\n");
1690169689Skan		  }
1691169689Skan
1692169689Skan		d->indent -= 2;
1693169689Skan		oprintf (d->of, "%*s}\n", d->indent, "");
1694169689Skan		d->val = d->prev_val[2];
1695169689Skan		d->prev_val[2] = oldprevval2;
1696169689Skan	      }
1697169689Skan	    else
1698169689Skan	      d->process_field (t->u.p, d);
1699117395Skan	  }
1700132718Skan	else
1701117395Skan	  {
1702132718Skan	    int loopcounter = d->counter++;
1703132718Skan	    const char *oldval = d->val;
1704132718Skan	    const char *oldprevval3 = d->prev_val[3];
1705117395Skan	    char *newval;
1706117395Skan
1707132718Skan	    oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
1708132718Skan	    d->indent += 2;
1709132718Skan	    oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1710169689Skan	    oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "",
1711132718Skan		     loopcounter, loopcounter);
1712132718Skan	    output_escaped_param (d, length, "length");
1713132718Skan	    oprintf (d->of, "); i%d++) {\n", loopcounter);
1714132718Skan	    d->indent += 2;
1715132718Skan	    d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1716132718Skan	    d->used_length = 1;
1717132718Skan	    d->prev_val[3] = oldval;
1718132718Skan	    walk_type (t->u.p, d);
1719117395Skan	    free (newval);
1720132718Skan	    d->val = oldval;
1721132718Skan	    d->prev_val[3] = oldprevval3;
1722132718Skan	    d->used_length = 0;
1723132718Skan	    d->indent -= 2;
1724132718Skan	    oprintf (d->of, "%*s}\n", d->indent, "");
1725132718Skan	    d->process_field(t, d);
1726132718Skan	    d->indent -= 2;
1727132718Skan	    oprintf (d->of, "%*s}\n", d->indent, "");
1728117395Skan	  }
1729132718Skan      }
1730132718Skan      break;
1731117395Skan
1732132718Skan    case TYPE_ARRAY:
1733132718Skan      {
1734132718Skan	int loopcounter = d->counter++;
1735132718Skan	const char *oldval = d->val;
1736132718Skan	char *newval;
1737132718Skan
1738132718Skan	/* If it's an array of scalars, we optimize by not generating
1739132718Skan	   any code.  */
1740132718Skan	if (t->u.a.p->kind == TYPE_SCALAR)
1741117395Skan	  break;
1742117395Skan
1743132718Skan	oprintf (d->of, "%*s{\n", d->indent, "");
1744132718Skan	d->indent += 2;
1745132718Skan	oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1746169689Skan	oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "",
1747132718Skan		 loopcounter, loopcounter);
1748132718Skan	if (length)
1749132718Skan	  output_escaped_param (d, length, "length");
1750132718Skan	else
1751132718Skan	  oprintf (d->of, "%s", t->u.a.len);
1752132718Skan	oprintf (d->of, "); i%d++) {\n", loopcounter);
1753132718Skan	d->indent += 2;
1754132718Skan	d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1755132718Skan	d->used_length = 1;
1756132718Skan	walk_type (t->u.a.p, d);
1757132718Skan	free (newval);
1758132718Skan	d->used_length = 0;
1759132718Skan	d->val = oldval;
1760132718Skan	d->indent -= 2;
1761132718Skan	oprintf (d->of, "%*s}\n", d->indent, "");
1762132718Skan	d->indent -= 2;
1763132718Skan	oprintf (d->of, "%*s}\n", d->indent, "");
1764132718Skan      }
1765132718Skan      break;
1766132718Skan
1767132718Skan    case TYPE_STRUCT:
1768132718Skan    case TYPE_UNION:
1769132718Skan      {
1770132718Skan	pair_p f;
1771132718Skan	const char *oldval = d->val;
1772132718Skan	const char *oldprevval1 = d->prev_val[1];
1773132718Skan	const char *oldprevval2 = d->prev_val[2];
1774132718Skan	const int union_p = t->kind == TYPE_UNION;
1775132718Skan	int seen_default_p = 0;
1776132718Skan	options_p o;
1777132718Skan
1778132718Skan	if (! t->u.s.line.file)
1779132718Skan	  error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
1780132718Skan
1781132718Skan	if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
1782117395Skan	  {
1783132718Skan	    error_at_line (d->line,
1784132718Skan			   "structure `%s' defined for mismatching languages",
1785132718Skan			   t->u.s.tag);
1786132718Skan	    error_at_line (&t->u.s.line, "one structure defined here");
1787132718Skan	  }
1788117395Skan
1789132718Skan	/* Some things may also be defined in the structure's options.  */
1790132718Skan	for (o = t->u.s.opt; o; o = o->next)
1791132718Skan	  if (! desc && strcmp (o->name, "desc") == 0)
1792169689Skan	    desc = o->info;
1793117395Skan
1794132718Skan	d->prev_val[2] = oldval;
1795132718Skan	d->prev_val[1] = oldprevval2;
1796132718Skan	if (union_p)
1797132718Skan	  {
1798132718Skan	    if (desc == NULL)
1799117395Skan	      {
1800132718Skan		error_at_line (d->line, "missing `desc' option for union `%s'",
1801132718Skan			       t->u.s.tag);
1802132718Skan		desc = "1";
1803117395Skan	      }
1804132718Skan	    oprintf (d->of, "%*sswitch (", d->indent, "");
1805132718Skan	    output_escaped_param (d, desc, "desc");
1806132718Skan	    oprintf (d->of, ")\n");
1807132718Skan	    d->indent += 2;
1808132718Skan	    oprintf (d->of, "%*s{\n", d->indent, "");
1809132718Skan	  }
1810132718Skan	for (f = t->u.s.fields; f; f = f->next)
1811132718Skan	  {
1812132718Skan	    options_p oo;
1813132718Skan	    const char *dot = ".";
1814132718Skan	    const char *tagid = NULL;
1815132718Skan	    int skip_p = 0;
1816132718Skan	    int default_p = 0;
1817132718Skan	    int use_param_p = 0;
1818132718Skan	    char *newval;
1819132718Skan
1820132718Skan	    d->reorder_fn = NULL;
1821132718Skan	    for (oo = f->opt; oo; oo = oo->next)
1822132718Skan	      if (strcmp (oo->name, "dot") == 0)
1823169689Skan		dot = oo->info;
1824132718Skan	      else if (strcmp (oo->name, "tag") == 0)
1825169689Skan		tagid = oo->info;
1826132718Skan	      else if (strcmp (oo->name, "skip") == 0)
1827132718Skan		skip_p = 1;
1828132718Skan	      else if (strcmp (oo->name, "default") == 0)
1829132718Skan		default_p = 1;
1830132718Skan	      else if (strcmp (oo->name, "reorder") == 0)
1831169689Skan		d->reorder_fn = oo->info;
1832132718Skan	      else if (strncmp (oo->name, "use_param", 9) == 0
1833132718Skan		       && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1834132718Skan		use_param_p = 1;
1835132718Skan
1836132718Skan	    if (skip_p)
1837132718Skan	      continue;
1838132718Skan
1839132718Skan	    if (union_p && tagid)
1840117395Skan	      {
1841132718Skan		oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
1842132718Skan		d->indent += 2;
1843117395Skan	      }
1844132718Skan	    else if (union_p && default_p)
1845117395Skan	      {
1846132718Skan		oprintf (d->of, "%*sdefault:\n", d->indent, "");
1847132718Skan		d->indent += 2;
1848132718Skan		seen_default_p = 1;
1849117395Skan	      }
1850132718Skan	    else if (! union_p && (default_p || tagid))
1851132718Skan	      error_at_line (d->line,
1852132718Skan			     "can't use `%s' outside a union on field `%s'",
1853132718Skan			     default_p ? "default" : "tag", f->name);
1854132718Skan	    else if (union_p && ! (default_p || tagid)
1855132718Skan		     && f->type->kind == TYPE_SCALAR)
1856117395Skan	      {
1857132718Skan		fprintf (stderr,
1858132718Skan	"%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
1859132718Skan			 d->line->file, d->line->line, f->name);
1860132718Skan		continue;
1861117395Skan	      }
1862132718Skan	    else if (union_p && ! (default_p || tagid))
1863132718Skan	      error_at_line (d->line,
1864132718Skan			     "field `%s' is missing `tag' or `default' option",
1865132718Skan			     f->name);
1866132718Skan
1867132718Skan	    d->line = &f->line;
1868132718Skan	    d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
1869132718Skan	    d->opt = f->opt;
1870169689Skan	    d->used_length = false;
1871132718Skan
1872132718Skan	    if (union_p && use_param_p && d->param == NULL)
1873169689Skan	      oprintf (d->of, "%*sgcc_unreachable ();\n", d->indent, "");
1874117395Skan	    else
1875132718Skan	      walk_type (f->type, d);
1876132718Skan
1877132718Skan	    free (newval);
1878132718Skan
1879132718Skan	    if (union_p)
1880117395Skan	      {
1881132718Skan		oprintf (d->of, "%*sbreak;\n", d->indent, "");
1882132718Skan		d->indent -= 2;
1883117395Skan	      }
1884132718Skan	  }
1885132718Skan	d->reorder_fn = NULL;
1886117395Skan
1887132718Skan	d->val = oldval;
1888132718Skan	d->prev_val[1] = oldprevval1;
1889132718Skan	d->prev_val[2] = oldprevval2;
1890132718Skan
1891132718Skan	if (union_p && ! seen_default_p)
1892132718Skan	  {
1893132718Skan	    oprintf (d->of, "%*sdefault:\n", d->indent, "");
1894132718Skan	    oprintf (d->of, "%*s  break;\n", d->indent, "");
1895117395Skan	  }
1896132718Skan	if (union_p)
1897132718Skan	  {
1898132718Skan	    oprintf (d->of, "%*s}\n", d->indent, "");
1899132718Skan	    d->indent -= 2;
1900132718Skan	  }
1901132718Skan      }
1902132718Skan      break;
1903117395Skan
1904132718Skan    case TYPE_LANG_STRUCT:
1905132718Skan      {
1906132718Skan	type_p nt;
1907132718Skan	for (nt = t->u.s.lang_struct; nt; nt = nt->next)
1908132718Skan	  if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
1909132718Skan	    break;
1910132718Skan	if (nt == NULL)
1911132718Skan	  error_at_line (d->line, "structure `%s' differs between languages",
1912132718Skan			 t->u.s.tag);
1913132718Skan	else
1914132718Skan	  walk_type (nt, d);
1915132718Skan      }
1916132718Skan      break;
1917132718Skan
1918132718Skan    case TYPE_PARAM_STRUCT:
1919132718Skan      {
1920132718Skan	type_p *oldparam = d->param;
1921132718Skan
1922132718Skan	d->param = t->u.param_struct.param;
1923132718Skan	walk_type (t->u.param_struct.stru, d);
1924132718Skan	d->param = oldparam;
1925132718Skan      }
1926132718Skan      break;
1927132718Skan
1928132718Skan    default:
1929169689Skan      gcc_unreachable ();
1930117395Skan    }
1931132718Skan}
1932132718Skan
1933132718Skan/* process_field routine for marking routines.  */
1934132718Skan
1935132718Skanstatic void
1936132718Skanwrite_types_process_field (type_p f, const struct walk_type_data *d)
1937132718Skan{
1938132718Skan  const struct write_types_data *wtd;
1939132718Skan  const char *cast = d->needs_cast_p ? "(void *)" : "";
1940132718Skan  wtd = (const struct write_types_data *) d->cookie;
1941132718Skan
1942132718Skan  switch (f->kind)
1943117395Skan    {
1944132718Skan    case TYPE_POINTER:
1945132718Skan      oprintf (d->of, "%*s%s (%s%s", d->indent, "",
1946132718Skan	       wtd->subfield_marker_routine, cast, d->val);
1947132718Skan      if (wtd->param_prefix)
1948117395Skan	{
1949132718Skan	  oprintf (d->of, ", %s", d->prev_val[3]);
1950132718Skan	  if (d->orig_s)
1951132718Skan	    {
1952132718Skan	      oprintf (d->of, ", gt_%s_", wtd->param_prefix);
1953132718Skan	      output_mangled_typename (d->of, d->orig_s);
1954132718Skan	    }
1955132718Skan	  else
1956132718Skan	    oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
1957169689Skan
1958169689Skan	  if (f->u.p->kind == TYPE_PARAM_STRUCT
1959169689Skan	      && f->u.p->u.s.line.file != NULL)
1960169689Skan	    {
1961169689Skan	      oprintf (d->of, ", gt_e_");
1962169689Skan	      output_mangled_typename (d->of, f);
1963169689Skan	    }
1964169689Skan	  else if (UNION_OR_STRUCT_P (f)
1965169689Skan		   && f->u.p->u.s.line.file != NULL)
1966169689Skan	    {
1967169689Skan	      oprintf (d->of, ", gt_ggc_e_");
1968169689Skan	      output_mangled_typename (d->of, f);
1969169689Skan	    }
1970169689Skan	  else
1971169689Skan	    oprintf (d->of, ", gt_types_enum_last");
1972117395Skan	}
1973132718Skan      oprintf (d->of, ");\n");
1974132718Skan      if (d->reorder_fn && wtd->reorder_note_routine)
1975132718Skan	oprintf (d->of, "%*s%s (%s%s, %s, %s);\n", d->indent, "",
1976132718Skan		 wtd->reorder_note_routine, cast, d->val,
1977132718Skan		 d->prev_val[3], d->reorder_fn);
1978132718Skan      break;
1979132718Skan
1980132718Skan    case TYPE_STRING:
1981132718Skan      if (wtd->param_prefix == NULL)
1982132718Skan	break;
1983132718Skan
1984132718Skan    case TYPE_STRUCT:
1985132718Skan    case TYPE_UNION:
1986132718Skan    case TYPE_LANG_STRUCT:
1987132718Skan    case TYPE_PARAM_STRUCT:
1988132718Skan      oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
1989132718Skan      output_mangled_typename (d->of, f);
1990132718Skan      oprintf (d->of, " (%s%s);\n", cast, d->val);
1991132718Skan      if (d->reorder_fn && wtd->reorder_note_routine)
1992132718Skan	oprintf (d->of, "%*s%s (%s%s, %s%s, %s);\n", d->indent, "",
1993132718Skan		 wtd->reorder_note_routine, cast, d->val, cast, d->val,
1994132718Skan		 d->reorder_fn);
1995132718Skan      break;
1996132718Skan
1997132718Skan    case TYPE_SCALAR:
1998132718Skan      break;
1999132718Skan
2000132718Skan    default:
2001169689Skan      gcc_unreachable ();
2002117395Skan    }
2003117395Skan}
2004117395Skan
2005169689Skan/* A subroutine of write_func_for_structure.  Write the enum tag for S.  */
2006169689Skan
2007169689Skanstatic void
2008169689Skanoutput_type_enum (outf_p of, type_p s)
2009169689Skan{
2010169689Skan  if (s->kind == TYPE_PARAM_STRUCT && s->u.s.line.file != NULL)
2011169689Skan    {
2012169689Skan      oprintf (of, ", gt_e_");
2013169689Skan      output_mangled_typename (of, s);
2014169689Skan    }
2015169689Skan  else if (UNION_OR_STRUCT_P (s) && s->u.s.line.file != NULL)
2016169689Skan    {
2017169689Skan      oprintf (of, ", gt_ggc_e_");
2018169689Skan      output_mangled_typename (of, s);
2019169689Skan    }
2020169689Skan  else
2021169689Skan    oprintf (of, ", gt_types_enum_last");
2022169689Skan}
2023169689Skan
2024132718Skan/* For S, a structure that's part of ORIG_S, and using parameters
2025132718Skan   PARAM, write out a routine that:
2026132718Skan   - Takes a parameter, a void * but actually of type *S
2027132718Skan   - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
2028132718Skan     field of S or its substructures and (in some cases) things
2029132718Skan     that are pointed to by S.
2030132718Skan*/
2031117395Skan
2032117395Skanstatic void
2033169689Skanwrite_func_for_structure (type_p orig_s, type_p s, type_p *param,
2034169689Skan			  const struct write_types_data *wtd)
2035117395Skan{
2036117395Skan  const char *fn = s->u.s.line.file;
2037117395Skan  int i;
2038117395Skan  const char *chain_next = NULL;
2039117395Skan  const char *chain_prev = NULL;
2040117395Skan  options_p opt;
2041132718Skan  struct walk_type_data d;
2042132718Skan
2043117395Skan  /* This is a hack, and not the good kind either.  */
2044117395Skan  for (i = NUM_PARAM - 1; i >= 0; i--)
2045132718Skan    if (param && param[i] && param[i]->kind == TYPE_POINTER
2046117395Skan	&& UNION_OR_STRUCT_P (param[i]->u.p))
2047117395Skan      fn = param[i]->u.p->u.s.line.file;
2048132718Skan
2049132718Skan  memset (&d, 0, sizeof (d));
2050132718Skan  d.of = get_output_file_with_visibility (fn);
2051132718Skan
2052117395Skan  for (opt = s->u.s.opt; opt; opt = opt->next)
2053117395Skan    if (strcmp (opt->name, "chain_next") == 0)
2054169689Skan      chain_next = opt->info;
2055117395Skan    else if (strcmp (opt->name, "chain_prev") == 0)
2056169689Skan      chain_prev = opt->info;
2057117395Skan
2058117395Skan  if (chain_prev != NULL && chain_next == NULL)
2059117395Skan    error_at_line (&s->u.s.line, "chain_prev without chain_next");
2060117395Skan
2061132718Skan  d.process_field = write_types_process_field;
2062132718Skan  d.cookie = wtd;
2063132718Skan  d.orig_s = orig_s;
2064132718Skan  d.opt = s->u.s.opt;
2065132718Skan  d.line = &s->u.s.line;
2066132718Skan  d.bitmap = s->u.s.bitmap;
2067132718Skan  d.param = param;
2068132718Skan  d.prev_val[0] = "*x";
2069132718Skan  d.prev_val[1] = "not valid postage";  /* Guarantee an error.  */
2070132718Skan  d.prev_val[3] = "x";
2071132718Skan  d.val = "(*x)";
2072132718Skan
2073132718Skan  oprintf (d.of, "\n");
2074132718Skan  oprintf (d.of, "void\n");
2075117395Skan  if (param == NULL)
2076132718Skan    oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
2077117395Skan  else
2078117395Skan    {
2079132718Skan      oprintf (d.of, "gt_%s_", wtd->prefix);
2080132718Skan      output_mangled_typename (d.of, orig_s);
2081117395Skan    }
2082132718Skan  oprintf (d.of, " (void *x_p)\n");
2083132718Skan  oprintf (d.of, "{\n");
2084132718Skan  oprintf (d.of, "  %s %s * %sx = (%s %s *)x_p;\n",
2085117395Skan	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2086117395Skan	   chain_next == NULL ? "const " : "",
2087117395Skan	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2088117395Skan  if (chain_next != NULL)
2089132718Skan    oprintf (d.of, "  %s %s * xlimit = x;\n",
2090117395Skan	     s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2091117395Skan  if (chain_next == NULL)
2092132718Skan    {
2093132718Skan      oprintf (d.of, "  if (%s (x", wtd->marker_routine);
2094132718Skan      if (wtd->param_prefix)
2095132718Skan	{
2096132718Skan	  oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
2097132718Skan	  output_mangled_typename (d.of, orig_s);
2098169689Skan	  output_type_enum (d.of, orig_s);
2099132718Skan	}
2100132718Skan      oprintf (d.of, "))\n");
2101132718Skan    }
2102117395Skan  else
2103117395Skan    {
2104132718Skan      oprintf (d.of, "  while (%s (xlimit", wtd->marker_routine);
2105132718Skan      if (wtd->param_prefix)
2106132718Skan	{
2107132718Skan	  oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
2108132718Skan	  output_mangled_typename (d.of, orig_s);
2109169689Skan	  output_type_enum (d.of, orig_s);
2110132718Skan	}
2111132718Skan      oprintf (d.of, "))\n");
2112132718Skan      oprintf (d.of, "   xlimit = (");
2113132718Skan      d.prev_val[2] = "*xlimit";
2114132718Skan      output_escaped_param (&d, chain_next, "chain_next");
2115132718Skan      oprintf (d.of, ");\n");
2116117395Skan      if (chain_prev != NULL)
2117117395Skan	{
2118132718Skan	  oprintf (d.of, "  if (x != xlimit)\n");
2119132718Skan	  oprintf (d.of, "    for (;;)\n");
2120132718Skan	  oprintf (d.of, "      {\n");
2121132718Skan	  oprintf (d.of, "        %s %s * const xprev = (",
2122117395Skan		   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2123132718Skan
2124132718Skan	  d.prev_val[2] = "*x";
2125132718Skan	  output_escaped_param (&d, chain_prev, "chain_prev");
2126132718Skan	  oprintf (d.of, ");\n");
2127132718Skan	  oprintf (d.of, "        if (xprev == NULL) break;\n");
2128132718Skan	  oprintf (d.of, "        x = xprev;\n");
2129132718Skan	  oprintf (d.of, "        (void) %s (xprev",
2130132718Skan		   wtd->marker_routine);
2131132718Skan	  if (wtd->param_prefix)
2132132718Skan	    {
2133132718Skan	      oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
2134132718Skan	      output_mangled_typename (d.of, orig_s);
2135169689Skan	      output_type_enum (d.of, orig_s);
2136132718Skan	    }
2137132718Skan	  oprintf (d.of, ");\n");
2138132718Skan	  oprintf (d.of, "      }\n");
2139117395Skan	}
2140132718Skan      oprintf (d.of, "  while (x != xlimit)\n");
2141117395Skan    }
2142132718Skan  oprintf (d.of, "    {\n");
2143132718Skan
2144132718Skan  d.prev_val[2] = "*x";
2145132718Skan  d.indent = 6;
2146132718Skan  walk_type (s, &d);
2147132718Skan
2148117395Skan  if (chain_next != NULL)
2149117395Skan    {
2150132718Skan      oprintf (d.of, "      x = (");
2151132718Skan      output_escaped_param (&d, chain_next, "chain_next");
2152132718Skan      oprintf (d.of, ");\n");
2153117395Skan    }
2154117395Skan
2155132718Skan  oprintf (d.of, "    }\n");
2156132718Skan  oprintf (d.of, "}\n");
2157117395Skan}
2158117395Skan
2159117395Skan/* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
2160117395Skan
2161117395Skanstatic void
2162132718Skanwrite_types (type_p structures, type_p param_structs,
2163132718Skan	     const struct write_types_data *wtd)
2164117395Skan{
2165117395Skan  type_p s;
2166132718Skan
2167132718Skan  oprintf (header_file, "\n/* %s*/\n", wtd->comment);
2168117395Skan  for (s = structures; s; s = s->next)
2169117395Skan    if (s->gc_used == GC_POINTED_TO
2170117395Skan	|| s->gc_used == GC_MAYBE_POINTED_TO)
2171117395Skan      {
2172117395Skan	options_p opt;
2173132718Skan
2174117395Skan	if (s->gc_used == GC_MAYBE_POINTED_TO
2175117395Skan	    && s->u.s.line.file == NULL)
2176117395Skan	  continue;
2177117395Skan
2178132718Skan	oprintf (header_file, "#define gt_%s_", wtd->prefix);
2179117395Skan	output_mangled_typename (header_file, s);
2180117395Skan	oprintf (header_file, "(X) do { \\\n");
2181117395Skan	oprintf (header_file,
2182132718Skan		 "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
2183132718Skan		 s->u.s.tag);
2184117395Skan	oprintf (header_file,
2185117395Skan		 "  } while (0)\n");
2186132718Skan
2187117395Skan	for (opt = s->u.s.opt; opt; opt = opt->next)
2188117395Skan	  if (strcmp (opt->name, "ptr_alias") == 0)
2189117395Skan	    {
2190117395Skan	      type_p t = (type_p) opt->info;
2191132718Skan	      if (t->kind == TYPE_STRUCT
2192117395Skan		  || t->kind == TYPE_UNION
2193117395Skan		  || t->kind == TYPE_LANG_STRUCT)
2194117395Skan		oprintf (header_file,
2195132718Skan			 "#define gt_%sx_%s gt_%sx_%s\n",
2196132718Skan			 wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
2197117395Skan	      else
2198132718Skan		error_at_line (&s->u.s.line,
2199117395Skan			       "structure alias is not a structure");
2200117395Skan	      break;
2201117395Skan	    }
2202117395Skan	if (opt)
2203117395Skan	  continue;
2204117395Skan
2205117395Skan	/* Declare the marker procedure only once.  */
2206132718Skan	oprintf (header_file,
2207132718Skan		 "extern void gt_%sx_%s (void *);\n",
2208132718Skan		 wtd->prefix, s->u.s.tag);
2209132718Skan
2210117395Skan	if (s->u.s.line.file == NULL)
2211117395Skan	  {
2212132718Skan	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
2213117395Skan		     s->u.s.tag);
2214117395Skan	    continue;
2215117395Skan	  }
2216132718Skan
2217117395Skan	if (s->kind == TYPE_LANG_STRUCT)
2218117395Skan	  {
2219117395Skan	    type_p ss;
2220117395Skan	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2221132718Skan	      write_func_for_structure (s, ss, NULL, wtd);
2222117395Skan	  }
2223117395Skan	else
2224132718Skan	  write_func_for_structure (s, s, NULL, wtd);
2225117395Skan      }
2226117395Skan
2227117395Skan  for (s = param_structs; s; s = s->next)
2228117395Skan    if (s->gc_used == GC_POINTED_TO)
2229117395Skan      {
2230117395Skan	type_p * param = s->u.param_struct.param;
2231117395Skan	type_p stru = s->u.param_struct.stru;
2232117395Skan
2233117395Skan	/* Declare the marker procedure.  */
2234132718Skan	oprintf (header_file, "extern void gt_%s_", wtd->prefix);
2235117395Skan	output_mangled_typename (header_file, s);
2236132718Skan	oprintf (header_file, " (void *);\n");
2237132718Skan
2238117395Skan	if (stru->u.s.line.file == NULL)
2239117395Skan	  {
2240132718Skan	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
2241117395Skan		     s->u.s.tag);
2242117395Skan	    continue;
2243117395Skan	  }
2244132718Skan
2245117395Skan	if (stru->kind == TYPE_LANG_STRUCT)
2246117395Skan	  {
2247117395Skan	    type_p ss;
2248117395Skan	    for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2249132718Skan	      write_func_for_structure (s, ss, param, wtd);
2250117395Skan	  }
2251117395Skan	else
2252132718Skan	  write_func_for_structure (s, stru, param, wtd);
2253117395Skan      }
2254117395Skan}
2255117395Skan
2256132718Skanstatic const struct write_types_data ggc_wtd =
2257132718Skan{
2258132718Skan  "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
2259132718Skan  "GC marker procedures.  "
2260132718Skan};
2261132718Skan
2262132718Skanstatic const struct write_types_data pch_wtd =
2263132718Skan{
2264132718Skan  "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
2265132718Skan  "gt_pch_note_reorder",
2266132718Skan  "PCH type-walking procedures.  "
2267132718Skan};
2268132718Skan
2269132718Skan/* Write out the local pointer-walking routines.  */
2270132718Skan
2271132718Skan/* process_field routine for local pointer-walking.  */
2272132718Skan
2273132718Skanstatic void
2274132718Skanwrite_types_local_process_field (type_p f, const struct walk_type_data *d)
2275132718Skan{
2276132718Skan  switch (f->kind)
2277132718Skan    {
2278132718Skan    case TYPE_POINTER:
2279132718Skan    case TYPE_STRUCT:
2280132718Skan    case TYPE_UNION:
2281132718Skan    case TYPE_LANG_STRUCT:
2282132718Skan    case TYPE_PARAM_STRUCT:
2283132718Skan    case TYPE_STRING:
2284132718Skan      oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
2285132718Skan	       d->prev_val[3]);
2286132718Skan      oprintf (d->of, "%*s  op (&(%s), cookie);\n", d->indent, "", d->val);
2287132718Skan      break;
2288132718Skan
2289132718Skan    case TYPE_SCALAR:
2290132718Skan      break;
2291132718Skan
2292132718Skan    default:
2293169689Skan      gcc_unreachable ();
2294132718Skan    }
2295132718Skan}
2296132718Skan
2297132718Skan/* For S, a structure that's part of ORIG_S, and using parameters
2298132718Skan   PARAM, write out a routine that:
2299132718Skan   - Is of type gt_note_pointers
2300169689Skan   - Calls PROCESS_FIELD on each field of S or its substructures.
2301132718Skan*/
2302132718Skan
2303132718Skanstatic void
2304132718Skanwrite_local_func_for_structure (type_p orig_s, type_p s, type_p *param)
2305132718Skan{
2306132718Skan  const char *fn = s->u.s.line.file;
2307132718Skan  int i;
2308132718Skan  struct walk_type_data d;
2309132718Skan
2310132718Skan  /* This is a hack, and not the good kind either.  */
2311132718Skan  for (i = NUM_PARAM - 1; i >= 0; i--)
2312132718Skan    if (param && param[i] && param[i]->kind == TYPE_POINTER
2313132718Skan	&& UNION_OR_STRUCT_P (param[i]->u.p))
2314132718Skan      fn = param[i]->u.p->u.s.line.file;
2315132718Skan
2316132718Skan  memset (&d, 0, sizeof (d));
2317132718Skan  d.of = get_output_file_with_visibility (fn);
2318132718Skan
2319132718Skan  d.process_field = write_types_local_process_field;
2320132718Skan  d.opt = s->u.s.opt;
2321132718Skan  d.line = &s->u.s.line;
2322132718Skan  d.bitmap = s->u.s.bitmap;
2323132718Skan  d.param = param;
2324132718Skan  d.prev_val[0] = d.prev_val[2] = "*x";
2325132718Skan  d.prev_val[1] = "not valid postage";  /* Guarantee an error.  */
2326132718Skan  d.prev_val[3] = "x";
2327132718Skan  d.val = "(*x)";
2328169689Skan  d.fn_wants_lvalue = true;
2329132718Skan
2330132718Skan  oprintf (d.of, "\n");
2331132718Skan  oprintf (d.of, "void\n");
2332132718Skan  oprintf (d.of, "gt_pch_p_");
2333132718Skan  output_mangled_typename (d.of, orig_s);
2334169689Skan  oprintf (d.of, " (ATTRIBUTE_UNUSED void *this_obj,\n"
2335169689Skan	   "\tvoid *x_p,\n"
2336169689Skan	   "\tATTRIBUTE_UNUSED gt_pointer_operator op,\n"
2337169689Skan	   "\tATTRIBUTE_UNUSED void *cookie)\n");
2338132718Skan  oprintf (d.of, "{\n");
2339132718Skan  oprintf (d.of, "  %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
2340132718Skan	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2341132718Skan	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2342132718Skan  d.indent = 2;
2343132718Skan  walk_type (s, &d);
2344132718Skan  oprintf (d.of, "}\n");
2345132718Skan}
2346132718Skan
2347132718Skan/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS.  */
2348132718Skan
2349132718Skanstatic void
2350132718Skanwrite_local (type_p structures, type_p param_structs)
2351132718Skan{
2352132718Skan  type_p s;
2353132718Skan
2354132718Skan  oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
2355132718Skan  for (s = structures; s; s = s->next)
2356132718Skan    if (s->gc_used == GC_POINTED_TO
2357132718Skan	|| s->gc_used == GC_MAYBE_POINTED_TO)
2358132718Skan      {
2359132718Skan	options_p opt;
2360132718Skan
2361132718Skan	if (s->u.s.line.file == NULL)
2362132718Skan	  continue;
2363132718Skan
2364132718Skan	for (opt = s->u.s.opt; opt; opt = opt->next)
2365132718Skan	  if (strcmp (opt->name, "ptr_alias") == 0)
2366132718Skan	    {
2367132718Skan	      type_p t = (type_p) opt->info;
2368132718Skan	      if (t->kind == TYPE_STRUCT
2369132718Skan		  || t->kind == TYPE_UNION
2370132718Skan		  || t->kind == TYPE_LANG_STRUCT)
2371132718Skan		{
2372132718Skan		  oprintf (header_file, "#define gt_pch_p_");
2373132718Skan		  output_mangled_typename (header_file, s);
2374132718Skan		  oprintf (header_file, " gt_pch_p_");
2375132718Skan		  output_mangled_typename (header_file, t);
2376132718Skan		  oprintf (header_file, "\n");
2377132718Skan		}
2378132718Skan	      else
2379132718Skan		error_at_line (&s->u.s.line,
2380132718Skan			       "structure alias is not a structure");
2381132718Skan	      break;
2382132718Skan	    }
2383132718Skan	if (opt)
2384132718Skan	  continue;
2385132718Skan
2386132718Skan	/* Declare the marker procedure only once.  */
2387132718Skan	oprintf (header_file, "extern void gt_pch_p_");
2388132718Skan	output_mangled_typename (header_file, s);
2389132718Skan	oprintf (header_file,
2390132718Skan	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
2391132718Skan
2392132718Skan	if (s->kind == TYPE_LANG_STRUCT)
2393132718Skan	  {
2394132718Skan	    type_p ss;
2395132718Skan	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2396132718Skan	      write_local_func_for_structure (s, ss, NULL);
2397132718Skan	  }
2398132718Skan	else
2399132718Skan	  write_local_func_for_structure (s, s, NULL);
2400132718Skan      }
2401132718Skan
2402132718Skan  for (s = param_structs; s; s = s->next)
2403132718Skan    if (s->gc_used == GC_POINTED_TO)
2404132718Skan      {
2405132718Skan	type_p * param = s->u.param_struct.param;
2406132718Skan	type_p stru = s->u.param_struct.stru;
2407132718Skan
2408132718Skan	/* Declare the marker procedure.  */
2409132718Skan	oprintf (header_file, "extern void gt_pch_p_");
2410132718Skan	output_mangled_typename (header_file, s);
2411132718Skan	oprintf (header_file,
2412132718Skan	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
2413132718Skan
2414132718Skan	if (stru->u.s.line.file == NULL)
2415132718Skan	  {
2416132718Skan	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
2417132718Skan		     s->u.s.tag);
2418132718Skan	    continue;
2419132718Skan	  }
2420132718Skan
2421132718Skan	if (stru->kind == TYPE_LANG_STRUCT)
2422132718Skan	  {
2423132718Skan	    type_p ss;
2424132718Skan	    for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2425132718Skan	      write_local_func_for_structure (s, ss, param);
2426132718Skan	  }
2427132718Skan	else
2428132718Skan	  write_local_func_for_structure (s, stru, param);
2429132718Skan      }
2430132718Skan}
2431132718Skan
2432117395Skan/* Write out the 'enum' definition for gt_types_enum.  */
2433117395Skan
2434117395Skanstatic void
2435169689Skanwrite_enum_defn (type_p structures, type_p param_structs)
2436117395Skan{
2437117395Skan  type_p s;
2438132718Skan
2439117395Skan  oprintf (header_file, "\n/* Enumeration of types known.  */\n");
2440117395Skan  oprintf (header_file, "enum gt_types_enum {\n");
2441117395Skan  for (s = structures; s; s = s->next)
2442117395Skan    if (s->gc_used == GC_POINTED_TO
2443117395Skan	|| s->gc_used == GC_MAYBE_POINTED_TO)
2444117395Skan      {
2445117395Skan	if (s->gc_used == GC_MAYBE_POINTED_TO
2446117395Skan	    && s->u.s.line.file == NULL)
2447117395Skan	  continue;
2448117395Skan
2449117395Skan	oprintf (header_file, " gt_ggc_e_");
2450117395Skan	output_mangled_typename (header_file, s);
2451117395Skan	oprintf (header_file, ", \n");
2452117395Skan      }
2453117395Skan  for (s = param_structs; s; s = s->next)
2454117395Skan    if (s->gc_used == GC_POINTED_TO)
2455117395Skan      {
2456117395Skan	oprintf (header_file, " gt_e_");
2457117395Skan	output_mangled_typename (header_file, s);
2458117395Skan	oprintf (header_file, ", \n");
2459117395Skan      }
2460117395Skan  oprintf (header_file, " gt_types_enum_last\n");
2461117395Skan  oprintf (header_file, "};\n");
2462117395Skan}
2463117395Skan
2464132718Skan/* Might T contain any non-pointer elements?  */
2465117395Skan
2466132718Skanstatic int
2467132718Skancontains_scalar_p (type_p t)
2468132718Skan{
2469132718Skan  switch (t->kind)
2470132718Skan    {
2471132718Skan    case TYPE_STRING:
2472132718Skan    case TYPE_POINTER:
2473132718Skan      return 0;
2474132718Skan    case TYPE_ARRAY:
2475132718Skan      return contains_scalar_p (t->u.a.p);
2476132718Skan    default:
2477132718Skan      /* Could also check for structures that have no non-pointer
2478132718Skan	 fields, but there aren't enough of those to worry about.  */
2479132718Skan      return 1;
2480132718Skan    }
2481132718Skan}
2482132718Skan
2483117395Skan/* Mangle FN and print it to F.  */
2484117395Skan
2485117395Skanstatic void
2486132718Skanput_mangled_filename (outf_p f, const char *fn)
2487117395Skan{
2488117395Skan  const char *name = get_output_file_name (fn);
2489117395Skan  for (; *name != 0; name++)
2490117395Skan    if (ISALNUM (*name))
2491117395Skan      oprintf (f, "%c", *name);
2492117395Skan    else
2493117395Skan      oprintf (f, "%c", '_');
2494117395Skan}
2495117395Skan
2496117395Skan/* Finish off the currently-created root tables in FLP.  PFX, TNAME,
2497117395Skan   LASTNAME, and NAME are all strings to insert in various places in
2498117395Skan   the resulting code.  */
2499117395Skan
2500117395Skanstatic void
2501132718Skanfinish_root_table (struct flist *flp, const char *pfx, const char *lastname,
2502132718Skan		   const char *tname, const char *name)
2503117395Skan{
2504117395Skan  struct flist *fli2;
2505132718Skan
2506117395Skan  for (fli2 = flp; fli2; fli2 = fli2->next)
2507117395Skan    if (fli2->started_p)
2508117395Skan      {
2509117395Skan	oprintf (fli2->f, "  %s\n", lastname);
2510117395Skan	oprintf (fli2->f, "};\n\n");
2511117395Skan      }
2512117395Skan
2513117395Skan  for (fli2 = flp; fli2; fli2 = fli2->next)
2514117395Skan    if (fli2->started_p)
2515117395Skan      {
2516117395Skan	lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2517117395Skan	int fnum;
2518117395Skan
2519117395Skan	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2520117395Skan	  if (bitmap & 1)
2521117395Skan	    {
2522117395Skan	      oprintf (base_files[fnum],
2523132718Skan		       "extern const struct %s gt_%s_",
2524117395Skan		       tname, pfx);
2525117395Skan	      put_mangled_filename (base_files[fnum], fli2->name);
2526117395Skan	      oprintf (base_files[fnum], "[];\n");
2527117395Skan	    }
2528117395Skan      }
2529117395Skan
2530132718Skan  {
2531132718Skan    size_t fnum;
2532132718Skan    for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2533132718Skan      oprintf (base_files [fnum],
2534132718Skan	       "const struct %s * const %s[] = {\n",
2535132718Skan	       tname, name);
2536132718Skan  }
2537132718Skan
2538132718Skan
2539117395Skan  for (fli2 = flp; fli2; fli2 = fli2->next)
2540117395Skan    if (fli2->started_p)
2541117395Skan      {
2542117395Skan	lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2543117395Skan	int fnum;
2544117395Skan
2545117395Skan	fli2->started_p = 0;
2546117395Skan
2547117395Skan	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2548117395Skan	  if (bitmap & 1)
2549117395Skan	    {
2550132718Skan	      oprintf (base_files[fnum], "  gt_%s_", pfx);
2551117395Skan	      put_mangled_filename (base_files[fnum], fli2->name);
2552117395Skan	      oprintf (base_files[fnum], ",\n");
2553117395Skan	    }
2554117395Skan      }
2555117395Skan
2556117395Skan  {
2557132718Skan    size_t fnum;
2558132718Skan    for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2559132718Skan      {
2560132718Skan	oprintf (base_files[fnum], "  NULL\n");
2561132718Skan	oprintf (base_files[fnum], "};\n");
2562132718Skan      }
2563117395Skan  }
2564117395Skan}
2565117395Skan
2566117395Skan/* Write out to F the table entry and any marker routines needed to
2567117395Skan   mark NAME as TYPE.  The original variable is V, at LINE.
2568117395Skan   HAS_LENGTH is nonzero iff V was a variable-length array.  IF_MARKED
2569117395Skan   is nonzero iff we are building the root table for hash table caches.  */
2570117395Skan
2571117395Skanstatic void
2572132718Skanwrite_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
2573132718Skan	    struct fileloc *line, const char *if_marked)
2574117395Skan{
2575117395Skan  switch (type->kind)
2576117395Skan    {
2577117395Skan    case TYPE_STRUCT:
2578117395Skan      {
2579117395Skan	pair_p fld;
2580117395Skan	for (fld = type->u.s.fields; fld; fld = fld->next)
2581117395Skan	  {
2582117395Skan	    int skip_p = 0;
2583117395Skan	    const char *desc = NULL;
2584117395Skan	    options_p o;
2585132718Skan
2586117395Skan	    for (o = fld->opt; o; o = o->next)
2587117395Skan	      if (strcmp (o->name, "skip") == 0)
2588117395Skan		skip_p = 1;
2589117395Skan	      else if (strcmp (o->name, "desc") == 0)
2590169689Skan		desc = o->info;
2591117395Skan	      else
2592117395Skan		error_at_line (line,
2593117395Skan		       "field `%s' of global `%s' has unknown option `%s'",
2594117395Skan			       fld->name, name, o->name);
2595132718Skan
2596117395Skan	    if (skip_p)
2597117395Skan	      continue;
2598117395Skan	    else if (desc && fld->type->kind == TYPE_UNION)
2599117395Skan	      {
2600117395Skan		pair_p validf = NULL;
2601117395Skan		pair_p ufld;
2602132718Skan
2603117395Skan		for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
2604117395Skan		  {
2605117395Skan		    const char *tag = NULL;
2606117395Skan		    options_p oo;
2607132718Skan
2608117395Skan		    for (oo = ufld->opt; oo; oo = oo->next)
2609117395Skan		      if (strcmp (oo->name, "tag") == 0)
2610169689Skan			tag = oo->info;
2611117395Skan		    if (tag == NULL || strcmp (tag, desc) != 0)
2612117395Skan		      continue;
2613117395Skan		    if (validf != NULL)
2614132718Skan		      error_at_line (line,
2615117395Skan			   "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
2616117395Skan				     name, fld->name, validf->name,
2617117395Skan				     name, fld->name, ufld->name,
2618117395Skan				     tag);
2619117395Skan		    validf = ufld;
2620117395Skan		  }
2621117395Skan		if (validf != NULL)
2622117395Skan		  {
2623117395Skan		    char *newname;
2624132718Skan		    newname = xasprintf ("%s.%s.%s",
2625117395Skan					 name, fld->name, validf->name);
2626132718Skan		    write_root (f, v, validf->type, newname, 0, line,
2627132718Skan				if_marked);
2628117395Skan		    free (newname);
2629117395Skan		  }
2630117395Skan	      }
2631117395Skan	    else if (desc)
2632132718Skan	      error_at_line (line,
2633117395Skan		     "global `%s.%s' has `desc' option but is not union",
2634117395Skan			     name, fld->name);
2635117395Skan	    else
2636117395Skan	      {
2637117395Skan		char *newname;
2638117395Skan		newname = xasprintf ("%s.%s", name, fld->name);
2639132718Skan		write_root (f, v, fld->type, newname, 0, line, if_marked);
2640117395Skan		free (newname);
2641117395Skan	      }
2642117395Skan	  }
2643117395Skan      }
2644117395Skan      break;
2645117395Skan
2646117395Skan    case TYPE_ARRAY:
2647117395Skan      {
2648117395Skan	char *newname;
2649117395Skan	newname = xasprintf ("%s[0]", name);
2650132718Skan	write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
2651117395Skan	free (newname);
2652117395Skan      }
2653117395Skan      break;
2654132718Skan
2655117395Skan    case TYPE_POINTER:
2656117395Skan      {
2657117395Skan	type_p ap, tp;
2658132718Skan
2659117395Skan	oprintf (f, "  {\n");
2660117395Skan	oprintf (f, "    &%s,\n", name);
2661117395Skan	oprintf (f, "    1");
2662132718Skan
2663117395Skan	for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2664117395Skan	  if (ap->u.a.len[0])
2665117395Skan	    oprintf (f, " * (%s)", ap->u.a.len);
2666117395Skan	  else if (ap == v->type)
2667117395Skan	    oprintf (f, " * ARRAY_SIZE (%s)", v->name);
2668117395Skan	oprintf (f, ",\n");
2669117395Skan	oprintf (f, "    sizeof (%s", v->name);
2670117395Skan	for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2671117395Skan	  oprintf (f, "[0]");
2672117395Skan	oprintf (f, "),\n");
2673132718Skan
2674117395Skan	tp = type->u.p;
2675132718Skan
2676117395Skan	if (! has_length && UNION_OR_STRUCT_P (tp))
2677117395Skan	  {
2678132718Skan	    oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
2679132718Skan	    oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
2680117395Skan	  }
2681117395Skan	else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
2682117395Skan	  {
2683117395Skan	    oprintf (f, "    &gt_ggc_m_");
2684117395Skan	    output_mangled_typename (f, tp);
2685132718Skan	    oprintf (f, ",\n    &gt_pch_n_");
2686132718Skan	    output_mangled_typename (f, tp);
2687117395Skan	  }
2688117395Skan	else if (has_length
2689117395Skan		 && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
2690117395Skan	  {
2691132718Skan	    oprintf (f, "    &gt_ggc_ma_%s,\n", name);
2692132718Skan	    oprintf (f, "    &gt_pch_na_%s", name);
2693117395Skan	  }
2694117395Skan	else
2695117395Skan	  {
2696132718Skan	    error_at_line (line,
2697117395Skan			   "global `%s' is pointer to unimplemented type",
2698117395Skan			   name);
2699117395Skan	  }
2700117395Skan	if (if_marked)
2701117395Skan	  oprintf (f, ",\n    &%s", if_marked);
2702117395Skan	oprintf (f, "\n  },\n");
2703117395Skan      }
2704117395Skan      break;
2705117395Skan
2706117395Skan    case TYPE_STRING:
2707132718Skan      {
2708132718Skan	oprintf (f, "  {\n");
2709132718Skan	oprintf (f, "    &%s,\n", name);
2710132718Skan	oprintf (f, "    1, \n");
2711132718Skan	oprintf (f, "    sizeof (%s),\n", v->name);
2712132718Skan	oprintf (f, "    &gt_ggc_m_S,\n");
2713132718Skan	oprintf (f, "    (gt_pointer_walker) &gt_pch_n_S\n");
2714132718Skan	oprintf (f, "  },\n");
2715132718Skan      }
2716117395Skan      break;
2717132718Skan
2718132718Skan    case TYPE_SCALAR:
2719132718Skan      break;
2720132718Skan
2721117395Skan    default:
2722132718Skan      error_at_line (line,
2723117395Skan		     "global `%s' is unimplemented type",
2724117395Skan		     name);
2725117395Skan    }
2726117395Skan}
2727117395Skan
2728132718Skan/* This generates a routine to walk an array.  */
2729132718Skan
2730132718Skanstatic void
2731132718Skanwrite_array (outf_p f, pair_p v, const struct write_types_data *wtd)
2732132718Skan{
2733132718Skan  struct walk_type_data d;
2734132718Skan  char *prevval3;
2735132718Skan
2736132718Skan  memset (&d, 0, sizeof (d));
2737132718Skan  d.of = f;
2738132718Skan  d.cookie = wtd;
2739132718Skan  d.indent = 2;
2740132718Skan  d.line = &v->line;
2741132718Skan  d.opt = v->opt;
2742132718Skan  d.bitmap = get_base_file_bitmap (v->line.file);
2743132718Skan  d.param = NULL;
2744132718Skan
2745132718Skan  d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
2746132718Skan
2747132718Skan  if (wtd->param_prefix)
2748132718Skan    {
2749132718Skan      oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
2750132718Skan      oprintf (f,
2751132718Skan       "    (void *, void *, gt_pointer_operator, void *);\n");
2752169689Skan      oprintf (f, "static void gt_%sa_%s (ATTRIBUTE_UNUSED void *this_obj,\n",
2753132718Skan	       wtd->param_prefix, v->name);
2754169689Skan      oprintf (d.of,
2755169689Skan	       "      ATTRIBUTE_UNUSED void *x_p,\n"
2756169689Skan	       "      ATTRIBUTE_UNUSED gt_pointer_operator op,\n"
2757169689Skan	       "      ATTRIBUTE_UNUSED void * cookie)\n");
2758132718Skan      oprintf (d.of, "{\n");
2759132718Skan      d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2760132718Skan      d.process_field = write_types_local_process_field;
2761132718Skan      walk_type (v->type, &d);
2762132718Skan      oprintf (f, "}\n\n");
2763132718Skan    }
2764132718Skan
2765132718Skan  d.opt = v->opt;
2766132718Skan  oprintf (f, "static void gt_%sa_%s (void *);\n",
2767132718Skan	   wtd->prefix, v->name);
2768169689Skan  oprintf (f, "static void\ngt_%sa_%s (ATTRIBUTE_UNUSED void *x_p)\n",
2769132718Skan	   wtd->prefix, v->name);
2770132718Skan  oprintf (f, "{\n");
2771132718Skan  d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2772132718Skan  d.process_field = write_types_process_field;
2773132718Skan  walk_type (v->type, &d);
2774132718Skan  free (prevval3);
2775132718Skan  oprintf (f, "}\n\n");
2776132718Skan}
2777132718Skan
2778117395Skan/* Output a table describing the locations and types of VARIABLES.  */
2779117395Skan
2780117395Skanstatic void
2781132718Skanwrite_roots (pair_p variables)
2782117395Skan{
2783117395Skan  pair_p v;
2784117395Skan  struct flist *flp = NULL;
2785117395Skan
2786117395Skan  for (v = variables; v; v = v->next)
2787117395Skan    {
2788117395Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2789117395Skan      struct flist *fli;
2790117395Skan      const char *length = NULL;
2791117395Skan      int deletable_p = 0;
2792117395Skan      options_p o;
2793117395Skan
2794117395Skan      for (o = v->opt; o; o = o->next)
2795117395Skan	if (strcmp (o->name, "length") == 0)
2796169689Skan	  length = o->info;
2797117395Skan	else if (strcmp (o->name, "deletable") == 0)
2798117395Skan	  deletable_p = 1;
2799117395Skan	else if (strcmp (o->name, "param_is") == 0)
2800117395Skan	  ;
2801132718Skan	else if (strncmp (o->name, "param", 5) == 0
2802117395Skan		 && ISDIGIT (o->name[5])
2803117395Skan		 && strcmp (o->name + 6, "_is") == 0)
2804117395Skan	  ;
2805117395Skan	else if (strcmp (o->name, "if_marked") == 0)
2806117395Skan	  ;
2807117395Skan	else
2808132718Skan	  error_at_line (&v->line,
2809117395Skan			 "global `%s' has unknown option `%s'",
2810117395Skan			 v->name, o->name);
2811117395Skan
2812117395Skan      for (fli = flp; fli; fli = fli->next)
2813117395Skan	if (fli->f == f)
2814117395Skan	  break;
2815117395Skan      if (fli == NULL)
2816117395Skan	{
2817169689Skan	  fli = XNEW (struct flist);
2818117395Skan	  fli->f = f;
2819117395Skan	  fli->next = flp;
2820117395Skan	  fli->started_p = 0;
2821117395Skan	  fli->name = v->line.file;
2822117395Skan	  flp = fli;
2823117395Skan
2824117395Skan	  oprintf (f, "\n/* GC roots.  */\n\n");
2825117395Skan	}
2826117395Skan
2827117395Skan      if (! deletable_p
2828117395Skan	  && length
2829117395Skan	  && v->type->kind == TYPE_POINTER
2830117395Skan	  && (v->type->u.p->kind == TYPE_POINTER
2831117395Skan	      || v->type->u.p->kind == TYPE_STRUCT))
2832117395Skan	{
2833132718Skan	  write_array (f, v, &ggc_wtd);
2834132718Skan	  write_array (f, v, &pch_wtd);
2835117395Skan	}
2836117395Skan    }
2837117395Skan
2838117395Skan  for (v = variables; v; v = v->next)
2839117395Skan    {
2840117395Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2841117395Skan      struct flist *fli;
2842117395Skan      int skip_p = 0;
2843117395Skan      int length_p = 0;
2844117395Skan      options_p o;
2845132718Skan
2846117395Skan      for (o = v->opt; o; o = o->next)
2847117395Skan	if (strcmp (o->name, "length") == 0)
2848117395Skan	  length_p = 1;
2849117395Skan	else if (strcmp (o->name, "deletable") == 0
2850117395Skan		 || strcmp (o->name, "if_marked") == 0)
2851117395Skan	  skip_p = 1;
2852117395Skan
2853117395Skan      if (skip_p)
2854117395Skan	continue;
2855117395Skan
2856117395Skan      for (fli = flp; fli; fli = fli->next)
2857117395Skan	if (fli->f == f)
2858117395Skan	  break;
2859117395Skan      if (! fli->started_p)
2860117395Skan	{
2861117395Skan	  fli->started_p = 1;
2862117395Skan
2863117395Skan	  oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
2864117395Skan	  put_mangled_filename (f, v->line.file);
2865117395Skan	  oprintf (f, "[] = {\n");
2866117395Skan	}
2867117395Skan
2868132718Skan      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2869117395Skan    }
2870117395Skan
2871132718Skan  finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2872117395Skan		     "gt_ggc_rtab");
2873117395Skan
2874117395Skan  for (v = variables; v; v = v->next)
2875117395Skan    {
2876117395Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2877117395Skan      struct flist *fli;
2878117395Skan      int skip_p = 1;
2879117395Skan      options_p o;
2880117395Skan
2881117395Skan      for (o = v->opt; o; o = o->next)
2882117395Skan	if (strcmp (o->name, "deletable") == 0)
2883117395Skan	  skip_p = 0;
2884117395Skan	else if (strcmp (o->name, "if_marked") == 0)
2885117395Skan	  skip_p = 1;
2886117395Skan
2887117395Skan      if (skip_p)
2888117395Skan	continue;
2889117395Skan
2890117395Skan      for (fli = flp; fli; fli = fli->next)
2891117395Skan	if (fli->f == f)
2892117395Skan	  break;
2893117395Skan      if (! fli->started_p)
2894117395Skan	{
2895117395Skan	  fli->started_p = 1;
2896117395Skan
2897117395Skan	  oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
2898117395Skan	  put_mangled_filename (f, v->line.file);
2899117395Skan	  oprintf (f, "[] = {\n");
2900117395Skan	}
2901132718Skan
2902132718Skan      oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
2903117395Skan	       v->name, v->name);
2904117395Skan    }
2905132718Skan
2906132718Skan  finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2907117395Skan		     "gt_ggc_deletable_rtab");
2908117395Skan
2909117395Skan  for (v = variables; v; v = v->next)
2910117395Skan    {
2911117395Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2912117395Skan      struct flist *fli;
2913117395Skan      const char *if_marked = NULL;
2914117395Skan      int length_p = 0;
2915117395Skan      options_p o;
2916132718Skan
2917117395Skan      for (o = v->opt; o; o = o->next)
2918117395Skan	if (strcmp (o->name, "length") == 0)
2919117395Skan	  length_p = 1;
2920117395Skan	else if (strcmp (o->name, "if_marked") == 0)
2921169689Skan	  if_marked = o->info;
2922117395Skan
2923117395Skan      if (if_marked == NULL)
2924117395Skan	continue;
2925117395Skan
2926117395Skan      if (v->type->kind != TYPE_POINTER
2927117395Skan	  || v->type->u.p->kind != TYPE_PARAM_STRUCT
2928117395Skan	  || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
2929117395Skan	{
2930117395Skan	  error_at_line (&v->line, "if_marked option used but not hash table");
2931117395Skan	  continue;
2932117395Skan	}
2933117395Skan
2934117395Skan      for (fli = flp; fli; fli = fli->next)
2935117395Skan	if (fli->f == f)
2936117395Skan	  break;
2937117395Skan      if (! fli->started_p)
2938117395Skan	{
2939117395Skan	  fli->started_p = 1;
2940117395Skan
2941117395Skan	  oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
2942117395Skan	  put_mangled_filename (f, v->line.file);
2943117395Skan	  oprintf (f, "[] = {\n");
2944117395Skan	}
2945132718Skan
2946132718Skan      write_root (f, v, v->type->u.p->u.param_struct.param[0],
2947117395Skan		     v->name, length_p, &v->line, if_marked);
2948117395Skan    }
2949132718Skan
2950132718Skan  finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
2951117395Skan		     "gt_ggc_cache_rtab");
2952132718Skan
2953132718Skan  for (v = variables; v; v = v->next)
2954132718Skan    {
2955132718Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2956132718Skan      struct flist *fli;
2957132718Skan      int length_p = 0;
2958132718Skan      int if_marked_p = 0;
2959132718Skan      options_p o;
2960132718Skan
2961132718Skan      for (o = v->opt; o; o = o->next)
2962132718Skan	if (strcmp (o->name, "length") == 0)
2963132718Skan	  length_p = 1;
2964132718Skan	else if (strcmp (o->name, "if_marked") == 0)
2965132718Skan	  if_marked_p = 1;
2966132718Skan
2967132718Skan      if (! if_marked_p)
2968132718Skan	continue;
2969132718Skan
2970132718Skan      for (fli = flp; fli; fli = fli->next)
2971132718Skan	if (fli->f == f)
2972132718Skan	  break;
2973132718Skan      if (! fli->started_p)
2974132718Skan	{
2975132718Skan	  fli->started_p = 1;
2976132718Skan
2977132718Skan	  oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
2978132718Skan	  put_mangled_filename (f, v->line.file);
2979132718Skan	  oprintf (f, "[] = {\n");
2980132718Skan	}
2981132718Skan
2982132718Skan      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2983132718Skan    }
2984132718Skan
2985132718Skan  finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2986132718Skan		     "gt_pch_cache_rtab");
2987132718Skan
2988132718Skan  for (v = variables; v; v = v->next)
2989132718Skan    {
2990132718Skan      outf_p f = get_output_file_with_visibility (v->line.file);
2991132718Skan      struct flist *fli;
2992132718Skan      int skip_p = 0;
2993132718Skan      options_p o;
2994132718Skan
2995132718Skan      for (o = v->opt; o; o = o->next)
2996132718Skan	if (strcmp (o->name, "deletable") == 0
2997132718Skan	    || strcmp (o->name, "if_marked") == 0)
2998132718Skan	  skip_p = 1;
2999132718Skan
3000132718Skan      if (skip_p)
3001132718Skan	continue;
3002132718Skan
3003132718Skan      if (! contains_scalar_p (v->type))
3004132718Skan	continue;
3005132718Skan
3006132718Skan      for (fli = flp; fli; fli = fli->next)
3007132718Skan	if (fli->f == f)
3008132718Skan	  break;
3009132718Skan      if (! fli->started_p)
3010132718Skan	{
3011132718Skan	  fli->started_p = 1;
3012132718Skan
3013132718Skan	  oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
3014132718Skan	  put_mangled_filename (f, v->line.file);
3015132718Skan	  oprintf (f, "[] = {\n");
3016132718Skan	}
3017132718Skan
3018132718Skan      oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
3019132718Skan	       v->name, v->name);
3020132718Skan    }
3021132718Skan
3022132718Skan  finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
3023132718Skan		     "gt_pch_scalar_rtab");
3024117395Skan}
3025117395Skan
3026117395Skan
3027132718Skanextern int main (int argc, char **argv);
3028132718Skanint
3029169689Skanmain(int ARG_UNUSED (argc), char ** ARG_UNUSED (argv))
3030117395Skan{
3031117395Skan  unsigned i;
3032117395Skan  static struct fileloc pos = { __FILE__, __LINE__ };
3033117395Skan  unsigned j;
3034132718Skan
3035117395Skan  gen_rtx_next ();
3036117395Skan
3037117395Skan  srcdir_len = strlen (srcdir);
3038117395Skan
3039117395Skan  do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
3040117395Skan  do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
3041169689Skan  do_scalar_typedef ("double_int", &pos);
3042117395Skan  do_scalar_typedef ("uint8", &pos);
3043117395Skan  do_scalar_typedef ("jword", &pos);
3044117395Skan  do_scalar_typedef ("JCF_u2", &pos);
3045169689Skan#ifdef USE_MAPPED_LOCATION
3046169689Skan  do_scalar_typedef ("location_t", &pos);
3047169689Skan  do_scalar_typedef ("source_locus", &pos);
3048169689Skan#endif
3049132718Skan  do_scalar_typedef ("void", &pos);
3050117395Skan
3051132718Skan  do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
3052132718Skan
3053117395Skan  do_typedef ("HARD_REG_SET", create_array (
3054117395Skan	      create_scalar_type ("unsigned long", strlen ("unsigned long")),
3055117395Skan	      "2"), &pos);
3056117395Skan
3057117395Skan  for (i = 0; i < NUM_GT_FILES; i++)
3058117395Skan    {
3059117395Skan      int dupflag = 0;
3060117395Skan      /* Omit if already seen.  */
3061117395Skan      for (j = 0; j < i; j++)
3062117395Skan        {
3063117395Skan          if (!strcmp (all_files[i], all_files[j]))
3064117395Skan            {
3065117395Skan              dupflag = 1;
3066117395Skan              break;
3067117395Skan            }
3068117395Skan        }
3069117395Skan      if (!dupflag)
3070117395Skan        parse_file (all_files[i]);
3071169689Skan#ifndef USE_MAPPED_LOCATION
3072169689Skan      /* temporary kludge - gengtype doesn't handle conditionals.
3073169689Skan	 Manually add source_locus *after* we've processed input.h.  */
3074169689Skan      if (i == 0)
3075169689Skan	do_typedef ("source_locus", create_pointer (resolve_typedef ("location_t", &pos)), &pos);
3076169689Skan#endif
3077117395Skan    }
3078117395Skan
3079117395Skan  if (hit_error != 0)
3080117395Skan    exit (1);
3081117395Skan
3082117395Skan  set_gc_used (variables);
3083117395Skan
3084117395Skan  open_base_files ();
3085117395Skan  write_enum_defn (structures, param_structs);
3086132718Skan  write_types (structures, param_structs, &ggc_wtd);
3087132718Skan  write_types (structures, param_structs, &pch_wtd);
3088132718Skan  write_local (structures, param_structs);
3089132718Skan  write_roots (variables);
3090117395Skan  write_rtx_next ();
3091117395Skan  close_output_files ();
3092117395Skan
3093117395Skan  return (hit_error != 0);
3094117395Skan}
3095