Mercurial > hg > CbC > CbC_gcc
annotate gcc/read-rtl.c @ 56:3c8a44c06a95
Added tag gcc-4.4.5 for changeset 77e2b8dfacca
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:41:23 +0900 |
parents | 77e2b8dfacca |
children | b7f97abdc517 |
rev | line source |
---|---|
0 | 1 /* RTL reader for GCC. |
2 Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, | |
3 2003, 2004, 2005, 2007, 2008 | |
4 Free Software Foundation, Inc. | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 #include "bconfig.h" | |
23 | |
24 /* Disable rtl checking; it conflicts with the iterator handling. */ | |
25 #undef ENABLE_RTL_CHECKING | |
26 | |
27 #include "system.h" | |
28 #include "coretypes.h" | |
29 #include "tm.h" | |
30 #include "rtl.h" | |
31 #include "obstack.h" | |
32 #include "hashtab.h" | |
33 #include "gensupport.h" | |
34 | |
35 static htab_t md_constants; | |
36 | |
37 /* One element in a singly-linked list of (integer, string) pairs. */ | |
38 struct map_value { | |
39 struct map_value *next; | |
40 int number; | |
41 const char *string; | |
42 }; | |
43 | |
44 /* Maps an iterator or attribute name to a list of (integer, string) pairs. | |
45 The integers are mode or code values; the strings are either C conditions | |
46 or attribute values. */ | |
47 struct mapping { | |
48 /* The name of the iterator or attribute. */ | |
49 const char *name; | |
50 | |
51 /* The group (modes or codes) to which the iterator or attribute belongs. */ | |
52 struct iterator_group *group; | |
53 | |
54 /* Gives a unique number to the attribute or iterator. Numbers are | |
55 allocated consecutively, starting at 0. */ | |
56 int index; | |
57 | |
58 /* The list of (integer, string) pairs. */ | |
59 struct map_value *values; | |
60 }; | |
61 | |
62 /* A structure for abstracting the common parts of code and mode iterators. */ | |
63 struct iterator_group { | |
64 /* Tables of "mapping" structures, one for attributes and one for iterators. */ | |
65 htab_t attrs, iterators; | |
66 | |
67 /* The number of "real" modes or codes (and by extension, the first | |
68 number available for use as an iterator placeholder). */ | |
69 int num_builtins; | |
70 | |
71 /* Treat the given string as the name of a standard mode or code and | |
72 return its integer value. Use the given file for error reporting. */ | |
73 int (*find_builtin) (const char *, FILE *); | |
74 | |
75 /* Return true if the given rtx uses the given mode or code. */ | |
76 bool (*uses_iterator_p) (rtx, int); | |
77 | |
78 /* Make the given rtx use the given mode or code. */ | |
79 void (*apply_iterator) (rtx, int); | |
80 }; | |
81 | |
82 /* Associates PTR (which can be a string, etc.) with the file location | |
83 specified by FILENAME and LINENO. */ | |
84 struct ptr_loc { | |
85 const void *ptr; | |
86 const char *filename; | |
87 int lineno; | |
88 }; | |
89 | |
90 /* A structure used to pass data from read_rtx to apply_iterator_traverse | |
91 via htab_traverse. */ | |
92 struct iterator_traverse_data { | |
93 /* Instruction queue. */ | |
94 rtx queue; | |
95 /* Attributes seen for modes. */ | |
96 struct map_value *mode_maps; | |
97 /* Input file. */ | |
98 FILE *infile; | |
99 /* The last unknown attribute used as a mode. */ | |
100 const char *unknown_mode_attr; | |
101 }; | |
102 | |
103 /* If CODE is the number of a code iterator, return a real rtx code that | |
104 has the same format. Return CODE otherwise. */ | |
105 #define BELLWETHER_CODE(CODE) \ | |
106 ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE]) | |
107 | |
108 static void fatal_with_file_and_line (FILE *, const char *, ...) | |
109 ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN; | |
110 static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN; | |
111 static int find_mode (const char *, FILE *); | |
112 static bool uses_mode_iterator_p (rtx, int); | |
113 static void apply_mode_iterator (rtx, int); | |
114 static int find_code (const char *, FILE *); | |
115 static bool uses_code_iterator_p (rtx, int); | |
116 static void apply_code_iterator (rtx, int); | |
117 static const char *apply_iterator_to_string (const char *, struct mapping *, int); | |
118 static rtx apply_iterator_to_rtx (rtx, struct mapping *, int, | |
119 struct map_value *, FILE *, const char **); | |
120 static bool uses_iterator_p (rtx, struct mapping *); | |
121 static const char *add_condition_to_string (const char *, const char *); | |
122 static void add_condition_to_rtx (rtx, const char *); | |
123 static int apply_iterator_traverse (void **, void *); | |
124 static struct mapping *add_mapping (struct iterator_group *, htab_t t, | |
125 const char *, FILE *); | |
126 static struct map_value **add_map_value (struct map_value **, | |
127 int, const char *); | |
128 static void initialize_iterators (void); | |
129 static void read_name (char *, FILE *); | |
130 static hashval_t leading_ptr_hash (const void *); | |
131 static int leading_ptr_eq_p (const void *, const void *); | |
132 static void set_rtx_ptr_loc (const void *, const char *, int); | |
133 static const struct ptr_loc *get_rtx_ptr_loc (const void *); | |
134 static char *read_string (FILE *, int); | |
135 static char *read_quoted_string (FILE *); | |
136 static char *read_braced_string (FILE *); | |
137 static void read_escape (FILE *); | |
138 static hashval_t def_hash (const void *); | |
139 static int def_name_eq_p (const void *, const void *); | |
140 static void read_constants (FILE *infile, char *tmp_char); | |
141 static void read_conditions (FILE *infile, char *tmp_char); | |
142 static void validate_const_int (FILE *, const char *); | |
143 static int find_iterator (struct iterator_group *, const char *, FILE *); | |
144 static struct mapping *read_mapping (struct iterator_group *, htab_t, FILE *); | |
145 static void check_code_iterator (struct mapping *, FILE *); | |
146 static rtx read_rtx_1 (FILE *, struct map_value **); | |
147 static rtx read_rtx_variadic (FILE *, struct map_value **, rtx); | |
148 | |
149 /* The mode and code iterator structures. */ | |
150 static struct iterator_group modes, codes; | |
151 | |
152 /* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE). */ | |
153 static enum rtx_code *bellwether_codes; | |
154 | |
155 /* Obstack used for allocating RTL strings. */ | |
156 static struct obstack string_obstack; | |
157 | |
158 /* A table of ptr_locs, hashed on the PTR field. */ | |
159 static htab_t ptr_locs; | |
160 | |
161 /* An obstack for the above. Plain xmalloc is a bit heavyweight for a | |
162 small structure like ptr_loc. */ | |
163 static struct obstack ptr_loc_obstack; | |
164 | |
165 /* A hash table of triples (A, B, C), where each of A, B and C is a condition | |
166 and A is equivalent to "B && C". This is used to keep track of the source | |
167 of conditions that are made up of separate rtx strings (such as the split | |
168 condition of a define_insn_and_split). */ | |
169 static htab_t joined_conditions; | |
170 | |
171 /* An obstack for allocating joined_conditions entries. */ | |
172 static struct obstack joined_conditions_obstack; | |
173 | |
174 /* Subroutines of read_rtx. */ | |
175 | |
176 /* The current line number for the file. */ | |
177 int read_rtx_lineno = 1; | |
178 | |
179 /* The filename for error reporting. */ | |
180 const char *read_rtx_filename = "<unknown>"; | |
181 | |
182 static void | |
183 fatal_with_file_and_line (FILE *infile, const char *msg, ...) | |
184 { | |
185 char context[64]; | |
186 size_t i; | |
187 int c; | |
188 va_list ap; | |
189 | |
190 va_start (ap, msg); | |
191 | |
192 fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno); | |
193 vfprintf (stderr, msg, ap); | |
194 putc ('\n', stderr); | |
195 | |
196 /* Gather some following context. */ | |
197 for (i = 0; i < sizeof (context)-1; ++i) | |
198 { | |
199 c = getc (infile); | |
200 if (c == EOF) | |
201 break; | |
202 if (c == '\r' || c == '\n') | |
203 break; | |
204 context[i] = c; | |
205 } | |
206 context[i] = '\0'; | |
207 | |
208 fprintf (stderr, "%s:%d: following context is `%s'\n", | |
209 read_rtx_filename, read_rtx_lineno, context); | |
210 | |
211 va_end (ap); | |
212 exit (1); | |
213 } | |
214 | |
215 /* Dump code after printing a message. Used when read_rtx finds | |
216 invalid data. */ | |
217 | |
218 static void | |
219 fatal_expected_char (FILE *infile, int expected_c, int actual_c) | |
220 { | |
221 if (actual_c == EOF) | |
222 fatal_with_file_and_line (infile, "expected character `%c', found EOF", | |
223 expected_c); | |
224 else | |
225 fatal_with_file_and_line (infile, "expected character `%c', found `%c'", | |
226 expected_c, actual_c); | |
227 } | |
228 | |
229 /* Implementations of the iterator_group callbacks for modes. */ | |
230 | |
231 static int | |
232 find_mode (const char *name, FILE *infile) | |
233 { | |
234 int i; | |
235 | |
236 for (i = 0; i < NUM_MACHINE_MODES; i++) | |
237 if (strcmp (GET_MODE_NAME (i), name) == 0) | |
238 return i; | |
239 | |
240 fatal_with_file_and_line (infile, "unknown mode `%s'", name); | |
241 } | |
242 | |
243 static bool | |
244 uses_mode_iterator_p (rtx x, int mode) | |
245 { | |
246 return (int) GET_MODE (x) == mode; | |
247 } | |
248 | |
249 static void | |
250 apply_mode_iterator (rtx x, int mode) | |
251 { | |
252 PUT_MODE (x, (enum machine_mode) mode); | |
253 } | |
254 | |
255 /* Implementations of the iterator_group callbacks for codes. */ | |
256 | |
257 static int | |
258 find_code (const char *name, FILE *infile) | |
259 { | |
260 int i; | |
261 | |
262 for (i = 0; i < NUM_RTX_CODE; i++) | |
263 if (strcmp (GET_RTX_NAME (i), name) == 0) | |
264 return i; | |
265 | |
266 fatal_with_file_and_line (infile, "unknown rtx code `%s'", name); | |
267 } | |
268 | |
269 static bool | |
270 uses_code_iterator_p (rtx x, int code) | |
271 { | |
272 return (int) GET_CODE (x) == code; | |
273 } | |
274 | |
275 static void | |
276 apply_code_iterator (rtx x, int code) | |
277 { | |
278 PUT_CODE (x, (enum rtx_code) code); | |
279 } | |
280 | |
281 /* Map a code or mode attribute string P to the underlying string for | |
282 ITERATOR and VALUE. */ | |
283 | |
284 static struct map_value * | |
285 map_attr_string (const char *p, struct mapping *iterator, int value) | |
286 { | |
287 const char *attr; | |
288 struct mapping *m; | |
289 struct map_value *v; | |
290 | |
291 /* If there's a "iterator:" prefix, check whether the iterator name matches. | |
292 Set ATTR to the start of the attribute name. */ | |
293 attr = strchr (p, ':'); | |
294 if (attr == 0) | |
295 attr = p; | |
296 else | |
297 { | |
298 if (strncmp (p, iterator->name, attr - p) != 0 | |
299 || iterator->name[attr - p] != 0) | |
300 return 0; | |
301 attr++; | |
302 } | |
303 | |
304 /* Find the attribute specification. */ | |
305 m = (struct mapping *) htab_find (iterator->group->attrs, &attr); | |
306 if (m == 0) | |
307 return 0; | |
308 | |
309 /* Find the attribute value for VALUE. */ | |
310 for (v = m->values; v != 0; v = v->next) | |
311 if (v->number == value) | |
312 break; | |
313 | |
314 return v; | |
315 } | |
316 | |
317 /* Given an attribute string used as a machine mode, return an index | |
318 to store in the machine mode to be translated by | |
319 apply_iterator_to_rtx. */ | |
320 | |
321 static unsigned int | |
322 mode_attr_index (struct map_value **mode_maps, const char *string) | |
323 { | |
324 char *p; | |
325 struct map_value *mv; | |
326 | |
327 /* Copy the attribute string into permanent storage, without the | |
328 angle brackets around it. */ | |
329 obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2); | |
330 p = XOBFINISH (&string_obstack, char *); | |
331 | |
332 mv = XNEW (struct map_value); | |
333 mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1; | |
334 mv->string = p; | |
335 mv->next = *mode_maps; | |
336 *mode_maps = mv; | |
337 | |
338 /* We return a code which we can map back into this string: the | |
339 number of machine modes + the number of mode iterators + the index | |
340 we just used. */ | |
341 return MAX_MACHINE_MODE + htab_elements (modes.iterators) + mv->number; | |
342 } | |
343 | |
344 /* Apply MODE_MAPS to the top level of X, expanding cases where an | |
345 attribute is used for a mode. ITERATOR is the current iterator we are | |
346 expanding, and VALUE is the value to which we are expanding it. | |
347 INFILE is used for error messages. This sets *UNKNOWN to true if | |
348 we find a mode attribute which has not yet been defined, and does | |
349 not change it otherwise. */ | |
350 | |
351 static void | |
352 apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *iterator, | |
353 int value, FILE *infile, const char **unknown) | |
354 { | |
355 unsigned int offset; | |
356 int indx; | |
357 struct map_value *pm; | |
358 | |
359 offset = MAX_MACHINE_MODE + htab_elements (modes.iterators); | |
360 if (GET_MODE (x) < offset) | |
361 return; | |
362 | |
363 indx = GET_MODE (x) - offset; | |
364 for (pm = mode_maps; pm; pm = pm->next) | |
365 { | |
366 if (pm->number == indx) | |
367 { | |
368 struct map_value *v; | |
369 | |
370 v = map_attr_string (pm->string, iterator, value); | |
371 if (v) | |
372 PUT_MODE (x, (enum machine_mode) find_mode (v->string, infile)); | |
373 else | |
374 *unknown = pm->string; | |
375 return; | |
376 } | |
377 } | |
378 } | |
379 | |
380 /* Given that ITERATOR is being expanded as VALUE, apply the appropriate | |
381 string substitutions to STRING. Return the new string if any changes | |
382 were needed, otherwise return STRING itself. */ | |
383 | |
384 static const char * | |
385 apply_iterator_to_string (const char *string, struct mapping *iterator, int value) | |
386 { | |
387 char *base, *copy, *p, *start, *end; | |
388 struct map_value *v; | |
389 | |
390 if (string == 0) | |
391 return string; | |
392 | |
393 base = p = copy = ASTRDUP (string); | |
394 while ((start = strchr (p, '<')) && (end = strchr (start, '>'))) | |
395 { | |
396 p = start + 1; | |
397 | |
398 *end = 0; | |
399 v = map_attr_string (p, iterator, value); | |
400 *end = '>'; | |
401 if (v == 0) | |
402 continue; | |
403 | |
404 /* Add everything between the last copied byte and the '<', | |
405 then add in the attribute value. */ | |
406 obstack_grow (&string_obstack, base, start - base); | |
407 obstack_grow (&string_obstack, v->string, strlen (v->string)); | |
408 base = end + 1; | |
409 } | |
410 if (base != copy) | |
411 { | |
412 obstack_grow (&string_obstack, base, strlen (base) + 1); | |
413 copy = XOBFINISH (&string_obstack, char *); | |
414 copy_rtx_ptr_loc (copy, string); | |
415 return copy; | |
416 } | |
417 return string; | |
418 } | |
419 | |
420 /* Return a copy of ORIGINAL in which all uses of ITERATOR have been | |
421 replaced by VALUE. MODE_MAPS holds information about attribute | |
422 strings used for modes. INFILE is used for error messages. This | |
423 sets *UNKNOWN_MODE_ATTR to the value of an unknown mode attribute, | |
424 and does not change it otherwise. */ | |
425 | |
426 static rtx | |
427 apply_iterator_to_rtx (rtx original, struct mapping *iterator, int value, | |
428 struct map_value *mode_maps, FILE *infile, | |
429 const char **unknown_mode_attr) | |
430 { | |
431 struct iterator_group *group; | |
432 const char *format_ptr; | |
433 int i, j; | |
434 rtx x; | |
435 enum rtx_code bellwether_code; | |
436 | |
437 if (original == 0) | |
438 return original; | |
439 | |
440 /* Create a shallow copy of ORIGINAL. */ | |
441 bellwether_code = BELLWETHER_CODE (GET_CODE (original)); | |
442 x = rtx_alloc (bellwether_code); | |
443 memcpy (x, original, RTX_CODE_SIZE (bellwether_code)); | |
444 | |
445 /* Change the mode or code itself. */ | |
446 group = iterator->group; | |
447 if (group->uses_iterator_p (x, iterator->index + group->num_builtins)) | |
448 group->apply_iterator (x, value); | |
449 | |
450 if (mode_maps) | |
451 apply_mode_maps (x, mode_maps, iterator, value, infile, unknown_mode_attr); | |
452 | |
453 /* Change each string and recursively change each rtx. */ | |
454 format_ptr = GET_RTX_FORMAT (bellwether_code); | |
455 for (i = 0; format_ptr[i] != 0; i++) | |
456 switch (format_ptr[i]) | |
457 { | |
458 case 'T': | |
459 XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i), iterator, value); | |
460 break; | |
461 | |
462 case 'S': | |
463 case 's': | |
464 XSTR (x, i) = apply_iterator_to_string (XSTR (x, i), iterator, value); | |
465 break; | |
466 | |
467 case 'e': | |
468 XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value, | |
469 mode_maps, infile, | |
470 unknown_mode_attr); | |
471 break; | |
472 | |
473 case 'V': | |
474 case 'E': | |
475 if (XVEC (original, i)) | |
476 { | |
477 XVEC (x, i) = rtvec_alloc (XVECLEN (original, i)); | |
478 for (j = 0; j < XVECLEN (x, i); j++) | |
479 XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j), | |
480 iterator, value, mode_maps, | |
481 infile, | |
482 unknown_mode_attr); | |
483 } | |
484 break; | |
485 | |
486 default: | |
487 break; | |
488 } | |
489 return x; | |
490 } | |
491 | |
492 /* Return true if X (or some subexpression of X) uses iterator ITERATOR. */ | |
493 | |
494 static bool | |
495 uses_iterator_p (rtx x, struct mapping *iterator) | |
496 { | |
497 struct iterator_group *group; | |
498 const char *format_ptr; | |
499 int i, j; | |
500 | |
501 if (x == 0) | |
502 return false; | |
503 | |
504 group = iterator->group; | |
505 if (group->uses_iterator_p (x, iterator->index + group->num_builtins)) | |
506 return true; | |
507 | |
508 format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x))); | |
509 for (i = 0; format_ptr[i] != 0; i++) | |
510 switch (format_ptr[i]) | |
511 { | |
512 case 'e': | |
513 if (uses_iterator_p (XEXP (x, i), iterator)) | |
514 return true; | |
515 break; | |
516 | |
517 case 'V': | |
518 case 'E': | |
519 if (XVEC (x, i)) | |
520 for (j = 0; j < XVECLEN (x, i); j++) | |
521 if (uses_iterator_p (XVECEXP (x, i, j), iterator)) | |
522 return true; | |
523 break; | |
524 | |
525 default: | |
526 break; | |
527 } | |
528 return false; | |
529 } | |
530 | |
531 /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL | |
532 has the form "&& ..." (as used in define_insn_and_splits), assume that | |
533 EXTRA is already satisfied. Empty strings are treated like "true". */ | |
534 | |
535 static const char * | |
536 add_condition_to_string (const char *original, const char *extra) | |
537 { | |
538 if (original != 0 && original[0] == '&' && original[1] == '&') | |
539 return original; | |
540 return join_c_conditions (original, extra); | |
541 } | |
542 | |
543 /* Like add_condition, but applied to all conditions in rtx X. */ | |
544 | |
545 static void | |
546 add_condition_to_rtx (rtx x, const char *extra) | |
547 { | |
548 switch (GET_CODE (x)) | |
549 { | |
550 case DEFINE_INSN: | |
551 case DEFINE_EXPAND: | |
552 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); | |
553 break; | |
554 | |
555 case DEFINE_SPLIT: | |
556 case DEFINE_PEEPHOLE: | |
557 case DEFINE_PEEPHOLE2: | |
558 case DEFINE_COND_EXEC: | |
559 XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra); | |
560 break; | |
561 | |
562 case DEFINE_INSN_AND_SPLIT: | |
563 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); | |
564 XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra); | |
565 break; | |
566 | |
567 default: | |
568 break; | |
569 } | |
570 } | |
571 | |
572 /* A htab_traverse callback. Search the EXPR_LIST given by DATA | |
573 for rtxes that use the iterator in *SLOT. Replace each such rtx | |
574 with a list of expansions. */ | |
575 | |
576 static int | |
577 apply_iterator_traverse (void **slot, void *data) | |
578 { | |
579 struct iterator_traverse_data *mtd = (struct iterator_traverse_data *) data; | |
580 struct mapping *iterator; | |
581 struct map_value *v; | |
582 rtx elem, new_elem, original, x; | |
583 | |
584 iterator = (struct mapping *) *slot; | |
585 for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1)) | |
586 if (uses_iterator_p (XEXP (elem, 0), iterator)) | |
587 { | |
588 /* For each iterator we expand, we set UNKNOWN_MODE_ATTR to NULL. | |
589 If apply_iterator_rtx finds an unknown attribute for a mode, | |
590 it will set it to the attribute. We want to know whether | |
591 the attribute is unknown after we have expanded all | |
592 possible iterators, so setting it to NULL here gives us the | |
593 right result when the hash table traversal is complete. */ | |
594 mtd->unknown_mode_attr = NULL; | |
595 | |
596 original = XEXP (elem, 0); | |
597 for (v = iterator->values; v != 0; v = v->next) | |
598 { | |
599 x = apply_iterator_to_rtx (original, iterator, v->number, | |
600 mtd->mode_maps, mtd->infile, | |
601 &mtd->unknown_mode_attr); | |
602 add_condition_to_rtx (x, v->string); | |
603 if (v != iterator->values) | |
604 { | |
605 /* Insert a new EXPR_LIST node after ELEM and put the | |
606 new expansion there. */ | |
607 new_elem = rtx_alloc (EXPR_LIST); | |
608 XEXP (new_elem, 1) = XEXP (elem, 1); | |
609 XEXP (elem, 1) = new_elem; | |
610 elem = new_elem; | |
611 } | |
612 XEXP (elem, 0) = x; | |
613 } | |
614 } | |
615 return 1; | |
616 } | |
617 | |
618 /* Add a new "mapping" structure to hashtable TABLE. NAME is the name | |
619 of the mapping, GROUP is the group to which it belongs, and INFILE | |
620 is the file that defined the mapping. */ | |
621 | |
622 static struct mapping * | |
623 add_mapping (struct iterator_group *group, htab_t table, | |
624 const char *name, FILE *infile) | |
625 { | |
626 struct mapping *m; | |
627 void **slot; | |
628 | |
629 m = XNEW (struct mapping); | |
630 m->name = xstrdup (name); | |
631 m->group = group; | |
632 m->index = htab_elements (table); | |
633 m->values = 0; | |
634 | |
635 slot = htab_find_slot (table, m, INSERT); | |
636 if (*slot != 0) | |
637 fatal_with_file_and_line (infile, "`%s' already defined", name); | |
638 | |
639 *slot = m; | |
640 return m; | |
641 } | |
642 | |
643 /* Add the pair (NUMBER, STRING) to a list of map_value structures. | |
644 END_PTR points to the current null terminator for the list; return | |
645 a pointer the new null terminator. */ | |
646 | |
647 static struct map_value ** | |
648 add_map_value (struct map_value **end_ptr, int number, const char *string) | |
649 { | |
650 struct map_value *value; | |
651 | |
652 value = XNEW (struct map_value); | |
653 value->next = 0; | |
654 value->number = number; | |
655 value->string = string; | |
656 | |
657 *end_ptr = value; | |
658 return &value->next; | |
659 } | |
660 | |
661 /* Do one-time initialization of the mode and code attributes. */ | |
662 | |
663 static void | |
664 initialize_iterators (void) | |
665 { | |
666 struct mapping *lower, *upper; | |
667 struct map_value **lower_ptr, **upper_ptr; | |
668 char *copy, *p; | |
669 int i; | |
670 | |
671 modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); | |
672 modes.iterators = htab_create (13, def_hash, def_name_eq_p, 0); | |
673 modes.num_builtins = MAX_MACHINE_MODE; | |
674 modes.find_builtin = find_mode; | |
675 modes.uses_iterator_p = uses_mode_iterator_p; | |
676 modes.apply_iterator = apply_mode_iterator; | |
677 | |
678 codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); | |
679 codes.iterators = htab_create (13, def_hash, def_name_eq_p, 0); | |
680 codes.num_builtins = NUM_RTX_CODE; | |
681 codes.find_builtin = find_code; | |
682 codes.uses_iterator_p = uses_code_iterator_p; | |
683 codes.apply_iterator = apply_code_iterator; | |
684 | |
685 lower = add_mapping (&modes, modes.attrs, "mode", 0); | |
686 upper = add_mapping (&modes, modes.attrs, "MODE", 0); | |
687 lower_ptr = &lower->values; | |
688 upper_ptr = &upper->values; | |
689 for (i = 0; i < MAX_MACHINE_MODE; i++) | |
690 { | |
691 copy = xstrdup (GET_MODE_NAME (i)); | |
692 for (p = copy; *p != 0; p++) | |
693 *p = TOLOWER (*p); | |
694 | |
695 upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i)); | |
696 lower_ptr = add_map_value (lower_ptr, i, copy); | |
697 } | |
698 | |
699 lower = add_mapping (&codes, codes.attrs, "code", 0); | |
700 upper = add_mapping (&codes, codes.attrs, "CODE", 0); | |
701 lower_ptr = &lower->values; | |
702 upper_ptr = &upper->values; | |
703 for (i = 0; i < NUM_RTX_CODE; i++) | |
704 { | |
705 copy = xstrdup (GET_RTX_NAME (i)); | |
706 for (p = copy; *p != 0; p++) | |
707 *p = TOUPPER (*p); | |
708 | |
709 lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i)); | |
710 upper_ptr = add_map_value (upper_ptr, i, copy); | |
711 } | |
712 } | |
713 | |
714 /* Return a hash value for the pointer pointed to by DEF. */ | |
715 | |
716 static hashval_t | |
717 leading_ptr_hash (const void *def) | |
718 { | |
719 return htab_hash_pointer (*(const void *const *) def); | |
720 } | |
721 | |
722 /* Return true if DEF1 and DEF2 are pointers to the same pointer. */ | |
723 | |
724 static int | |
725 leading_ptr_eq_p (const void *def1, const void *def2) | |
726 { | |
727 return *(const void *const *) def1 == *(const void *const *) def2; | |
728 } | |
729 | |
730 /* Associate PTR with the file position given by FILENAME and LINENO. */ | |
731 | |
732 static void | |
733 set_rtx_ptr_loc (const void *ptr, const char *filename, int lineno) | |
734 { | |
735 struct ptr_loc *loc; | |
736 | |
737 loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack, | |
738 sizeof (struct ptr_loc)); | |
739 loc->ptr = ptr; | |
740 loc->filename = filename; | |
741 loc->lineno = lineno; | |
742 *htab_find_slot (ptr_locs, loc, INSERT) = loc; | |
743 } | |
744 | |
745 /* Return the position associated with pointer PTR. Return null if no | |
746 position was set. */ | |
747 | |
748 static const struct ptr_loc * | |
749 get_rtx_ptr_loc (const void *ptr) | |
750 { | |
751 return (const struct ptr_loc *) htab_find (ptr_locs, &ptr); | |
752 } | |
753 | |
754 /* Associate NEW_PTR with the same file position as OLD_PTR. */ | |
755 | |
756 void | |
757 copy_rtx_ptr_loc (const void *new_ptr, const void *old_ptr) | |
758 { | |
759 const struct ptr_loc *loc = get_rtx_ptr_loc (old_ptr); | |
760 if (loc != 0) | |
761 set_rtx_ptr_loc (new_ptr, loc->filename, loc->lineno); | |
762 } | |
763 | |
764 /* If PTR is associated with a known file position, print a #line | |
765 directive for it. */ | |
766 | |
767 void | |
768 print_rtx_ptr_loc (const void *ptr) | |
769 { | |
770 const struct ptr_loc *loc = get_rtx_ptr_loc (ptr); | |
771 if (loc != 0) | |
772 printf ("#line %d \"%s\"\n", loc->lineno, loc->filename); | |
773 } | |
774 | |
775 /* Return a condition that satisfies both COND1 and COND2. Either string | |
776 may be null or empty. */ | |
777 | |
778 const char * | |
779 join_c_conditions (const char *cond1, const char *cond2) | |
780 { | |
781 char *result; | |
782 const void **entry; | |
783 | |
784 if (cond1 == 0 || cond1[0] == 0) | |
785 return cond2; | |
786 | |
787 if (cond2 == 0 || cond2[0] == 0) | |
788 return cond1; | |
789 | |
790 if (strcmp (cond1, cond2) == 0) | |
791 return cond1; | |
792 | |
793 result = concat ("(", cond1, ") && (", cond2, ")", NULL); | |
794 obstack_ptr_grow (&joined_conditions_obstack, result); | |
795 obstack_ptr_grow (&joined_conditions_obstack, cond1); | |
796 obstack_ptr_grow (&joined_conditions_obstack, cond2); | |
797 entry = XOBFINISH (&joined_conditions_obstack, const void **); | |
798 *htab_find_slot (joined_conditions, entry, INSERT) = entry; | |
799 return result; | |
800 } | |
801 | |
802 /* Print condition COND, wrapped in brackets. If COND was created by | |
803 join_c_conditions, recursively invoke this function for the original | |
804 conditions and join the result with "&&". Otherwise print a #line | |
805 directive for COND if its original file position is known. */ | |
806 | |
807 void | |
808 print_c_condition (const char *cond) | |
809 { | |
810 const char **halves = (const char **) htab_find (joined_conditions, &cond); | |
811 if (halves != 0) | |
812 { | |
813 printf ("("); | |
814 print_c_condition (halves[1]); | |
815 printf (" && "); | |
816 print_c_condition (halves[2]); | |
817 printf (")"); | |
818 } | |
819 else | |
820 { | |
821 putc ('\n', stdout); | |
822 print_rtx_ptr_loc (cond); | |
823 printf ("(%s)", cond); | |
824 } | |
825 } | |
826 | |
827 /* Read chars from INFILE until a non-whitespace char | |
828 and return that. Comments, both Lisp style and C style, | |
829 are treated as whitespace. | |
830 Tools such as genflags use this function. */ | |
831 | |
832 int | |
833 read_skip_spaces (FILE *infile) | |
834 { | |
835 int c; | |
836 | |
837 while (1) | |
838 { | |
839 c = getc (infile); | |
840 switch (c) | |
841 { | |
842 case '\n': | |
843 read_rtx_lineno++; | |
844 break; | |
845 | |
846 case ' ': case '\t': case '\f': case '\r': | |
847 break; | |
848 | |
849 case ';': | |
850 do | |
851 c = getc (infile); | |
852 while (c != '\n' && c != EOF); | |
853 read_rtx_lineno++; | |
854 break; | |
855 | |
856 case '/': | |
857 { | |
858 int prevc; | |
859 c = getc (infile); | |
860 if (c != '*') | |
861 fatal_expected_char (infile, '*', c); | |
862 | |
863 prevc = 0; | |
864 while ((c = getc (infile)) && c != EOF) | |
865 { | |
866 if (c == '\n') | |
867 read_rtx_lineno++; | |
868 else if (prevc == '*' && c == '/') | |
869 break; | |
870 prevc = c; | |
871 } | |
872 } | |
873 break; | |
874 | |
875 default: | |
876 return c; | |
877 } | |
878 } | |
879 } | |
880 | |
881 /* Read an rtx code name into the buffer STR[]. | |
882 It is terminated by any of the punctuation chars of rtx printed syntax. */ | |
883 | |
884 static void | |
885 read_name (char *str, FILE *infile) | |
886 { | |
887 char *p; | |
888 int c; | |
889 | |
890 c = read_skip_spaces (infile); | |
891 | |
892 p = str; | |
893 while (1) | |
894 { | |
895 if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == EOF) | |
896 break; | |
897 if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/' | |
898 || c == '(' || c == '[') | |
899 { | |
900 ungetc (c, infile); | |
901 break; | |
902 } | |
903 *p++ = c; | |
904 c = getc (infile); | |
905 } | |
906 if (p == str) | |
907 fatal_with_file_and_line (infile, "missing name or number"); | |
908 if (c == '\n') | |
909 read_rtx_lineno++; | |
910 | |
911 *p = 0; | |
912 | |
913 if (md_constants) | |
914 { | |
915 /* Do constant expansion. */ | |
916 struct md_constant *def; | |
917 | |
918 p = str; | |
919 do | |
920 { | |
921 struct md_constant tmp_def; | |
922 | |
923 tmp_def.name = p; | |
924 def = (struct md_constant *) htab_find (md_constants, &tmp_def); | |
925 if (def) | |
926 p = def->value; | |
927 } while (def); | |
928 if (p != str) | |
929 strcpy (str, p); | |
930 } | |
931 } | |
932 | |
933 /* Subroutine of the string readers. Handles backslash escapes. | |
934 Caller has read the backslash, but not placed it into the obstack. */ | |
935 static void | |
936 read_escape (FILE *infile) | |
937 { | |
938 int c = getc (infile); | |
939 | |
940 switch (c) | |
941 { | |
942 /* Backslash-newline is replaced by nothing, as in C. */ | |
943 case '\n': | |
944 read_rtx_lineno++; | |
945 return; | |
946 | |
947 /* \" \' \\ are replaced by the second character. */ | |
948 case '\\': | |
949 case '"': | |
950 case '\'': | |
951 break; | |
952 | |
953 /* Standard C string escapes: | |
954 \a \b \f \n \r \t \v | |
955 \[0-7] \x | |
956 all are passed through to the output string unmolested. | |
957 In normal use these wind up in a string constant processed | |
958 by the C compiler, which will translate them appropriately. | |
959 We do not bother checking that \[0-7] are followed by up to | |
960 two octal digits, or that \x is followed by N hex digits. | |
961 \? \u \U are left out because they are not in traditional C. */ | |
962 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': | |
963 case '0': case '1': case '2': case '3': case '4': case '5': case '6': | |
964 case '7': case 'x': | |
965 obstack_1grow (&string_obstack, '\\'); | |
966 break; | |
967 | |
968 /* \; makes stuff for a C string constant containing | |
969 newline and tab. */ | |
970 case ';': | |
971 obstack_grow (&string_obstack, "\\n\\t", 4); | |
972 return; | |
973 | |
974 /* pass anything else through, but issue a warning. */ | |
975 default: | |
976 fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n", | |
977 read_rtx_filename, read_rtx_lineno, c); | |
978 obstack_1grow (&string_obstack, '\\'); | |
979 break; | |
980 } | |
981 | |
982 obstack_1grow (&string_obstack, c); | |
983 } | |
984 | |
985 | |
986 /* Read a double-quoted string onto the obstack. Caller has scanned | |
987 the leading quote. */ | |
988 static char * | |
989 read_quoted_string (FILE *infile) | |
990 { | |
991 int c; | |
992 | |
993 while (1) | |
994 { | |
995 c = getc (infile); /* Read the string */ | |
996 if (c == '\n') | |
997 read_rtx_lineno++; | |
998 else if (c == '\\') | |
999 { | |
1000 read_escape (infile); | |
1001 continue; | |
1002 } | |
1003 else if (c == '"' || c == EOF) | |
1004 break; | |
1005 | |
1006 obstack_1grow (&string_obstack, c); | |
1007 } | |
1008 | |
1009 obstack_1grow (&string_obstack, 0); | |
1010 return XOBFINISH (&string_obstack, char *); | |
1011 } | |
1012 | |
1013 /* Read a braced string (a la Tcl) onto the string obstack. Caller | |
1014 has scanned the leading brace. Note that unlike quoted strings, | |
1015 the outermost braces _are_ included in the string constant. */ | |
1016 static char * | |
1017 read_braced_string (FILE *infile) | |
1018 { | |
1019 int c; | |
1020 int brace_depth = 1; /* caller-processed */ | |
1021 unsigned long starting_read_rtx_lineno = read_rtx_lineno; | |
1022 | |
1023 obstack_1grow (&string_obstack, '{'); | |
1024 while (brace_depth) | |
1025 { | |
1026 c = getc (infile); /* Read the string */ | |
1027 | |
1028 if (c == '\n') | |
1029 read_rtx_lineno++; | |
1030 else if (c == '{') | |
1031 brace_depth++; | |
1032 else if (c == '}') | |
1033 brace_depth--; | |
1034 else if (c == '\\') | |
1035 { | |
1036 read_escape (infile); | |
1037 continue; | |
1038 } | |
1039 else if (c == EOF) | |
1040 fatal_with_file_and_line | |
1041 (infile, "missing closing } for opening brace on line %lu", | |
1042 starting_read_rtx_lineno); | |
1043 | |
1044 obstack_1grow (&string_obstack, c); | |
1045 } | |
1046 | |
1047 obstack_1grow (&string_obstack, 0); | |
1048 return XOBFINISH (&string_obstack, char *); | |
1049 } | |
1050 | |
1051 /* Read some kind of string constant. This is the high-level routine | |
1052 used by read_rtx. It handles surrounding parentheses, leading star, | |
1053 and dispatch to the appropriate string constant reader. */ | |
1054 | |
1055 static char * | |
1056 read_string (FILE *infile, int star_if_braced) | |
1057 { | |
1058 char *stringbuf; | |
1059 int saw_paren = 0; | |
1060 int c, old_lineno; | |
1061 | |
1062 c = read_skip_spaces (infile); | |
1063 if (c == '(') | |
1064 { | |
1065 saw_paren = 1; | |
1066 c = read_skip_spaces (infile); | |
1067 } | |
1068 | |
1069 old_lineno = read_rtx_lineno; | |
1070 if (c == '"') | |
1071 stringbuf = read_quoted_string (infile); | |
1072 else if (c == '{') | |
1073 { | |
1074 if (star_if_braced) | |
1075 obstack_1grow (&string_obstack, '*'); | |
1076 stringbuf = read_braced_string (infile); | |
1077 } | |
1078 else | |
1079 fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c); | |
1080 | |
1081 if (saw_paren) | |
1082 { | |
1083 c = read_skip_spaces (infile); | |
1084 if (c != ')') | |
1085 fatal_expected_char (infile, ')', c); | |
1086 } | |
1087 | |
1088 set_rtx_ptr_loc (stringbuf, read_rtx_filename, old_lineno); | |
1089 return stringbuf; | |
1090 } | |
1091 | |
1092 /* Provide a version of a function to read a long long if the system does | |
1093 not provide one. */ | |
1094 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ) | |
1095 HOST_WIDE_INT atoll (const char *); | |
1096 | |
1097 HOST_WIDE_INT | |
1098 atoll (const char *p) | |
1099 { | |
1100 int neg = 0; | |
1101 HOST_WIDE_INT tmp_wide; | |
1102 | |
1103 while (ISSPACE (*p)) | |
1104 p++; | |
1105 if (*p == '-') | |
1106 neg = 1, p++; | |
1107 else if (*p == '+') | |
1108 p++; | |
1109 | |
1110 tmp_wide = 0; | |
1111 while (ISDIGIT (*p)) | |
1112 { | |
1113 HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0'); | |
1114 if (new_wide < tmp_wide) | |
1115 { | |
1116 /* Return INT_MAX equiv on overflow. */ | |
1117 tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1; | |
1118 break; | |
1119 } | |
1120 tmp_wide = new_wide; | |
1121 p++; | |
1122 } | |
1123 | |
1124 if (neg) | |
1125 tmp_wide = -tmp_wide; | |
1126 return tmp_wide; | |
1127 } | |
1128 #endif | |
1129 | |
1130 /* Given an object that starts with a char * name field, return a hash | |
1131 code for its name. */ | |
1132 static hashval_t | |
1133 def_hash (const void *def) | |
1134 { | |
1135 unsigned result, i; | |
1136 const char *string = *(const char *const *) def; | |
1137 | |
1138 for (result = i = 0; *string++ != '\0'; i++) | |
1139 result += ((unsigned char) *string << (i % CHAR_BIT)); | |
1140 return result; | |
1141 } | |
1142 | |
1143 /* Given two objects that start with char * name fields, return true if | |
1144 they have the same name. */ | |
1145 static int | |
1146 def_name_eq_p (const void *def1, const void *def2) | |
1147 { | |
1148 return ! strcmp (*(const char *const *) def1, | |
1149 *(const char *const *) def2); | |
1150 } | |
1151 | |
1152 /* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer suitable | |
1153 to read a name or number into. Process a define_constants directive, | |
1154 starting with the optional space after the "define_constants". */ | |
1155 static void | |
1156 read_constants (FILE *infile, char *tmp_char) | |
1157 { | |
1158 int c; | |
1159 htab_t defs; | |
1160 | |
1161 c = read_skip_spaces (infile); | |
1162 if (c != '[') | |
1163 fatal_expected_char (infile, '[', c); | |
1164 defs = md_constants; | |
1165 if (! defs) | |
1166 defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0); | |
1167 /* Disable constant expansion during definition processing. */ | |
1168 md_constants = 0; | |
1169 while ( (c = read_skip_spaces (infile)) != ']') | |
1170 { | |
1171 struct md_constant *def; | |
1172 void **entry_ptr; | |
1173 | |
1174 if (c != '(') | |
1175 fatal_expected_char (infile, '(', c); | |
1176 def = XNEW (struct md_constant); | |
1177 def->name = tmp_char; | |
1178 read_name (tmp_char, infile); | |
1179 entry_ptr = htab_find_slot (defs, def, INSERT); | |
1180 if (! *entry_ptr) | |
1181 def->name = xstrdup (tmp_char); | |
1182 c = read_skip_spaces (infile); | |
1183 ungetc (c, infile); | |
1184 read_name (tmp_char, infile); | |
1185 if (! *entry_ptr) | |
1186 { | |
1187 def->value = xstrdup (tmp_char); | |
1188 *entry_ptr = def; | |
1189 } | |
1190 else | |
1191 { | |
1192 def = (struct md_constant *) *entry_ptr; | |
1193 if (strcmp (def->value, tmp_char)) | |
1194 fatal_with_file_and_line (infile, | |
1195 "redefinition of %s, was %s, now %s", | |
1196 def->name, def->value, tmp_char); | |
1197 } | |
1198 c = read_skip_spaces (infile); | |
1199 if (c != ')') | |
1200 fatal_expected_char (infile, ')', c); | |
1201 } | |
1202 md_constants = defs; | |
1203 c = read_skip_spaces (infile); | |
1204 if (c != ')') | |
1205 fatal_expected_char (infile, ')', c); | |
1206 } | |
1207 | |
1208 /* For every constant definition, call CALLBACK with two arguments: | |
1209 a pointer a pointer to the constant definition and INFO. | |
1210 Stops when CALLBACK returns zero. */ | |
1211 void | |
1212 traverse_md_constants (htab_trav callback, void *info) | |
1213 { | |
1214 if (md_constants) | |
1215 htab_traverse (md_constants, callback, info); | |
1216 } | |
1217 | |
1218 /* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer | |
1219 suitable to read a name or number into. Process a | |
1220 define_conditions directive, starting with the optional space after | |
1221 the "define_conditions". The directive looks like this: | |
1222 | |
1223 (define_conditions [ | |
1224 (number "string") | |
1225 (number "string") | |
1226 ... | |
1227 ]) | |
1228 | |
1229 It's not intended to appear in machine descriptions. It is | |
1230 generated by (the program generated by) genconditions.c, and | |
1231 slipped in at the beginning of the sequence of MD files read by | |
1232 most of the other generators. */ | |
1233 static void | |
1234 read_conditions (FILE *infile, char *tmp_char) | |
1235 { | |
1236 int c; | |
1237 | |
1238 c = read_skip_spaces (infile); | |
1239 if (c != '[') | |
1240 fatal_expected_char (infile, '[', c); | |
1241 | |
1242 while ( (c = read_skip_spaces (infile)) != ']') | |
1243 { | |
1244 char *expr; | |
1245 int value; | |
1246 | |
1247 if (c != '(') | |
1248 fatal_expected_char (infile, '(', c); | |
1249 | |
1250 read_name (tmp_char, infile); | |
1251 validate_const_int (infile, tmp_char); | |
1252 value = atoi (tmp_char); | |
1253 | |
1254 c = read_skip_spaces (infile); | |
1255 if (c != '"') | |
1256 fatal_expected_char (infile, '"', c); | |
1257 expr = read_quoted_string (infile); | |
1258 | |
1259 c = read_skip_spaces (infile); | |
1260 if (c != ')') | |
1261 fatal_expected_char (infile, ')', c); | |
1262 | |
1263 add_c_test (expr, value); | |
1264 } | |
1265 c = read_skip_spaces (infile); | |
1266 if (c != ')') | |
1267 fatal_expected_char (infile, ')', c); | |
1268 } | |
1269 | |
1270 static void | |
1271 validate_const_int (FILE *infile, const char *string) | |
1272 { | |
1273 const char *cp; | |
1274 int valid = 1; | |
1275 | |
1276 cp = string; | |
1277 while (*cp && ISSPACE (*cp)) | |
1278 cp++; | |
1279 if (*cp == '-' || *cp == '+') | |
1280 cp++; | |
1281 if (*cp == 0) | |
1282 valid = 0; | |
1283 for (; *cp; cp++) | |
1284 if (! ISDIGIT (*cp)) | |
1285 valid = 0; | |
1286 if (!valid) | |
1287 fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string); | |
1288 } | |
1289 | |
1290 /* Search GROUP for a mode or code called NAME and return its numerical | |
1291 identifier. INFILE is the file that contained NAME. */ | |
1292 | |
1293 static int | |
1294 find_iterator (struct iterator_group *group, const char *name, FILE *infile) | |
1295 { | |
1296 struct mapping *m; | |
1297 | |
1298 m = (struct mapping *) htab_find (group->iterators, &name); | |
1299 if (m != 0) | |
1300 return m->index + group->num_builtins; | |
1301 return group->find_builtin (name, infile); | |
1302 } | |
1303 | |
1304 /* Finish reading a declaration of the form: | |
1305 | |
1306 (define... <name> [<value1> ... <valuen>]) | |
1307 | |
1308 from INFILE, where each <valuei> is either a bare symbol name or a | |
1309 "(<name> <string>)" pair. The "(define..." part has already been read. | |
1310 | |
1311 Represent the declaration as a "mapping" structure; add it to TABLE | |
1312 (which belongs to GROUP) and return it. */ | |
1313 | |
1314 static struct mapping * | |
1315 read_mapping (struct iterator_group *group, htab_t table, FILE *infile) | |
1316 { | |
1317 char tmp_char[256]; | |
1318 struct mapping *m; | |
1319 struct map_value **end_ptr; | |
1320 const char *string; | |
1321 int number, c; | |
1322 | |
1323 /* Read the mapping name and create a structure for it. */ | |
1324 read_name (tmp_char, infile); | |
1325 m = add_mapping (group, table, tmp_char, infile); | |
1326 | |
1327 c = read_skip_spaces (infile); | |
1328 if (c != '[') | |
1329 fatal_expected_char (infile, '[', c); | |
1330 | |
1331 /* Read each value. */ | |
1332 end_ptr = &m->values; | |
1333 c = read_skip_spaces (infile); | |
1334 do | |
1335 { | |
1336 if (c != '(') | |
1337 { | |
1338 /* A bare symbol name that is implicitly paired to an | |
1339 empty string. */ | |
1340 ungetc (c, infile); | |
1341 read_name (tmp_char, infile); | |
1342 string = ""; | |
1343 } | |
1344 else | |
1345 { | |
1346 /* A "(name string)" pair. */ | |
1347 read_name (tmp_char, infile); | |
1348 string = read_string (infile, false); | |
1349 c = read_skip_spaces (infile); | |
1350 if (c != ')') | |
1351 fatal_expected_char (infile, ')', c); | |
1352 } | |
1353 number = group->find_builtin (tmp_char, infile); | |
1354 end_ptr = add_map_value (end_ptr, number, string); | |
1355 c = read_skip_spaces (infile); | |
1356 } | |
1357 while (c != ']'); | |
1358 | |
1359 c = read_skip_spaces (infile); | |
1360 if (c != ')') | |
1361 fatal_expected_char (infile, ')', c); | |
1362 | |
1363 return m; | |
1364 } | |
1365 | |
1366 /* Check newly-created code iterator ITERATOR to see whether every code has the | |
1367 same format. Initialize the iterator's entry in bellwether_codes. */ | |
1368 | |
1369 static void | |
1370 check_code_iterator (struct mapping *iterator, FILE *infile) | |
1371 { | |
1372 struct map_value *v; | |
1373 enum rtx_code bellwether; | |
1374 | |
1375 bellwether = (enum rtx_code) iterator->values->number; | |
1376 for (v = iterator->values->next; v != 0; v = v->next) | |
1377 if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0) | |
1378 fatal_with_file_and_line (infile, "code iterator `%s' combines " | |
1379 "different rtx formats", iterator->name); | |
1380 | |
1381 bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes, | |
1382 iterator->index + 1); | |
1383 bellwether_codes[iterator->index] = bellwether; | |
1384 } | |
1385 | |
1386 /* Read an rtx in printed representation from INFILE and store its | |
1387 core representation in *X. Also store the line number of the | |
1388 opening '(' in *LINENO. Return true on success or false if the | |
1389 end of file has been reached. | |
1390 | |
1391 read_rtx is not used in the compiler proper, but rather in | |
1392 the utilities gen*.c that construct C code from machine descriptions. */ | |
1393 | |
1394 bool | |
1395 read_rtx (FILE *infile, rtx *x, int *lineno) | |
1396 { | |
1397 static rtx queue_head, queue_next; | |
1398 static int queue_lineno; | |
1399 int c; | |
1400 | |
1401 /* Do one-time initialization. */ | |
1402 if (queue_head == 0) | |
1403 { | |
1404 initialize_iterators (); | |
1405 obstack_init (&string_obstack); | |
1406 queue_head = rtx_alloc (EXPR_LIST); | |
1407 ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0); | |
1408 obstack_init (&ptr_loc_obstack); | |
1409 joined_conditions = htab_create (161, leading_ptr_hash, | |
1410 leading_ptr_eq_p, 0); | |
1411 obstack_init (&joined_conditions_obstack); | |
1412 } | |
1413 | |
1414 if (queue_next == 0) | |
1415 { | |
1416 struct map_value *mode_maps; | |
1417 struct iterator_traverse_data mtd; | |
1418 rtx from_file; | |
1419 | |
1420 c = read_skip_spaces (infile); | |
1421 if (c == EOF) | |
1422 return false; | |
1423 ungetc (c, infile); | |
1424 | |
1425 queue_lineno = read_rtx_lineno; | |
1426 mode_maps = 0; | |
1427 from_file = read_rtx_1 (infile, &mode_maps); | |
1428 if (from_file == 0) | |
1429 return false; /* This confuses a top level (nil) with end of | |
1430 file, but a top level (nil) would have | |
1431 crashed our caller anyway. */ | |
1432 | |
1433 queue_next = queue_head; | |
1434 XEXP (queue_next, 0) = from_file; | |
1435 XEXP (queue_next, 1) = 0; | |
1436 | |
1437 mtd.queue = queue_next; | |
1438 mtd.mode_maps = mode_maps; | |
1439 mtd.infile = infile; | |
1440 mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL; | |
1441 htab_traverse (modes.iterators, apply_iterator_traverse, &mtd); | |
1442 htab_traverse (codes.iterators, apply_iterator_traverse, &mtd); | |
1443 if (mtd.unknown_mode_attr) | |
1444 fatal_with_file_and_line (infile, | |
1445 "undefined attribute '%s' used for mode", | |
1446 mtd.unknown_mode_attr); | |
1447 } | |
1448 | |
1449 *x = XEXP (queue_next, 0); | |
1450 *lineno = queue_lineno; | |
1451 queue_next = XEXP (queue_next, 1); | |
1452 | |
1453 return true; | |
1454 } | |
1455 | |
1456 /* Subroutine of read_rtx that reads one construct from INFILE but | |
1457 doesn't apply any iterators. */ | |
1458 | |
1459 static rtx | |
1460 read_rtx_1 (FILE *infile, struct map_value **mode_maps) | |
1461 { | |
1462 int i; | |
1463 RTX_CODE real_code, bellwether_code; | |
1464 const char *format_ptr; | |
1465 /* tmp_char is a buffer used for reading decimal integers | |
1466 and names of rtx types and machine modes. | |
1467 Therefore, 256 must be enough. */ | |
1468 char tmp_char[256]; | |
1469 rtx return_rtx; | |
1470 int c; | |
1471 int tmp_int; | |
1472 HOST_WIDE_INT tmp_wide; | |
1473 | |
1474 /* Linked list structure for making RTXs: */ | |
1475 struct rtx_list | |
1476 { | |
1477 struct rtx_list *next; | |
1478 rtx value; /* Value of this node. */ | |
1479 }; | |
1480 | |
1481 again: | |
1482 c = read_skip_spaces (infile); /* Should be open paren. */ | |
1483 | |
1484 if (c == EOF) | |
1485 return 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1486 |
0 | 1487 if (c != '(') |
1488 fatal_expected_char (infile, '(', c); | |
1489 | |
1490 read_name (tmp_char, infile); | |
1491 if (strcmp (tmp_char, "nil") == 0) | |
1492 { | |
1493 /* (nil) stands for an expression that isn't there. */ | |
1494 c = read_skip_spaces (infile); | |
1495 if (c != ')') | |
1496 fatal_expected_char (infile, ')', c); | |
1497 return 0; | |
1498 } | |
1499 if (strcmp (tmp_char, "define_constants") == 0) | |
1500 { | |
1501 read_constants (infile, tmp_char); | |
1502 goto again; | |
1503 } | |
1504 if (strcmp (tmp_char, "define_conditions") == 0) | |
1505 { | |
1506 read_conditions (infile, tmp_char); | |
1507 goto again; | |
1508 } | |
1509 if (strcmp (tmp_char, "define_mode_attr") == 0) | |
1510 { | |
1511 read_mapping (&modes, modes.attrs, infile); | |
1512 goto again; | |
1513 } | |
1514 if (strcmp (tmp_char, "define_mode_iterator") == 0) | |
1515 { | |
1516 read_mapping (&modes, modes.iterators, infile); | |
1517 goto again; | |
1518 } | |
1519 if (strcmp (tmp_char, "define_code_attr") == 0) | |
1520 { | |
1521 read_mapping (&codes, codes.attrs, infile); | |
1522 goto again; | |
1523 } | |
1524 if (strcmp (tmp_char, "define_code_iterator") == 0) | |
1525 { | |
1526 check_code_iterator (read_mapping (&codes, codes.iterators, infile), | |
1527 infile); | |
1528 goto again; | |
1529 } | |
1530 real_code = (enum rtx_code) find_iterator (&codes, tmp_char, infile); | |
1531 bellwether_code = BELLWETHER_CODE (real_code); | |
1532 | |
1533 /* If we end up with an insn expression then we free this space below. */ | |
1534 return_rtx = rtx_alloc (bellwether_code); | |
1535 format_ptr = GET_RTX_FORMAT (bellwether_code); | |
1536 PUT_CODE (return_rtx, real_code); | |
1537 | |
1538 /* If what follows is `: mode ', read it and | |
1539 store the mode in the rtx. */ | |
1540 | |
1541 i = read_skip_spaces (infile); | |
1542 if (i == ':') | |
1543 { | |
1544 unsigned int mode; | |
1545 | |
1546 read_name (tmp_char, infile); | |
1547 if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>') | |
1548 mode = find_iterator (&modes, tmp_char, infile); | |
1549 else | |
1550 mode = mode_attr_index (mode_maps, tmp_char); | |
1551 PUT_MODE (return_rtx, (enum machine_mode) mode); | |
1552 if (GET_MODE (return_rtx) != mode) | |
1553 fatal_with_file_and_line (infile, "mode too large"); | |
1554 } | |
1555 else | |
1556 ungetc (i, infile); | |
1557 | |
1558 for (i = 0; format_ptr[i] != 0; i++) | |
1559 switch (format_ptr[i]) | |
1560 { | |
1561 /* 0 means a field for internal use only. | |
1562 Don't expect it to be present in the input. */ | |
1563 case '0': | |
1564 break; | |
1565 | |
1566 case 'e': | |
1567 case 'u': | |
1568 XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps); | |
1569 break; | |
1570 | |
1571 case 'V': | |
1572 /* 'V' is an optional vector: if a closeparen follows, | |
1573 just store NULL for this element. */ | |
1574 c = read_skip_spaces (infile); | |
1575 ungetc (c, infile); | |
1576 if (c == ')') | |
1577 { | |
1578 XVEC (return_rtx, i) = 0; | |
1579 break; | |
1580 } | |
1581 /* Now process the vector. */ | |
1582 | |
1583 case 'E': | |
1584 { | |
1585 /* Obstack to store scratch vector in. */ | |
1586 struct obstack vector_stack; | |
1587 int list_counter = 0; | |
1588 rtvec return_vec = NULL_RTVEC; | |
1589 | |
1590 c = read_skip_spaces (infile); | |
1591 if (c != '[') | |
1592 fatal_expected_char (infile, '[', c); | |
1593 | |
1594 /* Add expressions to a list, while keeping a count. */ | |
1595 obstack_init (&vector_stack); | |
1596 while ((c = read_skip_spaces (infile)) && c != ']') | |
1597 { | |
1598 ungetc (c, infile); | |
1599 list_counter++; | |
1600 obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps)); | |
1601 } | |
1602 if (list_counter > 0) | |
1603 { | |
1604 return_vec = rtvec_alloc (list_counter); | |
1605 memcpy (&return_vec->elem[0], obstack_finish (&vector_stack), | |
1606 list_counter * sizeof (rtx)); | |
1607 } | |
1608 else if (format_ptr[i] == 'E') | |
1609 fatal_with_file_and_line (infile, | |
1610 "vector must have at least one element"); | |
1611 XVEC (return_rtx, i) = return_vec; | |
1612 obstack_free (&vector_stack, NULL); | |
1613 /* close bracket gotten */ | |
1614 } | |
1615 break; | |
1616 | |
1617 case 'S': | |
1618 case 'T': | |
1619 case 's': | |
1620 { | |
1621 char *stringbuf; | |
1622 int star_if_braced; | |
1623 | |
1624 c = read_skip_spaces (infile); | |
1625 ungetc (c, infile); | |
1626 if (c == ')') | |
1627 { | |
1628 /* 'S' fields are optional and should be NULL if no string | |
1629 was given. Also allow normal 's' and 'T' strings to be | |
1630 omitted, treating them in the same way as empty strings. */ | |
1631 XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : ""); | |
1632 break; | |
1633 } | |
1634 | |
1635 /* The output template slot of a DEFINE_INSN, | |
1636 DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically | |
1637 gets a star inserted as its first character, if it is | |
1638 written with a brace block instead of a string constant. */ | |
1639 star_if_braced = (format_ptr[i] == 'T'); | |
1640 | |
1641 stringbuf = read_string (infile, star_if_braced); | |
1642 | |
1643 /* For insn patterns, we want to provide a default name | |
1644 based on the file and line, like "*foo.md:12", if the | |
1645 given name is blank. These are only for define_insn and | |
1646 define_insn_and_split, to aid debugging. */ | |
1647 if (*stringbuf == '\0' | |
1648 && i == 0 | |
1649 && (GET_CODE (return_rtx) == DEFINE_INSN | |
1650 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) | |
1651 { | |
1652 char line_name[20]; | |
1653 const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx"); | |
1654 const char *slash; | |
1655 for (slash = fn; *slash; slash ++) | |
1656 if (*slash == '/' || *slash == '\\' || *slash == ':') | |
1657 fn = slash + 1; | |
1658 obstack_1grow (&string_obstack, '*'); | |
1659 obstack_grow (&string_obstack, fn, strlen (fn)); | |
1660 sprintf (line_name, ":%d", read_rtx_lineno); | |
1661 obstack_grow (&string_obstack, line_name, strlen (line_name)+1); | |
1662 stringbuf = XOBFINISH (&string_obstack, char *); | |
1663 } | |
1664 | |
1665 if (star_if_braced) | |
1666 XTMPL (return_rtx, i) = stringbuf; | |
1667 else | |
1668 XSTR (return_rtx, i) = stringbuf; | |
1669 } | |
1670 break; | |
1671 | |
1672 case 'w': | |
1673 read_name (tmp_char, infile); | |
1674 validate_const_int (infile, tmp_char); | |
1675 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT | |
1676 tmp_wide = atoi (tmp_char); | |
1677 #else | |
1678 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG | |
1679 tmp_wide = atol (tmp_char); | |
1680 #else | |
1681 /* Prefer atoll over atoq, since the former is in the ISO C99 standard. | |
1682 But prefer not to use our hand-rolled function above either. */ | |
1683 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ) | |
1684 tmp_wide = atoll (tmp_char); | |
1685 #else | |
1686 tmp_wide = atoq (tmp_char); | |
1687 #endif | |
1688 #endif | |
1689 #endif | |
1690 XWINT (return_rtx, i) = tmp_wide; | |
1691 break; | |
1692 | |
1693 case 'i': | |
1694 case 'n': | |
1695 read_name (tmp_char, infile); | |
1696 validate_const_int (infile, tmp_char); | |
1697 tmp_int = atoi (tmp_char); | |
1698 XINT (return_rtx, i) = tmp_int; | |
1699 break; | |
1700 | |
1701 default: | |
1702 gcc_unreachable (); | |
1703 } | |
1704 | |
1705 c = read_skip_spaces (infile); | |
1706 if (c != ')') | |
1707 { | |
1708 /* Syntactic sugar for AND and IOR, allowing Lisp-like | |
1709 arbitrary number of arguments for them. */ | |
1710 if (c == '(' && (GET_CODE (return_rtx) == AND | |
1711 || GET_CODE (return_rtx) == IOR)) | |
1712 return read_rtx_variadic (infile, mode_maps, return_rtx); | |
1713 else | |
1714 fatal_expected_char (infile, ')', c); | |
1715 } | |
1716 | |
1717 return return_rtx; | |
1718 } | |
1719 | |
1720 /* Mutually recursive subroutine of read_rtx which reads | |
1721 (thing x1 x2 x3 ...) and produces RTL as if | |
1722 (thing x1 (thing x2 (thing x3 ...))) had been written. | |
1723 When called, FORM is (thing x1 x2), and the file position | |
1724 is just past the leading parenthesis of x3. Only works | |
1725 for THINGs which are dyadic expressions, e.g. AND, IOR. */ | |
1726 static rtx | |
1727 read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form) | |
1728 { | |
1729 char c = '('; | |
1730 rtx p = form, q; | |
1731 | |
1732 do | |
1733 { | |
1734 ungetc (c, infile); | |
1735 | |
1736 q = rtx_alloc (GET_CODE (p)); | |
1737 PUT_MODE (q, GET_MODE (p)); | |
1738 | |
1739 XEXP (q, 0) = XEXP (p, 1); | |
1740 XEXP (q, 1) = read_rtx_1 (infile, mode_maps); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1741 |
0 | 1742 XEXP (p, 1) = q; |
1743 p = q; | |
1744 c = read_skip_spaces (infile); | |
1745 } | |
1746 while (c == '('); | |
1747 | |
1748 if (c != ')') | |
1749 fatal_expected_char (infile, ')', c); | |
1750 | |
1751 return form; | |
1752 } |