00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "hconfig.h"
00027 #include "system.h"
00028 #include "rtl.h"
00029 #include "obstack.h"
00030 #include "hashtab.h"
00031
00032 static htab_t md_constants;
00033
00034 static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
00035 ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
00036 static void fatal_expected_char PARAMS ((FILE *, int, int)) ATTRIBUTE_NORETURN;
00037 static void read_name PARAMS ((char *, FILE *));
00038 static char *read_string PARAMS ((struct obstack *, FILE *, int));
00039 static char *read_quoted_string PARAMS ((struct obstack *, FILE *));
00040 static char *read_braced_string PARAMS ((struct obstack *, FILE *));
00041 static void read_escape PARAMS ((struct obstack *, FILE *));
00042 static hashval_t def_hash PARAMS ((const void *));
00043 static int def_name_eq_p PARAMS ((const void *, const void *));
00044 static void read_constants PARAMS ((FILE *infile, char *tmp_char));
00045 static void validate_const_int PARAMS ((FILE *, const char *));
00046
00047
00048
00049
00050 int read_rtx_lineno = 1;
00051
00052
00053 const char *read_rtx_filename = "<unknown>";
00054
00055 static void
00056 fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
00057 {
00058 char context[64];
00059 size_t i;
00060 int c;
00061
00062 VA_OPEN (ap, msg);
00063 VA_FIXEDARG (ap, FILE *, infile);
00064 VA_FIXEDARG (ap, const char *, msg);
00065
00066 fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
00067 vfprintf (stderr, msg, ap);
00068 putc ('\n', stderr);
00069
00070
00071 for (i = 0; i < sizeof (context)-1; ++i)
00072 {
00073 c = getc (infile);
00074 if (c == EOF)
00075 break;
00076 if (c == '\r' || c == '\n')
00077 break;
00078 context[i] = c;
00079 }
00080 context[i] = '\0';
00081
00082 fprintf (stderr, "%s:%d: following context is `%s'\n",
00083 read_rtx_filename, read_rtx_lineno, context);
00084
00085 VA_CLOSE (ap);
00086 exit (1);
00087 }
00088
00089
00090
00091
00092 static void
00093 fatal_expected_char (infile, expected_c, actual_c)
00094 FILE *infile;
00095 int expected_c, actual_c;
00096 {
00097 fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
00098 expected_c, actual_c);
00099 }
00100
00101
00102
00103
00104
00105
00106 int
00107 read_skip_spaces (infile)
00108 FILE *infile;
00109 {
00110 int c;
00111
00112 while (1)
00113 {
00114 c = getc (infile);
00115 switch (c)
00116 {
00117 case '\n':
00118 read_rtx_lineno++;
00119 break;
00120
00121 case ' ': case '\t': case '\f': case '\r':
00122 break;
00123
00124 case ';':
00125 do
00126 c = getc (infile);
00127 while (c != '\n' && c != EOF);
00128 read_rtx_lineno++;
00129 break;
00130
00131 case '/':
00132 {
00133 int prevc;
00134 c = getc (infile);
00135 if (c != '*')
00136 fatal_expected_char (infile, '*', c);
00137
00138 prevc = 0;
00139 while ((c = getc (infile)) && c != EOF)
00140 {
00141 if (c == '\n')
00142 read_rtx_lineno++;
00143 else if (prevc == '*' && c == '/')
00144 break;
00145 prevc = c;
00146 }
00147 }
00148 break;
00149
00150 default:
00151 return c;
00152 }
00153 }
00154 }
00155
00156
00157
00158
00159 static void
00160 read_name (str, infile)
00161 char *str;
00162 FILE *infile;
00163 {
00164 char *p;
00165 int c;
00166
00167 c = read_skip_spaces (infile);
00168
00169 p = str;
00170 while (1)
00171 {
00172 if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
00173 break;
00174 if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
00175 || c == '(' || c == '[')
00176 {
00177 ungetc (c, infile);
00178 break;
00179 }
00180 *p++ = c;
00181 c = getc (infile);
00182 }
00183 if (p == str)
00184 fatal_with_file_and_line (infile, "missing name or number");
00185 if (c == '\n')
00186 read_rtx_lineno++;
00187
00188 *p = 0;
00189
00190 #ifndef SGI_MONGOOSE
00191 if (md_constants)
00192 {
00193
00194 struct md_constant *def;
00195
00196 p = str;
00197 do
00198 {
00199 struct md_constant tmp_def;
00200
00201 tmp_def.name = p;
00202 def = htab_find (md_constants, &tmp_def);
00203 if (def)
00204 p = def->value;
00205 } while (def);
00206 if (p != str)
00207 strcpy (str, p);
00208 }
00209 #endif
00210 }
00211
00212
00213
00214 static void
00215 read_escape (ob, infile)
00216 struct obstack *ob;
00217 FILE *infile;
00218 {
00219 int c = getc (infile);
00220
00221 switch (c)
00222 {
00223
00224 case '\n':
00225 read_rtx_lineno++;
00226 return;
00227
00228
00229 case '\\':
00230 case '"':
00231 case '\'':
00232 break;
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
00244 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
00245 case '7': case 'x':
00246 obstack_1grow (ob, '\\');
00247 break;
00248
00249
00250
00251 case ';':
00252 obstack_grow (ob, "\\n\\t", 4);
00253 return;
00254
00255
00256 default:
00257 fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
00258 read_rtx_filename, read_rtx_lineno, c);
00259 obstack_1grow (ob, '\\');
00260 break;
00261 }
00262
00263 obstack_1grow (ob, c);
00264 }
00265
00266
00267
00268
00269 static char *
00270 read_quoted_string (ob, infile)
00271 struct obstack *ob;
00272 FILE *infile;
00273 {
00274 int c;
00275
00276 while (1)
00277 {
00278 c = getc (infile);
00279 if (c == '\n')
00280 read_rtx_lineno++;
00281 else if (c == '\\')
00282 {
00283 read_escape (ob, infile);
00284 continue;
00285 }
00286 else if (c == '"')
00287 break;
00288
00289 obstack_1grow (ob, c);
00290 }
00291
00292 obstack_1grow (ob, 0);
00293 return obstack_finish (ob);
00294 }
00295
00296
00297
00298
00299 static char *
00300 read_braced_string (ob, infile)
00301 struct obstack *ob;
00302 FILE *infile;
00303 {
00304 int c;
00305 int brace_depth = 1;
00306
00307 obstack_1grow (ob, '{');
00308 while (brace_depth)
00309 {
00310 c = getc (infile);
00311 if (c == '\n')
00312 read_rtx_lineno++;
00313 else if (c == '{')
00314 brace_depth++;
00315 else if (c == '}')
00316 brace_depth--;
00317 else if (c == '\\')
00318 {
00319 read_escape (ob, infile);
00320 continue;
00321 }
00322
00323 obstack_1grow (ob, c);
00324 }
00325
00326 obstack_1grow (ob, 0);
00327 return obstack_finish (ob);
00328 }
00329
00330
00331
00332
00333
00334 static char *
00335 read_string (ob, infile, star_if_braced)
00336 struct obstack *ob;
00337 FILE *infile;
00338 int star_if_braced;
00339 {
00340 char *stringbuf;
00341 int saw_paren = 0;
00342 int c;
00343
00344 c = read_skip_spaces (infile);
00345 if (c == '(')
00346 {
00347 saw_paren = 1;
00348 c = read_skip_spaces (infile);
00349 }
00350
00351 if (c == '"')
00352 stringbuf = read_quoted_string (ob, infile);
00353 else if (c == '{')
00354 {
00355 if (star_if_braced)
00356 obstack_1grow (ob, '*');
00357 stringbuf = read_braced_string (ob, infile);
00358 }
00359 else
00360 fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
00361
00362 if (saw_paren)
00363 {
00364 c = read_skip_spaces (infile);
00365 if (c != ')')
00366 fatal_expected_char (infile, ')', c);
00367 }
00368
00369 return stringbuf;
00370 }
00371
00372
00373
00374 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
00375 HOST_WIDE_INT
00376 atoll (p)
00377 const char *p;
00378 {
00379 int neg = 0;
00380 HOST_WIDE_INT tmp_wide;
00381
00382 while (ISSPACE (*p))
00383 p++;
00384 if (*p == '-')
00385 neg = 1, p++;
00386 else if (*p == '+')
00387 p++;
00388
00389 tmp_wide = 0;
00390 while (ISDIGIT (*p))
00391 {
00392 HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
00393 if (new_wide < tmp_wide)
00394 {
00395
00396 tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
00397 break;
00398 }
00399 tmp_wide = new_wide;
00400 p++;
00401 }
00402
00403 if (neg)
00404 tmp_wide = -tmp_wide;
00405 return tmp_wide;
00406 }
00407 #endif
00408
00409
00410 static hashval_t
00411 def_hash (def)
00412 const void *def;
00413 {
00414 unsigned result, i;
00415 const char *string = ((const struct md_constant *) def)->name;
00416
00417 for (result = i = 0;*string++ != '\0'; i++)
00418 result += ((unsigned char) *string << (i % CHAR_BIT));
00419 return result;
00420 }
00421
00422
00423 static int
00424 def_name_eq_p (def1, def2)
00425 const void *def1, *def2;
00426 {
00427 return ! strcmp (((const struct md_constant *) def1)->name,
00428 ((const struct md_constant *) def2)->name);
00429 }
00430
00431
00432
00433
00434 #ifndef SGI_MONGOOSE
00435 static void
00436 read_constants (infile, tmp_char)
00437 FILE *infile;
00438 char *tmp_char;
00439 {
00440 int c;
00441 htab_t defs;
00442
00443 c = read_skip_spaces (infile);
00444 if (c != '[')
00445 fatal_expected_char (infile, '[', c);
00446 defs = md_constants;
00447 if (! defs)
00448 defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
00449
00450 md_constants = 0;
00451 while ( (c = read_skip_spaces (infile)) != ']')
00452 {
00453 struct md_constant *def;
00454 void **entry_ptr;
00455
00456 if (c != '(')
00457 fatal_expected_char (infile, '(', c);
00458 def = xmalloc (sizeof (struct md_constant));
00459 def->name = tmp_char;
00460 read_name (tmp_char, infile);
00461 entry_ptr = htab_find_slot (defs, def, TRUE);
00462 if (! *entry_ptr)
00463 def->name = xstrdup (tmp_char);
00464 c = read_skip_spaces (infile);
00465 ungetc (c, infile);
00466 read_name (tmp_char, infile);
00467 if (! *entry_ptr)
00468 {
00469 def->value = xstrdup (tmp_char);
00470 *entry_ptr = def;
00471 }
00472 else
00473 {
00474 def = *entry_ptr;
00475 if (strcmp (def->value, tmp_char))
00476 fatal_with_file_and_line (infile,
00477 "redefinition of %s, was %s, now %s",
00478 def->name, def->value, tmp_char);
00479 }
00480 c = read_skip_spaces (infile);
00481 if (c != ')')
00482 fatal_expected_char (infile, ')', c);
00483 }
00484 md_constants = defs;
00485 c = read_skip_spaces (infile);
00486 if (c != ')')
00487 fatal_expected_char (infile, ')', c);
00488 }
00489 #endif
00490
00491
00492
00493
00494 void
00495 traverse_md_constants (callback, info)
00496 htab_trav callback;
00497 void *info;
00498 {
00499 #ifndef SGI_MONGOOSE
00500 if (md_constants)
00501 htab_traverse (md_constants, callback, info);
00502 #endif
00503 }
00504
00505 static void
00506 validate_const_int (infile, string)
00507 FILE *infile;
00508 const char *string;
00509 {
00510 const char *cp;
00511 int valid = 1;
00512
00513 cp = string;
00514 while (*cp && ISSPACE (*cp))
00515 cp++;
00516 if (*cp == '-' || *cp == '+')
00517 cp++;
00518 if (*cp == 0)
00519 valid = 0;
00520 for (; *cp; cp++)
00521 if (! ISDIGIT (*cp))
00522 valid = 0;
00523 if (!valid)
00524 fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
00525 }
00526
00527
00528
00529
00530
00531
00532 rtx
00533 read_rtx (infile)
00534 FILE *infile;
00535 {
00536 int i, j;
00537 RTX_CODE tmp_code;
00538 const char *format_ptr;
00539
00540
00541
00542 char tmp_char[256];
00543 rtx return_rtx;
00544 int c;
00545 int tmp_int;
00546 HOST_WIDE_INT tmp_wide;
00547
00548
00549 static struct obstack rtl_obstack;
00550 static int initialized;
00551
00552
00553 struct rtx_list
00554 {
00555 struct rtx_list *next;
00556 rtx value;
00557 };
00558
00559 if (!initialized) {
00560 obstack_init (&rtl_obstack);
00561 initialized = 1;
00562 }
00563
00564 again:
00565 c = read_skip_spaces (infile);
00566 if (c != '(')
00567 fatal_expected_char (infile, '(', c);
00568
00569 read_name (tmp_char, infile);
00570
00571 tmp_code = UNKNOWN;
00572
00573 #ifndef SGI_MONGOOSE
00574 if (! strcmp (tmp_char, "define_constants"))
00575 {
00576 read_constants (infile, tmp_char);
00577 goto again;
00578 }
00579 #endif
00580 for (i = 0; i < NUM_RTX_CODE; i++)
00581 if (! strcmp (tmp_char, GET_RTX_NAME (i)))
00582 {
00583 tmp_code = (RTX_CODE) i;
00584 break;
00585 }
00586
00587 if (tmp_code == UNKNOWN)
00588 fatal_with_file_and_line (infile, "unknown rtx code `%s'", tmp_char);
00589
00590
00591 if (tmp_code == NIL)
00592 {
00593
00594 while ((c = getc (infile)) && c != ')')
00595 ;
00596
00597 return 0;
00598 }
00599
00600
00601 return_rtx = rtx_alloc (tmp_code);
00602 format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
00603
00604
00605
00606
00607 i = read_skip_spaces (infile);
00608 if (i == ':')
00609 {
00610 read_name (tmp_char, infile);
00611 for (j = 0; j < NUM_MACHINE_MODES; j++)
00612 if (! strcmp (GET_MODE_NAME (j), tmp_char))
00613 break;
00614
00615 if (j == MAX_MACHINE_MODE)
00616 fatal_with_file_and_line (infile, "unknown mode `%s'", tmp_char);
00617
00618 PUT_MODE (return_rtx, (enum machine_mode) j);
00619 }
00620 else
00621 ungetc (i, infile);
00622
00623 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
00624 switch (*format_ptr++)
00625 {
00626
00627
00628 case '0':
00629 break;
00630
00631 case 'e':
00632 case 'u':
00633 XEXP (return_rtx, i) = read_rtx (infile);
00634 break;
00635
00636 case 'V':
00637
00638
00639 c = read_skip_spaces (infile);
00640 ungetc (c, infile);
00641 if (c == ')')
00642 {
00643 XVEC (return_rtx, i) = 0;
00644 break;
00645 }
00646
00647
00648 case 'E':
00649 {
00650
00651 struct obstack vector_stack;
00652 int list_counter = 0;
00653 rtvec return_vec = NULL_RTVEC;
00654
00655 c = read_skip_spaces (infile);
00656 if (c != '[')
00657 fatal_expected_char (infile, '[', c);
00658
00659
00660 obstack_init (&vector_stack);
00661 while ((c = read_skip_spaces (infile)) && c != ']')
00662 {
00663 ungetc (c, infile);
00664 list_counter++;
00665 obstack_ptr_grow (&vector_stack, (PTR) read_rtx (infile));
00666 }
00667 if (list_counter > 0)
00668 {
00669 return_vec = rtvec_alloc (list_counter);
00670 memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
00671 list_counter * sizeof (rtx));
00672 }
00673 XVEC (return_rtx, i) = return_vec;
00674 obstack_free (&vector_stack, NULL);
00675
00676 }
00677 break;
00678
00679 case 'S':
00680
00681
00682 c = read_skip_spaces (infile);
00683 ungetc (c, infile);
00684 if (c == ')')
00685 {
00686 XSTR (return_rtx, i) = 0;
00687 break;
00688 }
00689
00690 case 'T':
00691 case 's':
00692 {
00693 char *stringbuf;
00694
00695
00696
00697
00698
00699 int star_if_braced = (format_ptr[-1] == 'T');
00700
00701 stringbuf = read_string (&rtl_obstack, infile, star_if_braced);
00702
00703
00704
00705
00706
00707 if (*stringbuf == '\0'
00708 && i == 0
00709 && (GET_CODE (return_rtx) == DEFINE_INSN
00710 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
00711 {
00712 char line_name[20];
00713 const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
00714 const char *slash;
00715 for (slash = fn; *slash; slash ++)
00716 if (*slash == '/' || *slash == '\\' || *slash == ':')
00717 fn = slash + 1;
00718 obstack_1grow (&rtl_obstack, '*');
00719 obstack_grow (&rtl_obstack, fn, strlen (fn));
00720 sprintf (line_name, ":%d", read_rtx_lineno);
00721 obstack_grow (&rtl_obstack, line_name, strlen (line_name)+1);
00722 stringbuf = (char *) obstack_finish (&rtl_obstack);
00723 }
00724
00725 if (star_if_braced)
00726 XTMPL (return_rtx, i) = stringbuf;
00727 else
00728 XSTR (return_rtx, i) = stringbuf;
00729 }
00730 break;
00731
00732 case 'w':
00733 read_name (tmp_char, infile);
00734 validate_const_int (infile, tmp_char);
00735 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
00736 tmp_wide = atoi (tmp_char);
00737 #else
00738 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
00739 tmp_wide = atol (tmp_char);
00740 #else
00741
00742
00743 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
00744 tmp_wide = atoll (tmp_char);
00745 #else
00746 tmp_wide = atoq (tmp_char);
00747 #endif
00748 #endif
00749 #endif
00750 XWINT (return_rtx, i) = tmp_wide;
00751 break;
00752
00753 case 'i':
00754 case 'n':
00755 read_name (tmp_char, infile);
00756 validate_const_int (infile, tmp_char);
00757 tmp_int = atoi (tmp_char);
00758 XINT (return_rtx, i) = tmp_int;
00759 break;
00760
00761 default:
00762 fprintf (stderr,
00763 "switch format wrong in rtl.read_rtx(). format was: %c.\n",
00764 format_ptr[-1]);
00765 fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
00766 abort ();
00767 }
00768
00769 c = read_skip_spaces (infile);
00770 if (c != ')')
00771 fatal_expected_char (infile, ')', c);
00772
00773 return return_rtx;
00774 }