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