00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "bconfig.h"
00024
00025
00026 #undef ENABLE_RTL_CHECKING
00027
00028 #include "system.h"
00029 #include "coretypes.h"
00030 #include "tm.h"
00031 #include "rtl.h"
00032 #include "obstack.h"
00033 #include "hashtab.h"
00034 #include "gensupport.h"
00035
00036 static htab_t md_constants;
00037
00038
00039 struct map_value {
00040 struct map_value *next;
00041 int number;
00042 const char *string;
00043 };
00044
00045
00046
00047
00048 struct mapping {
00049
00050 const char *name;
00051
00052
00053 struct macro_group *group;
00054
00055
00056
00057 int index;
00058
00059
00060 struct map_value *values;
00061 };
00062
00063
00064 struct macro_group {
00065
00066 htab_t attrs, macros;
00067
00068
00069
00070 int num_builtins;
00071
00072
00073
00074 int (*find_builtin) (const char *, FILE *);
00075
00076
00077 bool (*uses_macro_p) (rtx, int);
00078
00079
00080 void (*apply_macro) (rtx, int);
00081 };
00082
00083
00084
00085 struct ptr_loc {
00086 const void *ptr;
00087 const char *filename;
00088 int lineno;
00089 };
00090
00091
00092
00093 struct macro_traverse_data {
00094
00095 rtx queue;
00096
00097 struct map_value *mode_maps;
00098
00099 FILE *infile;
00100
00101 const char *unknown_mode_attr;
00102 };
00103
00104
00105
00106 #define BELLWETHER_CODE(CODE) \
00107 ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE])
00108
00109 static void fatal_with_file_and_line (FILE *, const char *, ...)
00110 ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
00111 static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN;
00112 static int find_mode (const char *, FILE *);
00113 static bool uses_mode_macro_p (rtx, int);
00114 static void apply_mode_macro (rtx, int);
00115 static int find_code (const char *, FILE *);
00116 static bool uses_code_macro_p (rtx, int);
00117 static void apply_code_macro (rtx, int);
00118 static const char *apply_macro_to_string (const char *, struct mapping *, int);
00119 static rtx apply_macro_to_rtx (rtx, struct mapping *, int,
00120 struct map_value *, FILE *, const char **);
00121 static bool uses_macro_p (rtx, struct mapping *);
00122 static const char *add_condition_to_string (const char *, const char *);
00123 static void add_condition_to_rtx (rtx, const char *);
00124 static int apply_macro_traverse (void **, void *);
00125 static struct mapping *add_mapping (struct macro_group *, htab_t t,
00126 const char *, FILE *);
00127 static struct map_value **add_map_value (struct map_value **,
00128 int, const char *);
00129 static void initialize_macros (void);
00130 static void read_name (char *, FILE *);
00131 static hashval_t leading_ptr_hash (const void *);
00132 static int leading_ptr_eq_p (const void *, const void *);
00133 static void set_rtx_ptr_loc (const void *, const char *, int);
00134 static const struct ptr_loc *get_rtx_ptr_loc (const void *);
00135 static char *read_string (FILE *, int);
00136 static char *read_quoted_string (FILE *);
00137 static char *read_braced_string (FILE *);
00138 static void read_escape (FILE *);
00139 static hashval_t def_hash (const void *);
00140 static int def_name_eq_p (const void *, const void *);
00141 static void read_constants (FILE *infile, char *tmp_char);
00142 static void read_conditions (FILE *infile, char *tmp_char);
00143 static void validate_const_int (FILE *, const char *);
00144 static int find_macro (struct macro_group *, const char *, FILE *);
00145 static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
00146 static void check_code_macro (struct mapping *, FILE *);
00147 static rtx read_rtx_1 (FILE *, struct map_value **);
00148 static rtx read_rtx_variadic (FILE *, struct map_value **, rtx);
00149
00150
00151 static struct macro_group modes, codes;
00152
00153
00154 static enum rtx_code *bellwether_codes;
00155
00156
00157 static struct obstack string_obstack;
00158
00159
00160 static htab_t ptr_locs;
00161
00162
00163
00164 static struct obstack ptr_loc_obstack;
00165
00166
00167
00168
00169
00170 static htab_t joined_conditions;
00171
00172
00173 static struct obstack joined_conditions_obstack;
00174
00175
00176
00177
00178 int read_rtx_lineno = 1;
00179
00180
00181 const char *read_rtx_filename = "<unknown>";
00182
00183 static void
00184 fatal_with_file_and_line (FILE *infile, const char *msg, ...)
00185 {
00186 char context[64];
00187 size_t i;
00188 int c;
00189 va_list ap;
00190
00191 va_start (ap, msg);
00192
00193 fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
00194 vfprintf (stderr, msg, ap);
00195 putc ('\n', stderr);
00196
00197
00198 for (i = 0; i < sizeof (context)-1; ++i)
00199 {
00200 c = getc (infile);
00201 if (c == EOF)
00202 break;
00203 if (c == '\r' || c == '\n')
00204 break;
00205 context[i] = c;
00206 }
00207 context[i] = '\0';
00208
00209 fprintf (stderr, "%s:%d: following context is `%s'\n",
00210 read_rtx_filename, read_rtx_lineno, context);
00211
00212 va_end (ap);
00213 exit (1);
00214 }
00215
00216
00217
00218
00219 static void
00220 fatal_expected_char (FILE *infile, int expected_c, int actual_c)
00221 {
00222 fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
00223 expected_c, actual_c);
00224 }
00225
00226
00227
00228 static int
00229 find_mode (const char *name, FILE *infile)
00230 {
00231 int i;
00232
00233 for (i = 0; i < NUM_MACHINE_MODES; i++)
00234 if (strcmp (GET_MODE_NAME (i), name) == 0)
00235 return i;
00236
00237 fatal_with_file_and_line (infile, "unknown mode `%s'", name);
00238 }
00239
00240 static bool
00241 uses_mode_macro_p (rtx x, int mode)
00242 {
00243 return (int) GET_MODE (x) == mode;
00244 }
00245
00246 static void
00247 apply_mode_macro (rtx x, int mode)
00248 {
00249 PUT_MODE (x, (enum machine_mode) mode);
00250 }
00251
00252
00253
00254 static int
00255 find_code (const char *name, FILE *infile)
00256 {
00257 int i;
00258
00259 for (i = 0; i < NUM_RTX_CODE; i++)
00260 if (strcmp (GET_RTX_NAME (i), name) == 0)
00261 return i;
00262
00263 fatal_with_file_and_line (infile, "unknown rtx code `%s'", name);
00264 }
00265
00266 static bool
00267 uses_code_macro_p (rtx x, int code)
00268 {
00269 return (int) GET_CODE (x) == code;
00270 }
00271
00272 static void
00273 apply_code_macro (rtx x, int code)
00274 {
00275 PUT_CODE (x, (enum rtx_code) code);
00276 }
00277
00278
00279
00280
00281 static struct map_value *
00282 map_attr_string (const char *p, struct mapping *macro, int value)
00283 {
00284 const char *attr;
00285 struct mapping *m;
00286 struct map_value *v;
00287
00288
00289
00290 attr = strchr (p, ':');
00291 if (attr == 0)
00292 attr = p;
00293 else
00294 {
00295 if (strncmp (p, macro->name, attr - p) != 0
00296 || macro->name[attr - p] != 0)
00297 return 0;
00298 attr++;
00299 }
00300
00301
00302 m = (struct mapping *) htab_find (macro->group->attrs, &attr);
00303 if (m == 0)
00304 return 0;
00305
00306
00307 for (v = m->values; v != 0; v = v->next)
00308 if (v->number == value)
00309 break;
00310
00311 return v;
00312 }
00313
00314
00315
00316
00317
00318 static unsigned int
00319 mode_attr_index (struct map_value **mode_maps, const char *string)
00320 {
00321 char *p;
00322 struct map_value *mv;
00323
00324
00325
00326 obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2);
00327 p = XOBFINISH (&string_obstack, char *);
00328
00329 mv = XNEW (struct map_value);
00330 mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
00331 mv->string = p;
00332 mv->next = *mode_maps;
00333 *mode_maps = mv;
00334
00335
00336
00337
00338 return MAX_MACHINE_MODE + htab_elements (modes.macros) + mv->number;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348 static void
00349 apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro,
00350 int value, FILE *infile, const char **unknown)
00351 {
00352 unsigned int offset;
00353 int indx;
00354 struct map_value *pm;
00355
00356 offset = MAX_MACHINE_MODE + htab_elements (modes.macros);
00357 if (GET_MODE (x) < offset)
00358 return;
00359
00360 indx = GET_MODE (x) - offset;
00361 for (pm = mode_maps; pm; pm = pm->next)
00362 {
00363 if (pm->number == indx)
00364 {
00365 struct map_value *v;
00366
00367 v = map_attr_string (pm->string, macro, value);
00368 if (v)
00369 PUT_MODE (x, (enum machine_mode) find_mode (v->string, infile));
00370 else
00371 *unknown = pm->string;
00372 return;
00373 }
00374 }
00375 }
00376
00377
00378
00379
00380
00381 static const char *
00382 apply_macro_to_string (const char *string, struct mapping *macro, int value)
00383 {
00384 char *base, *copy, *p, *start, *end;
00385 struct map_value *v;
00386
00387 if (string == 0)
00388 return string;
00389
00390 base = p = copy = ASTRDUP (string);
00391 while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
00392 {
00393 p = start + 1;
00394
00395 *end = 0;
00396 v = map_attr_string (p, macro, value);
00397 *end = '>';
00398 if (v == 0)
00399 continue;
00400
00401
00402
00403 obstack_grow (&string_obstack, base, start - base);
00404 obstack_grow (&string_obstack, v->string, strlen (v->string));
00405 base = end + 1;
00406 }
00407 if (base != copy)
00408 {
00409 obstack_grow (&string_obstack, base, strlen (base) + 1);
00410 copy = XOBFINISH (&string_obstack, char *);
00411 copy_rtx_ptr_loc (copy, string);
00412 return copy;
00413 }
00414 return string;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423 static rtx
00424 apply_macro_to_rtx (rtx original, struct mapping *macro, int value,
00425 struct map_value *mode_maps, FILE *infile,
00426 const char **unknown_mode_attr)
00427 {
00428 struct macro_group *group;
00429 const char *format_ptr;
00430 int i, j;
00431 rtx x;
00432 enum rtx_code bellwether_code;
00433
00434 if (original == 0)
00435 return original;
00436
00437
00438 bellwether_code = BELLWETHER_CODE (GET_CODE (original));
00439 x = rtx_alloc (bellwether_code);
00440 memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
00441
00442
00443 group = macro->group;
00444 if (group->uses_macro_p (x, macro->index + group->num_builtins))
00445 group->apply_macro (x, value);
00446
00447 if (mode_maps)
00448 apply_mode_maps (x, mode_maps, macro, value, infile, unknown_mode_attr);
00449
00450
00451 format_ptr = GET_RTX_FORMAT (bellwether_code);
00452 for (i = 0; format_ptr[i] != 0; i++)
00453 switch (format_ptr[i])
00454 {
00455 case 'T':
00456 XTMPL (x, i) = apply_macro_to_string (XTMPL (x, i), macro, value);
00457 break;
00458
00459 case 'S':
00460 case 's':
00461 XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value);
00462 break;
00463
00464 case 'e':
00465 XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value,
00466 mode_maps, infile,
00467 unknown_mode_attr);
00468 break;
00469
00470 case 'V':
00471 case 'E':
00472 if (XVEC (original, i))
00473 {
00474 XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
00475 for (j = 0; j < XVECLEN (x, i); j++)
00476 XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j),
00477 macro, value, mode_maps,
00478 infile,
00479 unknown_mode_attr);
00480 }
00481 break;
00482
00483 default:
00484 break;
00485 }
00486 return x;
00487 }
00488
00489
00490
00491 static bool
00492 uses_macro_p (rtx x, struct mapping *macro)
00493 {
00494 struct macro_group *group;
00495 const char *format_ptr;
00496 int i, j;
00497
00498 if (x == 0)
00499 return false;
00500
00501 group = macro->group;
00502 if (group->uses_macro_p (x, macro->index + group->num_builtins))
00503 return true;
00504
00505 format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x)));
00506 for (i = 0; format_ptr[i] != 0; i++)
00507 switch (format_ptr[i])
00508 {
00509 case 'e':
00510 if (uses_macro_p (XEXP (x, i), macro))
00511 return true;
00512 break;
00513
00514 case 'V':
00515 case 'E':
00516 if (XVEC (x, i))
00517 for (j = 0; j < XVECLEN (x, i); j++)
00518 if (uses_macro_p (XVECEXP (x, i, j), macro))
00519 return true;
00520 break;
00521
00522 default:
00523 break;
00524 }
00525 return false;
00526 }
00527
00528
00529
00530
00531
00532 static const char *
00533 add_condition_to_string (const char *original, const char *extra)
00534 {
00535 if (original != 0 && original[0] == '&' && original[1] == '&')
00536 return original;
00537 return join_c_conditions (original, extra);
00538 }
00539
00540
00541
00542 static void
00543 add_condition_to_rtx (rtx x, const char *extra)
00544 {
00545 switch (GET_CODE (x))
00546 {
00547 case DEFINE_INSN:
00548 case DEFINE_EXPAND:
00549 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
00550 break;
00551
00552 case DEFINE_SPLIT:
00553 case DEFINE_PEEPHOLE:
00554 case DEFINE_PEEPHOLE2:
00555 case DEFINE_COND_EXEC:
00556 XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
00557 break;
00558
00559 case DEFINE_INSN_AND_SPLIT:
00560 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
00561 XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
00562 break;
00563
00564 default:
00565 break;
00566 }
00567 }
00568
00569
00570
00571
00572
00573 static int
00574 apply_macro_traverse (void **slot, void *data)
00575 {
00576 struct macro_traverse_data *mtd = (struct macro_traverse_data *) data;
00577 struct mapping *macro;
00578 struct map_value *v;
00579 rtx elem, new_elem, original, x;
00580
00581 macro = (struct mapping *) *slot;
00582 for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
00583 if (uses_macro_p (XEXP (elem, 0), macro))
00584 {
00585
00586
00587
00588
00589
00590
00591 mtd->unknown_mode_attr = NULL;
00592
00593 original = XEXP (elem, 0);
00594 for (v = macro->values; v != 0; v = v->next)
00595 {
00596 x = apply_macro_to_rtx (original, macro, v->number,
00597 mtd->mode_maps, mtd->infile,
00598 &mtd->unknown_mode_attr);
00599 add_condition_to_rtx (x, v->string);
00600 if (v != macro->values)
00601 {
00602
00603
00604 new_elem = rtx_alloc (EXPR_LIST);
00605 XEXP (new_elem, 1) = XEXP (elem, 1);
00606 XEXP (elem, 1) = new_elem;
00607 elem = new_elem;
00608 }
00609 XEXP (elem, 0) = x;
00610 }
00611 }
00612 return 1;
00613 }
00614
00615
00616
00617
00618
00619 static struct mapping *
00620 add_mapping (struct macro_group *group, htab_t table,
00621 const char *name, FILE *infile)
00622 {
00623 struct mapping *m;
00624 void **slot;
00625
00626 m = XNEW (struct mapping);
00627 m->name = xstrdup (name);
00628 m->group = group;
00629 m->index = htab_elements (table);
00630 m->values = 0;
00631
00632 slot = htab_find_slot (table, m, INSERT);
00633 if (*slot != 0)
00634 fatal_with_file_and_line (infile, "`%s' already defined", name);
00635
00636 *slot = m;
00637 return m;
00638 }
00639
00640
00641
00642
00643
00644 static struct map_value **
00645 add_map_value (struct map_value **end_ptr, int number, const char *string)
00646 {
00647 struct map_value *value;
00648
00649 value = XNEW (struct map_value);
00650 value->next = 0;
00651 value->number = number;
00652 value->string = string;
00653
00654 *end_ptr = value;
00655 return &value->next;
00656 }
00657
00658
00659
00660 static void
00661 initialize_macros (void)
00662 {
00663 struct mapping *lower, *upper;
00664 struct map_value **lower_ptr, **upper_ptr;
00665 char *copy, *p;
00666 int i;
00667
00668 modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
00669 modes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
00670 modes.num_builtins = MAX_MACHINE_MODE;
00671 modes.find_builtin = find_mode;
00672 modes.uses_macro_p = uses_mode_macro_p;
00673 modes.apply_macro = apply_mode_macro;
00674
00675 codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
00676 codes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
00677 codes.num_builtins = NUM_RTX_CODE;
00678 codes.find_builtin = find_code;
00679 codes.uses_macro_p = uses_code_macro_p;
00680 codes.apply_macro = apply_code_macro;
00681
00682 lower = add_mapping (&modes, modes.attrs, "mode", 0);
00683 upper = add_mapping (&modes, modes.attrs, "MODE", 0);
00684 lower_ptr = &lower->values;
00685 upper_ptr = &upper->values;
00686 for (i = 0; i < MAX_MACHINE_MODE; i++)
00687 {
00688 copy = xstrdup (GET_MODE_NAME (i));
00689 for (p = copy; *p != 0; p++)
00690 *p = TOLOWER (*p);
00691
00692 upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
00693 lower_ptr = add_map_value (lower_ptr, i, copy);
00694 }
00695
00696 lower = add_mapping (&codes, codes.attrs, "code", 0);
00697 upper = add_mapping (&codes, codes.attrs, "CODE", 0);
00698 lower_ptr = &lower->values;
00699 upper_ptr = &upper->values;
00700 for (i = 0; i < NUM_RTX_CODE; i++)
00701 {
00702 copy = xstrdup (GET_RTX_NAME (i));
00703 for (p = copy; *p != 0; p++)
00704 *p = TOUPPER (*p);
00705
00706 lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
00707 upper_ptr = add_map_value (upper_ptr, i, copy);
00708 }
00709 }
00710
00711
00712
00713 static hashval_t
00714 leading_ptr_hash (const void *def)
00715 {
00716 return htab_hash_pointer (*(const void *const *) def);
00717 }
00718
00719
00720
00721 static int
00722 leading_ptr_eq_p (const void *def1, const void *def2)
00723 {
00724 return *(const void *const *) def1 == *(const void *const *) def2;
00725 }
00726
00727
00728
00729 static void
00730 set_rtx_ptr_loc (const void *ptr, const char *filename, int lineno)
00731 {
00732 struct ptr_loc *loc;
00733
00734 loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack,
00735 sizeof (struct ptr_loc));
00736 loc->ptr = ptr;
00737 loc->filename = filename;
00738 loc->lineno = lineno;
00739 *htab_find_slot (ptr_locs, loc, INSERT) = loc;
00740 }
00741
00742
00743
00744
00745 static const struct ptr_loc *
00746 get_rtx_ptr_loc (const void *ptr)
00747 {
00748 return (const struct ptr_loc *) htab_find (ptr_locs, &ptr);
00749 }
00750
00751
00752
00753 void
00754 copy_rtx_ptr_loc (const void *new_ptr, const void *old_ptr)
00755 {
00756 const struct ptr_loc *loc = get_rtx_ptr_loc (old_ptr);
00757 if (loc != 0)
00758 set_rtx_ptr_loc (new_ptr, loc->filename, loc->lineno);
00759 }
00760
00761
00762
00763
00764 void
00765 print_rtx_ptr_loc (const void *ptr)
00766 {
00767 const struct ptr_loc *loc = get_rtx_ptr_loc (ptr);
00768 if (loc != 0)
00769 printf ("#line %d \"%s\"\n", loc->lineno, loc->filename);
00770 }
00771
00772
00773
00774
00775 const char *
00776 join_c_conditions (const char *cond1, const char *cond2)
00777 {
00778 char *result;
00779 const void **entry;
00780
00781 if (cond1 == 0 || cond1[0] == 0)
00782 return cond2;
00783
00784 if (cond2 == 0 || cond2[0] == 0)
00785 return cond1;
00786
00787 result = concat ("(", cond1, ") && (", cond2, ")", NULL);
00788 obstack_ptr_grow (&joined_conditions_obstack, result);
00789 obstack_ptr_grow (&joined_conditions_obstack, cond1);
00790 obstack_ptr_grow (&joined_conditions_obstack, cond2);
00791 entry = XOBFINISH (&joined_conditions_obstack, const void **);
00792 *htab_find_slot (joined_conditions, entry, INSERT) = entry;
00793 return result;
00794 }
00795
00796
00797
00798
00799
00800
00801 void
00802 print_c_condition (const char *cond)
00803 {
00804 const char **halves = (const char **) htab_find (joined_conditions, &cond);
00805 if (halves != 0)
00806 {
00807 printf ("(");
00808 print_c_condition (halves[1]);
00809 printf (" && ");
00810 print_c_condition (halves[2]);
00811 printf (")");
00812 }
00813 else
00814 {
00815 putc ('\n', stdout);
00816 print_rtx_ptr_loc (cond);
00817 printf ("(%s)", cond);
00818 }
00819 }
00820
00821
00822
00823
00824
00825
00826 int
00827 read_skip_spaces (FILE *infile)
00828 {
00829 int c;
00830
00831 while (1)
00832 {
00833 c = getc (infile);
00834 switch (c)
00835 {
00836 case '\n':
00837 read_rtx_lineno++;
00838 break;
00839
00840 case ' ': case '\t': case '\f': case '\r':
00841 break;
00842
00843 case ';':
00844 do
00845 c = getc (infile);
00846 while (c != '\n' && c != EOF);
00847 read_rtx_lineno++;
00848 break;
00849
00850 case '/':
00851 {
00852 int prevc;
00853 c = getc (infile);
00854 if (c != '*')
00855 fatal_expected_char (infile, '*', c);
00856
00857 prevc = 0;
00858 while ((c = getc (infile)) && c != EOF)
00859 {
00860 if (c == '\n')
00861 read_rtx_lineno++;
00862 else if (prevc == '*' && c == '/')
00863 break;
00864 prevc = c;
00865 }
00866 }
00867 break;
00868
00869 default:
00870 return c;
00871 }
00872 }
00873 }
00874
00875
00876
00877
00878 static void
00879 read_name (char *str, FILE *infile)
00880 {
00881 char *p;
00882 int c;
00883
00884 c = read_skip_spaces (infile);
00885
00886 p = str;
00887 while (1)
00888 {
00889 if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == EOF)
00890 break;
00891 if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
00892 || c == '(' || c == '[')
00893 {
00894 ungetc (c, infile);
00895 break;
00896 }
00897 *p++ = c;
00898 c = getc (infile);
00899 }
00900 if (p == str)
00901 fatal_with_file_and_line (infile, "missing name or number");
00902 if (c == '\n')
00903 read_rtx_lineno++;
00904
00905 *p = 0;
00906
00907 if (md_constants)
00908 {
00909
00910 struct md_constant *def;
00911
00912 p = str;
00913 do
00914 {
00915 struct md_constant tmp_def;
00916
00917 tmp_def.name = p;
00918 def = (struct md_constant *) htab_find (md_constants, &tmp_def);
00919 if (def)
00920 p = def->value;
00921 } while (def);
00922 if (p != str)
00923 strcpy (str, p);
00924 }
00925 }
00926
00927
00928
00929 static void
00930 read_escape (FILE *infile)
00931 {
00932 int c = getc (infile);
00933
00934 switch (c)
00935 {
00936
00937 case '\n':
00938 read_rtx_lineno++;
00939 return;
00940
00941
00942 case '\\':
00943 case '"':
00944 case '\'':
00945 break;
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
00957 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
00958 case '7': case 'x':
00959 obstack_1grow (&string_obstack, '\\');
00960 break;
00961
00962
00963
00964 case ';':
00965 obstack_grow (&string_obstack, "\\n\\t", 4);
00966 return;
00967
00968
00969 default:
00970 fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
00971 read_rtx_filename, read_rtx_lineno, c);
00972 obstack_1grow (&string_obstack, '\\');
00973 break;
00974 }
00975
00976 obstack_1grow (&string_obstack, c);
00977 }
00978
00979
00980
00981
00982 static char *
00983 read_quoted_string (FILE *infile)
00984 {
00985 int c;
00986
00987 while (1)
00988 {
00989 c = getc (infile);
00990 if (c == '\n')
00991 read_rtx_lineno++;
00992 else if (c == '\\')
00993 {
00994 read_escape (infile);
00995 continue;
00996 }
00997 else if (c == '"' || c == EOF)
00998 break;
00999
01000 obstack_1grow (&string_obstack, c);
01001 }
01002
01003 obstack_1grow (&string_obstack, 0);
01004 return XOBFINISH (&string_obstack, char *);
01005 }
01006
01007
01008
01009
01010 static char *
01011 read_braced_string (FILE *infile)
01012 {
01013 int c;
01014 int brace_depth = 1;
01015 unsigned long starting_read_rtx_lineno = read_rtx_lineno;
01016
01017 obstack_1grow (&string_obstack, '{');
01018 while (brace_depth)
01019 {
01020 c = getc (infile);
01021
01022 if (c == '\n')
01023 read_rtx_lineno++;
01024 else if (c == '{')
01025 brace_depth++;
01026 else if (c == '}')
01027 brace_depth--;
01028 else if (c == '\\')
01029 {
01030 read_escape (infile);
01031 continue;
01032 }
01033 else if (c == EOF)
01034 fatal_with_file_and_line
01035 (infile, "missing closing } for opening brace on line %lu",
01036 starting_read_rtx_lineno);
01037
01038 obstack_1grow (&string_obstack, c);
01039 }
01040
01041 obstack_1grow (&string_obstack, 0);
01042 return XOBFINISH (&string_obstack, char *);
01043 }
01044
01045
01046
01047
01048
01049 static char *
01050 read_string (FILE *infile, int star_if_braced)
01051 {
01052 char *stringbuf;
01053 int saw_paren = 0;
01054 int c, old_lineno;
01055
01056 c = read_skip_spaces (infile);
01057 if (c == '(')
01058 {
01059 saw_paren = 1;
01060 c = read_skip_spaces (infile);
01061 }
01062
01063 old_lineno = read_rtx_lineno;
01064 if (c == '"')
01065 stringbuf = read_quoted_string (infile);
01066 else if (c == '{')
01067 {
01068 if (star_if_braced)
01069 obstack_1grow (&string_obstack, '*');
01070 stringbuf = read_braced_string (infile);
01071 }
01072 else
01073 fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
01074
01075 if (saw_paren)
01076 {
01077 c = read_skip_spaces (infile);
01078 if (c != ')')
01079 fatal_expected_char (infile, ')', c);
01080 }
01081
01082 set_rtx_ptr_loc (stringbuf, read_rtx_filename, old_lineno);
01083 return stringbuf;
01084 }
01085
01086
01087
01088 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
01089 HOST_WIDE_INT atoll (const char *);
01090
01091 HOST_WIDE_INT
01092 atoll (const char *p)
01093 {
01094 int neg = 0;
01095 HOST_WIDE_INT tmp_wide;
01096
01097 while (ISSPACE (*p))
01098 p++;
01099 if (*p == '-')
01100 neg = 1, p++;
01101 else if (*p == '+')
01102 p++;
01103
01104 tmp_wide = 0;
01105 while (ISDIGIT (*p))
01106 {
01107 HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
01108 if (new_wide < tmp_wide)
01109 {
01110
01111 tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
01112 break;
01113 }
01114 tmp_wide = new_wide;
01115 p++;
01116 }
01117
01118 if (neg)
01119 tmp_wide = -tmp_wide;
01120 return tmp_wide;
01121 }
01122 #endif
01123
01124
01125
01126 static hashval_t
01127 def_hash (const void *def)
01128 {
01129 unsigned result, i;
01130 const char *string = *(const char *const *) def;
01131
01132 for (result = i = 0; *string++ != '\0'; i++)
01133 result += ((unsigned char) *string << (i % CHAR_BIT));
01134 return result;
01135 }
01136
01137
01138
01139 static int
01140 def_name_eq_p (const void *def1, const void *def2)
01141 {
01142 return ! strcmp (*(const char *const *) def1,
01143 *(const char *const *) def2);
01144 }
01145
01146
01147
01148
01149 static void
01150 read_constants (FILE *infile, char *tmp_char)
01151 {
01152 int c;
01153 htab_t defs;
01154
01155 c = read_skip_spaces (infile);
01156 if (c != '[')
01157 fatal_expected_char (infile, '[', c);
01158 defs = md_constants;
01159 if (! defs)
01160 defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
01161
01162 md_constants = 0;
01163 while ( (c = read_skip_spaces (infile)) != ']')
01164 {
01165 struct md_constant *def;
01166 void **entry_ptr;
01167
01168 if (c != '(')
01169 fatal_expected_char (infile, '(', c);
01170 def = XNEW (struct md_constant);
01171 def->name = tmp_char;
01172 read_name (tmp_char, infile);
01173 entry_ptr = htab_find_slot (defs, def, INSERT);
01174 if (! *entry_ptr)
01175 def->name = xstrdup (tmp_char);
01176 c = read_skip_spaces (infile);
01177 ungetc (c, infile);
01178 read_name (tmp_char, infile);
01179 if (! *entry_ptr)
01180 {
01181 def->value = xstrdup (tmp_char);
01182 *entry_ptr = def;
01183 }
01184 else
01185 {
01186 def = (struct md_constant *) *entry_ptr;
01187 if (strcmp (def->value, tmp_char))
01188 fatal_with_file_and_line (infile,
01189 "redefinition of %s, was %s, now %s",
01190 def->name, def->value, tmp_char);
01191 }
01192 c = read_skip_spaces (infile);
01193 if (c != ')')
01194 fatal_expected_char (infile, ')', c);
01195 }
01196 md_constants = defs;
01197 c = read_skip_spaces (infile);
01198 if (c != ')')
01199 fatal_expected_char (infile, ')', c);
01200 }
01201
01202
01203
01204
01205 void
01206 traverse_md_constants (htab_trav callback, void *info)
01207 {
01208 if (md_constants)
01209 htab_traverse (md_constants, callback, info);
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 static void
01228 read_conditions (FILE *infile, char *tmp_char)
01229 {
01230 int c;
01231
01232 c = read_skip_spaces (infile);
01233 if (c != '[')
01234 fatal_expected_char (infile, '[', c);
01235
01236 while ( (c = read_skip_spaces (infile)) != ']')
01237 {
01238 char *expr;
01239 int value;
01240
01241 if (c != '(')
01242 fatal_expected_char (infile, '(', c);
01243
01244 read_name (tmp_char, infile);
01245 validate_const_int (infile, tmp_char);
01246 value = atoi (tmp_char);
01247
01248 c = read_skip_spaces (infile);
01249 if (c != '"')
01250 fatal_expected_char (infile, '"', c);
01251 expr = read_quoted_string (infile);
01252
01253 c = read_skip_spaces (infile);
01254 if (c != ')')
01255 fatal_expected_char (infile, ')', c);
01256
01257 add_c_test (expr, value);
01258 }
01259 c = read_skip_spaces (infile);
01260 if (c != ')')
01261 fatal_expected_char (infile, ')', c);
01262 }
01263
01264 static void
01265 validate_const_int (FILE *infile, const char *string)
01266 {
01267 const char *cp;
01268 int valid = 1;
01269
01270 cp = string;
01271 while (*cp && ISSPACE (*cp))
01272 cp++;
01273 if (*cp == '-' || *cp == '+')
01274 cp++;
01275 if (*cp == 0)
01276 valid = 0;
01277 for (; *cp; cp++)
01278 if (! ISDIGIT (*cp))
01279 valid = 0;
01280 if (!valid)
01281 fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
01282 }
01283
01284
01285
01286
01287 static int
01288 find_macro (struct macro_group *group, const char *name, FILE *infile)
01289 {
01290 struct mapping *m;
01291
01292 m = (struct mapping *) htab_find (group->macros, &name);
01293 if (m != 0)
01294 return m->index + group->num_builtins;
01295 return group->find_builtin (name, infile);
01296 }
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 static struct mapping *
01309 read_mapping (struct macro_group *group, htab_t table, FILE *infile)
01310 {
01311 char tmp_char[256];
01312 struct mapping *m;
01313 struct map_value **end_ptr;
01314 const char *string;
01315 int number, c;
01316
01317
01318 read_name (tmp_char, infile);
01319 m = add_mapping (group, table, tmp_char, infile);
01320
01321 c = read_skip_spaces (infile);
01322 if (c != '[')
01323 fatal_expected_char (infile, '[', c);
01324
01325
01326 end_ptr = &m->values;
01327 c = read_skip_spaces (infile);
01328 do
01329 {
01330 if (c != '(')
01331 {
01332
01333
01334 ungetc (c, infile);
01335 read_name (tmp_char, infile);
01336 string = "";
01337 }
01338 else
01339 {
01340
01341 read_name (tmp_char, infile);
01342 string = read_string (infile, false);
01343 c = read_skip_spaces (infile);
01344 if (c != ')')
01345 fatal_expected_char (infile, ')', c);
01346 }
01347 number = group->find_builtin (tmp_char, infile);
01348 end_ptr = add_map_value (end_ptr, number, string);
01349 c = read_skip_spaces (infile);
01350 }
01351 while (c != ']');
01352
01353 c = read_skip_spaces (infile);
01354 if (c != ')')
01355 fatal_expected_char (infile, ')', c);
01356
01357 return m;
01358 }
01359
01360
01361
01362
01363 static void
01364 check_code_macro (struct mapping *macro, FILE *infile)
01365 {
01366 struct map_value *v;
01367 enum rtx_code bellwether;
01368
01369 bellwether = (enum rtx_code) macro->values->number;
01370 for (v = macro->values->next; v != 0; v = v->next)
01371 if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
01372 fatal_with_file_and_line (infile, "code macro `%s' combines "
01373 "different rtx formats", macro->name);
01374
01375 bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
01376 macro->index + 1);
01377 bellwether_codes[macro->index] = bellwether;
01378 }
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 bool
01389 read_rtx (FILE *infile, rtx *x, int *lineno)
01390 {
01391 static rtx queue_head, queue_next;
01392 static int queue_lineno;
01393 int c;
01394
01395
01396 if (queue_head == 0)
01397 {
01398 initialize_macros ();
01399 obstack_init (&string_obstack);
01400 queue_head = rtx_alloc (EXPR_LIST);
01401 ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
01402 obstack_init (&ptr_loc_obstack);
01403 joined_conditions = htab_create (161, leading_ptr_hash,
01404 leading_ptr_eq_p, 0);
01405 obstack_init (&joined_conditions_obstack);
01406 }
01407
01408 if (queue_next == 0)
01409 {
01410 struct map_value *mode_maps;
01411 struct macro_traverse_data mtd;
01412 rtx from_file;
01413
01414 c = read_skip_spaces (infile);
01415 if (c == EOF)
01416 return false;
01417 ungetc (c, infile);
01418
01419 queue_lineno = read_rtx_lineno;
01420 mode_maps = 0;
01421 from_file = read_rtx_1 (infile, &mode_maps);
01422 if (from_file == 0)
01423 return false;
01424
01425
01426
01427 queue_next = queue_head;
01428 XEXP (queue_next, 0) = from_file;
01429 XEXP (queue_next, 1) = 0;
01430
01431 mtd.queue = queue_next;
01432 mtd.mode_maps = mode_maps;
01433 mtd.infile = infile;
01434 mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
01435 htab_traverse (modes.macros, apply_macro_traverse, &mtd);
01436 htab_traverse (codes.macros, apply_macro_traverse, &mtd);
01437 if (mtd.unknown_mode_attr)
01438 fatal_with_file_and_line (infile,
01439 "undefined attribute '%s' used for mode",
01440 mtd.unknown_mode_attr);
01441 }
01442
01443 *x = XEXP (queue_next, 0);
01444 *lineno = queue_lineno;
01445 queue_next = XEXP (queue_next, 1);
01446
01447 return true;
01448 }
01449
01450
01451
01452
01453 static rtx
01454 read_rtx_1 (FILE *infile, struct map_value **mode_maps)
01455 {
01456 int i;
01457 RTX_CODE real_code, bellwether_code;
01458 const char *format_ptr;
01459
01460
01461
01462 char tmp_char[256];
01463 rtx return_rtx;
01464 int c;
01465 int tmp_int;
01466 HOST_WIDE_INT tmp_wide;
01467
01468
01469 struct rtx_list
01470 {
01471 struct rtx_list *next;
01472 rtx value;
01473 };
01474
01475 again:
01476 c = read_skip_spaces (infile);
01477
01478 if (c == EOF)
01479 return 0;
01480
01481 if (c != '(')
01482 fatal_expected_char (infile, '(', c);
01483
01484 read_name (tmp_char, infile);
01485 if (strcmp (tmp_char, "nil") == 0)
01486 {
01487
01488 c = read_skip_spaces (infile);
01489 if (c != ')')
01490 fatal_expected_char (infile, ')', c);
01491 return 0;
01492 }
01493 if (strcmp (tmp_char, "define_constants") == 0)
01494 {
01495 read_constants (infile, tmp_char);
01496 goto again;
01497 }
01498 if (strcmp (tmp_char, "define_conditions") == 0)
01499 {
01500 read_conditions (infile, tmp_char);
01501 goto again;
01502 }
01503 if (strcmp (tmp_char, "define_mode_attr") == 0)
01504 {
01505 read_mapping (&modes, modes.attrs, infile);
01506 goto again;
01507 }
01508 if (strcmp (tmp_char, "define_mode_macro") == 0)
01509 {
01510 read_mapping (&modes, modes.macros, infile);
01511 goto again;
01512 }
01513 if (strcmp (tmp_char, "define_code_attr") == 0)
01514 {
01515 read_mapping (&codes, codes.attrs, infile);
01516 goto again;
01517 }
01518 if (strcmp (tmp_char, "define_code_macro") == 0)
01519 {
01520 check_code_macro (read_mapping (&codes, codes.macros, infile), infile);
01521 goto again;
01522 }
01523 real_code = (enum rtx_code) find_macro (&codes, tmp_char, infile);
01524 bellwether_code = BELLWETHER_CODE (real_code);
01525
01526
01527 return_rtx = rtx_alloc (bellwether_code);
01528 format_ptr = GET_RTX_FORMAT (bellwether_code);
01529 PUT_CODE (return_rtx, real_code);
01530
01531
01532
01533
01534 i = read_skip_spaces (infile);
01535 if (i == ':')
01536 {
01537 unsigned int mode;
01538
01539 read_name (tmp_char, infile);
01540 if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>')
01541 mode = find_macro (&modes, tmp_char, infile);
01542 else
01543 mode = mode_attr_index (mode_maps, tmp_char);
01544 PUT_MODE (return_rtx, (enum machine_mode) mode);
01545 if (GET_MODE (return_rtx) != mode)
01546 fatal_with_file_and_line (infile, "mode too large");
01547 }
01548 else
01549 ungetc (i, infile);
01550
01551 for (i = 0; format_ptr[i] != 0; i++)
01552 switch (format_ptr[i])
01553 {
01554
01555
01556 case '0':
01557 break;
01558
01559 case 'e':
01560 case 'u':
01561 XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps);
01562 break;
01563
01564 case 'V':
01565
01566
01567 c = read_skip_spaces (infile);
01568 ungetc (c, infile);
01569 if (c == ')')
01570 {
01571 XVEC (return_rtx, i) = 0;
01572 break;
01573 }
01574
01575
01576 case 'E':
01577 {
01578
01579 struct obstack vector_stack;
01580 int list_counter = 0;
01581 rtvec return_vec = NULL_RTVEC;
01582
01583 c = read_skip_spaces (infile);
01584 if (c != '[')
01585 fatal_expected_char (infile, '[', c);
01586
01587
01588 obstack_init (&vector_stack);
01589 while ((c = read_skip_spaces (infile)) && c != ']')
01590 {
01591 ungetc (c, infile);
01592 list_counter++;
01593 obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps));
01594 }
01595 if (list_counter > 0)
01596 {
01597 return_vec = rtvec_alloc (list_counter);
01598 memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
01599 list_counter * sizeof (rtx));
01600 }
01601 else if (format_ptr[i] == 'E')
01602 fatal_with_file_and_line (infile,
01603 "vector must have at least one element");
01604 XVEC (return_rtx, i) = return_vec;
01605 obstack_free (&vector_stack, NULL);
01606
01607 }
01608 break;
01609
01610 case 'S':
01611 case 'T':
01612 case 's':
01613 {
01614 char *stringbuf;
01615 int star_if_braced;
01616
01617 c = read_skip_spaces (infile);
01618 ungetc (c, infile);
01619 if (c == ')')
01620 {
01621
01622
01623
01624 XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : "");
01625 break;
01626 }
01627
01628
01629
01630
01631
01632 star_if_braced = (format_ptr[i] == 'T');
01633
01634 stringbuf = read_string (infile, star_if_braced);
01635
01636
01637
01638
01639
01640 if (*stringbuf == '\0'
01641 && i == 0
01642 && (GET_CODE (return_rtx) == DEFINE_INSN
01643 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
01644 {
01645 char line_name[20];
01646 const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
01647 const char *slash;
01648 for (slash = fn; *slash; slash ++)
01649 if (*slash == '/' || *slash == '\\' || *slash == ':')
01650 fn = slash + 1;
01651 obstack_1grow (&string_obstack, '*');
01652 obstack_grow (&string_obstack, fn, strlen (fn));
01653 sprintf (line_name, ":%d", read_rtx_lineno);
01654 obstack_grow (&string_obstack, line_name, strlen (line_name)+1);
01655 stringbuf = XOBFINISH (&string_obstack, char *);
01656 }
01657
01658 if (star_if_braced)
01659 XTMPL (return_rtx, i) = stringbuf;
01660 else
01661 XSTR (return_rtx, i) = stringbuf;
01662 }
01663 break;
01664
01665 case 'w':
01666 read_name (tmp_char, infile);
01667 validate_const_int (infile, tmp_char);
01668 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
01669 tmp_wide = atoi (tmp_char);
01670 #else
01671 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
01672 tmp_wide = atol (tmp_char);
01673 #else
01674
01675
01676 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
01677 tmp_wide = atoll (tmp_char);
01678 #else
01679 tmp_wide = atoq (tmp_char);
01680 #endif
01681 #endif
01682 #endif
01683 XWINT (return_rtx, i) = tmp_wide;
01684 break;
01685
01686 case 'i':
01687 case 'n':
01688 read_name (tmp_char, infile);
01689 validate_const_int (infile, tmp_char);
01690 tmp_int = atoi (tmp_char);
01691 XINT (return_rtx, i) = tmp_int;
01692 break;
01693
01694 default:
01695 gcc_unreachable ();
01696 }
01697
01698 c = read_skip_spaces (infile);
01699 if (c != ')')
01700 {
01701
01702
01703 if (c == '(' && (GET_CODE (return_rtx) == AND
01704 || GET_CODE (return_rtx) == IOR))
01705 return read_rtx_variadic (infile, mode_maps, return_rtx);
01706 else
01707 fatal_expected_char (infile, ')', c);
01708 }
01709
01710 return return_rtx;
01711 }
01712
01713
01714
01715
01716
01717
01718
01719 static rtx
01720 read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form)
01721 {
01722 char c = '(';
01723 rtx p = form, q;
01724
01725 do
01726 {
01727 ungetc (c, infile);
01728
01729 q = rtx_alloc (GET_CODE (p));
01730 PUT_MODE (q, GET_MODE (p));
01731
01732 XEXP (q, 0) = XEXP (p, 1);
01733 XEXP (q, 1) = read_rtx_1 (infile, mode_maps);
01734
01735 XEXP (p, 1) = q;
01736 p = q;
01737 c = read_skip_spaces (infile);
01738 }
01739 while (c == '(');
01740
01741 if (c != ')')
01742 fatal_expected_char (infile, ')', c);
01743
01744 return form;
01745 }