]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gengtype.c
* internal.h (xnew, xcnew, xnewvec, xcnewvec, xobnew): Remove.
[thirdparty/gcc.git] / gcc / gengtype.c
CommitLineData
1f3233d1 1/* Process source files and output type information.
a8349c62 2 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
1f3233d1 3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 2, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING. If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
805e22b2 21#include "bconfig.h"
1f3233d1 22#include "system.h"
805e22b2 23#include "coretypes.h"
24#include "tm.h"
1f3233d1 25#include "gengtype.h"
776c30b8 26#include "gtyp-gen.h"
1f3233d1 27
acfcaf8d 28#define NO_GENRTL_H
29#include "rtl.h"
30#undef abort
31
155e048d 32/* Nonzero iff an error has occurred. */
1f3233d1 33static int hit_error = 0;
155e048d 34
1a97be37 35static void gen_rtx_next (void);
36static void write_rtx_next (void);
37static void open_base_files (void);
38static void close_output_files (void);
4b6ffd1b 39
155e048d 40/* Report an error at POS, printing MSG. */
41
1f3233d1 42void
ee582a61 43error_at_line (struct fileloc *pos, const char *msg, ...)
1f3233d1 44{
ee582a61 45 va_list ap;
1a97be37 46
ee582a61 47 va_start (ap, msg);
1f3233d1 48
49 fprintf (stderr, "%s:%d: ", pos->file, pos->line);
50 vfprintf (stderr, msg, ap);
51 fputc ('\n', stderr);
52 hit_error = 1;
53
ee582a61 54 va_end (ap);
1f3233d1 55}
56
92570e7a 57/* vasprintf, but produces fatal message on out-of-memory. */
58int
1a97be37 59xvasprintf (char **result, const char *format, va_list args)
92570e7a 60{
61 int ret = vasprintf (result, format, args);
62 if (*result == NULL || ret < 0)
63 {
64 fputs ("gengtype: out of memory", stderr);
65 xexit (1);
66 }
67 return ret;
68}
69
70/* Wrapper for xvasprintf. */
71char *
ee582a61 72xasprintf (const char *format, ...)
92570e7a 73{
74 char *result;
ee582a61 75 va_list ap;
1a97be37 76
ee582a61 77 va_start (ap, format);
92570e7a 78 xvasprintf (&result, format, ap);
ee582a61 79 va_end (ap);
92570e7a 80 return result;
81}
82
155e048d 83/* The one and only TYPE_STRING. */
84
1f3233d1 85struct type string_type = {
5ffca67a 86 TYPE_STRING, NULL, NULL, GC_USED, {0}
1a97be37 87};
1f3233d1 88
155e048d 89/* Lists of various things. */
90
1f3233d1 91static pair_p typedefs;
92static type_p structures;
93static type_p param_structs;
94static pair_p variables;
95
1a97be37 96static void do_scalar_typedef (const char *, struct fileloc *);
97static type_p find_param_structure
98 (type_p t, type_p param[NUM_PARAM]);
99static type_p adjust_field_tree_exp (type_p t, options_p opt);
100static type_p adjust_field_rtx_def (type_p t, options_p opt);
c849df63 101
155e048d 102/* Define S as a typedef to T at POS. */
103
1f3233d1 104void
1a97be37 105do_typedef (const char *s, type_p t, struct fileloc *pos)
1f3233d1 106{
107 pair_p p;
108
109 for (p = typedefs; p != NULL; p = p->next)
110 if (strcmp (p->name, s) == 0)
111 {
112 if (p->type != t)
113 {
114 error_at_line (pos, "type `%s' previously defined", s);
115 error_at_line (&p->line, "previously defined here");
116 }
117 return;
118 }
119
120 p = xmalloc (sizeof (struct pair));
121 p->next = typedefs;
122 p->name = s;
123 p->type = t;
124 p->line = *pos;
125 typedefs = p;
126}
127
c849df63 128/* Define S as a typename of a scalar. */
129
130static void
1a97be37 131do_scalar_typedef (const char *s, struct fileloc *pos)
c849df63 132{
133 do_typedef (s, create_scalar_type (s, strlen (s)), pos);
134}
135
102502d4 136/* Return the type previously defined for S. Use POS to report errors. */
155e048d 137
1f3233d1 138type_p
1a97be37 139resolve_typedef (const char *s, struct fileloc *pos)
1f3233d1 140{
141 pair_p p;
142 for (p = typedefs; p != NULL; p = p->next)
143 if (strcmp (p->name, s) == 0)
144 return p->type;
145 error_at_line (pos, "unidentified type `%s'", s);
146 return create_scalar_type ("char", 4);
147}
148
155e048d 149/* Create a new structure with tag NAME (or a union iff ISUNION is nonzero),
150 at POS with fields FIELDS and options O. */
151
1f3233d1 152void
1a97be37 153new_structure (const char *name, int isunion, struct fileloc *pos,
154 pair_p fields, options_p o)
1f3233d1 155{
156 type_p si;
157 type_p s = NULL;
158 lang_bitmap bitmap = get_base_file_bitmap (pos->file);
159
160 for (si = structures; si != NULL; si = si->next)
1a97be37 161 if (strcmp (name, si->u.s.tag) == 0
1f3233d1 162 && UNION_P (si) == isunion)
163 {
164 type_p ls = NULL;
165 if (si->kind == TYPE_LANG_STRUCT)
166 {
167 ls = si;
1a97be37 168
1f3233d1 169 for (si = ls->u.s.lang_struct; si != NULL; si = si->next)
170 if (si->u.s.bitmap == bitmap)
171 s = si;
172 }
173 else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
174 {
175 ls = si;
176 si = xcalloc (1, sizeof (struct type));
177 memcpy (si, ls, sizeof (struct type));
178 ls->kind = TYPE_LANG_STRUCT;
179 ls->u.s.lang_struct = si;
180 ls->u.s.fields = NULL;
181 si->next = NULL;
182 si->pointer_to = NULL;
183 si->u.s.lang_struct = ls;
184 }
185 else
186 s = si;
187
188 if (ls != NULL && s == NULL)
189 {
190 s = xcalloc (1, sizeof (struct type));
191 s->next = ls->u.s.lang_struct;
192 ls->u.s.lang_struct = s;
193 s->u.s.lang_struct = ls;
194 }
195 break;
196 }
1a97be37 197
1f3233d1 198 if (s == NULL)
199 {
200 s = xcalloc (1, sizeof (struct type));
201 s->next = structures;
202 structures = s;
203 }
204
205 if (s->u.s.line.file != NULL
206 || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
207 {
208 error_at_line (pos, "duplicate structure definition");
209 error_at_line (&s->u.s.line, "previous definition here");
210 }
211
212 s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
213 s->u.s.tag = name;
214 s->u.s.line = *pos;
215 s->u.s.fields = fields;
216 s->u.s.opt = o;
217 s->u.s.bitmap = bitmap;
218 if (s->u.s.lang_struct)
219 s->u.s.lang_struct->u.s.bitmap |= bitmap;
220}
221
155e048d 222/* Return the previously-defined structure with tag NAME (or a union
223 iff ISUNION is nonzero), or a new empty structure or union if none
224 was defined previously. */
225
1f3233d1 226type_p
1a97be37 227find_structure (const char *name, int isunion)
1f3233d1 228{
229 type_p s;
230
231 for (s = structures; s != NULL; s = s->next)
1a97be37 232 if (strcmp (name, s->u.s.tag) == 0
1f3233d1 233 && UNION_P (s) == isunion)
234 return s;
235
236 s = xcalloc (1, sizeof (struct type));
237 s->next = structures;
238 structures = s;
239 s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
240 s->u.s.tag = name;
241 structures = s;
242 return s;
243}
244
a8b24921 245/* Return the previously-defined parameterized structure for structure
246 T and parameters PARAM, or a new parameterized empty structure or
9cb8e99f 247 union if none was defined previously. */
c849df63 248
249static type_p
1a97be37 250find_param_structure (type_p t, type_p param[NUM_PARAM])
c849df63 251{
252 type_p res;
1a97be37 253
c849df63 254 for (res = param_structs; res; res = res->next)
255 if (res->u.param_struct.stru == t
1a97be37 256 && memcmp (res->u.param_struct.param, param,
c849df63 257 sizeof (type_p) * NUM_PARAM) == 0)
258 break;
259 if (res == NULL)
260 {
261 res = xcalloc (1, sizeof (*res));
262 res->kind = TYPE_PARAM_STRUCT;
263 res->next = param_structs;
264 param_structs = res;
265 res->u.param_struct.stru = t;
266 memcpy (res->u.param_struct.param, param, sizeof (type_p) * NUM_PARAM);
267 }
268 return res;
269}
270
155e048d 271/* Return a scalar type with name NAME. */
272
1f3233d1 273type_p
1a97be37 274create_scalar_type (const char *name, size_t name_len)
1f3233d1 275{
276 type_p r = xcalloc (1, sizeof (struct type));
277 r->kind = TYPE_SCALAR;
278 r->u.sc = xmemdup (name, name_len, name_len + 1);
279 return r;
280}
281
155e048d 282/* Return a pointer to T. */
283
1f3233d1 284type_p
1a97be37 285create_pointer (type_p t)
1f3233d1 286{
287 if (! t->pointer_to)
288 {
289 type_p r = xcalloc (1, sizeof (struct type));
290 r->kind = TYPE_POINTER;
291 r->u.p = t;
292 t->pointer_to = r;
293 }
294 return t->pointer_to;
295}
296
155e048d 297/* Return an array of length LEN. */
298
1f3233d1 299type_p
1a97be37 300create_array (type_p t, const char *len)
1f3233d1 301{
302 type_p v;
1a97be37 303
1f3233d1 304 v = xcalloc (1, sizeof (*v));
305 v->kind = TYPE_ARRAY;
306 v->u.a.p = t;
307 v->u.a.len = len;
308 return v;
309}
310
7035b2ab 311/* Return an options structure with name NAME and info INFO. */
312options_p
313create_option (const char *name, void *info)
314{
315 options_p o = xmalloc (sizeof (*o));
316 o->name = name;
317 o->info = info;
318 return o;
319}
320
c849df63 321/* Add a variable named S of type T with options O defined at POS,
322 to `variables'. */
323
324void
1a97be37 325note_variable (const char *s, type_p t, options_p o, struct fileloc *pos)
c849df63 326{
327 pair_p n;
328 n = xmalloc (sizeof (*n));
329 n->name = s;
330 n->type = t;
331 n->line = *pos;
332 n->opt = o;
333 n->next = variables;
334 variables = n;
335}
336
c849df63 337/* We really don't care how long a CONST_DOUBLE is. */
338#define CONST_DOUBLE_FORMAT "ww"
acfcaf8d 339const char * const rtx_format[NUM_RTX_CODE] = {
c849df63 340#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
341#include "rtl.def"
342#undef DEF_RTL_EXPR
343};
344
acfcaf8d 345static int rtx_next_new[NUM_RTX_CODE];
c849df63 346
347/* Generate the contents of the rtx_next array. This really doesn't belong
348 in gengtype at all, but it's needed for adjust_field_rtx_def. */
349
350static void
1a97be37 351gen_rtx_next (void)
c849df63 352{
353 int i;
354 for (i = 0; i < NUM_RTX_CODE; i++)
355 {
356 int k;
1a97be37 357
acfcaf8d 358 rtx_next_new[i] = -1;
c849df63 359 if (strncmp (rtx_format[i], "iuu", 3) == 0)
acfcaf8d 360 rtx_next_new[i] = 2;
c849df63 361 else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
acfcaf8d 362 rtx_next_new[i] = 1;
1a97be37 363 else
c849df63 364 for (k = strlen (rtx_format[i]) - 1; k >= 0; k--)
365 if (rtx_format[i][k] == 'e' || rtx_format[i][k] == 'u')
acfcaf8d 366 rtx_next_new[i] = k;
c849df63 367 }
368}
369
370/* Write out the contents of the rtx_next array. */
371static void
1a97be37 372write_rtx_next (void)
c849df63 373{
374 outf_p f = get_output_file_with_visibility (NULL);
375 int i;
1a97be37 376
c849df63 377 oprintf (f, "\n/* Used to implement the RTX_NEXT macro. */\n");
378 oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
379 for (i = 0; i < NUM_RTX_CODE; i++)
acfcaf8d 380 if (rtx_next_new[i] == -1)
c849df63 381 oprintf (f, " 0,\n");
382 else
1a97be37 383 oprintf (f,
bf6b5685 384 " RTX_HDR_SIZE + %d * sizeof (rtunion),\n",
acfcaf8d 385 rtx_next_new[i]);
c849df63 386 oprintf (f, "};\n");
387}
388
389/* Handle `special("rtx_def")'. This is a special case for field
390 `fld' of struct rtx_def, which is an array of unions whose values
391 are based in a complex way on the type of RTL. */
392
393static type_p
1a97be37 394adjust_field_rtx_def (type_p t, options_p opt ATTRIBUTE_UNUSED)
c849df63 395{
396 pair_p flds = NULL;
397 options_p nodot;
398 int i;
399 type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp;
ca74b940 400 type_p bitmap_tp, basic_block_tp, reg_attrs_tp;
c849df63 401
402 static const char * const rtx_name[NUM_RTX_CODE] = {
403#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
404#include "rtl.def"
405#undef DEF_RTL_EXPR
406 };
1a97be37 407
bf6b5685 408 if (t->kind != TYPE_UNION)
c849df63 409 {
1a97be37 410 error_at_line (&lexer_line,
bf6b5685 411 "special `rtx_def' must be applied to a union");
c849df63 412 return &string_type;
413 }
1a97be37 414
c849df63 415 nodot = xmalloc (sizeof (*nodot));
416 nodot->next = NULL;
417 nodot->name = "dot";
418 nodot->info = "";
419
420 rtx_tp = create_pointer (find_structure ("rtx_def", 0));
421 rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
422 tree_tp = create_pointer (find_structure ("tree_node", 1));
423 mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0));
ca74b940 424 reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0));
c849df63 425 bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
426 basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
427 scalar_tp = create_scalar_type ("rtunion scalar", 14);
428
429 {
430 pair_p note_flds = NULL;
431 int c;
acfcaf8d 432
433 for (c = NOTE_INSN_BIAS; c <= NOTE_INSN_MAX; c++)
c849df63 434 {
435 pair_p old_note_flds = note_flds;
1a97be37 436
c849df63 437 note_flds = xmalloc (sizeof (*note_flds));
438 note_flds->line.file = __FILE__;
439 note_flds->line.line = __LINE__;
c849df63 440 note_flds->opt = xmalloc (sizeof (*note_flds->opt));
441 note_flds->opt->next = nodot;
442 note_flds->opt->name = "tag";
acfcaf8d 443 note_flds->opt->info = xasprintf ("%d", c);
c849df63 444 note_flds->next = old_note_flds;
acfcaf8d 445
446 switch (c)
447 {
448 /* NOTE_INSN_MAX is used as the default field for line
449 number notes. */
450 case NOTE_INSN_MAX:
451 note_flds->opt->name = "default";
452 note_flds->name = "rtstr";
453 note_flds->type = &string_type;
454 break;
455
456 case NOTE_INSN_BLOCK_BEG:
457 case NOTE_INSN_BLOCK_END:
458 note_flds->name = "rttree";
459 note_flds->type = tree_tp;
460 break;
1a97be37 461
acfcaf8d 462 case NOTE_INSN_EXPECTED_VALUE:
5923a5e7 463 case NOTE_INSN_VAR_LOCATION:
acfcaf8d 464 note_flds->name = "rtx";
465 note_flds->type = rtx_tp;
466 break;
467
468 default:
469 note_flds->name = "rtint";
470 note_flds->type = scalar_tp;
471 break;
472 }
c849df63 473 }
c849df63 474 new_structure ("rtx_def_note_subunion", 1, &lexer_line, note_flds, NULL);
475 }
1a97be37 476
c849df63 477 note_union_tp = find_structure ("rtx_def_note_subunion", 1);
478
479 for (i = 0; i < NUM_RTX_CODE; i++)
480 {
481 pair_p old_flds = flds;
482 pair_p subfields = NULL;
483 size_t aindex, nmindex;
484 const char *sname;
485 char *ftag;
486
487 for (aindex = 0; aindex < strlen (rtx_format[i]); aindex++)
488 {
489 pair_p old_subf = subfields;
490 type_p t;
491 const char *subname;
492
493 switch (rtx_format[i][aindex])
494 {
495 case '*':
496 case 'i':
497 case 'n':
498 case 'w':
499 t = scalar_tp;
500 subname = "rtint";
501 break;
502
503 case '0':
504 if (i == MEM && aindex == 1)
505 t = mem_attrs_tp, subname = "rtmem";
506 else if (i == JUMP_INSN && aindex == 9)
507 t = rtx_tp, subname = "rtx";
508 else if (i == CODE_LABEL && aindex == 4)
509 t = scalar_tp, subname = "rtint";
510 else if (i == CODE_LABEL && aindex == 5)
511 t = rtx_tp, subname = "rtx";
512 else if (i == LABEL_REF
513 && (aindex == 1 || aindex == 2))
514 t = rtx_tp, subname = "rtx";
515 else if (i == NOTE && aindex == 4)
516 t = note_union_tp, subname = "";
517 else if (i == NOTE && aindex >= 7)
518 t = scalar_tp, subname = "rtint";
519 else if (i == ADDR_DIFF_VEC && aindex == 4)
520 t = scalar_tp, subname = "rtint";
521 else if (i == VALUE && aindex == 0)
522 t = scalar_tp, subname = "rtint";
523 else if (i == REG && aindex == 1)
524 t = scalar_tp, subname = "rtint";
ca74b940 525 else if (i == REG && aindex == 2)
526 t = reg_attrs_tp, subname = "rtreg";
c849df63 527 else if (i == SCRATCH && aindex == 0)
528 t = scalar_tp, subname = "rtint";
001be062 529 else if (i == SYMBOL_REF && aindex == 1)
530 t = scalar_tp, subname = "rtint";
531 else if (i == SYMBOL_REF && aindex == 2)
532 t = tree_tp, subname = "rttree";
c849df63 533 else if (i == BARRIER && aindex >= 3)
534 t = scalar_tp, subname = "rtint";
535 else
536 {
1a97be37 537 error_at_line (&lexer_line,
e72117bc 538 "rtx type `%s' has `0' in position %lu, can't handle",
539 rtx_name[i], (unsigned long) aindex);
c849df63 540 t = &string_type;
541 subname = "rtint";
542 }
543 break;
1a97be37 544
c849df63 545 case 's':
546 case 'S':
547 case 'T':
548 t = &string_type;
549 subname = "rtstr";
550 break;
551
552 case 'e':
553 case 'u':
554 t = rtx_tp;
555 subname = "rtx";
556 break;
557
558 case 'E':
559 case 'V':
560 t = rtvec_tp;
561 subname = "rtvec";
562 break;
563
564 case 't':
565 t = tree_tp;
566 subname = "rttree";
567 break;
568
569 case 'b':
570 t = bitmap_tp;
571 subname = "rtbit";
572 break;
573
574 case 'B':
575 t = basic_block_tp;
576 subname = "bb";
577 break;
578
579 default:
1a97be37 580 error_at_line (&lexer_line,
e72117bc 581 "rtx type `%s' has `%c' in position %lu, can't handle",
c849df63 582 rtx_name[i], rtx_format[i][aindex],
e72117bc 583 (unsigned long)aindex);
c849df63 584 t = &string_type;
585 subname = "rtint";
586 break;
587 }
588
589 subfields = xmalloc (sizeof (*subfields));
590 subfields->next = old_subf;
591 subfields->type = t;
bf6b5685 592 subfields->name = xasprintf (".fld[%lu].%s", (unsigned long)aindex,
e72117bc 593 subname);
c849df63 594 subfields->line.file = __FILE__;
595 subfields->line.line = __LINE__;
596 if (t == note_union_tp)
597 {
598 subfields->opt = xmalloc (sizeof (*subfields->opt));
599 subfields->opt->next = nodot;
600 subfields->opt->name = "desc";
601 subfields->opt->info = "NOTE_LINE_NUMBER (&%0)";
602 }
603 else if (t == basic_block_tp)
604 {
9cb8e99f 605 /* We don't presently GC basic block structures... */
c849df63 606 subfields->opt = xmalloc (sizeof (*subfields->opt));
607 subfields->opt->next = nodot;
608 subfields->opt->name = "skip";
609 subfields->opt->info = NULL;
610 }
c849df63 611 else
612 subfields->opt = nodot;
613 }
614
615 flds = xmalloc (sizeof (*flds));
616 flds->next = old_flds;
617 flds->name = "";
618 sname = xasprintf ("rtx_def_%s", rtx_name[i]);
619 new_structure (sname, 0, &lexer_line, subfields, NULL);
620 flds->type = find_structure (sname, 0);
621 flds->line.file = __FILE__;
622 flds->line.line = __LINE__;
623 flds->opt = xmalloc (sizeof (*flds->opt));
624 flds->opt->next = nodot;
625 flds->opt->name = "tag";
626 ftag = xstrdup (rtx_name[i]);
627 for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
628 ftag[nmindex] = TOUPPER (ftag[nmindex]);
629 flds->opt->info = ftag;
630 }
631
632 new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
633 return find_structure ("rtx_def_subunion", 1);
634}
635
636/* Handle `special("tree_exp")'. This is a special case for
637 field `operands' of struct tree_exp, which although it claims to contain
1a97be37 638 pointers to trees, actually sometimes contains pointers to RTL too.
c849df63 639 Passed T, the old type of the field, and OPT its options. Returns
640 a new type for the field. */
641
642static type_p
1a97be37 643adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED)
c849df63 644{
645 pair_p flds;
646 options_p nodot;
1a97be37 647
c849df63 648 if (t->kind != TYPE_ARRAY)
649 {
1a97be37 650 error_at_line (&lexer_line,
c849df63 651 "special `tree_exp' must be applied to an array");
652 return &string_type;
653 }
1a97be37 654
c849df63 655 nodot = xmalloc (sizeof (*nodot));
656 nodot->next = NULL;
657 nodot->name = "dot";
658 nodot->info = "";
659
660 flds = xmalloc (sizeof (*flds));
661 flds->next = NULL;
662 flds->name = "";
663 flds->type = t;
664 flds->line.file = __FILE__;
665 flds->line.line = __LINE__;
666 flds->opt = xmalloc (sizeof (*flds->opt));
667 flds->opt->next = nodot;
668 flds->opt->name = "length";
669 flds->opt->info = "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))";
670 {
671 options_p oldopt = flds->opt;
672 flds->opt = xmalloc (sizeof (*flds->opt));
673 flds->opt->next = oldopt;
674 flds->opt->name = "default";
675 flds->opt->info = "";
676 }
1a97be37 677
c849df63 678 new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
679 return find_structure ("tree_exp_subunion", 1);
680}
681
155e048d 682/* Perform any special processing on a type T, about to become the type
683 of a field. Return the appropriate type for the field.
684 At present:
685 - Converts pointer-to-char, with no length parameter, to TYPE_STRING;
686 - Similarly for arrays of pointer-to-char;
687 - Converts structures for which a parameter is provided to
c849df63 688 TYPE_PARAM_STRUCT;
689 - Handles "special" options.
1a97be37 690*/
155e048d 691
1f3233d1 692type_p
1a97be37 693adjust_field_type (type_p t, options_p opt)
1f3233d1 694{
695 int length_p = 0;
696 const int pointer_p = t->kind == TYPE_POINTER;
c849df63 697 type_p params[NUM_PARAM];
698 int params_p = 0;
699 int i;
700
701 for (i = 0; i < NUM_PARAM; i++)
702 params[i] = NULL;
1a97be37 703
1f3233d1 704 for (; opt; opt = opt->next)
705 if (strcmp (opt->name, "length") == 0)
706 length_p = 1;
c849df63 707 else if (strcmp (opt->name, "param_is") == 0
708 || (strncmp (opt->name, "param", 5) == 0
709 && ISDIGIT (opt->name[5])
710 && strcmp (opt->name + 6, "_is") == 0))
1f3233d1 711 {
c849df63 712 int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
1f3233d1 713
c849df63 714 if (! UNION_OR_STRUCT_P (t)
715 && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
716 {
1a97be37 717 error_at_line (&lexer_line,
c849df63 718 "option `%s' may only be applied to structures or structure pointers",
719 opt->name);
720 return t;
721 }
722
723 params_p = 1;
724 if (params[num] != NULL)
725 error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
726 if (! ISDIGIT (opt->name[5]))
727 params[num] = create_pointer ((type_p) opt->info);
728 else
729 params[num] = (type_p) opt->info;
1f3233d1 730 }
c849df63 731 else if (strcmp (opt->name, "special") == 0)
732 {
733 const char *special_name = (const char *)opt->info;
734 if (strcmp (special_name, "tree_exp") == 0)
735 t = adjust_field_tree_exp (t, opt);
736 else if (strcmp (special_name, "rtx_def") == 0)
737 t = adjust_field_rtx_def (t, opt);
738 else
739 error_at_line (&lexer_line, "unknown special `%s'", special_name);
740 }
741
742 if (params_p)
743 {
744 type_p realt;
1a97be37 745
c849df63 746 if (pointer_p)
747 t = t->u.p;
748 realt = find_param_structure (t, params);
749 t = pointer_p ? create_pointer (realt) : realt;
750 }
751
1f3233d1 752 if (! length_p
753 && pointer_p
754 && t->u.p->kind == TYPE_SCALAR
755 && (strcmp (t->u.p->u.sc, "char") == 0
756 || strcmp (t->u.p->u.sc, "unsigned char") == 0))
757 return &string_type;
758 if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
759 && t->u.a.p->u.p->kind == TYPE_SCALAR
760 && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
761 || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
762 return create_array (&string_type, t->u.a.len);
763
764 return t;
765}
766
155e048d 767/* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
98667efb 768 and information about the correspondence between token types and fields
155e048d 769 in TYPEINFO. POS is used for error messages. */
770
1f3233d1 771void
1a97be37 772note_yacc_type (options_p o, pair_p fields, pair_p typeinfo,
773 struct fileloc *pos)
1f3233d1 774{
775 pair_p p;
776 pair_p *p_p;
1a97be37 777
1f3233d1 778 for (p = typeinfo; p; p = p->next)
779 {
780 pair_p m;
1a97be37 781
1f3233d1 782 if (p->name == NULL)
783 continue;
784
785 if (p->type == (type_p) 1)
786 {
787 pair_p pp;
788 int ok = 0;
1a97be37 789
1f3233d1 790 for (pp = typeinfo; pp; pp = pp->next)
791 if (pp->type != (type_p) 1
792 && strcmp (pp->opt->info, p->opt->info) == 0)
793 {
794 ok = 1;
795 break;
796 }
797 if (! ok)
798 continue;
799 }
800
801 for (m = fields; m; m = m->next)
802 if (strcmp (m->name, p->name) == 0)
803 p->type = m->type;
804 if (p->type == NULL)
805 {
1a97be37 806 error_at_line (&p->line,
1f3233d1 807 "couldn't match fieldname `%s'", p->name);
808 p->name = NULL;
809 }
810 }
1a97be37 811
1f3233d1 812 p_p = &typeinfo;
813 while (*p_p)
814 {
815 pair_p p = *p_p;
816
817 if (p->name == NULL
818 || p->type == (type_p) 1)
819 *p_p = p->next;
820 else
821 p_p = &p->next;
822 }
823
824 new_structure ("yy_union", 1, pos, typeinfo, o);
825 do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos);
826}
827\f
1a97be37 828static void process_gc_options (options_p, enum gc_used_enum,
c39ed964 829 int *, int *, int *, type_p *);
1a97be37 830static void set_gc_used_type (type_p, enum gc_used_enum, type_p *);
831static void set_gc_used (pair_p);
1f3233d1 832
155e048d 833/* Handle OPT for set_gc_used_type. */
834
1f3233d1 835static void
1a97be37 836process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
c39ed964 837 int *pass_param, int *length, type_p *nested_ptr)
1f3233d1 838{
839 options_p o;
840 for (o = opt; o; o = o->next)
841 if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
c849df63 842 set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL);
1f3233d1 843 else if (strcmp (o->name, "maybe_undef") == 0)
844 *maybe_undef = 1;
c849df63 845 else if (strcmp (o->name, "use_params") == 0)
846 *pass_param = 1;
847 else if (strcmp (o->name, "length") == 0)
848 *length = 1;
c39ed964 849 else if (strcmp (o->name, "nested_ptr") == 0)
850 *nested_ptr = ((const struct nested_ptr_data *) o->info)->type;
1f3233d1 851}
852
155e048d 853/* Set the gc_used field of T to LEVEL, and handle the types it references. */
854
1f3233d1 855static void
1a97be37 856set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
1f3233d1 857{
858 if (t->gc_used >= level)
859 return;
1a97be37 860
1f3233d1 861 t->gc_used = level;
862
863 switch (t->kind)
864 {
865 case TYPE_STRUCT:
866 case TYPE_UNION:
867 {
868 pair_p f;
869 int dummy;
c39ed964 870 type_p dummy2;
1f3233d1 871
c39ed964 872 process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy,
873 &dummy2);
1f3233d1 874
875 for (f = t->u.s.fields; f; f = f->next)
876 {
877 int maybe_undef = 0;
c849df63 878 int pass_param = 0;
879 int length = 0;
c39ed964 880 type_p nested_ptr = NULL;
c849df63 881 process_gc_options (f->opt, level, &maybe_undef, &pass_param,
c39ed964 882 &length, &nested_ptr);
1a97be37 883
c39ed964 884 if (nested_ptr && f->type->kind == TYPE_POINTER)
885 set_gc_used_type (nested_ptr, GC_POINTED_TO,
886 pass_param ? param : NULL);
887 else if (length && f->type->kind == TYPE_POINTER)
c849df63 888 set_gc_used_type (f->type->u.p, GC_USED, NULL);
889 else if (maybe_undef && f->type->kind == TYPE_POINTER)
890 set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
891 else if (pass_param && f->type->kind == TYPE_POINTER && param)
892 set_gc_used_type (find_param_structure (f->type->u.p, param),
893 GC_POINTED_TO, NULL);
1f3233d1 894 else
c849df63 895 set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
1f3233d1 896 }
897 break;
898 }
899
900 case TYPE_POINTER:
c849df63 901 set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
1f3233d1 902 break;
903
904 case TYPE_ARRAY:
c849df63 905 set_gc_used_type (t->u.a.p, GC_USED, param);
1f3233d1 906 break;
1a97be37 907
1f3233d1 908 case TYPE_LANG_STRUCT:
909 for (t = t->u.s.lang_struct; t; t = t->next)
c849df63 910 set_gc_used_type (t, level, param);
1f3233d1 911 break;
912
913 case TYPE_PARAM_STRUCT:
c849df63 914 {
915 int i;
916 for (i = 0; i < NUM_PARAM; i++)
917 if (t->u.param_struct.param[i] != 0)
918 set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
919 }
920 if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
921 level = GC_POINTED_TO;
922 else
923 level = GC_USED;
924 t->u.param_struct.stru->gc_used = GC_UNUSED;
1a97be37 925 set_gc_used_type (t->u.param_struct.stru, level,
c849df63 926 t->u.param_struct.param);
1f3233d1 927 break;
928
929 default:
930 break;
931 }
932}
933
c849df63 934/* Set the gc_used fields of all the types pointed to by VARIABLES. */
155e048d 935
1f3233d1 936static void
1a97be37 937set_gc_used (pair_p variables)
1f3233d1 938{
939 pair_p p;
940 for (p = variables; p; p = p->next)
c849df63 941 set_gc_used_type (p->type, GC_USED, NULL);
1f3233d1 942}
943\f
944/* File mapping routines. For each input file, there is one output .c file
945 (but some output files have many input files), and there is one .h file
946 for the whole build. */
947
155e048d 948/* The list of output files. */
92570e7a 949static outf_p output_files;
155e048d 950
951/* The output header file that is included into pretty much every
952 source file. */
00775b04 953static outf_p header_file;
1f3233d1 954
776c30b8 955/* Number of files specified in gtfiles. */
956#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
4d26f199 957
776c30b8 958/* Number of files in the language files array. */
959#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
960
961/* Length of srcdir name. */
962static int srcdir_len = 0;
963
964#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
92570e7a 965outf_p base_files[NUM_BASE_FILES];
1f3233d1 966
1a97be37 967static outf_p create_file (const char *, const char *);
968static const char * get_file_basename (const char *);
1f3233d1 969
92570e7a 970/* Create and return an outf_p for a new file for NAME, to be called
971 ONAME. */
155e048d 972
92570e7a 973static outf_p
1a97be37 974create_file (const char *name, const char *oname)
1f3233d1 975{
976 static const char *const hdr[] = {
c39ed964 977 " Copyright (C) 2004 Free Software Foundation, Inc.\n",
1f3233d1 978 "\n",
979 "This file is part of GCC.\n",
980 "\n",
981 "GCC is free software; you can redistribute it and/or modify it under\n",
982 "the terms of the GNU General Public License as published by the Free\n",
983 "Software Foundation; either version 2, or (at your option) any later\n",
984 "version.\n",
985 "\n",
986 "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
987 "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
988 "FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n",
989 "for more details.\n",
990 "\n",
991 "You should have received a copy of the GNU General Public License\n",
992 "along with GCC; see the file COPYING. If not, write to the Free\n",
993 "Software Foundation, 59 Temple Place - Suite 330, Boston, MA\n",
994 "02111-1307, USA. */\n",
995 "\n",
996 "/* This file is machine generated. Do not edit. */\n"
997 };
92570e7a 998 outf_p f;
1f3233d1 999 size_t i;
1a97be37 1000
92570e7a 1001 f = xcalloc (sizeof (*f), 1);
1002 f->next = output_files;
1003 f->name = oname;
1004 output_files = f;
1005
1006 oprintf (f, "/* Type information for %s.\n", name);
0480d780 1007 for (i = 0; i < ARRAY_SIZE (hdr); i++)
92570e7a 1008 oprintf (f, "%s", hdr[i]);
1f3233d1 1009 return f;
1010}
1011
92570e7a 1012/* Print, like fprintf, to O. */
1a97be37 1013void
ee582a61 1014oprintf (outf_p o, const char *format, ...)
92570e7a 1015{
1016 char *s;
1017 size_t slength;
ee582a61 1018 va_list ap;
1a97be37 1019
ee582a61 1020 va_start (ap, format);
92570e7a 1021 slength = xvasprintf (&s, format, ap);
92570e7a 1022
1023 if (o->bufused + slength > o->buflength)
1024 {
1025 size_t new_len = o->buflength;
1026 if (new_len == 0)
1027 new_len = 1024;
1028 do {
1029 new_len *= 2;
1030 } while (o->bufused + slength >= new_len);
1031 o->buf = xrealloc (o->buf, new_len);
1032 o->buflength = new_len;
1033 }
1034 memcpy (o->buf + o->bufused, s, slength);
1035 o->bufused += slength;
1036 free (s);
ee582a61 1037 va_end (ap);
92570e7a 1038}
1039
155e048d 1040/* Open the global header file and the language-specific header files. */
1041
1f3233d1 1042static void
1a97be37 1043open_base_files (void)
1f3233d1 1044{
1045 size_t i;
1a97be37 1046
92570e7a 1047 header_file = create_file ("GCC", "gtype-desc.h");
1f3233d1 1048
1049 for (i = 0; i < NUM_BASE_FILES; i++)
1a97be37 1050 base_files[i] = create_file (lang_dir_names[i],
776c30b8 1051 xasprintf ("gtype-%s.h", lang_dir_names[i]));
92570e7a 1052
1053 /* gtype-desc.c is a little special, so we create it here. */
1054 {
1055 /* The order of files here matters very much. */
1056 static const char *const ifiles [] = {
4ee9c684 1057 "config.h", "system.h", "coretypes.h", "tm.h", "varray.h",
512e0fec 1058 "hashtab.h", "splay-tree.h", "bitmap.h", "input.h", "tree.h", "rtl.h",
805e22b2 1059 "function.h", "insn-config.h", "expr.h", "hard-reg-set.h",
5ff51111 1060 "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h",
5d31fea4 1061 "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
2bc9fc53 1062 "tree-alias-type.h", "tree-flow.h", "reload.h",
c39ed964 1063 "cpp-id-data.h",
1364018f 1064 "tree-chrec.h",
92570e7a 1065 NULL
1066 };
1067 const char *const *ifp;
1068 outf_p gtype_desc_c;
1a97be37 1069
92570e7a 1070 gtype_desc_c = create_file ("GCC", "gtype-desc.c");
1071 for (ifp = ifiles; *ifp; ifp++)
1072 oprintf (gtype_desc_c, "#include \"%s\"\n", *ifp);
1073 }
1f3233d1 1074}
1075
155e048d 1076/* Determine the pathname to F relative to $(srcdir). */
1077
1f3233d1 1078static const char *
1a97be37 1079get_file_basename (const char *f)
1f3233d1 1080{
1f3233d1 1081 const char *basename;
776c30b8 1082 unsigned i;
1a97be37 1083
1f3233d1 1084 basename = strrchr (f, '/');
1a97be37 1085
776c30b8 1086 if (!basename)
1087 return f;
1a97be37 1088
776c30b8 1089 basename++;
1a97be37 1090
776c30b8 1091 for (i = 1; i < NUM_BASE_FILES; i++)
1092 {
1093 const char * s1;
1094 const char * s2;
1095 int l1;
1096 int l2;
1097 s1 = basename - strlen (lang_dir_names [i]) - 1;
1098 s2 = lang_dir_names [i];
1099 l1 = strlen (s1);
1100 l2 = strlen (s2);
1101 if (l1 >= l2 && !memcmp (s1, s2, l2))
1102 {
1103 basename -= l2 + 1;
1104 if ((basename - f - 1) != srcdir_len)
1105 abort (); /* Match is wrong - should be preceded by $srcdir. */
1106 break;
1107 }
1108 }
1a97be37 1109
1f3233d1 1110 return basename;
1111}
1112
155e048d 1113/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
1a97be37 1114 INPUT_FILE is used by <lang>.
155e048d 1115
1116 This function should be written to assume that a file _is_ used
1117 if the situation is unclear. If it wrongly assumes a file _is_ used,
1118 a linker error will result. If it wrongly assumes a file _is not_ used,
1119 some GC roots may be missed, which is a much harder-to-debug problem. */
1120
1f3233d1 1121unsigned
1a97be37 1122get_base_file_bitmap (const char *input_file)
1f3233d1 1123{
1124 const char *basename = get_file_basename (input_file);
1125 const char *slashpos = strchr (basename, '/');
776c30b8 1126 unsigned j;
1127 unsigned k;
1128 unsigned bitmap;
1a97be37 1129
776c30b8 1130 if (slashpos)
1f3233d1 1131 {
1132 size_t i;
776c30b8 1133 for (i = 1; i < NUM_BASE_FILES; i++)
1134 if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
1135 && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
1136 {
1137 /* It's in a language directory, set that language. */
1138 bitmap = 1 << i;
1139 return bitmap;
1140 }
1141
1142 abort (); /* Should have found the language. */
1f3233d1 1143 }
776c30b8 1144
1145 /* If it's in any config-lang.in, then set for the languages
1146 specified. */
1147
1148 bitmap = 0;
1149
1150 for (j = 0; j < NUM_LANG_FILES; j++)
1151 {
1152 if (!strcmp(input_file, lang_files[j]))
1153 {
1154 for (k = 0; k < NUM_BASE_FILES; k++)
1155 {
1156 if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
1157 bitmap |= (1 << k);
1158 }
1159 }
1160 }
1a97be37 1161
776c30b8 1162 /* Otherwise, set all languages. */
1163 if (!bitmap)
1164 bitmap = (1 << NUM_BASE_FILES) - 1;
1165
1166 return bitmap;
1f3233d1 1167}
1168
155e048d 1169/* An output file, suitable for definitions, that can see declarations
1170 made in INPUT_FILE and is linked into every language that uses
1171 INPUT_FILE. */
1172
92570e7a 1173outf_p
1a97be37 1174get_output_file_with_visibility (const char *input_file)
1f3233d1 1175{
92570e7a 1176 outf_p r;
1f3233d1 1177 size_t len;
1178 const char *basename;
92570e7a 1179 const char *for_name;
1180 const char *output_name;
1f3233d1 1181
92570e7a 1182 /* This can happen when we need a file with visibility on a
1183 structure that we've never seen. We have to just hope that it's
1184 globally visible. */
1185 if (input_file == NULL)
1186 input_file = "system.h";
1f3233d1 1187
1f3233d1 1188 /* Determine the output file name. */
1189 basename = get_file_basename (input_file);
1190
1191 len = strlen (basename);
1192 if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
1193 || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
1194 || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
1195 {
1196 char *s;
1a97be37 1197
92570e7a 1198 output_name = s = xasprintf ("gt-%s", basename);
1f3233d1 1199 for (; *s != '.'; s++)
74863452 1200 if (! ISALNUM (*s) && *s != '-')
1f3233d1 1201 *s = '-';
1202 memcpy (s, ".h", sizeof (".h"));
92570e7a 1203 for_name = basename;
1f3233d1 1204 }
1205 else if (strcmp (basename, "c-common.h") == 0)
92570e7a 1206 output_name = "gt-c-common.h", for_name = "c-common.c";
1f3233d1 1207 else if (strcmp (basename, "c-tree.h") == 0)
92570e7a 1208 output_name = "gt-c-decl.h", for_name = "c-decl.c";
1a97be37 1209 else
1f3233d1 1210 {
1211 size_t i;
1a97be37 1212
1f3233d1 1213 for (i = 0; i < NUM_BASE_FILES; i++)
776c30b8 1214 if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
1215 && basename[strlen(lang_dir_names[i])] == '/')
92570e7a 1216 return base_files[i];
1217
1218 output_name = "gtype-desc.c";
1219 for_name = NULL;
1f3233d1 1220 }
1221
1222 /* Look through to see if we've ever seen this output filename before. */
92570e7a 1223 for (r = output_files; r; r = r->next)
1224 if (strcmp (r->name, output_name) == 0)
1225 return r;
1f3233d1 1226
1227 /* If not, create it. */
92570e7a 1228 r = create_file (for_name, output_name);
1f3233d1 1229
92570e7a 1230 return r;
1f3233d1 1231}
1232
155e048d 1233/* The name of an output file, suitable for definitions, that can see
1234 declarations made in INPUT_FILE and is linked into every language
1235 that uses INPUT_FILE. */
1236
1f3233d1 1237const char *
1a97be37 1238get_output_file_name (const char *input_file)
1f3233d1 1239{
92570e7a 1240 return get_output_file_with_visibility (input_file)->name;
1f3233d1 1241}
1242
92570e7a 1243/* Copy the output to its final destination,
155e048d 1244 but don't unnecessarily change modification times. */
1245
1f3233d1 1246static void
1a97be37 1247close_output_files (void)
1f3233d1 1248{
92570e7a 1249 outf_p of;
1a97be37 1250
92570e7a 1251 for (of = output_files; of; of = of->next)
1f3233d1 1252 {
92570e7a 1253 FILE * newfile;
1254
1255 newfile = fopen (of->name, "r");
1256 if (newfile != NULL )
1f3233d1 1257 {
92570e7a 1258 int no_write_p;
1259 size_t i;
1f3233d1 1260
92570e7a 1261 for (i = 0; i < of->bufused; i++)
1262 {
1263 int ch;
1264 ch = fgetc (newfile);
1265 if (ch == EOF || ch != (unsigned char) of->buf[i])
1266 break;
1267 }
1268 no_write_p = i == of->bufused && fgetc (newfile) == EOF;
1f3233d1 1269 fclose (newfile);
92570e7a 1270
1271 if (no_write_p)
1272 continue;
1f3233d1 1273 }
1274
92570e7a 1275 newfile = fopen (of->name, "w");
1f3233d1 1276 if (newfile == NULL)
1277 {
1278 perror ("opening output file");
1279 exit (1);
1280 }
92570e7a 1281 if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
1282 {
1283 perror ("writing output file");
1284 exit (1);
1285 }
1286 if (fclose (newfile) != 0)
1287 {
1288 perror ("closing output file");
1289 exit (1);
1290 }
1f3233d1 1291 }
1292}
1293\f
1294struct flist {
1295 struct flist *next;
1296 int started_p;
1297 const char *name;
92570e7a 1298 outf_p f;
1f3233d1 1299};
1300
573aba85 1301struct walk_type_data;
1302
1303/* For scalars and strings, given the item in 'val'.
1304 For structures, given a pointer to the item in 'val'.
1305 For misc. pointers, given the item in 'val'.
1306*/
1a97be37 1307typedef void (*process_field_fn)
1308 (type_p f, const struct walk_type_data *p);
573aba85 1309typedef void (*func_name_fn)
1a97be37 1310 (type_p s, const struct walk_type_data *p);
573aba85 1311
1312/* Parameters for write_types. */
1313
1a97be37 1314struct write_types_data
573aba85 1315{
1316 const char *prefix;
1317 const char *param_prefix;
1318 const char *subfield_marker_routine;
1319 const char *marker_routine;
1320 const char *reorder_note_routine;
1321 const char *comment;
1322};
1323
1a97be37 1324static void output_escaped_param (struct walk_type_data *d,
1325 const char *, const char *);
1326static void output_mangled_typename (outf_p, type_p);
1327static void walk_type (type_p t, struct walk_type_data *d);
573aba85 1328static void write_func_for_structure
1a97be37 1329 (type_p orig_s, type_p s, type_p * param,
1330 const struct write_types_data *wtd);
1331static void write_types_process_field
1332 (type_p f, const struct walk_type_data *d);
1333static void write_types (type_p structures,
1334 type_p param_structs,
1335 const struct write_types_data *wtd);
573aba85 1336static void write_types_local_process_field
1a97be37 1337 (type_p f, const struct walk_type_data *d);
573aba85 1338static void write_local_func_for_structure
1a97be37 1339 (type_p orig_s, type_p s, type_p * param);
1340static void write_local (type_p structures,
1341 type_p param_structs);
1342static void write_enum_defn (type_p structures, type_p param_structs);
1343static int contains_scalar_p (type_p t);
1344static void put_mangled_filename (outf_p , const char *);
1345static void finish_root_table (struct flist *flp, const char *pfx,
1346 const char *tname, const char *lastname,
1347 const char *name);
1348static void write_root (outf_p , pair_p, type_p, const char *, int,
1349 struct fileloc *, const char *);
1350static void write_array (outf_p f, pair_p v,
1351 const struct write_types_data *wtd);
1352static void write_roots (pair_p);
1f3233d1 1353
573aba85 1354/* Parameters for walk_type. */
1f3233d1 1355
573aba85 1356struct walk_type_data
1f3233d1 1357{
573aba85 1358 process_field_fn process_field;
1359 const void *cookie;
1360 outf_p of;
1361 options_p opt;
1362 const char *val;
1363 const char *prev_val[4];
1364 int indent;
1365 int counter;
1366 struct fileloc *line;
1367 lang_bitmap bitmap;
1368 type_p *param;
1369 int used_length;
1370 type_p orig_s;
1371 const char *reorder_fn;
c39ed964 1372 bool needs_cast_p;
1373 bool fn_wants_lvalue;
573aba85 1374};
c849df63 1375
1376/* Print a mangled name representing T to OF. */
1377
1378static void
1a97be37 1379output_mangled_typename (outf_p of, type_p t)
c849df63 1380{
1381 if (t == NULL)
1382 oprintf (of, "Z");
1383 else switch (t->kind)
1384 {
1385 case TYPE_POINTER:
1386 oprintf (of, "P");
1387 output_mangled_typename (of, t->u.p);
1388 break;
1389 case TYPE_SCALAR:
1390 oprintf (of, "I");
1391 break;
1392 case TYPE_STRING:
1393 oprintf (of, "S");
1394 break;
1395 case TYPE_STRUCT:
1396 case TYPE_UNION:
1397 case TYPE_LANG_STRUCT:
e72117bc 1398 oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag);
c849df63 1399 break;
1400 case TYPE_PARAM_STRUCT:
1401 {
1402 int i;
1403 for (i = 0; i < NUM_PARAM; i++)
1404 if (t->u.param_struct.param[i] != NULL)
1405 output_mangled_typename (of, t->u.param_struct.param[i]);
1a97be37 1406 output_mangled_typename (of, t->u.param_struct.stru);
c849df63 1407 }
1408 break;
1409 case TYPE_ARRAY:
1410 abort ();
1411 }
1f3233d1 1412}
1413
573aba85 1414/* Print PARAM to D->OF processing escapes. D->VAL references the
1415 current object, D->PREV_VAL the object containing the current
1416 object, ONAME is the name of the option and D->LINE is used to
1417 print error messages. */
155e048d 1418
1f3233d1 1419static void
1a97be37 1420output_escaped_param (struct walk_type_data *d, const char *param,
1421 const char *oname)
1f3233d1 1422{
573aba85 1423 const char *p;
1a97be37 1424
573aba85 1425 for (p = param; *p; p++)
1426 if (*p != '%')
1427 oprintf (d->of, "%c", *p);
1428 else switch (*++p)
1429 {
1430 case 'h':
1431 oprintf (d->of, "(%s)", d->prev_val[2]);
1432 break;
1433 case '0':
1434 oprintf (d->of, "(%s)", d->prev_val[0]);
1435 break;
1436 case '1':
1437 oprintf (d->of, "(%s)", d->prev_val[1]);
1438 break;
1439 case 'a':
1f3233d1 1440 {
573aba85 1441 const char *pp = d->val + strlen (d->val);
1442 while (pp[-1] == ']')
1443 while (*pp != '[')
1444 pp--;
1445 oprintf (d->of, "%s", pp);
1f3233d1 1446 }
573aba85 1447 break;
1448 default:
1449 error_at_line (d->line, "`%s' option contains bad escape %c%c",
1450 oname, '%', *p);
1451 }
1452}
1f3233d1 1453
573aba85 1454/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
1455 which is of type T. Write code to D->OF to constrain execution (at
1456 the point that D->PROCESS_FIELD is called) to the appropriate
b14c9131 1457 cases. Call D->PROCESS_FIELD on subobjects before calling it on
1458 pointers to those objects. D->PREV_VAL lists the objects
1459 containing the current object, D->OPT is a list of options to
1460 apply, D->INDENT is the current indentation level, D->LINE is used
1461 to print error messages, D->BITMAP indicates which languages to
1462 print the structure for, and D->PARAM is the current parameter
1463 (from an enclosing param_is option). */
1f3233d1 1464
573aba85 1465static void
1a97be37 1466walk_type (type_p t, struct walk_type_data *d)
573aba85 1467{
1468 const char *length = NULL;
1469 const char *desc = NULL;
1470 int maybe_undef_p = 0;
1471 int use_param_num = -1;
1472 int use_params_p = 0;
573aba85 1473 options_p oo;
8ed01400 1474 const struct nested_ptr_data *nested_ptr_d = NULL;
1a97be37 1475
c39ed964 1476 d->needs_cast_p = false;
573aba85 1477 for (oo = d->opt; oo; oo = oo->next)
1478 if (strcmp (oo->name, "length") == 0)
1479 length = (const char *)oo->info;
1480 else if (strcmp (oo->name, "maybe_undef") == 0)
1481 maybe_undef_p = 1;
1482 else if (strncmp (oo->name, "use_param", 9) == 0
1483 && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1484 use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
1485 else if (strcmp (oo->name, "use_params") == 0)
1486 use_params_p = 1;
1487 else if (strcmp (oo->name, "desc") == 0)
1488 desc = (const char *)oo->info;
8ed01400 1489 else if (strcmp (oo->name, "nested_ptr") == 0)
c39ed964 1490 nested_ptr_d = (const struct nested_ptr_data *) oo->info;
573aba85 1491 else if (strcmp (oo->name, "dot") == 0)
1492 ;
1493 else if (strcmp (oo->name, "tag") == 0)
1494 ;
1495 else if (strcmp (oo->name, "special") == 0)
1496 ;
1497 else if (strcmp (oo->name, "skip") == 0)
1498 ;
1499 else if (strcmp (oo->name, "default") == 0)
1500 ;
1501 else if (strcmp (oo->name, "descbits") == 0)
1502 ;
1503 else if (strcmp (oo->name, "param_is") == 0)
1504 ;
8578ce7b 1505 else if (strncmp (oo->name, "param", 5) == 0
1506 && ISDIGIT (oo->name[5])
1507 && strcmp (oo->name + 6, "_is") == 0)
1508 ;
573aba85 1509 else if (strcmp (oo->name, "chain_next") == 0)
1510 ;
1511 else if (strcmp (oo->name, "chain_prev") == 0)
1512 ;
1513 else if (strcmp (oo->name, "reorder") == 0)
1514 ;
1515 else
1516 error_at_line (d->line, "unknown option `%s'\n", oo->name);
c849df63 1517
573aba85 1518 if (d->used_length)
1519 length = NULL;
c849df63 1520
573aba85 1521 if (use_params_p)
1522 {
1523 int pointer_p = t->kind == TYPE_POINTER;
1a97be37 1524
573aba85 1525 if (pointer_p)
1526 t = t->u.p;
1527 if (! UNION_OR_STRUCT_P (t))
1528 error_at_line (d->line, "`use_params' option on unimplemented type");
1a97be37 1529 else
573aba85 1530 t = find_param_structure (t, d->param);
1531 if (pointer_p)
1532 t = create_pointer (t);
1533 }
1a97be37 1534
573aba85 1535 if (use_param_num != -1)
1536 {
1537 if (d->param != NULL && d->param[use_param_num] != NULL)
1f3233d1 1538 {
573aba85 1539 type_p nt = d->param[use_param_num];
1a97be37 1540
573aba85 1541 if (t->kind == TYPE_ARRAY)
1542 nt = create_array (nt, t->u.a.len);
1543 else if (length != NULL && t->kind == TYPE_POINTER)
1544 nt = create_pointer (nt);
b41d328d 1545 d->needs_cast_p = (t->kind != TYPE_POINTER
1546 && (nt->kind == TYPE_POINTER
1547 || nt->kind == TYPE_STRING));
573aba85 1548 t = nt;
1f3233d1 1549 }
573aba85 1550 else
1551 error_at_line (d->line, "no parameter defined for `%s'",
1552 d->val);
1553 }
1a97be37 1554
1555 if (maybe_undef_p
573aba85 1556 && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
1557 {
1a97be37 1558 error_at_line (d->line,
573aba85 1559 "field `%s' has invalid option `maybe_undef_p'\n",
1560 d->val);
1561 return;
1562 }
1a97be37 1563
573aba85 1564 switch (t->kind)
1565 {
1566 case TYPE_SCALAR:
1567 case TYPE_STRING:
1568 d->process_field (t, d);
1569 break;
1a97be37 1570
573aba85 1571 case TYPE_POINTER:
1572 {
1573 if (maybe_undef_p
1574 && t->u.p->u.s.line.file == NULL)
1575 {
1576 oprintf (d->of, "%*sif (%s) abort();\n", d->indent, "", d->val);
1577 break;
1578 }
1f3233d1 1579
573aba85 1580 if (! length)
1f3233d1 1581 {
573aba85 1582 if (! UNION_OR_STRUCT_P (t->u.p)
1583 && t->u.p->kind != TYPE_PARAM_STRUCT)
1f3233d1 1584 {
1a97be37 1585 error_at_line (d->line,
573aba85 1586 "field `%s' is pointer to unimplemented type",
1587 d->val);
1f3233d1 1588 break;
1589 }
1a97be37 1590
8ed01400 1591 if (nested_ptr_d)
1592 {
1593 const char *oldprevval2 = d->prev_val[2];
1594
1595 if (! UNION_OR_STRUCT_P (nested_ptr_d->type))
1596 {
1597 error_at_line (d->line,
1598 "field `%s' has invalid "
1599 "option `nested_ptr'\n",
1600 d->val);
1601 return;
1602 }
1603
1604 d->prev_val[2] = d->val;
1605 oprintf (d->of, "%*s{\n", d->indent, "");
1606 d->indent += 2;
1607 d->val = xasprintf ("x%d", d->counter++);
c39ed964 1608 oprintf (d->of, "%*s%s %s * %s%s =\n", d->indent, "",
8ed01400 1609 (nested_ptr_d->type->kind == TYPE_UNION
1610 ? "union" : "struct"),
c39ed964 1611 nested_ptr_d->type->u.s.tag,
1612 d->fn_wants_lvalue ? "" : "const ",
1613 d->val);
8ed01400 1614 oprintf (d->of, "%*s", d->indent + 2, "");
1615 output_escaped_param (d, nested_ptr_d->convert_from,
1616 "nested_ptr");
1617 oprintf (d->of, ";\n");
1618
1619 d->process_field (nested_ptr_d->type, d);
1620
c39ed964 1621 if (d->fn_wants_lvalue)
1622 {
1623 oprintf (d->of, "%*s%s = ", d->indent, "",
1624 d->prev_val[2]);
1625 d->prev_val[2] = d->val;
1626 output_escaped_param (d, nested_ptr_d->convert_to,
1627 "nested_ptr");
1628 oprintf (d->of, ";\n");
1629 }
8ed01400 1630
1631 d->indent -= 2;
1632 oprintf (d->of, "%*s}\n", d->indent, "");
1633 d->val = d->prev_val[2];
1634 d->prev_val[2] = oldprevval2;
1635 }
1636 else
1637 d->process_field (t->u.p, d);
1f3233d1 1638 }
1a97be37 1639 else
1f3233d1 1640 {
573aba85 1641 int loopcounter = d->counter++;
1642 const char *oldval = d->val;
1643 const char *oldprevval3 = d->prev_val[3];
1f3233d1 1644 char *newval;
1645
573aba85 1646 oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
1647 d->indent += 2;
1648 oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1a97be37 1649 oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
573aba85 1650 loopcounter, loopcounter);
1651 output_escaped_param (d, length, "length");
1652 oprintf (d->of, "); i%d++) {\n", loopcounter);
1653 d->indent += 2;
1654 d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1655 d->used_length = 1;
1656 d->prev_val[3] = oldval;
1657 walk_type (t->u.p, d);
1f3233d1 1658 free (newval);
573aba85 1659 d->val = oldval;
1660 d->prev_val[3] = oldprevval3;
1661 d->used_length = 0;
1662 d->indent -= 2;
1663 oprintf (d->of, "%*s}\n", d->indent, "");
b14c9131 1664 d->process_field(t, d);
573aba85 1665 d->indent -= 2;
1666 oprintf (d->of, "%*s}\n", d->indent, "");
1f3233d1 1667 }
573aba85 1668 }
1669 break;
1f3233d1 1670
573aba85 1671 case TYPE_ARRAY:
1672 {
1673 int loopcounter = d->counter++;
1674 const char *oldval = d->val;
1675 char *newval;
1676
7ef5b942 1677 /* If it's an array of scalars, we optimize by not generating
573aba85 1678 any code. */
1679 if (t->u.a.p->kind == TYPE_SCALAR)
1f3233d1 1680 break;
1a97be37 1681
573aba85 1682 oprintf (d->of, "%*s{\n", d->indent, "");
1683 d->indent += 2;
1684 oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1a97be37 1685 oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
573aba85 1686 loopcounter, loopcounter);
1687 if (length)
1688 output_escaped_param (d, length, "length");
1689 else
1690 oprintf (d->of, "%s", t->u.a.len);
1691 oprintf (d->of, "); i%d++) {\n", loopcounter);
1692 d->indent += 2;
1693 d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1694 d->used_length = 1;
1695 walk_type (t->u.a.p, d);
1696 free (newval);
1697 d->used_length = 0;
1698 d->val = oldval;
1699 d->indent -= 2;
1700 oprintf (d->of, "%*s}\n", d->indent, "");
1701 d->indent -= 2;
1702 oprintf (d->of, "%*s}\n", d->indent, "");
1703 }
1704 break;
1a97be37 1705
573aba85 1706 case TYPE_STRUCT:
1707 case TYPE_UNION:
1708 {
1709 pair_p f;
1710 const char *oldval = d->val;
1711 const char *oldprevval1 = d->prev_val[1];
1712 const char *oldprevval2 = d->prev_val[2];
1713 const int union_p = t->kind == TYPE_UNION;
1714 int seen_default_p = 0;
1715 options_p o;
1716
1717 if (! t->u.s.line.file)
1718 error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
1f3233d1 1719
573aba85 1720 if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
1f3233d1 1721 {
573aba85 1722 error_at_line (d->line,
1723 "structure `%s' defined for mismatching languages",
1724 t->u.s.tag);
1725 error_at_line (&t->u.s.line, "one structure defined here");
1726 }
1f3233d1 1727
573aba85 1728 /* Some things may also be defined in the structure's options. */
1729 for (o = t->u.s.opt; o; o = o->next)
1730 if (! desc && strcmp (o->name, "desc") == 0)
1731 desc = (const char *)o->info;
1f3233d1 1732
573aba85 1733 d->prev_val[2] = oldval;
1734 d->prev_val[1] = oldprevval2;
1735 if (union_p)
1736 {
1737 if (desc == NULL)
1f3233d1 1738 {
573aba85 1739 error_at_line (d->line, "missing `desc' option for union `%s'",
1740 t->u.s.tag);
1741 desc = "1";
1f3233d1 1742 }
573aba85 1743 oprintf (d->of, "%*sswitch (", d->indent, "");
1744 output_escaped_param (d, desc, "desc");
1745 oprintf (d->of, ")\n");
1746 d->indent += 2;
1747 oprintf (d->of, "%*s{\n", d->indent, "");
1748 }
1749 for (f = t->u.s.fields; f; f = f->next)
1750 {
1751 options_p oo;
1752 const char *dot = ".";
1753 const char *tagid = NULL;
1754 int skip_p = 0;
1755 int default_p = 0;
1756 int use_param_p = 0;
1757 char *newval;
1758
1759 d->reorder_fn = NULL;
1760 for (oo = f->opt; oo; oo = oo->next)
1761 if (strcmp (oo->name, "dot") == 0)
1762 dot = (const char *)oo->info;
1763 else if (strcmp (oo->name, "tag") == 0)
1764 tagid = (const char *)oo->info;
1765 else if (strcmp (oo->name, "skip") == 0)
1766 skip_p = 1;
1767 else if (strcmp (oo->name, "default") == 0)
1768 default_p = 1;
1769 else if (strcmp (oo->name, "reorder") == 0)
1770 d->reorder_fn = (const char *)oo->info;
1771 else if (strncmp (oo->name, "use_param", 9) == 0
1772 && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1773 use_param_p = 1;
1774
1775 if (skip_p)
1776 continue;
1777
1778 if (union_p && tagid)
1f3233d1 1779 {
573aba85 1780 oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
1781 d->indent += 2;
1f3233d1 1782 }
573aba85 1783 else if (union_p && default_p)
1f3233d1 1784 {
573aba85 1785 oprintf (d->of, "%*sdefault:\n", d->indent, "");
1786 d->indent += 2;
1787 seen_default_p = 1;
1f3233d1 1788 }
573aba85 1789 else if (! union_p && (default_p || tagid))
1a97be37 1790 error_at_line (d->line,
573aba85 1791 "can't use `%s' outside a union on field `%s'",
1792 default_p ? "default" : "tag", f->name);
1793 else if (union_p && ! (default_p || tagid)
1794 && f->type->kind == TYPE_SCALAR)
1f3233d1 1795 {
573aba85 1796 fprintf (stderr,
1797 "%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
1798 d->line->file, d->line->line, f->name);
1799 continue;
1f3233d1 1800 }
573aba85 1801 else if (union_p && ! (default_p || tagid))
1a97be37 1802 error_at_line (d->line,
573aba85 1803 "field `%s' is missing `tag' or `default' option",
1f3233d1 1804 f->name);
1a97be37 1805
573aba85 1806 d->line = &f->line;
1807 d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
1808 d->opt = f->opt;
c39ed964 1809 d->used_length = false;
573aba85 1810
1811 if (union_p && use_param_p && d->param == NULL)
1812 oprintf (d->of, "%*sabort();\n", d->indent, "");
1813 else
1814 walk_type (f->type, d);
1815
1816 free (newval);
1817
1818 if (union_p)
1f3233d1 1819 {
573aba85 1820 oprintf (d->of, "%*sbreak;\n", d->indent, "");
1821 d->indent -= 2;
1f3233d1 1822 }
573aba85 1823 }
1824 d->reorder_fn = NULL;
1f3233d1 1825
573aba85 1826 d->val = oldval;
1827 d->prev_val[1] = oldprevval1;
1828 d->prev_val[2] = oldprevval2;
1829
1830 if (union_p && ! seen_default_p)
1831 {
1832 oprintf (d->of, "%*sdefault:\n", d->indent, "");
1833 oprintf (d->of, "%*s break;\n", d->indent, "");
1834 }
1835 if (union_p)
1836 {
1837 oprintf (d->of, "%*s}\n", d->indent, "");
1838 d->indent -= 2;
1f3233d1 1839 }
573aba85 1840 }
1841 break;
1f3233d1 1842
573aba85 1843 case TYPE_LANG_STRUCT:
1844 {
1845 type_p nt;
1846 for (nt = t->u.s.lang_struct; nt; nt = nt->next)
1847 if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
1848 break;
1849 if (nt == NULL)
1850 error_at_line (d->line, "structure `%s' differs between languages",
1851 t->u.s.tag);
1852 else
1853 walk_type (nt, d);
1854 }
1855 break;
1856
1857 case TYPE_PARAM_STRUCT:
1858 {
1859 type_p *oldparam = d->param;
1a97be37 1860
573aba85 1861 d->param = t->u.param_struct.param;
1862 walk_type (t->u.param_struct.stru, d);
1863 d->param = oldparam;
1864 }
1865 break;
1a97be37 1866
573aba85 1867 default:
1868 abort ();
1f3233d1 1869 }
573aba85 1870}
1871
1872/* process_field routine for marking routines. */
1873
1874static void
1a97be37 1875write_types_process_field (type_p f, const struct walk_type_data *d)
573aba85 1876{
1877 const struct write_types_data *wtd;
b41d328d 1878 const char *cast = d->needs_cast_p ? "(void *)" : "";
573aba85 1879 wtd = (const struct write_types_data *) d->cookie;
1a97be37 1880
573aba85 1881 switch (f->kind)
1f3233d1 1882 {
573aba85 1883 case TYPE_POINTER:
1a97be37 1884 oprintf (d->of, "%*s%s (%s%s", d->indent, "",
b41d328d 1885 wtd->subfield_marker_routine, cast, d->val);
573aba85 1886 if (wtd->param_prefix)
c849df63 1887 {
573aba85 1888 oprintf (d->of, ", %s", d->prev_val[3]);
1889 if (d->orig_s)
1890 {
1891 oprintf (d->of, ", gt_%s_", wtd->param_prefix);
1892 output_mangled_typename (d->of, d->orig_s);
1893 }
1894 else
1895 oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
c849df63 1896 }
573aba85 1897 oprintf (d->of, ");\n");
1898 if (d->reorder_fn && wtd->reorder_note_routine)
1a97be37 1899 oprintf (d->of, "%*s%s (%s%s, %s, %s);\n", d->indent, "",
b41d328d 1900 wtd->reorder_note_routine, cast, d->val,
573aba85 1901 d->prev_val[3], d->reorder_fn);
1902 break;
1903
1904 case TYPE_STRING:
1905 if (wtd->param_prefix == NULL)
1906 break;
1907
1908 case TYPE_STRUCT:
1909 case TYPE_UNION:
1910 case TYPE_LANG_STRUCT:
1911 case TYPE_PARAM_STRUCT:
1912 oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
1913 output_mangled_typename (d->of, f);
b41d328d 1914 oprintf (d->of, " (%s%s);\n", cast, d->val);
573aba85 1915 if (d->reorder_fn && wtd->reorder_note_routine)
1a97be37 1916 oprintf (d->of, "%*s%s (%s%s, %s%s, %s);\n", d->indent, "",
b41d328d 1917 wtd->reorder_note_routine, cast, d->val, cast, d->val,
573aba85 1918 d->reorder_fn);
1919 break;
1920
1921 case TYPE_SCALAR:
1922 break;
1a97be37 1923
573aba85 1924 default:
1925 abort ();
1f3233d1 1926 }
1927}
1928
573aba85 1929/* For S, a structure that's part of ORIG_S, and using parameters
1930 PARAM, write out a routine that:
1931 - Takes a parameter, a void * but actually of type *S
1932 - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
1933 field of S or its substructures and (in some cases) things
1934 that are pointed to by S.
1935*/
155e048d 1936
1f3233d1 1937static void
00775b04 1938write_func_for_structure (type_p orig_s, type_p s, type_p *param,
1939 const struct write_types_data *wtd)
1f3233d1 1940{
c849df63 1941 const char *fn = s->u.s.line.file;
1942 int i;
1943 const char *chain_next = NULL;
1944 const char *chain_prev = NULL;
1945 options_p opt;
573aba85 1946 struct walk_type_data d;
1a97be37 1947
c849df63 1948 /* This is a hack, and not the good kind either. */
1949 for (i = NUM_PARAM - 1; i >= 0; i--)
1a97be37 1950 if (param && param[i] && param[i]->kind == TYPE_POINTER
c849df63 1951 && UNION_OR_STRUCT_P (param[i]->u.p))
1952 fn = param[i]->u.p->u.s.line.file;
1a97be37 1953
573aba85 1954 memset (&d, 0, sizeof (d));
1955 d.of = get_output_file_with_visibility (fn);
1a97be37 1956
c849df63 1957 for (opt = s->u.s.opt; opt; opt = opt->next)
1958 if (strcmp (opt->name, "chain_next") == 0)
1959 chain_next = (const char *) opt->info;
1960 else if (strcmp (opt->name, "chain_prev") == 0)
1961 chain_prev = (const char *) opt->info;
1962
1963 if (chain_prev != NULL && chain_next == NULL)
1964 error_at_line (&s->u.s.line, "chain_prev without chain_next");
1965
573aba85 1966 d.process_field = write_types_process_field;
1967 d.cookie = wtd;
1968 d.orig_s = orig_s;
1969 d.opt = s->u.s.opt;
1970 d.line = &s->u.s.line;
1971 d.bitmap = s->u.s.bitmap;
1972 d.param = param;
1973 d.prev_val[0] = "*x";
21dda4ee 1974 d.prev_val[1] = "not valid postage"; /* Guarantee an error. */
573aba85 1975 d.prev_val[3] = "x";
1976 d.val = "(*x)";
1977
1978 oprintf (d.of, "\n");
1979 oprintf (d.of, "void\n");
1f3233d1 1980 if (param == NULL)
573aba85 1981 oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
1f3233d1 1982 else
c849df63 1983 {
573aba85 1984 oprintf (d.of, "gt_%s_", wtd->prefix);
1985 output_mangled_typename (d.of, orig_s);
c849df63 1986 }
69dc4d00 1987 oprintf (d.of, " (void *x_p)\n");
573aba85 1988 oprintf (d.of, "{\n");
1989 oprintf (d.of, " %s %s * %sx = (%s %s *)x_p;\n",
1f3233d1 1990 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
c849df63 1991 chain_next == NULL ? "const " : "",
1f3233d1 1992 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
c849df63 1993 if (chain_next != NULL)
573aba85 1994 oprintf (d.of, " %s %s * xlimit = x;\n",
c849df63 1995 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1996 if (chain_next == NULL)
573aba85 1997 {
1998 oprintf (d.of, " if (%s (x", wtd->marker_routine);
1999 if (wtd->param_prefix)
2000 {
2001 oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
2002 output_mangled_typename (d.of, orig_s);
2003 }
2004 oprintf (d.of, "))\n");
2005 }
c849df63 2006 else
2007 {
573aba85 2008 oprintf (d.of, " while (%s (xlimit", wtd->marker_routine);
2009 if (wtd->param_prefix)
2010 {
2011 oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
2012 output_mangled_typename (d.of, orig_s);
2013 }
2014 oprintf (d.of, "))\n");
2015 oprintf (d.of, " xlimit = (");
2016 d.prev_val[2] = "*xlimit";
2017 output_escaped_param (&d, chain_next, "chain_next");
2018 oprintf (d.of, ");\n");
c849df63 2019 if (chain_prev != NULL)
2020 {
573aba85 2021 oprintf (d.of, " if (x != xlimit)\n");
2022 oprintf (d.of, " for (;;)\n");
2023 oprintf (d.of, " {\n");
2024 oprintf (d.of, " %s %s * const xprev = (",
c849df63 2025 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1a97be37 2026
573aba85 2027 d.prev_val[2] = "*x";
2028 output_escaped_param (&d, chain_prev, "chain_prev");
2029 oprintf (d.of, ");\n");
2030 oprintf (d.of, " if (xprev == NULL) break;\n");
2031 oprintf (d.of, " x = xprev;\n");
1a97be37 2032 oprintf (d.of, " (void) %s (xprev",
573aba85 2033 wtd->marker_routine);
2034 if (wtd->param_prefix)
2035 {
2036 oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
2037 output_mangled_typename (d.of, orig_s);
2038 }
2039 oprintf (d.of, ");\n");
2040 oprintf (d.of, " }\n");
c849df63 2041 }
573aba85 2042 oprintf (d.of, " while (x != xlimit)\n");
c849df63 2043 }
573aba85 2044 oprintf (d.of, " {\n");
1a97be37 2045
573aba85 2046 d.prev_val[2] = "*x";
2047 d.indent = 6;
2048 walk_type (s, &d);
1a97be37 2049
c849df63 2050 if (chain_next != NULL)
2051 {
573aba85 2052 oprintf (d.of, " x = (");
2053 output_escaped_param (&d, chain_next, "chain_next");
2054 oprintf (d.of, ");\n");
c849df63 2055 }
2056
573aba85 2057 oprintf (d.of, " }\n");
2058 oprintf (d.of, "}\n");
1f3233d1 2059}
155e048d 2060
2061/* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */
1f3233d1 2062
2063static void
1a97be37 2064write_types (type_p structures, type_p param_structs,
2065 const struct write_types_data *wtd)
1f3233d1 2066{
2067 type_p s;
1a97be37 2068
573aba85 2069 oprintf (header_file, "\n/* %s*/\n", wtd->comment);
1f3233d1 2070 for (s = structures; s; s = s->next)
2071 if (s->gc_used == GC_POINTED_TO
2072 || s->gc_used == GC_MAYBE_POINTED_TO)
2073 {
2074 options_p opt;
1a97be37 2075
1f3233d1 2076 if (s->gc_used == GC_MAYBE_POINTED_TO
2077 && s->u.s.line.file == NULL)
2078 continue;
2079
573aba85 2080 oprintf (header_file, "#define gt_%s_", wtd->prefix);
c849df63 2081 output_mangled_typename (header_file, s);
2082 oprintf (header_file, "(X) do { \\\n");
92570e7a 2083 oprintf (header_file,
1a97be37 2084 " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
573aba85 2085 s->u.s.tag);
92570e7a 2086 oprintf (header_file,
1f3233d1 2087 " } while (0)\n");
1a97be37 2088
1f3233d1 2089 for (opt = s->u.s.opt; opt; opt = opt->next)
2090 if (strcmp (opt->name, "ptr_alias") == 0)
2091 {
2092 type_p t = (type_p) opt->info;
1a97be37 2093 if (t->kind == TYPE_STRUCT
1f3233d1 2094 || t->kind == TYPE_UNION
2095 || t->kind == TYPE_LANG_STRUCT)
92570e7a 2096 oprintf (header_file,
573aba85 2097 "#define gt_%sx_%s gt_%sx_%s\n",
2098 wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
1f3233d1 2099 else
1a97be37 2100 error_at_line (&s->u.s.line,
1f3233d1 2101 "structure alias is not a structure");
2102 break;
2103 }
2104 if (opt)
2105 continue;
2106
2107 /* Declare the marker procedure only once. */
1a97be37 2108 oprintf (header_file,
2109 "extern void gt_%sx_%s (void *);\n",
573aba85 2110 wtd->prefix, s->u.s.tag);
1a97be37 2111
1f3233d1 2112 if (s->u.s.line.file == NULL)
2113 {
1a97be37 2114 fprintf (stderr, "warning: structure `%s' used but not defined\n",
1f3233d1 2115 s->u.s.tag);
2116 continue;
2117 }
1a97be37 2118
1f3233d1 2119 if (s->kind == TYPE_LANG_STRUCT)
2120 {
2121 type_p ss;
2122 for (ss = s->u.s.lang_struct; ss; ss = ss->next)
573aba85 2123 write_func_for_structure (s, ss, NULL, wtd);
1f3233d1 2124 }
2125 else
573aba85 2126 write_func_for_structure (s, s, NULL, wtd);
1f3233d1 2127 }
2128
2129 for (s = param_structs; s; s = s->next)
2130 if (s->gc_used == GC_POINTED_TO)
2131 {
c849df63 2132 type_p * param = s->u.param_struct.param;
1f3233d1 2133 type_p stru = s->u.param_struct.stru;
2134
1f3233d1 2135 /* Declare the marker procedure. */
573aba85 2136 oprintf (header_file, "extern void gt_%s_", wtd->prefix);
c849df63 2137 output_mangled_typename (header_file, s);
1a97be37 2138 oprintf (header_file, " (void *);\n");
2139
1f3233d1 2140 if (stru->u.s.line.file == NULL)
2141 {
1a97be37 2142 fprintf (stderr, "warning: structure `%s' used but not defined\n",
1f3233d1 2143 s->u.s.tag);
2144 continue;
2145 }
1a97be37 2146
1f3233d1 2147 if (stru->kind == TYPE_LANG_STRUCT)
2148 {
2149 type_p ss;
2150 for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
573aba85 2151 write_func_for_structure (s, ss, param, wtd);
2152 }
2153 else
2154 write_func_for_structure (s, stru, param, wtd);
2155 }
2156}
2157
2158static const struct write_types_data ggc_wtd =
2159{
2160 "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
2161 "GC marker procedures. "
2162};
2163
2164static const struct write_types_data pch_wtd =
2165{
2166 "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
2167 "gt_pch_note_reorder",
2168 "PCH type-walking procedures. "
2169};
2170
2171/* Write out the local pointer-walking routines. */
2172
2173/* process_field routine for local pointer-walking. */
2174
2175static void
1a97be37 2176write_types_local_process_field (type_p f, const struct walk_type_data *d)
573aba85 2177{
2178 switch (f->kind)
2179 {
2180 case TYPE_POINTER:
2181 case TYPE_STRUCT:
2182 case TYPE_UNION:
2183 case TYPE_LANG_STRUCT:
2184 case TYPE_PARAM_STRUCT:
2185 case TYPE_STRING:
2186 oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
2187 d->prev_val[3]);
2188 oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
2189 break;
2190
2191 case TYPE_SCALAR:
2192 break;
1a97be37 2193
573aba85 2194 default:
2195 abort ();
2196 }
2197}
2198
2199/* For S, a structure that's part of ORIG_S, and using parameters
2200 PARAM, write out a routine that:
2201 - Is of type gt_note_pointers
c39ed964 2202 - Calls PROCESS_FIELD on each field of S or its substructures.
573aba85 2203*/
2204
2205static void
1a97be37 2206write_local_func_for_structure (type_p orig_s, type_p s, type_p *param)
573aba85 2207{
2208 const char *fn = s->u.s.line.file;
2209 int i;
2210 struct walk_type_data d;
1a97be37 2211
573aba85 2212 /* This is a hack, and not the good kind either. */
2213 for (i = NUM_PARAM - 1; i >= 0; i--)
1a97be37 2214 if (param && param[i] && param[i]->kind == TYPE_POINTER
573aba85 2215 && UNION_OR_STRUCT_P (param[i]->u.p))
2216 fn = param[i]->u.p->u.s.line.file;
1a97be37 2217
573aba85 2218 memset (&d, 0, sizeof (d));
2219 d.of = get_output_file_with_visibility (fn);
1a97be37 2220
573aba85 2221 d.process_field = write_types_local_process_field;
2222 d.opt = s->u.s.opt;
2223 d.line = &s->u.s.line;
2224 d.bitmap = s->u.s.bitmap;
2225 d.param = param;
2226 d.prev_val[0] = d.prev_val[2] = "*x";
21dda4ee 2227 d.prev_val[1] = "not valid postage"; /* Guarantee an error. */
573aba85 2228 d.prev_val[3] = "x";
2229 d.val = "(*x)";
c39ed964 2230 d.fn_wants_lvalue = true;
573aba85 2231
2232 oprintf (d.of, "\n");
2233 oprintf (d.of, "void\n");
2234 oprintf (d.of, "gt_pch_p_");
2235 output_mangled_typename (d.of, orig_s);
69dc4d00 2236 oprintf (d.of, " (void *this_obj ATTRIBUTE_UNUSED,\n\tvoid *x_p,\n\tgt_pointer_operator op ATTRIBUTE_UNUSED,\n\tvoid *cookie ATTRIBUTE_UNUSED)\n");
573aba85 2237 oprintf (d.of, "{\n");
2238 oprintf (d.of, " %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
2239 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2240 s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2241 d.indent = 2;
2242 walk_type (s, &d);
2243 oprintf (d.of, "}\n");
2244}
2245
2246/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS. */
2247
2248static void
1a97be37 2249write_local (type_p structures, type_p param_structs)
573aba85 2250{
2251 type_p s;
1a97be37 2252
573aba85 2253 oprintf (header_file, "\n/* Local pointer-walking routines. */\n");
2254 for (s = structures; s; s = s->next)
2255 if (s->gc_used == GC_POINTED_TO
2256 || s->gc_used == GC_MAYBE_POINTED_TO)
2257 {
2258 options_p opt;
1a97be37 2259
573aba85 2260 if (s->u.s.line.file == NULL)
2261 continue;
2262
2263 for (opt = s->u.s.opt; opt; opt = opt->next)
2264 if (strcmp (opt->name, "ptr_alias") == 0)
2265 {
2266 type_p t = (type_p) opt->info;
1a97be37 2267 if (t->kind == TYPE_STRUCT
573aba85 2268 || t->kind == TYPE_UNION
2269 || t->kind == TYPE_LANG_STRUCT)
2270 {
2271 oprintf (header_file, "#define gt_pch_p_");
2272 output_mangled_typename (header_file, s);
2273 oprintf (header_file, " gt_pch_p_");
2274 output_mangled_typename (header_file, t);
2275 oprintf (header_file, "\n");
2276 }
2277 else
1a97be37 2278 error_at_line (&s->u.s.line,
573aba85 2279 "structure alias is not a structure");
2280 break;
2281 }
2282 if (opt)
2283 continue;
2284
2285 /* Declare the marker procedure only once. */
2286 oprintf (header_file, "extern void gt_pch_p_");
2287 output_mangled_typename (header_file, s);
1a97be37 2288 oprintf (header_file,
2289 "\n (void *, void *, gt_pointer_operator, void *);\n");
2290
573aba85 2291 if (s->kind == TYPE_LANG_STRUCT)
2292 {
2293 type_p ss;
2294 for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2295 write_local_func_for_structure (s, ss, NULL);
2296 }
2297 else
2298 write_local_func_for_structure (s, s, NULL);
2299 }
2300
2301 for (s = param_structs; s; s = s->next)
2302 if (s->gc_used == GC_POINTED_TO)
2303 {
2304 type_p * param = s->u.param_struct.param;
2305 type_p stru = s->u.param_struct.stru;
2306
2307 /* Declare the marker procedure. */
2308 oprintf (header_file, "extern void gt_pch_p_");
2309 output_mangled_typename (header_file, s);
1a97be37 2310 oprintf (header_file,
2311 "\n (void *, void *, gt_pointer_operator, void *);\n");
2312
573aba85 2313 if (stru->u.s.line.file == NULL)
2314 {
1a97be37 2315 fprintf (stderr, "warning: structure `%s' used but not defined\n",
573aba85 2316 s->u.s.tag);
2317 continue;
2318 }
1a97be37 2319
573aba85 2320 if (stru->kind == TYPE_LANG_STRUCT)
2321 {
2322 type_p ss;
2323 for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2324 write_local_func_for_structure (s, ss, param);
1f3233d1 2325 }
2326 else
573aba85 2327 write_local_func_for_structure (s, stru, param);
c849df63 2328 }
2329}
2330
2331/* Write out the 'enum' definition for gt_types_enum. */
2332
2333static void
00775b04 2334write_enum_defn (type_p structures, type_p param_structs)
c849df63 2335{
2336 type_p s;
1a97be37 2337
c849df63 2338 oprintf (header_file, "\n/* Enumeration of types known. */\n");
2339 oprintf (header_file, "enum gt_types_enum {\n");
2340 for (s = structures; s; s = s->next)
2341 if (s->gc_used == GC_POINTED_TO
2342 || s->gc_used == GC_MAYBE_POINTED_TO)
2343 {
2344 if (s->gc_used == GC_MAYBE_POINTED_TO
2345 && s->u.s.line.file == NULL)
2346 continue;
2347
2348 oprintf (header_file, " gt_ggc_e_");
2349 output_mangled_typename (header_file, s);
2350 oprintf (header_file, ", \n");
1f3233d1 2351 }
c849df63 2352 for (s = param_structs; s; s = s->next)
2353 if (s->gc_used == GC_POINTED_TO)
2354 {
2355 oprintf (header_file, " gt_e_");
2356 output_mangled_typename (header_file, s);
2357 oprintf (header_file, ", \n");
2358 }
2359 oprintf (header_file, " gt_types_enum_last\n");
2360 oprintf (header_file, "};\n");
1f3233d1 2361}
2362
573aba85 2363/* Might T contain any non-pointer elements? */
2364
2365static int
1a97be37 2366contains_scalar_p (type_p t)
573aba85 2367{
2368 switch (t->kind)
2369 {
2370 case TYPE_STRING:
2371 case TYPE_POINTER:
2372 return 0;
2373 case TYPE_ARRAY:
2374 return contains_scalar_p (t->u.a.p);
2375 default:
2376 /* Could also check for structures that have no non-pointer
2377 fields, but there aren't enough of those to worry about. */
2378 return 1;
2379 }
2380}
c849df63 2381
155e048d 2382/* Mangle FN and print it to F. */
2383
1f3233d1 2384static void
1a97be37 2385put_mangled_filename (outf_p f, const char *fn)
1f3233d1 2386{
2387 const char *name = get_output_file_name (fn);
2388 for (; *name != 0; name++)
74863452 2389 if (ISALNUM (*name))
92570e7a 2390 oprintf (f, "%c", *name);
1f3233d1 2391 else
92570e7a 2392 oprintf (f, "%c", '_');
1f3233d1 2393}
2394
155e048d 2395/* Finish off the currently-created root tables in FLP. PFX, TNAME,
2396 LASTNAME, and NAME are all strings to insert in various places in
2397 the resulting code. */
2398
1f3233d1 2399static void
1a97be37 2400finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
2401 const char *tname, const char *name)
1f3233d1 2402{
2403 struct flist *fli2;
1a97be37 2404
1f3233d1 2405 for (fli2 = flp; fli2; fli2 = fli2->next)
2406 if (fli2->started_p)
2407 {
92570e7a 2408 oprintf (fli2->f, " %s\n", lastname);
2409 oprintf (fli2->f, "};\n\n");
1f3233d1 2410 }
2411
2412 for (fli2 = flp; fli2; fli2 = fli2->next)
2413 if (fli2->started_p)
2414 {
2415 lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2416 int fnum;
2417
2418 for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2419 if (bitmap & 1)
2420 {
92570e7a 2421 oprintf (base_files[fnum],
573aba85 2422 "extern const struct %s gt_%s_",
1f3233d1 2423 tname, pfx);
2424 put_mangled_filename (base_files[fnum], fli2->name);
92570e7a 2425 oprintf (base_files[fnum], "[];\n");
1f3233d1 2426 }
2427 }
1a97be37 2428
573aba85 2429 {
2430 size_t fnum;
2431 for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2432 oprintf (base_files [fnum],
2433 "const struct %s * const %s[] = {\n",
2434 tname, name);
2435 }
1a97be37 2436
1f3233d1 2437
2438 for (fli2 = flp; fli2; fli2 = fli2->next)
2439 if (fli2->started_p)
2440 {
2441 lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2442 int fnum;
2443
2444 fli2->started_p = 0;
2445
2446 for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2447 if (bitmap & 1)
2448 {
573aba85 2449 oprintf (base_files[fnum], " gt_%s_", pfx);
1f3233d1 2450 put_mangled_filename (base_files[fnum], fli2->name);
92570e7a 2451 oprintf (base_files[fnum], ",\n");
1f3233d1 2452 }
2453 }
2454
2455 {
573aba85 2456 size_t fnum;
2457 for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2458 {
2459 oprintf (base_files[fnum], " NULL\n");
2460 oprintf (base_files[fnum], "};\n");
2461 }
1f3233d1 2462 }
2463}
2464
155e048d 2465/* Write out to F the table entry and any marker routines needed to
2466 mark NAME as TYPE. The original variable is V, at LINE.
2467 HAS_LENGTH is nonzero iff V was a variable-length array. IF_MARKED
2468 is nonzero iff we are building the root table for hash table caches. */
2469
1f3233d1 2470static void
1a97be37 2471write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
2472 struct fileloc *line, const char *if_marked)
1f3233d1 2473{
2474 switch (type->kind)
2475 {
2476 case TYPE_STRUCT:
2477 {
2478 pair_p fld;
2479 for (fld = type->u.s.fields; fld; fld = fld->next)
2480 {
2481 int skip_p = 0;
2482 const char *desc = NULL;
2483 options_p o;
1a97be37 2484
1f3233d1 2485 for (o = fld->opt; o; o = o->next)
2486 if (strcmp (o->name, "skip") == 0)
2487 skip_p = 1;
2488 else if (strcmp (o->name, "desc") == 0)
2489 desc = (const char *)o->info;
2490 else
2491 error_at_line (line,
2492 "field `%s' of global `%s' has unknown option `%s'",
2493 fld->name, name, o->name);
1a97be37 2494
1f3233d1 2495 if (skip_p)
2496 continue;
2497 else if (desc && fld->type->kind == TYPE_UNION)
2498 {
2499 pair_p validf = NULL;
2500 pair_p ufld;
1a97be37 2501
1f3233d1 2502 for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
2503 {
2504 const char *tag = NULL;
2505 options_p oo;
1a97be37 2506
1f3233d1 2507 for (oo = ufld->opt; oo; oo = oo->next)
2508 if (strcmp (oo->name, "tag") == 0)
2509 tag = (const char *)oo->info;
2510 if (tag == NULL || strcmp (tag, desc) != 0)
2511 continue;
2512 if (validf != NULL)
1a97be37 2513 error_at_line (line,
1f3233d1 2514 "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
2515 name, fld->name, validf->name,
2516 name, fld->name, ufld->name,
2517 tag);
2518 validf = ufld;
2519 }
2520 if (validf != NULL)
2521 {
2522 char *newname;
1a97be37 2523 newname = xasprintf ("%s.%s.%s",
92570e7a 2524 name, fld->name, validf->name);
573aba85 2525 write_root (f, v, validf->type, newname, 0, line,
2526 if_marked);
1f3233d1 2527 free (newname);
2528 }
2529 }
2530 else if (desc)
1a97be37 2531 error_at_line (line,
1f3233d1 2532 "global `%s.%s' has `desc' option but is not union",
2533 name, fld->name);
2534 else
2535 {
2536 char *newname;
92570e7a 2537 newname = xasprintf ("%s.%s", name, fld->name);
573aba85 2538 write_root (f, v, fld->type, newname, 0, line, if_marked);
1f3233d1 2539 free (newname);
2540 }
2541 }
2542 }
2543 break;
2544
2545 case TYPE_ARRAY:
2546 {
2547 char *newname;
92570e7a 2548 newname = xasprintf ("%s[0]", name);
573aba85 2549 write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
1f3233d1 2550 free (newname);
2551 }
2552 break;
1a97be37 2553
1f3233d1 2554 case TYPE_POINTER:
2555 {
2556 type_p ap, tp;
1a97be37 2557
92570e7a 2558 oprintf (f, " {\n");
2559 oprintf (f, " &%s,\n", name);
2560 oprintf (f, " 1");
1a97be37 2561
1f3233d1 2562 for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2563 if (ap->u.a.len[0])
92570e7a 2564 oprintf (f, " * (%s)", ap->u.a.len);
1f3233d1 2565 else if (ap == v->type)
0480d780 2566 oprintf (f, " * ARRAY_SIZE (%s)", v->name);
92570e7a 2567 oprintf (f, ",\n");
2568 oprintf (f, " sizeof (%s", v->name);
1f3233d1 2569 for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
92570e7a 2570 oprintf (f, "[0]");
2571 oprintf (f, "),\n");
1a97be37 2572
1f3233d1 2573 tp = type->u.p;
1a97be37 2574
1f3233d1 2575 if (! has_length && UNION_OR_STRUCT_P (tp))
2576 {
573aba85 2577 oprintf (f, " &gt_ggc_mx_%s,\n", tp->u.s.tag);
2578 oprintf (f, " &gt_pch_nx_%s", tp->u.s.tag);
1f3233d1 2579 }
2580 else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
2581 {
c849df63 2582 oprintf (f, " &gt_ggc_m_");
2583 output_mangled_typename (f, tp);
573aba85 2584 oprintf (f, ",\n &gt_pch_n_");
2585 output_mangled_typename (f, tp);
1f3233d1 2586 }
2587 else if (has_length
e6baa273 2588 && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
1f3233d1 2589 {
573aba85 2590 oprintf (f, " &gt_ggc_ma_%s,\n", name);
2591 oprintf (f, " &gt_pch_na_%s", name);
1f3233d1 2592 }
2593 else
2594 {
1a97be37 2595 error_at_line (line,
1f3233d1 2596 "global `%s' is pointer to unimplemented type",
2597 name);
2598 }
2599 if (if_marked)
92570e7a 2600 oprintf (f, ",\n &%s", if_marked);
2601 oprintf (f, "\n },\n");
1f3233d1 2602 }
2603 break;
2604
1f3233d1 2605 case TYPE_STRING:
573aba85 2606 {
2607 oprintf (f, " {\n");
2608 oprintf (f, " &%s,\n", name);
2609 oprintf (f, " 1, \n");
2610 oprintf (f, " sizeof (%s),\n", v->name);
2611 oprintf (f, " &gt_ggc_m_S,\n");
b41d328d 2612 oprintf (f, " (gt_pointer_walker) &gt_pch_n_S\n");
573aba85 2613 oprintf (f, " },\n");
2614 }
2615 break;
1a97be37 2616
573aba85 2617 case TYPE_SCALAR:
1f3233d1 2618 break;
1a97be37 2619
1f3233d1 2620 default:
1a97be37 2621 error_at_line (line,
1f3233d1 2622 "global `%s' is unimplemented type",
2623 name);
2624 }
2625}
2626
573aba85 2627/* This generates a routine to walk an array. */
2628
2629static void
1a97be37 2630write_array (outf_p f, pair_p v, const struct write_types_data *wtd)
573aba85 2631{
2632 struct walk_type_data d;
2633 char *prevval3;
1a97be37 2634
573aba85 2635 memset (&d, 0, sizeof (d));
2636 d.of = f;
2637 d.cookie = wtd;
2638 d.indent = 2;
2639 d.line = &v->line;
2640 d.opt = v->opt;
2641 d.bitmap = get_base_file_bitmap (v->line.file);
2642 d.param = NULL;
2643
2644 d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
2645
2646 if (wtd->param_prefix)
2647 {
2648 oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
1a97be37 2649 oprintf (f,
2650 " (void *, void *, gt_pointer_operator, void *);\n");
f82b06e0 2651 oprintf (f, "static void gt_%sa_%s (void *this_obj ATTRIBUTE_UNUSED,\n",
573aba85 2652 wtd->param_prefix, v->name);
f82b06e0 2653 oprintf (d.of, " void *x_p ATTRIBUTE_UNUSED,\n");
2654 oprintf (d.of, " gt_pointer_operator op ATTRIBUTE_UNUSED,\n");
2655 oprintf (d.of, " void *cookie ATTRIBUTE_UNUSED)\n");
573aba85 2656 oprintf (d.of, "{\n");
2657 d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2658 d.process_field = write_types_local_process_field;
2659 walk_type (v->type, &d);
2660 oprintf (f, "}\n\n");
2661 }
2662
2663 d.opt = v->opt;
1a97be37 2664 oprintf (f, "static void gt_%sa_%s (void *);\n",
573aba85 2665 wtd->prefix, v->name);
f82b06e0 2666 oprintf (f, "static void\ngt_%sa_%s (void *x_p ATTRIBUTE_UNUSED)\n",
573aba85 2667 wtd->prefix, v->name);
573aba85 2668 oprintf (f, "{\n");
2669 d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2670 d.process_field = write_types_process_field;
2671 walk_type (v->type, &d);
2672 free (prevval3);
2673 oprintf (f, "}\n\n");
2674}
2675
155e048d 2676/* Output a table describing the locations and types of VARIABLES. */
2677
1f3233d1 2678static void
1a97be37 2679write_roots (pair_p variables)
1f3233d1 2680{
2681 pair_p v;
2682 struct flist *flp = NULL;
2683
2684 for (v = variables; v; v = v->next)
2685 {
92570e7a 2686 outf_p f = get_output_file_with_visibility (v->line.file);
1f3233d1 2687 struct flist *fli;
2688 const char *length = NULL;
2689 int deletable_p = 0;
2690 options_p o;
2691
2692 for (o = v->opt; o; o = o->next)
2693 if (strcmp (o->name, "length") == 0)
2694 length = (const char *)o->info;
2695 else if (strcmp (o->name, "deletable") == 0)
2696 deletable_p = 1;
2697 else if (strcmp (o->name, "param_is") == 0)
2698 ;
1a97be37 2699 else if (strncmp (o->name, "param", 5) == 0
c849df63 2700 && ISDIGIT (o->name[5])
2701 && strcmp (o->name + 6, "_is") == 0)
2702 ;
1f3233d1 2703 else if (strcmp (o->name, "if_marked") == 0)
2704 ;
2705 else
1a97be37 2706 error_at_line (&v->line,
1f3233d1 2707 "global `%s' has unknown option `%s'",
2708 v->name, o->name);
2709
2710 for (fli = flp; fli; fli = fli->next)
2711 if (fli->f == f)
2712 break;
2713 if (fli == NULL)
2714 {
2715 fli = xmalloc (sizeof (*fli));
2716 fli->f = f;
2717 fli->next = flp;
2718 fli->started_p = 0;
2719 fli->name = v->line.file;
2720 flp = fli;
2721
92570e7a 2722 oprintf (f, "\n/* GC roots. */\n\n");
1f3233d1 2723 }
2724
2725 if (! deletable_p
2726 && length
2727 && v->type->kind == TYPE_POINTER
2728 && (v->type->u.p->kind == TYPE_POINTER
2729 || v->type->u.p->kind == TYPE_STRUCT))
2730 {
573aba85 2731 write_array (f, v, &ggc_wtd);
2732 write_array (f, v, &pch_wtd);
1f3233d1 2733 }
2734 }
2735
2736 for (v = variables; v; v = v->next)
2737 {
92570e7a 2738 outf_p f = get_output_file_with_visibility (v->line.file);
1f3233d1 2739 struct flist *fli;
2740 int skip_p = 0;
2741 int length_p = 0;
2742 options_p o;
1a97be37 2743
1f3233d1 2744 for (o = v->opt; o; o = o->next)
2745 if (strcmp (o->name, "length") == 0)
2746 length_p = 1;
2747 else if (strcmp (o->name, "deletable") == 0
2748 || strcmp (o->name, "if_marked") == 0)
2749 skip_p = 1;
2750
2751 if (skip_p)
2752 continue;
2753
2754 for (fli = flp; fli; fli = fli->next)
2755 if (fli->f == f)
2756 break;
2757 if (! fli->started_p)
2758 {
2759 fli->started_p = 1;
2760
92570e7a 2761 oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
1f3233d1 2762 put_mangled_filename (f, v->line.file);
92570e7a 2763 oprintf (f, "[] = {\n");
1f3233d1 2764 }
2765
573aba85 2766 write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
1f3233d1 2767 }
2768
1a97be37 2769 finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
1f3233d1 2770 "gt_ggc_rtab");
2771
2772 for (v = variables; v; v = v->next)
2773 {
92570e7a 2774 outf_p f = get_output_file_with_visibility (v->line.file);
1f3233d1 2775 struct flist *fli;
2776 int skip_p = 1;
2777 options_p o;
2778
2779 for (o = v->opt; o; o = o->next)
2780 if (strcmp (o->name, "deletable") == 0)
2781 skip_p = 0;
2782 else if (strcmp (o->name, "if_marked") == 0)
2783 skip_p = 1;
2784
2785 if (skip_p)
2786 continue;
2787
2788 for (fli = flp; fli; fli = fli->next)
2789 if (fli->f == f)
2790 break;
2791 if (! fli->started_p)
2792 {
2793 fli->started_p = 1;
2794
92570e7a 2795 oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
1f3233d1 2796 put_mangled_filename (f, v->line.file);
92570e7a 2797 oprintf (f, "[] = {\n");
1f3233d1 2798 }
1a97be37 2799
573aba85 2800 oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
1f3233d1 2801 v->name, v->name);
2802 }
1a97be37 2803
573aba85 2804 finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
1f3233d1 2805 "gt_ggc_deletable_rtab");
2806
2807 for (v = variables; v; v = v->next)
2808 {
92570e7a 2809 outf_p f = get_output_file_with_visibility (v->line.file);
1f3233d1 2810 struct flist *fli;
2811 const char *if_marked = NULL;
2812 int length_p = 0;
2813 options_p o;
1a97be37 2814
1f3233d1 2815 for (o = v->opt; o; o = o->next)
2816 if (strcmp (o->name, "length") == 0)
2817 length_p = 1;
2818 else if (strcmp (o->name, "if_marked") == 0)
2819 if_marked = (const char *) o->info;
2820
2821 if (if_marked == NULL)
2822 continue;
2823
2824 if (v->type->kind != TYPE_POINTER
2825 || v->type->u.p->kind != TYPE_PARAM_STRUCT
2826 || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
2827 {
2828 error_at_line (&v->line, "if_marked option used but not hash table");
2829 continue;
2830 }
2831
2832 for (fli = flp; fli; fli = fli->next)
2833 if (fli->f == f)
2834 break;
2835 if (! fli->started_p)
2836 {
2837 fli->started_p = 1;
2838
92570e7a 2839 oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
1f3233d1 2840 put_mangled_filename (f, v->line.file);
92570e7a 2841 oprintf (f, "[] = {\n");
1f3233d1 2842 }
1a97be37 2843
573aba85 2844 write_root (f, v, v->type->u.p->u.param_struct.param[0],
1f3233d1 2845 v->name, length_p, &v->line, if_marked);
2846 }
1a97be37 2847
573aba85 2848 finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
1f3233d1 2849 "gt_ggc_cache_rtab");
573aba85 2850
2851 for (v = variables; v; v = v->next)
2852 {
2853 outf_p f = get_output_file_with_visibility (v->line.file);
2854 struct flist *fli;
2855 int length_p = 0;
2856 int if_marked_p = 0;
2857 options_p o;
1a97be37 2858
573aba85 2859 for (o = v->opt; o; o = o->next)
2860 if (strcmp (o->name, "length") == 0)
2861 length_p = 1;
2862 else if (strcmp (o->name, "if_marked") == 0)
2863 if_marked_p = 1;
2864
2865 if (! if_marked_p)
2866 continue;
2867
2868 for (fli = flp; fli; fli = fli->next)
2869 if (fli->f == f)
2870 break;
2871 if (! fli->started_p)
2872 {
2873 fli->started_p = 1;
2874
2875 oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
2876 put_mangled_filename (f, v->line.file);
2877 oprintf (f, "[] = {\n");
2878 }
2879
2880 write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2881 }
1a97be37 2882
573aba85 2883 finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2884 "gt_pch_cache_rtab");
2885
2886 for (v = variables; v; v = v->next)
2887 {
2888 outf_p f = get_output_file_with_visibility (v->line.file);
2889 struct flist *fli;
2890 int skip_p = 0;
2891 options_p o;
2892
2893 for (o = v->opt; o; o = o->next)
2894 if (strcmp (o->name, "deletable") == 0
2895 || strcmp (o->name, "if_marked") == 0)
2896 skip_p = 1;
2897
2898 if (skip_p)
2899 continue;
2900
2901 if (! contains_scalar_p (v->type))
2902 continue;
2903
2904 for (fli = flp; fli; fli = fli->next)
2905 if (fli->f == f)
2906 break;
2907 if (! fli->started_p)
2908 {
2909 fli->started_p = 1;
2910
2911 oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
2912 put_mangled_filename (f, v->line.file);
2913 oprintf (f, "[] = {\n");
2914 }
1a97be37 2915
573aba85 2916 oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
2917 v->name, v->name);
2918 }
1a97be37 2919
573aba85 2920 finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2921 "gt_pch_scalar_rtab");
1f3233d1 2922}
2923
2924\f
1a97be37 2925extern int main (int argc, char **argv);
2926int
2927main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
1f3233d1 2928{
776c30b8 2929 unsigned i;
1f3233d1 2930 static struct fileloc pos = { __FILE__, __LINE__ };
776c30b8 2931 unsigned j;
1a97be37 2932
c849df63 2933 gen_rtx_next ();
2934
776c30b8 2935 srcdir_len = strlen (srcdir);
1f3233d1 2936
c849df63 2937 do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
2938 do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
2939 do_scalar_typedef ("uint8", &pos);
2940 do_scalar_typedef ("jword", &pos);
2941 do_scalar_typedef ("JCF_u2", &pos);
512e0fec 2942#ifdef USE_MAPPED_LOCATION
2943 do_scalar_typedef ("location_t", &pos);
2944 do_scalar_typedef ("source_locus", &pos);
2945#endif
5496dbfc 2946 do_scalar_typedef ("void", &pos);
2947
2948 do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
c849df63 2949
cb5c5698 2950 do_typedef ("HARD_REG_SET", create_array (
2951 create_scalar_type ("unsigned long", strlen ("unsigned long")),
2952 "2"), &pos);
2953
776c30b8 2954 for (i = 0; i < NUM_GT_FILES; i++)
2955 {
2956 int dupflag = 0;
2957 /* Omit if already seen. */
2958 for (j = 0; j < i; j++)
2959 {
2960 if (!strcmp (all_files[i], all_files[j]))
2961 {
2962 dupflag = 1;
2963 break;
2964 }
2965 }
2966 if (!dupflag)
2967 parse_file (all_files[i]);
512e0fec 2968#ifndef USE_MAPPED_LOCATION
2969 /* temporary kludge - gengtype doesn't handle conditionals.
2970 Manually add source_locus *after* we've processed input.h. */
2971 if (i == 0)
2972 do_typedef ("source_locus", create_pointer (resolve_typedef ("location_t", &pos)), &pos);
2973#endif
776c30b8 2974 }
1f3233d1 2975
2976 if (hit_error != 0)
2977 exit (1);
2978
2979 set_gc_used (variables);
2980
2981 open_base_files ();
c849df63 2982 write_enum_defn (structures, param_structs);
573aba85 2983 write_types (structures, param_structs, &ggc_wtd);
2984 write_types (structures, param_structs, &pch_wtd);
2985 write_local (structures, param_structs);
2986 write_roots (variables);
c849df63 2987 write_rtx_next ();
1f3233d1 2988 close_output_files ();
2989
2990 return (hit_error != 0);
2991}