]>
Commit | Line | Data |
---|---|---|
6de9cd9a DN |
1 | /* Tree lowering pass. This pass converts the GENERIC functions-as-trees |
2 | tree representation into the GIMPLE form. | |
6de9cd9a DN |
3 | Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
4 | Major work done by Sebastian Pop <s.pop@laposte.net>, | |
5 | Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>. | |
6 | ||
7 | This file is part of GCC. | |
8 | ||
9 | GCC is free software; you can redistribute it and/or modify it under | |
10 | the terms of the GNU General Public License as published by the Free | |
11 | Software Foundation; either version 2, or (at your option) any later | |
12 | version. | |
13 | ||
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GCC; see the file COPYING. If not, write to the Free | |
21 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
22 | 02111-1307, USA. */ | |
23 | ||
24 | #include "config.h" | |
25 | #include "system.h" | |
26 | #include "coretypes.h" | |
27 | #include "tm.h" | |
28 | #include "tree.h" | |
29 | #include "rtl.h" | |
30 | #include "errors.h" | |
31 | #include "varray.h" | |
eadf906f | 32 | #include "tree-gimple.h" |
6de9cd9a DN |
33 | #include "tree-inline.h" |
34 | #include "diagnostic.h" | |
35 | #include "langhooks.h" | |
36 | #include "langhooks-def.h" | |
37 | #include "tree-flow.h" | |
44de5aeb | 38 | #include "cgraph.h" |
6de9cd9a DN |
39 | #include "timevar.h" |
40 | #include "except.h" | |
41 | #include "hashtab.h" | |
42 | #include "flags.h" | |
43 | #include "real.h" | |
44 | #include "function.h" | |
45 | #include "output.h" | |
46 | #include "expr.h" | |
47 | #include "ggc.h" | |
cd3ce9b4 | 48 | #include "target.h" |
6de9cd9a DN |
49 | |
50 | static struct gimplify_ctx | |
51 | { | |
52 | tree current_bind_expr; | |
53 | bool save_stack; | |
54 | tree temps; | |
55 | tree conditional_cleanups; | |
56 | int conditions; | |
57 | tree exit_label; | |
71877985 | 58 | tree return_temp; |
6de9cd9a DN |
59 | varray_type case_labels; |
60 | /* The formal temporary table. Should this be persistent? */ | |
61 | htab_t temp_htab; | |
62 | } *gimplify_ctxp; | |
63 | ||
64 | ||
65 | /* Formal (expression) temporary table handling: Multiple occurrences of | |
66 | the same scalar expression are evaluated into the same temporary. */ | |
67 | ||
68 | typedef struct gimple_temp_hash_elt | |
69 | { | |
70 | tree val; /* Key */ | |
71 | tree temp; /* Value */ | |
72 | } elt_t; | |
73 | ||
44de5aeb RK |
74 | /* Forward declarations. */ |
75 | static hashval_t gimple_tree_hash (const void *); | |
76 | static int gimple_tree_eq (const void *, const void *); | |
77 | static bool gimple_conditional_context (void); | |
78 | static void gimple_push_condition (void); | |
79 | static void gimple_pop_condition (tree *); | |
80 | static void append_to_statement_list_1 (tree, tree *, bool); | |
81 | static inline void remove_suffix (char *, int); | |
82 | static inline tree create_tmp_from_val (tree); | |
83 | static tree lookup_tmp_var (tree, bool); | |
84 | static tree internal_get_tmp_var (tree, tree *, tree *, bool); | |
85 | static bool should_carry_locus_p (tree); | |
86 | static tree mostly_copy_tree_r (tree *, int *, void *); | |
87 | static tree mark_decls_volatile_r (tree *, int *, void *); | |
88 | static tree copy_if_shared_r (tree *, int *, void *); | |
89 | static tree unmark_visited_r (tree *, int *, void *); | |
90 | static void unshare_body (tree *, tree); | |
91 | static void unvisit_body (tree *, tree); | |
92 | static void build_stack_save_restore (tree *, tree *); | |
93 | static enum gimplify_status gimplify_bind_expr (tree *, tree, tree *); | |
94 | static enum gimplify_status gimplify_return_expr (tree, tree *); | |
95 | static enum gimplify_status gimplify_loop_expr (tree *, tree *); | |
96 | static int compare_case_labels (const void *, const void *); | |
97 | static enum gimplify_status gimplify_switch_expr (tree *, tree *); | |
98 | static enum gimplify_status gimplify_case_label_expr (tree *); | |
99 | static enum gimplify_status gimplify_labeled_block_expr (tree *); | |
100 | static enum gimplify_status gimplify_exit_block_expr (tree *); | |
101 | static enum gimplify_status gimplify_exit_expr (tree *); | |
102 | static enum gimplify_status gimplify_init_constructor (tree *, tree *, tree *, | |
103 | bool); | |
104 | static void canonicalize_component_ref (tree *); | |
105 | static void canonicalize_addr_expr (tree *); | |
106 | static enum gimplify_status gimplify_conversion (tree *); | |
107 | static enum gimplify_status gimplify_minimax_expr (tree *, tree *, tree *); | |
108 | static enum gimplify_status gimplify_array_ref_to_plus (tree *, tree *, | |
109 | tree *); | |
110 | static tree build_addr_expr_with_type (tree, tree); | |
111 | static tree build_addr_expr (tree); | |
112 | static enum gimplify_status gimplify_compound_lval (tree *, tree *, tree *, | |
113 | bool); | |
114 | static enum gimplify_status gimplify_self_mod_expr (tree *, tree *, tree *, | |
115 | bool); | |
116 | static enum gimplify_status gimplify_call_expr (tree *, tree *, | |
117 | bool (*) (tree)); | |
118 | static tree shortcut_cond_r (tree, tree *, tree *); | |
119 | static tree shortcut_cond_expr (tree); | |
120 | static tree gimple_boolify (tree); | |
121 | static enum gimplify_status gimplify_cond_expr (tree *, tree *, tree); | |
122 | static enum gimplify_status gimplify_modify_expr (tree *, tree *, tree *, | |
123 | bool); | |
124 | static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *, | |
125 | tree *, tree *, bool); | |
126 | static enum gimplify_status gimplify_variable_sized_compare (tree *); | |
127 | static enum gimplify_status gimplify_boolean_expr (tree *); | |
128 | static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool); | |
129 | static enum gimplify_status gimplify_statement_list (tree *); | |
130 | static enum gimplify_status gimplify_save_expr (tree *, tree *, tree *); | |
131 | static enum gimplify_status gimplify_addr_expr (tree *, tree *, tree *); | |
132 | static enum gimplify_status gimplify_asm_expr (tree *, tree *, tree *); | |
133 | static enum gimplify_status gimplify_cleanup_point_expr (tree *, tree *); | |
134 | static void gimple_push_cleanup (tree, tree, tree *); | |
135 | static enum gimplify_status gimplify_target_expr (tree *, tree *, tree *); | |
136 | #ifdef ENABLE_CHECKING | |
137 | static bool cpt_same_type (tree, tree); | |
138 | static tree check_pointer_types_r (tree *, int *, void *); | |
139 | #endif | |
140 | ||
6de9cd9a DN |
141 | /* Return a hash value for a formal temporary table entry. */ |
142 | ||
143 | static hashval_t | |
144 | gimple_tree_hash (const void *p) | |
145 | { | |
146 | tree t = ((const elt_t *)p)->val; | |
147 | return iterative_hash_expr (t, 0); | |
148 | } | |
149 | ||
150 | /* Compare two formal temporary table entries. */ | |
151 | ||
152 | static int | |
153 | gimple_tree_eq (const void *p1, const void *p2) | |
154 | { | |
155 | tree t1 = ((const elt_t *)p1)->val; | |
156 | tree t2 = ((const elt_t *)p2)->val; | |
157 | enum tree_code code = TREE_CODE (t1); | |
158 | ||
159 | if (TREE_CODE (t2) != code | |
160 | || TREE_TYPE (t1) != TREE_TYPE (t2)) | |
161 | return 0; | |
162 | ||
163 | if (!operand_equal_p (t1, t2, 0)) | |
164 | return 0; | |
165 | ||
166 | /* Only allow them to compare equal if they also hash equal; otherwise | |
167 | results are nondeterminate, and we fail bootstrap comparison. */ | |
168 | if (gimple_tree_hash (p1) != gimple_tree_hash (p2)) | |
169 | abort (); | |
170 | ||
171 | return 1; | |
172 | } | |
173 | ||
174 | /* Set up a context for the gimplifier. */ | |
175 | ||
176 | void | |
177 | push_gimplify_context (void) | |
178 | { | |
179 | if (gimplify_ctxp) | |
180 | abort (); | |
181 | gimplify_ctxp | |
182 | = (struct gimplify_ctx *) xcalloc (1, sizeof (struct gimplify_ctx)); | |
183 | gimplify_ctxp->temp_htab | |
184 | = htab_create (1000, gimple_tree_hash, gimple_tree_eq, free); | |
185 | } | |
186 | ||
187 | /* Tear down a context for the gimplifier. If BODY is non-null, then | |
188 | put the temporaries into the outer BIND_EXPR. Otherwise, put them | |
189 | in the unexpanded_var_list. */ | |
190 | ||
191 | void | |
192 | pop_gimplify_context (tree body) | |
193 | { | |
194 | if (!gimplify_ctxp || gimplify_ctxp->current_bind_expr) | |
195 | abort (); | |
196 | ||
197 | if (body) | |
198 | declare_tmp_vars (gimplify_ctxp->temps, body); | |
199 | else | |
200 | record_vars (gimplify_ctxp->temps); | |
201 | ||
202 | #if 0 | |
203 | if (!quiet_flag) | |
204 | fprintf (stderr, " collisions: %f ", | |
205 | htab_collisions (gimplify_ctxp->temp_htab)); | |
206 | #endif | |
207 | ||
208 | htab_delete (gimplify_ctxp->temp_htab); | |
209 | free (gimplify_ctxp); | |
210 | gimplify_ctxp = NULL; | |
211 | } | |
212 | ||
213 | void | |
214 | gimple_push_bind_expr (tree bind) | |
215 | { | |
216 | TREE_CHAIN (bind) = gimplify_ctxp->current_bind_expr; | |
217 | gimplify_ctxp->current_bind_expr = bind; | |
218 | } | |
219 | ||
220 | void | |
221 | gimple_pop_bind_expr (void) | |
222 | { | |
223 | gimplify_ctxp->current_bind_expr | |
224 | = TREE_CHAIN (gimplify_ctxp->current_bind_expr); | |
225 | } | |
226 | ||
227 | tree | |
228 | gimple_current_bind_expr (void) | |
229 | { | |
230 | return gimplify_ctxp->current_bind_expr; | |
231 | } | |
232 | ||
233 | /* Returns true iff there is a COND_EXPR between us and the innermost | |
234 | CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */ | |
235 | ||
236 | static bool | |
237 | gimple_conditional_context (void) | |
238 | { | |
239 | return gimplify_ctxp->conditions > 0; | |
240 | } | |
241 | ||
242 | /* Note that we've entered a COND_EXPR. */ | |
243 | ||
244 | static void | |
245 | gimple_push_condition (void) | |
246 | { | |
247 | ++(gimplify_ctxp->conditions); | |
248 | } | |
249 | ||
250 | /* Note that we've left a COND_EXPR. If we're back at unconditional scope | |
251 | now, add any conditional cleanups we've seen to the prequeue. */ | |
252 | ||
253 | static void | |
254 | gimple_pop_condition (tree *pre_p) | |
255 | { | |
256 | int conds = --(gimplify_ctxp->conditions); | |
257 | if (conds == 0) | |
258 | { | |
259 | append_to_statement_list (gimplify_ctxp->conditional_cleanups, pre_p); | |
260 | gimplify_ctxp->conditional_cleanups = NULL_TREE; | |
261 | } | |
262 | else if (conds < 0) | |
263 | abort (); | |
264 | } | |
265 | ||
266 | /* A subroutine of append_to_statement_list{,_force}. */ | |
267 | ||
268 | static void | |
269 | append_to_statement_list_1 (tree t, tree *list_p, bool side_effects) | |
270 | { | |
271 | tree list = *list_p; | |
272 | tree_stmt_iterator i; | |
273 | ||
be00f578 JM |
274 | if (!side_effects) |
275 | return; | |
276 | ||
6de9cd9a DN |
277 | if (!list) |
278 | { | |
279 | if (t && TREE_CODE (t) == STATEMENT_LIST) | |
280 | { | |
281 | *list_p = t; | |
282 | return; | |
283 | } | |
284 | *list_p = list = alloc_stmt_list (); | |
285 | } | |
286 | ||
6de9cd9a DN |
287 | i = tsi_last (list); |
288 | tsi_link_after (&i, t, TSI_CONTINUE_LINKING); | |
289 | } | |
290 | ||
291 | /* Add T to the end of the list container pointed by LIST_P. | |
292 | If T is an expression with no effects, it is ignored. */ | |
293 | ||
294 | void | |
295 | append_to_statement_list (tree t, tree *list_p) | |
296 | { | |
297 | append_to_statement_list_1 (t, list_p, t ? TREE_SIDE_EFFECTS (t) : false); | |
298 | } | |
299 | ||
300 | /* Similar, but the statement is always added, regardless of side effects. */ | |
301 | ||
302 | void | |
303 | append_to_statement_list_force (tree t, tree *list_p) | |
304 | { | |
305 | append_to_statement_list_1 (t, list_p, t != NULL); | |
306 | } | |
307 | ||
cd3ce9b4 JM |
308 | /* Both gimplify the statement T and append it to LIST_P. */ |
309 | ||
310 | void | |
311 | gimplify_and_add (tree t, tree *list_p) | |
312 | { | |
313 | gimplify_stmt (&t); | |
314 | append_to_statement_list (t, list_p); | |
315 | } | |
316 | ||
6de9cd9a DN |
317 | /* Strip off a legitimate source ending from the input string NAME of |
318 | length LEN. Rather than having to know the names used by all of | |
319 | our front ends, we strip off an ending of a period followed by | |
320 | up to five characters. (Java uses ".class".) */ | |
321 | ||
322 | static inline void | |
323 | remove_suffix (char *name, int len) | |
324 | { | |
325 | int i; | |
326 | ||
327 | for (i = 2; i < 8 && len > i; i++) | |
328 | { | |
329 | if (name[len - i] == '.') | |
330 | { | |
331 | name[len - i] = '\0'; | |
332 | break; | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | /* Create a nameless artificial label and put it in the current function | |
338 | context. Returns the newly created label. */ | |
339 | ||
340 | tree | |
341 | create_artificial_label (void) | |
342 | { | |
343 | tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node); | |
344 | DECL_ARTIFICIAL (lab) = 1; | |
345 | DECL_CONTEXT (lab) = current_function_decl; | |
346 | return lab; | |
347 | } | |
348 | ||
1ea7e6ad | 349 | /* Create a new temporary name with PREFIX. Returns an identifier. */ |
6de9cd9a DN |
350 | |
351 | static GTY(()) unsigned int tmp_var_id_num; | |
352 | ||
7e140280 | 353 | tree |
6de9cd9a DN |
354 | create_tmp_var_name (const char *prefix) |
355 | { | |
356 | char *tmp_name; | |
357 | ||
358 | if (prefix) | |
359 | { | |
360 | char *preftmp = ASTRDUP (prefix); | |
361 | remove_suffix (preftmp, strlen (preftmp)); | |
362 | prefix = preftmp; | |
363 | } | |
364 | ||
365 | ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "T", tmp_var_id_num++); | |
366 | return get_identifier (tmp_name); | |
367 | } | |
368 | ||
369 | ||
370 | /* Create a new temporary variable declaration of type TYPE. | |
371 | Does NOT push it into the current binding. */ | |
372 | ||
373 | tree | |
374 | create_tmp_var_raw (tree type, const char *prefix) | |
375 | { | |
376 | tree tmp_var; | |
377 | tree new_type; | |
378 | ||
379 | /* Make the type of the variable writable. */ | |
380 | new_type = build_type_variant (type, 0, 0); | |
381 | TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type); | |
382 | ||
383 | tmp_var = build_decl (VAR_DECL, create_tmp_var_name (prefix), type); | |
384 | ||
385 | /* The variable was declared by the compiler. */ | |
386 | DECL_ARTIFICIAL (tmp_var) = 1; | |
387 | /* And we don't want debug info for it. */ | |
388 | DECL_IGNORED_P (tmp_var) = 1; | |
389 | ||
390 | /* Make the variable writable. */ | |
391 | TREE_READONLY (tmp_var) = 0; | |
392 | ||
393 | DECL_EXTERNAL (tmp_var) = 0; | |
394 | TREE_STATIC (tmp_var) = 0; | |
395 | TREE_USED (tmp_var) = 1; | |
396 | ||
397 | return tmp_var; | |
398 | } | |
399 | ||
400 | /* Create a new temporary variable declaration of type TYPE. DOES push the | |
401 | variable into the current binding. Further, assume that this is called | |
402 | only from gimplification or optimization, at which point the creation of | |
403 | certain types are bugs. */ | |
404 | ||
405 | tree | |
406 | create_tmp_var (tree type, const char *prefix) | |
407 | { | |
408 | tree tmp_var; | |
409 | ||
410 | #if defined ENABLE_CHECKING | |
44de5aeb RK |
411 | /* We don't allow types that are addressable (meaning we can't make copies), |
412 | incomplete, or of variable size. */ | |
413 | if (TREE_ADDRESSABLE (type) | |
414 | || !COMPLETE_TYPE_P (type) | |
415 | || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) | |
6de9cd9a DN |
416 | abort (); |
417 | #endif | |
418 | ||
419 | tmp_var = create_tmp_var_raw (type, prefix); | |
420 | gimple_add_tmp_var (tmp_var); | |
421 | return tmp_var; | |
422 | } | |
423 | ||
424 | /* Given a tree, try to return a useful variable name that we can use | |
425 | to prefix a temporary that is being assigned the value of the tree. | |
426 | I.E. given <temp> = &A, return A. */ | |
427 | ||
428 | const char * | |
429 | get_name (tree t) | |
430 | { | |
431 | tree stripped_decl; | |
432 | ||
433 | stripped_decl = t; | |
434 | STRIP_NOPS (stripped_decl); | |
435 | if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl)) | |
436 | return IDENTIFIER_POINTER (DECL_NAME (stripped_decl)); | |
437 | else | |
438 | { | |
439 | switch (TREE_CODE (stripped_decl)) | |
440 | { | |
441 | case ADDR_EXPR: | |
442 | return get_name (TREE_OPERAND (stripped_decl, 0)); | |
443 | break; | |
444 | default: | |
445 | return NULL; | |
446 | } | |
447 | } | |
448 | } | |
449 | ||
450 | /* Create a temporary with a name derived from VAL. Subroutine of | |
451 | lookup_tmp_var; nobody else should call this function. */ | |
452 | ||
453 | static inline tree | |
454 | create_tmp_from_val (tree val) | |
455 | { | |
456 | return create_tmp_var (TREE_TYPE (val), get_name (val)); | |
457 | } | |
458 | ||
459 | /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse | |
460 | an existing expression temporary. */ | |
461 | ||
462 | static tree | |
463 | lookup_tmp_var (tree val, bool is_formal) | |
464 | { | |
465 | if (!is_formal || TREE_SIDE_EFFECTS (val)) | |
466 | return create_tmp_from_val (val); | |
467 | else | |
468 | { | |
469 | elt_t elt, *elt_p; | |
470 | void **slot; | |
471 | ||
472 | elt.val = val; | |
473 | slot = htab_find_slot (gimplify_ctxp->temp_htab, (void *)&elt, INSERT); | |
474 | if (*slot == NULL) | |
475 | { | |
476 | elt_p = xmalloc (sizeof (*elt_p)); | |
477 | elt_p->val = val; | |
478 | elt_p->temp = create_tmp_from_val (val); | |
479 | *slot = (void *)elt_p; | |
480 | } | |
481 | else | |
482 | elt_p = (elt_t *) *slot; | |
483 | ||
484 | return elt_p->temp; | |
485 | } | |
486 | } | |
487 | ||
488 | /* Returns a formal temporary variable initialized with VAL. PRE_P is as | |
489 | in gimplify_expr. Only use this function if: | |
490 | ||
491 | 1) The value of the unfactored expression represented by VAL will not | |
492 | change between the initialization and use of the temporary, and | |
493 | 2) The temporary will not be otherwise modified. | |
494 | ||
495 | For instance, #1 means that this is inappropriate for SAVE_EXPR temps, | |
496 | and #2 means it is inappropriate for && temps. | |
497 | ||
498 | For other cases, use get_initialized_tmp_var instead. */ | |
499 | ||
500 | static tree | |
501 | internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal) | |
502 | { | |
503 | tree t, mod; | |
504 | char class; | |
505 | ||
506 | gimplify_expr (&val, pre_p, post_p, is_gimple_rhs, fb_rvalue); | |
507 | ||
508 | t = lookup_tmp_var (val, is_formal); | |
509 | ||
510 | mod = build (MODIFY_EXPR, TREE_TYPE (t), t, val); | |
511 | ||
512 | class = TREE_CODE_CLASS (TREE_CODE (val)); | |
513 | if (EXPR_LOCUS (val)) | |
514 | SET_EXPR_LOCUS (mod, EXPR_LOCUS (val)); | |
515 | else | |
516 | annotate_with_locus (mod, input_location); | |
517 | /* gimplify_modify_expr might want to reduce this further. */ | |
518 | gimplify_stmt (&mod); | |
519 | append_to_statement_list (mod, pre_p); | |
520 | ||
521 | return t; | |
522 | } | |
523 | ||
524 | tree | |
525 | get_formal_tmp_var (tree val, tree *pre_p) | |
526 | { | |
527 | return internal_get_tmp_var (val, pre_p, NULL, true); | |
528 | } | |
529 | ||
530 | /* Returns a temporary variable initialized with VAL. PRE_P and POST_P | |
531 | are as in gimplify_expr. */ | |
532 | ||
533 | tree | |
534 | get_initialized_tmp_var (tree val, tree *pre_p, tree *post_p) | |
535 | { | |
536 | return internal_get_tmp_var (val, pre_p, post_p, false); | |
537 | } | |
538 | ||
539 | /* Returns true if T is a GIMPLE temporary variable, false otherwise. */ | |
540 | ||
541 | bool | |
542 | is_gimple_tmp_var (tree t) | |
543 | { | |
544 | /* FIXME this could trigger for other local artificials, too. */ | |
545 | return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t) | |
546 | && !TREE_STATIC (t) && !DECL_EXTERNAL (t)); | |
547 | } | |
548 | ||
549 | /* Declares all the variables in VARS in SCOPE. Returns the last | |
550 | DECL_STMT emitted. */ | |
551 | ||
552 | void | |
553 | declare_tmp_vars (tree vars, tree scope) | |
554 | { | |
555 | tree last = vars; | |
556 | if (last) | |
557 | { | |
558 | tree temps; | |
559 | ||
560 | /* C99 mode puts the default 'return 0;' for main() outside the outer | |
561 | braces. So drill down until we find an actual scope. */ | |
562 | while (TREE_CODE (scope) == COMPOUND_EXPR) | |
563 | scope = TREE_OPERAND (scope, 0); | |
564 | ||
565 | if (TREE_CODE (scope) != BIND_EXPR) | |
566 | abort (); | |
567 | ||
568 | temps = nreverse (last); | |
569 | TREE_CHAIN (last) = BIND_EXPR_VARS (scope); | |
570 | BIND_EXPR_VARS (scope) = temps; | |
571 | ||
572 | /* We don't add the temps to the block for this BIND_EXPR, as we're | |
573 | not interested in debugging info for them. */ | |
574 | } | |
575 | } | |
576 | ||
577 | void | |
578 | gimple_add_tmp_var (tree tmp) | |
579 | { | |
580 | if (TREE_CHAIN (tmp) || tmp->decl.seen_in_bind_expr) | |
581 | abort (); | |
582 | ||
583 | DECL_CONTEXT (tmp) = current_function_decl; | |
584 | tmp->decl.seen_in_bind_expr = 1; | |
585 | ||
586 | if (gimplify_ctxp) | |
587 | { | |
588 | TREE_CHAIN (tmp) = gimplify_ctxp->temps; | |
589 | gimplify_ctxp->temps = tmp; | |
590 | } | |
591 | else if (cfun) | |
592 | record_vars (tmp); | |
593 | else | |
594 | declare_tmp_vars (tmp, DECL_SAVED_TREE (current_function_decl)); | |
595 | } | |
596 | ||
597 | /* Determines whether to assign a locus to the statement STMT. */ | |
598 | ||
599 | static bool | |
600 | should_carry_locus_p (tree stmt) | |
601 | { | |
602 | /* Don't emit a line note for a label. We particularly don't want to | |
603 | emit one for the break label, since it doesn't actually correspond | |
604 | to the beginning of the loop/switch. */ | |
605 | if (TREE_CODE (stmt) == LABEL_EXPR) | |
606 | return false; | |
607 | ||
608 | /* Do not annotate empty statements, since it confuses gcov. */ | |
609 | if (!TREE_SIDE_EFFECTS (stmt)) | |
610 | return false; | |
611 | ||
612 | return true; | |
613 | } | |
614 | ||
7c34ced1 RH |
615 | static void |
616 | annotate_one_with_locus (tree t, location_t locus) | |
617 | { | |
618 | if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))) | |
619 | && ! EXPR_HAS_LOCATION (t) | |
620 | && should_carry_locus_p (t)) | |
621 | annotate_with_locus (t, locus); | |
622 | } | |
623 | ||
6de9cd9a DN |
624 | void |
625 | annotate_all_with_locus (tree *stmt_p, location_t locus) | |
626 | { | |
627 | tree_stmt_iterator i; | |
628 | ||
629 | if (!*stmt_p) | |
630 | return; | |
631 | ||
632 | for (i = tsi_start (*stmt_p); !tsi_end_p (i); tsi_next (&i)) | |
633 | { | |
634 | tree t = tsi_stmt (i); | |
635 | ||
636 | #ifdef ENABLE_CHECKING | |
637 | /* Assuming we've already been gimplified, we shouldn't | |
638 | see nested chaining constructs anymore. */ | |
639 | if (TREE_CODE (t) == STATEMENT_LIST | |
640 | || TREE_CODE (t) == COMPOUND_EXPR) | |
641 | abort (); | |
642 | #endif | |
643 | ||
7c34ced1 | 644 | annotate_one_with_locus (t, locus); |
6de9cd9a DN |
645 | } |
646 | } | |
647 | ||
648 | /* Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes. | |
649 | These nodes model computations that should only be done once. If we | |
650 | were to unshare something like SAVE_EXPR(i++), the gimplification | |
651 | process would create wrong code. */ | |
652 | ||
653 | static tree | |
654 | mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data) | |
655 | { | |
656 | enum tree_code code = TREE_CODE (*tp); | |
f0638e1d | 657 | /* Don't unshare types, decls, constants and SAVE_EXPR nodes. */ |
6de9cd9a | 658 | if (TREE_CODE_CLASS (code) == 't' |
f0638e1d | 659 | || TREE_CODE_CLASS (code) == 'd' |
6de9cd9a DN |
660 | || TREE_CODE_CLASS (code) == 'c' |
661 | || code == SAVE_EXPR || code == TARGET_EXPR | |
662 | /* We can't do anything sensible with a BLOCK used as an expression, | |
663 | but we also can't abort when we see it because of non-expression | |
664 | uses. So just avert our eyes and cross our fingers. Silly Java. */ | |
665 | || code == BLOCK) | |
666 | *walk_subtrees = 0; | |
667 | else if (code == BIND_EXPR) | |
668 | abort (); | |
669 | else | |
670 | copy_tree_r (tp, walk_subtrees, data); | |
671 | ||
672 | return NULL_TREE; | |
673 | } | |
674 | ||
675 | /* Mark all the _DECL nodes under *TP as volatile. FIXME: This must die | |
676 | after VA_ARG_EXPRs are properly lowered. */ | |
677 | ||
678 | static tree | |
679 | mark_decls_volatile_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, | |
680 | void *data ATTRIBUTE_UNUSED) | |
681 | { | |
682 | if (SSA_VAR_P (*tp)) | |
683 | TREE_THIS_VOLATILE (*tp) = 1; | |
684 | ||
685 | return NULL_TREE; | |
686 | } | |
687 | ||
688 | ||
689 | /* Callback for walk_tree to unshare most of the shared trees rooted at | |
690 | *TP. If *TP has been visited already (i.e., TREE_VISITED (*TP) == 1), | |
691 | then *TP is deep copied by calling copy_tree_r. | |
692 | ||
693 | This unshares the same trees as copy_tree_r with the exception of | |
694 | SAVE_EXPR nodes. These nodes model computations that should only be | |
695 | done once. If we were to unshare something like SAVE_EXPR(i++), the | |
696 | gimplification process would create wrong code. */ | |
697 | ||
698 | static tree | |
699 | copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, | |
700 | void *data ATTRIBUTE_UNUSED) | |
701 | { | |
f0638e1d RH |
702 | tree t = *tp; |
703 | enum tree_code code = TREE_CODE (t); | |
704 | ||
44de5aeb RK |
705 | /* Skip types, decls, and constants. But we do want to look at their |
706 | types and the bounds of types. Mark them as visited so we properly | |
707 | unmark their subtrees on the unmark pass. If we've already seen them, | |
708 | don't look down further. */ | |
f0638e1d RH |
709 | if (TREE_CODE_CLASS (code) == 't' |
710 | || TREE_CODE_CLASS (code) == 'd' | |
711 | || TREE_CODE_CLASS (code) == 'c') | |
44de5aeb RK |
712 | { |
713 | if (TREE_VISITED (t)) | |
714 | *walk_subtrees = 0; | |
715 | else | |
716 | TREE_VISITED (t) = 1; | |
717 | } | |
f0638e1d RH |
718 | |
719 | /* Special-case BIND_EXPR. We should never be copying these, therefore | |
720 | we can omit examining BIND_EXPR_VARS. Which also avoids problems with | |
721 | double processing of the DECL_INITIAL, which could be seen via both | |
722 | the BIND_EXPR_VARS and a DECL_STMT. */ | |
723 | else if (code == BIND_EXPR) | |
724 | { | |
725 | if (TREE_VISITED (t)) | |
726 | abort (); | |
727 | TREE_VISITED (t) = 1; | |
728 | *walk_subtrees = 0; | |
729 | walk_tree (&BIND_EXPR_BODY (t), copy_if_shared_r, NULL, NULL); | |
730 | } | |
731 | ||
6de9cd9a DN |
732 | /* If this node has been visited already, unshare it and don't look |
733 | any deeper. */ | |
f0638e1d | 734 | else if (TREE_VISITED (t)) |
6de9cd9a DN |
735 | { |
736 | walk_tree (tp, mostly_copy_tree_r, NULL, NULL); | |
737 | *walk_subtrees = 0; | |
738 | } | |
f0638e1d RH |
739 | |
740 | /* Otherwise, mark the tree as visited and keep looking. */ | |
6de9cd9a | 741 | else |
0b1d52f7 AO |
742 | { |
743 | TREE_VISITED (t) = 1; | |
cd3ce9b4 JM |
744 | if (TREE_CODE (*tp) == VA_ARG_EXPR |
745 | && targetm.calls.gimplify_va_arg_expr == NULL) | |
0b1d52f7 AO |
746 | { |
747 | /* Mark any _DECL inside the operand as volatile to avoid | |
748 | the optimizers messing around with it. We have to do this | |
749 | early, otherwise we might mark a variable as volatile | |
750 | after we gimplify other statements that use the variable | |
751 | assuming it's not volatile. */ | |
cd3ce9b4 JM |
752 | |
753 | /* FIXME once most targets define the above hook, this should | |
754 | go away (perhaps along with the #include "target.h"). */ | |
0b1d52f7 AO |
755 | walk_tree (&TREE_OPERAND (*tp, 0), mark_decls_volatile_r, |
756 | NULL, NULL); | |
757 | } | |
758 | } | |
f0638e1d | 759 | |
6de9cd9a DN |
760 | return NULL_TREE; |
761 | } | |
762 | ||
763 | static tree | |
764 | unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, | |
765 | void *data ATTRIBUTE_UNUSED) | |
766 | { | |
767 | if (TREE_VISITED (*tp)) | |
768 | TREE_VISITED (*tp) = 0; | |
769 | else | |
770 | *walk_subtrees = 0; | |
771 | ||
772 | return NULL_TREE; | |
773 | } | |
774 | ||
44de5aeb RK |
775 | /* Unshare all the trees in BODY_P, a pointer to the body of FNDECL, and the |
776 | bodies of any nested functions. */ | |
777 | ||
778 | static void | |
779 | unshare_body (tree *body_p, tree fndecl) | |
780 | { | |
781 | struct cgraph_node *cgn = cgraph_node (fndecl); | |
782 | ||
783 | walk_tree (body_p, copy_if_shared_r, NULL, NULL); | |
784 | for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) | |
785 | unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl); | |
786 | } | |
787 | ||
788 | /* Likewise, but mark all trees as not visited. */ | |
789 | ||
790 | static void | |
791 | unvisit_body (tree *body_p, tree fndecl) | |
792 | { | |
793 | struct cgraph_node *cgn = cgraph_node (fndecl); | |
794 | ||
795 | walk_tree (body_p, unmark_visited_r, NULL, NULL); | |
796 | for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) | |
797 | unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl); | |
798 | } | |
799 | ||
6de9cd9a DN |
800 | /* Unshare T and all the trees reached from T via TREE_CHAIN. */ |
801 | ||
802 | void | |
803 | unshare_all_trees (tree t) | |
804 | { | |
805 | walk_tree (&t, copy_if_shared_r, NULL, NULL); | |
806 | walk_tree (&t, unmark_visited_r, NULL, NULL); | |
807 | } | |
808 | ||
809 | /* Unconditionally make an unshared copy of EXPR. This is used when using | |
810 | stored expressions which span multiple functions, such as BINFO_VTABLE, | |
811 | as the normal unsharing process can't tell that they're shared. */ | |
812 | ||
813 | tree | |
814 | unshare_expr (tree expr) | |
815 | { | |
816 | walk_tree (&expr, mostly_copy_tree_r, NULL, NULL); | |
817 | return expr; | |
818 | } | |
819 | ||
820 | /* A terser interface for building a representation of a exception | |
821 | specification. */ | |
822 | ||
823 | tree | |
824 | gimple_build_eh_filter (tree body, tree allowed, tree failure) | |
825 | { | |
826 | tree t; | |
827 | ||
828 | /* FIXME should the allowed types go in TREE_TYPE? */ | |
829 | t = build (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE); | |
830 | append_to_statement_list (failure, &EH_FILTER_FAILURE (t)); | |
831 | ||
832 | t = build (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t); | |
833 | append_to_statement_list (body, &TREE_OPERAND (t, 0)); | |
834 | ||
835 | return t; | |
836 | } | |
837 | ||
838 | \f | |
839 | /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both | |
840 | contain statements and have a value. Assign its value to a temporary | |
841 | and give it void_type_node. Returns the temporary, or NULL_TREE if | |
842 | WRAPPER was already void. */ | |
843 | ||
844 | tree | |
325c3691 | 845 | voidify_wrapper_expr (tree wrapper, tree temp) |
6de9cd9a DN |
846 | { |
847 | if (!VOID_TYPE_P (TREE_TYPE (wrapper))) | |
848 | { | |
325c3691 | 849 | tree *p, sub = wrapper; |
6de9cd9a | 850 | |
325c3691 | 851 | restart: |
6de9cd9a | 852 | /* Set p to point to the body of the wrapper. */ |
325c3691 | 853 | switch (TREE_CODE (sub)) |
6de9cd9a DN |
854 | { |
855 | case BIND_EXPR: | |
856 | /* For a BIND_EXPR, the body is operand 1. */ | |
325c3691 | 857 | p = &BIND_EXPR_BODY (sub); |
6de9cd9a DN |
858 | break; |
859 | ||
860 | default: | |
325c3691 | 861 | p = &TREE_OPERAND (sub, 0); |
6de9cd9a DN |
862 | break; |
863 | } | |
864 | ||
865 | /* Advance to the last statement. Set all container types to void. */ | |
866 | if (TREE_CODE (*p) == STATEMENT_LIST) | |
867 | { | |
868 | tree_stmt_iterator i = tsi_last (*p); | |
869 | p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i); | |
870 | } | |
871 | else | |
872 | { | |
873 | for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1)) | |
874 | { | |
875 | TREE_SIDE_EFFECTS (*p) = 1; | |
876 | TREE_TYPE (*p) = void_type_node; | |
877 | } | |
878 | } | |
879 | ||
325c3691 RH |
880 | if (p == NULL || IS_EMPTY_STMT (*p)) |
881 | ; | |
882 | /* Look through exception handling. */ | |
883 | else if (TREE_CODE (*p) == TRY_FINALLY_EXPR | |
884 | || TREE_CODE (*p) == TRY_CATCH_EXPR) | |
6de9cd9a | 885 | { |
325c3691 RH |
886 | sub = *p; |
887 | goto restart; | |
6de9cd9a | 888 | } |
325c3691 RH |
889 | /* The C++ frontend already did this for us. */ |
890 | else if (TREE_CODE (*p) == INIT_EXPR) | |
891 | temp = TREE_OPERAND (*p, 0); | |
892 | /* If we're returning a dereference, move the dereference | |
893 | outside the wrapper. */ | |
894 | else if (TREE_CODE (*p) == INDIRECT_REF) | |
6de9cd9a | 895 | { |
6de9cd9a DN |
896 | tree ptr = TREE_OPERAND (*p, 0); |
897 | temp = create_tmp_var (TREE_TYPE (ptr), "retval"); | |
898 | *p = build (MODIFY_EXPR, TREE_TYPE (ptr), temp, ptr); | |
899 | temp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp)), temp); | |
900 | /* If this is a BIND_EXPR for a const inline function, it might not | |
901 | have TREE_SIDE_EFFECTS set. That is no longer accurate. */ | |
902 | TREE_SIDE_EFFECTS (wrapper) = 1; | |
903 | } | |
904 | else | |
905 | { | |
325c3691 RH |
906 | if (!temp) |
907 | temp = create_tmp_var (TREE_TYPE (wrapper), "retval"); | |
908 | *p = build (MODIFY_EXPR, TREE_TYPE (temp), temp, *p); | |
909 | TREE_SIDE_EFFECTS (wrapper) = 1; | |
6de9cd9a DN |
910 | } |
911 | ||
912 | TREE_TYPE (wrapper) = void_type_node; | |
913 | return temp; | |
914 | } | |
915 | ||
916 | return NULL_TREE; | |
917 | } | |
918 | ||
919 | /* Prepare calls to builtins to SAVE and RESTORE the stack as well as | |
1ea7e6ad | 920 | a temporary through which they communicate. */ |
6de9cd9a DN |
921 | |
922 | static void | |
923 | build_stack_save_restore (tree *save, tree *restore) | |
924 | { | |
925 | tree save_call, tmp_var; | |
926 | ||
927 | save_call = | |
928 | build_function_call_expr (implicit_built_in_decls[BUILT_IN_STACK_SAVE], | |
929 | NULL_TREE); | |
930 | tmp_var = create_tmp_var (ptr_type_node, "saved_stack"); | |
931 | ||
932 | *save = build (MODIFY_EXPR, ptr_type_node, tmp_var, save_call); | |
933 | *restore = | |
934 | build_function_call_expr (implicit_built_in_decls[BUILT_IN_STACK_RESTORE], | |
935 | tree_cons (NULL_TREE, tmp_var, NULL_TREE)); | |
936 | } | |
937 | ||
938 | /* Gimplify a BIND_EXPR. Just voidify and recurse. */ | |
939 | ||
940 | static enum gimplify_status | |
325c3691 | 941 | gimplify_bind_expr (tree *expr_p, tree temp, tree *pre_p) |
6de9cd9a DN |
942 | { |
943 | tree bind_expr = *expr_p; | |
6de9cd9a DN |
944 | bool old_save_stack = gimplify_ctxp->save_stack; |
945 | tree t; | |
946 | ||
325c3691 RH |
947 | temp = voidify_wrapper_expr (bind_expr, temp); |
948 | ||
6de9cd9a DN |
949 | /* Mark variables seen in this bind expr. */ |
950 | for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t)) | |
951 | t->decl.seen_in_bind_expr = 1; | |
952 | ||
953 | gimple_push_bind_expr (bind_expr); | |
954 | gimplify_ctxp->save_stack = false; | |
955 | ||
956 | gimplify_to_stmt_list (&BIND_EXPR_BODY (bind_expr)); | |
957 | ||
958 | if (gimplify_ctxp->save_stack) | |
959 | { | |
960 | tree stack_save, stack_restore; | |
961 | ||
962 | /* Save stack on entry and restore it on exit. Add a try_finally | |
963 | block to achieve this. Note that mudflap depends on the | |
964 | format of the emitted code: see mx_register_decls(). */ | |
965 | build_stack_save_restore (&stack_save, &stack_restore); | |
966 | ||
967 | t = build (TRY_FINALLY_EXPR, void_type_node, | |
968 | BIND_EXPR_BODY (bind_expr), NULL_TREE); | |
969 | append_to_statement_list (stack_restore, &TREE_OPERAND (t, 1)); | |
970 | ||
971 | BIND_EXPR_BODY (bind_expr) = NULL_TREE; | |
972 | append_to_statement_list (stack_save, &BIND_EXPR_BODY (bind_expr)); | |
973 | append_to_statement_list (t, &BIND_EXPR_BODY (bind_expr)); | |
974 | } | |
975 | ||
976 | gimplify_ctxp->save_stack = old_save_stack; | |
977 | gimple_pop_bind_expr (); | |
978 | ||
979 | if (temp) | |
980 | { | |
981 | *expr_p = temp; | |
982 | append_to_statement_list (bind_expr, pre_p); | |
983 | return GS_OK; | |
984 | } | |
985 | else | |
986 | return GS_ALL_DONE; | |
987 | } | |
988 | ||
989 | /* Gimplify a RETURN_EXPR. If the expression to be returned is not a | |
990 | GIMPLE value, it is assigned to a new temporary and the statement is | |
991 | re-written to return the temporary. | |
992 | ||
993 | PRE_P points to the list where side effects that must happen before | |
994 | STMT should be stored. */ | |
995 | ||
996 | static enum gimplify_status | |
997 | gimplify_return_expr (tree stmt, tree *pre_p) | |
998 | { | |
999 | tree ret_expr = TREE_OPERAND (stmt, 0); | |
71877985 | 1000 | tree result_decl, result; |
6de9cd9a DN |
1001 | |
1002 | if (!ret_expr || TREE_CODE (ret_expr) == RESULT_DECL) | |
1003 | return GS_ALL_DONE; | |
1004 | ||
1005 | if (ret_expr == error_mark_node) | |
1006 | return GS_ERROR; | |
1007 | ||
1008 | if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))) | |
71877985 | 1009 | result_decl = NULL_TREE; |
6de9cd9a DN |
1010 | else |
1011 | { | |
71877985 | 1012 | result_decl = TREE_OPERAND (ret_expr, 0); |
6de9cd9a DN |
1013 | #ifdef ENABLE_CHECKING |
1014 | if ((TREE_CODE (ret_expr) != MODIFY_EXPR | |
1015 | && TREE_CODE (ret_expr) != INIT_EXPR) | |
71877985 | 1016 | || TREE_CODE (result_decl) != RESULT_DECL) |
6de9cd9a DN |
1017 | abort (); |
1018 | #endif | |
1019 | } | |
1020 | ||
71877985 RH |
1021 | /* If aggregate_value_p is true, then we can return the bare RESULT_DECL. |
1022 | Recall that aggregate_value_p is FALSE for any aggregate type that is | |
1023 | returned in registers. If we're returning values in registers, then | |
1024 | we don't want to extend the lifetime of the RESULT_DECL, particularly | |
1025 | across another call. In addition, for those aggregates for which | |
1026 | hard_function_value generates a PARALLEL, we'll abort during normal | |
1027 | expansion of structure assignments; there's special code in expand_return | |
1028 | to handle this case that does not exist in expand_expr. */ | |
1029 | if (!result_decl | |
1030 | || aggregate_value_p (result_decl, TREE_TYPE (current_function_decl))) | |
1031 | result = result_decl; | |
1032 | else if (gimplify_ctxp->return_temp) | |
1033 | result = gimplify_ctxp->return_temp; | |
1034 | else | |
1035 | { | |
1036 | result = create_tmp_var (TREE_TYPE (result_decl), NULL); | |
ff98621c RH |
1037 | |
1038 | /* ??? With complex control flow (usually involving abnormal edges), | |
1039 | we can wind up warning about an uninitialized value for this. Due | |
1040 | to how this variable is constructed and initialized, this is never | |
1041 | true. Give up and never warn. */ | |
1042 | TREE_NO_WARNING (result) = 1; | |
1043 | ||
71877985 RH |
1044 | gimplify_ctxp->return_temp = result; |
1045 | } | |
1046 | ||
1047 | /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use. | |
1048 | Then gimplify the whole thing. */ | |
1049 | if (result != result_decl) | |
1050 | TREE_OPERAND (ret_expr, 0) = result; | |
f5a76aea RH |
1051 | gimplify_stmt (&TREE_OPERAND (stmt, 0)); |
1052 | append_to_statement_list (TREE_OPERAND (stmt, 0), pre_p); | |
6de9cd9a | 1053 | |
71877985 RH |
1054 | /* If we didn't use a temporary, then the result is just the result_decl. |
1055 | Otherwise we need a simple copy. This should already be gimple. */ | |
1056 | if (result == result_decl) | |
1057 | ret_expr = result; | |
1058 | else | |
1059 | ret_expr = build (MODIFY_EXPR, TREE_TYPE (result), result_decl, result); | |
1060 | TREE_OPERAND (stmt, 0) = ret_expr; | |
6de9cd9a | 1061 | |
6de9cd9a DN |
1062 | return GS_ALL_DONE; |
1063 | } | |
1064 | ||
1065 | /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body | |
1066 | and replacing the LOOP_EXPR with goto, but if the loop contains an | |
1067 | EXIT_EXPR, we need to append a label for it to jump to. */ | |
1068 | ||
1069 | static enum gimplify_status | |
1070 | gimplify_loop_expr (tree *expr_p, tree *pre_p) | |
1071 | { | |
1072 | tree saved_label = gimplify_ctxp->exit_label; | |
1073 | tree start_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE); | |
1074 | tree jump_stmt = build_and_jump (&LABEL_EXPR_LABEL (start_label)); | |
1075 | ||
1076 | append_to_statement_list (start_label, pre_p); | |
1077 | ||
1078 | gimplify_ctxp->exit_label = NULL_TREE; | |
1079 | ||
1080 | gimplify_stmt (&LOOP_EXPR_BODY (*expr_p)); | |
1081 | append_to_statement_list (LOOP_EXPR_BODY (*expr_p), pre_p); | |
1082 | ||
1083 | if (gimplify_ctxp->exit_label) | |
1084 | { | |
1085 | append_to_statement_list (jump_stmt, pre_p); | |
1086 | *expr_p = build1 (LABEL_EXPR, void_type_node, gimplify_ctxp->exit_label); | |
1087 | } | |
1088 | else | |
1089 | *expr_p = jump_stmt; | |
1090 | ||
1091 | gimplify_ctxp->exit_label = saved_label; | |
1092 | ||
1093 | return GS_ALL_DONE; | |
1094 | } | |
1095 | ||
f667741c SB |
1096 | /* Compare two case labels. Because the front end should already have |
1097 | made sure that case ranges do not overlap, it is enough to only compare | |
1098 | the CASE_LOW values of each case label. */ | |
1099 | ||
1100 | static int | |
1101 | compare_case_labels (const void *p1, const void *p2) | |
1102 | { | |
1103 | tree case1 = *(tree *)p1; | |
1104 | tree case2 = *(tree *)p2; | |
1105 | ||
1106 | return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); | |
1107 | } | |
1108 | ||
0f1f6967 SB |
1109 | /* Sort the case labels in LABEL_VEC in ascending order. */ |
1110 | ||
1111 | void | |
1112 | sort_case_labels (tree label_vec) | |
1113 | { | |
1114 | size_t len = TREE_VEC_LENGTH (label_vec); | |
1115 | tree default_case = TREE_VEC_ELT (label_vec, len - 1); | |
1116 | ||
1117 | if (CASE_LOW (default_case)) | |
1118 | { | |
1119 | size_t i; | |
1120 | ||
1121 | /* The last label in the vector should be the default case | |
1122 | but it is not. */ | |
1123 | for (i = 0; i < len; ++i) | |
1124 | { | |
1125 | tree t = TREE_VEC_ELT (label_vec, i); | |
1126 | if (!CASE_LOW (t)) | |
1127 | { | |
1128 | default_case = t; | |
1129 | TREE_VEC_ELT (label_vec, i) = TREE_VEC_ELT (label_vec, len - 1); | |
1130 | TREE_VEC_ELT (label_vec, len - 1) = default_case; | |
1131 | break; | |
1132 | } | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | qsort (&TREE_VEC_ELT (label_vec, 0), len - 1, sizeof (tree), | |
1137 | compare_case_labels); | |
1138 | } | |
1139 | ||
6de9cd9a DN |
1140 | /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can |
1141 | branch to. */ | |
1142 | ||
1143 | static enum gimplify_status | |
1144 | gimplify_switch_expr (tree *expr_p, tree *pre_p) | |
1145 | { | |
1146 | tree switch_expr = *expr_p; | |
1147 | enum gimplify_status ret; | |
1148 | ||
1149 | ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, | |
1150 | is_gimple_val, fb_rvalue); | |
1151 | ||
1152 | if (SWITCH_BODY (switch_expr)) | |
1153 | { | |
1154 | varray_type labels, saved_labels; | |
f667741c | 1155 | tree label_vec, default_case = NULL_TREE; |
6de9cd9a DN |
1156 | size_t i, len; |
1157 | ||
1158 | /* If someone can be bothered to fill in the labels, they can | |
1159 | be bothered to null out the body too. */ | |
1160 | if (SWITCH_LABELS (switch_expr)) | |
1161 | abort (); | |
1162 | ||
1163 | saved_labels = gimplify_ctxp->case_labels; | |
1164 | VARRAY_TREE_INIT (gimplify_ctxp->case_labels, 8, "case_labels"); | |
1165 | ||
1166 | gimplify_to_stmt_list (&SWITCH_BODY (switch_expr)); | |
1167 | ||
1168 | labels = gimplify_ctxp->case_labels; | |
1169 | gimplify_ctxp->case_labels = saved_labels; | |
1170 | ||
1171 | len = VARRAY_ACTIVE_SIZE (labels); | |
6de9cd9a DN |
1172 | |
1173 | for (i = 0; i < len; ++i) | |
1174 | { | |
f667741c | 1175 | tree t = VARRAY_TREE (labels, i); |
6de9cd9a DN |
1176 | if (!CASE_LOW (t)) |
1177 | { | |
f667741c SB |
1178 | /* The default case must be the last label in the list. */ |
1179 | default_case = t; | |
1180 | VARRAY_TREE (labels, i) = VARRAY_TREE (labels, len - 1); | |
1181 | len--; | |
6de9cd9a DN |
1182 | break; |
1183 | } | |
1184 | } | |
1185 | ||
f667741c | 1186 | label_vec = make_tree_vec (len + 1); |
6de9cd9a | 1187 | SWITCH_LABELS (*expr_p) = label_vec; |
6de9cd9a DN |
1188 | append_to_statement_list (switch_expr, pre_p); |
1189 | ||
f667741c | 1190 | if (! default_case) |
6de9cd9a | 1191 | { |
f667741c SB |
1192 | /* If the switch has no default label, add one, so that we jump |
1193 | around the switch body. */ | |
1194 | default_case = build (CASE_LABEL_EXPR, void_type_node, NULL_TREE, | |
1195 | NULL_TREE, create_artificial_label ()); | |
6de9cd9a | 1196 | append_to_statement_list (SWITCH_BODY (switch_expr), pre_p); |
f667741c SB |
1197 | *expr_p = build (LABEL_EXPR, void_type_node, |
1198 | CASE_LABEL (default_case)); | |
6de9cd9a DN |
1199 | } |
1200 | else | |
1201 | *expr_p = SWITCH_BODY (switch_expr); | |
1202 | ||
f667741c SB |
1203 | for (i = 0; i < len; ++i) |
1204 | TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i); | |
1205 | TREE_VEC_ELT (label_vec, len) = default_case; | |
1206 | ||
0f1f6967 SB |
1207 | sort_case_labels (label_vec); |
1208 | ||
6de9cd9a DN |
1209 | SWITCH_BODY (switch_expr) = NULL; |
1210 | } | |
1211 | else if (!SWITCH_LABELS (switch_expr)) | |
1212 | abort (); | |
1213 | ||
1214 | return ret; | |
1215 | } | |
1216 | ||
1217 | static enum gimplify_status | |
1218 | gimplify_case_label_expr (tree *expr_p) | |
1219 | { | |
1220 | tree expr = *expr_p; | |
1221 | if (gimplify_ctxp->case_labels) | |
1222 | VARRAY_PUSH_TREE (gimplify_ctxp->case_labels, expr); | |
1223 | else | |
1224 | abort (); | |
1225 | *expr_p = build (LABEL_EXPR, void_type_node, CASE_LABEL (expr)); | |
1226 | return GS_ALL_DONE; | |
1227 | } | |
1228 | ||
1229 | /* Gimplify a LABELED_BLOCK_EXPR into a LABEL_EXPR following | |
1230 | a (possibly empty) body. */ | |
1231 | ||
1232 | static enum gimplify_status | |
1233 | gimplify_labeled_block_expr (tree *expr_p) | |
1234 | { | |
1235 | tree body = LABELED_BLOCK_BODY (*expr_p); | |
1236 | tree label = LABELED_BLOCK_LABEL (*expr_p); | |
1237 | tree t; | |
1238 | ||
1239 | DECL_CONTEXT (label) = current_function_decl; | |
1240 | t = build (LABEL_EXPR, void_type_node, label); | |
1241 | if (body != NULL_TREE) | |
1242 | t = build (COMPOUND_EXPR, void_type_node, body, t); | |
1243 | *expr_p = t; | |
1244 | ||
1245 | return GS_OK; | |
1246 | } | |
1247 | ||
1248 | /* Gimplify a EXIT_BLOCK_EXPR into a GOTO_EXPR. */ | |
1249 | ||
1250 | static enum gimplify_status | |
1251 | gimplify_exit_block_expr (tree *expr_p) | |
1252 | { | |
1253 | tree labeled_block = TREE_OPERAND (*expr_p, 0); | |
1254 | tree label; | |
1255 | ||
1256 | /* First operand must be a LABELED_BLOCK_EXPR, which should | |
1257 | already be lowered (or partially lowered) when we get here. */ | |
1258 | #if defined ENABLE_CHECKING | |
1259 | if (TREE_CODE (labeled_block) != LABELED_BLOCK_EXPR) | |
1260 | abort (); | |
1261 | #endif | |
1262 | ||
1263 | label = LABELED_BLOCK_LABEL (labeled_block); | |
1264 | *expr_p = build1 (GOTO_EXPR, void_type_node, label); | |
1265 | ||
1266 | return GS_OK; | |
1267 | } | |
1268 | ||
1269 | /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first | |
1270 | if necessary. */ | |
1271 | ||
1272 | tree | |
1273 | build_and_jump (tree *label_p) | |
1274 | { | |
1275 | if (label_p == NULL) | |
1276 | /* If there's nowhere to jump, just fall through. */ | |
65355d53 | 1277 | return NULL_TREE; |
6de9cd9a DN |
1278 | |
1279 | if (*label_p == NULL_TREE) | |
1280 | { | |
1281 | tree label = create_artificial_label (); | |
1282 | *label_p = label; | |
1283 | } | |
1284 | ||
1285 | return build1 (GOTO_EXPR, void_type_node, *label_p); | |
1286 | } | |
1287 | ||
1288 | /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR. | |
1289 | This also involves building a label to jump to and communicating it to | |
1290 | gimplify_loop_expr through gimplify_ctxp->exit_label. */ | |
1291 | ||
1292 | static enum gimplify_status | |
1293 | gimplify_exit_expr (tree *expr_p) | |
1294 | { | |
1295 | tree cond = TREE_OPERAND (*expr_p, 0); | |
1296 | tree expr; | |
1297 | ||
1298 | expr = build_and_jump (&gimplify_ctxp->exit_label); | |
65355d53 | 1299 | expr = build (COND_EXPR, void_type_node, cond, expr, NULL_TREE); |
6de9cd9a DN |
1300 | *expr_p = expr; |
1301 | ||
1302 | return GS_OK; | |
1303 | } | |
1304 | ||
1305 | /* A helper function to be called via walk_tree. Mark all labels under *TP | |
1306 | as being forced. To be called for DECL_INITIAL of static variables. */ | |
1307 | ||
1308 | tree | |
1309 | force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) | |
1310 | { | |
1311 | if (TYPE_P (*tp)) | |
1312 | *walk_subtrees = 0; | |
1313 | if (TREE_CODE (*tp) == LABEL_DECL) | |
1314 | FORCED_LABEL (*tp) = 1; | |
1315 | ||
1316 | return NULL_TREE; | |
1317 | } | |
1318 | ||
1319 | /* Break out elements of a constructor used as an initializer into separate | |
1320 | MODIFY_EXPRs. | |
1321 | ||
1322 | Note that we still need to clear any elements that don't have explicit | |
1323 | initializers, so if not all elements are initialized we keep the | |
1324 | original MODIFY_EXPR, we just remove all of the constructor elements. */ | |
1325 | ||
1326 | static enum gimplify_status | |
1327 | gimplify_init_constructor (tree *expr_p, tree *pre_p, | |
44de5aeb | 1328 | tree *post_p, bool want_value) |
6de9cd9a DN |
1329 | { |
1330 | tree object = TREE_OPERAND (*expr_p, 0); | |
1331 | tree ctor = TREE_OPERAND (*expr_p, 1); | |
1332 | tree type = TREE_TYPE (ctor); | |
1333 | enum gimplify_status ret; | |
1334 | tree elt_list; | |
1335 | ||
1336 | if (TREE_CODE (ctor) != CONSTRUCTOR) | |
1337 | return GS_UNHANDLED; | |
1338 | ||
1339 | elt_list = CONSTRUCTOR_ELTS (ctor); | |
1340 | ||
1341 | ret = GS_ALL_DONE; | |
1342 | switch (TREE_CODE (type)) | |
1343 | { | |
1344 | case RECORD_TYPE: | |
1345 | case UNION_TYPE: | |
1346 | case QUAL_UNION_TYPE: | |
1347 | case ARRAY_TYPE: | |
1348 | { | |
1349 | HOST_WIDE_INT i, num_elements, num_nonzero_elements; | |
1350 | HOST_WIDE_INT num_nonconstant_elements; | |
1351 | bool cleared; | |
1352 | ||
1353 | /* Aggregate types must lower constructors to initialization of | |
1354 | individual elements. The exception is that a CONSTRUCTOR node | |
1355 | with no elements indicates zero-initialization of the whole. */ | |
1356 | if (elt_list == NULL) | |
1357 | { | |
1358 | if (want_value) | |
1359 | { | |
1360 | *expr_p = object; | |
1361 | return GS_OK; | |
1362 | } | |
1363 | else | |
44de5aeb | 1364 | return GS_UNHANDLED; |
6de9cd9a DN |
1365 | } |
1366 | ||
1367 | categorize_ctor_elements (ctor, &num_nonzero_elements, | |
1368 | &num_nonconstant_elements); | |
1369 | num_elements = count_type_elements (TREE_TYPE (ctor)); | |
1370 | ||
1371 | /* If a const aggregate variable is being initialized, then it | |
1372 | should never be a lose to promote the variable to be static. */ | |
1373 | if (num_nonconstant_elements == 0 | |
1374 | && TREE_READONLY (object) | |
1375 | && TREE_CODE (object) == VAR_DECL) | |
1376 | { | |
1377 | DECL_INITIAL (object) = ctor; | |
1378 | TREE_STATIC (object) = 1; | |
1379 | if (!DECL_NAME (object)) | |
1380 | DECL_NAME (object) = create_tmp_var_name ("C"); | |
1381 | walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL); | |
1382 | ||
1383 | /* ??? C++ doesn't automatically append a .<number> to the | |
1384 | assembler name, and even when it does, it looks a FE private | |
1385 | data structures to figure out what that number should be, | |
1386 | which are not set for this variable. I suppose this is | |
1387 | important for local statics for inline functions, which aren't | |
1388 | "local" in the object file sense. So in order to get a unique | |
1389 | TU-local symbol, we must invoke the lhd version now. */ | |
1390 | lhd_set_decl_assembler_name (object); | |
1391 | ||
65355d53 | 1392 | *expr_p = NULL_TREE; |
6de9cd9a DN |
1393 | break; |
1394 | } | |
1395 | ||
1396 | /* If there are "lots" of initialized elements, and all of them | |
1397 | are valid address constants, then the entire initializer can | |
1398 | be dropped to memory, and then memcpy'd out. */ | |
1399 | if (num_nonconstant_elements == 0) | |
1400 | { | |
1401 | HOST_WIDE_INT size = int_size_in_bytes (type); | |
1402 | unsigned int align; | |
1403 | ||
1404 | /* ??? We can still get unbounded array types, at least | |
1405 | from the C++ front end. This seems wrong, but attempt | |
1406 | to work around it for now. */ | |
1407 | if (size < 0) | |
1408 | { | |
1409 | size = int_size_in_bytes (TREE_TYPE (object)); | |
1410 | if (size >= 0) | |
1411 | TREE_TYPE (ctor) = type = TREE_TYPE (object); | |
1412 | } | |
1413 | ||
1414 | /* Find the maximum alignment we can assume for the object. */ | |
1415 | /* ??? Make use of DECL_OFFSET_ALIGN. */ | |
1416 | if (DECL_P (object)) | |
1417 | align = DECL_ALIGN (object); | |
1418 | else | |
1419 | align = TYPE_ALIGN (type); | |
1420 | ||
1421 | if (size > 0 && !can_move_by_pieces (size, align)) | |
1422 | { | |
1423 | tree new = create_tmp_var_raw (type, "C"); | |
1424 | gimple_add_tmp_var (new); | |
1425 | TREE_STATIC (new) = 1; | |
1426 | TREE_READONLY (new) = 1; | |
1427 | DECL_INITIAL (new) = ctor; | |
1428 | if (align > DECL_ALIGN (new)) | |
1429 | { | |
1430 | DECL_ALIGN (new) = align; | |
1431 | DECL_USER_ALIGN (new) = 1; | |
1432 | } | |
1433 | walk_tree (&DECL_INITIAL (new), force_labels_r, NULL, NULL); | |
1434 | ||
1435 | TREE_OPERAND (*expr_p, 1) = new; | |
1436 | break; | |
1437 | } | |
1438 | } | |
1439 | ||
1440 | /* If there are "lots" of initialized elements, even discounting | |
1441 | those that are not address constants (and thus *must* be | |
1442 | computed at runtime), then partition the constructor into | |
1443 | constant and non-constant parts. Block copy the constant | |
1444 | parts in, then generate code for the non-constant parts. */ | |
1445 | /* TODO. There's code in cp/typeck.c to do this. */ | |
1446 | ||
1447 | /* If there are "lots" of zeros, then block clear the object first. */ | |
1448 | cleared = false; | |
1449 | if (num_elements - num_nonzero_elements > CLEAR_RATIO | |
1450 | && num_nonzero_elements < num_elements/4) | |
1451 | cleared = true; | |
1452 | ||
1453 | /* ??? This bit ought not be needed. For any element not present | |
1454 | in the initializer, we should simply set them to zero. Except | |
1455 | we'd need to *find* the elements that are not present, and that | |
1ea7e6ad | 1456 | requires trickery to avoid quadratic compile-time behavior in |
6de9cd9a DN |
1457 | large cases or excessive memory use in small cases. */ |
1458 | else | |
1459 | { | |
1460 | HOST_WIDE_INT len = list_length (elt_list); | |
1461 | if (TREE_CODE (type) == ARRAY_TYPE) | |
1462 | { | |
1463 | tree nelts = array_type_nelts (type); | |
1464 | if (!host_integerp (nelts, 1) | |
1465 | || tree_low_cst (nelts, 1) != len) | |
1466 | cleared = 1;; | |
1467 | } | |
1468 | else if (len != fields_length (type)) | |
1469 | cleared = 1; | |
1470 | } | |
1471 | ||
1472 | if (cleared) | |
1473 | { | |
1474 | CONSTRUCTOR_ELTS (ctor) = NULL_TREE; | |
1475 | append_to_statement_list (*expr_p, pre_p); | |
1476 | } | |
1477 | ||
1478 | for (i = 0; elt_list; i++, elt_list = TREE_CHAIN (elt_list)) | |
1479 | { | |
1480 | tree purpose, value, cref, init; | |
1481 | ||
1482 | purpose = TREE_PURPOSE (elt_list); | |
1483 | value = TREE_VALUE (elt_list); | |
1484 | ||
1485 | if (cleared && initializer_zerop (value)) | |
1486 | continue; | |
1487 | ||
1488 | if (TREE_CODE (type) == ARRAY_TYPE) | |
1489 | { | |
1490 | tree t = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object))); | |
1491 | ||
1492 | /* ??? Here's to hoping the front end fills in all of the | |
1493 | indicies, so we don't have to figure out what's missing | |
1494 | ourselves. */ | |
1495 | if (!purpose) | |
1496 | abort (); | |
1497 | /* ??? Need to handle this. */ | |
1498 | if (TREE_CODE (purpose) == RANGE_EXPR) | |
1499 | abort (); | |
1500 | ||
44de5aeb | 1501 | cref = build (ARRAY_REF, t, object, purpose, NULL_TREE, NULL_TREE); |
6de9cd9a DN |
1502 | } |
1503 | else | |
44de5aeb RK |
1504 | cref = build (COMPONENT_REF, TREE_TYPE (purpose), object, |
1505 | purpose, NULL_TREE); | |
6de9cd9a DN |
1506 | |
1507 | init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value); | |
1508 | /* Each member initialization is a full-expression. */ | |
1509 | gimplify_stmt (&init); | |
1510 | append_to_statement_list (init, pre_p); | |
1511 | } | |
1512 | ||
65355d53 | 1513 | *expr_p = NULL_TREE; |
6de9cd9a DN |
1514 | } |
1515 | break; | |
1516 | ||
1517 | case COMPLEX_TYPE: | |
1518 | { | |
1519 | tree r, i; | |
1520 | ||
1521 | /* Extract the real and imaginary parts out of the ctor. */ | |
1522 | r = i = NULL_TREE; | |
1523 | if (elt_list) | |
1524 | { | |
1525 | r = TREE_VALUE (elt_list); | |
1526 | elt_list = TREE_CHAIN (elt_list); | |
1527 | if (elt_list) | |
1528 | { | |
1529 | i = TREE_VALUE (elt_list); | |
1530 | if (TREE_CHAIN (elt_list)) | |
1531 | abort (); | |
1532 | } | |
1533 | } | |
1534 | if (r == NULL || i == NULL) | |
1535 | { | |
1536 | tree zero = convert (TREE_TYPE (type), integer_zero_node); | |
1537 | if (r == NULL) | |
1538 | r = zero; | |
1539 | if (i == NULL) | |
1540 | i = zero; | |
1541 | } | |
1542 | ||
1543 | /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to | |
1544 | represent creation of a complex value. */ | |
1545 | if (TREE_CONSTANT (r) && TREE_CONSTANT (i)) | |
1546 | { | |
1547 | ctor = build_complex (type, r, i); | |
1548 | TREE_OPERAND (*expr_p, 1) = ctor; | |
1549 | } | |
1550 | else | |
1551 | { | |
1552 | ctor = build (COMPLEX_EXPR, type, r, i); | |
1553 | TREE_OPERAND (*expr_p, 1) = ctor; | |
1554 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, | |
1555 | is_gimple_rhs, fb_rvalue); | |
1556 | } | |
1557 | } | |
1558 | break; | |
1559 | ||
1560 | case VECTOR_TYPE: | |
1561 | /* Go ahead and simplify constant constructors to VECTOR_CST. */ | |
1562 | if (TREE_CONSTANT (ctor)) | |
1563 | TREE_OPERAND (*expr_p, 1) = build_vector (type, elt_list); | |
1564 | else | |
1565 | { | |
1566 | /* Vector types use CONSTRUCTOR all the way through gimple | |
1567 | compilation as a general initializer. */ | |
1568 | for (; elt_list; elt_list = TREE_CHAIN (elt_list)) | |
1569 | { | |
1570 | enum gimplify_status tret; | |
1571 | tret = gimplify_expr (&TREE_VALUE (elt_list), pre_p, post_p, | |
1572 | is_gimple_constructor_elt, fb_rvalue); | |
1573 | if (tret == GS_ERROR) | |
1574 | ret = GS_ERROR; | |
1575 | } | |
1576 | } | |
1577 | break; | |
1578 | ||
1579 | default: | |
1580 | /* So how did we get a CONSTRUCTOR for a scalar type? */ | |
1581 | abort (); | |
1582 | } | |
1583 | ||
1584 | if (ret == GS_ERROR) | |
1585 | return GS_ERROR; | |
1586 | else if (want_value) | |
1587 | { | |
1588 | append_to_statement_list (*expr_p, pre_p); | |
1589 | *expr_p = object; | |
1590 | return GS_OK; | |
1591 | } | |
1592 | else | |
1593 | return GS_ALL_DONE; | |
1594 | } | |
1595 | ||
1596 | /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is | |
1597 | different from its canonical type, wrap the whole thing inside a | |
1598 | NOP_EXPR and force the type of the COMPONENT_REF to be the canonical | |
1599 | type. | |
1600 | ||
1601 | The canonical type of a COMPONENT_REF is the type of the field being | |
1602 | referenced--unless the field is a bit-field which can be read directly | |
1603 | in a smaller mode, in which case the canonical type is the | |
1604 | sign-appropriate type corresponding to that mode. */ | |
1605 | ||
1606 | static void | |
1607 | canonicalize_component_ref (tree *expr_p) | |
1608 | { | |
1609 | tree expr = *expr_p; | |
1610 | tree type; | |
1611 | ||
1612 | if (TREE_CODE (expr) != COMPONENT_REF) | |
1613 | abort (); | |
1614 | ||
1615 | if (INTEGRAL_TYPE_P (TREE_TYPE (expr))) | |
1616 | type = TREE_TYPE (get_unwidened (expr, NULL_TREE)); | |
1617 | else | |
1618 | type = TREE_TYPE (TREE_OPERAND (expr, 1)); | |
1619 | ||
1620 | if (TREE_TYPE (expr) != type) | |
1621 | { | |
1622 | tree old_type = TREE_TYPE (expr); | |
1623 | ||
1624 | /* Set the type of the COMPONENT_REF to the underlying type. */ | |
1625 | TREE_TYPE (expr) = type; | |
1626 | ||
1627 | /* And wrap the whole thing inside a NOP_EXPR. */ | |
1628 | expr = build1 (NOP_EXPR, old_type, expr); | |
1629 | ||
1630 | *expr_p = expr; | |
1631 | } | |
1632 | } | |
1633 | ||
1634 | /* If a NOP conversion is changing a pointer to array of foo to a pointer | |
44de5aeb RK |
1635 | to foo, embed that change in the ADDR_EXPR by converting |
1636 | T array[U]; | |
1637 | (T *)&array | |
6de9cd9a | 1638 | ==> |
44de5aeb RK |
1639 | &array[L] |
1640 | where L is the lower bound. Only do this for constant lower bound since | |
1641 | we have no place to put any statements made during gimplification of | |
1642 | the lower bound. */ | |
6de9cd9a DN |
1643 | |
1644 | static void | |
44de5aeb | 1645 | canonicalize_addr_expr (tree *expr_p) |
6de9cd9a DN |
1646 | { |
1647 | tree expr = *expr_p; | |
1648 | tree ctype = TREE_TYPE (expr); | |
1649 | tree addr_expr = TREE_OPERAND (expr, 0); | |
1650 | tree atype = TREE_TYPE (addr_expr); | |
1651 | tree dctype, datype, ddatype, otype, obj_expr; | |
1652 | ||
1653 | /* Both cast and addr_expr types should be pointers. */ | |
1654 | if (!POINTER_TYPE_P (ctype) || !POINTER_TYPE_P (atype)) | |
1655 | return; | |
1656 | ||
1657 | /* The addr_expr type should be a pointer to an array. */ | |
1658 | datype = TREE_TYPE (atype); | |
1659 | if (TREE_CODE (datype) != ARRAY_TYPE) | |
1660 | return; | |
1661 | ||
1662 | /* Both cast and addr_expr types should address the same object type. */ | |
1663 | dctype = TREE_TYPE (ctype); | |
1664 | ddatype = TREE_TYPE (datype); | |
1665 | if (!lang_hooks.types_compatible_p (ddatype, dctype)) | |
1666 | return; | |
1667 | ||
1668 | /* The addr_expr and the object type should match. */ | |
1669 | obj_expr = TREE_OPERAND (addr_expr, 0); | |
1670 | otype = TREE_TYPE (obj_expr); | |
1671 | if (!lang_hooks.types_compatible_p (otype, datype)) | |
1672 | return; | |
1673 | ||
44de5aeb RK |
1674 | /* The lower bound and element sizes must be constant. */ |
1675 | if (TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST | |
1676 | || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype)) | |
1677 | || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST) | |
1678 | return; | |
1679 | ||
6de9cd9a | 1680 | /* All checks succeeded. Build a new node to merge the cast. */ |
44de5aeb RK |
1681 | *expr_p = build4 (ARRAY_REF, dctype, obj_expr, |
1682 | TYPE_MIN_VALUE (TYPE_DOMAIN (datype)), | |
1683 | TYPE_MIN_VALUE (TYPE_DOMAIN (datype)), | |
1684 | size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (dctype), | |
1685 | size_int (TYPE_ALIGN (dctype) | |
1686 | / BITS_PER_UNIT))); | |
1687 | *expr_p = build1 (ADDR_EXPR, ctype, *expr_p); | |
6de9cd9a DN |
1688 | } |
1689 | ||
1690 | /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions | |
1691 | underneath as appropriate. */ | |
1692 | ||
1693 | static enum gimplify_status | |
1694 | gimplify_conversion (tree *expr_p) | |
1695 | { | |
1696 | /* Strip away as many useless type conversions as possible | |
1697 | at the toplevel. */ | |
1698 | STRIP_USELESS_TYPE_CONVERSION (*expr_p); | |
1699 | ||
1700 | /* If we still have a conversion at the toplevel, then strip | |
1701 | away all but the outermost conversion. */ | |
1702 | if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR) | |
1703 | { | |
1704 | STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0)); | |
1705 | ||
1706 | /* And remove the outermost conversion if it's useless. */ | |
1707 | if (tree_ssa_useless_type_conversion (*expr_p)) | |
1708 | *expr_p = TREE_OPERAND (*expr_p, 0); | |
1709 | } | |
1710 | ||
1711 | /* If we still have a conversion at the toplevel, | |
1712 | then canonicalize some constructs. */ | |
1713 | if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR) | |
1714 | { | |
1715 | tree sub = TREE_OPERAND (*expr_p, 0); | |
1716 | ||
1717 | /* If a NOP conversion is changing the type of a COMPONENT_REF | |
1718 | expression, then canonicalize its type now in order to expose more | |
1719 | redundant conversions. */ | |
1720 | if (TREE_CODE (sub) == COMPONENT_REF) | |
1721 | canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0)); | |
1722 | ||
1723 | /* If a NOP conversion is changing a pointer to array of foo | |
1724 | to a pointer to foo, embed that change in the ADDR_EXPR. */ | |
1725 | else if (TREE_CODE (sub) == ADDR_EXPR) | |
1726 | canonicalize_addr_expr (expr_p); | |
1727 | } | |
1728 | ||
1729 | return GS_OK; | |
1730 | } | |
1731 | ||
1732 | /* Reduce MIN/MAX_EXPR to a COND_EXPR for further gimplification. */ | |
1733 | ||
1734 | static enum gimplify_status | |
1735 | gimplify_minimax_expr (tree *expr_p, tree *pre_p, tree *post_p) | |
1736 | { | |
1737 | tree op1 = TREE_OPERAND (*expr_p, 0); | |
1738 | tree op2 = TREE_OPERAND (*expr_p, 1); | |
1739 | enum tree_code code; | |
1740 | enum gimplify_status r0, r1; | |
1741 | ||
1742 | if (TREE_CODE (*expr_p) == MIN_EXPR) | |
1743 | code = LE_EXPR; | |
1744 | else | |
1745 | code = GE_EXPR; | |
1746 | ||
1747 | r0 = gimplify_expr (&op1, pre_p, post_p, is_gimple_val, fb_rvalue); | |
1748 | r1 = gimplify_expr (&op2, pre_p, post_p, is_gimple_val, fb_rvalue); | |
1749 | ||
1750 | *expr_p = build (COND_EXPR, TREE_TYPE (*expr_p), | |
1751 | build (code, boolean_type_node, op1, op2), | |
1752 | op1, op2); | |
1753 | ||
1754 | if (r0 == GS_ERROR || r1 == GS_ERROR) | |
1755 | return GS_ERROR; | |
1756 | else | |
1757 | return GS_OK; | |
1758 | } | |
1759 | ||
44de5aeb | 1760 | /* Subroutine of gimplify_compound_lval. |
6de9cd9a DN |
1761 | Converts an ARRAY_REF to the equivalent *(&array + offset) form. */ |
1762 | ||
1763 | static enum gimplify_status | |
1764 | gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p) | |
1765 | { | |
1766 | tree array = TREE_OPERAND (*expr_p, 0); | |
1767 | tree arrtype = TREE_TYPE (array); | |
1768 | tree elttype = TREE_TYPE (arrtype); | |
44de5aeb | 1769 | tree size = array_ref_element_size (*expr_p); |
6de9cd9a DN |
1770 | tree ptrtype = build_pointer_type (elttype); |
1771 | enum tree_code add_code = PLUS_EXPR; | |
1772 | tree idx = TREE_OPERAND (*expr_p, 1); | |
44de5aeb RK |
1773 | tree minidx = unshare_expr (array_ref_low_bound (*expr_p)); |
1774 | tree offset, addr, result; | |
6de9cd9a DN |
1775 | enum gimplify_status ret; |
1776 | ||
1777 | /* If the array domain does not start at zero, apply the offset. */ | |
44de5aeb | 1778 | if (!integer_zerop (minidx)) |
6de9cd9a | 1779 | { |
44de5aeb RK |
1780 | idx = convert (TREE_TYPE (minidx), idx); |
1781 | idx = fold (build (MINUS_EXPR, TREE_TYPE (minidx), idx, minidx)); | |
6de9cd9a | 1782 | } |
44de5aeb | 1783 | |
6de9cd9a DN |
1784 | /* If the index is negative -- a technically invalid situation now |
1785 | that we've biased the index back to zero -- then casting it to | |
1786 | unsigned has ill effects. In particular, -1*4U/4U != -1. | |
1787 | Represent this as a subtraction of a positive rather than addition | |
1788 | of a negative. This will prevent any conversion back to ARRAY_REF | |
1789 | from getting the wrong results from the division. */ | |
1790 | if (TREE_CODE (idx) == INTEGER_CST && tree_int_cst_sgn (idx) < 0) | |
1791 | { | |
1792 | idx = fold (build1 (NEGATE_EXPR, TREE_TYPE (idx), idx)); | |
1793 | add_code = MINUS_EXPR; | |
1794 | } | |
1795 | ||
1796 | /* Pointer arithmetic must be done in sizetype. */ | |
44de5aeb | 1797 | idx = fold_convert (sizetype, idx); |
6de9cd9a DN |
1798 | |
1799 | /* Convert the index to a byte offset. */ | |
1800 | offset = size_binop (MULT_EXPR, size, idx); | |
1801 | ||
1802 | ret = gimplify_expr (&array, pre_p, post_p, is_gimple_min_lval, fb_lvalue); | |
1803 | if (ret == GS_ERROR) | |
1804 | return ret; | |
1805 | ||
cd3ce9b4 | 1806 | addr = build_fold_addr_expr_with_type (array, ptrtype); |
6de9cd9a DN |
1807 | result = fold (build (add_code, ptrtype, addr, offset)); |
1808 | *expr_p = build1 (INDIRECT_REF, elttype, result); | |
1809 | ||
1810 | return GS_OK; | |
1811 | } | |
1812 | ||
44de5aeb RK |
1813 | /* Build an expression for the address of T. Folds away INDIRECT_REF to |
1814 | avoid confusing the gimplify process. */ | |
1815 | ||
1816 | static tree | |
1817 | build_addr_expr_with_type (tree t, tree ptrtype) | |
1818 | { | |
1819 | if (TREE_CODE (t) == INDIRECT_REF) | |
1820 | { | |
1821 | t = TREE_OPERAND (t, 0); | |
1822 | if (TREE_TYPE (t) != ptrtype) | |
1823 | t = build1 (NOP_EXPR, ptrtype, t); | |
1824 | } | |
1825 | else | |
1826 | { | |
1827 | tree base = t; | |
1828 | ||
1829 | if (TREE_CODE (base) == REALPART_EXPR | |
1830 | || TREE_CODE (base) == IMAGPART_EXPR) | |
1831 | base = TREE_OPERAND (base, 0); | |
1832 | else | |
1833 | while (handled_component_p (base)) | |
1834 | base = TREE_OPERAND (base, 0); | |
1835 | ||
1836 | if (DECL_P (base)) | |
1837 | TREE_ADDRESSABLE (base) = 1; | |
1838 | ||
1839 | t = build1 (ADDR_EXPR, ptrtype, t); | |
1840 | } | |
1841 | ||
1842 | return t; | |
1843 | } | |
1844 | ||
1845 | static tree | |
1846 | build_addr_expr (tree t) | |
1847 | { | |
1848 | return build_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t))); | |
1849 | } | |
1850 | ||
6de9cd9a DN |
1851 | /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR |
1852 | node pointed by EXPR_P. | |
1853 | ||
1854 | compound_lval | |
1855 | : min_lval '[' val ']' | |
1856 | | min_lval '.' ID | |
1857 | | compound_lval '[' val ']' | |
1858 | | compound_lval '.' ID | |
1859 | ||
1860 | This is not part of the original SIMPLE definition, which separates | |
1861 | array and member references, but it seems reasonable to handle them | |
1862 | together. Also, this way we don't run into problems with union | |
1863 | aliasing; gcc requires that for accesses through a union to alias, the | |
1864 | union reference must be explicit, which was not always the case when we | |
1865 | were splitting up array and member refs. | |
1866 | ||
1867 | PRE_P points to the list where side effects that must happen before | |
1868 | *EXPR_P should be stored. | |
1869 | ||
1870 | POST_P points to the list where side effects that must happen after | |
1871 | *EXPR_P should be stored. */ | |
1872 | ||
1873 | static enum gimplify_status | |
1874 | gimplify_compound_lval (tree *expr_p, tree *pre_p, | |
44de5aeb | 1875 | tree *post_p, bool want_lvalue) |
6de9cd9a DN |
1876 | { |
1877 | tree *p; | |
6de9cd9a | 1878 | varray_type stack; |
44de5aeb | 1879 | enum gimplify_status ret = GS_OK, tret; |
6de9cd9a DN |
1880 | |
1881 | #if defined ENABLE_CHECKING | |
1882 | if (TREE_CODE (*expr_p) != ARRAY_REF | |
44de5aeb | 1883 | && TREE_CODE (*expr_p) != ARRAY_RANGE_REF |
6de9cd9a | 1884 | && TREE_CODE (*expr_p) != COMPONENT_REF |
44de5aeb | 1885 | && TREE_CODE (*expr_p) != BIT_FIELD_REF |
6de9cd9a DN |
1886 | && TREE_CODE (*expr_p) != REALPART_EXPR |
1887 | && TREE_CODE (*expr_p) != IMAGPART_EXPR) | |
1888 | abort (); | |
1889 | #endif | |
1890 | ||
6de9cd9a DN |
1891 | /* Create a stack of the subexpressions so later we can walk them in |
1892 | order from inner to outer. */ | |
1893 | VARRAY_TREE_INIT (stack, 10, "stack"); | |
1894 | ||
44de5aeb RK |
1895 | /* We can either handle one REALPART_EXPR or IMAGEPART_EXPR or |
1896 | nest of handled components. */ | |
1897 | if (TREE_CODE (*expr_p) == REALPART_EXPR | |
1898 | || TREE_CODE (*expr_p) == IMAGPART_EXPR) | |
1899 | p = &TREE_OPERAND (*expr_p, 0); | |
1900 | else | |
1901 | for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0)) | |
6de9cd9a | 1902 | VARRAY_PUSH_TREE (stack, *p); |
6de9cd9a | 1903 | |
44de5aeb RK |
1904 | /* Now STACK is a stack of pointers to all the refs we've walked through |
1905 | and P points to the innermost expression. | |
6de9cd9a | 1906 | |
44de5aeb RK |
1907 | Process each of the outer nodes from left to right, then gimplify the |
1908 | base. We need to do it in this order so that PLACEHOLDER_EXPRs | |
1909 | can be resolved. */ | |
6de9cd9a DN |
1910 | for (; VARRAY_ACTIVE_SIZE (stack) > 0; ) |
1911 | { | |
1912 | tree t = VARRAY_TOP_TREE (stack); | |
44de5aeb RK |
1913 | |
1914 | if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) | |
6de9cd9a | 1915 | { |
44de5aeb RK |
1916 | /* Gimplify the dimension. |
1917 | Temporary fix for gcc.c-torture/execute/20040313-1.c. | |
6de9cd9a DN |
1918 | Gimplify non-constant array indices into a temporary |
1919 | variable. | |
1920 | FIXME - The real fix is to gimplify post-modify | |
1921 | expressions into a minimal gimple lvalue. However, that | |
1922 | exposes bugs in alias analysis. The alias analyzer does | |
1923 | not handle &PTR->FIELD very well. Will fix after the | |
1924 | branch is merged into mainline (dnovillo 2004-05-03). */ | |
1925 | if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))) | |
1926 | { | |
1927 | tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, | |
1928 | is_gimple_tmp_var, fb_rvalue); | |
44de5aeb RK |
1929 | ret = MIN (ret, tret); |
1930 | } | |
1931 | ||
1932 | /* Gimplify the low bound and element type size and put them into | |
1933 | the ARRAY_REF. If these values are set, they have already been | |
1934 | gimplified. */ | |
1935 | if (!TREE_OPERAND (t, 2)) | |
1936 | { | |
a7cc468a RH |
1937 | tree low = unshare_expr (array_ref_low_bound (t)); |
1938 | if (!is_gimple_min_invariant (low)) | |
44de5aeb | 1939 | { |
a7cc468a | 1940 | TREE_OPERAND (t, 2) = low; |
44de5aeb RK |
1941 | tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, |
1942 | is_gimple_tmp_var, fb_rvalue); | |
1943 | ret = MIN (ret, tret); | |
1944 | } | |
1945 | } | |
1946 | ||
1947 | if (!TREE_OPERAND (t, 3)) | |
1948 | { | |
1949 | tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))); | |
1950 | tree elmt_size = unshare_expr (array_ref_element_size (t)); | |
1951 | tree factor = size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT); | |
1952 | ||
1953 | /* Divide the element size by the alignment of the element | |
1954 | type (above). */ | |
1955 | elmt_size = size_binop (EXACT_DIV_EXPR, elmt_size, factor); | |
1956 | ||
a7cc468a | 1957 | if (!is_gimple_min_invariant (elmt_size)) |
44de5aeb | 1958 | { |
a7cc468a | 1959 | TREE_OPERAND (t, 3) = elmt_size; |
44de5aeb RK |
1960 | tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, |
1961 | is_gimple_tmp_var, fb_rvalue); | |
1962 | ret = MIN (ret, tret); | |
1963 | } | |
6de9cd9a DN |
1964 | } |
1965 | } | |
44de5aeb RK |
1966 | else if (TREE_CODE (t) == COMPONENT_REF) |
1967 | { | |
1968 | /* Set the field offset into T and gimplify it. */ | |
1969 | if (!TREE_OPERAND (t, 2)) | |
1970 | { | |
1971 | tree offset = unshare_expr (component_ref_field_offset (t)); | |
1972 | tree field = TREE_OPERAND (t, 1); | |
1973 | tree factor | |
1974 | = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT); | |
1975 | ||
1976 | /* Divide the offset by its alignment. */ | |
1977 | offset = size_binop (EXACT_DIV_EXPR, offset, factor); | |
1978 | ||
a7cc468a | 1979 | if (!is_gimple_min_invariant (offset)) |
44de5aeb | 1980 | { |
a7cc468a | 1981 | TREE_OPERAND (t, 2) = offset; |
44de5aeb RK |
1982 | tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, |
1983 | is_gimple_tmp_var, fb_rvalue); | |
1984 | ret = MIN (ret, tret); | |
1985 | } | |
1986 | } | |
1987 | } | |
1988 | else if (TREE_CODE (t) == BIT_FIELD_REF) | |
1989 | { | |
1990 | tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, | |
1991 | is_gimple_val, fb_rvalue); | |
1992 | ret = MIN (ret, tret); | |
1993 | tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, | |
1994 | is_gimple_val, fb_rvalue); | |
1995 | ret = MIN (ret, tret); | |
1996 | } | |
1997 | ||
6de9cd9a DN |
1998 | recalculate_side_effects (t); |
1999 | VARRAY_POP (stack); | |
2000 | } | |
2001 | ||
44de5aeb RK |
2002 | tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval, |
2003 | want_lvalue ? fb_lvalue : fb_rvalue); | |
2004 | ret = MIN (ret, tret); | |
2005 | ||
6de9cd9a DN |
2006 | /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */ |
2007 | if (!want_lvalue && TREE_CODE (*expr_p) == COMPONENT_REF) | |
2008 | { | |
2009 | canonicalize_component_ref (expr_p); | |
2010 | ret = MIN (ret, GS_OK); | |
2011 | } | |
2012 | ||
2013 | return ret; | |
2014 | } | |
2015 | ||
6de9cd9a DN |
2016 | /* Gimplify the self modifying expression pointed by EXPR_P (++, --, +=, -=). |
2017 | ||
2018 | PRE_P points to the list where side effects that must happen before | |
2019 | *EXPR_P should be stored. | |
2020 | ||
2021 | POST_P points to the list where side effects that must happen after | |
2022 | *EXPR_P should be stored. | |
2023 | ||
2024 | WANT_VALUE is nonzero iff we want to use the value of this expression | |
2025 | in another expression. */ | |
2026 | ||
2027 | static enum gimplify_status | |
2028 | gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p, | |
44de5aeb | 2029 | bool want_value) |
6de9cd9a DN |
2030 | { |
2031 | enum tree_code code; | |
2032 | tree lhs, lvalue, rhs, t1; | |
2033 | bool postfix; | |
2034 | enum tree_code arith_code; | |
2035 | enum gimplify_status ret; | |
2036 | ||
2037 | code = TREE_CODE (*expr_p); | |
2038 | ||
2039 | #if defined ENABLE_CHECKING | |
2040 | if (code != POSTINCREMENT_EXPR | |
2041 | && code != POSTDECREMENT_EXPR | |
2042 | && code != PREINCREMENT_EXPR | |
2043 | && code != PREDECREMENT_EXPR) | |
2044 | abort (); | |
2045 | #endif | |
2046 | ||
2047 | /* Prefix or postfix? */ | |
2048 | if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) | |
2049 | /* Faster to treat as prefix if result is not used. */ | |
2050 | postfix = want_value; | |
2051 | else | |
2052 | postfix = false; | |
2053 | ||
2054 | /* Add or subtract? */ | |
2055 | if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) | |
2056 | arith_code = PLUS_EXPR; | |
2057 | else | |
2058 | arith_code = MINUS_EXPR; | |
2059 | ||
2060 | /* Gimplify the LHS into a GIMPLE lvalue. */ | |
2061 | lvalue = TREE_OPERAND (*expr_p, 0); | |
2062 | ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue); | |
2063 | if (ret == GS_ERROR) | |
2064 | return ret; | |
2065 | ||
2066 | /* Extract the operands to the arithmetic operation. */ | |
2067 | lhs = lvalue; | |
2068 | rhs = TREE_OPERAND (*expr_p, 1); | |
2069 | ||
2070 | /* For postfix operator, we evaluate the LHS to an rvalue and then use | |
2071 | that as the result value and in the postqueue operation. */ | |
2072 | if (postfix) | |
2073 | { | |
2074 | ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue); | |
2075 | if (ret == GS_ERROR) | |
2076 | return ret; | |
2077 | } | |
2078 | ||
2079 | t1 = build (arith_code, TREE_TYPE (*expr_p), lhs, rhs); | |
2080 | t1 = build (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1); | |
2081 | ||
2082 | if (postfix) | |
2083 | { | |
2084 | gimplify_stmt (&t1); | |
2085 | append_to_statement_list (t1, post_p); | |
2086 | *expr_p = lhs; | |
2087 | return GS_ALL_DONE; | |
2088 | } | |
2089 | else | |
2090 | { | |
2091 | *expr_p = t1; | |
2092 | return GS_OK; | |
2093 | } | |
2094 | } | |
2095 | ||
2096 | /* Gimplify the CALL_EXPR node pointed by EXPR_P. | |
2097 | ||
2098 | call_expr | |
2099 | : ID '(' arglist ')' | |
2100 | ||
2101 | arglist | |
2102 | : arglist ',' val | |
2103 | | val | |
2104 | ||
2105 | PRE_P points to the list where side effects that must happen before | |
2106 | *EXPR_P should be stored. */ | |
2107 | ||
2108 | static enum gimplify_status | |
2109 | gimplify_call_expr (tree *expr_p, tree *pre_p, bool (*gimple_test_f) (tree)) | |
2110 | { | |
2111 | tree decl; | |
2112 | tree arglist; | |
2113 | enum gimplify_status ret; | |
2114 | ||
2115 | #if defined ENABLE_CHECKING | |
2116 | if (TREE_CODE (*expr_p) != CALL_EXPR) | |
2117 | abort (); | |
2118 | #endif | |
2119 | ||
2120 | /* For reliable diagnostics during inlining, it is necessary that | |
2121 | every call_expr be annotated with file and line. */ | |
2122 | if (!EXPR_LOCUS (*expr_p)) | |
2123 | annotate_with_locus (*expr_p, input_location); | |
2124 | ||
2125 | /* This may be a call to a builtin function. | |
2126 | ||
2127 | Builtin function calls may be transformed into different | |
2128 | (and more efficient) builtin function calls under certain | |
2129 | circumstances. Unfortunately, gimplification can muck things | |
2130 | up enough that the builtin expanders are not aware that certain | |
2131 | transformations are still valid. | |
2132 | ||
2133 | So we attempt transformation/gimplification of the call before | |
2134 | we gimplify the CALL_EXPR. At this time we do not manage to | |
2135 | transform all calls in the same manner as the expanders do, but | |
2136 | we do transform most of them. */ | |
2137 | decl = get_callee_fndecl (*expr_p); | |
2138 | if (decl && DECL_BUILT_IN (decl)) | |
2139 | { | |
2140 | tree new; | |
2141 | ||
2142 | /* If it is allocation of stack, record the need to restore the memory | |
2143 | when the enclosing bind_expr is exited. */ | |
2144 | if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_ALLOC) | |
2145 | gimplify_ctxp->save_stack = true; | |
2146 | ||
2147 | /* If it is restore of the stack, reset it, since it means we are | |
2148 | regimplifying the bind_expr. Note that we use the fact that | |
2149 | for try_finally_expr, try part is processed first. */ | |
2150 | if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_RESTORE) | |
2151 | gimplify_ctxp->save_stack = false; | |
2152 | ||
2153 | new = simplify_builtin (*expr_p, gimple_test_f == is_gimple_stmt); | |
2154 | ||
2155 | if (new && new != *expr_p) | |
2156 | { | |
2157 | /* There was a transformation of this call which computes the | |
2158 | same value, but in a more efficient way. Return and try | |
2159 | again. */ | |
2160 | *expr_p = new; | |
2161 | return GS_OK; | |
2162 | } | |
2163 | } | |
2164 | ||
2165 | /* There is a sequence point before the call, so any side effects in | |
2166 | the calling expression must occur before the actual call. Force | |
2167 | gimplify_expr to use an internal post queue. */ | |
2168 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL, | |
0f59171d | 2169 | is_gimple_call_addr, fb_rvalue); |
6de9cd9a DN |
2170 | |
2171 | if (PUSH_ARGS_REVERSED) | |
2172 | TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1)); | |
2173 | for (arglist = TREE_OPERAND (*expr_p, 1); arglist; | |
2174 | arglist = TREE_CHAIN (arglist)) | |
2175 | { | |
2176 | enum gimplify_status t; | |
2177 | ||
2178 | /* There is a sequence point before a function call. Side effects in | |
2179 | the argument list must occur before the actual call. So, when | |
2180 | gimplifying arguments, force gimplify_expr to use an internal | |
2181 | post queue which is then appended to the end of PRE_P. */ | |
2182 | t = gimplify_expr (&TREE_VALUE (arglist), pre_p, NULL, is_gimple_val, | |
2183 | fb_rvalue); | |
2184 | ||
2185 | if (t == GS_ERROR) | |
2186 | ret = GS_ERROR; | |
2187 | } | |
2188 | if (PUSH_ARGS_REVERSED) | |
2189 | TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1)); | |
2190 | ||
2191 | /* Try this again in case gimplification exposed something. */ | |
2192 | if (ret != GS_ERROR && decl && DECL_BUILT_IN (decl)) | |
2193 | { | |
2194 | tree new = simplify_builtin (*expr_p, gimple_test_f == is_gimple_stmt); | |
2195 | ||
2196 | if (new && new != *expr_p) | |
2197 | { | |
2198 | /* There was a transformation of this call which computes the | |
2199 | same value, but in a more efficient way. Return and try | |
2200 | again. */ | |
2201 | *expr_p = new; | |
2202 | return GS_OK; | |
2203 | } | |
2204 | } | |
2205 | ||
2206 | /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its | |
2207 | decl. This allows us to eliminate redundant or useless | |
2208 | calls to "const" functions. */ | |
2209 | if (TREE_CODE (*expr_p) == CALL_EXPR | |
2210 | && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE))) | |
2211 | TREE_SIDE_EFFECTS (*expr_p) = 0; | |
2212 | ||
2213 | return ret; | |
2214 | } | |
2215 | ||
2216 | /* Handle shortcut semantics in the predicate operand of a COND_EXPR by | |
2217 | rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs. | |
2218 | ||
2219 | TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the | |
2220 | condition is true or false, respectively. If null, we should generate | |
2221 | our own to skip over the evaluation of this specific expression. | |
2222 | ||
2223 | This function is the tree equivalent of do_jump. | |
2224 | ||
2225 | shortcut_cond_r should only be called by shortcut_cond_expr. */ | |
2226 | ||
2227 | static tree | |
2228 | shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p) | |
2229 | { | |
2230 | tree local_label = NULL_TREE; | |
2231 | tree t, expr = NULL; | |
2232 | ||
2233 | /* OK, it's not a simple case; we need to pull apart the COND_EXPR to | |
2234 | retain the shortcut semantics. Just insert the gotos here; | |
2235 | shortcut_cond_expr will append the real blocks later. */ | |
2236 | if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR) | |
2237 | { | |
2238 | /* Turn if (a && b) into | |
2239 | ||
2240 | if (a); else goto no; | |
2241 | if (b) goto yes; else goto no; | |
2242 | (no:) */ | |
2243 | ||
2244 | if (false_label_p == NULL) | |
2245 | false_label_p = &local_label; | |
2246 | ||
2247 | t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p); | |
2248 | append_to_statement_list (t, &expr); | |
2249 | ||
2250 | t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, | |
2251 | false_label_p); | |
2252 | append_to_statement_list (t, &expr); | |
2253 | } | |
2254 | else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR) | |
2255 | { | |
2256 | /* Turn if (a || b) into | |
2257 | ||
2258 | if (a) goto yes; | |
2259 | if (b) goto yes; else goto no; | |
2260 | (yes:) */ | |
2261 | ||
2262 | if (true_label_p == NULL) | |
2263 | true_label_p = &local_label; | |
2264 | ||
2265 | t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL); | |
2266 | append_to_statement_list (t, &expr); | |
2267 | ||
2268 | t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, | |
2269 | false_label_p); | |
2270 | append_to_statement_list (t, &expr); | |
2271 | } | |
2272 | else if (TREE_CODE (pred) == COND_EXPR) | |
2273 | { | |
2274 | /* As long as we're messing with gotos, turn if (a ? b : c) into | |
2275 | if (a) | |
2276 | if (b) goto yes; else goto no; | |
2277 | else | |
2278 | if (c) goto yes; else goto no; */ | |
2279 | expr = build (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0), | |
2280 | shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, | |
2281 | false_label_p), | |
2282 | shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p, | |
2283 | false_label_p)); | |
2284 | } | |
2285 | else | |
2286 | { | |
2287 | expr = build (COND_EXPR, void_type_node, pred, | |
2288 | build_and_jump (true_label_p), | |
2289 | build_and_jump (false_label_p)); | |
2290 | } | |
2291 | ||
2292 | if (local_label) | |
2293 | { | |
2294 | t = build1 (LABEL_EXPR, void_type_node, local_label); | |
2295 | append_to_statement_list (t, &expr); | |
2296 | } | |
2297 | ||
2298 | return expr; | |
2299 | } | |
2300 | ||
2301 | static tree | |
2302 | shortcut_cond_expr (tree expr) | |
2303 | { | |
2304 | tree pred = TREE_OPERAND (expr, 0); | |
2305 | tree then_ = TREE_OPERAND (expr, 1); | |
2306 | tree else_ = TREE_OPERAND (expr, 2); | |
2307 | tree true_label, false_label, end_label, t; | |
2308 | tree *true_label_p; | |
2309 | tree *false_label_p; | |
2310 | bool emit_end, emit_false; | |
65355d53 RH |
2311 | bool then_se = then_ && TREE_SIDE_EFFECTS (then_); |
2312 | bool else_se = else_ && TREE_SIDE_EFFECTS (else_); | |
6de9cd9a DN |
2313 | |
2314 | /* First do simple transformations. */ | |
65355d53 | 2315 | if (!else_se) |
6de9cd9a DN |
2316 | { |
2317 | /* If there is no 'else', turn (a && b) into if (a) if (b). */ | |
2318 | while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR) | |
2319 | { | |
2320 | TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); | |
2321 | then_ = shortcut_cond_expr (expr); | |
2322 | pred = TREE_OPERAND (pred, 0); | |
65355d53 | 2323 | expr = build (COND_EXPR, void_type_node, pred, then_, NULL_TREE); |
6de9cd9a DN |
2324 | } |
2325 | } | |
65355d53 | 2326 | if (!then_se) |
6de9cd9a DN |
2327 | { |
2328 | /* If there is no 'then', turn | |
2329 | if (a || b); else d | |
2330 | into | |
2331 | if (a); else if (b); else d. */ | |
2332 | while (TREE_CODE (pred) == TRUTH_ORIF_EXPR) | |
2333 | { | |
2334 | TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); | |
2335 | else_ = shortcut_cond_expr (expr); | |
2336 | pred = TREE_OPERAND (pred, 0); | |
65355d53 | 2337 | expr = build (COND_EXPR, void_type_node, pred, NULL_TREE, else_); |
6de9cd9a DN |
2338 | } |
2339 | } | |
2340 | ||
2341 | /* If we're done, great. */ | |
2342 | if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR | |
2343 | && TREE_CODE (pred) != TRUTH_ORIF_EXPR) | |
2344 | return expr; | |
2345 | ||
2346 | /* Otherwise we need to mess with gotos. Change | |
2347 | if (a) c; else d; | |
2348 | to | |
2349 | if (a); else goto no; | |
2350 | c; goto end; | |
2351 | no: d; end: | |
2352 | and recursively gimplify the condition. */ | |
2353 | ||
2354 | true_label = false_label = end_label = NULL_TREE; | |
2355 | ||
2356 | /* If our arms just jump somewhere, hijack those labels so we don't | |
2357 | generate jumps to jumps. */ | |
2358 | ||
65355d53 RH |
2359 | if (then_ |
2360 | && TREE_CODE (then_) == GOTO_EXPR | |
6de9cd9a DN |
2361 | && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL) |
2362 | { | |
2363 | true_label = GOTO_DESTINATION (then_); | |
65355d53 RH |
2364 | then_ = NULL; |
2365 | then_se = false; | |
6de9cd9a DN |
2366 | } |
2367 | ||
65355d53 RH |
2368 | if (else_ |
2369 | && TREE_CODE (else_) == GOTO_EXPR | |
6de9cd9a DN |
2370 | && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL) |
2371 | { | |
2372 | false_label = GOTO_DESTINATION (else_); | |
65355d53 RH |
2373 | else_ = NULL; |
2374 | else_se = false; | |
6de9cd9a DN |
2375 | } |
2376 | ||
9cf737f8 | 2377 | /* If we aren't hijacking a label for the 'then' branch, it falls through. */ |
6de9cd9a DN |
2378 | if (true_label) |
2379 | true_label_p = &true_label; | |
2380 | else | |
2381 | true_label_p = NULL; | |
2382 | ||
2383 | /* The 'else' branch also needs a label if it contains interesting code. */ | |
65355d53 | 2384 | if (false_label || else_se) |
6de9cd9a DN |
2385 | false_label_p = &false_label; |
2386 | else | |
2387 | false_label_p = NULL; | |
2388 | ||
2389 | /* If there was nothing else in our arms, just forward the label(s). */ | |
65355d53 | 2390 | if (!then_se && !else_se) |
6de9cd9a DN |
2391 | return shortcut_cond_r (pred, true_label_p, false_label_p); |
2392 | ||
2393 | /* If our last subexpression already has a terminal label, reuse it. */ | |
65355d53 | 2394 | if (else_se) |
6de9cd9a | 2395 | expr = expr_last (else_); |
65355d53 | 2396 | else if (then_se) |
6de9cd9a | 2397 | expr = expr_last (then_); |
65355d53 RH |
2398 | else |
2399 | expr = NULL; | |
2400 | if (expr && TREE_CODE (expr) == LABEL_EXPR) | |
6de9cd9a DN |
2401 | end_label = LABEL_EXPR_LABEL (expr); |
2402 | ||
2403 | /* If we don't care about jumping to the 'else' branch, jump to the end | |
2404 | if the condition is false. */ | |
2405 | if (!false_label_p) | |
2406 | false_label_p = &end_label; | |
2407 | ||
2408 | /* We only want to emit these labels if we aren't hijacking them. */ | |
2409 | emit_end = (end_label == NULL_TREE); | |
2410 | emit_false = (false_label == NULL_TREE); | |
2411 | ||
2412 | pred = shortcut_cond_r (pred, true_label_p, false_label_p); | |
2413 | ||
2414 | expr = NULL; | |
2415 | append_to_statement_list (pred, &expr); | |
2416 | ||
2417 | append_to_statement_list (then_, &expr); | |
65355d53 | 2418 | if (else_se) |
6de9cd9a DN |
2419 | { |
2420 | t = build_and_jump (&end_label); | |
2421 | append_to_statement_list (t, &expr); | |
2422 | if (emit_false) | |
2423 | { | |
2424 | t = build1 (LABEL_EXPR, void_type_node, false_label); | |
2425 | append_to_statement_list (t, &expr); | |
2426 | } | |
2427 | append_to_statement_list (else_, &expr); | |
2428 | } | |
2429 | if (emit_end && end_label) | |
2430 | { | |
2431 | t = build1 (LABEL_EXPR, void_type_node, end_label); | |
2432 | append_to_statement_list (t, &expr); | |
2433 | } | |
2434 | ||
2435 | return expr; | |
2436 | } | |
2437 | ||
2438 | /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */ | |
2439 | ||
2440 | static tree | |
2441 | gimple_boolify (tree expr) | |
2442 | { | |
2443 | tree type = TREE_TYPE (expr); | |
2444 | ||
2445 | if (TREE_CODE (type) == BOOLEAN_TYPE) | |
2446 | return expr; | |
2447 | ||
2448 | /* If this is the predicate of a COND_EXPR, it might not even be a | |
2449 | truthvalue yet. */ | |
673fda6b | 2450 | expr = lang_hooks.truthvalue_conversion (expr); |
6de9cd9a DN |
2451 | |
2452 | switch (TREE_CODE (expr)) | |
2453 | { | |
2454 | case TRUTH_AND_EXPR: | |
2455 | case TRUTH_OR_EXPR: | |
2456 | case TRUTH_XOR_EXPR: | |
2457 | case TRUTH_ANDIF_EXPR: | |
2458 | case TRUTH_ORIF_EXPR: | |
2459 | /* Also boolify the arguments of truth exprs. */ | |
2460 | TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1)); | |
2461 | /* FALLTHRU */ | |
2462 | ||
2463 | case TRUTH_NOT_EXPR: | |
2464 | TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0)); | |
2465 | /* FALLTHRU */ | |
2466 | ||
2467 | case EQ_EXPR: case NE_EXPR: | |
2468 | case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR: | |
2469 | /* These expressions always produce boolean results. */ | |
2470 | TREE_TYPE (expr) = boolean_type_node; | |
2471 | return expr; | |
2472 | ||
2473 | default: | |
2474 | /* Other expressions that get here must have boolean values, but | |
2475 | might need to be converted to the appropriate mode. */ | |
2476 | return convert (boolean_type_node, expr); | |
2477 | } | |
2478 | } | |
2479 | ||
2480 | /* Convert the conditional expression pointed by EXPR_P '(p) ? a : b;' | |
2481 | into | |
2482 | ||
2483 | if (p) if (p) | |
2484 | t1 = a; a; | |
2485 | else or else | |
2486 | t1 = b; b; | |
2487 | t1; | |
2488 | ||
2489 | The second form is used when *EXPR_P is of type void. | |
2490 | ||
44de5aeb RK |
2491 | TARGET is the tree for T1 above. |
2492 | ||
6de9cd9a DN |
2493 | PRE_P points to the list where side effects that must happen before |
2494 | *EXPR_P should be stored. */ | |
2495 | ||
2496 | static enum gimplify_status | |
2497 | gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target) | |
2498 | { | |
2499 | tree expr = *expr_p; | |
506e2710 | 2500 | tree tmp, type; |
6de9cd9a DN |
2501 | enum gimplify_status ret; |
2502 | ||
506e2710 RH |
2503 | type = TREE_TYPE (expr); |
2504 | if (!type) | |
2505 | TREE_TYPE (expr) = void_type_node; | |
2506 | ||
6de9cd9a DN |
2507 | /* If this COND_EXPR has a value, copy the values into a temporary within |
2508 | the arms. */ | |
506e2710 | 2509 | else if (! VOID_TYPE_P (type)) |
6de9cd9a DN |
2510 | { |
2511 | if (target) | |
2512 | { | |
2513 | tmp = target; | |
2514 | ret = GS_OK; | |
2515 | } | |
2516 | else | |
2517 | { | |
2518 | tmp = create_tmp_var (TREE_TYPE (expr), "iftmp"); | |
2519 | ret = GS_ALL_DONE; | |
2520 | } | |
2521 | ||
2522 | /* Build the then clause, 't1 = a;'. But don't build an assignment | |
2523 | if this branch is void; in C++ it can be, if it's a throw. */ | |
2524 | if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node) | |
2525 | TREE_OPERAND (expr, 1) | |
2526 | = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 1)); | |
2527 | ||
2528 | /* Build the else clause, 't1 = b;'. */ | |
2529 | if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node) | |
2530 | TREE_OPERAND (expr, 2) | |
2531 | = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 2)); | |
2532 | ||
2533 | TREE_TYPE (expr) = void_type_node; | |
2534 | recalculate_side_effects (expr); | |
2535 | ||
2536 | /* Move the COND_EXPR to the prequeue and use the temp in its place. */ | |
2537 | gimplify_stmt (&expr); | |
2538 | append_to_statement_list (expr, pre_p); | |
2539 | *expr_p = tmp; | |
2540 | ||
2541 | return ret; | |
2542 | } | |
2543 | ||
2544 | /* Make sure the condition has BOOLEAN_TYPE. */ | |
2545 | TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0)); | |
2546 | ||
2547 | /* Break apart && and || conditions. */ | |
2548 | if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR | |
2549 | || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR) | |
2550 | { | |
2551 | expr = shortcut_cond_expr (expr); | |
2552 | ||
2553 | if (expr != *expr_p) | |
2554 | { | |
2555 | *expr_p = expr; | |
2556 | ||
2557 | /* We can't rely on gimplify_expr to re-gimplify the expanded | |
2558 | form properly, as cleanups might cause the target labels to be | |
2559 | wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to | |
2560 | set up a conditional context. */ | |
2561 | gimple_push_condition (); | |
2562 | gimplify_stmt (expr_p); | |
2563 | gimple_pop_condition (pre_p); | |
2564 | ||
2565 | return GS_ALL_DONE; | |
2566 | } | |
2567 | } | |
2568 | ||
2569 | /* Now do the normal gimplification. */ | |
2570 | ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, | |
2571 | is_gimple_condexpr, fb_rvalue); | |
2572 | ||
2573 | gimple_push_condition (); | |
2574 | ||
2575 | gimplify_to_stmt_list (&TREE_OPERAND (expr, 1)); | |
2576 | gimplify_to_stmt_list (&TREE_OPERAND (expr, 2)); | |
2577 | recalculate_side_effects (expr); | |
2578 | ||
2579 | gimple_pop_condition (pre_p); | |
2580 | ||
2581 | if (ret == GS_ERROR) | |
2582 | ; | |
2583 | else if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))) | |
2584 | ret = GS_ALL_DONE; | |
2585 | else if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))) | |
2586 | /* Rewrite "if (a); else b" to "if (!a) b" */ | |
2587 | { | |
2588 | TREE_OPERAND (expr, 0) = invert_truthvalue (TREE_OPERAND (expr, 0)); | |
2589 | ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, | |
2590 | is_gimple_condexpr, fb_rvalue); | |
2591 | ||
2592 | tmp = TREE_OPERAND (expr, 1); | |
2593 | TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 2); | |
2594 | TREE_OPERAND (expr, 2) = tmp; | |
2595 | } | |
2596 | else | |
2597 | /* Both arms are empty; replace the COND_EXPR with its predicate. */ | |
2598 | expr = TREE_OPERAND (expr, 0); | |
2599 | ||
2600 | *expr_p = expr; | |
2601 | return ret; | |
2602 | } | |
2603 | ||
2604 | /* Gimplify the MODIFY_EXPR node pointed by EXPR_P. | |
2605 | ||
2606 | modify_expr | |
2607 | : varname '=' rhs | |
2608 | | '*' ID '=' rhs | |
2609 | ||
2610 | PRE_P points to the list where side effects that must happen before | |
2611 | *EXPR_P should be stored. | |
2612 | ||
2613 | POST_P points to the list where side effects that must happen after | |
2614 | *EXPR_P should be stored. | |
2615 | ||
2616 | WANT_VALUE is nonzero iff we want to use the value of this expression | |
2617 | in another expression. */ | |
2618 | ||
2619 | static enum gimplify_status | |
2620 | gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) | |
2621 | { | |
2622 | tree *from_p = &TREE_OPERAND (*expr_p, 1); | |
2623 | tree *to_p = &TREE_OPERAND (*expr_p, 0); | |
44de5aeb | 2624 | enum gimplify_status ret = GS_UNHANDLED; |
6de9cd9a DN |
2625 | |
2626 | #if defined ENABLE_CHECKING | |
2627 | if (TREE_CODE (*expr_p) != MODIFY_EXPR && TREE_CODE (*expr_p) != INIT_EXPR) | |
2628 | abort (); | |
2629 | #endif | |
2630 | ||
2631 | /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer useful. */ | |
2632 | if (TREE_CODE (*expr_p) == INIT_EXPR) | |
2633 | TREE_SET_CODE (*expr_p, MODIFY_EXPR); | |
2634 | ||
44de5aeb RK |
2635 | /* See if any simplifications can be done based on what the RHS is. */ |
2636 | ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p, | |
2637 | want_value); | |
2638 | if (ret != GS_UNHANDLED) | |
6de9cd9a DN |
2639 | return ret; |
2640 | ||
44de5aeb RK |
2641 | /* If the value being copied is of variable width, expose the length |
2642 | if the copy by converting the whole thing to a memcpy. Note that | |
2643 | we need to do this before gimplifying any of the operands | |
2644 | so that we can resolve any PLACEHOLDER_EXPRs in the size. */ | |
2645 | if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST) | |
3a5b9284 | 2646 | { |
44de5aeb RK |
2647 | tree args, t, dest; |
2648 | ||
2649 | t = TYPE_SIZE_UNIT (TREE_TYPE (*to_p)); | |
2650 | t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *to_p); | |
2651 | t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *from_p); | |
2652 | t = unshare_expr (t); | |
2653 | args = tree_cons (NULL, t, NULL); | |
2654 | t = build_fold_addr_expr (*from_p); | |
2655 | args = tree_cons (NULL, t, args); | |
2656 | dest = build_fold_addr_expr (*to_p); | |
2657 | args = tree_cons (NULL, dest, args); | |
2658 | t = implicit_built_in_decls[BUILT_IN_MEMCPY]; | |
2659 | t = build_function_call_expr (t, args); | |
2660 | if (want_value) | |
2661 | { | |
2662 | t = build1 (NOP_EXPR, TREE_TYPE (dest), t); | |
2663 | t = build1 (INDIRECT_REF, TREE_TYPE (*to_p), t); | |
2664 | } | |
2665 | *expr_p = t; | |
2666 | return GS_OK; | |
3a5b9284 | 2667 | } |
6de9cd9a | 2668 | |
44de5aeb RK |
2669 | ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue); |
2670 | if (ret == GS_ERROR) | |
2671 | return ret; | |
6de9cd9a DN |
2672 | |
2673 | ret = gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue); | |
2674 | if (ret == GS_ERROR) | |
2675 | return ret; | |
2676 | ||
44de5aeb RK |
2677 | /* Now see if the above changed *from_p to something we handle specially. */ |
2678 | ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p, | |
2679 | want_value); | |
6de9cd9a DN |
2680 | if (ret != GS_UNHANDLED) |
2681 | return ret; | |
2682 | ||
2683 | /* If the destination is already simple, nothing else needed. */ | |
2684 | if (is_gimple_tmp_var (*to_p)) | |
2685 | ret = GS_ALL_DONE; | |
2686 | else | |
2687 | { | |
2688 | /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto and | |
2689 | the LHS is a user variable, then we need to introduce a temporary. | |
2690 | ie temp = RHS; LHS = temp. | |
2691 | ||
2692 | This way the optimizers can determine that the user variable is | |
2693 | only modified if evaluation of the RHS does not throw. | |
2694 | ||
2695 | FIXME this should be handled by the is_gimple_rhs predicate. */ | |
2696 | ||
3bcb4e37 JM |
2697 | if (aggregate_value_p (TREE_TYPE (*from_p), NULL_TREE)) |
2698 | /* Don't force a temp of a large aggregate type; the copy could be | |
2699 | arbitrarily expensive. Instead we will generate a V_MAY_DEF for | |
2700 | the assignment. */; | |
2701 | else if (TREE_CODE (*from_p) == CALL_EXPR | |
2702 | || (flag_non_call_exceptions && tree_could_trap_p (*from_p)) | |
2703 | /* If we're dealing with a renamable type, either source or dest | |
2704 | must be a renamed variable. */ | |
2705 | || (is_gimple_reg_type (TREE_TYPE (*from_p)) | |
2706 | && !is_gimple_reg (*to_p))) | |
6de9cd9a DN |
2707 | gimplify_expr (from_p, pre_p, post_p, is_gimple_val, fb_rvalue); |
2708 | ||
6de9cd9a DN |
2709 | ret = want_value ? GS_OK : GS_ALL_DONE; |
2710 | } | |
2711 | ||
2712 | if (want_value) | |
2713 | { | |
2714 | append_to_statement_list (*expr_p, pre_p); | |
2715 | *expr_p = *to_p; | |
2716 | } | |
2717 | ||
2718 | return ret; | |
2719 | } | |
2720 | ||
44de5aeb RK |
2721 | /* Subroutine of above to do simplications of MODIFY_EXPRs based on |
2722 | the code of the RHS. We loop for as long as we can do something. */ | |
2723 | ||
2724 | static enum gimplify_status | |
2725 | gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, | |
2726 | tree *post_p, bool want_value) | |
2727 | { | |
2728 | enum gimplify_status ret = GS_OK; | |
2729 | ||
2730 | while (ret != GS_UNHANDLED) | |
2731 | switch (TREE_CODE (*from_p)) | |
2732 | { | |
2733 | case TARGET_EXPR: | |
2734 | { | |
2735 | /* If we are initializing something from a TARGET_EXPR, strip the | |
2736 | TARGET_EXPR and initialize it directly, if possible. This can't | |
2737 | be done if the initializer is void, since that implies that the | |
2738 | temporary is set in some non-trivial way. | |
2739 | ||
2740 | ??? What about code that pulls out the temp and uses it | |
2741 | elsewhere? I think that such code never uses the TARGET_EXPR as | |
2742 | an initializer. If I'm wrong, we'll abort because the temp won't | |
2743 | have any RTL. In that case, I guess we'll need to replace | |
2744 | references somehow. */ | |
2745 | tree init = TARGET_EXPR_INITIAL (*from_p); | |
2746 | ||
2747 | if (!VOID_TYPE_P (TREE_TYPE (init))) | |
2748 | { | |
2749 | *from_p = init; | |
2750 | ret = GS_OK; | |
2751 | } | |
2752 | else | |
2753 | ret = GS_UNHANDLED; | |
2754 | } | |
2755 | break; | |
2756 | ||
2757 | case COMPOUND_EXPR: | |
2758 | /* Remove any COMPOUND_EXPR in the RHS so the following cases will be | |
2759 | caught. */ | |
2760 | gimplify_compound_expr (from_p, pre_p, true); | |
2761 | ret = GS_OK; | |
2762 | break; | |
2763 | ||
2764 | case CONSTRUCTOR: | |
2765 | /* If we're initializing from a CONSTRUCTOR, break this into | |
2766 | individual MODIFY_EXPRs. */ | |
2767 | return gimplify_init_constructor (expr_p, pre_p, post_p, want_value); | |
2768 | ||
2769 | case COND_EXPR: | |
2770 | /* If we're assigning from a ?: expression with ADDRESSABLE type, push | |
2771 | the assignment down into the branches, since we can't generate a | |
2772 | temporary of such a type. */ | |
2773 | if (TREE_ADDRESSABLE (TREE_TYPE (*from_p))) | |
2774 | { | |
2775 | *expr_p = *from_p; | |
2776 | return gimplify_cond_expr (expr_p, pre_p, *to_p); | |
2777 | } | |
2778 | else | |
2779 | ret = GS_UNHANDLED; | |
2780 | break; | |
2781 | ||
2782 | default: | |
2783 | ret = GS_UNHANDLED; | |
2784 | break; | |
2785 | } | |
2786 | ||
2787 | return ret; | |
2788 | } | |
2789 | ||
2790 | /* Gimplify a comparison between two variable-sized objects. Do this | |
2791 | with a call to BUILT_IN_MEMCMP. */ | |
2792 | ||
2793 | static enum gimplify_status | |
2794 | gimplify_variable_sized_compare (tree *expr_p) | |
2795 | { | |
2796 | tree op0 = TREE_OPERAND (*expr_p, 0); | |
2797 | tree op1 = TREE_OPERAND (*expr_p, 1); | |
2798 | tree args, t, dest; | |
2799 | ||
2800 | t = TYPE_SIZE_UNIT (TREE_TYPE (op0)); | |
2801 | t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, op0); | |
2802 | t = unshare_expr (t); | |
2803 | args = tree_cons (NULL, t, NULL); | |
2804 | t = build_addr_expr (op1); | |
2805 | args = tree_cons (NULL, t, args); | |
2806 | dest = build_addr_expr (op0); | |
2807 | args = tree_cons (NULL, dest, args); | |
2808 | t = implicit_built_in_decls[BUILT_IN_MEMCMP]; | |
2809 | t = build_function_call_expr (t, args); | |
2810 | *expr_p | |
2811 | = build (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node); | |
2812 | ||
2813 | return GS_OK; | |
2814 | } | |
2815 | ||
6de9cd9a DN |
2816 | /* Gimplify TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR expressions. EXPR_P |
2817 | points to the expression to gimplify. | |
2818 | ||
2819 | Expressions of the form 'a && b' are gimplified to: | |
2820 | ||
2821 | a && b ? true : false | |
2822 | ||
2823 | gimplify_cond_expr will do the rest. | |
2824 | ||
2825 | PRE_P points to the list where side effects that must happen before | |
2826 | *EXPR_P should be stored. */ | |
2827 | ||
2828 | static enum gimplify_status | |
2829 | gimplify_boolean_expr (tree *expr_p) | |
2830 | { | |
2831 | /* Preserve the original type of the expression. */ | |
2832 | tree type = TREE_TYPE (*expr_p); | |
2833 | ||
2834 | *expr_p = build (COND_EXPR, type, *expr_p, | |
2835 | convert (type, boolean_true_node), | |
2836 | convert (type, boolean_false_node)); | |
2837 | ||
2838 | return GS_OK; | |
2839 | } | |
2840 | ||
2841 | /* Gimplifies an expression sequence. This function gimplifies each | |
2842 | expression and re-writes the original expression with the last | |
2843 | expression of the sequence in GIMPLE form. | |
2844 | ||
2845 | PRE_P points to the list where the side effects for all the | |
2846 | expressions in the sequence will be emitted. | |
2847 | ||
2848 | WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */ | |
2849 | /* ??? Should rearrange to share the pre-queue with all the indirect | |
2850 | invocations of gimplify_expr. Would probably save on creations | |
2851 | of statement_list nodes. */ | |
2852 | ||
2853 | static enum gimplify_status | |
2854 | gimplify_compound_expr (tree *expr_p, tree *pre_p, bool want_value) | |
2855 | { | |
2856 | tree t = *expr_p; | |
2857 | ||
2858 | do | |
2859 | { | |
2860 | tree *sub_p = &TREE_OPERAND (t, 0); | |
2861 | ||
2862 | if (TREE_CODE (*sub_p) == COMPOUND_EXPR) | |
2863 | gimplify_compound_expr (sub_p, pre_p, false); | |
2864 | else | |
2865 | gimplify_stmt (sub_p); | |
2866 | append_to_statement_list (*sub_p, pre_p); | |
2867 | ||
2868 | t = TREE_OPERAND (t, 1); | |
2869 | } | |
2870 | while (TREE_CODE (t) == COMPOUND_EXPR); | |
2871 | ||
2872 | *expr_p = t; | |
2873 | if (want_value) | |
2874 | return GS_OK; | |
2875 | else | |
2876 | { | |
2877 | gimplify_stmt (expr_p); | |
2878 | return GS_ALL_DONE; | |
2879 | } | |
2880 | } | |
2881 | ||
2882 | /* Gimplifies a statement list. These may be created either by an | |
1ea7e6ad | 2883 | enlightened front-end, or by shortcut_cond_expr. */ |
6de9cd9a DN |
2884 | |
2885 | static enum gimplify_status | |
2886 | gimplify_statement_list (tree *expr_p) | |
2887 | { | |
2888 | tree_stmt_iterator i = tsi_start (*expr_p); | |
2889 | ||
2890 | while (!tsi_end_p (i)) | |
2891 | { | |
2892 | tree t; | |
2893 | ||
2894 | gimplify_stmt (tsi_stmt_ptr (i)); | |
2895 | ||
2896 | t = tsi_stmt (i); | |
65355d53 RH |
2897 | if (t == NULL) |
2898 | tsi_delink (&i); | |
2899 | else if (TREE_CODE (t) == STATEMENT_LIST) | |
6de9cd9a DN |
2900 | { |
2901 | tsi_link_before (&i, t, TSI_SAME_STMT); | |
2902 | tsi_delink (&i); | |
2903 | } | |
2904 | else | |
2905 | tsi_next (&i); | |
2906 | } | |
2907 | ||
2908 | return GS_ALL_DONE; | |
2909 | } | |
2910 | ||
2911 | /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to | |
2912 | gimplify. After gimplification, EXPR_P will point to a new temporary | |
2913 | that holds the original value of the SAVE_EXPR node. | |
2914 | ||
2915 | PRE_P points to the list where side effects that must happen before | |
2916 | *EXPR_P should be stored. */ | |
2917 | ||
2918 | static enum gimplify_status | |
2919 | gimplify_save_expr (tree *expr_p, tree *pre_p, tree *post_p) | |
2920 | { | |
2921 | enum gimplify_status ret = GS_ALL_DONE; | |
2922 | tree val; | |
2923 | ||
2924 | #if defined ENABLE_CHECKING | |
2925 | if (TREE_CODE (*expr_p) != SAVE_EXPR) | |
2926 | abort (); | |
2927 | #endif | |
2928 | ||
2929 | val = TREE_OPERAND (*expr_p, 0); | |
2930 | ||
2931 | /* If the operand is already a GIMPLE temporary, just re-write the | |
2932 | SAVE_EXPR node. */ | |
2933 | if (is_gimple_tmp_var (val)) | |
2934 | *expr_p = val; | |
2935 | /* The operand may be a void-valued expression such as SAVE_EXPRs | |
2936 | generated by the Java frontend for class initialization. It is | |
2937 | being executed only for its side-effects. */ | |
2938 | else if (TREE_TYPE (val) == void_type_node) | |
2939 | { | |
2940 | tree body = TREE_OPERAND (*expr_p, 0); | |
2941 | ret = gimplify_expr (& body, pre_p, post_p, is_gimple_stmt, fb_none); | |
2942 | append_to_statement_list (body, pre_p); | |
65355d53 | 2943 | *expr_p = NULL; |
6de9cd9a DN |
2944 | } |
2945 | else | |
2946 | *expr_p = TREE_OPERAND (*expr_p, 0) | |
2947 | = get_initialized_tmp_var (val, pre_p, post_p); | |
2948 | ||
2949 | return ret; | |
2950 | } | |
2951 | ||
2952 | /* Re-write the ADDR_EXPR node pointed by EXPR_P | |
2953 | ||
2954 | unary_expr | |
2955 | : ... | |
2956 | | '&' varname | |
2957 | ... | |
2958 | ||
2959 | PRE_P points to the list where side effects that must happen before | |
2960 | *EXPR_P should be stored. | |
2961 | ||
2962 | POST_P points to the list where side effects that must happen after | |
2963 | *EXPR_P should be stored. */ | |
2964 | ||
2965 | static enum gimplify_status | |
2966 | gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p) | |
2967 | { | |
2968 | tree expr = *expr_p; | |
2969 | tree op0 = TREE_OPERAND (expr, 0); | |
2970 | enum gimplify_status ret; | |
2971 | ||
2972 | switch (TREE_CODE (op0)) | |
2973 | { | |
2974 | case INDIRECT_REF: | |
2975 | /* Check if we are dealing with an expression of the form '&*ptr'. | |
2976 | While the front end folds away '&*ptr' into 'ptr', these | |
2977 | expressions may be generated internally by the compiler (e.g., | |
2978 | builtins like __builtin_va_end). */ | |
2979 | *expr_p = TREE_OPERAND (op0, 0); | |
2980 | ret = GS_OK; | |
2981 | break; | |
2982 | ||
2983 | case ARRAY_REF: | |
2984 | /* Fold &a[6] to (&a + 6). */ | |
2985 | ret = gimplify_array_ref_to_plus (&TREE_OPERAND (expr, 0), | |
2986 | pre_p, post_p); | |
2987 | ||
2988 | /* This added an INDIRECT_REF. Fold it away. */ | |
44de5aeb RK |
2989 | *expr_p = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); |
2990 | break; | |
6de9cd9a | 2991 | |
44de5aeb RK |
2992 | case VIEW_CONVERT_EXPR: |
2993 | /* Take the address of our operand and then convert it to the type of | |
2994 | this ADDR_EXPR. */ | |
2995 | *expr_p = fold_convert (TREE_TYPE (expr), | |
2996 | build_addr_expr (TREE_OPERAND (op0, 0))); | |
2997 | ret = GS_OK; | |
6de9cd9a DN |
2998 | break; |
2999 | ||
3000 | default: | |
3001 | /* We use fb_either here because the C frontend sometimes takes | |
3002 | the address of a call that returns a struct. */ | |
3003 | ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p, | |
3004 | is_gimple_addr_expr_arg, fb_either); | |
3005 | if (ret != GS_ERROR) | |
3006 | { | |
3007 | /* At this point, the argument of the ADDR_EXPR should be | |
3008 | sufficiently simple that there are never side effects. */ | |
3009 | /* ??? Could split out the decision code from build1 to verify. */ | |
3010 | TREE_SIDE_EFFECTS (expr) = 0; | |
3011 | ||
3012 | /* Make sure TREE_INVARIANT/TREE_CONSTANT is set properly. */ | |
3013 | recompute_tree_invarant_for_addr_expr (expr); | |
3014 | ||
3015 | /* Mark the RHS addressable. */ | |
673fda6b | 3016 | lang_hooks.mark_addressable (TREE_OPERAND (expr, 0)); |
6de9cd9a DN |
3017 | } |
3018 | break; | |
3019 | } | |
3020 | ||
3021 | /* If the operand is gimplified into a _DECL, mark the address expression | |
3022 | as TREE_INVARIANT. */ | |
3023 | if (DECL_P (TREE_OPERAND (expr, 0))) | |
3024 | TREE_INVARIANT (expr) = 1; | |
3025 | ||
3026 | return ret; | |
3027 | } | |
3028 | ||
3029 | /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple | |
3030 | value; output operands should be a gimple lvalue. */ | |
3031 | ||
3032 | static enum gimplify_status | |
3033 | gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p) | |
3034 | { | |
3035 | tree expr = *expr_p; | |
3036 | int noutputs = list_length (ASM_OUTPUTS (expr)); | |
3037 | const char **oconstraints | |
3038 | = (const char **) alloca ((noutputs) * sizeof (const char *)); | |
3039 | int i; | |
3040 | tree link; | |
3041 | const char *constraint; | |
3042 | bool allows_mem, allows_reg, is_inout; | |
3043 | enum gimplify_status ret, tret; | |
3044 | ||
3045 | ASM_STRING (expr) | |
3046 | = resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr), | |
3047 | ASM_INPUTS (expr)); | |
3048 | ||
3049 | ret = GS_ALL_DONE; | |
3050 | for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link)) | |
3051 | { | |
3052 | oconstraints[i] = constraint | |
3053 | = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); | |
3054 | ||
3055 | parse_output_constraint (&constraint, i, 0, 0, | |
3056 | &allows_mem, &allows_reg, &is_inout); | |
3057 | ||
3058 | if (!allows_reg && allows_mem) | |
673fda6b | 3059 | lang_hooks.mark_addressable (TREE_VALUE (link)); |
6de9cd9a DN |
3060 | |
3061 | tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, | |
3062 | is_inout ? is_gimple_min_lval : is_gimple_lvalue, | |
3063 | fb_lvalue | fb_mayfail); | |
3064 | if (tret == GS_ERROR) | |
3065 | { | |
3066 | error ("invalid lvalue in asm output %d", i); | |
3067 | ret = tret; | |
3068 | } | |
3069 | ||
3070 | if (is_inout) | |
3071 | { | |
3072 | /* An input/output operand. To give the optimizers more | |
3073 | flexibility, split it into separate input and output | |
3074 | operands. */ | |
3075 | tree input; | |
3076 | char buf[10]; | |
3077 | size_t constraint_len = strlen (constraint); | |
3078 | ||
3079 | /* Turn the in/out constraint into an output constraint. */ | |
3080 | char *p = xstrdup (constraint); | |
3081 | p[0] = '='; | |
3082 | TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p); | |
3083 | free (p); | |
3084 | ||
3085 | /* And add a matching input constraint. */ | |
3086 | if (allows_reg) | |
3087 | { | |
3088 | sprintf (buf, "%d", i); | |
3089 | input = build_string (strlen (buf), buf); | |
3090 | } | |
3091 | else | |
3092 | input = build_string (constraint_len - 1, constraint + 1); | |
3093 | input = build_tree_list (build_tree_list (NULL_TREE, input), | |
3094 | unshare_expr (TREE_VALUE (link))); | |
3095 | ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input); | |
3096 | } | |
3097 | } | |
3098 | ||
3099 | for (link = ASM_INPUTS (expr); link; ++i, link = TREE_CHAIN (link)) | |
3100 | { | |
3101 | constraint | |
3102 | = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); | |
3103 | parse_input_constraint (&constraint, 0, 0, noutputs, 0, | |
3104 | oconstraints, &allows_mem, &allows_reg); | |
3105 | ||
3106 | /* If the operand is a memory input, it should be an lvalue. */ | |
3107 | if (!allows_reg && allows_mem) | |
3108 | { | |
673fda6b | 3109 | lang_hooks.mark_addressable (TREE_VALUE (link)); |
6de9cd9a DN |
3110 | tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, |
3111 | is_gimple_lvalue, fb_lvalue | fb_mayfail); | |
3112 | if (tret == GS_ERROR) | |
3113 | { | |
3114 | error ("memory input %d is not directly addressable", i); | |
3115 | ret = tret; | |
3116 | } | |
3117 | } | |
3118 | else | |
3119 | { | |
3120 | tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, | |
3121 | is_gimple_val, fb_rvalue); | |
3122 | if (tret == GS_ERROR) | |
3123 | ret = tret; | |
3124 | } | |
3125 | } | |
3126 | ||
3127 | return ret; | |
3128 | } | |
3129 | ||
3130 | /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding | |
3131 | WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while | |
3132 | gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we | |
3133 | return to this function. | |
3134 | ||
3135 | FIXME should we complexify the prequeue handling instead? Or use flags | |
3136 | for all the cleanups and let the optimizer tighten them up? The current | |
3137 | code seems pretty fragile; it will break on a cleanup within any | |
3138 | non-conditional nesting. But any such nesting would be broken, anyway; | |
3139 | we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct | |
3140 | and continues out of it. We can do that at the RTL level, though, so | |
3141 | having an optimizer to tighten up try/finally regions would be a Good | |
3142 | Thing. */ | |
3143 | ||
3144 | static enum gimplify_status | |
3145 | gimplify_cleanup_point_expr (tree *expr_p, tree *pre_p) | |
3146 | { | |
3147 | tree_stmt_iterator iter; | |
3148 | tree body; | |
3149 | ||
325c3691 | 3150 | tree temp = voidify_wrapper_expr (*expr_p, NULL); |
6de9cd9a DN |
3151 | |
3152 | /* We only care about the number of conditions between the innermost | |
3153 | CLEANUP_POINT_EXPR and the cleanup. So save and reset the count. */ | |
3154 | int old_conds = gimplify_ctxp->conditions; | |
3155 | gimplify_ctxp->conditions = 0; | |
3156 | ||
3157 | body = TREE_OPERAND (*expr_p, 0); | |
3158 | gimplify_to_stmt_list (&body); | |
3159 | ||
3160 | gimplify_ctxp->conditions = old_conds; | |
3161 | ||
3162 | for (iter = tsi_start (body); !tsi_end_p (iter); ) | |
3163 | { | |
3164 | tree *wce_p = tsi_stmt_ptr (iter); | |
3165 | tree wce = *wce_p; | |
3166 | ||
3167 | if (TREE_CODE (wce) == WITH_CLEANUP_EXPR) | |
3168 | { | |
3169 | if (tsi_one_before_end_p (iter)) | |
3170 | { | |
3171 | tsi_link_before (&iter, TREE_OPERAND (wce, 1), TSI_SAME_STMT); | |
3172 | tsi_delink (&iter); | |
3173 | break; | |
3174 | } | |
3175 | else | |
3176 | { | |
3177 | tree sl, tfe; | |
3178 | ||
3179 | sl = tsi_split_statement_list_after (&iter); | |
3180 | tfe = build (TRY_FINALLY_EXPR, void_type_node, sl, NULL_TREE); | |
3181 | append_to_statement_list (TREE_OPERAND (wce, 1), | |
3182 | &TREE_OPERAND (tfe, 1)); | |
3183 | *wce_p = tfe; | |
3184 | iter = tsi_start (sl); | |
3185 | } | |
3186 | } | |
3187 | else | |
3188 | tsi_next (&iter); | |
3189 | } | |
3190 | ||
3191 | if (temp) | |
3192 | { | |
3193 | *expr_p = temp; | |
3194 | append_to_statement_list (body, pre_p); | |
3195 | return GS_OK; | |
3196 | } | |
3197 | else | |
3198 | { | |
3199 | *expr_p = body; | |
3200 | return GS_ALL_DONE; | |
3201 | } | |
3202 | } | |
3203 | ||
3204 | /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP | |
3205 | is the cleanup action required. */ | |
3206 | ||
3207 | static void | |
3208 | gimple_push_cleanup (tree var, tree cleanup, tree *pre_p) | |
3209 | { | |
3210 | tree wce; | |
3211 | ||
3212 | /* Errors can result in improperly nested cleanups. Which results in | |
3213 | confusion when trying to resolve the WITH_CLEANUP_EXPR. */ | |
3214 | if (errorcount || sorrycount) | |
3215 | return; | |
3216 | ||
3217 | if (gimple_conditional_context ()) | |
3218 | { | |
3219 | /* If we're in a conditional context, this is more complex. We only | |
3220 | want to run the cleanup if we actually ran the initialization that | |
3221 | necessitates it, but we want to run it after the end of the | |
3222 | conditional context. So we wrap the try/finally around the | |
3223 | condition and use a flag to determine whether or not to actually | |
3224 | run the destructor. Thus | |
3225 | ||
3226 | test ? f(A()) : 0 | |
3227 | ||
3228 | becomes (approximately) | |
3229 | ||
3230 | flag = 0; | |
3231 | try { | |
3232 | if (test) { A::A(temp); flag = 1; val = f(temp); } | |
3233 | else { val = 0; } | |
3234 | } finally { | |
3235 | if (flag) A::~A(temp); | |
3236 | } | |
3237 | val | |
3238 | */ | |
3239 | ||
3240 | tree flag = create_tmp_var (boolean_type_node, "cleanup"); | |
3241 | tree ffalse = build (MODIFY_EXPR, void_type_node, flag, | |
3242 | boolean_false_node); | |
3243 | tree ftrue = build (MODIFY_EXPR, void_type_node, flag, | |
3244 | boolean_true_node); | |
65355d53 | 3245 | cleanup = build (COND_EXPR, void_type_node, flag, cleanup, NULL); |
6de9cd9a DN |
3246 | wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE, |
3247 | cleanup, NULL_TREE); | |
3248 | append_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups); | |
3249 | append_to_statement_list (wce, &gimplify_ctxp->conditional_cleanups); | |
3250 | append_to_statement_list (ftrue, pre_p); | |
3251 | ||
3252 | /* Because of this manipulation, and the EH edges that jump | |
3253 | threading cannot redirect, the temporary (VAR) will appear | |
3254 | to be used uninitialized. Don't warn. */ | |
3255 | TREE_NO_WARNING (var) = 1; | |
3256 | } | |
3257 | else | |
3258 | { | |
3259 | wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE, | |
3260 | cleanup, NULL_TREE); | |
3261 | append_to_statement_list (wce, pre_p); | |
3262 | } | |
3263 | ||
3264 | gimplify_stmt (&TREE_OPERAND (wce, 1)); | |
3265 | } | |
3266 | ||
3267 | /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */ | |
3268 | ||
3269 | static enum gimplify_status | |
3270 | gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p) | |
3271 | { | |
3272 | tree targ = *expr_p; | |
3273 | tree temp = TARGET_EXPR_SLOT (targ); | |
3274 | tree init = TARGET_EXPR_INITIAL (targ); | |
3275 | enum gimplify_status ret; | |
3276 | ||
3277 | if (init) | |
3278 | { | |
3a5b9284 RH |
3279 | /* TARGET_EXPR temps aren't part of the enclosing block, so add it |
3280 | to the temps list. */ | |
6de9cd9a DN |
3281 | gimple_add_tmp_var (temp); |
3282 | ||
3a5b9284 RH |
3283 | /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the |
3284 | expression is supposed to initialize the slot. */ | |
3285 | if (VOID_TYPE_P (TREE_TYPE (init))) | |
3286 | ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none); | |
3287 | else | |
325c3691 | 3288 | { |
3a5b9284 RH |
3289 | /* Special handling for BIND_EXPR can result in fewer temps. */ |
3290 | ret = GS_OK; | |
3291 | if (TREE_CODE (init) == BIND_EXPR) | |
3292 | gimplify_bind_expr (&init, temp, pre_p); | |
3293 | if (init != temp) | |
3294 | { | |
3295 | init = build (MODIFY_EXPR, void_type_node, temp, init); | |
3296 | ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, | |
3297 | fb_none); | |
3298 | } | |
325c3691 | 3299 | } |
3a5b9284 RH |
3300 | if (ret == GS_ERROR) |
3301 | return GS_ERROR; | |
6de9cd9a DN |
3302 | append_to_statement_list (init, pre_p); |
3303 | ||
3304 | /* If needed, push the cleanup for the temp. */ | |
3305 | if (TARGET_EXPR_CLEANUP (targ)) | |
3306 | { | |
3307 | gimplify_stmt (&TARGET_EXPR_CLEANUP (targ)); | |
3308 | gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ), pre_p); | |
3309 | } | |
3310 | ||
3311 | /* Only expand this once. */ | |
3312 | TREE_OPERAND (targ, 3) = init; | |
3313 | TARGET_EXPR_INITIAL (targ) = NULL_TREE; | |
3314 | } | |
3315 | else if (!temp->decl.seen_in_bind_expr) | |
3316 | /* We should have expanded this before. */ | |
3317 | abort (); | |
3318 | ||
3319 | *expr_p = temp; | |
3320 | return GS_OK; | |
3321 | } | |
3322 | ||
3323 | /* Gimplification of expression trees. */ | |
3324 | ||
3325 | /* Gimplify an expression which appears at statement context; usually, this | |
be00f578 | 3326 | means replacing it with a suitably gimple STATEMENT_LIST. */ |
6de9cd9a DN |
3327 | |
3328 | void | |
3329 | gimplify_stmt (tree *stmt_p) | |
3330 | { | |
3331 | gimplify_expr (stmt_p, NULL, NULL, is_gimple_stmt, fb_none); | |
6de9cd9a DN |
3332 | } |
3333 | ||
3334 | /* Similarly, but force the result to be a STATEMENT_LIST. */ | |
3335 | ||
3336 | void | |
3337 | gimplify_to_stmt_list (tree *stmt_p) | |
3338 | { | |
3339 | gimplify_stmt (stmt_p); | |
65355d53 RH |
3340 | if (!*stmt_p) |
3341 | *stmt_p = alloc_stmt_list (); | |
3342 | else if (TREE_CODE (*stmt_p) != STATEMENT_LIST) | |
6de9cd9a DN |
3343 | { |
3344 | tree t = *stmt_p; | |
be00f578 | 3345 | *stmt_p = alloc_stmt_list (); |
6de9cd9a DN |
3346 | append_to_statement_list (t, stmt_p); |
3347 | } | |
3348 | } | |
3349 | ||
3350 | ||
3351 | /* Gimplifies the expression tree pointed by EXPR_P. Return 0 if | |
3352 | gimplification failed. | |
3353 | ||
3354 | PRE_P points to the list where side effects that must happen before | |
3355 | EXPR should be stored. | |
3356 | ||
3357 | POST_P points to the list where side effects that must happen after | |
3358 | EXPR should be stored, or NULL if there is no suitable list. In | |
3359 | that case, we copy the result to a temporary, emit the | |
3360 | post-effects, and then return the temporary. | |
3361 | ||
3362 | GIMPLE_TEST_F points to a function that takes a tree T and | |
3363 | returns nonzero if T is in the GIMPLE form requested by the | |
eadf906f | 3364 | caller. The GIMPLE predicates are in tree-gimple.c. |
6de9cd9a DN |
3365 | |
3366 | This test is used twice. Before gimplification, the test is | |
3367 | invoked to determine whether *EXPR_P is already gimple enough. If | |
3368 | that fails, *EXPR_P is gimplified according to its code and | |
3369 | GIMPLE_TEST_F is called again. If the test still fails, then a new | |
3370 | temporary variable is created and assigned the value of the | |
3371 | gimplified expression. | |
3372 | ||
3373 | FALLBACK tells the function what sort of a temporary we want. If the 1 | |
3374 | bit is set, an rvalue is OK. If the 2 bit is set, an lvalue is OK. | |
3375 | If both are set, either is OK, but an lvalue is preferable. | |
3376 | ||
3377 | The return value is either GS_ERROR or GS_ALL_DONE, since this function | |
3378 | iterates until solution. */ | |
3379 | ||
3380 | enum gimplify_status | |
3381 | gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, | |
3382 | bool (* gimple_test_f) (tree), fallback_t fallback) | |
3383 | { | |
3384 | tree tmp; | |
3385 | tree internal_pre = NULL_TREE; | |
3386 | tree internal_post = NULL_TREE; | |
3387 | tree save_expr; | |
3388 | int is_statement = (pre_p == NULL); | |
3389 | location_t *locus; | |
3390 | location_t saved_location; | |
3391 | enum gimplify_status ret; | |
3392 | ||
3393 | save_expr = *expr_p; | |
3394 | if (save_expr == NULL_TREE) | |
3395 | return GS_ALL_DONE; | |
3396 | ||
3397 | /* We used to check the predicate here and return immediately if it | |
3398 | succeeds. This is wrong; the design is for gimplification to be | |
3399 | idempotent, and for the predicates to only test for valid forms, not | |
3400 | whether they are fully simplified. */ | |
3401 | ||
3402 | /* Set up our internal queues if needed. */ | |
3403 | if (pre_p == NULL) | |
3404 | pre_p = &internal_pre; | |
3405 | if (post_p == NULL) | |
3406 | post_p = &internal_post; | |
3407 | ||
3408 | saved_location = input_location; | |
3409 | if (save_expr == error_mark_node) | |
3410 | locus = NULL; | |
3411 | else | |
3412 | locus = EXPR_LOCUS (save_expr); | |
3413 | if (locus) | |
3414 | input_location = *locus; | |
3415 | ||
3416 | /* Loop over the specific gimplifiers until the toplevel node | |
3417 | remains the same. */ | |
3418 | do | |
3419 | { | |
3420 | /* Strip any uselessness. */ | |
3421 | STRIP_MAIN_TYPE_NOPS (*expr_p); | |
3422 | ||
3423 | /* Remember the expr. */ | |
3424 | save_expr = *expr_p; | |
3425 | ||
3426 | /* Die, die, die, my darling. */ | |
3427 | if (save_expr == error_mark_node | |
65355d53 RH |
3428 | || (TREE_TYPE (save_expr) |
3429 | && TREE_TYPE (save_expr) == error_mark_node)) | |
6de9cd9a DN |
3430 | { |
3431 | ret = GS_ERROR; | |
3432 | break; | |
3433 | } | |
3434 | ||
3435 | /* Do any language-specific gimplification. */ | |
673fda6b | 3436 | ret = lang_hooks.gimplify_expr (expr_p, pre_p, post_p); |
6de9cd9a DN |
3437 | if (ret == GS_OK) |
3438 | { | |
3439 | if (*expr_p == NULL_TREE) | |
3440 | break; | |
3441 | if (*expr_p != save_expr) | |
3442 | continue; | |
3443 | } | |
3444 | else if (ret != GS_UNHANDLED) | |
3445 | break; | |
3446 | ||
3447 | ret = GS_OK; | |
3448 | switch (TREE_CODE (*expr_p)) | |
3449 | { | |
3450 | /* First deal with the special cases. */ | |
3451 | ||
3452 | case POSTINCREMENT_EXPR: | |
3453 | case POSTDECREMENT_EXPR: | |
3454 | case PREINCREMENT_EXPR: | |
3455 | case PREDECREMENT_EXPR: | |
3456 | ret = gimplify_self_mod_expr (expr_p, pre_p, post_p, | |
3457 | fallback != fb_none); | |
3458 | break; | |
3459 | ||
3460 | case ARRAY_REF: | |
44de5aeb RK |
3461 | case ARRAY_RANGE_REF: |
3462 | case REALPART_EXPR: | |
3463 | case IMAGPART_EXPR: | |
6de9cd9a DN |
3464 | case COMPONENT_REF: |
3465 | ret = gimplify_compound_lval (expr_p, pre_p, post_p, | |
3466 | fallback & fb_lvalue); | |
3467 | break; | |
3468 | ||
3469 | case COND_EXPR: | |
3470 | ret = gimplify_cond_expr (expr_p, pre_p, NULL_TREE); | |
3471 | break; | |
3472 | ||
3473 | case CALL_EXPR: | |
3474 | ret = gimplify_call_expr (expr_p, pre_p, gimple_test_f); | |
3475 | break; | |
3476 | ||
3477 | case TREE_LIST: | |
3478 | abort (); | |
3479 | ||
3480 | case COMPOUND_EXPR: | |
3481 | ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none); | |
3482 | break; | |
3483 | ||
6de9cd9a DN |
3484 | case MODIFY_EXPR: |
3485 | case INIT_EXPR: | |
3486 | ret = gimplify_modify_expr (expr_p, pre_p, post_p, | |
3487 | fallback != fb_none); | |
3488 | break; | |
3489 | ||
3490 | case TRUTH_ANDIF_EXPR: | |
3491 | case TRUTH_ORIF_EXPR: | |
3492 | ret = gimplify_boolean_expr (expr_p); | |
3493 | break; | |
3494 | ||
3495 | case TRUTH_NOT_EXPR: | |
3496 | TREE_OPERAND (*expr_p, 0) | |
3497 | = gimple_boolify (TREE_OPERAND (*expr_p, 0)); | |
3498 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3499 | is_gimple_val, fb_rvalue); | |
3500 | recalculate_side_effects (*expr_p); | |
3501 | break; | |
3502 | ||
3503 | case ADDR_EXPR: | |
3504 | ret = gimplify_addr_expr (expr_p, pre_p, post_p); | |
3505 | break; | |
3506 | ||
3507 | case VA_ARG_EXPR: | |
cd3ce9b4 | 3508 | ret = gimplify_va_arg_expr (expr_p, pre_p, post_p); |
6de9cd9a DN |
3509 | break; |
3510 | ||
44de5aeb RK |
3511 | case VIEW_CONVERT_EXPR: |
3512 | if (VOID_TYPE_P (TREE_TYPE (*expr_p)) | |
3513 | || fallback == fb_none) | |
3514 | { | |
3515 | /* Just strip a conversion to void (or in void context) and | |
3516 | try again. */ | |
3517 | *expr_p = TREE_OPERAND (*expr_p, 0); | |
3518 | break; | |
3519 | } | |
3520 | ||
3521 | /* If both types are BLKmode or if one type is of variable size, | |
3522 | convert this into a pointer punning operation. This avoids | |
3523 | copies of large data or making a variable-size temporary. */ | |
3524 | if ((TYPE_MODE (TREE_TYPE (*expr_p)) == BLKmode | |
3525 | && TYPE_MODE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) == BLKmode) | |
3526 | || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (*expr_p))) | |
3527 | || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE | |
3528 | (TREE_OPERAND (*expr_p,0))))) | |
3529 | { | |
3530 | tree restype = TREE_TYPE (*expr_p); | |
3531 | *expr_p = build1 (INDIRECT_REF, TREE_TYPE (*expr_p), | |
3532 | fold_convert (build_pointer_type (restype), | |
3533 | build_addr_expr | |
3534 | (TREE_OPERAND (*expr_p, 0)))); | |
3535 | break; | |
3536 | } | |
3537 | goto unary; | |
3538 | ||
6de9cd9a DN |
3539 | case CONVERT_EXPR: |
3540 | case NOP_EXPR: | |
3541 | if (IS_EMPTY_STMT (*expr_p)) | |
3542 | { | |
3543 | ret = GS_ALL_DONE; | |
3544 | break; | |
3545 | } | |
3546 | ||
3547 | if (VOID_TYPE_P (TREE_TYPE (*expr_p)) | |
3548 | || fallback == fb_none) | |
3549 | { | |
3550 | /* Just strip a conversion to void (or in void context) and | |
3551 | try again. */ | |
3552 | *expr_p = TREE_OPERAND (*expr_p, 0); | |
3553 | break; | |
3554 | } | |
3555 | ||
3556 | ret = gimplify_conversion (expr_p); | |
3557 | if (ret == GS_ERROR) | |
3558 | break; | |
3559 | if (*expr_p != save_expr) | |
3560 | break; | |
3561 | /* FALLTHRU */ | |
3562 | ||
3563 | case FIX_TRUNC_EXPR: | |
3564 | case FIX_CEIL_EXPR: | |
3565 | case FIX_FLOOR_EXPR: | |
3566 | case FIX_ROUND_EXPR: | |
44de5aeb | 3567 | unary: |
6de9cd9a DN |
3568 | /* unary_expr: ... | '(' cast ')' val | ... */ |
3569 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3570 | is_gimple_val, fb_rvalue); | |
3571 | recalculate_side_effects (*expr_p); | |
3572 | break; | |
3573 | ||
3574 | case INDIRECT_REF: | |
3575 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3576 | is_gimple_reg, fb_rvalue); | |
3577 | recalculate_side_effects (*expr_p); | |
3578 | break; | |
3579 | ||
3580 | /* Constants need not be gimplified. */ | |
3581 | case INTEGER_CST: | |
3582 | case REAL_CST: | |
3583 | case STRING_CST: | |
3584 | case COMPLEX_CST: | |
3585 | case VECTOR_CST: | |
3586 | ret = GS_ALL_DONE; | |
3587 | break; | |
3588 | ||
3589 | case CONST_DECL: | |
3590 | *expr_p = DECL_INITIAL (*expr_p); | |
3591 | break; | |
3592 | ||
3593 | case EXC_PTR_EXPR: | |
3594 | /* FIXME make this a decl. */ | |
3595 | ret = GS_ALL_DONE; | |
3596 | break; | |
3597 | ||
3598 | case BIND_EXPR: | |
325c3691 | 3599 | ret = gimplify_bind_expr (expr_p, NULL, pre_p); |
6de9cd9a DN |
3600 | break; |
3601 | ||
3602 | case LOOP_EXPR: | |
3603 | ret = gimplify_loop_expr (expr_p, pre_p); | |
3604 | break; | |
3605 | ||
3606 | case SWITCH_EXPR: | |
3607 | ret = gimplify_switch_expr (expr_p, pre_p); | |
3608 | break; | |
3609 | ||
3610 | case LABELED_BLOCK_EXPR: | |
3611 | ret = gimplify_labeled_block_expr (expr_p); | |
3612 | break; | |
3613 | ||
3614 | case EXIT_BLOCK_EXPR: | |
3615 | ret = gimplify_exit_block_expr (expr_p); | |
3616 | break; | |
3617 | ||
3618 | case EXIT_EXPR: | |
3619 | ret = gimplify_exit_expr (expr_p); | |
3620 | break; | |
3621 | ||
3622 | case GOTO_EXPR: | |
3623 | /* If the target is not LABEL, then it is a computed jump | |
3624 | and the target needs to be gimplified. */ | |
3625 | if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL) | |
3626 | ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p, | |
3627 | NULL, is_gimple_val, fb_rvalue); | |
3628 | break; | |
3629 | ||
3630 | case LABEL_EXPR: | |
3631 | ret = GS_ALL_DONE; | |
3632 | #ifdef ENABLE_CHECKING | |
3633 | if (decl_function_context (LABEL_EXPR_LABEL (*expr_p)) != current_function_decl) | |
3634 | abort (); | |
3635 | #endif | |
3636 | break; | |
3637 | ||
3638 | case CASE_LABEL_EXPR: | |
3639 | ret = gimplify_case_label_expr (expr_p); | |
3640 | break; | |
3641 | ||
3642 | case RETURN_EXPR: | |
3643 | ret = gimplify_return_expr (*expr_p, pre_p); | |
3644 | break; | |
3645 | ||
3646 | case CONSTRUCTOR: | |
3647 | /* Don't reduce this in place; let gimplify_init_constructor work | |
3648 | its magic. */ | |
3649 | ret = GS_ALL_DONE; | |
3650 | break; | |
3651 | ||
3652 | /* The following are special cases that are not handled by the | |
3653 | original GIMPLE grammar. */ | |
3654 | ||
3655 | /* SAVE_EXPR nodes are converted into a GIMPLE identifier and | |
3656 | eliminated. */ | |
3657 | case SAVE_EXPR: | |
3658 | ret = gimplify_save_expr (expr_p, pre_p, post_p); | |
3659 | break; | |
3660 | ||
3661 | case BIT_FIELD_REF: | |
3662 | { | |
3663 | enum gimplify_status r0, r1, r2; | |
3664 | ||
3665 | r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3666 | is_gimple_min_lval, fb_either); | |
3667 | r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, | |
3668 | is_gimple_val, fb_rvalue); | |
3669 | r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p, post_p, | |
3670 | is_gimple_val, fb_rvalue); | |
3671 | recalculate_side_effects (*expr_p); | |
3672 | ||
3673 | ret = MIN (r0, MIN (r1, r2)); | |
3674 | } | |
3675 | break; | |
3676 | ||
3677 | case NON_LVALUE_EXPR: | |
3678 | /* This should have been stripped above. */ | |
3679 | abort (); | |
3680 | break; | |
3681 | ||
3682 | case ASM_EXPR: | |
3683 | ret = gimplify_asm_expr (expr_p, pre_p, post_p); | |
3684 | break; | |
3685 | ||
3686 | case TRY_FINALLY_EXPR: | |
3687 | case TRY_CATCH_EXPR: | |
3688 | gimplify_to_stmt_list (&TREE_OPERAND (*expr_p, 0)); | |
3689 | gimplify_to_stmt_list (&TREE_OPERAND (*expr_p, 1)); | |
3690 | ret = GS_ALL_DONE; | |
3691 | break; | |
3692 | ||
3693 | case CLEANUP_POINT_EXPR: | |
3694 | ret = gimplify_cleanup_point_expr (expr_p, pre_p); | |
3695 | break; | |
3696 | ||
3697 | case TARGET_EXPR: | |
3698 | ret = gimplify_target_expr (expr_p, pre_p, post_p); | |
3699 | break; | |
3700 | ||
3701 | case CATCH_EXPR: | |
3702 | gimplify_to_stmt_list (&CATCH_BODY (*expr_p)); | |
3703 | ret = GS_ALL_DONE; | |
3704 | break; | |
3705 | ||
3706 | case EH_FILTER_EXPR: | |
3707 | gimplify_to_stmt_list (&EH_FILTER_FAILURE (*expr_p)); | |
3708 | ret = GS_ALL_DONE; | |
3709 | break; | |
3710 | ||
0f59171d RH |
3711 | case OBJ_TYPE_REF: |
3712 | { | |
3713 | enum gimplify_status r0, r1; | |
3714 | r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, post_p, | |
3715 | is_gimple_val, fb_rvalue); | |
3716 | r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p, | |
3717 | is_gimple_val, fb_rvalue); | |
3718 | ret = MIN (r0, r1); | |
3719 | } | |
6de9cd9a DN |
3720 | break; |
3721 | ||
3722 | case MIN_EXPR: | |
3723 | case MAX_EXPR: | |
3724 | ret = gimplify_minimax_expr (expr_p, pre_p, post_p); | |
3725 | break; | |
3726 | ||
3727 | case LABEL_DECL: | |
3728 | /* We get here when taking the address of a label. We mark | |
3729 | the label as "forced"; meaning it can never be removed and | |
3730 | it is a potential target for any computed goto. */ | |
3731 | FORCED_LABEL (*expr_p) = 1; | |
3732 | ret = GS_ALL_DONE; | |
3733 | break; | |
3734 | ||
3735 | case STATEMENT_LIST: | |
3736 | ret = gimplify_statement_list (expr_p); | |
3737 | break; | |
3738 | ||
3739 | case VAR_DECL: | |
3740 | /* ??? If this is a local variable, and it has not been seen in any | |
3741 | outer BIND_EXPR, then it's probably the result of a duplicate | |
3742 | declaration, for which we've already issued an error. It would | |
3743 | be really nice if the front end wouldn't leak these at all. | |
3744 | Currently the only known culprit is C++ destructors, as seen | |
3745 | in g++.old-deja/g++.jason/binding.C. */ | |
3746 | tmp = *expr_p; | |
3747 | if (!TREE_STATIC (tmp) && !DECL_EXTERNAL (tmp) | |
3748 | && decl_function_context (tmp) == current_function_decl | |
3749 | && !tmp->decl.seen_in_bind_expr) | |
3750 | { | |
3751 | #ifdef ENABLE_CHECKING | |
3752 | if (!errorcount && !sorrycount) | |
3753 | abort (); | |
3754 | #endif | |
3755 | ret = GS_ERROR; | |
3756 | } | |
3757 | else | |
3758 | ret = GS_ALL_DONE; | |
3759 | break; | |
3760 | ||
3761 | default: | |
44de5aeb RK |
3762 | /* If this is a comparison of objects of aggregate type, handle |
3763 | it specially (by converting to a call to memcmp). It would be | |
3764 | nice to only have to do this for variable-sized objects, but | |
3765 | then we'd have to allow the same nest of reference nodes we | |
3766 | allow for MODIFY_EXPR and that's too complex. */ | |
3767 | if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<' | |
3768 | && (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 1))))) | |
3769 | ret = gimplify_variable_sized_compare (expr_p); | |
3770 | ||
6de9cd9a DN |
3771 | /* If *EXPR_P does not need to be special-cased, handle it |
3772 | according to its class. */ | |
44de5aeb | 3773 | else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1') |
6de9cd9a DN |
3774 | ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, |
3775 | post_p, is_gimple_val, fb_rvalue); | |
3776 | else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2' | |
3777 | || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<' | |
3778 | || TREE_CODE (*expr_p) == TRUTH_AND_EXPR | |
3779 | || TREE_CODE (*expr_p) == TRUTH_OR_EXPR | |
3780 | || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR) | |
3781 | { | |
3782 | enum gimplify_status r0, r1; | |
3783 | ||
3784 | r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, | |
3785 | post_p, is_gimple_val, fb_rvalue); | |
3786 | r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, | |
3787 | post_p, is_gimple_val, fb_rvalue); | |
3788 | ||
3789 | ret = MIN (r0, r1); | |
3790 | } | |
3791 | else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == 'd' | |
3792 | || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == 'c') | |
3793 | { | |
3794 | ret = GS_ALL_DONE; | |
3795 | break; | |
3796 | } | |
3797 | else | |
3798 | /* Fail if we don't know how to handle this tree code. */ | |
3799 | abort (); | |
3800 | ||
3801 | recalculate_side_effects (*expr_p); | |
3802 | break; | |
3803 | } | |
3804 | ||
3805 | /* If we replaced *expr_p, gimplify again. */ | |
3806 | if (ret == GS_OK && (*expr_p == NULL || *expr_p == save_expr)) | |
3807 | ret = GS_ALL_DONE; | |
3808 | } | |
3809 | while (ret == GS_OK); | |
3810 | ||
3811 | /* If we encountered an error_mark somewhere nested inside, either | |
3812 | stub out the statement or propagate the error back out. */ | |
3813 | if (ret == GS_ERROR) | |
3814 | { | |
3815 | if (is_statement) | |
65355d53 | 3816 | *expr_p = NULL; |
6de9cd9a DN |
3817 | goto out; |
3818 | } | |
3819 | ||
3820 | #ifdef ENABLE_CHECKING | |
3821 | /* This was only valid as a return value from the langhook, which | |
3822 | we handled. Make sure it doesn't escape from any other context. */ | |
3823 | if (ret == GS_UNHANDLED) | |
3824 | abort (); | |
3825 | #endif | |
3826 | ||
65355d53 | 3827 | if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p)) |
6de9cd9a DN |
3828 | { |
3829 | /* We aren't looking for a value, and we don't have a valid | |
3830 | statement. If it doesn't have side-effects, throw it away. */ | |
3831 | if (!TREE_SIDE_EFFECTS (*expr_p)) | |
65355d53 | 3832 | *expr_p = NULL; |
6de9cd9a | 3833 | else if (!TREE_THIS_VOLATILE (*expr_p)) |
44de5aeb RK |
3834 | { |
3835 | /* This is probably a _REF that contains something nested that | |
3836 | has side effects. Recurse through the operands to find it. */ | |
3837 | enum tree_code code = TREE_CODE (*expr_p); | |
3838 | ||
3839 | if (code == COMPONENT_REF | |
3840 | || code == REALPART_EXPR || code == IMAGPART_EXPR) | |
3841 | gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3842 | gimple_test_f, fallback); | |
3843 | else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) | |
3844 | { | |
3845 | gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
3846 | gimple_test_f, fallback); | |
3847 | gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, | |
3848 | gimple_test_f, fallback); | |
3849 | } | |
3850 | else | |
3851 | /* Anything else with side-effects | |
3852 | must be converted to a valid statement before we get here. */ | |
3853 | abort (); | |
3854 | ||
65355d53 | 3855 | *expr_p = NULL; |
44de5aeb | 3856 | } |
6de9cd9a DN |
3857 | else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))) |
3858 | { | |
3859 | /* Historically, the compiler has treated a bare | |
3860 | reference to a volatile lvalue as forcing a load. */ | |
3861 | tree tmp = create_tmp_var (TREE_TYPE (*expr_p), "vol"); | |
3862 | *expr_p = build (MODIFY_EXPR, TREE_TYPE (tmp), tmp, *expr_p); | |
3863 | } | |
3864 | else | |
3865 | /* We can't do anything useful with a volatile reference to | |
3866 | incomplete type, so just throw it away. */ | |
65355d53 | 3867 | *expr_p = NULL; |
6de9cd9a DN |
3868 | } |
3869 | ||
3870 | /* If we are gimplifying at the statement level, we're done. Tack | |
3871 | everything together and replace the original statement with the | |
3872 | gimplified form. */ | |
325c3691 | 3873 | if (fallback == fb_none || is_statement) |
6de9cd9a | 3874 | { |
be00f578 JM |
3875 | if (internal_pre || internal_post) |
3876 | { | |
3877 | append_to_statement_list (*expr_p, &internal_pre); | |
3878 | append_to_statement_list (internal_post, &internal_pre); | |
3879 | annotate_all_with_locus (&internal_pre, input_location); | |
3880 | *expr_p = internal_pre; | |
3881 | } | |
65355d53 RH |
3882 | else if (!*expr_p) |
3883 | ; | |
7c34ced1 RH |
3884 | else if (TREE_CODE (*expr_p) == STATEMENT_LIST) |
3885 | annotate_all_with_locus (expr_p, input_location); | |
3886 | else | |
3887 | annotate_one_with_locus (*expr_p, input_location); | |
6de9cd9a DN |
3888 | goto out; |
3889 | } | |
3890 | ||
3891 | /* Otherwise we're gimplifying a subexpression, so the resulting value is | |
3892 | interesting. */ | |
3893 | ||
3894 | /* If it's sufficiently simple already, we're done. Unless we are | |
3895 | handling some post-effects internally; if that's the case, we need to | |
3896 | copy into a temp before adding the post-effects to the tree. */ | |
3897 | if (!internal_post && (*gimple_test_f) (*expr_p)) | |
3898 | goto out; | |
3899 | ||
3900 | /* Otherwise, we need to create a new temporary for the gimplified | |
3901 | expression. */ | |
3902 | ||
3903 | /* We can't return an lvalue if we have an internal postqueue. The | |
3904 | object the lvalue refers to would (probably) be modified by the | |
3905 | postqueue; we need to copy the value out first, which means an | |
3906 | rvalue. */ | |
3907 | if ((fallback & fb_lvalue) && !internal_post | |
3908 | && is_gimple_addr_expr_arg (*expr_p)) | |
3909 | { | |
3910 | /* An lvalue will do. Take the address of the expression, store it | |
3911 | in a temporary, and replace the expression with an INDIRECT_REF of | |
3912 | that temporary. */ | |
cd3ce9b4 | 3913 | tmp = build_fold_addr_expr (*expr_p); |
6de9cd9a DN |
3914 | gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue); |
3915 | *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp); | |
3916 | } | |
3917 | else if ((fallback & fb_rvalue) && is_gimple_rhs (*expr_p)) | |
3918 | { | |
3919 | #if defined ENABLE_CHECKING | |
3920 | if (VOID_TYPE_P (TREE_TYPE (*expr_p))) | |
3921 | abort (); | |
3922 | #endif | |
3923 | ||
3924 | /* An rvalue will do. Assign the gimplified expression into a new | |
3925 | temporary TMP and replace the original expression with TMP. */ | |
3926 | ||
3927 | if (internal_post || (fallback & fb_lvalue)) | |
3928 | /* The postqueue might change the value of the expression between | |
3929 | the initialization and use of the temporary, so we can't use a | |
3930 | formal temp. FIXME do we care? */ | |
3931 | *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); | |
3932 | else | |
3933 | *expr_p = get_formal_tmp_var (*expr_p, pre_p); | |
3934 | } | |
3935 | else if (fallback & fb_mayfail) | |
3936 | { | |
3937 | /* If this is an asm statement, and the user asked for the impossible, | |
3938 | don't abort. Fail and let gimplify_asm_expr issue an error. */ | |
3939 | ret = GS_ERROR; | |
3940 | goto out; | |
3941 | } | |
3942 | else | |
3943 | { | |
3944 | fprintf (stderr, "gimplification failed:\n"); | |
3945 | print_generic_expr (stderr, *expr_p, 0); | |
3946 | debug_tree (*expr_p); | |
3947 | abort (); | |
3948 | } | |
3949 | ||
3950 | #if defined ENABLE_CHECKING | |
3951 | /* Make sure the temporary matches our predicate. */ | |
3952 | if (!(*gimple_test_f) (*expr_p)) | |
3953 | abort (); | |
3954 | #endif | |
3955 | ||
3956 | if (internal_post) | |
3957 | { | |
3958 | annotate_all_with_locus (&internal_post, input_location); | |
3959 | append_to_statement_list (internal_post, pre_p); | |
3960 | } | |
3961 | ||
3962 | out: | |
3963 | input_location = saved_location; | |
3964 | return ret; | |
3965 | } | |
3966 | ||
44de5aeb | 3967 | /* Look through TYPE for variable-sized objects and gimplify each such |
65355d53 | 3968 | size that we find. Add to LIST_P any statements generated. */ |
44de5aeb | 3969 | |
65355d53 RH |
3970 | void |
3971 | gimplify_type_sizes (tree type, tree *list_p) | |
44de5aeb | 3972 | { |
44de5aeb RK |
3973 | tree field; |
3974 | ||
3975 | switch (TREE_CODE (type)) | |
3976 | { | |
3977 | case ERROR_MARK: | |
65355d53 | 3978 | return; |
44de5aeb RK |
3979 | |
3980 | case INTEGER_TYPE: | |
3981 | case ENUMERAL_TYPE: | |
3982 | case BOOLEAN_TYPE: | |
3983 | case CHAR_TYPE: | |
3984 | case REAL_TYPE: | |
65355d53 RH |
3985 | gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p); |
3986 | gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p); | |
44de5aeb RK |
3987 | break; |
3988 | ||
3989 | case ARRAY_TYPE: | |
3990 | /* These anonymous types don't have declarations, so handle them here. */ | |
65355d53 | 3991 | gimplify_type_sizes (TYPE_DOMAIN (type), list_p); |
44de5aeb RK |
3992 | break; |
3993 | ||
3994 | case RECORD_TYPE: | |
3995 | case UNION_TYPE: | |
3996 | case QUAL_UNION_TYPE: | |
3997 | for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) | |
3998 | if (TREE_CODE (field) == FIELD_DECL) | |
65355d53 | 3999 | gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p); |
44de5aeb RK |
4000 | break; |
4001 | ||
4002 | default: | |
4003 | break; | |
4004 | } | |
4005 | ||
65355d53 RH |
4006 | gimplify_one_sizepos (&TYPE_SIZE (type), list_p); |
4007 | gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p); | |
44de5aeb RK |
4008 | } |
4009 | ||
4010 | /* Subroutine of the above to gimplify one size or position, *EXPR_P. | |
4011 | We add any required statements to STMT_P. */ | |
4012 | ||
4013 | void | |
4014 | gimplify_one_sizepos (tree *expr_p, tree *stmt_p) | |
4015 | { | |
44de5aeb RK |
4016 | /* We don't do anything if the value isn't there, is constant, or contains |
4017 | A PLACEHOLDER_EXPR. */ | |
4018 | if (*expr_p == NULL_TREE || TREE_CONSTANT (*expr_p) | |
4019 | || CONTAINS_PLACEHOLDER_P (*expr_p)) | |
4020 | return; | |
4021 | ||
65355d53 | 4022 | gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue); |
44de5aeb RK |
4023 | } |
4024 | \f | |
6de9cd9a DN |
4025 | #ifdef ENABLE_CHECKING |
4026 | /* Compare types A and B for a "close enough" match. */ | |
4027 | ||
4028 | static bool | |
4029 | cpt_same_type (tree a, tree b) | |
4030 | { | |
4031 | if (lang_hooks.types_compatible_p (a, b)) | |
4032 | return true; | |
4033 | ||
4034 | /* ??? The C++ FE decomposes METHOD_TYPES to FUNCTION_TYPES and doesn't | |
4035 | link them together. This routine is intended to catch type errors | |
4036 | that will affect the optimizers, and the optimizers don't add new | |
4037 | dereferences of function pointers, so ignore it. */ | |
4038 | if ((TREE_CODE (a) == FUNCTION_TYPE || TREE_CODE (a) == METHOD_TYPE) | |
4039 | && (TREE_CODE (b) == FUNCTION_TYPE || TREE_CODE (b) == METHOD_TYPE)) | |
4040 | return true; | |
4041 | ||
4042 | /* ??? The C FE pushes type qualifiers after the fact into the type of | |
4043 | the element from the type of the array. See build_unary_op's handling | |
4044 | of ADDR_EXPR. This seems wrong -- if we were going to do this, we | |
4045 | should have done it when creating the variable in the first place. | |
4046 | Alternately, why aren't the two array types made variants? */ | |
4047 | if (TREE_CODE (a) == ARRAY_TYPE && TREE_CODE (b) == ARRAY_TYPE) | |
4048 | return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b)); | |
4049 | ||
4050 | /* And because of those, we have to recurse down through pointers. */ | |
4051 | if (POINTER_TYPE_P (a) && POINTER_TYPE_P (b)) | |
4052 | return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b)); | |
4053 | ||
4054 | return false; | |
4055 | } | |
4056 | ||
4057 | /* Check for some cases of the front end missing cast expressions. | |
4058 | The type of a dereference should correspond to the pointer type; | |
4059 | similarly the type of an address should match its object. */ | |
4060 | ||
4061 | static tree | |
4062 | check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, | |
4063 | void *data ATTRIBUTE_UNUSED) | |
4064 | { | |
4065 | tree t = *tp; | |
4066 | tree ptype, otype, dtype; | |
4067 | ||
4068 | switch (TREE_CODE (t)) | |
4069 | { | |
4070 | case INDIRECT_REF: | |
4071 | case ARRAY_REF: | |
4072 | otype = TREE_TYPE (t); | |
4073 | ptype = TREE_TYPE (TREE_OPERAND (t, 0)); | |
4074 | dtype = TREE_TYPE (ptype); | |
4075 | if (!cpt_same_type (otype, dtype)) | |
4076 | abort (); | |
4077 | break; | |
4078 | ||
4079 | case ADDR_EXPR: | |
4080 | ptype = TREE_TYPE (t); | |
4081 | otype = TREE_TYPE (TREE_OPERAND (t, 0)); | |
4082 | dtype = TREE_TYPE (ptype); | |
4083 | if (!cpt_same_type (otype, dtype)) | |
4084 | { | |
44de5aeb RK |
4085 | /* &array is allowed to produce a pointer to the element, rather than |
4086 | a pointer to the array type. We must allow this in order to | |
4087 | properly represent assigning the address of an array in C into | |
4088 | pointer to the element type. */ | |
6de9cd9a DN |
4089 | if (TREE_CODE (otype) == ARRAY_TYPE |
4090 | && POINTER_TYPE_P (ptype) | |
4091 | && cpt_same_type (TREE_TYPE (otype), dtype)) | |
4092 | break; | |
4093 | abort (); | |
4094 | } | |
4095 | break; | |
4096 | ||
4097 | default: | |
4098 | return NULL_TREE; | |
4099 | } | |
4100 | ||
4101 | ||
4102 | return NULL_TREE; | |
4103 | } | |
4104 | #endif | |
4105 | ||
4106 | /* Gimplify the body of statements pointed by BODY_P. FNDECL is the | |
4107 | function decl containing BODY. */ | |
4108 | ||
4109 | void | |
4110 | gimplify_body (tree *body_p, tree fndecl) | |
4111 | { | |
4112 | location_t saved_location = input_location; | |
4113 | tree body; | |
4114 | ||
4115 | timevar_push (TV_TREE_GIMPLIFY); | |
4116 | push_gimplify_context (); | |
4117 | ||
44de5aeb RK |
4118 | /* Unshare most shared trees in the body and in that of any nested functions. |
4119 | It would seem we don't have to do this for nested functions because | |
4120 | they are supposed to be output and then the outer function gimplified | |
4121 | first, but the g++ front end doesn't always do it that way. */ | |
4122 | unshare_body (body_p, fndecl); | |
4123 | unvisit_body (body_p, fndecl); | |
6de9cd9a DN |
4124 | |
4125 | /* Make sure input_location isn't set to something wierd. */ | |
4126 | input_location = DECL_SOURCE_LOCATION (fndecl); | |
4127 | ||
4128 | /* Gimplify the function's body. */ | |
4129 | gimplify_stmt (body_p); | |
4130 | body = *body_p; | |
4131 | ||
4132 | /* Unshare again, in case gimplification was sloppy. */ | |
4133 | unshare_all_trees (body); | |
4134 | ||
be1ba3d1 RH |
4135 | if (!body) |
4136 | body = alloc_stmt_list (); | |
4137 | else if (TREE_CODE (body) == STATEMENT_LIST) | |
6de9cd9a DN |
4138 | { |
4139 | tree t = expr_only (*body_p); | |
4140 | if (t) | |
4141 | body = t; | |
4142 | } | |
44de5aeb RK |
4143 | |
4144 | /* If there isn't an outer BIND_EXPR, add one. */ | |
6de9cd9a DN |
4145 | if (TREE_CODE (body) != BIND_EXPR) |
4146 | { | |
4147 | tree b = build (BIND_EXPR, void_type_node, NULL_TREE, | |
4148 | NULL_TREE, NULL_TREE); | |
4149 | TREE_SIDE_EFFECTS (b) = 1; | |
be00f578 | 4150 | append_to_statement_list_force (body, &BIND_EXPR_BODY (b)); |
6de9cd9a DN |
4151 | body = b; |
4152 | } | |
4153 | *body_p = body; | |
4154 | ||
4155 | pop_gimplify_context (body); | |
4156 | ||
4157 | #ifdef ENABLE_CHECKING | |
4158 | walk_tree (body_p, check_pointer_types_r, NULL, NULL); | |
4159 | #endif | |
4160 | ||
4161 | timevar_pop (TV_TREE_GIMPLIFY); | |
4162 | input_location = saved_location; | |
4163 | } | |
4164 | ||
4165 | /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL | |
4166 | node for the function we want to gimplify. */ | |
4167 | ||
4168 | void | |
4169 | gimplify_function_tree (tree fndecl) | |
4170 | { | |
4171 | tree oldfn; | |
4172 | ||
4173 | oldfn = current_function_decl; | |
4174 | current_function_decl = fndecl; | |
4175 | ||
4176 | gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl); | |
4177 | ||
4178 | /* If we're instrumenting function entry/exit, then prepend the call to | |
4179 | the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to | |
4180 | catch the exit hook. */ | |
4181 | /* ??? Add some way to ignore exceptions for this TFE. */ | |
4182 | if (flag_instrument_function_entry_exit | |
4183 | && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)) | |
4184 | { | |
4185 | tree tf, x, bind; | |
4186 | ||
4187 | tf = build (TRY_FINALLY_EXPR, void_type_node, NULL, NULL); | |
4188 | TREE_SIDE_EFFECTS (tf) = 1; | |
4189 | x = DECL_SAVED_TREE (fndecl); | |
4190 | append_to_statement_list (x, &TREE_OPERAND (tf, 0)); | |
4191 | x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT]; | |
4192 | x = build_function_call_expr (x, NULL); | |
4193 | append_to_statement_list (x, &TREE_OPERAND (tf, 1)); | |
4194 | ||
4195 | bind = build (BIND_EXPR, void_type_node, NULL, NULL, NULL); | |
4196 | TREE_SIDE_EFFECTS (bind) = 1; | |
4197 | x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER]; | |
4198 | x = build_function_call_expr (x, NULL); | |
4199 | append_to_statement_list (x, &BIND_EXPR_BODY (bind)); | |
4200 | append_to_statement_list (tf, &BIND_EXPR_BODY (bind)); | |
4201 | ||
4202 | DECL_SAVED_TREE (fndecl) = bind; | |
4203 | } | |
4204 | ||
4205 | current_function_decl = oldfn; | |
4206 | } | |
4207 | ||
4208 | #include "gt-gimplify.h" |