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