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