File: | build/gcc/genmatch.cc |
Warning: | line 1918, column 3 Potential leak of memory pointed to by 'n' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Generate pattern matching and transform code shared between | |||
2 | GENERIC and GIMPLE folding code from match-and-simplify description. | |||
3 | ||||
4 | Copyright (C) 2014-2023 Free Software Foundation, Inc. | |||
5 | Contributed by Richard Biener <rguenther@suse.de> | |||
6 | and Prathamesh Kulkarni <bilbotheelffriend@gmail.com> | |||
7 | ||||
8 | This file is part of GCC. | |||
9 | ||||
10 | GCC is free software; you can redistribute it and/or modify it under | |||
11 | the terms of the GNU General Public License as published by the Free | |||
12 | Software Foundation; either version 3, or (at your option) any later | |||
13 | version. | |||
14 | ||||
15 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |||
16 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
17 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
18 | for more details. | |||
19 | ||||
20 | You should have received a copy of the GNU General Public License | |||
21 | along with GCC; see the file COPYING3. If not see | |||
22 | <http://www.gnu.org/licenses/>. */ | |||
23 | ||||
24 | #include "bconfig.h" | |||
25 | #include "system.h" | |||
26 | #include "coretypes.h" | |||
27 | #include <cpplib.h> | |||
28 | #include "errors.h" | |||
29 | #include "hash-table.h" | |||
30 | #include "hash-set.h" | |||
31 | #include "is-a.h" | |||
32 | ||||
33 | ||||
34 | /* Stubs for GGC referenced through instantiations triggered by hash-map. */ | |||
35 | void *ggc_internal_cleared_alloc (size_t, void (*)(void *), | |||
36 | size_t, size_t MEM_STAT_DECL) | |||
37 | { | |||
38 | return NULLnullptr; | |||
39 | } | |||
40 | void ggc_free (void *) | |||
41 | { | |||
42 | } | |||
43 | ||||
44 | ||||
45 | /* Global state. */ | |||
46 | ||||
47 | /* Verboseness. 0 is quiet, 1 adds some warnings, 2 is for debugging. */ | |||
48 | unsigned verbose; | |||
49 | ||||
50 | ||||
51 | /* libccp helpers. */ | |||
52 | ||||
53 | static class line_maps *line_table; | |||
54 | ||||
55 | /* The rich_location class within libcpp requires a way to expand | |||
56 | location_t instances, and relies on the client code | |||
57 | providing a symbol named | |||
58 | linemap_client_expand_location_to_spelling_point | |||
59 | to do this. | |||
60 | ||||
61 | This is the implementation for genmatch. */ | |||
62 | ||||
63 | expanded_location | |||
64 | linemap_client_expand_location_to_spelling_point (location_t loc, | |||
65 | enum location_aspect) | |||
66 | { | |||
67 | const struct line_map_ordinary *map; | |||
68 | loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION, &map); | |||
69 | return linemap_expand_location (line_table, map, loc); | |||
70 | } | |||
71 | ||||
72 | static bool | |||
73 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
74 | __attribute__((format (printf, 5, 0))) | |||
75 | #endif | |||
76 | diagnostic_cb (cpp_reader *, enum cpp_diagnostic_level errtype, | |||
77 | enum cpp_warning_reason, rich_location *richloc, | |||
78 | const char *msg, va_list *ap) | |||
79 | { | |||
80 | const line_map_ordinary *map; | |||
81 | location_t location = richloc->get_loc (); | |||
82 | linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map); | |||
83 | expanded_location loc = linemap_expand_location (line_table, map, location); | |||
84 | fprintf (stderrstderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column, | |||
85 | (errtype == CPP_DL_WARNING) ? "warning" : "error"); | |||
86 | vfprintf (stderrstderr, msg, *ap); | |||
87 | fprintf (stderrstderr, "\n"); | |||
88 | FILE *f = fopen (loc.file, "r")fopen_unlocked (loc.file, "r"); | |||
89 | if (f) | |||
90 | { | |||
91 | char buf[128]; | |||
92 | while (loc.line > 0) | |||
93 | { | |||
94 | if (!fgets (buf, 128, f)fgets_unlocked (buf, 128, f)) | |||
95 | goto notfound; | |||
96 | if (buf[strlen (buf) - 1] != '\n') | |||
97 | { | |||
98 | if (loc.line > 1) | |||
99 | loc.line++; | |||
100 | } | |||
101 | loc.line--; | |||
102 | } | |||
103 | fprintf (stderrstderr, "%s", buf); | |||
104 | for (int i = 0; i < loc.column - 1; ++i) | |||
105 | fputc (' ', stderr)fputc_unlocked (' ', stderr); | |||
106 | fputc ('^', stderr)fputc_unlocked ('^', stderr); | |||
107 | fputc ('\n', stderr)fputc_unlocked ('\n', stderr); | |||
108 | notfound: | |||
109 | fclose (f); | |||
110 | } | |||
111 | ||||
112 | if (errtype == CPP_DL_FATAL) | |||
113 | exit (1); | |||
114 | return false; | |||
115 | } | |||
116 | ||||
117 | static void | |||
118 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
119 | __attribute__((format (printf, 2, 3))) | |||
120 | #endif | |||
121 | fatal_at (const cpp_token *tk, const char *msg, ...) | |||
122 | { | |||
123 | rich_location richloc (line_table, tk->src_loc); | |||
124 | va_list ap; | |||
125 | va_start (ap, msg)__builtin_va_start(ap, msg); | |||
126 | diagnostic_cb (NULLnullptr, CPP_DL_FATAL, CPP_W_NONE, &richloc, msg, &ap); | |||
127 | va_end (ap)__builtin_va_end(ap); | |||
128 | } | |||
129 | ||||
130 | static void | |||
131 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
132 | __attribute__((format (printf, 2, 3))) | |||
133 | #endif | |||
134 | fatal_at (location_t loc, const char *msg, ...) | |||
135 | { | |||
136 | rich_location richloc (line_table, loc); | |||
137 | va_list ap; | |||
138 | va_start (ap, msg)__builtin_va_start(ap, msg); | |||
139 | diagnostic_cb (NULLnullptr, CPP_DL_FATAL, CPP_W_NONE, &richloc, msg, &ap); | |||
140 | va_end (ap)__builtin_va_end(ap); | |||
141 | } | |||
142 | ||||
143 | static void | |||
144 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
145 | __attribute__((format (printf, 2, 3))) | |||
146 | #endif | |||
147 | warning_at (const cpp_token *tk, const char *msg, ...) | |||
148 | { | |||
149 | rich_location richloc (line_table, tk->src_loc); | |||
150 | va_list ap; | |||
151 | va_start (ap, msg)__builtin_va_start(ap, msg); | |||
152 | diagnostic_cb (NULLnullptr, CPP_DL_WARNING, CPP_W_NONE, &richloc, msg, &ap); | |||
153 | va_end (ap)__builtin_va_end(ap); | |||
154 | } | |||
155 | ||||
156 | static void | |||
157 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
158 | __attribute__((format (printf, 2, 3))) | |||
159 | #endif | |||
160 | warning_at (location_t loc, const char *msg, ...) | |||
161 | { | |||
162 | rich_location richloc (line_table, loc); | |||
163 | va_list ap; | |||
164 | va_start (ap, msg)__builtin_va_start(ap, msg); | |||
165 | diagnostic_cb (NULLnullptr, CPP_DL_WARNING, CPP_W_NONE, &richloc, msg, &ap); | |||
166 | va_end (ap)__builtin_va_end(ap); | |||
167 | } | |||
168 | ||||
169 | /* Like fprintf, but print INDENT spaces at the beginning. */ | |||
170 | ||||
171 | static void | |||
172 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
173 | __attribute__((format (printf, 3, 4))) | |||
174 | #endif | |||
175 | fprintf_indent (FILE *f, unsigned int indent, const char *format, ...) | |||
176 | { | |||
177 | va_list ap; | |||
178 | for (; indent >= 8; indent -= 8) | |||
179 | fputc ('\t', f)fputc_unlocked ('\t', f); | |||
180 | fprintf (f, "%*s", indent, ""); | |||
181 | va_start (ap, format)__builtin_va_start(ap, format); | |||
182 | vfprintf (f, format, ap); | |||
183 | va_end (ap)__builtin_va_end(ap); | |||
184 | } | |||
185 | ||||
186 | static void | |||
187 | output_line_directive (FILE *f, location_t location, | |||
188 | bool dumpfile = false, bool fnargs = false) | |||
189 | { | |||
190 | const line_map_ordinary *map; | |||
191 | linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map); | |||
192 | expanded_location loc = linemap_expand_location (line_table, map, location); | |||
193 | if (dumpfile) | |||
194 | { | |||
195 | /* When writing to a dumpfile only dump the filename. */ | |||
196 | const char *file = strrchr (loc.file, DIR_SEPARATOR'/'); | |||
197 | #if defined(DIR_SEPARATOR_2) | |||
198 | const char *pos2 = strrchr (loc.file, DIR_SEPARATOR_2); | |||
199 | if (pos2 && (!file || (pos2 > file))) | |||
200 | file = pos2; | |||
201 | #endif | |||
202 | if (!file) | |||
203 | file = loc.file; | |||
204 | else | |||
205 | ++file; | |||
206 | ||||
207 | if (fnargs) | |||
208 | fprintf (f, "\"%s\", %d", file, loc.line); | |||
209 | else | |||
210 | fprintf (f, "%s:%d", file, loc.line); | |||
211 | } | |||
212 | else | |||
213 | /* Other gen programs really output line directives here, at least for | |||
214 | development it's right now more convenient to have line information | |||
215 | from the generated file. Still keep the directives as comment for now | |||
216 | to easily back-point to the meta-description. */ | |||
217 | fprintf (f, "/* #line %d \"%s\" */\n", loc.line, loc.file); | |||
218 | } | |||
219 | ||||
220 | ||||
221 | /* Pull in tree codes and builtin function codes from their | |||
222 | definition files. */ | |||
223 | ||||
224 | #define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM, | |||
225 | enum tree_code { | |||
226 | #include "tree.def" | |||
227 | MAX_TREE_CODES | |||
228 | }; | |||
229 | #undef DEFTREECODE | |||
230 | ||||
231 | #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) ENUM, | |||
232 | enum built_in_function { | |||
233 | #include "builtins.def" | |||
234 | END_BUILTINS | |||
235 | }; | |||
236 | ||||
237 | #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) IFN_##CODE, | |||
238 | enum internal_fn { | |||
239 | #include "internal-fn.def" | |||
240 | IFN_LAST | |||
241 | }; | |||
242 | ||||
243 | enum combined_fn { | |||
244 | #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \ | |||
245 | CFN_##ENUM = int (ENUM), | |||
246 | #include "builtins.def" | |||
247 | ||||
248 | #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ | |||
249 | CFN_##CODE = int (END_BUILTINS) + int (IFN_##CODE), | |||
250 | #include "internal-fn.def" | |||
251 | ||||
252 | CFN_LAST | |||
253 | }; | |||
254 | ||||
255 | #include "case-cfn-macros.h" | |||
256 | ||||
257 | /* Return true if CODE represents a commutative tree code. Otherwise | |||
258 | return false. */ | |||
259 | bool | |||
260 | commutative_tree_code (enum tree_code code) | |||
261 | { | |||
262 | switch (code) | |||
263 | { | |||
264 | case PLUS_EXPR: | |||
265 | case MULT_EXPR: | |||
266 | case MULT_HIGHPART_EXPR: | |||
267 | case MIN_EXPR: | |||
268 | case MAX_EXPR: | |||
269 | case BIT_IOR_EXPR: | |||
270 | case BIT_XOR_EXPR: | |||
271 | case BIT_AND_EXPR: | |||
272 | case NE_EXPR: | |||
273 | case EQ_EXPR: | |||
274 | case UNORDERED_EXPR: | |||
275 | case ORDERED_EXPR: | |||
276 | case UNEQ_EXPR: | |||
277 | case LTGT_EXPR: | |||
278 | case TRUTH_AND_EXPR: | |||
279 | case TRUTH_XOR_EXPR: | |||
280 | case TRUTH_OR_EXPR: | |||
281 | case WIDEN_MULT_EXPR: | |||
282 | case VEC_WIDEN_MULT_HI_EXPR: | |||
283 | case VEC_WIDEN_MULT_LO_EXPR: | |||
284 | case VEC_WIDEN_MULT_EVEN_EXPR: | |||
285 | case VEC_WIDEN_MULT_ODD_EXPR: | |||
286 | return true; | |||
287 | ||||
288 | default: | |||
289 | break; | |||
290 | } | |||
291 | return false; | |||
292 | } | |||
293 | ||||
294 | /* Return true if CODE represents a ternary tree code for which the | |||
295 | first two operands are commutative. Otherwise return false. */ | |||
296 | bool | |||
297 | commutative_ternary_tree_code (enum tree_code code) | |||
298 | { | |||
299 | switch (code) | |||
300 | { | |||
301 | case WIDEN_MULT_PLUS_EXPR: | |||
302 | case WIDEN_MULT_MINUS_EXPR: | |||
303 | case DOT_PROD_EXPR: | |||
304 | return true; | |||
305 | ||||
306 | default: | |||
307 | break; | |||
308 | } | |||
309 | return false; | |||
310 | } | |||
311 | ||||
312 | /* Return true if CODE is a comparison. */ | |||
313 | ||||
314 | bool | |||
315 | comparison_code_p (enum tree_code code) | |||
316 | { | |||
317 | switch (code) | |||
318 | { | |||
319 | case EQ_EXPR: | |||
320 | case NE_EXPR: | |||
321 | case ORDERED_EXPR: | |||
322 | case UNORDERED_EXPR: | |||
323 | case LTGT_EXPR: | |||
324 | case UNEQ_EXPR: | |||
325 | case GT_EXPR: | |||
326 | case GE_EXPR: | |||
327 | case LT_EXPR: | |||
328 | case LE_EXPR: | |||
329 | case UNGT_EXPR: | |||
330 | case UNGE_EXPR: | |||
331 | case UNLT_EXPR: | |||
332 | case UNLE_EXPR: | |||
333 | return true; | |||
334 | ||||
335 | default: | |||
336 | break; | |||
337 | } | |||
338 | return false; | |||
339 | } | |||
340 | ||||
341 | ||||
342 | /* Base class for all identifiers the parser knows. */ | |||
343 | ||||
344 | class id_base : public nofree_ptr_hash<id_base> | |||
345 | { | |||
346 | public: | |||
347 | enum id_kind { CODE, FN, PREDICATE, USER, NULL_ID } kind; | |||
348 | ||||
349 | id_base (id_kind, const char *, int = -1); | |||
350 | ||||
351 | hashval_t hashval; | |||
352 | int nargs; | |||
353 | const char *id; | |||
354 | ||||
355 | /* hash_table support. */ | |||
356 | static inline hashval_t hash (const id_base *); | |||
357 | static inline int equal (const id_base *, const id_base *); | |||
358 | }; | |||
359 | ||||
360 | inline hashval_t | |||
361 | id_base::hash (const id_base *op) | |||
362 | { | |||
363 | return op->hashval; | |||
364 | } | |||
365 | ||||
366 | inline int | |||
367 | id_base::equal (const id_base *op1, | |||
368 | const id_base *op2) | |||
369 | { | |||
370 | return (op1->hashval == op2->hashval | |||
371 | && strcmp (op1->id, op2->id) == 0); | |||
372 | } | |||
373 | ||||
374 | /* The special id "null", which matches nothing. */ | |||
375 | static id_base *null_id; | |||
376 | ||||
377 | /* Hashtable of known pattern operators. This is pre-seeded from | |||
378 | all known tree codes and all known builtin function ids. */ | |||
379 | static hash_table<id_base> *operators; | |||
380 | ||||
381 | id_base::id_base (id_kind kind_, const char *id_, int nargs_) | |||
382 | { | |||
383 | kind = kind_; | |||
384 | id = id_; | |||
385 | nargs = nargs_; | |||
386 | hashval = htab_hash_string (id); | |||
387 | } | |||
388 | ||||
389 | /* Identifier that maps to a tree code. */ | |||
390 | ||||
391 | class operator_id : public id_base | |||
392 | { | |||
393 | public: | |||
394 | operator_id (enum tree_code code_, const char *id_, unsigned nargs_, | |||
395 | const char *tcc_) | |||
396 | : id_base (id_base::CODE, id_, nargs_), code (code_), tcc (tcc_) {} | |||
397 | enum tree_code code; | |||
398 | const char *tcc; | |||
399 | }; | |||
400 | ||||
401 | /* Identifier that maps to a builtin or internal function code. */ | |||
402 | ||||
403 | class fn_id : public id_base | |||
404 | { | |||
405 | public: | |||
406 | fn_id (enum built_in_function fn_, const char *id_) | |||
407 | : id_base (id_base::FN, id_), fn (fn_) {} | |||
408 | fn_id (enum internal_fn fn_, const char *id_) | |||
409 | : id_base (id_base::FN, id_), fn (int (END_BUILTINS) + int (fn_)) {} | |||
410 | unsigned int fn; | |||
411 | }; | |||
412 | ||||
413 | class simplify; | |||
414 | ||||
415 | /* Identifier that maps to a user-defined predicate. */ | |||
416 | ||||
417 | class predicate_id : public id_base | |||
418 | { | |||
419 | public: | |||
420 | predicate_id (const char *id_) | |||
421 | : id_base (id_base::PREDICATE, id_), matchers (vNULL) {} | |||
422 | vec<simplify *> matchers; | |||
423 | }; | |||
424 | ||||
425 | /* Identifier that maps to a operator defined by a 'for' directive. */ | |||
426 | ||||
427 | class user_id : public id_base | |||
428 | { | |||
429 | public: | |||
430 | user_id (const char *id_, bool is_oper_list_ = false) | |||
431 | : id_base (id_base::USER, id_), substitutes (vNULL), | |||
432 | used (false), is_oper_list (is_oper_list_) {} | |||
433 | vec<id_base *> substitutes; | |||
434 | bool used; | |||
435 | bool is_oper_list; | |||
436 | }; | |||
437 | ||||
438 | template<> | |||
439 | template<> | |||
440 | inline bool | |||
441 | is_a_helper <fn_id *>::test (id_base *id) | |||
442 | { | |||
443 | return id->kind == id_base::FN; | |||
444 | } | |||
445 | ||||
446 | template<> | |||
447 | template<> | |||
448 | inline bool | |||
449 | is_a_helper <operator_id *>::test (id_base *id) | |||
450 | { | |||
451 | return id->kind == id_base::CODE; | |||
452 | } | |||
453 | ||||
454 | template<> | |||
455 | template<> | |||
456 | inline bool | |||
457 | is_a_helper <predicate_id *>::test (id_base *id) | |||
458 | { | |||
459 | return id->kind == id_base::PREDICATE; | |||
460 | } | |||
461 | ||||
462 | template<> | |||
463 | template<> | |||
464 | inline bool | |||
465 | is_a_helper <user_id *>::test (id_base *id) | |||
466 | { | |||
467 | return id->kind == id_base::USER; | |||
468 | } | |||
469 | ||||
470 | /* If ID has a pair of consecutive, commutative operands, return the | |||
471 | index of the first, otherwise return -1. */ | |||
472 | ||||
473 | static int | |||
474 | commutative_op (id_base *id) | |||
475 | { | |||
476 | if (operator_id *code = dyn_cast <operator_id *> (id)) | |||
477 | { | |||
478 | if (commutative_tree_code (code->code) | |||
479 | || commutative_ternary_tree_code (code->code)) | |||
480 | return 0; | |||
481 | return -1; | |||
482 | } | |||
483 | if (fn_id *fn = dyn_cast <fn_id *> (id)) | |||
484 | switch (fn->fn) | |||
485 | { | |||
486 | CASE_CFN_FMAcase CFN_FMA: case CFN_BUILT_IN_FMAF: case CFN_BUILT_IN_FMA: case CFN_BUILT_IN_FMAL: | |||
487 | case CFN_FMS: | |||
488 | case CFN_FNMA: | |||
489 | case CFN_FNMS: | |||
490 | return 0; | |||
491 | ||||
492 | case CFN_COND_ADD: | |||
493 | case CFN_COND_MUL: | |||
494 | case CFN_COND_MIN: | |||
495 | case CFN_COND_MAX: | |||
496 | case CFN_COND_FMIN: | |||
497 | case CFN_COND_FMAX: | |||
498 | case CFN_COND_AND: | |||
499 | case CFN_COND_IOR: | |||
500 | case CFN_COND_XOR: | |||
501 | case CFN_COND_FMA: | |||
502 | case CFN_COND_FMS: | |||
503 | case CFN_COND_FNMA: | |||
504 | case CFN_COND_FNMS: | |||
505 | return 1; | |||
506 | ||||
507 | default: | |||
508 | return -1; | |||
509 | } | |||
510 | if (user_id *uid = dyn_cast<user_id *> (id)) | |||
511 | { | |||
512 | int res = commutative_op (uid->substitutes[0]); | |||
513 | if (res < 0) | |||
514 | return -1; | |||
515 | for (unsigned i = 1; i < uid->substitutes.length (); ++i) | |||
516 | if (res != commutative_op (uid->substitutes[i])) | |||
517 | return -1; | |||
518 | return res; | |||
519 | } | |||
520 | return -1; | |||
521 | } | |||
522 | ||||
523 | /* Add a predicate identifier to the hash. */ | |||
524 | ||||
525 | static predicate_id * | |||
526 | add_predicate (const char *id) | |||
527 | { | |||
528 | predicate_id *p = new predicate_id (id); | |||
529 | id_base **slot = operators->find_slot_with_hash (p, p->hashval, INSERT); | |||
530 | if (*slot) | |||
531 | fatal ("duplicate id definition"); | |||
532 | *slot = p; | |||
533 | return p; | |||
534 | } | |||
535 | ||||
536 | /* Add a tree code identifier to the hash. */ | |||
537 | ||||
538 | static void | |||
539 | add_operator (enum tree_code code, const char *id, | |||
540 | const char *tcc, unsigned nargs) | |||
541 | { | |||
542 | if (strcmp (tcc, "tcc_unary") != 0 | |||
543 | && strcmp (tcc, "tcc_binary") != 0 | |||
544 | && strcmp (tcc, "tcc_comparison") != 0 | |||
545 | && strcmp (tcc, "tcc_expression") != 0 | |||
546 | /* For {REAL,IMAG}PART_EXPR and VIEW_CONVERT_EXPR. */ | |||
547 | && strcmp (tcc, "tcc_reference") != 0 | |||
548 | /* To have INTEGER_CST and friends as "predicate operators". */ | |||
549 | && strcmp (tcc, "tcc_constant") != 0 | |||
550 | /* And allow CONSTRUCTOR for vector initializers. */ | |||
551 | && !(code == CONSTRUCTOR) | |||
552 | /* Allow SSA_NAME as predicate operator. */ | |||
553 | && !(code == SSA_NAME)) | |||
554 | return; | |||
555 | /* Treat ADDR_EXPR as atom, thus don't allow matching its operand. */ | |||
556 | if (code == ADDR_EXPR) | |||
557 | nargs = 0; | |||
558 | operator_id *op = new operator_id (code, id, nargs, tcc); | |||
559 | id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); | |||
560 | if (*slot) | |||
561 | fatal ("duplicate id definition"); | |||
562 | *slot = op; | |||
563 | } | |||
564 | ||||
565 | /* Add a built-in or internal function identifier to the hash. ID is | |||
566 | the name of its CFN_* enumeration value. */ | |||
567 | ||||
568 | template <typename T> | |||
569 | static void | |||
570 | add_function (T code, const char *id) | |||
571 | { | |||
572 | fn_id *fn = new fn_id (code, id); | |||
573 | id_base **slot = operators->find_slot_with_hash (fn, fn->hashval, INSERT); | |||
574 | if (*slot) | |||
575 | fatal ("duplicate id definition"); | |||
576 | *slot = fn; | |||
577 | } | |||
578 | ||||
579 | /* Helper for easy comparing ID with tree code CODE. */ | |||
580 | ||||
581 | static bool | |||
582 | operator==(id_base &id, enum tree_code code) | |||
583 | { | |||
584 | if (operator_id *oid = dyn_cast <operator_id *> (&id)) | |||
585 | return oid->code == code; | |||
586 | return false; | |||
587 | } | |||
588 | ||||
589 | /* Lookup the identifier ID. Allow "null" if ALLOW_NULL. */ | |||
590 | ||||
591 | id_base * | |||
592 | get_operator (const char *id, bool allow_null = false) | |||
593 | { | |||
594 | if (allow_null && strcmp (id, "null") == 0) | |||
595 | return null_id; | |||
596 | ||||
597 | id_base tem (id_base::CODE, id); | |||
598 | ||||
599 | id_base *op = operators->find_with_hash (&tem, tem.hashval); | |||
600 | if (op) | |||
601 | { | |||
602 | /* If this is a user-defined identifier track whether it was used. */ | |||
603 | if (user_id *uid = dyn_cast<user_id *> (op)) | |||
604 | uid->used = true; | |||
605 | return op; | |||
606 | } | |||
607 | ||||
608 | char *id2; | |||
609 | bool all_upper = true; | |||
610 | bool all_lower = true; | |||
611 | for (unsigned int i = 0; id[i]; ++i) | |||
612 | if (ISUPPER (id[i])(_sch_istable[(id[i]) & 0xff] & (unsigned short)(_sch_isupper ))) | |||
613 | all_lower = false; | |||
614 | else if (ISLOWER (id[i])(_sch_istable[(id[i]) & 0xff] & (unsigned short)(_sch_islower ))) | |||
615 | all_upper = false; | |||
616 | if (all_lower) | |||
617 | { | |||
618 | /* Try in caps with _EXPR appended. */ | |||
619 | id2 = ACONCAT ((id, "_EXPR", NULL))(libiberty_concat_ptr = (char *) __builtin_alloca(concat_length (id, "_EXPR", nullptr) + 1), concat_copy2 (id, "_EXPR", nullptr )); | |||
620 | for (unsigned int i = 0; id2[i]; ++i) | |||
621 | id2[i] = TOUPPER (id2[i])_sch_toupper[(id2[i]) & 0xff]; | |||
622 | } | |||
623 | else if (all_upper && startswith (id, "IFN_")) | |||
624 | /* Try CFN_ instead of IFN_. */ | |||
625 | id2 = ACONCAT (("CFN_", id + 4, NULL))(libiberty_concat_ptr = (char *) __builtin_alloca(concat_length ("CFN_", id + 4, nullptr) + 1), concat_copy2 ("CFN_", id + 4 , nullptr)); | |||
626 | else if (all_upper && startswith (id, "BUILT_IN_")) | |||
627 | /* Try prepending CFN_. */ | |||
628 | id2 = ACONCAT (("CFN_", id, NULL))(libiberty_concat_ptr = (char *) __builtin_alloca(concat_length ("CFN_", id, nullptr) + 1), concat_copy2 ("CFN_", id, nullptr )); | |||
629 | else | |||
630 | return NULLnullptr; | |||
631 | ||||
632 | new (&tem) id_base (id_base::CODE, id2); | |||
633 | return operators->find_with_hash (&tem, tem.hashval); | |||
634 | } | |||
635 | ||||
636 | /* Return the comparison operators that results if the operands are | |||
637 | swapped. This is safe for floating-point. */ | |||
638 | ||||
639 | id_base * | |||
640 | swap_tree_comparison (operator_id *p) | |||
641 | { | |||
642 | switch (p->code) | |||
643 | { | |||
644 | case EQ_EXPR: | |||
645 | case NE_EXPR: | |||
646 | case ORDERED_EXPR: | |||
647 | case UNORDERED_EXPR: | |||
648 | case LTGT_EXPR: | |||
649 | case UNEQ_EXPR: | |||
650 | return p; | |||
651 | case GT_EXPR: | |||
652 | return get_operator ("LT_EXPR"); | |||
653 | case GE_EXPR: | |||
654 | return get_operator ("LE_EXPR"); | |||
655 | case LT_EXPR: | |||
656 | return get_operator ("GT_EXPR"); | |||
657 | case LE_EXPR: | |||
658 | return get_operator ("GE_EXPR"); | |||
659 | case UNGT_EXPR: | |||
660 | return get_operator ("UNLT_EXPR"); | |||
661 | case UNGE_EXPR: | |||
662 | return get_operator ("UNLE_EXPR"); | |||
663 | case UNLT_EXPR: | |||
664 | return get_operator ("UNGT_EXPR"); | |||
665 | case UNLE_EXPR: | |||
666 | return get_operator ("UNGE_EXPR"); | |||
667 | default: | |||
668 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 668, __FUNCTION__)); | |||
669 | } | |||
670 | } | |||
671 | ||||
672 | typedef hash_map<nofree_string_hash, unsigned> cid_map_t; | |||
673 | ||||
674 | ||||
675 | /* The AST produced by parsing of the pattern definitions. */ | |||
676 | ||||
677 | class dt_operand; | |||
678 | class capture_info; | |||
679 | ||||
680 | /* The base class for operands. */ | |||
681 | ||||
682 | class operand { | |||
683 | public: | |||
684 | enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR, OP_IF, OP_WITH }; | |||
685 | operand (enum op_type type_, location_t loc_) | |||
686 | : type (type_), location (loc_) {} | |||
687 | enum op_type type; | |||
688 | location_t location; | |||
689 | virtual void gen_transform (FILE *, int, const char *, bool, int, | |||
690 | const char *, capture_info *, | |||
691 | dt_operand ** = 0, | |||
692 | int = 0) | |||
693 | { gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 693, __FUNCTION__)); } | |||
694 | }; | |||
695 | ||||
696 | /* A predicate operand. Predicates are leafs in the AST. */ | |||
697 | ||||
698 | class predicate : public operand | |||
699 | { | |||
700 | public: | |||
701 | predicate (predicate_id *p_, location_t loc) | |||
702 | : operand (OP_PREDICATE, loc), p (p_) {} | |||
703 | predicate_id *p; | |||
704 | }; | |||
705 | ||||
706 | /* An operand that constitutes an expression. Expressions include | |||
707 | function calls and user-defined predicate invocations. */ | |||
708 | ||||
709 | class expr : public operand | |||
710 | { | |||
711 | public: | |||
712 | expr (id_base *operation_, location_t loc, bool is_commutative_ = false) | |||
713 | : operand (OP_EXPR, loc), operation (operation_), | |||
714 | ops (vNULL), expr_type (NULLnullptr), is_commutative (is_commutative_), | |||
715 | is_generic (false), force_single_use (false), force_leaf (false), | |||
716 | opt_grp (0) {} | |||
717 | expr (expr *e) | |||
718 | : operand (OP_EXPR, e->location), operation (e->operation), | |||
719 | ops (vNULL), expr_type (e->expr_type), is_commutative (e->is_commutative), | |||
720 | is_generic (e->is_generic), force_single_use (e->force_single_use), | |||
721 | force_leaf (e->force_leaf), opt_grp (e->opt_grp) {} | |||
722 | void append_op (operand *op) { ops.safe_push (op); } | |||
723 | /* The operator and its operands. */ | |||
724 | id_base *operation; | |||
725 | vec<operand *> ops; | |||
726 | /* An explicitely specified type - used exclusively for conversions. */ | |||
727 | const char *expr_type; | |||
728 | /* Whether the operation is to be applied commutatively. This is | |||
729 | later lowered to two separate patterns. */ | |||
730 | bool is_commutative; | |||
731 | /* Whether the expression is expected to be in GENERIC form. */ | |||
732 | bool is_generic; | |||
733 | /* Whether pushing any stmt to the sequence should be conditional | |||
734 | on this expression having a single-use. */ | |||
735 | bool force_single_use; | |||
736 | /* Whether in the result expression this should be a leaf node | |||
737 | with any children simplified down to simple operands. */ | |||
738 | bool force_leaf; | |||
739 | /* If non-zero, the group for optional handling. */ | |||
740 | unsigned char opt_grp; | |||
741 | void gen_transform (FILE *f, int, const char *, bool, int, | |||
742 | const char *, capture_info *, | |||
743 | dt_operand ** = 0, int = 0) override; | |||
744 | }; | |||
745 | ||||
746 | /* An operator that is represented by native C code. This is always | |||
747 | a leaf operand in the AST. This class is also used to represent | |||
748 | the code to be generated for 'if' and 'with' expressions. */ | |||
749 | ||||
750 | class c_expr : public operand | |||
751 | { | |||
752 | public: | |||
753 | /* A mapping of an identifier and its replacement. Used to apply | |||
754 | 'for' lowering. */ | |||
755 | class id_tab { | |||
756 | public: | |||
757 | const char *id; | |||
758 | const char *oper; | |||
759 | id_tab (const char *id_, const char *oper_): id (id_), oper (oper_) {} | |||
760 | }; | |||
761 | ||||
762 | c_expr (cpp_reader *r_, location_t loc, | |||
763 | vec<cpp_token> code_, unsigned nr_stmts_, | |||
764 | vec<id_tab> ids_, cid_map_t *capture_ids_) | |||
765 | : operand (OP_C_EXPR, loc), r (r_), code (code_), | |||
766 | capture_ids (capture_ids_), nr_stmts (nr_stmts_), ids (ids_) {} | |||
767 | /* cpplib tokens and state to transform this back to source. */ | |||
768 | cpp_reader *r; | |||
769 | vec<cpp_token> code; | |||
770 | cid_map_t *capture_ids; | |||
771 | /* The number of statements parsed (well, the number of ';'s). */ | |||
772 | unsigned nr_stmts; | |||
773 | /* The identifier replacement vector. */ | |||
774 | vec<id_tab> ids; | |||
775 | void gen_transform (FILE *f, int, const char *, bool, int, | |||
776 | const char *, capture_info *, | |||
777 | dt_operand ** = 0, int = 0) final override; | |||
778 | }; | |||
779 | ||||
780 | /* A wrapper around another operand that captures its value. */ | |||
781 | ||||
782 | class capture : public operand | |||
783 | { | |||
784 | public: | |||
785 | capture (location_t loc, unsigned where_, operand *what_, bool value_) | |||
786 | : operand (OP_CAPTURE, loc), where (where_), value_match (value_), | |||
787 | what (what_) {} | |||
788 | /* Identifier index for the value. */ | |||
789 | unsigned where; | |||
790 | /* Whether in a match of two operands the compare should be for | |||
791 | equal values rather than equal atoms (boils down to a type | |||
792 | check or not). */ | |||
793 | bool value_match; | |||
794 | /* The captured value. */ | |||
795 | operand *what; | |||
796 | void gen_transform (FILE *f, int, const char *, bool, int, | |||
797 | const char *, capture_info *, | |||
798 | dt_operand ** = 0, int = 0) final override; | |||
799 | }; | |||
800 | ||||
801 | /* if expression. */ | |||
802 | ||||
803 | class if_expr : public operand | |||
804 | { | |||
805 | public: | |||
806 | if_expr (location_t loc) | |||
807 | : operand (OP_IF, loc), cond (NULLnullptr), trueexpr (NULLnullptr), falseexpr (NULLnullptr) {} | |||
808 | c_expr *cond; | |||
809 | operand *trueexpr; | |||
810 | operand *falseexpr; | |||
811 | }; | |||
812 | ||||
813 | /* with expression. */ | |||
814 | ||||
815 | class with_expr : public operand | |||
816 | { | |||
817 | public: | |||
818 | with_expr (location_t loc) | |||
819 | : operand (OP_WITH, loc), with (NULLnullptr), subexpr (NULLnullptr) {} | |||
820 | c_expr *with; | |||
821 | operand *subexpr; | |||
822 | }; | |||
823 | ||||
824 | template<> | |||
825 | template<> | |||
826 | inline bool | |||
827 | is_a_helper <capture *>::test (operand *op) | |||
828 | { | |||
829 | return op->type == operand::OP_CAPTURE; | |||
830 | } | |||
831 | ||||
832 | template<> | |||
833 | template<> | |||
834 | inline bool | |||
835 | is_a_helper <predicate *>::test (operand *op) | |||
836 | { | |||
837 | return op->type == operand::OP_PREDICATE; | |||
838 | } | |||
839 | ||||
840 | template<> | |||
841 | template<> | |||
842 | inline bool | |||
843 | is_a_helper <c_expr *>::test (operand *op) | |||
844 | { | |||
845 | return op->type == operand::OP_C_EXPR; | |||
846 | } | |||
847 | ||||
848 | template<> | |||
849 | template<> | |||
850 | inline bool | |||
851 | is_a_helper <expr *>::test (operand *op) | |||
852 | { | |||
853 | return op->type == operand::OP_EXPR; | |||
854 | } | |||
855 | ||||
856 | template<> | |||
857 | template<> | |||
858 | inline bool | |||
859 | is_a_helper <if_expr *>::test (operand *op) | |||
860 | { | |||
861 | return op->type == operand::OP_IF; | |||
862 | } | |||
863 | ||||
864 | template<> | |||
865 | template<> | |||
866 | inline bool | |||
867 | is_a_helper <with_expr *>::test (operand *op) | |||
868 | { | |||
869 | return op->type == operand::OP_WITH; | |||
870 | } | |||
871 | ||||
872 | /* The main class of a pattern and its transform. This is used to | |||
873 | represent both (simplify ...) and (match ...) kinds. The AST | |||
874 | duplicates all outer 'if' and 'for' expressions here so each | |||
875 | simplify can exist in isolation. */ | |||
876 | ||||
877 | class simplify | |||
878 | { | |||
879 | public: | |||
880 | enum simplify_kind { SIMPLIFY, MATCH }; | |||
881 | ||||
882 | simplify (simplify_kind kind_, unsigned id_, operand *match_, | |||
883 | operand *result_, vec<vec<user_id *> > for_vec_, | |||
884 | cid_map_t *capture_ids_) | |||
885 | : kind (kind_), id (id_), match (match_), result (result_), | |||
886 | for_vec (for_vec_), for_subst_vec (vNULL), | |||
887 | capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1) {} | |||
888 | ||||
889 | simplify_kind kind; | |||
890 | /* ID. This is kept to easily associate related simplifies expanded | |||
891 | from the same original one. */ | |||
892 | unsigned id; | |||
893 | /* The expression that is matched against the GENERIC or GIMPLE IL. */ | |||
894 | operand *match; | |||
895 | /* For a (simplify ...) an expression with ifs and withs with the expression | |||
896 | produced when the pattern applies in the leafs. | |||
897 | For a (match ...) the leafs are either empty if it is a simple predicate | |||
898 | or the single expression specifying the matched operands. */ | |||
899 | class operand *result; | |||
900 | /* Collected 'for' expression operators that have to be replaced | |||
901 | in the lowering phase. */ | |||
902 | vec<vec<user_id *> > for_vec; | |||
903 | vec<std::pair<user_id *, id_base *> > for_subst_vec; | |||
904 | /* A map of capture identifiers to indexes. */ | |||
905 | cid_map_t *capture_ids; | |||
906 | int capture_max; | |||
907 | }; | |||
908 | ||||
909 | /* Debugging routines for dumping the AST. */ | |||
910 | ||||
911 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
912 | print_operand (operand *o, FILE *f = stderrstderr, bool flattened = false) | |||
913 | { | |||
914 | if (capture *c = dyn_cast<capture *> (o)) | |||
915 | { | |||
916 | if (c->what && flattened == false) | |||
917 | print_operand (c->what, f, flattened); | |||
918 | fprintf (f, "@%u", c->where); | |||
919 | } | |||
920 | ||||
921 | else if (predicate *p = dyn_cast<predicate *> (o)) | |||
922 | fprintf (f, "%s", p->p->id); | |||
923 | ||||
924 | else if (is_a<c_expr *> (o)) | |||
925 | fprintf (f, "c_expr"); | |||
926 | ||||
927 | else if (expr *e = dyn_cast<expr *> (o)) | |||
928 | { | |||
929 | if (e->ops.length () == 0) | |||
930 | fprintf (f, "%s", e->operation->id); | |||
931 | else | |||
932 | { | |||
933 | fprintf (f, "(%s", e->operation->id); | |||
934 | ||||
935 | if (flattened == false) | |||
936 | { | |||
937 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
938 | { | |||
939 | putc (' ', f)putc_unlocked (' ', f); | |||
940 | print_operand (e->ops[i], f, flattened); | |||
941 | } | |||
942 | } | |||
943 | putc (')', f)putc_unlocked (')', f); | |||
944 | } | |||
945 | } | |||
946 | ||||
947 | else | |||
948 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 948, __FUNCTION__)); | |||
949 | } | |||
950 | ||||
951 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
952 | print_matches (class simplify *s, FILE *f = stderrstderr) | |||
953 | { | |||
954 | fprintf (f, "for expression: "); | |||
955 | print_operand (s->match, f); | |||
956 | putc ('\n', f)putc_unlocked ('\n', f); | |||
957 | } | |||
958 | ||||
959 | ||||
960 | /* AST lowering. */ | |||
961 | ||||
962 | /* Lowering of commutative operators. */ | |||
963 | ||||
964 | static void | |||
965 | cartesian_product (const vec< vec<operand *> >& ops_vector, | |||
966 | vec< vec<operand *> >& result, vec<operand *>& v, unsigned n) | |||
967 | { | |||
968 | if (n == ops_vector.length ()) | |||
969 | { | |||
970 | vec<operand *> xv = v.copy (); | |||
971 | result.safe_push (xv); | |||
972 | return; | |||
973 | } | |||
974 | ||||
975 | for (unsigned i = 0; i < ops_vector[n].length (); ++i) | |||
976 | { | |||
977 | v[n] = ops_vector[n][i]; | |||
978 | cartesian_product (ops_vector, result, v, n + 1); | |||
979 | } | |||
980 | } | |||
981 | ||||
982 | /* Lower OP to two operands in case it is marked as commutative. */ | |||
983 | ||||
984 | static vec<operand *> | |||
985 | commutate (operand *op, vec<vec<user_id *> > &for_vec) | |||
986 | { | |||
987 | vec<operand *> ret = vNULL; | |||
988 | ||||
989 | if (capture *c = dyn_cast <capture *> (op)) | |||
990 | { | |||
991 | if (!c->what) | |||
992 | { | |||
993 | ret.safe_push (op); | |||
994 | return ret; | |||
995 | } | |||
996 | vec<operand *> v = commutate (c->what, for_vec); | |||
997 | for (unsigned i = 0; i < v.length (); ++i) | |||
998 | { | |||
999 | capture *nc = new capture (c->location, c->where, v[i], | |||
1000 | c->value_match); | |||
1001 | ret.safe_push (nc); | |||
1002 | } | |||
1003 | return ret; | |||
1004 | } | |||
1005 | ||||
1006 | expr *e = dyn_cast <expr *> (op); | |||
1007 | if (!e || e->ops.length () == 0) | |||
1008 | { | |||
1009 | ret.safe_push (op); | |||
1010 | return ret; | |||
1011 | } | |||
1012 | ||||
1013 | vec< vec<operand *> > ops_vector = vNULL; | |||
1014 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1015 | ops_vector.safe_push (commutate (e->ops[i], for_vec)); | |||
1016 | ||||
1017 | auto_vec< vec<operand *> > result; | |||
1018 | auto_vec<operand *> v (e->ops.length ()); | |||
1019 | v.quick_grow_cleared (e->ops.length ()); | |||
1020 | cartesian_product (ops_vector, result, v, 0); | |||
1021 | ||||
1022 | ||||
1023 | for (unsigned i = 0; i < result.length (); ++i) | |||
1024 | { | |||
1025 | expr *ne = new expr (e); | |||
1026 | ne->is_commutative = false; | |||
1027 | for (unsigned j = 0; j < result[i].length (); ++j) | |||
1028 | ne->append_op (result[i][j]); | |||
1029 | ret.safe_push (ne); | |||
1030 | } | |||
1031 | ||||
1032 | if (!e->is_commutative) | |||
1033 | return ret; | |||
1034 | ||||
1035 | /* The operation is always binary if it isn't inherently commutative. */ | |||
1036 | int natural_opno = commutative_op (e->operation); | |||
1037 | unsigned int opno = natural_opno >= 0 ? natural_opno : 0; | |||
1038 | for (unsigned i = 0; i < result.length (); ++i) | |||
1039 | { | |||
1040 | expr *ne = new expr (e); | |||
1041 | if (operator_id *r = dyn_cast <operator_id *> (ne->operation)) | |||
1042 | { | |||
1043 | if (comparison_code_p (r->code)) | |||
1044 | ne->operation = swap_tree_comparison (r); | |||
1045 | } | |||
1046 | else if (user_id *p = dyn_cast <user_id *> (ne->operation)) | |||
1047 | { | |||
1048 | bool found_compare = false; | |||
1049 | for (unsigned j = 0; j < p->substitutes.length (); ++j) | |||
1050 | if (operator_id *q = dyn_cast <operator_id *> (p->substitutes[j])) | |||
1051 | { | |||
1052 | if (comparison_code_p (q->code) | |||
1053 | && swap_tree_comparison (q) != q) | |||
1054 | { | |||
1055 | found_compare = true; | |||
1056 | break; | |||
1057 | } | |||
1058 | } | |||
1059 | if (found_compare) | |||
1060 | { | |||
1061 | user_id *newop = new user_id ("<internal>"); | |||
1062 | for (unsigned j = 0; j < p->substitutes.length (); ++j) | |||
1063 | { | |||
1064 | id_base *subst = p->substitutes[j]; | |||
1065 | if (operator_id *q = dyn_cast <operator_id *> (subst)) | |||
1066 | { | |||
1067 | if (comparison_code_p (q->code)) | |||
1068 | subst = swap_tree_comparison (q); | |||
1069 | } | |||
1070 | newop->substitutes.safe_push (subst); | |||
1071 | } | |||
1072 | ne->operation = newop; | |||
1073 | /* Search for 'p' inside the for vector and push 'newop' | |||
1074 | to the same level. */ | |||
1075 | for (unsigned j = 0; newop && j < for_vec.length (); ++j) | |||
1076 | for (unsigned k = 0; k < for_vec[j].length (); ++k) | |||
1077 | if (for_vec[j][k] == p) | |||
1078 | { | |||
1079 | for_vec[j].safe_push (newop); | |||
1080 | newop = NULLnullptr; | |||
1081 | break; | |||
1082 | } | |||
1083 | } | |||
1084 | } | |||
1085 | ne->is_commutative = false; | |||
1086 | for (unsigned j = 0; j < result[i].length (); ++j) | |||
1087 | { | |||
1088 | int old_j = (j == opno ? opno + 1 : j == opno + 1 ? opno : j); | |||
1089 | ne->append_op (result[i][old_j]); | |||
1090 | } | |||
1091 | ret.safe_push (ne); | |||
1092 | } | |||
1093 | ||||
1094 | return ret; | |||
1095 | } | |||
1096 | ||||
1097 | /* Lower operations marked as commutative in the AST of S and push | |||
1098 | the resulting patterns to SIMPLIFIERS. */ | |||
1099 | ||||
1100 | static void | |||
1101 | lower_commutative (simplify *s, vec<simplify *>& simplifiers) | |||
1102 | { | |||
1103 | vec<operand *> matchers = commutate (s->match, s->for_vec); | |||
1104 | for (unsigned i = 0; i < matchers.length (); ++i) | |||
1105 | { | |||
1106 | simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result, | |||
1107 | s->for_vec, s->capture_ids); | |||
1108 | simplifiers.safe_push (ns); | |||
1109 | } | |||
1110 | } | |||
1111 | ||||
1112 | /* Strip conditional operations using group GRP from O and its | |||
1113 | children if STRIP, else replace them with an unconditional operation. */ | |||
1114 | ||||
1115 | operand * | |||
1116 | lower_opt (operand *o, unsigned char grp, bool strip) | |||
1117 | { | |||
1118 | if (capture *c = dyn_cast<capture *> (o)) | |||
1119 | { | |||
1120 | if (c->what) | |||
1121 | return new capture (c->location, c->where, | |||
1122 | lower_opt (c->what, grp, strip), | |||
1123 | c->value_match); | |||
1124 | else | |||
1125 | return c; | |||
1126 | } | |||
1127 | ||||
1128 | expr *e = dyn_cast<expr *> (o); | |||
1129 | if (!e) | |||
1130 | return o; | |||
1131 | ||||
1132 | if (e->opt_grp == grp) | |||
1133 | { | |||
1134 | if (strip) | |||
1135 | return lower_opt (e->ops[0], grp, strip); | |||
1136 | ||||
1137 | expr *ne = new expr (e); | |||
1138 | ne->opt_grp = 0; | |||
1139 | ne->append_op (lower_opt (e->ops[0], grp, strip)); | |||
1140 | return ne; | |||
1141 | } | |||
1142 | ||||
1143 | expr *ne = new expr (e); | |||
1144 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1145 | ne->append_op (lower_opt (e->ops[i], grp, strip)); | |||
1146 | ||||
1147 | return ne; | |||
1148 | } | |||
1149 | ||||
1150 | /* Determine whether O or its children uses the conditional operation | |||
1151 | group GRP. */ | |||
1152 | ||||
1153 | static bool | |||
1154 | has_opt (operand *o, unsigned char grp) | |||
1155 | { | |||
1156 | if (capture *c = dyn_cast<capture *> (o)) | |||
1157 | { | |||
1158 | if (c->what) | |||
1159 | return has_opt (c->what, grp); | |||
1160 | else | |||
1161 | return false; | |||
1162 | } | |||
1163 | ||||
1164 | expr *e = dyn_cast<expr *> (o); | |||
1165 | if (!e) | |||
1166 | return false; | |||
1167 | ||||
1168 | if (e->opt_grp == grp) | |||
1169 | return true; | |||
1170 | ||||
1171 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1172 | if (has_opt (e->ops[i], grp)) | |||
1173 | return true; | |||
1174 | ||||
1175 | return false; | |||
1176 | } | |||
1177 | ||||
1178 | /* Lower conditional convert operators in O, expanding it to a vector | |||
1179 | if required. */ | |||
1180 | ||||
1181 | static vec<operand *> | |||
1182 | lower_opt (operand *o) | |||
1183 | { | |||
1184 | vec<operand *> v1 = vNULL, v2; | |||
1185 | ||||
1186 | v1.safe_push (o); | |||
1187 | ||||
1188 | /* Conditional operations are lowered to a pattern with the | |||
1189 | operation and one without. All different conditional operation | |||
1190 | groups are lowered separately. */ | |||
1191 | ||||
1192 | for (unsigned i = 1; i <= 10; ++i) | |||
1193 | { | |||
1194 | v2 = vNULL; | |||
1195 | for (unsigned j = 0; j < v1.length (); ++j) | |||
1196 | if (has_opt (v1[j], i)) | |||
1197 | { | |||
1198 | v2.safe_push (lower_opt (v1[j], i, false)); | |||
1199 | v2.safe_push (lower_opt (v1[j], i, true)); | |||
1200 | } | |||
1201 | ||||
1202 | if (v2 != vNULL) | |||
1203 | { | |||
1204 | v1 = vNULL; | |||
1205 | for (unsigned j = 0; j < v2.length (); ++j) | |||
1206 | v1.safe_push (v2[j]); | |||
1207 | } | |||
1208 | } | |||
1209 | ||||
1210 | return v1; | |||
1211 | } | |||
1212 | ||||
1213 | /* Lower conditional convert operators in the AST of S and push | |||
1214 | the resulting multiple patterns to SIMPLIFIERS. */ | |||
1215 | ||||
1216 | static void | |||
1217 | lower_opt (simplify *s, vec<simplify *>& simplifiers) | |||
1218 | { | |||
1219 | vec<operand *> matchers = lower_opt (s->match); | |||
1220 | for (unsigned i = 0; i < matchers.length (); ++i) | |||
1221 | { | |||
1222 | simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result, | |||
1223 | s->for_vec, s->capture_ids); | |||
1224 | simplifiers.safe_push (ns); | |||
1225 | } | |||
1226 | } | |||
1227 | ||||
1228 | /* Lower the compare operand of COND_EXPRs to a | |||
1229 | GENERIC and a GIMPLE variant. */ | |||
1230 | ||||
1231 | static vec<operand *> | |||
1232 | lower_cond (operand *o) | |||
1233 | { | |||
1234 | vec<operand *> ro = vNULL; | |||
1235 | ||||
1236 | if (capture *c = dyn_cast<capture *> (o)) | |||
1237 | { | |||
1238 | if (c->what) | |||
1239 | { | |||
1240 | vec<operand *> lop = vNULL; | |||
1241 | lop = lower_cond (c->what); | |||
1242 | ||||
1243 | for (unsigned i = 0; i < lop.length (); ++i) | |||
1244 | ro.safe_push (new capture (c->location, c->where, lop[i], | |||
1245 | c->value_match)); | |||
1246 | return ro; | |||
1247 | } | |||
1248 | } | |||
1249 | ||||
1250 | expr *e = dyn_cast<expr *> (o); | |||
1251 | if (!e || e->ops.length () == 0) | |||
1252 | { | |||
1253 | ro.safe_push (o); | |||
1254 | return ro; | |||
1255 | } | |||
1256 | ||||
1257 | vec< vec<operand *> > ops_vector = vNULL; | |||
1258 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1259 | ops_vector.safe_push (lower_cond (e->ops[i])); | |||
1260 | ||||
1261 | auto_vec< vec<operand *> > result; | |||
1262 | auto_vec<operand *> v (e->ops.length ()); | |||
1263 | v.quick_grow_cleared (e->ops.length ()); | |||
1264 | cartesian_product (ops_vector, result, v, 0); | |||
1265 | ||||
1266 | for (unsigned i = 0; i < result.length (); ++i) | |||
1267 | { | |||
1268 | expr *ne = new expr (e); | |||
1269 | for (unsigned j = 0; j < result[i].length (); ++j) | |||
1270 | ne->append_op (result[i][j]); | |||
1271 | ro.safe_push (ne); | |||
1272 | /* If this is a COND with a captured expression or an | |||
1273 | expression with two operands then also match a GENERIC | |||
1274 | form on the compare. */ | |||
1275 | if (*e->operation == COND_EXPR | |||
1276 | && ((is_a <capture *> (e->ops[0]) | |||
1277 | && as_a <capture *> (e->ops[0])->what | |||
1278 | && is_a <expr *> (as_a <capture *> (e->ops[0])->what) | |||
1279 | && as_a <expr *> | |||
1280 | (as_a <capture *> (e->ops[0])->what)->ops.length () == 2) | |||
1281 | || (is_a <expr *> (e->ops[0]) | |||
1282 | && as_a <expr *> (e->ops[0])->ops.length () == 2))) | |||
1283 | { | |||
1284 | ne = new expr (e); | |||
1285 | for (unsigned j = 0; j < result[i].length (); ++j) | |||
1286 | ne->append_op (result[i][j]); | |||
1287 | if (capture *c = dyn_cast <capture *> (ne->ops[0])) | |||
1288 | { | |||
1289 | expr *ocmp = as_a <expr *> (c->what); | |||
1290 | expr *cmp = new expr (ocmp); | |||
1291 | for (unsigned j = 0; j < ocmp->ops.length (); ++j) | |||
1292 | cmp->append_op (ocmp->ops[j]); | |||
1293 | cmp->is_generic = true; | |||
1294 | ne->ops[0] = new capture (c->location, c->where, cmp, | |||
1295 | c->value_match); | |||
1296 | } | |||
1297 | else | |||
1298 | { | |||
1299 | expr *ocmp = as_a <expr *> (ne->ops[0]); | |||
1300 | expr *cmp = new expr (ocmp); | |||
1301 | for (unsigned j = 0; j < ocmp->ops.length (); ++j) | |||
1302 | cmp->append_op (ocmp->ops[j]); | |||
1303 | cmp->is_generic = true; | |||
1304 | ne->ops[0] = cmp; | |||
1305 | } | |||
1306 | ro.safe_push (ne); | |||
1307 | } | |||
1308 | } | |||
1309 | ||||
1310 | return ro; | |||
1311 | } | |||
1312 | ||||
1313 | /* Lower the compare operand of COND_EXPRs to a | |||
1314 | GENERIC and a GIMPLE variant. */ | |||
1315 | ||||
1316 | static void | |||
1317 | lower_cond (simplify *s, vec<simplify *>& simplifiers) | |||
1318 | { | |||
1319 | vec<operand *> matchers = lower_cond (s->match); | |||
1320 | for (unsigned i = 0; i < matchers.length (); ++i) | |||
1321 | { | |||
1322 | simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result, | |||
1323 | s->for_vec, s->capture_ids); | |||
1324 | ns->for_subst_vec.safe_splice (s->for_subst_vec); | |||
1325 | simplifiers.safe_push (ns); | |||
1326 | } | |||
1327 | } | |||
1328 | ||||
1329 | /* Return true if O refers to ID. */ | |||
1330 | ||||
1331 | bool | |||
1332 | contains_id (operand *o, user_id *id) | |||
1333 | { | |||
1334 | if (capture *c = dyn_cast<capture *> (o)) | |||
1335 | return c->what && contains_id (c->what, id); | |||
1336 | ||||
1337 | if (expr *e = dyn_cast<expr *> (o)) | |||
1338 | { | |||
1339 | if (e->operation == id) | |||
1340 | return true; | |||
1341 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1342 | if (contains_id (e->ops[i], id)) | |||
1343 | return true; | |||
1344 | return false; | |||
1345 | } | |||
1346 | ||||
1347 | if (with_expr *w = dyn_cast <with_expr *> (o)) | |||
1348 | return (contains_id (w->with, id) | |||
1349 | || contains_id (w->subexpr, id)); | |||
1350 | ||||
1351 | if (if_expr *ife = dyn_cast <if_expr *> (o)) | |||
1352 | return (contains_id (ife->cond, id) | |||
1353 | || contains_id (ife->trueexpr, id) | |||
1354 | || (ife->falseexpr && contains_id (ife->falseexpr, id))); | |||
1355 | ||||
1356 | if (c_expr *ce = dyn_cast<c_expr *> (o)) | |||
1357 | return ce->capture_ids && ce->capture_ids->get (id->id); | |||
1358 | ||||
1359 | return false; | |||
1360 | } | |||
1361 | ||||
1362 | ||||
1363 | /* In AST operand O replace operator ID with operator WITH. */ | |||
1364 | ||||
1365 | operand * | |||
1366 | replace_id (operand *o, user_id *id, id_base *with) | |||
1367 | { | |||
1368 | /* Deep-copy captures and expressions, replacing operations as | |||
1369 | needed. */ | |||
1370 | if (capture *c = dyn_cast<capture *> (o)) | |||
1371 | { | |||
1372 | if (!c->what) | |||
1373 | return c; | |||
1374 | return new capture (c->location, c->where, | |||
1375 | replace_id (c->what, id, with), c->value_match); | |||
1376 | } | |||
1377 | else if (expr *e = dyn_cast<expr *> (o)) | |||
1378 | { | |||
1379 | expr *ne = new expr (e); | |||
1380 | if (e->operation == id) | |||
1381 | ne->operation = with; | |||
1382 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
1383 | ne->append_op (replace_id (e->ops[i], id, with)); | |||
1384 | return ne; | |||
1385 | } | |||
1386 | else if (with_expr *w = dyn_cast <with_expr *> (o)) | |||
1387 | { | |||
1388 | with_expr *nw = new with_expr (w->location); | |||
1389 | nw->with = as_a <c_expr *> (replace_id (w->with, id, with)); | |||
1390 | nw->subexpr = replace_id (w->subexpr, id, with); | |||
1391 | return nw; | |||
1392 | } | |||
1393 | else if (if_expr *ife = dyn_cast <if_expr *> (o)) | |||
1394 | { | |||
1395 | if_expr *nife = new if_expr (ife->location); | |||
1396 | nife->cond = as_a <c_expr *> (replace_id (ife->cond, id, with)); | |||
1397 | nife->trueexpr = replace_id (ife->trueexpr, id, with); | |||
1398 | if (ife->falseexpr) | |||
1399 | nife->falseexpr = replace_id (ife->falseexpr, id, with); | |||
1400 | return nife; | |||
1401 | } | |||
1402 | ||||
1403 | /* For c_expr we simply record a string replacement table which is | |||
1404 | applied at code-generation time. */ | |||
1405 | if (c_expr *ce = dyn_cast<c_expr *> (o)) | |||
1406 | { | |||
1407 | vec<c_expr::id_tab> ids = ce->ids.copy (); | |||
1408 | ids.safe_push (c_expr::id_tab (id->id, with->id)); | |||
1409 | return new c_expr (ce->r, ce->location, | |||
1410 | ce->code, ce->nr_stmts, ids, ce->capture_ids); | |||
1411 | } | |||
1412 | ||||
1413 | return o; | |||
1414 | } | |||
1415 | ||||
1416 | /* Return true if the binary operator OP is ok for delayed substitution | |||
1417 | during for lowering. */ | |||
1418 | ||||
1419 | static bool | |||
1420 | binary_ok (operator_id *op) | |||
1421 | { | |||
1422 | switch (op->code) | |||
1423 | { | |||
1424 | case PLUS_EXPR: | |||
1425 | case MINUS_EXPR: | |||
1426 | case MULT_EXPR: | |||
1427 | case TRUNC_DIV_EXPR: | |||
1428 | case CEIL_DIV_EXPR: | |||
1429 | case FLOOR_DIV_EXPR: | |||
1430 | case ROUND_DIV_EXPR: | |||
1431 | case TRUNC_MOD_EXPR: | |||
1432 | case CEIL_MOD_EXPR: | |||
1433 | case FLOOR_MOD_EXPR: | |||
1434 | case ROUND_MOD_EXPR: | |||
1435 | case RDIV_EXPR: | |||
1436 | case EXACT_DIV_EXPR: | |||
1437 | case MIN_EXPR: | |||
1438 | case MAX_EXPR: | |||
1439 | case BIT_IOR_EXPR: | |||
1440 | case BIT_XOR_EXPR: | |||
1441 | case BIT_AND_EXPR: | |||
1442 | return true; | |||
1443 | default: | |||
1444 | return false; | |||
1445 | } | |||
1446 | } | |||
1447 | ||||
1448 | /* Lower recorded fors for SIN and output to SIMPLIFIERS. */ | |||
1449 | ||||
1450 | static void | |||
1451 | lower_for (simplify *sin, vec<simplify *>& simplifiers) | |||
1452 | { | |||
1453 | vec<vec<user_id *> >& for_vec = sin->for_vec; | |||
1454 | unsigned worklist_start = 0; | |||
1455 | auto_vec<simplify *> worklist; | |||
1456 | worklist.safe_push (sin); | |||
1457 | ||||
1458 | /* Lower each recorded for separately, operating on the | |||
1459 | set of simplifiers created by the previous one. | |||
1460 | Lower inner-to-outer so inner for substitutes can refer | |||
1461 | to operators replaced by outer fors. */ | |||
1462 | for (int fi = for_vec.length () - 1; fi >= 0; --fi) | |||
1463 | { | |||
1464 | vec<user_id *>& ids = for_vec[fi]; | |||
1465 | unsigned n_ids = ids.length (); | |||
1466 | unsigned max_n_opers = 0; | |||
1467 | bool can_delay_subst = (sin->kind == simplify::SIMPLIFY); | |||
1468 | for (unsigned i = 0; i < n_ids; ++i) | |||
1469 | { | |||
1470 | if (ids[i]->substitutes.length () > max_n_opers) | |||
1471 | max_n_opers = ids[i]->substitutes.length (); | |||
1472 | /* Require that all substitutes are of the same kind so that | |||
1473 | if we delay substitution to the result op code generation | |||
1474 | can look at the first substitute for deciding things like | |||
1475 | types of operands. */ | |||
1476 | enum id_base::id_kind kind = ids[i]->substitutes[0]->kind; | |||
1477 | for (unsigned j = 0; j < ids[i]->substitutes.length (); ++j) | |||
1478 | if (ids[i]->substitutes[j]->kind != kind) | |||
1479 | can_delay_subst = false; | |||
1480 | else if (operator_id *op | |||
1481 | = dyn_cast <operator_id *> (ids[i]->substitutes[j])) | |||
1482 | { | |||
1483 | operator_id *op0 | |||
1484 | = as_a <operator_id *> (ids[i]->substitutes[0]); | |||
1485 | if (strcmp (op->tcc, "tcc_comparison") == 0 | |||
1486 | && strcmp (op0->tcc, "tcc_comparison") == 0) | |||
1487 | ; | |||
1488 | /* Unfortunately we can't just allow all tcc_binary. */ | |||
1489 | else if (strcmp (op->tcc, "tcc_binary") == 0 | |||
1490 | && strcmp (op0->tcc, "tcc_binary") == 0 | |||
1491 | && binary_ok (op) | |||
1492 | && binary_ok (op0)) | |||
1493 | ; | |||
1494 | else if ((strcmp (op->id + 1, "SHIFT_EXPR") == 0 | |||
1495 | || strcmp (op->id + 1, "ROTATE_EXPR") == 0) | |||
1496 | && (strcmp (op0->id + 1, "SHIFT_EXPR") == 0 | |||
1497 | || strcmp (op0->id + 1, "ROTATE_EXPR") == 0)) | |||
1498 | ; | |||
1499 | else | |||
1500 | can_delay_subst = false; | |||
1501 | } | |||
1502 | else if (is_a <fn_id *> (ids[i]->substitutes[j])) | |||
1503 | ; | |||
1504 | else | |||
1505 | can_delay_subst = false; | |||
1506 | } | |||
1507 | ||||
1508 | unsigned worklist_end = worklist.length (); | |||
1509 | for (unsigned si = worklist_start; si < worklist_end; ++si) | |||
1510 | { | |||
1511 | simplify *s = worklist[si]; | |||
1512 | for (unsigned j = 0; j < max_n_opers; ++j) | |||
1513 | { | |||
1514 | operand *match_op = s->match; | |||
1515 | operand *result_op = s->result; | |||
1516 | auto_vec<std::pair<user_id *, id_base *> > subst (n_ids); | |||
1517 | bool skip = false; | |||
1518 | for (unsigned i = 0; i < n_ids; ++i) | |||
1519 | { | |||
1520 | user_id *id = ids[i]; | |||
1521 | id_base *oper = id->substitutes[j % id->substitutes.length ()]; | |||
1522 | if (oper == null_id | |||
1523 | && (contains_id (match_op, id) | |||
1524 | || contains_id (result_op, id))) | |||
1525 | { | |||
1526 | skip = true; | |||
1527 | break; | |||
1528 | } | |||
1529 | subst.quick_push (std::make_pair (id, oper)); | |||
1530 | match_op = replace_id (match_op, id, oper); | |||
1531 | if (result_op | |||
1532 | && !can_delay_subst) | |||
1533 | result_op = replace_id (result_op, id, oper); | |||
1534 | } | |||
1535 | if (skip) | |||
1536 | continue; | |||
1537 | ||||
1538 | simplify *ns = new simplify (s->kind, s->id, match_op, result_op, | |||
1539 | vNULL, s->capture_ids); | |||
1540 | ns->for_subst_vec.safe_splice (s->for_subst_vec); | |||
1541 | if (result_op | |||
1542 | && can_delay_subst) | |||
1543 | ns->for_subst_vec.safe_splice (subst); | |||
1544 | ||||
1545 | worklist.safe_push (ns); | |||
1546 | } | |||
1547 | } | |||
1548 | worklist_start = worklist_end; | |||
1549 | } | |||
1550 | ||||
1551 | /* Copy out the result from the last for lowering. */ | |||
1552 | for (unsigned i = worklist_start; i < worklist.length (); ++i) | |||
1553 | simplifiers.safe_push (worklist[i]); | |||
1554 | } | |||
1555 | ||||
1556 | /* Lower the AST for everything in SIMPLIFIERS. */ | |||
1557 | ||||
1558 | static void | |||
1559 | lower (vec<simplify *>& simplifiers, bool gimple) | |||
1560 | { | |||
1561 | auto_vec<simplify *> out_simplifiers; | |||
1562 | for (auto s: simplifiers) | |||
1563 | lower_opt (s, out_simplifiers); | |||
1564 | ||||
1565 | simplifiers.truncate (0); | |||
1566 | for (auto s: out_simplifiers) | |||
1567 | lower_commutative (s, simplifiers); | |||
1568 | ||||
1569 | /* Lower for needs to happen before lowering cond | |||
1570 | to support (for cnd (cond vec_cond)). This is | |||
1571 | safe as substitution delay does not happen for | |||
1572 | cond or vec_cond. */ | |||
1573 | out_simplifiers.truncate (0); | |||
1574 | for (auto s: simplifiers) | |||
1575 | lower_for (s, out_simplifiers); | |||
1576 | ||||
1577 | simplifiers.truncate (0); | |||
1578 | if (gimple) | |||
1579 | for (auto s: out_simplifiers) | |||
1580 | lower_cond (s, simplifiers); | |||
1581 | else | |||
1582 | simplifiers.safe_splice (out_simplifiers); | |||
1583 | } | |||
1584 | ||||
1585 | ||||
1586 | ||||
1587 | ||||
1588 | /* The decision tree built for generating GIMPLE and GENERIC pattern | |||
1589 | matching code. It represents the 'match' expression of all | |||
1590 | simplifies and has those as its leafs. */ | |||
1591 | ||||
1592 | class dt_simplify; | |||
1593 | ||||
1594 | /* A hash-map collecting semantically equivalent leafs in the decision | |||
1595 | tree for splitting out to separate functions. */ | |||
1596 | struct sinfo | |||
1597 | { | |||
1598 | dt_simplify *s; | |||
1599 | ||||
1600 | const char *fname; | |||
1601 | unsigned cnt; | |||
1602 | }; | |||
1603 | ||||
1604 | struct sinfo_hashmap_traits : simple_hashmap_traits<pointer_hash<dt_simplify>, | |||
1605 | sinfo *> | |||
1606 | { | |||
1607 | static inline hashval_t hash (const key_type &); | |||
1608 | static inline bool equal_keys (const key_type &, const key_type &); | |||
1609 | template <typename T> static inline void remove (T &) {} | |||
1610 | }; | |||
1611 | ||||
1612 | typedef hash_map<void * /* unused */, sinfo *, sinfo_hashmap_traits> | |||
1613 | sinfo_map_t; | |||
1614 | ||||
1615 | /* Current simplifier ID we are processing during insertion into the | |||
1616 | decision tree. */ | |||
1617 | static unsigned current_id; | |||
1618 | ||||
1619 | /* Decision tree base class, used for DT_NODE. */ | |||
1620 | ||||
1621 | class dt_node | |||
1622 | { | |||
1623 | public: | |||
1624 | enum dt_type { DT_NODE, DT_OPERAND, DT_TRUE, DT_MATCH, DT_SIMPLIFY }; | |||
1625 | ||||
1626 | enum dt_type type; | |||
1627 | unsigned level; | |||
1628 | dt_node *parent; | |||
1629 | vec<dt_node *> kids; | |||
1630 | ||||
1631 | /* Statistics. */ | |||
1632 | unsigned num_leafs; | |||
1633 | unsigned total_size; | |||
1634 | unsigned max_level; | |||
1635 | ||||
1636 | dt_node (enum dt_type type_, dt_node *parent_) | |||
1637 | : type (type_), level (0), parent (parent_), kids (vNULL) {} | |||
1638 | ||||
1639 | dt_node *append_node (dt_node *); | |||
1640 | dt_node *append_op (operand *, dt_node *parent, unsigned pos); | |||
1641 | dt_node *append_true_op (operand *, dt_node *parent, unsigned pos); | |||
1642 | dt_node *append_match_op (operand *, dt_operand *, dt_node *parent, | |||
1643 | unsigned pos); | |||
1644 | dt_node *append_simplify (simplify *, unsigned, dt_operand **); | |||
1645 | ||||
1646 | virtual void gen (FILE *, int, bool, int) {} | |||
1647 | ||||
1648 | void gen_kids (FILE *, int, bool, int); | |||
1649 | void gen_kids_1 (FILE *, int, bool, int, | |||
1650 | const vec<dt_operand *> &, const vec<dt_operand *> &, | |||
1651 | const vec<dt_operand *> &, const vec<dt_operand *> &, | |||
1652 | const vec<dt_operand *> &, const vec<dt_node *> &); | |||
1653 | ||||
1654 | void analyze (sinfo_map_t &); | |||
1655 | }; | |||
1656 | ||||
1657 | /* Generic decision tree node used for DT_OPERAND, DT_MATCH and DT_TRUE. */ | |||
1658 | ||||
1659 | class dt_operand : public dt_node | |||
1660 | { | |||
1661 | public: | |||
1662 | operand *op; | |||
1663 | dt_operand *match_dop; | |||
1664 | unsigned pos; | |||
1665 | bool value_match; | |||
1666 | unsigned for_id; | |||
1667 | ||||
1668 | dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_, | |||
1669 | dt_operand *parent_, unsigned pos_) | |||
1670 | : dt_node (type, parent_), op (op_), match_dop (match_dop_), | |||
1671 | pos (pos_), value_match (false), for_id (current_id) {} | |||
1672 | ||||
1673 | void gen (FILE *, int, bool, int) final override; | |||
1674 | unsigned gen_predicate (FILE *, int, const char *, bool); | |||
1675 | unsigned gen_match_op (FILE *, int, const char *, bool); | |||
1676 | ||||
1677 | unsigned gen_gimple_expr (FILE *, int, int); | |||
1678 | unsigned gen_generic_expr (FILE *, int, const char *); | |||
1679 | ||||
1680 | char *get_name (char *); | |||
1681 | void gen_opname (char *, unsigned); | |||
1682 | }; | |||
1683 | ||||
1684 | /* Leaf node of the decision tree, used for DT_SIMPLIFY. */ | |||
1685 | ||||
1686 | class dt_simplify : public dt_node | |||
1687 | { | |||
1688 | public: | |||
1689 | simplify *s; | |||
1690 | unsigned pattern_no; | |||
1691 | dt_operand **indexes; | |||
1692 | sinfo *info; | |||
1693 | ||||
1694 | dt_simplify (simplify *s_, unsigned pattern_no_, dt_operand **indexes_) | |||
1695 | : dt_node (DT_SIMPLIFY, NULLnullptr), s (s_), pattern_no (pattern_no_), | |||
1696 | indexes (indexes_), info (NULLnullptr) {} | |||
1697 | ||||
1698 | void gen_1 (FILE *, int, bool, operand *); | |||
1699 | void gen (FILE *f, int, bool, int) final override; | |||
1700 | }; | |||
1701 | ||||
1702 | template<> | |||
1703 | template<> | |||
1704 | inline bool | |||
1705 | is_a_helper <dt_operand *>::test (dt_node *n) | |||
1706 | { | |||
1707 | return (n->type == dt_node::DT_OPERAND | |||
1708 | || n->type == dt_node::DT_MATCH | |||
1709 | || n->type == dt_node::DT_TRUE); | |||
1710 | } | |||
1711 | ||||
1712 | template<> | |||
1713 | template<> | |||
1714 | inline bool | |||
1715 | is_a_helper <dt_simplify *>::test (dt_node *n) | |||
1716 | { | |||
1717 | return n->type == dt_node::DT_SIMPLIFY; | |||
1718 | } | |||
1719 | ||||
1720 | ||||
1721 | ||||
1722 | /* A container for the actual decision tree. */ | |||
1723 | ||||
1724 | class decision_tree | |||
1725 | { | |||
1726 | public: | |||
1727 | dt_node *root; | |||
1728 | ||||
1729 | void insert (class simplify *, unsigned); | |||
1730 | void gen (FILE *f, bool gimple); | |||
1731 | void print (FILE *f = stderrstderr); | |||
1732 | ||||
1733 | decision_tree () { root = new dt_node (dt_node::DT_NODE, NULLnullptr); } | |||
1734 | ||||
1735 | static dt_node *insert_operand (dt_node *, operand *, dt_operand **indexes, | |||
1736 | unsigned pos = 0, dt_node *parent = 0); | |||
1737 | static dt_node *find_node (vec<dt_node *>&, dt_node *); | |||
1738 | static bool cmp_node (dt_node *, dt_node *); | |||
1739 | static void print_node (dt_node *, FILE *f = stderrstderr, unsigned = 0); | |||
1740 | }; | |||
1741 | ||||
1742 | /* Compare two AST operands O1 and O2 and return true if they are equal. */ | |||
1743 | ||||
1744 | bool | |||
1745 | cmp_operand (operand *o1, operand *o2) | |||
1746 | { | |||
1747 | if (!o1 || !o2 || o1->type != o2->type) | |||
1748 | return false; | |||
1749 | ||||
1750 | if (o1->type == operand::OP_PREDICATE) | |||
1751 | { | |||
1752 | predicate *p1 = as_a<predicate *>(o1); | |||
1753 | predicate *p2 = as_a<predicate *>(o2); | |||
1754 | return p1->p == p2->p; | |||
1755 | } | |||
1756 | else if (o1->type == operand::OP_EXPR) | |||
1757 | { | |||
1758 | expr *e1 = static_cast<expr *>(o1); | |||
1759 | expr *e2 = static_cast<expr *>(o2); | |||
1760 | return (e1->operation == e2->operation | |||
1761 | && e1->is_generic == e2->is_generic); | |||
1762 | } | |||
1763 | else | |||
1764 | return false; | |||
1765 | } | |||
1766 | ||||
1767 | /* Compare two decision tree nodes N1 and N2 and return true if they | |||
1768 | are equal. */ | |||
1769 | ||||
1770 | bool | |||
1771 | decision_tree::cmp_node (dt_node *n1, dt_node *n2) | |||
1772 | { | |||
1773 | if (!n1 || !n2 || n1->type != n2->type) | |||
1774 | return false; | |||
1775 | ||||
1776 | if (n1 == n2) | |||
1777 | return true; | |||
1778 | ||||
1779 | if (n1->type == dt_node::DT_TRUE) | |||
1780 | return false; | |||
1781 | ||||
1782 | if (n1->type == dt_node::DT_OPERAND) | |||
1783 | return cmp_operand ((as_a<dt_operand *> (n1))->op, | |||
1784 | (as_a<dt_operand *> (n2))->op); | |||
1785 | else if (n1->type == dt_node::DT_MATCH) | |||
1786 | return (((as_a<dt_operand *> (n1))->match_dop | |||
1787 | == (as_a<dt_operand *> (n2))->match_dop) | |||
1788 | && ((as_a<dt_operand *> (n1))->value_match | |||
1789 | == (as_a<dt_operand *> (n2))->value_match)); | |||
1790 | return false; | |||
1791 | } | |||
1792 | ||||
1793 | /* Search OPS for a decision tree node like P and return it if found. */ | |||
1794 | ||||
1795 | dt_node * | |||
1796 | decision_tree::find_node (vec<dt_node *>& ops, dt_node *p) | |||
1797 | { | |||
1798 | /* We can merge adjacent DT_TRUE. */ | |||
1799 | if (p->type == dt_node::DT_TRUE | |||
1800 | && !ops.is_empty () | |||
1801 | && ops.last ()->type == dt_node::DT_TRUE) | |||
1802 | return ops.last (); | |||
1803 | dt_operand *true_node = NULLnullptr; | |||
1804 | for (int i = ops.length () - 1; i >= 0; --i) | |||
1805 | { | |||
1806 | /* But we can't merge across DT_TRUE nodes as they serve as | |||
1807 | pattern order barriers to make sure that patterns apply | |||
1808 | in order of appearance in case multiple matches are possible. */ | |||
1809 | if (ops[i]->type == dt_node::DT_TRUE) | |||
1810 | { | |||
1811 | if (! true_node | |||
1812 | || as_a <dt_operand *> (ops[i])->for_id > true_node->for_id) | |||
1813 | true_node = as_a <dt_operand *> (ops[i]); | |||
1814 | } | |||
1815 | if (decision_tree::cmp_node (ops[i], p)) | |||
1816 | { | |||
1817 | /* Unless we are processing the same pattern or the blocking | |||
1818 | pattern is before the one we are going to merge with. */ | |||
1819 | if (true_node | |||
1820 | && true_node->for_id != current_id | |||
1821 | && true_node->for_id > as_a <dt_operand *> (ops[i])->for_id) | |||
1822 | { | |||
1823 | if (verbose >= 1) | |||
1824 | { | |||
1825 | location_t p_loc = 0; | |||
1826 | if (p->type == dt_node::DT_OPERAND) | |||
1827 | p_loc = as_a <dt_operand *> (p)->op->location; | |||
1828 | location_t op_loc = 0; | |||
1829 | if (ops[i]->type == dt_node::DT_OPERAND) | |||
1830 | op_loc = as_a <dt_operand *> (ops[i])->op->location; | |||
1831 | location_t true_loc = 0; | |||
1832 | true_loc = true_node->op->location; | |||
1833 | warning_at (p_loc, | |||
1834 | "failed to merge decision tree node"); | |||
1835 | warning_at (op_loc, | |||
1836 | "with the following"); | |||
1837 | warning_at (true_loc, | |||
1838 | "because of the following which serves as ordering " | |||
1839 | "barrier"); | |||
1840 | } | |||
1841 | return NULLnullptr; | |||
1842 | } | |||
1843 | return ops[i]; | |||
1844 | } | |||
1845 | } | |||
1846 | return NULLnullptr; | |||
1847 | } | |||
1848 | ||||
1849 | /* Append N to the decision tree if it there is not already an existing | |||
1850 | identical child. */ | |||
1851 | ||||
1852 | dt_node * | |||
1853 | dt_node::append_node (dt_node *n) | |||
1854 | { | |||
1855 | dt_node *kid; | |||
1856 | ||||
1857 | kid = decision_tree::find_node (kids, n); | |||
1858 | if (kid) | |||
1859 | return kid; | |||
1860 | ||||
1861 | kids.safe_push (n); | |||
1862 | n->level = this->level + 1; | |||
1863 | ||||
1864 | return n; | |||
1865 | } | |||
1866 | ||||
1867 | /* Append OP to the decision tree. */ | |||
1868 | ||||
1869 | dt_node * | |||
1870 | dt_node::append_op (operand *op, dt_node *parent, unsigned pos) | |||
1871 | { | |||
1872 | dt_operand *parent_ = safe_as_a<dt_operand *> (parent); | |||
1873 | dt_operand *n = new dt_operand (DT_OPERAND, op, 0, parent_, pos); | |||
1874 | return append_node (n); | |||
1875 | } | |||
1876 | ||||
1877 | /* Append a DT_TRUE decision tree node. */ | |||
1878 | ||||
1879 | dt_node * | |||
1880 | dt_node::append_true_op (operand *op, dt_node *parent, unsigned pos) | |||
1881 | { | |||
1882 | dt_operand *parent_ = safe_as_a<dt_operand *> (parent); | |||
1883 | dt_operand *n = new dt_operand (DT_TRUE, op, 0, parent_, pos); | |||
1884 | return append_node (n); | |||
1885 | } | |||
1886 | ||||
1887 | /* Append a DT_MATCH decision tree node. */ | |||
1888 | ||||
1889 | dt_node * | |||
1890 | dt_node::append_match_op (operand *op, dt_operand *match_dop, | |||
1891 | dt_node *parent, unsigned pos) | |||
1892 | { | |||
1893 | dt_operand *parent_ = as_a<dt_operand *> (parent); | |||
1894 | dt_operand *n = new dt_operand (DT_MATCH, op, match_dop, parent_, pos); | |||
1895 | return append_node (n); | |||
1896 | } | |||
1897 | ||||
1898 | /* Append S to the decision tree. */ | |||
1899 | ||||
1900 | dt_node * | |||
1901 | dt_node::append_simplify (simplify *s, unsigned pattern_no, | |||
1902 | dt_operand **indexes) | |||
1903 | { | |||
1904 | dt_simplify *s2; | |||
1905 | dt_simplify *n = new dt_simplify (s, pattern_no, indexes); | |||
1906 | for (unsigned i = 0; i < kids.length (); ++i) | |||
1907 | if ((s2 = dyn_cast <dt_simplify *> (kids[i])) | |||
1908 | && (verbose >= 1 | |||
1909 | || s->match->location != s2->s->match->location)) | |||
1910 | { | |||
1911 | /* With a nested patters, it's hard to avoid these in order | |||
1912 | to keep match.pd rules relatively small. */ | |||
1913 | warning_at (s->match->location, "duplicate pattern"); | |||
1914 | warning_at (s2->s->match->location, "previous pattern defined here"); | |||
1915 | print_operand (s->match, stderrstderr); | |||
1916 | fprintf (stderrstderr, "\n"); | |||
1917 | } | |||
1918 | return append_node (n); | |||
| ||||
1919 | } | |||
1920 | ||||
1921 | /* Analyze the node and its children. */ | |||
1922 | ||||
1923 | void | |||
1924 | dt_node::analyze (sinfo_map_t &map) | |||
1925 | { | |||
1926 | num_leafs = 0; | |||
1927 | total_size = 1; | |||
1928 | max_level = level; | |||
1929 | ||||
1930 | if (type == DT_SIMPLIFY) | |||
1931 | { | |||
1932 | /* Populate the map of equivalent simplifies. */ | |||
1933 | dt_simplify *s = as_a <dt_simplify *> (this); | |||
1934 | bool existed; | |||
1935 | sinfo *&si = map.get_or_insert (s, &existed); | |||
1936 | if (!existed) | |||
1937 | { | |||
1938 | si = new sinfo; | |||
1939 | si->s = s; | |||
1940 | si->cnt = 1; | |||
1941 | si->fname = NULLnullptr; | |||
1942 | } | |||
1943 | else | |||
1944 | si->cnt++; | |||
1945 | s->info = si; | |||
1946 | num_leafs = 1; | |||
1947 | return; | |||
1948 | } | |||
1949 | ||||
1950 | for (unsigned i = 0; i < kids.length (); ++i) | |||
1951 | { | |||
1952 | kids[i]->analyze (map); | |||
1953 | num_leafs += kids[i]->num_leafs; | |||
1954 | total_size += kids[i]->total_size; | |||
1955 | max_level = MAX (max_level, kids[i]->max_level)((max_level) > (kids[i]->max_level) ? (max_level) : (kids [i]->max_level)); | |||
1956 | } | |||
1957 | } | |||
1958 | ||||
1959 | /* Insert O into the decision tree and return the decision tree node found | |||
1960 | or created. */ | |||
1961 | ||||
1962 | dt_node * | |||
1963 | decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes, | |||
1964 | unsigned pos, dt_node *parent) | |||
1965 | { | |||
1966 | dt_node *q, *elm = 0; | |||
1967 | ||||
1968 | if (capture *c = dyn_cast<capture *> (o)) | |||
1969 | { | |||
1970 | unsigned capt_index = c->where; | |||
1971 | ||||
1972 | if (indexes[capt_index] == 0) | |||
1973 | { | |||
1974 | if (c->what) | |||
1975 | q = insert_operand (p, c->what, indexes, pos, parent); | |||
1976 | else | |||
1977 | { | |||
1978 | q = elm = p->append_true_op (o, parent, pos); | |||
1979 | goto at_assert_elm; | |||
1980 | } | |||
1981 | // get to the last capture | |||
1982 | for (operand *what = c->what; | |||
1983 | what && is_a<capture *> (what); | |||
1984 | c = as_a<capture *> (what), what = c->what) | |||
1985 | ; | |||
1986 | ||||
1987 | if (!c->what) | |||
1988 | { | |||
1989 | unsigned cc_index = c->where; | |||
1990 | dt_operand *match_op = indexes[cc_index]; | |||
1991 | ||||
1992 | dt_operand temp (dt_node::DT_TRUE, 0, 0, 0, 0); | |||
1993 | elm = decision_tree::find_node (p->kids, &temp); | |||
1994 | ||||
1995 | if (elm == 0) | |||
1996 | { | |||
1997 | dt_operand match (dt_node::DT_MATCH, 0, match_op, 0, 0); | |||
1998 | match.value_match = c->value_match; | |||
1999 | elm = decision_tree::find_node (p->kids, &match); | |||
2000 | } | |||
2001 | } | |||
2002 | else | |||
2003 | { | |||
2004 | dt_operand temp (dt_node::DT_OPERAND, c->what, 0, 0, 0); | |||
2005 | elm = decision_tree::find_node (p->kids, &temp); | |||
2006 | } | |||
2007 | ||||
2008 | at_assert_elm: | |||
2009 | gcc_assert (elm->type == dt_node::DT_TRUE((void)(!(elm->type == dt_node::DT_TRUE || elm->type == dt_node::DT_OPERAND || elm->type == dt_node::DT_MATCH) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2011, __FUNCTION__), 0 : 0)) | |||
2010 | || elm->type == dt_node::DT_OPERAND((void)(!(elm->type == dt_node::DT_TRUE || elm->type == dt_node::DT_OPERAND || elm->type == dt_node::DT_MATCH) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2011, __FUNCTION__), 0 : 0)) | |||
2011 | || elm->type == dt_node::DT_MATCH)((void)(!(elm->type == dt_node::DT_TRUE || elm->type == dt_node::DT_OPERAND || elm->type == dt_node::DT_MATCH) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2011, __FUNCTION__), 0 : 0)); | |||
2012 | indexes[capt_index] = static_cast<dt_operand *> (elm); | |||
2013 | return q; | |||
2014 | } | |||
2015 | else | |||
2016 | { | |||
2017 | p = p->append_match_op (o, indexes[capt_index], parent, pos); | |||
2018 | as_a <dt_operand *>(p)->value_match = c->value_match; | |||
2019 | if (c->what) | |||
2020 | return insert_operand (p, c->what, indexes, 0, p); | |||
2021 | else | |||
2022 | return p; | |||
2023 | } | |||
2024 | } | |||
2025 | p = p->append_op (o, parent, pos); | |||
2026 | q = p; | |||
2027 | ||||
2028 | if (expr *e = dyn_cast <expr *>(o)) | |||
2029 | { | |||
2030 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
2031 | q = decision_tree::insert_operand (q, e->ops[i], indexes, i, p); | |||
2032 | } | |||
2033 | ||||
2034 | return q; | |||
2035 | } | |||
2036 | ||||
2037 | /* Insert S into the decision tree. */ | |||
2038 | ||||
2039 | void | |||
2040 | decision_tree::insert (class simplify *s, unsigned pattern_no) | |||
2041 | { | |||
2042 | current_id = s->id; | |||
2043 | dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1)((dt_operand * *) xcalloc ((s->capture_max + 1), sizeof (dt_operand *))); | |||
2044 | dt_node *p = decision_tree::insert_operand (root, s->match, indexes); | |||
2045 | p->append_simplify (s, pattern_no, indexes); | |||
| ||||
2046 | } | |||
2047 | ||||
2048 | /* Debug functions to dump the decision tree. */ | |||
2049 | ||||
2050 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
2051 | decision_tree::print_node (dt_node *p, FILE *f, unsigned indent) | |||
2052 | { | |||
2053 | if (p->type == dt_node::DT_NODE) | |||
2054 | fprintf (f, "root"); | |||
2055 | else | |||
2056 | { | |||
2057 | fprintf (f, "|"); | |||
2058 | for (unsigned i = 0; i < indent; i++) | |||
2059 | fprintf (f, "-"); | |||
2060 | ||||
2061 | if (p->type == dt_node::DT_OPERAND) | |||
2062 | { | |||
2063 | dt_operand *dop = static_cast<dt_operand *>(p); | |||
2064 | print_operand (dop->op, f, true); | |||
2065 | } | |||
2066 | else if (p->type == dt_node::DT_TRUE) | |||
2067 | fprintf (f, "true"); | |||
2068 | else if (p->type == dt_node::DT_MATCH) | |||
2069 | fprintf (f, "match (%p)", (void *)((as_a<dt_operand *>(p))->match_dop)); | |||
2070 | else if (p->type == dt_node::DT_SIMPLIFY) | |||
2071 | { | |||
2072 | dt_simplify *s = static_cast<dt_simplify *> (p); | |||
2073 | fprintf (f, "simplify_%u { ", s->pattern_no); | |||
2074 | for (int i = 0; i <= s->s->capture_max; ++i) | |||
2075 | fprintf (f, "%p, ", (void *) s->indexes[i]); | |||
2076 | fprintf (f, " } "); | |||
2077 | } | |||
2078 | if (is_a <dt_operand *> (p)) | |||
2079 | fprintf (f, " [%u]", as_a <dt_operand *> (p)->for_id); | |||
2080 | } | |||
2081 | ||||
2082 | fprintf (stderrstderr, " (%p, %p), %u, %u\n", | |||
2083 | (void *) p, (void *) p->parent, p->level, p->kids.length ()); | |||
2084 | ||||
2085 | for (unsigned i = 0; i < p->kids.length (); ++i) | |||
2086 | decision_tree::print_node (p->kids[i], f, indent + 2); | |||
2087 | } | |||
2088 | ||||
2089 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
2090 | decision_tree::print (FILE *f) | |||
2091 | { | |||
2092 | return decision_tree::print_node (root, f); | |||
2093 | } | |||
2094 | ||||
2095 | ||||
2096 | /* For GENERIC we have to take care of wrapping multiple-used | |||
2097 | expressions with side-effects in save_expr and preserve side-effects | |||
2098 | of expressions with omit_one_operand. Analyze captures in | |||
2099 | match, result and with expressions and perform early-outs | |||
2100 | on the outermost match expression operands for cases we cannot | |||
2101 | handle. */ | |||
2102 | ||||
2103 | class capture_info | |||
2104 | { | |||
2105 | public: | |||
2106 | capture_info (simplify *s, operand *, bool); | |||
2107 | void walk_match (operand *o, unsigned toplevel_arg, bool, bool); | |||
2108 | bool walk_result (operand *o, bool, operand *); | |||
2109 | void walk_c_expr (c_expr *); | |||
2110 | ||||
2111 | struct cinfo | |||
2112 | { | |||
2113 | bool expr_p; | |||
2114 | bool cse_p; | |||
2115 | bool force_no_side_effects_p; | |||
2116 | bool force_single_use; | |||
2117 | bool cond_expr_cond_p; | |||
2118 | unsigned long toplevel_msk; | |||
2119 | unsigned match_use_count; | |||
2120 | unsigned result_use_count; | |||
2121 | unsigned same_as; | |||
2122 | capture *c; | |||
2123 | }; | |||
2124 | ||||
2125 | auto_vec<cinfo> info; | |||
2126 | unsigned long force_no_side_effects; | |||
2127 | bool gimple; | |||
2128 | }; | |||
2129 | ||||
2130 | /* Analyze captures in S. */ | |||
2131 | ||||
2132 | capture_info::capture_info (simplify *s, operand *result, bool gimple_) | |||
2133 | { | |||
2134 | gimple = gimple_; | |||
2135 | ||||
2136 | expr *e; | |||
2137 | if (s->kind == simplify::MATCH) | |||
2138 | { | |||
2139 | force_no_side_effects = -1; | |||
2140 | return; | |||
2141 | } | |||
2142 | ||||
2143 | force_no_side_effects = 0; | |||
2144 | info.safe_grow_cleared (s->capture_max + 1, true); | |||
2145 | for (int i = 0; i <= s->capture_max; ++i) | |||
2146 | info[i].same_as = i; | |||
2147 | ||||
2148 | e = as_a <expr *> (s->match); | |||
2149 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
2150 | walk_match (e->ops[i], i, | |||
2151 | (i != 0 && *e->operation == COND_EXPR) | |||
2152 | || *e->operation == TRUTH_ANDIF_EXPR | |||
2153 | || *e->operation == TRUTH_ORIF_EXPR, | |||
2154 | i == 0 && *e->operation == COND_EXPR); | |||
2155 | ||||
2156 | walk_result (s->result, false, result); | |||
2157 | } | |||
2158 | ||||
2159 | /* Analyze captures in the match expression piece O. */ | |||
2160 | ||||
2161 | void | |||
2162 | capture_info::walk_match (operand *o, unsigned toplevel_arg, | |||
2163 | bool conditional_p, bool cond_expr_cond_p) | |||
2164 | { | |||
2165 | if (capture *c = dyn_cast <capture *> (o)) | |||
2166 | { | |||
2167 | unsigned where = c->where; | |||
2168 | info[where].match_use_count++; | |||
2169 | info[where].toplevel_msk |= 1 << toplevel_arg; | |||
2170 | info[where].force_no_side_effects_p |= conditional_p; | |||
2171 | info[where].cond_expr_cond_p |= cond_expr_cond_p; | |||
2172 | if (!info[where].c) | |||
2173 | info[where].c = c; | |||
2174 | if (!c->what) | |||
2175 | return; | |||
2176 | /* Recurse to exprs and captures. */ | |||
2177 | if (is_a <capture *> (c->what) | |||
2178 | || is_a <expr *> (c->what)) | |||
2179 | walk_match (c->what, toplevel_arg, conditional_p, false); | |||
2180 | /* We need to look past multiple captures to find a captured | |||
2181 | expression as with conditional converts two captures | |||
2182 | can be collapsed onto the same expression. Also collect | |||
2183 | what captures capture the same thing. */ | |||
2184 | while (c->what && is_a <capture *> (c->what)) | |||
2185 | { | |||
2186 | c = as_a <capture *> (c->what); | |||
2187 | if (info[c->where].same_as != c->where | |||
2188 | && info[c->where].same_as != info[where].same_as) | |||
2189 | fatal_at (c->location, "cannot handle this collapsed capture"); | |||
2190 | info[c->where].same_as = info[where].same_as; | |||
2191 | } | |||
2192 | /* Mark expr (non-leaf) captures and forced single-use exprs. */ | |||
2193 | expr *e; | |||
2194 | if (c->what | |||
2195 | && (e = dyn_cast <expr *> (c->what))) | |||
2196 | { | |||
2197 | /* Zero-operand expression captures like ADDR_EXPR@0 are | |||
2198 | similar as predicates -- if they are not mentioned in | |||
2199 | the result we have to force them to have no side-effects. */ | |||
2200 | if (e->ops.length () != 0) | |||
2201 | info[where].expr_p = true; | |||
2202 | info[where].force_single_use |= e->force_single_use; | |||
2203 | } | |||
2204 | } | |||
2205 | else if (expr *e = dyn_cast <expr *> (o)) | |||
2206 | { | |||
2207 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
2208 | { | |||
2209 | bool cond_p = conditional_p; | |||
2210 | bool expr_cond_p = false; | |||
2211 | if (i != 0 && *e->operation == COND_EXPR) | |||
2212 | cond_p = true; | |||
2213 | else if (*e->operation == TRUTH_ANDIF_EXPR | |||
2214 | || *e->operation == TRUTH_ORIF_EXPR) | |||
2215 | cond_p = true; | |||
2216 | if (i == 0 | |||
2217 | && *e->operation == COND_EXPR) | |||
2218 | expr_cond_p = true; | |||
2219 | walk_match (e->ops[i], toplevel_arg, cond_p, expr_cond_p); | |||
2220 | } | |||
2221 | } | |||
2222 | else if (is_a <predicate *> (o)) | |||
2223 | { | |||
2224 | /* Mark non-captured leafs toplevel arg for checking. */ | |||
2225 | force_no_side_effects |= 1 << toplevel_arg; | |||
2226 | if (verbose >= 1 | |||
2227 | && !gimple) | |||
2228 | warning_at (o->location, | |||
2229 | "forcing no side-effects on possibly lost leaf"); | |||
2230 | } | |||
2231 | else | |||
2232 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2232, __FUNCTION__)); | |||
2233 | } | |||
2234 | ||||
2235 | /* Analyze captures in the result expression piece O. Return true | |||
2236 | if RESULT was visited in one of the children. Only visit | |||
2237 | non-if/with children if they are rooted on RESULT. */ | |||
2238 | ||||
2239 | bool | |||
2240 | capture_info::walk_result (operand *o, bool conditional_p, operand *result) | |||
2241 | { | |||
2242 | if (capture *c = dyn_cast <capture *> (o)) | |||
2243 | { | |||
2244 | unsigned where = info[c->where].same_as; | |||
2245 | info[where].result_use_count++; | |||
2246 | /* If we substitute an expression capture we don't know | |||
2247 | which captures this will end up using (well, we don't | |||
2248 | compute that). Force the uses to be side-effect free | |||
2249 | which means forcing the toplevels that reach the | |||
2250 | expression side-effect free. */ | |||
2251 | if (info[where].expr_p) | |||
2252 | force_no_side_effects |= info[where].toplevel_msk; | |||
2253 | /* Mark CSE capture uses as forced to have no side-effects. */ | |||
2254 | if (c->what | |||
2255 | && is_a <expr *> (c->what)) | |||
2256 | { | |||
2257 | info[where].cse_p = true; | |||
2258 | walk_result (c->what, true, result); | |||
2259 | } | |||
2260 | } | |||
2261 | else if (expr *e = dyn_cast <expr *> (o)) | |||
2262 | { | |||
2263 | id_base *opr = e->operation; | |||
2264 | if (user_id *uid = dyn_cast <user_id *> (opr)) | |||
2265 | opr = uid->substitutes[0]; | |||
2266 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
2267 | { | |||
2268 | bool cond_p = conditional_p; | |||
2269 | if (i != 0 && *e->operation == COND_EXPR) | |||
2270 | cond_p = true; | |||
2271 | else if (*e->operation == TRUTH_ANDIF_EXPR | |||
2272 | || *e->operation == TRUTH_ORIF_EXPR) | |||
2273 | cond_p = true; | |||
2274 | walk_result (e->ops[i], cond_p, result); | |||
2275 | } | |||
2276 | } | |||
2277 | else if (if_expr *ie = dyn_cast <if_expr *> (o)) | |||
2278 | { | |||
2279 | /* 'if' conditions should be all fine. */ | |||
2280 | if (ie->trueexpr == result) | |||
2281 | { | |||
2282 | walk_result (ie->trueexpr, false, result); | |||
2283 | return true; | |||
2284 | } | |||
2285 | if (ie->falseexpr == result) | |||
2286 | { | |||
2287 | walk_result (ie->falseexpr, false, result); | |||
2288 | return true; | |||
2289 | } | |||
2290 | bool res = false; | |||
2291 | if (is_a <if_expr *> (ie->trueexpr) | |||
2292 | || is_a <with_expr *> (ie->trueexpr)) | |||
2293 | res |= walk_result (ie->trueexpr, false, result); | |||
2294 | if (ie->falseexpr | |||
2295 | && (is_a <if_expr *> (ie->falseexpr) | |||
2296 | || is_a <with_expr *> (ie->falseexpr))) | |||
2297 | res |= walk_result (ie->falseexpr, false, result); | |||
2298 | return res; | |||
2299 | } | |||
2300 | else if (with_expr *we = dyn_cast <with_expr *> (o)) | |||
2301 | { | |||
2302 | bool res = (we->subexpr == result); | |||
2303 | if (res | |||
2304 | || is_a <if_expr *> (we->subexpr) | |||
2305 | || is_a <with_expr *> (we->subexpr)) | |||
2306 | res |= walk_result (we->subexpr, false, result); | |||
2307 | if (res) | |||
2308 | walk_c_expr (we->with); | |||
2309 | return res; | |||
2310 | } | |||
2311 | else if (c_expr *ce = dyn_cast <c_expr *> (o)) | |||
2312 | walk_c_expr (ce); | |||
2313 | else | |||
2314 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2314, __FUNCTION__)); | |||
2315 | ||||
2316 | return false; | |||
2317 | } | |||
2318 | ||||
2319 | /* Look for captures in the C expr E. */ | |||
2320 | ||||
2321 | void | |||
2322 | capture_info::walk_c_expr (c_expr *e) | |||
2323 | { | |||
2324 | /* Give up for C exprs mentioning captures not inside TREE_TYPE, | |||
2325 | TREE_REAL_CST, TREE_CODE or a predicate where they cannot | |||
2326 | really escape through. */ | |||
2327 | unsigned p_depth = 0; | |||
2328 | for (unsigned i = 0; i < e->code.length (); ++i) | |||
2329 | { | |||
2330 | const cpp_token *t = &e->code[i]; | |||
2331 | const cpp_token *n = i < e->code.length () - 1 ? &e->code[i+1] : NULLnullptr; | |||
2332 | id_base *id; | |||
2333 | if (t->type == CPP_NAME | |||
2334 | && (strcmp ((const char *)CPP_HASHNODE((cpp_hashnode *) (t->val.node.node)) | |||
2335 | (t->val.node.node)((cpp_hashnode *) (t->val.node.node))->ident.str, "TREE_TYPE") == 0 | |||
2336 | || strcmp ((const char *)CPP_HASHNODE((cpp_hashnode *) (t->val.node.node)) | |||
2337 | (t->val.node.node)((cpp_hashnode *) (t->val.node.node))->ident.str, "TREE_CODE") == 0 | |||
2338 | || strcmp ((const char *)CPP_HASHNODE((cpp_hashnode *) (t->val.node.node)) | |||
2339 | (t->val.node.node)((cpp_hashnode *) (t->val.node.node))->ident.str, "TREE_REAL_CST") == 0 | |||
2340 | || ((id = get_operator ((const char *)CPP_HASHNODE((cpp_hashnode *) (t->val.node.node)) | |||
2341 | (t->val.node.node)((cpp_hashnode *) (t->val.node.node))->ident.str)) | |||
2342 | && is_a <predicate_id *> (id))) | |||
2343 | && n->type == CPP_OPEN_PAREN) | |||
2344 | p_depth++; | |||
2345 | else if (t->type == CPP_CLOSE_PAREN | |||
2346 | && p_depth > 0) | |||
2347 | p_depth--; | |||
2348 | else if (p_depth == 0 | |||
2349 | && t->type == CPP_ATSIGN | |||
2350 | && (n->type == CPP_NUMBER | |||
2351 | || n->type == CPP_NAME) | |||
2352 | && !(n->flags & PREV_WHITE(1 << 0))) | |||
2353 | { | |||
2354 | const char *id1; | |||
2355 | if (n->type == CPP_NUMBER) | |||
2356 | id1 = (const char *)n->val.str.text; | |||
2357 | else | |||
2358 | id1 = (const char *)CPP_HASHNODE (n->val.node.node)((cpp_hashnode *) (n->val.node.node))->ident.str; | |||
2359 | unsigned *where = e->capture_ids->get(id1); | |||
2360 | if (! where) | |||
2361 | fatal_at (n, "unknown capture id '%s'", id1); | |||
2362 | info[info[*where].same_as].force_no_side_effects_p = true; | |||
2363 | if (verbose >= 1 | |||
2364 | && !gimple) | |||
2365 | warning_at (t, "capture escapes"); | |||
2366 | } | |||
2367 | } | |||
2368 | } | |||
2369 | ||||
2370 | ||||
2371 | /* The current label failing the current matched pattern during | |||
2372 | code generation. */ | |||
2373 | static char *fail_label; | |||
2374 | ||||
2375 | /* Code generation off the decision tree and the refered AST nodes. */ | |||
2376 | ||||
2377 | bool | |||
2378 | is_conversion (id_base *op) | |||
2379 | { | |||
2380 | return (*op == CONVERT_EXPR | |||
2381 | || *op == NOP_EXPR | |||
2382 | || *op == FLOAT_EXPR | |||
2383 | || *op == FIX_TRUNC_EXPR | |||
2384 | || *op == VIEW_CONVERT_EXPR); | |||
2385 | } | |||
2386 | ||||
2387 | /* Get the type to be used for generating operand POS of OP from the | |||
2388 | various sources. */ | |||
2389 | ||||
2390 | static const char * | |||
2391 | get_operand_type (id_base *op, unsigned pos, | |||
2392 | const char *in_type, | |||
2393 | const char *expr_type, | |||
2394 | const char *other_oprnd_type) | |||
2395 | { | |||
2396 | /* Generally operands whose type does not match the type of the | |||
2397 | expression generated need to know their types but match and | |||
2398 | thus can fall back to 'other_oprnd_type'. */ | |||
2399 | if (is_conversion (op)) | |||
2400 | return other_oprnd_type; | |||
2401 | else if (*op == REALPART_EXPR | |||
2402 | || *op == IMAGPART_EXPR) | |||
2403 | return other_oprnd_type; | |||
2404 | else if (is_a <operator_id *> (op) | |||
2405 | && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0) | |||
2406 | return other_oprnd_type; | |||
2407 | else if (*op == COND_EXPR | |||
2408 | && pos == 0) | |||
2409 | return "boolean_type_node"; | |||
2410 | else if (startswith (op->id, "CFN_COND_")) | |||
2411 | { | |||
2412 | /* IFN_COND_* operands 1 and later by default have the same type | |||
2413 | as the result. The type of operand 0 needs to be specified | |||
2414 | explicitly. */ | |||
2415 | if (pos > 0 && expr_type) | |||
2416 | return expr_type; | |||
2417 | else if (pos > 0 && in_type) | |||
2418 | return in_type; | |||
2419 | else | |||
2420 | return NULLnullptr; | |||
2421 | } | |||
2422 | else | |||
2423 | { | |||
2424 | /* Otherwise all types should match - choose one in order of | |||
2425 | preference. */ | |||
2426 | if (expr_type) | |||
2427 | return expr_type; | |||
2428 | else if (in_type) | |||
2429 | return in_type; | |||
2430 | else | |||
2431 | return other_oprnd_type; | |||
2432 | } | |||
2433 | } | |||
2434 | ||||
2435 | /* Generate transform code for an expression. */ | |||
2436 | ||||
2437 | void | |||
2438 | expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, | |||
2439 | int depth, const char *in_type, capture_info *cinfo, | |||
2440 | dt_operand **indexes, int) | |||
2441 | { | |||
2442 | id_base *opr = operation; | |||
2443 | /* When we delay operator substituting during lowering of fors we | |||
2444 | make sure that for code-gen purposes the effects of each substitute | |||
2445 | are the same. Thus just look at that. */ | |||
2446 | if (user_id *uid = dyn_cast <user_id *> (opr)) | |||
2447 | opr = uid->substitutes[0]; | |||
2448 | ||||
2449 | bool conversion_p = is_conversion (opr); | |||
2450 | const char *type = expr_type; | |||
2451 | char optype[64]; | |||
2452 | if (type) | |||
2453 | /* If there was a type specification in the pattern use it. */ | |||
2454 | ; | |||
2455 | else if (conversion_p) | |||
2456 | /* For conversions we need to build the expression using the | |||
2457 | outer type passed in. */ | |||
2458 | type = in_type; | |||
2459 | else if (*opr == REALPART_EXPR | |||
2460 | || *opr == IMAGPART_EXPR) | |||
2461 | { | |||
2462 | /* __real and __imag use the component type of its operand. */ | |||
2463 | snprintf (optype, sizeof (optype), "TREE_TYPE (TREE_TYPE (_o%d[0]))", | |||
2464 | depth); | |||
2465 | type = optype; | |||
2466 | } | |||
2467 | else if (is_a <operator_id *> (opr) | |||
2468 | && !strcmp (as_a <operator_id *> (opr)->tcc, "tcc_comparison")) | |||
2469 | { | |||
2470 | /* comparisons use boolean_type_node (or what gets in), but | |||
2471 | their operands need to figure out the types themselves. */ | |||
2472 | if (in_type) | |||
2473 | type = in_type; | |||
2474 | else | |||
2475 | { | |||
2476 | snprintf (optype, sizeof (optype), "boolean_type_node"); | |||
2477 | type = optype; | |||
2478 | } | |||
2479 | in_type = NULLnullptr; | |||
2480 | } | |||
2481 | else if (*opr == COND_EXPR | |||
2482 | || *opr == VEC_COND_EXPR | |||
2483 | || startswith (opr->id, "CFN_COND_")) | |||
2484 | { | |||
2485 | /* Conditions are of the same type as their first alternative. */ | |||
2486 | snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[1])", depth); | |||
2487 | type = optype; | |||
2488 | } | |||
2489 | else | |||
2490 | { | |||
2491 | /* Other operations are of the same type as their first operand. */ | |||
2492 | snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[0])", depth); | |||
2493 | type = optype; | |||
2494 | } | |||
2495 | if (!type) | |||
2496 | fatal_at (location, "cannot determine type of operand"); | |||
2497 | ||||
2498 | fprintf_indent (f, indent, "{\n"); | |||
2499 | indent += 2; | |||
2500 | fprintf_indent (f, indent, | |||
2501 | "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth); | |||
2502 | char op0type[64]; | |||
2503 | snprintf (op0type, sizeof (op0type), "TREE_TYPE (_o%d[0])", depth); | |||
2504 | for (unsigned i = 0; i < ops.length (); ++i) | |||
2505 | { | |||
2506 | char dest1[32]; | |||
2507 | snprintf (dest1, sizeof (dest1), "_o%d[%u]", depth, i); | |||
2508 | const char *optype1 | |||
2509 | = get_operand_type (opr, i, in_type, expr_type, | |||
2510 | i == 0 ? NULLnullptr : op0type); | |||
2511 | ops[i]->gen_transform (f, indent, dest1, gimple, depth + 1, optype1, | |||
2512 | cinfo, indexes, | |||
2513 | *opr == COND_EXPR && i == 0 ? 1 : 2); | |||
2514 | } | |||
2515 | ||||
2516 | const char *opr_name; | |||
2517 | if (*operation == CONVERT_EXPR) | |||
2518 | opr_name = "NOP_EXPR"; | |||
2519 | else | |||
2520 | opr_name = operation->id; | |||
2521 | ||||
2522 | if (gimple) | |||
2523 | { | |||
2524 | if (*opr == CONVERT_EXPR) | |||
2525 | { | |||
2526 | fprintf_indent (f, indent, | |||
2527 | "if (%s != TREE_TYPE (_o%d[0])\n", | |||
2528 | type, depth); | |||
2529 | fprintf_indent (f, indent, | |||
2530 | " && !useless_type_conversion_p (%s, TREE_TYPE " | |||
2531 | "(_o%d[0])))\n", | |||
2532 | type, depth); | |||
2533 | fprintf_indent (f, indent + 2, "{\n"); | |||
2534 | indent += 4; | |||
2535 | } | |||
2536 | /* ??? Building a stmt can fail for various reasons here, seq being | |||
2537 | NULL or the stmt referencing SSA names occuring in abnormal PHIs. | |||
2538 | So if we fail here we should continue matching other patterns. */ | |||
2539 | fprintf_indent (f, indent, "gimple_match_op tem_op " | |||
2540 | "(res_op->cond.any_else (), %s, %s", opr_name, type); | |||
2541 | for (unsigned i = 0; i < ops.length (); ++i) | |||
2542 | fprintf (f, ", _o%d[%u]", depth, i); | |||
2543 | fprintf (f, ");\n"); | |||
2544 | fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize);\n", | |||
2545 | !force_leaf ? "lseq" : "NULL"); | |||
2546 | fprintf_indent (f, indent, | |||
2547 | "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n", depth, | |||
2548 | !force_leaf ? "lseq" : "NULL"); | |||
2549 | fprintf_indent (f, indent, | |||
2550 | "if (!_r%d) goto %s;\n", | |||
2551 | depth, fail_label); | |||
2552 | if (*opr == CONVERT_EXPR) | |||
2553 | { | |||
2554 | indent -= 4; | |||
2555 | fprintf_indent (f, indent, " }\n"); | |||
2556 | fprintf_indent (f, indent, "else\n"); | |||
2557 | fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth); | |||
2558 | } | |||
2559 | } | |||
2560 | else | |||
2561 | { | |||
2562 | if (*opr == CONVERT_EXPR) | |||
2563 | { | |||
2564 | fprintf_indent (f, indent, "if (TREE_TYPE (_o%d[0]) != %s)\n", | |||
2565 | depth, type); | |||
2566 | indent += 2; | |||
2567 | } | |||
2568 | if (opr->kind == id_base::CODE) | |||
2569 | fprintf_indent (f, indent, "_r%d = fold_build%d_loc (loc, %s, %s", | |||
2570 | depth, ops.length(), opr_name, type); | |||
2571 | else | |||
2572 | fprintf_indent (f, indent, "_r%d = maybe_build_call_expr_loc (loc, " | |||
2573 | "%s, %s, %d", depth, opr_name, type, ops.length()); | |||
2574 | for (unsigned i = 0; i < ops.length (); ++i) | |||
2575 | fprintf (f, ", _o%d[%u]", depth, i); | |||
2576 | fprintf (f, ");\n"); | |||
2577 | if (opr->kind != id_base::CODE) | |||
2578 | { | |||
2579 | fprintf_indent (f, indent, "if (!_r%d)\n", depth); | |||
2580 | fprintf_indent (f, indent, " goto %s;\n", fail_label); | |||
2581 | } | |||
2582 | if (force_leaf) | |||
2583 | { | |||
2584 | fprintf_indent (f, indent, "if (EXPR_P (_r%d))\n", depth); | |||
2585 | fprintf_indent (f, indent, " goto %s;\n", fail_label); | |||
2586 | } | |||
2587 | if (*opr == CONVERT_EXPR) | |||
2588 | { | |||
2589 | indent -= 2; | |||
2590 | fprintf_indent (f, indent, "else\n"); | |||
2591 | fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth); | |||
2592 | } | |||
2593 | } | |||
2594 | fprintf_indent (f, indent, "%s = _r%d;\n", dest, depth); | |||
2595 | indent -= 2; | |||
2596 | fprintf_indent (f, indent, "}\n"); | |||
2597 | } | |||
2598 | ||||
2599 | /* Generate code for a c_expr which is either the expression inside | |||
2600 | an if statement or a sequence of statements which computes a | |||
2601 | result to be stored to DEST. */ | |||
2602 | ||||
2603 | void | |||
2604 | c_expr::gen_transform (FILE *f, int indent, const char *dest, | |||
2605 | bool, int, const char *, capture_info *, | |||
2606 | dt_operand **, int) | |||
2607 | { | |||
2608 | if (dest && nr_stmts == 1) | |||
2609 | fprintf_indent (f, indent, "%s = ", dest); | |||
2610 | ||||
2611 | unsigned stmt_nr = 1; | |||
2612 | int prev_line = -1; | |||
2613 | for (unsigned i = 0; i < code.length (); ++i) | |||
2614 | { | |||
2615 | const cpp_token *token = &code[i]; | |||
2616 | ||||
2617 | /* We can't recover from all lexing losses but we can roughly restore line | |||
2618 | breaks from location info. */ | |||
2619 | const line_map_ordinary *map; | |||
2620 | linemap_resolve_location (line_table, token->src_loc, | |||
2621 | LRK_SPELLING_LOCATION, &map); | |||
2622 | expanded_location loc = linemap_expand_location (line_table, map, | |||
2623 | token->src_loc); | |||
2624 | if (prev_line != -1 && loc.line != prev_line) | |||
2625 | fputc ('\n', f)fputc_unlocked ('\n', f); | |||
2626 | prev_line = loc.line; | |||
2627 | ||||
2628 | /* Replace captures for code-gen. */ | |||
2629 | if (token->type == CPP_ATSIGN) | |||
2630 | { | |||
2631 | const cpp_token *n = &code[i+1]; | |||
2632 | if ((n->type == CPP_NUMBER | |||
2633 | || n->type == CPP_NAME) | |||
2634 | && !(n->flags & PREV_WHITE(1 << 0))) | |||
2635 | { | |||
2636 | if (token->flags & PREV_WHITE(1 << 0)) | |||
2637 | fputc (' ', f)fputc_unlocked (' ', f); | |||
2638 | const char *id; | |||
2639 | if (n->type == CPP_NUMBER) | |||
2640 | id = (const char *)n->val.str.text; | |||
2641 | else | |||
2642 | id = (const char *)CPP_HASHNODE (n->val.node.node)((cpp_hashnode *) (n->val.node.node))->ident.str; | |||
2643 | unsigned *cid = capture_ids->get (id); | |||
2644 | if (!cid) | |||
2645 | fatal_at (token, "unknown capture id"); | |||
2646 | fprintf (f, "captures[%u]", *cid); | |||
2647 | ++i; | |||
2648 | continue; | |||
2649 | } | |||
2650 | } | |||
2651 | ||||
2652 | if (token->flags & PREV_WHITE(1 << 0)) | |||
2653 | fputc (' ', f)fputc_unlocked (' ', f); | |||
2654 | ||||
2655 | if (token->type == CPP_NAME) | |||
2656 | { | |||
2657 | const char *id = (const char *) NODE_NAME (token->val.node.node)(((&(token->val.node.node)->ident))->str); | |||
2658 | unsigned j; | |||
2659 | for (j = 0; j < ids.length (); ++j) | |||
2660 | { | |||
2661 | if (strcmp (id, ids[j].id) == 0) | |||
2662 | { | |||
2663 | fprintf (f, "%s", ids[j].oper); | |||
2664 | break; | |||
2665 | } | |||
2666 | } | |||
2667 | if (j < ids.length ()) | |||
2668 | continue; | |||
2669 | } | |||
2670 | ||||
2671 | /* Output the token as string. */ | |||
2672 | char *tk = (char *)cpp_token_as_text (r, token); | |||
2673 | fputs (tk, f)fputs_unlocked (tk, f); | |||
2674 | ||||
2675 | if (token->type == CPP_SEMICOLON) | |||
2676 | { | |||
2677 | stmt_nr++; | |||
2678 | if (dest && stmt_nr == nr_stmts) | |||
2679 | fprintf_indent (f, indent, "%s = ", dest); | |||
2680 | } | |||
2681 | } | |||
2682 | fputc ('\n', f)fputc_unlocked ('\n', f); | |||
2683 | } | |||
2684 | ||||
2685 | /* Generate transform code for a capture. */ | |||
2686 | ||||
2687 | void | |||
2688 | capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple, | |||
2689 | int depth, const char *in_type, capture_info *cinfo, | |||
2690 | dt_operand **indexes, int cond_handling) | |||
2691 | { | |||
2692 | if (what && is_a<expr *> (what)) | |||
2693 | { | |||
2694 | if (indexes[where] == 0) | |||
2695 | { | |||
2696 | char buf[20]; | |||
2697 | snprintf (buf, sizeof (buf), "captures[%u]", where); | |||
2698 | what->gen_transform (f, indent, buf, gimple, depth, in_type, | |||
2699 | cinfo, NULLnullptr); | |||
2700 | } | |||
2701 | } | |||
2702 | ||||
2703 | /* If in GENERIC some capture is used multiple times, unshare it except | |||
2704 | when emitting the last use. */ | |||
2705 | if (!gimple | |||
2706 | && cinfo->info.exists () | |||
2707 | && cinfo->info[cinfo->info[where].same_as].result_use_count > 1) | |||
2708 | { | |||
2709 | fprintf_indent (f, indent, "%s = unshare_expr (captures[%u]);\n", | |||
2710 | dest, where); | |||
2711 | cinfo->info[cinfo->info[where].same_as].result_use_count--; | |||
2712 | } | |||
2713 | else | |||
2714 | fprintf_indent (f, indent, "%s = captures[%u];\n", dest, where); | |||
2715 | ||||
2716 | /* ??? Stupid tcc_comparison GENERIC trees in COND_EXPRs. Deal | |||
2717 | with substituting a capture of that. */ | |||
2718 | if (gimple | |||
2719 | && cond_handling != 0 | |||
2720 | && cinfo->info[where].cond_expr_cond_p) | |||
2721 | { | |||
2722 | /* If substituting into a cond_expr condition, unshare. */ | |||
2723 | if (cond_handling == 1) | |||
2724 | fprintf_indent (f, indent, "%s = unshare_expr (%s);\n", dest, dest); | |||
2725 | /* If substituting elsewhere we might need to decompose it. */ | |||
2726 | else if (cond_handling == 2) | |||
2727 | { | |||
2728 | /* ??? Returning false here will also not allow any other patterns | |||
2729 | to match unless this generator was split out. */ | |||
2730 | fprintf_indent (f, indent, "if (COMPARISON_CLASS_P (%s))\n", dest); | |||
2731 | fprintf_indent (f, indent, " {\n"); | |||
2732 | fprintf_indent (f, indent, " if (!seq) return false;\n"); | |||
2733 | fprintf_indent (f, indent, " %s = gimple_build (seq," | |||
2734 | " TREE_CODE (%s)," | |||
2735 | " TREE_TYPE (%s), TREE_OPERAND (%s, 0)," | |||
2736 | " TREE_OPERAND (%s, 1));\n", | |||
2737 | dest, dest, dest, dest, dest); | |||
2738 | fprintf_indent (f, indent, " }\n"); | |||
2739 | } | |||
2740 | } | |||
2741 | } | |||
2742 | ||||
2743 | /* Return the name of the operand representing the decision tree node. | |||
2744 | Use NAME as space to generate it. */ | |||
2745 | ||||
2746 | char * | |||
2747 | dt_operand::get_name (char *name) | |||
2748 | { | |||
2749 | if (! parent) | |||
2750 | sprintf (name, "t"); | |||
2751 | else if (parent->level == 1) | |||
2752 | sprintf (name, "_p%u", pos); | |||
2753 | else if (parent->type == dt_node::DT_MATCH) | |||
2754 | return as_a <dt_operand *> (parent)->get_name (name); | |||
2755 | else | |||
2756 | sprintf (name, "_q%u%u", parent->level, pos); | |||
2757 | return name; | |||
2758 | } | |||
2759 | ||||
2760 | /* Fill NAME with the operand name at position POS. */ | |||
2761 | ||||
2762 | void | |||
2763 | dt_operand::gen_opname (char *name, unsigned pos) | |||
2764 | { | |||
2765 | if (! parent) | |||
2766 | sprintf (name, "_p%u", pos); | |||
2767 | else | |||
2768 | sprintf (name, "_q%u%u", level, pos); | |||
2769 | } | |||
2770 | ||||
2771 | /* Generate matching code for the decision tree operand which is | |||
2772 | a predicate. */ | |||
2773 | ||||
2774 | unsigned | |||
2775 | dt_operand::gen_predicate (FILE *f, int indent, const char *opname, bool gimple) | |||
2776 | { | |||
2777 | predicate *p = as_a <predicate *> (op); | |||
2778 | ||||
2779 | if (p->p->matchers.exists ()) | |||
2780 | { | |||
2781 | /* If this is a predicate generated from a pattern mangle its | |||
2782 | name and pass on the valueize hook. */ | |||
2783 | if (gimple) | |||
2784 | fprintf_indent (f, indent, "if (gimple_%s (%s, valueize))\n", | |||
2785 | p->p->id, opname); | |||
2786 | else | |||
2787 | fprintf_indent (f, indent, "if (tree_%s (%s))\n", p->p->id, opname); | |||
2788 | } | |||
2789 | else | |||
2790 | fprintf_indent (f, indent, "if (%s (%s))\n", p->p->id, opname); | |||
2791 | fprintf_indent (f, indent + 2, "{\n"); | |||
2792 | return 1; | |||
2793 | } | |||
2794 | ||||
2795 | /* Generate matching code for the decision tree operand which is | |||
2796 | a capture-match. */ | |||
2797 | ||||
2798 | unsigned | |||
2799 | dt_operand::gen_match_op (FILE *f, int indent, const char *opname, bool) | |||
2800 | { | |||
2801 | char match_opname[20]; | |||
2802 | match_dop->get_name (match_opname); | |||
2803 | if (value_match) | |||
2804 | fprintf_indent (f, indent, "if ((%s == %s && ! TREE_SIDE_EFFECTS (%s)) " | |||
2805 | "|| operand_equal_p (%s, %s, 0))\n", | |||
2806 | opname, match_opname, opname, opname, match_opname); | |||
2807 | else | |||
2808 | fprintf_indent (f, indent, "if ((%s == %s && ! TREE_SIDE_EFFECTS (%s)) " | |||
2809 | "|| (operand_equal_p (%s, %s, 0) " | |||
2810 | "&& types_match (%s, %s)))\n", | |||
2811 | opname, match_opname, opname, opname, match_opname, | |||
2812 | opname, match_opname); | |||
2813 | fprintf_indent (f, indent + 2, "{\n"); | |||
2814 | return 1; | |||
2815 | } | |||
2816 | ||||
2817 | /* Generate GIMPLE matching code for the decision tree operand. */ | |||
2818 | ||||
2819 | unsigned | |||
2820 | dt_operand::gen_gimple_expr (FILE *f, int indent, int depth) | |||
2821 | { | |||
2822 | expr *e = static_cast<expr *> (op); | |||
2823 | id_base *id = e->operation; | |||
2824 | unsigned n_ops = e->ops.length (); | |||
2825 | unsigned n_braces = 0; | |||
2826 | ||||
2827 | for (unsigned i = 0; i < n_ops; ++i) | |||
2828 | { | |||
2829 | char child_opname[20]; | |||
2830 | gen_opname (child_opname, i); | |||
2831 | ||||
2832 | if (id->kind == id_base::CODE) | |||
2833 | { | |||
2834 | if (e->is_generic | |||
2835 | || *id == REALPART_EXPR || *id == IMAGPART_EXPR | |||
2836 | || *id == BIT_FIELD_REF || *id == VIEW_CONVERT_EXPR) | |||
2837 | { | |||
2838 | /* ??? If this is a memory operation we can't (and should not) | |||
2839 | match this. The only sensible operand types are | |||
2840 | SSA names and invariants. */ | |||
2841 | if (e->is_generic) | |||
2842 | { | |||
2843 | char opname[20]; | |||
2844 | get_name (opname); | |||
2845 | fprintf_indent (f, indent, | |||
2846 | "tree %s = TREE_OPERAND (%s, %i);\n", | |||
2847 | child_opname, opname, i); | |||
2848 | } | |||
2849 | else | |||
2850 | fprintf_indent (f, indent, | |||
2851 | "tree %s = TREE_OPERAND " | |||
2852 | "(gimple_assign_rhs1 (_a%d), %i);\n", | |||
2853 | child_opname, depth, i); | |||
2854 | fprintf_indent (f, indent, | |||
2855 | "if ((TREE_CODE (%s) == SSA_NAME\n", | |||
2856 | child_opname); | |||
2857 | fprintf_indent (f, indent, | |||
2858 | " || is_gimple_min_invariant (%s)))\n", | |||
2859 | child_opname); | |||
2860 | fprintf_indent (f, indent, | |||
2861 | " {\n"); | |||
2862 | indent += 4; | |||
2863 | n_braces++; | |||
2864 | fprintf_indent (f, indent, | |||
2865 | "%s = do_valueize (valueize, %s);\n", | |||
2866 | child_opname, child_opname); | |||
2867 | continue; | |||
2868 | } | |||
2869 | else | |||
2870 | fprintf_indent (f, indent, | |||
2871 | "tree %s = gimple_assign_rhs%u (_a%d);\n", | |||
2872 | child_opname, i + 1, depth); | |||
2873 | } | |||
2874 | else | |||
2875 | fprintf_indent (f, indent, | |||
2876 | "tree %s = gimple_call_arg (_c%d, %u);\n", | |||
2877 | child_opname, depth, i); | |||
2878 | fprintf_indent (f, indent, | |||
2879 | "%s = do_valueize (valueize, %s);\n", | |||
2880 | child_opname, child_opname); | |||
2881 | } | |||
2882 | /* While the toplevel operands are canonicalized by the caller | |||
2883 | after valueizing operands of sub-expressions we have to | |||
2884 | re-canonicalize operand order. */ | |||
2885 | int opno = commutative_op (id); | |||
2886 | if (opno >= 0) | |||
2887 | { | |||
2888 | char child_opname0[20], child_opname1[20]; | |||
2889 | gen_opname (child_opname0, opno); | |||
2890 | gen_opname (child_opname1, opno + 1); | |||
2891 | fprintf_indent (f, indent, | |||
2892 | "if (tree_swap_operands_p (%s, %s))\n", | |||
2893 | child_opname0, child_opname1); | |||
2894 | fprintf_indent (f, indent, | |||
2895 | " std::swap (%s, %s);\n", | |||
2896 | child_opname0, child_opname1); | |||
2897 | } | |||
2898 | ||||
2899 | return n_braces; | |||
2900 | } | |||
2901 | ||||
2902 | /* Generate GENERIC matching code for the decision tree operand. */ | |||
2903 | ||||
2904 | unsigned | |||
2905 | dt_operand::gen_generic_expr (FILE *f, int indent, const char *opname) | |||
2906 | { | |||
2907 | expr *e = static_cast<expr *> (op); | |||
2908 | unsigned n_ops = e->ops.length (); | |||
2909 | ||||
2910 | for (unsigned i = 0; i < n_ops; ++i) | |||
2911 | { | |||
2912 | char child_opname[20]; | |||
2913 | gen_opname (child_opname, i); | |||
2914 | ||||
2915 | if (e->operation->kind == id_base::CODE) | |||
2916 | fprintf_indent (f, indent, "tree %s = TREE_OPERAND (%s, %u);\n", | |||
2917 | child_opname, opname, i); | |||
2918 | else | |||
2919 | fprintf_indent (f, indent, "tree %s = CALL_EXPR_ARG (%s, %u);\n", | |||
2920 | child_opname, opname, i); | |||
2921 | } | |||
2922 | ||||
2923 | return 0; | |||
2924 | } | |||
2925 | ||||
2926 | /* Generate matching code for the children of the decision tree node. */ | |||
2927 | ||||
2928 | void | |||
2929 | dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth) | |||
2930 | { | |||
2931 | auto_vec<dt_operand *> gimple_exprs; | |||
2932 | auto_vec<dt_operand *> generic_exprs; | |||
2933 | auto_vec<dt_operand *> fns; | |||
2934 | auto_vec<dt_operand *> generic_fns; | |||
2935 | auto_vec<dt_operand *> preds; | |||
2936 | auto_vec<dt_node *> others; | |||
2937 | ||||
2938 | for (unsigned i = 0; i < kids.length (); ++i) | |||
2939 | { | |||
2940 | if (kids[i]->type == dt_node::DT_OPERAND) | |||
2941 | { | |||
2942 | dt_operand *op = as_a<dt_operand *> (kids[i]); | |||
2943 | if (expr *e = dyn_cast <expr *> (op->op)) | |||
2944 | { | |||
2945 | if (e->ops.length () == 0 | |||
2946 | /* In GIMPLE a CONSTRUCTOR always appears in a | |||
2947 | separate definition. */ | |||
2948 | && (!gimple || !(*e->operation == CONSTRUCTOR))) | |||
2949 | { | |||
2950 | generic_exprs.safe_push (op); | |||
2951 | /* But ADDR_EXPRs can appear directly when invariant | |||
2952 | and in a separate definition when not. */ | |||
2953 | if (gimple && *e->operation == ADDR_EXPR) | |||
2954 | gimple_exprs.safe_push (op); | |||
2955 | } | |||
2956 | else if (e->operation->kind == id_base::FN) | |||
2957 | { | |||
2958 | if (gimple) | |||
2959 | fns.safe_push (op); | |||
2960 | else | |||
2961 | generic_fns.safe_push (op); | |||
2962 | } | |||
2963 | else if (e->operation->kind == id_base::PREDICATE) | |||
2964 | preds.safe_push (op); | |||
2965 | else | |||
2966 | { | |||
2967 | if (gimple && !e->is_generic) | |||
2968 | gimple_exprs.safe_push (op); | |||
2969 | else | |||
2970 | generic_exprs.safe_push (op); | |||
2971 | } | |||
2972 | } | |||
2973 | else if (op->op->type == operand::OP_PREDICATE) | |||
2974 | others.safe_push (kids[i]); | |||
2975 | else | |||
2976 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 2976, __FUNCTION__)); | |||
2977 | } | |||
2978 | else if (kids[i]->type == dt_node::DT_SIMPLIFY) | |||
2979 | others.safe_push (kids[i]); | |||
2980 | else if (kids[i]->type == dt_node::DT_MATCH | |||
2981 | || kids[i]->type == dt_node::DT_TRUE) | |||
2982 | { | |||
2983 | /* A DT_TRUE operand serves as a barrier - generate code now | |||
2984 | for what we have collected sofar. | |||
2985 | Like DT_TRUE, DT_MATCH serves as a barrier as it can cause | |||
2986 | dependent matches to get out-of-order. Generate code now | |||
2987 | for what we have collected sofar. */ | |||
2988 | gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs, | |||
2989 | fns, generic_fns, preds, others); | |||
2990 | /* And output the true operand itself. */ | |||
2991 | kids[i]->gen (f, indent, gimple, depth); | |||
2992 | gimple_exprs.truncate (0); | |||
2993 | generic_exprs.truncate (0); | |||
2994 | fns.truncate (0); | |||
2995 | generic_fns.truncate (0); | |||
2996 | preds.truncate (0); | |||
2997 | others.truncate (0); | |||
2998 | } | |||
2999 | else | |||
3000 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3000, __FUNCTION__)); | |||
3001 | } | |||
3002 | ||||
3003 | /* Generate code for the remains. */ | |||
3004 | gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs, | |||
3005 | fns, generic_fns, preds, others); | |||
3006 | } | |||
3007 | ||||
3008 | /* Generate matching code for the children of the decision tree node. */ | |||
3009 | ||||
3010 | void | |||
3011 | dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth, | |||
3012 | const vec<dt_operand *> &gimple_exprs, | |||
3013 | const vec<dt_operand *> &generic_exprs, | |||
3014 | const vec<dt_operand *> &fns, | |||
3015 | const vec<dt_operand *> &generic_fns, | |||
3016 | const vec<dt_operand *> &preds, | |||
3017 | const vec<dt_node *> &others) | |||
3018 | { | |||
3019 | char buf[128]; | |||
3020 | char *kid_opname = buf; | |||
3021 | ||||
3022 | unsigned exprs_len = gimple_exprs.length (); | |||
3023 | unsigned gexprs_len = generic_exprs.length (); | |||
3024 | unsigned fns_len = fns.length (); | |||
3025 | unsigned gfns_len = generic_fns.length (); | |||
3026 | ||||
3027 | if (exprs_len || fns_len || gexprs_len || gfns_len) | |||
3028 | { | |||
3029 | if (exprs_len) | |||
3030 | gimple_exprs[0]->get_name (kid_opname); | |||
3031 | else if (fns_len) | |||
3032 | fns[0]->get_name (kid_opname); | |||
3033 | else if (gfns_len) | |||
3034 | generic_fns[0]->get_name (kid_opname); | |||
3035 | else | |||
3036 | generic_exprs[0]->get_name (kid_opname); | |||
3037 | ||||
3038 | fprintf_indent (f, indent, "switch (TREE_CODE (%s))\n", kid_opname); | |||
3039 | fprintf_indent (f, indent, " {\n"); | |||
3040 | indent += 2; | |||
3041 | } | |||
3042 | ||||
3043 | if (exprs_len || fns_len) | |||
3044 | { | |||
3045 | depth++; | |||
3046 | fprintf_indent (f, indent, | |||
3047 | "case SSA_NAME:\n"); | |||
3048 | fprintf_indent (f, indent, | |||
3049 | " if (gimple *_d%d = get_def (valueize, %s))\n", | |||
3050 | depth, kid_opname); | |||
3051 | fprintf_indent (f, indent, | |||
3052 | " {\n"); | |||
3053 | indent += 6; | |||
3054 | if (exprs_len) | |||
3055 | { | |||
3056 | fprintf_indent (f, indent, | |||
3057 | "if (gassign *_a%d = dyn_cast <gassign *> (_d%d))\n", | |||
3058 | depth, depth); | |||
3059 | fprintf_indent (f, indent, | |||
3060 | " switch (gimple_assign_rhs_code (_a%d))\n", | |||
3061 | depth); | |||
3062 | indent += 4; | |||
3063 | fprintf_indent (f, indent, "{\n"); | |||
3064 | for (unsigned i = 0; i < exprs_len; ++i) | |||
3065 | { | |||
3066 | expr *e = as_a <expr *> (gimple_exprs[i]->op); | |||
3067 | id_base *op = e->operation; | |||
3068 | if (*op == CONVERT_EXPR || *op == NOP_EXPR) | |||
3069 | fprintf_indent (f, indent, "CASE_CONVERT:\n"); | |||
3070 | else | |||
3071 | fprintf_indent (f, indent, "case %s:\n", op->id); | |||
3072 | fprintf_indent (f, indent, " {\n"); | |||
3073 | gimple_exprs[i]->gen (f, indent + 4, true, depth); | |||
3074 | fprintf_indent (f, indent, " break;\n"); | |||
3075 | fprintf_indent (f, indent, " }\n"); | |||
3076 | } | |||
3077 | fprintf_indent (f, indent, "default:;\n"); | |||
3078 | fprintf_indent (f, indent, "}\n"); | |||
3079 | indent -= 4; | |||
3080 | } | |||
3081 | ||||
3082 | if (fns_len) | |||
3083 | { | |||
3084 | fprintf_indent (f, indent, | |||
3085 | "%sif (gcall *_c%d = dyn_cast <gcall *> (_d%d))\n", | |||
3086 | exprs_len ? "else " : "", depth, depth); | |||
3087 | fprintf_indent (f, indent, | |||
3088 | " switch (gimple_call_combined_fn (_c%d))\n", | |||
3089 | depth); | |||
3090 | ||||
3091 | indent += 4; | |||
3092 | fprintf_indent (f, indent, "{\n"); | |||
3093 | for (unsigned i = 0; i < fns_len; ++i) | |||
3094 | { | |||
3095 | expr *e = as_a <expr *>(fns[i]->op); | |||
3096 | fprintf_indent (f, indent, "case %s:\n", e->operation->id); | |||
3097 | /* We need to be defensive against bogus prototypes allowing | |||
3098 | calls with not enough arguments. */ | |||
3099 | fprintf_indent (f, indent, | |||
3100 | " if (gimple_call_num_args (_c%d) == %d)\n", | |||
3101 | depth, e->ops.length ()); | |||
3102 | fprintf_indent (f, indent, " {\n"); | |||
3103 | fns[i]->gen (f, indent + 6, true, depth); | |||
3104 | fprintf_indent (f, indent, " }\n"); | |||
3105 | fprintf_indent (f, indent, " break;\n"); | |||
3106 | } | |||
3107 | ||||
3108 | fprintf_indent (f, indent, "default:;\n"); | |||
3109 | fprintf_indent (f, indent, "}\n"); | |||
3110 | indent -= 4; | |||
3111 | } | |||
3112 | ||||
3113 | indent -= 6; | |||
3114 | depth--; | |||
3115 | fprintf_indent (f, indent, " }\n"); | |||
3116 | /* See if there is SSA_NAME among generic_exprs and if yes, emit it | |||
3117 | here rather than in the next loop. */ | |||
3118 | for (unsigned i = 0; i < generic_exprs.length (); ++i) | |||
3119 | { | |||
3120 | expr *e = as_a <expr *>(generic_exprs[i]->op); | |||
3121 | id_base *op = e->operation; | |||
3122 | if (*op == SSA_NAME && (exprs_len || fns_len)) | |||
3123 | { | |||
3124 | fprintf_indent (f, indent + 4, "{\n"); | |||
3125 | generic_exprs[i]->gen (f, indent + 6, gimple, depth); | |||
3126 | fprintf_indent (f, indent + 4, "}\n"); | |||
3127 | } | |||
3128 | } | |||
3129 | ||||
3130 | fprintf_indent (f, indent, " break;\n"); | |||
3131 | } | |||
3132 | ||||
3133 | for (unsigned i = 0; i < generic_exprs.length (); ++i) | |||
3134 | { | |||
3135 | expr *e = as_a <expr *>(generic_exprs[i]->op); | |||
3136 | id_base *op = e->operation; | |||
3137 | if (*op == CONVERT_EXPR || *op == NOP_EXPR) | |||
3138 | fprintf_indent (f, indent, "CASE_CONVERT:\n"); | |||
3139 | else if (*op == SSA_NAME && (exprs_len || fns_len)) | |||
3140 | /* Already handled above. */ | |||
3141 | continue; | |||
3142 | else | |||
3143 | fprintf_indent (f, indent, "case %s:\n", op->id); | |||
3144 | fprintf_indent (f, indent, " {\n"); | |||
3145 | generic_exprs[i]->gen (f, indent + 4, gimple, depth); | |||
3146 | fprintf_indent (f, indent, " break;\n"); | |||
3147 | fprintf_indent (f, indent, " }\n"); | |||
3148 | } | |||
3149 | ||||
3150 | if (gfns_len) | |||
3151 | { | |||
3152 | fprintf_indent (f, indent, | |||
3153 | "case CALL_EXPR:\n"); | |||
3154 | fprintf_indent (f, indent, | |||
3155 | " switch (get_call_combined_fn (%s))\n", | |||
3156 | kid_opname); | |||
3157 | fprintf_indent (f, indent, | |||
3158 | " {\n"); | |||
3159 | indent += 4; | |||
3160 | ||||
3161 | for (unsigned j = 0; j < generic_fns.length (); ++j) | |||
3162 | { | |||
3163 | expr *e = as_a <expr *>(generic_fns[j]->op); | |||
3164 | gcc_assert (e->operation->kind == id_base::FN)((void)(!(e->operation->kind == id_base::FN) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3164, __FUNCTION__), 0 : 0)); | |||
3165 | ||||
3166 | fprintf_indent (f, indent, "case %s:\n", e->operation->id); | |||
3167 | fprintf_indent (f, indent, " if (call_expr_nargs (%s) == %d)\n" | |||
3168 | " {\n", kid_opname, e->ops.length ()); | |||
3169 | generic_fns[j]->gen (f, indent + 6, false, depth); | |||
3170 | fprintf_indent (f, indent, " }\n" | |||
3171 | " break;\n"); | |||
3172 | } | |||
3173 | fprintf_indent (f, indent, "default:;\n"); | |||
3174 | ||||
3175 | indent -= 4; | |||
3176 | fprintf_indent (f, indent, " }\n"); | |||
3177 | fprintf_indent (f, indent, " break;\n"); | |||
3178 | } | |||
3179 | ||||
3180 | /* Close switch (TREE_CODE ()). */ | |||
3181 | if (exprs_len || fns_len || gexprs_len || gfns_len) | |||
3182 | { | |||
3183 | indent -= 4; | |||
3184 | fprintf_indent (f, indent, " default:;\n"); | |||
3185 | fprintf_indent (f, indent, " }\n"); | |||
3186 | } | |||
3187 | ||||
3188 | for (unsigned i = 0; i < preds.length (); ++i) | |||
3189 | { | |||
3190 | expr *e = as_a <expr *> (preds[i]->op); | |||
3191 | predicate_id *p = as_a <predicate_id *> (e->operation); | |||
3192 | preds[i]->get_name (kid_opname); | |||
3193 | fprintf_indent (f, indent, "{\n"); | |||
3194 | indent += 2; | |||
3195 | fprintf_indent (f, indent, "tree %s_pops[%d];\n", kid_opname, p->nargs); | |||
3196 | fprintf_indent (f, indent, "if (%s_%s (%s, %s_pops%s))\n", | |||
3197 | gimple ? "gimple" : "tree", | |||
3198 | p->id, kid_opname, kid_opname, | |||
3199 | gimple ? ", valueize" : ""); | |||
3200 | fprintf_indent (f, indent, " {\n"); | |||
3201 | for (int j = 0; j < p->nargs; ++j) | |||
3202 | { | |||
3203 | char child_opname[20]; | |||
3204 | preds[i]->gen_opname (child_opname, j); | |||
3205 | fprintf_indent (f, indent + 4, "tree %s = %s_pops[%d];\n", | |||
3206 | child_opname, kid_opname, j); | |||
3207 | } | |||
3208 | preds[i]->gen_kids (f, indent + 4, gimple, depth); | |||
3209 | fprintf (f, "}\n"); | |||
3210 | indent -= 2; | |||
3211 | fprintf_indent (f, indent, "}\n"); | |||
3212 | } | |||
3213 | ||||
3214 | for (unsigned i = 0; i < others.length (); ++i) | |||
3215 | others[i]->gen (f, indent, gimple, depth); | |||
3216 | } | |||
3217 | ||||
3218 | /* Generate matching code for the decision tree operand. */ | |||
3219 | ||||
3220 | void | |||
3221 | dt_operand::gen (FILE *f, int indent, bool gimple, int depth) | |||
3222 | { | |||
3223 | char opname[20]; | |||
3224 | get_name (opname); | |||
3225 | ||||
3226 | unsigned n_braces = 0; | |||
3227 | ||||
3228 | if (type == DT_OPERAND) | |||
3229 | switch (op->type) | |||
3230 | { | |||
3231 | case operand::OP_PREDICATE: | |||
3232 | n_braces = gen_predicate (f, indent, opname, gimple); | |||
3233 | break; | |||
3234 | ||||
3235 | case operand::OP_EXPR: | |||
3236 | if (gimple) | |||
3237 | n_braces = gen_gimple_expr (f, indent, depth); | |||
3238 | else | |||
3239 | n_braces = gen_generic_expr (f, indent, opname); | |||
3240 | break; | |||
3241 | ||||
3242 | default: | |||
3243 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3243, __FUNCTION__)); | |||
3244 | } | |||
3245 | else if (type == DT_TRUE) | |||
3246 | ; | |||
3247 | else if (type == DT_MATCH) | |||
3248 | n_braces = gen_match_op (f, indent, opname, gimple); | |||
3249 | else | |||
3250 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3250, __FUNCTION__)); | |||
3251 | ||||
3252 | indent += 4 * n_braces; | |||
3253 | gen_kids (f, indent, gimple, depth); | |||
3254 | ||||
3255 | for (unsigned i = 0; i < n_braces; ++i) | |||
3256 | { | |||
3257 | indent -= 4; | |||
3258 | if (indent < 0) | |||
3259 | indent = 0; | |||
3260 | fprintf_indent (f, indent, " }\n"); | |||
3261 | } | |||
3262 | } | |||
3263 | ||||
3264 | ||||
3265 | /* Generate code for the '(if ...)', '(with ..)' and actual transform | |||
3266 | step of a '(simplify ...)' or '(match ...)'. This handles everything | |||
3267 | that is not part of the decision tree (simplify->match). | |||
3268 | Main recursive worker. */ | |||
3269 | ||||
3270 | void | |||
3271 | dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) | |||
3272 | { | |||
3273 | if (result) | |||
3274 | { | |||
3275 | if (with_expr *w = dyn_cast <with_expr *> (result)) | |||
3276 | { | |||
3277 | fprintf_indent (f, indent, "{\n"); | |||
3278 | indent += 4; | |||
3279 | output_line_directive (f, w->location); | |||
3280 | w->with->gen_transform (f, indent, NULLnullptr, true, 1, "type", NULLnullptr); | |||
3281 | gen_1 (f, indent, gimple, w->subexpr); | |||
3282 | indent -= 4; | |||
3283 | fprintf_indent (f, indent, "}\n"); | |||
3284 | return; | |||
3285 | } | |||
3286 | else if (if_expr *ife = dyn_cast <if_expr *> (result)) | |||
3287 | { | |||
3288 | output_line_directive (f, ife->location); | |||
3289 | fprintf_indent (f, indent, "if ("); | |||
3290 | ife->cond->gen_transform (f, indent, NULLnullptr, true, 1, "type", NULLnullptr); | |||
3291 | fprintf (f, ")\n"); | |||
3292 | fprintf_indent (f, indent + 2, "{\n"); | |||
3293 | indent += 4; | |||
3294 | gen_1 (f, indent, gimple, ife->trueexpr); | |||
3295 | indent -= 4; | |||
3296 | fprintf_indent (f, indent + 2, "}\n"); | |||
3297 | if (ife->falseexpr) | |||
3298 | { | |||
3299 | fprintf_indent (f, indent, "else\n"); | |||
3300 | fprintf_indent (f, indent + 2, "{\n"); | |||
3301 | indent += 4; | |||
3302 | gen_1 (f, indent, gimple, ife->falseexpr); | |||
3303 | indent -= 4; | |||
3304 | fprintf_indent (f, indent + 2, "}\n"); | |||
3305 | } | |||
3306 | return; | |||
3307 | } | |||
3308 | } | |||
3309 | ||||
3310 | static unsigned fail_label_cnt; | |||
3311 | char local_fail_label[256]; | |||
3312 | snprintf (local_fail_label, 256, "next_after_fail%u", ++fail_label_cnt); | |||
3313 | fail_label = local_fail_label; | |||
3314 | ||||
3315 | /* Analyze captures and perform early-outs on the incoming arguments | |||
3316 | that cover cases we cannot handle. */ | |||
3317 | capture_info cinfo (s, result, gimple); | |||
3318 | if (s->kind == simplify::SIMPLIFY) | |||
3319 | { | |||
3320 | if (!gimple) | |||
3321 | { | |||
3322 | for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i) | |||
3323 | if (cinfo.force_no_side_effects & (1 << i)) | |||
3324 | { | |||
3325 | fprintf_indent (f, indent, | |||
3326 | "if (TREE_SIDE_EFFECTS (_p%d)) goto %s;\n", | |||
3327 | i, fail_label); | |||
3328 | if (verbose >= 1) | |||
3329 | warning_at (as_a <expr *> (s->match)->ops[i]->location, | |||
3330 | "forcing toplevel operand to have no " | |||
3331 | "side-effects"); | |||
3332 | } | |||
3333 | for (int i = 0; i <= s->capture_max; ++i) | |||
3334 | if (cinfo.info[i].cse_p) | |||
3335 | ; | |||
3336 | else if (cinfo.info[i].force_no_side_effects_p | |||
3337 | && (cinfo.info[i].toplevel_msk | |||
3338 | & cinfo.force_no_side_effects) == 0) | |||
3339 | { | |||
3340 | fprintf_indent (f, indent, | |||
3341 | "if (TREE_SIDE_EFFECTS (captures[%d])) " | |||
3342 | "goto %s;\n", i, fail_label); | |||
3343 | if (verbose >= 1) | |||
3344 | warning_at (cinfo.info[i].c->location, | |||
3345 | "forcing captured operand to have no " | |||
3346 | "side-effects"); | |||
3347 | } | |||
3348 | else if ((cinfo.info[i].toplevel_msk | |||
3349 | & cinfo.force_no_side_effects) != 0) | |||
3350 | /* Mark capture as having no side-effects if we had to verify | |||
3351 | that via forced toplevel operand checks. */ | |||
3352 | cinfo.info[i].force_no_side_effects_p = true; | |||
3353 | } | |||
3354 | if (gimple) | |||
3355 | { | |||
3356 | /* Force single-use restriction by only allowing simple | |||
3357 | results via setting seq to NULL. */ | |||
3358 | fprintf_indent (f, indent, "gimple_seq *lseq = seq;\n"); | |||
3359 | bool first_p = true; | |||
3360 | for (int i = 0; i <= s->capture_max; ++i) | |||
3361 | if (cinfo.info[i].force_single_use) | |||
3362 | { | |||
3363 | if (first_p) | |||
3364 | { | |||
3365 | fprintf_indent (f, indent, "if (lseq\n"); | |||
3366 | fprintf_indent (f, indent, " && ("); | |||
3367 | first_p = false; | |||
3368 | } | |||
3369 | else | |||
3370 | { | |||
3371 | fprintf (f, "\n"); | |||
3372 | fprintf_indent (f, indent, " || "); | |||
3373 | } | |||
3374 | fprintf (f, "!single_use (captures[%d])", i); | |||
3375 | } | |||
3376 | if (!first_p) | |||
3377 | { | |||
3378 | fprintf (f, "))\n"); | |||
3379 | fprintf_indent (f, indent, " lseq = NULL;\n"); | |||
3380 | } | |||
3381 | } | |||
3382 | } | |||
3383 | ||||
3384 | if (s->kind == simplify::SIMPLIFY) | |||
3385 | fprintf_indent (f, indent, "if (UNLIKELY (!dbg_cnt (match))) goto %s;\n", fail_label); | |||
3386 | ||||
3387 | fprintf_indent (f, indent, "if (UNLIKELY (dump_file && (dump_flags & TDF_FOLDING))) " | |||
3388 | "fprintf (dump_file, \"%s ", | |||
3389 | s->kind == simplify::SIMPLIFY | |||
3390 | ? "Applying pattern" : "Matching expression"); | |||
3391 | fprintf (f, "%%s:%%d, %%s:%%d\\n\", "); | |||
3392 | output_line_directive (f, | |||
3393 | result ? result->location : s->match->location, true, | |||
3394 | true); | |||
3395 | fprintf (f, ", __FILE__, __LINE__);\n"); | |||
3396 | ||||
3397 | fprintf_indent (f, indent, "{\n"); | |||
3398 | indent += 2; | |||
3399 | if (!result) | |||
3400 | { | |||
3401 | /* If there is no result then this is a predicate implementation. */ | |||
3402 | fprintf_indent (f, indent, "return true;\n"); | |||
3403 | } | |||
3404 | else if (gimple) | |||
3405 | { | |||
3406 | /* For GIMPLE simply drop NON_LVALUE_EXPR (which only appears | |||
3407 | in outermost position). */ | |||
3408 | if (result->type == operand::OP_EXPR | |||
3409 | && *as_a <expr *> (result)->operation == NON_LVALUE_EXPR) | |||
3410 | result = as_a <expr *> (result)->ops[0]; | |||
3411 | if (result->type == operand::OP_EXPR) | |||
3412 | { | |||
3413 | expr *e = as_a <expr *> (result); | |||
3414 | id_base *opr = e->operation; | |||
3415 | bool is_predicate = false; | |||
3416 | /* When we delay operator substituting during lowering of fors we | |||
3417 | make sure that for code-gen purposes the effects of each substitute | |||
3418 | are the same. Thus just look at that. */ | |||
3419 | if (user_id *uid = dyn_cast <user_id *> (opr)) | |||
3420 | opr = uid->substitutes[0]; | |||
3421 | else if (is_a <predicate_id *> (opr)) | |||
3422 | is_predicate = true; | |||
3423 | if (!is_predicate) | |||
3424 | fprintf_indent (f, indent, "res_op->set_op (%s, type, %d);\n", | |||
3425 | *e->operation == CONVERT_EXPR | |||
3426 | ? "NOP_EXPR" : e->operation->id, | |||
3427 | e->ops.length ()); | |||
3428 | for (unsigned j = 0; j < e->ops.length (); ++j) | |||
3429 | { | |||
3430 | char dest[32]; | |||
3431 | if (is_predicate) | |||
3432 | snprintf (dest, sizeof (dest), "res_ops[%d]", j); | |||
3433 | else | |||
3434 | snprintf (dest, sizeof (dest), "res_op->ops[%d]", j); | |||
3435 | const char *optype | |||
3436 | = get_operand_type (opr, j, | |||
3437 | "type", e->expr_type, | |||
3438 | j == 0 ? NULLnullptr | |||
3439 | : "TREE_TYPE (res_op->ops[0])"); | |||
3440 | /* We need to expand GENERIC conditions we captured from | |||
3441 | COND_EXPRs and we need to unshare them when substituting | |||
3442 | into COND_EXPRs. */ | |||
3443 | int cond_handling = 0; | |||
3444 | if (!is_predicate) | |||
3445 | cond_handling = (*opr == COND_EXPR && j == 0) ? 1 : 2; | |||
3446 | e->ops[j]->gen_transform (f, indent, dest, true, 1, optype, | |||
3447 | &cinfo, indexes, cond_handling); | |||
3448 | } | |||
3449 | ||||
3450 | /* Re-fold the toplevel result. It's basically an embedded | |||
3451 | gimple_build w/o actually building the stmt. */ | |||
3452 | if (!is_predicate) | |||
3453 | { | |||
3454 | fprintf_indent (f, indent, | |||
3455 | "res_op->resimplify (%s, valueize);\n", | |||
3456 | !e->force_leaf ? "lseq" : "NULL"); | |||
3457 | if (e->force_leaf) | |||
3458 | fprintf_indent (f, indent, | |||
3459 | "if (!maybe_push_res_to_seq (res_op, NULL)) " | |||
3460 | "goto %s;\n", fail_label); | |||
3461 | } | |||
3462 | } | |||
3463 | else if (result->type == operand::OP_CAPTURE | |||
3464 | || result->type == operand::OP_C_EXPR) | |||
3465 | { | |||
3466 | fprintf_indent (f, indent, "tree tem;\n"); | |||
3467 | result->gen_transform (f, indent, "tem", true, 1, "type", | |||
3468 | &cinfo, indexes); | |||
3469 | fprintf_indent (f, indent, "res_op->set_value (tem);\n"); | |||
3470 | if (is_a <capture *> (result) | |||
3471 | && cinfo.info[as_a <capture *> (result)->where].cond_expr_cond_p) | |||
3472 | { | |||
3473 | /* ??? Stupid tcc_comparison GENERIC trees in COND_EXPRs. Deal | |||
3474 | with substituting a capture of that. */ | |||
3475 | fprintf_indent (f, indent, | |||
3476 | "if (COMPARISON_CLASS_P (tem))\n"); | |||
3477 | fprintf_indent (f, indent, | |||
3478 | " {\n"); | |||
3479 | fprintf_indent (f, indent, | |||
3480 | " res_op->ops[0] = TREE_OPERAND (tem, 0);\n"); | |||
3481 | fprintf_indent (f, indent, | |||
3482 | " res_op->ops[1] = TREE_OPERAND (tem, 1);\n"); | |||
3483 | fprintf_indent (f, indent, | |||
3484 | " }\n"); | |||
3485 | } | |||
3486 | } | |||
3487 | else | |||
3488 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3488, __FUNCTION__)); | |||
3489 | fprintf_indent (f, indent, "return true;\n"); | |||
3490 | } | |||
3491 | else /* GENERIC */ | |||
3492 | { | |||
3493 | bool is_predicate = false; | |||
3494 | if (result->type == operand::OP_EXPR) | |||
3495 | { | |||
3496 | expr *e = as_a <expr *> (result); | |||
3497 | id_base *opr = e->operation; | |||
3498 | /* When we delay operator substituting during lowering of fors we | |||
3499 | make sure that for code-gen purposes the effects of each substitute | |||
3500 | are the same. Thus just look at that. */ | |||
3501 | if (user_id *uid = dyn_cast <user_id *> (opr)) | |||
3502 | opr = uid->substitutes[0]; | |||
3503 | else if (is_a <predicate_id *> (opr)) | |||
3504 | is_predicate = true; | |||
3505 | /* Search for captures used multiple times in the result expression | |||
3506 | and wrap them in a SAVE_EXPR. Allow as many uses as in the | |||
3507 | original expression. */ | |||
3508 | if (!is_predicate) | |||
3509 | for (int i = 0; i < s->capture_max + 1; ++i) | |||
3510 | { | |||
3511 | if (cinfo.info[i].same_as != (unsigned)i | |||
3512 | || cinfo.info[i].cse_p) | |||
3513 | continue; | |||
3514 | if (cinfo.info[i].result_use_count | |||
3515 | > cinfo.info[i].match_use_count) | |||
3516 | fprintf_indent (f, indent, | |||
3517 | "if (! tree_invariant_p (captures[%d])) " | |||
3518 | "goto %s;\n", i, fail_label); | |||
3519 | } | |||
3520 | for (unsigned j = 0; j < e->ops.length (); ++j) | |||
3521 | { | |||
3522 | char dest[32]; | |||
3523 | if (is_predicate) | |||
3524 | snprintf (dest, sizeof (dest), "res_ops[%d]", j); | |||
3525 | else | |||
3526 | { | |||
3527 | fprintf_indent (f, indent, "tree res_op%d;\n", j); | |||
3528 | snprintf (dest, sizeof (dest), "res_op%d", j); | |||
3529 | } | |||
3530 | const char *optype | |||
3531 | = get_operand_type (opr, j, | |||
3532 | "type", e->expr_type, | |||
3533 | j == 0 | |||
3534 | ? NULLnullptr : "TREE_TYPE (res_op0)"); | |||
3535 | e->ops[j]->gen_transform (f, indent, dest, false, 1, optype, | |||
3536 | &cinfo, indexes); | |||
3537 | } | |||
3538 | if (is_predicate) | |||
3539 | fprintf_indent (f, indent, "return true;\n"); | |||
3540 | else | |||
3541 | { | |||
3542 | fprintf_indent (f, indent, "tree _r;\n"); | |||
3543 | /* Re-fold the toplevel result. Use non_lvalue to | |||
3544 | build NON_LVALUE_EXPRs so they get properly | |||
3545 | ignored when in GIMPLE form. */ | |||
3546 | if (*opr == NON_LVALUE_EXPR) | |||
3547 | fprintf_indent (f, indent, | |||
3548 | "_r = non_lvalue_loc (loc, res_op0);\n"); | |||
3549 | else | |||
3550 | { | |||
3551 | if (is_a <operator_id *> (opr)) | |||
3552 | fprintf_indent (f, indent, | |||
3553 | "_r = fold_build%d_loc (loc, %s, type", | |||
3554 | e->ops.length (), | |||
3555 | *e->operation == CONVERT_EXPR | |||
3556 | ? "NOP_EXPR" : e->operation->id); | |||
3557 | else | |||
3558 | fprintf_indent (f, indent, | |||
3559 | "_r = maybe_build_call_expr_loc (loc, " | |||
3560 | "%s, type, %d", e->operation->id, | |||
3561 | e->ops.length()); | |||
3562 | for (unsigned j = 0; j < e->ops.length (); ++j) | |||
3563 | fprintf (f, ", res_op%d", j); | |||
3564 | fprintf (f, ");\n"); | |||
3565 | if (!is_a <operator_id *> (opr)) | |||
3566 | { | |||
3567 | fprintf_indent (f, indent, "if (!_r)\n"); | |||
3568 | fprintf_indent (f, indent, " goto %s;\n", fail_label); | |||
3569 | } | |||
3570 | } | |||
3571 | } | |||
3572 | } | |||
3573 | else if (result->type == operand::OP_CAPTURE | |||
3574 | || result->type == operand::OP_C_EXPR) | |||
3575 | ||||
3576 | { | |||
3577 | fprintf_indent (f, indent, "tree _r;\n"); | |||
3578 | result->gen_transform (f, indent, "_r", false, 1, "type", | |||
3579 | &cinfo, indexes); | |||
3580 | } | |||
3581 | else | |||
3582 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3582, __FUNCTION__)); | |||
3583 | if (!is_predicate) | |||
3584 | { | |||
3585 | /* Search for captures not used in the result expression and dependent | |||
3586 | on TREE_SIDE_EFFECTS emit omit_one_operand. */ | |||
3587 | for (int i = 0; i < s->capture_max + 1; ++i) | |||
3588 | { | |||
3589 | if (cinfo.info[i].same_as != (unsigned)i) | |||
3590 | continue; | |||
3591 | if (!cinfo.info[i].force_no_side_effects_p | |||
3592 | && !cinfo.info[i].expr_p | |||
3593 | && cinfo.info[i].result_use_count == 0) | |||
3594 | { | |||
3595 | fprintf_indent (f, indent, | |||
3596 | "if (TREE_SIDE_EFFECTS (captures[%d]))\n", | |||
3597 | i); | |||
3598 | fprintf_indent (f, indent + 2, | |||
3599 | "_r = build2_loc (loc, COMPOUND_EXPR, type, " | |||
3600 | "fold_ignored_result (captures[%d]), _r);\n", | |||
3601 | i); | |||
3602 | } | |||
3603 | } | |||
3604 | fprintf_indent (f, indent, "return _r;\n"); | |||
3605 | } | |||
3606 | } | |||
3607 | indent -= 2; | |||
3608 | fprintf_indent (f, indent, "}\n"); | |||
3609 | fprintf (f, "%s:;\n", fail_label); | |||
3610 | fail_label = NULLnullptr; | |||
3611 | } | |||
3612 | ||||
3613 | /* Generate code for the '(if ...)', '(with ..)' and actual transform | |||
3614 | step of a '(simplify ...)' or '(match ...)'. This handles everything | |||
3615 | that is not part of the decision tree (simplify->match). */ | |||
3616 | ||||
3617 | void | |||
3618 | dt_simplify::gen (FILE *f, int indent, bool gimple, int depth ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
3619 | { | |||
3620 | fprintf_indent (f, indent, "{\n"); | |||
3621 | indent += 2; | |||
3622 | output_line_directive (f, | |||
3623 | s->result ? s->result->location : s->match->location); | |||
3624 | if (s->capture_max >= 0) | |||
3625 | { | |||
3626 | char opname[20]; | |||
3627 | fprintf_indent (f, indent, "tree captures[%u] ATTRIBUTE_UNUSED = { %s", | |||
3628 | s->capture_max + 1, indexes[0]->get_name (opname)); | |||
3629 | ||||
3630 | for (int i = 1; i <= s->capture_max; ++i) | |||
3631 | { | |||
3632 | if (!indexes[i]) | |||
3633 | break; | |||
3634 | fprintf (f, ", %s", indexes[i]->get_name (opname)); | |||
3635 | } | |||
3636 | fprintf (f, " };\n"); | |||
3637 | } | |||
3638 | ||||
3639 | /* If we have a split-out function for the actual transform, call it. */ | |||
3640 | if (info && info->fname) | |||
3641 | { | |||
3642 | if (gimple) | |||
3643 | { | |||
3644 | fprintf_indent (f, indent, "if (%s (res_op, seq, " | |||
3645 | "valueize, type, captures", info->fname); | |||
3646 | for (unsigned i = 0; i < s->for_subst_vec.length (); ++i) | |||
3647 | if (s->for_subst_vec[i].first->used) | |||
3648 | fprintf (f, ", %s", s->for_subst_vec[i].second->id); | |||
3649 | fprintf (f, "))\n"); | |||
3650 | fprintf_indent (f, indent, " return true;\n"); | |||
3651 | } | |||
3652 | else | |||
3653 | { | |||
3654 | fprintf_indent (f, indent, "tree res = %s (loc, type", | |||
3655 | info->fname); | |||
3656 | for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i) | |||
3657 | fprintf (f, ", _p%d", i); | |||
3658 | fprintf (f, ", captures"); | |||
3659 | for (unsigned i = 0; i < s->for_subst_vec.length (); ++i) | |||
3660 | { | |||
3661 | if (s->for_subst_vec[i].first->used) | |||
3662 | fprintf (f, ", %s", s->for_subst_vec[i].second->id); | |||
3663 | } | |||
3664 | fprintf (f, ");\n"); | |||
3665 | fprintf_indent (f, indent, "if (res) return res;\n"); | |||
3666 | } | |||
3667 | } | |||
3668 | else | |||
3669 | { | |||
3670 | for (unsigned i = 0; i < s->for_subst_vec.length (); ++i) | |||
3671 | { | |||
3672 | if (! s->for_subst_vec[i].first->used) | |||
3673 | continue; | |||
3674 | if (is_a <operator_id *> (s->for_subst_vec[i].second)) | |||
3675 | fprintf_indent (f, indent, "const enum tree_code %s = %s;\n", | |||
3676 | s->for_subst_vec[i].first->id, | |||
3677 | s->for_subst_vec[i].second->id); | |||
3678 | else if (is_a <fn_id *> (s->for_subst_vec[i].second)) | |||
3679 | fprintf_indent (f, indent, "const combined_fn %s = %s;\n", | |||
3680 | s->for_subst_vec[i].first->id, | |||
3681 | s->for_subst_vec[i].second->id); | |||
3682 | else | |||
3683 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 3683, __FUNCTION__)); | |||
3684 | } | |||
3685 | gen_1 (f, indent, gimple, s->result); | |||
3686 | } | |||
3687 | ||||
3688 | indent -= 2; | |||
3689 | fprintf_indent (f, indent, "}\n"); | |||
3690 | } | |||
3691 | ||||
3692 | ||||
3693 | /* Hash function for finding equivalent transforms. */ | |||
3694 | ||||
3695 | hashval_t | |||
3696 | sinfo_hashmap_traits::hash (const key_type &v) | |||
3697 | { | |||
3698 | /* Only bother to compare those originating from the same source pattern. */ | |||
3699 | return v->s->result->location; | |||
3700 | } | |||
3701 | ||||
3702 | /* Compare function for finding equivalent transforms. */ | |||
3703 | ||||
3704 | static bool | |||
3705 | compare_op (operand *o1, simplify *s1, operand *o2, simplify *s2) | |||
3706 | { | |||
3707 | if (o1->type != o2->type) | |||
3708 | return false; | |||
3709 | ||||
3710 | switch (o1->type) | |||
3711 | { | |||
3712 | case operand::OP_IF: | |||
3713 | { | |||
3714 | if_expr *if1 = as_a <if_expr *> (o1); | |||
3715 | if_expr *if2 = as_a <if_expr *> (o2); | |||
3716 | /* ??? Properly compare c-exprs. */ | |||
3717 | if (if1->cond != if2->cond) | |||
3718 | return false; | |||
3719 | if (!compare_op (if1->trueexpr, s1, if2->trueexpr, s2)) | |||
3720 | return false; | |||
3721 | if (if1->falseexpr != if2->falseexpr | |||
3722 | || (if1->falseexpr | |||
3723 | && !compare_op (if1->falseexpr, s1, if2->falseexpr, s2))) | |||
3724 | return false; | |||
3725 | return true; | |||
3726 | } | |||
3727 | case operand::OP_WITH: | |||
3728 | { | |||
3729 | with_expr *with1 = as_a <with_expr *> (o1); | |||
3730 | with_expr *with2 = as_a <with_expr *> (o2); | |||
3731 | if (with1->with != with2->with) | |||
3732 | return false; | |||
3733 | return compare_op (with1->subexpr, s1, with2->subexpr, s2); | |||
3734 | } | |||
3735 | default:; | |||
3736 | } | |||
3737 | ||||
3738 | /* We've hit a result. Time to compare capture-infos - this is required | |||
3739 | in addition to the conservative pointer-equivalency of the result IL. */ | |||
3740 | capture_info cinfo1 (s1, o1, true); | |||
3741 | capture_info cinfo2 (s2, o2, true); | |||
3742 | ||||
3743 | if (cinfo1.force_no_side_effects != cinfo2.force_no_side_effects | |||
3744 | || cinfo1.info.length () != cinfo2.info.length ()) | |||
3745 | return false; | |||
3746 | ||||
3747 | for (unsigned i = 0; i < cinfo1.info.length (); ++i) | |||
3748 | { | |||
3749 | if (cinfo1.info[i].expr_p != cinfo2.info[i].expr_p | |||
3750 | || cinfo1.info[i].cse_p != cinfo2.info[i].cse_p | |||
3751 | || (cinfo1.info[i].force_no_side_effects_p | |||
3752 | != cinfo2.info[i].force_no_side_effects_p) | |||
3753 | || cinfo1.info[i].force_single_use != cinfo2.info[i].force_single_use | |||
3754 | || cinfo1.info[i].cond_expr_cond_p != cinfo2.info[i].cond_expr_cond_p | |||
3755 | /* toplevel_msk is an optimization */ | |||
3756 | || cinfo1.info[i].result_use_count != cinfo2.info[i].result_use_count | |||
3757 | || cinfo1.info[i].same_as != cinfo2.info[i].same_as | |||
3758 | /* the pointer back to the capture is for diagnostics only */) | |||
3759 | return false; | |||
3760 | } | |||
3761 | ||||
3762 | /* ??? Deep-compare the actual result. */ | |||
3763 | return o1 == o2; | |||
3764 | } | |||
3765 | ||||
3766 | bool | |||
3767 | sinfo_hashmap_traits::equal_keys (const key_type &v, | |||
3768 | const key_type &candidate) | |||
3769 | { | |||
3770 | return compare_op (v->s->result, v->s, candidate->s->result, candidate->s); | |||
3771 | } | |||
3772 | ||||
3773 | ||||
3774 | /* Main entry to generate code for matching GIMPLE IL off the decision | |||
3775 | tree. */ | |||
3776 | ||||
3777 | void | |||
3778 | decision_tree::gen (FILE *f, bool gimple) | |||
3779 | { | |||
3780 | sinfo_map_t si; | |||
3781 | ||||
3782 | root->analyze (si); | |||
3783 | ||||
3784 | fprintf (stderrstderr, "%s decision tree has %u leafs, maximum depth %u and " | |||
3785 | "a total number of %u nodes\n", | |||
3786 | gimple ? "GIMPLE" : "GENERIC", | |||
3787 | root->num_leafs, root->max_level, root->total_size); | |||
3788 | ||||
3789 | /* First split out the transform part of equal leafs. */ | |||
3790 | unsigned rcnt = 0; | |||
3791 | unsigned fcnt = 1; | |||
3792 | for (sinfo_map_t::iterator iter = si.begin (); | |||
3793 | iter != si.end (); ++iter) | |||
3794 | { | |||
3795 | sinfo *s = (*iter).second; | |||
3796 | /* Do not split out single uses. */ | |||
3797 | if (s->cnt <= 1) | |||
3798 | continue; | |||
3799 | ||||
3800 | rcnt += s->cnt - 1; | |||
3801 | if (verbose >= 1) | |||
3802 | { | |||
3803 | fprintf (stderrstderr, "found %u uses of", s->cnt); | |||
3804 | output_line_directive (stderrstderr, s->s->s->result->location); | |||
3805 | } | |||
3806 | ||||
3807 | /* Generate a split out function with the leaf transform code. */ | |||
3808 | s->fname = xasprintf ("%s_simplify_%u", gimple ? "gimple" : "generic", | |||
3809 | fcnt++); | |||
3810 | if (gimple) | |||
3811 | fprintf (f, "\nstatic bool\n" | |||
3812 | "%s (gimple_match_op *res_op, gimple_seq *seq,\n" | |||
3813 | " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n" | |||
3814 | " const tree ARG_UNUSED (type), tree *ARG_UNUSED " | |||
3815 | "(captures)\n", | |||
3816 | s->fname); | |||
3817 | else | |||
3818 | { | |||
3819 | fprintf (f, "\nstatic tree\n" | |||
3820 | "%s (location_t ARG_UNUSED (loc), const tree ARG_UNUSED (type),\n", | |||
3821 | (*iter).second->fname); | |||
3822 | for (unsigned i = 0; | |||
3823 | i < as_a <expr *>(s->s->s->match)->ops.length (); ++i) | |||
3824 | fprintf (f, " tree ARG_UNUSED (_p%d),", i); | |||
3825 | fprintf (f, " tree *captures\n"); | |||
3826 | } | |||
3827 | for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i) | |||
3828 | { | |||
3829 | if (! s->s->s->for_subst_vec[i].first->used) | |||
3830 | continue; | |||
3831 | if (is_a <operator_id *> (s->s->s->for_subst_vec[i].second)) | |||
3832 | fprintf (f, ", const enum tree_code ARG_UNUSED (%s)", | |||
3833 | s->s->s->for_subst_vec[i].first->id); | |||
3834 | else if (is_a <fn_id *> (s->s->s->for_subst_vec[i].second)) | |||
3835 | fprintf (f, ", const combined_fn ARG_UNUSED (%s)", | |||
3836 | s->s->s->for_subst_vec[i].first->id); | |||
3837 | } | |||
3838 | ||||
3839 | fprintf (f, ")\n{\n"); | |||
3840 | s->s->gen_1 (f, 2, gimple, s->s->s->result); | |||
3841 | if (gimple) | |||
3842 | fprintf (f, " return false;\n"); | |||
3843 | else | |||
3844 | fprintf (f, " return NULL_TREE;\n"); | |||
3845 | fprintf (f, "}\n"); | |||
3846 | } | |||
3847 | fprintf (stderrstderr, "removed %u duplicate tails\n", rcnt); | |||
3848 | ||||
3849 | for (unsigned n = 1; n <= 5; ++n) | |||
3850 | { | |||
3851 | bool has_kids_p = false; | |||
3852 | ||||
3853 | /* First generate split-out functions. */ | |||
3854 | for (unsigned j = 0; j < root->kids.length (); j++) | |||
3855 | { | |||
3856 | dt_operand *dop = static_cast<dt_operand *>(root->kids[j]); | |||
3857 | expr *e = static_cast<expr *>(dop->op); | |||
3858 | if (e->ops.length () != n | |||
3859 | /* Builtin simplifications are somewhat premature on | |||
3860 | GENERIC. The following drops patterns with outermost | |||
3861 | calls. It's easy to emit overloads for function code | |||
3862 | though if necessary. */ | |||
3863 | || (!gimple | |||
3864 | && e->operation->kind != id_base::CODE)) | |||
3865 | continue; | |||
3866 | ||||
3867 | if (gimple) | |||
3868 | fprintf (f, "\nstatic bool\n" | |||
3869 | "gimple_simplify_%s (gimple_match_op *res_op," | |||
3870 | " gimple_seq *seq,\n" | |||
3871 | " tree (*valueize)(tree) " | |||
3872 | "ATTRIBUTE_UNUSED,\n" | |||
3873 | " code_helper ARG_UNUSED (code), tree " | |||
3874 | "ARG_UNUSED (type)\n", | |||
3875 | e->operation->id); | |||
3876 | else | |||
3877 | fprintf (f, "\nstatic tree\n" | |||
3878 | "generic_simplify_%s (location_t ARG_UNUSED (loc), enum " | |||
3879 | "tree_code ARG_UNUSED (code), const tree ARG_UNUSED (type)", | |||
3880 | e->operation->id); | |||
3881 | for (unsigned i = 0; i < n; ++i) | |||
3882 | fprintf (f, ", tree _p%d", i); | |||
3883 | fprintf (f, ")\n"); | |||
3884 | fprintf (f, "{\n"); | |||
3885 | dop->gen_kids (f, 2, gimple, 0); | |||
3886 | if (gimple) | |||
3887 | fprintf (f, " return false;\n"); | |||
3888 | else | |||
3889 | fprintf (f, " return NULL_TREE;\n"); | |||
3890 | fprintf (f, "}\n"); | |||
3891 | has_kids_p = true; | |||
3892 | } | |||
3893 | ||||
3894 | /* If this main entry has no children, avoid generating code | |||
3895 | with compiler warnings, by generating a simple stub. */ | |||
3896 | if (! has_kids_p) | |||
3897 | { | |||
3898 | if (gimple) | |||
3899 | fprintf (f, "\nstatic bool\n" | |||
3900 | "gimple_simplify (gimple_match_op*, gimple_seq*,\n" | |||
3901 | " tree (*)(tree), code_helper,\n" | |||
3902 | " const tree"); | |||
3903 | else | |||
3904 | fprintf (f, "\ntree\n" | |||
3905 | "generic_simplify (location_t, enum tree_code,\n" | |||
3906 | " const tree"); | |||
3907 | for (unsigned i = 0; i < n; ++i) | |||
3908 | fprintf (f, ", tree"); | |||
3909 | fprintf (f, ")\n"); | |||
3910 | fprintf (f, "{\n"); | |||
3911 | if (gimple) | |||
3912 | fprintf (f, " return false;\n"); | |||
3913 | else | |||
3914 | fprintf (f, " return NULL_TREE;\n"); | |||
3915 | fprintf (f, "}\n"); | |||
3916 | continue; | |||
3917 | } | |||
3918 | ||||
3919 | /* Then generate the main entry with the outermost switch and | |||
3920 | tail-calls to the split-out functions. */ | |||
3921 | if (gimple) | |||
3922 | fprintf (f, "\nstatic bool\n" | |||
3923 | "gimple_simplify (gimple_match_op *res_op, gimple_seq *seq,\n" | |||
3924 | " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n" | |||
3925 | " code_helper code, const tree type"); | |||
3926 | else | |||
3927 | fprintf (f, "\ntree\n" | |||
3928 | "generic_simplify (location_t loc, enum tree_code code, " | |||
3929 | "const tree type ATTRIBUTE_UNUSED"); | |||
3930 | for (unsigned i = 0; i < n; ++i) | |||
3931 | fprintf (f, ", tree _p%d", i); | |||
3932 | fprintf (f, ")\n"); | |||
3933 | fprintf (f, "{\n"); | |||
3934 | ||||
3935 | if (gimple) | |||
3936 | fprintf (f, " switch (code.get_rep())\n" | |||
3937 | " {\n"); | |||
3938 | else | |||
3939 | fprintf (f, " switch (code)\n" | |||
3940 | " {\n"); | |||
3941 | for (unsigned i = 0; i < root->kids.length (); i++) | |||
3942 | { | |||
3943 | dt_operand *dop = static_cast<dt_operand *>(root->kids[i]); | |||
3944 | expr *e = static_cast<expr *>(dop->op); | |||
3945 | if (e->ops.length () != n | |||
3946 | /* Builtin simplifications are somewhat premature on | |||
3947 | GENERIC. The following drops patterns with outermost | |||
3948 | calls. It's easy to emit overloads for function code | |||
3949 | though if necessary. */ | |||
3950 | || (!gimple | |||
3951 | && e->operation->kind != id_base::CODE)) | |||
3952 | continue; | |||
3953 | ||||
3954 | if (*e->operation == CONVERT_EXPR | |||
3955 | || *e->operation == NOP_EXPR) | |||
3956 | fprintf (f, " CASE_CONVERT:\n"); | |||
3957 | else | |||
3958 | fprintf (f, " case %s%s:\n", | |||
3959 | is_a <fn_id *> (e->operation) ? "-" : "", | |||
3960 | e->operation->id); | |||
3961 | if (gimple) | |||
3962 | fprintf (f, " return gimple_simplify_%s (res_op, " | |||
3963 | "seq, valueize, code, type", e->operation->id); | |||
3964 | else | |||
3965 | fprintf (f, " return generic_simplify_%s (loc, code, type", | |||
3966 | e->operation->id); | |||
3967 | for (unsigned j = 0; j < n; ++j) | |||
3968 | fprintf (f, ", _p%d", j); | |||
3969 | fprintf (f, ");\n"); | |||
3970 | } | |||
3971 | fprintf (f, " default:;\n" | |||
3972 | " }\n"); | |||
3973 | ||||
3974 | if (gimple) | |||
3975 | fprintf (f, " return false;\n"); | |||
3976 | else | |||
3977 | fprintf (f, " return NULL_TREE;\n"); | |||
3978 | fprintf (f, "}\n"); | |||
3979 | } | |||
3980 | } | |||
3981 | ||||
3982 | /* Output code to implement the predicate P from the decision tree DT. */ | |||
3983 | ||||
3984 | void | |||
3985 | write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple) | |||
3986 | { | |||
3987 | fprintf (f, "\nbool\n" | |||
3988 | "%s%s (tree t%s%s)\n" | |||
3989 | "{\n", gimple ? "gimple_" : "tree_", p->id, | |||
3990 | p->nargs > 0 ? ", tree *res_ops" : "", | |||
3991 | gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : ""); | |||
3992 | /* Conveniently make 'type' available. */ | |||
3993 | fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n"); | |||
3994 | ||||
3995 | if (!gimple) | |||
3996 | fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n"); | |||
3997 | dt.root->gen_kids (f, 2, gimple, 0); | |||
3998 | ||||
3999 | fprintf_indent (f, 2, "return false;\n" | |||
4000 | "}\n"); | |||
4001 | } | |||
4002 | ||||
4003 | /* Write the common header for the GIMPLE/GENERIC IL matching routines. */ | |||
4004 | ||||
4005 | static void | |||
4006 | write_header (FILE *f, const char *head) | |||
4007 | { | |||
4008 | fprintf (f, "/* Generated automatically by the program `genmatch' from\n"); | |||
4009 | fprintf (f, " a IL pattern matching and simplification description. */\n"); | |||
4010 | ||||
4011 | /* Include the header instead of writing it awkwardly quoted here. */ | |||
4012 | fprintf (f, "\n#include \"%s\"\n", head); | |||
4013 | } | |||
4014 | ||||
4015 | ||||
4016 | ||||
4017 | /* AST parsing. */ | |||
4018 | ||||
4019 | class parser | |||
4020 | { | |||
4021 | public: | |||
4022 | parser (cpp_reader *, bool gimple); | |||
4023 | ||||
4024 | private: | |||
4025 | const cpp_token *next (); | |||
4026 | const cpp_token *peek (unsigned = 1); | |||
4027 | const cpp_token *peek_ident (const char * = NULLnullptr, unsigned = 1); | |||
4028 | const cpp_token *expect (enum cpp_ttype); | |||
4029 | const cpp_token *eat_token (enum cpp_ttype); | |||
4030 | const char *get_string (); | |||
4031 | const char *get_ident (); | |||
4032 | const cpp_token *eat_ident (const char *); | |||
4033 | const char *get_number (); | |||
4034 | ||||
4035 | unsigned get_internal_capture_id (); | |||
4036 | ||||
4037 | id_base *parse_operation (unsigned char &); | |||
4038 | operand *parse_capture (operand *, bool); | |||
4039 | operand *parse_expr (); | |||
4040 | c_expr *parse_c_expr (cpp_ttype); | |||
4041 | operand *parse_op (); | |||
4042 | ||||
4043 | void record_operlist (location_t, user_id *); | |||
4044 | ||||
4045 | void parse_pattern (); | |||
4046 | operand *parse_result (operand *, predicate_id *); | |||
4047 | void push_simplify (simplify::simplify_kind, | |||
4048 | vec<simplify *>&, operand *, operand *); | |||
4049 | void parse_simplify (simplify::simplify_kind, | |||
4050 | vec<simplify *>&, predicate_id *, operand *); | |||
4051 | void parse_for (location_t); | |||
4052 | void parse_if (location_t); | |||
4053 | void parse_predicates (location_t); | |||
4054 | void parse_operator_list (location_t); | |||
4055 | ||||
4056 | void finish_match_operand (operand *); | |||
4057 | ||||
4058 | cpp_reader *r; | |||
4059 | bool gimple; | |||
4060 | vec<c_expr *> active_ifs; | |||
4061 | vec<vec<user_id *> > active_fors; | |||
4062 | hash_set<user_id *> *oper_lists_set; | |||
4063 | vec<user_id *> oper_lists; | |||
4064 | ||||
4065 | cid_map_t *capture_ids; | |||
4066 | unsigned last_id; | |||
4067 | ||||
4068 | public: | |||
4069 | vec<simplify *> simplifiers; | |||
4070 | vec<predicate_id *> user_predicates; | |||
4071 | bool parsing_match_operand; | |||
4072 | }; | |||
4073 | ||||
4074 | /* Lexing helpers. */ | |||
4075 | ||||
4076 | /* Read the next non-whitespace token from R. */ | |||
4077 | ||||
4078 | const cpp_token * | |||
4079 | parser::next () | |||
4080 | { | |||
4081 | const cpp_token *token; | |||
4082 | do | |||
4083 | { | |||
4084 | token = cpp_get_token (r); | |||
4085 | } | |||
4086 | while (token->type == CPP_PADDING); | |||
4087 | return token; | |||
4088 | } | |||
4089 | ||||
4090 | /* Peek at the next non-whitespace token from R. */ | |||
4091 | ||||
4092 | const cpp_token * | |||
4093 | parser::peek (unsigned num) | |||
4094 | { | |||
4095 | const cpp_token *token; | |||
4096 | unsigned i = 0; | |||
4097 | do | |||
4098 | { | |||
4099 | token = cpp_peek_token (r, i++); | |||
4100 | } | |||
4101 | while (token->type == CPP_PADDING | |||
4102 | || (--num > 0)); | |||
4103 | /* If we peek at EOF this is a fatal error as it leaves the | |||
4104 | cpp_reader in unusable state. Assume we really wanted a | |||
4105 | token and thus this EOF is unexpected. */ | |||
4106 | if (token->type == CPP_EOF) | |||
4107 | fatal_at (token, "unexpected end of file"); | |||
4108 | return token; | |||
4109 | } | |||
4110 | ||||
4111 | /* Peek at the next identifier token (or return NULL if the next | |||
4112 | token is not an identifier or equal to ID if supplied). */ | |||
4113 | ||||
4114 | const cpp_token * | |||
4115 | parser::peek_ident (const char *id, unsigned num) | |||
4116 | { | |||
4117 | const cpp_token *token = peek (num); | |||
4118 | if (token->type != CPP_NAME) | |||
4119 | return 0; | |||
4120 | ||||
4121 | if (id == 0) | |||
4122 | return token; | |||
4123 | ||||
4124 | const char *t = (const char *) CPP_HASHNODE (token->val.node.node)((cpp_hashnode *) (token->val.node.node))->ident.str; | |||
4125 | if (strcmp (id, t) == 0) | |||
4126 | return token; | |||
4127 | ||||
4128 | return 0; | |||
4129 | } | |||
4130 | ||||
4131 | /* Read the next token from R and assert it is of type TK. */ | |||
4132 | ||||
4133 | const cpp_token * | |||
4134 | parser::expect (enum cpp_ttype tk) | |||
4135 | { | |||
4136 | const cpp_token *token = next (); | |||
4137 | if (token->type != tk) | |||
4138 | fatal_at (token, "expected %s, got %s", | |||
4139 | cpp_type2name (tk, 0), cpp_type2name (token->type, 0)); | |||
4140 | ||||
4141 | return token; | |||
4142 | } | |||
4143 | ||||
4144 | /* Consume the next token from R and assert it is of type TK. */ | |||
4145 | ||||
4146 | const cpp_token * | |||
4147 | parser::eat_token (enum cpp_ttype tk) | |||
4148 | { | |||
4149 | return expect (tk); | |||
4150 | } | |||
4151 | ||||
4152 | /* Read the next token from R and assert it is of type CPP_STRING and | |||
4153 | return its value. */ | |||
4154 | ||||
4155 | const char * | |||
4156 | parser::get_string () | |||
4157 | { | |||
4158 | const cpp_token *token = expect (CPP_STRING); | |||
4159 | return (const char *)token->val.str.text; | |||
4160 | } | |||
4161 | ||||
4162 | /* Read the next token from R and assert it is of type CPP_NAME and | |||
4163 | return its value. */ | |||
4164 | ||||
4165 | const char * | |||
4166 | parser::get_ident () | |||
4167 | { | |||
4168 | const cpp_token *token = expect (CPP_NAME); | |||
4169 | return (const char *)CPP_HASHNODE (token->val.node.node)((cpp_hashnode *) (token->val.node.node))->ident.str; | |||
4170 | } | |||
4171 | ||||
4172 | /* Eat an identifier token with value S from R. */ | |||
4173 | ||||
4174 | const cpp_token * | |||
4175 | parser::eat_ident (const char *s) | |||
4176 | { | |||
4177 | const cpp_token *token = peek (); | |||
4178 | const char *t = get_ident (); | |||
4179 | if (strcmp (s, t) != 0) | |||
4180 | fatal_at (token, "expected '%s' got '%s'\n", s, t); | |||
4181 | return token; | |||
4182 | } | |||
4183 | ||||
4184 | /* Read the next token from R and assert it is of type CPP_NUMBER and | |||
4185 | return its value. */ | |||
4186 | ||||
4187 | const char * | |||
4188 | parser::get_number () | |||
4189 | { | |||
4190 | const cpp_token *token = expect (CPP_NUMBER); | |||
4191 | return (const char *)token->val.str.text; | |||
4192 | } | |||
4193 | ||||
4194 | /* Return a capture ID that can be used internally. */ | |||
4195 | ||||
4196 | unsigned | |||
4197 | parser::get_internal_capture_id () | |||
4198 | { | |||
4199 | unsigned newid = capture_ids->elements (); | |||
4200 | /* Big enough for a 32-bit UINT_MAX plus prefix. */ | |||
4201 | char id[13]; | |||
4202 | bool existed; | |||
4203 | snprintf (id, sizeof (id), "__%u", newid); | |||
4204 | capture_ids->get_or_insert (xstrdup (id), &existed); | |||
4205 | if (existed) | |||
4206 | fatal ("reserved capture id '%s' already used", id); | |||
4207 | return newid; | |||
4208 | } | |||
4209 | ||||
4210 | /* Record an operator-list use for transparent for handling. */ | |||
4211 | ||||
4212 | void | |||
4213 | parser::record_operlist (location_t loc, user_id *p) | |||
4214 | { | |||
4215 | if (!oper_lists_set->add (p)) | |||
4216 | { | |||
4217 | if (!oper_lists.is_empty () | |||
4218 | && oper_lists[0]->substitutes.length () != p->substitutes.length ()) | |||
4219 | fatal_at (loc, "User-defined operator list does not have the " | |||
4220 | "same number of entries as others used in the pattern"); | |||
4221 | oper_lists.safe_push (p); | |||
4222 | } | |||
4223 | } | |||
4224 | ||||
4225 | /* Parse the operator ID, special-casing convert?, convert1? and | |||
4226 | convert2? */ | |||
4227 | ||||
4228 | id_base * | |||
4229 | parser::parse_operation (unsigned char &opt_grp) | |||
4230 | { | |||
4231 | const cpp_token *id_tok = peek (); | |||
4232 | char *alt_id = NULLnullptr; | |||
4233 | const char *id = get_ident (); | |||
4234 | const cpp_token *token = peek (); | |||
4235 | opt_grp = 0; | |||
4236 | if (token->type == CPP_QUERY | |||
4237 | && !(token->flags & PREV_WHITE(1 << 0))) | |||
4238 | { | |||
4239 | if (!parsing_match_operand) | |||
4240 | fatal_at (id_tok, "conditional convert can only be used in " | |||
4241 | "match expression"); | |||
4242 | if (ISDIGIT (id[strlen (id) - 1])(_sch_istable[(id[strlen (id) - 1]) & 0xff] & (unsigned short)(_sch_isdigit))) | |||
4243 | { | |||
4244 | opt_grp = id[strlen (id) - 1] - '0' + 1; | |||
4245 | alt_id = xstrdup (id); | |||
4246 | alt_id[strlen (id) - 1] = '\0'; | |||
4247 | if (opt_grp == 1) | |||
4248 | fatal_at (id_tok, "use '%s?' here", alt_id); | |||
4249 | } | |||
4250 | else | |||
4251 | opt_grp = 1; | |||
4252 | eat_token (CPP_QUERY); | |||
4253 | } | |||
4254 | id_base *op = get_operator (alt_id ? alt_id : id); | |||
4255 | if (!op) | |||
4256 | fatal_at (id_tok, "unknown operator %s", alt_id ? alt_id : id); | |||
4257 | if (alt_id) | |||
4258 | free (alt_id); | |||
4259 | user_id *p = dyn_cast<user_id *> (op); | |||
4260 | if (p && p->is_oper_list) | |||
4261 | { | |||
4262 | if (active_fors.length() == 0) | |||
4263 | record_operlist (id_tok->src_loc, p); | |||
4264 | else | |||
4265 | fatal_at (id_tok, "operator-list %s cannot be expanded inside 'for'", id); | |||
4266 | } | |||
4267 | return op; | |||
4268 | } | |||
4269 | ||||
4270 | /* Parse a capture. | |||
4271 | capture = '@'<number> */ | |||
4272 | ||||
4273 | class operand * | |||
4274 | parser::parse_capture (operand *op, bool require_existing) | |||
4275 | { | |||
4276 | location_t src_loc = eat_token (CPP_ATSIGN)->src_loc; | |||
4277 | const cpp_token *token = peek (); | |||
4278 | const char *id = NULLnullptr; | |||
4279 | bool value_match = false; | |||
4280 | /* For matches parse @@ as a value-match denoting the prevailing operand. */ | |||
4281 | if (token->type == CPP_ATSIGN | |||
4282 | && ! (token->flags & PREV_WHITE(1 << 0)) | |||
4283 | && parsing_match_operand) | |||
4284 | { | |||
4285 | eat_token (CPP_ATSIGN); | |||
4286 | token = peek (); | |||
4287 | value_match = true; | |||
4288 | } | |||
4289 | if (token->type == CPP_NUMBER) | |||
4290 | id = get_number (); | |||
4291 | else if (token->type == CPP_NAME) | |||
4292 | id = get_ident (); | |||
4293 | else | |||
4294 | fatal_at (token, "expected number or identifier"); | |||
4295 | unsigned next_id = capture_ids->elements (); | |||
4296 | bool existed; | |||
4297 | unsigned &num = capture_ids->get_or_insert (id, &existed); | |||
4298 | if (!existed) | |||
4299 | { | |||
4300 | if (require_existing) | |||
4301 | fatal_at (src_loc, "unknown capture id"); | |||
4302 | num = next_id; | |||
4303 | } | |||
4304 | return new capture (src_loc, num, op, value_match); | |||
4305 | } | |||
4306 | ||||
4307 | /* Parse an expression | |||
4308 | expr = '(' <operation>[capture][flag][type] <operand>... ')' */ | |||
4309 | ||||
4310 | class operand * | |||
4311 | parser::parse_expr () | |||
4312 | { | |||
4313 | const cpp_token *token = peek (); | |||
4314 | unsigned char opt_grp; | |||
4315 | expr *e = new expr (parse_operation (opt_grp), token->src_loc); | |||
4316 | token = peek (); | |||
4317 | operand *op; | |||
4318 | bool is_commutative = false; | |||
4319 | bool force_capture = false; | |||
4320 | const char *expr_type = NULLnullptr; | |||
4321 | ||||
4322 | if (!parsing_match_operand | |||
4323 | && token->type == CPP_NOT | |||
4324 | && !(token->flags & PREV_WHITE(1 << 0))) | |||
4325 | { | |||
4326 | eat_token (CPP_NOT); | |||
4327 | e->force_leaf = true; | |||
4328 | } | |||
4329 | ||||
4330 | if (token->type == CPP_COLON | |||
4331 | && !(token->flags & PREV_WHITE(1 << 0))) | |||
4332 | { | |||
4333 | eat_token (CPP_COLON); | |||
4334 | token = peek (); | |||
4335 | if (token->type == CPP_NAME | |||
4336 | && !(token->flags & PREV_WHITE(1 << 0))) | |||
4337 | { | |||
4338 | const char *s = get_ident (); | |||
4339 | if (!parsing_match_operand) | |||
4340 | expr_type = s; | |||
4341 | else | |||
4342 | { | |||
4343 | const char *sp = s; | |||
4344 | while (*sp) | |||
4345 | { | |||
4346 | if (*sp == 'c') | |||
4347 | { | |||
4348 | if (operator_id *o | |||
4349 | = dyn_cast<operator_id *> (e->operation)) | |||
4350 | { | |||
4351 | if (!commutative_tree_code (o->code) | |||
4352 | && !comparison_code_p (o->code)) | |||
4353 | fatal_at (token, "operation is not commutative"); | |||
4354 | } | |||
4355 | else if (user_id *p = dyn_cast<user_id *> (e->operation)) | |||
4356 | for (unsigned i = 0; | |||
4357 | i < p->substitutes.length (); ++i) | |||
4358 | { | |||
4359 | if (operator_id *q | |||
4360 | = dyn_cast<operator_id *> (p->substitutes[i])) | |||
4361 | { | |||
4362 | if (!commutative_tree_code (q->code) | |||
4363 | && !comparison_code_p (q->code)) | |||
4364 | fatal_at (token, "operation %s is not " | |||
4365 | "commutative", q->id); | |||
4366 | } | |||
4367 | } | |||
4368 | is_commutative = true; | |||
4369 | } | |||
4370 | else if (*sp == 'C') | |||
4371 | is_commutative = true; | |||
4372 | else if (*sp == 's') | |||
4373 | { | |||
4374 | e->force_single_use = true; | |||
4375 | force_capture = true; | |||
4376 | } | |||
4377 | else | |||
4378 | fatal_at (token, "flag %c not recognized", *sp); | |||
4379 | sp++; | |||
4380 | } | |||
4381 | } | |||
4382 | token = peek (); | |||
4383 | } | |||
4384 | else | |||
4385 | fatal_at (token, "expected flag or type specifying identifier"); | |||
4386 | } | |||
4387 | ||||
4388 | if (token->type == CPP_ATSIGN | |||
4389 | && !(token->flags & PREV_WHITE(1 << 0))) | |||
4390 | op = parse_capture (e, false); | |||
4391 | else if (force_capture) | |||
4392 | { | |||
4393 | unsigned num = get_internal_capture_id (); | |||
4394 | op = new capture (token->src_loc, num, e, false); | |||
4395 | } | |||
4396 | else | |||
4397 | op = e; | |||
4398 | do | |||
4399 | { | |||
4400 | token = peek (); | |||
4401 | if (token->type == CPP_CLOSE_PAREN) | |||
4402 | { | |||
4403 | if (e->operation->nargs != -1 | |||
4404 | && e->operation->nargs != (int) e->ops.length ()) | |||
4405 | fatal_at (token, "'%s' expects %u operands, not %u", | |||
4406 | e->operation->id, e->operation->nargs, e->ops.length ()); | |||
4407 | if (is_commutative) | |||
4408 | { | |||
4409 | if (e->ops.length () == 2 | |||
4410 | || commutative_op (e->operation) >= 0) | |||
4411 | e->is_commutative = true; | |||
4412 | else | |||
4413 | fatal_at (token, "only binary operators or functions with " | |||
4414 | "two arguments can be marked commutative, " | |||
4415 | "unless the operation is known to be inherently " | |||
4416 | "commutative"); | |||
4417 | } | |||
4418 | e->expr_type = expr_type; | |||
4419 | if (opt_grp != 0) | |||
4420 | { | |||
4421 | if (e->ops.length () != 1) | |||
4422 | fatal_at (token, "only unary operations can be conditional"); | |||
4423 | e->opt_grp = opt_grp; | |||
4424 | } | |||
4425 | return op; | |||
4426 | } | |||
4427 | else if (!(token->flags & PREV_WHITE(1 << 0))) | |||
4428 | fatal_at (token, "expected expression operand"); | |||
4429 | ||||
4430 | e->append_op (parse_op ()); | |||
4431 | } | |||
4432 | while (1); | |||
4433 | } | |||
4434 | ||||
4435 | /* Lex native C code delimited by START recording the preprocessing tokens | |||
4436 | for later processing. | |||
4437 | c_expr = ('{'|'(') <pp token>... ('}'|')') */ | |||
4438 | ||||
4439 | c_expr * | |||
4440 | parser::parse_c_expr (cpp_ttype start) | |||
4441 | { | |||
4442 | const cpp_token *token; | |||
4443 | cpp_ttype end; | |||
4444 | unsigned opencnt; | |||
4445 | vec<cpp_token> code = vNULL; | |||
4446 | unsigned nr_stmts = 0; | |||
4447 | location_t loc = eat_token (start)->src_loc; | |||
4448 | if (start == CPP_OPEN_PAREN) | |||
4449 | end = CPP_CLOSE_PAREN; | |||
4450 | else if (start == CPP_OPEN_BRACE) | |||
4451 | end = CPP_CLOSE_BRACE; | |||
4452 | else | |||
4453 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genmatch.cc" , 4453, __FUNCTION__)); | |||
4454 | opencnt = 1; | |||
4455 | do | |||
4456 | { | |||
4457 | token = next (); | |||
4458 | ||||
4459 | /* Count brace pairs to find the end of the expr to match. */ | |||
4460 | if (token->type == start) | |||
4461 | opencnt++; | |||
4462 | else if (token->type == end | |||
4463 | && --opencnt == 0) | |||
4464 | break; | |||
4465 | else if (token->type == CPP_EOF) | |||
4466 | fatal_at (token, "unexpected end of file"); | |||
4467 | ||||
4468 | /* This is a lame way of counting the number of statements. */ | |||
4469 | if (token->type == CPP_SEMICOLON) | |||
4470 | nr_stmts++; | |||
4471 | ||||
4472 | /* If this is possibly a user-defined identifier mark it used. */ | |||
4473 | if (token->type == CPP_NAME) | |||
4474 | { | |||
4475 | const char *str | |||
4476 | = (const char *)CPP_HASHNODE (token->val.node.node)((cpp_hashnode *) (token->val.node.node))->ident.str; | |||
4477 | if (strcmp (str, "return") == 0) | |||
4478 | fatal_at (token, "return statement not allowed in C expression"); | |||
4479 | id_base *idb = get_operator (str); | |||
4480 | user_id *p; | |||
4481 | if (idb && (p = dyn_cast<user_id *> (idb)) && p->is_oper_list) | |||
4482 | record_operlist (token->src_loc, p); | |||
4483 | } | |||
4484 | ||||
4485 | /* Record the token. */ | |||
4486 | code.safe_push (*token); | |||
4487 | } | |||
4488 | while (1); | |||
4489 | return new c_expr (r, loc, code, nr_stmts, vNULL, capture_ids); | |||
4490 | } | |||
4491 | ||||
4492 | /* Parse an operand which is either an expression, a predicate or | |||
4493 | a standalone capture. | |||
4494 | op = predicate | expr | c_expr | capture */ | |||
4495 | ||||
4496 | class operand * | |||
4497 | parser::parse_op () | |||
4498 | { | |||
4499 | const cpp_token *token = peek (); | |||
4500 | class operand *op = NULLnullptr; | |||
4501 | if (token->type == CPP_OPEN_PAREN) | |||
4502 | { | |||
4503 | eat_token (CPP_OPEN_PAREN); | |||
4504 | op = parse_expr (); | |||
4505 | eat_token (CPP_CLOSE_PAREN); | |||
4506 | } | |||
4507 | else if (token->type == CPP_OPEN_BRACE) | |||
4508 | { | |||
4509 | op = parse_c_expr (CPP_OPEN_BRACE); | |||
4510 | } | |||
4511 | else | |||
4512 | { | |||
4513 | /* Remaining ops are either empty or predicates */ | |||
4514 | if (token->type == CPP_NAME) | |||
4515 | { | |||
4516 | const char *id = get_ident (); | |||
4517 | id_base *opr = get_operator (id); | |||
4518 | if (!opr) | |||
4519 | fatal_at (token, "expected predicate name"); | |||
4520 | if (operator_id *code1 = dyn_cast <operator_id *> (opr)) | |||
4521 | { | |||
4522 | if (code1->nargs != 0) | |||
4523 | fatal_at (token, "using an operator with operands as predicate"); | |||
4524 | /* Parse the zero-operand operator "predicates" as | |||
4525 | expression. */ | |||
4526 | op = new expr (opr, token->src_loc); | |||
4527 | } | |||
4528 | else if (user_id *code2 = dyn_cast <user_id *> (opr)) | |||
4529 | { | |||
4530 | if (code2->nargs != 0) | |||
4531 | fatal_at (token, "using an operator with operands as predicate"); | |||
4532 | /* Parse the zero-operand operator "predicates" as | |||
4533 | expression. */ | |||
4534 | op = new expr (opr, token->src_loc); | |||
4535 | } | |||
4536 | else if (predicate_id *p = dyn_cast <predicate_id *> (opr)) | |||
4537 | op = new predicate (p, token->src_loc); | |||
4538 | else | |||
4539 | fatal_at (token, "using an unsupported operator as predicate"); | |||
4540 | if (!parsing_match_operand) | |||
4541 | fatal_at (token, "predicates are only allowed in match expression"); | |||
4542 | token = peek (); | |||
4543 | if (token->flags & PREV_WHITE(1 << 0)) | |||
4544 | return op; | |||
4545 | } | |||
4546 | else if (token->type != CPP_COLON | |||
4547 | && token->type != CPP_ATSIGN) | |||
4548 | fatal_at (token, "expected expression or predicate"); | |||
4549 | /* optionally followed by a capture and a predicate. */ | |||
4550 | if (token->type == CPP_COLON) | |||
4551 | fatal_at (token, "not implemented: predicate on leaf operand"); | |||
4552 | if (token->type == CPP_ATSIGN) | |||
4553 | op = parse_capture (op, !parsing_match_operand); | |||
4554 | } | |||
4555 | ||||
4556 | return op; | |||
4557 | } | |||
4558 | ||||
4559 | /* Create a new simplify from the current parsing state and MATCH, | |||
4560 | MATCH_LOC, RESULT and RESULT_LOC and push it to SIMPLIFIERS. */ | |||
4561 | ||||
4562 | void | |||
4563 | parser::push_simplify (simplify::simplify_kind kind, | |||
4564 | vec<simplify *>& simplifiers, | |||
4565 | operand *match, operand *result) | |||
4566 | { | |||
4567 | /* Build and push a temporary for operator list uses in expressions. */ | |||
4568 | if (!oper_lists.is_empty ()) | |||
4569 | active_fors.safe_push (oper_lists); | |||
4570 | ||||
4571 | simplifiers.safe_push | |||
4572 | (new simplify (kind, last_id++, match, result, | |||
4573 | active_fors.copy (), capture_ids)); | |||
4574 | ||||
4575 | if (!oper_lists.is_empty ()) | |||
4576 | active_fors.pop (); | |||
4577 | } | |||
4578 | ||||
4579 | /* Parse | |||
4580 | <result-op> = <op> | <if> | <with> | |||
4581 | <if> = '(' 'if' '(' <c-expr> ')' <result-op> ')' | |||
4582 | <with> = '(' 'with' '{' <c-expr> '}' <result-op> ')' | |||
4583 | and return it. */ | |||
4584 | ||||
4585 | operand * | |||
4586 | parser::parse_result (operand *result, predicate_id *matcher) | |||
4587 | { | |||
4588 | const cpp_token *token = peek (); | |||
4589 | if (token->type != CPP_OPEN_PAREN) | |||
4590 | return parse_op (); | |||
4591 | ||||
4592 | eat_token (CPP_OPEN_PAREN); | |||
4593 | if (peek_ident ("if")) | |||
4594 | { | |||
4595 | eat_ident ("if"); | |||
4596 | if_expr *ife = new if_expr (token->src_loc); | |||
4597 | ife->cond = parse_c_expr (CPP_OPEN_PAREN); | |||
4598 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4599 | { | |||
4600 | ife->trueexpr = parse_result (result, matcher); | |||
4601 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4602 | ife->falseexpr = parse_result (result, matcher); | |||
4603 | else if (peek ()->type != CPP_CLOSE_PAREN) | |||
4604 | ife->falseexpr = parse_op (); | |||
4605 | } | |||
4606 | else if (peek ()->type != CPP_CLOSE_PAREN) | |||
4607 | { | |||
4608 | ife->trueexpr = parse_op (); | |||
4609 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4610 | ife->falseexpr = parse_result (result, matcher); | |||
4611 | else if (peek ()->type != CPP_CLOSE_PAREN) | |||
4612 | ife->falseexpr = parse_op (); | |||
4613 | } | |||
4614 | /* If this if is immediately closed then it contains a | |||
4615 | manual matcher or is part of a predicate definition. */ | |||
4616 | else /* if (peek ()->type == CPP_CLOSE_PAREN) */ | |||
4617 | { | |||
4618 | if (!matcher) | |||
4619 | fatal_at (peek (), "manual transform not implemented"); | |||
4620 | ife->trueexpr = result; | |||
4621 | } | |||
4622 | eat_token (CPP_CLOSE_PAREN); | |||
4623 | return ife; | |||
4624 | } | |||
4625 | else if (peek_ident ("with")) | |||
4626 | { | |||
4627 | eat_ident ("with"); | |||
4628 | with_expr *withe = new with_expr (token->src_loc); | |||
4629 | /* Parse (with c-expr expr) as (if-with (true) expr). */ | |||
4630 | withe->with = parse_c_expr (CPP_OPEN_BRACE); | |||
4631 | withe->with->nr_stmts = 0; | |||
4632 | withe->subexpr = parse_result (result, matcher); | |||
4633 | eat_token (CPP_CLOSE_PAREN); | |||
4634 | return withe; | |||
4635 | } | |||
4636 | else if (peek_ident ("switch")) | |||
4637 | { | |||
4638 | token = eat_ident ("switch"); | |||
4639 | location_t ifloc = eat_token (CPP_OPEN_PAREN)->src_loc; | |||
4640 | eat_ident ("if"); | |||
4641 | if_expr *ife = new if_expr (ifloc); | |||
4642 | operand *res = ife; | |||
4643 | ife->cond = parse_c_expr (CPP_OPEN_PAREN); | |||
4644 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4645 | ife->trueexpr = parse_result (result, matcher); | |||
4646 | else | |||
4647 | ife->trueexpr = parse_op (); | |||
4648 | eat_token (CPP_CLOSE_PAREN); | |||
4649 | if (peek ()->type != CPP_OPEN_PAREN | |||
4650 | || !peek_ident ("if", 2)) | |||
4651 | fatal_at (token, "switch can be implemented with a single if"); | |||
4652 | while (peek ()->type != CPP_CLOSE_PAREN) | |||
4653 | { | |||
4654 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4655 | { | |||
4656 | if (peek_ident ("if", 2)) | |||
4657 | { | |||
4658 | ifloc = eat_token (CPP_OPEN_PAREN)->src_loc; | |||
4659 | eat_ident ("if"); | |||
4660 | ife->falseexpr = new if_expr (ifloc); | |||
4661 | ife = as_a <if_expr *> (ife->falseexpr); | |||
4662 | ife->cond = parse_c_expr (CPP_OPEN_PAREN); | |||
4663 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4664 | ife->trueexpr = parse_result (result, matcher); | |||
4665 | else | |||
4666 | ife->trueexpr = parse_op (); | |||
4667 | eat_token (CPP_CLOSE_PAREN); | |||
4668 | } | |||
4669 | else | |||
4670 | { | |||
4671 | /* switch default clause */ | |||
4672 | ife->falseexpr = parse_result (result, matcher); | |||
4673 | eat_token (CPP_CLOSE_PAREN); | |||
4674 | return res; | |||
4675 | } | |||
4676 | } | |||
4677 | else | |||
4678 | { | |||
4679 | /* switch default clause */ | |||
4680 | ife->falseexpr = parse_op (); | |||
4681 | eat_token (CPP_CLOSE_PAREN); | |||
4682 | return res; | |||
4683 | } | |||
4684 | } | |||
4685 | eat_token (CPP_CLOSE_PAREN); | |||
4686 | return res; | |||
4687 | } | |||
4688 | else | |||
4689 | { | |||
4690 | operand *op = result; | |||
4691 | if (!matcher) | |||
4692 | op = parse_expr (); | |||
4693 | eat_token (CPP_CLOSE_PAREN); | |||
4694 | return op; | |||
4695 | } | |||
4696 | } | |||
4697 | ||||
4698 | /* Parse | |||
4699 | simplify = 'simplify' <expr> <result-op> | |||
4700 | or | |||
4701 | match = 'match' <ident> <expr> [<result-op>] | |||
4702 | and fill SIMPLIFIERS with the results. */ | |||
4703 | ||||
4704 | void | |||
4705 | parser::parse_simplify (simplify::simplify_kind kind, | |||
4706 | vec<simplify *>& simplifiers, predicate_id *matcher, | |||
4707 | operand *result) | |||
4708 | { | |||
4709 | /* Reset the capture map. */ | |||
4710 | if (!capture_ids) | |||
4711 | capture_ids = new cid_map_t; | |||
4712 | /* Reset oper_lists and set. */ | |||
4713 | hash_set <user_id *> olist; | |||
4714 | oper_lists_set = &olist; | |||
4715 | oper_lists = vNULL; | |||
4716 | ||||
4717 | const cpp_token *loc = peek (); | |||
4718 | parsing_match_operand = true; | |||
4719 | class operand *match = parse_op (); | |||
4720 | finish_match_operand (match); | |||
4721 | parsing_match_operand = false; | |||
4722 | if (match->type == operand::OP_CAPTURE && !matcher) | |||
4723 | fatal_at (loc, "outermost expression cannot be captured"); | |||
4724 | if (match->type == operand::OP_EXPR | |||
4725 | && is_a <predicate_id *> (as_a <expr *> (match)->operation)) | |||
4726 | fatal_at (loc, "outermost expression cannot be a predicate"); | |||
4727 | ||||
4728 | /* Splice active_ifs onto result and continue parsing the | |||
4729 | "then" expr. */ | |||
4730 | if_expr *active_if = NULLnullptr; | |||
4731 | for (int i = active_ifs.length (); i > 0; --i) | |||
4732 | { | |||
4733 | if_expr *ifc = new if_expr (active_ifs[i-1]->location); | |||
4734 | ifc->cond = active_ifs[i-1]; | |||
4735 | ifc->trueexpr = active_if; | |||
4736 | active_if = ifc; | |||
4737 | } | |||
4738 | if_expr *outermost_if = active_if; | |||
4739 | while (active_if && active_if->trueexpr) | |||
4740 | active_if = as_a <if_expr *> (active_if->trueexpr); | |||
4741 | ||||
4742 | const cpp_token *token = peek (); | |||
4743 | ||||
4744 | /* If this if is immediately closed then it is part of a predicate | |||
4745 | definition. Push it. */ | |||
4746 | if (token->type == CPP_CLOSE_PAREN) | |||
4747 | { | |||
4748 | if (!matcher) | |||
4749 | fatal_at (token, "expected transform expression"); | |||
4750 | if (active_if) | |||
4751 | { | |||
4752 | active_if->trueexpr = result; | |||
4753 | result = outermost_if; | |||
4754 | } | |||
4755 | push_simplify (kind, simplifiers, match, result); | |||
4756 | return; | |||
4757 | } | |||
4758 | ||||
4759 | operand *tem = parse_result (result, matcher); | |||
4760 | if (active_if) | |||
4761 | { | |||
4762 | active_if->trueexpr = tem; | |||
4763 | result = outermost_if; | |||
4764 | } | |||
4765 | else | |||
4766 | result = tem; | |||
4767 | ||||
4768 | push_simplify (kind, simplifiers, match, result); | |||
4769 | } | |||
4770 | ||||
4771 | /* Parsing of the outer control structures. */ | |||
4772 | ||||
4773 | /* Parse a for expression | |||
4774 | for = '(' 'for' <subst>... <pattern> ')' | |||
4775 | subst = <ident> '(' <ident>... ')' */ | |||
4776 | ||||
4777 | void | |||
4778 | parser::parse_for (location_t) | |||
4779 | { | |||
4780 | auto_vec<const cpp_token *> user_id_tokens; | |||
4781 | vec<user_id *> user_ids = vNULL; | |||
4782 | const cpp_token *token; | |||
4783 | unsigned min_n_opers = 0, max_n_opers = 0; | |||
4784 | ||||
4785 | while (1) | |||
4786 | { | |||
4787 | token = peek (); | |||
4788 | if (token->type != CPP_NAME) | |||
4789 | break; | |||
4790 | ||||
4791 | /* Insert the user defined operators into the operator hash. */ | |||
4792 | const char *id = get_ident (); | |||
4793 | if (get_operator (id, true) != NULLnullptr) | |||
4794 | fatal_at (token, "operator already defined"); | |||
4795 | user_id *op = new user_id (id); | |||
4796 | id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); | |||
4797 | *slot = op; | |||
4798 | user_ids.safe_push (op); | |||
4799 | user_id_tokens.safe_push (token); | |||
4800 | ||||
4801 | eat_token (CPP_OPEN_PAREN); | |||
4802 | ||||
4803 | int arity = -1; | |||
4804 | while ((token = peek_ident ()) != 0) | |||
4805 | { | |||
4806 | const char *oper = get_ident (); | |||
4807 | id_base *idb = get_operator (oper, true); | |||
4808 | if (idb == NULLnullptr) | |||
4809 | fatal_at (token, "no such operator '%s'", oper); | |||
4810 | ||||
4811 | if (arity == -1) | |||
4812 | arity = idb->nargs; | |||
4813 | else if (idb->nargs == -1) | |||
4814 | ; | |||
4815 | else if (idb->nargs != arity) | |||
4816 | fatal_at (token, "operator '%s' with arity %d does not match " | |||
4817 | "others with arity %d", oper, idb->nargs, arity); | |||
4818 | ||||
4819 | user_id *p = dyn_cast<user_id *> (idb); | |||
4820 | if (p) | |||
4821 | { | |||
4822 | if (p->is_oper_list) | |||
4823 | op->substitutes.safe_splice (p->substitutes); | |||
4824 | else | |||
4825 | fatal_at (token, "iterator cannot be used as operator-list"); | |||
4826 | } | |||
4827 | else | |||
4828 | op->substitutes.safe_push (idb); | |||
4829 | } | |||
4830 | op->nargs = arity; | |||
4831 | token = expect (CPP_CLOSE_PAREN); | |||
4832 | ||||
4833 | unsigned nsubstitutes = op->substitutes.length (); | |||
4834 | if (nsubstitutes == 0) | |||
4835 | fatal_at (token, "A user-defined operator must have at least " | |||
4836 | "one substitution"); | |||
4837 | if (max_n_opers == 0) | |||
4838 | { | |||
4839 | min_n_opers = nsubstitutes; | |||
4840 | max_n_opers = nsubstitutes; | |||
4841 | } | |||
4842 | else | |||
4843 | { | |||
4844 | if (nsubstitutes % min_n_opers != 0 | |||
4845 | && min_n_opers % nsubstitutes != 0) | |||
4846 | fatal_at (token, "All user-defined identifiers must have a " | |||
4847 | "multiple number of operator substitutions of the " | |||
4848 | "smallest number of substitutions"); | |||
4849 | if (nsubstitutes < min_n_opers) | |||
4850 | min_n_opers = nsubstitutes; | |||
4851 | else if (nsubstitutes > max_n_opers) | |||
4852 | max_n_opers = nsubstitutes; | |||
4853 | } | |||
4854 | } | |||
4855 | ||||
4856 | unsigned n_ids = user_ids.length (); | |||
4857 | if (n_ids == 0) | |||
4858 | fatal_at (token, "for requires at least one user-defined identifier"); | |||
4859 | ||||
4860 | token = peek (); | |||
4861 | if (token->type == CPP_CLOSE_PAREN) | |||
4862 | fatal_at (token, "no pattern defined in for"); | |||
4863 | ||||
4864 | active_fors.safe_push (user_ids); | |||
4865 | while (1) | |||
4866 | { | |||
4867 | token = peek (); | |||
4868 | if (token->type == CPP_CLOSE_PAREN) | |||
4869 | break; | |||
4870 | parse_pattern (); | |||
4871 | } | |||
4872 | active_fors.pop (); | |||
4873 | ||||
4874 | /* Remove user-defined operators from the hash again. */ | |||
4875 | for (unsigned i = 0; i < user_ids.length (); ++i) | |||
4876 | { | |||
4877 | if (!user_ids[i]->used) | |||
4878 | warning_at (user_id_tokens[i], | |||
4879 | "operator %s defined but not used", user_ids[i]->id); | |||
4880 | operators->remove_elt (user_ids[i]); | |||
4881 | } | |||
4882 | } | |||
4883 | ||||
4884 | /* Parse an identifier associated with a list of operators. | |||
4885 | oprs = '(' 'define_operator_list' <ident> <ident>... ')' */ | |||
4886 | ||||
4887 | void | |||
4888 | parser::parse_operator_list (location_t) | |||
4889 | { | |||
4890 | const cpp_token *token = peek (); | |||
4891 | const char *id = get_ident (); | |||
4892 | ||||
4893 | if (get_operator (id, true) != 0) | |||
4894 | fatal_at (token, "operator %s already defined", id); | |||
4895 | ||||
4896 | user_id *op = new user_id (id, true); | |||
4897 | int arity = -1; | |||
4898 | ||||
4899 | while ((token = peek_ident ()) != 0) | |||
4900 | { | |||
4901 | token = peek (); | |||
4902 | const char *oper = get_ident (); | |||
4903 | id_base *idb = get_operator (oper, true); | |||
4904 | ||||
4905 | if (idb == 0) | |||
4906 | fatal_at (token, "no such operator '%s'", oper); | |||
4907 | ||||
4908 | if (arity == -1) | |||
4909 | arity = idb->nargs; | |||
4910 | else if (idb->nargs == -1) | |||
4911 | ; | |||
4912 | else if (arity != idb->nargs) | |||
4913 | fatal_at (token, "operator '%s' with arity %d does not match " | |||
4914 | "others with arity %d", oper, idb->nargs, arity); | |||
4915 | ||||
4916 | /* We allow composition of multiple operator lists. */ | |||
4917 | if (user_id *p = dyn_cast<user_id *> (idb)) | |||
4918 | op->substitutes.safe_splice (p->substitutes); | |||
4919 | else | |||
4920 | op->substitutes.safe_push (idb); | |||
4921 | } | |||
4922 | ||||
4923 | // Check that there is no junk after id-list | |||
4924 | token = peek(); | |||
4925 | if (token->type != CPP_CLOSE_PAREN) | |||
4926 | fatal_at (token, "expected identifier got %s", cpp_type2name (token->type, 0)); | |||
4927 | ||||
4928 | if (op->substitutes.length () == 0) | |||
4929 | fatal_at (token, "operator-list cannot be empty"); | |||
4930 | ||||
4931 | op->nargs = arity; | |||
4932 | id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); | |||
4933 | *slot = op; | |||
4934 | } | |||
4935 | ||||
4936 | /* Parse an outer if expression. | |||
4937 | if = '(' 'if' '(' <c-expr> ')' <pattern> ')' */ | |||
4938 | ||||
4939 | void | |||
4940 | parser::parse_if (location_t) | |||
4941 | { | |||
4942 | c_expr *ifexpr = parse_c_expr (CPP_OPEN_PAREN); | |||
4943 | ||||
4944 | const cpp_token *token = peek (); | |||
4945 | if (token->type == CPP_CLOSE_PAREN) | |||
4946 | fatal_at (token, "no pattern defined in if"); | |||
4947 | ||||
4948 | active_ifs.safe_push (ifexpr); | |||
4949 | while (1) | |||
4950 | { | |||
4951 | token = peek (); | |||
4952 | if (token->type == CPP_CLOSE_PAREN) | |||
4953 | break; | |||
4954 | ||||
4955 | parse_pattern (); | |||
4956 | } | |||
4957 | active_ifs.pop (); | |||
4958 | } | |||
4959 | ||||
4960 | /* Parse a list of predefined predicate identifiers. | |||
4961 | preds = '(' 'define_predicates' <ident>... ')' */ | |||
4962 | ||||
4963 | void | |||
4964 | parser::parse_predicates (location_t) | |||
4965 | { | |||
4966 | do | |||
4967 | { | |||
4968 | const cpp_token *token = peek (); | |||
4969 | if (token->type != CPP_NAME) | |||
4970 | break; | |||
4971 | ||||
4972 | add_predicate (get_ident ()); | |||
4973 | } | |||
4974 | while (1); | |||
4975 | } | |||
4976 | ||||
4977 | /* Parse outer control structures. | |||
4978 | pattern = <preds>|<for>|<if>|<simplify>|<match> */ | |||
4979 | ||||
4980 | void | |||
4981 | parser::parse_pattern () | |||
4982 | { | |||
4983 | /* All clauses start with '('. */ | |||
4984 | eat_token (CPP_OPEN_PAREN); | |||
4985 | const cpp_token *token = peek (); | |||
4986 | const char *id = get_ident (); | |||
4987 | if (strcmp (id, "simplify") == 0) | |||
4988 | { | |||
4989 | parse_simplify (simplify::SIMPLIFY, simplifiers, NULLnullptr, NULLnullptr); | |||
4990 | capture_ids = NULLnullptr; | |||
4991 | } | |||
4992 | else if (strcmp (id, "match") == 0) | |||
4993 | { | |||
4994 | bool with_args = false; | |||
4995 | location_t e_loc = peek ()->src_loc; | |||
4996 | if (peek ()->type == CPP_OPEN_PAREN) | |||
4997 | { | |||
4998 | eat_token (CPP_OPEN_PAREN); | |||
4999 | with_args = true; | |||
5000 | } | |||
5001 | const char *name = get_ident (); | |||
5002 | id_base *id1 = get_operator (name); | |||
5003 | predicate_id *p; | |||
5004 | if (!id1) | |||
5005 | { | |||
5006 | p = add_predicate (name); | |||
5007 | user_predicates.safe_push (p); | |||
5008 | } | |||
5009 | else if ((p = dyn_cast <predicate_id *> (id1))) | |||
5010 | ; | |||
5011 | else | |||
5012 | fatal_at (token, "cannot add a match to a non-predicate ID"); | |||
5013 | /* Parse (match <id> <arg>... (match-expr)) here. */ | |||
5014 | expr *e = NULLnullptr; | |||
5015 | if (with_args) | |||
5016 | { | |||
5017 | capture_ids = new cid_map_t; | |||
5018 | e = new expr (p, e_loc); | |||
5019 | while (peek ()->type == CPP_ATSIGN) | |||
5020 | e->append_op (parse_capture (NULLnullptr, false)); | |||
5021 | eat_token (CPP_CLOSE_PAREN); | |||
5022 | } | |||
5023 | if (p->nargs != -1 | |||
5024 | && ((e && e->ops.length () != (unsigned)p->nargs) | |||
5025 | || (!e && p->nargs != 0))) | |||
5026 | fatal_at (token, "non-matching number of match operands"); | |||
5027 | p->nargs = e ? e->ops.length () : 0; | |||
5028 | parse_simplify (simplify::MATCH, p->matchers, p, e); | |||
5029 | capture_ids = NULLnullptr; | |||
5030 | } | |||
5031 | else if (strcmp (id, "for") == 0) | |||
5032 | parse_for (token->src_loc); | |||
5033 | else if (strcmp (id, "if") == 0) | |||
5034 | parse_if (token->src_loc); | |||
5035 | else if (strcmp (id, "define_predicates") == 0) | |||
5036 | { | |||
5037 | if (active_ifs.length () > 0 | |||
5038 | || active_fors.length () > 0) | |||
5039 | fatal_at (token, "define_predicates inside if or for is not supported"); | |||
5040 | parse_predicates (token->src_loc); | |||
5041 | } | |||
5042 | else if (strcmp (id, "define_operator_list") == 0) | |||
5043 | { | |||
5044 | if (active_ifs.length () > 0 | |||
5045 | || active_fors.length () > 0) | |||
5046 | fatal_at (token, "operator-list inside if or for is not supported"); | |||
5047 | parse_operator_list (token->src_loc); | |||
5048 | } | |||
5049 | else | |||
5050 | fatal_at (token, "expected %s'simplify', 'match', 'for' or 'if'", | |||
5051 | active_ifs.length () == 0 && active_fors.length () == 0 | |||
5052 | ? "'define_predicates', " : ""); | |||
5053 | ||||
5054 | eat_token (CPP_CLOSE_PAREN); | |||
5055 | } | |||
5056 | ||||
5057 | /* Helper for finish_match_operand, collecting captures of OP in CPTS | |||
5058 | recursively. */ | |||
5059 | ||||
5060 | static void | |||
5061 | walk_captures (operand *op, vec<vec<capture *> > &cpts) | |||
5062 | { | |||
5063 | if (! op) | |||
5064 | return; | |||
5065 | ||||
5066 | if (capture *c = dyn_cast <capture *> (op)) | |||
5067 | { | |||
5068 | cpts[c->where].safe_push (c); | |||
5069 | walk_captures (c->what, cpts); | |||
5070 | } | |||
5071 | else if (expr *e = dyn_cast <expr *> (op)) | |||
5072 | for (unsigned i = 0; i < e->ops.length (); ++i) | |||
5073 | walk_captures (e->ops[i], cpts); | |||
5074 | } | |||
5075 | ||||
5076 | /* Finish up OP which is a match operand. */ | |||
5077 | ||||
5078 | void | |||
5079 | parser::finish_match_operand (operand *op) | |||
5080 | { | |||
5081 | /* Look for matching captures, diagnose mis-uses of @@ and apply | |||
5082 | early lowering and distribution of value_match. */ | |||
5083 | auto_vec<vec<capture *> > cpts; | |||
5084 | cpts.safe_grow_cleared (capture_ids->elements (), true); | |||
5085 | walk_captures (op, cpts); | |||
5086 | for (unsigned i = 0; i < cpts.length (); ++i) | |||
5087 | { | |||
5088 | capture *value_match = NULLnullptr; | |||
5089 | for (unsigned j = 0; j < cpts[i].length (); ++j) | |||
5090 | { | |||
5091 | if (cpts[i][j]->value_match) | |||
5092 | { | |||
5093 | if (value_match) | |||
5094 | fatal_at (cpts[i][j]->location, "duplicate @@"); | |||
5095 | value_match = cpts[i][j]; | |||
5096 | } | |||
5097 | } | |||
5098 | if (cpts[i].length () == 1 && value_match) | |||
5099 | fatal_at (value_match->location, "@@ without a matching capture"); | |||
5100 | if (value_match) | |||
5101 | { | |||
5102 | /* Duplicate prevailing capture with the existing ID, create | |||
5103 | a fake ID and rewrite all captures to use it. This turns | |||
5104 | @@1 into @__<newid>@1 and @1 into @__<newid>. */ | |||
5105 | value_match->what = new capture (value_match->location, | |||
5106 | value_match->where, | |||
5107 | value_match->what, false); | |||
5108 | /* Create a fake ID and rewrite all captures to use it. */ | |||
5109 | unsigned newid = get_internal_capture_id (); | |||
5110 | for (unsigned j = 0; j < cpts[i].length (); ++j) | |||
5111 | { | |||
5112 | cpts[i][j]->where = newid; | |||
5113 | cpts[i][j]->value_match = true; | |||
5114 | } | |||
5115 | } | |||
5116 | cpts[i].release (); | |||
5117 | } | |||
5118 | } | |||
5119 | ||||
5120 | /* Main entry of the parser. Repeatedly parse outer control structures. */ | |||
5121 | ||||
5122 | parser::parser (cpp_reader *r_, bool gimple_) | |||
5123 | { | |||
5124 | r = r_; | |||
5125 | gimple = gimple_; | |||
5126 | active_ifs = vNULL; | |||
5127 | active_fors = vNULL; | |||
5128 | simplifiers = vNULL; | |||
5129 | oper_lists_set = NULLnullptr; | |||
5130 | oper_lists = vNULL; | |||
5131 | capture_ids = NULLnullptr; | |||
5132 | user_predicates = vNULL; | |||
5133 | parsing_match_operand = false; | |||
5134 | last_id = 0; | |||
5135 | ||||
5136 | const cpp_token *token = next (); | |||
5137 | while (token->type != CPP_EOF) | |||
5138 | { | |||
5139 | _cpp_backup_tokens (r, 1); | |||
5140 | parse_pattern (); | |||
5141 | token = next (); | |||
5142 | } | |||
5143 | } | |||
5144 | ||||
5145 | ||||
5146 | /* Helper for the linemap code. */ | |||
5147 | ||||
5148 | static size_t | |||
5149 | round_alloc_size (size_t s) | |||
5150 | { | |||
5151 | return s; | |||
5152 | } | |||
5153 | ||||
5154 | ||||
5155 | /* The genmatch generator program. It reads from a pattern description | |||
5156 | and outputs GIMPLE or GENERIC IL matching and simplification routines. */ | |||
5157 | ||||
5158 | int | |||
5159 | main (int argc, char **argv) | |||
5160 | { | |||
5161 | cpp_reader *r; | |||
5162 | ||||
5163 | progname = "genmatch"; | |||
5164 | ||||
5165 | if (argc < 2) | |||
5166 | return 1; | |||
5167 | ||||
5168 | bool gimple = true; | |||
5169 | char *input = argv[argc-1]; | |||
5170 | for (int i = 1; i < argc - 1; ++i) | |||
5171 | { | |||
5172 | if (strcmp (argv[i], "--gimple") == 0) | |||
5173 | gimple = true; | |||
5174 | else if (strcmp (argv[i], "--generic") == 0) | |||
5175 | gimple = false; | |||
5176 | else if (strcmp (argv[i], "-v") == 0) | |||
5177 | verbose = 1; | |||
5178 | else if (strcmp (argv[i], "-vv") == 0) | |||
5179 | verbose = 2; | |||
5180 | else | |||
5181 | { | |||
5182 | fprintf (stderrstderr, "Usage: genmatch " | |||
5183 | "[--gimple] [--generic] [-v[v]] input\n"); | |||
5184 | return 1; | |||
5185 | } | |||
5186 | } | |||
5187 | ||||
5188 | line_table = XCNEW (class line_maps)((class line_maps *) xcalloc (1, sizeof (class line_maps))); | |||
5189 | linemap_init (line_table, 0); | |||
5190 | line_table->reallocator = xrealloc; | |||
5191 | line_table->round_alloc_size = round_alloc_size; | |||
5192 | ||||
5193 | r = cpp_create_reader (CLK_GNUC99, NULLnullptr, line_table); | |||
5194 | cpp_callbacks *cb = cpp_get_callbacks (r); | |||
5195 | cb->diagnostic = diagnostic_cb; | |||
5196 | ||||
5197 | /* Add the build directory to the #include "" search path. */ | |||
5198 | cpp_dir *dir = XCNEW (cpp_dir)((cpp_dir *) xcalloc (1, sizeof (cpp_dir))); | |||
5199 | dir->name = getpwd (); | |||
5200 | if (!dir->name) | |||
5201 | dir->name = ASTRDUP (".")(__extension__ ({ const char *const libiberty_optr = ("."); const unsigned long libiberty_len = strlen (libiberty_optr) + 1; char *const libiberty_nptr = (char *) __builtin_alloca(libiberty_len ); (char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len ); })); | |||
5202 | cpp_set_include_chains (r, dir, NULLnullptr, false); | |||
5203 | ||||
5204 | if (!cpp_read_main_file (r, input)) | |||
5205 | return 1; | |||
5206 | cpp_define (r, gimple ? "GIMPLE=1": "GENERIC=1"); | |||
5207 | cpp_define (r, gimple ? "GENERIC=0": "GIMPLE=0"); | |||
5208 | ||||
5209 | null_id = new id_base (id_base::NULL_ID, "null"); | |||
5210 | ||||
5211 | /* Pre-seed operators. */ | |||
5212 | operators = new hash_table<id_base> (1024); | |||
5213 | #define DEFTREECODE(SYM, STRING, TYPE, NARGS) \ | |||
5214 | add_operator (SYM, # SYM, # TYPE, NARGS); | |||
5215 | #define END_OF_BASE_TREE_CODES | |||
5216 | #include "tree.def" | |||
5217 | #undef END_OF_BASE_TREE_CODES | |||
5218 | #undef DEFTREECODE | |||
5219 | ||||
5220 | /* Pre-seed builtin functions. | |||
5221 | ??? Cannot use N (name) as that is targetm.emultls.get_address | |||
5222 | for BUILT_IN_EMUTLS_GET_ADDRESS ... */ | |||
5223 | #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \ | |||
5224 | add_function (ENUM, "CFN_" # ENUM); | |||
5225 | #include "builtins.def" | |||
5226 | ||||
5227 | #define DEF_INTERNAL_FN(CODE, NAME, FNSPEC) \ | |||
5228 | add_function (IFN_##CODE, "CFN_" #CODE); | |||
5229 | #include "internal-fn.def" | |||
5230 | ||||
5231 | /* Parse ahead! */ | |||
5232 | parser p (r, gimple); | |||
5233 | ||||
5234 | if (gimple) | |||
5235 | write_header (stdoutstdout, "gimple-match-head.cc"); | |||
5236 | else | |||
5237 | write_header (stdoutstdout, "generic-match-head.cc"); | |||
5238 | ||||
5239 | /* Go over all predicates defined with patterns and perform | |||
5240 | lowering and code generation. */ | |||
5241 | for (unsigned i = 0; i < p.user_predicates.length (); ++i) | |||
5242 | { | |||
5243 | predicate_id *pred = p.user_predicates[i]; | |||
5244 | lower (pred->matchers, gimple); | |||
5245 | ||||
5246 | if (verbose == 2) | |||
5247 | for (unsigned j = 0; j < pred->matchers.length (); ++j) | |||
5248 | print_matches (pred->matchers[j]); | |||
5249 | ||||
5250 | decision_tree dt; | |||
5251 | for (unsigned j = 0; j < pred->matchers.length (); ++j) | |||
5252 | dt.insert (pred->matchers[j], j); | |||
5253 | ||||
5254 | if (verbose == 2) | |||
5255 | dt.print (stderrstderr); | |||
5256 | ||||
5257 | write_predicate (stdoutstdout, pred, dt, gimple); | |||
5258 | } | |||
5259 | ||||
5260 | /* Lower the main simplifiers and generate code for them. */ | |||
5261 | lower (p.simplifiers, gimple); | |||
5262 | ||||
5263 | if (verbose == 2) | |||
5264 | for (unsigned i = 0; i < p.simplifiers.length (); ++i) | |||
5265 | print_matches (p.simplifiers[i]); | |||
5266 | ||||
5267 | decision_tree dt; | |||
5268 | for (unsigned i = 0; i < p.simplifiers.length (); ++i) | |||
5269 | dt.insert (p.simplifiers[i], i); | |||
5270 | ||||
5271 | if (verbose == 2) | |||
5272 | dt.print (stderrstderr); | |||
5273 | ||||
5274 | dt.gen (stdoutstdout, gimple); | |||
5275 | ||||
5276 | /* Finalize. */ | |||
5277 | cpp_finish (r, NULLnullptr); | |||
5278 | cpp_destroy (r); | |||
5279 | ||||
5280 | delete operators; | |||
5281 | ||||
5282 | return 0; | |||
5283 | } |