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 #include "hconfig.h"
00026 #include "system.h"
00027 #include "rtl.h"
00028 #include "obstack.h"
00029 #include "errors.h"
00030 #include "hashtab.h"
00031 #include "gensupport.h"
00032
00033
00034
00035 int target_flags;
00036
00037 int insn_elision = 1;
00038
00039 static struct obstack obstack;
00040 struct obstack *rtl_obstack = &obstack;
00041
00042 static int sequence_num;
00043 static int errors;
00044
00045 static int predicable_default;
00046 static const char *predicable_true;
00047 static const char *predicable_false;
00048
00049 static htab_t condition_table;
00050
00051 static char *base_dir = NULL;
00052
00053
00054
00055
00056 struct queue_elem
00057 {
00058 rtx data;
00059 const char *filename;
00060 int lineno;
00061 struct queue_elem *next;
00062 };
00063
00064 static struct queue_elem *define_attr_queue;
00065 static struct queue_elem **define_attr_tail = &define_attr_queue;
00066 static struct queue_elem *define_insn_queue;
00067 static struct queue_elem **define_insn_tail = &define_insn_queue;
00068 static struct queue_elem *define_cond_exec_queue;
00069 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
00070 static struct queue_elem *other_queue;
00071 static struct queue_elem **other_tail = &other_queue;
00072
00073 static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
00074 const char *, int));
00075
00076
00077
00078
00079 size_t max_include_len;
00080
00081 struct file_name_list
00082 {
00083 struct file_name_list *next;
00084 const char *fname;
00085 };
00086
00087 struct file_name_list *first_dir_md_include = 0;
00088
00089 struct file_name_list *first_bracket_include = 0;
00090 struct file_name_list *last_dir_md_include = 0;
00091
00092 static void remove_constraints PARAMS ((rtx));
00093 static void process_rtx PARAMS ((rtx, int));
00094
00095 static int is_predicable PARAMS ((struct queue_elem *));
00096 static void identify_predicable_attribute PARAMS ((void));
00097 static int n_alternatives PARAMS ((const char *));
00098 static void collect_insn_data PARAMS ((rtx, int *, int *));
00099 static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
00100 static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
00101 struct queue_elem *));
00102 static char *shift_output_template PARAMS ((char *, const char *, int));
00103 static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
00104 struct queue_elem *,
00105 int, int));
00106 static void process_one_cond_exec PARAMS ((struct queue_elem *));
00107 static void process_define_cond_exec PARAMS ((void));
00108 static void process_include PARAMS ((rtx, int));
00109 static char *save_string PARAMS ((const char *, int));
00110
00111 void
00112 message_with_line VPARAMS ((int lineno, const char *msg, ...))
00113 {
00114 #ifdef SGI_MONGOOSE
00115 va_list ap;
00116 VA_START (ap, msg);
00117 #else
00118 VA_OPEN (ap, msg);
00119 VA_FIXEDARG (ap, int, lineno);
00120 VA_FIXEDARG (ap, const char *, msg);
00121 #endif
00122
00123 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
00124 vfprintf (stderr, msg, ap);
00125 fputc ('\n', stderr);
00126
00127 #ifndef SGI_MONGOOSE
00128 VA_CLOSE (ap);
00129 #else
00130 va_end (ap);
00131 #endif
00132 }
00133
00134
00135
00136
00137 rtx
00138 gen_rtx_CONST_INT (mode, arg)
00139 enum machine_mode mode ATTRIBUTE_UNUSED;
00140 HOST_WIDE_INT arg;
00141 {
00142 rtx rt = rtx_alloc (CONST_INT);
00143
00144 XWINT (rt, 0) = arg;
00145 return rt;
00146 }
00147
00148
00149
00150 static void
00151 queue_pattern (pattern, list_tail, filename, lineno)
00152 rtx pattern;
00153 struct queue_elem ***list_tail;
00154 const char *filename;
00155 int lineno;
00156 {
00157 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
00158 e->data = pattern;
00159 e->filename = filename;
00160 e->lineno = lineno;
00161 e->next = NULL;
00162 **list_tail = e;
00163 *list_tail = &e->next;
00164 }
00165
00166
00167
00168 static void
00169 remove_constraints (part)
00170 rtx part;
00171 {
00172 int i, j;
00173 const char *format_ptr;
00174
00175 if (part == 0)
00176 return;
00177
00178 if (GET_CODE (part) == MATCH_OPERAND)
00179 XSTR (part, 2) = "";
00180 else if (GET_CODE (part) == MATCH_SCRATCH)
00181 XSTR (part, 1) = "";
00182
00183 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
00184
00185 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
00186 switch (*format_ptr++)
00187 {
00188 case 'e':
00189 case 'u':
00190 remove_constraints (XEXP (part, i));
00191 break;
00192 case 'E':
00193 if (XVEC (part, i) != NULL)
00194 for (j = 0; j < XVECLEN (part, i); j++)
00195 remove_constraints (XVECEXP (part, i, j));
00196 break;
00197 }
00198 }
00199
00200
00201
00202
00203 static void
00204 process_include (desc, lineno)
00205 rtx desc;
00206 int lineno;
00207 {
00208 const char *filename = XSTR (desc, 0);
00209 const char *old_filename;
00210 int old_lineno;
00211 char *pathname;
00212 FILE *input_file;
00213
00214
00215 if (! IS_ABSOLUTE_PATHNAME (filename))
00216 {
00217 struct file_name_list *stackp;
00218
00219
00220 for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
00221 {
00222 static const char sep[2] = { DIR_SEPARATOR, '\0' };
00223
00224 pathname = concat (stackp->fname, sep, filename, NULL);
00225 input_file = fopen (pathname, "r");
00226 if (input_file != NULL)
00227 goto success;
00228 free (pathname);
00229 }
00230 }
00231
00232 if (base_dir)
00233 pathname = concat (base_dir, filename, NULL);
00234 else
00235 pathname = xstrdup (filename);
00236 input_file = fopen (pathname, "r");
00237 if (input_file == NULL)
00238 {
00239 free (pathname);
00240 message_with_line (lineno, "include file `%s' not found", filename);
00241 errors = 1;
00242 return;
00243 }
00244 success:
00245
00246
00247
00248
00249 old_filename = read_rtx_filename;
00250 old_lineno = read_rtx_lineno;
00251 read_rtx_filename = pathname;
00252 read_rtx_lineno = 1;
00253
00254
00255 while (1)
00256 {
00257 rtx desc;
00258 int c;
00259
00260 c = read_skip_spaces (input_file);
00261 if (c == EOF)
00262 break;
00263
00264 ungetc (c, input_file);
00265 lineno = read_rtx_lineno;
00266 desc = read_rtx (input_file);
00267 process_rtx (desc, lineno);
00268 }
00269
00270
00271
00272
00273 read_rtx_filename = old_filename;
00274 read_rtx_lineno = old_lineno;
00275
00276 fclose (input_file);
00277 }
00278
00279
00280
00281 static void
00282 process_rtx (desc, lineno)
00283 rtx desc;
00284 int lineno;
00285 {
00286 switch (GET_CODE (desc))
00287 {
00288 case DEFINE_INSN:
00289 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
00290 break;
00291
00292 case DEFINE_COND_EXEC:
00293 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
00294 break;
00295
00296 case DEFINE_ATTR:
00297 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
00298 break;
00299
00300 case INCLUDE:
00301 process_include (desc, lineno);
00302 break;
00303
00304 case DEFINE_INSN_AND_SPLIT:
00305 {
00306 const char *split_cond;
00307 rtx split;
00308 rtvec attr;
00309 int i;
00310
00311
00312 split = rtx_alloc (DEFINE_SPLIT);
00313
00314 i = XVECLEN (desc, 1);
00315 XVEC (split, 0) = rtvec_alloc (i);
00316 while (--i >= 0)
00317 {
00318 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
00319 remove_constraints (XVECEXP (split, 0, i));
00320 }
00321
00322
00323
00324 split_cond = XSTR (desc, 4);
00325 if (split_cond[0] == '&' && split_cond[1] == '&')
00326 split_cond = concat (XSTR (desc, 2), split_cond, NULL);
00327 XSTR (split, 1) = split_cond;
00328 XVEC (split, 2) = XVEC (desc, 5);
00329 XSTR (split, 3) = XSTR (desc, 6);
00330
00331
00332 attr = XVEC (desc, 7);
00333 PUT_CODE (desc, DEFINE_INSN);
00334 XVEC (desc, 4) = attr;
00335
00336
00337 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
00338 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
00339 break;
00340 }
00341
00342 default:
00343 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
00344 break;
00345 }
00346 }
00347
00348
00349
00350
00351 static int
00352 is_predicable (elem)
00353 struct queue_elem *elem;
00354 {
00355 rtvec vec = XVEC (elem->data, 4);
00356 const char *value;
00357 int i;
00358
00359 if (! vec)
00360 return predicable_default;
00361
00362 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
00363 {
00364 rtx sub = RTVEC_ELT (vec, i);
00365 switch (GET_CODE (sub))
00366 {
00367 case SET_ATTR:
00368 if (strcmp (XSTR (sub, 0), "predicable") == 0)
00369 {
00370 value = XSTR (sub, 1);
00371 goto found;
00372 }
00373 break;
00374
00375 case SET_ATTR_ALTERNATIVE:
00376 if (strcmp (XSTR (sub, 0), "predicable") == 0)
00377 {
00378 message_with_line (elem->lineno,
00379 "multiple alternatives for `predicable'");
00380 errors = 1;
00381 return 0;
00382 }
00383 break;
00384
00385 case SET:
00386 if (GET_CODE (SET_DEST (sub)) != ATTR
00387 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
00388 break;
00389 sub = SET_SRC (sub);
00390 if (GET_CODE (sub) == CONST_STRING)
00391 {
00392 value = XSTR (sub, 0);
00393 goto found;
00394 }
00395
00396
00397
00398
00399 message_with_line (elem->lineno,
00400 "non-constant value for `predicable'");
00401 errors = 1;
00402 return 0;
00403
00404 default:
00405 abort ();
00406 }
00407 }
00408
00409 return predicable_default;
00410
00411 found:
00412
00413
00414
00415
00416 if (strchr (value, ',') != NULL)
00417 {
00418 message_with_line (elem->lineno,
00419 "multiple alternatives for `predicable'");
00420 errors = 1;
00421 return 0;
00422 }
00423
00424
00425 if (strcmp (value, predicable_true) == 0)
00426 return 1;
00427 if (strcmp (value, predicable_false) == 0)
00428 return 0;
00429
00430 message_with_line (elem->lineno,
00431 "unknown value `%s' for `predicable' attribute",
00432 value);
00433 errors = 1;
00434 return 0;
00435 }
00436
00437
00438
00439
00440 static void
00441 identify_predicable_attribute ()
00442 {
00443 struct queue_elem *elem;
00444 char *p_true, *p_false;
00445 const char *value;
00446
00447
00448 for (elem = define_attr_queue; elem ; elem = elem->next)
00449 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
00450 goto found;
00451
00452 message_with_line (define_cond_exec_queue->lineno,
00453 "attribute `predicable' not defined");
00454 errors = 1;
00455 return;
00456
00457 found:
00458 value = XSTR (elem->data, 1);
00459 p_false = xstrdup (value);
00460 p_true = strchr (p_false, ',');
00461 if (p_true == NULL || strchr (++p_true, ',') != NULL)
00462 {
00463 message_with_line (elem->lineno,
00464 "attribute `predicable' is not a boolean");
00465 errors = 1;
00466 return;
00467 }
00468 p_true[-1] = '\0';
00469
00470 predicable_true = p_true;
00471 predicable_false = p_false;
00472
00473 switch (GET_CODE (XEXP (elem->data, 2)))
00474 {
00475 case CONST_STRING:
00476 value = XSTR (XEXP (elem->data, 2), 0);
00477 break;
00478
00479 case CONST:
00480 message_with_line (elem->lineno,
00481 "attribute `predicable' cannot be const");
00482 errors = 1;
00483 return;
00484
00485 default:
00486 message_with_line (elem->lineno,
00487 "attribute `predicable' must have a constant default");
00488 errors = 1;
00489 return;
00490 }
00491
00492 if (strcmp (value, p_true) == 0)
00493 predicable_default = 1;
00494 else if (strcmp (value, p_false) == 0)
00495 predicable_default = 0;
00496 else
00497 {
00498 message_with_line (elem->lineno,
00499 "unknown value `%s' for `predicable' attribute",
00500 value);
00501 errors = 1;
00502 }
00503 }
00504
00505
00506
00507 static int
00508 n_alternatives (s)
00509 const char *s;
00510 {
00511 int n = 1;
00512
00513 if (s)
00514 while (*s)
00515 n += (*s++ == ',');
00516
00517 return n;
00518 }
00519
00520
00521
00522
00523 static void
00524 collect_insn_data (pattern, palt, pmax)
00525 rtx pattern;
00526 int *palt, *pmax;
00527 {
00528 const char *fmt;
00529 enum rtx_code code;
00530 int i, j, len;
00531
00532 code = GET_CODE (pattern);
00533 switch (code)
00534 {
00535 case MATCH_OPERAND:
00536 i = n_alternatives (XSTR (pattern, 2));
00537 *palt = (i > *palt ? i : *palt);
00538
00539
00540 case MATCH_OPERATOR:
00541 case MATCH_SCRATCH:
00542 case MATCH_PARALLEL:
00543 case MATCH_INSN:
00544 i = XINT (pattern, 0);
00545 if (i > *pmax)
00546 *pmax = i;
00547 break;
00548
00549 default:
00550 break;
00551 }
00552
00553 fmt = GET_RTX_FORMAT (code);
00554 len = GET_RTX_LENGTH (code);
00555 for (i = 0; i < len; i++)
00556 {
00557 switch (fmt[i])
00558 {
00559 case 'e': case 'u':
00560 collect_insn_data (XEXP (pattern, i), palt, pmax);
00561 break;
00562
00563 case 'V':
00564 if (XVEC (pattern, i) == NULL)
00565 break;
00566
00567 case 'E':
00568 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
00569 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
00570 break;
00571
00572 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
00573 break;
00574
00575 default:
00576 abort ();
00577 }
00578 }
00579 }
00580
00581 static rtx
00582 alter_predicate_for_insn (pattern, alt, max_op, lineno)
00583 rtx pattern;
00584 int alt, max_op, lineno;
00585 {
00586 const char *fmt;
00587 enum rtx_code code;
00588 int i, j, len;
00589
00590 code = GET_CODE (pattern);
00591 switch (code)
00592 {
00593 case MATCH_OPERAND:
00594 {
00595 const char *c = XSTR (pattern, 2);
00596
00597 if (n_alternatives (c) != 1)
00598 {
00599 message_with_line (lineno,
00600 "too many alternatives for operand %d",
00601 XINT (pattern, 0));
00602 errors = 1;
00603 return NULL;
00604 }
00605
00606
00607 if (c && *c && alt > 1)
00608 {
00609 size_t c_len = strlen (c);
00610 size_t len = alt * (c_len + 1);
00611 char *new_c = (char *) xmalloc (len);
00612
00613 memcpy (new_c, c, c_len);
00614 for (i = 1; i < alt; ++i)
00615 {
00616 new_c[i * (c_len + 1) - 1] = ',';
00617 memcpy (&new_c[i * (c_len + 1)], c, c_len);
00618 }
00619 new_c[len - 1] = '\0';
00620 XSTR (pattern, 2) = new_c;
00621 }
00622 }
00623
00624
00625 case MATCH_OPERATOR:
00626 case MATCH_SCRATCH:
00627 case MATCH_PARALLEL:
00628 case MATCH_INSN:
00629 XINT (pattern, 0) += max_op;
00630 break;
00631
00632 default:
00633 break;
00634 }
00635
00636 fmt = GET_RTX_FORMAT (code);
00637 len = GET_RTX_LENGTH (code);
00638 for (i = 0; i < len; i++)
00639 {
00640 rtx r;
00641
00642 switch (fmt[i])
00643 {
00644 case 'e': case 'u':
00645 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
00646 max_op, lineno);
00647 if (r == NULL)
00648 return r;
00649 break;
00650
00651 case 'E':
00652 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
00653 {
00654 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
00655 alt, max_op, lineno);
00656 if (r == NULL)
00657 return r;
00658 }
00659 break;
00660
00661 case 'i': case 'w': case '0': case 's':
00662 break;
00663
00664 default:
00665 abort ();
00666 }
00667 }
00668
00669 return pattern;
00670 }
00671
00672 static const char *
00673 alter_test_for_insn (ce_elem, insn_elem)
00674 struct queue_elem *ce_elem, *insn_elem;
00675 {
00676 const char *ce_test, *insn_test;
00677
00678 ce_test = XSTR (ce_elem->data, 1);
00679 insn_test = XSTR (insn_elem->data, 2);
00680 if (!ce_test || *ce_test == '\0')
00681 return insn_test;
00682 if (!insn_test || *insn_test == '\0')
00683 return ce_test;
00684
00685 return concat ("(", ce_test, ") && (", insn_test, ")", NULL);
00686 }
00687
00688
00689
00690
00691
00692 static char *
00693 shift_output_template (new, old, disp)
00694 char *new;
00695 const char *old;
00696 int disp;
00697 {
00698 while (*old)
00699 {
00700 char c = *old++;
00701 *new++ = c;
00702 if (c == '%')
00703 {
00704 c = *old++;
00705 if (ISDIGIT ((unsigned char) c))
00706 c += disp;
00707 else if (ISALPHA (c))
00708 {
00709 *new++ = c;
00710 c = *old++ + disp;
00711 }
00712 *new++ = c;
00713 }
00714 }
00715
00716 return new;
00717 }
00718
00719 static const char *
00720 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
00721 struct queue_elem *ce_elem, *insn_elem;
00722 int alt, max_op;
00723 {
00724 const char *ce_out, *insn_out;
00725 char *new, *p;
00726 size_t len, ce_len, insn_len;
00727
00728
00729
00730 ce_out = XSTR (ce_elem->data, 2);
00731 insn_out = XTMPL (insn_elem->data, 3);
00732 if (!ce_out || *ce_out == '\0')
00733 return insn_out;
00734
00735 ce_len = strlen (ce_out);
00736 insn_len = strlen (insn_out);
00737
00738 if (*insn_out == '*')
00739
00740 return insn_out;
00741
00742 if (*insn_out == '@')
00743 {
00744 len = (ce_len + 1) * alt + insn_len + 1;
00745 p = new = xmalloc (len);
00746
00747 do
00748 {
00749 do
00750 *p++ = *insn_out++;
00751 while (ISSPACE ((unsigned char) *insn_out));
00752
00753 if (*insn_out != '#')
00754 {
00755 p = shift_output_template (p, ce_out, max_op);
00756 *p++ = ' ';
00757 }
00758
00759 do
00760 *p++ = *insn_out++;
00761 while (*insn_out && *insn_out != '\n');
00762 }
00763 while (*insn_out);
00764 *p = '\0';
00765 }
00766 else
00767 {
00768 len = ce_len + 1 + insn_len + 1;
00769 new = xmalloc (len);
00770
00771 p = shift_output_template (new, ce_out, max_op);
00772 *p++ = ' ';
00773 memcpy (p, insn_out, insn_len + 1);
00774 }
00775
00776 return new;
00777 }
00778
00779
00780
00781 static void
00782 process_one_cond_exec (ce_elem)
00783 struct queue_elem *ce_elem;
00784 {
00785 struct queue_elem *insn_elem;
00786 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
00787 {
00788 int alternatives, max_operand;
00789 rtx pred, insn, pattern;
00790
00791 if (! is_predicable (insn_elem))
00792 continue;
00793
00794 alternatives = 1;
00795 max_operand = -1;
00796 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
00797 max_operand += 1;
00798
00799 if (XVECLEN (ce_elem->data, 0) != 1)
00800 {
00801 message_with_line (ce_elem->lineno,
00802 "too many patterns in predicate");
00803 errors = 1;
00804 return;
00805 }
00806
00807 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
00808 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
00809 ce_elem->lineno);
00810 if (pred == NULL)
00811 return;
00812
00813
00814 insn = copy_rtx (insn_elem->data);
00815 XSTR (insn, 0) = "";
00816 pattern = rtx_alloc (COND_EXEC);
00817 XEXP (pattern, 0) = pred;
00818 if (XVECLEN (insn, 1) == 1)
00819 {
00820 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
00821 XVECEXP (insn, 1, 0) = pattern;
00822 PUT_NUM_ELEM (XVEC (insn, 1), 1);
00823 }
00824 else
00825 {
00826 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
00827 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
00828 XVEC (insn, 1) = rtvec_alloc (1);
00829 XVECEXP (insn, 1, 0) = pattern;
00830 }
00831
00832 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
00833 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
00834 alternatives, max_operand);
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 queue_pattern (insn, &other_tail, insn_elem->filename,
00851 insn_elem->lineno);
00852 }
00853 }
00854
00855
00856
00857
00858 static void
00859 process_define_cond_exec ()
00860 {
00861 struct queue_elem *elem;
00862
00863 identify_predicable_attribute ();
00864 if (errors)
00865 return;
00866
00867 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
00868 process_one_cond_exec (elem);
00869 }
00870
00871 static char *
00872 save_string (s, len)
00873 const char *s;
00874 int len;
00875 {
00876 register char *result = xmalloc (len + 1);
00877
00878 memcpy (result, s, len);
00879 result[len] = 0;
00880 return result;
00881 }
00882
00883
00884
00885
00886 int
00887 init_md_reader_args (argc, argv)
00888 int argc;
00889 char **argv;
00890 {
00891 int i;
00892 const char *in_fname;
00893
00894 max_include_len = 0;
00895 in_fname = NULL;
00896 for (i = 1; i < argc; i++)
00897 {
00898 if (argv[i][0] != '-')
00899 {
00900 if (in_fname == NULL)
00901 in_fname = argv[i];
00902 }
00903 else
00904 {
00905 int c = argv[i][1];
00906 switch (c)
00907 {
00908 case 'I':
00909 {
00910 struct file_name_list *dirtmp;
00911
00912 dirtmp = (struct file_name_list *)
00913 xmalloc (sizeof (struct file_name_list));
00914 dirtmp->next = 0;
00915 if (first_dir_md_include == 0)
00916 first_dir_md_include = dirtmp;
00917 else
00918 last_dir_md_include->next = dirtmp;
00919 last_dir_md_include = dirtmp;
00920 if (argv[i][1] == 'I' && argv[i][2] != 0)
00921 dirtmp->fname = argv[i] + 2;
00922 else if (i + 1 == argc)
00923 fatal ("directory name missing after -I option");
00924 else
00925 dirtmp->fname = argv[++i];
00926 if (strlen (dirtmp->fname) > max_include_len)
00927 max_include_len = strlen (dirtmp->fname);
00928 }
00929 break;
00930 default:
00931 fatal ("invalid option `%s'", argv[i]);
00932
00933 }
00934 }
00935 }
00936 return init_md_reader (in_fname);
00937 }
00938
00939
00940
00941 int
00942 init_md_reader (filename)
00943 const char *filename;
00944 {
00945 FILE *input_file;
00946 int c;
00947 size_t i;
00948 char *lastsl;
00949
00950 lastsl = strrchr (filename, '/');
00951 if (lastsl != NULL)
00952 base_dir = save_string (filename, lastsl - filename + 1 );
00953
00954 read_rtx_filename = filename;
00955 input_file = fopen (filename, "r");
00956 if (input_file == 0)
00957 {
00958 perror (filename);
00959 return FATAL_EXIT_CODE;
00960 }
00961
00962
00963 condition_table = htab_create (n_insn_conditions,
00964 hash_c_test, cmp_c_test, NULL);
00965
00966 for (i = 0; i < n_insn_conditions; i++)
00967 *(htab_find_slot (condition_table, (PTR) &insn_conditions[i], INSERT))
00968 = (PTR) &insn_conditions[i];
00969
00970 obstack_init (rtl_obstack);
00971 errors = 0;
00972 sequence_num = 0;
00973
00974
00975 while (1)
00976 {
00977 rtx desc;
00978 int lineno;
00979
00980 c = read_skip_spaces (input_file);
00981 if (c == EOF)
00982 break;
00983
00984 ungetc (c, input_file);
00985 lineno = read_rtx_lineno;
00986 desc = read_rtx (input_file);
00987 process_rtx (desc, lineno);
00988 }
00989 fclose (input_file);
00990
00991
00992 if (define_cond_exec_queue != NULL)
00993 process_define_cond_exec ();
00994
00995 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
00996 }
00997
00998
00999
01000 rtx
01001 read_md_rtx (lineno, seqnr)
01002 int *lineno;
01003 int *seqnr;
01004 {
01005 struct queue_elem **queue, *elem;
01006 rtx desc;
01007
01008 discard:
01009
01010
01011 if (define_attr_queue != NULL)
01012 queue = &define_attr_queue;
01013 else if (define_insn_queue != NULL)
01014 queue = &define_insn_queue;
01015 else if (other_queue != NULL)
01016 queue = &other_queue;
01017 else
01018 return NULL_RTX;
01019
01020 elem = *queue;
01021 *queue = elem->next;
01022 desc = elem->data;
01023 read_rtx_filename = elem->filename;
01024 *lineno = elem->lineno;
01025 *seqnr = sequence_num;
01026
01027 free (elem);
01028
01029
01030
01031
01032
01033
01034
01035 switch (GET_CODE (desc))
01036 {
01037 case DEFINE_INSN:
01038 case DEFINE_EXPAND:
01039 if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
01040 sequence_num++;
01041 else if (insn_elision)
01042 goto discard;
01043 break;
01044
01045 case DEFINE_SPLIT:
01046 case DEFINE_PEEPHOLE:
01047 case DEFINE_PEEPHOLE2:
01048 if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
01049 sequence_num++;
01050 else if (insn_elision)
01051 goto discard;
01052 break;
01053
01054 default:
01055 break;
01056 }
01057
01058 return desc;
01059 }
01060
01061
01062
01063
01064
01065 hashval_t
01066 hash_c_test (x)
01067 const PTR x;
01068 {
01069 const struct c_test *a = (const struct c_test *) x;
01070 const unsigned char *base, *s = (const unsigned char *) a->expr;
01071 hashval_t hash;
01072 unsigned char c;
01073 unsigned int len;
01074
01075 base = s;
01076 hash = 0;
01077
01078 while ((c = *s++) != '\0')
01079 {
01080 hash += c + (c << 17);
01081 hash ^= hash >> 2;
01082 }
01083
01084 len = s - base;
01085 hash += len + (len << 17);
01086 hash ^= hash >> 2;
01087
01088 return hash;
01089 }
01090
01091
01092 int
01093 cmp_c_test (x, y)
01094 const PTR x;
01095 const PTR y;
01096 {
01097 const struct c_test *a = (const struct c_test *) x;
01098 const struct c_test *b = (const struct c_test *) y;
01099
01100 return !strcmp (a->expr, b->expr);
01101 }
01102
01103
01104
01105
01106
01107 int
01108 maybe_eval_c_test (expr)
01109 const char *expr;
01110 {
01111 const struct c_test *test;
01112 struct c_test dummy;
01113
01114 if (expr[0] == 0)
01115 return 1;
01116
01117 if (insn_elision_unavailable)
01118 return -1;
01119
01120 dummy.expr = expr;
01121 test = (const struct c_test *) htab_find (condition_table, &dummy);
01122 if (!test)
01123 abort ();
01124
01125 return test->value;
01126 }
01127
01128
01129
01130 int
01131 n_comma_elts (s)
01132 const char *s;
01133 {
01134 int n;
01135
01136 if (*s == '\0')
01137 return 0;
01138
01139 for (n = 1; *s; s++)
01140 if (*s == ',')
01141 n++;
01142
01143 return n;
01144 }
01145
01146
01147
01148
01149
01150
01151
01152 const char *
01153 scan_comma_elt (pstr)
01154 const char **pstr;
01155 {
01156 const char *start;
01157 const char *p = *pstr;
01158
01159 if (*p == ',')
01160 p++;
01161 while (ISSPACE(*p))
01162 p++;
01163
01164 if (*p == '\0')
01165 return NULL;
01166
01167 start = p;
01168
01169 while (*p != ',' && *p != '\0')
01170 p++;
01171
01172 *pstr = p;
01173 return start;
01174 }
01175
01176 #ifndef KEY // We should get these now from libiberty
01177 #ifdef SGI_MONGOOSE
01178
01179 char *
01180 xstrdup (input)
01181 const char *input;
01182 {
01183 register size_t len = strlen (input) + 1;
01184 register char *output = xmalloc (len);
01185 memcpy (output, input, len);
01186 return output;
01187 }
01188
01189 PTR
01190 xrealloc (old, size)
01191 PTR old;
01192 size_t size;
01193 {
01194 register PTR ptr;
01195 if (old)
01196 #if (GCC_VERSION >= 3000)
01197 ptr = (PTR) really_call_realloc (old, size);
01198 #else
01199 ptr = (PTR) realloc (old, size);
01200 #endif
01201 else
01202 #if (GCC_VERSION >= 3000)
01203 ptr = (PTR) really_call_malloc (size);
01204 #else
01205 ptr = (PTR) malloc (size);
01206 #endif
01207 if (!ptr)
01208 fatal ("virtual memory exhausted");
01209 return ptr;
01210 }
01211
01212 PTR
01213 xmalloc (size)
01214 size_t size;
01215 {
01216 #if (GCC_VERSION >= 3000)
01217 register PTR val = (PTR) really_call_malloc (size);
01218 #else
01219 register PTR val = (PTR) malloc (size);
01220 #endif
01221
01222 if (val == 0)
01223 fatal ("virtual memory exhausted");
01224 return val;
01225 }
01226 #endif
01227 #endif // !KEY