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