]>
Commit | Line | Data |
---|---|---|
5e6908ea | 1 | /* RTL reader for GCC. |
0c20a65f | 2 | Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, |
88462c42 | 3 | 2003, 2004 |
0f40f9f7 ZW |
4 | Free Software Foundation, Inc. |
5 | ||
1322177d | 6 | This file is part of GCC. |
0f40f9f7 | 7 | |
1322177d LB |
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 2, or (at your option) any later | |
11 | version. | |
0f40f9f7 | 12 | |
1322177d LB |
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. | |
0f40f9f7 ZW |
17 | |
18 | You should have received a copy of the GNU General Public License | |
1322177d LB |
19 | along with GCC; see the file COPYING. If not, write to the Free |
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
21 | 02111-1307, USA. */ | |
0f40f9f7 | 22 | |
4977bab6 | 23 | #include "bconfig.h" |
0f40f9f7 | 24 | #include "system.h" |
4977bab6 ZW |
25 | #include "coretypes.h" |
26 | #include "tm.h" | |
0f40f9f7 ZW |
27 | #include "rtl.h" |
28 | #include "obstack.h" | |
29 | #include "hashtab.h" | |
30 | ||
0f40f9f7 ZW |
31 | static htab_t md_constants; |
32 | ||
032e8348 RS |
33 | /* One element in a singly-linked list of (integer, string) pairs. */ |
34 | struct map_value { | |
35 | struct map_value *next; | |
36 | int number; | |
37 | const char *string; | |
38 | }; | |
39 | ||
40 | /* Maps a macro or attribute name to a list of (integer, string) pairs. | |
41 | The integers are mode or code values; the strings are either C conditions | |
42 | or attribute values. */ | |
43 | struct mapping { | |
44 | /* The name of the macro or attribute. */ | |
45 | const char *name; | |
46 | ||
47 | /* The group (modes or codes) to which the macro or attribute belongs. */ | |
48 | struct macro_group *group; | |
49 | ||
50 | /* Gives a unique number to the attribute or macro. Numbers are | |
51 | allocated consecutively, starting at 0. */ | |
52 | int index; | |
53 | ||
54 | /* The list of (integer, string) pairs. */ | |
55 | struct map_value *values; | |
56 | }; | |
57 | ||
58 | /* A structure for abstracting the common parts of code and mode macros. */ | |
59 | struct macro_group { | |
60 | /* Tables of "mapping" structures, one for attributes and one for macros. */ | |
61 | htab_t attrs, macros; | |
62 | ||
63 | /* The number of "real" modes or codes (and by extension, the first | |
64 | number available for use as a macro placeholder). */ | |
65 | int num_builtins; | |
66 | ||
67 | /* Treat the given string as the name of a standard mode or code and | |
68 | return its integer value. Use the given file for error reporting. */ | |
69 | int (*find_builtin) (const char *, FILE *); | |
70 | ||
71 | /* Return true if the given rtx uses the given mode or code. */ | |
72 | bool (*uses_macro_p) (rtx, int); | |
73 | ||
74 | /* Make the given rtx use the given mode or code. */ | |
75 | void (*apply_macro) (rtx, int); | |
76 | }; | |
77 | ||
78 | /* If CODE is the number of a code macro, return a real rtx code that | |
79 | has the same format. Return CODE otherwise. */ | |
80 | #define BELLWETHER_CODE(CODE) \ | |
81 | ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE]) | |
82 | ||
0c20a65f | 83 | static void fatal_with_file_and_line (FILE *, const char *, ...) |
0f40f9f7 | 84 | ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN; |
0c20a65f | 85 | static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN; |
032e8348 RS |
86 | static int find_mode (const char *, FILE *); |
87 | static bool uses_mode_macro_p (rtx, int); | |
88 | static void apply_mode_macro (rtx, int); | |
89 | static int find_code (const char *, FILE *); | |
90 | static bool uses_code_macro_p (rtx, int); | |
91 | static void apply_code_macro (rtx, int); | |
92 | static const char *apply_macro_to_string (const char *, struct mapping *, int); | |
93 | static rtx apply_macro_to_rtx (rtx, struct mapping *, int); | |
94 | static bool uses_macro_p (rtx, struct mapping *); | |
95 | static const char *add_condition_to_string (const char *, const char *); | |
96 | static void add_condition_to_rtx (rtx, const char *); | |
97 | static int apply_macro_traverse (void **, void *); | |
98 | static struct mapping *add_mapping (struct macro_group *, htab_t t, | |
99 | const char *, FILE *); | |
100 | static struct map_value **add_map_value (struct map_value **, | |
101 | int, const char *); | |
102 | static void initialize_macros (void); | |
0c20a65f | 103 | static void read_name (char *, FILE *); |
a269d6c8 RS |
104 | static char *read_string (FILE *, int); |
105 | static char *read_quoted_string (FILE *); | |
106 | static char *read_braced_string (FILE *); | |
107 | static void read_escape (FILE *); | |
0c20a65f AJ |
108 | static hashval_t def_hash (const void *); |
109 | static int def_name_eq_p (const void *, const void *); | |
110 | static void read_constants (FILE *infile, char *tmp_char); | |
111 | static void validate_const_int (FILE *, const char *); | |
032e8348 RS |
112 | static int find_macro (struct macro_group *, const char *, FILE *); |
113 | static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *); | |
114 | static void check_code_macro (struct mapping *, FILE *); | |
115 | static rtx read_rtx_1 (FILE *); | |
116 | ||
117 | /* The mode and code macro structures. */ | |
118 | static struct macro_group modes, codes; | |
119 | ||
120 | /* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE). */ | |
121 | static enum rtx_code *bellwether_codes; | |
0f40f9f7 | 122 | |
a269d6c8 RS |
123 | /* Obstack used for allocating RTL strings. */ |
124 | static struct obstack string_obstack; | |
125 | ||
0f40f9f7 ZW |
126 | /* Subroutines of read_rtx. */ |
127 | ||
128 | /* The current line number for the file. */ | |
129 | int read_rtx_lineno = 1; | |
130 | ||
131 | /* The filename for aborting with file and line. */ | |
132 | const char *read_rtx_filename = "<unknown>"; | |
133 | ||
134 | static void | |
e34d07f2 | 135 | fatal_with_file_and_line (FILE *infile, const char *msg, ...) |
0f40f9f7 | 136 | { |
0f40f9f7 ZW |
137 | char context[64]; |
138 | size_t i; | |
139 | int c; | |
e34d07f2 | 140 | va_list ap; |
0f40f9f7 | 141 | |
e34d07f2 | 142 | va_start (ap, msg); |
0f40f9f7 ZW |
143 | |
144 | fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno); | |
145 | vfprintf (stderr, msg, ap); | |
146 | putc ('\n', stderr); | |
147 | ||
148 | /* Gather some following context. */ | |
8e2e89f7 | 149 | for (i = 0; i < sizeof (context)-1; ++i) |
0f40f9f7 ZW |
150 | { |
151 | c = getc (infile); | |
152 | if (c == EOF) | |
153 | break; | |
154 | if (c == '\r' || c == '\n') | |
155 | break; | |
156 | context[i] = c; | |
157 | } | |
158 | context[i] = '\0'; | |
159 | ||
160 | fprintf (stderr, "%s:%d: following context is `%s'\n", | |
161 | read_rtx_filename, read_rtx_lineno, context); | |
162 | ||
e34d07f2 | 163 | va_end (ap); |
0f40f9f7 ZW |
164 | exit (1); |
165 | } | |
166 | ||
167 | /* Dump code after printing a message. Used when read_rtx finds | |
168 | invalid data. */ | |
169 | ||
170 | static void | |
0c20a65f | 171 | fatal_expected_char (FILE *infile, int expected_c, int actual_c) |
0f40f9f7 ZW |
172 | { |
173 | fatal_with_file_and_line (infile, "expected character `%c', found `%c'", | |
174 | expected_c, actual_c); | |
175 | } | |
176 | ||
032e8348 RS |
177 | /* Implementations of the macro_group callbacks for modes. */ |
178 | ||
179 | static int | |
180 | find_mode (const char *name, FILE *infile) | |
181 | { | |
182 | int i; | |
183 | ||
184 | for (i = 0; i < NUM_MACHINE_MODES; i++) | |
185 | if (strcmp (GET_MODE_NAME (i), name) == 0) | |
186 | return i; | |
187 | ||
188 | fatal_with_file_and_line (infile, "unknown mode `%s'", name); | |
189 | } | |
190 | ||
191 | static bool | |
192 | uses_mode_macro_p (rtx x, int mode) | |
193 | { | |
194 | return (int) GET_MODE (x) == mode; | |
195 | } | |
196 | ||
197 | static void | |
198 | apply_mode_macro (rtx x, int mode) | |
199 | { | |
200 | PUT_MODE (x, mode); | |
201 | } | |
202 | ||
203 | /* Implementations of the macro_group callbacks for codes. */ | |
204 | ||
205 | static int | |
206 | find_code (const char *name, FILE *infile) | |
207 | { | |
208 | int i; | |
209 | ||
210 | for (i = 0; i < NUM_RTX_CODE; i++) | |
211 | if (strcmp (GET_RTX_NAME (i), name) == 0) | |
212 | return i; | |
213 | ||
214 | fatal_with_file_and_line (infile, "unknown rtx code `%s'", name); | |
215 | } | |
216 | ||
217 | static bool | |
218 | uses_code_macro_p (rtx x, int code) | |
219 | { | |
220 | return (int) GET_CODE (x) == code; | |
221 | } | |
222 | ||
223 | static void | |
224 | apply_code_macro (rtx x, int code) | |
225 | { | |
226 | PUT_CODE (x, code); | |
227 | } | |
228 | ||
229 | /* Given that MACRO is being expanded as VALUE, apply the appropriate | |
230 | string substitutions to STRING. Return the new string if any changes | |
231 | were needed, otherwise return STRING itself. */ | |
232 | ||
233 | static const char * | |
234 | apply_macro_to_string (const char *string, struct mapping *macro, int value) | |
235 | { | |
236 | char *base, *copy, *p, *attr, *start, *end; | |
237 | struct mapping *m; | |
238 | struct map_value *v; | |
239 | ||
240 | if (string == 0) | |
241 | return string; | |
242 | ||
243 | base = p = copy = ASTRDUP (string); | |
244 | while ((start = index (p, '<')) && (end = index (start, '>'))) | |
245 | { | |
246 | p = start + 1; | |
247 | ||
248 | /* If there's a "macro:" prefix, check whether the macro name matches. | |
249 | Set ATTR to the start of the attribute name. */ | |
250 | attr = index (p, ':'); | |
251 | if (attr == 0 || attr > end) | |
252 | attr = p; | |
253 | else | |
254 | { | |
255 | if (strncmp (p, macro->name, attr - p) != 0 | |
256 | || macro->name[attr - p] != 0) | |
257 | continue; | |
258 | attr++; | |
259 | } | |
260 | ||
261 | /* Find the attribute specification. */ | |
262 | *end = 0; | |
263 | m = (struct mapping *) htab_find (macro->group->attrs, &attr); | |
264 | *end = '>'; | |
265 | if (m == 0) | |
266 | continue; | |
267 | ||
268 | /* Find the attribute value for VALUE. */ | |
269 | for (v = m->values; v != 0; v = v->next) | |
270 | if (v->number == value) | |
271 | break; | |
272 | if (v == 0) | |
273 | continue; | |
274 | ||
275 | /* Add everything between the last copied byte and the '<', | |
276 | then add in the attribute value. */ | |
277 | obstack_grow (&string_obstack, base, start - base); | |
278 | obstack_grow (&string_obstack, v->string, strlen (v->string)); | |
279 | base = end + 1; | |
280 | } | |
281 | if (base != copy) | |
282 | { | |
283 | obstack_grow (&string_obstack, base, strlen (base) + 1); | |
284 | return (char *) obstack_finish (&string_obstack); | |
285 | } | |
286 | return string; | |
287 | } | |
288 | ||
289 | /* Return a copy of ORIGINAL in which all uses of MACRO have been | |
290 | replaced by VALUE. */ | |
291 | ||
292 | static rtx | |
293 | apply_macro_to_rtx (rtx original, struct mapping *macro, int value) | |
294 | { | |
295 | struct macro_group *group; | |
296 | const char *format_ptr; | |
297 | int i, j; | |
298 | rtx x; | |
299 | enum rtx_code bellwether_code; | |
300 | ||
301 | if (original == 0) | |
302 | return original; | |
303 | ||
304 | /* Create a shallow copy of ORIGINAL. */ | |
305 | bellwether_code = BELLWETHER_CODE (GET_CODE (original)); | |
306 | x = rtx_alloc (bellwether_code); | |
307 | memcpy (x, original, RTX_SIZE (bellwether_code)); | |
308 | ||
309 | /* Change the mode or code itself. */ | |
310 | group = macro->group; | |
311 | if (group->uses_macro_p (x, macro->index + group->num_builtins)) | |
312 | group->apply_macro (x, value); | |
313 | ||
314 | /* Change each string and recursively change each rtx. */ | |
315 | format_ptr = GET_RTX_FORMAT (bellwether_code); | |
316 | for (i = 0; format_ptr[i] != 0; i++) | |
317 | switch (format_ptr[i]) | |
318 | { | |
319 | case 'S': | |
320 | case 'T': | |
321 | case 's': | |
322 | XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value); | |
323 | break; | |
324 | ||
325 | case 'e': | |
326 | XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value); | |
327 | break; | |
328 | ||
329 | case 'V': | |
330 | case 'E': | |
331 | if (XVEC (original, i)) | |
332 | { | |
333 | XVEC (x, i) = rtvec_alloc (XVECLEN (original, i)); | |
334 | for (j = 0; j < XVECLEN (x, i); j++) | |
335 | XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j), | |
336 | macro, value); | |
337 | } | |
338 | break; | |
339 | ||
340 | default: | |
341 | break; | |
342 | } | |
343 | return x; | |
344 | } | |
345 | ||
346 | /* Return true if X (or some subexpression of X) uses macro MACRO. */ | |
347 | ||
348 | static bool | |
349 | uses_macro_p (rtx x, struct mapping *macro) | |
350 | { | |
351 | struct macro_group *group; | |
352 | const char *format_ptr; | |
353 | int i, j; | |
354 | ||
355 | if (x == 0) | |
356 | return false; | |
357 | ||
358 | group = macro->group; | |
359 | if (group->uses_macro_p (x, macro->index + group->num_builtins)) | |
360 | return true; | |
361 | ||
362 | format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x))); | |
363 | for (i = 0; format_ptr[i] != 0; i++) | |
364 | switch (format_ptr[i]) | |
365 | { | |
366 | case 'e': | |
367 | if (uses_macro_p (XEXP (x, i), macro)) | |
368 | return true; | |
369 | break; | |
370 | ||
371 | case 'V': | |
372 | case 'E': | |
373 | if (XVEC (x, i)) | |
374 | for (j = 0; j < XVECLEN (x, i); j++) | |
375 | if (uses_macro_p (XVECEXP (x, i, j), macro)) | |
376 | return true; | |
377 | break; | |
378 | ||
379 | default: | |
380 | break; | |
381 | } | |
382 | return false; | |
383 | } | |
384 | ||
385 | /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL | |
386 | has the form "&& ..." (as used in define_insn_and_splits), assume that | |
387 | EXTRA is already satisfied. Empty strings are treated like "true". */ | |
388 | ||
389 | static const char * | |
390 | add_condition_to_string (const char *original, const char *extra) | |
391 | { | |
392 | char *result; | |
393 | ||
394 | if (original == 0 || original[0] == 0) | |
395 | return extra; | |
396 | ||
397 | if ((original[0] == '&' && original[1] == '&') || extra[0] == 0) | |
398 | return original; | |
399 | ||
400 | asprintf (&result, "(%s) && (%s)", original, extra); | |
401 | return result; | |
402 | } | |
403 | ||
404 | /* Like add_condition, but applied to all conditions in rtx X. */ | |
405 | ||
406 | static void | |
407 | add_condition_to_rtx (rtx x, const char *extra) | |
408 | { | |
409 | switch (GET_CODE (x)) | |
410 | { | |
411 | case DEFINE_INSN: | |
412 | case DEFINE_EXPAND: | |
413 | XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); | |
414 | break; | |
415 | ||
416 | case DEFINE_SPLIT: | |
417 | case DEFINE_PEEPHOLE: | |
418 | case DEFINE_PEEPHOLE2: | |
419 | case DEFINE_COND_EXEC: | |
420 | XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra); | |
421 | break; | |
422 | ||
423 | case DEFINE_INSN_AND_SPLIT: | |
424 | XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); | |
425 | XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra); | |
426 | break; | |
427 | ||
428 | default: | |
429 | break; | |
430 | } | |
431 | } | |
432 | ||
433 | /* A htab_traverse callback. Search the EXPR_LIST given by DATA | |
434 | for rtxes that use the macro in *SLOT. Replace each such rtx | |
435 | with a list of expansions. */ | |
436 | ||
437 | static int | |
438 | apply_macro_traverse (void **slot, void *data) | |
439 | { | |
440 | struct mapping *macro; | |
441 | struct map_value *v; | |
442 | rtx elem, new_elem, original, x; | |
443 | ||
444 | macro = (struct mapping *) *slot; | |
445 | for (elem = (rtx) data; elem != 0; elem = XEXP (elem, 1)) | |
446 | if (uses_macro_p (XEXP (elem, 0), macro)) | |
447 | { | |
448 | original = XEXP (elem, 0); | |
449 | for (v = macro->values; v != 0; v = v->next) | |
450 | { | |
451 | x = apply_macro_to_rtx (original, macro, v->number); | |
452 | add_condition_to_rtx (x, v->string); | |
453 | if (v != macro->values) | |
454 | { | |
455 | /* Insert a new EXPR_LIST node after ELEM and put the | |
456 | new expansion there. */ | |
457 | new_elem = rtx_alloc (EXPR_LIST); | |
458 | XEXP (new_elem, 1) = XEXP (elem, 1); | |
459 | XEXP (elem, 1) = new_elem; | |
460 | elem = new_elem; | |
461 | } | |
462 | XEXP (elem, 0) = x; | |
463 | } | |
464 | } | |
465 | return 1; | |
466 | } | |
467 | ||
468 | /* Add a new "mapping" structure to hashtable TABLE. NAME is the name | |
469 | of the mapping, GROUP is the group to which it belongs, and INFILE | |
470 | is the file that defined the mapping. */ | |
471 | ||
472 | static struct mapping * | |
473 | add_mapping (struct macro_group *group, htab_t table, | |
474 | const char *name, FILE *infile) | |
475 | { | |
476 | struct mapping *m; | |
477 | void **slot; | |
478 | ||
479 | m = XNEW (struct mapping); | |
480 | m->name = xstrdup (name); | |
481 | m->group = group; | |
482 | m->index = htab_elements (table); | |
483 | m->values = 0; | |
484 | ||
485 | slot = htab_find_slot (table, m, INSERT); | |
486 | if (*slot != 0) | |
487 | fatal_with_file_and_line (infile, "`%s' already defined", name); | |
488 | ||
489 | *slot = m; | |
490 | return m; | |
491 | } | |
492 | ||
493 | /* Add the pair (NUMBER, STRING) to a list of map_value structures. | |
494 | END_PTR points to the current null terminator for the list; return | |
495 | a pointer the new null terminator. */ | |
496 | ||
497 | static struct map_value ** | |
498 | add_map_value (struct map_value **end_ptr, int number, const char *string) | |
499 | { | |
500 | struct map_value *value; | |
501 | ||
502 | value = XNEW (struct map_value); | |
503 | value->next = 0; | |
504 | value->number = number; | |
505 | value->string = string; | |
506 | ||
507 | *end_ptr = value; | |
508 | return &value->next; | |
509 | } | |
510 | ||
511 | /* Do one-time initialization of the mode and code attributes. */ | |
512 | ||
513 | static void | |
514 | initialize_macros (void) | |
515 | { | |
516 | struct mapping *lower, *upper; | |
517 | struct map_value **lower_ptr, **upper_ptr; | |
518 | char *copy, *p; | |
519 | int i; | |
520 | ||
521 | modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); | |
522 | modes.macros = htab_create (13, def_hash, def_name_eq_p, 0); | |
523 | modes.num_builtins = MAX_MACHINE_MODE; | |
524 | modes.find_builtin = find_mode; | |
525 | modes.uses_macro_p = uses_mode_macro_p; | |
526 | modes.apply_macro = apply_mode_macro; | |
527 | ||
528 | codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); | |
529 | codes.macros = htab_create (13, def_hash, def_name_eq_p, 0); | |
530 | codes.num_builtins = NUM_RTX_CODE; | |
531 | codes.find_builtin = find_code; | |
532 | codes.uses_macro_p = uses_code_macro_p; | |
533 | codes.apply_macro = apply_code_macro; | |
534 | ||
535 | lower = add_mapping (&modes, modes.attrs, "mode", 0); | |
536 | upper = add_mapping (&modes, modes.attrs, "MODE", 0); | |
537 | lower_ptr = &lower->values; | |
538 | upper_ptr = &upper->values; | |
539 | for (i = 0; i < MAX_MACHINE_MODE; i++) | |
540 | { | |
541 | copy = xstrdup (GET_MODE_NAME (i)); | |
542 | for (p = copy; *p != 0; p++) | |
543 | *p = TOLOWER (*p); | |
544 | ||
545 | upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i)); | |
546 | lower_ptr = add_map_value (lower_ptr, i, copy); | |
547 | } | |
548 | ||
549 | lower = add_mapping (&codes, codes.attrs, "code", 0); | |
550 | upper = add_mapping (&codes, codes.attrs, "CODE", 0); | |
551 | lower_ptr = &lower->values; | |
552 | upper_ptr = &upper->values; | |
553 | for (i = 0; i < NUM_RTX_CODE; i++) | |
554 | { | |
555 | copy = xstrdup (GET_RTX_NAME (i)); | |
556 | for (p = copy; *p != 0; p++) | |
557 | *p = TOUPPER (*p); | |
558 | ||
559 | lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i)); | |
560 | upper_ptr = add_map_value (upper_ptr, i, copy); | |
561 | } | |
562 | } | |
563 | ||
0f40f9f7 ZW |
564 | /* Read chars from INFILE until a non-whitespace char |
565 | and return that. Comments, both Lisp style and C style, | |
566 | are treated as whitespace. | |
567 | Tools such as genflags use this function. */ | |
568 | ||
569 | int | |
0c20a65f | 570 | read_skip_spaces (FILE *infile) |
0f40f9f7 | 571 | { |
b3694847 SS |
572 | int c; |
573 | ||
0f40f9f7 ZW |
574 | while (1) |
575 | { | |
576 | c = getc (infile); | |
577 | switch (c) | |
578 | { | |
579 | case '\n': | |
580 | read_rtx_lineno++; | |
581 | break; | |
582 | ||
583 | case ' ': case '\t': case '\f': case '\r': | |
584 | break; | |
585 | ||
586 | case ';': | |
587 | do | |
588 | c = getc (infile); | |
589 | while (c != '\n' && c != EOF); | |
590 | read_rtx_lineno++; | |
591 | break; | |
592 | ||
593 | case '/': | |
594 | { | |
b3694847 | 595 | int prevc; |
0f40f9f7 ZW |
596 | c = getc (infile); |
597 | if (c != '*') | |
598 | fatal_expected_char (infile, '*', c); | |
599 | ||
600 | prevc = 0; | |
601 | while ((c = getc (infile)) && c != EOF) | |
602 | { | |
603 | if (c == '\n') | |
604 | read_rtx_lineno++; | |
605 | else if (prevc == '*' && c == '/') | |
606 | break; | |
607 | prevc = c; | |
608 | } | |
609 | } | |
610 | break; | |
611 | ||
612 | default: | |
613 | return c; | |
614 | } | |
615 | } | |
616 | } | |
617 | ||
618 | /* Read an rtx code name into the buffer STR[]. | |
619 | It is terminated by any of the punctuation chars of rtx printed syntax. */ | |
620 | ||
621 | static void | |
0c20a65f | 622 | read_name (char *str, FILE *infile) |
0f40f9f7 | 623 | { |
b3694847 SS |
624 | char *p; |
625 | int c; | |
0f40f9f7 | 626 | |
b3694847 | 627 | c = read_skip_spaces (infile); |
0f40f9f7 ZW |
628 | |
629 | p = str; | |
630 | while (1) | |
631 | { | |
b38b083a | 632 | if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r') |
0f40f9f7 ZW |
633 | break; |
634 | if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/' | |
635 | || c == '(' || c == '[') | |
636 | { | |
637 | ungetc (c, infile); | |
638 | break; | |
639 | } | |
640 | *p++ = c; | |
641 | c = getc (infile); | |
642 | } | |
643 | if (p == str) | |
644 | fatal_with_file_and_line (infile, "missing name or number"); | |
645 | if (c == '\n') | |
646 | read_rtx_lineno++; | |
647 | ||
648 | *p = 0; | |
649 | ||
650 | if (md_constants) | |
651 | { | |
652 | /* Do constant expansion. */ | |
653 | struct md_constant *def; | |
654 | ||
655 | p = str; | |
656 | do | |
657 | { | |
658 | struct md_constant tmp_def; | |
659 | ||
660 | tmp_def.name = p; | |
28dab132 | 661 | def = (struct md_constant *) htab_find (md_constants, &tmp_def); |
0f40f9f7 ZW |
662 | if (def) |
663 | p = def->value; | |
664 | } while (def); | |
665 | if (p != str) | |
666 | strcpy (str, p); | |
667 | } | |
668 | } | |
669 | ||
1f3b37a3 ZW |
670 | /* Subroutine of the string readers. Handles backslash escapes. |
671 | Caller has read the backslash, but not placed it into the obstack. */ | |
672 | static void | |
a269d6c8 | 673 | read_escape (FILE *infile) |
1f3b37a3 ZW |
674 | { |
675 | int c = getc (infile); | |
b3694847 | 676 | |
1f3b37a3 ZW |
677 | switch (c) |
678 | { | |
679 | /* Backslash-newline is replaced by nothing, as in C. */ | |
680 | case '\n': | |
681 | read_rtx_lineno++; | |
682 | return; | |
683 | ||
684 | /* \" \' \\ are replaced by the second character. */ | |
685 | case '\\': | |
686 | case '"': | |
687 | case '\'': | |
688 | break; | |
689 | ||
690 | /* Standard C string escapes: | |
691 | \a \b \f \n \r \t \v | |
692 | \[0-7] \x | |
693 | all are passed through to the output string unmolested. | |
694 | In normal use these wind up in a string constant processed | |
695 | by the C compiler, which will translate them appropriately. | |
696 | We do not bother checking that \[0-7] are followed by up to | |
697 | two octal digits, or that \x is followed by N hex digits. | |
698 | \? \u \U are left out because they are not in traditional C. */ | |
699 | case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': | |
700 | case '0': case '1': case '2': case '3': case '4': case '5': case '6': | |
701 | case '7': case 'x': | |
a269d6c8 | 702 | obstack_1grow (&string_obstack, '\\'); |
1f3b37a3 ZW |
703 | break; |
704 | ||
705 | /* \; makes stuff for a C string constant containing | |
706 | newline and tab. */ | |
707 | case ';': | |
a269d6c8 | 708 | obstack_grow (&string_obstack, "\\n\\t", 4); |
1f3b37a3 ZW |
709 | return; |
710 | ||
711 | /* pass anything else through, but issue a warning. */ | |
712 | default: | |
713 | fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n", | |
714 | read_rtx_filename, read_rtx_lineno, c); | |
a269d6c8 | 715 | obstack_1grow (&string_obstack, '\\'); |
1f3b37a3 ZW |
716 | break; |
717 | } | |
718 | ||
a269d6c8 | 719 | obstack_1grow (&string_obstack, c); |
1f3b37a3 | 720 | } |
a6a2274a | 721 | |
1f3b37a3 | 722 | |
0f40f9f7 ZW |
723 | /* Read a double-quoted string onto the obstack. Caller has scanned |
724 | the leading quote. */ | |
725 | static char * | |
a269d6c8 | 726 | read_quoted_string (FILE *infile) |
0f40f9f7 ZW |
727 | { |
728 | int c; | |
b3694847 | 729 | |
0f40f9f7 ZW |
730 | while (1) |
731 | { | |
732 | c = getc (infile); /* Read the string */ | |
733 | if (c == '\n') | |
734 | read_rtx_lineno++; | |
735 | else if (c == '\\') | |
736 | { | |
a269d6c8 | 737 | read_escape (infile); |
1f3b37a3 | 738 | continue; |
0f40f9f7 ZW |
739 | } |
740 | else if (c == '"') | |
741 | break; | |
742 | ||
a269d6c8 | 743 | obstack_1grow (&string_obstack, c); |
0f40f9f7 ZW |
744 | } |
745 | ||
a269d6c8 RS |
746 | obstack_1grow (&string_obstack, 0); |
747 | return (char *) obstack_finish (&string_obstack); | |
0f40f9f7 ZW |
748 | } |
749 | ||
a269d6c8 RS |
750 | /* Read a braced string (a la Tcl) onto the string obstack. Caller |
751 | has scanned the leading brace. Note that unlike quoted strings, | |
0f40f9f7 ZW |
752 | the outermost braces _are_ included in the string constant. */ |
753 | static char * | |
a269d6c8 | 754 | read_braced_string (FILE *infile) |
0f40f9f7 ZW |
755 | { |
756 | int c; | |
757 | int brace_depth = 1; /* caller-processed */ | |
a3c18e4f | 758 | unsigned long starting_read_rtx_lineno = read_rtx_lineno; |
0f40f9f7 | 759 | |
a269d6c8 | 760 | obstack_1grow (&string_obstack, '{'); |
0f40f9f7 ZW |
761 | while (brace_depth) |
762 | { | |
763 | c = getc (infile); /* Read the string */ | |
a3c18e4f | 764 | |
0f40f9f7 ZW |
765 | if (c == '\n') |
766 | read_rtx_lineno++; | |
767 | else if (c == '{') | |
768 | brace_depth++; | |
769 | else if (c == '}') | |
770 | brace_depth--; | |
771 | else if (c == '\\') | |
772 | { | |
a269d6c8 | 773 | read_escape (infile); |
1f3b37a3 | 774 | continue; |
0f40f9f7 | 775 | } |
a3c18e4f NC |
776 | else if (c == EOF) |
777 | fatal_with_file_and_line | |
778 | (infile, "missing closing } for opening brace on line %lu", | |
0c20a65f | 779 | starting_read_rtx_lineno); |
0f40f9f7 | 780 | |
a269d6c8 | 781 | obstack_1grow (&string_obstack, c); |
0f40f9f7 | 782 | } |
a6a2274a | 783 | |
a269d6c8 RS |
784 | obstack_1grow (&string_obstack, 0); |
785 | return (char *) obstack_finish (&string_obstack); | |
0f40f9f7 ZW |
786 | } |
787 | ||
788 | /* Read some kind of string constant. This is the high-level routine | |
789 | used by read_rtx. It handles surrounding parentheses, leading star, | |
790 | and dispatch to the appropriate string constant reader. */ | |
791 | ||
792 | static char * | |
a269d6c8 | 793 | read_string (FILE *infile, int star_if_braced) |
0f40f9f7 ZW |
794 | { |
795 | char *stringbuf; | |
796 | int saw_paren = 0; | |
797 | int c; | |
798 | ||
799 | c = read_skip_spaces (infile); | |
800 | if (c == '(') | |
801 | { | |
802 | saw_paren = 1; | |
803 | c = read_skip_spaces (infile); | |
804 | } | |
805 | ||
806 | if (c == '"') | |
a269d6c8 | 807 | stringbuf = read_quoted_string (infile); |
0f40f9f7 ZW |
808 | else if (c == '{') |
809 | { | |
810 | if (star_if_braced) | |
a269d6c8 RS |
811 | obstack_1grow (&string_obstack, '*'); |
812 | stringbuf = read_braced_string (infile); | |
0f40f9f7 ZW |
813 | } |
814 | else | |
815 | fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c); | |
a6a2274a | 816 | |
0f40f9f7 ZW |
817 | if (saw_paren) |
818 | { | |
819 | c = read_skip_spaces (infile); | |
820 | if (c != ')') | |
821 | fatal_expected_char (infile, ')', c); | |
822 | } | |
823 | ||
824 | return stringbuf; | |
825 | } | |
826 | \f | |
827 | /* Provide a version of a function to read a long long if the system does | |
828 | not provide one. */ | |
829 | #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ) | |
0c20a65f | 830 | HOST_WIDE_INT atoll (const char *); |
825c5408 | 831 | |
0f40f9f7 | 832 | HOST_WIDE_INT |
0c20a65f | 833 | atoll (const char *p) |
0f40f9f7 ZW |
834 | { |
835 | int neg = 0; | |
836 | HOST_WIDE_INT tmp_wide; | |
837 | ||
8e2e89f7 | 838 | while (ISSPACE (*p)) |
0f40f9f7 ZW |
839 | p++; |
840 | if (*p == '-') | |
841 | neg = 1, p++; | |
842 | else if (*p == '+') | |
843 | p++; | |
844 | ||
845 | tmp_wide = 0; | |
8e2e89f7 | 846 | while (ISDIGIT (*p)) |
0f40f9f7 ZW |
847 | { |
848 | HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0'); | |
849 | if (new_wide < tmp_wide) | |
850 | { | |
851 | /* Return INT_MAX equiv on overflow. */ | |
f4f4d0f8 | 852 | tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1; |
0f40f9f7 ZW |
853 | break; |
854 | } | |
855 | tmp_wide = new_wide; | |
856 | p++; | |
857 | } | |
858 | ||
859 | if (neg) | |
860 | tmp_wide = -tmp_wide; | |
861 | return tmp_wide; | |
862 | } | |
863 | #endif | |
864 | ||
032e8348 RS |
865 | /* Given an object that starts with a char * name field, return a hash |
866 | code for its name. */ | |
fb7e6024 | 867 | static hashval_t |
0c20a65f | 868 | def_hash (const void *def) |
0f40f9f7 ZW |
869 | { |
870 | unsigned result, i; | |
032e8348 | 871 | const char *string = *(const char *const *) def; |
0f40f9f7 | 872 | |
032e8348 | 873 | for (result = i = 0; *string++ != '\0'; i++) |
0f40f9f7 ZW |
874 | result += ((unsigned char) *string << (i % CHAR_BIT)); |
875 | return result; | |
876 | } | |
877 | ||
032e8348 RS |
878 | /* Given two objects that start with char * name fields, return true if |
879 | they have the same name. */ | |
0f40f9f7 | 880 | static int |
0c20a65f | 881 | def_name_eq_p (const void *def1, const void *def2) |
0f40f9f7 | 882 | { |
032e8348 RS |
883 | return ! strcmp (*(const char *const *) def1, |
884 | *(const char *const *) def2); | |
0f40f9f7 ZW |
885 | } |
886 | ||
887 | /* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer suitable | |
888 | to read a name or number into. Process a define_constants directive, | |
889 | starting with the optional space after the "define_constants". */ | |
890 | static void | |
0c20a65f | 891 | read_constants (FILE *infile, char *tmp_char) |
0f40f9f7 ZW |
892 | { |
893 | int c; | |
894 | htab_t defs; | |
895 | ||
896 | c = read_skip_spaces (infile); | |
897 | if (c != '[') | |
898 | fatal_expected_char (infile, '[', c); | |
899 | defs = md_constants; | |
900 | if (! defs) | |
901 | defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0); | |
902 | /* Disable constant expansion during definition processing. */ | |
903 | md_constants = 0; | |
904 | while ( (c = read_skip_spaces (infile)) != ']') | |
905 | { | |
906 | struct md_constant *def; | |
907 | void **entry_ptr; | |
908 | ||
909 | if (c != '(') | |
910 | fatal_expected_char (infile, '(', c); | |
5d038c4c | 911 | def = XNEW (struct md_constant); |
0f40f9f7 ZW |
912 | def->name = tmp_char; |
913 | read_name (tmp_char, infile); | |
5d038c4c | 914 | entry_ptr = htab_find_slot (defs, def, INSERT); |
0f40f9f7 ZW |
915 | if (! *entry_ptr) |
916 | def->name = xstrdup (tmp_char); | |
917 | c = read_skip_spaces (infile); | |
918 | ungetc (c, infile); | |
919 | read_name (tmp_char, infile); | |
920 | if (! *entry_ptr) | |
921 | { | |
922 | def->value = xstrdup (tmp_char); | |
923 | *entry_ptr = def; | |
924 | } | |
925 | else | |
926 | { | |
28dab132 | 927 | def = (struct md_constant *) *entry_ptr; |
0f40f9f7 ZW |
928 | if (strcmp (def->value, tmp_char)) |
929 | fatal_with_file_and_line (infile, | |
930 | "redefinition of %s, was %s, now %s", | |
931 | def->name, def->value, tmp_char); | |
932 | } | |
933 | c = read_skip_spaces (infile); | |
934 | if (c != ')') | |
935 | fatal_expected_char (infile, ')', c); | |
936 | } | |
937 | md_constants = defs; | |
938 | c = read_skip_spaces (infile); | |
939 | if (c != ')') | |
940 | fatal_expected_char (infile, ')', c); | |
941 | } | |
942 | ||
943 | /* For every constant definition, call CALLBACK with two arguments: | |
944 | a pointer a pointer to the constant definition and INFO. | |
945 | Stops when CALLBACK returns zero. */ | |
946 | void | |
0c20a65f | 947 | traverse_md_constants (htab_trav callback, void *info) |
0f40f9f7 ZW |
948 | { |
949 | if (md_constants) | |
950 | htab_traverse (md_constants, callback, info); | |
951 | } | |
952 | ||
53c98b1f | 953 | static void |
0c20a65f | 954 | validate_const_int (FILE *infile, const char *string) |
53c98b1f DD |
955 | { |
956 | const char *cp; | |
957 | int valid = 1; | |
958 | ||
959 | cp = string; | |
8e2e89f7 | 960 | while (*cp && ISSPACE (*cp)) |
53c98b1f DD |
961 | cp++; |
962 | if (*cp == '-' || *cp == '+') | |
963 | cp++; | |
964 | if (*cp == 0) | |
965 | valid = 0; | |
966 | for (; *cp; cp++) | |
967 | if (! ISDIGIT (*cp)) | |
968 | valid = 0; | |
969 | if (!valid) | |
970 | fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string); | |
971 | } | |
972 | ||
032e8348 RS |
973 | /* Search GROUP for a mode or code called NAME and return its numerical |
974 | identifier. INFILE is the file that contained NAME. */ | |
975 | ||
976 | static int | |
977 | find_macro (struct macro_group *group, const char *name, FILE *infile) | |
978 | { | |
979 | struct mapping *m; | |
980 | ||
981 | m = (struct mapping *) htab_find (group->macros, &name); | |
982 | if (m != 0) | |
983 | return m->index + group->num_builtins; | |
984 | return group->find_builtin (name, infile); | |
985 | } | |
986 | ||
987 | /* Finish reading a declaration of the form: | |
988 | ||
989 | (define... <name> [<value1> ... <valuen>]) | |
990 | ||
991 | from INFILE, where each <valuei> is either a bare symbol name or a | |
992 | "(<name> <string>)" pair. The "(define..." part has already been read. | |
993 | ||
994 | Represent the declaration as a "mapping" structure; add it to TABLE | |
995 | (which belongs to GROUP) and return it. */ | |
996 | ||
997 | static struct mapping * | |
998 | read_mapping (struct macro_group *group, htab_t table, FILE *infile) | |
999 | { | |
1000 | char tmp_char[256]; | |
1001 | struct mapping *m; | |
1002 | struct map_value **end_ptr; | |
1003 | const char *string; | |
1004 | int number, c; | |
1005 | ||
1006 | /* Read the mapping name and create a structure for it. */ | |
1007 | read_name (tmp_char, infile); | |
1008 | m = add_mapping (group, table, tmp_char, infile); | |
1009 | ||
1010 | c = read_skip_spaces (infile); | |
1011 | if (c != '[') | |
1012 | fatal_expected_char (infile, '[', c); | |
1013 | ||
1014 | /* Read each value. */ | |
1015 | end_ptr = &m->values; | |
1016 | c = read_skip_spaces (infile); | |
1017 | do | |
1018 | { | |
1019 | if (c != '(') | |
1020 | { | |
1021 | /* A bare symbol name that is implicitly paired to an | |
1022 | empty string. */ | |
1023 | ungetc (c, infile); | |
1024 | read_name (tmp_char, infile); | |
1025 | string = ""; | |
1026 | } | |
1027 | else | |
1028 | { | |
1029 | /* A "(name string)" pair. */ | |
1030 | read_name (tmp_char, infile); | |
1031 | string = read_string (infile, false); | |
1032 | c = read_skip_spaces (infile); | |
1033 | if (c != ')') | |
1034 | fatal_expected_char (infile, ')', c); | |
1035 | } | |
1036 | number = group->find_builtin (tmp_char, infile); | |
1037 | end_ptr = add_map_value (end_ptr, number, string); | |
1038 | c = read_skip_spaces (infile); | |
1039 | } | |
1040 | while (c != ']'); | |
1041 | ||
1042 | c = read_skip_spaces (infile); | |
1043 | if (c != ')') | |
1044 | fatal_expected_char (infile, ')', c); | |
1045 | ||
1046 | return m; | |
1047 | } | |
1048 | ||
1049 | /* Check newly-created code macro MACRO to see whether every code has the | |
1050 | same format. Initialize the macro's entry in bellwether_codes. */ | |
1051 | ||
1052 | static void | |
1053 | check_code_macro (struct mapping *macro, FILE *infile) | |
1054 | { | |
1055 | struct map_value *v; | |
1056 | enum rtx_code bellwether; | |
1057 | ||
1058 | bellwether = macro->values->number; | |
1059 | for (v = macro->values->next; v != 0; v = v->next) | |
1060 | if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0) | |
1061 | fatal_with_file_and_line (infile, "code macro `%s' combines " | |
1062 | "different rtx formats", macro->name); | |
1063 | ||
1064 | bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes, | |
1065 | macro->index + 1); | |
1066 | bellwether_codes[macro->index] = bellwether; | |
1067 | } | |
1068 | ||
0f40f9f7 ZW |
1069 | /* Read an rtx in printed representation from INFILE |
1070 | and return an actual rtx in core constructed accordingly. | |
1071 | read_rtx is not used in the compiler proper, but rather in | |
1072 | the utilities gen*.c that construct C code from machine descriptions. */ | |
1073 | ||
1074 | rtx | |
0c20a65f | 1075 | read_rtx (FILE *infile) |
0f40f9f7 | 1076 | { |
032e8348 RS |
1077 | static rtx queue_head, queue_next; |
1078 | rtx return_rtx; | |
1079 | ||
1080 | /* Do one-time initialization. */ | |
1081 | if (queue_head == 0) | |
1082 | { | |
1083 | initialize_macros (); | |
1084 | obstack_init (&string_obstack); | |
1085 | queue_head = rtx_alloc (EXPR_LIST); | |
1086 | } | |
1087 | ||
1088 | if (queue_next == 0) | |
1089 | { | |
1090 | queue_next = queue_head; | |
1091 | ||
1092 | XEXP (queue_next, 0) = read_rtx_1 (infile); | |
1093 | XEXP (queue_next, 1) = 0; | |
1094 | ||
1095 | htab_traverse (modes.macros, apply_macro_traverse, queue_next); | |
1096 | htab_traverse (codes.macros, apply_macro_traverse, queue_next); | |
1097 | } | |
1098 | ||
1099 | return_rtx = XEXP (queue_next, 0); | |
1100 | queue_next = XEXP (queue_next, 1); | |
1101 | ||
1102 | return return_rtx; | |
1103 | } | |
1104 | ||
1105 | /* Subroutine of read_rtx that reads one construct from INFILE but | |
1106 | doesn't apply any macros. */ | |
1107 | ||
1108 | static rtx | |
1109 | read_rtx_1 (FILE *infile) | |
1110 | { | |
1111 | int i; | |
1112 | RTX_CODE real_code, bellwether_code; | |
b3694847 | 1113 | const char *format_ptr; |
0f40f9f7 ZW |
1114 | /* tmp_char is a buffer used for reading decimal integers |
1115 | and names of rtx types and machine modes. | |
1116 | Therefore, 256 must be enough. */ | |
1117 | char tmp_char[256]; | |
1118 | rtx return_rtx; | |
b3694847 | 1119 | int c; |
0f40f9f7 ZW |
1120 | int tmp_int; |
1121 | HOST_WIDE_INT tmp_wide; | |
1122 | ||
0f40f9f7 ZW |
1123 | /* Linked list structure for making RTXs: */ |
1124 | struct rtx_list | |
1125 | { | |
1126 | struct rtx_list *next; | |
1127 | rtx value; /* Value of this node. */ | |
1128 | }; | |
1129 | ||
032e8348 | 1130 | again: |
0f40f9f7 ZW |
1131 | c = read_skip_spaces (infile); /* Should be open paren. */ |
1132 | if (c != '(') | |
1133 | fatal_expected_char (infile, '(', c); | |
1134 | ||
1135 | read_name (tmp_char, infile); | |
032e8348 | 1136 | if (strcmp (tmp_char, "nil") == 0) |
0f40f9f7 | 1137 | { |
f822d252 | 1138 | /* (nil) stands for an expression that isn't there. */ |
032e8348 RS |
1139 | c = read_skip_spaces (infile); |
1140 | if (c != ')') | |
1141 | fatal_expected_char (infile, ')', c); | |
1142 | return 0; | |
1143 | } | |
1144 | if (strcmp (tmp_char, "define_constants") == 0) | |
1145 | { | |
1146 | read_constants (infile, tmp_char); | |
1147 | goto again; | |
1148 | } | |
1149 | if (strcmp (tmp_char, "define_mode_attr") == 0) | |
1150 | { | |
1151 | read_mapping (&modes, modes.attrs, infile); | |
1152 | goto again; | |
1153 | } | |
1154 | if (strcmp (tmp_char, "define_mode_macro") == 0) | |
1155 | { | |
1156 | read_mapping (&modes, modes.macros, infile); | |
1157 | goto again; | |
0f40f9f7 | 1158 | } |
032e8348 RS |
1159 | if (strcmp (tmp_char, "define_code_attr") == 0) |
1160 | { | |
1161 | read_mapping (&codes, codes.attrs, infile); | |
1162 | goto again; | |
1163 | } | |
1164 | if (strcmp (tmp_char, "define_code_macro") == 0) | |
1165 | { | |
1166 | check_code_macro (read_mapping (&codes, codes.macros, infile), infile); | |
1167 | goto again; | |
1168 | } | |
1169 | real_code = find_macro (&codes, tmp_char, infile); | |
1170 | bellwether_code = BELLWETHER_CODE (real_code); | |
0f40f9f7 ZW |
1171 | |
1172 | /* If we end up with an insn expression then we free this space below. */ | |
032e8348 RS |
1173 | return_rtx = rtx_alloc (bellwether_code); |
1174 | format_ptr = GET_RTX_FORMAT (bellwether_code); | |
1175 | PUT_CODE (return_rtx, real_code); | |
0f40f9f7 ZW |
1176 | |
1177 | /* If what follows is `: mode ', read it and | |
1178 | store the mode in the rtx. */ | |
1179 | ||
1180 | i = read_skip_spaces (infile); | |
1181 | if (i == ':') | |
1182 | { | |
1183 | read_name (tmp_char, infile); | |
032e8348 | 1184 | PUT_MODE (return_rtx, find_macro (&modes, tmp_char, infile)); |
0f40f9f7 ZW |
1185 | } |
1186 | else | |
1187 | ungetc (i, infile); | |
1188 | ||
ecce923e RS |
1189 | for (i = 0; format_ptr[i] != 0; i++) |
1190 | switch (format_ptr[i]) | |
0f40f9f7 ZW |
1191 | { |
1192 | /* 0 means a field for internal use only. | |
1193 | Don't expect it to be present in the input. */ | |
1194 | case '0': | |
1195 | break; | |
1196 | ||
1197 | case 'e': | |
1198 | case 'u': | |
032e8348 | 1199 | XEXP (return_rtx, i) = read_rtx_1 (infile); |
0f40f9f7 ZW |
1200 | break; |
1201 | ||
1202 | case 'V': | |
1203 | /* 'V' is an optional vector: if a closeparen follows, | |
1204 | just store NULL for this element. */ | |
1205 | c = read_skip_spaces (infile); | |
1206 | ungetc (c, infile); | |
1207 | if (c == ')') | |
1208 | { | |
1209 | XVEC (return_rtx, i) = 0; | |
1210 | break; | |
a6a2274a | 1211 | } |
0f40f9f7 ZW |
1212 | /* Now process the vector. */ |
1213 | ||
1214 | case 'E': | |
1215 | { | |
1216 | /* Obstack to store scratch vector in. */ | |
1217 | struct obstack vector_stack; | |
1218 | int list_counter = 0; | |
1219 | rtvec return_vec = NULL_RTVEC; | |
1220 | ||
1221 | c = read_skip_spaces (infile); | |
1222 | if (c != '[') | |
1223 | fatal_expected_char (infile, '[', c); | |
1224 | ||
a1105617 | 1225 | /* Add expressions to a list, while keeping a count. */ |
0f40f9f7 ZW |
1226 | obstack_init (&vector_stack); |
1227 | while ((c = read_skip_spaces (infile)) && c != ']') | |
1228 | { | |
1229 | ungetc (c, infile); | |
1230 | list_counter++; | |
032e8348 | 1231 | obstack_ptr_grow (&vector_stack, read_rtx_1 (infile)); |
0f40f9f7 ZW |
1232 | } |
1233 | if (list_counter > 0) | |
1234 | { | |
1235 | return_vec = rtvec_alloc (list_counter); | |
1236 | memcpy (&return_vec->elem[0], obstack_finish (&vector_stack), | |
1237 | list_counter * sizeof (rtx)); | |
1238 | } | |
1239 | XVEC (return_rtx, i) = return_vec; | |
1240 | obstack_free (&vector_stack, NULL); | |
1241 | /* close bracket gotten */ | |
1242 | } | |
1243 | break; | |
1244 | ||
1245 | case 'S': | |
1f3b37a3 | 1246 | case 'T': |
0f40f9f7 ZW |
1247 | case 's': |
1248 | { | |
1249 | char *stringbuf; | |
62d45923 RS |
1250 | int star_if_braced; |
1251 | ||
1252 | c = read_skip_spaces (infile); | |
1253 | ungetc (c, infile); | |
1254 | if (c == ')') | |
1255 | { | |
1256 | /* 'S' fields are optional and should be NULL if no string | |
1257 | was given. Also allow normal 's' and 'T' strings to be | |
1258 | omitted, treating them in the same way as empty strings. */ | |
ecce923e | 1259 | XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : ""); |
62d45923 RS |
1260 | break; |
1261 | } | |
0f40f9f7 ZW |
1262 | |
1263 | /* The output template slot of a DEFINE_INSN, | |
1264 | DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically | |
1265 | gets a star inserted as its first character, if it is | |
1266 | written with a brace block instead of a string constant. */ | |
ecce923e | 1267 | star_if_braced = (format_ptr[i] == 'T'); |
a6a2274a | 1268 | |
a269d6c8 | 1269 | stringbuf = read_string (infile, star_if_braced); |
0f40f9f7 ZW |
1270 | |
1271 | /* For insn patterns, we want to provide a default name | |
1272 | based on the file and line, like "*foo.md:12", if the | |
1273 | given name is blank. These are only for define_insn and | |
1274 | define_insn_and_split, to aid debugging. */ | |
1275 | if (*stringbuf == '\0' | |
1276 | && i == 0 | |
1277 | && (GET_CODE (return_rtx) == DEFINE_INSN | |
1278 | || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) | |
1279 | { | |
1280 | char line_name[20]; | |
1281 | const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx"); | |
1282 | const char *slash; | |
1283 | for (slash = fn; *slash; slash ++) | |
1284 | if (*slash == '/' || *slash == '\\' || *slash == ':') | |
1285 | fn = slash + 1; | |
a269d6c8 RS |
1286 | obstack_1grow (&string_obstack, '*'); |
1287 | obstack_grow (&string_obstack, fn, strlen (fn)); | |
0f40f9f7 | 1288 | sprintf (line_name, ":%d", read_rtx_lineno); |
a269d6c8 RS |
1289 | obstack_grow (&string_obstack, line_name, strlen (line_name)+1); |
1290 | stringbuf = (char *) obstack_finish (&string_obstack); | |
0f40f9f7 ZW |
1291 | } |
1292 | ||
1f3b37a3 ZW |
1293 | if (star_if_braced) |
1294 | XTMPL (return_rtx, i) = stringbuf; | |
1295 | else | |
1296 | XSTR (return_rtx, i) = stringbuf; | |
0f40f9f7 ZW |
1297 | } |
1298 | break; | |
1299 | ||
1300 | case 'w': | |
1301 | read_name (tmp_char, infile); | |
8e2e89f7 | 1302 | validate_const_int (infile, tmp_char); |
0f40f9f7 ZW |
1303 | #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT |
1304 | tmp_wide = atoi (tmp_char); | |
1305 | #else | |
1306 | #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG | |
1307 | tmp_wide = atol (tmp_char); | |
1308 | #else | |
1309 | /* Prefer atoll over atoq, since the former is in the ISO C99 standard. | |
1310 | But prefer not to use our hand-rolled function above either. */ | |
1311 | #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ) | |
1312 | tmp_wide = atoll (tmp_char); | |
1313 | #else | |
1314 | tmp_wide = atoq (tmp_char); | |
1315 | #endif | |
1316 | #endif | |
1317 | #endif | |
1318 | XWINT (return_rtx, i) = tmp_wide; | |
1319 | break; | |
1320 | ||
1321 | case 'i': | |
1322 | case 'n': | |
1323 | read_name (tmp_char, infile); | |
8e2e89f7 | 1324 | validate_const_int (infile, tmp_char); |
0f40f9f7 ZW |
1325 | tmp_int = atoi (tmp_char); |
1326 | XINT (return_rtx, i) = tmp_int; | |
1327 | break; | |
1328 | ||
1329 | default: | |
1330 | fprintf (stderr, | |
1331 | "switch format wrong in rtl.read_rtx(). format was: %c.\n", | |
ecce923e | 1332 | format_ptr[i]); |
0f40f9f7 ZW |
1333 | fprintf (stderr, "\tfile position: %ld\n", ftell (infile)); |
1334 | abort (); | |
1335 | } | |
1336 | ||
1337 | c = read_skip_spaces (infile); | |
1338 | if (c != ')') | |
1339 | fatal_expected_char (infile, ')', c); | |
1340 | ||
1341 | return return_rtx; | |
1342 | } |