Mercurial > hg > CbC > CbC_gcc
annotate gcc/read-rtl.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* RTL reader for GCC. |
145 | 2 Copyright (C) 1987-2020 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
111 | 20 /* This file is compiled twice: once for the generator programs |
21 once for the compiler. */ | |
22 #ifdef GENERATOR_FILE | |
0 | 23 #include "bconfig.h" |
111 | 24 #else |
25 #include "config.h" | |
26 #endif | |
0 | 27 |
28 /* Disable rtl checking; it conflicts with the iterator handling. */ | |
29 #undef ENABLE_RTL_CHECKING | |
30 | |
31 #include "system.h" | |
32 #include "coretypes.h" | |
33 #include "tm.h" | |
34 #include "rtl.h" | |
35 #include "obstack.h" | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
36 #include "read-md.h" |
0 | 37 #include "gensupport.h" |
38 | |
111 | 39 #ifndef GENERATOR_FILE |
40 #include "function.h" | |
41 #include "memmodel.h" | |
42 #include "emit-rtl.h" | |
43 #endif | |
44 | |
0 | 45 /* One element in a singly-linked list of (integer, string) pairs. */ |
46 struct map_value { | |
47 struct map_value *next; | |
48 int number; | |
49 const char *string; | |
50 }; | |
51 | |
52 /* Maps an iterator or attribute name to a list of (integer, string) pairs. | |
111 | 53 The integers are iterator values; the strings are either C conditions |
0 | 54 or attribute values. */ |
55 struct mapping { | |
56 /* The name of the iterator or attribute. */ | |
57 const char *name; | |
58 | |
59 /* The group (modes or codes) to which the iterator or attribute belongs. */ | |
60 struct iterator_group *group; | |
61 | |
62 /* The list of (integer, string) pairs. */ | |
63 struct map_value *values; | |
111 | 64 |
65 /* For iterators, records the current value of the iterator. */ | |
66 struct map_value *current_value; | |
0 | 67 }; |
68 | |
111 | 69 /* A structure for abstracting the common parts of iterators. */ |
0 | 70 struct iterator_group { |
111 | 71 /* Tables of "mapping" structures, one for attributes and one for |
72 iterators. */ | |
0 | 73 htab_t attrs, iterators; |
74 | |
131 | 75 /* The C++ type of the iterator, such as "machine_mode" for modes. */ |
76 const char *type; | |
77 | |
111 | 78 /* Treat the given string as the name of a standard mode, etc., and |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
79 return its integer value. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
80 int (*find_builtin) (const char *); |
0 | 81 |
111 | 82 /* Make the given rtx use the iterator value given by the third argument. |
83 If the iterator applies to operands, the second argument gives the | |
84 operand index, otherwise it is ignored. */ | |
85 void (*apply_iterator) (rtx, unsigned int, int); | |
131 | 86 |
87 /* Return the C token for the given standard mode, code, etc. */ | |
88 const char *(*get_c_token) (int); | |
0 | 89 }; |
90 | |
111 | 91 /* Records one use of an iterator. */ |
92 struct iterator_use { | |
93 /* The iterator itself. */ | |
94 struct mapping *iterator; | |
95 | |
96 /* The location of the use, as passed to the apply_iterator callback. | |
97 The index is the number of the operand that used the iterator | |
98 if applicable, otherwise it is ignored. */ | |
99 rtx x; | |
100 unsigned int index; | |
0 | 101 }; |
102 | |
111 | 103 /* Records one use of an attribute (the "<[iterator:]attribute>" syntax) |
104 in a non-string rtx field. */ | |
105 struct attribute_use { | |
106 /* The group that describes the use site. */ | |
107 struct iterator_group *group; | |
108 | |
145 | 109 /* The location at which the use occurs. */ |
110 file_location loc; | |
111 | |
111 | 112 /* The name of the attribute, possibly with an "iterator:" prefix. */ |
113 const char *value; | |
114 | |
115 /* The location of the use, as passed to GROUP's apply_iterator callback. | |
116 The index is the number of the operand that used the iterator | |
117 if applicable, otherwise it is ignored. */ | |
118 rtx x; | |
119 unsigned int index; | |
120 }; | |
0 | 121 |
111 | 122 /* This struct is used to link subst_attr named ATTR_NAME with |
123 corresponding define_subst named ITER_NAME. */ | |
124 struct subst_attr_to_iter_mapping | |
125 { | |
126 char *attr_name; | |
127 char *iter_name; | |
128 }; | |
129 | |
130 /* Hash-table to store links between subst-attributes and | |
131 define_substs. */ | |
132 htab_t subst_attr_to_iter_map = NULL; | |
133 /* This global stores name of subst-iterator which is currently being | |
134 processed. */ | |
135 const char *current_iterator_name; | |
136 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
137 static void validate_const_int (const char *); |
111 | 138 static void one_time_initialization (void); |
139 | |
140 /* Global singleton. */ | |
141 rtx_reader *rtx_reader_ptr = NULL; | |
0 | 142 |
143 /* The mode and code iterator structures. */ | |
111 | 144 static struct iterator_group modes, codes, ints, substs; |
145 | |
146 /* All iterators used in the current rtx. */ | |
147 static vec<mapping *> current_iterators; | |
0 | 148 |
111 | 149 /* The list of all iterator uses in the current rtx. */ |
150 static vec<iterator_use> iterator_uses; | |
151 | |
152 /* The list of all attribute uses in the current rtx. */ | |
153 static vec<attribute_use> attribute_uses; | |
0 | 154 |
155 /* Implementations of the iterator_group callbacks for modes. */ | |
156 | |
157 static int | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
158 find_mode (const char *name) |
0 | 159 { |
160 int i; | |
161 | |
162 for (i = 0; i < NUM_MACHINE_MODES; i++) | |
163 if (strcmp (GET_MODE_NAME (i), name) == 0) | |
164 return i; | |
165 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
166 fatal_with_file_and_line ("unknown mode `%s'", name); |
0 | 167 } |
168 | |
111 | 169 static void |
170 apply_mode_iterator (rtx x, unsigned int, int mode) | |
0 | 171 { |
111 | 172 PUT_MODE (x, (machine_mode) mode); |
0 | 173 } |
174 | |
131 | 175 static const char * |
176 get_mode_token (int mode) | |
177 { | |
178 return concat ("E_", GET_MODE_NAME (mode), "mode", NULL); | |
179 } | |
180 | |
111 | 181 /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn", |
182 "cnote" etc, and CODE_LABEL is special-cased as "clabel". */ | |
183 | |
184 struct compact_insn_name { | |
185 RTX_CODE code; | |
186 const char *name; | |
187 }; | |
188 | |
189 static const compact_insn_name compact_insn_names[] = { | |
190 { DEBUG_INSN, "cdebug_insn" }, | |
191 { INSN, "cinsn" }, | |
192 { JUMP_INSN, "cjump_insn" }, | |
193 { CALL_INSN, "ccall_insn" }, | |
194 { JUMP_TABLE_DATA, "cjump_table_data" }, | |
195 { BARRIER, "cbarrier" }, | |
196 { CODE_LABEL, "clabel" }, | |
197 { NOTE, "cnote" } | |
198 }; | |
0 | 199 |
145 | 200 /* Return the rtx code for NAME, or UNKNOWN if NAME isn't a valid rtx code. */ |
201 | |
202 static rtx_code | |
203 maybe_find_code (const char *name) | |
204 { | |
205 for (int i = 0; i < NUM_RTX_CODE; i++) | |
206 if (strcmp (GET_RTX_NAME (i), name) == 0) | |
207 return (rtx_code) i; | |
208 | |
209 for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++) | |
210 if (strcmp (compact_insn_names[i].name, name) == 0) | |
211 return compact_insn_names[i].code; | |
212 | |
213 return UNKNOWN; | |
214 } | |
215 | |
0 | 216 /* Implementations of the iterator_group callbacks for codes. */ |
217 | |
218 static int | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
219 find_code (const char *name) |
0 | 220 { |
145 | 221 rtx_code code = maybe_find_code (name); |
222 if (code == UNKNOWN) | |
223 fatal_with_file_and_line ("unknown rtx code `%s'", name); | |
224 return code; | |
0 | 225 } |
226 | |
227 static void | |
111 | 228 apply_code_iterator (rtx x, unsigned int, int code) |
0 | 229 { |
230 PUT_CODE (x, (enum rtx_code) code); | |
231 } | |
232 | |
131 | 233 static const char * |
234 get_code_token (int code) | |
235 { | |
236 char *name = xstrdup (GET_RTX_NAME (code)); | |
237 for (int i = 0; name[i]; ++i) | |
238 name[i] = TOUPPER (name[i]); | |
239 return name; | |
240 } | |
241 | |
111 | 242 /* Implementations of the iterator_group callbacks for ints. */ |
243 | |
244 /* Since GCC does not construct a table of valid constants, | |
245 we have to accept any int as valid. No cross-checking can | |
246 be done. */ | |
247 | |
248 static int | |
249 find_int (const char *name) | |
250 { | |
251 validate_const_int (name); | |
252 return atoi (name); | |
253 } | |
254 | |
255 static void | |
256 apply_int_iterator (rtx x, unsigned int index, int value) | |
257 { | |
131 | 258 if (GET_CODE (x) == SUBREG) |
259 SUBREG_BYTE (x) = value; | |
260 else | |
261 XINT (x, index) = value; | |
262 } | |
263 | |
264 static const char * | |
265 get_int_token (int value) | |
266 { | |
267 char buffer[HOST_BITS_PER_INT + 1]; | |
268 sprintf (buffer, "%d", value); | |
269 return xstrdup (buffer); | |
111 | 270 } |
271 | |
272 #ifdef GENERATOR_FILE | |
273 | |
274 /* This routine adds attribute or does nothing depending on VALUE. When | |
275 VALUE is 1, it does nothing - the first duplicate of original | |
276 template is kept untouched when it's subjected to a define_subst. | |
277 When VALUE isn't 1, the routine modifies RTL-template RT, adding | |
278 attribute, named exactly as define_subst, which later will be | |
279 applied. If such attribute has already been added, then no the | |
280 routine has no effect. */ | |
281 static void | |
282 apply_subst_iterator (rtx rt, unsigned int, int value) | |
283 { | |
284 rtx new_attr; | |
285 rtvec attrs_vec, new_attrs_vec; | |
286 int i; | |
145 | 287 /* define_split has no attributes. */ |
288 if (value == 1 || GET_CODE (rt) == DEFINE_SPLIT) | |
111 | 289 return; |
290 gcc_assert (GET_CODE (rt) == DEFINE_INSN | |
145 | 291 || GET_CODE (rt) == DEFINE_INSN_AND_SPLIT |
292 || GET_CODE (rt) == DEFINE_INSN_AND_REWRITE | |
111 | 293 || GET_CODE (rt) == DEFINE_EXPAND); |
294 | |
145 | 295 int attrs = (GET_CODE (rt) == DEFINE_INSN_AND_SPLIT ? 7 |
296 : GET_CODE (rt) == DEFINE_INSN_AND_REWRITE ? 6 : 4); | |
297 attrs_vec = XVEC (rt, attrs); | |
111 | 298 |
299 /* If we've already added attribute 'current_iterator_name', then we | |
300 have nothing to do now. */ | |
301 if (attrs_vec) | |
302 { | |
303 for (i = 0; i < GET_NUM_ELEM (attrs_vec); i++) | |
304 { | |
305 if (strcmp (XSTR (attrs_vec->elem[i], 0), current_iterator_name) == 0) | |
306 return; | |
307 } | |
308 } | |
309 | |
310 /* Add attribute with subst name - it serves as a mark for | |
311 define_subst which later would be applied to this pattern. */ | |
312 new_attr = rtx_alloc (SET_ATTR); | |
313 PUT_CODE (new_attr, SET_ATTR); | |
314 XSTR (new_attr, 0) = xstrdup (current_iterator_name); | |
315 XSTR (new_attr, 1) = xstrdup ("yes"); | |
316 | |
317 if (!attrs_vec) | |
318 { | |
319 new_attrs_vec = rtvec_alloc (1); | |
320 new_attrs_vec->elem[0] = new_attr; | |
321 } | |
322 else | |
323 { | |
324 new_attrs_vec = rtvec_alloc (GET_NUM_ELEM (attrs_vec) + 1); | |
325 memcpy (&new_attrs_vec->elem[0], &attrs_vec->elem[0], | |
326 GET_NUM_ELEM (attrs_vec) * sizeof (rtx)); | |
327 new_attrs_vec->elem[GET_NUM_ELEM (attrs_vec)] = new_attr; | |
328 } | |
145 | 329 XVEC (rt, attrs) = new_attrs_vec; |
111 | 330 } |
331 | |
332 /* Map subst-attribute ATTR to subst iterator ITER. */ | |
333 | |
334 static void | |
335 bind_subst_iter_and_attr (const char *iter, const char *attr) | |
336 { | |
337 struct subst_attr_to_iter_mapping *value; | |
338 void **slot; | |
339 if (!subst_attr_to_iter_map) | |
340 subst_attr_to_iter_map = | |
341 htab_create (1, leading_string_hash, leading_string_eq_p, 0); | |
342 value = XNEW (struct subst_attr_to_iter_mapping); | |
343 value->attr_name = xstrdup (attr); | |
344 value->iter_name = xstrdup (iter); | |
345 slot = htab_find_slot (subst_attr_to_iter_map, value, INSERT); | |
346 *slot = value; | |
347 } | |
348 | |
349 #endif /* #ifdef GENERATOR_FILE */ | |
350 | |
351 /* Return name of a subst-iterator, corresponding to subst-attribute ATTR. */ | |
352 | |
353 static char* | |
354 find_subst_iter_by_attr (const char *attr) | |
355 { | |
356 char *iter_name = NULL; | |
357 struct subst_attr_to_iter_mapping *value; | |
358 value = (struct subst_attr_to_iter_mapping*) | |
359 htab_find (subst_attr_to_iter_map, &attr); | |
360 if (value) | |
361 iter_name = value->iter_name; | |
362 return iter_name; | |
363 } | |
364 | |
365 /* Map attribute string P to its current value. Return null if the attribute | |
131 | 366 isn't known. If ITERATOR_OUT is nonnull, store the associated iterator |
145 | 367 there. Report any errors against location LOC. */ |
0 | 368 |
369 static struct map_value * | |
145 | 370 map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0) |
0 | 371 { |
372 const char *attr; | |
111 | 373 struct mapping *iterator; |
374 unsigned int i; | |
0 | 375 struct mapping *m; |
376 struct map_value *v; | |
111 | 377 int iterator_name_len; |
145 | 378 struct map_value *res = NULL; |
379 struct mapping *prev = NULL; | |
0 | 380 |
111 | 381 /* Peel off any "iterator:" prefix. Set ATTR to the start of the |
382 attribute name. */ | |
0 | 383 attr = strchr (p, ':'); |
384 if (attr == 0) | |
111 | 385 { |
386 iterator_name_len = -1; | |
387 attr = p; | |
388 } | |
0 | 389 else |
390 { | |
111 | 391 iterator_name_len = attr - p; |
0 | 392 attr++; |
393 } | |
394 | |
111 | 395 FOR_EACH_VEC_ELT (current_iterators, i, iterator) |
396 { | |
397 /* If an iterator name was specified, check that it matches. */ | |
398 if (iterator_name_len >= 0 | |
399 && (strncmp (p, iterator->name, iterator_name_len) != 0 | |
400 || iterator->name[iterator_name_len] != 0)) | |
401 continue; | |
0 | 402 |
111 | 403 /* Find the attribute specification. */ |
404 m = (struct mapping *) htab_find (iterator->group->attrs, &attr); | |
405 if (m) | |
406 { | |
407 /* In contrast to code/mode/int iterators, attributes of subst | |
408 iterators are linked to one specific subst-iterator. So, if | |
409 we are dealing with subst-iterator, we should check if it's | |
410 the one which linked with the given attribute. */ | |
411 if (iterator->group == &substs) | |
412 { | |
413 char *iter_name = find_subst_iter_by_attr (attr); | |
414 if (strcmp (iter_name, iterator->name) != 0) | |
415 continue; | |
416 } | |
417 /* Find the attribute value associated with the current | |
418 iterator value. */ | |
419 for (v = m->values; v; v = v->next) | |
420 if (v->number == iterator->current_value->number) | |
131 | 421 { |
145 | 422 if (res && strcmp (v->string, res->string) != 0) |
423 { | |
424 error_at (loc, "ambiguous attribute '%s'; could be" | |
425 " '%s' (via '%s:%s') or '%s' (via '%s:%s')", | |
426 attr, res->string, prev->name, attr, | |
427 v->string, iterator->name, attr); | |
428 return v; | |
429 } | |
131 | 430 if (iterator_out) |
431 *iterator_out = iterator; | |
145 | 432 prev = iterator; |
433 res = v; | |
131 | 434 } |
111 | 435 } |
436 } | |
145 | 437 return res; |
0 | 438 } |
439 | |
111 | 440 /* Apply the current iterator values to STRING. Return the new string |
441 if any changes were needed, otherwise return STRING itself. */ | |
0 | 442 |
111 | 443 const char * |
444 md_reader::apply_iterator_to_string (const char *string) | |
0 | 445 { |
446 char *base, *copy, *p, *start, *end; | |
447 struct map_value *v; | |
448 | |
145 | 449 if (string == 0 || string[0] == 0) |
0 | 450 return string; |
451 | |
145 | 452 file_location loc = get_md_ptr_loc (string)->loc; |
0 | 453 base = p = copy = ASTRDUP (string); |
454 while ((start = strchr (p, '<')) && (end = strchr (start, '>'))) | |
455 { | |
456 p = start + 1; | |
457 | |
458 *end = 0; | |
145 | 459 v = map_attr_string (loc, p); |
0 | 460 *end = '>'; |
461 if (v == 0) | |
462 continue; | |
463 | |
464 /* Add everything between the last copied byte and the '<', | |
465 then add in the attribute value. */ | |
111 | 466 obstack_grow (&m_string_obstack, base, start - base); |
467 obstack_grow (&m_string_obstack, v->string, strlen (v->string)); | |
0 | 468 base = end + 1; |
469 } | |
470 if (base != copy) | |
471 { | |
111 | 472 obstack_grow (&m_string_obstack, base, strlen (base) + 1); |
473 copy = XOBFINISH (&m_string_obstack, char *); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
474 copy_md_ptr_loc (copy, string); |
0 | 475 return copy; |
476 } | |
477 return string; | |
478 } | |
479 | |
111 | 480 /* Return a deep copy of X, substituting the current iterator |
481 values into any strings. */ | |
0 | 482 |
111 | 483 rtx |
484 md_reader::copy_rtx_for_iterators (rtx original) | |
0 | 485 { |
111 | 486 const char *format_ptr, *p; |
0 | 487 int i, j; |
488 rtx x; | |
489 | |
490 if (original == 0) | |
491 return original; | |
492 | |
493 /* Create a shallow copy of ORIGINAL. */ | |
111 | 494 x = rtx_alloc (GET_CODE (original)); |
495 memcpy (x, original, RTX_CODE_SIZE (GET_CODE (original))); | |
0 | 496 |
497 /* Change each string and recursively change each rtx. */ | |
111 | 498 format_ptr = GET_RTX_FORMAT (GET_CODE (original)); |
0 | 499 for (i = 0; format_ptr[i] != 0; i++) |
500 switch (format_ptr[i]) | |
501 { | |
502 case 'T': | |
111 | 503 while (XTMPL (x, i) != (p = apply_iterator_to_string (XTMPL (x, i)))) |
504 XTMPL (x, i) = p; | |
0 | 505 break; |
506 | |
507 case 'S': | |
508 case 's': | |
111 | 509 while (XSTR (x, i) != (p = apply_iterator_to_string (XSTR (x, i)))) |
510 XSTR (x, i) = p; | |
0 | 511 break; |
512 | |
513 case 'e': | |
111 | 514 XEXP (x, i) = copy_rtx_for_iterators (XEXP (x, i)); |
0 | 515 break; |
516 | |
517 case 'V': | |
518 case 'E': | |
519 if (XVEC (original, i)) | |
520 { | |
521 XVEC (x, i) = rtvec_alloc (XVECLEN (original, i)); | |
522 for (j = 0; j < XVECLEN (x, i); j++) | |
111 | 523 XVECEXP (x, i, j) |
524 = copy_rtx_for_iterators (XVECEXP (original, i, j)); | |
0 | 525 } |
526 break; | |
527 | |
528 default: | |
529 break; | |
530 } | |
531 return x; | |
532 } | |
533 | |
111 | 534 #ifdef GENERATOR_FILE |
0 | 535 |
536 /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL | |
537 has the form "&& ..." (as used in define_insn_and_splits), assume that | |
538 EXTRA is already satisfied. Empty strings are treated like "true". */ | |
539 | |
540 static const char * | |
541 add_condition_to_string (const char *original, const char *extra) | |
542 { | |
543 if (original != 0 && original[0] == '&' && original[1] == '&') | |
544 return original; | |
111 | 545 return rtx_reader_ptr->join_c_conditions (original, extra); |
0 | 546 } |
547 | |
548 /* Like add_condition, but applied to all conditions in rtx X. */ | |
549 | |
550 static void | |
551 add_condition_to_rtx (rtx x, const char *extra) | |
552 { | |
553 switch (GET_CODE (x)) | |
554 { | |
555 case DEFINE_INSN: | |
556 case DEFINE_EXPAND: | |
111 | 557 case DEFINE_SUBST: |
0 | 558 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); |
559 break; | |
560 | |
561 case DEFINE_SPLIT: | |
562 case DEFINE_PEEPHOLE: | |
563 case DEFINE_PEEPHOLE2: | |
564 case DEFINE_COND_EXEC: | |
565 XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra); | |
566 break; | |
567 | |
568 case DEFINE_INSN_AND_SPLIT: | |
145 | 569 case DEFINE_INSN_AND_REWRITE: |
0 | 570 XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra); |
571 XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra); | |
572 break; | |
573 | |
574 default: | |
575 break; | |
576 } | |
577 } | |
578 | |
111 | 579 /* Apply the current iterator values to all attribute_uses. */ |
580 | |
581 static void | |
582 apply_attribute_uses (void) | |
583 { | |
584 struct map_value *v; | |
585 attribute_use *ause; | |
586 unsigned int i; | |
587 | |
588 FOR_EACH_VEC_ELT (attribute_uses, i, ause) | |
589 { | |
145 | 590 v = map_attr_string (ause->loc, ause->value); |
111 | 591 if (!v) |
592 fatal_with_file_and_line ("unknown iterator value `%s'", ause->value); | |
593 ause->group->apply_iterator (ause->x, ause->index, | |
594 ause->group->find_builtin (v->string)); | |
595 } | |
596 } | |
597 | |
598 /* A htab_traverse callback for iterators. Add all used iterators | |
599 to current_iterators. */ | |
0 | 600 |
601 static int | |
111 | 602 add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED) |
0 | 603 { |
604 struct mapping *iterator; | |
605 | |
606 iterator = (struct mapping *) *slot; | |
111 | 607 if (iterator->current_value) |
608 current_iterators.safe_push (iterator); | |
0 | 609 return 1; |
610 } | |
611 | |
131 | 612 /* Return a hash value for overloaded_name UNCAST_ONAME. There shouldn't |
613 be many instances of two overloaded_names having the same name but | |
614 different arguments, so hashing on the name should be good enough in | |
615 practice. */ | |
616 | |
617 static hashval_t | |
618 overloaded_name_hash (const void *uncast_oname) | |
619 { | |
620 const overloaded_name *oname = (const overloaded_name *) uncast_oname; | |
621 return htab_hash_string (oname->name); | |
622 } | |
623 | |
624 /* Return true if two overloaded_names are similar enough to share | |
625 the same generated functions. */ | |
626 | |
627 static int | |
628 overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2) | |
629 { | |
630 const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1; | |
631 const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2; | |
632 if (strcmp (oname1->name, oname2->name) != 0 | |
633 || oname1->arg_types.length () != oname2->arg_types.length ()) | |
634 return 0; | |
635 | |
636 for (unsigned int i = 0; i < oname1->arg_types.length (); ++i) | |
637 if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0) | |
638 return 0; | |
639 | |
640 return 1; | |
641 } | |
642 | |
643 /* Return true if X has an instruction name in XSTR (X, 0). */ | |
644 | |
645 static bool | |
646 named_rtx_p (rtx x) | |
647 { | |
648 switch (GET_CODE (x)) | |
649 { | |
650 case DEFINE_EXPAND: | |
651 case DEFINE_INSN: | |
652 case DEFINE_INSN_AND_SPLIT: | |
145 | 653 case DEFINE_INSN_AND_REWRITE: |
131 | 654 return true; |
655 | |
656 default: | |
657 return false; | |
658 } | |
659 } | |
660 | |
661 /* Check whether ORIGINAL is a named pattern whose name starts with '@'. | |
662 If so, return the associated overloaded_name and add the iterator for | |
663 each argument to ITERATORS. Return null otherwise. */ | |
664 | |
665 overloaded_name * | |
666 md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators) | |
667 { | |
668 /* Check for the leading '@'. */ | |
669 if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@') | |
670 return NULL; | |
671 | |
672 /* Remove the '@', so that no other code needs to worry about it. */ | |
673 const char *name = XSTR (original, 0); | |
145 | 674 file_location loc = get_md_ptr_loc (name)->loc; |
131 | 675 copy_md_ptr_loc (name + 1, name); |
676 name += 1; | |
677 XSTR (original, 0) = name; | |
678 | |
679 /* Build a copy of the name without the '<...>' attribute strings. | |
680 Add the iterator associated with each such attribute string to ITERATORS | |
681 and add an associated argument to TMP_ONAME. */ | |
682 char *copy = ASTRDUP (name); | |
683 char *base = copy, *start, *end; | |
684 overloaded_name tmp_oname; | |
685 tmp_oname.arg_types.create (current_iterators.length ()); | |
686 bool pending_underscore_p = false; | |
687 while ((start = strchr (base, '<')) && (end = strchr (start, '>'))) | |
688 { | |
689 *end = 0; | |
690 mapping *iterator; | |
145 | 691 if (!map_attr_string (loc, start + 1, &iterator)) |
131 | 692 fatal_with_file_and_line ("unknown iterator `%s'", start + 1); |
693 *end = '>'; | |
694 | |
695 /* Remove a trailing underscore, so that we don't end a name | |
696 with "_" or turn "_<...>_" into "__". */ | |
697 if (start != base && start[-1] == '_') | |
698 { | |
699 start -= 1; | |
700 pending_underscore_p = true; | |
701 } | |
702 | |
703 /* Add the text between either the last '>' or the start of | |
704 the string and this '<'. */ | |
705 obstack_grow (&m_string_obstack, base, start - base); | |
706 base = end + 1; | |
707 | |
708 /* If there's a character we need to keep after the '>', check | |
709 whether we should prefix it with a previously-dropped '_'. */ | |
710 if (base[0] != 0 && base[0] != '<') | |
711 { | |
712 if (pending_underscore_p && base[0] != '_') | |
713 obstack_1grow (&m_string_obstack, '_'); | |
714 pending_underscore_p = false; | |
715 } | |
716 | |
717 /* Record an argument for ITERATOR. */ | |
718 iterators->safe_push (iterator); | |
719 tmp_oname.arg_types.safe_push (iterator->group->type); | |
720 } | |
721 if (base == copy) | |
722 fatal_with_file_and_line ("no iterator attributes in name `%s'", name); | |
723 | |
724 size_t length = obstack_object_size (&m_string_obstack); | |
725 if (length == 0) | |
726 fatal_with_file_and_line ("`%s' only contains iterator attributes", name); | |
727 | |
728 /* Get the completed name. */ | |
729 obstack_grow (&m_string_obstack, base, strlen (base) + 1); | |
730 char *new_name = XOBFINISH (&m_string_obstack, char *); | |
731 tmp_oname.name = new_name; | |
732 | |
733 if (!m_overloads_htab) | |
734 m_overloads_htab = htab_create (31, overloaded_name_hash, | |
735 overloaded_name_eq_p, NULL); | |
736 | |
737 /* See whether another pattern had the same overload name and list | |
738 of argument types. Create a new permanent one if not. */ | |
739 void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT); | |
740 overloaded_name *oname = (overloaded_name *) *slot; | |
741 if (!oname) | |
742 { | |
743 *slot = oname = new overloaded_name; | |
744 oname->name = tmp_oname.name; | |
745 oname->arg_types = tmp_oname.arg_types; | |
746 oname->next = NULL; | |
747 oname->first_instance = NULL; | |
748 oname->next_instance_ptr = &oname->first_instance; | |
749 | |
750 *m_next_overload_ptr = oname; | |
751 m_next_overload_ptr = &oname->next; | |
752 } | |
753 else | |
754 { | |
755 obstack_free (&m_string_obstack, new_name); | |
756 tmp_oname.arg_types.release (); | |
757 } | |
758 | |
759 return oname; | |
760 } | |
761 | |
762 /* Add an instance of ONAME for instruction pattern X. ITERATORS[I] | |
763 gives the iterator associated with argument I of ONAME. */ | |
764 | |
765 static void | |
766 add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x) | |
767 { | |
768 /* Create the instance. */ | |
769 overloaded_instance *instance = new overloaded_instance; | |
770 instance->next = NULL; | |
771 instance->arg_values.create (oname->arg_types.length ()); | |
772 for (unsigned int i = 0; i < iterators.length (); ++i) | |
773 { | |
774 int value = iterators[i]->current_value->number; | |
775 const char *name = iterators[i]->group->get_c_token (value); | |
776 instance->arg_values.quick_push (name); | |
777 } | |
778 instance->name = XSTR (x, 0); | |
779 instance->insn = x; | |
780 | |
781 /* Chain it onto the end of ONAME's list. */ | |
782 *oname->next_instance_ptr = instance; | |
783 oname->next_instance_ptr = &instance->next; | |
784 } | |
785 | |
111 | 786 /* Expand all iterators in the current rtx, which is given as ORIGINAL. |
787 Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE. */ | |
788 | |
789 static void | |
790 apply_iterators (rtx original, vec<rtx> *queue) | |
791 { | |
792 unsigned int i; | |
793 const char *condition; | |
794 iterator_use *iuse; | |
795 struct mapping *iterator; | |
796 struct map_value *v; | |
797 rtx x; | |
798 | |
799 if (iterator_uses.is_empty ()) | |
800 { | |
801 /* Raise an error if any attributes were used. */ | |
802 apply_attribute_uses (); | |
131 | 803 |
804 if (named_rtx_p (original) && XSTR (original, 0)[0] == '@') | |
805 fatal_with_file_and_line ("'@' used without iterators"); | |
806 | |
111 | 807 queue->safe_push (original); |
808 return; | |
809 } | |
810 | |
811 /* Clear out the iterators from the previous run. */ | |
812 FOR_EACH_VEC_ELT (current_iterators, i, iterator) | |
813 iterator->current_value = NULL; | |
814 current_iterators.truncate (0); | |
815 | |
816 /* Mark the iterators that we need this time. */ | |
817 FOR_EACH_VEC_ELT (iterator_uses, i, iuse) | |
818 iuse->iterator->current_value = iuse->iterator->values; | |
819 | |
820 /* Get the list of iterators that are in use, preserving the | |
821 definition order within each group. */ | |
822 htab_traverse (modes.iterators, add_current_iterators, NULL); | |
823 htab_traverse (codes.iterators, add_current_iterators, NULL); | |
824 htab_traverse (ints.iterators, add_current_iterators, NULL); | |
825 htab_traverse (substs.iterators, add_current_iterators, NULL); | |
826 gcc_assert (!current_iterators.is_empty ()); | |
827 | |
131 | 828 /* Check whether this is a '@' overloaded pattern. */ |
829 auto_vec<mapping *, 16> iterators; | |
830 overloaded_name *oname | |
831 = rtx_reader_ptr->handle_overloaded_name (original, &iterators); | |
832 | |
111 | 833 for (;;) |
834 { | |
835 /* Apply the current iterator values. Accumulate a condition to | |
836 say when the resulting rtx can be used. */ | |
837 condition = ""; | |
838 FOR_EACH_VEC_ELT (iterator_uses, i, iuse) | |
839 { | |
840 if (iuse->iterator->group == &substs) | |
841 continue; | |
842 v = iuse->iterator->current_value; | |
843 iuse->iterator->group->apply_iterator (iuse->x, iuse->index, | |
844 v->number); | |
845 condition = rtx_reader_ptr->join_c_conditions (condition, v->string); | |
846 } | |
847 apply_attribute_uses (); | |
848 x = rtx_reader_ptr->copy_rtx_for_iterators (original); | |
849 add_condition_to_rtx (x, condition); | |
850 | |
851 /* We apply subst iterator after RTL-template is copied, as during | |
852 subst-iterator processing, we could add an attribute to the | |
853 RTL-template, and we don't want to do it in the original one. */ | |
854 FOR_EACH_VEC_ELT (iterator_uses, i, iuse) | |
855 { | |
856 v = iuse->iterator->current_value; | |
857 if (iuse->iterator->group == &substs) | |
858 { | |
859 iuse->x = x; | |
860 iuse->index = 0; | |
861 current_iterator_name = iuse->iterator->name; | |
862 iuse->iterator->group->apply_iterator (iuse->x, iuse->index, | |
863 v->number); | |
864 } | |
865 } | |
131 | 866 |
867 if (oname) | |
868 add_overload_instance (oname, iterators, x); | |
869 | |
111 | 870 /* Add the new rtx to the end of the queue. */ |
871 queue->safe_push (x); | |
872 | |
873 /* Lexicographically increment the iterator value sequence. | |
874 That is, cycle through iterator values, starting from the right, | |
875 and stopping when one of them doesn't wrap around. */ | |
876 i = current_iterators.length (); | |
877 for (;;) | |
878 { | |
879 if (i == 0) | |
880 return; | |
881 i--; | |
882 iterator = current_iterators[i]; | |
883 iterator->current_value = iterator->current_value->next; | |
884 if (iterator->current_value) | |
885 break; | |
886 iterator->current_value = iterator->values; | |
887 } | |
888 } | |
889 } | |
890 #endif /* #ifdef GENERATOR_FILE */ | |
891 | |
0 | 892 /* Add a new "mapping" structure to hashtable TABLE. NAME is the name |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
893 of the mapping and GROUP is the group to which it belongs. */ |
0 | 894 |
895 static struct mapping * | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
896 add_mapping (struct iterator_group *group, htab_t table, const char *name) |
0 | 897 { |
898 struct mapping *m; | |
899 void **slot; | |
900 | |
901 m = XNEW (struct mapping); | |
902 m->name = xstrdup (name); | |
903 m->group = group; | |
904 m->values = 0; | |
111 | 905 m->current_value = NULL; |
0 | 906 |
907 slot = htab_find_slot (table, m, INSERT); | |
908 if (*slot != 0) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
909 fatal_with_file_and_line ("`%s' already defined", name); |
0 | 910 |
911 *slot = m; | |
912 return m; | |
913 } | |
914 | |
915 /* Add the pair (NUMBER, STRING) to a list of map_value structures. | |
916 END_PTR points to the current null terminator for the list; return | |
917 a pointer the new null terminator. */ | |
918 | |
919 static struct map_value ** | |
920 add_map_value (struct map_value **end_ptr, int number, const char *string) | |
921 { | |
922 struct map_value *value; | |
923 | |
924 value = XNEW (struct map_value); | |
925 value->next = 0; | |
926 value->number = number; | |
927 value->string = string; | |
928 | |
929 *end_ptr = value; | |
930 return &value->next; | |
931 } | |
932 | |
933 /* Do one-time initialization of the mode and code attributes. */ | |
934 | |
935 static void | |
936 initialize_iterators (void) | |
937 { | |
938 struct mapping *lower, *upper; | |
939 struct map_value **lower_ptr, **upper_ptr; | |
940 char *copy, *p; | |
941 int i; | |
942 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
943 modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
944 modes.iterators = htab_create (13, leading_string_hash, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
945 leading_string_eq_p, 0); |
131 | 946 modes.type = "machine_mode"; |
0 | 947 modes.find_builtin = find_mode; |
948 modes.apply_iterator = apply_mode_iterator; | |
131 | 949 modes.get_c_token = get_mode_token; |
0 | 950 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
951 codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
952 codes.iterators = htab_create (13, leading_string_hash, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
953 leading_string_eq_p, 0); |
131 | 954 codes.type = "rtx_code"; |
0 | 955 codes.find_builtin = find_code; |
956 codes.apply_iterator = apply_code_iterator; | |
131 | 957 codes.get_c_token = get_code_token; |
0 | 958 |
111 | 959 ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); |
960 ints.iterators = htab_create (13, leading_string_hash, | |
961 leading_string_eq_p, 0); | |
131 | 962 ints.type = "int"; |
111 | 963 ints.find_builtin = find_int; |
964 ints.apply_iterator = apply_int_iterator; | |
131 | 965 ints.get_c_token = get_int_token; |
111 | 966 |
967 substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); | |
968 substs.iterators = htab_create (13, leading_string_hash, | |
969 leading_string_eq_p, 0); | |
131 | 970 substs.type = "int"; |
111 | 971 substs.find_builtin = find_int; /* We don't use it, anyway. */ |
972 #ifdef GENERATOR_FILE | |
973 substs.apply_iterator = apply_subst_iterator; | |
974 #endif | |
131 | 975 substs.get_c_token = get_int_token; |
111 | 976 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
977 lower = add_mapping (&modes, modes.attrs, "mode"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
978 upper = add_mapping (&modes, modes.attrs, "MODE"); |
0 | 979 lower_ptr = &lower->values; |
980 upper_ptr = &upper->values; | |
981 for (i = 0; i < MAX_MACHINE_MODE; i++) | |
982 { | |
983 copy = xstrdup (GET_MODE_NAME (i)); | |
984 for (p = copy; *p != 0; p++) | |
985 *p = TOLOWER (*p); | |
986 | |
987 upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i)); | |
988 lower_ptr = add_map_value (lower_ptr, i, copy); | |
989 } | |
990 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
991 lower = add_mapping (&codes, codes.attrs, "code"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
992 upper = add_mapping (&codes, codes.attrs, "CODE"); |
0 | 993 lower_ptr = &lower->values; |
994 upper_ptr = &upper->values; | |
995 for (i = 0; i < NUM_RTX_CODE; i++) | |
996 { | |
997 copy = xstrdup (GET_RTX_NAME (i)); | |
998 for (p = copy; *p != 0; p++) | |
999 *p = TOUPPER (*p); | |
1000 | |
1001 lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i)); | |
1002 upper_ptr = add_map_value (upper_ptr, i, copy); | |
1003 } | |
1004 } | |
1005 | |
1006 /* Provide a version of a function to read a long long if the system does | |
1007 not provide one. */ | |
111 | 1008 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !HAVE_DECL_ATOLL && !defined(HAVE_ATOQ) |
0 | 1009 HOST_WIDE_INT atoll (const char *); |
1010 | |
1011 HOST_WIDE_INT | |
1012 atoll (const char *p) | |
1013 { | |
1014 int neg = 0; | |
1015 HOST_WIDE_INT tmp_wide; | |
1016 | |
1017 while (ISSPACE (*p)) | |
1018 p++; | |
1019 if (*p == '-') | |
1020 neg = 1, p++; | |
1021 else if (*p == '+') | |
1022 p++; | |
1023 | |
1024 tmp_wide = 0; | |
1025 while (ISDIGIT (*p)) | |
1026 { | |
1027 HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0'); | |
1028 if (new_wide < tmp_wide) | |
1029 { | |
1030 /* Return INT_MAX equiv on overflow. */ | |
111 | 1031 tmp_wide = HOST_WIDE_INT_M1U >> 1; |
0 | 1032 break; |
1033 } | |
1034 tmp_wide = new_wide; | |
1035 p++; | |
1036 } | |
1037 | |
1038 if (neg) | |
1039 tmp_wide = -tmp_wide; | |
1040 return tmp_wide; | |
1041 } | |
1042 #endif | |
1043 | |
111 | 1044 |
1045 #ifdef GENERATOR_FILE | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1046 /* Process a define_conditions directive, starting with the optional |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1047 space after the "define_conditions". The directive looks like this: |
0 | 1048 |
1049 (define_conditions [ | |
1050 (number "string") | |
1051 (number "string") | |
1052 ... | |
1053 ]) | |
1054 | |
1055 It's not intended to appear in machine descriptions. It is | |
1056 generated by (the program generated by) genconditions.c, and | |
1057 slipped in at the beginning of the sequence of MD files read by | |
1058 most of the other generators. */ | |
111 | 1059 void |
1060 md_reader::read_conditions () | |
0 | 1061 { |
1062 int c; | |
1063 | |
111 | 1064 require_char_ws ('['); |
0 | 1065 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1066 while ( (c = read_skip_spaces ()) != ']') |
0 | 1067 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1068 struct md_name name; |
0 | 1069 char *expr; |
1070 int value; | |
1071 | |
1072 if (c != '(') | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1073 fatal_expected_char ('(', c); |
0 | 1074 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1075 read_name (&name); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1076 validate_const_int (name.string); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1077 value = atoi (name.string); |
0 | 1078 |
111 | 1079 require_char_ws ('"'); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1080 expr = read_quoted_string (); |
0 | 1081 |
111 | 1082 require_char_ws (')'); |
0 | 1083 |
1084 add_c_test (expr, value); | |
1085 } | |
1086 } | |
111 | 1087 #endif /* #ifdef GENERATOR_FILE */ |
0 | 1088 |
1089 static void | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1090 validate_const_int (const char *string) |
0 | 1091 { |
1092 const char *cp; | |
1093 int valid = 1; | |
1094 | |
1095 cp = string; | |
1096 while (*cp && ISSPACE (*cp)) | |
1097 cp++; | |
1098 if (*cp == '-' || *cp == '+') | |
1099 cp++; | |
1100 if (*cp == 0) | |
1101 valid = 0; | |
1102 for (; *cp; cp++) | |
1103 if (! ISDIGIT (*cp)) | |
111 | 1104 { |
1105 valid = 0; | |
1106 break; | |
1107 } | |
0 | 1108 if (!valid) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1109 fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string); |
0 | 1110 } |
1111 | |
111 | 1112 static void |
1113 validate_const_wide_int (const char *string) | |
1114 { | |
1115 const char *cp; | |
1116 int valid = 1; | |
1117 | |
1118 cp = string; | |
1119 while (*cp && ISSPACE (*cp)) | |
1120 cp++; | |
1121 /* Skip the leading 0x. */ | |
1122 if (cp[0] == '0' || cp[1] == 'x') | |
1123 cp += 2; | |
1124 else | |
1125 valid = 0; | |
1126 if (*cp == 0) | |
1127 valid = 0; | |
1128 for (; *cp; cp++) | |
1129 if (! ISXDIGIT (*cp)) | |
1130 valid = 0; | |
1131 if (!valid) | |
1132 fatal_with_file_and_line ("invalid hex constant \"%s\"\n", string); | |
1133 } | |
1134 | |
1135 /* Record that X uses iterator ITERATOR. If the use is in an operand | |
1136 of X, INDEX is the index of that operand, otherwise it is ignored. */ | |
0 | 1137 |
111 | 1138 static void |
1139 record_iterator_use (struct mapping *iterator, rtx x, unsigned int index) | |
1140 { | |
1141 struct iterator_use iuse = {iterator, x, index}; | |
1142 iterator_uses.safe_push (iuse); | |
1143 } | |
1144 | |
145 | 1145 /* Record that X uses attribute VALUE at location LOC, where VALUE must |
1146 match a built-in value from group GROUP. If the use is in an operand | |
1147 of X, INDEX is the index of that operand, otherwise it is ignored. */ | |
111 | 1148 |
1149 static void | |
145 | 1150 record_attribute_use (struct iterator_group *group, file_location loc, rtx x, |
111 | 1151 unsigned int index, const char *value) |
1152 { | |
145 | 1153 struct attribute_use ause = {group, loc, value, x, index}; |
111 | 1154 attribute_uses.safe_push (ause); |
1155 } | |
1156 | |
1157 /* Interpret NAME as either a built-in value, iterator or attribute | |
1158 for group GROUP. X and INDEX are the values to pass to GROUP's | |
145 | 1159 apply_iterator callback. LOC is the location of the use. */ |
111 | 1160 |
1161 void | |
1162 md_reader::record_potential_iterator_use (struct iterator_group *group, | |
145 | 1163 file_location loc, |
111 | 1164 rtx x, unsigned int index, |
1165 const char *name) | |
0 | 1166 { |
1167 struct mapping *m; | |
111 | 1168 size_t len; |
0 | 1169 |
111 | 1170 len = strlen (name); |
1171 if (name[0] == '<' && name[len - 1] == '>') | |
1172 { | |
1173 /* Copy the attribute string into permanent storage, without the | |
1174 angle brackets around it. */ | |
1175 obstack_grow0 (&m_string_obstack, name + 1, len - 2); | |
145 | 1176 record_attribute_use (group, loc, x, index, |
111 | 1177 XOBFINISH (&m_string_obstack, char *)); |
1178 } | |
1179 else | |
1180 { | |
1181 m = (struct mapping *) htab_find (group->iterators, &name); | |
1182 if (m != 0) | |
1183 record_iterator_use (m, x, index); | |
1184 else | |
1185 group->apply_iterator (x, index, group->find_builtin (name)); | |
1186 } | |
0 | 1187 } |
1188 | |
111 | 1189 #ifdef GENERATOR_FILE |
1190 | |
0 | 1191 /* Finish reading a declaration of the form: |
1192 | |
1193 (define... <name> [<value1> ... <valuen>]) | |
1194 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1195 from the MD file, where each <valuei> is either a bare symbol name or a |
0 | 1196 "(<name> <string>)" pair. The "(define..." part has already been read. |
1197 | |
1198 Represent the declaration as a "mapping" structure; add it to TABLE | |
1199 (which belongs to GROUP) and return it. */ | |
1200 | |
111 | 1201 struct mapping * |
1202 md_reader::read_mapping (struct iterator_group *group, htab_t table) | |
0 | 1203 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1204 struct md_name name; |
0 | 1205 struct mapping *m; |
1206 struct map_value **end_ptr; | |
1207 const char *string; | |
1208 int number, c; | |
1209 | |
1210 /* Read the mapping name and create a structure for it. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1211 read_name (&name); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1212 m = add_mapping (group, table, name.string); |
0 | 1213 |
111 | 1214 require_char_ws ('['); |
0 | 1215 |
1216 /* Read each value. */ | |
1217 end_ptr = &m->values; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1218 c = read_skip_spaces (); |
0 | 1219 do |
1220 { | |
1221 if (c != '(') | |
1222 { | |
1223 /* A bare symbol name that is implicitly paired to an | |
1224 empty string. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1225 unread_char (c); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1226 read_name (&name); |
0 | 1227 string = ""; |
1228 } | |
1229 else | |
1230 { | |
1231 /* A "(name string)" pair. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1232 read_name (&name); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1233 string = read_string (false); |
111 | 1234 require_char_ws (')'); |
0 | 1235 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1236 number = group->find_builtin (name.string); |
0 | 1237 end_ptr = add_map_value (end_ptr, number, string); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1238 c = read_skip_spaces (); |
0 | 1239 } |
1240 while (c != ']'); | |
1241 | |
1242 return m; | |
1243 } | |
1244 | |
111 | 1245 /* For iterator with name ATTR_NAME generate define_attr with values |
1246 'yes' and 'no'. This attribute is used to mark templates to which | |
1247 define_subst ATTR_NAME should be applied. This attribute is set and | |
1248 defined implicitly and automatically. */ | |
1249 static void | |
1250 add_define_attr_for_define_subst (const char *attr_name, vec<rtx> *queue) | |
1251 { | |
1252 rtx const_str, return_rtx; | |
1253 | |
1254 return_rtx = rtx_alloc (DEFINE_ATTR); | |
1255 PUT_CODE (return_rtx, DEFINE_ATTR); | |
1256 | |
1257 const_str = rtx_alloc (CONST_STRING); | |
1258 PUT_CODE (const_str, CONST_STRING); | |
1259 XSTR (const_str, 0) = xstrdup ("no"); | |
1260 | |
1261 XSTR (return_rtx, 0) = xstrdup (attr_name); | |
1262 XSTR (return_rtx, 1) = xstrdup ("no,yes"); | |
1263 XEXP (return_rtx, 2) = const_str; | |
1264 | |
1265 queue->safe_push (return_rtx); | |
1266 } | |
1267 | |
1268 /* This routine generates DEFINE_SUBST_ATTR expression with operands | |
1269 ATTR_OPERANDS and places it to QUEUE. */ | |
1270 static void | |
1271 add_define_subst_attr (const char **attr_operands, vec<rtx> *queue) | |
1272 { | |
1273 rtx return_rtx; | |
1274 int i; | |
1275 | |
1276 return_rtx = rtx_alloc (DEFINE_SUBST_ATTR); | |
1277 PUT_CODE (return_rtx, DEFINE_SUBST_ATTR); | |
1278 | |
1279 for (i = 0; i < 4; i++) | |
1280 XSTR (return_rtx, i) = xstrdup (attr_operands[i]); | |
1281 | |
1282 queue->safe_push (return_rtx); | |
1283 } | |
1284 | |
1285 /* Read define_subst_attribute construction. It has next form: | |
1286 (define_subst_attribute <attribute_name> <iterator_name> <value1> <value2>) | |
1287 Attribute is substituted with value1 when no subst is applied and with | |
1288 value2 in the opposite case. | |
1289 Attributes are added to SUBST_ATTRS_TABLE. | |
1290 In case the iterator is encountered for the first time, it's added to | |
1291 SUBST_ITERS_TABLE. Also, implicit define_attr is generated. */ | |
1292 | |
1293 static void | |
1294 read_subst_mapping (htab_t subst_iters_table, htab_t subst_attrs_table, | |
1295 vec<rtx> *queue) | |
1296 { | |
1297 struct mapping *m; | |
1298 struct map_value **end_ptr; | |
1299 const char *attr_operands[4]; | |
1300 int i; | |
1301 | |
1302 for (i = 0; i < 4; i++) | |
1303 attr_operands[i] = rtx_reader_ptr->read_string (false); | |
1304 | |
1305 add_define_subst_attr (attr_operands, queue); | |
1306 | |
1307 bind_subst_iter_and_attr (attr_operands[1], attr_operands[0]); | |
1308 | |
1309 m = (struct mapping *) htab_find (substs.iterators, &attr_operands[1]); | |
1310 if (!m) | |
1311 { | |
1312 m = add_mapping (&substs, subst_iters_table, attr_operands[1]); | |
1313 end_ptr = &m->values; | |
1314 end_ptr = add_map_value (end_ptr, 1, ""); | |
145 | 1315 add_map_value (end_ptr, 2, ""); |
111 | 1316 |
1317 add_define_attr_for_define_subst (attr_operands[1], queue); | |
1318 } | |
1319 | |
1320 m = add_mapping (&substs, subst_attrs_table, attr_operands[0]); | |
1321 end_ptr = &m->values; | |
1322 end_ptr = add_map_value (end_ptr, 1, attr_operands[2]); | |
145 | 1323 add_map_value (end_ptr, 2, attr_operands[3]); |
111 | 1324 } |
1325 | |
0 | 1326 /* Check newly-created code iterator ITERATOR to see whether every code has the |
111 | 1327 same format. */ |
0 | 1328 |
1329 static void | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1330 check_code_iterator (struct mapping *iterator) |
0 | 1331 { |
1332 struct map_value *v; | |
1333 enum rtx_code bellwether; | |
1334 | |
1335 bellwether = (enum rtx_code) iterator->values->number; | |
1336 for (v = iterator->values->next; v != 0; v = v->next) | |
1337 if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1338 fatal_with_file_and_line ("code iterator `%s' combines " |
145 | 1339 "`%s' and `%s', which have different " |
1340 "rtx formats", iterator->name, | |
1341 GET_RTX_NAME (bellwether), | |
1342 GET_RTX_NAME (v->number)); | |
1343 } | |
1344 | |
1345 /* Check that all values of attribute ATTR are rtx codes that have a | |
1346 consistent format. Return a representative code. */ | |
1347 | |
1348 static rtx_code | |
1349 check_code_attribute (mapping *attr) | |
1350 { | |
1351 rtx_code bellwether = UNKNOWN; | |
1352 for (map_value *v = attr->values; v != 0; v = v->next) | |
1353 { | |
1354 rtx_code code = maybe_find_code (v->string); | |
1355 if (code == UNKNOWN) | |
1356 fatal_with_file_and_line ("code attribute `%s' contains " | |
1357 "unrecognized rtx code `%s'", | |
1358 attr->name, v->string); | |
1359 if (bellwether == UNKNOWN) | |
1360 bellwether = code; | |
1361 else if (strcmp (GET_RTX_FORMAT (bellwether), | |
1362 GET_RTX_FORMAT (code)) != 0) | |
1363 fatal_with_file_and_line ("code attribute `%s' combines " | |
1364 "`%s' and `%s', which have different " | |
1365 "rtx formats", attr->name, | |
1366 GET_RTX_NAME (bellwether), | |
1367 GET_RTX_NAME (code)); | |
1368 } | |
1369 return bellwether; | |
0 | 1370 } |
1371 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1372 /* Read an rtx-related declaration from the MD file, given that it |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1373 starts with directive name RTX_NAME. Return true if it expands to |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1374 one or more rtxes (as defined by rtx.def). When returning true, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1375 store the list of rtxes as an EXPR_LIST in *X. */ |
0 | 1376 |
1377 bool | |
111 | 1378 rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen) |
0 | 1379 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1380 /* Handle various rtx-related declarations that aren't themselves |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1381 encoded as rtxes. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1382 if (strcmp (rtx_name, "define_conditions") == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1383 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1384 read_conditions (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1385 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1386 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1387 if (strcmp (rtx_name, "define_mode_attr") == 0) |
0 | 1388 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1389 read_mapping (&modes, modes.attrs); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1390 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1391 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1392 if (strcmp (rtx_name, "define_mode_iterator") == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1393 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1394 read_mapping (&modes, modes.iterators); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1395 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1396 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1397 if (strcmp (rtx_name, "define_code_attr") == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1398 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1399 read_mapping (&codes, codes.attrs); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1400 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1401 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1402 if (strcmp (rtx_name, "define_code_iterator") == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1403 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1404 check_code_iterator (read_mapping (&codes, codes.iterators)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1405 return false; |
0 | 1406 } |
111 | 1407 if (strcmp (rtx_name, "define_int_attr") == 0) |
1408 { | |
1409 read_mapping (&ints, ints.attrs); | |
1410 return false; | |
1411 } | |
1412 if (strcmp (rtx_name, "define_int_iterator") == 0) | |
1413 { | |
1414 read_mapping (&ints, ints.iterators); | |
1415 return false; | |
1416 } | |
1417 if (strcmp (rtx_name, "define_subst_attr") == 0) | |
1418 { | |
1419 read_subst_mapping (substs.iterators, substs.attrs, rtxen); | |
0 | 1420 |
111 | 1421 /* READ_SUBST_MAPPING could generate a new DEFINE_ATTR. Return |
1422 TRUE to process it. */ | |
1423 return true; | |
1424 } | |
1425 | |
1426 apply_iterators (rtx_reader_ptr->read_rtx_code (rtx_name), rtxen); | |
1427 iterator_uses.truncate (0); | |
1428 attribute_uses.truncate (0); | |
1429 | |
1430 return true; | |
1431 } | |
1432 | |
1433 #endif /* #ifdef GENERATOR_FILE */ | |
1434 | |
1435 /* Do one-time initialization. */ | |
1436 | |
1437 static void | |
1438 one_time_initialization (void) | |
1439 { | |
1440 static bool initialized = false; | |
1441 | |
1442 if (!initialized) | |
1443 { | |
1444 initialize_iterators (); | |
1445 initialized = true; | |
1446 } | |
1447 } | |
1448 | |
1449 /* Consume characters until encountering a character in TERMINATOR_CHARS, | |
1450 consuming the terminator character if CONSUME_TERMINATOR is true. | |
1451 Return all characters before the terminator as an allocated buffer. */ | |
0 | 1452 |
111 | 1453 char * |
1454 rtx_reader::read_until (const char *terminator_chars, bool consume_terminator) | |
1455 { | |
1456 int ch = read_skip_spaces (); | |
1457 unread_char (ch); | |
1458 auto_vec<char> buf; | |
1459 while (1) | |
1460 { | |
1461 ch = read_char (); | |
1462 if (strchr (terminator_chars, ch)) | |
1463 { | |
1464 if (!consume_terminator) | |
1465 unread_char (ch); | |
1466 break; | |
1467 } | |
1468 buf.safe_push (ch); | |
1469 } | |
1470 buf.safe_push ('\0'); | |
1471 return xstrdup (buf.address ()); | |
1472 } | |
1473 | |
1474 /* Subroutine of read_rtx_code, for parsing zero or more flags. */ | |
1475 | |
1476 static void | |
1477 read_flags (rtx return_rtx) | |
1478 { | |
1479 while (1) | |
1480 { | |
1481 int ch = read_char (); | |
1482 if (ch != '/') | |
1483 { | |
1484 unread_char (ch); | |
1485 break; | |
1486 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1487 |
111 | 1488 int flag_char = read_char (); |
1489 switch (flag_char) | |
1490 { | |
1491 case 's': | |
1492 RTX_FLAG (return_rtx, in_struct) = 1; | |
1493 break; | |
1494 case 'v': | |
1495 RTX_FLAG (return_rtx, volatil) = 1; | |
1496 break; | |
1497 case 'u': | |
1498 RTX_FLAG (return_rtx, unchanging) = 1; | |
1499 break; | |
1500 case 'f': | |
1501 RTX_FLAG (return_rtx, frame_related) = 1; | |
1502 break; | |
1503 case 'j': | |
1504 RTX_FLAG (return_rtx, jump) = 1; | |
1505 break; | |
1506 case 'c': | |
1507 RTX_FLAG (return_rtx, call) = 1; | |
1508 break; | |
1509 case 'i': | |
1510 RTX_FLAG (return_rtx, return_val) = 1; | |
1511 break; | |
1512 default: | |
1513 fatal_with_file_and_line ("unrecognized flag: `%c'", flag_char); | |
1514 } | |
1515 } | |
1516 } | |
1517 | |
1518 /* Return the numeric value n for GET_REG_NOTE_NAME (n) for STRING, | |
1519 or fail if STRING isn't recognized. */ | |
1520 | |
1521 static int | |
1522 parse_reg_note_name (const char *string) | |
1523 { | |
1524 for (int i = 0; i < REG_NOTE_MAX; i++) | |
131 | 1525 if (strcmp (string, GET_REG_NOTE_NAME (i)) == 0) |
111 | 1526 return i; |
1527 fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string); | |
0 | 1528 } |
1529 | |
145 | 1530 /* Allocate an rtx for code NAME. If NAME is a code iterator or code |
1531 attribute, record its use for later and use one of its possible | |
1532 values as an interim rtx code. */ | |
1533 | |
1534 rtx | |
1535 rtx_reader::rtx_alloc_for_name (const char *name) | |
1536 { | |
1537 #ifdef GENERATOR_FILE | |
1538 size_t len = strlen (name); | |
1539 if (name[0] == '<' && name[len - 1] == '>') | |
1540 { | |
1541 /* Copy the attribute string into permanent storage, without the | |
1542 angle brackets around it. */ | |
1543 obstack *strings = get_string_obstack (); | |
1544 obstack_grow0 (strings, name + 1, len - 2); | |
1545 char *deferred_name = XOBFINISH (strings, char *); | |
1546 | |
1547 /* Find the name of the attribute. */ | |
1548 const char *attr = strchr (deferred_name, ':'); | |
1549 if (!attr) | |
1550 attr = deferred_name; | |
1551 | |
1552 /* Find the attribute itself. */ | |
1553 mapping *m = (mapping *) htab_find (codes.attrs, &attr); | |
1554 if (!m) | |
1555 fatal_with_file_and_line ("unknown code attribute `%s'", attr); | |
1556 | |
1557 /* Pick the first possible code for now, and record the attribute | |
1558 use for later. */ | |
1559 rtx x = rtx_alloc (check_code_attribute (m)); | |
1560 record_attribute_use (&codes, get_current_location (), | |
1561 x, 0, deferred_name); | |
1562 return x; | |
1563 } | |
1564 | |
1565 mapping *iterator = (mapping *) htab_find (codes.iterators, &name); | |
1566 if (iterator != 0) | |
1567 { | |
1568 /* Pick the first possible code for now, and record the iterator | |
1569 use for later. */ | |
1570 rtx x = rtx_alloc (rtx_code (iterator->values->number)); | |
1571 record_iterator_use (iterator, x, 0); | |
1572 return x; | |
1573 } | |
1574 #endif | |
1575 | |
1576 return rtx_alloc (rtx_code (codes.find_builtin (name))); | |
1577 } | |
1578 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1579 /* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1580 either an rtx code or a code iterator. Parse the rest of the rtx and |
111 | 1581 return it. */ |
0 | 1582 |
111 | 1583 rtx |
1584 rtx_reader::read_rtx_code (const char *code_name) | |
0 | 1585 { |
111 | 1586 RTX_CODE code; |
0 | 1587 const char *format_ptr; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1588 struct md_name name; |
0 | 1589 rtx return_rtx; |
1590 int c; | |
111 | 1591 long reuse_id = -1; |
0 | 1592 |
1593 /* Linked list structure for making RTXs: */ | |
1594 struct rtx_list | |
1595 { | |
1596 struct rtx_list *next; | |
1597 rtx value; /* Value of this node. */ | |
1598 }; | |
1599 | |
111 | 1600 /* Handle reuse_rtx ids e.g. "(0|scratch:DI)". */ |
1601 if (ISDIGIT (code_name[0])) | |
1602 { | |
1603 reuse_id = atoi (code_name); | |
1604 while (char ch = *code_name++) | |
1605 if (ch == '|') | |
1606 break; | |
1607 } | |
1608 | |
1609 /* Handle "reuse_rtx". */ | |
1610 if (strcmp (code_name, "reuse_rtx") == 0) | |
1611 { | |
1612 read_name (&name); | |
1613 unsigned idx = atoi (name.string); | |
1614 /* Look it up by ID. */ | |
1615 gcc_assert (idx < m_reuse_rtx_by_id.length ()); | |
1616 return_rtx = m_reuse_rtx_by_id[idx]; | |
1617 return return_rtx; | |
1618 } | |
1619 | |
0 | 1620 /* If we end up with an insn expression then we free this space below. */ |
145 | 1621 return_rtx = rtx_alloc_for_name (code_name); |
1622 code = GET_CODE (return_rtx); | |
111 | 1623 format_ptr = GET_RTX_FORMAT (code); |
1624 memset (return_rtx, 0, RTX_CODE_SIZE (code)); | |
1625 PUT_CODE (return_rtx, code); | |
1626 | |
1627 if (reuse_id != -1) | |
1628 { | |
1629 /* Store away for later reuse. */ | |
1630 m_reuse_rtx_by_id.safe_grow_cleared (reuse_id + 1); | |
1631 m_reuse_rtx_by_id[reuse_id] = return_rtx; | |
1632 } | |
1633 | |
1634 /* Check for flags. */ | |
1635 read_flags (return_rtx); | |
1636 | |
1637 /* Read REG_NOTE names for EXPR_LIST and INSN_LIST. */ | |
1638 if ((GET_CODE (return_rtx) == EXPR_LIST | |
1639 || GET_CODE (return_rtx) == INSN_LIST | |
1640 || GET_CODE (return_rtx) == INT_LIST) | |
1641 && !m_in_call_function_usage) | |
1642 { | |
1643 char ch = read_char (); | |
1644 if (ch == ':') | |
1645 { | |
1646 read_name (&name); | |
1647 PUT_MODE_RAW (return_rtx, | |
1648 (machine_mode)parse_reg_note_name (name.string)); | |
1649 } | |
1650 else | |
1651 unread_char (ch); | |
1652 } | |
0 | 1653 |
1654 /* If what follows is `: mode ', read it and | |
1655 store the mode in the rtx. */ | |
1656 | |
111 | 1657 c = read_skip_spaces (); |
1658 if (c == ':') | |
0 | 1659 { |
145 | 1660 file_location loc = read_name (&name); |
1661 record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string); | |
0 | 1662 } |
1663 else | |
111 | 1664 unread_char (c); |
1665 | |
1666 if (INSN_CHAIN_CODE_P (code)) | |
1667 { | |
1668 read_name (&name); | |
1669 INSN_UID (return_rtx) = atoi (name.string); | |
1670 } | |
0 | 1671 |
111 | 1672 /* Use the format_ptr to parse the various operands of this rtx. */ |
1673 for (int idx = 0; format_ptr[idx] != 0; idx++) | |
1674 return_rtx = read_rtx_operand (return_rtx, idx); | |
1675 | |
1676 /* Handle any additional information that after the regular fields | |
1677 (e.g. when parsing function dumps). */ | |
1678 handle_any_trailing_information (return_rtx); | |
1679 | |
1680 if (CONST_WIDE_INT_P (return_rtx)) | |
1681 { | |
1682 read_name (&name); | |
1683 validate_const_wide_int (name.string); | |
0 | 1684 { |
111 | 1685 const char *s = name.string; |
1686 int len; | |
1687 int index = 0; | |
1688 int gs = HOST_BITS_PER_WIDE_INT/4; | |
1689 int pos; | |
1690 char * buf = XALLOCAVEC (char, gs + 1); | |
1691 unsigned HOST_WIDE_INT wi; | |
1692 int wlen; | |
1693 | |
1694 /* Skip the leading spaces. */ | |
1695 while (*s && ISSPACE (*s)) | |
1696 s++; | |
1697 | |
1698 /* Skip the leading 0x. */ | |
1699 gcc_assert (s[0] == '0'); | |
1700 gcc_assert (s[1] == 'x'); | |
1701 s += 2; | |
1702 | |
1703 len = strlen (s); | |
1704 pos = len - gs; | |
1705 wlen = (len + gs - 1) / gs; /* Number of words needed */ | |
1706 | |
1707 return_rtx = const_wide_int_alloc (wlen); | |
1708 | |
1709 while (pos > 0) | |
1710 { | |
1711 #if HOST_BITS_PER_WIDE_INT == 64 | |
1712 sscanf (s + pos, "%16" HOST_WIDE_INT_PRINT "x", &wi); | |
1713 #else | |
1714 sscanf (s + pos, "%8" HOST_WIDE_INT_PRINT "x", &wi); | |
1715 #endif | |
1716 CWI_ELT (return_rtx, index++) = wi; | |
1717 pos -= gs; | |
1718 } | |
1719 strncpy (buf, s, gs - pos); | |
1720 buf [gs - pos] = 0; | |
1721 sscanf (buf, "%" HOST_WIDE_INT_PRINT "x", &wi); | |
1722 CWI_ELT (return_rtx, index++) = wi; | |
1723 /* TODO: After reading, do we want to canonicalize with: | |
1724 value = lookup_const_wide_int (value); ? */ | |
1725 } | |
1726 } | |
1727 | |
1728 c = read_skip_spaces (); | |
1729 /* Syntactic sugar for AND and IOR, allowing Lisp-like | |
1730 arbitrary number of arguments for them. */ | |
1731 if (c == '(' | |
1732 && (GET_CODE (return_rtx) == AND | |
1733 || GET_CODE (return_rtx) == IOR)) | |
1734 return read_rtx_variadic (return_rtx); | |
1735 | |
1736 unread_char (c); | |
1737 return return_rtx; | |
1738 } | |
1739 | |
1740 /* Subroutine of read_rtx_code. Parse operand IDX within RETURN_RTX, | |
1741 based on the corresponding format character within GET_RTX_FORMAT | |
1742 for the GET_CODE (RETURN_RTX), and return RETURN_RTX. | |
1743 This is a virtual function, so that function_reader can override | |
1744 some parsing, and potentially return a different rtx. */ | |
1745 | |
1746 rtx | |
1747 rtx_reader::read_rtx_operand (rtx return_rtx, int idx) | |
1748 { | |
1749 RTX_CODE code = GET_CODE (return_rtx); | |
1750 const char *format_ptr = GET_RTX_FORMAT (code); | |
1751 int c; | |
1752 struct md_name name; | |
0 | 1753 |
111 | 1754 switch (format_ptr[idx]) |
1755 { | |
1756 /* 0 means a field for internal use only. | |
1757 Don't expect it to be present in the input. */ | |
1758 case '0': | |
1759 if (code == REG) | |
1760 ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx); | |
1761 break; | |
1762 | |
1763 case 'e': | |
1764 XEXP (return_rtx, idx) = read_nested_rtx (); | |
1765 break; | |
1766 | |
1767 case 'u': | |
1768 XEXP (return_rtx, idx) = read_nested_rtx (); | |
1769 break; | |
1770 | |
1771 case 'V': | |
1772 /* 'V' is an optional vector: if a closeparen follows, | |
1773 just store NULL for this element. */ | |
1774 c = read_skip_spaces (); | |
1775 unread_char (c); | |
1776 if (c == ')') | |
1777 { | |
1778 XVEC (return_rtx, idx) = 0; | |
1779 break; | |
1780 } | |
1781 /* Now process the vector. */ | |
1782 /* FALLTHRU */ | |
0 | 1783 |
111 | 1784 case 'E': |
1785 { | |
1786 /* Obstack to store scratch vector in. */ | |
1787 struct obstack vector_stack; | |
1788 int list_counter = 0; | |
1789 rtvec return_vec = NULL_RTVEC; | |
131 | 1790 rtx saved_rtx = NULL_RTX; |
111 | 1791 |
1792 require_char_ws ('['); | |
1793 | |
1794 /* Add expressions to a list, while keeping a count. */ | |
1795 obstack_init (&vector_stack); | |
1796 while ((c = read_skip_spaces ()) && c != ']') | |
1797 { | |
1798 if (c == EOF) | |
1799 fatal_expected_char (']', c); | |
1800 unread_char (c); | |
131 | 1801 |
1802 rtx value; | |
1803 int repeat_count = 1; | |
1804 if (c == 'r') | |
1805 { | |
1806 /* Process "repeated xN" directive. */ | |
1807 read_name (&name); | |
1808 if (strcmp (name.string, "repeated")) | |
1809 fatal_with_file_and_line ("invalid directive \"%s\"\n", | |
1810 name.string); | |
1811 read_name (&name); | |
1812 if (!sscanf (name.string, "x%d", &repeat_count)) | |
1813 fatal_with_file_and_line ("invalid repeat count \"%s\"\n", | |
1814 name.string); | |
1815 | |
1816 /* We already saw one of the instances. */ | |
1817 repeat_count--; | |
1818 value = saved_rtx; | |
1819 } | |
1820 else | |
1821 value = read_nested_rtx (); | |
1822 | |
1823 for (; repeat_count > 0; repeat_count--) | |
1824 { | |
1825 list_counter++; | |
1826 obstack_ptr_grow (&vector_stack, value); | |
1827 } | |
1828 saved_rtx = value; | |
111 | 1829 } |
1830 if (list_counter > 0) | |
1831 { | |
1832 return_vec = rtvec_alloc (list_counter); | |
1833 memcpy (&return_vec->elem[0], obstack_finish (&vector_stack), | |
1834 list_counter * sizeof (rtx)); | |
1835 } | |
1836 else if (format_ptr[idx] == 'E') | |
1837 fatal_with_file_and_line ("vector must have at least one element"); | |
1838 XVEC (return_rtx, idx) = return_vec; | |
1839 obstack_free (&vector_stack, NULL); | |
1840 /* close bracket gotten */ | |
1841 } | |
1842 break; | |
1843 | |
1844 case 'S': | |
1845 case 'T': | |
1846 case 's': | |
1847 { | |
1848 char *stringbuf; | |
1849 int star_if_braced; | |
1850 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1851 c = read_skip_spaces (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1852 unread_char (c); |
0 | 1853 if (c == ')') |
1854 { | |
111 | 1855 /* 'S' fields are optional and should be NULL if no string |
1856 was given. Also allow normal 's' and 'T' strings to be | |
1857 omitted, treating them in the same way as empty strings. */ | |
1858 XSTR (return_rtx, idx) = (format_ptr[idx] == 'S' ? NULL : ""); | |
0 | 1859 break; |
1860 } | |
1861 | |
145 | 1862 /* The output template slot of a DEFINE_INSN, DEFINE_INSN_AND_SPLIT, |
1863 DEFINE_INSN_AND_REWRITE or DEFINE_PEEPHOLE automatically | |
111 | 1864 gets a star inserted as its first character, if it is |
1865 written with a brace block instead of a string constant. */ | |
1866 star_if_braced = (format_ptr[idx] == 'T'); | |
0 | 1867 |
111 | 1868 stringbuf = read_string (star_if_braced); |
1869 if (!stringbuf) | |
1870 break; | |
0 | 1871 |
111 | 1872 #ifdef GENERATOR_FILE |
1873 /* For insn patterns, we want to provide a default name | |
1874 based on the file and line, like "*foo.md:12", if the | |
1875 given name is blank. These are only for define_insn and | |
1876 define_insn_and_split, to aid debugging. */ | |
1877 if (*stringbuf == '\0' | |
1878 && idx == 0 | |
1879 && (GET_CODE (return_rtx) == DEFINE_INSN | |
145 | 1880 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT |
1881 || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE)) | |
111 | 1882 { |
145 | 1883 const char *old_stringbuf = stringbuf; |
111 | 1884 struct obstack *string_obstack = get_string_obstack (); |
1885 char line_name[20]; | |
1886 const char *read_md_filename = get_filename (); | |
1887 const char *fn = (read_md_filename ? read_md_filename : "rtx"); | |
1888 const char *slash; | |
1889 for (slash = fn; *slash; slash ++) | |
1890 if (*slash == '/' || *slash == '\\' || *slash == ':') | |
1891 fn = slash + 1; | |
1892 obstack_1grow (string_obstack, '*'); | |
1893 obstack_grow (string_obstack, fn, strlen (fn)); | |
1894 sprintf (line_name, ":%d", get_lineno ()); | |
1895 obstack_grow (string_obstack, line_name, strlen (line_name)+1); | |
1896 stringbuf = XOBFINISH (string_obstack, char *); | |
145 | 1897 copy_md_ptr_loc (stringbuf, old_stringbuf); |
111 | 1898 } |
0 | 1899 |
111 | 1900 /* Find attr-names in the string. */ |
1901 char *str; | |
1902 char *start, *end, *ptr; | |
1903 char tmpstr[256]; | |
1904 ptr = &tmpstr[0]; | |
1905 end = stringbuf; | |
1906 while ((start = strchr (end, '<')) && (end = strchr (start, '>'))) | |
1907 { | |
1908 if ((end - start - 1 > 0) | |
1909 && (end - start - 1 < (int)sizeof (tmpstr))) | |
1910 { | |
1911 strncpy (tmpstr, start+1, end-start-1); | |
1912 tmpstr[end-start-1] = 0; | |
1913 end++; | |
1914 } | |
1915 else | |
0 | 1916 break; |
111 | 1917 struct mapping *m |
1918 = (struct mapping *) htab_find (substs.attrs, &ptr); | |
1919 if (m != 0) | |
1920 { | |
1921 /* Here we should find linked subst-iter. */ | |
1922 str = find_subst_iter_by_attr (ptr); | |
1923 if (str) | |
1924 m = (struct mapping *) htab_find (substs.iterators, &str); | |
1925 else | |
1926 m = 0; | |
1927 } | |
1928 if (m != 0) | |
1929 record_iterator_use (m, return_rtx, 0); | |
1930 } | |
1931 #endif /* #ifdef GENERATOR_FILE */ | |
0 | 1932 |
111 | 1933 const char *string_ptr = finalize_string (stringbuf); |
0 | 1934 |
111 | 1935 if (star_if_braced) |
1936 XTMPL (return_rtx, idx) = string_ptr; | |
1937 else | |
1938 XSTR (return_rtx, idx) = string_ptr; | |
1939 } | |
1940 break; | |
0 | 1941 |
111 | 1942 case 'w': |
1943 { | |
1944 HOST_WIDE_INT tmp_wide; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1945 read_name (&name); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1946 validate_const_int (name.string); |
0 | 1947 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1948 tmp_wide = atoi (name.string); |
0 | 1949 #else |
1950 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1951 tmp_wide = atol (name.string); |
0 | 1952 #else |
1953 /* Prefer atoll over atoq, since the former is in the ISO C99 standard. | |
1954 But prefer not to use our hand-rolled function above either. */ | |
111 | 1955 #if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1956 tmp_wide = atoll (name.string); |
0 | 1957 #else |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1958 tmp_wide = atoq (name.string); |
0 | 1959 #endif |
1960 #endif | |
1961 #endif | |
111 | 1962 XWINT (return_rtx, idx) = tmp_wide; |
1963 } | |
1964 break; | |
0 | 1965 |
111 | 1966 case 'i': |
1967 case 'n': | |
131 | 1968 case 'p': |
145 | 1969 { |
1970 /* Can be an iterator or an integer constant. */ | |
1971 file_location loc = read_name (&name); | |
1972 record_potential_iterator_use (&ints, loc, return_rtx, idx, | |
1973 name.string); | |
1974 break; | |
1975 } | |
0 | 1976 |
111 | 1977 case 'r': |
1978 read_name (&name); | |
1979 validate_const_int (name.string); | |
1980 set_regno_raw (return_rtx, atoi (name.string), 1); | |
1981 REG_ATTRS (return_rtx) = NULL; | |
1982 break; | |
0 | 1983 |
111 | 1984 default: |
1985 gcc_unreachable (); | |
1986 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1987 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1988 return return_rtx; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1989 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1990 |
111 | 1991 /* Read a nested rtx construct from the MD file and return it. */ |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1992 |
111 | 1993 rtx |
1994 rtx_reader::read_nested_rtx () | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1995 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1996 struct md_name name; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1997 rtx return_rtx; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1998 |
111 | 1999 /* In compact dumps, trailing "(nil)" values can be omitted. |
2000 Handle such dumps. */ | |
2001 if (peek_char () == ')') | |
2002 return NULL_RTX; | |
2003 | |
2004 require_char_ws ('('); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2005 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2006 read_name (&name); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2007 if (strcmp (name.string, "nil") == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2008 return_rtx = NULL; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2009 else |
111 | 2010 return_rtx = read_rtx_code (name.string); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2011 |
111 | 2012 require_char_ws (')'); |
2013 | |
2014 return_rtx = postprocess (return_rtx); | |
0 | 2015 |
2016 return return_rtx; | |
2017 } | |
2018 | |
2019 /* Mutually recursive subroutine of read_rtx which reads | |
2020 (thing x1 x2 x3 ...) and produces RTL as if | |
2021 (thing x1 (thing x2 (thing x3 ...))) had been written. | |
2022 When called, FORM is (thing x1 x2), and the file position | |
2023 is just past the leading parenthesis of x3. Only works | |
2024 for THINGs which are dyadic expressions, e.g. AND, IOR. */ | |
111 | 2025 rtx |
2026 rtx_reader::read_rtx_variadic (rtx form) | |
0 | 2027 { |
2028 char c = '('; | |
2029 rtx p = form, q; | |
2030 | |
2031 do | |
2032 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2033 unread_char (c); |
0 | 2034 |
2035 q = rtx_alloc (GET_CODE (p)); | |
2036 PUT_MODE (q, GET_MODE (p)); | |
2037 | |
2038 XEXP (q, 0) = XEXP (p, 1); | |
111 | 2039 XEXP (q, 1) = read_nested_rtx (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2040 |
0 | 2041 XEXP (p, 1) = q; |
2042 p = q; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2043 c = read_skip_spaces (); |
0 | 2044 } |
2045 while (c == '('); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2046 unread_char (c); |
0 | 2047 return form; |
2048 } | |
111 | 2049 |
2050 /* Constructor for class rtx_reader. */ | |
2051 | |
2052 rtx_reader::rtx_reader (bool compact) | |
2053 : md_reader (compact), | |
2054 m_in_call_function_usage (false) | |
2055 { | |
2056 /* Set the global singleton pointer. */ | |
2057 rtx_reader_ptr = this; | |
2058 | |
2059 one_time_initialization (); | |
2060 } | |
2061 | |
2062 /* Destructor for class rtx_reader. */ | |
2063 | |
2064 rtx_reader::~rtx_reader () | |
2065 { | |
2066 /* Clear the global singleton pointer. */ | |
2067 rtx_reader_ptr = NULL; | |
2068 } |