Mercurial > hg > CbC > CbC_gcc
comparison gcc/gensupport.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
24 #include "tm.h" | 24 #include "tm.h" |
25 #include "rtl.h" | 25 #include "rtl.h" |
26 #include "obstack.h" | 26 #include "obstack.h" |
27 #include "errors.h" | 27 #include "errors.h" |
28 #include "hashtab.h" | 28 #include "hashtab.h" |
29 #include "read-md.h" | |
29 #include "gensupport.h" | 30 #include "gensupport.h" |
30 | 31 |
31 | 32 |
32 /* In case some macros used by files we include need it, define this here. */ | 33 /* In case some macros used by files we include need it, define this here. */ |
33 int target_flags; | 34 int target_flags; |
34 | 35 |
35 int insn_elision = 1; | 36 int insn_elision = 1; |
36 | 37 |
37 const char *in_fname; | |
38 | |
39 /* This callback will be invoked whenever an rtl include directive is | |
40 processed. To be used for creation of the dependency file. */ | |
41 void (*include_callback) (const char *); | |
42 | |
43 static struct obstack obstack; | 38 static struct obstack obstack; |
44 struct obstack *rtl_obstack = &obstack; | 39 struct obstack *rtl_obstack = &obstack; |
45 | 40 |
46 static int sequence_num; | 41 static int sequence_num; |
47 static int errors; | |
48 | 42 |
49 static int predicable_default; | 43 static int predicable_default; |
50 static const char *predicable_true; | 44 static const char *predicable_true; |
51 static const char *predicable_false; | 45 static const char *predicable_false; |
52 | 46 |
53 static htab_t condition_table; | 47 static htab_t condition_table; |
54 | |
55 static char *base_dir = NULL; | |
56 | 48 |
57 /* We initially queue all patterns, process the define_insn and | 49 /* We initially queue all patterns, process the define_insn and |
58 define_cond_exec patterns, then return them one at a time. */ | 50 define_cond_exec patterns, then return them one at a time. */ |
59 | 51 |
60 struct queue_elem | 52 struct queue_elem |
65 struct queue_elem *next; | 57 struct queue_elem *next; |
66 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT | 58 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT |
67 points to the generated DEFINE_SPLIT. */ | 59 points to the generated DEFINE_SPLIT. */ |
68 struct queue_elem *split; | 60 struct queue_elem *split; |
69 }; | 61 }; |
62 | |
63 #define MNEMONIC_ATTR_NAME "mnemonic" | |
64 #define MNEMONIC_HTAB_SIZE 1024 | |
70 | 65 |
71 static struct queue_elem *define_attr_queue; | 66 static struct queue_elem *define_attr_queue; |
72 static struct queue_elem **define_attr_tail = &define_attr_queue; | 67 static struct queue_elem **define_attr_tail = &define_attr_queue; |
73 static struct queue_elem *define_pred_queue; | 68 static struct queue_elem *define_pred_queue; |
74 static struct queue_elem **define_pred_tail = &define_pred_queue; | 69 static struct queue_elem **define_pred_tail = &define_pred_queue; |
79 static struct queue_elem *other_queue; | 74 static struct queue_elem *other_queue; |
80 static struct queue_elem **other_tail = &other_queue; | 75 static struct queue_elem **other_tail = &other_queue; |
81 | 76 |
82 static struct queue_elem *queue_pattern (rtx, struct queue_elem ***, | 77 static struct queue_elem *queue_pattern (rtx, struct queue_elem ***, |
83 const char *, int); | 78 const char *, int); |
84 | |
85 /* Current maximum length of directory names in the search path | |
86 for include files. (Altered as we get more of them.) */ | |
87 | |
88 size_t max_include_len; | |
89 | |
90 struct file_name_list | |
91 { | |
92 struct file_name_list *next; | |
93 const char *fname; | |
94 }; | |
95 | |
96 struct file_name_list *first_dir_md_include = 0; /* First dir to search */ | |
97 /* First dir to search for <file> */ | |
98 struct file_name_list *first_bracket_include = 0; | |
99 struct file_name_list *last_dir_md_include = 0; /* Last in chain */ | |
100 | 79 |
101 static void remove_constraints (rtx); | 80 static void remove_constraints (rtx); |
102 static void process_rtx (rtx, int); | 81 static void process_rtx (rtx, int); |
103 | 82 |
104 static int is_predicable (struct queue_elem *); | 83 static int is_predicable (struct queue_elem *); |
112 static const char *alter_output_for_insn (struct queue_elem *, | 91 static const char *alter_output_for_insn (struct queue_elem *, |
113 struct queue_elem *, | 92 struct queue_elem *, |
114 int, int); | 93 int, int); |
115 static void process_one_cond_exec (struct queue_elem *); | 94 static void process_one_cond_exec (struct queue_elem *); |
116 static void process_define_cond_exec (void); | 95 static void process_define_cond_exec (void); |
117 static void process_include (rtx, int); | |
118 static char *save_string (const char *, int); | |
119 static void init_predicate_table (void); | 96 static void init_predicate_table (void); |
120 static void record_insn_name (int, const char *); | 97 static void record_insn_name (int, const char *); |
121 | 98 |
122 void | |
123 message_with_line (int lineno, const char *msg, ...) | |
124 { | |
125 va_list ap; | |
126 | |
127 va_start (ap, msg); | |
128 | |
129 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno); | |
130 vfprintf (stderr, msg, ap); | |
131 fputc ('\n', stderr); | |
132 | |
133 va_end (ap); | |
134 } | |
135 | |
136 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in | 99 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in |
137 the gensupport programs. */ | 100 the gensupport programs. */ |
138 | 101 |
139 rtx | 102 rtx |
140 gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode), | 103 gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode), |
195 remove_constraints (XVECEXP (part, i, j)); | 158 remove_constraints (XVECEXP (part, i, j)); |
196 break; | 159 break; |
197 } | 160 } |
198 } | 161 } |
199 | 162 |
200 /* Process an include file assuming that it lives in gcc/config/{target}/ | |
201 if the include looks like (include "file"). */ | |
202 | |
203 static void | |
204 process_include (rtx desc, int lineno) | |
205 { | |
206 const char *filename = XSTR (desc, 0); | |
207 const char *old_filename; | |
208 int old_lineno; | |
209 char *pathname; | |
210 FILE *input_file; | |
211 | |
212 /* If specified file name is absolute, skip the include stack. */ | |
213 if (! IS_ABSOLUTE_PATH (filename)) | |
214 { | |
215 struct file_name_list *stackp; | |
216 | |
217 /* Search directory path, trying to open the file. */ | |
218 for (stackp = first_dir_md_include; stackp; stackp = stackp->next) | |
219 { | |
220 static const char sep[2] = { DIR_SEPARATOR, '\0' }; | |
221 | |
222 pathname = concat (stackp->fname, sep, filename, NULL); | |
223 input_file = fopen (pathname, "r"); | |
224 if (input_file != NULL) | |
225 goto success; | |
226 free (pathname); | |
227 } | |
228 } | |
229 | |
230 if (base_dir) | |
231 pathname = concat (base_dir, filename, NULL); | |
232 else | |
233 pathname = xstrdup (filename); | |
234 input_file = fopen (pathname, "r"); | |
235 if (input_file == NULL) | |
236 { | |
237 free (pathname); | |
238 message_with_line (lineno, "include file `%s' not found", filename); | |
239 errors = 1; | |
240 return; | |
241 } | |
242 success: | |
243 | |
244 /* Save old cursor; setup new for the new file. Note that "lineno" the | |
245 argument to this function is the beginning of the include statement, | |
246 while read_rtx_lineno has already been advanced. */ | |
247 old_filename = read_rtx_filename; | |
248 old_lineno = read_rtx_lineno; | |
249 read_rtx_filename = pathname; | |
250 read_rtx_lineno = 1; | |
251 | |
252 if (include_callback) | |
253 include_callback (pathname); | |
254 | |
255 /* Read the entire file. */ | |
256 while (read_rtx (input_file, &desc, &lineno)) | |
257 process_rtx (desc, lineno); | |
258 | |
259 /* Do not free pathname. It is attached to the various rtx queue | |
260 elements. */ | |
261 | |
262 read_rtx_filename = old_filename; | |
263 read_rtx_lineno = old_lineno; | |
264 | |
265 fclose (input_file); | |
266 } | |
267 | |
268 /* Process a top level rtx in some way, queuing as appropriate. */ | 163 /* Process a top level rtx in some way, queuing as appropriate. */ |
269 | 164 |
270 static void | 165 static void |
271 process_rtx (rtx desc, int lineno) | 166 process_rtx (rtx desc, int lineno) |
272 { | 167 { |
273 switch (GET_CODE (desc)) | 168 switch (GET_CODE (desc)) |
274 { | 169 { |
275 case DEFINE_INSN: | 170 case DEFINE_INSN: |
276 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno); | 171 queue_pattern (desc, &define_insn_tail, read_md_filename, lineno); |
277 break; | 172 break; |
278 | 173 |
279 case DEFINE_COND_EXEC: | 174 case DEFINE_COND_EXEC: |
280 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno); | 175 queue_pattern (desc, &define_cond_exec_tail, read_md_filename, lineno); |
281 break; | 176 break; |
282 | 177 |
283 case DEFINE_ATTR: | 178 case DEFINE_ATTR: |
284 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno); | 179 case DEFINE_ENUM_ATTR: |
180 queue_pattern (desc, &define_attr_tail, read_md_filename, lineno); | |
285 break; | 181 break; |
286 | 182 |
287 case DEFINE_PREDICATE: | 183 case DEFINE_PREDICATE: |
288 case DEFINE_SPECIAL_PREDICATE: | 184 case DEFINE_SPECIAL_PREDICATE: |
289 case DEFINE_CONSTRAINT: | 185 case DEFINE_CONSTRAINT: |
290 case DEFINE_REGISTER_CONSTRAINT: | 186 case DEFINE_REGISTER_CONSTRAINT: |
291 case DEFINE_MEMORY_CONSTRAINT: | 187 case DEFINE_MEMORY_CONSTRAINT: |
292 case DEFINE_ADDRESS_CONSTRAINT: | 188 case DEFINE_ADDRESS_CONSTRAINT: |
293 queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno); | 189 queue_pattern (desc, &define_pred_tail, read_md_filename, lineno); |
294 break; | |
295 | |
296 case INCLUDE: | |
297 process_include (desc, lineno); | |
298 break; | 190 break; |
299 | 191 |
300 case DEFINE_INSN_AND_SPLIT: | 192 case DEFINE_INSN_AND_SPLIT: |
301 { | 193 { |
302 const char *split_cond; | 194 const char *split_cond; |
320 /* If the split condition starts with "&&", append it to the | 212 /* If the split condition starts with "&&", append it to the |
321 insn condition to create the new split condition. */ | 213 insn condition to create the new split condition. */ |
322 split_cond = XSTR (desc, 4); | 214 split_cond = XSTR (desc, 4); |
323 if (split_cond[0] == '&' && split_cond[1] == '&') | 215 if (split_cond[0] == '&' && split_cond[1] == '&') |
324 { | 216 { |
325 copy_rtx_ptr_loc (split_cond + 2, split_cond); | 217 copy_md_ptr_loc (split_cond + 2, split_cond); |
326 split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2); | 218 split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2); |
327 } | 219 } |
328 XSTR (split, 1) = split_cond; | 220 XSTR (split, 1) = split_cond; |
329 XVEC (split, 2) = XVEC (desc, 5); | 221 XVEC (split, 2) = XVEC (desc, 5); |
330 XSTR (split, 3) = XSTR (desc, 6); | 222 XSTR (split, 3) = XSTR (desc, 6); |
334 PUT_CODE (desc, DEFINE_INSN); | 226 PUT_CODE (desc, DEFINE_INSN); |
335 XVEC (desc, 4) = attr; | 227 XVEC (desc, 4) = attr; |
336 | 228 |
337 /* Queue them. */ | 229 /* Queue them. */ |
338 insn_elem | 230 insn_elem |
339 = queue_pattern (desc, &define_insn_tail, read_rtx_filename, | 231 = queue_pattern (desc, &define_insn_tail, read_md_filename, |
340 lineno); | 232 lineno); |
341 split_elem | 233 split_elem |
342 = queue_pattern (split, &other_tail, read_rtx_filename, lineno); | 234 = queue_pattern (split, &other_tail, read_md_filename, lineno); |
343 insn_elem->split = split_elem; | 235 insn_elem->split = split_elem; |
344 break; | 236 break; |
345 } | 237 } |
346 | 238 |
347 default: | 239 default: |
348 queue_pattern (desc, &other_tail, read_rtx_filename, lineno); | 240 queue_pattern (desc, &other_tail, read_md_filename, lineno); |
349 break; | 241 break; |
350 } | 242 } |
351 } | 243 } |
352 | 244 |
353 /* Return true if attribute PREDICABLE is true for ELEM, which holds | 245 /* Return true if attribute PREDICABLE is true for ELEM, which holds |
377 break; | 269 break; |
378 | 270 |
379 case SET_ATTR_ALTERNATIVE: | 271 case SET_ATTR_ALTERNATIVE: |
380 if (strcmp (XSTR (sub, 0), "predicable") == 0) | 272 if (strcmp (XSTR (sub, 0), "predicable") == 0) |
381 { | 273 { |
382 message_with_line (elem->lineno, | 274 error_with_line (elem->lineno, |
383 "multiple alternatives for `predicable'"); | 275 "multiple alternatives for `predicable'"); |
384 errors = 1; | |
385 return 0; | 276 return 0; |
386 } | 277 } |
387 break; | 278 break; |
388 | 279 |
389 case SET: | 280 case SET: |
398 } | 289 } |
399 | 290 |
400 /* ??? It would be possible to handle this if we really tried. | 291 /* ??? It would be possible to handle this if we really tried. |
401 It's not easy though, and I'm not going to bother until it | 292 It's not easy though, and I'm not going to bother until it |
402 really proves necessary. */ | 293 really proves necessary. */ |
403 message_with_line (elem->lineno, | 294 error_with_line (elem->lineno, |
404 "non-constant value for `predicable'"); | 295 "non-constant value for `predicable'"); |
405 errors = 1; | |
406 return 0; | 296 return 0; |
407 | 297 |
408 default: | 298 default: |
409 gcc_unreachable (); | 299 gcc_unreachable (); |
410 } | 300 } |
417 /* ??? It should be possible to handle this by simply eliminating | 307 /* ??? It should be possible to handle this by simply eliminating |
418 the non-predicable alternatives from the insn. FRV would like | 308 the non-predicable alternatives from the insn. FRV would like |
419 to do this. Delay this until we've got the basics solid. */ | 309 to do this. Delay this until we've got the basics solid. */ |
420 if (strchr (value, ',') != NULL) | 310 if (strchr (value, ',') != NULL) |
421 { | 311 { |
422 message_with_line (elem->lineno, | 312 error_with_line (elem->lineno, "multiple alternatives for `predicable'"); |
423 "multiple alternatives for `predicable'"); | |
424 errors = 1; | |
425 return 0; | 313 return 0; |
426 } | 314 } |
427 | 315 |
428 /* Find out which value we're looking at. */ | 316 /* Find out which value we're looking at. */ |
429 if (strcmp (value, predicable_true) == 0) | 317 if (strcmp (value, predicable_true) == 0) |
430 return 1; | 318 return 1; |
431 if (strcmp (value, predicable_false) == 0) | 319 if (strcmp (value, predicable_false) == 0) |
432 return 0; | 320 return 0; |
433 | 321 |
434 message_with_line (elem->lineno, | 322 error_with_line (elem->lineno, |
435 "unknown value `%s' for `predicable' attribute", | 323 "unknown value `%s' for `predicable' attribute", value); |
436 value); | |
437 errors = 1; | |
438 return 0; | 324 return 0; |
439 } | 325 } |
440 | 326 |
441 /* Examine the attribute "predicable"; discover its boolean values | 327 /* Examine the attribute "predicable"; discover its boolean values |
442 and its default. */ | 328 and its default. */ |
451 /* Look for the DEFINE_ATTR for `predicable', which must exist. */ | 337 /* Look for the DEFINE_ATTR for `predicable', which must exist. */ |
452 for (elem = define_attr_queue; elem ; elem = elem->next) | 338 for (elem = define_attr_queue; elem ; elem = elem->next) |
453 if (strcmp (XSTR (elem->data, 0), "predicable") == 0) | 339 if (strcmp (XSTR (elem->data, 0), "predicable") == 0) |
454 goto found; | 340 goto found; |
455 | 341 |
456 message_with_line (define_cond_exec_queue->lineno, | 342 error_with_line (define_cond_exec_queue->lineno, |
457 "attribute `predicable' not defined"); | 343 "attribute `predicable' not defined"); |
458 errors = 1; | |
459 return; | 344 return; |
460 | 345 |
461 found: | 346 found: |
462 value = XSTR (elem->data, 1); | 347 value = XSTR (elem->data, 1); |
463 p_false = xstrdup (value); | 348 p_false = xstrdup (value); |
464 p_true = strchr (p_false, ','); | 349 p_true = strchr (p_false, ','); |
465 if (p_true == NULL || strchr (++p_true, ',') != NULL) | 350 if (p_true == NULL || strchr (++p_true, ',') != NULL) |
466 { | 351 { |
467 message_with_line (elem->lineno, | 352 error_with_line (elem->lineno, "attribute `predicable' is not a boolean"); |
468 "attribute `predicable' is not a boolean"); | |
469 errors = 1; | |
470 if (p_false) | 353 if (p_false) |
471 free (p_false); | 354 free (p_false); |
472 return; | 355 return; |
473 } | 356 } |
474 p_true[-1] = '\0'; | 357 p_true[-1] = '\0'; |
481 case CONST_STRING: | 364 case CONST_STRING: |
482 value = XSTR (XEXP (elem->data, 2), 0); | 365 value = XSTR (XEXP (elem->data, 2), 0); |
483 break; | 366 break; |
484 | 367 |
485 case CONST: | 368 case CONST: |
486 message_with_line (elem->lineno, | 369 error_with_line (elem->lineno, "attribute `predicable' cannot be const"); |
487 "attribute `predicable' cannot be const"); | |
488 errors = 1; | |
489 if (p_false) | 370 if (p_false) |
490 free (p_false); | 371 free (p_false); |
491 return; | 372 return; |
492 | 373 |
493 default: | 374 default: |
494 message_with_line (elem->lineno, | 375 error_with_line (elem->lineno, |
495 "attribute `predicable' must have a constant default"); | 376 "attribute `predicable' must have a constant default"); |
496 errors = 1; | |
497 if (p_false) | 377 if (p_false) |
498 free (p_false); | 378 free (p_false); |
499 return; | 379 return; |
500 } | 380 } |
501 | 381 |
503 predicable_default = 1; | 383 predicable_default = 1; |
504 else if (strcmp (value, p_false) == 0) | 384 else if (strcmp (value, p_false) == 0) |
505 predicable_default = 0; | 385 predicable_default = 0; |
506 else | 386 else |
507 { | 387 { |
508 message_with_line (elem->lineno, | 388 error_with_line (elem->lineno, |
509 "unknown value `%s' for `predicable' attribute", | 389 "unknown value `%s' for `predicable' attribute", value); |
510 value); | |
511 errors = 1; | |
512 if (p_false) | 390 if (p_false) |
513 free (p_false); | 391 free (p_false); |
514 } | 392 } |
515 } | 393 } |
516 | 394 |
600 { | 478 { |
601 const char *c = XSTR (pattern, 2); | 479 const char *c = XSTR (pattern, 2); |
602 | 480 |
603 if (n_alternatives (c) != 1) | 481 if (n_alternatives (c) != 1) |
604 { | 482 { |
605 message_with_line (lineno, | 483 error_with_line (lineno, "too many alternatives for operand %d", |
606 "too many alternatives for operand %d", | 484 XINT (pattern, 0)); |
607 XINT (pattern, 0)); | |
608 errors = 1; | |
609 return NULL; | 485 return NULL; |
610 } | 486 } |
611 | 487 |
612 /* Replicate C as needed to fill out ALT alternatives. */ | 488 /* Replicate C as needed to fill out ALT alternatives. */ |
613 if (c && *c && alt > 1) | 489 if (c && *c && alt > 1) |
791 collect_insn_data (insn_elem->data, &alternatives, &max_operand); | 667 collect_insn_data (insn_elem->data, &alternatives, &max_operand); |
792 max_operand += 1; | 668 max_operand += 1; |
793 | 669 |
794 if (XVECLEN (ce_elem->data, 0) != 1) | 670 if (XVECLEN (ce_elem->data, 0) != 1) |
795 { | 671 { |
796 message_with_line (ce_elem->lineno, | 672 error_with_line (ce_elem->lineno, "too many patterns in predicate"); |
797 "too many patterns in predicate"); | |
798 errors = 1; | |
799 return; | 673 return; |
800 } | 674 } |
801 | 675 |
802 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0)); | 676 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0)); |
803 pred = alter_predicate_for_insn (pred, alternatives, max_operand, | 677 pred = alter_predicate_for_insn (pred, alternatives, max_operand, |
876 XEXP (pattern, 0) = pred; | 750 XEXP (pattern, 0) = pred; |
877 XEXP (pattern, 1) = XVECEXP (split, 2, i); | 751 XEXP (pattern, 1) = XVECEXP (split, 2, i); |
878 XVECEXP (split, 2, i) = pattern; | 752 XVECEXP (split, 2, i) = pattern; |
879 } | 753 } |
880 /* Add the new split to the queue. */ | 754 /* Add the new split to the queue. */ |
881 queue_pattern (split, &other_tail, read_rtx_filename, | 755 queue_pattern (split, &other_tail, read_md_filename, |
882 insn_elem->split->lineno); | 756 insn_elem->split->lineno); |
883 } | 757 } |
884 } | 758 } |
885 | 759 |
886 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN | 760 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN |
890 process_define_cond_exec (void) | 764 process_define_cond_exec (void) |
891 { | 765 { |
892 struct queue_elem *elem; | 766 struct queue_elem *elem; |
893 | 767 |
894 identify_predicable_attribute (); | 768 identify_predicable_attribute (); |
895 if (errors) | 769 if (have_error) |
896 return; | 770 return; |
897 | 771 |
898 for (elem = define_cond_exec_queue; elem ; elem = elem->next) | 772 for (elem = define_cond_exec_queue; elem ; elem = elem->next) |
899 process_one_cond_exec (elem); | 773 process_one_cond_exec (elem); |
900 } | 774 } |
901 | |
902 static char * | |
903 save_string (const char *s, int len) | |
904 { | |
905 char *result = XNEWVEC (char, len + 1); | |
906 | |
907 memcpy (result, s, len); | |
908 result[len] = 0; | |
909 return result; | |
910 } | |
911 | |
912 | 775 |
776 /* A read_md_files callback for reading an rtx. */ | |
777 | |
778 static void | |
779 rtx_handle_directive (int lineno, const char *rtx_name) | |
780 { | |
781 rtx queue, x; | |
782 | |
783 if (read_rtx (rtx_name, &queue)) | |
784 for (x = queue; x; x = XEXP (x, 1)) | |
785 process_rtx (XEXP (x, 0), lineno); | |
786 } | |
787 | |
788 /* Comparison function for the mnemonic hash table. */ | |
789 | |
790 static int | |
791 htab_eq_string (const void *s1, const void *s2) | |
792 { | |
793 return strcmp ((const char*)s1, (const char*)s2) == 0; | |
794 } | |
795 | |
796 /* Add mnemonic STR with length LEN to the mnemonic hash table | |
797 MNEMONIC_HTAB. A trailing zero end character is appendend to STR | |
798 and a permanent heap copy of STR is created. */ | |
799 | |
800 static void | |
801 add_mnemonic_string (htab_t mnemonic_htab, const char *str, int len) | |
802 { | |
803 char *new_str; | |
804 void **slot; | |
805 char *str_zero = (char*)alloca (len + 1); | |
806 | |
807 memcpy (str_zero, str, len); | |
808 str_zero[len] = '\0'; | |
809 | |
810 slot = htab_find_slot (mnemonic_htab, str_zero, INSERT); | |
811 | |
812 if (*slot) | |
813 return; | |
814 | |
815 /* Not found; create a permanent copy and add it to the hash table. */ | |
816 new_str = XNEWVAR (char, len + 1); | |
817 memcpy (new_str, str_zero, len + 1); | |
818 *slot = new_str; | |
819 } | |
820 | |
821 /* Scan INSN for mnemonic strings and add them to the mnemonic hash | |
822 table in MNEMONIC_HTAB. | |
823 | |
824 The mnemonics cannot be found if they are emitted using C code. | |
825 | |
826 If a mnemonic string contains ';' or a newline the string assumed | |
827 to consist of more than a single instruction. The attribute value | |
828 will then be set to the user defined default value. */ | |
829 | |
830 static void | |
831 gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn) | |
832 { | |
833 const char *template_code, *cp; | |
834 int i; | |
835 int vec_len; | |
836 rtx set_attr; | |
837 char *attr_name; | |
838 rtvec new_vec; | |
839 | |
840 template_code = XTMPL (insn, 3); | |
841 | |
842 /* Skip patterns which use C code to emit the template. */ | |
843 if (template_code[0] == '*') | |
844 return; | |
845 | |
846 if (template_code[0] == '@') | |
847 cp = &template_code[1]; | |
848 else | |
849 cp = &template_code[0]; | |
850 | |
851 for (i = 0; *cp; ) | |
852 { | |
853 const char *ep, *sp; | |
854 int size = 0; | |
855 | |
856 while (ISSPACE (*cp)) | |
857 cp++; | |
858 | |
859 for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep) | |
860 if (!ISSPACE (*ep)) | |
861 sp = ep + 1; | |
862 | |
863 if (i > 0) | |
864 obstack_1grow (&string_obstack, ','); | |
865 | |
866 while (cp < sp && ((*cp >= '0' && *cp <= '9') | |
867 || (*cp >= 'a' && *cp <= 'z'))) | |
868 | |
869 { | |
870 obstack_1grow (&string_obstack, *cp); | |
871 cp++; | |
872 size++; | |
873 } | |
874 | |
875 while (cp < sp) | |
876 { | |
877 if (*cp == ';' || (*cp == '\\' && cp[1] == 'n')) | |
878 { | |
879 /* Don't set a value if there are more than one | |
880 instruction in the string. */ | |
881 obstack_next_free (&string_obstack) = | |
882 obstack_next_free (&string_obstack) - size; | |
883 size = 0; | |
884 | |
885 cp = sp; | |
886 break; | |
887 } | |
888 cp++; | |
889 } | |
890 if (size == 0) | |
891 obstack_1grow (&string_obstack, '*'); | |
892 else | |
893 add_mnemonic_string (mnemonic_htab, | |
894 obstack_next_free (&string_obstack) - size, | |
895 size); | |
896 i++; | |
897 } | |
898 | |
899 /* An insn definition might emit an empty string. */ | |
900 if (obstack_object_size (&string_obstack) == 0) | |
901 return; | |
902 | |
903 obstack_1grow (&string_obstack, '\0'); | |
904 | |
905 set_attr = rtx_alloc (SET_ATTR); | |
906 XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *); | |
907 attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1); | |
908 strcpy (attr_name, MNEMONIC_ATTR_NAME); | |
909 XSTR (set_attr, 0) = attr_name; | |
910 | |
911 if (!XVEC (insn, 4)) | |
912 vec_len = 0; | |
913 else | |
914 vec_len = XVECLEN (insn, 4); | |
915 | |
916 new_vec = rtvec_alloc (vec_len + 1); | |
917 for (i = 0; i < vec_len; i++) | |
918 RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i); | |
919 RTVEC_ELT (new_vec, vec_len) = set_attr; | |
920 XVEC (insn, 4) = new_vec; | |
921 } | |
922 | |
923 /* This function is called for the elements in the mnemonic hashtable | |
924 and generates a comma separated list of the mnemonics. */ | |
925 | |
926 static int | |
927 mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED) | |
928 { | |
929 obstack_grow (&string_obstack, (char*)*slot, strlen ((char*)*slot)); | |
930 obstack_1grow (&string_obstack, ','); | |
931 return 1; | |
932 } | |
933 | |
934 /* Generate (set_attr "mnemonic" "..") RTXs and append them to every | |
935 insn definition in case the back end requests it by defining the | |
936 mnemonic attribute. The values for the attribute will be extracted | |
937 from the output patterns of the insn definitions as far as | |
938 possible. */ | |
939 | |
940 static void | |
941 gen_mnemonic_attr (void) | |
942 { | |
943 struct queue_elem *elem; | |
944 rtx mnemonic_attr = NULL; | |
945 htab_t mnemonic_htab; | |
946 const char *str, *p; | |
947 int i; | |
948 | |
949 if (have_error) | |
950 return; | |
951 | |
952 /* Look for the DEFINE_ATTR for `mnemonic'. */ | |
953 for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next) | |
954 if (GET_CODE (elem->data) == DEFINE_ATTR | |
955 && strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0) | |
956 { | |
957 mnemonic_attr = elem->data; | |
958 break; | |
959 } | |
960 | |
961 /* A (define_attr "mnemonic" "...") indicates that the back-end | |
962 wants a mnemonic attribute to be generated. */ | |
963 if (!mnemonic_attr) | |
964 return; | |
965 | |
966 mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string, | |
967 htab_eq_string, 0, xcalloc, free); | |
968 | |
969 for (elem = define_insn_queue; elem; elem = elem->next) | |
970 { | |
971 rtx insn = elem->data; | |
972 bool found = false; | |
973 | |
974 /* Check if the insn definition already has | |
975 (set_attr "mnemonic" ...). */ | |
976 if (XVEC (insn, 4)) | |
977 for (i = 0; i < XVECLEN (insn, 4); i++) | |
978 if (strcmp (XSTR (XVECEXP (insn, 4, i), 0), MNEMONIC_ATTR_NAME) == 0) | |
979 { | |
980 found = true; | |
981 break; | |
982 } | |
983 | |
984 if (!found) | |
985 gen_mnemonic_setattr (mnemonic_htab, insn); | |
986 } | |
987 | |
988 /* Add the user defined values to the hash table. */ | |
989 str = XSTR (mnemonic_attr, 1); | |
990 while ((p = scan_comma_elt (&str)) != NULL) | |
991 add_mnemonic_string (mnemonic_htab, p, str - p); | |
992 | |
993 htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL); | |
994 | |
995 /* Replace the last ',' with the zero end character. */ | |
996 *((char *)obstack_next_free (&string_obstack) - 1) = '\0'; | |
997 XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char *); | |
998 } | |
999 | |
913 /* The entry point for initializing the reader. */ | 1000 /* The entry point for initializing the reader. */ |
914 | 1001 |
915 int | 1002 bool |
916 init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *)) | 1003 init_rtx_reader_args_cb (int argc, char **argv, |
917 { | 1004 bool (*parse_opt) (const char *)) |
918 FILE *input_file; | 1005 { |
919 int c, i, lineno; | |
920 char *lastsl; | |
921 rtx desc; | |
922 bool no_more_options; | |
923 bool already_read_stdin; | |
924 | |
925 /* Unlock the stdio streams. */ | |
926 unlock_std_streams (); | |
927 | |
928 /* First we loop over all the options. */ | |
929 for (i = 1; i < argc; i++) | |
930 { | |
931 if (argv[i][0] != '-') | |
932 continue; | |
933 | |
934 c = argv[i][1]; | |
935 switch (c) | |
936 { | |
937 case 'I': /* Add directory to path for includes. */ | |
938 { | |
939 struct file_name_list *dirtmp; | |
940 | |
941 dirtmp = XNEW (struct file_name_list); | |
942 dirtmp->next = 0; /* New one goes on the end */ | |
943 if (first_dir_md_include == 0) | |
944 first_dir_md_include = dirtmp; | |
945 else | |
946 last_dir_md_include->next = dirtmp; | |
947 last_dir_md_include = dirtmp; /* Tail follows the last one */ | |
948 if (argv[i][1] == 'I' && argv[i][2] != 0) | |
949 dirtmp->fname = argv[i] + 2; | |
950 else if (i + 1 == argc) | |
951 fatal ("directory name missing after -I option"); | |
952 else | |
953 dirtmp->fname = argv[++i]; | |
954 if (strlen (dirtmp->fname) > max_include_len) | |
955 max_include_len = strlen (dirtmp->fname); | |
956 } | |
957 break; | |
958 | |
959 case '\0': | |
960 /* An argument consisting of exactly one dash is a request to | |
961 read stdin. This will be handled in the second loop. */ | |
962 continue; | |
963 | |
964 case '-': | |
965 /* An argument consisting of just two dashes causes option | |
966 parsing to cease. */ | |
967 if (argv[i][2] == '\0') | |
968 goto stop_parsing_options; | |
969 | |
970 default: | |
971 /* The program may have provided a callback so it can | |
972 accept its own options. */ | |
973 if (parse_opt && parse_opt (argv[i])) | |
974 break; | |
975 | |
976 fatal ("invalid option `%s'", argv[i]); | |
977 } | |
978 } | |
979 | |
980 stop_parsing_options: | |
981 | |
982 /* Prepare to read input. */ | 1006 /* Prepare to read input. */ |
983 condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL); | 1007 condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL); |
984 init_predicate_table (); | 1008 init_predicate_table (); |
985 obstack_init (rtl_obstack); | 1009 obstack_init (rtl_obstack); |
986 errors = 0; | |
987 sequence_num = 0; | 1010 sequence_num = 0; |
988 no_more_options = false; | 1011 |
989 already_read_stdin = false; | 1012 read_md_files (argc, argv, parse_opt, rtx_handle_directive); |
990 | |
991 | |
992 /* Now loop over all input files. */ | |
993 for (i = 1; i < argc; i++) | |
994 { | |
995 if (argv[i][0] == '-') | |
996 { | |
997 if (argv[i][1] == '\0') | |
998 { | |
999 /* Read stdin. */ | |
1000 if (already_read_stdin) | |
1001 fatal ("cannot read standard input twice"); | |
1002 | |
1003 base_dir = NULL; | |
1004 read_rtx_filename = in_fname = "<stdin>"; | |
1005 read_rtx_lineno = 1; | |
1006 input_file = stdin; | |
1007 already_read_stdin = true; | |
1008 | |
1009 while (read_rtx (input_file, &desc, &lineno)) | |
1010 process_rtx (desc, lineno); | |
1011 fclose (input_file); | |
1012 continue; | |
1013 } | |
1014 else if (argv[i][1] == '-' && argv[i][2] == '\0') | |
1015 { | |
1016 /* No further arguments are to be treated as options. */ | |
1017 no_more_options = true; | |
1018 continue; | |
1019 } | |
1020 else if (!no_more_options) | |
1021 continue; | |
1022 } | |
1023 | |
1024 /* If we get here we are looking at a non-option argument, i.e. | |
1025 a file to be processed. */ | |
1026 | |
1027 in_fname = argv[i]; | |
1028 lastsl = strrchr (in_fname, '/'); | |
1029 if (lastsl != NULL) | |
1030 base_dir = save_string (in_fname, lastsl - in_fname + 1 ); | |
1031 else | |
1032 base_dir = NULL; | |
1033 | |
1034 read_rtx_filename = in_fname; | |
1035 read_rtx_lineno = 1; | |
1036 input_file = fopen (in_fname, "r"); | |
1037 if (input_file == 0) | |
1038 { | |
1039 perror (in_fname); | |
1040 return FATAL_EXIT_CODE; | |
1041 } | |
1042 | |
1043 while (read_rtx (input_file, &desc, &lineno)) | |
1044 process_rtx (desc, lineno); | |
1045 fclose (input_file); | |
1046 } | |
1047 | |
1048 /* If we get to this point without having seen any files to process, | |
1049 read standard input now. */ | |
1050 if (!in_fname) | |
1051 { | |
1052 base_dir = NULL; | |
1053 read_rtx_filename = in_fname = "<stdin>"; | |
1054 read_rtx_lineno = 1; | |
1055 input_file = stdin; | |
1056 | |
1057 while (read_rtx (input_file, &desc, &lineno)) | |
1058 process_rtx (desc, lineno); | |
1059 fclose (input_file); | |
1060 } | |
1061 | 1013 |
1062 /* Process define_cond_exec patterns. */ | 1014 /* Process define_cond_exec patterns. */ |
1063 if (define_cond_exec_queue != NULL) | 1015 if (define_cond_exec_queue != NULL) |
1064 process_define_cond_exec (); | 1016 process_define_cond_exec (); |
1065 | 1017 |
1066 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE; | 1018 if (define_attr_queue != NULL) |
1019 gen_mnemonic_attr (); | |
1020 | |
1021 return !have_error; | |
1067 } | 1022 } |
1068 | 1023 |
1069 /* Programs that don't have their own options can use this entry point | 1024 /* Programs that don't have their own options can use this entry point |
1070 instead. */ | 1025 instead. */ |
1071 int | 1026 bool |
1072 init_md_reader_args (int argc, char **argv) | 1027 init_rtx_reader_args (int argc, char **argv) |
1073 { | 1028 { |
1074 return init_md_reader_args_cb (argc, argv, 0); | 1029 return init_rtx_reader_args_cb (argc, argv, 0); |
1075 } | 1030 } |
1076 | 1031 |
1077 /* The entry point for reading a single rtx from an md file. */ | 1032 /* The entry point for reading a single rtx from an md file. */ |
1078 | 1033 |
1079 rtx | 1034 rtx |
1097 return NULL_RTX; | 1052 return NULL_RTX; |
1098 | 1053 |
1099 elem = *queue; | 1054 elem = *queue; |
1100 *queue = elem->next; | 1055 *queue = elem->next; |
1101 desc = elem->data; | 1056 desc = elem->data; |
1102 read_rtx_filename = elem->filename; | 1057 read_md_filename = elem->filename; |
1103 *lineno = elem->lineno; | 1058 *lineno = elem->lineno; |
1104 *seqnr = sequence_num; | 1059 *seqnr = sequence_num; |
1105 | 1060 |
1106 free (elem); | 1061 free (elem); |
1107 | 1062 |
1223 void | 1178 void |
1224 traverse_c_tests (htab_trav callback, void *info) | 1179 traverse_c_tests (htab_trav callback, void *info) |
1225 { | 1180 { |
1226 if (condition_table) | 1181 if (condition_table) |
1227 htab_traverse (condition_table, callback, info); | 1182 htab_traverse (condition_table, callback, info); |
1228 } | |
1229 | |
1230 | |
1231 /* Given a string, return the number of comma-separated elements in it. | |
1232 Return 0 for the null string. */ | |
1233 int | |
1234 n_comma_elts (const char *s) | |
1235 { | |
1236 int n; | |
1237 | |
1238 if (*s == '\0') | |
1239 return 0; | |
1240 | |
1241 for (n = 1; *s; s++) | |
1242 if (*s == ',') | |
1243 n++; | |
1244 | |
1245 return n; | |
1246 } | |
1247 | |
1248 /* Given a pointer to a (char *), return a pointer to the beginning of the | |
1249 next comma-separated element in the string. Advance the pointer given | |
1250 to the end of that element. Return NULL if at end of string. Caller | |
1251 is responsible for copying the string if necessary. White space between | |
1252 a comma and an element is ignored. */ | |
1253 | |
1254 const char * | |
1255 scan_comma_elt (const char **pstr) | |
1256 { | |
1257 const char *start; | |
1258 const char *p = *pstr; | |
1259 | |
1260 if (*p == ',') | |
1261 p++; | |
1262 while (ISSPACE(*p)) | |
1263 p++; | |
1264 | |
1265 if (*p == '\0') | |
1266 return NULL; | |
1267 | |
1268 start = p; | |
1269 | |
1270 while (*p != ',' && *p != '\0') | |
1271 p++; | |
1272 | |
1273 *pstr = p; | |
1274 return start; | |
1275 } | 1183 } |
1276 | 1184 |
1277 /* Helper functions for define_predicate and define_special_predicate | 1185 /* Helper functions for define_predicate and define_special_predicate |
1278 processing. Shared between genrecog.c and genpreds.c. */ | 1186 processing. Shared between genrecog.c and genpreds.c. */ |
1279 | 1187 |