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