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
00035 static htab_t md_constants;
00036
00037
00038 struct map_value {
00039 struct map_value *next;
00040 int number;
00041 const char *string;
00042 };
00043
00044
00045
00046
00047 struct mapping {
00048
00049 const char *name;
00050
00051
00052 struct macro_group *group;
00053
00054
00055
00056 int index;
00057
00058
00059 struct map_value *values;
00060 };
00061
00062
00063 struct macro_group {
00064
00065 htab_t attrs, macros;
00066
00067
00068
00069 int num_builtins;
00070
00071
00072
00073 int (*find_builtin) (const char *, FILE *);
00074
00075
00076 bool (*uses_macro_p) (rtx, int);
00077
00078
00079 void (*apply_macro) (rtx, int);
00080 };
00081
00082
00083
00084 #define BELLWETHER_CODE(CODE) \
00085 ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE])
00086
00087 static void fatal_with_file_and_line (FILE *, const char *, ...)
00088 ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
00089 static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN;
00090 static int find_mode (const char *, FILE *);
00091 static bool uses_mode_macro_p (rtx, int);
00092 static void apply_mode_macro (rtx, int);
00093 static int find_code (const char *, FILE *);
00094 static bool uses_code_macro_p (rtx, int);
00095 static void apply_code_macro (rtx, int);
00096 static const char *apply_macro_to_string (const char *, struct mapping *, int);
00097 static rtx apply_macro_to_rtx (rtx, struct mapping *, int);
00098 static bool uses_macro_p (rtx, struct mapping *);
00099 static const char *add_condition_to_string (const char *, const char *);
00100 static void add_condition_to_rtx (rtx, const char *);
00101 static int apply_macro_traverse (void **, void *);
00102 static struct mapping *add_mapping (struct macro_group *, htab_t t,
00103 const char *, FILE *);
00104 static struct map_value **add_map_value (struct map_value **,
00105 int, const char *);
00106 static void initialize_macros (void);
00107 static void read_name (char *, FILE *);
00108 static char *read_string (FILE *, int);
00109 static char *read_quoted_string (FILE *);
00110 static char *read_braced_string (FILE *);
00111 static void read_escape (FILE *);
00112 static hashval_t def_hash (const void *);
00113 static int def_name_eq_p (const void *, const void *);
00114 static void read_constants (FILE *infile, char *tmp_char);
00115 static void validate_const_int (FILE *, const char *);
00116 static int find_macro (struct macro_group *, const char *, FILE *);
00117 static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
00118 static void check_code_macro (struct mapping *, FILE *);
00119 static rtx read_rtx_1 (FILE *);
00120
00121
00122 static struct macro_group modes, codes;
00123
00124
00125 static enum rtx_code *bellwether_codes;
00126
00127
00128 static struct obstack string_obstack;
00129
00130
00131
00132
00133 int read_rtx_lineno = 1;
00134
00135
00136 const char *read_rtx_filename = "<unknown>";
00137
00138 static void
00139 fatal_with_file_and_line (FILE *infile, const char *msg, ...)
00140 {
00141 char context[64];
00142 size_t i;
00143 int c;
00144 va_list ap;
00145
00146 va_start (ap, msg);
00147
00148 fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
00149 vfprintf (stderr, msg, ap);
00150 putc ('\n', stderr);
00151
00152
00153 for (i = 0; i < sizeof (context)-1; ++i)
00154 {
00155 c = getc (infile);
00156 if (c == EOF)
00157 break;
00158 if (c == '\r' || c == '\n')
00159 break;
00160 context[i] = c;
00161 }
00162 context[i] = '\0';
00163
00164 fprintf (stderr, "%s:%d: following context is `%s'\n",
00165 read_rtx_filename, read_rtx_lineno, context);
00166
00167 va_end (ap);
00168 exit (1);
00169 }
00170
00171
00172
00173
00174 static void
00175 fatal_expected_char (FILE *infile, int expected_c, int actual_c)
00176 {
00177 fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
00178 expected_c, actual_c);
00179 }
00180
00181
00182
00183 static int
00184 find_mode (const char *name, FILE *infile)
00185 {
00186 int i;
00187
00188 for (i = 0; i < NUM_MACHINE_MODES; i++)
00189 if (strcmp (GET_MODE_NAME (i), name) == 0)
00190 return i;
00191
00192 fatal_with_file_and_line (infile, "unknown mode `%s'", name);
00193 }
00194
00195 static bool
00196 uses_mode_macro_p (rtx x, int mode)
00197 {
00198 return (int) GET_MODE (x) == mode;
00199 }
00200
00201 static void
00202 apply_mode_macro (rtx x, int mode)
00203 {
00204 PUT_MODE (x, mode);
00205 }
00206
00207
00208
00209 static int
00210 find_code (const char *name, FILE *infile)
00211 {
00212 int i;
00213
00214 for (i = 0; i < NUM_RTX_CODE; i++)
00215 if (strcmp (GET_RTX_NAME (i), name) == 0)
00216 return i;
00217
00218 fatal_with_file_and_line (infile, "unknown rtx code `%s'", name);
00219 }
00220
00221 static bool
00222 uses_code_macro_p (rtx x, int code)
00223 {
00224 return (int) GET_CODE (x) == code;
00225 }
00226
00227 static void
00228 apply_code_macro (rtx x, int code)
00229 {
00230 PUT_CODE (x, code);
00231 }
00232
00233
00234
00235
00236
00237 static const char *
00238 apply_macro_to_string (const char *string, struct mapping *macro, int value)
00239 {
00240 char *base, *copy, *p, *attr, *start, *end;
00241 struct mapping *m;
00242 struct map_value *v;
00243
00244 if (string == 0)
00245 return string;
00246
00247 base = p = copy = ASTRDUP (string);
00248 while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
00249 {
00250 p = start + 1;
00251
00252
00253
00254 attr = strchr (p, ':');
00255 if (attr == 0 || attr > end)
00256 attr = p;
00257 else
00258 {
00259 if (strncmp (p, macro->name, attr - p) != 0
00260 || macro->name[attr - p] != 0)
00261 continue;
00262 attr++;
00263 }
00264
00265
00266 *end = 0;
00267 m = (struct mapping *) htab_find (macro->group->attrs, &attr);
00268 *end = '>';
00269 if (m == 0)
00270 continue;
00271
00272
00273 for (v = m->values; v != 0; v = v->next)
00274 if (v->number == value)
00275 break;
00276 if (v == 0)
00277 continue;
00278
00279
00280
00281 obstack_grow (&string_obstack, base, start - base);
00282 obstack_grow (&string_obstack, v->string, strlen (v->string));
00283 base = end + 1;
00284 }
00285 if (base != copy)
00286 {
00287 obstack_grow (&string_obstack, base, strlen (base) + 1);
00288 return (char *) obstack_finish (&string_obstack);
00289 }
00290 return string;
00291 }
00292
00293
00294
00295
00296 static rtx
00297 apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
00298 {
00299 struct macro_group *group;
00300 const char *format_ptr;
00301 int i, j;
00302 rtx x;
00303 enum rtx_code bellwether_code;
00304
00305 if (original == 0)
00306 return original;
00307
00308
00309 bellwether_code = BELLWETHER_CODE (GET_CODE (original));
00310 x = rtx_alloc (bellwether_code);
00311 memcpy (x, original, RTX_SIZE (bellwether_code));
00312
00313
00314 group = macro->group;
00315 if (group->uses_macro_p (x, macro->index + group->num_builtins))
00316 group->apply_macro (x, value);
00317
00318
00319 format_ptr = GET_RTX_FORMAT (bellwether_code);
00320 for (i = 0; format_ptr[i] != 0; i++)
00321 switch (format_ptr[i])
00322 {
00323 case 'T':
00324 XTMPL (x, i) = apply_macro_to_string (XTMPL (x, i), macro, value);
00325 break;
00326
00327 case 'S':
00328 case 's':
00329 XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value);
00330 break;
00331
00332 case 'e':
00333 XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value);
00334 break;
00335
00336 case 'V':
00337 case 'E':
00338 if (XVEC (original, i))
00339 {
00340 XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
00341 for (j = 0; j < XVECLEN (x, i); j++)
00342 XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j),
00343 macro, value);
00344 }
00345 break;
00346
00347 default:
00348 break;
00349 }
00350 return x;
00351 }
00352
00353
00354
00355 static bool
00356 uses_macro_p (rtx x, struct mapping *macro)
00357 {
00358 struct macro_group *group;
00359 const char *format_ptr;
00360 int i, j;
00361
00362 if (x == 0)
00363 return false;
00364
00365 group = macro->group;
00366 if (group->uses_macro_p (x, macro->index + group->num_builtins))
00367 return true;
00368
00369 format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x)));
00370 for (i = 0; format_ptr[i] != 0; i++)
00371 switch (format_ptr[i])
00372 {
00373 case 'e':
00374 if (uses_macro_p (XEXP (x, i), macro))
00375 return true;
00376 break;
00377
00378 case 'V':
00379 case 'E':
00380 if (XVEC (x, i))
00381 for (j = 0; j < XVECLEN (x, i); j++)
00382 if (uses_macro_p (XVECEXP (x, i, j), macro))
00383 return true;
00384 break;
00385
00386 default:
00387 break;
00388 }
00389 return false;
00390 }
00391
00392
00393
00394
00395
00396 static const char *
00397 add_condition_to_string (const char *original, const char *extra)
00398 {
00399 char *result;
00400
00401 if (original == 0 || original[0] == 0)
00402 return extra;
00403
00404 if ((original[0] == '&' && original[1] == '&') || extra[0] == 0)
00405 return original;
00406
00407 asprintf (&result, "(%s) && (%s)", original, extra);
00408 return result;
00409 }
00410
00411
00412
00413 static void
00414 add_condition_to_rtx (rtx x, const char *extra)
00415 {
00416 switch (GET_CODE (x))
00417 {
00418 case DEFINE_INSN:
00419 case DEFINE_EXPAND:
00420 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
00421 break;
00422
00423 case DEFINE_SPLIT:
00424 case DEFINE_PEEPHOLE:
00425 case DEFINE_PEEPHOLE2:
00426 case DEFINE_COND_EXEC:
00427 XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
00428 break;
00429
00430 case DEFINE_INSN_AND_SPLIT:
00431 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
00432 XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
00433 break;
00434
00435 default:
00436 break;
00437 }
00438 }
00439
00440
00441
00442
00443
00444 static int
00445 apply_macro_traverse (void **slot, void *data)
00446 {
00447 struct mapping *macro;
00448 struct map_value *v;
00449 rtx elem, new_elem, original, x;
00450
00451 macro = (struct mapping *) *slot;
00452 for (elem = (rtx) data; elem != 0; elem = XEXP (elem, 1))
00453 if (uses_macro_p (XEXP (elem, 0), macro))
00454 {
00455 original = XEXP (elem, 0);
00456 for (v = macro->values; v != 0; v = v->next)
00457 {
00458 x = apply_macro_to_rtx (original, macro, v->number);
00459 add_condition_to_rtx (x, v->string);
00460 if (v != macro->values)
00461 {
00462
00463
00464 new_elem = rtx_alloc (EXPR_LIST);
00465 XEXP (new_elem, 1) = XEXP (elem, 1);
00466 XEXP (elem, 1) = new_elem;
00467 elem = new_elem;
00468 }
00469 XEXP (elem, 0) = x;
00470 }
00471 }
00472 return 1;
00473 }
00474
00475
00476
00477
00478
00479 static struct mapping *
00480 add_mapping (struct macro_group *group, htab_t table,
00481 const char *name, FILE *infile)
00482 {
00483 struct mapping *m;
00484 void **slot;
00485
00486 m = XNEW (struct mapping);
00487 m->name = xstrdup (name);
00488 m->group = group;
00489 m->index = htab_elements (table);
00490 m->values = 0;
00491
00492 slot = htab_find_slot (table, m, INSERT);
00493 if (*slot != 0)
00494 fatal_with_file_and_line (infile, "`%s' already defined", name);
00495
00496 *slot = m;
00497 return m;
00498 }
00499
00500
00501
00502
00503
00504 static struct map_value **
00505 add_map_value (struct map_value **end_ptr, int number, const char *string)
00506 {
00507 struct map_value *value;
00508
00509 value = XNEW (struct map_value);
00510 value->next = 0;
00511 value->number = number;
00512 value->string = string;
00513
00514 *end_ptr = value;
00515 return &value->next;
00516 }
00517
00518
00519
00520 static void
00521 initialize_macros (void)
00522 {
00523 struct mapping *lower, *upper;
00524 struct map_value **lower_ptr, **upper_ptr;
00525 char *copy, *p;
00526 int i;
00527
00528 modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
00529 modes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
00530 modes.num_builtins = MAX_MACHINE_MODE;
00531 modes.find_builtin = find_mode;
00532 modes.uses_macro_p = uses_mode_macro_p;
00533 modes.apply_macro = apply_mode_macro;
00534
00535 codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
00536 codes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
00537 codes.num_builtins = NUM_RTX_CODE;
00538 codes.find_builtin = find_code;
00539 codes.uses_macro_p = uses_code_macro_p;
00540 codes.apply_macro = apply_code_macro;
00541
00542 lower = add_mapping (&modes, modes.attrs, "mode", 0);
00543 upper = add_mapping (&modes, modes.attrs, "MODE", 0);
00544 lower_ptr = &lower->values;
00545 upper_ptr = &upper->values;
00546 for (i = 0; i < MAX_MACHINE_MODE; i++)
00547 {
00548 copy = xstrdup (GET_MODE_NAME (i));
00549 for (p = copy; *p != 0; p++)
00550 *p = TOLOWER (*p);
00551
00552 upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
00553 lower_ptr = add_map_value (lower_ptr, i, copy);
00554 }
00555
00556 lower = add_mapping (&codes, codes.attrs, "code", 0);
00557 upper = add_mapping (&codes, codes.attrs, "CODE", 0);
00558 lower_ptr = &lower->values;
00559 upper_ptr = &upper->values;
00560 for (i = 0; i < NUM_RTX_CODE; i++)
00561 {
00562 copy = xstrdup (GET_RTX_NAME (i));
00563 for (p = copy; *p != 0; p++)
00564 *p = TOUPPER (*p);
00565
00566 lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
00567 upper_ptr = add_map_value (upper_ptr, i, copy);
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576 int
00577 read_skip_spaces (FILE *infile)
00578 {
00579 int c;
00580
00581 while (1)
00582 {
00583 c = getc (infile);
00584 switch (c)
00585 {
00586 case '\n':
00587 read_rtx_lineno++;
00588 break;
00589
00590 case ' ': case '\t': case '\f': case '\r':
00591 break;
00592
00593 case ';':
00594 do
00595 c = getc (infile);
00596 while (c != '\n' && c != EOF);
00597 read_rtx_lineno++;
00598 break;
00599
00600 case '/':
00601 {
00602 int prevc;
00603 c = getc (infile);
00604 if (c != '*')
00605 fatal_expected_char (infile, '*', c);
00606
00607 prevc = 0;
00608 while ((c = getc (infile)) && c != EOF)
00609 {
00610 if (c == '\n')
00611 read_rtx_lineno++;
00612 else if (prevc == '*' && c == '/')
00613 break;
00614 prevc = c;
00615 }
00616 }
00617 break;
00618
00619 default:
00620 return c;
00621 }
00622 }
00623 }
00624
00625
00626
00627
00628 static void
00629 read_name (char *str, FILE *infile)
00630 {
00631 char *p;
00632 int c;
00633
00634 c = read_skip_spaces (infile);
00635
00636 p = str;
00637 while (1)
00638 {
00639 if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
00640 break;
00641 if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
00642 || c == '(' || c == '[')
00643 {
00644 ungetc (c, infile);
00645 break;
00646 }
00647 *p++ = c;
00648 c = getc (infile);
00649 }
00650 if (p == str)
00651 fatal_with_file_and_line (infile, "missing name or number");
00652 if (c == '\n')
00653 read_rtx_lineno++;
00654
00655 *p = 0;
00656
00657 if (md_constants)
00658 {
00659
00660 struct md_constant *def;
00661
00662 p = str;
00663 do
00664 {
00665 struct md_constant tmp_def;
00666
00667 tmp_def.name = p;
00668 def = (struct md_constant *) htab_find (md_constants, &tmp_def);
00669 if (def)
00670 p = def->value;
00671 } while (def);
00672 if (p != str)
00673 strcpy (str, p);
00674 }
00675 }
00676
00677
00678
00679 static void
00680 read_escape (FILE *infile)
00681 {
00682 int c = getc (infile);
00683
00684 switch (c)
00685 {
00686
00687 case '\n':
00688 read_rtx_lineno++;
00689 return;
00690
00691
00692 case '\\':
00693 case '"':
00694 case '\'':
00695 break;
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
00707 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
00708 case '7': case 'x':
00709 obstack_1grow (&string_obstack, '\\');
00710 break;
00711
00712
00713
00714 case ';':
00715 obstack_grow (&string_obstack, "\\n\\t", 4);
00716 return;
00717
00718
00719 default:
00720 fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
00721 read_rtx_filename, read_rtx_lineno, c);
00722 obstack_1grow (&string_obstack, '\\');
00723 break;
00724 }
00725
00726 obstack_1grow (&string_obstack, c);
00727 }
00728
00729
00730
00731
00732 static char *
00733 read_quoted_string (FILE *infile)
00734 {
00735 int c;
00736
00737 while (1)
00738 {
00739 c = getc (infile);
00740 if (c == '\n')
00741 read_rtx_lineno++;
00742 else if (c == '\\')
00743 {
00744 read_escape (infile);
00745 continue;
00746 }
00747 else if (c == '"')
00748 break;
00749
00750 obstack_1grow (&string_obstack, c);
00751 }
00752
00753 obstack_1grow (&string_obstack, 0);
00754 return (char *) obstack_finish (&string_obstack);
00755 }
00756
00757
00758
00759
00760 static char *
00761 read_braced_string (FILE *infile)
00762 {
00763 int c;
00764 int brace_depth = 1;
00765 unsigned long starting_read_rtx_lineno = read_rtx_lineno;
00766
00767 obstack_1grow (&string_obstack, '{');
00768 while (brace_depth)
00769 {
00770 c = getc (infile);
00771
00772 if (c == '\n')
00773 read_rtx_lineno++;
00774 else if (c == '{')
00775 brace_depth++;
00776 else if (c == '}')
00777 brace_depth--;
00778 else if (c == '\\')
00779 {
00780 read_escape (infile);
00781 continue;
00782 }
00783 else if (c == EOF)
00784 fatal_with_file_and_line
00785 (infile, "missing closing } for opening brace on line %lu",
00786 starting_read_rtx_lineno);
00787
00788 obstack_1grow (&string_obstack, c);
00789 }
00790
00791 obstack_1grow (&string_obstack, 0);
00792 return (char *) obstack_finish (&string_obstack);
00793 }
00794
00795
00796
00797
00798
00799 static char *
00800 read_string (FILE *infile, int star_if_braced)
00801 {
00802 char *stringbuf;
00803 int saw_paren = 0;
00804 int c;
00805
00806 c = read_skip_spaces (infile);
00807 if (c == '(')
00808 {
00809 saw_paren = 1;
00810 c = read_skip_spaces (infile);
00811 }
00812
00813 if (c == '"')
00814 stringbuf = read_quoted_string (infile);
00815 else if (c == '{')
00816 {
00817 if (star_if_braced)
00818 obstack_1grow (&string_obstack, '*');
00819 stringbuf = read_braced_string (infile);
00820 }
00821 else
00822 fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
00823
00824 if (saw_paren)
00825 {
00826 c = read_skip_spaces (infile);
00827 if (c != ')')
00828 fatal_expected_char (infile, ')', c);
00829 }
00830
00831 return stringbuf;
00832 }
00833
00834
00835
00836 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
00837 HOST_WIDE_INT atoll (const char *);
00838
00839 HOST_WIDE_INT
00840 atoll (const char *p)
00841 {
00842 int neg = 0;
00843 HOST_WIDE_INT tmp_wide;
00844
00845 while (ISSPACE (*p))
00846 p++;
00847 if (*p == '-')
00848 neg = 1, p++;
00849 else if (*p == '+')
00850 p++;
00851
00852 tmp_wide = 0;
00853 while (ISDIGIT (*p))
00854 {
00855 HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
00856 if (new_wide < tmp_wide)
00857 {
00858
00859 tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
00860 break;
00861 }
00862 tmp_wide = new_wide;
00863 p++;
00864 }
00865
00866 if (neg)
00867 tmp_wide = -tmp_wide;
00868 return tmp_wide;
00869 }
00870 #endif
00871
00872
00873
00874 static hashval_t
00875 def_hash (const void *def)
00876 {
00877 unsigned result, i;
00878 const char *string = *(const char *const *) def;
00879
00880 for (result = i = 0; *string++ != '\0'; i++)
00881 result += ((unsigned char) *string << (i % CHAR_BIT));
00882 return result;
00883 }
00884
00885
00886
00887 static int
00888 def_name_eq_p (const void *def1, const void *def2)
00889 {
00890 return ! strcmp (*(const char *const *) def1,
00891 *(const char *const *) def2);
00892 }
00893
00894
00895
00896
00897 static void
00898 read_constants (FILE *infile, char *tmp_char)
00899 {
00900 int c;
00901 htab_t defs;
00902
00903 c = read_skip_spaces (infile);
00904 if (c != '[')
00905 fatal_expected_char (infile, '[', c);
00906 defs = md_constants;
00907 if (! defs)
00908 defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
00909
00910 md_constants = 0;
00911 while ( (c = read_skip_spaces (infile)) != ']')
00912 {
00913 struct md_constant *def;
00914 void **entry_ptr;
00915
00916 if (c != '(')
00917 fatal_expected_char (infile, '(', c);
00918 def = XNEW (struct md_constant);
00919 def->name = tmp_char;
00920 read_name (tmp_char, infile);
00921 entry_ptr = htab_find_slot (defs, def, INSERT);
00922 if (! *entry_ptr)
00923 def->name = xstrdup (tmp_char);
00924 c = read_skip_spaces (infile);
00925 ungetc (c, infile);
00926 read_name (tmp_char, infile);
00927 if (! *entry_ptr)
00928 {
00929 def->value = xstrdup (tmp_char);
00930 *entry_ptr = def;
00931 }
00932 else
00933 {
00934 def = (struct md_constant *) *entry_ptr;
00935 if (strcmp (def->value, tmp_char))
00936 fatal_with_file_and_line (infile,
00937 "redefinition of %s, was %s, now %s",
00938 def->name, def->value, tmp_char);
00939 }
00940 c = read_skip_spaces (infile);
00941 if (c != ')')
00942 fatal_expected_char (infile, ')', c);
00943 }
00944 md_constants = defs;
00945 c = read_skip_spaces (infile);
00946 if (c != ')')
00947 fatal_expected_char (infile, ')', c);
00948 }
00949
00950
00951
00952
00953 void
00954 traverse_md_constants (htab_trav callback, void *info)
00955 {
00956 if (md_constants)
00957 htab_traverse (md_constants, callback, info);
00958 }
00959
00960 static void
00961 validate_const_int (FILE *infile, const char *string)
00962 {
00963 const char *cp;
00964 int valid = 1;
00965
00966 cp = string;
00967 while (*cp && ISSPACE (*cp))
00968 cp++;
00969 if (*cp == '-' || *cp == '+')
00970 cp++;
00971 if (*cp == 0)
00972 valid = 0;
00973 for (; *cp; cp++)
00974 if (! ISDIGIT (*cp))
00975 valid = 0;
00976 if (!valid)
00977 fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
00978 }
00979
00980
00981
00982
00983 static int
00984 find_macro (struct macro_group *group, const char *name, FILE *infile)
00985 {
00986 struct mapping *m;
00987
00988 m = (struct mapping *) htab_find (group->macros, &name);
00989 if (m != 0)
00990 return m->index + group->num_builtins;
00991 return group->find_builtin (name, infile);
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 static struct mapping *
01005 read_mapping (struct macro_group *group, htab_t table, FILE *infile)
01006 {
01007 char tmp_char[256];
01008 struct mapping *m;
01009 struct map_value **end_ptr;
01010 const char *string;
01011 int number, c;
01012
01013
01014 read_name (tmp_char, infile);
01015 m = add_mapping (group, table, tmp_char, infile);
01016
01017 c = read_skip_spaces (infile);
01018 if (c != '[')
01019 fatal_expected_char (infile, '[', c);
01020
01021
01022 end_ptr = &m->values;
01023 c = read_skip_spaces (infile);
01024 do
01025 {
01026 if (c != '(')
01027 {
01028
01029
01030 ungetc (c, infile);
01031 read_name (tmp_char, infile);
01032 string = "";
01033 }
01034 else
01035 {
01036
01037 read_name (tmp_char, infile);
01038 string = read_string (infile, false);
01039 c = read_skip_spaces (infile);
01040 if (c != ')')
01041 fatal_expected_char (infile, ')', c);
01042 }
01043 number = group->find_builtin (tmp_char, infile);
01044 end_ptr = add_map_value (end_ptr, number, string);
01045 c = read_skip_spaces (infile);
01046 }
01047 while (c != ']');
01048
01049 c = read_skip_spaces (infile);
01050 if (c != ')')
01051 fatal_expected_char (infile, ')', c);
01052
01053 return m;
01054 }
01055
01056
01057
01058
01059 static void
01060 check_code_macro (struct mapping *macro, FILE *infile)
01061 {
01062 struct map_value *v;
01063 enum rtx_code bellwether;
01064
01065 bellwether = macro->values->number;
01066 for (v = macro->values->next; v != 0; v = v->next)
01067 if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
01068 fatal_with_file_and_line (infile, "code macro `%s' combines "
01069 "different rtx formats", macro->name);
01070
01071 bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
01072 macro->index + 1);
01073 bellwether_codes[macro->index] = bellwether;
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 bool
01085 read_rtx (FILE *infile, rtx *x, int *lineno)
01086 {
01087 static rtx queue_head, queue_next;
01088 static int queue_lineno;
01089 int c;
01090
01091
01092 if (queue_head == 0)
01093 {
01094 initialize_macros ();
01095 obstack_init (&string_obstack);
01096 queue_head = rtx_alloc (EXPR_LIST);
01097 }
01098
01099 if (queue_next == 0)
01100 {
01101 c = read_skip_spaces (infile);
01102 if (c == EOF)
01103 return false;
01104 ungetc (c, infile);
01105
01106 queue_next = queue_head;
01107 queue_lineno = read_rtx_lineno;
01108 XEXP (queue_next, 0) = read_rtx_1 (infile);
01109 XEXP (queue_next, 1) = 0;
01110
01111 htab_traverse (modes.macros, apply_macro_traverse, queue_next);
01112 htab_traverse (codes.macros, apply_macro_traverse, queue_next);
01113 }
01114
01115 *x = XEXP (queue_next, 0);
01116 *lineno = queue_lineno;
01117 queue_next = XEXP (queue_next, 1);
01118
01119 return true;
01120 }
01121
01122
01123
01124
01125 static rtx
01126 read_rtx_1 (FILE *infile)
01127 {
01128 int i;
01129 RTX_CODE real_code, bellwether_code;
01130 const char *format_ptr;
01131
01132
01133
01134 char tmp_char[256];
01135 rtx return_rtx;
01136 int c;
01137 int tmp_int;
01138 HOST_WIDE_INT tmp_wide;
01139
01140
01141 struct rtx_list
01142 {
01143 struct rtx_list *next;
01144 rtx value;
01145 };
01146
01147 again:
01148 c = read_skip_spaces (infile);
01149 if (c != '(')
01150 fatal_expected_char (infile, '(', c);
01151
01152 read_name (tmp_char, infile);
01153 if (strcmp (tmp_char, "nil") == 0)
01154 {
01155
01156 c = read_skip_spaces (infile);
01157 if (c != ')')
01158 fatal_expected_char (infile, ')', c);
01159 return 0;
01160 }
01161 if (strcmp (tmp_char, "define_constants") == 0)
01162 {
01163 read_constants (infile, tmp_char);
01164 goto again;
01165 }
01166 if (strcmp (tmp_char, "define_mode_attr") == 0)
01167 {
01168 read_mapping (&modes, modes.attrs, infile);
01169 goto again;
01170 }
01171 if (strcmp (tmp_char, "define_mode_macro") == 0)
01172 {
01173 read_mapping (&modes, modes.macros, infile);
01174 goto again;
01175 }
01176 if (strcmp (tmp_char, "define_code_attr") == 0)
01177 {
01178 read_mapping (&codes, codes.attrs, infile);
01179 goto again;
01180 }
01181 if (strcmp (tmp_char, "define_code_macro") == 0)
01182 {
01183 check_code_macro (read_mapping (&codes, codes.macros, infile), infile);
01184 goto again;
01185 }
01186 real_code = find_macro (&codes, tmp_char, infile);
01187 bellwether_code = BELLWETHER_CODE (real_code);
01188
01189
01190 return_rtx = rtx_alloc (bellwether_code);
01191 format_ptr = GET_RTX_FORMAT (bellwether_code);
01192 PUT_CODE (return_rtx, real_code);
01193
01194
01195
01196
01197 i = read_skip_spaces (infile);
01198 if (i == ':')
01199 {
01200 read_name (tmp_char, infile);
01201 PUT_MODE (return_rtx, find_macro (&modes, tmp_char, infile));
01202 }
01203 else
01204 ungetc (i, infile);
01205
01206 for (i = 0; format_ptr[i] != 0; i++)
01207 switch (format_ptr[i])
01208 {
01209
01210
01211 case '0':
01212 break;
01213
01214 case 'e':
01215 case 'u':
01216 XEXP (return_rtx, i) = read_rtx_1 (infile);
01217 break;
01218
01219 case 'V':
01220
01221
01222 c = read_skip_spaces (infile);
01223 ungetc (c, infile);
01224 if (c == ')')
01225 {
01226 XVEC (return_rtx, i) = 0;
01227 break;
01228 }
01229
01230
01231 case 'E':
01232 {
01233
01234 struct obstack vector_stack;
01235 int list_counter = 0;
01236 rtvec return_vec = NULL_RTVEC;
01237
01238 c = read_skip_spaces (infile);
01239 if (c != '[')
01240 fatal_expected_char (infile, '[', c);
01241
01242
01243 obstack_init (&vector_stack);
01244 while ((c = read_skip_spaces (infile)) && c != ']')
01245 {
01246 ungetc (c, infile);
01247 list_counter++;
01248 obstack_ptr_grow (&vector_stack, read_rtx_1 (infile));
01249 }
01250 if (list_counter > 0)
01251 {
01252 return_vec = rtvec_alloc (list_counter);
01253 memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
01254 list_counter * sizeof (rtx));
01255 }
01256 else if (format_ptr[i] == 'E')
01257 fatal_with_file_and_line (infile,
01258 "vector must have at least one element");
01259 XVEC (return_rtx, i) = return_vec;
01260 obstack_free (&vector_stack, NULL);
01261
01262 }
01263 break;
01264
01265 case 'S':
01266 case 'T':
01267 case 's':
01268 {
01269 char *stringbuf;
01270 int star_if_braced;
01271
01272 c = read_skip_spaces (infile);
01273 ungetc (c, infile);
01274 if (c == ')')
01275 {
01276
01277
01278
01279 XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : "");
01280 break;
01281 }
01282
01283
01284
01285
01286
01287 star_if_braced = (format_ptr[i] == 'T');
01288
01289 stringbuf = read_string (infile, star_if_braced);
01290
01291
01292
01293
01294
01295 if (*stringbuf == '\0'
01296 && i == 0
01297 && (GET_CODE (return_rtx) == DEFINE_INSN
01298 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
01299 {
01300 char line_name[20];
01301 const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
01302 const char *slash;
01303 for (slash = fn; *slash; slash ++)
01304 if (*slash == '/' || *slash == '\\' || *slash == ':')
01305 fn = slash + 1;
01306 obstack_1grow (&string_obstack, '*');
01307 obstack_grow (&string_obstack, fn, strlen (fn));
01308 sprintf (line_name, ":%d", read_rtx_lineno);
01309 obstack_grow (&string_obstack, line_name, strlen (line_name)+1);
01310 stringbuf = (char *) obstack_finish (&string_obstack);
01311 }
01312
01313 if (star_if_braced)
01314 XTMPL (return_rtx, i) = stringbuf;
01315 else
01316 XSTR (return_rtx, i) = stringbuf;
01317 }
01318 break;
01319
01320 case 'w':
01321 read_name (tmp_char, infile);
01322 validate_const_int (infile, tmp_char);
01323 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
01324 tmp_wide = atoi (tmp_char);
01325 #else
01326 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
01327 tmp_wide = atol (tmp_char);
01328 #else
01329
01330
01331 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
01332 tmp_wide = atoll (tmp_char);
01333 #else
01334 tmp_wide = atoq (tmp_char);
01335 #endif
01336 #endif
01337 #endif
01338 XWINT (return_rtx, i) = tmp_wide;
01339 break;
01340
01341 case 'i':
01342 case 'n':
01343 read_name (tmp_char, infile);
01344 validate_const_int (infile, tmp_char);
01345 tmp_int = atoi (tmp_char);
01346 XINT (return_rtx, i) = tmp_int;
01347 break;
01348
01349 default:
01350 fprintf (stderr,
01351 "switch format wrong in rtl.read_rtx(). format was: %c.\n",
01352 format_ptr[i]);
01353 fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
01354 abort ();
01355 }
01356
01357 c = read_skip_spaces (infile);
01358 if (c != ')')
01359 fatal_expected_char (infile, ')', c);
01360
01361 return return_rtx;
01362 }