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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #include "bconfig.h"
00089 #include "system.h"
00090 #include "coretypes.h"
00091 #include "tm.h"
00092 #include "rtl.h"
00093 #include "errors.h"
00094 #include "gensupport.h"
00095
00096
00097
00098
00099
00100 #define MAX_MAX_OPERANDS 40
00101
00102 static int n_occurrences (int, const char *);
00103 static const char *strip_whitespace (const char *);
00104
00105
00106
00107
00108
00109 static int next_code_number;
00110
00111
00112
00113
00114 static int next_index_number;
00115
00116
00117
00118 static int next_operand_number = 1;
00119
00120
00121
00122 struct operand_data
00123 {
00124 struct operand_data *next;
00125 int index;
00126 const char *predicate;
00127 const char *constraint;
00128 enum machine_mode mode;
00129 unsigned char n_alternatives;
00130 char address_p;
00131 char strict_low;
00132 char eliminable;
00133 char seen;
00134 };
00135
00136
00137
00138 static struct operand_data null_operand =
00139 {
00140 0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0
00141 };
00142
00143 static struct operand_data *odata = &null_operand;
00144 static struct operand_data **odata_end = &null_operand.next;
00145
00146
00147
00148 #define INSN_OUTPUT_FORMAT_NONE 0
00149 #define INSN_OUTPUT_FORMAT_SINGLE 1
00150 #define INSN_OUTPUT_FORMAT_MULTI 2
00151 #define INSN_OUTPUT_FORMAT_FUNCTION 3
00152
00153
00154
00155
00156 struct data
00157 {
00158 struct data *next;
00159 const char *name;
00160 const char *template;
00161 int code_number;
00162 int index_number;
00163 const char *filename;
00164 int lineno;
00165 int n_operands;
00166 int n_dups;
00167 int n_alternatives;
00168 int operand_number;
00169 int output_format;
00170 struct operand_data operand[MAX_MAX_OPERANDS];
00171 };
00172
00173
00174
00175 static struct data *idata, **idata_end = &idata;
00176
00177 static void output_prologue (void);
00178 static void output_operand_data (void);
00179 static void output_insn_data (void);
00180 static void output_get_insn_name (void);
00181 static void scan_operands (struct data *, rtx, int, int);
00182 static int compare_operands (struct operand_data *,
00183 struct operand_data *);
00184 static void place_operands (struct data *);
00185 static void process_template (struct data *, const char *);
00186 static void validate_insn_alternatives (struct data *);
00187 static void validate_insn_operands (struct data *);
00188 static void gen_insn (rtx, int);
00189 static void gen_peephole (rtx, int);
00190 static void gen_expand (rtx, int);
00191 static void gen_split (rtx, int);
00192 static void check_constraint_len (void);
00193 static int constraint_len (const char *, int);
00194
00195 const char *
00196 get_insn_name (int index)
00197 {
00198 static char buf[100];
00199
00200 struct data *i, *last_named = NULL;
00201 for (i = idata; i ; i = i->next)
00202 {
00203 if (i->index_number == index)
00204 return i->name;
00205 if (i->name)
00206 last_named = i;
00207 }
00208
00209 if (last_named)
00210 sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number);
00211 else
00212 sprintf(buf, "insn %d", index);
00213
00214 return buf;
00215 }
00216
00217 static void
00218 output_prologue (void)
00219 {
00220 printf ("/* Generated automatically by the program `genoutput'\n\
00221 from the machine description file `md'. */\n\n");
00222
00223 printf ("#include \"config.h\"\n");
00224 printf ("#include \"system.h\"\n");
00225 printf ("#include \"coretypes.h\"\n");
00226 printf ("#include \"tm.h\"\n");
00227 printf ("#include \"flags.h\"\n");
00228 printf ("#include \"ggc.h\"\n");
00229 printf ("#include \"rtl.h\"\n");
00230 printf ("#include \"expr.h\"\n");
00231 printf ("#include \"insn-codes.h\"\n");
00232 printf ("#include \"tm_p.h\"\n");
00233 printf ("#include \"function.h\"\n");
00234 printf ("#include \"regs.h\"\n");
00235 printf ("#include \"hard-reg-set.h\"\n");
00236 printf ("#include \"real.h\"\n");
00237 printf ("#include \"insn-config.h\"\n\n");
00238 printf ("#include \"conditions.h\"\n");
00239 printf ("#include \"insn-attr.h\"\n\n");
00240 printf ("#include \"recog.h\"\n\n");
00241 printf ("#include \"toplev.h\"\n");
00242 printf ("#include \"output.h\"\n");
00243 printf ("#include \"target.h\"\n");
00244 }
00245
00246 static void
00247 output_operand_data (void)
00248 {
00249 struct operand_data *d;
00250
00251 printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n");
00252
00253 for (d = odata; d; d = d->next)
00254 {
00255 printf (" {\n");
00256
00257 printf (" %s,\n",
00258 d->predicate && d->predicate[0] ? d->predicate : "0");
00259
00260 printf (" \"%s\",\n", d->constraint ? d->constraint : "");
00261
00262 printf (" %smode,\n", GET_MODE_NAME (d->mode));
00263
00264 printf (" %d,\n", d->strict_low);
00265
00266 printf (" %d\n", d->eliminable);
00267
00268 printf(" },\n");
00269 }
00270 printf("};\n\n\n");
00271 }
00272
00273 static void
00274 output_insn_data (void)
00275 {
00276 struct data *d;
00277 int name_offset = 0;
00278 int next_name_offset;
00279 const char * last_name = 0;
00280 const char * next_name = 0;
00281 struct data *n;
00282
00283 for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++)
00284 if (n->name)
00285 {
00286 next_name = n->name;
00287 break;
00288 }
00289
00290 printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
00291 printf ("\nconst struct insn_data insn_data[] = \n{\n");
00292
00293 for (d = idata; d; d = d->next)
00294 {
00295 printf (" /* %s:%d */\n", d->filename, d->lineno);
00296 printf (" {\n");
00297
00298 if (d->name)
00299 {
00300 printf (" \"%s\",\n", d->name);
00301 name_offset = 0;
00302 last_name = d->name;
00303 next_name = 0;
00304 for (n = d->next, next_name_offset = 1; n;
00305 n = n->next, next_name_offset++)
00306 {
00307 if (n->name)
00308 {
00309 next_name = n->name;
00310 break;
00311 }
00312 }
00313 }
00314 else
00315 {
00316 name_offset++;
00317 if (next_name && (last_name == 0
00318 || name_offset > next_name_offset / 2))
00319 printf (" \"%s-%d\",\n", next_name,
00320 next_name_offset - name_offset);
00321 else
00322 printf (" \"%s+%d\",\n", last_name, name_offset);
00323 }
00324
00325 switch (d->output_format)
00326 {
00327 case INSN_OUTPUT_FORMAT_NONE:
00328 printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
00329 printf (" { 0 },\n");
00330 printf ("#else\n");
00331 printf (" { 0, 0, 0 },\n");
00332 printf ("#endif\n");
00333 break;
00334 case INSN_OUTPUT_FORMAT_SINGLE:
00335 {
00336 const char *p = d->template;
00337 char prev = 0;
00338
00339 printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
00340 printf (" { .single =\n");
00341 printf ("#else\n");
00342 printf (" {\n");
00343 printf ("#endif\n");
00344 printf (" \"");
00345 while (*p)
00346 {
00347 if (IS_VSPACE (*p) && prev != '\\')
00348 {
00349
00350
00351 if (*p == '\n' && prev != '\r')
00352 printf ("\\n\\\n");
00353 }
00354 else
00355 putchar (*p);
00356 prev = *p;
00357 ++p;
00358 }
00359 printf ("\",\n");
00360 printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
00361 printf (" },\n");
00362 printf ("#else\n");
00363 printf (" 0, 0 },\n");
00364 printf ("#endif\n");
00365 }
00366 break;
00367 case INSN_OUTPUT_FORMAT_MULTI:
00368 printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
00369 printf (" { .multi = output_%d },\n", d->code_number);
00370 printf ("#else\n");
00371 printf (" { 0, output_%d, 0 },\n", d->code_number);
00372 printf ("#endif\n");
00373 break;
00374 case INSN_OUTPUT_FORMAT_FUNCTION:
00375 printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
00376 printf (" { .function = output_%d },\n", d->code_number);
00377 printf ("#else\n");
00378 printf (" { 0, 0, output_%d },\n", d->code_number);
00379 printf ("#endif\n");
00380 break;
00381 default:
00382 gcc_unreachable ();
00383 }
00384
00385 if (d->name && d->name[0] != '*')
00386 printf (" (insn_gen_fn) gen_%s,\n", d->name);
00387 else
00388 printf (" 0,\n");
00389
00390 printf (" &operand_data[%d],\n", d->operand_number);
00391 printf (" %d,\n", d->n_operands);
00392 printf (" %d,\n", d->n_dups);
00393 printf (" %d,\n", d->n_alternatives);
00394 printf (" %d\n", d->output_format);
00395
00396 printf(" },\n");
00397 }
00398 printf ("};\n\n\n");
00399 }
00400
00401 static void
00402 output_get_insn_name (void)
00403 {
00404 printf ("const char *\n");
00405 printf ("get_insn_name (int code)\n");
00406 printf ("{\n");
00407 printf (" if (code == NOOP_MOVE_INSN_CODE)\n");
00408 printf (" return \"NOOP_MOVE\";\n");
00409 printf (" else\n");
00410 printf (" return insn_data[code].name;\n");
00411 printf ("}\n");
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 static int max_opno;
00423 static int num_dups;
00424
00425 static void
00426 scan_operands (struct data *d, rtx part, int this_address_p,
00427 int this_strict_low)
00428 {
00429 int i, j;
00430 const char *format_ptr;
00431 int opno;
00432
00433 if (part == 0)
00434 return;
00435
00436 switch (GET_CODE (part))
00437 {
00438 case MATCH_OPERAND:
00439 opno = XINT (part, 0);
00440 if (opno > max_opno)
00441 max_opno = opno;
00442 if (max_opno >= MAX_MAX_OPERANDS)
00443 {
00444 message_with_line (d->lineno,
00445 "maximum number of operands exceeded");
00446 have_error = 1;
00447 return;
00448 }
00449 if (d->operand[opno].seen)
00450 {
00451 message_with_line (d->lineno,
00452 "repeated operand number %d\n", opno);
00453 have_error = 1;
00454 }
00455
00456 d->operand[opno].seen = 1;
00457 d->operand[opno].mode = GET_MODE (part);
00458 d->operand[opno].strict_low = this_strict_low;
00459 d->operand[opno].predicate = XSTR (part, 1);
00460 d->operand[opno].constraint = strip_whitespace (XSTR (part, 2));
00461 d->operand[opno].n_alternatives
00462 = n_occurrences (',', d->operand[opno].constraint) + 1;
00463 d->operand[opno].address_p = this_address_p;
00464 d->operand[opno].eliminable = 1;
00465 return;
00466
00467 case MATCH_SCRATCH:
00468 opno = XINT (part, 0);
00469 if (opno > max_opno)
00470 max_opno = opno;
00471 if (max_opno >= MAX_MAX_OPERANDS)
00472 {
00473 message_with_line (d->lineno,
00474 "maximum number of operands exceeded");
00475 have_error = 1;
00476 return;
00477 }
00478 if (d->operand[opno].seen)
00479 {
00480 message_with_line (d->lineno,
00481 "repeated operand number %d\n", opno);
00482 have_error = 1;
00483 }
00484
00485 d->operand[opno].seen = 1;
00486 d->operand[opno].mode = GET_MODE (part);
00487 d->operand[opno].strict_low = 0;
00488 d->operand[opno].predicate = "scratch_operand";
00489 d->operand[opno].constraint = strip_whitespace (XSTR (part, 1));
00490 d->operand[opno].n_alternatives
00491 = n_occurrences (',', d->operand[opno].constraint) + 1;
00492 d->operand[opno].address_p = 0;
00493 d->operand[opno].eliminable = 0;
00494 return;
00495
00496 case MATCH_OPERATOR:
00497 case MATCH_PARALLEL:
00498 opno = XINT (part, 0);
00499 if (opno > max_opno)
00500 max_opno = opno;
00501 if (max_opno >= MAX_MAX_OPERANDS)
00502 {
00503 message_with_line (d->lineno,
00504 "maximum number of operands exceeded");
00505 have_error = 1;
00506 return;
00507 }
00508 if (d->operand[opno].seen)
00509 {
00510 message_with_line (d->lineno,
00511 "repeated operand number %d\n", opno);
00512 have_error = 1;
00513 }
00514
00515 d->operand[opno].seen = 1;
00516 d->operand[opno].mode = GET_MODE (part);
00517 d->operand[opno].strict_low = 0;
00518 d->operand[opno].predicate = XSTR (part, 1);
00519 d->operand[opno].constraint = 0;
00520 d->operand[opno].address_p = 0;
00521 d->operand[opno].eliminable = 0;
00522 for (i = 0; i < XVECLEN (part, 2); i++)
00523 scan_operands (d, XVECEXP (part, 2, i), 0, 0);
00524 return;
00525
00526 case MATCH_DUP:
00527 case MATCH_OP_DUP:
00528 case MATCH_PAR_DUP:
00529 ++num_dups;
00530 break;
00531
00532 case ADDRESS:
00533 scan_operands (d, XEXP (part, 0), 1, 0);
00534 return;
00535
00536 case STRICT_LOW_PART:
00537 scan_operands (d, XEXP (part, 0), 0, 1);
00538 return;
00539
00540 default:
00541 break;
00542 }
00543
00544 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
00545
00546 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
00547 switch (*format_ptr++)
00548 {
00549 case 'e':
00550 case 'u':
00551 scan_operands (d, XEXP (part, i), 0, 0);
00552 break;
00553 case 'E':
00554 if (XVEC (part, i) != NULL)
00555 for (j = 0; j < XVECLEN (part, i); j++)
00556 scan_operands (d, XVECEXP (part, i, j), 0, 0);
00557 break;
00558 }
00559 }
00560
00561
00562
00563 static int
00564 compare_operands (struct operand_data *d0, struct operand_data *d1)
00565 {
00566 const char *p0, *p1;
00567
00568 p0 = d0->predicate;
00569 if (!p0)
00570 p0 = "";
00571 p1 = d1->predicate;
00572 if (!p1)
00573 p1 = "";
00574 if (strcmp (p0, p1) != 0)
00575 return 0;
00576
00577 p0 = d0->constraint;
00578 if (!p0)
00579 p0 = "";
00580 p1 = d1->constraint;
00581 if (!p1)
00582 p1 = "";
00583 if (strcmp (p0, p1) != 0)
00584 return 0;
00585
00586 if (d0->mode != d1->mode)
00587 return 0;
00588
00589 if (d0->strict_low != d1->strict_low)
00590 return 0;
00591
00592 if (d0->eliminable != d1->eliminable)
00593 return 0;
00594
00595 return 1;
00596 }
00597
00598
00599
00600
00601 static void
00602 place_operands (struct data *d)
00603 {
00604 struct operand_data *od, *od2;
00605 int i;
00606
00607 if (d->n_operands == 0)
00608 {
00609 d->operand_number = 0;
00610 return;
00611 }
00612
00613
00614 for (od = odata, i = 0; od; od = od->next, i = 0)
00615 if (compare_operands (od, &d->operand[0]))
00616 {
00617 od2 = od->next;
00618 i = 1;
00619 while (1)
00620 {
00621 if (i == d->n_operands)
00622 goto full_match;
00623 if (od2 == NULL)
00624 goto partial_match;
00625 if (! compare_operands (od2, &d->operand[i]))
00626 break;
00627 ++i, od2 = od2->next;
00628 }
00629 }
00630
00631
00632
00633 partial_match:
00634 d->operand_number = next_operand_number - i;
00635 for (; i < d->n_operands; ++i)
00636 {
00637 od2 = &d->operand[i];
00638 *odata_end = od2;
00639 odata_end = &od2->next;
00640 od2->index = next_operand_number++;
00641 }
00642 *odata_end = NULL;
00643 return;
00644
00645 full_match:
00646 d->operand_number = od->index;
00647 return;
00648 }
00649
00650
00651
00652
00653
00654
00655 static void
00656 process_template (struct data *d, const char *template)
00657 {
00658 const char *cp;
00659 int i;
00660
00661
00662 if (template[0] == '*')
00663 {
00664 d->template = 0;
00665 d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
00666
00667 puts ("\nstatic const char *");
00668 printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
00669 d->code_number);
00670 puts ("{");
00671
00672 puts (template + 1);
00673 puts ("}");
00674 }
00675
00676
00677
00678 else if (template[0] == '@')
00679 {
00680 d->template = 0;
00681 d->output_format = INSN_OUTPUT_FORMAT_MULTI;
00682
00683 printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
00684
00685 for (i = 0, cp = &template[1]; *cp; )
00686 {
00687 const char *ep, *sp;
00688
00689 while (ISSPACE (*cp))
00690 cp++;
00691
00692 printf (" \"");
00693
00694 for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
00695 if (!ISSPACE (*ep))
00696 sp = ep + 1;
00697
00698 if (sp != ep)
00699 message_with_line (d->lineno,
00700 "trailing whitespace in output template");
00701
00702 while (cp < sp)
00703 {
00704 putchar (*cp);
00705 cp++;
00706 }
00707
00708 printf ("\",\n");
00709 i++;
00710 }
00711 if (i == 1)
00712 message_with_line (d->lineno,
00713 "'@' is redundant for output template with single alternative");
00714 if (i != d->n_alternatives)
00715 {
00716 message_with_line (d->lineno,
00717 "wrong number of alternatives in the output template");
00718 have_error = 1;
00719 }
00720
00721 printf ("};\n");
00722 }
00723 else
00724 {
00725 d->template = template;
00726 d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
00727 }
00728 }
00729
00730
00731
00732 static void
00733 validate_insn_alternatives (struct data *d)
00734 {
00735 int n = 0, start;
00736
00737
00738
00739 for (start = 0; start < d->n_operands; start++)
00740 if (d->operand[start].n_alternatives > 0)
00741 {
00742 int len, i;
00743 const char *p;
00744 char c;
00745 int which_alternative = 0;
00746 int alternative_count_unsure = 0;
00747
00748 for (p = d->operand[start].constraint; (c = *p); p += len)
00749 {
00750 len = CONSTRAINT_LEN (c, p);
00751
00752 if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
00753 {
00754 message_with_line (d->lineno,
00755 "invalid length %d for char '%c' in alternative %d of operand %d",
00756 len, c, which_alternative, start);
00757 len = 1;
00758 have_error = 1;
00759 }
00760
00761 if (c == ',')
00762 {
00763 which_alternative++;
00764 continue;
00765 }
00766
00767 for (i = 1; i < len; i++)
00768 if (p[i] == '\0')
00769 {
00770 message_with_line (d->lineno,
00771 "NUL in alternative %d of operand %d",
00772 which_alternative, start);
00773 alternative_count_unsure = 1;
00774 break;
00775 }
00776 else if (strchr (",#*", p[i]))
00777 {
00778 message_with_line (d->lineno,
00779 "'%c' in alternative %d of operand %d",
00780 p[i], which_alternative, start);
00781 alternative_count_unsure = 1;
00782 }
00783 }
00784 if (alternative_count_unsure)
00785 have_error = 1;
00786 else if (n == 0)
00787 n = d->operand[start].n_alternatives;
00788 else if (n != d->operand[start].n_alternatives)
00789 {
00790 message_with_line (d->lineno,
00791 "wrong number of alternatives in operand %d",
00792 start);
00793 have_error = 1;
00794 }
00795 }
00796
00797
00798 d->n_alternatives = n;
00799 }
00800
00801
00802
00803 static void
00804 validate_insn_operands (struct data *d)
00805 {
00806 int i;
00807
00808 for (i = 0; i < d->n_operands; ++i)
00809 if (d->operand[i].seen == 0)
00810 {
00811 message_with_line (d->lineno, "missing operand %d", i);
00812 have_error = 1;
00813 }
00814 }
00815
00816
00817
00818
00819
00820 static void
00821 gen_insn (rtx insn, int lineno)
00822 {
00823 struct data *d = xmalloc (sizeof (struct data));
00824 int i;
00825
00826 d->code_number = next_code_number;
00827 d->index_number = next_index_number;
00828 d->filename = read_rtx_filename;
00829 d->lineno = lineno;
00830 if (XSTR (insn, 0)[0])
00831 d->name = XSTR (insn, 0);
00832 else
00833 d->name = 0;
00834
00835
00836
00837 d->next = 0;
00838 *idata_end = d;
00839 idata_end = &d->next;
00840
00841 max_opno = -1;
00842 num_dups = 0;
00843 memset (d->operand, 0, sizeof (d->operand));
00844
00845 for (i = 0; i < XVECLEN (insn, 1); i++)
00846 scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
00847
00848 d->n_operands = max_opno + 1;
00849 d->n_dups = num_dups;
00850
00851 check_constraint_len ();
00852 validate_insn_operands (d);
00853 validate_insn_alternatives (d);
00854 place_operands (d);
00855 process_template (d, XTMPL (insn, 3));
00856 }
00857
00858
00859
00860
00861
00862 static void
00863 gen_peephole (rtx peep, int lineno)
00864 {
00865 struct data *d = xmalloc (sizeof (struct data));
00866 int i;
00867
00868 d->code_number = next_code_number;
00869 d->index_number = next_index_number;
00870 d->filename = read_rtx_filename;
00871 d->lineno = lineno;
00872 d->name = 0;
00873
00874
00875
00876 d->next = 0;
00877 *idata_end = d;
00878 idata_end = &d->next;
00879
00880 max_opno = -1;
00881 num_dups = 0;
00882 memset (d->operand, 0, sizeof (d->operand));
00883
00884
00885
00886
00887 for (i = 0; i < XVECLEN (peep, 0); i++)
00888 scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
00889
00890 d->n_operands = max_opno + 1;
00891 d->n_dups = 0;
00892
00893 validate_insn_alternatives (d);
00894 place_operands (d);
00895 process_template (d, XTMPL (peep, 2));
00896 }
00897
00898
00899
00900
00901 static void
00902 gen_expand (rtx insn, int lineno)
00903 {
00904 struct data *d = xmalloc (sizeof (struct data));
00905 int i;
00906
00907 d->code_number = next_code_number;
00908 d->index_number = next_index_number;
00909 d->filename = read_rtx_filename;
00910 d->lineno = lineno;
00911 if (XSTR (insn, 0)[0])
00912 d->name = XSTR (insn, 0);
00913 else
00914 d->name = 0;
00915
00916
00917
00918 d->next = 0;
00919 *idata_end = d;
00920 idata_end = &d->next;
00921
00922 max_opno = -1;
00923 num_dups = 0;
00924 memset (d->operand, 0, sizeof (d->operand));
00925
00926
00927
00928
00929 if (XVEC (insn, 1))
00930 for (i = 0; i < XVECLEN (insn, 1); i++)
00931 scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
00932
00933 d->n_operands = max_opno + 1;
00934 d->n_dups = num_dups;
00935 d->template = 0;
00936 d->output_format = INSN_OUTPUT_FORMAT_NONE;
00937
00938 validate_insn_alternatives (d);
00939 place_operands (d);
00940 }
00941
00942
00943
00944
00945 static void
00946 gen_split (rtx split, int lineno)
00947 {
00948 struct data *d = xmalloc (sizeof (struct data));
00949 int i;
00950
00951 d->code_number = next_code_number;
00952 d->index_number = next_index_number;
00953 d->filename = read_rtx_filename;
00954 d->lineno = lineno;
00955 d->name = 0;
00956
00957
00958
00959 d->next = 0;
00960 *idata_end = d;
00961 idata_end = &d->next;
00962
00963 max_opno = -1;
00964 num_dups = 0;
00965 memset (d->operand, 0, sizeof (d->operand));
00966
00967
00968
00969
00970 for (i = 0; i < XVECLEN (split, 0); i++)
00971 scan_operands (d, XVECEXP (split, 0, i), 0, 0);
00972
00973 d->n_operands = max_opno + 1;
00974 d->n_dups = 0;
00975 d->n_alternatives = 0;
00976 d->template = 0;
00977 d->output_format = INSN_OUTPUT_FORMAT_NONE;
00978
00979 place_operands (d);
00980 }
00981
00982 extern int main (int, char **);
00983
00984 int
00985 main (int argc, char **argv)
00986 {
00987 rtx desc;
00988
00989 progname = "genoutput";
00990
00991 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
00992 return (FATAL_EXIT_CODE);
00993
00994 output_prologue ();
00995 next_code_number = 0;
00996 next_index_number = 0;
00997
00998
00999
01000 while (1)
01001 {
01002 int line_no;
01003
01004 desc = read_md_rtx (&line_no, &next_code_number);
01005 if (desc == NULL)
01006 break;
01007
01008 if (GET_CODE (desc) == DEFINE_INSN)
01009 gen_insn (desc, line_no);
01010 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
01011 gen_peephole (desc, line_no);
01012 if (GET_CODE (desc) == DEFINE_EXPAND)
01013 gen_expand (desc, line_no);
01014 if (GET_CODE (desc) == DEFINE_SPLIT
01015 || GET_CODE (desc) == DEFINE_PEEPHOLE2)
01016 gen_split (desc, line_no);
01017 next_index_number++;
01018 }
01019
01020 printf("\n\n");
01021 output_operand_data ();
01022 output_insn_data ();
01023 output_get_insn_name ();
01024
01025 fflush (stdout);
01026 return (ferror (stdout) != 0 || have_error
01027 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
01028 }
01029
01030
01031
01032
01033 static int
01034 n_occurrences (int c, const char *s)
01035 {
01036 int n = 0;
01037
01038 if (s == 0 || *s == '\0')
01039 return -1;
01040
01041 while (*s)
01042 n += (*s++ == c);
01043
01044 return n;
01045 }
01046
01047
01048
01049
01050 static const char *
01051 strip_whitespace (const char *s)
01052 {
01053 char *p, *q;
01054 char ch;
01055
01056 if (s == 0)
01057 return 0;
01058
01059 p = q = xmalloc (strlen (s) + 1);
01060 while ((ch = *s++) != '\0')
01061 if (! ISSPACE (ch))
01062 *p++ = ch;
01063
01064 *p = '\0';
01065 return q;
01066 }
01067
01068
01069
01070
01071 static void
01072 check_constraint_len (void)
01073 {
01074 const char *p;
01075 int d;
01076
01077 for (p = ",#*+=&%!1234567890"; *p; p++)
01078 for (d = -9; d < 9; d++)
01079 gcc_assert (constraint_len (p, d) == d);
01080 }
01081
01082 static int
01083 constraint_len (const char *p, int genoutput_default_constraint_len)
01084 {
01085
01086
01087 gcc_assert (DEFAULT_CONSTRAINT_LEN (*p, p) == 1);
01088
01089
01090 #define DEFAULT_CONSTRAINT_LEN(C,STR) 1
01091
01092
01093 #undef DEFAULT_CONSTRAINT_LEN
01094 #define DEFAULT_CONSTRAINT_LEN(C,STR) \
01095 ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len)
01096 return CONSTRAINT_LEN (*p, p);
01097
01098 #undef DEFAULT_CONSTRAINT_LEN
01099 #define DEFAULT_CONSTRAINT_LEN(C,STR) 1
01100 }