11debfc3dSmrg /* Generate code from to output assembler insns as recognized from rtl.
2*8feb0f0bSmrg Copyright (C) 1987-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg
211debfc3dSmrg /* This program reads the machine description for the compiler target machine
221debfc3dSmrg and produces a file containing these things:
231debfc3dSmrg
241debfc3dSmrg 1. An array of `struct insn_data_d', which is indexed by insn code number,
251debfc3dSmrg which contains:
261debfc3dSmrg
271debfc3dSmrg a. `name' is the name for that pattern. Nameless patterns are
281debfc3dSmrg given a name.
291debfc3dSmrg
301debfc3dSmrg b. `output' hold either the output template, an array of output
311debfc3dSmrg templates, or an output function.
321debfc3dSmrg
331debfc3dSmrg c. `genfun' is the function to generate a body for that pattern,
341debfc3dSmrg given operands as arguments.
351debfc3dSmrg
361debfc3dSmrg d. `n_operands' is the number of distinct operands in the pattern
371debfc3dSmrg for that insn,
381debfc3dSmrg
391debfc3dSmrg e. `n_dups' is the number of match_dup's that appear in the insn's
401debfc3dSmrg pattern. This says how many elements of `recog_data.dup_loc' are
411debfc3dSmrg significant after an insn has been recognized.
421debfc3dSmrg
431debfc3dSmrg f. `n_alternatives' is the number of alternatives in the constraints
441debfc3dSmrg of each pattern.
451debfc3dSmrg
461debfc3dSmrg g. `output_format' tells what type of thing `output' is.
471debfc3dSmrg
481debfc3dSmrg h. `operand' is the base of an array of operand data for the insn.
491debfc3dSmrg
501debfc3dSmrg 2. An array of `struct insn_operand data', used by `operand' above.
511debfc3dSmrg
521debfc3dSmrg a. `predicate', an int-valued function, is the match_operand predicate
531debfc3dSmrg for this operand.
541debfc3dSmrg
551debfc3dSmrg b. `constraint' is the constraint for this operand.
561debfc3dSmrg
571debfc3dSmrg c. `address_p' indicates that the operand appears within ADDRESS
581debfc3dSmrg rtx's.
591debfc3dSmrg
601debfc3dSmrg d. `mode' is the machine mode that that operand is supposed to have.
611debfc3dSmrg
621debfc3dSmrg e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART.
631debfc3dSmrg
641debfc3dSmrg f. `eliminable', is nonzero for operands that are matched normally by
651debfc3dSmrg MATCH_OPERAND; it is zero for operands that should not be changed during
661debfc3dSmrg register elimination such as MATCH_OPERATORs.
671debfc3dSmrg
681debfc3dSmrg g. `allows_mem', is true for operands that accept MEM rtxes.
691debfc3dSmrg
701debfc3dSmrg The code number of an insn is simply its position in the machine
711debfc3dSmrg description; code numbers are assigned sequentially to entries in
721debfc3dSmrg the description, starting with code number 0.
731debfc3dSmrg
741debfc3dSmrg Thus, the following entry in the machine description
751debfc3dSmrg
761debfc3dSmrg (define_insn "clrdf"
771debfc3dSmrg [(set (match_operand:DF 0 "general_operand" "")
781debfc3dSmrg (const_int 0))]
791debfc3dSmrg ""
801debfc3dSmrg "clrd %0")
811debfc3dSmrg
821debfc3dSmrg assuming it is the 25th entry present, would cause
831debfc3dSmrg insn_data[24].template to be "clrd %0", and
841debfc3dSmrg insn_data[24].n_operands to be 1. */
851debfc3dSmrg
861debfc3dSmrg #include "bconfig.h"
871debfc3dSmrg #include "system.h"
881debfc3dSmrg #include "coretypes.h"
891debfc3dSmrg #include "tm.h"
901debfc3dSmrg #include "rtl.h"
911debfc3dSmrg #include "errors.h"
921debfc3dSmrg #include "read-md.h"
931debfc3dSmrg #include "gensupport.h"
941debfc3dSmrg
951debfc3dSmrg /* No instruction can have more operands than this. Sorry for this
961debfc3dSmrg arbitrary limit, but what machine will have an instruction with
971debfc3dSmrg this many operands? */
981debfc3dSmrg
991debfc3dSmrg #define MAX_MAX_OPERANDS 40
1001debfc3dSmrg
1011debfc3dSmrg static char general_mem[] = { TARGET_MEM_CONSTRAINT, 0 };
1021debfc3dSmrg
1031debfc3dSmrg static int n_occurrences (int, const char *);
1041debfc3dSmrg static const char *strip_whitespace (const char *);
1051debfc3dSmrg
1061debfc3dSmrg /* This counts all operands used in the md file. The first is null. */
1071debfc3dSmrg
1081debfc3dSmrg static int next_operand_number = 1;
1091debfc3dSmrg
1101debfc3dSmrg /* Record in this chain all information about the operands we will output. */
1111debfc3dSmrg
1121debfc3dSmrg struct operand_data
1131debfc3dSmrg {
1141debfc3dSmrg struct operand_data *next;
1151debfc3dSmrg int index;
1161debfc3dSmrg const char *predicate;
1171debfc3dSmrg const char *constraint;
1181debfc3dSmrg machine_mode mode;
1191debfc3dSmrg unsigned char n_alternatives;
1201debfc3dSmrg char address_p;
1211debfc3dSmrg char strict_low;
1221debfc3dSmrg char eliminable;
1231debfc3dSmrg char seen;
1241debfc3dSmrg };
1251debfc3dSmrg
1261debfc3dSmrg /* Begin with a null operand at index 0. */
1271debfc3dSmrg
1281debfc3dSmrg static struct operand_data null_operand =
1291debfc3dSmrg {
130a2dc1f3fSmrg 0, 0, "", "", E_VOIDmode, 0, 0, 0, 0, 0
1311debfc3dSmrg };
1321debfc3dSmrg
1331debfc3dSmrg static struct operand_data *odata = &null_operand;
1341debfc3dSmrg static struct operand_data **odata_end = &null_operand.next;
1351debfc3dSmrg
1361debfc3dSmrg /* Must match the constants in recog.h. */
1371debfc3dSmrg
1381debfc3dSmrg #define INSN_OUTPUT_FORMAT_NONE 0 /* abort */
1391debfc3dSmrg #define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */
1401debfc3dSmrg #define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */
1411debfc3dSmrg #define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */
1421debfc3dSmrg
1431debfc3dSmrg /* Record in this chain all information that we will output,
1441debfc3dSmrg associated with the code number of the insn. */
1451debfc3dSmrg
146*8feb0f0bSmrg class data
1471debfc3dSmrg {
148*8feb0f0bSmrg public:
149*8feb0f0bSmrg class data *next;
1501debfc3dSmrg const char *name;
1511debfc3dSmrg const char *template_code;
1521debfc3dSmrg file_location loc;
1531debfc3dSmrg int code_number;
1541debfc3dSmrg int n_generator_args; /* Number of arguments passed to generator */
1551debfc3dSmrg int n_operands; /* Number of operands this insn recognizes */
1561debfc3dSmrg int n_dups; /* Number times match_dup appears in pattern */
1571debfc3dSmrg int n_alternatives; /* Number of alternatives in each constraint */
1581debfc3dSmrg int operand_number; /* Operand index in the big array. */
1591debfc3dSmrg int output_format; /* INSN_OUTPUT_FORMAT_*. */
1601debfc3dSmrg struct operand_data operand[MAX_MAX_OPERANDS];
1611debfc3dSmrg };
1621debfc3dSmrg
1631debfc3dSmrg /* This variable points to the first link in the insn chain. */
164*8feb0f0bSmrg static class data *idata;
1651debfc3dSmrg
1661debfc3dSmrg /* This variable points to the end of the insn chain. This is where
1671debfc3dSmrg everything relevant from the machien description is appended to. */
168*8feb0f0bSmrg static class data **idata_end;
1691debfc3dSmrg
1701debfc3dSmrg
1711debfc3dSmrg static void output_prologue (void);
1721debfc3dSmrg static void output_operand_data (void);
1731debfc3dSmrg static void output_insn_data (void);
1741debfc3dSmrg static void output_get_insn_name (void);
175*8feb0f0bSmrg static void scan_operands (class data *, rtx, int, int);
1761debfc3dSmrg static int compare_operands (struct operand_data *,
1771debfc3dSmrg struct operand_data *);
178*8feb0f0bSmrg static void place_operands (class data *);
179*8feb0f0bSmrg static void process_template (class data *, const char *);
180*8feb0f0bSmrg static void validate_insn_alternatives (class data *);
181*8feb0f0bSmrg static void validate_insn_operands (class data *);
1821debfc3dSmrg
183*8feb0f0bSmrg class constraint_data
1841debfc3dSmrg {
185*8feb0f0bSmrg public:
186*8feb0f0bSmrg class constraint_data *next_this_letter;
1871debfc3dSmrg file_location loc;
1881debfc3dSmrg unsigned int namelen;
1891debfc3dSmrg char name[1];
1901debfc3dSmrg };
1911debfc3dSmrg
1921debfc3dSmrg /* All machine-independent constraint characters (except digits) that
1931debfc3dSmrg are handled outside the define*_constraint mechanism. */
1941debfc3dSmrg static const char indep_constraints[] = ",=+%*?!^$#&g";
1951debfc3dSmrg
196*8feb0f0bSmrg static class constraint_data *
1971debfc3dSmrg constraints_by_letter_table[1 << CHAR_BIT];
1981debfc3dSmrg
1991debfc3dSmrg static int mdep_constraint_len (const char *, file_location, int);
2001debfc3dSmrg static void note_constraint (md_rtx_info *);
2011debfc3dSmrg
2021debfc3dSmrg static void
output_prologue(void)2031debfc3dSmrg output_prologue (void)
2041debfc3dSmrg {
2051debfc3dSmrg printf ("/* Generated automatically by the program `genoutput'\n\
2061debfc3dSmrg from the machine description file `md'. */\n\n");
2071debfc3dSmrg
208a2dc1f3fSmrg printf ("#define IN_TARGET_CODE 1\n");
2091debfc3dSmrg printf ("#include \"config.h\"\n");
2101debfc3dSmrg printf ("#include \"system.h\"\n");
2111debfc3dSmrg printf ("#include \"coretypes.h\"\n");
2121debfc3dSmrg printf ("#include \"backend.h\"\n");
2131debfc3dSmrg printf ("#include \"predict.h\"\n");
2141debfc3dSmrg printf ("#include \"tree.h\"\n");
2151debfc3dSmrg printf ("#include \"rtl.h\"\n");
2161debfc3dSmrg printf ("#include \"flags.h\"\n");
2171debfc3dSmrg printf ("#include \"alias.h\"\n");
2181debfc3dSmrg printf ("#include \"varasm.h\"\n");
2191debfc3dSmrg printf ("#include \"stor-layout.h\"\n");
2201debfc3dSmrg printf ("#include \"calls.h\"\n");
2211debfc3dSmrg printf ("#include \"insn-config.h\"\n");
2221debfc3dSmrg printf ("#include \"expmed.h\"\n");
2231debfc3dSmrg printf ("#include \"dojump.h\"\n");
2241debfc3dSmrg printf ("#include \"explow.h\"\n");
2251debfc3dSmrg printf ("#include \"memmodel.h\"\n");
2261debfc3dSmrg printf ("#include \"emit-rtl.h\"\n");
2271debfc3dSmrg printf ("#include \"stmt.h\"\n");
2281debfc3dSmrg printf ("#include \"expr.h\"\n");
2291debfc3dSmrg printf ("#include \"insn-codes.h\"\n");
2301debfc3dSmrg printf ("#include \"tm_p.h\"\n");
2311debfc3dSmrg printf ("#include \"regs.h\"\n");
2321debfc3dSmrg printf ("#include \"conditions.h\"\n");
2331debfc3dSmrg printf ("#include \"insn-attr.h\"\n\n");
2341debfc3dSmrg printf ("#include \"recog.h\"\n\n");
2351debfc3dSmrg printf ("#include \"diagnostic-core.h\"\n");
2361debfc3dSmrg printf ("#include \"output.h\"\n");
2371debfc3dSmrg printf ("#include \"target.h\"\n");
2381debfc3dSmrg printf ("#include \"tm-constrs.h\"\n");
2391debfc3dSmrg }
2401debfc3dSmrg
2411debfc3dSmrg static void
output_operand_data(void)2421debfc3dSmrg output_operand_data (void)
2431debfc3dSmrg {
2441debfc3dSmrg struct operand_data *d;
2451debfc3dSmrg
2461debfc3dSmrg printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n");
2471debfc3dSmrg
2481debfc3dSmrg for (d = odata; d; d = d->next)
2491debfc3dSmrg {
2501debfc3dSmrg struct pred_data *pred;
2511debfc3dSmrg
2521debfc3dSmrg printf (" {\n");
2531debfc3dSmrg
2541debfc3dSmrg printf (" %s,\n",
2551debfc3dSmrg d->predicate && d->predicate[0] ? d->predicate : "0");
2561debfc3dSmrg
2571debfc3dSmrg printf (" \"%s\",\n", d->constraint ? d->constraint : "");
2581debfc3dSmrg
259a2dc1f3fSmrg printf (" E_%smode,\n", GET_MODE_NAME (d->mode));
2601debfc3dSmrg
2611debfc3dSmrg printf (" %d,\n", d->strict_low);
2621debfc3dSmrg
2631debfc3dSmrg printf (" %d,\n", d->constraint == NULL ? 1 : 0);
2641debfc3dSmrg
2651debfc3dSmrg printf (" %d,\n", d->eliminable);
2661debfc3dSmrg
2671debfc3dSmrg pred = NULL;
2681debfc3dSmrg if (d->predicate)
2691debfc3dSmrg pred = lookup_predicate (d->predicate);
2701debfc3dSmrg printf (" %d\n", pred && pred->codes[MEM]);
2711debfc3dSmrg
2721debfc3dSmrg printf (" },\n");
2731debfc3dSmrg }
2741debfc3dSmrg printf ("};\n\n\n");
2751debfc3dSmrg }
2761debfc3dSmrg
2771debfc3dSmrg static void
output_insn_data(void)2781debfc3dSmrg output_insn_data (void)
2791debfc3dSmrg {
280*8feb0f0bSmrg class data *d;
2811debfc3dSmrg int name_offset = 0;
2821debfc3dSmrg int next_name_offset;
2831debfc3dSmrg const char * last_name = 0;
2841debfc3dSmrg const char * next_name = 0;
285*8feb0f0bSmrg class data *n;
2861debfc3dSmrg
2871debfc3dSmrg for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++)
2881debfc3dSmrg if (n->name)
2891debfc3dSmrg {
2901debfc3dSmrg next_name = n->name;
2911debfc3dSmrg break;
2921debfc3dSmrg }
2931debfc3dSmrg
2941debfc3dSmrg printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
2951debfc3dSmrg printf ("\nconst struct insn_data_d insn_data[] = \n{\n");
2961debfc3dSmrg
2971debfc3dSmrg for (d = idata; d; d = d->next)
2981debfc3dSmrg {
2991debfc3dSmrg printf (" /* %s:%d */\n", d->loc.filename, d->loc.lineno);
3001debfc3dSmrg printf (" {\n");
3011debfc3dSmrg
3021debfc3dSmrg if (d->name)
3031debfc3dSmrg {
3041debfc3dSmrg printf (" \"%s\",\n", d->name);
3051debfc3dSmrg name_offset = 0;
3061debfc3dSmrg last_name = d->name;
3071debfc3dSmrg next_name = 0;
3081debfc3dSmrg for (n = d->next, next_name_offset = 1; n;
3091debfc3dSmrg n = n->next, next_name_offset++)
3101debfc3dSmrg {
3111debfc3dSmrg if (n->name)
3121debfc3dSmrg {
3131debfc3dSmrg next_name = n->name;
3141debfc3dSmrg break;
3151debfc3dSmrg }
3161debfc3dSmrg }
3171debfc3dSmrg }
3181debfc3dSmrg else
3191debfc3dSmrg {
3201debfc3dSmrg name_offset++;
3211debfc3dSmrg if (next_name && (last_name == 0
3221debfc3dSmrg || name_offset > next_name_offset / 2))
3231debfc3dSmrg printf (" \"%s-%d\",\n", next_name,
3241debfc3dSmrg next_name_offset - name_offset);
3251debfc3dSmrg else
3261debfc3dSmrg printf (" \"%s+%d\",\n", last_name, name_offset);
3271debfc3dSmrg }
3281debfc3dSmrg
3291debfc3dSmrg switch (d->output_format)
3301debfc3dSmrg {
3311debfc3dSmrg case INSN_OUTPUT_FORMAT_NONE:
3321debfc3dSmrg printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
3331debfc3dSmrg printf (" { 0 },\n");
3341debfc3dSmrg printf ("#else\n");
3351debfc3dSmrg printf (" { 0, 0, 0 },\n");
3361debfc3dSmrg printf ("#endif\n");
3371debfc3dSmrg break;
3381debfc3dSmrg case INSN_OUTPUT_FORMAT_SINGLE:
3391debfc3dSmrg {
3401debfc3dSmrg const char *p = d->template_code;
3411debfc3dSmrg char prev = 0;
3421debfc3dSmrg
3431debfc3dSmrg printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
3441debfc3dSmrg printf (" { .single =\n");
3451debfc3dSmrg printf ("#else\n");
3461debfc3dSmrg printf (" {\n");
3471debfc3dSmrg printf ("#endif\n");
3481debfc3dSmrg printf (" \"");
3491debfc3dSmrg while (*p)
3501debfc3dSmrg {
3511debfc3dSmrg if (IS_VSPACE (*p) && prev != '\\')
3521debfc3dSmrg {
3531debfc3dSmrg /* Preserve two consecutive \n's or \r's, but treat \r\n
3541debfc3dSmrg as a single newline. */
3551debfc3dSmrg if (*p == '\n' && prev != '\r')
3561debfc3dSmrg printf ("\\n\\\n");
3571debfc3dSmrg }
3581debfc3dSmrg else
3591debfc3dSmrg putchar (*p);
3601debfc3dSmrg prev = *p;
3611debfc3dSmrg ++p;
3621debfc3dSmrg }
3631debfc3dSmrg printf ("\",\n");
3641debfc3dSmrg printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
3651debfc3dSmrg printf (" },\n");
3661debfc3dSmrg printf ("#else\n");
3671debfc3dSmrg printf (" 0, 0 },\n");
3681debfc3dSmrg printf ("#endif\n");
3691debfc3dSmrg }
3701debfc3dSmrg break;
3711debfc3dSmrg case INSN_OUTPUT_FORMAT_MULTI:
3721debfc3dSmrg printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
3731debfc3dSmrg printf (" { .multi = output_%d },\n", d->code_number);
3741debfc3dSmrg printf ("#else\n");
3751debfc3dSmrg printf (" { 0, output_%d, 0 },\n", d->code_number);
3761debfc3dSmrg printf ("#endif\n");
3771debfc3dSmrg break;
3781debfc3dSmrg case INSN_OUTPUT_FORMAT_FUNCTION:
3791debfc3dSmrg printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
3801debfc3dSmrg printf (" { .function = output_%d },\n", d->code_number);
3811debfc3dSmrg printf ("#else\n");
3821debfc3dSmrg printf (" { 0, 0, output_%d },\n", d->code_number);
3831debfc3dSmrg printf ("#endif\n");
3841debfc3dSmrg break;
3851debfc3dSmrg default:
3861debfc3dSmrg gcc_unreachable ();
3871debfc3dSmrg }
3881debfc3dSmrg
3891debfc3dSmrg if (d->name && d->name[0] != '*')
3901debfc3dSmrg printf (" { (insn_gen_fn::stored_funcptr) gen_%s },\n", d->name);
3911debfc3dSmrg else
3921debfc3dSmrg printf (" { 0 },\n");
3931debfc3dSmrg
3941debfc3dSmrg printf (" &operand_data[%d],\n", d->operand_number);
3951debfc3dSmrg printf (" %d,\n", d->n_generator_args);
3961debfc3dSmrg printf (" %d,\n", d->n_operands);
3971debfc3dSmrg printf (" %d,\n", d->n_dups);
3981debfc3dSmrg printf (" %d,\n", d->n_alternatives);
3991debfc3dSmrg printf (" %d\n", d->output_format);
4001debfc3dSmrg
4011debfc3dSmrg printf (" },\n");
4021debfc3dSmrg }
4031debfc3dSmrg printf ("};\n\n\n");
4041debfc3dSmrg }
4051debfc3dSmrg
4061debfc3dSmrg static void
output_get_insn_name(void)4071debfc3dSmrg output_get_insn_name (void)
4081debfc3dSmrg {
4091debfc3dSmrg printf ("const char *\n");
4101debfc3dSmrg printf ("get_insn_name (int code)\n");
4111debfc3dSmrg printf ("{\n");
4121debfc3dSmrg printf (" if (code == NOOP_MOVE_INSN_CODE)\n");
4131debfc3dSmrg printf (" return \"NOOP_MOVE\";\n");
4141debfc3dSmrg printf (" else\n");
4151debfc3dSmrg printf (" return insn_data[code].name;\n");
4161debfc3dSmrg printf ("}\n");
4171debfc3dSmrg }
4181debfc3dSmrg
4191debfc3dSmrg
4201debfc3dSmrg /* Stores the operand data into `d->operand[i]'.
4211debfc3dSmrg
4221debfc3dSmrg THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
4231debfc3dSmrg THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */
4241debfc3dSmrg
4251debfc3dSmrg static void
scan_operands(class data * d,rtx part,int this_address_p,int this_strict_low)426*8feb0f0bSmrg scan_operands (class data *d, rtx part, int this_address_p,
4271debfc3dSmrg int this_strict_low)
4281debfc3dSmrg {
4291debfc3dSmrg int i, j;
4301debfc3dSmrg const char *format_ptr;
4311debfc3dSmrg int opno;
4321debfc3dSmrg
4331debfc3dSmrg if (part == 0)
4341debfc3dSmrg return;
4351debfc3dSmrg
4361debfc3dSmrg switch (GET_CODE (part))
4371debfc3dSmrg {
4381debfc3dSmrg case MATCH_OPERAND:
4391debfc3dSmrg opno = XINT (part, 0);
4401debfc3dSmrg if (opno >= MAX_MAX_OPERANDS)
4411debfc3dSmrg {
4421debfc3dSmrg error_at (d->loc, "maximum number of operands exceeded");
4431debfc3dSmrg return;
4441debfc3dSmrg }
4451debfc3dSmrg if (d->operand[opno].seen)
4461debfc3dSmrg error_at (d->loc, "repeated operand number %d\n", opno);
4471debfc3dSmrg
4481debfc3dSmrg d->operand[opno].seen = 1;
4491debfc3dSmrg d->operand[opno].mode = GET_MODE (part);
4501debfc3dSmrg d->operand[opno].strict_low = this_strict_low;
4511debfc3dSmrg d->operand[opno].predicate = XSTR (part, 1);
4521debfc3dSmrg d->operand[opno].constraint = strip_whitespace (XSTR (part, 2));
4531debfc3dSmrg d->operand[opno].n_alternatives
4541debfc3dSmrg = n_occurrences (',', d->operand[opno].constraint) + 1;
4551debfc3dSmrg d->operand[opno].address_p = this_address_p;
4561debfc3dSmrg d->operand[opno].eliminable = 1;
4571debfc3dSmrg return;
4581debfc3dSmrg
4591debfc3dSmrg case MATCH_SCRATCH:
4601debfc3dSmrg opno = XINT (part, 0);
4611debfc3dSmrg if (opno >= MAX_MAX_OPERANDS)
4621debfc3dSmrg {
4631debfc3dSmrg error_at (d->loc, "maximum number of operands exceeded");
4641debfc3dSmrg return;
4651debfc3dSmrg }
4661debfc3dSmrg if (d->operand[opno].seen)
4671debfc3dSmrg error_at (d->loc, "repeated operand number %d\n", opno);
4681debfc3dSmrg
4691debfc3dSmrg d->operand[opno].seen = 1;
4701debfc3dSmrg d->operand[opno].mode = GET_MODE (part);
4711debfc3dSmrg d->operand[opno].strict_low = 0;
4721debfc3dSmrg d->operand[opno].predicate = "scratch_operand";
4731debfc3dSmrg d->operand[opno].constraint = strip_whitespace (XSTR (part, 1));
4741debfc3dSmrg d->operand[opno].n_alternatives
4751debfc3dSmrg = n_occurrences (',', d->operand[opno].constraint) + 1;
4761debfc3dSmrg d->operand[opno].address_p = 0;
4771debfc3dSmrg d->operand[opno].eliminable = 0;
4781debfc3dSmrg return;
4791debfc3dSmrg
4801debfc3dSmrg case MATCH_OPERATOR:
4811debfc3dSmrg case MATCH_PARALLEL:
4821debfc3dSmrg opno = XINT (part, 0);
4831debfc3dSmrg if (opno >= MAX_MAX_OPERANDS)
4841debfc3dSmrg {
4851debfc3dSmrg error_at (d->loc, "maximum number of operands exceeded");
4861debfc3dSmrg return;
4871debfc3dSmrg }
4881debfc3dSmrg if (d->operand[opno].seen)
4891debfc3dSmrg error_at (d->loc, "repeated operand number %d\n", opno);
4901debfc3dSmrg
4911debfc3dSmrg d->operand[opno].seen = 1;
4921debfc3dSmrg d->operand[opno].mode = GET_MODE (part);
4931debfc3dSmrg d->operand[opno].strict_low = 0;
4941debfc3dSmrg d->operand[opno].predicate = XSTR (part, 1);
4951debfc3dSmrg d->operand[opno].constraint = 0;
4961debfc3dSmrg d->operand[opno].address_p = 0;
4971debfc3dSmrg d->operand[opno].eliminable = 0;
4981debfc3dSmrg for (i = 0; i < XVECLEN (part, 2); i++)
4991debfc3dSmrg scan_operands (d, XVECEXP (part, 2, i), 0, 0);
5001debfc3dSmrg return;
5011debfc3dSmrg
5021debfc3dSmrg case STRICT_LOW_PART:
5031debfc3dSmrg scan_operands (d, XEXP (part, 0), 0, 1);
5041debfc3dSmrg return;
5051debfc3dSmrg
5061debfc3dSmrg default:
5071debfc3dSmrg break;
5081debfc3dSmrg }
5091debfc3dSmrg
5101debfc3dSmrg format_ptr = GET_RTX_FORMAT (GET_CODE (part));
5111debfc3dSmrg
5121debfc3dSmrg for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
5131debfc3dSmrg switch (*format_ptr++)
5141debfc3dSmrg {
5151debfc3dSmrg case 'e':
5161debfc3dSmrg case 'u':
5171debfc3dSmrg scan_operands (d, XEXP (part, i), 0, 0);
5181debfc3dSmrg break;
5191debfc3dSmrg case 'E':
5201debfc3dSmrg if (XVEC (part, i) != NULL)
5211debfc3dSmrg for (j = 0; j < XVECLEN (part, i); j++)
5221debfc3dSmrg scan_operands (d, XVECEXP (part, i, j), 0, 0);
5231debfc3dSmrg break;
5241debfc3dSmrg }
5251debfc3dSmrg }
5261debfc3dSmrg
5271debfc3dSmrg /* Compare two operands for content equality. */
5281debfc3dSmrg
5291debfc3dSmrg static int
compare_operands(struct operand_data * d0,struct operand_data * d1)5301debfc3dSmrg compare_operands (struct operand_data *d0, struct operand_data *d1)
5311debfc3dSmrg {
5321debfc3dSmrg const char *p0, *p1;
5331debfc3dSmrg
5341debfc3dSmrg p0 = d0->predicate;
5351debfc3dSmrg if (!p0)
5361debfc3dSmrg p0 = "";
5371debfc3dSmrg p1 = d1->predicate;
5381debfc3dSmrg if (!p1)
5391debfc3dSmrg p1 = "";
5401debfc3dSmrg if (strcmp (p0, p1) != 0)
5411debfc3dSmrg return 0;
5421debfc3dSmrg
5431debfc3dSmrg p0 = d0->constraint;
5441debfc3dSmrg if (!p0)
5451debfc3dSmrg p0 = "";
5461debfc3dSmrg p1 = d1->constraint;
5471debfc3dSmrg if (!p1)
5481debfc3dSmrg p1 = "";
5491debfc3dSmrg if (strcmp (p0, p1) != 0)
5501debfc3dSmrg return 0;
5511debfc3dSmrg
5521debfc3dSmrg if (d0->mode != d1->mode)
5531debfc3dSmrg return 0;
5541debfc3dSmrg
5551debfc3dSmrg if (d0->strict_low != d1->strict_low)
5561debfc3dSmrg return 0;
5571debfc3dSmrg
5581debfc3dSmrg if (d0->eliminable != d1->eliminable)
5591debfc3dSmrg return 0;
5601debfc3dSmrg
5611debfc3dSmrg return 1;
5621debfc3dSmrg }
5631debfc3dSmrg
5641debfc3dSmrg /* Scan the list of operands we've already committed to output and either
5651debfc3dSmrg find a subsequence that is the same, or allocate a new one at the end. */
5661debfc3dSmrg
5671debfc3dSmrg static void
place_operands(class data * d)568*8feb0f0bSmrg place_operands (class data *d)
5691debfc3dSmrg {
5701debfc3dSmrg struct operand_data *od, *od2;
5711debfc3dSmrg int i;
5721debfc3dSmrg
5731debfc3dSmrg if (d->n_operands == 0)
5741debfc3dSmrg {
5751debfc3dSmrg d->operand_number = 0;
5761debfc3dSmrg return;
5771debfc3dSmrg }
5781debfc3dSmrg
5791debfc3dSmrg /* Brute force substring search. */
5801debfc3dSmrg for (od = odata, i = 0; od; od = od->next, i = 0)
5811debfc3dSmrg if (compare_operands (od, &d->operand[0]))
5821debfc3dSmrg {
5831debfc3dSmrg od2 = od->next;
5841debfc3dSmrg i = 1;
5851debfc3dSmrg while (1)
5861debfc3dSmrg {
5871debfc3dSmrg if (i == d->n_operands)
5881debfc3dSmrg goto full_match;
5891debfc3dSmrg if (od2 == NULL)
5901debfc3dSmrg goto partial_match;
5911debfc3dSmrg if (! compare_operands (od2, &d->operand[i]))
5921debfc3dSmrg break;
5931debfc3dSmrg ++i, od2 = od2->next;
5941debfc3dSmrg }
5951debfc3dSmrg }
5961debfc3dSmrg
5971debfc3dSmrg /* Either partial match at the end of the list, or no match. In either
5981debfc3dSmrg case, we tack on what operands are remaining to the end of the list. */
5991debfc3dSmrg partial_match:
6001debfc3dSmrg d->operand_number = next_operand_number - i;
6011debfc3dSmrg for (; i < d->n_operands; ++i)
6021debfc3dSmrg {
6031debfc3dSmrg od2 = &d->operand[i];
6041debfc3dSmrg *odata_end = od2;
6051debfc3dSmrg odata_end = &od2->next;
6061debfc3dSmrg od2->index = next_operand_number++;
6071debfc3dSmrg }
6081debfc3dSmrg *odata_end = NULL;
6091debfc3dSmrg return;
6101debfc3dSmrg
6111debfc3dSmrg full_match:
6121debfc3dSmrg d->operand_number = od->index;
6131debfc3dSmrg return;
6141debfc3dSmrg }
6151debfc3dSmrg
6161debfc3dSmrg
6171debfc3dSmrg /* Process an assembler template from a define_insn or a define_peephole.
6181debfc3dSmrg It is either the assembler code template, a list of assembler code
6191debfc3dSmrg templates, or C code to generate the assembler code template. */
6201debfc3dSmrg
6211debfc3dSmrg static void
process_template(class data * d,const char * template_code)622*8feb0f0bSmrg process_template (class data *d, const char *template_code)
6231debfc3dSmrg {
6241debfc3dSmrg const char *cp;
6251debfc3dSmrg int i;
6261debfc3dSmrg
6271debfc3dSmrg /* Templates starting with * contain straight code to be run. */
6281debfc3dSmrg if (template_code[0] == '*')
6291debfc3dSmrg {
6301debfc3dSmrg d->template_code = 0;
6311debfc3dSmrg d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
6321debfc3dSmrg
6331debfc3dSmrg puts ("\nstatic const char *");
6341debfc3dSmrg printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx_insn *insn ATTRIBUTE_UNUSED)\n",
6351debfc3dSmrg d->code_number);
6361debfc3dSmrg puts ("{");
6371debfc3dSmrg rtx_reader_ptr->print_md_ptr_loc (template_code);
6381debfc3dSmrg puts (template_code + 1);
6391debfc3dSmrg puts ("}");
6401debfc3dSmrg }
6411debfc3dSmrg
6421debfc3dSmrg /* If the assembler code template starts with a @ it is a newline-separated
6431debfc3dSmrg list of assembler code templates, one for each alternative. */
6441debfc3dSmrg else if (template_code[0] == '@')
6451debfc3dSmrg {
6461debfc3dSmrg int found_star = 0;
6471debfc3dSmrg
6481debfc3dSmrg for (cp = &template_code[1]; *cp; )
6491debfc3dSmrg {
6501debfc3dSmrg while (ISSPACE (*cp))
6511debfc3dSmrg cp++;
6521debfc3dSmrg if (*cp == '*')
6531debfc3dSmrg found_star = 1;
6541debfc3dSmrg while (!IS_VSPACE (*cp) && *cp != '\0')
6551debfc3dSmrg ++cp;
6561debfc3dSmrg }
6571debfc3dSmrg d->template_code = 0;
6581debfc3dSmrg if (found_star)
6591debfc3dSmrg {
6601debfc3dSmrg d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
6611debfc3dSmrg puts ("\nstatic const char *");
6621debfc3dSmrg printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, "
6631debfc3dSmrg "rtx_insn *insn ATTRIBUTE_UNUSED)\n", d->code_number);
6641debfc3dSmrg puts ("{");
6651debfc3dSmrg puts (" switch (which_alternative)\n {");
6661debfc3dSmrg }
6671debfc3dSmrg else
6681debfc3dSmrg {
6691debfc3dSmrg d->output_format = INSN_OUTPUT_FORMAT_MULTI;
6701debfc3dSmrg printf ("\nstatic const char * const output_%d[] = {\n",
6711debfc3dSmrg d->code_number);
6721debfc3dSmrg }
6731debfc3dSmrg
6741debfc3dSmrg for (i = 0, cp = &template_code[1]; *cp; )
6751debfc3dSmrg {
6761debfc3dSmrg const char *ep, *sp, *bp;
6771debfc3dSmrg
6781debfc3dSmrg while (ISSPACE (*cp))
6791debfc3dSmrg cp++;
6801debfc3dSmrg
6811debfc3dSmrg bp = cp;
6821debfc3dSmrg if (found_star)
6831debfc3dSmrg {
6841debfc3dSmrg printf (" case %d:", i);
6851debfc3dSmrg if (*cp == '*')
6861debfc3dSmrg {
6871debfc3dSmrg printf ("\n ");
6881debfc3dSmrg cp++;
6891debfc3dSmrg }
6901debfc3dSmrg else
6911debfc3dSmrg printf (" return \"");
6921debfc3dSmrg }
6931debfc3dSmrg else
6941debfc3dSmrg printf (" \"");
6951debfc3dSmrg
6961debfc3dSmrg for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
6971debfc3dSmrg if (!ISSPACE (*ep))
6981debfc3dSmrg sp = ep + 1;
6991debfc3dSmrg
7001debfc3dSmrg if (sp != ep)
7011debfc3dSmrg message_at (d->loc, "trailing whitespace in output template");
7021debfc3dSmrg
7031debfc3dSmrg while (cp < sp)
7041debfc3dSmrg {
7051debfc3dSmrg putchar (*cp);
7061debfc3dSmrg cp++;
7071debfc3dSmrg }
7081debfc3dSmrg
7091debfc3dSmrg if (!found_star)
7101debfc3dSmrg puts ("\",");
7111debfc3dSmrg else if (*bp != '*')
7121debfc3dSmrg puts ("\";");
7131debfc3dSmrg else
7141debfc3dSmrg {
7151debfc3dSmrg /* The usual action will end with a return.
7161debfc3dSmrg If there is neither break or return at the end, this is
7171debfc3dSmrg assumed to be intentional; this allows to have multiple
7181debfc3dSmrg consecutive alternatives share some code. */
7191debfc3dSmrg puts ("");
7201debfc3dSmrg }
7211debfc3dSmrg i++;
7221debfc3dSmrg }
7231debfc3dSmrg if (i == 1)
7241debfc3dSmrg message_at (d->loc, "'@' is redundant for output template with"
7251debfc3dSmrg " single alternative");
7261debfc3dSmrg if (i != d->n_alternatives)
7271debfc3dSmrg error_at (d->loc, "wrong number of alternatives in the output"
7281debfc3dSmrg " template");
7291debfc3dSmrg
7301debfc3dSmrg if (found_star)
7311debfc3dSmrg puts (" default: gcc_unreachable ();\n }\n}");
7321debfc3dSmrg else
7331debfc3dSmrg printf ("};\n");
7341debfc3dSmrg }
7351debfc3dSmrg else
7361debfc3dSmrg {
7371debfc3dSmrg d->template_code = template_code;
7381debfc3dSmrg d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
7391debfc3dSmrg }
7401debfc3dSmrg }
7411debfc3dSmrg
7421debfc3dSmrg /* Check insn D for consistency in number of constraint alternatives. */
7431debfc3dSmrg
7441debfc3dSmrg static void
validate_insn_alternatives(class data * d)745*8feb0f0bSmrg validate_insn_alternatives (class data *d)
7461debfc3dSmrg {
7471debfc3dSmrg int n = 0, start;
7481debfc3dSmrg
7491debfc3dSmrg /* Make sure all the operands have the same number of alternatives
7501debfc3dSmrg in their constraints. Let N be that number. */
7511debfc3dSmrg for (start = 0; start < d->n_operands; start++)
7521debfc3dSmrg if (d->operand[start].n_alternatives > 0)
7531debfc3dSmrg {
7541debfc3dSmrg int len, i;
7551debfc3dSmrg const char *p;
7561debfc3dSmrg char c;
7571debfc3dSmrg int which_alternative = 0;
7581debfc3dSmrg int alternative_count_unsure = 0;
7591debfc3dSmrg bool seen_write = false;
7601debfc3dSmrg
7611debfc3dSmrg for (p = d->operand[start].constraint; (c = *p); p += len)
7621debfc3dSmrg {
7631debfc3dSmrg if ((c == '%' || c == '=' || c == '+')
7641debfc3dSmrg && p != d->operand[start].constraint)
7651debfc3dSmrg error_at (d->loc, "character '%c' can only be used at the"
7661debfc3dSmrg " beginning of a constraint string", c);
7671debfc3dSmrg
7681debfc3dSmrg if (c == '=' || c == '+')
7691debfc3dSmrg seen_write = true;
7701debfc3dSmrg
7711debfc3dSmrg /* Earlyclobber operands must always be marked write-only
7721debfc3dSmrg or read/write. */
7731debfc3dSmrg if (!seen_write && c == '&')
7741debfc3dSmrg error_at (d->loc, "earlyclobber operands may not be"
7751debfc3dSmrg " read-only in alternative %d", which_alternative);
7761debfc3dSmrg
7771debfc3dSmrg if (ISSPACE (c) || strchr (indep_constraints, c))
7781debfc3dSmrg len = 1;
7791debfc3dSmrg else if (ISDIGIT (c))
7801debfc3dSmrg {
7811debfc3dSmrg const char *q = p;
7821debfc3dSmrg do
7831debfc3dSmrg q++;
7841debfc3dSmrg while (ISDIGIT (*q));
7851debfc3dSmrg len = q - p;
7861debfc3dSmrg }
7871debfc3dSmrg else
7881debfc3dSmrg len = mdep_constraint_len (p, d->loc, start);
7891debfc3dSmrg
7901debfc3dSmrg if (c == ',')
7911debfc3dSmrg {
7921debfc3dSmrg which_alternative++;
7931debfc3dSmrg continue;
7941debfc3dSmrg }
7951debfc3dSmrg
7961debfc3dSmrg for (i = 1; i < len; i++)
7971debfc3dSmrg if (p[i] == '\0')
7981debfc3dSmrg {
7991debfc3dSmrg error_at (d->loc, "NUL in alternative %d of operand %d",
8001debfc3dSmrg which_alternative, start);
8011debfc3dSmrg alternative_count_unsure = 1;
8021debfc3dSmrg break;
8031debfc3dSmrg }
8041debfc3dSmrg else if (strchr (",#*", p[i]))
8051debfc3dSmrg {
8061debfc3dSmrg error_at (d->loc, "'%c' in alternative %d of operand %d",
8071debfc3dSmrg p[i], which_alternative, start);
8081debfc3dSmrg alternative_count_unsure = 1;
8091debfc3dSmrg }
8101debfc3dSmrg }
8111debfc3dSmrg if (!alternative_count_unsure)
8121debfc3dSmrg {
8131debfc3dSmrg if (n == 0)
8141debfc3dSmrg n = d->operand[start].n_alternatives;
8151debfc3dSmrg else if (n != d->operand[start].n_alternatives)
8161debfc3dSmrg error_at (d->loc, "wrong number of alternatives in operand %d",
8171debfc3dSmrg start);
8181debfc3dSmrg }
8191debfc3dSmrg }
8201debfc3dSmrg
8211debfc3dSmrg /* Record the insn's overall number of alternatives. */
8221debfc3dSmrg d->n_alternatives = n;
8231debfc3dSmrg }
8241debfc3dSmrg
8251debfc3dSmrg /* Verify that there are no gaps in operand numbers for INSNs. */
8261debfc3dSmrg
8271debfc3dSmrg static void
validate_insn_operands(class data * d)828*8feb0f0bSmrg validate_insn_operands (class data *d)
8291debfc3dSmrg {
8301debfc3dSmrg int i;
8311debfc3dSmrg
8321debfc3dSmrg for (i = 0; i < d->n_operands; ++i)
8331debfc3dSmrg if (d->operand[i].seen == 0)
8341debfc3dSmrg error_at (d->loc, "missing operand %d", i);
8351debfc3dSmrg }
8361debfc3dSmrg
8371debfc3dSmrg static void
validate_optab_operands(class data * d)838*8feb0f0bSmrg validate_optab_operands (class data *d)
8391debfc3dSmrg {
8401debfc3dSmrg if (!d->name || d->name[0] == '\0' || d->name[0] == '*')
8411debfc3dSmrg return;
8421debfc3dSmrg
8431debfc3dSmrg /* Miscellaneous tests. */
8441debfc3dSmrg if (strncmp (d->name, "cstore", 6) == 0
8451debfc3dSmrg && d->name[strlen (d->name) - 1] == '4'
8461debfc3dSmrg && d->operand[0].mode == VOIDmode)
8471debfc3dSmrg {
8481debfc3dSmrg message_at (d->loc, "missing mode for operand 0 of cstore");
8491debfc3dSmrg have_error = 1;
8501debfc3dSmrg }
8511debfc3dSmrg }
8521debfc3dSmrg
8531debfc3dSmrg /* Look at a define_insn just read. Assign its code number. Record
8541debfc3dSmrg on idata the template and the number of arguments. If the insn has
8551debfc3dSmrg a hairy output action, output a function for now. */
8561debfc3dSmrg
8571debfc3dSmrg static void
gen_insn(md_rtx_info * info)8581debfc3dSmrg gen_insn (md_rtx_info *info)
8591debfc3dSmrg {
8601debfc3dSmrg struct pattern_stats stats;
8611debfc3dSmrg rtx insn = info->def;
8621debfc3dSmrg data *d = new data;
8631debfc3dSmrg int i;
8641debfc3dSmrg
8651debfc3dSmrg d->code_number = info->index;
8661debfc3dSmrg d->loc = info->loc;
8671debfc3dSmrg if (XSTR (insn, 0)[0])
8681debfc3dSmrg d->name = XSTR (insn, 0);
8691debfc3dSmrg else
8701debfc3dSmrg d->name = 0;
8711debfc3dSmrg
8721debfc3dSmrg /* Build up the list in the same order as the insns are seen
8731debfc3dSmrg in the machine description. */
8741debfc3dSmrg d->next = 0;
8751debfc3dSmrg *idata_end = d;
8761debfc3dSmrg idata_end = &d->next;
8771debfc3dSmrg
8781debfc3dSmrg memset (d->operand, 0, sizeof (d->operand));
8791debfc3dSmrg
8801debfc3dSmrg for (i = 0; i < XVECLEN (insn, 1); i++)
8811debfc3dSmrg scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
8821debfc3dSmrg
8831debfc3dSmrg get_pattern_stats (&stats, XVEC (insn, 1));
8841debfc3dSmrg d->n_generator_args = stats.num_generator_args;
8851debfc3dSmrg d->n_operands = stats.num_insn_operands;
8861debfc3dSmrg d->n_dups = stats.num_dups;
8871debfc3dSmrg
8881debfc3dSmrg validate_insn_operands (d);
8891debfc3dSmrg validate_insn_alternatives (d);
8901debfc3dSmrg validate_optab_operands (d);
8911debfc3dSmrg place_operands (d);
8921debfc3dSmrg process_template (d, XTMPL (insn, 3));
8931debfc3dSmrg }
8941debfc3dSmrg
8951debfc3dSmrg /* Look at a define_peephole just read. Assign its code number.
8961debfc3dSmrg Record on idata the template and the number of arguments.
8971debfc3dSmrg If the insn has a hairy output action, output it now. */
8981debfc3dSmrg
8991debfc3dSmrg static void
gen_peephole(md_rtx_info * info)9001debfc3dSmrg gen_peephole (md_rtx_info *info)
9011debfc3dSmrg {
9021debfc3dSmrg struct pattern_stats stats;
9031debfc3dSmrg data *d = new data;
9041debfc3dSmrg int i;
9051debfc3dSmrg
9061debfc3dSmrg d->code_number = info->index;
9071debfc3dSmrg d->loc = info->loc;
9081debfc3dSmrg d->name = 0;
9091debfc3dSmrg
9101debfc3dSmrg /* Build up the list in the same order as the insns are seen
9111debfc3dSmrg in the machine description. */
9121debfc3dSmrg d->next = 0;
9131debfc3dSmrg *idata_end = d;
9141debfc3dSmrg idata_end = &d->next;
9151debfc3dSmrg
9161debfc3dSmrg memset (d->operand, 0, sizeof (d->operand));
9171debfc3dSmrg
9181debfc3dSmrg /* Get the number of operands by scanning all the patterns of the
9191debfc3dSmrg peephole optimizer. But ignore all the rest of the information
9201debfc3dSmrg thus obtained. */
9211debfc3dSmrg rtx peep = info->def;
9221debfc3dSmrg for (i = 0; i < XVECLEN (peep, 0); i++)
9231debfc3dSmrg scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
9241debfc3dSmrg
9251debfc3dSmrg get_pattern_stats (&stats, XVEC (peep, 0));
9261debfc3dSmrg d->n_generator_args = 0;
9271debfc3dSmrg d->n_operands = stats.num_insn_operands;
9281debfc3dSmrg d->n_dups = 0;
9291debfc3dSmrg
9301debfc3dSmrg validate_insn_alternatives (d);
9311debfc3dSmrg place_operands (d);
9321debfc3dSmrg process_template (d, XTMPL (peep, 2));
9331debfc3dSmrg }
9341debfc3dSmrg
9351debfc3dSmrg /* Process a define_expand just read. Assign its code number,
9361debfc3dSmrg only for the purposes of `insn_gen_function'. */
9371debfc3dSmrg
9381debfc3dSmrg static void
gen_expand(md_rtx_info * info)9391debfc3dSmrg gen_expand (md_rtx_info *info)
9401debfc3dSmrg {
9411debfc3dSmrg struct pattern_stats stats;
9421debfc3dSmrg rtx insn = info->def;
9431debfc3dSmrg data *d = new data;
9441debfc3dSmrg int i;
9451debfc3dSmrg
9461debfc3dSmrg d->code_number = info->index;
9471debfc3dSmrg d->loc = info->loc;
9481debfc3dSmrg if (XSTR (insn, 0)[0])
9491debfc3dSmrg d->name = XSTR (insn, 0);
9501debfc3dSmrg else
9511debfc3dSmrg d->name = 0;
9521debfc3dSmrg
9531debfc3dSmrg /* Build up the list in the same order as the insns are seen
9541debfc3dSmrg in the machine description. */
9551debfc3dSmrg d->next = 0;
9561debfc3dSmrg *idata_end = d;
9571debfc3dSmrg idata_end = &d->next;
9581debfc3dSmrg
9591debfc3dSmrg memset (d->operand, 0, sizeof (d->operand));
9601debfc3dSmrg
9611debfc3dSmrg /* Scan the operands to get the specified predicates and modes,
9621debfc3dSmrg since expand_binop needs to know them. */
9631debfc3dSmrg
9641debfc3dSmrg if (XVEC (insn, 1))
9651debfc3dSmrg for (i = 0; i < XVECLEN (insn, 1); i++)
9661debfc3dSmrg scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
9671debfc3dSmrg
9681debfc3dSmrg get_pattern_stats (&stats, XVEC (insn, 1));
9691debfc3dSmrg d->n_generator_args = stats.num_generator_args;
9701debfc3dSmrg d->n_operands = stats.num_insn_operands;
9711debfc3dSmrg d->n_dups = stats.num_dups;
9721debfc3dSmrg d->template_code = 0;
9731debfc3dSmrg d->output_format = INSN_OUTPUT_FORMAT_NONE;
9741debfc3dSmrg
9751debfc3dSmrg validate_insn_alternatives (d);
9761debfc3dSmrg validate_optab_operands (d);
9771debfc3dSmrg place_operands (d);
9781debfc3dSmrg }
9791debfc3dSmrg
9801debfc3dSmrg static void
init_insn_for_nothing(void)9811debfc3dSmrg init_insn_for_nothing (void)
9821debfc3dSmrg {
983*8feb0f0bSmrg idata = XCNEW (class data);
9841debfc3dSmrg new (idata) data ();
9851debfc3dSmrg idata->name = "*placeholder_for_nothing";
9861debfc3dSmrg idata->loc = file_location ("<internal>", 0, 0);
9871debfc3dSmrg idata_end = &idata->next;
9881debfc3dSmrg }
9891debfc3dSmrg
9901debfc3dSmrg extern int main (int, const char **);
9911debfc3dSmrg
9921debfc3dSmrg int
main(int argc,const char ** argv)9931debfc3dSmrg main (int argc, const char **argv)
9941debfc3dSmrg {
9951debfc3dSmrg progname = "genoutput";
9961debfc3dSmrg
9971debfc3dSmrg init_insn_for_nothing ();
9981debfc3dSmrg
9991debfc3dSmrg if (!init_rtx_reader_args (argc, argv))
10001debfc3dSmrg return (FATAL_EXIT_CODE);
10011debfc3dSmrg
10021debfc3dSmrg output_prologue ();
10031debfc3dSmrg
10041debfc3dSmrg /* Read the machine description. */
10051debfc3dSmrg
10061debfc3dSmrg md_rtx_info info;
10071debfc3dSmrg while (read_md_rtx (&info))
10081debfc3dSmrg switch (GET_CODE (info.def))
10091debfc3dSmrg {
10101debfc3dSmrg case DEFINE_INSN:
10111debfc3dSmrg gen_insn (&info);
10121debfc3dSmrg break;
10131debfc3dSmrg
10141debfc3dSmrg case DEFINE_PEEPHOLE:
10151debfc3dSmrg gen_peephole (&info);
10161debfc3dSmrg break;
10171debfc3dSmrg
10181debfc3dSmrg case DEFINE_EXPAND:
10191debfc3dSmrg gen_expand (&info);
10201debfc3dSmrg break;
10211debfc3dSmrg
10221debfc3dSmrg case DEFINE_CONSTRAINT:
10231debfc3dSmrg case DEFINE_REGISTER_CONSTRAINT:
10241debfc3dSmrg case DEFINE_ADDRESS_CONSTRAINT:
10251debfc3dSmrg case DEFINE_MEMORY_CONSTRAINT:
10261debfc3dSmrg case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
10271debfc3dSmrg note_constraint (&info);
10281debfc3dSmrg break;
10291debfc3dSmrg
10301debfc3dSmrg default:
10311debfc3dSmrg break;
10321debfc3dSmrg }
10331debfc3dSmrg
10341debfc3dSmrg printf ("\n\n");
10351debfc3dSmrg output_operand_data ();
10361debfc3dSmrg output_insn_data ();
10371debfc3dSmrg output_get_insn_name ();
10381debfc3dSmrg
10391debfc3dSmrg fflush (stdout);
10401debfc3dSmrg return (ferror (stdout) != 0 || have_error
10411debfc3dSmrg ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
10421debfc3dSmrg }
10431debfc3dSmrg
10441debfc3dSmrg /* Return the number of occurrences of character C in string S or
10451debfc3dSmrg -1 if S is the null string. */
10461debfc3dSmrg
10471debfc3dSmrg static int
n_occurrences(int c,const char * s)10481debfc3dSmrg n_occurrences (int c, const char *s)
10491debfc3dSmrg {
10501debfc3dSmrg int n = 0;
10511debfc3dSmrg
10521debfc3dSmrg if (s == 0 || *s == '\0')
10531debfc3dSmrg return -1;
10541debfc3dSmrg
10551debfc3dSmrg while (*s)
10561debfc3dSmrg n += (*s++ == c);
10571debfc3dSmrg
10581debfc3dSmrg return n;
10591debfc3dSmrg }
10601debfc3dSmrg
10611debfc3dSmrg /* Remove whitespace in `s' by moving up characters until the end.
10621debfc3dSmrg Return a new string. */
10631debfc3dSmrg
10641debfc3dSmrg static const char *
strip_whitespace(const char * s)10651debfc3dSmrg strip_whitespace (const char *s)
10661debfc3dSmrg {
10671debfc3dSmrg char *p, *q;
10681debfc3dSmrg char ch;
10691debfc3dSmrg
10701debfc3dSmrg if (s == 0)
10711debfc3dSmrg return 0;
10721debfc3dSmrg
10731debfc3dSmrg p = q = XNEWVEC (char, strlen (s) + 1);
10741debfc3dSmrg while ((ch = *s++) != '\0')
10751debfc3dSmrg if (! ISSPACE (ch))
10761debfc3dSmrg *p++ = ch;
10771debfc3dSmrg
10781debfc3dSmrg *p = '\0';
10791debfc3dSmrg return q;
10801debfc3dSmrg }
10811debfc3dSmrg
10821debfc3dSmrg /* Record just enough information about the constraint in *INFO to allow
10831debfc3dSmrg checking of operand constraint strings above, in validate_insn_alternatives.
10841debfc3dSmrg Does not validate most properties of the constraint itself; does enforce
10851debfc3dSmrg no duplicate names, no overlap with MI constraints, and no prefixes. */
10861debfc3dSmrg static void
note_constraint(md_rtx_info * info)10871debfc3dSmrg note_constraint (md_rtx_info *info)
10881debfc3dSmrg {
10891debfc3dSmrg rtx exp = info->def;
10901debfc3dSmrg const char *name = XSTR (exp, 0);
1091*8feb0f0bSmrg class constraint_data **iter, **slot, *new_cdata;
10921debfc3dSmrg
10931debfc3dSmrg if (strcmp (name, "TARGET_MEM_CONSTRAINT") == 0)
10941debfc3dSmrg name = general_mem;
10951debfc3dSmrg unsigned int namelen = strlen (name);
10961debfc3dSmrg
10971debfc3dSmrg if (strchr (indep_constraints, name[0]))
10981debfc3dSmrg {
10991debfc3dSmrg if (name[1] == '\0')
11001debfc3dSmrg error_at (info->loc, "constraint letter '%s' cannot be "
11011debfc3dSmrg "redefined by the machine description", name);
11021debfc3dSmrg else
11031debfc3dSmrg error_at (info->loc, "constraint name '%s' cannot be defined by "
11041debfc3dSmrg "the machine description, as it begins with '%c'",
11051debfc3dSmrg name, name[0]);
11061debfc3dSmrg return;
11071debfc3dSmrg }
11081debfc3dSmrg
11091debfc3dSmrg slot = &constraints_by_letter_table[(unsigned int)name[0]];
11101debfc3dSmrg for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
11111debfc3dSmrg {
11121debfc3dSmrg /* This causes slot to end up pointing to the
11131debfc3dSmrg next_this_letter field of the last constraint with a name
11141debfc3dSmrg of equal or greater length than the new constraint; hence
11151debfc3dSmrg the new constraint will be inserted after all previous
11161debfc3dSmrg constraints with names of the same length. */
11171debfc3dSmrg if ((*iter)->namelen >= namelen)
11181debfc3dSmrg slot = iter;
11191debfc3dSmrg
11201debfc3dSmrg if (!strcmp ((*iter)->name, name))
11211debfc3dSmrg {
11221debfc3dSmrg error_at (info->loc, "redefinition of constraint '%s'", name);
11231debfc3dSmrg message_at ((*iter)->loc, "previous definition is here");
11241debfc3dSmrg return;
11251debfc3dSmrg }
11261debfc3dSmrg else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
11271debfc3dSmrg {
11281debfc3dSmrg error_at (info->loc, "defining constraint '%s' here", name);
11291debfc3dSmrg message_at ((*iter)->loc, "renders constraint '%s' "
11301debfc3dSmrg "(defined here) a prefix", (*iter)->name);
11311debfc3dSmrg return;
11321debfc3dSmrg }
11331debfc3dSmrg else if (!strncmp ((*iter)->name, name, namelen))
11341debfc3dSmrg {
11351debfc3dSmrg error_at (info->loc, "constraint '%s' is a prefix", name);
11361debfc3dSmrg message_at ((*iter)->loc, "of constraint '%s' "
11371debfc3dSmrg "(defined here)", (*iter)->name);
11381debfc3dSmrg return;
11391debfc3dSmrg }
11401debfc3dSmrg }
1141*8feb0f0bSmrg new_cdata = XNEWVAR (class constraint_data,
1142*8feb0f0bSmrg sizeof (class constraint_data) + namelen);
11431debfc3dSmrg new (new_cdata) constraint_data ();
11441debfc3dSmrg strcpy (CONST_CAST (char *, new_cdata->name), name);
11451debfc3dSmrg new_cdata->namelen = namelen;
11461debfc3dSmrg new_cdata->loc = info->loc;
11471debfc3dSmrg new_cdata->next_this_letter = *slot;
11481debfc3dSmrg *slot = new_cdata;
11491debfc3dSmrg }
11501debfc3dSmrg
11511debfc3dSmrg /* Return the length of the constraint name beginning at position S
11521debfc3dSmrg of an operand constraint string, or issue an error message if there
11531debfc3dSmrg is no such constraint. Does not expect to be called for generic
11541debfc3dSmrg constraints. */
11551debfc3dSmrg static int
mdep_constraint_len(const char * s,file_location loc,int opno)11561debfc3dSmrg mdep_constraint_len (const char *s, file_location loc, int opno)
11571debfc3dSmrg {
1158*8feb0f0bSmrg class constraint_data *p;
11591debfc3dSmrg
11601debfc3dSmrg p = constraints_by_letter_table[(unsigned int)s[0]];
11611debfc3dSmrg
11621debfc3dSmrg if (p)
11631debfc3dSmrg for (; p; p = p->next_this_letter)
11641debfc3dSmrg if (!strncmp (s, p->name, p->namelen))
11651debfc3dSmrg return p->namelen;
11661debfc3dSmrg
11671debfc3dSmrg error_at (loc, "error: undefined machine-specific constraint "
11681debfc3dSmrg "at this point: \"%s\"", s);
11691debfc3dSmrg message_at (loc, "note: in operand %d", opno);
11701debfc3dSmrg return 1; /* safe */
11711debfc3dSmrg }
1172