]>
Commit | Line | Data |
---|---|---|
9db4e0ec | 1 | /* Generate code from to output assembler insns as recognized from rtl. |
58b23af8 | 2 | Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002, |
c59ffc41 | 3 | 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
9db4e0ec | 4 | |
1322177d | 5 | This file is part of GCC. |
9db4e0ec | 6 | |
1322177d LB |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 9 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 10 | version. |
9db4e0ec | 11 | |
1322177d LB |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
9db4e0ec RK |
16 | |
17 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
9db4e0ec RK |
20 | |
21 | ||
22 | /* This program reads the machine description for the compiler target machine | |
23 | and produces a file containing these things: | |
24 | ||
f12c802a | 25 | 1. An array of `struct insn_data_d', which is indexed by insn code number, |
a995e389 | 26 | which contains: |
9db4e0ec | 27 | |
a995e389 RH |
28 | a. `name' is the name for that pattern. Nameless patterns are |
29 | given a name. | |
30 | ||
4bbf910e RH |
31 | b. `output' hold either the output template, an array of output |
32 | templates, or an output function. | |
33 | ||
34 | c. `genfun' is the function to generate a body for that pattern, | |
a995e389 RH |
35 | given operands as arguments. |
36 | ||
4bbf910e | 37 | d. `n_operands' is the number of distinct operands in the pattern |
a995e389 | 38 | for that insn, |
9db4e0ec | 39 | |
4bbf910e | 40 | e. `n_dups' is the number of match_dup's that appear in the insn's |
a995e389 RH |
41 | pattern. This says how many elements of `recog_data.dup_loc' are |
42 | significant after an insn has been recognized. | |
9db4e0ec | 43 | |
4bbf910e | 44 | f. `n_alternatives' is the number of alternatives in the constraints |
a995e389 | 45 | of each pattern. |
9db4e0ec | 46 | |
4bbf910e RH |
47 | g. `output_format' tells what type of thing `output' is. |
48 | ||
a995e389 | 49 | h. `operand' is the base of an array of operand data for the insn. |
9db4e0ec | 50 | |
a995e389 | 51 | 2. An array of `struct insn_operand data', used by `operand' above. |
9db4e0ec | 52 | |
a995e389 RH |
53 | a. `predicate', an int-valued function, is the match_operand predicate |
54 | for this operand. | |
9db4e0ec | 55 | |
f38840db | 56 | b. `constraint' is the constraint for this operand. |
9db4e0ec | 57 | |
a995e389 | 58 | c. `address_p' indicates that the operand appears within ADDRESS |
f38840db | 59 | rtx's. |
9db4e0ec | 60 | |
a995e389 | 61 | d. `mode' is the machine mode that that operand is supposed to have. |
9db4e0ec | 62 | |
a995e389 | 63 | e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART. |
9db4e0ec | 64 | |
dfac187e BS |
65 | f. `eliminable', is nonzero for operands that are matched normally by |
66 | MATCH_OPERAND; it is zero for operands that should not be changed during | |
67 | register elimination such as MATCH_OPERATORs. | |
68 | ||
a995e389 RH |
69 | The code number of an insn is simply its position in the machine |
70 | description; code numbers are assigned sequentially to entries in | |
71 | the description, starting with code number 0. | |
9db4e0ec | 72 | |
a995e389 | 73 | Thus, the following entry in the machine description |
9db4e0ec RK |
74 | |
75 | (define_insn "clrdf" | |
76 | [(set (match_operand:DF 0 "general_operand" "") | |
77 | (const_int 0))] | |
78 | "" | |
79 | "clrd %0") | |
80 | ||
a995e389 RH |
81 | assuming it is the 25th entry present, would cause |
82 | insn_data[24].template to be "clrd %0", and | |
83 | insn_data[24].n_operands to be 1. */ | |
9db4e0ec | 84 | \f |
4977bab6 | 85 | #include "bconfig.h" |
0b93b64e | 86 | #include "system.h" |
4977bab6 ZW |
87 | #include "coretypes.h" |
88 | #include "tm.h" | |
9db4e0ec | 89 | #include "rtl.h" |
d80eb1e1 | 90 | #include "errors.h" |
10692477 | 91 | #include "read-md.h" |
c88c0d42 | 92 | #include "gensupport.h" |
9db4e0ec | 93 | |
a995e389 RH |
94 | /* No instruction can have more operands than this. Sorry for this |
95 | arbitrary limit, but what machine will have an instruction with | |
96 | this many operands? */ | |
9db4e0ec RK |
97 | |
98 | #define MAX_MAX_OPERANDS 40 | |
99 | ||
3d7aafde AJ |
100 | static int n_occurrences (int, const char *); |
101 | static const char *strip_whitespace (const char *); | |
9db4e0ec RK |
102 | |
103 | /* insns in the machine description are assigned sequential code numbers | |
104 | that are used by insn-recog.c (produced by genrecog) to communicate | |
105 | to insn-output.c (produced by this program). */ | |
106 | ||
107 | static int next_code_number; | |
108 | ||
109 | /* This counts all definitions in the md file, | |
110 | for the sake of error messages. */ | |
111 | ||
112 | static int next_index_number; | |
113 | ||
a995e389 RH |
114 | /* This counts all operands used in the md file. The first is null. */ |
115 | ||
116 | static int next_operand_number = 1; | |
117 | ||
118 | /* Record in this chain all information about the operands we will output. */ | |
119 | ||
120 | struct operand_data | |
121 | { | |
122 | struct operand_data *next; | |
123 | int index; | |
c1b59dce KG |
124 | const char *predicate; |
125 | const char *constraint; | |
a995e389 RH |
126 | enum machine_mode mode; |
127 | unsigned char n_alternatives; | |
128 | char address_p; | |
129 | char strict_low; | |
dfac187e | 130 | char eliminable; |
a995e389 RH |
131 | char seen; |
132 | }; | |
133 | ||
134 | /* Begin with a null operand at index 0. */ | |
135 | ||
136 | static struct operand_data null_operand = | |
137 | { | |
f4e2ed09 | 138 | 0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0 |
a995e389 RH |
139 | }; |
140 | ||
141 | static struct operand_data *odata = &null_operand; | |
142 | static struct operand_data **odata_end = &null_operand.next; | |
143 | ||
4bbf910e RH |
144 | /* Must match the constants in recog.h. */ |
145 | ||
146 | #define INSN_OUTPUT_FORMAT_NONE 0 /* abort */ | |
147 | #define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */ | |
148 | #define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */ | |
149 | #define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */ | |
150 | ||
9db4e0ec RK |
151 | /* Record in this chain all information that we will output, |
152 | associated with the code number of the insn. */ | |
153 | ||
154 | struct data | |
155 | { | |
a995e389 | 156 | struct data *next; |
c1b59dce | 157 | const char *name; |
8ad97cfc | 158 | const char *template_code; |
a995e389 RH |
159 | int code_number; |
160 | int index_number; | |
1e9c8405 | 161 | const char *filename; |
d96a2fcd | 162 | int lineno; |
9db4e0ec RK |
163 | int n_operands; /* Number of operands this insn recognizes */ |
164 | int n_dups; /* Number times match_dup appears in pattern */ | |
165 | int n_alternatives; /* Number of alternatives in each constraint */ | |
a995e389 | 166 | int operand_number; /* Operand index in the big array. */ |
4bbf910e | 167 | int output_format; /* INSN_OUTPUT_FORMAT_*. */ |
a995e389 | 168 | struct operand_data operand[MAX_MAX_OPERANDS]; |
9db4e0ec RK |
169 | }; |
170 | ||
a995e389 | 171 | /* This variable points to the first link in the insn chain. */ |
9db4e0ec | 172 | |
a995e389 | 173 | static struct data *idata, **idata_end = &idata; |
9db4e0ec | 174 | \f |
3d7aafde | 175 | static void output_prologue (void); |
3d7aafde AJ |
176 | static void output_operand_data (void); |
177 | static void output_insn_data (void); | |
178 | static void output_get_insn_name (void); | |
179 | static void scan_operands (struct data *, rtx, int, int); | |
180 | static int compare_operands (struct operand_data *, | |
181 | struct operand_data *); | |
182 | static void place_operands (struct data *); | |
183 | static void process_template (struct data *, const char *); | |
184 | static void validate_insn_alternatives (struct data *); | |
185 | static void validate_insn_operands (struct data *); | |
186 | static void gen_insn (rtx, int); | |
187 | static void gen_peephole (rtx, int); | |
188 | static void gen_expand (rtx, int); | |
189 | static void gen_split (rtx, int); | |
f38840db ZW |
190 | |
191 | #ifdef USE_MD_CONSTRAINTS | |
192 | ||
193 | struct constraint_data | |
194 | { | |
195 | struct constraint_data *next_this_letter; | |
196 | int lineno; | |
197 | unsigned int namelen; | |
198 | const char name[1]; | |
199 | }; | |
200 | ||
201 | /* This is a complete list (unlike the one in genpreds.c) of constraint | |
202 | letters and modifiers with machine-independent meaning. The only | |
203 | omission is digits, as these are handled specially. */ | |
204 | static const char indep_constraints[] = ",=+%*?!#&<>EFVXgimnoprs"; | |
205 | ||
206 | static struct constraint_data * | |
207 | constraints_by_letter_table[1 << CHAR_BIT]; | |
208 | ||
209 | static int mdep_constraint_len (const char *, int, int); | |
210 | static void note_constraint (rtx, int); | |
211 | ||
212 | #else /* !USE_MD_CONSTRAINTS */ | |
213 | ||
3d7aafde AJ |
214 | static void check_constraint_len (void); |
215 | static int constraint_len (const char *, int); | |
f38840db ZW |
216 | |
217 | #endif /* !USE_MD_CONSTRAINTS */ | |
218 | ||
56c0e996 | 219 | \f |
9db4e0ec | 220 | static void |
3d7aafde | 221 | output_prologue (void) |
9db4e0ec | 222 | { |
9db4e0ec | 223 | printf ("/* Generated automatically by the program `genoutput'\n\ |
d96a2fcd | 224 | from the machine description file `md'. */\n\n"); |
9db4e0ec RK |
225 | |
226 | printf ("#include \"config.h\"\n"); | |
729da3f5 | 227 | printf ("#include \"system.h\"\n"); |
4977bab6 ZW |
228 | printf ("#include \"coretypes.h\"\n"); |
229 | printf ("#include \"tm.h\"\n"); | |
ccd043a9 | 230 | printf ("#include \"flags.h\"\n"); |
3bc9f12b | 231 | printf ("#include \"ggc.h\"\n"); |
9db4e0ec | 232 | printf ("#include \"rtl.h\"\n"); |
f3a8030a | 233 | printf ("#include \"expr.h\"\n"); |
e78d8e51 | 234 | printf ("#include \"insn-codes.h\"\n"); |
6baf1cc8 | 235 | printf ("#include \"tm_p.h\"\n"); |
49ad7cfa | 236 | printf ("#include \"function.h\"\n"); |
9db4e0ec RK |
237 | printf ("#include \"regs.h\"\n"); |
238 | printf ("#include \"hard-reg-set.h\"\n"); | |
9db4e0ec RK |
239 | printf ("#include \"insn-config.h\"\n\n"); |
240 | printf ("#include \"conditions.h\"\n"); | |
9db4e0ec | 241 | printf ("#include \"insn-attr.h\"\n\n"); |
9db4e0ec | 242 | printf ("#include \"recog.h\"\n\n"); |
79a3f089 | 243 | printf ("#include \"diagnostic-core.h\"\n"); |
9db4e0ec | 244 | printf ("#include \"output.h\"\n"); |
4977bab6 | 245 | printf ("#include \"target.h\"\n"); |
279bb624 | 246 | printf ("#include \"tm-constrs.h\"\n"); |
9db4e0ec RK |
247 | } |
248 | ||
a995e389 | 249 | static void |
3d7aafde | 250 | output_operand_data (void) |
a995e389 | 251 | { |
b3694847 | 252 | struct operand_data *d; |
a995e389 RH |
253 | |
254 | printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n"); | |
255 | ||
256 | for (d = odata; d; d = d->next) | |
9db4e0ec | 257 | { |
a995e389 RH |
258 | printf (" {\n"); |
259 | ||
260 | printf (" %s,\n", | |
261 | d->predicate && d->predicate[0] ? d->predicate : "0"); | |
262 | ||
19af6455 | 263 | printf (" \"%s\",\n", d->constraint ? d->constraint : ""); |
9db4e0ec | 264 | |
a995e389 RH |
265 | printf (" %smode,\n", GET_MODE_NAME (d->mode)); |
266 | ||
dfac187e BS |
267 | printf (" %d,\n", d->strict_low); |
268 | ||
6ddfdb0f BS |
269 | printf (" %d,\n", d->constraint == NULL ? 1 : 0); |
270 | ||
dfac187e | 271 | printf (" %d\n", d->eliminable); |
a995e389 RH |
272 | |
273 | printf(" },\n"); | |
274 | } | |
275 | printf("};\n\n\n"); | |
276 | } | |
277 | ||
278 | static void | |
3d7aafde | 279 | output_insn_data (void) |
a995e389 | 280 | { |
b3694847 | 281 | struct data *d; |
a995e389 RH |
282 | int name_offset = 0; |
283 | int next_name_offset; | |
284 | const char * last_name = 0; | |
285 | const char * next_name = 0; | |
b3694847 | 286 | struct data *n; |
a995e389 RH |
287 | |
288 | for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++) | |
289 | if (n->name) | |
9db4e0ec | 290 | { |
a995e389 RH |
291 | next_name = n->name; |
292 | break; | |
9db4e0ec | 293 | } |
9db4e0ec | 294 | |
3897f229 | 295 | printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n"); |
f12c802a | 296 | printf ("\nconst struct insn_data_d insn_data[] = \n{\n"); |
9db4e0ec | 297 | |
a995e389 | 298 | for (d = idata; d; d = d->next) |
9db4e0ec | 299 | { |
1e9c8405 | 300 | printf (" /* %s:%d */\n", d->filename, d->lineno); |
a995e389 RH |
301 | printf (" {\n"); |
302 | ||
303 | if (d->name) | |
9db4e0ec | 304 | { |
a995e389 RH |
305 | printf (" \"%s\",\n", d->name); |
306 | name_offset = 0; | |
307 | last_name = d->name; | |
308 | next_name = 0; | |
309 | for (n = d->next, next_name_offset = 1; n; | |
310 | n = n->next, next_name_offset++) | |
9db4e0ec | 311 | { |
a995e389 RH |
312 | if (n->name) |
313 | { | |
314 | next_name = n->name; | |
315 | break; | |
316 | } | |
9db4e0ec | 317 | } |
9db4e0ec | 318 | } |
a995e389 | 319 | else |
9db4e0ec | 320 | { |
a995e389 RH |
321 | name_offset++; |
322 | if (next_name && (last_name == 0 | |
323 | || name_offset > next_name_offset / 2)) | |
324 | printf (" \"%s-%d\",\n", next_name, | |
325 | next_name_offset - name_offset); | |
326 | else | |
327 | printf (" \"%s+%d\",\n", last_name, name_offset); | |
9db4e0ec | 328 | } |
9db4e0ec | 329 | |
4bbf910e RH |
330 | switch (d->output_format) |
331 | { | |
332 | case INSN_OUTPUT_FORMAT_NONE: | |
3897f229 JM |
333 | printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); |
334 | printf (" { 0 },\n"); | |
335 | printf ("#else\n"); | |
336 | printf (" { 0, 0, 0 },\n"); | |
337 | printf ("#endif\n"); | |
4bbf910e RH |
338 | break; |
339 | case INSN_OUTPUT_FORMAT_SINGLE: | |
212d447c | 340 | { |
8ad97cfc | 341 | const char *p = d->template_code; |
212d447c | 342 | char prev = 0; |
3d7aafde | 343 | |
3897f229 JM |
344 | printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); |
345 | printf (" { .single =\n"); | |
346 | printf ("#else\n"); | |
347 | printf (" {\n"); | |
348 | printf ("#endif\n"); | |
212d447c DC |
349 | printf (" \""); |
350 | while (*p) | |
351 | { | |
6b8b9d7b CM |
352 | if (IS_VSPACE (*p) && prev != '\\') |
353 | { | |
354 | /* Preserve two consecutive \n's or \r's, but treat \r\n | |
355 | as a single newline. */ | |
356 | if (*p == '\n' && prev != '\r') | |
357 | printf ("\\n\\\n"); | |
358 | } | |
212d447c DC |
359 | else |
360 | putchar (*p); | |
361 | prev = *p; | |
362 | ++p; | |
363 | } | |
364 | printf ("\",\n"); | |
3897f229 JM |
365 | printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); |
366 | printf (" },\n"); | |
367 | printf ("#else\n"); | |
368 | printf (" 0, 0 },\n"); | |
369 | printf ("#endif\n"); | |
212d447c | 370 | } |
4bbf910e RH |
371 | break; |
372 | case INSN_OUTPUT_FORMAT_MULTI: | |
3897f229 JM |
373 | printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); |
374 | printf (" { .multi = output_%d },\n", d->code_number); | |
375 | printf ("#else\n"); | |
376 | printf (" { 0, output_%d, 0 },\n", d->code_number); | |
377 | printf ("#endif\n"); | |
378 | break; | |
4bbf910e | 379 | case INSN_OUTPUT_FORMAT_FUNCTION: |
3897f229 JM |
380 | printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); |
381 | printf (" { .function = output_%d },\n", d->code_number); | |
382 | printf ("#else\n"); | |
383 | printf (" { 0, 0, output_%d },\n", d->code_number); | |
384 | printf ("#endif\n"); | |
4bbf910e RH |
385 | break; |
386 | default: | |
b2d59f6f | 387 | gcc_unreachable (); |
4bbf910e | 388 | } |
a995e389 RH |
389 | |
390 | if (d->name && d->name[0] != '*') | |
706b0f60 | 391 | printf (" (insn_gen_fn) gen_%s,\n", d->name); |
a995e389 RH |
392 | else |
393 | printf (" 0,\n"); | |
394 | ||
395 | printf (" &operand_data[%d],\n", d->operand_number); | |
396 | printf (" %d,\n", d->n_operands); | |
397 | printf (" %d,\n", d->n_dups); | |
4bbf910e RH |
398 | printf (" %d,\n", d->n_alternatives); |
399 | printf (" %d\n", d->output_format); | |
a995e389 RH |
400 | |
401 | printf(" },\n"); | |
9db4e0ec | 402 | } |
a995e389 RH |
403 | printf ("};\n\n\n"); |
404 | } | |
9db4e0ec | 405 | |
a995e389 | 406 | static void |
3d7aafde | 407 | output_get_insn_name (void) |
a995e389 RH |
408 | { |
409 | printf ("const char *\n"); | |
6906ba40 | 410 | printf ("get_insn_name (int code)\n"); |
a995e389 | 411 | printf ("{\n"); |
a0f0e963 SB |
412 | printf (" if (code == NOOP_MOVE_INSN_CODE)\n"); |
413 | printf (" return \"NOOP_MOVE\";\n"); | |
414 | printf (" else\n"); | |
415 | printf (" return insn_data[code].name;\n"); | |
a995e389 | 416 | printf ("}\n"); |
9db4e0ec | 417 | } |
a995e389 | 418 | |
9db4e0ec | 419 | \f |
a995e389 RH |
420 | /* Stores in max_opno the largest operand number present in `part', if |
421 | that is larger than the previous value of max_opno, and the rest of | |
422 | the operand data into `d->operand[i]'. | |
9db4e0ec RK |
423 | |
424 | THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. | |
425 | THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ | |
426 | ||
427 | static int max_opno; | |
428 | static int num_dups; | |
9db4e0ec RK |
429 | |
430 | static void | |
3d7aafde AJ |
431 | scan_operands (struct data *d, rtx part, int this_address_p, |
432 | int this_strict_low) | |
9db4e0ec | 433 | { |
b3694847 SS |
434 | int i, j; |
435 | const char *format_ptr; | |
9db4e0ec RK |
436 | int opno; |
437 | ||
438 | if (part == 0) | |
439 | return; | |
440 | ||
441 | switch (GET_CODE (part)) | |
442 | { | |
443 | case MATCH_OPERAND: | |
444 | opno = XINT (part, 0); | |
445 | if (opno > max_opno) | |
446 | max_opno = opno; | |
447 | if (max_opno >= MAX_MAX_OPERANDS) | |
5a806d65 | 448 | { |
bb933490 | 449 | error_with_line (d->lineno, "maximum number of operands exceeded"); |
5a806d65 RK |
450 | return; |
451 | } | |
a995e389 | 452 | if (d->operand[opno].seen) |
bb933490 | 453 | error_with_line (d->lineno, "repeated operand number %d\n", opno); |
d96a2fcd | 454 | |
a995e389 RH |
455 | d->operand[opno].seen = 1; |
456 | d->operand[opno].mode = GET_MODE (part); | |
457 | d->operand[opno].strict_low = this_strict_low; | |
458 | d->operand[opno].predicate = XSTR (part, 1); | |
665f2503 RK |
459 | d->operand[opno].constraint = strip_whitespace (XSTR (part, 2)); |
460 | d->operand[opno].n_alternatives | |
461 | = n_occurrences (',', d->operand[opno].constraint) + 1; | |
a995e389 | 462 | d->operand[opno].address_p = this_address_p; |
dfac187e | 463 | d->operand[opno].eliminable = 1; |
9db4e0ec RK |
464 | return; |
465 | ||
466 | case MATCH_SCRATCH: | |
467 | opno = XINT (part, 0); | |
468 | if (opno > max_opno) | |
469 | max_opno = opno; | |
470 | if (max_opno >= MAX_MAX_OPERANDS) | |
5a806d65 | 471 | { |
bb933490 | 472 | error_with_line (d->lineno, "maximum number of operands exceeded"); |
5a806d65 RK |
473 | return; |
474 | } | |
a995e389 | 475 | if (d->operand[opno].seen) |
bb933490 | 476 | error_with_line (d->lineno, "repeated operand number %d\n", opno); |
d96a2fcd | 477 | |
a995e389 RH |
478 | d->operand[opno].seen = 1; |
479 | d->operand[opno].mode = GET_MODE (part); | |
480 | d->operand[opno].strict_low = 0; | |
481 | d->operand[opno].predicate = "scratch_operand"; | |
665f2503 RK |
482 | d->operand[opno].constraint = strip_whitespace (XSTR (part, 1)); |
483 | d->operand[opno].n_alternatives | |
484 | = n_occurrences (',', d->operand[opno].constraint) + 1; | |
a995e389 | 485 | d->operand[opno].address_p = 0; |
dfac187e | 486 | d->operand[opno].eliminable = 0; |
9db4e0ec RK |
487 | return; |
488 | ||
489 | case MATCH_OPERATOR: | |
490 | case MATCH_PARALLEL: | |
491 | opno = XINT (part, 0); | |
492 | if (opno > max_opno) | |
493 | max_opno = opno; | |
494 | if (max_opno >= MAX_MAX_OPERANDS) | |
5a806d65 | 495 | { |
bb933490 | 496 | error_with_line (d->lineno, "maximum number of operands exceeded"); |
5a806d65 RK |
497 | return; |
498 | } | |
a995e389 | 499 | if (d->operand[opno].seen) |
bb933490 | 500 | error_with_line (d->lineno, "repeated operand number %d\n", opno); |
d96a2fcd | 501 | |
a995e389 RH |
502 | d->operand[opno].seen = 1; |
503 | d->operand[opno].mode = GET_MODE (part); | |
504 | d->operand[opno].strict_low = 0; | |
505 | d->operand[opno].predicate = XSTR (part, 1); | |
506 | d->operand[opno].constraint = 0; | |
507 | d->operand[opno].address_p = 0; | |
dfac187e | 508 | d->operand[opno].eliminable = 0; |
9db4e0ec | 509 | for (i = 0; i < XVECLEN (part, 2); i++) |
a995e389 | 510 | scan_operands (d, XVECEXP (part, 2, i), 0, 0); |
9db4e0ec RK |
511 | return; |
512 | ||
513 | case MATCH_DUP: | |
514 | case MATCH_OP_DUP: | |
ed18f94d | 515 | case MATCH_PAR_DUP: |
9db4e0ec | 516 | ++num_dups; |
6d7a1c4c | 517 | break; |
9db4e0ec RK |
518 | |
519 | case ADDRESS: | |
a995e389 | 520 | scan_operands (d, XEXP (part, 0), 1, 0); |
9db4e0ec RK |
521 | return; |
522 | ||
523 | case STRICT_LOW_PART: | |
a995e389 | 524 | scan_operands (d, XEXP (part, 0), 0, 1); |
9db4e0ec | 525 | return; |
3d7aafde | 526 | |
ccd043a9 RL |
527 | default: |
528 | break; | |
9db4e0ec RK |
529 | } |
530 | ||
531 | format_ptr = GET_RTX_FORMAT (GET_CODE (part)); | |
532 | ||
533 | for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) | |
534 | switch (*format_ptr++) | |
535 | { | |
536 | case 'e': | |
ccd043a9 | 537 | case 'u': |
a995e389 | 538 | scan_operands (d, XEXP (part, i), 0, 0); |
9db4e0ec RK |
539 | break; |
540 | case 'E': | |
541 | if (XVEC (part, i) != NULL) | |
542 | for (j = 0; j < XVECLEN (part, i); j++) | |
a995e389 | 543 | scan_operands (d, XVECEXP (part, i, j), 0, 0); |
9db4e0ec RK |
544 | break; |
545 | } | |
546 | } | |
a995e389 RH |
547 | |
548 | /* Compare two operands for content equality. */ | |
549 | ||
550 | static int | |
3d7aafde | 551 | compare_operands (struct operand_data *d0, struct operand_data *d1) |
a995e389 | 552 | { |
c1b59dce | 553 | const char *p0, *p1; |
a995e389 RH |
554 | |
555 | p0 = d0->predicate; | |
556 | if (!p0) | |
557 | p0 = ""; | |
558 | p1 = d1->predicate; | |
559 | if (!p1) | |
560 | p1 = ""; | |
561 | if (strcmp (p0, p1) != 0) | |
562 | return 0; | |
563 | ||
19af6455 BS |
564 | p0 = d0->constraint; |
565 | if (!p0) | |
566 | p0 = ""; | |
567 | p1 = d1->constraint; | |
568 | if (!p1) | |
569 | p1 = ""; | |
570 | if (strcmp (p0, p1) != 0) | |
571 | return 0; | |
a995e389 RH |
572 | |
573 | if (d0->mode != d1->mode) | |
574 | return 0; | |
575 | ||
a995e389 RH |
576 | if (d0->strict_low != d1->strict_low) |
577 | return 0; | |
578 | ||
dfac187e BS |
579 | if (d0->eliminable != d1->eliminable) |
580 | return 0; | |
581 | ||
a995e389 RH |
582 | return 1; |
583 | } | |
584 | ||
585 | /* Scan the list of operands we've already committed to output and either | |
586 | find a subsequence that is the same, or allocate a new one at the end. */ | |
587 | ||
588 | static void | |
3d7aafde | 589 | place_operands (struct data *d) |
a995e389 RH |
590 | { |
591 | struct operand_data *od, *od2; | |
592 | int i; | |
593 | ||
594 | if (d->n_operands == 0) | |
595 | { | |
596 | d->operand_number = 0; | |
597 | return; | |
598 | } | |
599 | ||
600 | /* Brute force substring search. */ | |
601 | for (od = odata, i = 0; od; od = od->next, i = 0) | |
602 | if (compare_operands (od, &d->operand[0])) | |
603 | { | |
604 | od2 = od->next; | |
605 | i = 1; | |
606 | while (1) | |
607 | { | |
608 | if (i == d->n_operands) | |
609 | goto full_match; | |
610 | if (od2 == NULL) | |
611 | goto partial_match; | |
612 | if (! compare_operands (od2, &d->operand[i])) | |
613 | break; | |
614 | ++i, od2 = od2->next; | |
615 | } | |
616 | } | |
617 | ||
618 | /* Either partial match at the end of the list, or no match. In either | |
619 | case, we tack on what operands are remaining to the end of the list. */ | |
620 | partial_match: | |
621 | d->operand_number = next_operand_number - i; | |
622 | for (; i < d->n_operands; ++i) | |
623 | { | |
624 | od2 = &d->operand[i]; | |
625 | *odata_end = od2; | |
626 | odata_end = &od2->next; | |
627 | od2->index = next_operand_number++; | |
628 | } | |
629 | *odata_end = NULL; | |
630 | return; | |
631 | ||
632 | full_match: | |
633 | d->operand_number = od->index; | |
634 | return; | |
635 | } | |
636 | ||
9db4e0ec RK |
637 | \f |
638 | /* Process an assembler template from a define_insn or a define_peephole. | |
639 | It is either the assembler code template, a list of assembler code | |
640 | templates, or C code to generate the assembler code template. */ | |
641 | ||
642 | static void | |
8ad97cfc | 643 | process_template (struct data *d, const char *template_code) |
9db4e0ec | 644 | { |
b3694847 SS |
645 | const char *cp; |
646 | int i; | |
9db4e0ec | 647 | |
4bbf910e | 648 | /* Templates starting with * contain straight code to be run. */ |
8ad97cfc | 649 | if (template_code[0] == '*') |
9db4e0ec | 650 | { |
8ad97cfc | 651 | d->template_code = 0; |
4bbf910e | 652 | d->output_format = INSN_OUTPUT_FORMAT_FUNCTION; |
9db4e0ec | 653 | |
4bbf910e | 654 | puts ("\nstatic const char *"); |
6906ba40 KG |
655 | printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n", |
656 | d->code_number); | |
4bbf910e | 657 | puts ("{"); |
d2a3ce4e | 658 | print_md_ptr_loc (template_code); |
8ad97cfc | 659 | puts (template_code + 1); |
4bbf910e RH |
660 | puts ("}"); |
661 | } | |
9db4e0ec RK |
662 | |
663 | /* If the assembler code template starts with a @ it is a newline-separated | |
4bbf910e | 664 | list of assembler code templates, one for each alternative. */ |
8ad97cfc | 665 | else if (template_code[0] == '@') |
9db4e0ec | 666 | { |
8ad97cfc | 667 | d->template_code = 0; |
4bbf910e | 668 | d->output_format = INSN_OUTPUT_FORMAT_MULTI; |
9db4e0ec | 669 | |
4bbf910e | 670 | printf ("\nstatic const char * const output_%d[] = {\n", d->code_number); |
9db4e0ec | 671 | |
8ad97cfc | 672 | for (i = 0, cp = &template_code[1]; *cp; ) |
9db4e0ec | 673 | { |
4112be4a JJ |
674 | const char *ep, *sp; |
675 | ||
6b8b9d7b | 676 | while (ISSPACE (*cp)) |
9db4e0ec RK |
677 | cp++; |
678 | ||
4bbf910e | 679 | printf (" \""); |
4112be4a JJ |
680 | |
681 | for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep) | |
682 | if (!ISSPACE (*ep)) | |
683 | sp = ep + 1; | |
684 | ||
685 | if (sp != ep) | |
686 | message_with_line (d->lineno, | |
687 | "trailing whitespace in output template"); | |
688 | ||
689 | while (cp < sp) | |
2f013c71 RK |
690 | { |
691 | putchar (*cp); | |
692 | cp++; | |
693 | } | |
9db4e0ec RK |
694 | |
695 | printf ("\",\n"); | |
696 | i++; | |
697 | } | |
c6d79bee JH |
698 | if (i == 1) |
699 | message_with_line (d->lineno, | |
700 | "'@' is redundant for output template with single alternative"); | |
701 | if (i != d->n_alternatives) | |
bb933490 RS |
702 | error_with_line (d->lineno, |
703 | "wrong number of alternatives in the output template"); | |
9db4e0ec | 704 | |
4bbf910e | 705 | printf ("};\n"); |
9db4e0ec RK |
706 | } |
707 | else | |
708 | { | |
8ad97cfc | 709 | d->template_code = template_code; |
4bbf910e | 710 | d->output_format = INSN_OUTPUT_FORMAT_SINGLE; |
9db4e0ec | 711 | } |
9db4e0ec RK |
712 | } |
713 | \f | |
714 | /* Check insn D for consistency in number of constraint alternatives. */ | |
715 | ||
716 | static void | |
3d7aafde | 717 | validate_insn_alternatives (struct data *d) |
9db4e0ec | 718 | { |
b3694847 | 719 | int n = 0, start; |
a995e389 RH |
720 | |
721 | /* Make sure all the operands have the same number of alternatives | |
722 | in their constraints. Let N be that number. */ | |
9db4e0ec | 723 | for (start = 0; start < d->n_operands; start++) |
a995e389 | 724 | if (d->operand[start].n_alternatives > 0) |
9db4e0ec | 725 | { |
97488870 R |
726 | int len, i; |
727 | const char *p; | |
728 | char c; | |
729 | int which_alternative = 0; | |
730 | int alternative_count_unsure = 0; | |
731 | ||
732 | for (p = d->operand[start].constraint; (c = *p); p += len) | |
733 | { | |
f38840db ZW |
734 | #ifdef USE_MD_CONSTRAINTS |
735 | if (ISSPACE (c) || strchr (indep_constraints, c)) | |
736 | len = 1; | |
737 | else if (ISDIGIT (c)) | |
738 | { | |
739 | const char *q = p; | |
740 | do | |
741 | q++; | |
742 | while (ISDIGIT (*q)); | |
743 | len = q - p; | |
744 | } | |
745 | else | |
746 | len = mdep_constraint_len (p, d->lineno, start); | |
747 | #else | |
97488870 R |
748 | len = CONSTRAINT_LEN (c, p); |
749 | ||
750 | if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c))) | |
751 | { | |
bb933490 RS |
752 | error_with_line (d->lineno, |
753 | "invalid length %d for char '%c' in" | |
754 | " alternative %d of operand %d", | |
755 | len, c, which_alternative, start); | |
97488870 | 756 | len = 1; |
97488870 | 757 | } |
f38840db | 758 | #endif |
97488870 R |
759 | |
760 | if (c == ',') | |
761 | { | |
762 | which_alternative++; | |
763 | continue; | |
764 | } | |
765 | ||
766 | for (i = 1; i < len; i++) | |
767 | if (p[i] == '\0') | |
768 | { | |
bb933490 RS |
769 | error_with_line (d->lineno, |
770 | "NUL in alternative %d of operand %d", | |
771 | which_alternative, start); | |
97488870 R |
772 | alternative_count_unsure = 1; |
773 | break; | |
774 | } | |
775 | else if (strchr (",#*", p[i])) | |
776 | { | |
bb933490 RS |
777 | error_with_line (d->lineno, |
778 | "'%c' in alternative %d of operand %d", | |
779 | p[i], which_alternative, start); | |
97488870 R |
780 | alternative_count_unsure = 1; |
781 | } | |
782 | } | |
bb933490 | 783 | if (!alternative_count_unsure) |
d96a2fcd | 784 | { |
bb933490 RS |
785 | if (n == 0) |
786 | n = d->operand[start].n_alternatives; | |
787 | else if (n != d->operand[start].n_alternatives) | |
788 | error_with_line (d->lineno, | |
d96a2fcd RH |
789 | "wrong number of alternatives in operand %d", |
790 | start); | |
d96a2fcd | 791 | } |
9db4e0ec | 792 | } |
a995e389 | 793 | |
9db4e0ec RK |
794 | /* Record the insn's overall number of alternatives. */ |
795 | d->n_alternatives = n; | |
796 | } | |
c77e04ae RH |
797 | |
798 | /* Verify that there are no gaps in operand numbers for INSNs. */ | |
799 | ||
800 | static void | |
3d7aafde | 801 | validate_insn_operands (struct data *d) |
c77e04ae RH |
802 | { |
803 | int i; | |
804 | ||
805 | for (i = 0; i < d->n_operands; ++i) | |
806 | if (d->operand[i].seen == 0) | |
bb933490 | 807 | error_with_line (d->lineno, "missing operand %d", i); |
c77e04ae | 808 | } |
7ddf71e3 PB |
809 | |
810 | static void | |
811 | validate_optab_operands (struct data *d) | |
812 | { | |
813 | if (!d->name || d->name[0] == '\0' || d->name[0] == '*') | |
814 | return; | |
815 | ||
816 | /* Miscellaneous tests. */ | |
817 | if (strncmp (d->name, "cstore", 6) == 0 | |
818 | && d->name[strlen (d->name) - 1] == '4' | |
819 | && d->operand[0].mode == VOIDmode) | |
820 | { | |
821 | message_with_line (d->lineno, "missing mode for operand 0 of cstore"); | |
822 | have_error = 1; | |
823 | } | |
824 | } | |
9db4e0ec | 825 | \f |
a995e389 RH |
826 | /* Look at a define_insn just read. Assign its code number. Record |
827 | on idata the template and the number of arguments. If the insn has | |
828 | a hairy output action, output a function for now. */ | |
9db4e0ec RK |
829 | |
830 | static void | |
3d7aafde | 831 | gen_insn (rtx insn, int lineno) |
9db4e0ec | 832 | { |
5ed6ace5 | 833 | struct data *d = XNEW (struct data); |
b3694847 | 834 | int i; |
9db4e0ec | 835 | |
c88c0d42 | 836 | d->code_number = next_code_number; |
9db4e0ec | 837 | d->index_number = next_index_number; |
d2a3ce4e | 838 | d->filename = read_md_filename; |
d96a2fcd | 839 | d->lineno = lineno; |
9db4e0ec RK |
840 | if (XSTR (insn, 0)[0]) |
841 | d->name = XSTR (insn, 0); | |
842 | else | |
843 | d->name = 0; | |
844 | ||
845 | /* Build up the list in the same order as the insns are seen | |
846 | in the machine description. */ | |
847 | d->next = 0; | |
a995e389 RH |
848 | *idata_end = d; |
849 | idata_end = &d->next; | |
9db4e0ec RK |
850 | |
851 | max_opno = -1; | |
852 | num_dups = 0; | |
a995e389 | 853 | memset (d->operand, 0, sizeof (d->operand)); |
9db4e0ec RK |
854 | |
855 | for (i = 0; i < XVECLEN (insn, 1); i++) | |
a995e389 | 856 | scan_operands (d, XVECEXP (insn, 1, i), 0, 0); |
9db4e0ec RK |
857 | |
858 | d->n_operands = max_opno + 1; | |
859 | d->n_dups = num_dups; | |
860 | ||
f38840db | 861 | #ifndef USE_MD_CONSTRAINTS |
97488870 | 862 | check_constraint_len (); |
f38840db | 863 | #endif |
c77e04ae | 864 | validate_insn_operands (d); |
9db4e0ec | 865 | validate_insn_alternatives (d); |
7ddf71e3 | 866 | validate_optab_operands (d); |
a995e389 | 867 | place_operands (d); |
1f3b37a3 | 868 | process_template (d, XTMPL (insn, 3)); |
9db4e0ec RK |
869 | } |
870 | \f | |
871 | /* Look at a define_peephole just read. Assign its code number. | |
a995e389 | 872 | Record on idata the template and the number of arguments. |
9db4e0ec RK |
873 | If the insn has a hairy output action, output it now. */ |
874 | ||
875 | static void | |
3d7aafde | 876 | gen_peephole (rtx peep, int lineno) |
9db4e0ec | 877 | { |
5ed6ace5 | 878 | struct data *d = XNEW (struct data); |
b3694847 | 879 | int i; |
9db4e0ec | 880 | |
c88c0d42 | 881 | d->code_number = next_code_number; |
9db4e0ec | 882 | d->index_number = next_index_number; |
d2a3ce4e | 883 | d->filename = read_md_filename; |
d96a2fcd | 884 | d->lineno = lineno; |
9db4e0ec RK |
885 | d->name = 0; |
886 | ||
887 | /* Build up the list in the same order as the insns are seen | |
888 | in the machine description. */ | |
889 | d->next = 0; | |
a995e389 RH |
890 | *idata_end = d; |
891 | idata_end = &d->next; | |
9db4e0ec RK |
892 | |
893 | max_opno = -1; | |
a995e389 RH |
894 | num_dups = 0; |
895 | memset (d->operand, 0, sizeof (d->operand)); | |
896 | ||
897 | /* Get the number of operands by scanning all the patterns of the | |
898 | peephole optimizer. But ignore all the rest of the information | |
899 | thus obtained. */ | |
9db4e0ec | 900 | for (i = 0; i < XVECLEN (peep, 0); i++) |
a995e389 | 901 | scan_operands (d, XVECEXP (peep, 0, i), 0, 0); |
9db4e0ec RK |
902 | |
903 | d->n_operands = max_opno + 1; | |
904 | d->n_dups = 0; | |
905 | ||
9db4e0ec | 906 | validate_insn_alternatives (d); |
a995e389 | 907 | place_operands (d); |
1f3b37a3 | 908 | process_template (d, XTMPL (peep, 2)); |
9db4e0ec RK |
909 | } |
910 | \f | |
911 | /* Process a define_expand just read. Assign its code number, | |
912 | only for the purposes of `insn_gen_function'. */ | |
913 | ||
914 | static void | |
3d7aafde | 915 | gen_expand (rtx insn, int lineno) |
9db4e0ec | 916 | { |
5ed6ace5 | 917 | struct data *d = XNEW (struct data); |
b3694847 | 918 | int i; |
9db4e0ec | 919 | |
c88c0d42 | 920 | d->code_number = next_code_number; |
9db4e0ec | 921 | d->index_number = next_index_number; |
d2a3ce4e | 922 | d->filename = read_md_filename; |
d96a2fcd | 923 | d->lineno = lineno; |
9db4e0ec RK |
924 | if (XSTR (insn, 0)[0]) |
925 | d->name = XSTR (insn, 0); | |
926 | else | |
927 | d->name = 0; | |
928 | ||
929 | /* Build up the list in the same order as the insns are seen | |
930 | in the machine description. */ | |
931 | d->next = 0; | |
a995e389 RH |
932 | *idata_end = d; |
933 | idata_end = &d->next; | |
9db4e0ec RK |
934 | |
935 | max_opno = -1; | |
936 | num_dups = 0; | |
a995e389 | 937 | memset (d->operand, 0, sizeof (d->operand)); |
9db4e0ec RK |
938 | |
939 | /* Scan the operands to get the specified predicates and modes, | |
940 | since expand_binop needs to know them. */ | |
941 | ||
9db4e0ec RK |
942 | if (XVEC (insn, 1)) |
943 | for (i = 0; i < XVECLEN (insn, 1); i++) | |
a995e389 | 944 | scan_operands (d, XVECEXP (insn, 1, i), 0, 0); |
9db4e0ec RK |
945 | |
946 | d->n_operands = max_opno + 1; | |
947 | d->n_dups = num_dups; | |
8ad97cfc | 948 | d->template_code = 0; |
4bbf910e | 949 | d->output_format = INSN_OUTPUT_FORMAT_NONE; |
a995e389 | 950 | |
9db4e0ec | 951 | validate_insn_alternatives (d); |
7ddf71e3 | 952 | validate_optab_operands (d); |
a995e389 | 953 | place_operands (d); |
9db4e0ec RK |
954 | } |
955 | \f | |
956 | /* Process a define_split just read. Assign its code number, | |
957 | only for reasons of consistency and to simplify genrecog. */ | |
958 | ||
9db4e0ec | 959 | static void |
3d7aafde | 960 | gen_split (rtx split, int lineno) |
9db4e0ec | 961 | { |
5ed6ace5 | 962 | struct data *d = XNEW (struct data); |
b3694847 | 963 | int i; |
9db4e0ec | 964 | |
c88c0d42 | 965 | d->code_number = next_code_number; |
9db4e0ec | 966 | d->index_number = next_index_number; |
d2a3ce4e | 967 | d->filename = read_md_filename; |
d96a2fcd | 968 | d->lineno = lineno; |
9db4e0ec RK |
969 | d->name = 0; |
970 | ||
971 | /* Build up the list in the same order as the insns are seen | |
972 | in the machine description. */ | |
973 | d->next = 0; | |
a995e389 RH |
974 | *idata_end = d; |
975 | idata_end = &d->next; | |
9db4e0ec RK |
976 | |
977 | max_opno = -1; | |
978 | num_dups = 0; | |
a995e389 | 979 | memset (d->operand, 0, sizeof (d->operand)); |
9db4e0ec | 980 | |
a995e389 RH |
981 | /* Get the number of operands by scanning all the patterns of the |
982 | split patterns. But ignore all the rest of the information thus | |
983 | obtained. */ | |
9db4e0ec | 984 | for (i = 0; i < XVECLEN (split, 0); i++) |
a995e389 | 985 | scan_operands (d, XVECEXP (split, 0, i), 0, 0); |
9db4e0ec RK |
986 | |
987 | d->n_operands = max_opno + 1; | |
9db4e0ec | 988 | d->n_dups = 0; |
42495ca0 | 989 | d->n_alternatives = 0; |
8ad97cfc | 990 | d->template_code = 0; |
4bbf910e | 991 | d->output_format = INSN_OUTPUT_FORMAT_NONE; |
a995e389 RH |
992 | |
993 | place_operands (d); | |
9db4e0ec | 994 | } |
9db4e0ec | 995 | |
3d7aafde | 996 | extern int main (int, char **); |
c1b59dce | 997 | |
9db4e0ec | 998 | int |
3d7aafde | 999 | main (int argc, char **argv) |
9db4e0ec RK |
1000 | { |
1001 | rtx desc; | |
9db4e0ec | 1002 | |
d80eb1e1 RH |
1003 | progname = "genoutput"; |
1004 | ||
600ab3fc | 1005 | if (!init_rtx_reader_args (argc, argv)) |
c88c0d42 | 1006 | return (FATAL_EXIT_CODE); |
9db4e0ec | 1007 | |
9db4e0ec RK |
1008 | output_prologue (); |
1009 | next_code_number = 0; | |
1010 | next_index_number = 0; | |
9db4e0ec RK |
1011 | |
1012 | /* Read the machine description. */ | |
1013 | ||
1014 | while (1) | |
1015 | { | |
c88c0d42 CP |
1016 | int line_no; |
1017 | ||
1018 | desc = read_md_rtx (&line_no, &next_code_number); | |
1019 | if (desc == NULL) | |
9db4e0ec | 1020 | break; |
9db4e0ec | 1021 | |
f38840db ZW |
1022 | switch (GET_CODE (desc)) |
1023 | { | |
1024 | case DEFINE_INSN: | |
1025 | gen_insn (desc, line_no); | |
1026 | break; | |
1027 | ||
1028 | case DEFINE_PEEPHOLE: | |
1029 | gen_peephole (desc, line_no); | |
1030 | break; | |
1031 | ||
1032 | case DEFINE_EXPAND: | |
1033 | gen_expand (desc, line_no); | |
1034 | break; | |
1035 | ||
1036 | case DEFINE_SPLIT: | |
1037 | case DEFINE_PEEPHOLE2: | |
1038 | gen_split (desc, line_no); | |
1039 | break; | |
1040 | ||
1041 | #ifdef USE_MD_CONSTRAINTS | |
1042 | case DEFINE_CONSTRAINT: | |
1043 | case DEFINE_REGISTER_CONSTRAINT: | |
1044 | case DEFINE_ADDRESS_CONSTRAINT: | |
1045 | case DEFINE_MEMORY_CONSTRAINT: | |
1046 | note_constraint (desc, line_no); | |
1047 | break; | |
1048 | #endif | |
1049 | ||
1050 | default: | |
1051 | break; | |
1052 | } | |
9db4e0ec RK |
1053 | next_index_number++; |
1054 | } | |
1055 | ||
a995e389 | 1056 | printf("\n\n"); |
a995e389 RH |
1057 | output_operand_data (); |
1058 | output_insn_data (); | |
1059 | output_get_insn_name (); | |
9db4e0ec RK |
1060 | |
1061 | fflush (stdout); | |
c1b59dce | 1062 | return (ferror (stdout) != 0 || have_error |
6a270722 | 1063 | ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); |
9db4e0ec RK |
1064 | } |
1065 | ||
665f2503 RK |
1066 | /* Return the number of occurrences of character C in string S or |
1067 | -1 if S is the null string. */ | |
1068 | ||
9db4e0ec | 1069 | static int |
3d7aafde | 1070 | n_occurrences (int c, const char *s) |
9db4e0ec RK |
1071 | { |
1072 | int n = 0; | |
665f2503 RK |
1073 | |
1074 | if (s == 0 || *s == '\0') | |
1075 | return -1; | |
1076 | ||
9db4e0ec RK |
1077 | while (*s) |
1078 | n += (*s++ == c); | |
665f2503 | 1079 | |
9db4e0ec RK |
1080 | return n; |
1081 | } | |
88a56c2e | 1082 | |
665f2503 RK |
1083 | /* Remove whitespace in `s' by moving up characters until the end. |
1084 | Return a new string. */ | |
1085 | ||
1086 | static const char * | |
3d7aafde | 1087 | strip_whitespace (const char *s) |
88a56c2e | 1088 | { |
665f2503 RK |
1089 | char *p, *q; |
1090 | char ch; | |
1091 | ||
1092 | if (s == 0) | |
1093 | return 0; | |
88a56c2e | 1094 | |
5ed6ace5 | 1095 | p = q = XNEWVEC (char, strlen (s) + 1); |
88a56c2e HPN |
1096 | while ((ch = *s++) != '\0') |
1097 | if (! ISSPACE (ch)) | |
1098 | *p++ = ch; | |
1099 | ||
1100 | *p = '\0'; | |
665f2503 | 1101 | return q; |
88a56c2e | 1102 | } |
97488870 | 1103 | |
f38840db ZW |
1104 | #ifdef USE_MD_CONSTRAINTS |
1105 | ||
1106 | /* Record just enough information about a constraint to allow checking | |
1107 | of operand constraint strings above, in validate_insn_alternatives. | |
1108 | Does not validate most properties of the constraint itself; does | |
1109 | enforce no duplicate names, no overlap with MI constraints, and no | |
1110 | prefixes. EXP is the define_*constraint form, LINENO the line number | |
1111 | reported by the reader. */ | |
1112 | static void | |
1113 | note_constraint (rtx exp, int lineno) | |
1114 | { | |
1115 | const char *name = XSTR (exp, 0); | |
1116 | unsigned int namelen = strlen (name); | |
8ad97cfc | 1117 | struct constraint_data **iter, **slot, *new_cdata; |
f38840db | 1118 | |
a4edaf83 AK |
1119 | /* The 'm' constraint is special here since that constraint letter |
1120 | can be overridden by the back end by defining the | |
1121 | TARGET_MEM_CONSTRAINT macro. */ | |
1122 | if (strchr (indep_constraints, name[0]) && name[0] != 'm') | |
f38840db ZW |
1123 | { |
1124 | if (name[1] == '\0') | |
bb933490 RS |
1125 | error_with_line (lineno, "constraint letter '%s' cannot be " |
1126 | "redefined by the machine description", name); | |
f38840db | 1127 | else |
bb933490 RS |
1128 | error_with_line (lineno, "constraint name '%s' cannot be defined by " |
1129 | "the machine description, as it begins with '%c'", | |
1130 | name, name[0]); | |
f38840db ZW |
1131 | return; |
1132 | } | |
1133 | ||
1134 | slot = &constraints_by_letter_table[(unsigned int)name[0]]; | |
1135 | for (iter = slot; *iter; iter = &(*iter)->next_this_letter) | |
1136 | { | |
1137 | /* This causes slot to end up pointing to the | |
1138 | next_this_letter field of the last constraint with a name | |
1139 | of equal or greater length than the new constraint; hence | |
1140 | the new constraint will be inserted after all previous | |
1141 | constraints with names of the same length. */ | |
1142 | if ((*iter)->namelen >= namelen) | |
1143 | slot = iter; | |
1144 | ||
1145 | if (!strcmp ((*iter)->name, name)) | |
1146 | { | |
bb933490 | 1147 | error_with_line (lineno, "redefinition of constraint '%s'", name); |
f38840db | 1148 | message_with_line ((*iter)->lineno, "previous definition is here"); |
f38840db ZW |
1149 | return; |
1150 | } | |
1151 | else if (!strncmp ((*iter)->name, name, (*iter)->namelen)) | |
1152 | { | |
bb933490 | 1153 | error_with_line (lineno, "defining constraint '%s' here", name); |
f38840db ZW |
1154 | message_with_line ((*iter)->lineno, "renders constraint '%s' " |
1155 | "(defined here) a prefix", (*iter)->name); | |
f38840db ZW |
1156 | return; |
1157 | } | |
1158 | else if (!strncmp ((*iter)->name, name, namelen)) | |
1159 | { | |
bb933490 | 1160 | error_with_line (lineno, "constraint '%s' is a prefix", name); |
f38840db ZW |
1161 | message_with_line ((*iter)->lineno, "of constraint '%s' " |
1162 | "(defined here)", (*iter)->name); | |
f38840db ZW |
1163 | return; |
1164 | } | |
1165 | } | |
8ad97cfc KG |
1166 | new_cdata = XNEWVAR (struct constraint_data, sizeof (struct constraint_data) + namelen); |
1167 | strcpy ((char *)new_cdata + offsetof(struct constraint_data, name), name); | |
1168 | new_cdata->namelen = namelen; | |
1169 | new_cdata->lineno = lineno; | |
1170 | new_cdata->next_this_letter = *slot; | |
1171 | *slot = new_cdata; | |
f38840db ZW |
1172 | } |
1173 | ||
1174 | /* Return the length of the constraint name beginning at position S | |
1175 | of an operand constraint string, or issue an error message if there | |
1176 | is no such constraint. Does not expect to be called for generic | |
1177 | constraints. */ | |
1178 | static int | |
1179 | mdep_constraint_len (const char *s, int lineno, int opno) | |
1180 | { | |
1181 | struct constraint_data *p; | |
1182 | ||
1183 | p = constraints_by_letter_table[(unsigned int)s[0]]; | |
1184 | ||
1185 | if (p) | |
1186 | for (; p; p = p->next_this_letter) | |
1187 | if (!strncmp (s, p->name, p->namelen)) | |
1188 | return p->namelen; | |
1189 | ||
bb933490 RS |
1190 | error_with_line (lineno, |
1191 | "error: undefined machine-specific constraint " | |
1192 | "at this point: \"%s\"", s); | |
f38840db | 1193 | message_with_line (lineno, "note: in operand %d", opno); |
f38840db ZW |
1194 | return 1; /* safe */ |
1195 | } | |
1196 | ||
1197 | #else | |
97488870 R |
1198 | /* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not |
1199 | tampered with. This isn't bullet-proof, but it should catch | |
1200 | most genuine mistakes. */ | |
1201 | static void | |
3d7aafde | 1202 | check_constraint_len (void) |
97488870 R |
1203 | { |
1204 | const char *p; | |
1205 | int d; | |
1206 | ||
1207 | for (p = ",#*+=&%!1234567890"; *p; p++) | |
1208 | for (d = -9; d < 9; d++) | |
b2d59f6f | 1209 | gcc_assert (constraint_len (p, d) == d); |
97488870 R |
1210 | } |
1211 | ||
1212 | static int | |
3d7aafde | 1213 | constraint_len (const char *p, int genoutput_default_constraint_len) |
97488870 R |
1214 | { |
1215 | /* Check that we still match defaults.h . First we do a generation-time | |
1216 | check that fails if the value is not the expected one... */ | |
b2d59f6f | 1217 | gcc_assert (DEFAULT_CONSTRAINT_LEN (*p, p) == 1); |
2067c116 | 1218 | /* And now a compile-time check that should give a diagnostic if the |
97488870 R |
1219 | definition doesn't exactly match. */ |
1220 | #define DEFAULT_CONSTRAINT_LEN(C,STR) 1 | |
1221 | /* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is | |
1222 | being used. */ | |
1223 | #undef DEFAULT_CONSTRAINT_LEN | |
1224 | #define DEFAULT_CONSTRAINT_LEN(C,STR) \ | |
1225 | ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len) | |
1226 | return CONSTRAINT_LEN (*p, p); | |
1227 | /* And set it back. */ | |
1228 | #undef DEFAULT_CONSTRAINT_LEN | |
1229 | #define DEFAULT_CONSTRAINT_LEN(C,STR) 1 | |
1230 | } | |
f38840db | 1231 | #endif |