1e4b17023SJohn Marino /* Tree lowering pass. This pass converts the GENERIC functions-as-trees
2e4b17023SJohn Marino tree representation into the GIMPLE form.
3e4b17023SJohn Marino Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
4e4b17023SJohn Marino 2012 Free Software Foundation, Inc.
5e4b17023SJohn Marino Major work done by Sebastian Pop <s.pop@laposte.net>,
6e4b17023SJohn Marino Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
7e4b17023SJohn Marino
8e4b17023SJohn Marino This file is part of GCC.
9e4b17023SJohn Marino
10e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
11e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
12e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
13e4b17023SJohn Marino version.
14e4b17023SJohn Marino
15e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
17e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18e4b17023SJohn Marino for more details.
19e4b17023SJohn Marino
20e4b17023SJohn Marino You should have received a copy of the GNU General Public License
21e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
22e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
23e4b17023SJohn Marino
24e4b17023SJohn Marino #include "config.h"
25e4b17023SJohn Marino #include "system.h"
26e4b17023SJohn Marino #include "coretypes.h"
27e4b17023SJohn Marino #include "tm.h"
28e4b17023SJohn Marino #include "tree.h"
29e4b17023SJohn Marino #include "gimple.h"
30e4b17023SJohn Marino #include "tree-iterator.h"
31e4b17023SJohn Marino #include "tree-inline.h"
32e4b17023SJohn Marino #include "tree-pretty-print.h"
33e4b17023SJohn Marino #include "langhooks.h"
34e4b17023SJohn Marino #include "tree-flow.h"
35e4b17023SJohn Marino #include "cgraph.h"
36e4b17023SJohn Marino #include "timevar.h"
37e4b17023SJohn Marino #include "hashtab.h"
38e4b17023SJohn Marino #include "flags.h"
39e4b17023SJohn Marino #include "function.h"
40e4b17023SJohn Marino #include "output.h"
41e4b17023SJohn Marino #include "ggc.h"
42e4b17023SJohn Marino #include "diagnostic-core.h"
43e4b17023SJohn Marino #include "target.h"
44e4b17023SJohn Marino #include "pointer-set.h"
45e4b17023SJohn Marino #include "splay-tree.h"
46e4b17023SJohn Marino #include "vec.h"
47e4b17023SJohn Marino #include "gimple.h"
48e4b17023SJohn Marino #include "tree-pass.h"
49e4b17023SJohn Marino
50e4b17023SJohn Marino #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name. */
51e4b17023SJohn Marino #include "expr.h" /* FIXME: for can_move_by_pieces
52e4b17023SJohn Marino and STACK_CHECK_MAX_VAR_SIZE. */
53e4b17023SJohn Marino
54e4b17023SJohn Marino enum gimplify_omp_var_data
55e4b17023SJohn Marino {
56e4b17023SJohn Marino GOVD_SEEN = 1,
57e4b17023SJohn Marino GOVD_EXPLICIT = 2,
58e4b17023SJohn Marino GOVD_SHARED = 4,
59e4b17023SJohn Marino GOVD_PRIVATE = 8,
60e4b17023SJohn Marino GOVD_FIRSTPRIVATE = 16,
61e4b17023SJohn Marino GOVD_LASTPRIVATE = 32,
62e4b17023SJohn Marino GOVD_REDUCTION = 64,
63e4b17023SJohn Marino GOVD_LOCAL = 128,
64e4b17023SJohn Marino GOVD_DEBUG_PRIVATE = 256,
65e4b17023SJohn Marino GOVD_PRIVATE_OUTER_REF = 512,
66e4b17023SJohn Marino GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
67e4b17023SJohn Marino | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LOCAL)
68e4b17023SJohn Marino };
69e4b17023SJohn Marino
70e4b17023SJohn Marino
71e4b17023SJohn Marino enum omp_region_type
72e4b17023SJohn Marino {
73e4b17023SJohn Marino ORT_WORKSHARE = 0,
74e4b17023SJohn Marino ORT_PARALLEL = 2,
75e4b17023SJohn Marino ORT_COMBINED_PARALLEL = 3,
76e4b17023SJohn Marino ORT_TASK = 4,
77e4b17023SJohn Marino ORT_UNTIED_TASK = 5
78e4b17023SJohn Marino };
79e4b17023SJohn Marino
80e4b17023SJohn Marino struct gimplify_omp_ctx
81e4b17023SJohn Marino {
82e4b17023SJohn Marino struct gimplify_omp_ctx *outer_context;
83e4b17023SJohn Marino splay_tree variables;
84e4b17023SJohn Marino struct pointer_set_t *privatized_types;
85e4b17023SJohn Marino location_t location;
86e4b17023SJohn Marino enum omp_clause_default_kind default_kind;
87e4b17023SJohn Marino enum omp_region_type region_type;
88e4b17023SJohn Marino };
89e4b17023SJohn Marino
90e4b17023SJohn Marino static struct gimplify_ctx *gimplify_ctxp;
91e4b17023SJohn Marino static struct gimplify_omp_ctx *gimplify_omp_ctxp;
92e4b17023SJohn Marino
93e4b17023SJohn Marino
94e4b17023SJohn Marino /* Formal (expression) temporary table handling: multiple occurrences of
95e4b17023SJohn Marino the same scalar expression are evaluated into the same temporary. */
96e4b17023SJohn Marino
97e4b17023SJohn Marino typedef struct gimple_temp_hash_elt
98e4b17023SJohn Marino {
99e4b17023SJohn Marino tree val; /* Key */
100e4b17023SJohn Marino tree temp; /* Value */
101e4b17023SJohn Marino } elt_t;
102e4b17023SJohn Marino
103e4b17023SJohn Marino /* Forward declaration. */
104e4b17023SJohn Marino static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
105e4b17023SJohn Marino
106e4b17023SJohn Marino /* Mark X addressable. Unlike the langhook we expect X to be in gimple
107e4b17023SJohn Marino form and we don't do any syntax checking. */
108e4b17023SJohn Marino
109e4b17023SJohn Marino void
mark_addressable(tree x)110e4b17023SJohn Marino mark_addressable (tree x)
111e4b17023SJohn Marino {
112e4b17023SJohn Marino while (handled_component_p (x))
113e4b17023SJohn Marino x = TREE_OPERAND (x, 0);
114e4b17023SJohn Marino if (TREE_CODE (x) == MEM_REF
115e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
116e4b17023SJohn Marino x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
117e4b17023SJohn Marino if (TREE_CODE (x) != VAR_DECL
118e4b17023SJohn Marino && TREE_CODE (x) != PARM_DECL
119e4b17023SJohn Marino && TREE_CODE (x) != RESULT_DECL)
120e4b17023SJohn Marino return;
121e4b17023SJohn Marino TREE_ADDRESSABLE (x) = 1;
1225ce9237cSJohn Marino
1235ce9237cSJohn Marino /* Also mark the artificial SSA_NAME that points to the partition of X. */
1245ce9237cSJohn Marino if (TREE_CODE (x) == VAR_DECL
1255ce9237cSJohn Marino && !DECL_EXTERNAL (x)
1265ce9237cSJohn Marino && !TREE_STATIC (x)
1275ce9237cSJohn Marino && cfun->gimple_df != NULL
1285ce9237cSJohn Marino && cfun->gimple_df->decls_to_pointers != NULL)
1295ce9237cSJohn Marino {
1305ce9237cSJohn Marino void *namep
1315ce9237cSJohn Marino = pointer_map_contains (cfun->gimple_df->decls_to_pointers, x);
1325ce9237cSJohn Marino if (namep)
1335ce9237cSJohn Marino TREE_ADDRESSABLE (*(tree *)namep) = 1;
1345ce9237cSJohn Marino }
135e4b17023SJohn Marino }
136e4b17023SJohn Marino
137e4b17023SJohn Marino /* Return a hash value for a formal temporary table entry. */
138e4b17023SJohn Marino
139e4b17023SJohn Marino static hashval_t
gimple_tree_hash(const void * p)140e4b17023SJohn Marino gimple_tree_hash (const void *p)
141e4b17023SJohn Marino {
142e4b17023SJohn Marino tree t = ((const elt_t *) p)->val;
143e4b17023SJohn Marino return iterative_hash_expr (t, 0);
144e4b17023SJohn Marino }
145e4b17023SJohn Marino
146e4b17023SJohn Marino /* Compare two formal temporary table entries. */
147e4b17023SJohn Marino
148e4b17023SJohn Marino static int
gimple_tree_eq(const void * p1,const void * p2)149e4b17023SJohn Marino gimple_tree_eq (const void *p1, const void *p2)
150e4b17023SJohn Marino {
151e4b17023SJohn Marino tree t1 = ((const elt_t *) p1)->val;
152e4b17023SJohn Marino tree t2 = ((const elt_t *) p2)->val;
153e4b17023SJohn Marino enum tree_code code = TREE_CODE (t1);
154e4b17023SJohn Marino
155e4b17023SJohn Marino if (TREE_CODE (t2) != code
156e4b17023SJohn Marino || TREE_TYPE (t1) != TREE_TYPE (t2))
157e4b17023SJohn Marino return 0;
158e4b17023SJohn Marino
159e4b17023SJohn Marino if (!operand_equal_p (t1, t2, 0))
160e4b17023SJohn Marino return 0;
161e4b17023SJohn Marino
162e4b17023SJohn Marino #ifdef ENABLE_CHECKING
163e4b17023SJohn Marino /* Only allow them to compare equal if they also hash equal; otherwise
164e4b17023SJohn Marino results are nondeterminate, and we fail bootstrap comparison. */
165e4b17023SJohn Marino gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
166e4b17023SJohn Marino #endif
167e4b17023SJohn Marino
168e4b17023SJohn Marino return 1;
169e4b17023SJohn Marino }
170e4b17023SJohn Marino
171e4b17023SJohn Marino /* Link gimple statement GS to the end of the sequence *SEQ_P. If
172e4b17023SJohn Marino *SEQ_P is NULL, a new sequence is allocated. This function is
173e4b17023SJohn Marino similar to gimple_seq_add_stmt, but does not scan the operands.
174e4b17023SJohn Marino During gimplification, we need to manipulate statement sequences
175e4b17023SJohn Marino before the def/use vectors have been constructed. */
176e4b17023SJohn Marino
177e4b17023SJohn Marino void
gimple_seq_add_stmt_without_update(gimple_seq * seq_p,gimple gs)178e4b17023SJohn Marino gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
179e4b17023SJohn Marino {
180e4b17023SJohn Marino gimple_stmt_iterator si;
181e4b17023SJohn Marino
182e4b17023SJohn Marino if (gs == NULL)
183e4b17023SJohn Marino return;
184e4b17023SJohn Marino
185e4b17023SJohn Marino if (*seq_p == NULL)
186e4b17023SJohn Marino *seq_p = gimple_seq_alloc ();
187e4b17023SJohn Marino
188e4b17023SJohn Marino si = gsi_last (*seq_p);
189e4b17023SJohn Marino
190e4b17023SJohn Marino gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
191e4b17023SJohn Marino }
192e4b17023SJohn Marino
193e4b17023SJohn Marino /* Shorter alias name for the above function for use in gimplify.c
194e4b17023SJohn Marino only. */
195e4b17023SJohn Marino
196e4b17023SJohn Marino static inline void
gimplify_seq_add_stmt(gimple_seq * seq_p,gimple gs)197e4b17023SJohn Marino gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
198e4b17023SJohn Marino {
199e4b17023SJohn Marino gimple_seq_add_stmt_without_update (seq_p, gs);
200e4b17023SJohn Marino }
201e4b17023SJohn Marino
202e4b17023SJohn Marino /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
203e4b17023SJohn Marino NULL, a new sequence is allocated. This function is
204e4b17023SJohn Marino similar to gimple_seq_add_seq, but does not scan the operands.
205e4b17023SJohn Marino During gimplification, we need to manipulate statement sequences
206e4b17023SJohn Marino before the def/use vectors have been constructed. */
207e4b17023SJohn Marino
208e4b17023SJohn Marino static void
gimplify_seq_add_seq(gimple_seq * dst_p,gimple_seq src)209e4b17023SJohn Marino gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
210e4b17023SJohn Marino {
211e4b17023SJohn Marino gimple_stmt_iterator si;
212e4b17023SJohn Marino
213e4b17023SJohn Marino if (src == NULL)
214e4b17023SJohn Marino return;
215e4b17023SJohn Marino
216e4b17023SJohn Marino if (*dst_p == NULL)
217e4b17023SJohn Marino *dst_p = gimple_seq_alloc ();
218e4b17023SJohn Marino
219e4b17023SJohn Marino si = gsi_last (*dst_p);
220e4b17023SJohn Marino gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
221e4b17023SJohn Marino }
222e4b17023SJohn Marino
223e4b17023SJohn Marino /* Set up a context for the gimplifier. */
224e4b17023SJohn Marino
225e4b17023SJohn Marino void
push_gimplify_context(struct gimplify_ctx * c)226e4b17023SJohn Marino push_gimplify_context (struct gimplify_ctx *c)
227e4b17023SJohn Marino {
228e4b17023SJohn Marino memset (c, '\0', sizeof (*c));
229e4b17023SJohn Marino c->prev_context = gimplify_ctxp;
230e4b17023SJohn Marino gimplify_ctxp = c;
231e4b17023SJohn Marino }
232e4b17023SJohn Marino
233e4b17023SJohn Marino /* Tear down a context for the gimplifier. If BODY is non-null, then
234e4b17023SJohn Marino put the temporaries into the outer BIND_EXPR. Otherwise, put them
235e4b17023SJohn Marino in the local_decls.
236e4b17023SJohn Marino
237e4b17023SJohn Marino BODY is not a sequence, but the first tuple in a sequence. */
238e4b17023SJohn Marino
239e4b17023SJohn Marino void
pop_gimplify_context(gimple body)240e4b17023SJohn Marino pop_gimplify_context (gimple body)
241e4b17023SJohn Marino {
242e4b17023SJohn Marino struct gimplify_ctx *c = gimplify_ctxp;
243e4b17023SJohn Marino
244e4b17023SJohn Marino gcc_assert (c && (c->bind_expr_stack == NULL
245e4b17023SJohn Marino || VEC_empty (gimple, c->bind_expr_stack)));
246e4b17023SJohn Marino VEC_free (gimple, heap, c->bind_expr_stack);
247e4b17023SJohn Marino gimplify_ctxp = c->prev_context;
248e4b17023SJohn Marino
249e4b17023SJohn Marino if (body)
250e4b17023SJohn Marino declare_vars (c->temps, body, false);
251e4b17023SJohn Marino else
252e4b17023SJohn Marino record_vars (c->temps);
253e4b17023SJohn Marino
254e4b17023SJohn Marino if (c->temp_htab)
255e4b17023SJohn Marino htab_delete (c->temp_htab);
256e4b17023SJohn Marino }
257e4b17023SJohn Marino
258e4b17023SJohn Marino /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
259e4b17023SJohn Marino
260e4b17023SJohn Marino static void
gimple_push_bind_expr(gimple gimple_bind)261e4b17023SJohn Marino gimple_push_bind_expr (gimple gimple_bind)
262e4b17023SJohn Marino {
263e4b17023SJohn Marino if (gimplify_ctxp->bind_expr_stack == NULL)
264e4b17023SJohn Marino gimplify_ctxp->bind_expr_stack = VEC_alloc (gimple, heap, 8);
265e4b17023SJohn Marino VEC_safe_push (gimple, heap, gimplify_ctxp->bind_expr_stack, gimple_bind);
266e4b17023SJohn Marino }
267e4b17023SJohn Marino
268e4b17023SJohn Marino /* Pop the first element off the stack of bindings. */
269e4b17023SJohn Marino
270e4b17023SJohn Marino static void
gimple_pop_bind_expr(void)271e4b17023SJohn Marino gimple_pop_bind_expr (void)
272e4b17023SJohn Marino {
273e4b17023SJohn Marino VEC_pop (gimple, gimplify_ctxp->bind_expr_stack);
274e4b17023SJohn Marino }
275e4b17023SJohn Marino
276e4b17023SJohn Marino /* Return the first element of the stack of bindings. */
277e4b17023SJohn Marino
278e4b17023SJohn Marino gimple
gimple_current_bind_expr(void)279e4b17023SJohn Marino gimple_current_bind_expr (void)
280e4b17023SJohn Marino {
281e4b17023SJohn Marino return VEC_last (gimple, gimplify_ctxp->bind_expr_stack);
282e4b17023SJohn Marino }
283e4b17023SJohn Marino
284e4b17023SJohn Marino /* Return the stack of bindings created during gimplification. */
285e4b17023SJohn Marino
VEC(gimple,heap)286e4b17023SJohn Marino VEC(gimple, heap) *
287e4b17023SJohn Marino gimple_bind_expr_stack (void)
288e4b17023SJohn Marino {
289e4b17023SJohn Marino return gimplify_ctxp->bind_expr_stack;
290e4b17023SJohn Marino }
291e4b17023SJohn Marino
292e4b17023SJohn Marino /* Return true iff there is a COND_EXPR between us and the innermost
293e4b17023SJohn Marino CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
294e4b17023SJohn Marino
295e4b17023SJohn Marino static bool
gimple_conditional_context(void)296e4b17023SJohn Marino gimple_conditional_context (void)
297e4b17023SJohn Marino {
298e4b17023SJohn Marino return gimplify_ctxp->conditions > 0;
299e4b17023SJohn Marino }
300e4b17023SJohn Marino
301e4b17023SJohn Marino /* Note that we've entered a COND_EXPR. */
302e4b17023SJohn Marino
303e4b17023SJohn Marino static void
gimple_push_condition(void)304e4b17023SJohn Marino gimple_push_condition (void)
305e4b17023SJohn Marino {
306e4b17023SJohn Marino #ifdef ENABLE_GIMPLE_CHECKING
307e4b17023SJohn Marino if (gimplify_ctxp->conditions == 0)
308e4b17023SJohn Marino gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
309e4b17023SJohn Marino #endif
310e4b17023SJohn Marino ++(gimplify_ctxp->conditions);
311e4b17023SJohn Marino }
312e4b17023SJohn Marino
313e4b17023SJohn Marino /* Note that we've left a COND_EXPR. If we're back at unconditional scope
314e4b17023SJohn Marino now, add any conditional cleanups we've seen to the prequeue. */
315e4b17023SJohn Marino
316e4b17023SJohn Marino static void
gimple_pop_condition(gimple_seq * pre_p)317e4b17023SJohn Marino gimple_pop_condition (gimple_seq *pre_p)
318e4b17023SJohn Marino {
319e4b17023SJohn Marino int conds = --(gimplify_ctxp->conditions);
320e4b17023SJohn Marino
321e4b17023SJohn Marino gcc_assert (conds >= 0);
322e4b17023SJohn Marino if (conds == 0)
323e4b17023SJohn Marino {
324e4b17023SJohn Marino gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
325e4b17023SJohn Marino gimplify_ctxp->conditional_cleanups = NULL;
326e4b17023SJohn Marino }
327e4b17023SJohn Marino }
328e4b17023SJohn Marino
329e4b17023SJohn Marino /* A stable comparison routine for use with splay trees and DECLs. */
330e4b17023SJohn Marino
331e4b17023SJohn Marino static int
splay_tree_compare_decl_uid(splay_tree_key xa,splay_tree_key xb)332e4b17023SJohn Marino splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
333e4b17023SJohn Marino {
334e4b17023SJohn Marino tree a = (tree) xa;
335e4b17023SJohn Marino tree b = (tree) xb;
336e4b17023SJohn Marino
337e4b17023SJohn Marino return DECL_UID (a) - DECL_UID (b);
338e4b17023SJohn Marino }
339e4b17023SJohn Marino
340e4b17023SJohn Marino /* Create a new omp construct that deals with variable remapping. */
341e4b17023SJohn Marino
342e4b17023SJohn Marino static struct gimplify_omp_ctx *
new_omp_context(enum omp_region_type region_type)343e4b17023SJohn Marino new_omp_context (enum omp_region_type region_type)
344e4b17023SJohn Marino {
345e4b17023SJohn Marino struct gimplify_omp_ctx *c;
346e4b17023SJohn Marino
347e4b17023SJohn Marino c = XCNEW (struct gimplify_omp_ctx);
348e4b17023SJohn Marino c->outer_context = gimplify_omp_ctxp;
349e4b17023SJohn Marino c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
350e4b17023SJohn Marino c->privatized_types = pointer_set_create ();
351e4b17023SJohn Marino c->location = input_location;
352e4b17023SJohn Marino c->region_type = region_type;
353e4b17023SJohn Marino if ((region_type & ORT_TASK) == 0)
354e4b17023SJohn Marino c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
355e4b17023SJohn Marino else
356e4b17023SJohn Marino c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
357e4b17023SJohn Marino
358e4b17023SJohn Marino return c;
359e4b17023SJohn Marino }
360e4b17023SJohn Marino
361e4b17023SJohn Marino /* Destroy an omp construct that deals with variable remapping. */
362e4b17023SJohn Marino
363e4b17023SJohn Marino static void
delete_omp_context(struct gimplify_omp_ctx * c)364e4b17023SJohn Marino delete_omp_context (struct gimplify_omp_ctx *c)
365e4b17023SJohn Marino {
366e4b17023SJohn Marino splay_tree_delete (c->variables);
367e4b17023SJohn Marino pointer_set_destroy (c->privatized_types);
368e4b17023SJohn Marino XDELETE (c);
369e4b17023SJohn Marino }
370e4b17023SJohn Marino
371e4b17023SJohn Marino static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
372e4b17023SJohn Marino static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
373e4b17023SJohn Marino
374e4b17023SJohn Marino /* Both gimplify the statement T and append it to *SEQ_P. This function
375e4b17023SJohn Marino behaves exactly as gimplify_stmt, but you don't have to pass T as a
376e4b17023SJohn Marino reference. */
377e4b17023SJohn Marino
378e4b17023SJohn Marino void
gimplify_and_add(tree t,gimple_seq * seq_p)379e4b17023SJohn Marino gimplify_and_add (tree t, gimple_seq *seq_p)
380e4b17023SJohn Marino {
381e4b17023SJohn Marino gimplify_stmt (&t, seq_p);
382e4b17023SJohn Marino }
383e4b17023SJohn Marino
384e4b17023SJohn Marino /* Gimplify statement T into sequence *SEQ_P, and return the first
385e4b17023SJohn Marino tuple in the sequence of generated tuples for this statement.
386e4b17023SJohn Marino Return NULL if gimplifying T produced no tuples. */
387e4b17023SJohn Marino
388e4b17023SJohn Marino static gimple
gimplify_and_return_first(tree t,gimple_seq * seq_p)389e4b17023SJohn Marino gimplify_and_return_first (tree t, gimple_seq *seq_p)
390e4b17023SJohn Marino {
391e4b17023SJohn Marino gimple_stmt_iterator last = gsi_last (*seq_p);
392e4b17023SJohn Marino
393e4b17023SJohn Marino gimplify_and_add (t, seq_p);
394e4b17023SJohn Marino
395e4b17023SJohn Marino if (!gsi_end_p (last))
396e4b17023SJohn Marino {
397e4b17023SJohn Marino gsi_next (&last);
398e4b17023SJohn Marino return gsi_stmt (last);
399e4b17023SJohn Marino }
400e4b17023SJohn Marino else
401e4b17023SJohn Marino return gimple_seq_first_stmt (*seq_p);
402e4b17023SJohn Marino }
403e4b17023SJohn Marino
404e4b17023SJohn Marino /* Strip off a legitimate source ending from the input string NAME of
405e4b17023SJohn Marino length LEN. Rather than having to know the names used by all of
406e4b17023SJohn Marino our front ends, we strip off an ending of a period followed by
407e4b17023SJohn Marino up to five characters. (Java uses ".class".) */
408e4b17023SJohn Marino
409e4b17023SJohn Marino static inline void
remove_suffix(char * name,int len)410e4b17023SJohn Marino remove_suffix (char *name, int len)
411e4b17023SJohn Marino {
412e4b17023SJohn Marino int i;
413e4b17023SJohn Marino
414e4b17023SJohn Marino for (i = 2; i < 8 && len > i; i++)
415e4b17023SJohn Marino {
416e4b17023SJohn Marino if (name[len - i] == '.')
417e4b17023SJohn Marino {
418e4b17023SJohn Marino name[len - i] = '\0';
419e4b17023SJohn Marino break;
420e4b17023SJohn Marino }
421e4b17023SJohn Marino }
422e4b17023SJohn Marino }
423e4b17023SJohn Marino
424e4b17023SJohn Marino /* Create a new temporary name with PREFIX. Return an identifier. */
425e4b17023SJohn Marino
426e4b17023SJohn Marino static GTY(()) unsigned int tmp_var_id_num;
427e4b17023SJohn Marino
428e4b17023SJohn Marino tree
create_tmp_var_name(const char * prefix)429e4b17023SJohn Marino create_tmp_var_name (const char *prefix)
430e4b17023SJohn Marino {
431e4b17023SJohn Marino char *tmp_name;
432e4b17023SJohn Marino
433e4b17023SJohn Marino if (prefix)
434e4b17023SJohn Marino {
435e4b17023SJohn Marino char *preftmp = ASTRDUP (prefix);
436e4b17023SJohn Marino
437e4b17023SJohn Marino remove_suffix (preftmp, strlen (preftmp));
438e4b17023SJohn Marino clean_symbol_name (preftmp);
439e4b17023SJohn Marino
440e4b17023SJohn Marino prefix = preftmp;
441e4b17023SJohn Marino }
442e4b17023SJohn Marino
443e4b17023SJohn Marino ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "T", tmp_var_id_num++);
444e4b17023SJohn Marino return get_identifier (tmp_name);
445e4b17023SJohn Marino }
446e4b17023SJohn Marino
447e4b17023SJohn Marino /* Create a new temporary variable declaration of type TYPE.
448e4b17023SJohn Marino Do NOT push it into the current binding. */
449e4b17023SJohn Marino
450e4b17023SJohn Marino tree
create_tmp_var_raw(tree type,const char * prefix)451e4b17023SJohn Marino create_tmp_var_raw (tree type, const char *prefix)
452e4b17023SJohn Marino {
453e4b17023SJohn Marino tree tmp_var;
454e4b17023SJohn Marino
455e4b17023SJohn Marino tmp_var = build_decl (input_location,
456e4b17023SJohn Marino VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
457e4b17023SJohn Marino type);
458e4b17023SJohn Marino
459e4b17023SJohn Marino /* The variable was declared by the compiler. */
460e4b17023SJohn Marino DECL_ARTIFICIAL (tmp_var) = 1;
461e4b17023SJohn Marino /* And we don't want debug info for it. */
462e4b17023SJohn Marino DECL_IGNORED_P (tmp_var) = 1;
463e4b17023SJohn Marino
464e4b17023SJohn Marino /* Make the variable writable. */
465e4b17023SJohn Marino TREE_READONLY (tmp_var) = 0;
466e4b17023SJohn Marino
467e4b17023SJohn Marino DECL_EXTERNAL (tmp_var) = 0;
468e4b17023SJohn Marino TREE_STATIC (tmp_var) = 0;
469e4b17023SJohn Marino TREE_USED (tmp_var) = 1;
470e4b17023SJohn Marino
471e4b17023SJohn Marino return tmp_var;
472e4b17023SJohn Marino }
473e4b17023SJohn Marino
474e4b17023SJohn Marino /* Create a new temporary variable declaration of type TYPE. DO push the
475e4b17023SJohn Marino variable into the current binding. Further, assume that this is called
476e4b17023SJohn Marino only from gimplification or optimization, at which point the creation of
477e4b17023SJohn Marino certain types are bugs. */
478e4b17023SJohn Marino
479e4b17023SJohn Marino tree
create_tmp_var(tree type,const char * prefix)480e4b17023SJohn Marino create_tmp_var (tree type, const char *prefix)
481e4b17023SJohn Marino {
482e4b17023SJohn Marino tree tmp_var;
483e4b17023SJohn Marino
484e4b17023SJohn Marino /* We don't allow types that are addressable (meaning we can't make copies),
485e4b17023SJohn Marino or incomplete. We also used to reject every variable size objects here,
486e4b17023SJohn Marino but now support those for which a constant upper bound can be obtained.
487e4b17023SJohn Marino The processing for variable sizes is performed in gimple_add_tmp_var,
488e4b17023SJohn Marino point at which it really matters and possibly reached via paths not going
489e4b17023SJohn Marino through this function, e.g. after direct calls to create_tmp_var_raw. */
490e4b17023SJohn Marino gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
491e4b17023SJohn Marino
492e4b17023SJohn Marino tmp_var = create_tmp_var_raw (type, prefix);
493e4b17023SJohn Marino gimple_add_tmp_var (tmp_var);
494e4b17023SJohn Marino return tmp_var;
495e4b17023SJohn Marino }
496e4b17023SJohn Marino
497e4b17023SJohn Marino /* Create a new temporary variable declaration of type TYPE by calling
498e4b17023SJohn Marino create_tmp_var and if TYPE is a vector or a complex number, mark the new
499e4b17023SJohn Marino temporary as gimple register. */
500e4b17023SJohn Marino
501e4b17023SJohn Marino tree
create_tmp_reg(tree type,const char * prefix)502e4b17023SJohn Marino create_tmp_reg (tree type, const char *prefix)
503e4b17023SJohn Marino {
504e4b17023SJohn Marino tree tmp;
505e4b17023SJohn Marino
506e4b17023SJohn Marino tmp = create_tmp_var (type, prefix);
507e4b17023SJohn Marino if (TREE_CODE (type) == COMPLEX_TYPE
508e4b17023SJohn Marino || TREE_CODE (type) == VECTOR_TYPE)
509e4b17023SJohn Marino DECL_GIMPLE_REG_P (tmp) = 1;
510e4b17023SJohn Marino
511e4b17023SJohn Marino return tmp;
512e4b17023SJohn Marino }
513e4b17023SJohn Marino
514e4b17023SJohn Marino /* Create a temporary with a name derived from VAL. Subroutine of
515e4b17023SJohn Marino lookup_tmp_var; nobody else should call this function. */
516e4b17023SJohn Marino
517e4b17023SJohn Marino static inline tree
create_tmp_from_val(tree val)518e4b17023SJohn Marino create_tmp_from_val (tree val)
519e4b17023SJohn Marino {
520e4b17023SJohn Marino /* Drop all qualifiers and address-space information from the value type. */
521e4b17023SJohn Marino return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
522e4b17023SJohn Marino }
523e4b17023SJohn Marino
524e4b17023SJohn Marino /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
525e4b17023SJohn Marino an existing expression temporary. */
526e4b17023SJohn Marino
527e4b17023SJohn Marino static tree
lookup_tmp_var(tree val,bool is_formal)528e4b17023SJohn Marino lookup_tmp_var (tree val, bool is_formal)
529e4b17023SJohn Marino {
530e4b17023SJohn Marino tree ret;
531e4b17023SJohn Marino
532e4b17023SJohn Marino /* If not optimizing, never really reuse a temporary. local-alloc
533e4b17023SJohn Marino won't allocate any variable that is used in more than one basic
534e4b17023SJohn Marino block, which means it will go into memory, causing much extra
535e4b17023SJohn Marino work in reload and final and poorer code generation, outweighing
536e4b17023SJohn Marino the extra memory allocation here. */
537e4b17023SJohn Marino if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
538e4b17023SJohn Marino ret = create_tmp_from_val (val);
539e4b17023SJohn Marino else
540e4b17023SJohn Marino {
541e4b17023SJohn Marino elt_t elt, *elt_p;
542e4b17023SJohn Marino void **slot;
543e4b17023SJohn Marino
544e4b17023SJohn Marino elt.val = val;
545e4b17023SJohn Marino if (gimplify_ctxp->temp_htab == NULL)
546e4b17023SJohn Marino gimplify_ctxp->temp_htab
547e4b17023SJohn Marino = htab_create (1000, gimple_tree_hash, gimple_tree_eq, free);
548e4b17023SJohn Marino slot = htab_find_slot (gimplify_ctxp->temp_htab, (void *)&elt, INSERT);
549e4b17023SJohn Marino if (*slot == NULL)
550e4b17023SJohn Marino {
551e4b17023SJohn Marino elt_p = XNEW (elt_t);
552e4b17023SJohn Marino elt_p->val = val;
553e4b17023SJohn Marino elt_p->temp = ret = create_tmp_from_val (val);
554e4b17023SJohn Marino *slot = (void *) elt_p;
555e4b17023SJohn Marino }
556e4b17023SJohn Marino else
557e4b17023SJohn Marino {
558e4b17023SJohn Marino elt_p = (elt_t *) *slot;
559e4b17023SJohn Marino ret = elt_p->temp;
560e4b17023SJohn Marino }
561e4b17023SJohn Marino }
562e4b17023SJohn Marino
563e4b17023SJohn Marino return ret;
564e4b17023SJohn Marino }
565e4b17023SJohn Marino
566e4b17023SJohn Marino /* Return true if T is a CALL_EXPR or an expression that can be
567e4b17023SJohn Marino assigned to a temporary. Note that this predicate should only be
568e4b17023SJohn Marino used during gimplification. See the rationale for this in
569e4b17023SJohn Marino gimplify_modify_expr. */
570e4b17023SJohn Marino
571e4b17023SJohn Marino static bool
is_gimple_reg_rhs_or_call(tree t)572e4b17023SJohn Marino is_gimple_reg_rhs_or_call (tree t)
573e4b17023SJohn Marino {
574e4b17023SJohn Marino return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
575e4b17023SJohn Marino || TREE_CODE (t) == CALL_EXPR);
576e4b17023SJohn Marino }
577e4b17023SJohn Marino
578e4b17023SJohn Marino /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
579e4b17023SJohn Marino this predicate should only be used during gimplification. See the
580e4b17023SJohn Marino rationale for this in gimplify_modify_expr. */
581e4b17023SJohn Marino
582e4b17023SJohn Marino static bool
is_gimple_mem_rhs_or_call(tree t)583e4b17023SJohn Marino is_gimple_mem_rhs_or_call (tree t)
584e4b17023SJohn Marino {
585e4b17023SJohn Marino /* If we're dealing with a renamable type, either source or dest must be
586e4b17023SJohn Marino a renamed variable. */
587e4b17023SJohn Marino if (is_gimple_reg_type (TREE_TYPE (t)))
588e4b17023SJohn Marino return is_gimple_val (t);
589e4b17023SJohn Marino else
590e4b17023SJohn Marino return (is_gimple_val (t) || is_gimple_lvalue (t)
591e4b17023SJohn Marino || TREE_CODE (t) == CALL_EXPR);
592e4b17023SJohn Marino }
593e4b17023SJohn Marino
594e4b17023SJohn Marino /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
595e4b17023SJohn Marino
596e4b17023SJohn Marino static tree
internal_get_tmp_var(tree val,gimple_seq * pre_p,gimple_seq * post_p,bool is_formal)597e4b17023SJohn Marino internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
598e4b17023SJohn Marino bool is_formal)
599e4b17023SJohn Marino {
600e4b17023SJohn Marino tree t, mod;
601e4b17023SJohn Marino
602e4b17023SJohn Marino /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
603e4b17023SJohn Marino can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
604e4b17023SJohn Marino gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
605e4b17023SJohn Marino fb_rvalue);
606e4b17023SJohn Marino
607e4b17023SJohn Marino t = lookup_tmp_var (val, is_formal);
608e4b17023SJohn Marino
609e4b17023SJohn Marino if (is_formal
610e4b17023SJohn Marino && (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
611e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE))
612e4b17023SJohn Marino DECL_GIMPLE_REG_P (t) = 1;
613e4b17023SJohn Marino
614e4b17023SJohn Marino mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
615e4b17023SJohn Marino
616e4b17023SJohn Marino SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val));
617e4b17023SJohn Marino
618e4b17023SJohn Marino /* gimplify_modify_expr might want to reduce this further. */
619e4b17023SJohn Marino gimplify_and_add (mod, pre_p);
620e4b17023SJohn Marino ggc_free (mod);
621e4b17023SJohn Marino
622e4b17023SJohn Marino /* If we're gimplifying into ssa, gimplify_modify_expr will have
623e4b17023SJohn Marino given our temporary an SSA name. Find and return it. */
624e4b17023SJohn Marino if (gimplify_ctxp->into_ssa)
625e4b17023SJohn Marino {
626e4b17023SJohn Marino gimple last = gimple_seq_last_stmt (*pre_p);
627e4b17023SJohn Marino t = gimple_get_lhs (last);
628e4b17023SJohn Marino }
629e4b17023SJohn Marino
630e4b17023SJohn Marino return t;
631e4b17023SJohn Marino }
632e4b17023SJohn Marino
633e4b17023SJohn Marino /* Return a formal temporary variable initialized with VAL. PRE_P is as
634e4b17023SJohn Marino in gimplify_expr. Only use this function if:
635e4b17023SJohn Marino
636e4b17023SJohn Marino 1) The value of the unfactored expression represented by VAL will not
637e4b17023SJohn Marino change between the initialization and use of the temporary, and
638e4b17023SJohn Marino 2) The temporary will not be otherwise modified.
639e4b17023SJohn Marino
640e4b17023SJohn Marino For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
641e4b17023SJohn Marino and #2 means it is inappropriate for && temps.
642e4b17023SJohn Marino
643e4b17023SJohn Marino For other cases, use get_initialized_tmp_var instead. */
644e4b17023SJohn Marino
645e4b17023SJohn Marino tree
get_formal_tmp_var(tree val,gimple_seq * pre_p)646e4b17023SJohn Marino get_formal_tmp_var (tree val, gimple_seq *pre_p)
647e4b17023SJohn Marino {
648e4b17023SJohn Marino return internal_get_tmp_var (val, pre_p, NULL, true);
649e4b17023SJohn Marino }
650e4b17023SJohn Marino
651e4b17023SJohn Marino /* Return a temporary variable initialized with VAL. PRE_P and POST_P
652e4b17023SJohn Marino are as in gimplify_expr. */
653e4b17023SJohn Marino
654e4b17023SJohn Marino tree
get_initialized_tmp_var(tree val,gimple_seq * pre_p,gimple_seq * post_p)655e4b17023SJohn Marino get_initialized_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p)
656e4b17023SJohn Marino {
657e4b17023SJohn Marino return internal_get_tmp_var (val, pre_p, post_p, false);
658e4b17023SJohn Marino }
659e4b17023SJohn Marino
660e4b17023SJohn Marino /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
661e4b17023SJohn Marino generate debug info for them; otherwise don't. */
662e4b17023SJohn Marino
663e4b17023SJohn Marino void
declare_vars(tree vars,gimple scope,bool debug_info)664e4b17023SJohn Marino declare_vars (tree vars, gimple scope, bool debug_info)
665e4b17023SJohn Marino {
666e4b17023SJohn Marino tree last = vars;
667e4b17023SJohn Marino if (last)
668e4b17023SJohn Marino {
669e4b17023SJohn Marino tree temps, block;
670e4b17023SJohn Marino
671e4b17023SJohn Marino gcc_assert (gimple_code (scope) == GIMPLE_BIND);
672e4b17023SJohn Marino
673e4b17023SJohn Marino temps = nreverse (last);
674e4b17023SJohn Marino
675e4b17023SJohn Marino block = gimple_bind_block (scope);
676e4b17023SJohn Marino gcc_assert (!block || TREE_CODE (block) == BLOCK);
677e4b17023SJohn Marino if (!block || !debug_info)
678e4b17023SJohn Marino {
679e4b17023SJohn Marino DECL_CHAIN (last) = gimple_bind_vars (scope);
680e4b17023SJohn Marino gimple_bind_set_vars (scope, temps);
681e4b17023SJohn Marino }
682e4b17023SJohn Marino else
683e4b17023SJohn Marino {
684e4b17023SJohn Marino /* We need to attach the nodes both to the BIND_EXPR and to its
685e4b17023SJohn Marino associated BLOCK for debugging purposes. The key point here
686e4b17023SJohn Marino is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
687e4b17023SJohn Marino is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
688e4b17023SJohn Marino if (BLOCK_VARS (block))
689e4b17023SJohn Marino BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
690e4b17023SJohn Marino else
691e4b17023SJohn Marino {
692e4b17023SJohn Marino gimple_bind_set_vars (scope,
693e4b17023SJohn Marino chainon (gimple_bind_vars (scope), temps));
694e4b17023SJohn Marino BLOCK_VARS (block) = temps;
695e4b17023SJohn Marino }
696e4b17023SJohn Marino }
697e4b17023SJohn Marino }
698e4b17023SJohn Marino }
699e4b17023SJohn Marino
700e4b17023SJohn Marino /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
701e4b17023SJohn Marino for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
702e4b17023SJohn Marino no such upper bound can be obtained. */
703e4b17023SJohn Marino
704e4b17023SJohn Marino static void
force_constant_size(tree var)705e4b17023SJohn Marino force_constant_size (tree var)
706e4b17023SJohn Marino {
707e4b17023SJohn Marino /* The only attempt we make is by querying the maximum size of objects
708e4b17023SJohn Marino of the variable's type. */
709e4b17023SJohn Marino
710e4b17023SJohn Marino HOST_WIDE_INT max_size;
711e4b17023SJohn Marino
712e4b17023SJohn Marino gcc_assert (TREE_CODE (var) == VAR_DECL);
713e4b17023SJohn Marino
714e4b17023SJohn Marino max_size = max_int_size_in_bytes (TREE_TYPE (var));
715e4b17023SJohn Marino
716e4b17023SJohn Marino gcc_assert (max_size >= 0);
717e4b17023SJohn Marino
718e4b17023SJohn Marino DECL_SIZE_UNIT (var)
719e4b17023SJohn Marino = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
720e4b17023SJohn Marino DECL_SIZE (var)
721e4b17023SJohn Marino = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
722e4b17023SJohn Marino }
723e4b17023SJohn Marino
724e4b17023SJohn Marino /* Push the temporary variable TMP into the current binding. */
725e4b17023SJohn Marino
726e4b17023SJohn Marino void
gimple_add_tmp_var(tree tmp)727e4b17023SJohn Marino gimple_add_tmp_var (tree tmp)
728e4b17023SJohn Marino {
729e4b17023SJohn Marino gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
730e4b17023SJohn Marino
731e4b17023SJohn Marino /* Later processing assumes that the object size is constant, which might
732e4b17023SJohn Marino not be true at this point. Force the use of a constant upper bound in
733e4b17023SJohn Marino this case. */
734e4b17023SJohn Marino if (!host_integerp (DECL_SIZE_UNIT (tmp), 1))
735e4b17023SJohn Marino force_constant_size (tmp);
736e4b17023SJohn Marino
737e4b17023SJohn Marino DECL_CONTEXT (tmp) = current_function_decl;
738e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
739e4b17023SJohn Marino
740e4b17023SJohn Marino if (gimplify_ctxp)
741e4b17023SJohn Marino {
742e4b17023SJohn Marino DECL_CHAIN (tmp) = gimplify_ctxp->temps;
743e4b17023SJohn Marino gimplify_ctxp->temps = tmp;
744e4b17023SJohn Marino
745e4b17023SJohn Marino /* Mark temporaries local within the nearest enclosing parallel. */
746e4b17023SJohn Marino if (gimplify_omp_ctxp)
747e4b17023SJohn Marino {
748e4b17023SJohn Marino struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
749e4b17023SJohn Marino while (ctx && ctx->region_type == ORT_WORKSHARE)
750e4b17023SJohn Marino ctx = ctx->outer_context;
751e4b17023SJohn Marino if (ctx)
752e4b17023SJohn Marino omp_add_variable (ctx, tmp, GOVD_LOCAL | GOVD_SEEN);
753e4b17023SJohn Marino }
754e4b17023SJohn Marino }
755e4b17023SJohn Marino else if (cfun)
756e4b17023SJohn Marino record_vars (tmp);
757e4b17023SJohn Marino else
758e4b17023SJohn Marino {
759e4b17023SJohn Marino gimple_seq body_seq;
760e4b17023SJohn Marino
761e4b17023SJohn Marino /* This case is for nested functions. We need to expose the locals
762e4b17023SJohn Marino they create. */
763e4b17023SJohn Marino body_seq = gimple_body (current_function_decl);
764e4b17023SJohn Marino declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
765e4b17023SJohn Marino }
766e4b17023SJohn Marino }
767e4b17023SJohn Marino
768e4b17023SJohn Marino /* Determine whether to assign a location to the statement GS. */
769e4b17023SJohn Marino
770e4b17023SJohn Marino static bool
should_carry_location_p(gimple gs)771e4b17023SJohn Marino should_carry_location_p (gimple gs)
772e4b17023SJohn Marino {
773e4b17023SJohn Marino /* Don't emit a line note for a label. We particularly don't want to
774e4b17023SJohn Marino emit one for the break label, since it doesn't actually correspond
775e4b17023SJohn Marino to the beginning of the loop/switch. */
776e4b17023SJohn Marino if (gimple_code (gs) == GIMPLE_LABEL)
777e4b17023SJohn Marino return false;
778e4b17023SJohn Marino
779e4b17023SJohn Marino return true;
780e4b17023SJohn Marino }
781e4b17023SJohn Marino
782e4b17023SJohn Marino /* Return true if a location should not be emitted for this statement
783e4b17023SJohn Marino by annotate_one_with_location. */
784e4b17023SJohn Marino
785e4b17023SJohn Marino static inline bool
gimple_do_not_emit_location_p(gimple g)786e4b17023SJohn Marino gimple_do_not_emit_location_p (gimple g)
787e4b17023SJohn Marino {
788e4b17023SJohn Marino return gimple_plf (g, GF_PLF_1);
789e4b17023SJohn Marino }
790e4b17023SJohn Marino
791e4b17023SJohn Marino /* Mark statement G so a location will not be emitted by
792e4b17023SJohn Marino annotate_one_with_location. */
793e4b17023SJohn Marino
794e4b17023SJohn Marino static inline void
gimple_set_do_not_emit_location(gimple g)795e4b17023SJohn Marino gimple_set_do_not_emit_location (gimple g)
796e4b17023SJohn Marino {
797e4b17023SJohn Marino /* The PLF flags are initialized to 0 when a new tuple is created,
798e4b17023SJohn Marino so no need to initialize it anywhere. */
799e4b17023SJohn Marino gimple_set_plf (g, GF_PLF_1, true);
800e4b17023SJohn Marino }
801e4b17023SJohn Marino
802e4b17023SJohn Marino /* Set the location for gimple statement GS to LOCATION. */
803e4b17023SJohn Marino
804e4b17023SJohn Marino static void
annotate_one_with_location(gimple gs,location_t location)805e4b17023SJohn Marino annotate_one_with_location (gimple gs, location_t location)
806e4b17023SJohn Marino {
807e4b17023SJohn Marino if (!gimple_has_location (gs)
808e4b17023SJohn Marino && !gimple_do_not_emit_location_p (gs)
809e4b17023SJohn Marino && should_carry_location_p (gs))
810e4b17023SJohn Marino gimple_set_location (gs, location);
811e4b17023SJohn Marino }
812e4b17023SJohn Marino
813e4b17023SJohn Marino /* Set LOCATION for all the statements after iterator GSI in sequence
814e4b17023SJohn Marino SEQ. If GSI is pointing to the end of the sequence, start with the
815e4b17023SJohn Marino first statement in SEQ. */
816e4b17023SJohn Marino
817e4b17023SJohn Marino static void
annotate_all_with_location_after(gimple_seq seq,gimple_stmt_iterator gsi,location_t location)818e4b17023SJohn Marino annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi,
819e4b17023SJohn Marino location_t location)
820e4b17023SJohn Marino {
821e4b17023SJohn Marino if (gsi_end_p (gsi))
822e4b17023SJohn Marino gsi = gsi_start (seq);
823e4b17023SJohn Marino else
824e4b17023SJohn Marino gsi_next (&gsi);
825e4b17023SJohn Marino
826e4b17023SJohn Marino for (; !gsi_end_p (gsi); gsi_next (&gsi))
827e4b17023SJohn Marino annotate_one_with_location (gsi_stmt (gsi), location);
828e4b17023SJohn Marino }
829e4b17023SJohn Marino
830e4b17023SJohn Marino /* Set the location for all the statements in a sequence STMT_P to LOCATION. */
831e4b17023SJohn Marino
832e4b17023SJohn Marino void
annotate_all_with_location(gimple_seq stmt_p,location_t location)833e4b17023SJohn Marino annotate_all_with_location (gimple_seq stmt_p, location_t location)
834e4b17023SJohn Marino {
835e4b17023SJohn Marino gimple_stmt_iterator i;
836e4b17023SJohn Marino
837e4b17023SJohn Marino if (gimple_seq_empty_p (stmt_p))
838e4b17023SJohn Marino return;
839e4b17023SJohn Marino
840e4b17023SJohn Marino for (i = gsi_start (stmt_p); !gsi_end_p (i); gsi_next (&i))
841e4b17023SJohn Marino {
842e4b17023SJohn Marino gimple gs = gsi_stmt (i);
843e4b17023SJohn Marino annotate_one_with_location (gs, location);
844e4b17023SJohn Marino }
845e4b17023SJohn Marino }
846e4b17023SJohn Marino
847e4b17023SJohn Marino /* This page contains routines to unshare tree nodes, i.e. to duplicate tree
848e4b17023SJohn Marino nodes that are referenced more than once in GENERIC functions. This is
849e4b17023SJohn Marino necessary because gimplification (translation into GIMPLE) is performed
850e4b17023SJohn Marino by modifying tree nodes in-place, so gimplication of a shared node in a
851e4b17023SJohn Marino first context could generate an invalid GIMPLE form in a second context.
852e4b17023SJohn Marino
853e4b17023SJohn Marino This is achieved with a simple mark/copy/unmark algorithm that walks the
854e4b17023SJohn Marino GENERIC representation top-down, marks nodes with TREE_VISITED the first
855e4b17023SJohn Marino time it encounters them, duplicates them if they already have TREE_VISITED
856e4b17023SJohn Marino set, and finally removes the TREE_VISITED marks it has set.
857e4b17023SJohn Marino
858e4b17023SJohn Marino The algorithm works only at the function level, i.e. it generates a GENERIC
859e4b17023SJohn Marino representation of a function with no nodes shared within the function when
860e4b17023SJohn Marino passed a GENERIC function (except for nodes that are allowed to be shared).
861e4b17023SJohn Marino
862e4b17023SJohn Marino At the global level, it is also necessary to unshare tree nodes that are
863e4b17023SJohn Marino referenced in more than one function, for the same aforementioned reason.
864e4b17023SJohn Marino This requires some cooperation from the front-end. There are 2 strategies:
865e4b17023SJohn Marino
866e4b17023SJohn Marino 1. Manual unsharing. The front-end needs to call unshare_expr on every
867e4b17023SJohn Marino expression that might end up being shared across functions.
868e4b17023SJohn Marino
869e4b17023SJohn Marino 2. Deep unsharing. This is an extension of regular unsharing. Instead
870e4b17023SJohn Marino of calling unshare_expr on expressions that might be shared across
871e4b17023SJohn Marino functions, the front-end pre-marks them with TREE_VISITED. This will
872e4b17023SJohn Marino ensure that they are unshared on the first reference within functions
873e4b17023SJohn Marino when the regular unsharing algorithm runs. The counterpart is that
874e4b17023SJohn Marino this algorithm must look deeper than for manual unsharing, which is
875e4b17023SJohn Marino specified by LANG_HOOKS_DEEP_UNSHARING.
876e4b17023SJohn Marino
877e4b17023SJohn Marino If there are only few specific cases of node sharing across functions, it is
878e4b17023SJohn Marino probably easier for a front-end to unshare the expressions manually. On the
879e4b17023SJohn Marino contrary, if the expressions generated at the global level are as widespread
880e4b17023SJohn Marino as expressions generated within functions, deep unsharing is very likely the
881e4b17023SJohn Marino way to go. */
882e4b17023SJohn Marino
883e4b17023SJohn Marino /* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
884e4b17023SJohn Marino These nodes model computations that must be done once. If we were to
885e4b17023SJohn Marino unshare something like SAVE_EXPR(i++), the gimplification process would
886e4b17023SJohn Marino create wrong code. However, if DATA is non-null, it must hold a pointer
887e4b17023SJohn Marino set that is used to unshare the subtrees of these nodes. */
888e4b17023SJohn Marino
889e4b17023SJohn Marino static tree
mostly_copy_tree_r(tree * tp,int * walk_subtrees,void * data)890e4b17023SJohn Marino mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
891e4b17023SJohn Marino {
892e4b17023SJohn Marino tree t = *tp;
893e4b17023SJohn Marino enum tree_code code = TREE_CODE (t);
894e4b17023SJohn Marino
895e4b17023SJohn Marino /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
896e4b17023SJohn Marino copy their subtrees if we can make sure to do it only once. */
897e4b17023SJohn Marino if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
898e4b17023SJohn Marino {
899e4b17023SJohn Marino if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
900e4b17023SJohn Marino ;
901e4b17023SJohn Marino else
902e4b17023SJohn Marino *walk_subtrees = 0;
903e4b17023SJohn Marino }
904e4b17023SJohn Marino
905e4b17023SJohn Marino /* Stop at types, decls, constants like copy_tree_r. */
906e4b17023SJohn Marino else if (TREE_CODE_CLASS (code) == tcc_type
907e4b17023SJohn Marino || TREE_CODE_CLASS (code) == tcc_declaration
908e4b17023SJohn Marino || TREE_CODE_CLASS (code) == tcc_constant
909e4b17023SJohn Marino /* We can't do anything sensible with a BLOCK used as an
910e4b17023SJohn Marino expression, but we also can't just die when we see it
911e4b17023SJohn Marino because of non-expression uses. So we avert our eyes
912e4b17023SJohn Marino and cross our fingers. Silly Java. */
913e4b17023SJohn Marino || code == BLOCK)
914e4b17023SJohn Marino *walk_subtrees = 0;
915e4b17023SJohn Marino
916e4b17023SJohn Marino /* Cope with the statement expression extension. */
917e4b17023SJohn Marino else if (code == STATEMENT_LIST)
918e4b17023SJohn Marino ;
919e4b17023SJohn Marino
920e4b17023SJohn Marino /* Leave the bulk of the work to copy_tree_r itself. */
921e4b17023SJohn Marino else
922e4b17023SJohn Marino copy_tree_r (tp, walk_subtrees, NULL);
923e4b17023SJohn Marino
924e4b17023SJohn Marino return NULL_TREE;
925e4b17023SJohn Marino }
926e4b17023SJohn Marino
927e4b17023SJohn Marino /* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
928e4b17023SJohn Marino If *TP has been visited already, then *TP is deeply copied by calling
929e4b17023SJohn Marino mostly_copy_tree_r. DATA is passed to mostly_copy_tree_r unmodified. */
930e4b17023SJohn Marino
931e4b17023SJohn Marino static tree
copy_if_shared_r(tree * tp,int * walk_subtrees,void * data)932e4b17023SJohn Marino copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
933e4b17023SJohn Marino {
934e4b17023SJohn Marino tree t = *tp;
935e4b17023SJohn Marino enum tree_code code = TREE_CODE (t);
936e4b17023SJohn Marino
937e4b17023SJohn Marino /* Skip types, decls, and constants. But we do want to look at their
938e4b17023SJohn Marino types and the bounds of types. Mark them as visited so we properly
939e4b17023SJohn Marino unmark their subtrees on the unmark pass. If we've already seen them,
940e4b17023SJohn Marino don't look down further. */
941e4b17023SJohn Marino if (TREE_CODE_CLASS (code) == tcc_type
942e4b17023SJohn Marino || TREE_CODE_CLASS (code) == tcc_declaration
943e4b17023SJohn Marino || TREE_CODE_CLASS (code) == tcc_constant)
944e4b17023SJohn Marino {
945e4b17023SJohn Marino if (TREE_VISITED (t))
946e4b17023SJohn Marino *walk_subtrees = 0;
947e4b17023SJohn Marino else
948e4b17023SJohn Marino TREE_VISITED (t) = 1;
949e4b17023SJohn Marino }
950e4b17023SJohn Marino
951e4b17023SJohn Marino /* If this node has been visited already, unshare it and don't look
952e4b17023SJohn Marino any deeper. */
953e4b17023SJohn Marino else if (TREE_VISITED (t))
954e4b17023SJohn Marino {
955e4b17023SJohn Marino walk_tree (tp, mostly_copy_tree_r, data, NULL);
956e4b17023SJohn Marino *walk_subtrees = 0;
957e4b17023SJohn Marino }
958e4b17023SJohn Marino
959e4b17023SJohn Marino /* Otherwise, mark the node as visited and keep looking. */
960e4b17023SJohn Marino else
961e4b17023SJohn Marino TREE_VISITED (t) = 1;
962e4b17023SJohn Marino
963e4b17023SJohn Marino return NULL_TREE;
964e4b17023SJohn Marino }
965e4b17023SJohn Marino
966e4b17023SJohn Marino /* Unshare most of the shared trees rooted at *TP. DATA is passed to the
967e4b17023SJohn Marino copy_if_shared_r callback unmodified. */
968e4b17023SJohn Marino
969e4b17023SJohn Marino static inline void
copy_if_shared(tree * tp,void * data)970e4b17023SJohn Marino copy_if_shared (tree *tp, void *data)
971e4b17023SJohn Marino {
972e4b17023SJohn Marino walk_tree (tp, copy_if_shared_r, data, NULL);
973e4b17023SJohn Marino }
974e4b17023SJohn Marino
975e4b17023SJohn Marino /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
976e4b17023SJohn Marino any nested functions. */
977e4b17023SJohn Marino
978e4b17023SJohn Marino static void
unshare_body(tree fndecl)979e4b17023SJohn Marino unshare_body (tree fndecl)
980e4b17023SJohn Marino {
981e4b17023SJohn Marino struct cgraph_node *cgn = cgraph_get_node (fndecl);
982e4b17023SJohn Marino /* If the language requires deep unsharing, we need a pointer set to make
983e4b17023SJohn Marino sure we don't repeatedly unshare subtrees of unshareable nodes. */
984e4b17023SJohn Marino struct pointer_set_t *visited
985e4b17023SJohn Marino = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
986e4b17023SJohn Marino
987e4b17023SJohn Marino copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
988e4b17023SJohn Marino copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
989e4b17023SJohn Marino copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
990e4b17023SJohn Marino
991e4b17023SJohn Marino if (visited)
992e4b17023SJohn Marino pointer_set_destroy (visited);
993e4b17023SJohn Marino
994e4b17023SJohn Marino if (cgn)
995e4b17023SJohn Marino for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
996e4b17023SJohn Marino unshare_body (cgn->decl);
997e4b17023SJohn Marino }
998e4b17023SJohn Marino
999e4b17023SJohn Marino /* Callback for walk_tree to unmark the visited trees rooted at *TP.
1000e4b17023SJohn Marino Subtrees are walked until the first unvisited node is encountered. */
1001e4b17023SJohn Marino
1002e4b17023SJohn Marino static tree
unmark_visited_r(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)1003e4b17023SJohn Marino unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1004e4b17023SJohn Marino {
1005e4b17023SJohn Marino tree t = *tp;
1006e4b17023SJohn Marino
1007e4b17023SJohn Marino /* If this node has been visited, unmark it and keep looking. */
1008e4b17023SJohn Marino if (TREE_VISITED (t))
1009e4b17023SJohn Marino TREE_VISITED (t) = 0;
1010e4b17023SJohn Marino
1011e4b17023SJohn Marino /* Otherwise, don't look any deeper. */
1012e4b17023SJohn Marino else
1013e4b17023SJohn Marino *walk_subtrees = 0;
1014e4b17023SJohn Marino
1015e4b17023SJohn Marino return NULL_TREE;
1016e4b17023SJohn Marino }
1017e4b17023SJohn Marino
1018e4b17023SJohn Marino /* Unmark the visited trees rooted at *TP. */
1019e4b17023SJohn Marino
1020e4b17023SJohn Marino static inline void
unmark_visited(tree * tp)1021e4b17023SJohn Marino unmark_visited (tree *tp)
1022e4b17023SJohn Marino {
1023e4b17023SJohn Marino walk_tree (tp, unmark_visited_r, NULL, NULL);
1024e4b17023SJohn Marino }
1025e4b17023SJohn Marino
1026e4b17023SJohn Marino /* Likewise, but mark all trees as not visited. */
1027e4b17023SJohn Marino
1028e4b17023SJohn Marino static void
unvisit_body(tree fndecl)1029e4b17023SJohn Marino unvisit_body (tree fndecl)
1030e4b17023SJohn Marino {
1031e4b17023SJohn Marino struct cgraph_node *cgn = cgraph_get_node (fndecl);
1032e4b17023SJohn Marino
1033e4b17023SJohn Marino unmark_visited (&DECL_SAVED_TREE (fndecl));
1034e4b17023SJohn Marino unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
1035e4b17023SJohn Marino unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
1036e4b17023SJohn Marino
1037e4b17023SJohn Marino if (cgn)
1038e4b17023SJohn Marino for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
1039e4b17023SJohn Marino unvisit_body (cgn->decl);
1040e4b17023SJohn Marino }
1041e4b17023SJohn Marino
1042e4b17023SJohn Marino /* Unconditionally make an unshared copy of EXPR. This is used when using
1043e4b17023SJohn Marino stored expressions which span multiple functions, such as BINFO_VTABLE,
1044e4b17023SJohn Marino as the normal unsharing process can't tell that they're shared. */
1045e4b17023SJohn Marino
1046e4b17023SJohn Marino tree
unshare_expr(tree expr)1047e4b17023SJohn Marino unshare_expr (tree expr)
1048e4b17023SJohn Marino {
1049e4b17023SJohn Marino walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
1050e4b17023SJohn Marino return expr;
1051e4b17023SJohn Marino }
1052e4b17023SJohn Marino
1053e4b17023SJohn Marino /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1054e4b17023SJohn Marino contain statements and have a value. Assign its value to a temporary
1055e4b17023SJohn Marino and give it void_type_node. Return the temporary, or NULL_TREE if
1056e4b17023SJohn Marino WRAPPER was already void. */
1057e4b17023SJohn Marino
1058e4b17023SJohn Marino tree
voidify_wrapper_expr(tree wrapper,tree temp)1059e4b17023SJohn Marino voidify_wrapper_expr (tree wrapper, tree temp)
1060e4b17023SJohn Marino {
1061e4b17023SJohn Marino tree type = TREE_TYPE (wrapper);
1062e4b17023SJohn Marino if (type && !VOID_TYPE_P (type))
1063e4b17023SJohn Marino {
1064e4b17023SJohn Marino tree *p;
1065e4b17023SJohn Marino
1066e4b17023SJohn Marino /* Set p to point to the body of the wrapper. Loop until we find
1067e4b17023SJohn Marino something that isn't a wrapper. */
1068e4b17023SJohn Marino for (p = &wrapper; p && *p; )
1069e4b17023SJohn Marino {
1070e4b17023SJohn Marino switch (TREE_CODE (*p))
1071e4b17023SJohn Marino {
1072e4b17023SJohn Marino case BIND_EXPR:
1073e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1074e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1075e4b17023SJohn Marino /* For a BIND_EXPR, the body is operand 1. */
1076e4b17023SJohn Marino p = &BIND_EXPR_BODY (*p);
1077e4b17023SJohn Marino break;
1078e4b17023SJohn Marino
1079e4b17023SJohn Marino case CLEANUP_POINT_EXPR:
1080e4b17023SJohn Marino case TRY_FINALLY_EXPR:
1081e4b17023SJohn Marino case TRY_CATCH_EXPR:
1082e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1083e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1084e4b17023SJohn Marino p = &TREE_OPERAND (*p, 0);
1085e4b17023SJohn Marino break;
1086e4b17023SJohn Marino
1087e4b17023SJohn Marino case STATEMENT_LIST:
1088e4b17023SJohn Marino {
1089e4b17023SJohn Marino tree_stmt_iterator i = tsi_last (*p);
1090e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1091e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1092e4b17023SJohn Marino p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1093e4b17023SJohn Marino }
1094e4b17023SJohn Marino break;
1095e4b17023SJohn Marino
1096e4b17023SJohn Marino case COMPOUND_EXPR:
1097e4b17023SJohn Marino /* Advance to the last statement. Set all container types to
1098e4b17023SJohn Marino void. */
1099e4b17023SJohn Marino for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1100e4b17023SJohn Marino {
1101e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1102e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1103e4b17023SJohn Marino }
1104e4b17023SJohn Marino break;
1105e4b17023SJohn Marino
1106e4b17023SJohn Marino case TRANSACTION_EXPR:
1107e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1108e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1109e4b17023SJohn Marino p = &TRANSACTION_EXPR_BODY (*p);
1110e4b17023SJohn Marino break;
1111e4b17023SJohn Marino
1112e4b17023SJohn Marino default:
1113e4b17023SJohn Marino /* Assume that any tree upon which voidify_wrapper_expr is
1114e4b17023SJohn Marino directly called is a wrapper, and that its body is op0. */
1115e4b17023SJohn Marino if (p == &wrapper)
1116e4b17023SJohn Marino {
1117e4b17023SJohn Marino TREE_SIDE_EFFECTS (*p) = 1;
1118e4b17023SJohn Marino TREE_TYPE (*p) = void_type_node;
1119e4b17023SJohn Marino p = &TREE_OPERAND (*p, 0);
1120e4b17023SJohn Marino break;
1121e4b17023SJohn Marino }
1122e4b17023SJohn Marino goto out;
1123e4b17023SJohn Marino }
1124e4b17023SJohn Marino }
1125e4b17023SJohn Marino
1126e4b17023SJohn Marino out:
1127e4b17023SJohn Marino if (p == NULL || IS_EMPTY_STMT (*p))
1128e4b17023SJohn Marino temp = NULL_TREE;
1129e4b17023SJohn Marino else if (temp)
1130e4b17023SJohn Marino {
1131e4b17023SJohn Marino /* The wrapper is on the RHS of an assignment that we're pushing
1132e4b17023SJohn Marino down. */
1133e4b17023SJohn Marino gcc_assert (TREE_CODE (temp) == INIT_EXPR
1134e4b17023SJohn Marino || TREE_CODE (temp) == MODIFY_EXPR);
1135e4b17023SJohn Marino TREE_OPERAND (temp, 1) = *p;
1136e4b17023SJohn Marino *p = temp;
1137e4b17023SJohn Marino }
1138e4b17023SJohn Marino else
1139e4b17023SJohn Marino {
1140e4b17023SJohn Marino temp = create_tmp_var (type, "retval");
1141e4b17023SJohn Marino *p = build2 (INIT_EXPR, type, temp, *p);
1142e4b17023SJohn Marino }
1143e4b17023SJohn Marino
1144e4b17023SJohn Marino return temp;
1145e4b17023SJohn Marino }
1146e4b17023SJohn Marino
1147e4b17023SJohn Marino return NULL_TREE;
1148e4b17023SJohn Marino }
1149e4b17023SJohn Marino
1150e4b17023SJohn Marino /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1151e4b17023SJohn Marino a temporary through which they communicate. */
1152e4b17023SJohn Marino
1153e4b17023SJohn Marino static void
build_stack_save_restore(gimple * save,gimple * restore)1154e4b17023SJohn Marino build_stack_save_restore (gimple *save, gimple *restore)
1155e4b17023SJohn Marino {
1156e4b17023SJohn Marino tree tmp_var;
1157e4b17023SJohn Marino
1158e4b17023SJohn Marino *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1159e4b17023SJohn Marino tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1160e4b17023SJohn Marino gimple_call_set_lhs (*save, tmp_var);
1161e4b17023SJohn Marino
1162e4b17023SJohn Marino *restore
1163e4b17023SJohn Marino = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1164e4b17023SJohn Marino 1, tmp_var);
1165e4b17023SJohn Marino }
1166e4b17023SJohn Marino
1167e4b17023SJohn Marino /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1168e4b17023SJohn Marino
1169e4b17023SJohn Marino static enum gimplify_status
gimplify_bind_expr(tree * expr_p,gimple_seq * pre_p)1170e4b17023SJohn Marino gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1171e4b17023SJohn Marino {
1172e4b17023SJohn Marino tree bind_expr = *expr_p;
1173e4b17023SJohn Marino bool old_save_stack = gimplify_ctxp->save_stack;
1174e4b17023SJohn Marino tree t;
1175e4b17023SJohn Marino gimple gimple_bind;
1176e4b17023SJohn Marino gimple_seq body, cleanup;
1177e4b17023SJohn Marino gimple stack_save;
1178e4b17023SJohn Marino
1179e4b17023SJohn Marino tree temp = voidify_wrapper_expr (bind_expr, NULL);
1180e4b17023SJohn Marino
1181e4b17023SJohn Marino /* Mark variables seen in this bind expr. */
1182e4b17023SJohn Marino for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1183e4b17023SJohn Marino {
1184e4b17023SJohn Marino if (TREE_CODE (t) == VAR_DECL)
1185e4b17023SJohn Marino {
1186e4b17023SJohn Marino struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1187e4b17023SJohn Marino
1188e4b17023SJohn Marino /* Mark variable as local. */
1189e4b17023SJohn Marino if (ctx && !DECL_EXTERNAL (t)
1190e4b17023SJohn Marino && (! DECL_SEEN_IN_BIND_EXPR_P (t)
1191e4b17023SJohn Marino || splay_tree_lookup (ctx->variables,
1192e4b17023SJohn Marino (splay_tree_key) t) == NULL))
1193e4b17023SJohn Marino omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN);
1194e4b17023SJohn Marino
1195e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1196e4b17023SJohn Marino
1197e4b17023SJohn Marino if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1198e4b17023SJohn Marino cfun->has_local_explicit_reg_vars = true;
1199e4b17023SJohn Marino }
1200e4b17023SJohn Marino
1201e4b17023SJohn Marino /* Preliminarily mark non-addressed complex variables as eligible
1202e4b17023SJohn Marino for promotion to gimple registers. We'll transform their uses
1203e4b17023SJohn Marino as we find them. */
1204e4b17023SJohn Marino if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
1205e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
1206e4b17023SJohn Marino && !TREE_THIS_VOLATILE (t)
1207e4b17023SJohn Marino && (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
1208e4b17023SJohn Marino && !needs_to_live_in_memory (t))
1209e4b17023SJohn Marino DECL_GIMPLE_REG_P (t) = 1;
1210e4b17023SJohn Marino }
1211e4b17023SJohn Marino
1212e4b17023SJohn Marino gimple_bind = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1213e4b17023SJohn Marino BIND_EXPR_BLOCK (bind_expr));
1214e4b17023SJohn Marino gimple_push_bind_expr (gimple_bind);
1215e4b17023SJohn Marino
1216e4b17023SJohn Marino gimplify_ctxp->save_stack = false;
1217e4b17023SJohn Marino
1218e4b17023SJohn Marino /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1219e4b17023SJohn Marino body = NULL;
1220e4b17023SJohn Marino gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1221e4b17023SJohn Marino gimple_bind_set_body (gimple_bind, body);
1222e4b17023SJohn Marino
1223e4b17023SJohn Marino cleanup = NULL;
1224e4b17023SJohn Marino stack_save = NULL;
1225e4b17023SJohn Marino if (gimplify_ctxp->save_stack)
1226e4b17023SJohn Marino {
1227e4b17023SJohn Marino gimple stack_restore;
1228e4b17023SJohn Marino
1229e4b17023SJohn Marino /* Save stack on entry and restore it on exit. Add a try_finally
1230e4b17023SJohn Marino block to achieve this. Note that mudflap depends on the
1231e4b17023SJohn Marino format of the emitted code: see mx_register_decls(). */
1232e4b17023SJohn Marino build_stack_save_restore (&stack_save, &stack_restore);
1233e4b17023SJohn Marino
1234e4b17023SJohn Marino gimplify_seq_add_stmt (&cleanup, stack_restore);
1235e4b17023SJohn Marino }
1236e4b17023SJohn Marino
1237e4b17023SJohn Marino /* Add clobbers for all variables that go out of scope. */
1238e4b17023SJohn Marino for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1239e4b17023SJohn Marino {
1240e4b17023SJohn Marino if (TREE_CODE (t) == VAR_DECL
1241e4b17023SJohn Marino && !is_global_var (t)
1242e4b17023SJohn Marino && DECL_CONTEXT (t) == current_function_decl
1243e4b17023SJohn Marino && !DECL_HARD_REGISTER (t)
1244e4b17023SJohn Marino && !TREE_THIS_VOLATILE (t)
1245e4b17023SJohn Marino && !DECL_HAS_VALUE_EXPR_P (t)
1246e4b17023SJohn Marino /* Only care for variables that have to be in memory. Others
1247e4b17023SJohn Marino will be rewritten into SSA names, hence moved to the top-level. */
1248e4b17023SJohn Marino && !is_gimple_reg (t))
1249e4b17023SJohn Marino {
1250e4b17023SJohn Marino tree clobber = build_constructor (TREE_TYPE (t), NULL);
1251e4b17023SJohn Marino TREE_THIS_VOLATILE (clobber) = 1;
1252e4b17023SJohn Marino gimplify_seq_add_stmt (&cleanup, gimple_build_assign (t, clobber));
1253e4b17023SJohn Marino }
1254e4b17023SJohn Marino }
1255e4b17023SJohn Marino
1256e4b17023SJohn Marino if (cleanup)
1257e4b17023SJohn Marino {
1258e4b17023SJohn Marino gimple gs;
1259e4b17023SJohn Marino gimple_seq new_body;
1260e4b17023SJohn Marino
1261e4b17023SJohn Marino new_body = NULL;
1262e4b17023SJohn Marino gs = gimple_build_try (gimple_bind_body (gimple_bind), cleanup,
1263e4b17023SJohn Marino GIMPLE_TRY_FINALLY);
1264e4b17023SJohn Marino
1265e4b17023SJohn Marino if (stack_save)
1266e4b17023SJohn Marino gimplify_seq_add_stmt (&new_body, stack_save);
1267e4b17023SJohn Marino gimplify_seq_add_stmt (&new_body, gs);
1268e4b17023SJohn Marino gimple_bind_set_body (gimple_bind, new_body);
1269e4b17023SJohn Marino }
1270e4b17023SJohn Marino
1271e4b17023SJohn Marino gimplify_ctxp->save_stack = old_save_stack;
1272e4b17023SJohn Marino gimple_pop_bind_expr ();
1273e4b17023SJohn Marino
1274e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_bind);
1275e4b17023SJohn Marino
1276e4b17023SJohn Marino if (temp)
1277e4b17023SJohn Marino {
1278e4b17023SJohn Marino *expr_p = temp;
1279e4b17023SJohn Marino return GS_OK;
1280e4b17023SJohn Marino }
1281e4b17023SJohn Marino
1282e4b17023SJohn Marino *expr_p = NULL_TREE;
1283e4b17023SJohn Marino return GS_ALL_DONE;
1284e4b17023SJohn Marino }
1285e4b17023SJohn Marino
1286e4b17023SJohn Marino /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1287e4b17023SJohn Marino GIMPLE value, it is assigned to a new temporary and the statement is
1288e4b17023SJohn Marino re-written to return the temporary.
1289e4b17023SJohn Marino
1290e4b17023SJohn Marino PRE_P points to the sequence where side effects that must happen before
1291e4b17023SJohn Marino STMT should be stored. */
1292e4b17023SJohn Marino
1293e4b17023SJohn Marino static enum gimplify_status
gimplify_return_expr(tree stmt,gimple_seq * pre_p)1294e4b17023SJohn Marino gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1295e4b17023SJohn Marino {
1296e4b17023SJohn Marino gimple ret;
1297e4b17023SJohn Marino tree ret_expr = TREE_OPERAND (stmt, 0);
1298e4b17023SJohn Marino tree result_decl, result;
1299e4b17023SJohn Marino
1300e4b17023SJohn Marino if (ret_expr == error_mark_node)
1301e4b17023SJohn Marino return GS_ERROR;
1302e4b17023SJohn Marino
1303e4b17023SJohn Marino if (!ret_expr
1304e4b17023SJohn Marino || TREE_CODE (ret_expr) == RESULT_DECL
1305e4b17023SJohn Marino || ret_expr == error_mark_node)
1306e4b17023SJohn Marino {
1307e4b17023SJohn Marino gimple ret = gimple_build_return (ret_expr);
1308e4b17023SJohn Marino gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
1309e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, ret);
1310e4b17023SJohn Marino return GS_ALL_DONE;
1311e4b17023SJohn Marino }
1312e4b17023SJohn Marino
1313e4b17023SJohn Marino if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1314e4b17023SJohn Marino result_decl = NULL_TREE;
1315e4b17023SJohn Marino else
1316e4b17023SJohn Marino {
1317e4b17023SJohn Marino result_decl = TREE_OPERAND (ret_expr, 0);
1318e4b17023SJohn Marino
1319e4b17023SJohn Marino /* See through a return by reference. */
1320e4b17023SJohn Marino if (TREE_CODE (result_decl) == INDIRECT_REF)
1321e4b17023SJohn Marino result_decl = TREE_OPERAND (result_decl, 0);
1322e4b17023SJohn Marino
1323e4b17023SJohn Marino gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1324e4b17023SJohn Marino || TREE_CODE (ret_expr) == INIT_EXPR)
1325e4b17023SJohn Marino && TREE_CODE (result_decl) == RESULT_DECL);
1326e4b17023SJohn Marino }
1327e4b17023SJohn Marino
1328e4b17023SJohn Marino /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1329e4b17023SJohn Marino Recall that aggregate_value_p is FALSE for any aggregate type that is
1330e4b17023SJohn Marino returned in registers. If we're returning values in registers, then
1331e4b17023SJohn Marino we don't want to extend the lifetime of the RESULT_DECL, particularly
1332e4b17023SJohn Marino across another call. In addition, for those aggregates for which
1333e4b17023SJohn Marino hard_function_value generates a PARALLEL, we'll die during normal
1334e4b17023SJohn Marino expansion of structure assignments; there's special code in expand_return
1335e4b17023SJohn Marino to handle this case that does not exist in expand_expr. */
1336e4b17023SJohn Marino if (!result_decl)
1337e4b17023SJohn Marino result = NULL_TREE;
1338e4b17023SJohn Marino else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1339e4b17023SJohn Marino {
1340e4b17023SJohn Marino if (TREE_CODE (DECL_SIZE (result_decl)) != INTEGER_CST)
1341e4b17023SJohn Marino {
1342e4b17023SJohn Marino if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1343e4b17023SJohn Marino gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1344e4b17023SJohn Marino /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1345e4b17023SJohn Marino should be effectively allocated by the caller, i.e. all calls to
1346e4b17023SJohn Marino this function must be subject to the Return Slot Optimization. */
1347e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1348e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1349e4b17023SJohn Marino }
1350e4b17023SJohn Marino result = result_decl;
1351e4b17023SJohn Marino }
1352e4b17023SJohn Marino else if (gimplify_ctxp->return_temp)
1353e4b17023SJohn Marino result = gimplify_ctxp->return_temp;
1354e4b17023SJohn Marino else
1355e4b17023SJohn Marino {
1356e4b17023SJohn Marino result = create_tmp_reg (TREE_TYPE (result_decl), NULL);
1357e4b17023SJohn Marino
1358e4b17023SJohn Marino /* ??? With complex control flow (usually involving abnormal edges),
1359e4b17023SJohn Marino we can wind up warning about an uninitialized value for this. Due
1360e4b17023SJohn Marino to how this variable is constructed and initialized, this is never
1361e4b17023SJohn Marino true. Give up and never warn. */
1362e4b17023SJohn Marino TREE_NO_WARNING (result) = 1;
1363e4b17023SJohn Marino
1364e4b17023SJohn Marino gimplify_ctxp->return_temp = result;
1365e4b17023SJohn Marino }
1366e4b17023SJohn Marino
1367e4b17023SJohn Marino /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1368e4b17023SJohn Marino Then gimplify the whole thing. */
1369e4b17023SJohn Marino if (result != result_decl)
1370e4b17023SJohn Marino TREE_OPERAND (ret_expr, 0) = result;
1371e4b17023SJohn Marino
1372e4b17023SJohn Marino gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1373e4b17023SJohn Marino
1374e4b17023SJohn Marino ret = gimple_build_return (result);
1375e4b17023SJohn Marino gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
1376e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, ret);
1377e4b17023SJohn Marino
1378e4b17023SJohn Marino return GS_ALL_DONE;
1379e4b17023SJohn Marino }
1380e4b17023SJohn Marino
1381e4b17023SJohn Marino /* Gimplify a variable-length array DECL. */
1382e4b17023SJohn Marino
1383e4b17023SJohn Marino static void
gimplify_vla_decl(tree decl,gimple_seq * seq_p)1384e4b17023SJohn Marino gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1385e4b17023SJohn Marino {
1386e4b17023SJohn Marino /* This is a variable-sized decl. Simplify its size and mark it
1387e4b17023SJohn Marino for deferred expansion. Note that mudflap depends on the format
1388e4b17023SJohn Marino of the emitted code: see mx_register_decls(). */
1389e4b17023SJohn Marino tree t, addr, ptr_type;
1390e4b17023SJohn Marino
1391e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1392e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1393e4b17023SJohn Marino
1394e4b17023SJohn Marino /* All occurrences of this decl in final gimplified code will be
1395e4b17023SJohn Marino replaced by indirection. Setting DECL_VALUE_EXPR does two
1396e4b17023SJohn Marino things: First, it lets the rest of the gimplifier know what
1397e4b17023SJohn Marino replacement to use. Second, it lets the debug info know
1398e4b17023SJohn Marino where to find the value. */
1399e4b17023SJohn Marino ptr_type = build_pointer_type (TREE_TYPE (decl));
1400e4b17023SJohn Marino addr = create_tmp_var (ptr_type, get_name (decl));
1401e4b17023SJohn Marino DECL_IGNORED_P (addr) = 0;
1402e4b17023SJohn Marino t = build_fold_indirect_ref (addr);
1403e4b17023SJohn Marino TREE_THIS_NOTRAP (t) = 1;
1404e4b17023SJohn Marino SET_DECL_VALUE_EXPR (decl, t);
1405e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (decl) = 1;
1406e4b17023SJohn Marino
1407e4b17023SJohn Marino t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
1408e4b17023SJohn Marino t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
1409e4b17023SJohn Marino size_int (DECL_ALIGN (decl)));
1410e4b17023SJohn Marino /* The call has been built for a variable-sized object. */
1411e4b17023SJohn Marino CALL_ALLOCA_FOR_VAR_P (t) = 1;
1412e4b17023SJohn Marino t = fold_convert (ptr_type, t);
1413e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1414e4b17023SJohn Marino
1415e4b17023SJohn Marino gimplify_and_add (t, seq_p);
1416e4b17023SJohn Marino
1417e4b17023SJohn Marino /* Indicate that we need to restore the stack level when the
1418e4b17023SJohn Marino enclosing BIND_EXPR is exited. */
1419e4b17023SJohn Marino gimplify_ctxp->save_stack = true;
1420e4b17023SJohn Marino }
1421e4b17023SJohn Marino
1422e4b17023SJohn Marino /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
1423e4b17023SJohn Marino and initialization explicit. */
1424e4b17023SJohn Marino
1425e4b17023SJohn Marino static enum gimplify_status
gimplify_decl_expr(tree * stmt_p,gimple_seq * seq_p)1426e4b17023SJohn Marino gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
1427e4b17023SJohn Marino {
1428e4b17023SJohn Marino tree stmt = *stmt_p;
1429e4b17023SJohn Marino tree decl = DECL_EXPR_DECL (stmt);
1430e4b17023SJohn Marino
1431e4b17023SJohn Marino *stmt_p = NULL_TREE;
1432e4b17023SJohn Marino
1433e4b17023SJohn Marino if (TREE_TYPE (decl) == error_mark_node)
1434e4b17023SJohn Marino return GS_ERROR;
1435e4b17023SJohn Marino
1436e4b17023SJohn Marino if ((TREE_CODE (decl) == TYPE_DECL
1437e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL)
1438e4b17023SJohn Marino && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
1439e4b17023SJohn Marino gimplify_type_sizes (TREE_TYPE (decl), seq_p);
1440e4b17023SJohn Marino
1441e4b17023SJohn Marino /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
1442e4b17023SJohn Marino in case its size expressions contain problematic nodes like CALL_EXPR. */
1443e4b17023SJohn Marino if (TREE_CODE (decl) == TYPE_DECL
1444e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (decl)
1445e4b17023SJohn Marino && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
1446e4b17023SJohn Marino gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
1447e4b17023SJohn Marino
1448e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
1449e4b17023SJohn Marino {
1450e4b17023SJohn Marino tree init = DECL_INITIAL (decl);
1451e4b17023SJohn Marino
1452e4b17023SJohn Marino if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
1453e4b17023SJohn Marino || (!TREE_STATIC (decl)
1454e4b17023SJohn Marino && flag_stack_check == GENERIC_STACK_CHECK
1455e4b17023SJohn Marino && compare_tree_int (DECL_SIZE_UNIT (decl),
1456e4b17023SJohn Marino STACK_CHECK_MAX_VAR_SIZE) > 0))
1457e4b17023SJohn Marino gimplify_vla_decl (decl, seq_p);
1458e4b17023SJohn Marino
1459e4b17023SJohn Marino /* Some front ends do not explicitly declare all anonymous
1460e4b17023SJohn Marino artificial variables. We compensate here by declaring the
1461e4b17023SJohn Marino variables, though it would be better if the front ends would
1462e4b17023SJohn Marino explicitly declare them. */
1463e4b17023SJohn Marino if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
1464e4b17023SJohn Marino && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
1465e4b17023SJohn Marino gimple_add_tmp_var (decl);
1466e4b17023SJohn Marino
1467e4b17023SJohn Marino if (init && init != error_mark_node)
1468e4b17023SJohn Marino {
1469e4b17023SJohn Marino if (!TREE_STATIC (decl))
1470e4b17023SJohn Marino {
1471e4b17023SJohn Marino DECL_INITIAL (decl) = NULL_TREE;
1472e4b17023SJohn Marino init = build2 (INIT_EXPR, void_type_node, decl, init);
1473e4b17023SJohn Marino gimplify_and_add (init, seq_p);
1474e4b17023SJohn Marino ggc_free (init);
1475e4b17023SJohn Marino }
1476e4b17023SJohn Marino else
1477e4b17023SJohn Marino /* We must still examine initializers for static variables
1478e4b17023SJohn Marino as they may contain a label address. */
1479e4b17023SJohn Marino walk_tree (&init, force_labels_r, NULL, NULL);
1480e4b17023SJohn Marino }
1481e4b17023SJohn Marino }
1482e4b17023SJohn Marino
1483e4b17023SJohn Marino return GS_ALL_DONE;
1484e4b17023SJohn Marino }
1485e4b17023SJohn Marino
1486e4b17023SJohn Marino /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
1487e4b17023SJohn Marino and replacing the LOOP_EXPR with goto, but if the loop contains an
1488e4b17023SJohn Marino EXIT_EXPR, we need to append a label for it to jump to. */
1489e4b17023SJohn Marino
1490e4b17023SJohn Marino static enum gimplify_status
gimplify_loop_expr(tree * expr_p,gimple_seq * pre_p)1491e4b17023SJohn Marino gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
1492e4b17023SJohn Marino {
1493e4b17023SJohn Marino tree saved_label = gimplify_ctxp->exit_label;
1494e4b17023SJohn Marino tree start_label = create_artificial_label (UNKNOWN_LOCATION);
1495e4b17023SJohn Marino
1496e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
1497e4b17023SJohn Marino
1498e4b17023SJohn Marino gimplify_ctxp->exit_label = NULL_TREE;
1499e4b17023SJohn Marino
1500e4b17023SJohn Marino gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
1501e4b17023SJohn Marino
1502e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
1503e4b17023SJohn Marino
1504e4b17023SJohn Marino if (gimplify_ctxp->exit_label)
1505e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p,
1506e4b17023SJohn Marino gimple_build_label (gimplify_ctxp->exit_label));
1507e4b17023SJohn Marino
1508e4b17023SJohn Marino gimplify_ctxp->exit_label = saved_label;
1509e4b17023SJohn Marino
1510e4b17023SJohn Marino *expr_p = NULL;
1511e4b17023SJohn Marino return GS_ALL_DONE;
1512e4b17023SJohn Marino }
1513e4b17023SJohn Marino
1514e4b17023SJohn Marino /* Gimplify a statement list onto a sequence. These may be created either
1515e4b17023SJohn Marino by an enlightened front-end, or by shortcut_cond_expr. */
1516e4b17023SJohn Marino
1517e4b17023SJohn Marino static enum gimplify_status
gimplify_statement_list(tree * expr_p,gimple_seq * pre_p)1518e4b17023SJohn Marino gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
1519e4b17023SJohn Marino {
1520e4b17023SJohn Marino tree temp = voidify_wrapper_expr (*expr_p, NULL);
1521e4b17023SJohn Marino
1522e4b17023SJohn Marino tree_stmt_iterator i = tsi_start (*expr_p);
1523e4b17023SJohn Marino
1524e4b17023SJohn Marino while (!tsi_end_p (i))
1525e4b17023SJohn Marino {
1526e4b17023SJohn Marino gimplify_stmt (tsi_stmt_ptr (i), pre_p);
1527e4b17023SJohn Marino tsi_delink (&i);
1528e4b17023SJohn Marino }
1529e4b17023SJohn Marino
1530e4b17023SJohn Marino if (temp)
1531e4b17023SJohn Marino {
1532e4b17023SJohn Marino *expr_p = temp;
1533e4b17023SJohn Marino return GS_OK;
1534e4b17023SJohn Marino }
1535e4b17023SJohn Marino
1536e4b17023SJohn Marino return GS_ALL_DONE;
1537e4b17023SJohn Marino }
1538e4b17023SJohn Marino
1539e4b17023SJohn Marino /* Compare two case labels. Because the front end should already have
1540e4b17023SJohn Marino made sure that case ranges do not overlap, it is enough to only compare
1541e4b17023SJohn Marino the CASE_LOW values of each case label. */
1542e4b17023SJohn Marino
1543e4b17023SJohn Marino static int
compare_case_labels(const void * p1,const void * p2)1544e4b17023SJohn Marino compare_case_labels (const void *p1, const void *p2)
1545e4b17023SJohn Marino {
1546e4b17023SJohn Marino const_tree const case1 = *(const_tree const*)p1;
1547e4b17023SJohn Marino const_tree const case2 = *(const_tree const*)p2;
1548e4b17023SJohn Marino
1549e4b17023SJohn Marino /* The 'default' case label always goes first. */
1550e4b17023SJohn Marino if (!CASE_LOW (case1))
1551e4b17023SJohn Marino return -1;
1552e4b17023SJohn Marino else if (!CASE_LOW (case2))
1553e4b17023SJohn Marino return 1;
1554e4b17023SJohn Marino else
1555e4b17023SJohn Marino return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
1556e4b17023SJohn Marino }
1557e4b17023SJohn Marino
1558e4b17023SJohn Marino /* Sort the case labels in LABEL_VEC in place in ascending order. */
1559e4b17023SJohn Marino
1560e4b17023SJohn Marino void
sort_case_labels(VEC (tree,heap)* label_vec)1561e4b17023SJohn Marino sort_case_labels (VEC(tree,heap)* label_vec)
1562e4b17023SJohn Marino {
1563e4b17023SJohn Marino VEC_qsort (tree, label_vec, compare_case_labels);
1564e4b17023SJohn Marino }
1565e4b17023SJohn Marino
1566e4b17023SJohn Marino /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can
1567e4b17023SJohn Marino branch to. */
1568e4b17023SJohn Marino
1569e4b17023SJohn Marino static enum gimplify_status
gimplify_switch_expr(tree * expr_p,gimple_seq * pre_p)1570e4b17023SJohn Marino gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
1571e4b17023SJohn Marino {
1572e4b17023SJohn Marino tree switch_expr = *expr_p;
1573e4b17023SJohn Marino gimple_seq switch_body_seq = NULL;
1574e4b17023SJohn Marino enum gimplify_status ret;
1575e4b17023SJohn Marino
1576e4b17023SJohn Marino ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
1577e4b17023SJohn Marino fb_rvalue);
1578e4b17023SJohn Marino if (ret == GS_ERROR || ret == GS_UNHANDLED)
1579e4b17023SJohn Marino return ret;
1580e4b17023SJohn Marino
1581e4b17023SJohn Marino if (SWITCH_BODY (switch_expr))
1582e4b17023SJohn Marino {
1583e4b17023SJohn Marino VEC (tree,heap) *labels;
1584e4b17023SJohn Marino VEC (tree,heap) *saved_labels;
1585e4b17023SJohn Marino tree default_case = NULL_TREE;
1586e4b17023SJohn Marino size_t i, len;
1587e4b17023SJohn Marino gimple gimple_switch;
1588e4b17023SJohn Marino
1589e4b17023SJohn Marino /* If someone can be bothered to fill in the labels, they can
1590e4b17023SJohn Marino be bothered to null out the body too. */
1591e4b17023SJohn Marino gcc_assert (!SWITCH_LABELS (switch_expr));
1592e4b17023SJohn Marino
1593e4b17023SJohn Marino /* save old labels, get new ones from body, then restore the old
1594e4b17023SJohn Marino labels. Save all the things from the switch body to append after. */
1595e4b17023SJohn Marino saved_labels = gimplify_ctxp->case_labels;
1596e4b17023SJohn Marino gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
1597e4b17023SJohn Marino
1598e4b17023SJohn Marino gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
1599e4b17023SJohn Marino labels = gimplify_ctxp->case_labels;
1600e4b17023SJohn Marino gimplify_ctxp->case_labels = saved_labels;
1601e4b17023SJohn Marino
1602e4b17023SJohn Marino i = 0;
1603e4b17023SJohn Marino while (i < VEC_length (tree, labels))
1604e4b17023SJohn Marino {
1605e4b17023SJohn Marino tree elt = VEC_index (tree, labels, i);
1606e4b17023SJohn Marino tree low = CASE_LOW (elt);
1607e4b17023SJohn Marino bool remove_element = FALSE;
1608e4b17023SJohn Marino
1609e4b17023SJohn Marino if (low)
1610e4b17023SJohn Marino {
1611e4b17023SJohn Marino /* Discard empty ranges. */
1612e4b17023SJohn Marino tree high = CASE_HIGH (elt);
1613e4b17023SJohn Marino if (high && tree_int_cst_lt (high, low))
1614e4b17023SJohn Marino remove_element = TRUE;
1615e4b17023SJohn Marino }
1616e4b17023SJohn Marino else
1617e4b17023SJohn Marino {
1618e4b17023SJohn Marino /* The default case must be the last label in the list. */
1619e4b17023SJohn Marino gcc_assert (!default_case);
1620e4b17023SJohn Marino default_case = elt;
1621e4b17023SJohn Marino remove_element = TRUE;
1622e4b17023SJohn Marino }
1623e4b17023SJohn Marino
1624e4b17023SJohn Marino if (remove_element)
1625e4b17023SJohn Marino VEC_ordered_remove (tree, labels, i);
1626e4b17023SJohn Marino else
1627e4b17023SJohn Marino i++;
1628e4b17023SJohn Marino }
1629e4b17023SJohn Marino len = i;
1630e4b17023SJohn Marino
1631e4b17023SJohn Marino if (!VEC_empty (tree, labels))
1632e4b17023SJohn Marino sort_case_labels (labels);
1633e4b17023SJohn Marino
1634e4b17023SJohn Marino if (!default_case)
1635e4b17023SJohn Marino {
1636e4b17023SJohn Marino tree type = TREE_TYPE (switch_expr);
1637e4b17023SJohn Marino
1638e4b17023SJohn Marino /* If the switch has no default label, add one, so that we jump
1639e4b17023SJohn Marino around the switch body. If the labels already cover the whole
1640e4b17023SJohn Marino range of type, add the default label pointing to one of the
1641e4b17023SJohn Marino existing labels. */
1642e4b17023SJohn Marino if (type == void_type_node)
1643e4b17023SJohn Marino type = TREE_TYPE (SWITCH_COND (switch_expr));
1644e4b17023SJohn Marino if (len
1645e4b17023SJohn Marino && INTEGRAL_TYPE_P (type)
1646e4b17023SJohn Marino && TYPE_MIN_VALUE (type)
1647e4b17023SJohn Marino && TYPE_MAX_VALUE (type)
1648e4b17023SJohn Marino && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
1649e4b17023SJohn Marino TYPE_MIN_VALUE (type)))
1650e4b17023SJohn Marino {
1651e4b17023SJohn Marino tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
1652e4b17023SJohn Marino if (!high)
1653e4b17023SJohn Marino high = CASE_LOW (VEC_index (tree, labels, len - 1));
1654e4b17023SJohn Marino if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
1655e4b17023SJohn Marino {
1656e4b17023SJohn Marino for (i = 1; i < len; i++)
1657e4b17023SJohn Marino {
1658e4b17023SJohn Marino high = CASE_LOW (VEC_index (tree, labels, i));
1659e4b17023SJohn Marino low = CASE_HIGH (VEC_index (tree, labels, i - 1));
1660e4b17023SJohn Marino if (!low)
1661e4b17023SJohn Marino low = CASE_LOW (VEC_index (tree, labels, i - 1));
1662e4b17023SJohn Marino if ((TREE_INT_CST_LOW (low) + 1
1663e4b17023SJohn Marino != TREE_INT_CST_LOW (high))
1664e4b17023SJohn Marino || (TREE_INT_CST_HIGH (low)
1665e4b17023SJohn Marino + (TREE_INT_CST_LOW (high) == 0)
1666e4b17023SJohn Marino != TREE_INT_CST_HIGH (high)))
1667e4b17023SJohn Marino break;
1668e4b17023SJohn Marino }
1669e4b17023SJohn Marino if (i == len)
1670e4b17023SJohn Marino {
1671e4b17023SJohn Marino tree label = CASE_LABEL (VEC_index (tree, labels, 0));
1672e4b17023SJohn Marino default_case = build_case_label (NULL_TREE, NULL_TREE,
1673e4b17023SJohn Marino label);
1674e4b17023SJohn Marino }
1675e4b17023SJohn Marino }
1676e4b17023SJohn Marino }
1677e4b17023SJohn Marino
1678e4b17023SJohn Marino if (!default_case)
1679e4b17023SJohn Marino {
1680e4b17023SJohn Marino gimple new_default;
1681e4b17023SJohn Marino
1682e4b17023SJohn Marino default_case
1683e4b17023SJohn Marino = build_case_label (NULL_TREE, NULL_TREE,
1684e4b17023SJohn Marino create_artificial_label (UNKNOWN_LOCATION));
1685e4b17023SJohn Marino new_default = gimple_build_label (CASE_LABEL (default_case));
1686e4b17023SJohn Marino gimplify_seq_add_stmt (&switch_body_seq, new_default);
1687e4b17023SJohn Marino }
1688e4b17023SJohn Marino }
1689e4b17023SJohn Marino
1690e4b17023SJohn Marino gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
1691e4b17023SJohn Marino default_case, labels);
1692e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_switch);
1693e4b17023SJohn Marino gimplify_seq_add_seq (pre_p, switch_body_seq);
1694e4b17023SJohn Marino VEC_free(tree, heap, labels);
1695e4b17023SJohn Marino }
1696e4b17023SJohn Marino else
1697e4b17023SJohn Marino gcc_assert (SWITCH_LABELS (switch_expr));
1698e4b17023SJohn Marino
1699e4b17023SJohn Marino return GS_ALL_DONE;
1700e4b17023SJohn Marino }
1701e4b17023SJohn Marino
1702e4b17023SJohn Marino /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
1703e4b17023SJohn Marino
1704e4b17023SJohn Marino static enum gimplify_status
gimplify_case_label_expr(tree * expr_p,gimple_seq * pre_p)1705e4b17023SJohn Marino gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
1706e4b17023SJohn Marino {
1707e4b17023SJohn Marino struct gimplify_ctx *ctxp;
1708e4b17023SJohn Marino gimple gimple_label;
1709e4b17023SJohn Marino
1710e4b17023SJohn Marino /* Invalid OpenMP programs can play Duff's Device type games with
1711e4b17023SJohn Marino #pragma omp parallel. At least in the C front end, we don't
1712e4b17023SJohn Marino detect such invalid branches until after gimplification. */
1713e4b17023SJohn Marino for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
1714e4b17023SJohn Marino if (ctxp->case_labels)
1715e4b17023SJohn Marino break;
1716e4b17023SJohn Marino
1717e4b17023SJohn Marino gimple_label = gimple_build_label (CASE_LABEL (*expr_p));
1718e4b17023SJohn Marino VEC_safe_push (tree, heap, ctxp->case_labels, *expr_p);
1719e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_label);
1720e4b17023SJohn Marino
1721e4b17023SJohn Marino return GS_ALL_DONE;
1722e4b17023SJohn Marino }
1723e4b17023SJohn Marino
1724e4b17023SJohn Marino /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
1725e4b17023SJohn Marino if necessary. */
1726e4b17023SJohn Marino
1727e4b17023SJohn Marino tree
build_and_jump(tree * label_p)1728e4b17023SJohn Marino build_and_jump (tree *label_p)
1729e4b17023SJohn Marino {
1730e4b17023SJohn Marino if (label_p == NULL)
1731e4b17023SJohn Marino /* If there's nowhere to jump, just fall through. */
1732e4b17023SJohn Marino return NULL_TREE;
1733e4b17023SJohn Marino
1734e4b17023SJohn Marino if (*label_p == NULL_TREE)
1735e4b17023SJohn Marino {
1736e4b17023SJohn Marino tree label = create_artificial_label (UNKNOWN_LOCATION);
1737e4b17023SJohn Marino *label_p = label;
1738e4b17023SJohn Marino }
1739e4b17023SJohn Marino
1740e4b17023SJohn Marino return build1 (GOTO_EXPR, void_type_node, *label_p);
1741e4b17023SJohn Marino }
1742e4b17023SJohn Marino
1743e4b17023SJohn Marino /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
1744e4b17023SJohn Marino This also involves building a label to jump to and communicating it to
1745e4b17023SJohn Marino gimplify_loop_expr through gimplify_ctxp->exit_label. */
1746e4b17023SJohn Marino
1747e4b17023SJohn Marino static enum gimplify_status
gimplify_exit_expr(tree * expr_p)1748e4b17023SJohn Marino gimplify_exit_expr (tree *expr_p)
1749e4b17023SJohn Marino {
1750e4b17023SJohn Marino tree cond = TREE_OPERAND (*expr_p, 0);
1751e4b17023SJohn Marino tree expr;
1752e4b17023SJohn Marino
1753e4b17023SJohn Marino expr = build_and_jump (&gimplify_ctxp->exit_label);
1754e4b17023SJohn Marino expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
1755e4b17023SJohn Marino *expr_p = expr;
1756e4b17023SJohn Marino
1757e4b17023SJohn Marino return GS_OK;
1758e4b17023SJohn Marino }
1759e4b17023SJohn Marino
1760e4b17023SJohn Marino /* A helper function to be called via walk_tree. Mark all labels under *TP
1761e4b17023SJohn Marino as being forced. To be called for DECL_INITIAL of static variables. */
1762e4b17023SJohn Marino
1763e4b17023SJohn Marino tree
force_labels_r(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)1764e4b17023SJohn Marino force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1765e4b17023SJohn Marino {
1766e4b17023SJohn Marino if (TYPE_P (*tp))
1767e4b17023SJohn Marino *walk_subtrees = 0;
1768e4b17023SJohn Marino if (TREE_CODE (*tp) == LABEL_DECL)
1769e4b17023SJohn Marino FORCED_LABEL (*tp) = 1;
1770e4b17023SJohn Marino
1771e4b17023SJohn Marino return NULL_TREE;
1772e4b17023SJohn Marino }
1773e4b17023SJohn Marino
1774e4b17023SJohn Marino /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
1775e4b17023SJohn Marino different from its canonical type, wrap the whole thing inside a
1776e4b17023SJohn Marino NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
1777e4b17023SJohn Marino type.
1778e4b17023SJohn Marino
1779e4b17023SJohn Marino The canonical type of a COMPONENT_REF is the type of the field being
1780e4b17023SJohn Marino referenced--unless the field is a bit-field which can be read directly
1781e4b17023SJohn Marino in a smaller mode, in which case the canonical type is the
1782e4b17023SJohn Marino sign-appropriate type corresponding to that mode. */
1783e4b17023SJohn Marino
1784e4b17023SJohn Marino static void
canonicalize_component_ref(tree * expr_p)1785e4b17023SJohn Marino canonicalize_component_ref (tree *expr_p)
1786e4b17023SJohn Marino {
1787e4b17023SJohn Marino tree expr = *expr_p;
1788e4b17023SJohn Marino tree type;
1789e4b17023SJohn Marino
1790e4b17023SJohn Marino gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
1791e4b17023SJohn Marino
1792e4b17023SJohn Marino if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
1793e4b17023SJohn Marino type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
1794e4b17023SJohn Marino else
1795e4b17023SJohn Marino type = TREE_TYPE (TREE_OPERAND (expr, 1));
1796e4b17023SJohn Marino
1797e4b17023SJohn Marino /* One could argue that all the stuff below is not necessary for
1798e4b17023SJohn Marino the non-bitfield case and declare it a FE error if type
1799e4b17023SJohn Marino adjustment would be needed. */
1800e4b17023SJohn Marino if (TREE_TYPE (expr) != type)
1801e4b17023SJohn Marino {
1802e4b17023SJohn Marino #ifdef ENABLE_TYPES_CHECKING
1803e4b17023SJohn Marino tree old_type = TREE_TYPE (expr);
1804e4b17023SJohn Marino #endif
1805e4b17023SJohn Marino int type_quals;
1806e4b17023SJohn Marino
1807e4b17023SJohn Marino /* We need to preserve qualifiers and propagate them from
1808e4b17023SJohn Marino operand 0. */
1809e4b17023SJohn Marino type_quals = TYPE_QUALS (type)
1810e4b17023SJohn Marino | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
1811e4b17023SJohn Marino if (TYPE_QUALS (type) != type_quals)
1812e4b17023SJohn Marino type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
1813e4b17023SJohn Marino
1814e4b17023SJohn Marino /* Set the type of the COMPONENT_REF to the underlying type. */
1815e4b17023SJohn Marino TREE_TYPE (expr) = type;
1816e4b17023SJohn Marino
1817e4b17023SJohn Marino #ifdef ENABLE_TYPES_CHECKING
1818e4b17023SJohn Marino /* It is now a FE error, if the conversion from the canonical
1819e4b17023SJohn Marino type to the original expression type is not useless. */
1820e4b17023SJohn Marino gcc_assert (useless_type_conversion_p (old_type, type));
1821e4b17023SJohn Marino #endif
1822e4b17023SJohn Marino }
1823e4b17023SJohn Marino }
1824e4b17023SJohn Marino
1825e4b17023SJohn Marino /* If a NOP conversion is changing a pointer to array of foo to a pointer
1826e4b17023SJohn Marino to foo, embed that change in the ADDR_EXPR by converting
1827e4b17023SJohn Marino T array[U];
1828e4b17023SJohn Marino (T *)&array
1829e4b17023SJohn Marino ==>
1830e4b17023SJohn Marino &array[L]
1831e4b17023SJohn Marino where L is the lower bound. For simplicity, only do this for constant
1832e4b17023SJohn Marino lower bound.
1833e4b17023SJohn Marino The constraint is that the type of &array[L] is trivially convertible
1834e4b17023SJohn Marino to T *. */
1835e4b17023SJohn Marino
1836e4b17023SJohn Marino static void
canonicalize_addr_expr(tree * expr_p)1837e4b17023SJohn Marino canonicalize_addr_expr (tree *expr_p)
1838e4b17023SJohn Marino {
1839e4b17023SJohn Marino tree expr = *expr_p;
1840e4b17023SJohn Marino tree addr_expr = TREE_OPERAND (expr, 0);
1841e4b17023SJohn Marino tree datype, ddatype, pddatype;
1842e4b17023SJohn Marino
1843e4b17023SJohn Marino /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
1844e4b17023SJohn Marino if (!POINTER_TYPE_P (TREE_TYPE (expr))
1845e4b17023SJohn Marino || TREE_CODE (addr_expr) != ADDR_EXPR)
1846e4b17023SJohn Marino return;
1847e4b17023SJohn Marino
1848e4b17023SJohn Marino /* The addr_expr type should be a pointer to an array. */
1849e4b17023SJohn Marino datype = TREE_TYPE (TREE_TYPE (addr_expr));
1850e4b17023SJohn Marino if (TREE_CODE (datype) != ARRAY_TYPE)
1851e4b17023SJohn Marino return;
1852e4b17023SJohn Marino
1853e4b17023SJohn Marino /* The pointer to element type shall be trivially convertible to
1854e4b17023SJohn Marino the expression pointer type. */
1855e4b17023SJohn Marino ddatype = TREE_TYPE (datype);
1856e4b17023SJohn Marino pddatype = build_pointer_type (ddatype);
1857e4b17023SJohn Marino if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
1858e4b17023SJohn Marino pddatype))
1859e4b17023SJohn Marino return;
1860e4b17023SJohn Marino
1861e4b17023SJohn Marino /* The lower bound and element sizes must be constant. */
1862e4b17023SJohn Marino if (!TYPE_SIZE_UNIT (ddatype)
1863e4b17023SJohn Marino || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
1864e4b17023SJohn Marino || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
1865e4b17023SJohn Marino || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
1866e4b17023SJohn Marino return;
1867e4b17023SJohn Marino
1868e4b17023SJohn Marino /* All checks succeeded. Build a new node to merge the cast. */
1869e4b17023SJohn Marino *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
1870e4b17023SJohn Marino TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
1871e4b17023SJohn Marino NULL_TREE, NULL_TREE);
1872e4b17023SJohn Marino *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
1873e4b17023SJohn Marino
1874e4b17023SJohn Marino /* We can have stripped a required restrict qualifier above. */
1875e4b17023SJohn Marino if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
1876e4b17023SJohn Marino *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
1877e4b17023SJohn Marino }
1878e4b17023SJohn Marino
1879e4b17023SJohn Marino /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
1880e4b17023SJohn Marino underneath as appropriate. */
1881e4b17023SJohn Marino
1882e4b17023SJohn Marino static enum gimplify_status
gimplify_conversion(tree * expr_p)1883e4b17023SJohn Marino gimplify_conversion (tree *expr_p)
1884e4b17023SJohn Marino {
1885e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
1886e4b17023SJohn Marino gcc_assert (CONVERT_EXPR_P (*expr_p));
1887e4b17023SJohn Marino
1888e4b17023SJohn Marino /* Then strip away all but the outermost conversion. */
1889e4b17023SJohn Marino STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
1890e4b17023SJohn Marino
1891e4b17023SJohn Marino /* And remove the outermost conversion if it's useless. */
1892e4b17023SJohn Marino if (tree_ssa_useless_type_conversion (*expr_p))
1893e4b17023SJohn Marino *expr_p = TREE_OPERAND (*expr_p, 0);
1894e4b17023SJohn Marino
1895e4b17023SJohn Marino /* If we still have a conversion at the toplevel,
1896e4b17023SJohn Marino then canonicalize some constructs. */
1897e4b17023SJohn Marino if (CONVERT_EXPR_P (*expr_p))
1898e4b17023SJohn Marino {
1899e4b17023SJohn Marino tree sub = TREE_OPERAND (*expr_p, 0);
1900e4b17023SJohn Marino
1901e4b17023SJohn Marino /* If a NOP conversion is changing the type of a COMPONENT_REF
1902e4b17023SJohn Marino expression, then canonicalize its type now in order to expose more
1903e4b17023SJohn Marino redundant conversions. */
1904e4b17023SJohn Marino if (TREE_CODE (sub) == COMPONENT_REF)
1905e4b17023SJohn Marino canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
1906e4b17023SJohn Marino
1907e4b17023SJohn Marino /* If a NOP conversion is changing a pointer to array of foo
1908e4b17023SJohn Marino to a pointer to foo, embed that change in the ADDR_EXPR. */
1909e4b17023SJohn Marino else if (TREE_CODE (sub) == ADDR_EXPR)
1910e4b17023SJohn Marino canonicalize_addr_expr (expr_p);
1911e4b17023SJohn Marino }
1912e4b17023SJohn Marino
1913e4b17023SJohn Marino /* If we have a conversion to a non-register type force the
1914e4b17023SJohn Marino use of a VIEW_CONVERT_EXPR instead. */
1915e4b17023SJohn Marino if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
1916e4b17023SJohn Marino *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
1917e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0));
1918e4b17023SJohn Marino
1919e4b17023SJohn Marino return GS_OK;
1920e4b17023SJohn Marino }
1921e4b17023SJohn Marino
1922e4b17023SJohn Marino /* Nonlocal VLAs seen in the current function. */
1923e4b17023SJohn Marino static struct pointer_set_t *nonlocal_vlas;
1924e4b17023SJohn Marino
1925*95d28233SJohn Marino /* The VAR_DECLs created for nonlocal VLAs for debug info purposes. */
1926*95d28233SJohn Marino static tree nonlocal_vla_vars;
1927*95d28233SJohn Marino
1928e4b17023SJohn Marino /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
1929e4b17023SJohn Marino DECL_VALUE_EXPR, and it's worth re-examining things. */
1930e4b17023SJohn Marino
1931e4b17023SJohn Marino static enum gimplify_status
gimplify_var_or_parm_decl(tree * expr_p)1932e4b17023SJohn Marino gimplify_var_or_parm_decl (tree *expr_p)
1933e4b17023SJohn Marino {
1934e4b17023SJohn Marino tree decl = *expr_p;
1935e4b17023SJohn Marino
1936e4b17023SJohn Marino /* ??? If this is a local variable, and it has not been seen in any
1937e4b17023SJohn Marino outer BIND_EXPR, then it's probably the result of a duplicate
1938e4b17023SJohn Marino declaration, for which we've already issued an error. It would
1939e4b17023SJohn Marino be really nice if the front end wouldn't leak these at all.
1940e4b17023SJohn Marino Currently the only known culprit is C++ destructors, as seen
1941e4b17023SJohn Marino in g++.old-deja/g++.jason/binding.C. */
1942e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
1943e4b17023SJohn Marino && !DECL_SEEN_IN_BIND_EXPR_P (decl)
1944e4b17023SJohn Marino && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
1945e4b17023SJohn Marino && decl_function_context (decl) == current_function_decl)
1946e4b17023SJohn Marino {
1947e4b17023SJohn Marino gcc_assert (seen_error ());
1948e4b17023SJohn Marino return GS_ERROR;
1949e4b17023SJohn Marino }
1950e4b17023SJohn Marino
1951e4b17023SJohn Marino /* When within an OpenMP context, notice uses of variables. */
1952e4b17023SJohn Marino if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
1953e4b17023SJohn Marino return GS_ALL_DONE;
1954e4b17023SJohn Marino
1955e4b17023SJohn Marino /* If the decl is an alias for another expression, substitute it now. */
1956e4b17023SJohn Marino if (DECL_HAS_VALUE_EXPR_P (decl))
1957e4b17023SJohn Marino {
1958e4b17023SJohn Marino tree value_expr = DECL_VALUE_EXPR (decl);
1959e4b17023SJohn Marino
1960e4b17023SJohn Marino /* For referenced nonlocal VLAs add a decl for debugging purposes
1961e4b17023SJohn Marino to the current function. */
1962e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
1963e4b17023SJohn Marino && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
1964e4b17023SJohn Marino && nonlocal_vlas != NULL
1965e4b17023SJohn Marino && TREE_CODE (value_expr) == INDIRECT_REF
1966e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL
1967e4b17023SJohn Marino && decl_function_context (decl) != current_function_decl)
1968e4b17023SJohn Marino {
1969e4b17023SJohn Marino struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1970e4b17023SJohn Marino while (ctx && ctx->region_type == ORT_WORKSHARE)
1971e4b17023SJohn Marino ctx = ctx->outer_context;
1972e4b17023SJohn Marino if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
1973e4b17023SJohn Marino {
1974*95d28233SJohn Marino tree copy = copy_node (decl);
1975e4b17023SJohn Marino
1976e4b17023SJohn Marino lang_hooks.dup_lang_specific_decl (copy);
1977e4b17023SJohn Marino SET_DECL_RTL (copy, 0);
1978e4b17023SJohn Marino TREE_USED (copy) = 1;
1979*95d28233SJohn Marino DECL_CHAIN (copy) = nonlocal_vla_vars;
1980*95d28233SJohn Marino nonlocal_vla_vars = copy;
1981e4b17023SJohn Marino SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
1982e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (copy) = 1;
1983e4b17023SJohn Marino }
1984e4b17023SJohn Marino }
1985e4b17023SJohn Marino
1986e4b17023SJohn Marino *expr_p = unshare_expr (value_expr);
1987e4b17023SJohn Marino return GS_OK;
1988e4b17023SJohn Marino }
1989e4b17023SJohn Marino
1990e4b17023SJohn Marino return GS_ALL_DONE;
1991e4b17023SJohn Marino }
1992e4b17023SJohn Marino
1993e4b17023SJohn Marino /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
1994e4b17023SJohn Marino node *EXPR_P.
1995e4b17023SJohn Marino
1996e4b17023SJohn Marino compound_lval
1997e4b17023SJohn Marino : min_lval '[' val ']'
1998e4b17023SJohn Marino | min_lval '.' ID
1999e4b17023SJohn Marino | compound_lval '[' val ']'
2000e4b17023SJohn Marino | compound_lval '.' ID
2001e4b17023SJohn Marino
2002e4b17023SJohn Marino This is not part of the original SIMPLE definition, which separates
2003e4b17023SJohn Marino array and member references, but it seems reasonable to handle them
2004e4b17023SJohn Marino together. Also, this way we don't run into problems with union
2005e4b17023SJohn Marino aliasing; gcc requires that for accesses through a union to alias, the
2006e4b17023SJohn Marino union reference must be explicit, which was not always the case when we
2007e4b17023SJohn Marino were splitting up array and member refs.
2008e4b17023SJohn Marino
2009e4b17023SJohn Marino PRE_P points to the sequence where side effects that must happen before
2010e4b17023SJohn Marino *EXPR_P should be stored.
2011e4b17023SJohn Marino
2012e4b17023SJohn Marino POST_P points to the sequence where side effects that must happen after
2013e4b17023SJohn Marino *EXPR_P should be stored. */
2014e4b17023SJohn Marino
2015e4b17023SJohn Marino static enum gimplify_status
gimplify_compound_lval(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,fallback_t fallback)2016e4b17023SJohn Marino gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
2017e4b17023SJohn Marino fallback_t fallback)
2018e4b17023SJohn Marino {
2019e4b17023SJohn Marino tree *p;
2020e4b17023SJohn Marino VEC(tree,heap) *stack;
2021e4b17023SJohn Marino enum gimplify_status ret = GS_ALL_DONE, tret;
2022e4b17023SJohn Marino int i;
2023e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
2024e4b17023SJohn Marino tree expr = *expr_p;
2025e4b17023SJohn Marino
2026e4b17023SJohn Marino /* Create a stack of the subexpressions so later we can walk them in
2027e4b17023SJohn Marino order from inner to outer. */
2028e4b17023SJohn Marino stack = VEC_alloc (tree, heap, 10);
2029e4b17023SJohn Marino
2030e4b17023SJohn Marino /* We can handle anything that get_inner_reference can deal with. */
2031e4b17023SJohn Marino for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
2032e4b17023SJohn Marino {
2033e4b17023SJohn Marino restart:
2034e4b17023SJohn Marino /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
2035e4b17023SJohn Marino if (TREE_CODE (*p) == INDIRECT_REF)
2036e4b17023SJohn Marino *p = fold_indirect_ref_loc (loc, *p);
2037e4b17023SJohn Marino
2038e4b17023SJohn Marino if (handled_component_p (*p))
2039e4b17023SJohn Marino ;
2040e4b17023SJohn Marino /* Expand DECL_VALUE_EXPR now. In some cases that may expose
2041e4b17023SJohn Marino additional COMPONENT_REFs. */
2042e4b17023SJohn Marino else if ((TREE_CODE (*p) == VAR_DECL || TREE_CODE (*p) == PARM_DECL)
2043e4b17023SJohn Marino && gimplify_var_or_parm_decl (p) == GS_OK)
2044e4b17023SJohn Marino goto restart;
2045e4b17023SJohn Marino else
2046e4b17023SJohn Marino break;
2047e4b17023SJohn Marino
2048e4b17023SJohn Marino VEC_safe_push (tree, heap, stack, *p);
2049e4b17023SJohn Marino }
2050e4b17023SJohn Marino
2051e4b17023SJohn Marino gcc_assert (VEC_length (tree, stack));
2052e4b17023SJohn Marino
2053e4b17023SJohn Marino /* Now STACK is a stack of pointers to all the refs we've walked through
2054e4b17023SJohn Marino and P points to the innermost expression.
2055e4b17023SJohn Marino
2056e4b17023SJohn Marino Java requires that we elaborated nodes in source order. That
2057e4b17023SJohn Marino means we must gimplify the inner expression followed by each of
2058e4b17023SJohn Marino the indices, in order. But we can't gimplify the inner
2059e4b17023SJohn Marino expression until we deal with any variable bounds, sizes, or
2060e4b17023SJohn Marino positions in order to deal with PLACEHOLDER_EXPRs.
2061e4b17023SJohn Marino
2062e4b17023SJohn Marino So we do this in three steps. First we deal with the annotations
2063e4b17023SJohn Marino for any variables in the components, then we gimplify the base,
2064e4b17023SJohn Marino then we gimplify any indices, from left to right. */
2065e4b17023SJohn Marino for (i = VEC_length (tree, stack) - 1; i >= 0; i--)
2066e4b17023SJohn Marino {
2067e4b17023SJohn Marino tree t = VEC_index (tree, stack, i);
2068e4b17023SJohn Marino
2069e4b17023SJohn Marino if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
2070e4b17023SJohn Marino {
2071e4b17023SJohn Marino /* Gimplify the low bound and element type size and put them into
2072e4b17023SJohn Marino the ARRAY_REF. If these values are set, they have already been
2073e4b17023SJohn Marino gimplified. */
2074e4b17023SJohn Marino if (TREE_OPERAND (t, 2) == NULL_TREE)
2075e4b17023SJohn Marino {
2076e4b17023SJohn Marino tree low = unshare_expr (array_ref_low_bound (t));
2077e4b17023SJohn Marino if (!is_gimple_min_invariant (low))
2078e4b17023SJohn Marino {
2079e4b17023SJohn Marino TREE_OPERAND (t, 2) = low;
2080e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
2081e4b17023SJohn Marino post_p, is_gimple_reg,
2082e4b17023SJohn Marino fb_rvalue);
2083e4b17023SJohn Marino ret = MIN (ret, tret);
2084e4b17023SJohn Marino }
2085e4b17023SJohn Marino }
2086e4b17023SJohn Marino else
2087e4b17023SJohn Marino {
2088e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
2089e4b17023SJohn Marino is_gimple_reg, fb_rvalue);
2090e4b17023SJohn Marino ret = MIN (ret, tret);
2091e4b17023SJohn Marino }
2092e4b17023SJohn Marino
2093e4b17023SJohn Marino if (TREE_OPERAND (t, 3) == NULL_TREE)
2094e4b17023SJohn Marino {
2095e4b17023SJohn Marino tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
2096e4b17023SJohn Marino tree elmt_size = unshare_expr (array_ref_element_size (t));
2097e4b17023SJohn Marino tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
2098e4b17023SJohn Marino
2099e4b17023SJohn Marino /* Divide the element size by the alignment of the element
2100e4b17023SJohn Marino type (above). */
2101e4b17023SJohn Marino elmt_size
2102e4b17023SJohn Marino = size_binop_loc (loc, EXACT_DIV_EXPR, elmt_size, factor);
2103e4b17023SJohn Marino
2104e4b17023SJohn Marino if (!is_gimple_min_invariant (elmt_size))
2105e4b17023SJohn Marino {
2106e4b17023SJohn Marino TREE_OPERAND (t, 3) = elmt_size;
2107e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
2108e4b17023SJohn Marino post_p, is_gimple_reg,
2109e4b17023SJohn Marino fb_rvalue);
2110e4b17023SJohn Marino ret = MIN (ret, tret);
2111e4b17023SJohn Marino }
2112e4b17023SJohn Marino }
2113e4b17023SJohn Marino else
2114e4b17023SJohn Marino {
2115e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
2116e4b17023SJohn Marino is_gimple_reg, fb_rvalue);
2117e4b17023SJohn Marino ret = MIN (ret, tret);
2118e4b17023SJohn Marino }
2119e4b17023SJohn Marino }
2120e4b17023SJohn Marino else if (TREE_CODE (t) == COMPONENT_REF)
2121e4b17023SJohn Marino {
2122e4b17023SJohn Marino /* Set the field offset into T and gimplify it. */
2123e4b17023SJohn Marino if (TREE_OPERAND (t, 2) == NULL_TREE)
2124e4b17023SJohn Marino {
2125e4b17023SJohn Marino tree offset = unshare_expr (component_ref_field_offset (t));
2126e4b17023SJohn Marino tree field = TREE_OPERAND (t, 1);
2127e4b17023SJohn Marino tree factor
2128e4b17023SJohn Marino = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
2129e4b17023SJohn Marino
2130e4b17023SJohn Marino /* Divide the offset by its alignment. */
2131e4b17023SJohn Marino offset = size_binop_loc (loc, EXACT_DIV_EXPR, offset, factor);
2132e4b17023SJohn Marino
2133e4b17023SJohn Marino if (!is_gimple_min_invariant (offset))
2134e4b17023SJohn Marino {
2135e4b17023SJohn Marino TREE_OPERAND (t, 2) = offset;
2136e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
2137e4b17023SJohn Marino post_p, is_gimple_reg,
2138e4b17023SJohn Marino fb_rvalue);
2139e4b17023SJohn Marino ret = MIN (ret, tret);
2140e4b17023SJohn Marino }
2141e4b17023SJohn Marino }
2142e4b17023SJohn Marino else
2143e4b17023SJohn Marino {
2144e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
2145e4b17023SJohn Marino is_gimple_reg, fb_rvalue);
2146e4b17023SJohn Marino ret = MIN (ret, tret);
2147e4b17023SJohn Marino }
2148e4b17023SJohn Marino }
2149e4b17023SJohn Marino }
2150e4b17023SJohn Marino
2151e4b17023SJohn Marino /* Step 2 is to gimplify the base expression. Make sure lvalue is set
2152e4b17023SJohn Marino so as to match the min_lval predicate. Failure to do so may result
2153e4b17023SJohn Marino in the creation of large aggregate temporaries. */
2154e4b17023SJohn Marino tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
2155e4b17023SJohn Marino fallback | fb_lvalue);
2156e4b17023SJohn Marino ret = MIN (ret, tret);
2157e4b17023SJohn Marino
2158e4b17023SJohn Marino /* And finally, the indices and operands to BIT_FIELD_REF. During this
2159e4b17023SJohn Marino loop we also remove any useless conversions. */
2160e4b17023SJohn Marino for (; VEC_length (tree, stack) > 0; )
2161e4b17023SJohn Marino {
2162e4b17023SJohn Marino tree t = VEC_pop (tree, stack);
2163e4b17023SJohn Marino
2164e4b17023SJohn Marino if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
2165e4b17023SJohn Marino {
2166e4b17023SJohn Marino /* Gimplify the dimension. */
2167e4b17023SJohn Marino if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
2168e4b17023SJohn Marino {
2169e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
2170e4b17023SJohn Marino is_gimple_val, fb_rvalue);
2171e4b17023SJohn Marino ret = MIN (ret, tret);
2172e4b17023SJohn Marino }
2173e4b17023SJohn Marino }
2174e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF)
2175e4b17023SJohn Marino {
2176e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
2177e4b17023SJohn Marino is_gimple_val, fb_rvalue);
2178e4b17023SJohn Marino ret = MIN (ret, tret);
2179e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
2180e4b17023SJohn Marino is_gimple_val, fb_rvalue);
2181e4b17023SJohn Marino ret = MIN (ret, tret);
2182e4b17023SJohn Marino }
2183e4b17023SJohn Marino
2184e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
2185e4b17023SJohn Marino
2186e4b17023SJohn Marino /* The innermost expression P may have originally had
2187e4b17023SJohn Marino TREE_SIDE_EFFECTS set which would have caused all the outer
2188e4b17023SJohn Marino expressions in *EXPR_P leading to P to also have had
2189e4b17023SJohn Marino TREE_SIDE_EFFECTS set. */
2190e4b17023SJohn Marino recalculate_side_effects (t);
2191e4b17023SJohn Marino }
2192e4b17023SJohn Marino
2193e4b17023SJohn Marino /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
2194e4b17023SJohn Marino if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
2195e4b17023SJohn Marino {
2196e4b17023SJohn Marino canonicalize_component_ref (expr_p);
2197e4b17023SJohn Marino }
2198e4b17023SJohn Marino
2199e4b17023SJohn Marino VEC_free (tree, heap, stack);
2200e4b17023SJohn Marino
2201e4b17023SJohn Marino gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
2202e4b17023SJohn Marino
2203e4b17023SJohn Marino return ret;
2204e4b17023SJohn Marino }
2205e4b17023SJohn Marino
2206e4b17023SJohn Marino /* Gimplify the self modifying expression pointed to by EXPR_P
2207e4b17023SJohn Marino (++, --, +=, -=).
2208e4b17023SJohn Marino
2209e4b17023SJohn Marino PRE_P points to the list where side effects that must happen before
2210e4b17023SJohn Marino *EXPR_P should be stored.
2211e4b17023SJohn Marino
2212e4b17023SJohn Marino POST_P points to the list where side effects that must happen after
2213e4b17023SJohn Marino *EXPR_P should be stored.
2214e4b17023SJohn Marino
2215e4b17023SJohn Marino WANT_VALUE is nonzero iff we want to use the value of this expression
2216e4b17023SJohn Marino in another expression. */
2217e4b17023SJohn Marino
2218e4b17023SJohn Marino static enum gimplify_status
gimplify_self_mod_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,bool want_value)2219e4b17023SJohn Marino gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
2220e4b17023SJohn Marino bool want_value)
2221e4b17023SJohn Marino {
2222e4b17023SJohn Marino enum tree_code code;
2223e4b17023SJohn Marino tree lhs, lvalue, rhs, t1;
2224e4b17023SJohn Marino gimple_seq post = NULL, *orig_post_p = post_p;
2225e4b17023SJohn Marino bool postfix;
2226e4b17023SJohn Marino enum tree_code arith_code;
2227e4b17023SJohn Marino enum gimplify_status ret;
2228e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
2229e4b17023SJohn Marino
2230e4b17023SJohn Marino code = TREE_CODE (*expr_p);
2231e4b17023SJohn Marino
2232e4b17023SJohn Marino gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
2233e4b17023SJohn Marino || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
2234e4b17023SJohn Marino
2235e4b17023SJohn Marino /* Prefix or postfix? */
2236e4b17023SJohn Marino if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
2237e4b17023SJohn Marino /* Faster to treat as prefix if result is not used. */
2238e4b17023SJohn Marino postfix = want_value;
2239e4b17023SJohn Marino else
2240e4b17023SJohn Marino postfix = false;
2241e4b17023SJohn Marino
2242e4b17023SJohn Marino /* For postfix, make sure the inner expression's post side effects
2243e4b17023SJohn Marino are executed after side effects from this expression. */
2244e4b17023SJohn Marino if (postfix)
2245e4b17023SJohn Marino post_p = &post;
2246e4b17023SJohn Marino
2247e4b17023SJohn Marino /* Add or subtract? */
2248e4b17023SJohn Marino if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
2249e4b17023SJohn Marino arith_code = PLUS_EXPR;
2250e4b17023SJohn Marino else
2251e4b17023SJohn Marino arith_code = MINUS_EXPR;
2252e4b17023SJohn Marino
2253e4b17023SJohn Marino /* Gimplify the LHS into a GIMPLE lvalue. */
2254e4b17023SJohn Marino lvalue = TREE_OPERAND (*expr_p, 0);
2255e4b17023SJohn Marino ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
2256e4b17023SJohn Marino if (ret == GS_ERROR)
2257e4b17023SJohn Marino return ret;
2258e4b17023SJohn Marino
2259e4b17023SJohn Marino /* Extract the operands to the arithmetic operation. */
2260e4b17023SJohn Marino lhs = lvalue;
2261e4b17023SJohn Marino rhs = TREE_OPERAND (*expr_p, 1);
2262e4b17023SJohn Marino
2263e4b17023SJohn Marino /* For postfix operator, we evaluate the LHS to an rvalue and then use
2264e4b17023SJohn Marino that as the result value and in the postqueue operation. We also
2265e4b17023SJohn Marino make sure to make lvalue a minimal lval, see
2266e4b17023SJohn Marino gcc.c-torture/execute/20040313-1.c for an example where this matters. */
2267e4b17023SJohn Marino if (postfix)
2268e4b17023SJohn Marino {
2269e4b17023SJohn Marino if (!is_gimple_min_lval (lvalue))
2270e4b17023SJohn Marino {
2271e4b17023SJohn Marino mark_addressable (lvalue);
2272e4b17023SJohn Marino lvalue = build_fold_addr_expr_loc (input_location, lvalue);
2273e4b17023SJohn Marino gimplify_expr (&lvalue, pre_p, post_p, is_gimple_val, fb_rvalue);
2274e4b17023SJohn Marino lvalue = build_fold_indirect_ref_loc (input_location, lvalue);
2275e4b17023SJohn Marino }
2276e4b17023SJohn Marino ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
2277e4b17023SJohn Marino if (ret == GS_ERROR)
2278e4b17023SJohn Marino return ret;
2279e4b17023SJohn Marino }
2280e4b17023SJohn Marino
2281e4b17023SJohn Marino /* For POINTERs increment, use POINTER_PLUS_EXPR. */
2282e4b17023SJohn Marino if (POINTER_TYPE_P (TREE_TYPE (lhs)))
2283e4b17023SJohn Marino {
2284e4b17023SJohn Marino rhs = convert_to_ptrofftype_loc (loc, rhs);
2285e4b17023SJohn Marino if (arith_code == MINUS_EXPR)
2286e4b17023SJohn Marino rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
2287e4b17023SJohn Marino arith_code = POINTER_PLUS_EXPR;
2288e4b17023SJohn Marino }
2289e4b17023SJohn Marino
2290e4b17023SJohn Marino t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
2291e4b17023SJohn Marino
2292e4b17023SJohn Marino if (postfix)
2293e4b17023SJohn Marino {
2294e4b17023SJohn Marino gimplify_assign (lvalue, t1, orig_post_p);
2295e4b17023SJohn Marino gimplify_seq_add_seq (orig_post_p, post);
2296e4b17023SJohn Marino *expr_p = lhs;
2297e4b17023SJohn Marino return GS_ALL_DONE;
2298e4b17023SJohn Marino }
2299e4b17023SJohn Marino else
2300e4b17023SJohn Marino {
2301e4b17023SJohn Marino *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
2302e4b17023SJohn Marino return GS_OK;
2303e4b17023SJohn Marino }
2304e4b17023SJohn Marino }
2305e4b17023SJohn Marino
2306e4b17023SJohn Marino /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
2307e4b17023SJohn Marino
2308e4b17023SJohn Marino static void
maybe_with_size_expr(tree * expr_p)2309e4b17023SJohn Marino maybe_with_size_expr (tree *expr_p)
2310e4b17023SJohn Marino {
2311e4b17023SJohn Marino tree expr = *expr_p;
2312e4b17023SJohn Marino tree type = TREE_TYPE (expr);
2313e4b17023SJohn Marino tree size;
2314e4b17023SJohn Marino
2315e4b17023SJohn Marino /* If we've already wrapped this or the type is error_mark_node, we can't do
2316e4b17023SJohn Marino anything. */
2317e4b17023SJohn Marino if (TREE_CODE (expr) == WITH_SIZE_EXPR
2318e4b17023SJohn Marino || type == error_mark_node)
2319e4b17023SJohn Marino return;
2320e4b17023SJohn Marino
2321e4b17023SJohn Marino /* If the size isn't known or is a constant, we have nothing to do. */
2322e4b17023SJohn Marino size = TYPE_SIZE_UNIT (type);
2323e4b17023SJohn Marino if (!size || TREE_CODE (size) == INTEGER_CST)
2324e4b17023SJohn Marino return;
2325e4b17023SJohn Marino
2326e4b17023SJohn Marino /* Otherwise, make a WITH_SIZE_EXPR. */
2327e4b17023SJohn Marino size = unshare_expr (size);
2328e4b17023SJohn Marino size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
2329e4b17023SJohn Marino *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
2330e4b17023SJohn Marino }
2331e4b17023SJohn Marino
2332e4b17023SJohn Marino /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
2333e4b17023SJohn Marino Store any side-effects in PRE_P. CALL_LOCATION is the location of
2334e4b17023SJohn Marino the CALL_EXPR. */
2335e4b17023SJohn Marino
2336e4b17023SJohn Marino static enum gimplify_status
gimplify_arg(tree * arg_p,gimple_seq * pre_p,location_t call_location)2337e4b17023SJohn Marino gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
2338e4b17023SJohn Marino {
2339e4b17023SJohn Marino bool (*test) (tree);
2340e4b17023SJohn Marino fallback_t fb;
2341e4b17023SJohn Marino
2342e4b17023SJohn Marino /* In general, we allow lvalues for function arguments to avoid
2343e4b17023SJohn Marino extra overhead of copying large aggregates out of even larger
2344e4b17023SJohn Marino aggregates into temporaries only to copy the temporaries to
2345e4b17023SJohn Marino the argument list. Make optimizers happy by pulling out to
2346e4b17023SJohn Marino temporaries those types that fit in registers. */
2347e4b17023SJohn Marino if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
2348e4b17023SJohn Marino test = is_gimple_val, fb = fb_rvalue;
2349e4b17023SJohn Marino else
2350e4b17023SJohn Marino {
2351e4b17023SJohn Marino test = is_gimple_lvalue, fb = fb_either;
2352e4b17023SJohn Marino /* Also strip a TARGET_EXPR that would force an extra copy. */
2353e4b17023SJohn Marino if (TREE_CODE (*arg_p) == TARGET_EXPR)
2354e4b17023SJohn Marino {
2355e4b17023SJohn Marino tree init = TARGET_EXPR_INITIAL (*arg_p);
2356e4b17023SJohn Marino if (init
2357e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (init)))
2358e4b17023SJohn Marino *arg_p = init;
2359e4b17023SJohn Marino }
2360e4b17023SJohn Marino }
2361e4b17023SJohn Marino
2362e4b17023SJohn Marino /* If this is a variable sized type, we must remember the size. */
2363e4b17023SJohn Marino maybe_with_size_expr (arg_p);
2364e4b17023SJohn Marino
2365e4b17023SJohn Marino /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
2366e4b17023SJohn Marino /* Make sure arguments have the same location as the function call
2367e4b17023SJohn Marino itself. */
2368e4b17023SJohn Marino protected_set_expr_location (*arg_p, call_location);
2369e4b17023SJohn Marino
2370e4b17023SJohn Marino /* There is a sequence point before a function call. Side effects in
2371e4b17023SJohn Marino the argument list must occur before the actual call. So, when
2372e4b17023SJohn Marino gimplifying arguments, force gimplify_expr to use an internal
2373e4b17023SJohn Marino post queue which is then appended to the end of PRE_P. */
2374e4b17023SJohn Marino return gimplify_expr (arg_p, pre_p, NULL, test, fb);
2375e4b17023SJohn Marino }
2376e4b17023SJohn Marino
2377e4b17023SJohn Marino /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
2378e4b17023SJohn Marino WANT_VALUE is true if the result of the call is desired. */
2379e4b17023SJohn Marino
2380e4b17023SJohn Marino static enum gimplify_status
gimplify_call_expr(tree * expr_p,gimple_seq * pre_p,bool want_value)2381e4b17023SJohn Marino gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
2382e4b17023SJohn Marino {
2383e4b17023SJohn Marino tree fndecl, parms, p, fnptrtype;
2384e4b17023SJohn Marino enum gimplify_status ret;
2385e4b17023SJohn Marino int i, nargs;
2386e4b17023SJohn Marino gimple call;
2387e4b17023SJohn Marino bool builtin_va_start_p = FALSE;
2388e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
2389e4b17023SJohn Marino
2390e4b17023SJohn Marino gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
2391e4b17023SJohn Marino
2392e4b17023SJohn Marino /* For reliable diagnostics during inlining, it is necessary that
2393e4b17023SJohn Marino every call_expr be annotated with file and line. */
2394e4b17023SJohn Marino if (! EXPR_HAS_LOCATION (*expr_p))
2395e4b17023SJohn Marino SET_EXPR_LOCATION (*expr_p, input_location);
2396e4b17023SJohn Marino
2397e4b17023SJohn Marino /* This may be a call to a builtin function.
2398e4b17023SJohn Marino
2399e4b17023SJohn Marino Builtin function calls may be transformed into different
2400e4b17023SJohn Marino (and more efficient) builtin function calls under certain
2401e4b17023SJohn Marino circumstances. Unfortunately, gimplification can muck things
2402e4b17023SJohn Marino up enough that the builtin expanders are not aware that certain
2403e4b17023SJohn Marino transformations are still valid.
2404e4b17023SJohn Marino
2405e4b17023SJohn Marino So we attempt transformation/gimplification of the call before
2406e4b17023SJohn Marino we gimplify the CALL_EXPR. At this time we do not manage to
2407e4b17023SJohn Marino transform all calls in the same manner as the expanders do, but
2408e4b17023SJohn Marino we do transform most of them. */
2409e4b17023SJohn Marino fndecl = get_callee_fndecl (*expr_p);
2410e4b17023SJohn Marino if (fndecl && DECL_BUILT_IN (fndecl))
2411e4b17023SJohn Marino {
2412e4b17023SJohn Marino tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
2413e4b17023SJohn Marino
2414e4b17023SJohn Marino if (new_tree && new_tree != *expr_p)
2415e4b17023SJohn Marino {
2416e4b17023SJohn Marino /* There was a transformation of this call which computes the
2417e4b17023SJohn Marino same value, but in a more efficient way. Return and try
2418e4b17023SJohn Marino again. */
2419e4b17023SJohn Marino *expr_p = new_tree;
2420e4b17023SJohn Marino return GS_OK;
2421e4b17023SJohn Marino }
2422e4b17023SJohn Marino
2423e4b17023SJohn Marino if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2424e4b17023SJohn Marino && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_VA_START)
2425e4b17023SJohn Marino {
2426e4b17023SJohn Marino builtin_va_start_p = TRUE;
2427e4b17023SJohn Marino if (call_expr_nargs (*expr_p) < 2)
2428e4b17023SJohn Marino {
2429e4b17023SJohn Marino error ("too few arguments to function %<va_start%>");
2430e4b17023SJohn Marino *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
2431e4b17023SJohn Marino return GS_OK;
2432e4b17023SJohn Marino }
2433e4b17023SJohn Marino
2434e4b17023SJohn Marino if (fold_builtin_next_arg (*expr_p, true))
2435e4b17023SJohn Marino {
2436e4b17023SJohn Marino *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
2437e4b17023SJohn Marino return GS_OK;
2438e4b17023SJohn Marino }
2439e4b17023SJohn Marino }
2440e4b17023SJohn Marino }
2441e4b17023SJohn Marino
2442e4b17023SJohn Marino /* Remember the original function pointer type. */
2443e4b17023SJohn Marino fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
2444e4b17023SJohn Marino
2445e4b17023SJohn Marino /* There is a sequence point before the call, so any side effects in
2446e4b17023SJohn Marino the calling expression must occur before the actual call. Force
2447e4b17023SJohn Marino gimplify_expr to use an internal post queue. */
2448e4b17023SJohn Marino ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
2449e4b17023SJohn Marino is_gimple_call_addr, fb_rvalue);
2450e4b17023SJohn Marino
2451e4b17023SJohn Marino nargs = call_expr_nargs (*expr_p);
2452e4b17023SJohn Marino
2453e4b17023SJohn Marino /* Get argument types for verification. */
2454e4b17023SJohn Marino fndecl = get_callee_fndecl (*expr_p);
2455e4b17023SJohn Marino parms = NULL_TREE;
2456e4b17023SJohn Marino if (fndecl)
2457e4b17023SJohn Marino parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
2458e4b17023SJohn Marino else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
2459e4b17023SJohn Marino parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
2460e4b17023SJohn Marino
2461e4b17023SJohn Marino if (fndecl && DECL_ARGUMENTS (fndecl))
2462e4b17023SJohn Marino p = DECL_ARGUMENTS (fndecl);
2463e4b17023SJohn Marino else if (parms)
2464e4b17023SJohn Marino p = parms;
2465e4b17023SJohn Marino else
2466e4b17023SJohn Marino p = NULL_TREE;
2467e4b17023SJohn Marino for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
2468e4b17023SJohn Marino ;
2469e4b17023SJohn Marino
2470e4b17023SJohn Marino /* If the last argument is __builtin_va_arg_pack () and it is not
2471e4b17023SJohn Marino passed as a named argument, decrease the number of CALL_EXPR
2472e4b17023SJohn Marino arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
2473e4b17023SJohn Marino if (!p
2474e4b17023SJohn Marino && i < nargs
2475e4b17023SJohn Marino && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
2476e4b17023SJohn Marino {
2477e4b17023SJohn Marino tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
2478e4b17023SJohn Marino tree last_arg_fndecl = get_callee_fndecl (last_arg);
2479e4b17023SJohn Marino
2480e4b17023SJohn Marino if (last_arg_fndecl
2481e4b17023SJohn Marino && TREE_CODE (last_arg_fndecl) == FUNCTION_DECL
2482e4b17023SJohn Marino && DECL_BUILT_IN_CLASS (last_arg_fndecl) == BUILT_IN_NORMAL
2483e4b17023SJohn Marino && DECL_FUNCTION_CODE (last_arg_fndecl) == BUILT_IN_VA_ARG_PACK)
2484e4b17023SJohn Marino {
2485e4b17023SJohn Marino tree call = *expr_p;
2486e4b17023SJohn Marino
2487e4b17023SJohn Marino --nargs;
2488e4b17023SJohn Marino *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
2489e4b17023SJohn Marino CALL_EXPR_FN (call),
2490e4b17023SJohn Marino nargs, CALL_EXPR_ARGP (call));
2491e4b17023SJohn Marino
2492e4b17023SJohn Marino /* Copy all CALL_EXPR flags, location and block, except
2493e4b17023SJohn Marino CALL_EXPR_VA_ARG_PACK flag. */
2494e4b17023SJohn Marino CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
2495e4b17023SJohn Marino CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
2496e4b17023SJohn Marino CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
2497e4b17023SJohn Marino = CALL_EXPR_RETURN_SLOT_OPT (call);
2498e4b17023SJohn Marino CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
2499e4b17023SJohn Marino SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
2500e4b17023SJohn Marino TREE_BLOCK (*expr_p) = TREE_BLOCK (call);
2501e4b17023SJohn Marino
2502e4b17023SJohn Marino /* Set CALL_EXPR_VA_ARG_PACK. */
2503e4b17023SJohn Marino CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
2504e4b17023SJohn Marino }
2505e4b17023SJohn Marino }
2506e4b17023SJohn Marino
2507e4b17023SJohn Marino /* Finally, gimplify the function arguments. */
2508e4b17023SJohn Marino if (nargs > 0)
2509e4b17023SJohn Marino {
2510e4b17023SJohn Marino for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
2511e4b17023SJohn Marino PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
2512e4b17023SJohn Marino PUSH_ARGS_REVERSED ? i-- : i++)
2513e4b17023SJohn Marino {
2514e4b17023SJohn Marino enum gimplify_status t;
2515e4b17023SJohn Marino
2516e4b17023SJohn Marino /* Avoid gimplifying the second argument to va_start, which needs to
2517e4b17023SJohn Marino be the plain PARM_DECL. */
2518e4b17023SJohn Marino if ((i != 1) || !builtin_va_start_p)
2519e4b17023SJohn Marino {
2520e4b17023SJohn Marino t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
2521e4b17023SJohn Marino EXPR_LOCATION (*expr_p));
2522e4b17023SJohn Marino
2523e4b17023SJohn Marino if (t == GS_ERROR)
2524e4b17023SJohn Marino ret = GS_ERROR;
2525e4b17023SJohn Marino }
2526e4b17023SJohn Marino }
2527e4b17023SJohn Marino }
2528e4b17023SJohn Marino
2529e4b17023SJohn Marino /* Verify the function result. */
2530e4b17023SJohn Marino if (want_value && fndecl
2531e4b17023SJohn Marino && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
2532e4b17023SJohn Marino {
2533e4b17023SJohn Marino error_at (loc, "using result of function returning %<void%>");
2534e4b17023SJohn Marino ret = GS_ERROR;
2535e4b17023SJohn Marino }
2536e4b17023SJohn Marino
2537e4b17023SJohn Marino /* Try this again in case gimplification exposed something. */
2538e4b17023SJohn Marino if (ret != GS_ERROR)
2539e4b17023SJohn Marino {
2540e4b17023SJohn Marino tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
2541e4b17023SJohn Marino
2542e4b17023SJohn Marino if (new_tree && new_tree != *expr_p)
2543e4b17023SJohn Marino {
2544e4b17023SJohn Marino /* There was a transformation of this call which computes the
2545e4b17023SJohn Marino same value, but in a more efficient way. Return and try
2546e4b17023SJohn Marino again. */
2547e4b17023SJohn Marino *expr_p = new_tree;
2548e4b17023SJohn Marino return GS_OK;
2549e4b17023SJohn Marino }
2550e4b17023SJohn Marino }
2551e4b17023SJohn Marino else
2552e4b17023SJohn Marino {
2553e4b17023SJohn Marino *expr_p = error_mark_node;
2554e4b17023SJohn Marino return GS_ERROR;
2555e4b17023SJohn Marino }
2556e4b17023SJohn Marino
2557e4b17023SJohn Marino /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
2558e4b17023SJohn Marino decl. This allows us to eliminate redundant or useless
2559e4b17023SJohn Marino calls to "const" functions. */
2560e4b17023SJohn Marino if (TREE_CODE (*expr_p) == CALL_EXPR)
2561e4b17023SJohn Marino {
2562e4b17023SJohn Marino int flags = call_expr_flags (*expr_p);
2563e4b17023SJohn Marino if (flags & (ECF_CONST | ECF_PURE)
2564e4b17023SJohn Marino /* An infinite loop is considered a side effect. */
2565e4b17023SJohn Marino && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
2566e4b17023SJohn Marino TREE_SIDE_EFFECTS (*expr_p) = 0;
2567e4b17023SJohn Marino }
2568e4b17023SJohn Marino
2569e4b17023SJohn Marino /* If the value is not needed by the caller, emit a new GIMPLE_CALL
2570e4b17023SJohn Marino and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
2571e4b17023SJohn Marino form and delegate the creation of a GIMPLE_CALL to
2572e4b17023SJohn Marino gimplify_modify_expr. This is always possible because when
2573e4b17023SJohn Marino WANT_VALUE is true, the caller wants the result of this call into
2574e4b17023SJohn Marino a temporary, which means that we will emit an INIT_EXPR in
2575e4b17023SJohn Marino internal_get_tmp_var which will then be handled by
2576e4b17023SJohn Marino gimplify_modify_expr. */
2577e4b17023SJohn Marino if (!want_value)
2578e4b17023SJohn Marino {
2579e4b17023SJohn Marino /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
2580e4b17023SJohn Marino have to do is replicate it as a GIMPLE_CALL tuple. */
2581e4b17023SJohn Marino gimple_stmt_iterator gsi;
2582e4b17023SJohn Marino call = gimple_build_call_from_tree (*expr_p);
2583e4b17023SJohn Marino gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
2584e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, call);
2585e4b17023SJohn Marino gsi = gsi_last (*pre_p);
2586e4b17023SJohn Marino fold_stmt (&gsi);
2587e4b17023SJohn Marino *expr_p = NULL_TREE;
2588e4b17023SJohn Marino }
2589e4b17023SJohn Marino else
2590e4b17023SJohn Marino /* Remember the original function type. */
2591e4b17023SJohn Marino CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
2592e4b17023SJohn Marino CALL_EXPR_FN (*expr_p));
2593e4b17023SJohn Marino
2594e4b17023SJohn Marino return ret;
2595e4b17023SJohn Marino }
2596e4b17023SJohn Marino
2597e4b17023SJohn Marino /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
2598e4b17023SJohn Marino rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
2599e4b17023SJohn Marino
2600e4b17023SJohn Marino TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
2601e4b17023SJohn Marino condition is true or false, respectively. If null, we should generate
2602e4b17023SJohn Marino our own to skip over the evaluation of this specific expression.
2603e4b17023SJohn Marino
2604e4b17023SJohn Marino LOCUS is the source location of the COND_EXPR.
2605e4b17023SJohn Marino
2606e4b17023SJohn Marino This function is the tree equivalent of do_jump.
2607e4b17023SJohn Marino
2608e4b17023SJohn Marino shortcut_cond_r should only be called by shortcut_cond_expr. */
2609e4b17023SJohn Marino
2610e4b17023SJohn Marino static tree
shortcut_cond_r(tree pred,tree * true_label_p,tree * false_label_p,location_t locus)2611e4b17023SJohn Marino shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
2612e4b17023SJohn Marino location_t locus)
2613e4b17023SJohn Marino {
2614e4b17023SJohn Marino tree local_label = NULL_TREE;
2615e4b17023SJohn Marino tree t, expr = NULL;
2616e4b17023SJohn Marino
2617e4b17023SJohn Marino /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
2618e4b17023SJohn Marino retain the shortcut semantics. Just insert the gotos here;
2619e4b17023SJohn Marino shortcut_cond_expr will append the real blocks later. */
2620e4b17023SJohn Marino if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
2621e4b17023SJohn Marino {
2622e4b17023SJohn Marino location_t new_locus;
2623e4b17023SJohn Marino
2624e4b17023SJohn Marino /* Turn if (a && b) into
2625e4b17023SJohn Marino
2626e4b17023SJohn Marino if (a); else goto no;
2627e4b17023SJohn Marino if (b) goto yes; else goto no;
2628e4b17023SJohn Marino (no:) */
2629e4b17023SJohn Marino
2630e4b17023SJohn Marino if (false_label_p == NULL)
2631e4b17023SJohn Marino false_label_p = &local_label;
2632e4b17023SJohn Marino
2633e4b17023SJohn Marino /* Keep the original source location on the first 'if'. */
2634e4b17023SJohn Marino t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus);
2635e4b17023SJohn Marino append_to_statement_list (t, &expr);
2636e4b17023SJohn Marino
2637e4b17023SJohn Marino /* Set the source location of the && on the second 'if'. */
2638e4b17023SJohn Marino new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
2639e4b17023SJohn Marino t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
2640e4b17023SJohn Marino new_locus);
2641e4b17023SJohn Marino append_to_statement_list (t, &expr);
2642e4b17023SJohn Marino }
2643e4b17023SJohn Marino else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
2644e4b17023SJohn Marino {
2645e4b17023SJohn Marino location_t new_locus;
2646e4b17023SJohn Marino
2647e4b17023SJohn Marino /* Turn if (a || b) into
2648e4b17023SJohn Marino
2649e4b17023SJohn Marino if (a) goto yes;
2650e4b17023SJohn Marino if (b) goto yes; else goto no;
2651e4b17023SJohn Marino (yes:) */
2652e4b17023SJohn Marino
2653e4b17023SJohn Marino if (true_label_p == NULL)
2654e4b17023SJohn Marino true_label_p = &local_label;
2655e4b17023SJohn Marino
2656e4b17023SJohn Marino /* Keep the original source location on the first 'if'. */
2657e4b17023SJohn Marino t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus);
2658e4b17023SJohn Marino append_to_statement_list (t, &expr);
2659e4b17023SJohn Marino
2660e4b17023SJohn Marino /* Set the source location of the || on the second 'if'. */
2661e4b17023SJohn Marino new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
2662e4b17023SJohn Marino t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
2663e4b17023SJohn Marino new_locus);
2664e4b17023SJohn Marino append_to_statement_list (t, &expr);
2665e4b17023SJohn Marino }
2666e4b17023SJohn Marino else if (TREE_CODE (pred) == COND_EXPR
2667e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
2668e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
2669e4b17023SJohn Marino {
2670e4b17023SJohn Marino location_t new_locus;
2671e4b17023SJohn Marino
2672e4b17023SJohn Marino /* As long as we're messing with gotos, turn if (a ? b : c) into
2673e4b17023SJohn Marino if (a)
2674e4b17023SJohn Marino if (b) goto yes; else goto no;
2675e4b17023SJohn Marino else
2676e4b17023SJohn Marino if (c) goto yes; else goto no;
2677e4b17023SJohn Marino
2678e4b17023SJohn Marino Don't do this if one of the arms has void type, which can happen
2679e4b17023SJohn Marino in C++ when the arm is throw. */
2680e4b17023SJohn Marino
2681e4b17023SJohn Marino /* Keep the original source location on the first 'if'. Set the source
2682e4b17023SJohn Marino location of the ? on the second 'if'. */
2683e4b17023SJohn Marino new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
2684e4b17023SJohn Marino expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
2685e4b17023SJohn Marino shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
2686e4b17023SJohn Marino false_label_p, locus),
2687e4b17023SJohn Marino shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
2688e4b17023SJohn Marino false_label_p, new_locus));
2689e4b17023SJohn Marino }
2690e4b17023SJohn Marino else
2691e4b17023SJohn Marino {
2692e4b17023SJohn Marino expr = build3 (COND_EXPR, void_type_node, pred,
2693e4b17023SJohn Marino build_and_jump (true_label_p),
2694e4b17023SJohn Marino build_and_jump (false_label_p));
2695e4b17023SJohn Marino SET_EXPR_LOCATION (expr, locus);
2696e4b17023SJohn Marino }
2697e4b17023SJohn Marino
2698e4b17023SJohn Marino if (local_label)
2699e4b17023SJohn Marino {
2700e4b17023SJohn Marino t = build1 (LABEL_EXPR, void_type_node, local_label);
2701e4b17023SJohn Marino append_to_statement_list (t, &expr);
2702e4b17023SJohn Marino }
2703e4b17023SJohn Marino
2704e4b17023SJohn Marino return expr;
2705e4b17023SJohn Marino }
2706e4b17023SJohn Marino
2707e4b17023SJohn Marino /* Given a conditional expression EXPR with short-circuit boolean
2708e4b17023SJohn Marino predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
2709e4b17023SJohn Marino predicate appart into the equivalent sequence of conditionals. */
2710e4b17023SJohn Marino
2711e4b17023SJohn Marino static tree
shortcut_cond_expr(tree expr)2712e4b17023SJohn Marino shortcut_cond_expr (tree expr)
2713e4b17023SJohn Marino {
2714e4b17023SJohn Marino tree pred = TREE_OPERAND (expr, 0);
2715e4b17023SJohn Marino tree then_ = TREE_OPERAND (expr, 1);
2716e4b17023SJohn Marino tree else_ = TREE_OPERAND (expr, 2);
2717e4b17023SJohn Marino tree true_label, false_label, end_label, t;
2718e4b17023SJohn Marino tree *true_label_p;
2719e4b17023SJohn Marino tree *false_label_p;
2720e4b17023SJohn Marino bool emit_end, emit_false, jump_over_else;
2721e4b17023SJohn Marino bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
2722e4b17023SJohn Marino bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
2723e4b17023SJohn Marino
2724e4b17023SJohn Marino /* First do simple transformations. */
2725e4b17023SJohn Marino if (!else_se)
2726e4b17023SJohn Marino {
2727e4b17023SJohn Marino /* If there is no 'else', turn
2728e4b17023SJohn Marino if (a && b) then c
2729e4b17023SJohn Marino into
2730e4b17023SJohn Marino if (a) if (b) then c. */
2731e4b17023SJohn Marino while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
2732e4b17023SJohn Marino {
2733e4b17023SJohn Marino /* Keep the original source location on the first 'if'. */
2734e4b17023SJohn Marino location_t locus = EXPR_LOC_OR_HERE (expr);
2735e4b17023SJohn Marino TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
2736e4b17023SJohn Marino /* Set the source location of the && on the second 'if'. */
2737e4b17023SJohn Marino if (EXPR_HAS_LOCATION (pred))
2738e4b17023SJohn Marino SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
2739e4b17023SJohn Marino then_ = shortcut_cond_expr (expr);
2740e4b17023SJohn Marino then_se = then_ && TREE_SIDE_EFFECTS (then_);
2741e4b17023SJohn Marino pred = TREE_OPERAND (pred, 0);
2742e4b17023SJohn Marino expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
2743e4b17023SJohn Marino SET_EXPR_LOCATION (expr, locus);
2744e4b17023SJohn Marino }
2745e4b17023SJohn Marino }
2746e4b17023SJohn Marino
2747e4b17023SJohn Marino if (!then_se)
2748e4b17023SJohn Marino {
2749e4b17023SJohn Marino /* If there is no 'then', turn
2750e4b17023SJohn Marino if (a || b); else d
2751e4b17023SJohn Marino into
2752e4b17023SJohn Marino if (a); else if (b); else d. */
2753e4b17023SJohn Marino while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
2754e4b17023SJohn Marino {
2755e4b17023SJohn Marino /* Keep the original source location on the first 'if'. */
2756e4b17023SJohn Marino location_t locus = EXPR_LOC_OR_HERE (expr);
2757e4b17023SJohn Marino TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
2758e4b17023SJohn Marino /* Set the source location of the || on the second 'if'. */
2759e4b17023SJohn Marino if (EXPR_HAS_LOCATION (pred))
2760e4b17023SJohn Marino SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
2761e4b17023SJohn Marino else_ = shortcut_cond_expr (expr);
2762e4b17023SJohn Marino else_se = else_ && TREE_SIDE_EFFECTS (else_);
2763e4b17023SJohn Marino pred = TREE_OPERAND (pred, 0);
2764e4b17023SJohn Marino expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
2765e4b17023SJohn Marino SET_EXPR_LOCATION (expr, locus);
2766e4b17023SJohn Marino }
2767e4b17023SJohn Marino }
2768e4b17023SJohn Marino
2769e4b17023SJohn Marino /* If we're done, great. */
2770e4b17023SJohn Marino if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
2771e4b17023SJohn Marino && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
2772e4b17023SJohn Marino return expr;
2773e4b17023SJohn Marino
2774e4b17023SJohn Marino /* Otherwise we need to mess with gotos. Change
2775e4b17023SJohn Marino if (a) c; else d;
2776e4b17023SJohn Marino to
2777e4b17023SJohn Marino if (a); else goto no;
2778e4b17023SJohn Marino c; goto end;
2779e4b17023SJohn Marino no: d; end:
2780e4b17023SJohn Marino and recursively gimplify the condition. */
2781e4b17023SJohn Marino
2782e4b17023SJohn Marino true_label = false_label = end_label = NULL_TREE;
2783e4b17023SJohn Marino
2784e4b17023SJohn Marino /* If our arms just jump somewhere, hijack those labels so we don't
2785e4b17023SJohn Marino generate jumps to jumps. */
2786e4b17023SJohn Marino
2787e4b17023SJohn Marino if (then_
2788e4b17023SJohn Marino && TREE_CODE (then_) == GOTO_EXPR
2789e4b17023SJohn Marino && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
2790e4b17023SJohn Marino {
2791e4b17023SJohn Marino true_label = GOTO_DESTINATION (then_);
2792e4b17023SJohn Marino then_ = NULL;
2793e4b17023SJohn Marino then_se = false;
2794e4b17023SJohn Marino }
2795e4b17023SJohn Marino
2796e4b17023SJohn Marino if (else_
2797e4b17023SJohn Marino && TREE_CODE (else_) == GOTO_EXPR
2798e4b17023SJohn Marino && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
2799e4b17023SJohn Marino {
2800e4b17023SJohn Marino false_label = GOTO_DESTINATION (else_);
2801e4b17023SJohn Marino else_ = NULL;
2802e4b17023SJohn Marino else_se = false;
2803e4b17023SJohn Marino }
2804e4b17023SJohn Marino
2805e4b17023SJohn Marino /* If we aren't hijacking a label for the 'then' branch, it falls through. */
2806e4b17023SJohn Marino if (true_label)
2807e4b17023SJohn Marino true_label_p = &true_label;
2808e4b17023SJohn Marino else
2809e4b17023SJohn Marino true_label_p = NULL;
2810e4b17023SJohn Marino
2811e4b17023SJohn Marino /* The 'else' branch also needs a label if it contains interesting code. */
2812e4b17023SJohn Marino if (false_label || else_se)
2813e4b17023SJohn Marino false_label_p = &false_label;
2814e4b17023SJohn Marino else
2815e4b17023SJohn Marino false_label_p = NULL;
2816e4b17023SJohn Marino
2817e4b17023SJohn Marino /* If there was nothing else in our arms, just forward the label(s). */
2818e4b17023SJohn Marino if (!then_se && !else_se)
2819e4b17023SJohn Marino return shortcut_cond_r (pred, true_label_p, false_label_p,
2820e4b17023SJohn Marino EXPR_LOC_OR_HERE (expr));
2821e4b17023SJohn Marino
2822e4b17023SJohn Marino /* If our last subexpression already has a terminal label, reuse it. */
2823e4b17023SJohn Marino if (else_se)
2824e4b17023SJohn Marino t = expr_last (else_);
2825e4b17023SJohn Marino else if (then_se)
2826e4b17023SJohn Marino t = expr_last (then_);
2827e4b17023SJohn Marino else
2828e4b17023SJohn Marino t = NULL;
2829e4b17023SJohn Marino if (t && TREE_CODE (t) == LABEL_EXPR)
2830e4b17023SJohn Marino end_label = LABEL_EXPR_LABEL (t);
2831e4b17023SJohn Marino
2832e4b17023SJohn Marino /* If we don't care about jumping to the 'else' branch, jump to the end
2833e4b17023SJohn Marino if the condition is false. */
2834e4b17023SJohn Marino if (!false_label_p)
2835e4b17023SJohn Marino false_label_p = &end_label;
2836e4b17023SJohn Marino
2837e4b17023SJohn Marino /* We only want to emit these labels if we aren't hijacking them. */
2838e4b17023SJohn Marino emit_end = (end_label == NULL_TREE);
2839e4b17023SJohn Marino emit_false = (false_label == NULL_TREE);
2840e4b17023SJohn Marino
2841e4b17023SJohn Marino /* We only emit the jump over the else clause if we have to--if the
2842e4b17023SJohn Marino then clause may fall through. Otherwise we can wind up with a
2843e4b17023SJohn Marino useless jump and a useless label at the end of gimplified code,
2844e4b17023SJohn Marino which will cause us to think that this conditional as a whole
2845e4b17023SJohn Marino falls through even if it doesn't. If we then inline a function
2846e4b17023SJohn Marino which ends with such a condition, that can cause us to issue an
2847e4b17023SJohn Marino inappropriate warning about control reaching the end of a
2848e4b17023SJohn Marino non-void function. */
2849e4b17023SJohn Marino jump_over_else = block_may_fallthru (then_);
2850e4b17023SJohn Marino
2851e4b17023SJohn Marino pred = shortcut_cond_r (pred, true_label_p, false_label_p,
2852e4b17023SJohn Marino EXPR_LOC_OR_HERE (expr));
2853e4b17023SJohn Marino
2854e4b17023SJohn Marino expr = NULL;
2855e4b17023SJohn Marino append_to_statement_list (pred, &expr);
2856e4b17023SJohn Marino
2857e4b17023SJohn Marino append_to_statement_list (then_, &expr);
2858e4b17023SJohn Marino if (else_se)
2859e4b17023SJohn Marino {
2860e4b17023SJohn Marino if (jump_over_else)
2861e4b17023SJohn Marino {
2862e4b17023SJohn Marino tree last = expr_last (expr);
2863e4b17023SJohn Marino t = build_and_jump (&end_label);
2864e4b17023SJohn Marino if (EXPR_HAS_LOCATION (last))
2865e4b17023SJohn Marino SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
2866e4b17023SJohn Marino append_to_statement_list (t, &expr);
2867e4b17023SJohn Marino }
2868e4b17023SJohn Marino if (emit_false)
2869e4b17023SJohn Marino {
2870e4b17023SJohn Marino t = build1 (LABEL_EXPR, void_type_node, false_label);
2871e4b17023SJohn Marino append_to_statement_list (t, &expr);
2872e4b17023SJohn Marino }
2873e4b17023SJohn Marino append_to_statement_list (else_, &expr);
2874e4b17023SJohn Marino }
2875e4b17023SJohn Marino if (emit_end && end_label)
2876e4b17023SJohn Marino {
2877e4b17023SJohn Marino t = build1 (LABEL_EXPR, void_type_node, end_label);
2878e4b17023SJohn Marino append_to_statement_list (t, &expr);
2879e4b17023SJohn Marino }
2880e4b17023SJohn Marino
2881e4b17023SJohn Marino return expr;
2882e4b17023SJohn Marino }
2883e4b17023SJohn Marino
2884e4b17023SJohn Marino /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
2885e4b17023SJohn Marino
2886e4b17023SJohn Marino tree
gimple_boolify(tree expr)2887e4b17023SJohn Marino gimple_boolify (tree expr)
2888e4b17023SJohn Marino {
2889e4b17023SJohn Marino tree type = TREE_TYPE (expr);
2890e4b17023SJohn Marino location_t loc = EXPR_LOCATION (expr);
2891e4b17023SJohn Marino
2892e4b17023SJohn Marino if (TREE_CODE (expr) == NE_EXPR
2893e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
2894e4b17023SJohn Marino && integer_zerop (TREE_OPERAND (expr, 1)))
2895e4b17023SJohn Marino {
2896e4b17023SJohn Marino tree call = TREE_OPERAND (expr, 0);
2897e4b17023SJohn Marino tree fn = get_callee_fndecl (call);
2898e4b17023SJohn Marino
2899e4b17023SJohn Marino /* For __builtin_expect ((long) (x), y) recurse into x as well
2900e4b17023SJohn Marino if x is truth_value_p. */
2901e4b17023SJohn Marino if (fn
2902e4b17023SJohn Marino && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
2903e4b17023SJohn Marino && DECL_FUNCTION_CODE (fn) == BUILT_IN_EXPECT
2904e4b17023SJohn Marino && call_expr_nargs (call) == 2)
2905e4b17023SJohn Marino {
2906e4b17023SJohn Marino tree arg = CALL_EXPR_ARG (call, 0);
2907e4b17023SJohn Marino if (arg)
2908e4b17023SJohn Marino {
2909e4b17023SJohn Marino if (TREE_CODE (arg) == NOP_EXPR
2910e4b17023SJohn Marino && TREE_TYPE (arg) == TREE_TYPE (call))
2911e4b17023SJohn Marino arg = TREE_OPERAND (arg, 0);
2912e4b17023SJohn Marino if (truth_value_p (TREE_CODE (arg)))
2913e4b17023SJohn Marino {
2914e4b17023SJohn Marino arg = gimple_boolify (arg);
2915e4b17023SJohn Marino CALL_EXPR_ARG (call, 0)
2916e4b17023SJohn Marino = fold_convert_loc (loc, TREE_TYPE (call), arg);
2917e4b17023SJohn Marino }
2918e4b17023SJohn Marino }
2919e4b17023SJohn Marino }
2920e4b17023SJohn Marino }
2921e4b17023SJohn Marino
2922e4b17023SJohn Marino switch (TREE_CODE (expr))
2923e4b17023SJohn Marino {
2924e4b17023SJohn Marino case TRUTH_AND_EXPR:
2925e4b17023SJohn Marino case TRUTH_OR_EXPR:
2926e4b17023SJohn Marino case TRUTH_XOR_EXPR:
2927e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
2928e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
2929e4b17023SJohn Marino /* Also boolify the arguments of truth exprs. */
2930e4b17023SJohn Marino TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
2931e4b17023SJohn Marino /* FALLTHRU */
2932e4b17023SJohn Marino
2933e4b17023SJohn Marino case TRUTH_NOT_EXPR:
2934e4b17023SJohn Marino TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
2935e4b17023SJohn Marino
2936e4b17023SJohn Marino /* These expressions always produce boolean results. */
2937e4b17023SJohn Marino if (TREE_CODE (type) != BOOLEAN_TYPE)
2938e4b17023SJohn Marino TREE_TYPE (expr) = boolean_type_node;
2939e4b17023SJohn Marino return expr;
2940e4b17023SJohn Marino
2941e4b17023SJohn Marino default:
2942e4b17023SJohn Marino if (COMPARISON_CLASS_P (expr))
2943e4b17023SJohn Marino {
2944e4b17023SJohn Marino /* There expressions always prduce boolean results. */
2945e4b17023SJohn Marino if (TREE_CODE (type) != BOOLEAN_TYPE)
2946e4b17023SJohn Marino TREE_TYPE (expr) = boolean_type_node;
2947e4b17023SJohn Marino return expr;
2948e4b17023SJohn Marino }
2949e4b17023SJohn Marino /* Other expressions that get here must have boolean values, but
2950e4b17023SJohn Marino might need to be converted to the appropriate mode. */
2951e4b17023SJohn Marino if (TREE_CODE (type) == BOOLEAN_TYPE)
2952e4b17023SJohn Marino return expr;
2953e4b17023SJohn Marino return fold_convert_loc (loc, boolean_type_node, expr);
2954e4b17023SJohn Marino }
2955e4b17023SJohn Marino }
2956e4b17023SJohn Marino
2957e4b17023SJohn Marino /* Given a conditional expression *EXPR_P without side effects, gimplify
2958e4b17023SJohn Marino its operands. New statements are inserted to PRE_P. */
2959e4b17023SJohn Marino
2960e4b17023SJohn Marino static enum gimplify_status
gimplify_pure_cond_expr(tree * expr_p,gimple_seq * pre_p)2961e4b17023SJohn Marino gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
2962e4b17023SJohn Marino {
2963e4b17023SJohn Marino tree expr = *expr_p, cond;
2964e4b17023SJohn Marino enum gimplify_status ret, tret;
2965e4b17023SJohn Marino enum tree_code code;
2966e4b17023SJohn Marino
2967e4b17023SJohn Marino cond = gimple_boolify (COND_EXPR_COND (expr));
2968e4b17023SJohn Marino
2969e4b17023SJohn Marino /* We need to handle && and || specially, as their gimplification
2970e4b17023SJohn Marino creates pure cond_expr, thus leading to an infinite cycle otherwise. */
2971e4b17023SJohn Marino code = TREE_CODE (cond);
2972e4b17023SJohn Marino if (code == TRUTH_ANDIF_EXPR)
2973e4b17023SJohn Marino TREE_SET_CODE (cond, TRUTH_AND_EXPR);
2974e4b17023SJohn Marino else if (code == TRUTH_ORIF_EXPR)
2975e4b17023SJohn Marino TREE_SET_CODE (cond, TRUTH_OR_EXPR);
2976e4b17023SJohn Marino ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_condexpr, fb_rvalue);
2977e4b17023SJohn Marino COND_EXPR_COND (*expr_p) = cond;
2978e4b17023SJohn Marino
2979e4b17023SJohn Marino tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
2980e4b17023SJohn Marino is_gimple_val, fb_rvalue);
2981e4b17023SJohn Marino ret = MIN (ret, tret);
2982e4b17023SJohn Marino tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
2983e4b17023SJohn Marino is_gimple_val, fb_rvalue);
2984e4b17023SJohn Marino
2985e4b17023SJohn Marino return MIN (ret, tret);
2986e4b17023SJohn Marino }
2987e4b17023SJohn Marino
2988e4b17023SJohn Marino /* Return true if evaluating EXPR could trap.
2989e4b17023SJohn Marino EXPR is GENERIC, while tree_could_trap_p can be called
2990e4b17023SJohn Marino only on GIMPLE. */
2991e4b17023SJohn Marino
2992e4b17023SJohn Marino static bool
generic_expr_could_trap_p(tree expr)2993e4b17023SJohn Marino generic_expr_could_trap_p (tree expr)
2994e4b17023SJohn Marino {
2995e4b17023SJohn Marino unsigned i, n;
2996e4b17023SJohn Marino
2997e4b17023SJohn Marino if (!expr || is_gimple_val (expr))
2998e4b17023SJohn Marino return false;
2999e4b17023SJohn Marino
3000e4b17023SJohn Marino if (!EXPR_P (expr) || tree_could_trap_p (expr))
3001e4b17023SJohn Marino return true;
3002e4b17023SJohn Marino
3003e4b17023SJohn Marino n = TREE_OPERAND_LENGTH (expr);
3004e4b17023SJohn Marino for (i = 0; i < n; i++)
3005e4b17023SJohn Marino if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
3006e4b17023SJohn Marino return true;
3007e4b17023SJohn Marino
3008e4b17023SJohn Marino return false;
3009e4b17023SJohn Marino }
3010e4b17023SJohn Marino
3011e4b17023SJohn Marino /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
3012e4b17023SJohn Marino into
3013e4b17023SJohn Marino
3014e4b17023SJohn Marino if (p) if (p)
3015e4b17023SJohn Marino t1 = a; a;
3016e4b17023SJohn Marino else or else
3017e4b17023SJohn Marino t1 = b; b;
3018e4b17023SJohn Marino t1;
3019e4b17023SJohn Marino
3020e4b17023SJohn Marino The second form is used when *EXPR_P is of type void.
3021e4b17023SJohn Marino
3022e4b17023SJohn Marino PRE_P points to the list where side effects that must happen before
3023e4b17023SJohn Marino *EXPR_P should be stored. */
3024e4b17023SJohn Marino
3025e4b17023SJohn Marino static enum gimplify_status
gimplify_cond_expr(tree * expr_p,gimple_seq * pre_p,fallback_t fallback)3026e4b17023SJohn Marino gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
3027e4b17023SJohn Marino {
3028e4b17023SJohn Marino tree expr = *expr_p;
3029e4b17023SJohn Marino tree type = TREE_TYPE (expr);
3030e4b17023SJohn Marino location_t loc = EXPR_LOCATION (expr);
3031e4b17023SJohn Marino tree tmp, arm1, arm2;
3032e4b17023SJohn Marino enum gimplify_status ret;
3033e4b17023SJohn Marino tree label_true, label_false, label_cont;
3034e4b17023SJohn Marino bool have_then_clause_p, have_else_clause_p;
3035e4b17023SJohn Marino gimple gimple_cond;
3036e4b17023SJohn Marino enum tree_code pred_code;
3037e4b17023SJohn Marino gimple_seq seq = NULL;
3038e4b17023SJohn Marino
3039e4b17023SJohn Marino /* If this COND_EXPR has a value, copy the values into a temporary within
3040e4b17023SJohn Marino the arms. */
3041e4b17023SJohn Marino if (!VOID_TYPE_P (type))
3042e4b17023SJohn Marino {
3043e4b17023SJohn Marino tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
3044e4b17023SJohn Marino tree result;
3045e4b17023SJohn Marino
3046e4b17023SJohn Marino /* If either an rvalue is ok or we do not require an lvalue, create the
3047e4b17023SJohn Marino temporary. But we cannot do that if the type is addressable. */
3048e4b17023SJohn Marino if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
3049e4b17023SJohn Marino && !TREE_ADDRESSABLE (type))
3050e4b17023SJohn Marino {
3051e4b17023SJohn Marino if (gimplify_ctxp->allow_rhs_cond_expr
3052e4b17023SJohn Marino /* If either branch has side effects or could trap, it can't be
3053e4b17023SJohn Marino evaluated unconditionally. */
3054e4b17023SJohn Marino && !TREE_SIDE_EFFECTS (then_)
3055e4b17023SJohn Marino && !generic_expr_could_trap_p (then_)
3056e4b17023SJohn Marino && !TREE_SIDE_EFFECTS (else_)
3057e4b17023SJohn Marino && !generic_expr_could_trap_p (else_))
3058e4b17023SJohn Marino return gimplify_pure_cond_expr (expr_p, pre_p);
3059e4b17023SJohn Marino
3060e4b17023SJohn Marino tmp = create_tmp_var (type, "iftmp");
3061e4b17023SJohn Marino result = tmp;
3062e4b17023SJohn Marino }
3063e4b17023SJohn Marino
3064e4b17023SJohn Marino /* Otherwise, only create and copy references to the values. */
3065e4b17023SJohn Marino else
3066e4b17023SJohn Marino {
3067e4b17023SJohn Marino type = build_pointer_type (type);
3068e4b17023SJohn Marino
3069e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (then_)))
3070e4b17023SJohn Marino then_ = build_fold_addr_expr_loc (loc, then_);
3071e4b17023SJohn Marino
3072e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (else_)))
3073e4b17023SJohn Marino else_ = build_fold_addr_expr_loc (loc, else_);
3074e4b17023SJohn Marino
3075e4b17023SJohn Marino expr
3076e4b17023SJohn Marino = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
3077e4b17023SJohn Marino
3078e4b17023SJohn Marino tmp = create_tmp_var (type, "iftmp");
3079e4b17023SJohn Marino result = build_simple_mem_ref_loc (loc, tmp);
3080e4b17023SJohn Marino }
3081e4b17023SJohn Marino
3082e4b17023SJohn Marino /* Build the new then clause, `tmp = then_;'. But don't build the
3083e4b17023SJohn Marino assignment if the value is void; in C++ it can be if it's a throw. */
3084e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (then_)))
3085e4b17023SJohn Marino TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
3086e4b17023SJohn Marino
3087e4b17023SJohn Marino /* Similarly, build the new else clause, `tmp = else_;'. */
3088e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (else_)))
3089e4b17023SJohn Marino TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
3090e4b17023SJohn Marino
3091e4b17023SJohn Marino TREE_TYPE (expr) = void_type_node;
3092e4b17023SJohn Marino recalculate_side_effects (expr);
3093e4b17023SJohn Marino
3094e4b17023SJohn Marino /* Move the COND_EXPR to the prequeue. */
3095e4b17023SJohn Marino gimplify_stmt (&expr, pre_p);
3096e4b17023SJohn Marino
3097e4b17023SJohn Marino *expr_p = result;
3098e4b17023SJohn Marino return GS_ALL_DONE;
3099e4b17023SJohn Marino }
3100e4b17023SJohn Marino
3101e4b17023SJohn Marino /* Remove any COMPOUND_EXPR so the following cases will be caught. */
3102e4b17023SJohn Marino STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
3103e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
3104e4b17023SJohn Marino gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
3105e4b17023SJohn Marino
3106e4b17023SJohn Marino /* Make sure the condition has BOOLEAN_TYPE. */
3107e4b17023SJohn Marino TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
3108e4b17023SJohn Marino
3109e4b17023SJohn Marino /* Break apart && and || conditions. */
3110e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
3111e4b17023SJohn Marino || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
3112e4b17023SJohn Marino {
3113e4b17023SJohn Marino expr = shortcut_cond_expr (expr);
3114e4b17023SJohn Marino
3115e4b17023SJohn Marino if (expr != *expr_p)
3116e4b17023SJohn Marino {
3117e4b17023SJohn Marino *expr_p = expr;
3118e4b17023SJohn Marino
3119e4b17023SJohn Marino /* We can't rely on gimplify_expr to re-gimplify the expanded
3120e4b17023SJohn Marino form properly, as cleanups might cause the target labels to be
3121e4b17023SJohn Marino wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
3122e4b17023SJohn Marino set up a conditional context. */
3123e4b17023SJohn Marino gimple_push_condition ();
3124e4b17023SJohn Marino gimplify_stmt (expr_p, &seq);
3125e4b17023SJohn Marino gimple_pop_condition (pre_p);
3126e4b17023SJohn Marino gimple_seq_add_seq (pre_p, seq);
3127e4b17023SJohn Marino
3128e4b17023SJohn Marino return GS_ALL_DONE;
3129e4b17023SJohn Marino }
3130e4b17023SJohn Marino }
3131e4b17023SJohn Marino
3132e4b17023SJohn Marino /* Now do the normal gimplification. */
3133e4b17023SJohn Marino
3134e4b17023SJohn Marino /* Gimplify condition. */
3135e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
3136e4b17023SJohn Marino fb_rvalue);
3137e4b17023SJohn Marino if (ret == GS_ERROR)
3138e4b17023SJohn Marino return GS_ERROR;
3139e4b17023SJohn Marino gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
3140e4b17023SJohn Marino
3141e4b17023SJohn Marino gimple_push_condition ();
3142e4b17023SJohn Marino
3143e4b17023SJohn Marino have_then_clause_p = have_else_clause_p = false;
3144e4b17023SJohn Marino if (TREE_OPERAND (expr, 1) != NULL
3145e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (expr, 1)) == GOTO_EXPR
3146e4b17023SJohn Marino && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 1))) == LABEL_DECL
3147e4b17023SJohn Marino && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 1)))
3148e4b17023SJohn Marino == current_function_decl)
3149e4b17023SJohn Marino /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
3150e4b17023SJohn Marino have different locations, otherwise we end up with incorrect
3151e4b17023SJohn Marino location information on the branches. */
3152e4b17023SJohn Marino && (optimize
3153e4b17023SJohn Marino || !EXPR_HAS_LOCATION (expr)
3154e4b17023SJohn Marino || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 1))
3155e4b17023SJohn Marino || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 1))))
3156e4b17023SJohn Marino {
3157e4b17023SJohn Marino label_true = GOTO_DESTINATION (TREE_OPERAND (expr, 1));
3158e4b17023SJohn Marino have_then_clause_p = true;
3159e4b17023SJohn Marino }
3160e4b17023SJohn Marino else
3161e4b17023SJohn Marino label_true = create_artificial_label (UNKNOWN_LOCATION);
3162e4b17023SJohn Marino if (TREE_OPERAND (expr, 2) != NULL
3163e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR
3164e4b17023SJohn Marino && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL
3165e4b17023SJohn Marino && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 2)))
3166e4b17023SJohn Marino == current_function_decl)
3167e4b17023SJohn Marino /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
3168e4b17023SJohn Marino have different locations, otherwise we end up with incorrect
3169e4b17023SJohn Marino location information on the branches. */
3170e4b17023SJohn Marino && (optimize
3171e4b17023SJohn Marino || !EXPR_HAS_LOCATION (expr)
3172e4b17023SJohn Marino || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 2))
3173e4b17023SJohn Marino || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 2))))
3174e4b17023SJohn Marino {
3175e4b17023SJohn Marino label_false = GOTO_DESTINATION (TREE_OPERAND (expr, 2));
3176e4b17023SJohn Marino have_else_clause_p = true;
3177e4b17023SJohn Marino }
3178e4b17023SJohn Marino else
3179e4b17023SJohn Marino label_false = create_artificial_label (UNKNOWN_LOCATION);
3180e4b17023SJohn Marino
3181e4b17023SJohn Marino gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
3182e4b17023SJohn Marino &arm2);
3183e4b17023SJohn Marino
3184e4b17023SJohn Marino gimple_cond = gimple_build_cond (pred_code, arm1, arm2, label_true,
3185e4b17023SJohn Marino label_false);
3186e4b17023SJohn Marino
3187e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, gimple_cond);
3188e4b17023SJohn Marino label_cont = NULL_TREE;
3189e4b17023SJohn Marino if (!have_then_clause_p)
3190e4b17023SJohn Marino {
3191e4b17023SJohn Marino /* For if (...) {} else { code; } put label_true after
3192e4b17023SJohn Marino the else block. */
3193e4b17023SJohn Marino if (TREE_OPERAND (expr, 1) == NULL_TREE
3194e4b17023SJohn Marino && !have_else_clause_p
3195e4b17023SJohn Marino && TREE_OPERAND (expr, 2) != NULL_TREE)
3196e4b17023SJohn Marino label_cont = label_true;
3197e4b17023SJohn Marino else
3198e4b17023SJohn Marino {
3199e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
3200e4b17023SJohn Marino have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
3201e4b17023SJohn Marino /* For if (...) { code; } else {} or
3202e4b17023SJohn Marino if (...) { code; } else goto label; or
3203e4b17023SJohn Marino if (...) { code; return; } else { ... }
3204e4b17023SJohn Marino label_cont isn't needed. */
3205e4b17023SJohn Marino if (!have_else_clause_p
3206e4b17023SJohn Marino && TREE_OPERAND (expr, 2) != NULL_TREE
3207e4b17023SJohn Marino && gimple_seq_may_fallthru (seq))
3208e4b17023SJohn Marino {
3209e4b17023SJohn Marino gimple g;
3210e4b17023SJohn Marino label_cont = create_artificial_label (UNKNOWN_LOCATION);
3211e4b17023SJohn Marino
3212e4b17023SJohn Marino g = gimple_build_goto (label_cont);
3213e4b17023SJohn Marino
3214e4b17023SJohn Marino /* GIMPLE_COND's are very low level; they have embedded
3215e4b17023SJohn Marino gotos. This particular embedded goto should not be marked
3216e4b17023SJohn Marino with the location of the original COND_EXPR, as it would
3217e4b17023SJohn Marino correspond to the COND_EXPR's condition, not the ELSE or the
3218e4b17023SJohn Marino THEN arms. To avoid marking it with the wrong location, flag
3219e4b17023SJohn Marino it as "no location". */
3220e4b17023SJohn Marino gimple_set_do_not_emit_location (g);
3221e4b17023SJohn Marino
3222e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, g);
3223e4b17023SJohn Marino }
3224e4b17023SJohn Marino }
3225e4b17023SJohn Marino }
3226e4b17023SJohn Marino if (!have_else_clause_p)
3227e4b17023SJohn Marino {
3228e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
3229e4b17023SJohn Marino have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
3230e4b17023SJohn Marino }
3231e4b17023SJohn Marino if (label_cont)
3232e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
3233e4b17023SJohn Marino
3234e4b17023SJohn Marino gimple_pop_condition (pre_p);
3235e4b17023SJohn Marino gimple_seq_add_seq (pre_p, seq);
3236e4b17023SJohn Marino
3237e4b17023SJohn Marino if (ret == GS_ERROR)
3238e4b17023SJohn Marino ; /* Do nothing. */
3239e4b17023SJohn Marino else if (have_then_clause_p || have_else_clause_p)
3240e4b17023SJohn Marino ret = GS_ALL_DONE;
3241e4b17023SJohn Marino else
3242e4b17023SJohn Marino {
3243e4b17023SJohn Marino /* Both arms are empty; replace the COND_EXPR with its predicate. */
3244e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
3245e4b17023SJohn Marino gimplify_stmt (&expr, pre_p);
3246e4b17023SJohn Marino }
3247e4b17023SJohn Marino
3248e4b17023SJohn Marino *expr_p = NULL;
3249e4b17023SJohn Marino return ret;
3250e4b17023SJohn Marino }
3251e4b17023SJohn Marino
3252e4b17023SJohn Marino /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
3253e4b17023SJohn Marino to be marked addressable.
3254e4b17023SJohn Marino
3255e4b17023SJohn Marino We cannot rely on such an expression being directly markable if a temporary
3256e4b17023SJohn Marino has been created by the gimplification. In this case, we create another
3257e4b17023SJohn Marino temporary and initialize it with a copy, which will become a store after we
3258e4b17023SJohn Marino mark it addressable. This can happen if the front-end passed us something
3259e4b17023SJohn Marino that it could not mark addressable yet, like a Fortran pass-by-reference
3260e4b17023SJohn Marino parameter (int) floatvar. */
3261e4b17023SJohn Marino
3262e4b17023SJohn Marino static void
prepare_gimple_addressable(tree * expr_p,gimple_seq * seq_p)3263e4b17023SJohn Marino prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
3264e4b17023SJohn Marino {
3265e4b17023SJohn Marino while (handled_component_p (*expr_p))
3266e4b17023SJohn Marino expr_p = &TREE_OPERAND (*expr_p, 0);
3267e4b17023SJohn Marino if (is_gimple_reg (*expr_p))
3268e4b17023SJohn Marino *expr_p = get_initialized_tmp_var (*expr_p, seq_p, NULL);
3269e4b17023SJohn Marino }
3270e4b17023SJohn Marino
3271e4b17023SJohn Marino /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
3272e4b17023SJohn Marino a call to __builtin_memcpy. */
3273e4b17023SJohn Marino
3274e4b17023SJohn Marino static enum gimplify_status
gimplify_modify_expr_to_memcpy(tree * expr_p,tree size,bool want_value,gimple_seq * seq_p)3275e4b17023SJohn Marino gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
3276e4b17023SJohn Marino gimple_seq *seq_p)
3277e4b17023SJohn Marino {
3278e4b17023SJohn Marino tree t, to, to_ptr, from, from_ptr;
3279e4b17023SJohn Marino gimple gs;
3280e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
3281e4b17023SJohn Marino
3282e4b17023SJohn Marino to = TREE_OPERAND (*expr_p, 0);
3283e4b17023SJohn Marino from = TREE_OPERAND (*expr_p, 1);
3284e4b17023SJohn Marino
3285e4b17023SJohn Marino /* Mark the RHS addressable. Beware that it may not be possible to do so
3286e4b17023SJohn Marino directly if a temporary has been created by the gimplification. */
3287e4b17023SJohn Marino prepare_gimple_addressable (&from, seq_p);
3288e4b17023SJohn Marino
3289e4b17023SJohn Marino mark_addressable (from);
3290e4b17023SJohn Marino from_ptr = build_fold_addr_expr_loc (loc, from);
3291e4b17023SJohn Marino gimplify_arg (&from_ptr, seq_p, loc);
3292e4b17023SJohn Marino
3293e4b17023SJohn Marino mark_addressable (to);
3294e4b17023SJohn Marino to_ptr = build_fold_addr_expr_loc (loc, to);
3295e4b17023SJohn Marino gimplify_arg (&to_ptr, seq_p, loc);
3296e4b17023SJohn Marino
3297e4b17023SJohn Marino t = builtin_decl_implicit (BUILT_IN_MEMCPY);
3298e4b17023SJohn Marino
3299e4b17023SJohn Marino gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
3300e4b17023SJohn Marino
3301e4b17023SJohn Marino if (want_value)
3302e4b17023SJohn Marino {
3303e4b17023SJohn Marino /* tmp = memcpy() */
3304e4b17023SJohn Marino t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
3305e4b17023SJohn Marino gimple_call_set_lhs (gs, t);
3306e4b17023SJohn Marino gimplify_seq_add_stmt (seq_p, gs);
3307e4b17023SJohn Marino
3308e4b17023SJohn Marino *expr_p = build_simple_mem_ref (t);
3309e4b17023SJohn Marino return GS_ALL_DONE;
3310e4b17023SJohn Marino }
3311e4b17023SJohn Marino
3312e4b17023SJohn Marino gimplify_seq_add_stmt (seq_p, gs);
3313e4b17023SJohn Marino *expr_p = NULL;
3314e4b17023SJohn Marino return GS_ALL_DONE;
3315e4b17023SJohn Marino }
3316e4b17023SJohn Marino
3317e4b17023SJohn Marino /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
3318e4b17023SJohn Marino a call to __builtin_memset. In this case we know that the RHS is
3319e4b17023SJohn Marino a CONSTRUCTOR with an empty element list. */
3320e4b17023SJohn Marino
3321e4b17023SJohn Marino static enum gimplify_status
gimplify_modify_expr_to_memset(tree * expr_p,tree size,bool want_value,gimple_seq * seq_p)3322e4b17023SJohn Marino gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
3323e4b17023SJohn Marino gimple_seq *seq_p)
3324e4b17023SJohn Marino {
3325e4b17023SJohn Marino tree t, from, to, to_ptr;
3326e4b17023SJohn Marino gimple gs;
3327e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
3328e4b17023SJohn Marino
3329e4b17023SJohn Marino /* Assert our assumptions, to abort instead of producing wrong code
3330e4b17023SJohn Marino silently if they are not met. Beware that the RHS CONSTRUCTOR might
3331e4b17023SJohn Marino not be immediately exposed. */
3332e4b17023SJohn Marino from = TREE_OPERAND (*expr_p, 1);
3333e4b17023SJohn Marino if (TREE_CODE (from) == WITH_SIZE_EXPR)
3334e4b17023SJohn Marino from = TREE_OPERAND (from, 0);
3335e4b17023SJohn Marino
3336e4b17023SJohn Marino gcc_assert (TREE_CODE (from) == CONSTRUCTOR
3337e4b17023SJohn Marino && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (from)));
3338e4b17023SJohn Marino
3339e4b17023SJohn Marino /* Now proceed. */
3340e4b17023SJohn Marino to = TREE_OPERAND (*expr_p, 0);
3341e4b17023SJohn Marino
3342e4b17023SJohn Marino to_ptr = build_fold_addr_expr_loc (loc, to);
3343e4b17023SJohn Marino gimplify_arg (&to_ptr, seq_p, loc);
3344e4b17023SJohn Marino t = builtin_decl_implicit (BUILT_IN_MEMSET);
3345e4b17023SJohn Marino
3346e4b17023SJohn Marino gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
3347e4b17023SJohn Marino
3348e4b17023SJohn Marino if (want_value)
3349e4b17023SJohn Marino {
3350e4b17023SJohn Marino /* tmp = memset() */
3351e4b17023SJohn Marino t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
3352e4b17023SJohn Marino gimple_call_set_lhs (gs, t);
3353e4b17023SJohn Marino gimplify_seq_add_stmt (seq_p, gs);
3354e4b17023SJohn Marino
3355e4b17023SJohn Marino *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
3356e4b17023SJohn Marino return GS_ALL_DONE;
3357e4b17023SJohn Marino }
3358e4b17023SJohn Marino
3359e4b17023SJohn Marino gimplify_seq_add_stmt (seq_p, gs);
3360e4b17023SJohn Marino *expr_p = NULL;
3361e4b17023SJohn Marino return GS_ALL_DONE;
3362e4b17023SJohn Marino }
3363e4b17023SJohn Marino
3364e4b17023SJohn Marino /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
3365e4b17023SJohn Marino determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
3366e4b17023SJohn Marino assignment. Return non-null if we detect a potential overlap. */
3367e4b17023SJohn Marino
3368e4b17023SJohn Marino struct gimplify_init_ctor_preeval_data
3369e4b17023SJohn Marino {
3370e4b17023SJohn Marino /* The base decl of the lhs object. May be NULL, in which case we
3371e4b17023SJohn Marino have to assume the lhs is indirect. */
3372e4b17023SJohn Marino tree lhs_base_decl;
3373e4b17023SJohn Marino
3374e4b17023SJohn Marino /* The alias set of the lhs object. */
3375e4b17023SJohn Marino alias_set_type lhs_alias_set;
3376e4b17023SJohn Marino };
3377e4b17023SJohn Marino
3378e4b17023SJohn Marino static tree
gimplify_init_ctor_preeval_1(tree * tp,int * walk_subtrees,void * xdata)3379e4b17023SJohn Marino gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
3380e4b17023SJohn Marino {
3381e4b17023SJohn Marino struct gimplify_init_ctor_preeval_data *data
3382e4b17023SJohn Marino = (struct gimplify_init_ctor_preeval_data *) xdata;
3383e4b17023SJohn Marino tree t = *tp;
3384e4b17023SJohn Marino
3385e4b17023SJohn Marino /* If we find the base object, obviously we have overlap. */
3386e4b17023SJohn Marino if (data->lhs_base_decl == t)
3387e4b17023SJohn Marino return t;
3388e4b17023SJohn Marino
3389e4b17023SJohn Marino /* If the constructor component is indirect, determine if we have a
3390e4b17023SJohn Marino potential overlap with the lhs. The only bits of information we
3391e4b17023SJohn Marino have to go on at this point are addressability and alias sets. */
3392e4b17023SJohn Marino if ((INDIRECT_REF_P (t)
3393e4b17023SJohn Marino || TREE_CODE (t) == MEM_REF)
3394e4b17023SJohn Marino && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
3395e4b17023SJohn Marino && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
3396e4b17023SJohn Marino return t;
3397e4b17023SJohn Marino
3398e4b17023SJohn Marino /* If the constructor component is a call, determine if it can hide a
3399e4b17023SJohn Marino potential overlap with the lhs through an INDIRECT_REF like above.
3400e4b17023SJohn Marino ??? Ugh - this is completely broken. In fact this whole analysis
3401e4b17023SJohn Marino doesn't look conservative. */
3402e4b17023SJohn Marino if (TREE_CODE (t) == CALL_EXPR)
3403e4b17023SJohn Marino {
3404e4b17023SJohn Marino tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
3405e4b17023SJohn Marino
3406e4b17023SJohn Marino for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
3407e4b17023SJohn Marino if (POINTER_TYPE_P (TREE_VALUE (type))
3408e4b17023SJohn Marino && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
3409e4b17023SJohn Marino && alias_sets_conflict_p (data->lhs_alias_set,
3410e4b17023SJohn Marino get_alias_set
3411e4b17023SJohn Marino (TREE_TYPE (TREE_VALUE (type)))))
3412e4b17023SJohn Marino return t;
3413e4b17023SJohn Marino }
3414e4b17023SJohn Marino
3415e4b17023SJohn Marino if (IS_TYPE_OR_DECL_P (t))
3416e4b17023SJohn Marino *walk_subtrees = 0;
3417e4b17023SJohn Marino return NULL;
3418e4b17023SJohn Marino }
3419e4b17023SJohn Marino
3420e4b17023SJohn Marino /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
3421e4b17023SJohn Marino force values that overlap with the lhs (as described by *DATA)
3422e4b17023SJohn Marino into temporaries. */
3423e4b17023SJohn Marino
3424e4b17023SJohn Marino static void
gimplify_init_ctor_preeval(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,struct gimplify_init_ctor_preeval_data * data)3425e4b17023SJohn Marino gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3426e4b17023SJohn Marino struct gimplify_init_ctor_preeval_data *data)
3427e4b17023SJohn Marino {
3428e4b17023SJohn Marino enum gimplify_status one;
3429e4b17023SJohn Marino
3430e4b17023SJohn Marino /* If the value is constant, then there's nothing to pre-evaluate. */
3431e4b17023SJohn Marino if (TREE_CONSTANT (*expr_p))
3432e4b17023SJohn Marino {
3433e4b17023SJohn Marino /* Ensure it does not have side effects, it might contain a reference to
3434e4b17023SJohn Marino the object we're initializing. */
3435e4b17023SJohn Marino gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
3436e4b17023SJohn Marino return;
3437e4b17023SJohn Marino }
3438e4b17023SJohn Marino
3439e4b17023SJohn Marino /* If the type has non-trivial constructors, we can't pre-evaluate. */
3440e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
3441e4b17023SJohn Marino return;
3442e4b17023SJohn Marino
3443e4b17023SJohn Marino /* Recurse for nested constructors. */
3444e4b17023SJohn Marino if (TREE_CODE (*expr_p) == CONSTRUCTOR)
3445e4b17023SJohn Marino {
3446e4b17023SJohn Marino unsigned HOST_WIDE_INT ix;
3447e4b17023SJohn Marino constructor_elt *ce;
3448e4b17023SJohn Marino VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p);
3449e4b17023SJohn Marino
3450e4b17023SJohn Marino FOR_EACH_VEC_ELT (constructor_elt, v, ix, ce)
3451e4b17023SJohn Marino gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
3452e4b17023SJohn Marino
3453e4b17023SJohn Marino return;
3454e4b17023SJohn Marino }
3455e4b17023SJohn Marino
3456e4b17023SJohn Marino /* If this is a variable sized type, we must remember the size. */
3457e4b17023SJohn Marino maybe_with_size_expr (expr_p);
3458e4b17023SJohn Marino
3459e4b17023SJohn Marino /* Gimplify the constructor element to something appropriate for the rhs
3460e4b17023SJohn Marino of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
3461e4b17023SJohn Marino the gimplifier will consider this a store to memory. Doing this
3462e4b17023SJohn Marino gimplification now means that we won't have to deal with complicated
3463e4b17023SJohn Marino language-specific trees, nor trees like SAVE_EXPR that can induce
3464e4b17023SJohn Marino exponential search behavior. */
3465e4b17023SJohn Marino one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
3466e4b17023SJohn Marino if (one == GS_ERROR)
3467e4b17023SJohn Marino {
3468e4b17023SJohn Marino *expr_p = NULL;
3469e4b17023SJohn Marino return;
3470e4b17023SJohn Marino }
3471e4b17023SJohn Marino
3472e4b17023SJohn Marino /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
3473e4b17023SJohn Marino with the lhs, since "a = { .x=a }" doesn't make sense. This will
3474e4b17023SJohn Marino always be true for all scalars, since is_gimple_mem_rhs insists on a
3475e4b17023SJohn Marino temporary variable for them. */
3476e4b17023SJohn Marino if (DECL_P (*expr_p))
3477e4b17023SJohn Marino return;
3478e4b17023SJohn Marino
3479e4b17023SJohn Marino /* If this is of variable size, we have no choice but to assume it doesn't
3480e4b17023SJohn Marino overlap since we can't make a temporary for it. */
3481e4b17023SJohn Marino if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
3482e4b17023SJohn Marino return;
3483e4b17023SJohn Marino
3484e4b17023SJohn Marino /* Otherwise, we must search for overlap ... */
3485e4b17023SJohn Marino if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
3486e4b17023SJohn Marino return;
3487e4b17023SJohn Marino
3488e4b17023SJohn Marino /* ... and if found, force the value into a temporary. */
3489e4b17023SJohn Marino *expr_p = get_formal_tmp_var (*expr_p, pre_p);
3490e4b17023SJohn Marino }
3491e4b17023SJohn Marino
3492e4b17023SJohn Marino /* A subroutine of gimplify_init_ctor_eval. Create a loop for
3493e4b17023SJohn Marino a RANGE_EXPR in a CONSTRUCTOR for an array.
3494e4b17023SJohn Marino
3495e4b17023SJohn Marino var = lower;
3496e4b17023SJohn Marino loop_entry:
3497e4b17023SJohn Marino object[var] = value;
3498e4b17023SJohn Marino if (var == upper)
3499e4b17023SJohn Marino goto loop_exit;
3500e4b17023SJohn Marino var = var + 1;
3501e4b17023SJohn Marino goto loop_entry;
3502e4b17023SJohn Marino loop_exit:
3503e4b17023SJohn Marino
3504e4b17023SJohn Marino We increment var _after_ the loop exit check because we might otherwise
3505e4b17023SJohn Marino fail if upper == TYPE_MAX_VALUE (type for upper).
3506e4b17023SJohn Marino
3507e4b17023SJohn Marino Note that we never have to deal with SAVE_EXPRs here, because this has
3508e4b17023SJohn Marino already been taken care of for us, in gimplify_init_ctor_preeval(). */
3509e4b17023SJohn Marino
3510e4b17023SJohn Marino static void gimplify_init_ctor_eval (tree, VEC(constructor_elt,gc) *,
3511e4b17023SJohn Marino gimple_seq *, bool);
3512e4b17023SJohn Marino
3513e4b17023SJohn Marino static void
gimplify_init_ctor_eval_range(tree object,tree lower,tree upper,tree value,tree array_elt_type,gimple_seq * pre_p,bool cleared)3514e4b17023SJohn Marino gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
3515e4b17023SJohn Marino tree value, tree array_elt_type,
3516e4b17023SJohn Marino gimple_seq *pre_p, bool cleared)
3517e4b17023SJohn Marino {
3518e4b17023SJohn Marino tree loop_entry_label, loop_exit_label, fall_thru_label;
3519e4b17023SJohn Marino tree var, var_type, cref, tmp;
3520e4b17023SJohn Marino
3521e4b17023SJohn Marino loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
3522e4b17023SJohn Marino loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
3523e4b17023SJohn Marino fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
3524e4b17023SJohn Marino
3525e4b17023SJohn Marino /* Create and initialize the index variable. */
3526e4b17023SJohn Marino var_type = TREE_TYPE (upper);
3527e4b17023SJohn Marino var = create_tmp_var (var_type, NULL);
3528e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
3529e4b17023SJohn Marino
3530e4b17023SJohn Marino /* Add the loop entry label. */
3531e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
3532e4b17023SJohn Marino
3533e4b17023SJohn Marino /* Build the reference. */
3534e4b17023SJohn Marino cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
3535e4b17023SJohn Marino var, NULL_TREE, NULL_TREE);
3536e4b17023SJohn Marino
3537e4b17023SJohn Marino /* If we are a constructor, just call gimplify_init_ctor_eval to do
3538e4b17023SJohn Marino the store. Otherwise just assign value to the reference. */
3539e4b17023SJohn Marino
3540e4b17023SJohn Marino if (TREE_CODE (value) == CONSTRUCTOR)
3541e4b17023SJohn Marino /* NB we might have to call ourself recursively through
3542e4b17023SJohn Marino gimplify_init_ctor_eval if the value is a constructor. */
3543e4b17023SJohn Marino gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
3544e4b17023SJohn Marino pre_p, cleared);
3545e4b17023SJohn Marino else
3546e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
3547e4b17023SJohn Marino
3548e4b17023SJohn Marino /* We exit the loop when the index var is equal to the upper bound. */
3549e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p,
3550e4b17023SJohn Marino gimple_build_cond (EQ_EXPR, var, upper,
3551e4b17023SJohn Marino loop_exit_label, fall_thru_label));
3552e4b17023SJohn Marino
3553e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
3554e4b17023SJohn Marino
3555e4b17023SJohn Marino /* Otherwise, increment the index var... */
3556e4b17023SJohn Marino tmp = build2 (PLUS_EXPR, var_type, var,
3557e4b17023SJohn Marino fold_convert (var_type, integer_one_node));
3558e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
3559e4b17023SJohn Marino
3560e4b17023SJohn Marino /* ...and jump back to the loop entry. */
3561e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
3562e4b17023SJohn Marino
3563e4b17023SJohn Marino /* Add the loop exit label. */
3564e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
3565e4b17023SJohn Marino }
3566e4b17023SJohn Marino
3567e4b17023SJohn Marino /* Return true if FDECL is accessing a field that is zero sized. */
3568e4b17023SJohn Marino
3569e4b17023SJohn Marino static bool
zero_sized_field_decl(const_tree fdecl)3570e4b17023SJohn Marino zero_sized_field_decl (const_tree fdecl)
3571e4b17023SJohn Marino {
3572e4b17023SJohn Marino if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl)
3573e4b17023SJohn Marino && integer_zerop (DECL_SIZE (fdecl)))
3574e4b17023SJohn Marino return true;
3575e4b17023SJohn Marino return false;
3576e4b17023SJohn Marino }
3577e4b17023SJohn Marino
3578e4b17023SJohn Marino /* Return true if TYPE is zero sized. */
3579e4b17023SJohn Marino
3580e4b17023SJohn Marino static bool
zero_sized_type(const_tree type)3581e4b17023SJohn Marino zero_sized_type (const_tree type)
3582e4b17023SJohn Marino {
3583e4b17023SJohn Marino if (AGGREGATE_TYPE_P (type) && TYPE_SIZE (type)
3584e4b17023SJohn Marino && integer_zerop (TYPE_SIZE (type)))
3585e4b17023SJohn Marino return true;
3586e4b17023SJohn Marino return false;
3587e4b17023SJohn Marino }
3588e4b17023SJohn Marino
3589e4b17023SJohn Marino /* A subroutine of gimplify_init_constructor. Generate individual
3590e4b17023SJohn Marino MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
3591e4b17023SJohn Marino assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
3592e4b17023SJohn Marino CONSTRUCTOR. CLEARED is true if the entire LHS object has been
3593e4b17023SJohn Marino zeroed first. */
3594e4b17023SJohn Marino
3595e4b17023SJohn Marino static void
gimplify_init_ctor_eval(tree object,VEC (constructor_elt,gc)* elts,gimple_seq * pre_p,bool cleared)3596e4b17023SJohn Marino gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
3597e4b17023SJohn Marino gimple_seq *pre_p, bool cleared)
3598e4b17023SJohn Marino {
3599e4b17023SJohn Marino tree array_elt_type = NULL;
3600e4b17023SJohn Marino unsigned HOST_WIDE_INT ix;
3601e4b17023SJohn Marino tree purpose, value;
3602e4b17023SJohn Marino
3603e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
3604e4b17023SJohn Marino array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
3605e4b17023SJohn Marino
3606e4b17023SJohn Marino FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
3607e4b17023SJohn Marino {
3608e4b17023SJohn Marino tree cref;
3609e4b17023SJohn Marino
3610e4b17023SJohn Marino /* NULL values are created above for gimplification errors. */
3611e4b17023SJohn Marino if (value == NULL)
3612e4b17023SJohn Marino continue;
3613e4b17023SJohn Marino
3614e4b17023SJohn Marino if (cleared && initializer_zerop (value))
3615e4b17023SJohn Marino continue;
3616e4b17023SJohn Marino
3617e4b17023SJohn Marino /* ??? Here's to hoping the front end fills in all of the indices,
3618e4b17023SJohn Marino so we don't have to figure out what's missing ourselves. */
3619e4b17023SJohn Marino gcc_assert (purpose);
3620e4b17023SJohn Marino
3621e4b17023SJohn Marino /* Skip zero-sized fields, unless value has side-effects. This can
3622e4b17023SJohn Marino happen with calls to functions returning a zero-sized type, which
3623e4b17023SJohn Marino we shouldn't discard. As a number of downstream passes don't
3624e4b17023SJohn Marino expect sets of zero-sized fields, we rely on the gimplification of
3625e4b17023SJohn Marino the MODIFY_EXPR we make below to drop the assignment statement. */
3626e4b17023SJohn Marino if (! TREE_SIDE_EFFECTS (value) && zero_sized_field_decl (purpose))
3627e4b17023SJohn Marino continue;
3628e4b17023SJohn Marino
3629e4b17023SJohn Marino /* If we have a RANGE_EXPR, we have to build a loop to assign the
3630e4b17023SJohn Marino whole range. */
3631e4b17023SJohn Marino if (TREE_CODE (purpose) == RANGE_EXPR)
3632e4b17023SJohn Marino {
3633e4b17023SJohn Marino tree lower = TREE_OPERAND (purpose, 0);
3634e4b17023SJohn Marino tree upper = TREE_OPERAND (purpose, 1);
3635e4b17023SJohn Marino
3636e4b17023SJohn Marino /* If the lower bound is equal to upper, just treat it as if
3637e4b17023SJohn Marino upper was the index. */
3638e4b17023SJohn Marino if (simple_cst_equal (lower, upper))
3639e4b17023SJohn Marino purpose = upper;
3640e4b17023SJohn Marino else
3641e4b17023SJohn Marino {
3642e4b17023SJohn Marino gimplify_init_ctor_eval_range (object, lower, upper, value,
3643e4b17023SJohn Marino array_elt_type, pre_p, cleared);
3644e4b17023SJohn Marino continue;
3645e4b17023SJohn Marino }
3646e4b17023SJohn Marino }
3647e4b17023SJohn Marino
3648e4b17023SJohn Marino if (array_elt_type)
3649e4b17023SJohn Marino {
3650e4b17023SJohn Marino /* Do not use bitsizetype for ARRAY_REF indices. */
3651e4b17023SJohn Marino if (TYPE_DOMAIN (TREE_TYPE (object)))
3652e4b17023SJohn Marino purpose
3653e4b17023SJohn Marino = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
3654e4b17023SJohn Marino purpose);
3655e4b17023SJohn Marino cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
3656e4b17023SJohn Marino purpose, NULL_TREE, NULL_TREE);
3657e4b17023SJohn Marino }
3658e4b17023SJohn Marino else
3659e4b17023SJohn Marino {
3660e4b17023SJohn Marino gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
3661e4b17023SJohn Marino cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
3662e4b17023SJohn Marino unshare_expr (object), purpose, NULL_TREE);
3663e4b17023SJohn Marino }
3664e4b17023SJohn Marino
3665e4b17023SJohn Marino if (TREE_CODE (value) == CONSTRUCTOR
3666e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
3667e4b17023SJohn Marino gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
3668e4b17023SJohn Marino pre_p, cleared);
3669e4b17023SJohn Marino else
3670e4b17023SJohn Marino {
3671e4b17023SJohn Marino tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
3672e4b17023SJohn Marino gimplify_and_add (init, pre_p);
3673e4b17023SJohn Marino ggc_free (init);
3674e4b17023SJohn Marino }
3675e4b17023SJohn Marino }
3676e4b17023SJohn Marino }
3677e4b17023SJohn Marino
3678e4b17023SJohn Marino /* Return the appropriate RHS predicate for this LHS. */
3679e4b17023SJohn Marino
3680e4b17023SJohn Marino gimple_predicate
rhs_predicate_for(tree lhs)3681e4b17023SJohn Marino rhs_predicate_for (tree lhs)
3682e4b17023SJohn Marino {
3683e4b17023SJohn Marino if (is_gimple_reg (lhs))
3684e4b17023SJohn Marino return is_gimple_reg_rhs_or_call;
3685e4b17023SJohn Marino else
3686e4b17023SJohn Marino return is_gimple_mem_rhs_or_call;
3687e4b17023SJohn Marino }
3688e4b17023SJohn Marino
3689e4b17023SJohn Marino /* Gimplify a C99 compound literal expression. This just means adding
3690e4b17023SJohn Marino the DECL_EXPR before the current statement and using its anonymous
3691e4b17023SJohn Marino decl instead. */
3692e4b17023SJohn Marino
3693e4b17023SJohn Marino static enum gimplify_status
gimplify_compound_literal_expr(tree * expr_p,gimple_seq * pre_p)3694e4b17023SJohn Marino gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p)
3695e4b17023SJohn Marino {
3696e4b17023SJohn Marino tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
3697e4b17023SJohn Marino tree decl = DECL_EXPR_DECL (decl_s);
3698e4b17023SJohn Marino /* Mark the decl as addressable if the compound literal
3699e4b17023SJohn Marino expression is addressable now, otherwise it is marked too late
3700e4b17023SJohn Marino after we gimplify the initialization expression. */
3701e4b17023SJohn Marino if (TREE_ADDRESSABLE (*expr_p))
3702e4b17023SJohn Marino TREE_ADDRESSABLE (decl) = 1;
3703e4b17023SJohn Marino
3704e4b17023SJohn Marino /* Preliminarily mark non-addressed complex variables as eligible
3705e4b17023SJohn Marino for promotion to gimple registers. We'll transform their uses
3706e4b17023SJohn Marino as we find them. */
3707e4b17023SJohn Marino if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE
3708e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE)
3709e4b17023SJohn Marino && !TREE_THIS_VOLATILE (decl)
3710e4b17023SJohn Marino && !needs_to_live_in_memory (decl))
3711e4b17023SJohn Marino DECL_GIMPLE_REG_P (decl) = 1;
3712e4b17023SJohn Marino
3713e4b17023SJohn Marino /* This decl isn't mentioned in the enclosing block, so add it to the
3714e4b17023SJohn Marino list of temps. FIXME it seems a bit of a kludge to say that
3715e4b17023SJohn Marino anonymous artificial vars aren't pushed, but everything else is. */
3716e4b17023SJohn Marino if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
3717e4b17023SJohn Marino gimple_add_tmp_var (decl);
3718e4b17023SJohn Marino
3719e4b17023SJohn Marino gimplify_and_add (decl_s, pre_p);
3720e4b17023SJohn Marino *expr_p = decl;
3721e4b17023SJohn Marino return GS_OK;
3722e4b17023SJohn Marino }
3723e4b17023SJohn Marino
3724e4b17023SJohn Marino /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
3725e4b17023SJohn Marino return a new CONSTRUCTOR if something changed. */
3726e4b17023SJohn Marino
3727e4b17023SJohn Marino static tree
optimize_compound_literals_in_ctor(tree orig_ctor)3728e4b17023SJohn Marino optimize_compound_literals_in_ctor (tree orig_ctor)
3729e4b17023SJohn Marino {
3730e4b17023SJohn Marino tree ctor = orig_ctor;
3731e4b17023SJohn Marino VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor);
3732e4b17023SJohn Marino unsigned int idx, num = VEC_length (constructor_elt, elts);
3733e4b17023SJohn Marino
3734e4b17023SJohn Marino for (idx = 0; idx < num; idx++)
3735e4b17023SJohn Marino {
3736e4b17023SJohn Marino tree value = VEC_index (constructor_elt, elts, idx)->value;
3737e4b17023SJohn Marino tree newval = value;
3738e4b17023SJohn Marino if (TREE_CODE (value) == CONSTRUCTOR)
3739e4b17023SJohn Marino newval = optimize_compound_literals_in_ctor (value);
3740e4b17023SJohn Marino else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
3741e4b17023SJohn Marino {
3742e4b17023SJohn Marino tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
3743e4b17023SJohn Marino tree decl = DECL_EXPR_DECL (decl_s);
3744e4b17023SJohn Marino tree init = DECL_INITIAL (decl);
3745e4b17023SJohn Marino
3746e4b17023SJohn Marino if (!TREE_ADDRESSABLE (value)
3747e4b17023SJohn Marino && !TREE_ADDRESSABLE (decl)
3748e4b17023SJohn Marino && init
3749e4b17023SJohn Marino && TREE_CODE (init) == CONSTRUCTOR)
3750e4b17023SJohn Marino newval = optimize_compound_literals_in_ctor (init);
3751e4b17023SJohn Marino }
3752e4b17023SJohn Marino if (newval == value)
3753e4b17023SJohn Marino continue;
3754e4b17023SJohn Marino
3755e4b17023SJohn Marino if (ctor == orig_ctor)
3756e4b17023SJohn Marino {
3757e4b17023SJohn Marino ctor = copy_node (orig_ctor);
3758e4b17023SJohn Marino CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts);
3759e4b17023SJohn Marino elts = CONSTRUCTOR_ELTS (ctor);
3760e4b17023SJohn Marino }
3761e4b17023SJohn Marino VEC_index (constructor_elt, elts, idx)->value = newval;
3762e4b17023SJohn Marino }
3763e4b17023SJohn Marino return ctor;
3764e4b17023SJohn Marino }
3765e4b17023SJohn Marino
3766e4b17023SJohn Marino /* A subroutine of gimplify_modify_expr. Break out elements of a
3767e4b17023SJohn Marino CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
3768e4b17023SJohn Marino
3769e4b17023SJohn Marino Note that we still need to clear any elements that don't have explicit
3770e4b17023SJohn Marino initializers, so if not all elements are initialized we keep the
3771e4b17023SJohn Marino original MODIFY_EXPR, we just remove all of the constructor elements.
3772e4b17023SJohn Marino
3773e4b17023SJohn Marino If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
3774e4b17023SJohn Marino GS_ERROR if we would have to create a temporary when gimplifying
3775e4b17023SJohn Marino this constructor. Otherwise, return GS_OK.
3776e4b17023SJohn Marino
3777e4b17023SJohn Marino If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
3778e4b17023SJohn Marino
3779e4b17023SJohn Marino static enum gimplify_status
gimplify_init_constructor(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,bool want_value,bool notify_temp_creation)3780e4b17023SJohn Marino gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3781e4b17023SJohn Marino bool want_value, bool notify_temp_creation)
3782e4b17023SJohn Marino {
3783e4b17023SJohn Marino tree object, ctor, type;
3784e4b17023SJohn Marino enum gimplify_status ret;
3785e4b17023SJohn Marino VEC(constructor_elt,gc) *elts;
3786e4b17023SJohn Marino
3787e4b17023SJohn Marino gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
3788e4b17023SJohn Marino
3789e4b17023SJohn Marino if (!notify_temp_creation)
3790e4b17023SJohn Marino {
3791e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
3792e4b17023SJohn Marino is_gimple_lvalue, fb_lvalue);
3793e4b17023SJohn Marino if (ret == GS_ERROR)
3794e4b17023SJohn Marino return ret;
3795e4b17023SJohn Marino }
3796e4b17023SJohn Marino
3797e4b17023SJohn Marino object = TREE_OPERAND (*expr_p, 0);
3798e4b17023SJohn Marino ctor = TREE_OPERAND (*expr_p, 1) =
3799e4b17023SJohn Marino optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
3800e4b17023SJohn Marino type = TREE_TYPE (ctor);
3801e4b17023SJohn Marino elts = CONSTRUCTOR_ELTS (ctor);
3802e4b17023SJohn Marino ret = GS_ALL_DONE;
3803e4b17023SJohn Marino
3804e4b17023SJohn Marino switch (TREE_CODE (type))
3805e4b17023SJohn Marino {
3806e4b17023SJohn Marino case RECORD_TYPE:
3807e4b17023SJohn Marino case UNION_TYPE:
3808e4b17023SJohn Marino case QUAL_UNION_TYPE:
3809e4b17023SJohn Marino case ARRAY_TYPE:
3810e4b17023SJohn Marino {
3811e4b17023SJohn Marino struct gimplify_init_ctor_preeval_data preeval_data;
3812e4b17023SJohn Marino HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
3813e4b17023SJohn Marino bool cleared, complete_p, valid_const_initializer;
3814e4b17023SJohn Marino
3815e4b17023SJohn Marino /* Aggregate types must lower constructors to initialization of
3816e4b17023SJohn Marino individual elements. The exception is that a CONSTRUCTOR node
3817e4b17023SJohn Marino with no elements indicates zero-initialization of the whole. */
3818e4b17023SJohn Marino if (VEC_empty (constructor_elt, elts))
3819e4b17023SJohn Marino {
3820e4b17023SJohn Marino if (notify_temp_creation)
3821e4b17023SJohn Marino return GS_OK;
3822e4b17023SJohn Marino break;
3823e4b17023SJohn Marino }
3824e4b17023SJohn Marino
3825e4b17023SJohn Marino /* Fetch information about the constructor to direct later processing.
3826e4b17023SJohn Marino We might want to make static versions of it in various cases, and
3827e4b17023SJohn Marino can only do so if it known to be a valid constant initializer. */
3828e4b17023SJohn Marino valid_const_initializer
3829e4b17023SJohn Marino = categorize_ctor_elements (ctor, &num_nonzero_elements,
3830e4b17023SJohn Marino &num_ctor_elements, &complete_p);
3831e4b17023SJohn Marino
3832e4b17023SJohn Marino /* If a const aggregate variable is being initialized, then it
3833e4b17023SJohn Marino should never be a lose to promote the variable to be static. */
3834e4b17023SJohn Marino if (valid_const_initializer
3835e4b17023SJohn Marino && num_nonzero_elements > 1
3836e4b17023SJohn Marino && TREE_READONLY (object)
3837e4b17023SJohn Marino && TREE_CODE (object) == VAR_DECL
3838e4b17023SJohn Marino && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)))
3839e4b17023SJohn Marino {
3840e4b17023SJohn Marino if (notify_temp_creation)
3841e4b17023SJohn Marino return GS_ERROR;
3842e4b17023SJohn Marino DECL_INITIAL (object) = ctor;
3843e4b17023SJohn Marino TREE_STATIC (object) = 1;
3844e4b17023SJohn Marino if (!DECL_NAME (object))
3845e4b17023SJohn Marino DECL_NAME (object) = create_tmp_var_name ("C");
3846e4b17023SJohn Marino walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
3847e4b17023SJohn Marino
3848e4b17023SJohn Marino /* ??? C++ doesn't automatically append a .<number> to the
3849e4b17023SJohn Marino assembler name, and even when it does, it looks a FE private
3850e4b17023SJohn Marino data structures to figure out what that number should be,
3851e4b17023SJohn Marino which are not set for this variable. I suppose this is
3852e4b17023SJohn Marino important for local statics for inline functions, which aren't
3853e4b17023SJohn Marino "local" in the object file sense. So in order to get a unique
3854e4b17023SJohn Marino TU-local symbol, we must invoke the lhd version now. */
3855e4b17023SJohn Marino lhd_set_decl_assembler_name (object);
3856e4b17023SJohn Marino
3857e4b17023SJohn Marino *expr_p = NULL_TREE;
3858e4b17023SJohn Marino break;
3859e4b17023SJohn Marino }
3860e4b17023SJohn Marino
3861e4b17023SJohn Marino /* If there are "lots" of initialized elements, even discounting
3862e4b17023SJohn Marino those that are not address constants (and thus *must* be
3863e4b17023SJohn Marino computed at runtime), then partition the constructor into
3864e4b17023SJohn Marino constant and non-constant parts. Block copy the constant
3865e4b17023SJohn Marino parts in, then generate code for the non-constant parts. */
3866e4b17023SJohn Marino /* TODO. There's code in cp/typeck.c to do this. */
3867e4b17023SJohn Marino
3868e4b17023SJohn Marino if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
3869e4b17023SJohn Marino /* store_constructor will ignore the clearing of variable-sized
3870e4b17023SJohn Marino objects. Initializers for such objects must explicitly set
3871e4b17023SJohn Marino every field that needs to be set. */
3872e4b17023SJohn Marino cleared = false;
3873e4b17023SJohn Marino else if (!complete_p)
3874e4b17023SJohn Marino /* If the constructor isn't complete, clear the whole object
3875e4b17023SJohn Marino beforehand.
3876e4b17023SJohn Marino
3877e4b17023SJohn Marino ??? This ought not to be needed. For any element not present
3878e4b17023SJohn Marino in the initializer, we should simply set them to zero. Except
3879e4b17023SJohn Marino we'd need to *find* the elements that are not present, and that
3880e4b17023SJohn Marino requires trickery to avoid quadratic compile-time behavior in
3881e4b17023SJohn Marino large cases or excessive memory use in small cases. */
3882e4b17023SJohn Marino cleared = true;
3883e4b17023SJohn Marino else if (num_ctor_elements - num_nonzero_elements
3884e4b17023SJohn Marino > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
3885e4b17023SJohn Marino && num_nonzero_elements < num_ctor_elements / 4)
3886e4b17023SJohn Marino /* If there are "lots" of zeros, it's more efficient to clear
3887e4b17023SJohn Marino the memory and then set the nonzero elements. */
3888e4b17023SJohn Marino cleared = true;
3889e4b17023SJohn Marino else
3890e4b17023SJohn Marino cleared = false;
3891e4b17023SJohn Marino
3892e4b17023SJohn Marino /* If there are "lots" of initialized elements, and all of them
3893e4b17023SJohn Marino are valid address constants, then the entire initializer can
3894e4b17023SJohn Marino be dropped to memory, and then memcpy'd out. Don't do this
3895e4b17023SJohn Marino for sparse arrays, though, as it's more efficient to follow
3896e4b17023SJohn Marino the standard CONSTRUCTOR behavior of memset followed by
3897e4b17023SJohn Marino individual element initialization. Also don't do this for small
3898e4b17023SJohn Marino all-zero initializers (which aren't big enough to merit
3899e4b17023SJohn Marino clearing), and don't try to make bitwise copies of
3900e4b17023SJohn Marino TREE_ADDRESSABLE types. */
3901e4b17023SJohn Marino if (valid_const_initializer
3902e4b17023SJohn Marino && !(cleared || num_nonzero_elements == 0)
3903e4b17023SJohn Marino && !TREE_ADDRESSABLE (type))
3904e4b17023SJohn Marino {
3905e4b17023SJohn Marino HOST_WIDE_INT size = int_size_in_bytes (type);
3906e4b17023SJohn Marino unsigned int align;
3907e4b17023SJohn Marino
3908e4b17023SJohn Marino /* ??? We can still get unbounded array types, at least
3909e4b17023SJohn Marino from the C++ front end. This seems wrong, but attempt
3910e4b17023SJohn Marino to work around it for now. */
3911e4b17023SJohn Marino if (size < 0)
3912e4b17023SJohn Marino {
3913e4b17023SJohn Marino size = int_size_in_bytes (TREE_TYPE (object));
3914e4b17023SJohn Marino if (size >= 0)
3915e4b17023SJohn Marino TREE_TYPE (ctor) = type = TREE_TYPE (object);
3916e4b17023SJohn Marino }
3917e4b17023SJohn Marino
3918e4b17023SJohn Marino /* Find the maximum alignment we can assume for the object. */
3919e4b17023SJohn Marino /* ??? Make use of DECL_OFFSET_ALIGN. */
3920e4b17023SJohn Marino if (DECL_P (object))
3921e4b17023SJohn Marino align = DECL_ALIGN (object);
3922e4b17023SJohn Marino else
3923e4b17023SJohn Marino align = TYPE_ALIGN (type);
3924e4b17023SJohn Marino
3925e4b17023SJohn Marino if (size > 0
3926e4b17023SJohn Marino && num_nonzero_elements > 1
3927e4b17023SJohn Marino && !can_move_by_pieces (size, align))
3928e4b17023SJohn Marino {
3929e4b17023SJohn Marino if (notify_temp_creation)
3930e4b17023SJohn Marino return GS_ERROR;
3931e4b17023SJohn Marino
3932e4b17023SJohn Marino walk_tree (&ctor, force_labels_r, NULL, NULL);
3933e4b17023SJohn Marino ctor = tree_output_constant_def (ctor);
3934e4b17023SJohn Marino if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
3935e4b17023SJohn Marino ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
3936e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = ctor;
3937e4b17023SJohn Marino
3938e4b17023SJohn Marino /* This is no longer an assignment of a CONSTRUCTOR, but
3939e4b17023SJohn Marino we still may have processing to do on the LHS. So
3940e4b17023SJohn Marino pretend we didn't do anything here to let that happen. */
3941e4b17023SJohn Marino return GS_UNHANDLED;
3942e4b17023SJohn Marino }
3943e4b17023SJohn Marino }
3944e4b17023SJohn Marino
3945e4b17023SJohn Marino /* If the target is volatile, we have non-zero elements and more than
3946e4b17023SJohn Marino one field to assign, initialize the target from a temporary. */
3947e4b17023SJohn Marino if (TREE_THIS_VOLATILE (object)
3948e4b17023SJohn Marino && !TREE_ADDRESSABLE (type)
3949e4b17023SJohn Marino && num_nonzero_elements > 0
3950e4b17023SJohn Marino && VEC_length (constructor_elt, elts) > 1)
3951e4b17023SJohn Marino {
3952e4b17023SJohn Marino tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
3953e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0) = temp;
3954e4b17023SJohn Marino *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
3955e4b17023SJohn Marino *expr_p,
3956e4b17023SJohn Marino build2 (MODIFY_EXPR, void_type_node,
3957e4b17023SJohn Marino object, temp));
3958e4b17023SJohn Marino return GS_OK;
3959e4b17023SJohn Marino }
3960e4b17023SJohn Marino
3961e4b17023SJohn Marino if (notify_temp_creation)
3962e4b17023SJohn Marino return GS_OK;
3963e4b17023SJohn Marino
3964e4b17023SJohn Marino /* If there are nonzero elements and if needed, pre-evaluate to capture
3965e4b17023SJohn Marino elements overlapping with the lhs into temporaries. We must do this
3966e4b17023SJohn Marino before clearing to fetch the values before they are zeroed-out. */
3967e4b17023SJohn Marino if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
3968e4b17023SJohn Marino {
3969e4b17023SJohn Marino preeval_data.lhs_base_decl = get_base_address (object);
3970e4b17023SJohn Marino if (!DECL_P (preeval_data.lhs_base_decl))
3971e4b17023SJohn Marino preeval_data.lhs_base_decl = NULL;
3972e4b17023SJohn Marino preeval_data.lhs_alias_set = get_alias_set (object);
3973e4b17023SJohn Marino
3974e4b17023SJohn Marino gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
3975e4b17023SJohn Marino pre_p, post_p, &preeval_data);
3976e4b17023SJohn Marino }
3977e4b17023SJohn Marino
3978e4b17023SJohn Marino if (cleared)
3979e4b17023SJohn Marino {
3980e4b17023SJohn Marino /* Zap the CONSTRUCTOR element list, which simplifies this case.
3981e4b17023SJohn Marino Note that we still have to gimplify, in order to handle the
3982e4b17023SJohn Marino case of variable sized types. Avoid shared tree structures. */
3983e4b17023SJohn Marino CONSTRUCTOR_ELTS (ctor) = NULL;
3984e4b17023SJohn Marino TREE_SIDE_EFFECTS (ctor) = 0;
3985e4b17023SJohn Marino object = unshare_expr (object);
3986e4b17023SJohn Marino gimplify_stmt (expr_p, pre_p);
3987e4b17023SJohn Marino }
3988e4b17023SJohn Marino
3989e4b17023SJohn Marino /* If we have not block cleared the object, or if there are nonzero
3990e4b17023SJohn Marino elements in the constructor, add assignments to the individual
3991e4b17023SJohn Marino scalar fields of the object. */
3992e4b17023SJohn Marino if (!cleared || num_nonzero_elements > 0)
3993e4b17023SJohn Marino gimplify_init_ctor_eval (object, elts, pre_p, cleared);
3994e4b17023SJohn Marino
3995e4b17023SJohn Marino *expr_p = NULL_TREE;
3996e4b17023SJohn Marino }
3997e4b17023SJohn Marino break;
3998e4b17023SJohn Marino
3999e4b17023SJohn Marino case COMPLEX_TYPE:
4000e4b17023SJohn Marino {
4001e4b17023SJohn Marino tree r, i;
4002e4b17023SJohn Marino
4003e4b17023SJohn Marino if (notify_temp_creation)
4004e4b17023SJohn Marino return GS_OK;
4005e4b17023SJohn Marino
4006e4b17023SJohn Marino /* Extract the real and imaginary parts out of the ctor. */
4007e4b17023SJohn Marino gcc_assert (VEC_length (constructor_elt, elts) == 2);
4008e4b17023SJohn Marino r = VEC_index (constructor_elt, elts, 0)->value;
4009e4b17023SJohn Marino i = VEC_index (constructor_elt, elts, 1)->value;
4010e4b17023SJohn Marino if (r == NULL || i == NULL)
4011e4b17023SJohn Marino {
4012e4b17023SJohn Marino tree zero = build_zero_cst (TREE_TYPE (type));
4013e4b17023SJohn Marino if (r == NULL)
4014e4b17023SJohn Marino r = zero;
4015e4b17023SJohn Marino if (i == NULL)
4016e4b17023SJohn Marino i = zero;
4017e4b17023SJohn Marino }
4018e4b17023SJohn Marino
4019e4b17023SJohn Marino /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
4020e4b17023SJohn Marino represent creation of a complex value. */
4021e4b17023SJohn Marino if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
4022e4b17023SJohn Marino {
4023e4b17023SJohn Marino ctor = build_complex (type, r, i);
4024e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = ctor;
4025e4b17023SJohn Marino }
4026e4b17023SJohn Marino else
4027e4b17023SJohn Marino {
4028e4b17023SJohn Marino ctor = build2 (COMPLEX_EXPR, type, r, i);
4029e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = ctor;
4030e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
4031e4b17023SJohn Marino pre_p,
4032e4b17023SJohn Marino post_p,
4033e4b17023SJohn Marino rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
4034e4b17023SJohn Marino fb_rvalue);
4035e4b17023SJohn Marino }
4036e4b17023SJohn Marino }
4037e4b17023SJohn Marino break;
4038e4b17023SJohn Marino
4039e4b17023SJohn Marino case VECTOR_TYPE:
4040e4b17023SJohn Marino {
4041e4b17023SJohn Marino unsigned HOST_WIDE_INT ix;
4042e4b17023SJohn Marino constructor_elt *ce;
4043e4b17023SJohn Marino
4044e4b17023SJohn Marino if (notify_temp_creation)
4045e4b17023SJohn Marino return GS_OK;
4046e4b17023SJohn Marino
4047e4b17023SJohn Marino /* Go ahead and simplify constant constructors to VECTOR_CST. */
4048e4b17023SJohn Marino if (TREE_CONSTANT (ctor))
4049e4b17023SJohn Marino {
4050e4b17023SJohn Marino bool constant_p = true;
4051e4b17023SJohn Marino tree value;
4052e4b17023SJohn Marino
4053e4b17023SJohn Marino /* Even when ctor is constant, it might contain non-*_CST
4054e4b17023SJohn Marino elements, such as addresses or trapping values like
4055e4b17023SJohn Marino 1.0/0.0 - 1.0/0.0. Such expressions don't belong
4056e4b17023SJohn Marino in VECTOR_CST nodes. */
4057e4b17023SJohn Marino FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
4058e4b17023SJohn Marino if (!CONSTANT_CLASS_P (value))
4059e4b17023SJohn Marino {
4060e4b17023SJohn Marino constant_p = false;
4061e4b17023SJohn Marino break;
4062e4b17023SJohn Marino }
4063e4b17023SJohn Marino
4064e4b17023SJohn Marino if (constant_p)
4065e4b17023SJohn Marino {
4066e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
4067e4b17023SJohn Marino break;
4068e4b17023SJohn Marino }
4069e4b17023SJohn Marino
4070e4b17023SJohn Marino /* Don't reduce an initializer constant even if we can't
4071e4b17023SJohn Marino make a VECTOR_CST. It won't do anything for us, and it'll
4072e4b17023SJohn Marino prevent us from representing it as a single constant. */
4073e4b17023SJohn Marino if (initializer_constant_valid_p (ctor, type))
4074e4b17023SJohn Marino break;
4075e4b17023SJohn Marino
4076e4b17023SJohn Marino TREE_CONSTANT (ctor) = 0;
4077e4b17023SJohn Marino }
4078e4b17023SJohn Marino
4079e4b17023SJohn Marino /* Vector types use CONSTRUCTOR all the way through gimple
4080e4b17023SJohn Marino compilation as a general initializer. */
4081e4b17023SJohn Marino FOR_EACH_VEC_ELT (constructor_elt, elts, ix, ce)
4082e4b17023SJohn Marino {
4083e4b17023SJohn Marino enum gimplify_status tret;
4084e4b17023SJohn Marino tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
4085e4b17023SJohn Marino fb_rvalue);
4086e4b17023SJohn Marino if (tret == GS_ERROR)
4087e4b17023SJohn Marino ret = GS_ERROR;
4088e4b17023SJohn Marino }
4089e4b17023SJohn Marino if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
4090e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
4091e4b17023SJohn Marino }
4092e4b17023SJohn Marino break;
4093e4b17023SJohn Marino
4094e4b17023SJohn Marino default:
4095e4b17023SJohn Marino /* So how did we get a CONSTRUCTOR for a scalar type? */
4096e4b17023SJohn Marino gcc_unreachable ();
4097e4b17023SJohn Marino }
4098e4b17023SJohn Marino
4099e4b17023SJohn Marino if (ret == GS_ERROR)
4100e4b17023SJohn Marino return GS_ERROR;
4101e4b17023SJohn Marino else if (want_value)
4102e4b17023SJohn Marino {
4103e4b17023SJohn Marino *expr_p = object;
4104e4b17023SJohn Marino return GS_OK;
4105e4b17023SJohn Marino }
4106e4b17023SJohn Marino else
4107e4b17023SJohn Marino {
4108e4b17023SJohn Marino /* If we have gimplified both sides of the initializer but have
4109e4b17023SJohn Marino not emitted an assignment, do so now. */
4110e4b17023SJohn Marino if (*expr_p)
4111e4b17023SJohn Marino {
4112e4b17023SJohn Marino tree lhs = TREE_OPERAND (*expr_p, 0);
4113e4b17023SJohn Marino tree rhs = TREE_OPERAND (*expr_p, 1);
4114e4b17023SJohn Marino gimple init = gimple_build_assign (lhs, rhs);
4115e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, init);
4116e4b17023SJohn Marino *expr_p = NULL;
4117e4b17023SJohn Marino }
4118e4b17023SJohn Marino
4119e4b17023SJohn Marino return GS_ALL_DONE;
4120e4b17023SJohn Marino }
4121e4b17023SJohn Marino }
4122e4b17023SJohn Marino
4123e4b17023SJohn Marino /* Given a pointer value OP0, return a simplified version of an
4124e4b17023SJohn Marino indirection through OP0, or NULL_TREE if no simplification is
4125e4b17023SJohn Marino possible. Note that the resulting type may be different from
4126e4b17023SJohn Marino the type pointed to in the sense that it is still compatible
4127e4b17023SJohn Marino from the langhooks point of view. */
4128e4b17023SJohn Marino
4129e4b17023SJohn Marino tree
gimple_fold_indirect_ref(tree t)4130e4b17023SJohn Marino gimple_fold_indirect_ref (tree t)
4131e4b17023SJohn Marino {
4132e4b17023SJohn Marino tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
4133e4b17023SJohn Marino tree sub = t;
4134e4b17023SJohn Marino tree subtype;
4135e4b17023SJohn Marino
4136e4b17023SJohn Marino STRIP_NOPS (sub);
4137e4b17023SJohn Marino subtype = TREE_TYPE (sub);
4138e4b17023SJohn Marino if (!POINTER_TYPE_P (subtype))
4139e4b17023SJohn Marino return NULL_TREE;
4140e4b17023SJohn Marino
4141e4b17023SJohn Marino if (TREE_CODE (sub) == ADDR_EXPR)
4142e4b17023SJohn Marino {
4143e4b17023SJohn Marino tree op = TREE_OPERAND (sub, 0);
4144e4b17023SJohn Marino tree optype = TREE_TYPE (op);
4145e4b17023SJohn Marino /* *&p => p */
4146e4b17023SJohn Marino if (useless_type_conversion_p (type, optype))
4147e4b17023SJohn Marino return op;
4148e4b17023SJohn Marino
4149e4b17023SJohn Marino /* *(foo *)&fooarray => fooarray[0] */
4150e4b17023SJohn Marino if (TREE_CODE (optype) == ARRAY_TYPE
4151e4b17023SJohn Marino && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
4152e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (optype)))
4153e4b17023SJohn Marino {
4154e4b17023SJohn Marino tree type_domain = TYPE_DOMAIN (optype);
4155e4b17023SJohn Marino tree min_val = size_zero_node;
4156e4b17023SJohn Marino if (type_domain && TYPE_MIN_VALUE (type_domain))
4157e4b17023SJohn Marino min_val = TYPE_MIN_VALUE (type_domain);
4158e4b17023SJohn Marino if (TREE_CODE (min_val) == INTEGER_CST)
4159e4b17023SJohn Marino return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
4160e4b17023SJohn Marino }
4161e4b17023SJohn Marino /* *(foo *)&complexfoo => __real__ complexfoo */
4162e4b17023SJohn Marino else if (TREE_CODE (optype) == COMPLEX_TYPE
4163e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (optype)))
4164e4b17023SJohn Marino return fold_build1 (REALPART_EXPR, type, op);
4165e4b17023SJohn Marino /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
4166e4b17023SJohn Marino else if (TREE_CODE (optype) == VECTOR_TYPE
4167e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (optype)))
4168e4b17023SJohn Marino {
4169e4b17023SJohn Marino tree part_width = TYPE_SIZE (type);
4170e4b17023SJohn Marino tree index = bitsize_int (0);
4171e4b17023SJohn Marino return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
4172e4b17023SJohn Marino }
4173e4b17023SJohn Marino }
4174e4b17023SJohn Marino
4175e4b17023SJohn Marino /* *(p + CST) -> ... */
4176e4b17023SJohn Marino if (TREE_CODE (sub) == POINTER_PLUS_EXPR
4177e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
4178e4b17023SJohn Marino {
4179e4b17023SJohn Marino tree addr = TREE_OPERAND (sub, 0);
4180e4b17023SJohn Marino tree off = TREE_OPERAND (sub, 1);
4181e4b17023SJohn Marino tree addrtype;
4182e4b17023SJohn Marino
4183e4b17023SJohn Marino STRIP_NOPS (addr);
4184e4b17023SJohn Marino addrtype = TREE_TYPE (addr);
4185e4b17023SJohn Marino
4186e4b17023SJohn Marino /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
4187e4b17023SJohn Marino if (TREE_CODE (addr) == ADDR_EXPR
4188e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
4189e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
4190e4b17023SJohn Marino && host_integerp (off, 1))
4191e4b17023SJohn Marino {
4192e4b17023SJohn Marino unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
4193e4b17023SJohn Marino tree part_width = TYPE_SIZE (type);
4194e4b17023SJohn Marino unsigned HOST_WIDE_INT part_widthi
4195e4b17023SJohn Marino = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
4196e4b17023SJohn Marino unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
4197e4b17023SJohn Marino tree index = bitsize_int (indexi);
4198e4b17023SJohn Marino if (offset / part_widthi
4199e4b17023SJohn Marino <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
4200e4b17023SJohn Marino return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
4201e4b17023SJohn Marino part_width, index);
4202e4b17023SJohn Marino }
4203e4b17023SJohn Marino
4204e4b17023SJohn Marino /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
4205e4b17023SJohn Marino if (TREE_CODE (addr) == ADDR_EXPR
4206e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
4207e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
4208e4b17023SJohn Marino {
4209e4b17023SJohn Marino tree size = TYPE_SIZE_UNIT (type);
4210e4b17023SJohn Marino if (tree_int_cst_equal (size, off))
4211e4b17023SJohn Marino return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
4212e4b17023SJohn Marino }
4213e4b17023SJohn Marino
4214e4b17023SJohn Marino /* *(p + CST) -> MEM_REF <p, CST>. */
4215e4b17023SJohn Marino if (TREE_CODE (addr) != ADDR_EXPR
4216e4b17023SJohn Marino || DECL_P (TREE_OPERAND (addr, 0)))
4217e4b17023SJohn Marino return fold_build2 (MEM_REF, type,
4218e4b17023SJohn Marino addr,
4219e4b17023SJohn Marino build_int_cst_wide (ptype,
4220e4b17023SJohn Marino TREE_INT_CST_LOW (off),
4221e4b17023SJohn Marino TREE_INT_CST_HIGH (off)));
4222e4b17023SJohn Marino }
4223e4b17023SJohn Marino
4224e4b17023SJohn Marino /* *(foo *)fooarrptr => (*fooarrptr)[0] */
4225e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
4226e4b17023SJohn Marino && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
4227e4b17023SJohn Marino && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
4228e4b17023SJohn Marino {
4229e4b17023SJohn Marino tree type_domain;
4230e4b17023SJohn Marino tree min_val = size_zero_node;
4231e4b17023SJohn Marino tree osub = sub;
4232e4b17023SJohn Marino sub = gimple_fold_indirect_ref (sub);
4233e4b17023SJohn Marino if (! sub)
4234e4b17023SJohn Marino sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub);
4235e4b17023SJohn Marino type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
4236e4b17023SJohn Marino if (type_domain && TYPE_MIN_VALUE (type_domain))
4237e4b17023SJohn Marino min_val = TYPE_MIN_VALUE (type_domain);
4238e4b17023SJohn Marino if (TREE_CODE (min_val) == INTEGER_CST)
4239e4b17023SJohn Marino return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
4240e4b17023SJohn Marino }
4241e4b17023SJohn Marino
4242e4b17023SJohn Marino return NULL_TREE;
4243e4b17023SJohn Marino }
4244e4b17023SJohn Marino
4245e4b17023SJohn Marino /* Given a pointer value OP0, return a simplified version of an
4246e4b17023SJohn Marino indirection through OP0, or NULL_TREE if no simplification is
4247e4b17023SJohn Marino possible. This may only be applied to a rhs of an expression.
4248e4b17023SJohn Marino Note that the resulting type may be different from the type pointed
4249e4b17023SJohn Marino to in the sense that it is still compatible from the langhooks
4250e4b17023SJohn Marino point of view. */
4251e4b17023SJohn Marino
4252e4b17023SJohn Marino static tree
gimple_fold_indirect_ref_rhs(tree t)4253e4b17023SJohn Marino gimple_fold_indirect_ref_rhs (tree t)
4254e4b17023SJohn Marino {
4255e4b17023SJohn Marino return gimple_fold_indirect_ref (t);
4256e4b17023SJohn Marino }
4257e4b17023SJohn Marino
4258e4b17023SJohn Marino /* Subroutine of gimplify_modify_expr to do simplifications of
4259e4b17023SJohn Marino MODIFY_EXPRs based on the code of the RHS. We loop for as long as
4260e4b17023SJohn Marino something changes. */
4261e4b17023SJohn Marino
4262e4b17023SJohn Marino static enum gimplify_status
gimplify_modify_expr_rhs(tree * expr_p,tree * from_p,tree * to_p,gimple_seq * pre_p,gimple_seq * post_p,bool want_value)4263e4b17023SJohn Marino gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
4264e4b17023SJohn Marino gimple_seq *pre_p, gimple_seq *post_p,
4265e4b17023SJohn Marino bool want_value)
4266e4b17023SJohn Marino {
4267e4b17023SJohn Marino enum gimplify_status ret = GS_UNHANDLED;
4268e4b17023SJohn Marino bool changed;
4269e4b17023SJohn Marino
4270e4b17023SJohn Marino do
4271e4b17023SJohn Marino {
4272e4b17023SJohn Marino changed = false;
4273e4b17023SJohn Marino switch (TREE_CODE (*from_p))
4274e4b17023SJohn Marino {
4275e4b17023SJohn Marino case VAR_DECL:
4276e4b17023SJohn Marino /* If we're assigning from a read-only variable initialized with
4277e4b17023SJohn Marino a constructor, do the direct assignment from the constructor,
4278e4b17023SJohn Marino but only if neither source nor target are volatile since this
4279e4b17023SJohn Marino latter assignment might end up being done on a per-field basis. */
4280e4b17023SJohn Marino if (DECL_INITIAL (*from_p)
4281e4b17023SJohn Marino && TREE_READONLY (*from_p)
4282e4b17023SJohn Marino && !TREE_THIS_VOLATILE (*from_p)
4283e4b17023SJohn Marino && !TREE_THIS_VOLATILE (*to_p)
4284e4b17023SJohn Marino && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
4285e4b17023SJohn Marino {
4286e4b17023SJohn Marino tree old_from = *from_p;
4287e4b17023SJohn Marino enum gimplify_status subret;
4288e4b17023SJohn Marino
4289e4b17023SJohn Marino /* Move the constructor into the RHS. */
4290e4b17023SJohn Marino *from_p = unshare_expr (DECL_INITIAL (*from_p));
4291e4b17023SJohn Marino
4292e4b17023SJohn Marino /* Let's see if gimplify_init_constructor will need to put
4293e4b17023SJohn Marino it in memory. */
4294e4b17023SJohn Marino subret = gimplify_init_constructor (expr_p, NULL, NULL,
4295e4b17023SJohn Marino false, true);
4296e4b17023SJohn Marino if (subret == GS_ERROR)
4297e4b17023SJohn Marino {
4298e4b17023SJohn Marino /* If so, revert the change. */
4299e4b17023SJohn Marino *from_p = old_from;
4300e4b17023SJohn Marino }
4301e4b17023SJohn Marino else
4302e4b17023SJohn Marino {
4303e4b17023SJohn Marino ret = GS_OK;
4304e4b17023SJohn Marino changed = true;
4305e4b17023SJohn Marino }
4306e4b17023SJohn Marino }
4307e4b17023SJohn Marino break;
4308e4b17023SJohn Marino case INDIRECT_REF:
4309e4b17023SJohn Marino {
4310e4b17023SJohn Marino /* If we have code like
4311e4b17023SJohn Marino
4312e4b17023SJohn Marino *(const A*)(A*)&x
4313e4b17023SJohn Marino
4314e4b17023SJohn Marino where the type of "x" is a (possibly cv-qualified variant
4315e4b17023SJohn Marino of "A"), treat the entire expression as identical to "x".
4316e4b17023SJohn Marino This kind of code arises in C++ when an object is bound
4317e4b17023SJohn Marino to a const reference, and if "x" is a TARGET_EXPR we want
4318e4b17023SJohn Marino to take advantage of the optimization below. */
4319e4b17023SJohn Marino bool volatile_p = TREE_THIS_VOLATILE (*from_p);
4320e4b17023SJohn Marino tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
4321e4b17023SJohn Marino if (t)
4322e4b17023SJohn Marino {
4323e4b17023SJohn Marino if (TREE_THIS_VOLATILE (t) != volatile_p)
4324e4b17023SJohn Marino {
4325e4b17023SJohn Marino if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
4326e4b17023SJohn Marino t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
4327e4b17023SJohn Marino build_fold_addr_expr (t));
4328e4b17023SJohn Marino if (REFERENCE_CLASS_P (t))
4329e4b17023SJohn Marino TREE_THIS_VOLATILE (t) = volatile_p;
4330e4b17023SJohn Marino }
4331e4b17023SJohn Marino *from_p = t;
4332e4b17023SJohn Marino ret = GS_OK;
4333e4b17023SJohn Marino changed = true;
4334e4b17023SJohn Marino }
4335e4b17023SJohn Marino break;
4336e4b17023SJohn Marino }
4337e4b17023SJohn Marino
4338e4b17023SJohn Marino case TARGET_EXPR:
4339e4b17023SJohn Marino {
4340e4b17023SJohn Marino /* If we are initializing something from a TARGET_EXPR, strip the
4341e4b17023SJohn Marino TARGET_EXPR and initialize it directly, if possible. This can't
4342e4b17023SJohn Marino be done if the initializer is void, since that implies that the
4343e4b17023SJohn Marino temporary is set in some non-trivial way.
4344e4b17023SJohn Marino
4345e4b17023SJohn Marino ??? What about code that pulls out the temp and uses it
4346e4b17023SJohn Marino elsewhere? I think that such code never uses the TARGET_EXPR as
4347e4b17023SJohn Marino an initializer. If I'm wrong, we'll die because the temp won't
4348e4b17023SJohn Marino have any RTL. In that case, I guess we'll need to replace
4349e4b17023SJohn Marino references somehow. */
4350e4b17023SJohn Marino tree init = TARGET_EXPR_INITIAL (*from_p);
4351e4b17023SJohn Marino
4352e4b17023SJohn Marino if (init
4353e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (init)))
4354e4b17023SJohn Marino {
4355e4b17023SJohn Marino *from_p = init;
4356e4b17023SJohn Marino ret = GS_OK;
4357e4b17023SJohn Marino changed = true;
4358e4b17023SJohn Marino }
4359e4b17023SJohn Marino }
4360e4b17023SJohn Marino break;
4361e4b17023SJohn Marino
4362e4b17023SJohn Marino case COMPOUND_EXPR:
4363e4b17023SJohn Marino /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
4364e4b17023SJohn Marino caught. */
4365e4b17023SJohn Marino gimplify_compound_expr (from_p, pre_p, true);
4366e4b17023SJohn Marino ret = GS_OK;
4367e4b17023SJohn Marino changed = true;
4368e4b17023SJohn Marino break;
4369e4b17023SJohn Marino
4370e4b17023SJohn Marino case CONSTRUCTOR:
4371e4b17023SJohn Marino /* If we already made some changes, let the front end have a
4372e4b17023SJohn Marino crack at this before we break it down. */
4373e4b17023SJohn Marino if (ret != GS_UNHANDLED)
4374e4b17023SJohn Marino break;
4375e4b17023SJohn Marino /* If we're initializing from a CONSTRUCTOR, break this into
4376e4b17023SJohn Marino individual MODIFY_EXPRs. */
4377e4b17023SJohn Marino return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
4378e4b17023SJohn Marino false);
4379e4b17023SJohn Marino
4380e4b17023SJohn Marino case COND_EXPR:
4381e4b17023SJohn Marino /* If we're assigning to a non-register type, push the assignment
4382e4b17023SJohn Marino down into the branches. This is mandatory for ADDRESSABLE types,
4383e4b17023SJohn Marino since we cannot generate temporaries for such, but it saves a
4384e4b17023SJohn Marino copy in other cases as well. */
4385e4b17023SJohn Marino if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
4386e4b17023SJohn Marino {
4387e4b17023SJohn Marino /* This code should mirror the code in gimplify_cond_expr. */
4388e4b17023SJohn Marino enum tree_code code = TREE_CODE (*expr_p);
4389e4b17023SJohn Marino tree cond = *from_p;
4390e4b17023SJohn Marino tree result = *to_p;
4391e4b17023SJohn Marino
4392e4b17023SJohn Marino ret = gimplify_expr (&result, pre_p, post_p,
4393e4b17023SJohn Marino is_gimple_lvalue, fb_lvalue);
4394e4b17023SJohn Marino if (ret != GS_ERROR)
4395e4b17023SJohn Marino ret = GS_OK;
4396e4b17023SJohn Marino
4397e4b17023SJohn Marino if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
4398e4b17023SJohn Marino TREE_OPERAND (cond, 1)
4399e4b17023SJohn Marino = build2 (code, void_type_node, result,
4400e4b17023SJohn Marino TREE_OPERAND (cond, 1));
4401e4b17023SJohn Marino if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
4402e4b17023SJohn Marino TREE_OPERAND (cond, 2)
4403e4b17023SJohn Marino = build2 (code, void_type_node, unshare_expr (result),
4404e4b17023SJohn Marino TREE_OPERAND (cond, 2));
4405e4b17023SJohn Marino
4406e4b17023SJohn Marino TREE_TYPE (cond) = void_type_node;
4407e4b17023SJohn Marino recalculate_side_effects (cond);
4408e4b17023SJohn Marino
4409e4b17023SJohn Marino if (want_value)
4410e4b17023SJohn Marino {
4411e4b17023SJohn Marino gimplify_and_add (cond, pre_p);
4412e4b17023SJohn Marino *expr_p = unshare_expr (result);
4413e4b17023SJohn Marino }
4414e4b17023SJohn Marino else
4415e4b17023SJohn Marino *expr_p = cond;
4416e4b17023SJohn Marino return ret;
4417e4b17023SJohn Marino }
4418e4b17023SJohn Marino break;
4419e4b17023SJohn Marino
4420e4b17023SJohn Marino case CALL_EXPR:
4421e4b17023SJohn Marino /* For calls that return in memory, give *to_p as the CALL_EXPR's
4422e4b17023SJohn Marino return slot so that we don't generate a temporary. */
4423e4b17023SJohn Marino if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
4424e4b17023SJohn Marino && aggregate_value_p (*from_p, *from_p))
4425e4b17023SJohn Marino {
4426e4b17023SJohn Marino bool use_target;
4427e4b17023SJohn Marino
4428e4b17023SJohn Marino if (!(rhs_predicate_for (*to_p))(*from_p))
4429e4b17023SJohn Marino /* If we need a temporary, *to_p isn't accurate. */
4430e4b17023SJohn Marino use_target = false;
4431e4b17023SJohn Marino /* It's OK to use the return slot directly unless it's an NRV. */
4432e4b17023SJohn Marino else if (TREE_CODE (*to_p) == RESULT_DECL
4433e4b17023SJohn Marino && DECL_NAME (*to_p) == NULL_TREE
4434e4b17023SJohn Marino && needs_to_live_in_memory (*to_p))
4435e4b17023SJohn Marino use_target = true;
4436e4b17023SJohn Marino else if (is_gimple_reg_type (TREE_TYPE (*to_p))
4437e4b17023SJohn Marino || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
4438e4b17023SJohn Marino /* Don't force regs into memory. */
4439e4b17023SJohn Marino use_target = false;
4440e4b17023SJohn Marino else if (TREE_CODE (*expr_p) == INIT_EXPR)
4441e4b17023SJohn Marino /* It's OK to use the target directly if it's being
4442e4b17023SJohn Marino initialized. */
4443e4b17023SJohn Marino use_target = true;
4444e4b17023SJohn Marino else if (variably_modified_type_p (TREE_TYPE (*to_p), NULL_TREE))
4445e4b17023SJohn Marino /* Always use the target and thus RSO for variable-sized types.
4446e4b17023SJohn Marino GIMPLE cannot deal with a variable-sized assignment
4447e4b17023SJohn Marino embedded in a call statement. */
4448e4b17023SJohn Marino use_target = true;
4449e4b17023SJohn Marino else if (TREE_CODE (*to_p) != SSA_NAME
4450e4b17023SJohn Marino && (!is_gimple_variable (*to_p)
4451e4b17023SJohn Marino || needs_to_live_in_memory (*to_p)))
4452e4b17023SJohn Marino /* Don't use the original target if it's already addressable;
4453e4b17023SJohn Marino if its address escapes, and the called function uses the
4454e4b17023SJohn Marino NRV optimization, a conforming program could see *to_p
4455e4b17023SJohn Marino change before the called function returns; see c++/19317.
4456e4b17023SJohn Marino When optimizing, the return_slot pass marks more functions
4457e4b17023SJohn Marino as safe after we have escape info. */
4458e4b17023SJohn Marino use_target = false;
4459e4b17023SJohn Marino else
4460e4b17023SJohn Marino use_target = true;
4461e4b17023SJohn Marino
4462e4b17023SJohn Marino if (use_target)
4463e4b17023SJohn Marino {
4464e4b17023SJohn Marino CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
4465e4b17023SJohn Marino mark_addressable (*to_p);
4466e4b17023SJohn Marino }
4467e4b17023SJohn Marino }
4468e4b17023SJohn Marino break;
4469e4b17023SJohn Marino
4470e4b17023SJohn Marino case WITH_SIZE_EXPR:
4471e4b17023SJohn Marino /* Likewise for calls that return an aggregate of non-constant size,
4472e4b17023SJohn Marino since we would not be able to generate a temporary at all. */
4473e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
4474e4b17023SJohn Marino {
4475e4b17023SJohn Marino *from_p = TREE_OPERAND (*from_p, 0);
4476e4b17023SJohn Marino /* We don't change ret in this case because the
4477e4b17023SJohn Marino WITH_SIZE_EXPR might have been added in
4478e4b17023SJohn Marino gimplify_modify_expr, so returning GS_OK would lead to an
4479e4b17023SJohn Marino infinite loop. */
4480e4b17023SJohn Marino changed = true;
4481e4b17023SJohn Marino }
4482e4b17023SJohn Marino break;
4483e4b17023SJohn Marino
4484e4b17023SJohn Marino /* If we're initializing from a container, push the initialization
4485e4b17023SJohn Marino inside it. */
4486e4b17023SJohn Marino case CLEANUP_POINT_EXPR:
4487e4b17023SJohn Marino case BIND_EXPR:
4488e4b17023SJohn Marino case STATEMENT_LIST:
4489e4b17023SJohn Marino {
4490e4b17023SJohn Marino tree wrap = *from_p;
4491e4b17023SJohn Marino tree t;
4492e4b17023SJohn Marino
4493e4b17023SJohn Marino ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
4494e4b17023SJohn Marino fb_lvalue);
4495e4b17023SJohn Marino if (ret != GS_ERROR)
4496e4b17023SJohn Marino ret = GS_OK;
4497e4b17023SJohn Marino
4498e4b17023SJohn Marino t = voidify_wrapper_expr (wrap, *expr_p);
4499e4b17023SJohn Marino gcc_assert (t == *expr_p);
4500e4b17023SJohn Marino
4501e4b17023SJohn Marino if (want_value)
4502e4b17023SJohn Marino {
4503e4b17023SJohn Marino gimplify_and_add (wrap, pre_p);
4504e4b17023SJohn Marino *expr_p = unshare_expr (*to_p);
4505e4b17023SJohn Marino }
4506e4b17023SJohn Marino else
4507e4b17023SJohn Marino *expr_p = wrap;
4508e4b17023SJohn Marino return GS_OK;
4509e4b17023SJohn Marino }
4510e4b17023SJohn Marino
4511e4b17023SJohn Marino case COMPOUND_LITERAL_EXPR:
4512e4b17023SJohn Marino {
4513e4b17023SJohn Marino tree complit = TREE_OPERAND (*expr_p, 1);
4514e4b17023SJohn Marino tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
4515e4b17023SJohn Marino tree decl = DECL_EXPR_DECL (decl_s);
4516e4b17023SJohn Marino tree init = DECL_INITIAL (decl);
4517e4b17023SJohn Marino
4518e4b17023SJohn Marino /* struct T x = (struct T) { 0, 1, 2 } can be optimized
4519e4b17023SJohn Marino into struct T x = { 0, 1, 2 } if the address of the
4520e4b17023SJohn Marino compound literal has never been taken. */
4521e4b17023SJohn Marino if (!TREE_ADDRESSABLE (complit)
4522e4b17023SJohn Marino && !TREE_ADDRESSABLE (decl)
4523e4b17023SJohn Marino && init)
4524e4b17023SJohn Marino {
4525e4b17023SJohn Marino *expr_p = copy_node (*expr_p);
4526e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = init;
4527e4b17023SJohn Marino return GS_OK;
4528e4b17023SJohn Marino }
4529e4b17023SJohn Marino }
4530e4b17023SJohn Marino
4531e4b17023SJohn Marino default:
4532e4b17023SJohn Marino break;
4533e4b17023SJohn Marino }
4534e4b17023SJohn Marino }
4535e4b17023SJohn Marino while (changed);
4536e4b17023SJohn Marino
4537e4b17023SJohn Marino return ret;
4538e4b17023SJohn Marino }
4539e4b17023SJohn Marino
4540e4b17023SJohn Marino /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
4541e4b17023SJohn Marino a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
4542e4b17023SJohn Marino DECL_GIMPLE_REG_P set.
4543e4b17023SJohn Marino
4544e4b17023SJohn Marino IMPORTANT NOTE: This promotion is performed by introducing a load of the
4545e4b17023SJohn Marino other, unmodified part of the complex object just before the total store.
4546e4b17023SJohn Marino As a consequence, if the object is still uninitialized, an undefined value
4547e4b17023SJohn Marino will be loaded into a register, which may result in a spurious exception
4548e4b17023SJohn Marino if the register is floating-point and the value happens to be a signaling
4549e4b17023SJohn Marino NaN for example. Then the fully-fledged complex operations lowering pass
4550e4b17023SJohn Marino followed by a DCE pass are necessary in order to fix things up. */
4551e4b17023SJohn Marino
4552e4b17023SJohn Marino static enum gimplify_status
gimplify_modify_expr_complex_part(tree * expr_p,gimple_seq * pre_p,bool want_value)4553e4b17023SJohn Marino gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
4554e4b17023SJohn Marino bool want_value)
4555e4b17023SJohn Marino {
4556e4b17023SJohn Marino enum tree_code code, ocode;
4557e4b17023SJohn Marino tree lhs, rhs, new_rhs, other, realpart, imagpart;
4558e4b17023SJohn Marino
4559e4b17023SJohn Marino lhs = TREE_OPERAND (*expr_p, 0);
4560e4b17023SJohn Marino rhs = TREE_OPERAND (*expr_p, 1);
4561e4b17023SJohn Marino code = TREE_CODE (lhs);
4562e4b17023SJohn Marino lhs = TREE_OPERAND (lhs, 0);
4563e4b17023SJohn Marino
4564e4b17023SJohn Marino ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
4565e4b17023SJohn Marino other = build1 (ocode, TREE_TYPE (rhs), lhs);
4566e4b17023SJohn Marino TREE_NO_WARNING (other) = 1;
4567e4b17023SJohn Marino other = get_formal_tmp_var (other, pre_p);
4568e4b17023SJohn Marino
4569e4b17023SJohn Marino realpart = code == REALPART_EXPR ? rhs : other;
4570e4b17023SJohn Marino imagpart = code == REALPART_EXPR ? other : rhs;
4571e4b17023SJohn Marino
4572e4b17023SJohn Marino if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
4573e4b17023SJohn Marino new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
4574e4b17023SJohn Marino else
4575e4b17023SJohn Marino new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
4576e4b17023SJohn Marino
4577e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
4578e4b17023SJohn Marino *expr_p = (want_value) ? rhs : NULL_TREE;
4579e4b17023SJohn Marino
4580e4b17023SJohn Marino return GS_ALL_DONE;
4581e4b17023SJohn Marino }
4582e4b17023SJohn Marino
4583e4b17023SJohn Marino /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
4584e4b17023SJohn Marino
4585e4b17023SJohn Marino modify_expr
4586e4b17023SJohn Marino : varname '=' rhs
4587e4b17023SJohn Marino | '*' ID '=' rhs
4588e4b17023SJohn Marino
4589e4b17023SJohn Marino PRE_P points to the list where side effects that must happen before
4590e4b17023SJohn Marino *EXPR_P should be stored.
4591e4b17023SJohn Marino
4592e4b17023SJohn Marino POST_P points to the list where side effects that must happen after
4593e4b17023SJohn Marino *EXPR_P should be stored.
4594e4b17023SJohn Marino
4595e4b17023SJohn Marino WANT_VALUE is nonzero iff we want to use the value of this expression
4596e4b17023SJohn Marino in another expression. */
4597e4b17023SJohn Marino
4598e4b17023SJohn Marino static enum gimplify_status
gimplify_modify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,bool want_value)4599e4b17023SJohn Marino gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
4600e4b17023SJohn Marino bool want_value)
4601e4b17023SJohn Marino {
4602e4b17023SJohn Marino tree *from_p = &TREE_OPERAND (*expr_p, 1);
4603e4b17023SJohn Marino tree *to_p = &TREE_OPERAND (*expr_p, 0);
4604e4b17023SJohn Marino enum gimplify_status ret = GS_UNHANDLED;
4605e4b17023SJohn Marino gimple assign;
4606e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
4607e4b17023SJohn Marino
4608e4b17023SJohn Marino gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
4609e4b17023SJohn Marino || TREE_CODE (*expr_p) == INIT_EXPR);
4610e4b17023SJohn Marino
4611e4b17023SJohn Marino /* Trying to simplify a clobber using normal logic doesn't work,
4612e4b17023SJohn Marino so handle it here. */
4613e4b17023SJohn Marino if (TREE_CLOBBER_P (*from_p))
4614e4b17023SJohn Marino {
4615e4b17023SJohn Marino gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL);
4616e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
4617e4b17023SJohn Marino *expr_p = NULL;
4618e4b17023SJohn Marino return GS_ALL_DONE;
4619e4b17023SJohn Marino }
4620e4b17023SJohn Marino
4621e4b17023SJohn Marino /* Insert pointer conversions required by the middle-end that are not
4622e4b17023SJohn Marino required by the frontend. This fixes middle-end type checking for
4623e4b17023SJohn Marino for example gcc.dg/redecl-6.c. */
4624e4b17023SJohn Marino if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
4625e4b17023SJohn Marino {
4626e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (*from_p);
4627e4b17023SJohn Marino if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
4628e4b17023SJohn Marino *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
4629e4b17023SJohn Marino }
4630e4b17023SJohn Marino
4631e4b17023SJohn Marino /* See if any simplifications can be done based on what the RHS is. */
4632e4b17023SJohn Marino ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
4633e4b17023SJohn Marino want_value);
4634e4b17023SJohn Marino if (ret != GS_UNHANDLED)
4635e4b17023SJohn Marino return ret;
4636e4b17023SJohn Marino
4637e4b17023SJohn Marino /* For zero sized types only gimplify the left hand side and right hand
4638e4b17023SJohn Marino side as statements and throw away the assignment. Do this after
4639e4b17023SJohn Marino gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
4640e4b17023SJohn Marino types properly. */
4641e4b17023SJohn Marino if (zero_sized_type (TREE_TYPE (*from_p)) && !want_value)
4642e4b17023SJohn Marino {
4643e4b17023SJohn Marino gimplify_stmt (from_p, pre_p);
4644e4b17023SJohn Marino gimplify_stmt (to_p, pre_p);
4645e4b17023SJohn Marino *expr_p = NULL_TREE;
4646e4b17023SJohn Marino return GS_ALL_DONE;
4647e4b17023SJohn Marino }
4648e4b17023SJohn Marino
4649e4b17023SJohn Marino /* If the value being copied is of variable width, compute the length
4650e4b17023SJohn Marino of the copy into a WITH_SIZE_EXPR. Note that we need to do this
4651e4b17023SJohn Marino before gimplifying any of the operands so that we can resolve any
4652e4b17023SJohn Marino PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
4653e4b17023SJohn Marino the size of the expression to be copied, not of the destination, so
4654e4b17023SJohn Marino that is what we must do here. */
4655e4b17023SJohn Marino maybe_with_size_expr (from_p);
4656e4b17023SJohn Marino
4657e4b17023SJohn Marino ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
4658e4b17023SJohn Marino if (ret == GS_ERROR)
4659e4b17023SJohn Marino return ret;
4660e4b17023SJohn Marino
4661e4b17023SJohn Marino /* As a special case, we have to temporarily allow for assignments
4662e4b17023SJohn Marino with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
4663e4b17023SJohn Marino a toplevel statement, when gimplifying the GENERIC expression
4664e4b17023SJohn Marino MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
4665e4b17023SJohn Marino GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
4666e4b17023SJohn Marino
4667e4b17023SJohn Marino Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
4668e4b17023SJohn Marino prevent gimplify_expr from trying to create a new temporary for
4669e4b17023SJohn Marino foo's LHS, we tell it that it should only gimplify until it
4670e4b17023SJohn Marino reaches the CALL_EXPR. On return from gimplify_expr, the newly
4671e4b17023SJohn Marino created GIMPLE_CALL <foo> will be the last statement in *PRE_P
4672e4b17023SJohn Marino and all we need to do here is set 'a' to be its LHS. */
4673e4b17023SJohn Marino ret = gimplify_expr (from_p, pre_p, post_p, rhs_predicate_for (*to_p),
4674e4b17023SJohn Marino fb_rvalue);
4675e4b17023SJohn Marino if (ret == GS_ERROR)
4676e4b17023SJohn Marino return ret;
4677e4b17023SJohn Marino
4678e4b17023SJohn Marino /* Now see if the above changed *from_p to something we handle specially. */
4679e4b17023SJohn Marino ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
4680e4b17023SJohn Marino want_value);
4681e4b17023SJohn Marino if (ret != GS_UNHANDLED)
4682e4b17023SJohn Marino return ret;
4683e4b17023SJohn Marino
4684e4b17023SJohn Marino /* If we've got a variable sized assignment between two lvalues (i.e. does
4685e4b17023SJohn Marino not involve a call), then we can make things a bit more straightforward
4686e4b17023SJohn Marino by converting the assignment to memcpy or memset. */
4687e4b17023SJohn Marino if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
4688e4b17023SJohn Marino {
4689e4b17023SJohn Marino tree from = TREE_OPERAND (*from_p, 0);
4690e4b17023SJohn Marino tree size = TREE_OPERAND (*from_p, 1);
4691e4b17023SJohn Marino
4692e4b17023SJohn Marino if (TREE_CODE (from) == CONSTRUCTOR)
4693e4b17023SJohn Marino return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
4694e4b17023SJohn Marino
4695e4b17023SJohn Marino if (is_gimple_addressable (from))
4696e4b17023SJohn Marino {
4697e4b17023SJohn Marino *from_p = from;
4698e4b17023SJohn Marino return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
4699e4b17023SJohn Marino pre_p);
4700e4b17023SJohn Marino }
4701e4b17023SJohn Marino }
4702e4b17023SJohn Marino
4703e4b17023SJohn Marino /* Transform partial stores to non-addressable complex variables into
4704e4b17023SJohn Marino total stores. This allows us to use real instead of virtual operands
4705e4b17023SJohn Marino for these variables, which improves optimization. */
4706e4b17023SJohn Marino if ((TREE_CODE (*to_p) == REALPART_EXPR
4707e4b17023SJohn Marino || TREE_CODE (*to_p) == IMAGPART_EXPR)
4708e4b17023SJohn Marino && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
4709e4b17023SJohn Marino return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
4710e4b17023SJohn Marino
4711e4b17023SJohn Marino /* Try to alleviate the effects of the gimplification creating artificial
4712e4b17023SJohn Marino temporaries (see for example is_gimple_reg_rhs) on the debug info. */
4713e4b17023SJohn Marino if (!gimplify_ctxp->into_ssa
4714e4b17023SJohn Marino && TREE_CODE (*from_p) == VAR_DECL
4715e4b17023SJohn Marino && DECL_IGNORED_P (*from_p)
4716e4b17023SJohn Marino && DECL_P (*to_p)
4717e4b17023SJohn Marino && !DECL_IGNORED_P (*to_p))
4718e4b17023SJohn Marino {
4719e4b17023SJohn Marino if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
4720e4b17023SJohn Marino DECL_NAME (*from_p)
4721e4b17023SJohn Marino = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
4722e4b17023SJohn Marino DECL_DEBUG_EXPR_IS_FROM (*from_p) = 1;
4723e4b17023SJohn Marino SET_DECL_DEBUG_EXPR (*from_p, *to_p);
4724e4b17023SJohn Marino }
4725e4b17023SJohn Marino
4726e4b17023SJohn Marino if (want_value && TREE_THIS_VOLATILE (*to_p))
4727e4b17023SJohn Marino *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
4728e4b17023SJohn Marino
4729e4b17023SJohn Marino if (TREE_CODE (*from_p) == CALL_EXPR)
4730e4b17023SJohn Marino {
4731e4b17023SJohn Marino /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
4732e4b17023SJohn Marino instead of a GIMPLE_ASSIGN. */
4733e4b17023SJohn Marino tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
4734e4b17023SJohn Marino CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
4735e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
4736e4b17023SJohn Marino assign = gimple_build_call_from_tree (*from_p);
4737e4b17023SJohn Marino gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
4738e4b17023SJohn Marino if (!gimple_call_noreturn_p (assign))
4739e4b17023SJohn Marino gimple_call_set_lhs (assign, *to_p);
4740e4b17023SJohn Marino }
4741e4b17023SJohn Marino else
4742e4b17023SJohn Marino {
4743e4b17023SJohn Marino assign = gimple_build_assign (*to_p, *from_p);
4744e4b17023SJohn Marino gimple_set_location (assign, EXPR_LOCATION (*expr_p));
4745e4b17023SJohn Marino }
4746e4b17023SJohn Marino
4747e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, assign);
4748e4b17023SJohn Marino
4749e4b17023SJohn Marino if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
4750e4b17023SJohn Marino {
4751e4b17023SJohn Marino /* If we've somehow already got an SSA_NAME on the LHS, then
4752e4b17023SJohn Marino we've probably modified it twice. Not good. */
4753e4b17023SJohn Marino gcc_assert (TREE_CODE (*to_p) != SSA_NAME);
4754e4b17023SJohn Marino *to_p = make_ssa_name (*to_p, assign);
4755e4b17023SJohn Marino gimple_set_lhs (assign, *to_p);
4756e4b17023SJohn Marino }
4757e4b17023SJohn Marino
4758e4b17023SJohn Marino if (want_value)
4759e4b17023SJohn Marino {
4760e4b17023SJohn Marino *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
4761e4b17023SJohn Marino return GS_OK;
4762e4b17023SJohn Marino }
4763e4b17023SJohn Marino else
4764e4b17023SJohn Marino *expr_p = NULL;
4765e4b17023SJohn Marino
4766e4b17023SJohn Marino return GS_ALL_DONE;
4767e4b17023SJohn Marino }
4768e4b17023SJohn Marino
4769e4b17023SJohn Marino /* Gimplify a comparison between two variable-sized objects. Do this
4770e4b17023SJohn Marino with a call to BUILT_IN_MEMCMP. */
4771e4b17023SJohn Marino
4772e4b17023SJohn Marino static enum gimplify_status
gimplify_variable_sized_compare(tree * expr_p)4773e4b17023SJohn Marino gimplify_variable_sized_compare (tree *expr_p)
4774e4b17023SJohn Marino {
4775e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
4776e4b17023SJohn Marino tree op0 = TREE_OPERAND (*expr_p, 0);
4777e4b17023SJohn Marino tree op1 = TREE_OPERAND (*expr_p, 1);
4778e4b17023SJohn Marino tree t, arg, dest, src, expr;
4779e4b17023SJohn Marino
4780e4b17023SJohn Marino arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
4781e4b17023SJohn Marino arg = unshare_expr (arg);
4782e4b17023SJohn Marino arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
4783e4b17023SJohn Marino src = build_fold_addr_expr_loc (loc, op1);
4784e4b17023SJohn Marino dest = build_fold_addr_expr_loc (loc, op0);
4785e4b17023SJohn Marino t = builtin_decl_implicit (BUILT_IN_MEMCMP);
4786e4b17023SJohn Marino t = build_call_expr_loc (loc, t, 3, dest, src, arg);
4787e4b17023SJohn Marino
4788e4b17023SJohn Marino expr
4789e4b17023SJohn Marino = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
4790e4b17023SJohn Marino SET_EXPR_LOCATION (expr, loc);
4791e4b17023SJohn Marino *expr_p = expr;
4792e4b17023SJohn Marino
4793e4b17023SJohn Marino return GS_OK;
4794e4b17023SJohn Marino }
4795e4b17023SJohn Marino
4796e4b17023SJohn Marino /* Gimplify a comparison between two aggregate objects of integral scalar
4797e4b17023SJohn Marino mode as a comparison between the bitwise equivalent scalar values. */
4798e4b17023SJohn Marino
4799e4b17023SJohn Marino static enum gimplify_status
gimplify_scalar_mode_aggregate_compare(tree * expr_p)4800e4b17023SJohn Marino gimplify_scalar_mode_aggregate_compare (tree *expr_p)
4801e4b17023SJohn Marino {
4802e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
4803e4b17023SJohn Marino tree op0 = TREE_OPERAND (*expr_p, 0);
4804e4b17023SJohn Marino tree op1 = TREE_OPERAND (*expr_p, 1);
4805e4b17023SJohn Marino
4806e4b17023SJohn Marino tree type = TREE_TYPE (op0);
4807e4b17023SJohn Marino tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
4808e4b17023SJohn Marino
4809e4b17023SJohn Marino op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
4810e4b17023SJohn Marino op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
4811e4b17023SJohn Marino
4812e4b17023SJohn Marino *expr_p
4813e4b17023SJohn Marino = fold_build2_loc (loc, TREE_CODE (*expr_p), TREE_TYPE (*expr_p), op0, op1);
4814e4b17023SJohn Marino
4815e4b17023SJohn Marino return GS_OK;
4816e4b17023SJohn Marino }
4817e4b17023SJohn Marino
4818e4b17023SJohn Marino /* Gimplify an expression sequence. This function gimplifies each
4819e4b17023SJohn Marino expression and rewrites the original expression with the last
4820e4b17023SJohn Marino expression of the sequence in GIMPLE form.
4821e4b17023SJohn Marino
4822e4b17023SJohn Marino PRE_P points to the list where the side effects for all the
4823e4b17023SJohn Marino expressions in the sequence will be emitted.
4824e4b17023SJohn Marino
4825e4b17023SJohn Marino WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
4826e4b17023SJohn Marino
4827e4b17023SJohn Marino static enum gimplify_status
gimplify_compound_expr(tree * expr_p,gimple_seq * pre_p,bool want_value)4828e4b17023SJohn Marino gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
4829e4b17023SJohn Marino {
4830e4b17023SJohn Marino tree t = *expr_p;
4831e4b17023SJohn Marino
4832e4b17023SJohn Marino do
4833e4b17023SJohn Marino {
4834e4b17023SJohn Marino tree *sub_p = &TREE_OPERAND (t, 0);
4835e4b17023SJohn Marino
4836e4b17023SJohn Marino if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
4837e4b17023SJohn Marino gimplify_compound_expr (sub_p, pre_p, false);
4838e4b17023SJohn Marino else
4839e4b17023SJohn Marino gimplify_stmt (sub_p, pre_p);
4840e4b17023SJohn Marino
4841e4b17023SJohn Marino t = TREE_OPERAND (t, 1);
4842e4b17023SJohn Marino }
4843e4b17023SJohn Marino while (TREE_CODE (t) == COMPOUND_EXPR);
4844e4b17023SJohn Marino
4845e4b17023SJohn Marino *expr_p = t;
4846e4b17023SJohn Marino if (want_value)
4847e4b17023SJohn Marino return GS_OK;
4848e4b17023SJohn Marino else
4849e4b17023SJohn Marino {
4850e4b17023SJohn Marino gimplify_stmt (expr_p, pre_p);
4851e4b17023SJohn Marino return GS_ALL_DONE;
4852e4b17023SJohn Marino }
4853e4b17023SJohn Marino }
4854e4b17023SJohn Marino
4855e4b17023SJohn Marino /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
4856e4b17023SJohn Marino gimplify. After gimplification, EXPR_P will point to a new temporary
4857e4b17023SJohn Marino that holds the original value of the SAVE_EXPR node.
4858e4b17023SJohn Marino
4859e4b17023SJohn Marino PRE_P points to the list where side effects that must happen before
4860e4b17023SJohn Marino *EXPR_P should be stored. */
4861e4b17023SJohn Marino
4862e4b17023SJohn Marino static enum gimplify_status
gimplify_save_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)4863e4b17023SJohn Marino gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
4864e4b17023SJohn Marino {
4865e4b17023SJohn Marino enum gimplify_status ret = GS_ALL_DONE;
4866e4b17023SJohn Marino tree val;
4867e4b17023SJohn Marino
4868e4b17023SJohn Marino gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
4869e4b17023SJohn Marino val = TREE_OPERAND (*expr_p, 0);
4870e4b17023SJohn Marino
4871e4b17023SJohn Marino /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
4872e4b17023SJohn Marino if (!SAVE_EXPR_RESOLVED_P (*expr_p))
4873e4b17023SJohn Marino {
4874e4b17023SJohn Marino /* The operand may be a void-valued expression such as SAVE_EXPRs
4875e4b17023SJohn Marino generated by the Java frontend for class initialization. It is
4876e4b17023SJohn Marino being executed only for its side-effects. */
4877e4b17023SJohn Marino if (TREE_TYPE (val) == void_type_node)
4878e4b17023SJohn Marino {
4879e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
4880e4b17023SJohn Marino is_gimple_stmt, fb_none);
4881e4b17023SJohn Marino val = NULL;
4882e4b17023SJohn Marino }
4883e4b17023SJohn Marino else
4884e4b17023SJohn Marino val = get_initialized_tmp_var (val, pre_p, post_p);
4885e4b17023SJohn Marino
4886e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0) = val;
4887e4b17023SJohn Marino SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
4888e4b17023SJohn Marino }
4889e4b17023SJohn Marino
4890e4b17023SJohn Marino *expr_p = val;
4891e4b17023SJohn Marino
4892e4b17023SJohn Marino return ret;
4893e4b17023SJohn Marino }
4894e4b17023SJohn Marino
4895e4b17023SJohn Marino /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
4896e4b17023SJohn Marino
4897e4b17023SJohn Marino unary_expr
4898e4b17023SJohn Marino : ...
4899e4b17023SJohn Marino | '&' varname
4900e4b17023SJohn Marino ...
4901e4b17023SJohn Marino
4902e4b17023SJohn Marino PRE_P points to the list where side effects that must happen before
4903e4b17023SJohn Marino *EXPR_P should be stored.
4904e4b17023SJohn Marino
4905e4b17023SJohn Marino POST_P points to the list where side effects that must happen after
4906e4b17023SJohn Marino *EXPR_P should be stored. */
4907e4b17023SJohn Marino
4908e4b17023SJohn Marino static enum gimplify_status
gimplify_addr_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)4909e4b17023SJohn Marino gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
4910e4b17023SJohn Marino {
4911e4b17023SJohn Marino tree expr = *expr_p;
4912e4b17023SJohn Marino tree op0 = TREE_OPERAND (expr, 0);
4913e4b17023SJohn Marino enum gimplify_status ret;
4914e4b17023SJohn Marino location_t loc = EXPR_LOCATION (*expr_p);
4915e4b17023SJohn Marino
4916e4b17023SJohn Marino switch (TREE_CODE (op0))
4917e4b17023SJohn Marino {
4918e4b17023SJohn Marino case INDIRECT_REF:
4919e4b17023SJohn Marino do_indirect_ref:
4920e4b17023SJohn Marino /* Check if we are dealing with an expression of the form '&*ptr'.
4921e4b17023SJohn Marino While the front end folds away '&*ptr' into 'ptr', these
4922e4b17023SJohn Marino expressions may be generated internally by the compiler (e.g.,
4923e4b17023SJohn Marino builtins like __builtin_va_end). */
4924e4b17023SJohn Marino /* Caution: the silent array decomposition semantics we allow for
4925e4b17023SJohn Marino ADDR_EXPR means we can't always discard the pair. */
4926e4b17023SJohn Marino /* Gimplification of the ADDR_EXPR operand may drop
4927e4b17023SJohn Marino cv-qualification conversions, so make sure we add them if
4928e4b17023SJohn Marino needed. */
4929e4b17023SJohn Marino {
4930e4b17023SJohn Marino tree op00 = TREE_OPERAND (op0, 0);
4931e4b17023SJohn Marino tree t_expr = TREE_TYPE (expr);
4932e4b17023SJohn Marino tree t_op00 = TREE_TYPE (op00);
4933e4b17023SJohn Marino
4934e4b17023SJohn Marino if (!useless_type_conversion_p (t_expr, t_op00))
4935e4b17023SJohn Marino op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
4936e4b17023SJohn Marino *expr_p = op00;
4937e4b17023SJohn Marino ret = GS_OK;
4938e4b17023SJohn Marino }
4939e4b17023SJohn Marino break;
4940e4b17023SJohn Marino
4941e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
4942e4b17023SJohn Marino /* Take the address of our operand and then convert it to the type of
4943e4b17023SJohn Marino this ADDR_EXPR.
4944e4b17023SJohn Marino
4945e4b17023SJohn Marino ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
4946e4b17023SJohn Marino all clear. The impact of this transformation is even less clear. */
4947e4b17023SJohn Marino
4948e4b17023SJohn Marino /* If the operand is a useless conversion, look through it. Doing so
4949e4b17023SJohn Marino guarantees that the ADDR_EXPR and its operand will remain of the
4950e4b17023SJohn Marino same type. */
4951e4b17023SJohn Marino if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
4952e4b17023SJohn Marino op0 = TREE_OPERAND (op0, 0);
4953e4b17023SJohn Marino
4954e4b17023SJohn Marino *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
4955e4b17023SJohn Marino build_fold_addr_expr_loc (loc,
4956e4b17023SJohn Marino TREE_OPERAND (op0, 0)));
4957e4b17023SJohn Marino ret = GS_OK;
4958e4b17023SJohn Marino break;
4959e4b17023SJohn Marino
4960e4b17023SJohn Marino default:
4961e4b17023SJohn Marino /* We use fb_either here because the C frontend sometimes takes
4962e4b17023SJohn Marino the address of a call that returns a struct; see
4963e4b17023SJohn Marino gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
4964e4b17023SJohn Marino the implied temporary explicit. */
4965e4b17023SJohn Marino
4966e4b17023SJohn Marino /* Make the operand addressable. */
4967e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
4968e4b17023SJohn Marino is_gimple_addressable, fb_either);
4969e4b17023SJohn Marino if (ret == GS_ERROR)
4970e4b17023SJohn Marino break;
4971e4b17023SJohn Marino
4972e4b17023SJohn Marino /* Then mark it. Beware that it may not be possible to do so directly
4973e4b17023SJohn Marino if a temporary has been created by the gimplification. */
4974e4b17023SJohn Marino prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
4975e4b17023SJohn Marino
4976e4b17023SJohn Marino op0 = TREE_OPERAND (expr, 0);
4977e4b17023SJohn Marino
4978e4b17023SJohn Marino /* For various reasons, the gimplification of the expression
4979e4b17023SJohn Marino may have made a new INDIRECT_REF. */
4980e4b17023SJohn Marino if (TREE_CODE (op0) == INDIRECT_REF)
4981e4b17023SJohn Marino goto do_indirect_ref;
4982e4b17023SJohn Marino
4983e4b17023SJohn Marino mark_addressable (TREE_OPERAND (expr, 0));
4984e4b17023SJohn Marino
4985e4b17023SJohn Marino /* The FEs may end up building ADDR_EXPRs early on a decl with
4986e4b17023SJohn Marino an incomplete type. Re-build ADDR_EXPRs in canonical form
4987e4b17023SJohn Marino here. */
4988e4b17023SJohn Marino if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
4989e4b17023SJohn Marino *expr_p = build_fold_addr_expr (op0);
4990e4b17023SJohn Marino
4991e4b17023SJohn Marino /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
4992e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (*expr_p);
4993e4b17023SJohn Marino
4994e4b17023SJohn Marino /* If we re-built the ADDR_EXPR add a conversion to the original type
4995e4b17023SJohn Marino if required. */
4996e4b17023SJohn Marino if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
4997e4b17023SJohn Marino *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
4998e4b17023SJohn Marino
4999e4b17023SJohn Marino break;
5000e4b17023SJohn Marino }
5001e4b17023SJohn Marino
5002e4b17023SJohn Marino return ret;
5003e4b17023SJohn Marino }
5004e4b17023SJohn Marino
5005e4b17023SJohn Marino /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
5006e4b17023SJohn Marino value; output operands should be a gimple lvalue. */
5007e4b17023SJohn Marino
5008e4b17023SJohn Marino static enum gimplify_status
gimplify_asm_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)5009e4b17023SJohn Marino gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
5010e4b17023SJohn Marino {
5011e4b17023SJohn Marino tree expr;
5012e4b17023SJohn Marino int noutputs;
5013e4b17023SJohn Marino const char **oconstraints;
5014e4b17023SJohn Marino int i;
5015e4b17023SJohn Marino tree link;
5016e4b17023SJohn Marino const char *constraint;
5017e4b17023SJohn Marino bool allows_mem, allows_reg, is_inout;
5018e4b17023SJohn Marino enum gimplify_status ret, tret;
5019e4b17023SJohn Marino gimple stmt;
5020e4b17023SJohn Marino VEC(tree, gc) *inputs;
5021e4b17023SJohn Marino VEC(tree, gc) *outputs;
5022e4b17023SJohn Marino VEC(tree, gc) *clobbers;
5023e4b17023SJohn Marino VEC(tree, gc) *labels;
5024e4b17023SJohn Marino tree link_next;
5025e4b17023SJohn Marino
5026e4b17023SJohn Marino expr = *expr_p;
5027e4b17023SJohn Marino noutputs = list_length (ASM_OUTPUTS (expr));
5028e4b17023SJohn Marino oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
5029e4b17023SJohn Marino
5030e4b17023SJohn Marino inputs = outputs = clobbers = labels = NULL;
5031e4b17023SJohn Marino
5032e4b17023SJohn Marino ret = GS_ALL_DONE;
5033e4b17023SJohn Marino link_next = NULL_TREE;
5034e4b17023SJohn Marino for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
5035e4b17023SJohn Marino {
5036e4b17023SJohn Marino bool ok;
5037e4b17023SJohn Marino size_t constraint_len;
5038e4b17023SJohn Marino
5039e4b17023SJohn Marino link_next = TREE_CHAIN (link);
5040e4b17023SJohn Marino
5041e4b17023SJohn Marino oconstraints[i]
5042e4b17023SJohn Marino = constraint
5043e4b17023SJohn Marino = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
5044e4b17023SJohn Marino constraint_len = strlen (constraint);
5045e4b17023SJohn Marino if (constraint_len == 0)
5046e4b17023SJohn Marino continue;
5047e4b17023SJohn Marino
5048e4b17023SJohn Marino ok = parse_output_constraint (&constraint, i, 0, 0,
5049e4b17023SJohn Marino &allows_mem, &allows_reg, &is_inout);
5050e4b17023SJohn Marino if (!ok)
5051e4b17023SJohn Marino {
5052e4b17023SJohn Marino ret = GS_ERROR;
5053e4b17023SJohn Marino is_inout = false;
5054e4b17023SJohn Marino }
5055e4b17023SJohn Marino
5056e4b17023SJohn Marino if (!allows_reg && allows_mem)
5057e4b17023SJohn Marino mark_addressable (TREE_VALUE (link));
5058e4b17023SJohn Marino
5059e4b17023SJohn Marino tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
5060e4b17023SJohn Marino is_inout ? is_gimple_min_lval : is_gimple_lvalue,
5061e4b17023SJohn Marino fb_lvalue | fb_mayfail);
5062e4b17023SJohn Marino if (tret == GS_ERROR)
5063e4b17023SJohn Marino {
5064e4b17023SJohn Marino error ("invalid lvalue in asm output %d", i);
5065e4b17023SJohn Marino ret = tret;
5066e4b17023SJohn Marino }
5067e4b17023SJohn Marino
5068e4b17023SJohn Marino VEC_safe_push (tree, gc, outputs, link);
5069e4b17023SJohn Marino TREE_CHAIN (link) = NULL_TREE;
5070e4b17023SJohn Marino
5071e4b17023SJohn Marino if (is_inout)
5072e4b17023SJohn Marino {
5073e4b17023SJohn Marino /* An input/output operand. To give the optimizers more
5074e4b17023SJohn Marino flexibility, split it into separate input and output
5075e4b17023SJohn Marino operands. */
5076e4b17023SJohn Marino tree input;
5077e4b17023SJohn Marino char buf[10];
5078e4b17023SJohn Marino
5079e4b17023SJohn Marino /* Turn the in/out constraint into an output constraint. */
5080e4b17023SJohn Marino char *p = xstrdup (constraint);
5081e4b17023SJohn Marino p[0] = '=';
5082e4b17023SJohn Marino TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
5083e4b17023SJohn Marino
5084e4b17023SJohn Marino /* And add a matching input constraint. */
5085e4b17023SJohn Marino if (allows_reg)
5086e4b17023SJohn Marino {
5087e4b17023SJohn Marino sprintf (buf, "%d", i);
5088e4b17023SJohn Marino
5089e4b17023SJohn Marino /* If there are multiple alternatives in the constraint,
5090e4b17023SJohn Marino handle each of them individually. Those that allow register
5091e4b17023SJohn Marino will be replaced with operand number, the others will stay
5092e4b17023SJohn Marino unchanged. */
5093e4b17023SJohn Marino if (strchr (p, ',') != NULL)
5094e4b17023SJohn Marino {
5095e4b17023SJohn Marino size_t len = 0, buflen = strlen (buf);
5096e4b17023SJohn Marino char *beg, *end, *str, *dst;
5097e4b17023SJohn Marino
5098e4b17023SJohn Marino for (beg = p + 1;;)
5099e4b17023SJohn Marino {
5100e4b17023SJohn Marino end = strchr (beg, ',');
5101e4b17023SJohn Marino if (end == NULL)
5102e4b17023SJohn Marino end = strchr (beg, '\0');
5103e4b17023SJohn Marino if ((size_t) (end - beg) < buflen)
5104e4b17023SJohn Marino len += buflen + 1;
5105e4b17023SJohn Marino else
5106e4b17023SJohn Marino len += end - beg + 1;
5107e4b17023SJohn Marino if (*end)
5108e4b17023SJohn Marino beg = end + 1;
5109e4b17023SJohn Marino else
5110e4b17023SJohn Marino break;
5111e4b17023SJohn Marino }
5112e4b17023SJohn Marino
5113e4b17023SJohn Marino str = (char *) alloca (len);
5114e4b17023SJohn Marino for (beg = p + 1, dst = str;;)
5115e4b17023SJohn Marino {
5116e4b17023SJohn Marino const char *tem;
5117e4b17023SJohn Marino bool mem_p, reg_p, inout_p;
5118e4b17023SJohn Marino
5119e4b17023SJohn Marino end = strchr (beg, ',');
5120e4b17023SJohn Marino if (end)
5121e4b17023SJohn Marino *end = '\0';
5122e4b17023SJohn Marino beg[-1] = '=';
5123e4b17023SJohn Marino tem = beg - 1;
5124e4b17023SJohn Marino parse_output_constraint (&tem, i, 0, 0,
5125e4b17023SJohn Marino &mem_p, ®_p, &inout_p);
5126e4b17023SJohn Marino if (dst != str)
5127e4b17023SJohn Marino *dst++ = ',';
5128e4b17023SJohn Marino if (reg_p)
5129e4b17023SJohn Marino {
5130e4b17023SJohn Marino memcpy (dst, buf, buflen);
5131e4b17023SJohn Marino dst += buflen;
5132e4b17023SJohn Marino }
5133e4b17023SJohn Marino else
5134e4b17023SJohn Marino {
5135e4b17023SJohn Marino if (end)
5136e4b17023SJohn Marino len = end - beg;
5137e4b17023SJohn Marino else
5138e4b17023SJohn Marino len = strlen (beg);
5139e4b17023SJohn Marino memcpy (dst, beg, len);
5140e4b17023SJohn Marino dst += len;
5141e4b17023SJohn Marino }
5142e4b17023SJohn Marino if (end)
5143e4b17023SJohn Marino beg = end + 1;
5144e4b17023SJohn Marino else
5145e4b17023SJohn Marino break;
5146e4b17023SJohn Marino }
5147e4b17023SJohn Marino *dst = '\0';
5148e4b17023SJohn Marino input = build_string (dst - str, str);
5149e4b17023SJohn Marino }
5150e4b17023SJohn Marino else
5151e4b17023SJohn Marino input = build_string (strlen (buf), buf);
5152e4b17023SJohn Marino }
5153e4b17023SJohn Marino else
5154e4b17023SJohn Marino input = build_string (constraint_len - 1, constraint + 1);
5155e4b17023SJohn Marino
5156e4b17023SJohn Marino free (p);
5157e4b17023SJohn Marino
5158e4b17023SJohn Marino input = build_tree_list (build_tree_list (NULL_TREE, input),
5159e4b17023SJohn Marino unshare_expr (TREE_VALUE (link)));
5160e4b17023SJohn Marino ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
5161e4b17023SJohn Marino }
5162e4b17023SJohn Marino }
5163e4b17023SJohn Marino
5164e4b17023SJohn Marino link_next = NULL_TREE;
5165e4b17023SJohn Marino for (link = ASM_INPUTS (expr); link; ++i, link = link_next)
5166e4b17023SJohn Marino {
5167e4b17023SJohn Marino link_next = TREE_CHAIN (link);
5168e4b17023SJohn Marino constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
5169e4b17023SJohn Marino parse_input_constraint (&constraint, 0, 0, noutputs, 0,
5170e4b17023SJohn Marino oconstraints, &allows_mem, &allows_reg);
5171e4b17023SJohn Marino
5172e4b17023SJohn Marino /* If we can't make copies, we can only accept memory. */
5173e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (link))))
5174e4b17023SJohn Marino {
5175e4b17023SJohn Marino if (allows_mem)
5176e4b17023SJohn Marino allows_reg = 0;
5177e4b17023SJohn Marino else
5178e4b17023SJohn Marino {
5179e4b17023SJohn Marino error ("impossible constraint in %<asm%>");
5180e4b17023SJohn Marino error ("non-memory input %d must stay in memory", i);
5181e4b17023SJohn Marino return GS_ERROR;
5182e4b17023SJohn Marino }
5183e4b17023SJohn Marino }
5184e4b17023SJohn Marino
5185e4b17023SJohn Marino /* If the operand is a memory input, it should be an lvalue. */
5186e4b17023SJohn Marino if (!allows_reg && allows_mem)
5187e4b17023SJohn Marino {
5188e4b17023SJohn Marino tree inputv = TREE_VALUE (link);
5189e4b17023SJohn Marino STRIP_NOPS (inputv);
5190e4b17023SJohn Marino if (TREE_CODE (inputv) == PREDECREMENT_EXPR
5191e4b17023SJohn Marino || TREE_CODE (inputv) == PREINCREMENT_EXPR
5192e4b17023SJohn Marino || TREE_CODE (inputv) == POSTDECREMENT_EXPR
5193e4b17023SJohn Marino || TREE_CODE (inputv) == POSTINCREMENT_EXPR)
5194e4b17023SJohn Marino TREE_VALUE (link) = error_mark_node;
5195e4b17023SJohn Marino tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
5196e4b17023SJohn Marino is_gimple_lvalue, fb_lvalue | fb_mayfail);
5197e4b17023SJohn Marino mark_addressable (TREE_VALUE (link));
5198e4b17023SJohn Marino if (tret == GS_ERROR)
5199e4b17023SJohn Marino {
5200e4b17023SJohn Marino if (EXPR_HAS_LOCATION (TREE_VALUE (link)))
5201e4b17023SJohn Marino input_location = EXPR_LOCATION (TREE_VALUE (link));
5202e4b17023SJohn Marino error ("memory input %d is not directly addressable", i);
5203e4b17023SJohn Marino ret = tret;
5204e4b17023SJohn Marino }
5205e4b17023SJohn Marino }
5206e4b17023SJohn Marino else
5207e4b17023SJohn Marino {
5208e4b17023SJohn Marino tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
5209e4b17023SJohn Marino is_gimple_asm_val, fb_rvalue);
5210e4b17023SJohn Marino if (tret == GS_ERROR)
5211e4b17023SJohn Marino ret = tret;
5212e4b17023SJohn Marino }
5213e4b17023SJohn Marino
5214e4b17023SJohn Marino TREE_CHAIN (link) = NULL_TREE;
5215e4b17023SJohn Marino VEC_safe_push (tree, gc, inputs, link);
5216e4b17023SJohn Marino }
5217e4b17023SJohn Marino
5218e4b17023SJohn Marino for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link))
5219e4b17023SJohn Marino VEC_safe_push (tree, gc, clobbers, link);
5220e4b17023SJohn Marino
5221e4b17023SJohn Marino for (link = ASM_LABELS (expr); link; ++i, link = TREE_CHAIN (link))
5222e4b17023SJohn Marino VEC_safe_push (tree, gc, labels, link);
5223e4b17023SJohn Marino
5224e4b17023SJohn Marino /* Do not add ASMs with errors to the gimple IL stream. */
5225e4b17023SJohn Marino if (ret != GS_ERROR)
5226e4b17023SJohn Marino {
5227e4b17023SJohn Marino stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
5228e4b17023SJohn Marino inputs, outputs, clobbers, labels);
5229e4b17023SJohn Marino
5230e4b17023SJohn Marino gimple_asm_set_volatile (stmt, ASM_VOLATILE_P (expr));
5231e4b17023SJohn Marino gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
5232e4b17023SJohn Marino
5233e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, stmt);
5234e4b17023SJohn Marino }
5235e4b17023SJohn Marino
5236e4b17023SJohn Marino return ret;
5237e4b17023SJohn Marino }
5238e4b17023SJohn Marino
5239e4b17023SJohn Marino /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
5240e4b17023SJohn Marino GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
5241e4b17023SJohn Marino gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
5242e4b17023SJohn Marino return to this function.
5243e4b17023SJohn Marino
5244e4b17023SJohn Marino FIXME should we complexify the prequeue handling instead? Or use flags
5245e4b17023SJohn Marino for all the cleanups and let the optimizer tighten them up? The current
5246e4b17023SJohn Marino code seems pretty fragile; it will break on a cleanup within any
5247e4b17023SJohn Marino non-conditional nesting. But any such nesting would be broken, anyway;
5248e4b17023SJohn Marino we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
5249e4b17023SJohn Marino and continues out of it. We can do that at the RTL level, though, so
5250e4b17023SJohn Marino having an optimizer to tighten up try/finally regions would be a Good
5251e4b17023SJohn Marino Thing. */
5252e4b17023SJohn Marino
5253e4b17023SJohn Marino static enum gimplify_status
gimplify_cleanup_point_expr(tree * expr_p,gimple_seq * pre_p)5254e4b17023SJohn Marino gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
5255e4b17023SJohn Marino {
5256e4b17023SJohn Marino gimple_stmt_iterator iter;
5257e4b17023SJohn Marino gimple_seq body_sequence = NULL;
5258e4b17023SJohn Marino
5259e4b17023SJohn Marino tree temp = voidify_wrapper_expr (*expr_p, NULL);
5260e4b17023SJohn Marino
5261e4b17023SJohn Marino /* We only care about the number of conditions between the innermost
5262e4b17023SJohn Marino CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
5263e4b17023SJohn Marino any cleanups collected outside the CLEANUP_POINT_EXPR. */
5264e4b17023SJohn Marino int old_conds = gimplify_ctxp->conditions;
5265e4b17023SJohn Marino gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
5266e4b17023SJohn Marino bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
5267e4b17023SJohn Marino gimplify_ctxp->conditions = 0;
5268e4b17023SJohn Marino gimplify_ctxp->conditional_cleanups = NULL;
5269e4b17023SJohn Marino gimplify_ctxp->in_cleanup_point_expr = true;
5270e4b17023SJohn Marino
5271e4b17023SJohn Marino gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
5272e4b17023SJohn Marino
5273e4b17023SJohn Marino gimplify_ctxp->conditions = old_conds;
5274e4b17023SJohn Marino gimplify_ctxp->conditional_cleanups = old_cleanups;
5275e4b17023SJohn Marino gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
5276e4b17023SJohn Marino
5277e4b17023SJohn Marino for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
5278e4b17023SJohn Marino {
5279e4b17023SJohn Marino gimple wce = gsi_stmt (iter);
5280e4b17023SJohn Marino
5281e4b17023SJohn Marino if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
5282e4b17023SJohn Marino {
5283e4b17023SJohn Marino if (gsi_one_before_end_p (iter))
5284e4b17023SJohn Marino {
5285e4b17023SJohn Marino /* Note that gsi_insert_seq_before and gsi_remove do not
5286e4b17023SJohn Marino scan operands, unlike some other sequence mutators. */
5287e4b17023SJohn Marino if (!gimple_wce_cleanup_eh_only (wce))
5288e4b17023SJohn Marino gsi_insert_seq_before_without_update (&iter,
5289e4b17023SJohn Marino gimple_wce_cleanup (wce),
5290e4b17023SJohn Marino GSI_SAME_STMT);
5291e4b17023SJohn Marino gsi_remove (&iter, true);
5292e4b17023SJohn Marino break;
5293e4b17023SJohn Marino }
5294e4b17023SJohn Marino else
5295e4b17023SJohn Marino {
5296e4b17023SJohn Marino gimple gtry;
5297e4b17023SJohn Marino gimple_seq seq;
5298e4b17023SJohn Marino enum gimple_try_flags kind;
5299e4b17023SJohn Marino
5300e4b17023SJohn Marino if (gimple_wce_cleanup_eh_only (wce))
5301e4b17023SJohn Marino kind = GIMPLE_TRY_CATCH;
5302e4b17023SJohn Marino else
5303e4b17023SJohn Marino kind = GIMPLE_TRY_FINALLY;
5304e4b17023SJohn Marino seq = gsi_split_seq_after (iter);
5305e4b17023SJohn Marino
5306e4b17023SJohn Marino gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
5307e4b17023SJohn Marino /* Do not use gsi_replace here, as it may scan operands.
5308e4b17023SJohn Marino We want to do a simple structural modification only. */
5309e4b17023SJohn Marino *gsi_stmt_ptr (&iter) = gtry;
5310e4b17023SJohn Marino iter = gsi_start (seq);
5311e4b17023SJohn Marino }
5312e4b17023SJohn Marino }
5313e4b17023SJohn Marino else
5314e4b17023SJohn Marino gsi_next (&iter);
5315e4b17023SJohn Marino }
5316e4b17023SJohn Marino
5317e4b17023SJohn Marino gimplify_seq_add_seq (pre_p, body_sequence);
5318e4b17023SJohn Marino if (temp)
5319e4b17023SJohn Marino {
5320e4b17023SJohn Marino *expr_p = temp;
5321e4b17023SJohn Marino return GS_OK;
5322e4b17023SJohn Marino }
5323e4b17023SJohn Marino else
5324e4b17023SJohn Marino {
5325e4b17023SJohn Marino *expr_p = NULL;
5326e4b17023SJohn Marino return GS_ALL_DONE;
5327e4b17023SJohn Marino }
5328e4b17023SJohn Marino }
5329e4b17023SJohn Marino
5330e4b17023SJohn Marino /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
5331e4b17023SJohn Marino is the cleanup action required. EH_ONLY is true if the cleanup should
5332e4b17023SJohn Marino only be executed if an exception is thrown, not on normal exit. */
5333e4b17023SJohn Marino
5334e4b17023SJohn Marino static void
gimple_push_cleanup(tree var,tree cleanup,bool eh_only,gimple_seq * pre_p)5335e4b17023SJohn Marino gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
5336e4b17023SJohn Marino {
5337e4b17023SJohn Marino gimple wce;
5338e4b17023SJohn Marino gimple_seq cleanup_stmts = NULL;
5339e4b17023SJohn Marino
5340e4b17023SJohn Marino /* Errors can result in improperly nested cleanups. Which results in
5341e4b17023SJohn Marino confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
5342e4b17023SJohn Marino if (seen_error ())
5343e4b17023SJohn Marino return;
5344e4b17023SJohn Marino
5345e4b17023SJohn Marino if (gimple_conditional_context ())
5346e4b17023SJohn Marino {
5347e4b17023SJohn Marino /* If we're in a conditional context, this is more complex. We only
5348e4b17023SJohn Marino want to run the cleanup if we actually ran the initialization that
5349e4b17023SJohn Marino necessitates it, but we want to run it after the end of the
5350e4b17023SJohn Marino conditional context. So we wrap the try/finally around the
5351e4b17023SJohn Marino condition and use a flag to determine whether or not to actually
5352e4b17023SJohn Marino run the destructor. Thus
5353e4b17023SJohn Marino
5354e4b17023SJohn Marino test ? f(A()) : 0
5355e4b17023SJohn Marino
5356e4b17023SJohn Marino becomes (approximately)
5357e4b17023SJohn Marino
5358e4b17023SJohn Marino flag = 0;
5359e4b17023SJohn Marino try {
5360e4b17023SJohn Marino if (test) { A::A(temp); flag = 1; val = f(temp); }
5361e4b17023SJohn Marino else { val = 0; }
5362e4b17023SJohn Marino } finally {
5363e4b17023SJohn Marino if (flag) A::~A(temp);
5364e4b17023SJohn Marino }
5365e4b17023SJohn Marino val
5366e4b17023SJohn Marino */
5367e4b17023SJohn Marino tree flag = create_tmp_var (boolean_type_node, "cleanup");
5368e4b17023SJohn Marino gimple ffalse = gimple_build_assign (flag, boolean_false_node);
5369e4b17023SJohn Marino gimple ftrue = gimple_build_assign (flag, boolean_true_node);
5370e4b17023SJohn Marino
5371e4b17023SJohn Marino cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
5372e4b17023SJohn Marino gimplify_stmt (&cleanup, &cleanup_stmts);
5373e4b17023SJohn Marino wce = gimple_build_wce (cleanup_stmts);
5374e4b17023SJohn Marino
5375e4b17023SJohn Marino gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
5376e4b17023SJohn Marino gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
5377e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, ftrue);
5378e4b17023SJohn Marino
5379e4b17023SJohn Marino /* Because of this manipulation, and the EH edges that jump
5380e4b17023SJohn Marino threading cannot redirect, the temporary (VAR) will appear
5381e4b17023SJohn Marino to be used uninitialized. Don't warn. */
5382e4b17023SJohn Marino TREE_NO_WARNING (var) = 1;
5383e4b17023SJohn Marino }
5384e4b17023SJohn Marino else
5385e4b17023SJohn Marino {
5386e4b17023SJohn Marino gimplify_stmt (&cleanup, &cleanup_stmts);
5387e4b17023SJohn Marino wce = gimple_build_wce (cleanup_stmts);
5388e4b17023SJohn Marino gimple_wce_set_cleanup_eh_only (wce, eh_only);
5389e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, wce);
5390e4b17023SJohn Marino }
5391e4b17023SJohn Marino }
5392e4b17023SJohn Marino
5393e4b17023SJohn Marino /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
5394e4b17023SJohn Marino
5395e4b17023SJohn Marino static enum gimplify_status
gimplify_target_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)5396e4b17023SJohn Marino gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
5397e4b17023SJohn Marino {
5398e4b17023SJohn Marino tree targ = *expr_p;
5399e4b17023SJohn Marino tree temp = TARGET_EXPR_SLOT (targ);
5400e4b17023SJohn Marino tree init = TARGET_EXPR_INITIAL (targ);
5401e4b17023SJohn Marino enum gimplify_status ret;
5402e4b17023SJohn Marino
5403e4b17023SJohn Marino if (init)
5404e4b17023SJohn Marino {
5405e4b17023SJohn Marino tree cleanup = NULL_TREE;
5406e4b17023SJohn Marino
5407e4b17023SJohn Marino /* TARGET_EXPR temps aren't part of the enclosing block, so add it
5408e4b17023SJohn Marino to the temps list. Handle also variable length TARGET_EXPRs. */
5409e4b17023SJohn Marino if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST)
5410e4b17023SJohn Marino {
5411e4b17023SJohn Marino if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
5412e4b17023SJohn Marino gimplify_type_sizes (TREE_TYPE (temp), pre_p);
5413e4b17023SJohn Marino gimplify_vla_decl (temp, pre_p);
5414e4b17023SJohn Marino }
5415e4b17023SJohn Marino else
5416e4b17023SJohn Marino gimple_add_tmp_var (temp);
5417e4b17023SJohn Marino
5418e4b17023SJohn Marino /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
5419e4b17023SJohn Marino expression is supposed to initialize the slot. */
5420e4b17023SJohn Marino if (VOID_TYPE_P (TREE_TYPE (init)))
5421e4b17023SJohn Marino ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
5422e4b17023SJohn Marino else
5423e4b17023SJohn Marino {
5424e4b17023SJohn Marino tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
5425e4b17023SJohn Marino init = init_expr;
5426e4b17023SJohn Marino ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
5427e4b17023SJohn Marino init = NULL;
5428e4b17023SJohn Marino ggc_free (init_expr);
5429e4b17023SJohn Marino }
5430e4b17023SJohn Marino if (ret == GS_ERROR)
5431e4b17023SJohn Marino {
5432e4b17023SJohn Marino /* PR c++/28266 Make sure this is expanded only once. */
5433e4b17023SJohn Marino TARGET_EXPR_INITIAL (targ) = NULL_TREE;
5434e4b17023SJohn Marino return GS_ERROR;
5435e4b17023SJohn Marino }
5436e4b17023SJohn Marino if (init)
5437e4b17023SJohn Marino gimplify_and_add (init, pre_p);
5438e4b17023SJohn Marino
5439e4b17023SJohn Marino /* If needed, push the cleanup for the temp. */
5440e4b17023SJohn Marino if (TARGET_EXPR_CLEANUP (targ))
5441e4b17023SJohn Marino {
5442e4b17023SJohn Marino if (CLEANUP_EH_ONLY (targ))
5443e4b17023SJohn Marino gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
5444e4b17023SJohn Marino CLEANUP_EH_ONLY (targ), pre_p);
5445e4b17023SJohn Marino else
5446e4b17023SJohn Marino cleanup = TARGET_EXPR_CLEANUP (targ);
5447e4b17023SJohn Marino }
5448e4b17023SJohn Marino
5449e4b17023SJohn Marino /* Add a clobber for the temporary going out of scope, like
5450e4b17023SJohn Marino gimplify_bind_expr. */
5451e4b17023SJohn Marino if (gimplify_ctxp->in_cleanup_point_expr
5452e4b17023SJohn Marino && needs_to_live_in_memory (temp))
5453e4b17023SJohn Marino {
5454e4b17023SJohn Marino tree clobber = build_constructor (TREE_TYPE (temp), NULL);
5455e4b17023SJohn Marino TREE_THIS_VOLATILE (clobber) = true;
5456e4b17023SJohn Marino clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
5457e4b17023SJohn Marino if (cleanup)
5458e4b17023SJohn Marino cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
5459e4b17023SJohn Marino clobber);
5460e4b17023SJohn Marino else
5461e4b17023SJohn Marino cleanup = clobber;
5462e4b17023SJohn Marino }
5463e4b17023SJohn Marino
5464e4b17023SJohn Marino if (cleanup)
5465e4b17023SJohn Marino gimple_push_cleanup (temp, cleanup, false, pre_p);
5466e4b17023SJohn Marino
5467e4b17023SJohn Marino /* Only expand this once. */
5468e4b17023SJohn Marino TREE_OPERAND (targ, 3) = init;
5469e4b17023SJohn Marino TARGET_EXPR_INITIAL (targ) = NULL_TREE;
5470e4b17023SJohn Marino }
5471e4b17023SJohn Marino else
5472e4b17023SJohn Marino /* We should have expanded this before. */
5473e4b17023SJohn Marino gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
5474e4b17023SJohn Marino
5475e4b17023SJohn Marino *expr_p = temp;
5476e4b17023SJohn Marino return GS_OK;
5477e4b17023SJohn Marino }
5478e4b17023SJohn Marino
5479e4b17023SJohn Marino /* Gimplification of expression trees. */
5480e4b17023SJohn Marino
5481e4b17023SJohn Marino /* Gimplify an expression which appears at statement context. The
5482e4b17023SJohn Marino corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
5483e4b17023SJohn Marino NULL, a new sequence is allocated.
5484e4b17023SJohn Marino
5485e4b17023SJohn Marino Return true if we actually added a statement to the queue. */
5486e4b17023SJohn Marino
5487e4b17023SJohn Marino bool
gimplify_stmt(tree * stmt_p,gimple_seq * seq_p)5488e4b17023SJohn Marino gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
5489e4b17023SJohn Marino {
5490e4b17023SJohn Marino gimple_seq_node last;
5491e4b17023SJohn Marino
5492e4b17023SJohn Marino if (!*seq_p)
5493e4b17023SJohn Marino *seq_p = gimple_seq_alloc ();
5494e4b17023SJohn Marino
5495e4b17023SJohn Marino last = gimple_seq_last (*seq_p);
5496e4b17023SJohn Marino gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
5497e4b17023SJohn Marino return last != gimple_seq_last (*seq_p);
5498e4b17023SJohn Marino }
5499e4b17023SJohn Marino
5500e4b17023SJohn Marino /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
5501e4b17023SJohn Marino to CTX. If entries already exist, force them to be some flavor of private.
5502e4b17023SJohn Marino If there is no enclosing parallel, do nothing. */
5503e4b17023SJohn Marino
5504e4b17023SJohn Marino void
omp_firstprivatize_variable(struct gimplify_omp_ctx * ctx,tree decl)5505e4b17023SJohn Marino omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
5506e4b17023SJohn Marino {
5507e4b17023SJohn Marino splay_tree_node n;
5508e4b17023SJohn Marino
5509e4b17023SJohn Marino if (decl == NULL || !DECL_P (decl))
5510e4b17023SJohn Marino return;
5511e4b17023SJohn Marino
5512e4b17023SJohn Marino do
5513e4b17023SJohn Marino {
5514e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
5515e4b17023SJohn Marino if (n != NULL)
5516e4b17023SJohn Marino {
5517e4b17023SJohn Marino if (n->value & GOVD_SHARED)
5518e4b17023SJohn Marino n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
5519e4b17023SJohn Marino else
5520e4b17023SJohn Marino return;
5521e4b17023SJohn Marino }
5522e4b17023SJohn Marino else if (ctx->region_type != ORT_WORKSHARE)
5523e4b17023SJohn Marino omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
5524e4b17023SJohn Marino
5525e4b17023SJohn Marino ctx = ctx->outer_context;
5526e4b17023SJohn Marino }
5527e4b17023SJohn Marino while (ctx);
5528e4b17023SJohn Marino }
5529e4b17023SJohn Marino
5530e4b17023SJohn Marino /* Similarly for each of the type sizes of TYPE. */
5531e4b17023SJohn Marino
5532e4b17023SJohn Marino static void
omp_firstprivatize_type_sizes(struct gimplify_omp_ctx * ctx,tree type)5533e4b17023SJohn Marino omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
5534e4b17023SJohn Marino {
5535e4b17023SJohn Marino if (type == NULL || type == error_mark_node)
5536e4b17023SJohn Marino return;
5537e4b17023SJohn Marino type = TYPE_MAIN_VARIANT (type);
5538e4b17023SJohn Marino
5539e4b17023SJohn Marino if (pointer_set_insert (ctx->privatized_types, type))
5540e4b17023SJohn Marino return;
5541e4b17023SJohn Marino
5542e4b17023SJohn Marino switch (TREE_CODE (type))
5543e4b17023SJohn Marino {
5544e4b17023SJohn Marino case INTEGER_TYPE:
5545e4b17023SJohn Marino case ENUMERAL_TYPE:
5546e4b17023SJohn Marino case BOOLEAN_TYPE:
5547e4b17023SJohn Marino case REAL_TYPE:
5548e4b17023SJohn Marino case FIXED_POINT_TYPE:
5549e4b17023SJohn Marino omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
5550e4b17023SJohn Marino omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
5551e4b17023SJohn Marino break;
5552e4b17023SJohn Marino
5553e4b17023SJohn Marino case ARRAY_TYPE:
5554e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
5555e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
5556e4b17023SJohn Marino break;
5557e4b17023SJohn Marino
5558e4b17023SJohn Marino case RECORD_TYPE:
5559e4b17023SJohn Marino case UNION_TYPE:
5560e4b17023SJohn Marino case QUAL_UNION_TYPE:
5561e4b17023SJohn Marino {
5562e4b17023SJohn Marino tree field;
5563e4b17023SJohn Marino for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
5564e4b17023SJohn Marino if (TREE_CODE (field) == FIELD_DECL)
5565e4b17023SJohn Marino {
5566e4b17023SJohn Marino omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
5567e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
5568e4b17023SJohn Marino }
5569e4b17023SJohn Marino }
5570e4b17023SJohn Marino break;
5571e4b17023SJohn Marino
5572e4b17023SJohn Marino case POINTER_TYPE:
5573e4b17023SJohn Marino case REFERENCE_TYPE:
5574e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
5575e4b17023SJohn Marino break;
5576e4b17023SJohn Marino
5577e4b17023SJohn Marino default:
5578e4b17023SJohn Marino break;
5579e4b17023SJohn Marino }
5580e4b17023SJohn Marino
5581e4b17023SJohn Marino omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
5582e4b17023SJohn Marino omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
5583e4b17023SJohn Marino lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
5584e4b17023SJohn Marino }
5585e4b17023SJohn Marino
5586e4b17023SJohn Marino /* Add an entry for DECL in the OpenMP context CTX with FLAGS. */
5587e4b17023SJohn Marino
5588e4b17023SJohn Marino static void
omp_add_variable(struct gimplify_omp_ctx * ctx,tree decl,unsigned int flags)5589e4b17023SJohn Marino omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
5590e4b17023SJohn Marino {
5591e4b17023SJohn Marino splay_tree_node n;
5592e4b17023SJohn Marino unsigned int nflags;
5593e4b17023SJohn Marino tree t;
5594e4b17023SJohn Marino
5595e4b17023SJohn Marino if (error_operand_p (decl))
5596e4b17023SJohn Marino return;
5597e4b17023SJohn Marino
5598e4b17023SJohn Marino /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
5599e4b17023SJohn Marino there are constructors involved somewhere. */
5600e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (decl))
5601e4b17023SJohn Marino || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
5602e4b17023SJohn Marino flags |= GOVD_SEEN;
5603e4b17023SJohn Marino
5604e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
5605e4b17023SJohn Marino if (n != NULL)
5606e4b17023SJohn Marino {
5607e4b17023SJohn Marino /* We shouldn't be re-adding the decl with the same data
5608e4b17023SJohn Marino sharing class. */
5609e4b17023SJohn Marino gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
5610e4b17023SJohn Marino /* The only combination of data sharing classes we should see is
5611e4b17023SJohn Marino FIRSTPRIVATE and LASTPRIVATE. */
5612e4b17023SJohn Marino nflags = n->value | flags;
5613e4b17023SJohn Marino gcc_assert ((nflags & GOVD_DATA_SHARE_CLASS)
5614e4b17023SJohn Marino == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE));
5615e4b17023SJohn Marino n->value = nflags;
5616e4b17023SJohn Marino return;
5617e4b17023SJohn Marino }
5618e4b17023SJohn Marino
5619e4b17023SJohn Marino /* When adding a variable-sized variable, we have to handle all sorts
5620e4b17023SJohn Marino of additional bits of data: the pointer replacement variable, and
5621e4b17023SJohn Marino the parameters of the type. */
5622e4b17023SJohn Marino if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
5623e4b17023SJohn Marino {
5624e4b17023SJohn Marino /* Add the pointer replacement variable as PRIVATE if the variable
5625e4b17023SJohn Marino replacement is private, else FIRSTPRIVATE since we'll need the
5626e4b17023SJohn Marino address of the original variable either for SHARED, or for the
5627e4b17023SJohn Marino copy into or out of the context. */
5628e4b17023SJohn Marino if (!(flags & GOVD_LOCAL))
5629e4b17023SJohn Marino {
5630e4b17023SJohn Marino nflags = flags & GOVD_PRIVATE ? GOVD_PRIVATE : GOVD_FIRSTPRIVATE;
5631e4b17023SJohn Marino nflags |= flags & GOVD_SEEN;
5632e4b17023SJohn Marino t = DECL_VALUE_EXPR (decl);
5633e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == INDIRECT_REF);
5634e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
5635e4b17023SJohn Marino gcc_assert (DECL_P (t));
5636e4b17023SJohn Marino omp_add_variable (ctx, t, nflags);
5637e4b17023SJohn Marino }
5638e4b17023SJohn Marino
5639e4b17023SJohn Marino /* Add all of the variable and type parameters (which should have
5640e4b17023SJohn Marino been gimplified to a formal temporary) as FIRSTPRIVATE. */
5641e4b17023SJohn Marino omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
5642e4b17023SJohn Marino omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
5643e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
5644e4b17023SJohn Marino
5645e4b17023SJohn Marino /* The variable-sized variable itself is never SHARED, only some form
5646e4b17023SJohn Marino of PRIVATE. The sharing would take place via the pointer variable
5647e4b17023SJohn Marino which we remapped above. */
5648e4b17023SJohn Marino if (flags & GOVD_SHARED)
5649e4b17023SJohn Marino flags = GOVD_PRIVATE | GOVD_DEBUG_PRIVATE
5650e4b17023SJohn Marino | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
5651e4b17023SJohn Marino
5652e4b17023SJohn Marino /* We're going to make use of the TYPE_SIZE_UNIT at least in the
5653e4b17023SJohn Marino alloca statement we generate for the variable, so make sure it
5654e4b17023SJohn Marino is available. This isn't automatically needed for the SHARED
5655e4b17023SJohn Marino case, since we won't be allocating local storage then.
5656e4b17023SJohn Marino For local variables TYPE_SIZE_UNIT might not be gimplified yet,
5657e4b17023SJohn Marino in this case omp_notice_variable will be called later
5658e4b17023SJohn Marino on when it is gimplified. */
5659e4b17023SJohn Marino else if (! (flags & GOVD_LOCAL)
5660e4b17023SJohn Marino && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
5661e4b17023SJohn Marino omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
5662e4b17023SJohn Marino }
5663e4b17023SJohn Marino else if (lang_hooks.decls.omp_privatize_by_reference (decl))
5664e4b17023SJohn Marino {
5665e4b17023SJohn Marino gcc_assert ((flags & GOVD_LOCAL) == 0);
5666e4b17023SJohn Marino omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
5667e4b17023SJohn Marino
5668e4b17023SJohn Marino /* Similar to the direct variable sized case above, we'll need the
5669e4b17023SJohn Marino size of references being privatized. */
5670e4b17023SJohn Marino if ((flags & GOVD_SHARED) == 0)
5671e4b17023SJohn Marino {
5672e4b17023SJohn Marino t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
5673e4b17023SJohn Marino if (TREE_CODE (t) != INTEGER_CST)
5674e4b17023SJohn Marino omp_notice_variable (ctx, t, true);
5675e4b17023SJohn Marino }
5676e4b17023SJohn Marino }
5677e4b17023SJohn Marino
5678e4b17023SJohn Marino splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
5679e4b17023SJohn Marino }
5680e4b17023SJohn Marino
5681e4b17023SJohn Marino /* Notice a threadprivate variable DECL used in OpenMP context CTX.
5682e4b17023SJohn Marino This just prints out diagnostics about threadprivate variable uses
5683e4b17023SJohn Marino in untied tasks. If DECL2 is non-NULL, prevent this warning
5684e4b17023SJohn Marino on that variable. */
5685e4b17023SJohn Marino
5686e4b17023SJohn Marino static bool
omp_notice_threadprivate_variable(struct gimplify_omp_ctx * ctx,tree decl,tree decl2)5687e4b17023SJohn Marino omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
5688e4b17023SJohn Marino tree decl2)
5689e4b17023SJohn Marino {
5690e4b17023SJohn Marino splay_tree_node n;
5691e4b17023SJohn Marino
5692e4b17023SJohn Marino if (ctx->region_type != ORT_UNTIED_TASK)
5693e4b17023SJohn Marino return false;
5694e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
5695e4b17023SJohn Marino if (n == NULL)
5696e4b17023SJohn Marino {
5697e4b17023SJohn Marino error ("threadprivate variable %qE used in untied task",
5698e4b17023SJohn Marino DECL_NAME (decl));
5699e4b17023SJohn Marino error_at (ctx->location, "enclosing task");
5700e4b17023SJohn Marino splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
5701e4b17023SJohn Marino }
5702e4b17023SJohn Marino if (decl2)
5703e4b17023SJohn Marino splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
5704e4b17023SJohn Marino return false;
5705e4b17023SJohn Marino }
5706e4b17023SJohn Marino
5707e4b17023SJohn Marino /* Record the fact that DECL was used within the OpenMP context CTX.
5708e4b17023SJohn Marino IN_CODE is true when real code uses DECL, and false when we should
5709e4b17023SJohn Marino merely emit default(none) errors. Return true if DECL is going to
5710e4b17023SJohn Marino be remapped and thus DECL shouldn't be gimplified into its
5711e4b17023SJohn Marino DECL_VALUE_EXPR (if any). */
5712e4b17023SJohn Marino
5713e4b17023SJohn Marino static bool
omp_notice_variable(struct gimplify_omp_ctx * ctx,tree decl,bool in_code)5714e4b17023SJohn Marino omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
5715e4b17023SJohn Marino {
5716e4b17023SJohn Marino splay_tree_node n;
5717e4b17023SJohn Marino unsigned flags = in_code ? GOVD_SEEN : 0;
5718e4b17023SJohn Marino bool ret = false, shared;
5719e4b17023SJohn Marino
5720e4b17023SJohn Marino if (error_operand_p (decl))
5721e4b17023SJohn Marino return false;
5722e4b17023SJohn Marino
5723e4b17023SJohn Marino /* Threadprivate variables are predetermined. */
5724e4b17023SJohn Marino if (is_global_var (decl))
5725e4b17023SJohn Marino {
5726e4b17023SJohn Marino if (DECL_THREAD_LOCAL_P (decl))
5727e4b17023SJohn Marino return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
5728e4b17023SJohn Marino
5729e4b17023SJohn Marino if (DECL_HAS_VALUE_EXPR_P (decl))
5730e4b17023SJohn Marino {
5731e4b17023SJohn Marino tree value = get_base_address (DECL_VALUE_EXPR (decl));
5732e4b17023SJohn Marino
5733e4b17023SJohn Marino if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
5734e4b17023SJohn Marino return omp_notice_threadprivate_variable (ctx, decl, value);
5735e4b17023SJohn Marino }
5736e4b17023SJohn Marino }
5737e4b17023SJohn Marino
5738e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
5739e4b17023SJohn Marino if (n == NULL)
5740e4b17023SJohn Marino {
5741e4b17023SJohn Marino enum omp_clause_default_kind default_kind, kind;
5742e4b17023SJohn Marino struct gimplify_omp_ctx *octx;
5743e4b17023SJohn Marino
5744e4b17023SJohn Marino if (ctx->region_type == ORT_WORKSHARE)
5745e4b17023SJohn Marino goto do_outer;
5746e4b17023SJohn Marino
5747e4b17023SJohn Marino /* ??? Some compiler-generated variables (like SAVE_EXPRs) could be
5748e4b17023SJohn Marino remapped firstprivate instead of shared. To some extent this is
5749e4b17023SJohn Marino addressed in omp_firstprivatize_type_sizes, but not effectively. */
5750e4b17023SJohn Marino default_kind = ctx->default_kind;
5751e4b17023SJohn Marino kind = lang_hooks.decls.omp_predetermined_sharing (decl);
5752e4b17023SJohn Marino if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
5753e4b17023SJohn Marino default_kind = kind;
5754e4b17023SJohn Marino
5755e4b17023SJohn Marino switch (default_kind)
5756e4b17023SJohn Marino {
5757e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT_NONE:
5758e4b17023SJohn Marino error ("%qE not specified in enclosing parallel",
5759e4b17023SJohn Marino DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
5760e4b17023SJohn Marino if ((ctx->region_type & ORT_TASK) != 0)
5761e4b17023SJohn Marino error_at (ctx->location, "enclosing task");
5762e4b17023SJohn Marino else
5763e4b17023SJohn Marino error_at (ctx->location, "enclosing parallel");
5764e4b17023SJohn Marino /* FALLTHRU */
5765e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT_SHARED:
5766e4b17023SJohn Marino flags |= GOVD_SHARED;
5767e4b17023SJohn Marino break;
5768e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT_PRIVATE:
5769e4b17023SJohn Marino flags |= GOVD_PRIVATE;
5770e4b17023SJohn Marino break;
5771e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
5772e4b17023SJohn Marino flags |= GOVD_FIRSTPRIVATE;
5773e4b17023SJohn Marino break;
5774e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
5775e4b17023SJohn Marino /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
5776e4b17023SJohn Marino gcc_assert ((ctx->region_type & ORT_TASK) != 0);
5777e4b17023SJohn Marino if (ctx->outer_context)
5778e4b17023SJohn Marino omp_notice_variable (ctx->outer_context, decl, in_code);
5779e4b17023SJohn Marino for (octx = ctx->outer_context; octx; octx = octx->outer_context)
5780e4b17023SJohn Marino {
5781e4b17023SJohn Marino splay_tree_node n2;
5782e4b17023SJohn Marino
5783e4b17023SJohn Marino n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
5784e4b17023SJohn Marino if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
5785e4b17023SJohn Marino {
5786e4b17023SJohn Marino flags |= GOVD_FIRSTPRIVATE;
5787e4b17023SJohn Marino break;
5788e4b17023SJohn Marino }
5789e4b17023SJohn Marino if ((octx->region_type & ORT_PARALLEL) != 0)
5790e4b17023SJohn Marino break;
5791e4b17023SJohn Marino }
5792e4b17023SJohn Marino if (flags & GOVD_FIRSTPRIVATE)
5793e4b17023SJohn Marino break;
5794e4b17023SJohn Marino if (octx == NULL
5795e4b17023SJohn Marino && (TREE_CODE (decl) == PARM_DECL
5796e4b17023SJohn Marino || (!is_global_var (decl)
5797e4b17023SJohn Marino && DECL_CONTEXT (decl) == current_function_decl)))
5798e4b17023SJohn Marino {
5799e4b17023SJohn Marino flags |= GOVD_FIRSTPRIVATE;
5800e4b17023SJohn Marino break;
5801e4b17023SJohn Marino }
5802e4b17023SJohn Marino flags |= GOVD_SHARED;
5803e4b17023SJohn Marino break;
5804e4b17023SJohn Marino default:
5805e4b17023SJohn Marino gcc_unreachable ();
5806e4b17023SJohn Marino }
5807e4b17023SJohn Marino
5808e4b17023SJohn Marino if ((flags & GOVD_PRIVATE)
5809e4b17023SJohn Marino && lang_hooks.decls.omp_private_outer_ref (decl))
5810e4b17023SJohn Marino flags |= GOVD_PRIVATE_OUTER_REF;
5811e4b17023SJohn Marino
5812e4b17023SJohn Marino omp_add_variable (ctx, decl, flags);
5813e4b17023SJohn Marino
5814e4b17023SJohn Marino shared = (flags & GOVD_SHARED) != 0;
5815e4b17023SJohn Marino ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
5816e4b17023SJohn Marino goto do_outer;
5817e4b17023SJohn Marino }
5818e4b17023SJohn Marino
5819e4b17023SJohn Marino if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
5820e4b17023SJohn Marino && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
5821e4b17023SJohn Marino && DECL_SIZE (decl)
5822e4b17023SJohn Marino && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
5823e4b17023SJohn Marino {
5824e4b17023SJohn Marino splay_tree_node n2;
5825e4b17023SJohn Marino tree t = DECL_VALUE_EXPR (decl);
5826e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == INDIRECT_REF);
5827e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
5828e4b17023SJohn Marino gcc_assert (DECL_P (t));
5829e4b17023SJohn Marino n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
5830e4b17023SJohn Marino n2->value |= GOVD_SEEN;
5831e4b17023SJohn Marino }
5832e4b17023SJohn Marino
5833e4b17023SJohn Marino shared = ((flags | n->value) & GOVD_SHARED) != 0;
5834e4b17023SJohn Marino ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
5835e4b17023SJohn Marino
5836e4b17023SJohn Marino /* If nothing changed, there's nothing left to do. */
5837e4b17023SJohn Marino if ((n->value & flags) == flags)
5838e4b17023SJohn Marino return ret;
5839e4b17023SJohn Marino flags |= n->value;
5840e4b17023SJohn Marino n->value = flags;
5841e4b17023SJohn Marino
5842e4b17023SJohn Marino do_outer:
5843e4b17023SJohn Marino /* If the variable is private in the current context, then we don't
5844e4b17023SJohn Marino need to propagate anything to an outer context. */
5845e4b17023SJohn Marino if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
5846e4b17023SJohn Marino return ret;
5847e4b17023SJohn Marino if (ctx->outer_context
5848e4b17023SJohn Marino && omp_notice_variable (ctx->outer_context, decl, in_code))
5849e4b17023SJohn Marino return true;
5850e4b17023SJohn Marino return ret;
5851e4b17023SJohn Marino }
5852e4b17023SJohn Marino
5853e4b17023SJohn Marino /* Verify that DECL is private within CTX. If there's specific information
5854e4b17023SJohn Marino to the contrary in the innermost scope, generate an error. */
5855e4b17023SJohn Marino
5856e4b17023SJohn Marino static bool
omp_is_private(struct gimplify_omp_ctx * ctx,tree decl)5857e4b17023SJohn Marino omp_is_private (struct gimplify_omp_ctx *ctx, tree decl)
5858e4b17023SJohn Marino {
5859e4b17023SJohn Marino splay_tree_node n;
5860e4b17023SJohn Marino
5861e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
5862e4b17023SJohn Marino if (n != NULL)
5863e4b17023SJohn Marino {
5864e4b17023SJohn Marino if (n->value & GOVD_SHARED)
5865e4b17023SJohn Marino {
5866e4b17023SJohn Marino if (ctx == gimplify_omp_ctxp)
5867e4b17023SJohn Marino {
5868e4b17023SJohn Marino error ("iteration variable %qE should be private",
5869e4b17023SJohn Marino DECL_NAME (decl));
5870e4b17023SJohn Marino n->value = GOVD_PRIVATE;
5871e4b17023SJohn Marino return true;
5872e4b17023SJohn Marino }
5873e4b17023SJohn Marino else
5874e4b17023SJohn Marino return false;
5875e4b17023SJohn Marino }
5876e4b17023SJohn Marino else if ((n->value & GOVD_EXPLICIT) != 0
5877e4b17023SJohn Marino && (ctx == gimplify_omp_ctxp
5878e4b17023SJohn Marino || (ctx->region_type == ORT_COMBINED_PARALLEL
5879e4b17023SJohn Marino && gimplify_omp_ctxp->outer_context == ctx)))
5880e4b17023SJohn Marino {
5881e4b17023SJohn Marino if ((n->value & GOVD_FIRSTPRIVATE) != 0)
5882e4b17023SJohn Marino error ("iteration variable %qE should not be firstprivate",
5883e4b17023SJohn Marino DECL_NAME (decl));
5884e4b17023SJohn Marino else if ((n->value & GOVD_REDUCTION) != 0)
5885e4b17023SJohn Marino error ("iteration variable %qE should not be reduction",
5886e4b17023SJohn Marino DECL_NAME (decl));
5887e4b17023SJohn Marino }
5888e4b17023SJohn Marino return (ctx == gimplify_omp_ctxp
5889e4b17023SJohn Marino || (ctx->region_type == ORT_COMBINED_PARALLEL
5890e4b17023SJohn Marino && gimplify_omp_ctxp->outer_context == ctx));
5891e4b17023SJohn Marino }
5892e4b17023SJohn Marino
5893e4b17023SJohn Marino if (ctx->region_type != ORT_WORKSHARE)
5894e4b17023SJohn Marino return false;
5895e4b17023SJohn Marino else if (ctx->outer_context)
5896e4b17023SJohn Marino return omp_is_private (ctx->outer_context, decl);
5897e4b17023SJohn Marino return false;
5898e4b17023SJohn Marino }
5899e4b17023SJohn Marino
5900e4b17023SJohn Marino /* Return true if DECL is private within a parallel region
5901e4b17023SJohn Marino that binds to the current construct's context or in parallel
5902e4b17023SJohn Marino region's REDUCTION clause. */
5903e4b17023SJohn Marino
5904e4b17023SJohn Marino static bool
omp_check_private(struct gimplify_omp_ctx * ctx,tree decl)5905e4b17023SJohn Marino omp_check_private (struct gimplify_omp_ctx *ctx, tree decl)
5906e4b17023SJohn Marino {
5907e4b17023SJohn Marino splay_tree_node n;
5908e4b17023SJohn Marino
5909e4b17023SJohn Marino do
5910e4b17023SJohn Marino {
5911e4b17023SJohn Marino ctx = ctx->outer_context;
5912e4b17023SJohn Marino if (ctx == NULL)
5913e4b17023SJohn Marino return !(is_global_var (decl)
5914e4b17023SJohn Marino /* References might be private, but might be shared too. */
5915e4b17023SJohn Marino || lang_hooks.decls.omp_privatize_by_reference (decl));
5916e4b17023SJohn Marino
5917e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
5918e4b17023SJohn Marino if (n != NULL)
5919e4b17023SJohn Marino return (n->value & GOVD_SHARED) == 0;
5920e4b17023SJohn Marino }
5921e4b17023SJohn Marino while (ctx->region_type == ORT_WORKSHARE);
5922e4b17023SJohn Marino return false;
5923e4b17023SJohn Marino }
5924e4b17023SJohn Marino
5925e4b17023SJohn Marino /* Scan the OpenMP clauses in *LIST_P, installing mappings into a new
5926e4b17023SJohn Marino and previous omp contexts. */
5927e4b17023SJohn Marino
5928e4b17023SJohn Marino static void
gimplify_scan_omp_clauses(tree * list_p,gimple_seq * pre_p,enum omp_region_type region_type)5929e4b17023SJohn Marino gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
5930e4b17023SJohn Marino enum omp_region_type region_type)
5931e4b17023SJohn Marino {
5932e4b17023SJohn Marino struct gimplify_omp_ctx *ctx, *outer_ctx;
5933e4b17023SJohn Marino struct gimplify_ctx gctx;
5934e4b17023SJohn Marino tree c;
5935e4b17023SJohn Marino
5936e4b17023SJohn Marino ctx = new_omp_context (region_type);
5937e4b17023SJohn Marino outer_ctx = ctx->outer_context;
5938e4b17023SJohn Marino
5939e4b17023SJohn Marino while ((c = *list_p) != NULL)
5940e4b17023SJohn Marino {
5941e4b17023SJohn Marino bool remove = false;
5942e4b17023SJohn Marino bool notice_outer = true;
5943e4b17023SJohn Marino const char *check_non_private = NULL;
5944e4b17023SJohn Marino unsigned int flags;
5945e4b17023SJohn Marino tree decl;
5946e4b17023SJohn Marino
5947e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (c))
5948e4b17023SJohn Marino {
5949e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
5950e4b17023SJohn Marino flags = GOVD_PRIVATE | GOVD_EXPLICIT;
5951e4b17023SJohn Marino if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
5952e4b17023SJohn Marino {
5953e4b17023SJohn Marino flags |= GOVD_PRIVATE_OUTER_REF;
5954e4b17023SJohn Marino OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
5955e4b17023SJohn Marino }
5956e4b17023SJohn Marino else
5957e4b17023SJohn Marino notice_outer = false;
5958e4b17023SJohn Marino goto do_add;
5959e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
5960e4b17023SJohn Marino flags = GOVD_SHARED | GOVD_EXPLICIT;
5961e4b17023SJohn Marino goto do_add;
5962e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
5963e4b17023SJohn Marino flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
5964e4b17023SJohn Marino check_non_private = "firstprivate";
5965e4b17023SJohn Marino goto do_add;
5966e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
5967e4b17023SJohn Marino flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
5968e4b17023SJohn Marino check_non_private = "lastprivate";
5969e4b17023SJohn Marino goto do_add;
5970e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
5971e4b17023SJohn Marino flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
5972e4b17023SJohn Marino check_non_private = "reduction";
5973e4b17023SJohn Marino goto do_add;
5974e4b17023SJohn Marino
5975e4b17023SJohn Marino do_add:
5976e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
5977e4b17023SJohn Marino if (error_operand_p (decl))
5978e4b17023SJohn Marino {
5979e4b17023SJohn Marino remove = true;
5980e4b17023SJohn Marino break;
5981e4b17023SJohn Marino }
5982e4b17023SJohn Marino omp_add_variable (ctx, decl, flags);
5983e4b17023SJohn Marino if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5984e4b17023SJohn Marino && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5985e4b17023SJohn Marino {
5986e4b17023SJohn Marino omp_add_variable (ctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
5987e4b17023SJohn Marino GOVD_LOCAL | GOVD_SEEN);
5988e4b17023SJohn Marino gimplify_omp_ctxp = ctx;
5989e4b17023SJohn Marino push_gimplify_context (&gctx);
5990e4b17023SJohn Marino
5991e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = gimple_seq_alloc ();
5992e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = gimple_seq_alloc ();
5993e4b17023SJohn Marino
5994e4b17023SJohn Marino gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
5995e4b17023SJohn Marino &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
5996e4b17023SJohn Marino pop_gimplify_context
5997e4b17023SJohn Marino (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
5998e4b17023SJohn Marino push_gimplify_context (&gctx);
5999e4b17023SJohn Marino gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
6000e4b17023SJohn Marino &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
6001e4b17023SJohn Marino pop_gimplify_context
6002e4b17023SJohn Marino (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
6003e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
6004e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
6005e4b17023SJohn Marino
6006e4b17023SJohn Marino gimplify_omp_ctxp = outer_ctx;
6007e4b17023SJohn Marino }
6008e4b17023SJohn Marino else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6009e4b17023SJohn Marino && OMP_CLAUSE_LASTPRIVATE_STMT (c))
6010e4b17023SJohn Marino {
6011e4b17023SJohn Marino gimplify_omp_ctxp = ctx;
6012e4b17023SJohn Marino push_gimplify_context (&gctx);
6013e4b17023SJohn Marino if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
6014e4b17023SJohn Marino {
6015e4b17023SJohn Marino tree bind = build3 (BIND_EXPR, void_type_node, NULL,
6016e4b17023SJohn Marino NULL, NULL);
6017e4b17023SJohn Marino TREE_SIDE_EFFECTS (bind) = 1;
6018e4b17023SJohn Marino BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
6019e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
6020e4b17023SJohn Marino }
6021e4b17023SJohn Marino gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
6022e4b17023SJohn Marino &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
6023e4b17023SJohn Marino pop_gimplify_context
6024e4b17023SJohn Marino (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
6025e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
6026e4b17023SJohn Marino
6027e4b17023SJohn Marino gimplify_omp_ctxp = outer_ctx;
6028e4b17023SJohn Marino }
6029e4b17023SJohn Marino if (notice_outer)
6030e4b17023SJohn Marino goto do_notice;
6031e4b17023SJohn Marino break;
6032e4b17023SJohn Marino
6033e4b17023SJohn Marino case OMP_CLAUSE_COPYIN:
6034e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE:
6035e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
6036e4b17023SJohn Marino if (error_operand_p (decl))
6037e4b17023SJohn Marino {
6038e4b17023SJohn Marino remove = true;
6039e4b17023SJohn Marino break;
6040e4b17023SJohn Marino }
6041e4b17023SJohn Marino do_notice:
6042e4b17023SJohn Marino if (outer_ctx)
6043e4b17023SJohn Marino omp_notice_variable (outer_ctx, decl, true);
6044e4b17023SJohn Marino if (check_non_private
6045e4b17023SJohn Marino && region_type == ORT_WORKSHARE
6046e4b17023SJohn Marino && omp_check_private (ctx, decl))
6047e4b17023SJohn Marino {
6048e4b17023SJohn Marino error ("%s variable %qE is private in outer context",
6049e4b17023SJohn Marino check_non_private, DECL_NAME (decl));
6050e4b17023SJohn Marino remove = true;
6051e4b17023SJohn Marino }
6052e4b17023SJohn Marino break;
6053e4b17023SJohn Marino
6054e4b17023SJohn Marino case OMP_CLAUSE_FINAL:
6055e4b17023SJohn Marino case OMP_CLAUSE_IF:
6056e4b17023SJohn Marino OMP_CLAUSE_OPERAND (c, 0)
6057e4b17023SJohn Marino = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
6058e4b17023SJohn Marino /* Fall through. */
6059e4b17023SJohn Marino
6060e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE:
6061e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS:
6062e4b17023SJohn Marino if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
6063e4b17023SJohn Marino is_gimple_val, fb_rvalue) == GS_ERROR)
6064e4b17023SJohn Marino remove = true;
6065e4b17023SJohn Marino break;
6066e4b17023SJohn Marino
6067e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT:
6068e4b17023SJohn Marino case OMP_CLAUSE_ORDERED:
6069e4b17023SJohn Marino case OMP_CLAUSE_UNTIED:
6070e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE:
6071e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE:
6072e4b17023SJohn Marino break;
6073e4b17023SJohn Marino
6074e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT:
6075e4b17023SJohn Marino ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
6076e4b17023SJohn Marino break;
6077e4b17023SJohn Marino
6078e4b17023SJohn Marino default:
6079e4b17023SJohn Marino gcc_unreachable ();
6080e4b17023SJohn Marino }
6081e4b17023SJohn Marino
6082e4b17023SJohn Marino if (remove)
6083e4b17023SJohn Marino *list_p = OMP_CLAUSE_CHAIN (c);
6084e4b17023SJohn Marino else
6085e4b17023SJohn Marino list_p = &OMP_CLAUSE_CHAIN (c);
6086e4b17023SJohn Marino }
6087e4b17023SJohn Marino
6088e4b17023SJohn Marino gimplify_omp_ctxp = ctx;
6089e4b17023SJohn Marino }
6090e4b17023SJohn Marino
6091e4b17023SJohn Marino /* For all variables that were not actually used within the context,
6092e4b17023SJohn Marino remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
6093e4b17023SJohn Marino
6094e4b17023SJohn Marino static int
gimplify_adjust_omp_clauses_1(splay_tree_node n,void * data)6095e4b17023SJohn Marino gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
6096e4b17023SJohn Marino {
6097e4b17023SJohn Marino tree *list_p = (tree *) data;
6098e4b17023SJohn Marino tree decl = (tree) n->key;
6099e4b17023SJohn Marino unsigned flags = n->value;
6100e4b17023SJohn Marino enum omp_clause_code code;
6101e4b17023SJohn Marino tree clause;
6102e4b17023SJohn Marino bool private_debug;
6103e4b17023SJohn Marino
6104e4b17023SJohn Marino if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
6105e4b17023SJohn Marino return 0;
6106e4b17023SJohn Marino if ((flags & GOVD_SEEN) == 0)
6107e4b17023SJohn Marino return 0;
6108e4b17023SJohn Marino if (flags & GOVD_DEBUG_PRIVATE)
6109e4b17023SJohn Marino {
6110e4b17023SJohn Marino gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_PRIVATE);
6111e4b17023SJohn Marino private_debug = true;
6112e4b17023SJohn Marino }
6113e4b17023SJohn Marino else
6114e4b17023SJohn Marino private_debug
6115e4b17023SJohn Marino = lang_hooks.decls.omp_private_debug_clause (decl,
6116e4b17023SJohn Marino !!(flags & GOVD_SHARED));
6117e4b17023SJohn Marino if (private_debug)
6118e4b17023SJohn Marino code = OMP_CLAUSE_PRIVATE;
6119e4b17023SJohn Marino else if (flags & GOVD_SHARED)
6120e4b17023SJohn Marino {
6121e4b17023SJohn Marino if (is_global_var (decl))
6122e4b17023SJohn Marino {
6123e4b17023SJohn Marino struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
6124e4b17023SJohn Marino while (ctx != NULL)
6125e4b17023SJohn Marino {
6126e4b17023SJohn Marino splay_tree_node on
6127e4b17023SJohn Marino = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
6128e4b17023SJohn Marino if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
6129e4b17023SJohn Marino | GOVD_PRIVATE | GOVD_REDUCTION)) != 0)
6130e4b17023SJohn Marino break;
6131e4b17023SJohn Marino ctx = ctx->outer_context;
6132e4b17023SJohn Marino }
6133e4b17023SJohn Marino if (ctx == NULL)
6134e4b17023SJohn Marino return 0;
6135e4b17023SJohn Marino }
6136e4b17023SJohn Marino code = OMP_CLAUSE_SHARED;
6137e4b17023SJohn Marino }
6138e4b17023SJohn Marino else if (flags & GOVD_PRIVATE)
6139e4b17023SJohn Marino code = OMP_CLAUSE_PRIVATE;
6140e4b17023SJohn Marino else if (flags & GOVD_FIRSTPRIVATE)
6141e4b17023SJohn Marino code = OMP_CLAUSE_FIRSTPRIVATE;
6142e4b17023SJohn Marino else
6143e4b17023SJohn Marino gcc_unreachable ();
6144e4b17023SJohn Marino
6145e4b17023SJohn Marino clause = build_omp_clause (input_location, code);
6146e4b17023SJohn Marino OMP_CLAUSE_DECL (clause) = decl;
6147e4b17023SJohn Marino OMP_CLAUSE_CHAIN (clause) = *list_p;
6148e4b17023SJohn Marino if (private_debug)
6149e4b17023SJohn Marino OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
6150e4b17023SJohn Marino else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
6151e4b17023SJohn Marino OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
6152e4b17023SJohn Marino *list_p = clause;
6153e4b17023SJohn Marino lang_hooks.decls.omp_finish_clause (clause);
6154e4b17023SJohn Marino
6155e4b17023SJohn Marino return 0;
6156e4b17023SJohn Marino }
6157e4b17023SJohn Marino
6158e4b17023SJohn Marino static void
gimplify_adjust_omp_clauses(tree * list_p)6159e4b17023SJohn Marino gimplify_adjust_omp_clauses (tree *list_p)
6160e4b17023SJohn Marino {
6161e4b17023SJohn Marino struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
6162e4b17023SJohn Marino tree c, decl;
6163e4b17023SJohn Marino
6164e4b17023SJohn Marino while ((c = *list_p) != NULL)
6165e4b17023SJohn Marino {
6166e4b17023SJohn Marino splay_tree_node n;
6167e4b17023SJohn Marino bool remove = false;
6168e4b17023SJohn Marino
6169e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (c))
6170e4b17023SJohn Marino {
6171e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
6172e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
6173e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
6174e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
6175e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
6176e4b17023SJohn Marino remove = !(n->value & GOVD_SEEN);
6177e4b17023SJohn Marino if (! remove)
6178e4b17023SJohn Marino {
6179e4b17023SJohn Marino bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
6180e4b17023SJohn Marino if ((n->value & GOVD_DEBUG_PRIVATE)
6181e4b17023SJohn Marino || lang_hooks.decls.omp_private_debug_clause (decl, shared))
6182e4b17023SJohn Marino {
6183e4b17023SJohn Marino gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
6184e4b17023SJohn Marino || ((n->value & GOVD_DATA_SHARE_CLASS)
6185e4b17023SJohn Marino == GOVD_PRIVATE));
6186e4b17023SJohn Marino OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
6187e4b17023SJohn Marino OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
6188e4b17023SJohn Marino }
6189e4b17023SJohn Marino }
6190e4b17023SJohn Marino break;
6191e4b17023SJohn Marino
6192e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
6193e4b17023SJohn Marino /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
6194e4b17023SJohn Marino accurately reflect the presence of a FIRSTPRIVATE clause. */
6195e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
6196e4b17023SJohn Marino n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
6197e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
6198e4b17023SJohn Marino = (n->value & GOVD_FIRSTPRIVATE) != 0;
6199e4b17023SJohn Marino break;
6200e4b17023SJohn Marino
6201e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
6202e4b17023SJohn Marino case OMP_CLAUSE_COPYIN:
6203e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE:
6204e4b17023SJohn Marino case OMP_CLAUSE_IF:
6205e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS:
6206e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE:
6207e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT:
6208e4b17023SJohn Marino case OMP_CLAUSE_ORDERED:
6209e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT:
6210e4b17023SJohn Marino case OMP_CLAUSE_UNTIED:
6211e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE:
6212e4b17023SJohn Marino case OMP_CLAUSE_FINAL:
6213e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE:
6214e4b17023SJohn Marino break;
6215e4b17023SJohn Marino
6216e4b17023SJohn Marino default:
6217e4b17023SJohn Marino gcc_unreachable ();
6218e4b17023SJohn Marino }
6219e4b17023SJohn Marino
6220e4b17023SJohn Marino if (remove)
6221e4b17023SJohn Marino *list_p = OMP_CLAUSE_CHAIN (c);
6222e4b17023SJohn Marino else
6223e4b17023SJohn Marino list_p = &OMP_CLAUSE_CHAIN (c);
6224e4b17023SJohn Marino }
6225e4b17023SJohn Marino
6226e4b17023SJohn Marino /* Add in any implicit data sharing. */
6227e4b17023SJohn Marino splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, list_p);
6228e4b17023SJohn Marino
6229e4b17023SJohn Marino gimplify_omp_ctxp = ctx->outer_context;
6230e4b17023SJohn Marino delete_omp_context (ctx);
6231e4b17023SJohn Marino }
6232e4b17023SJohn Marino
6233e4b17023SJohn Marino /* Gimplify the contents of an OMP_PARALLEL statement. This involves
6234e4b17023SJohn Marino gimplification of the body, as well as scanning the body for used
6235e4b17023SJohn Marino variables. We need to do this scan now, because variable-sized
6236e4b17023SJohn Marino decls will be decomposed during gimplification. */
6237e4b17023SJohn Marino
6238e4b17023SJohn Marino static void
gimplify_omp_parallel(tree * expr_p,gimple_seq * pre_p)6239e4b17023SJohn Marino gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
6240e4b17023SJohn Marino {
6241e4b17023SJohn Marino tree expr = *expr_p;
6242e4b17023SJohn Marino gimple g;
6243e4b17023SJohn Marino gimple_seq body = NULL;
6244e4b17023SJohn Marino struct gimplify_ctx gctx;
6245e4b17023SJohn Marino
6246e4b17023SJohn Marino gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
6247e4b17023SJohn Marino OMP_PARALLEL_COMBINED (expr)
6248e4b17023SJohn Marino ? ORT_COMBINED_PARALLEL
6249e4b17023SJohn Marino : ORT_PARALLEL);
6250e4b17023SJohn Marino
6251e4b17023SJohn Marino push_gimplify_context (&gctx);
6252e4b17023SJohn Marino
6253e4b17023SJohn Marino g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
6254e4b17023SJohn Marino if (gimple_code (g) == GIMPLE_BIND)
6255e4b17023SJohn Marino pop_gimplify_context (g);
6256e4b17023SJohn Marino else
6257e4b17023SJohn Marino pop_gimplify_context (NULL);
6258e4b17023SJohn Marino
6259e4b17023SJohn Marino gimplify_adjust_omp_clauses (&OMP_PARALLEL_CLAUSES (expr));
6260e4b17023SJohn Marino
6261e4b17023SJohn Marino g = gimple_build_omp_parallel (body,
6262e4b17023SJohn Marino OMP_PARALLEL_CLAUSES (expr),
6263e4b17023SJohn Marino NULL_TREE, NULL_TREE);
6264e4b17023SJohn Marino if (OMP_PARALLEL_COMBINED (expr))
6265e4b17023SJohn Marino gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
6266e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, g);
6267e4b17023SJohn Marino *expr_p = NULL_TREE;
6268e4b17023SJohn Marino }
6269e4b17023SJohn Marino
6270e4b17023SJohn Marino /* Gimplify the contents of an OMP_TASK statement. This involves
6271e4b17023SJohn Marino gimplification of the body, as well as scanning the body for used
6272e4b17023SJohn Marino variables. We need to do this scan now, because variable-sized
6273e4b17023SJohn Marino decls will be decomposed during gimplification. */
6274e4b17023SJohn Marino
6275e4b17023SJohn Marino static void
gimplify_omp_task(tree * expr_p,gimple_seq * pre_p)6276e4b17023SJohn Marino gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
6277e4b17023SJohn Marino {
6278e4b17023SJohn Marino tree expr = *expr_p;
6279e4b17023SJohn Marino gimple g;
6280e4b17023SJohn Marino gimple_seq body = NULL;
6281e4b17023SJohn Marino struct gimplify_ctx gctx;
6282e4b17023SJohn Marino
6283e4b17023SJohn Marino gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
6284e4b17023SJohn Marino find_omp_clause (OMP_TASK_CLAUSES (expr),
6285e4b17023SJohn Marino OMP_CLAUSE_UNTIED)
6286e4b17023SJohn Marino ? ORT_UNTIED_TASK : ORT_TASK);
6287e4b17023SJohn Marino
6288e4b17023SJohn Marino push_gimplify_context (&gctx);
6289e4b17023SJohn Marino
6290e4b17023SJohn Marino g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
6291e4b17023SJohn Marino if (gimple_code (g) == GIMPLE_BIND)
6292e4b17023SJohn Marino pop_gimplify_context (g);
6293e4b17023SJohn Marino else
6294e4b17023SJohn Marino pop_gimplify_context (NULL);
6295e4b17023SJohn Marino
6296e4b17023SJohn Marino gimplify_adjust_omp_clauses (&OMP_TASK_CLAUSES (expr));
6297e4b17023SJohn Marino
6298e4b17023SJohn Marino g = gimple_build_omp_task (body,
6299e4b17023SJohn Marino OMP_TASK_CLAUSES (expr),
6300e4b17023SJohn Marino NULL_TREE, NULL_TREE,
6301e4b17023SJohn Marino NULL_TREE, NULL_TREE, NULL_TREE);
6302e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, g);
6303e4b17023SJohn Marino *expr_p = NULL_TREE;
6304e4b17023SJohn Marino }
6305e4b17023SJohn Marino
6306e4b17023SJohn Marino /* Gimplify the gross structure of an OMP_FOR statement. */
6307e4b17023SJohn Marino
6308e4b17023SJohn Marino static enum gimplify_status
gimplify_omp_for(tree * expr_p,gimple_seq * pre_p)6309e4b17023SJohn Marino gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
6310e4b17023SJohn Marino {
6311e4b17023SJohn Marino tree for_stmt, decl, var, t;
6312e4b17023SJohn Marino enum gimplify_status ret = GS_ALL_DONE;
6313e4b17023SJohn Marino enum gimplify_status tret;
6314e4b17023SJohn Marino gimple gfor;
6315e4b17023SJohn Marino gimple_seq for_body, for_pre_body;
6316e4b17023SJohn Marino int i;
6317e4b17023SJohn Marino
6318e4b17023SJohn Marino for_stmt = *expr_p;
6319e4b17023SJohn Marino
6320e4b17023SJohn Marino gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
6321e4b17023SJohn Marino ORT_WORKSHARE);
6322e4b17023SJohn Marino
6323e4b17023SJohn Marino /* Handle OMP_FOR_INIT. */
6324e4b17023SJohn Marino for_pre_body = NULL;
6325e4b17023SJohn Marino gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
6326e4b17023SJohn Marino OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
6327e4b17023SJohn Marino
6328e4b17023SJohn Marino for_body = gimple_seq_alloc ();
6329e4b17023SJohn Marino gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
6330e4b17023SJohn Marino == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
6331e4b17023SJohn Marino gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
6332e4b17023SJohn Marino == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
6333e4b17023SJohn Marino for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
6334e4b17023SJohn Marino {
6335e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
6336e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
6337e4b17023SJohn Marino decl = TREE_OPERAND (t, 0);
6338e4b17023SJohn Marino gcc_assert (DECL_P (decl));
6339e4b17023SJohn Marino gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
6340e4b17023SJohn Marino || POINTER_TYPE_P (TREE_TYPE (decl)));
6341e4b17023SJohn Marino
6342e4b17023SJohn Marino /* Make sure the iteration variable is private. */
6343e4b17023SJohn Marino if (omp_is_private (gimplify_omp_ctxp, decl))
6344e4b17023SJohn Marino omp_notice_variable (gimplify_omp_ctxp, decl, true);
6345e4b17023SJohn Marino else
6346e4b17023SJohn Marino omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
6347e4b17023SJohn Marino
6348e4b17023SJohn Marino /* If DECL is not a gimple register, create a temporary variable to act
6349e4b17023SJohn Marino as an iteration counter. This is valid, since DECL cannot be
6350e4b17023SJohn Marino modified in the body of the loop. */
6351e4b17023SJohn Marino if (!is_gimple_reg (decl))
6352e4b17023SJohn Marino {
6353e4b17023SJohn Marino var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
6354e4b17023SJohn Marino TREE_OPERAND (t, 0) = var;
6355e4b17023SJohn Marino
6356e4b17023SJohn Marino gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
6357e4b17023SJohn Marino
6358e4b17023SJohn Marino omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
6359e4b17023SJohn Marino }
6360e4b17023SJohn Marino else
6361e4b17023SJohn Marino var = decl;
6362e4b17023SJohn Marino
6363e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
6364e4b17023SJohn Marino is_gimple_val, fb_rvalue);
6365e4b17023SJohn Marino ret = MIN (ret, tret);
6366e4b17023SJohn Marino if (ret == GS_ERROR)
6367e4b17023SJohn Marino return ret;
6368e4b17023SJohn Marino
6369e4b17023SJohn Marino /* Handle OMP_FOR_COND. */
6370e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
6371e4b17023SJohn Marino gcc_assert (COMPARISON_CLASS_P (t));
6372e4b17023SJohn Marino gcc_assert (TREE_OPERAND (t, 0) == decl);
6373e4b17023SJohn Marino
6374e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
6375e4b17023SJohn Marino is_gimple_val, fb_rvalue);
6376e4b17023SJohn Marino ret = MIN (ret, tret);
6377e4b17023SJohn Marino
6378e4b17023SJohn Marino /* Handle OMP_FOR_INCR. */
6379e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
6380e4b17023SJohn Marino switch (TREE_CODE (t))
6381e4b17023SJohn Marino {
6382e4b17023SJohn Marino case PREINCREMENT_EXPR:
6383e4b17023SJohn Marino case POSTINCREMENT_EXPR:
6384e4b17023SJohn Marino t = build_int_cst (TREE_TYPE (decl), 1);
6385e4b17023SJohn Marino t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
6386e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
6387e4b17023SJohn Marino TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
6388e4b17023SJohn Marino break;
6389e4b17023SJohn Marino
6390e4b17023SJohn Marino case PREDECREMENT_EXPR:
6391e4b17023SJohn Marino case POSTDECREMENT_EXPR:
6392e4b17023SJohn Marino t = build_int_cst (TREE_TYPE (decl), -1);
6393e4b17023SJohn Marino t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
6394e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
6395e4b17023SJohn Marino TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
6396e4b17023SJohn Marino break;
6397e4b17023SJohn Marino
6398e4b17023SJohn Marino case MODIFY_EXPR:
6399e4b17023SJohn Marino gcc_assert (TREE_OPERAND (t, 0) == decl);
6400e4b17023SJohn Marino TREE_OPERAND (t, 0) = var;
6401e4b17023SJohn Marino
6402e4b17023SJohn Marino t = TREE_OPERAND (t, 1);
6403e4b17023SJohn Marino switch (TREE_CODE (t))
6404e4b17023SJohn Marino {
6405e4b17023SJohn Marino case PLUS_EXPR:
6406e4b17023SJohn Marino if (TREE_OPERAND (t, 1) == decl)
6407e4b17023SJohn Marino {
6408e4b17023SJohn Marino TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
6409e4b17023SJohn Marino TREE_OPERAND (t, 0) = var;
6410e4b17023SJohn Marino break;
6411e4b17023SJohn Marino }
6412e4b17023SJohn Marino
6413e4b17023SJohn Marino /* Fallthru. */
6414e4b17023SJohn Marino case MINUS_EXPR:
6415e4b17023SJohn Marino case POINTER_PLUS_EXPR:
6416e4b17023SJohn Marino gcc_assert (TREE_OPERAND (t, 0) == decl);
6417e4b17023SJohn Marino TREE_OPERAND (t, 0) = var;
6418e4b17023SJohn Marino break;
6419e4b17023SJohn Marino default:
6420e4b17023SJohn Marino gcc_unreachable ();
6421e4b17023SJohn Marino }
6422e4b17023SJohn Marino
6423e4b17023SJohn Marino tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
6424e4b17023SJohn Marino is_gimple_val, fb_rvalue);
6425e4b17023SJohn Marino ret = MIN (ret, tret);
6426e4b17023SJohn Marino break;
6427e4b17023SJohn Marino
6428e4b17023SJohn Marino default:
6429e4b17023SJohn Marino gcc_unreachable ();
6430e4b17023SJohn Marino }
6431e4b17023SJohn Marino
6432e4b17023SJohn Marino if (var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
6433e4b17023SJohn Marino {
6434e4b17023SJohn Marino tree c;
6435e4b17023SJohn Marino for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
6436e4b17023SJohn Marino if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6437e4b17023SJohn Marino && OMP_CLAUSE_DECL (c) == decl
6438e4b17023SJohn Marino && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
6439e4b17023SJohn Marino {
6440e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
6441e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
6442e4b17023SJohn Marino gcc_assert (TREE_OPERAND (t, 0) == var);
6443e4b17023SJohn Marino t = TREE_OPERAND (t, 1);
6444e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == PLUS_EXPR
6445e4b17023SJohn Marino || TREE_CODE (t) == MINUS_EXPR
6446e4b17023SJohn Marino || TREE_CODE (t) == POINTER_PLUS_EXPR);
6447e4b17023SJohn Marino gcc_assert (TREE_OPERAND (t, 0) == var);
6448e4b17023SJohn Marino t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl,
6449e4b17023SJohn Marino TREE_OPERAND (t, 1));
6450e4b17023SJohn Marino gimplify_assign (decl, t,
6451e4b17023SJohn Marino &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
6452e4b17023SJohn Marino }
6453e4b17023SJohn Marino }
6454e4b17023SJohn Marino }
6455e4b17023SJohn Marino
6456e4b17023SJohn Marino gimplify_and_add (OMP_FOR_BODY (for_stmt), &for_body);
6457e4b17023SJohn Marino
6458e4b17023SJohn Marino gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
6459e4b17023SJohn Marino
6460e4b17023SJohn Marino gfor = gimple_build_omp_for (for_body, OMP_FOR_CLAUSES (for_stmt),
6461e4b17023SJohn Marino TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
6462e4b17023SJohn Marino for_pre_body);
6463e4b17023SJohn Marino
6464e4b17023SJohn Marino for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
6465e4b17023SJohn Marino {
6466e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
6467e4b17023SJohn Marino gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
6468e4b17023SJohn Marino gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
6469e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
6470e4b17023SJohn Marino gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
6471e4b17023SJohn Marino gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
6472e4b17023SJohn Marino t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
6473e4b17023SJohn Marino gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
6474e4b17023SJohn Marino }
6475e4b17023SJohn Marino
6476e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, gfor);
6477e4b17023SJohn Marino return ret == GS_ALL_DONE ? GS_ALL_DONE : GS_ERROR;
6478e4b17023SJohn Marino }
6479e4b17023SJohn Marino
6480e4b17023SJohn Marino /* Gimplify the gross structure of other OpenMP worksharing constructs.
6481e4b17023SJohn Marino In particular, OMP_SECTIONS and OMP_SINGLE. */
6482e4b17023SJohn Marino
6483e4b17023SJohn Marino static void
gimplify_omp_workshare(tree * expr_p,gimple_seq * pre_p)6484e4b17023SJohn Marino gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
6485e4b17023SJohn Marino {
6486e4b17023SJohn Marino tree expr = *expr_p;
6487e4b17023SJohn Marino gimple stmt;
6488e4b17023SJohn Marino gimple_seq body = NULL;
6489e4b17023SJohn Marino
6490e4b17023SJohn Marino gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ORT_WORKSHARE);
6491e4b17023SJohn Marino gimplify_and_add (OMP_BODY (expr), &body);
6492e4b17023SJohn Marino gimplify_adjust_omp_clauses (&OMP_CLAUSES (expr));
6493e4b17023SJohn Marino
6494e4b17023SJohn Marino if (TREE_CODE (expr) == OMP_SECTIONS)
6495e4b17023SJohn Marino stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
6496e4b17023SJohn Marino else if (TREE_CODE (expr) == OMP_SINGLE)
6497e4b17023SJohn Marino stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
6498e4b17023SJohn Marino else
6499e4b17023SJohn Marino gcc_unreachable ();
6500e4b17023SJohn Marino
6501e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, stmt);
6502e4b17023SJohn Marino }
6503e4b17023SJohn Marino
6504e4b17023SJohn Marino /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
6505e4b17023SJohn Marino stabilized the lhs of the atomic operation as *ADDR. Return true if
6506e4b17023SJohn Marino EXPR is this stabilized form. */
6507e4b17023SJohn Marino
6508e4b17023SJohn Marino static bool
goa_lhs_expr_p(tree expr,tree addr)6509e4b17023SJohn Marino goa_lhs_expr_p (tree expr, tree addr)
6510e4b17023SJohn Marino {
6511e4b17023SJohn Marino /* Also include casts to other type variants. The C front end is fond
6512e4b17023SJohn Marino of adding these for e.g. volatile variables. This is like
6513e4b17023SJohn Marino STRIP_TYPE_NOPS but includes the main variant lookup. */
6514e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (expr);
6515e4b17023SJohn Marino
6516e4b17023SJohn Marino if (TREE_CODE (expr) == INDIRECT_REF)
6517e4b17023SJohn Marino {
6518e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
6519e4b17023SJohn Marino while (expr != addr
6520e4b17023SJohn Marino && (CONVERT_EXPR_P (expr)
6521e4b17023SJohn Marino || TREE_CODE (expr) == NON_LVALUE_EXPR)
6522e4b17023SJohn Marino && TREE_CODE (expr) == TREE_CODE (addr)
6523e4b17023SJohn Marino && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
6524e4b17023SJohn Marino {
6525e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
6526e4b17023SJohn Marino addr = TREE_OPERAND (addr, 0);
6527e4b17023SJohn Marino }
6528e4b17023SJohn Marino if (expr == addr)
6529e4b17023SJohn Marino return true;
6530e4b17023SJohn Marino return (TREE_CODE (addr) == ADDR_EXPR
6531e4b17023SJohn Marino && TREE_CODE (expr) == ADDR_EXPR
6532e4b17023SJohn Marino && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
6533e4b17023SJohn Marino }
6534e4b17023SJohn Marino if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
6535e4b17023SJohn Marino return true;
6536e4b17023SJohn Marino return false;
6537e4b17023SJohn Marino }
6538e4b17023SJohn Marino
6539e4b17023SJohn Marino /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
6540e4b17023SJohn Marino expression does not involve the lhs, evaluate it into a temporary.
6541e4b17023SJohn Marino Return 1 if the lhs appeared as a subexpression, 0 if it did not,
6542e4b17023SJohn Marino or -1 if an error was encountered. */
6543e4b17023SJohn Marino
6544e4b17023SJohn Marino static int
goa_stabilize_expr(tree * expr_p,gimple_seq * pre_p,tree lhs_addr,tree lhs_var)6545e4b17023SJohn Marino goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
6546e4b17023SJohn Marino tree lhs_var)
6547e4b17023SJohn Marino {
6548e4b17023SJohn Marino tree expr = *expr_p;
6549e4b17023SJohn Marino int saw_lhs;
6550e4b17023SJohn Marino
6551e4b17023SJohn Marino if (goa_lhs_expr_p (expr, lhs_addr))
6552e4b17023SJohn Marino {
6553e4b17023SJohn Marino *expr_p = lhs_var;
6554e4b17023SJohn Marino return 1;
6555e4b17023SJohn Marino }
6556e4b17023SJohn Marino if (is_gimple_val (expr))
6557e4b17023SJohn Marino return 0;
6558e4b17023SJohn Marino
6559e4b17023SJohn Marino saw_lhs = 0;
6560e4b17023SJohn Marino switch (TREE_CODE_CLASS (TREE_CODE (expr)))
6561e4b17023SJohn Marino {
6562e4b17023SJohn Marino case tcc_binary:
6563e4b17023SJohn Marino case tcc_comparison:
6564e4b17023SJohn Marino saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
6565e4b17023SJohn Marino lhs_var);
6566e4b17023SJohn Marino case tcc_unary:
6567e4b17023SJohn Marino saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
6568e4b17023SJohn Marino lhs_var);
6569e4b17023SJohn Marino break;
6570e4b17023SJohn Marino case tcc_expression:
6571e4b17023SJohn Marino switch (TREE_CODE (expr))
6572e4b17023SJohn Marino {
6573e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
6574e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
6575e4b17023SJohn Marino case TRUTH_AND_EXPR:
6576e4b17023SJohn Marino case TRUTH_OR_EXPR:
6577e4b17023SJohn Marino case TRUTH_XOR_EXPR:
6578e4b17023SJohn Marino saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
6579e4b17023SJohn Marino lhs_addr, lhs_var);
6580e4b17023SJohn Marino case TRUTH_NOT_EXPR:
6581e4b17023SJohn Marino saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
6582e4b17023SJohn Marino lhs_addr, lhs_var);
6583e4b17023SJohn Marino break;
6584e4b17023SJohn Marino case COMPOUND_EXPR:
6585e4b17023SJohn Marino /* Break out any preevaluations from cp_build_modify_expr. */
6586e4b17023SJohn Marino for (; TREE_CODE (expr) == COMPOUND_EXPR;
6587e4b17023SJohn Marino expr = TREE_OPERAND (expr, 1))
6588e4b17023SJohn Marino gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
6589e4b17023SJohn Marino *expr_p = expr;
6590e4b17023SJohn Marino return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
6591e4b17023SJohn Marino default:
6592e4b17023SJohn Marino break;
6593e4b17023SJohn Marino }
6594e4b17023SJohn Marino break;
6595e4b17023SJohn Marino default:
6596e4b17023SJohn Marino break;
6597e4b17023SJohn Marino }
6598e4b17023SJohn Marino
6599e4b17023SJohn Marino if (saw_lhs == 0)
6600e4b17023SJohn Marino {
6601e4b17023SJohn Marino enum gimplify_status gs;
6602e4b17023SJohn Marino gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
6603e4b17023SJohn Marino if (gs != GS_ALL_DONE)
6604e4b17023SJohn Marino saw_lhs = -1;
6605e4b17023SJohn Marino }
6606e4b17023SJohn Marino
6607e4b17023SJohn Marino return saw_lhs;
6608e4b17023SJohn Marino }
6609e4b17023SJohn Marino
6610e4b17023SJohn Marino /* Gimplify an OMP_ATOMIC statement. */
6611e4b17023SJohn Marino
6612e4b17023SJohn Marino static enum gimplify_status
gimplify_omp_atomic(tree * expr_p,gimple_seq * pre_p)6613e4b17023SJohn Marino gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
6614e4b17023SJohn Marino {
6615e4b17023SJohn Marino tree addr = TREE_OPERAND (*expr_p, 0);
6616e4b17023SJohn Marino tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
6617e4b17023SJohn Marino ? NULL : TREE_OPERAND (*expr_p, 1);
6618e4b17023SJohn Marino tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
6619e4b17023SJohn Marino tree tmp_load;
6620e4b17023SJohn Marino gimple loadstmt, storestmt;
6621e4b17023SJohn Marino
6622e4b17023SJohn Marino tmp_load = create_tmp_reg (type, NULL);
6623e4b17023SJohn Marino if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
6624e4b17023SJohn Marino return GS_ERROR;
6625e4b17023SJohn Marino
6626e4b17023SJohn Marino if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
6627e4b17023SJohn Marino != GS_ALL_DONE)
6628e4b17023SJohn Marino return GS_ERROR;
6629e4b17023SJohn Marino
6630e4b17023SJohn Marino loadstmt = gimple_build_omp_atomic_load (tmp_load, addr);
6631e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, loadstmt);
6632e4b17023SJohn Marino if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
6633e4b17023SJohn Marino != GS_ALL_DONE)
6634e4b17023SJohn Marino return GS_ERROR;
6635e4b17023SJohn Marino
6636e4b17023SJohn Marino if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
6637e4b17023SJohn Marino rhs = tmp_load;
6638e4b17023SJohn Marino storestmt = gimple_build_omp_atomic_store (rhs);
6639e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, storestmt);
6640e4b17023SJohn Marino switch (TREE_CODE (*expr_p))
6641e4b17023SJohn Marino {
6642e4b17023SJohn Marino case OMP_ATOMIC_READ:
6643e4b17023SJohn Marino case OMP_ATOMIC_CAPTURE_OLD:
6644e4b17023SJohn Marino *expr_p = tmp_load;
6645e4b17023SJohn Marino gimple_omp_atomic_set_need_value (loadstmt);
6646e4b17023SJohn Marino break;
6647e4b17023SJohn Marino case OMP_ATOMIC_CAPTURE_NEW:
6648e4b17023SJohn Marino *expr_p = rhs;
6649e4b17023SJohn Marino gimple_omp_atomic_set_need_value (storestmt);
6650e4b17023SJohn Marino break;
6651e4b17023SJohn Marino default:
6652e4b17023SJohn Marino *expr_p = NULL;
6653e4b17023SJohn Marino break;
6654e4b17023SJohn Marino }
6655e4b17023SJohn Marino
6656e4b17023SJohn Marino return GS_ALL_DONE;
6657e4b17023SJohn Marino }
6658e4b17023SJohn Marino
6659e4b17023SJohn Marino /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
6660e4b17023SJohn Marino body, and adding some EH bits. */
6661e4b17023SJohn Marino
6662e4b17023SJohn Marino static enum gimplify_status
gimplify_transaction(tree * expr_p,gimple_seq * pre_p)6663e4b17023SJohn Marino gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
6664e4b17023SJohn Marino {
6665e4b17023SJohn Marino tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
6666e4b17023SJohn Marino gimple g;
6667e4b17023SJohn Marino gimple_seq body = NULL;
6668e4b17023SJohn Marino struct gimplify_ctx gctx;
6669e4b17023SJohn Marino int subcode = 0;
6670e4b17023SJohn Marino
6671e4b17023SJohn Marino /* Wrap the transaction body in a BIND_EXPR so we have a context
6672e4b17023SJohn Marino where to put decls for OpenMP. */
6673e4b17023SJohn Marino if (TREE_CODE (tbody) != BIND_EXPR)
6674e4b17023SJohn Marino {
6675e4b17023SJohn Marino tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
6676e4b17023SJohn Marino TREE_SIDE_EFFECTS (bind) = 1;
6677e4b17023SJohn Marino SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
6678e4b17023SJohn Marino TRANSACTION_EXPR_BODY (expr) = bind;
6679e4b17023SJohn Marino }
6680e4b17023SJohn Marino
6681e4b17023SJohn Marino push_gimplify_context (&gctx);
6682e4b17023SJohn Marino temp = voidify_wrapper_expr (*expr_p, NULL);
6683e4b17023SJohn Marino
6684e4b17023SJohn Marino g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
6685e4b17023SJohn Marino pop_gimplify_context (g);
6686e4b17023SJohn Marino
6687e4b17023SJohn Marino g = gimple_build_transaction (body, NULL);
6688e4b17023SJohn Marino if (TRANSACTION_EXPR_OUTER (expr))
6689e4b17023SJohn Marino subcode = GTMA_IS_OUTER;
6690e4b17023SJohn Marino else if (TRANSACTION_EXPR_RELAXED (expr))
6691e4b17023SJohn Marino subcode = GTMA_IS_RELAXED;
6692e4b17023SJohn Marino gimple_transaction_set_subcode (g, subcode);
6693e4b17023SJohn Marino
6694e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, g);
6695e4b17023SJohn Marino
6696e4b17023SJohn Marino if (temp)
6697e4b17023SJohn Marino {
6698e4b17023SJohn Marino *expr_p = temp;
6699e4b17023SJohn Marino return GS_OK;
6700e4b17023SJohn Marino }
6701e4b17023SJohn Marino
6702e4b17023SJohn Marino *expr_p = NULL_TREE;
6703e4b17023SJohn Marino return GS_ALL_DONE;
6704e4b17023SJohn Marino }
6705e4b17023SJohn Marino
6706e4b17023SJohn Marino /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
6707e4b17023SJohn Marino expression produces a value to be used as an operand inside a GIMPLE
6708e4b17023SJohn Marino statement, the value will be stored back in *EXPR_P. This value will
6709e4b17023SJohn Marino be a tree of class tcc_declaration, tcc_constant, tcc_reference or
6710e4b17023SJohn Marino an SSA_NAME. The corresponding sequence of GIMPLE statements is
6711e4b17023SJohn Marino emitted in PRE_P and POST_P.
6712e4b17023SJohn Marino
6713e4b17023SJohn Marino Additionally, this process may overwrite parts of the input
6714e4b17023SJohn Marino expression during gimplification. Ideally, it should be
6715e4b17023SJohn Marino possible to do non-destructive gimplification.
6716e4b17023SJohn Marino
6717e4b17023SJohn Marino EXPR_P points to the GENERIC expression to convert to GIMPLE. If
6718e4b17023SJohn Marino the expression needs to evaluate to a value to be used as
6719e4b17023SJohn Marino an operand in a GIMPLE statement, this value will be stored in
6720e4b17023SJohn Marino *EXPR_P on exit. This happens when the caller specifies one
6721e4b17023SJohn Marino of fb_lvalue or fb_rvalue fallback flags.
6722e4b17023SJohn Marino
6723e4b17023SJohn Marino PRE_P will contain the sequence of GIMPLE statements corresponding
6724e4b17023SJohn Marino to the evaluation of EXPR and all the side-effects that must
6725e4b17023SJohn Marino be executed before the main expression. On exit, the last
6726e4b17023SJohn Marino statement of PRE_P is the core statement being gimplified. For
6727e4b17023SJohn Marino instance, when gimplifying 'if (++a)' the last statement in
6728e4b17023SJohn Marino PRE_P will be 'if (t.1)' where t.1 is the result of
6729e4b17023SJohn Marino pre-incrementing 'a'.
6730e4b17023SJohn Marino
6731e4b17023SJohn Marino POST_P will contain the sequence of GIMPLE statements corresponding
6732e4b17023SJohn Marino to the evaluation of all the side-effects that must be executed
6733e4b17023SJohn Marino after the main expression. If this is NULL, the post
6734e4b17023SJohn Marino side-effects are stored at the end of PRE_P.
6735e4b17023SJohn Marino
6736e4b17023SJohn Marino The reason why the output is split in two is to handle post
6737e4b17023SJohn Marino side-effects explicitly. In some cases, an expression may have
6738e4b17023SJohn Marino inner and outer post side-effects which need to be emitted in
6739e4b17023SJohn Marino an order different from the one given by the recursive
6740e4b17023SJohn Marino traversal. For instance, for the expression (*p--)++ the post
6741e4b17023SJohn Marino side-effects of '--' must actually occur *after* the post
6742e4b17023SJohn Marino side-effects of '++'. However, gimplification will first visit
6743e4b17023SJohn Marino the inner expression, so if a separate POST sequence was not
6744e4b17023SJohn Marino used, the resulting sequence would be:
6745e4b17023SJohn Marino
6746e4b17023SJohn Marino 1 t.1 = *p
6747e4b17023SJohn Marino 2 p = p - 1
6748e4b17023SJohn Marino 3 t.2 = t.1 + 1
6749e4b17023SJohn Marino 4 *p = t.2
6750e4b17023SJohn Marino
6751e4b17023SJohn Marino However, the post-decrement operation in line #2 must not be
6752e4b17023SJohn Marino evaluated until after the store to *p at line #4, so the
6753e4b17023SJohn Marino correct sequence should be:
6754e4b17023SJohn Marino
6755e4b17023SJohn Marino 1 t.1 = *p
6756e4b17023SJohn Marino 2 t.2 = t.1 + 1
6757e4b17023SJohn Marino 3 *p = t.2
6758e4b17023SJohn Marino 4 p = p - 1
6759e4b17023SJohn Marino
6760e4b17023SJohn Marino So, by specifying a separate post queue, it is possible
6761e4b17023SJohn Marino to emit the post side-effects in the correct order.
6762e4b17023SJohn Marino If POST_P is NULL, an internal queue will be used. Before
6763e4b17023SJohn Marino returning to the caller, the sequence POST_P is appended to
6764e4b17023SJohn Marino the main output sequence PRE_P.
6765e4b17023SJohn Marino
6766e4b17023SJohn Marino GIMPLE_TEST_F points to a function that takes a tree T and
6767e4b17023SJohn Marino returns nonzero if T is in the GIMPLE form requested by the
6768e4b17023SJohn Marino caller. The GIMPLE predicates are in gimple.c.
6769e4b17023SJohn Marino
6770e4b17023SJohn Marino FALLBACK tells the function what sort of a temporary we want if
6771e4b17023SJohn Marino gimplification cannot produce an expression that complies with
6772e4b17023SJohn Marino GIMPLE_TEST_F.
6773e4b17023SJohn Marino
6774e4b17023SJohn Marino fb_none means that no temporary should be generated
6775e4b17023SJohn Marino fb_rvalue means that an rvalue is OK to generate
6776e4b17023SJohn Marino fb_lvalue means that an lvalue is OK to generate
6777e4b17023SJohn Marino fb_either means that either is OK, but an lvalue is preferable.
6778e4b17023SJohn Marino fb_mayfail means that gimplification may fail (in which case
6779e4b17023SJohn Marino GS_ERROR will be returned)
6780e4b17023SJohn Marino
6781e4b17023SJohn Marino The return value is either GS_ERROR or GS_ALL_DONE, since this
6782e4b17023SJohn Marino function iterates until EXPR is completely gimplified or an error
6783e4b17023SJohn Marino occurs. */
6784e4b17023SJohn Marino
6785e4b17023SJohn Marino enum gimplify_status
gimplify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p,bool (* gimple_test_f)(tree),fallback_t fallback)6786e4b17023SJohn Marino gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6787e4b17023SJohn Marino bool (*gimple_test_f) (tree), fallback_t fallback)
6788e4b17023SJohn Marino {
6789e4b17023SJohn Marino tree tmp;
6790e4b17023SJohn Marino gimple_seq internal_pre = NULL;
6791e4b17023SJohn Marino gimple_seq internal_post = NULL;
6792e4b17023SJohn Marino tree save_expr;
6793e4b17023SJohn Marino bool is_statement;
6794e4b17023SJohn Marino location_t saved_location;
6795e4b17023SJohn Marino enum gimplify_status ret;
6796e4b17023SJohn Marino gimple_stmt_iterator pre_last_gsi, post_last_gsi;
6797e4b17023SJohn Marino
6798e4b17023SJohn Marino save_expr = *expr_p;
6799e4b17023SJohn Marino if (save_expr == NULL_TREE)
6800e4b17023SJohn Marino return GS_ALL_DONE;
6801e4b17023SJohn Marino
6802e4b17023SJohn Marino /* If we are gimplifying a top-level statement, PRE_P must be valid. */
6803e4b17023SJohn Marino is_statement = gimple_test_f == is_gimple_stmt;
6804e4b17023SJohn Marino if (is_statement)
6805e4b17023SJohn Marino gcc_assert (pre_p);
6806e4b17023SJohn Marino
6807e4b17023SJohn Marino /* Consistency checks. */
6808e4b17023SJohn Marino if (gimple_test_f == is_gimple_reg)
6809e4b17023SJohn Marino gcc_assert (fallback & (fb_rvalue | fb_lvalue));
6810e4b17023SJohn Marino else if (gimple_test_f == is_gimple_val
6811e4b17023SJohn Marino || gimple_test_f == is_gimple_call_addr
6812e4b17023SJohn Marino || gimple_test_f == is_gimple_condexpr
6813e4b17023SJohn Marino || gimple_test_f == is_gimple_mem_rhs
6814e4b17023SJohn Marino || gimple_test_f == is_gimple_mem_rhs_or_call
6815e4b17023SJohn Marino || gimple_test_f == is_gimple_reg_rhs
6816e4b17023SJohn Marino || gimple_test_f == is_gimple_reg_rhs_or_call
6817e4b17023SJohn Marino || gimple_test_f == is_gimple_asm_val
6818e4b17023SJohn Marino || gimple_test_f == is_gimple_mem_ref_addr)
6819e4b17023SJohn Marino gcc_assert (fallback & fb_rvalue);
6820e4b17023SJohn Marino else if (gimple_test_f == is_gimple_min_lval
6821e4b17023SJohn Marino || gimple_test_f == is_gimple_lvalue)
6822e4b17023SJohn Marino gcc_assert (fallback & fb_lvalue);
6823e4b17023SJohn Marino else if (gimple_test_f == is_gimple_addressable)
6824e4b17023SJohn Marino gcc_assert (fallback & fb_either);
6825e4b17023SJohn Marino else if (gimple_test_f == is_gimple_stmt)
6826e4b17023SJohn Marino gcc_assert (fallback == fb_none);
6827e4b17023SJohn Marino else
6828e4b17023SJohn Marino {
6829e4b17023SJohn Marino /* We should have recognized the GIMPLE_TEST_F predicate to
6830e4b17023SJohn Marino know what kind of fallback to use in case a temporary is
6831e4b17023SJohn Marino needed to hold the value or address of *EXPR_P. */
6832e4b17023SJohn Marino gcc_unreachable ();
6833e4b17023SJohn Marino }
6834e4b17023SJohn Marino
6835e4b17023SJohn Marino /* We used to check the predicate here and return immediately if it
6836e4b17023SJohn Marino succeeds. This is wrong; the design is for gimplification to be
6837e4b17023SJohn Marino idempotent, and for the predicates to only test for valid forms, not
6838e4b17023SJohn Marino whether they are fully simplified. */
6839e4b17023SJohn Marino if (pre_p == NULL)
6840e4b17023SJohn Marino pre_p = &internal_pre;
6841e4b17023SJohn Marino
6842e4b17023SJohn Marino if (post_p == NULL)
6843e4b17023SJohn Marino post_p = &internal_post;
6844e4b17023SJohn Marino
6845e4b17023SJohn Marino /* Remember the last statements added to PRE_P and POST_P. Every
6846e4b17023SJohn Marino new statement added by the gimplification helpers needs to be
6847e4b17023SJohn Marino annotated with location information. To centralize the
6848e4b17023SJohn Marino responsibility, we remember the last statement that had been
6849e4b17023SJohn Marino added to both queues before gimplifying *EXPR_P. If
6850e4b17023SJohn Marino gimplification produces new statements in PRE_P and POST_P, those
6851e4b17023SJohn Marino statements will be annotated with the same location information
6852e4b17023SJohn Marino as *EXPR_P. */
6853e4b17023SJohn Marino pre_last_gsi = gsi_last (*pre_p);
6854e4b17023SJohn Marino post_last_gsi = gsi_last (*post_p);
6855e4b17023SJohn Marino
6856e4b17023SJohn Marino saved_location = input_location;
6857e4b17023SJohn Marino if (save_expr != error_mark_node
6858e4b17023SJohn Marino && EXPR_HAS_LOCATION (*expr_p))
6859e4b17023SJohn Marino input_location = EXPR_LOCATION (*expr_p);
6860e4b17023SJohn Marino
6861e4b17023SJohn Marino /* Loop over the specific gimplifiers until the toplevel node
6862e4b17023SJohn Marino remains the same. */
6863e4b17023SJohn Marino do
6864e4b17023SJohn Marino {
6865e4b17023SJohn Marino /* Strip away as many useless type conversions as possible
6866e4b17023SJohn Marino at the toplevel. */
6867e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (*expr_p);
6868e4b17023SJohn Marino
6869e4b17023SJohn Marino /* Remember the expr. */
6870e4b17023SJohn Marino save_expr = *expr_p;
6871e4b17023SJohn Marino
6872e4b17023SJohn Marino /* Die, die, die, my darling. */
6873e4b17023SJohn Marino if (save_expr == error_mark_node
6874e4b17023SJohn Marino || (TREE_TYPE (save_expr)
6875e4b17023SJohn Marino && TREE_TYPE (save_expr) == error_mark_node))
6876e4b17023SJohn Marino {
6877e4b17023SJohn Marino ret = GS_ERROR;
6878e4b17023SJohn Marino break;
6879e4b17023SJohn Marino }
6880e4b17023SJohn Marino
6881e4b17023SJohn Marino /* Do any language-specific gimplification. */
6882e4b17023SJohn Marino ret = ((enum gimplify_status)
6883e4b17023SJohn Marino lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
6884e4b17023SJohn Marino if (ret == GS_OK)
6885e4b17023SJohn Marino {
6886e4b17023SJohn Marino if (*expr_p == NULL_TREE)
6887e4b17023SJohn Marino break;
6888e4b17023SJohn Marino if (*expr_p != save_expr)
6889e4b17023SJohn Marino continue;
6890e4b17023SJohn Marino }
6891e4b17023SJohn Marino else if (ret != GS_UNHANDLED)
6892e4b17023SJohn Marino break;
6893e4b17023SJohn Marino
6894e4b17023SJohn Marino /* Make sure that all the cases set 'ret' appropriately. */
6895e4b17023SJohn Marino ret = GS_UNHANDLED;
6896e4b17023SJohn Marino switch (TREE_CODE (*expr_p))
6897e4b17023SJohn Marino {
6898e4b17023SJohn Marino /* First deal with the special cases. */
6899e4b17023SJohn Marino
6900e4b17023SJohn Marino case POSTINCREMENT_EXPR:
6901e4b17023SJohn Marino case POSTDECREMENT_EXPR:
6902e4b17023SJohn Marino case PREINCREMENT_EXPR:
6903e4b17023SJohn Marino case PREDECREMENT_EXPR:
6904e4b17023SJohn Marino ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
6905e4b17023SJohn Marino fallback != fb_none);
6906e4b17023SJohn Marino break;
6907e4b17023SJohn Marino
6908e4b17023SJohn Marino case ARRAY_REF:
6909e4b17023SJohn Marino case ARRAY_RANGE_REF:
6910e4b17023SJohn Marino case REALPART_EXPR:
6911e4b17023SJohn Marino case IMAGPART_EXPR:
6912e4b17023SJohn Marino case COMPONENT_REF:
6913e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
6914e4b17023SJohn Marino ret = gimplify_compound_lval (expr_p, pre_p, post_p,
6915e4b17023SJohn Marino fallback ? fallback : fb_rvalue);
6916e4b17023SJohn Marino break;
6917e4b17023SJohn Marino
6918e4b17023SJohn Marino case COND_EXPR:
6919e4b17023SJohn Marino ret = gimplify_cond_expr (expr_p, pre_p, fallback);
6920e4b17023SJohn Marino
6921e4b17023SJohn Marino /* C99 code may assign to an array in a structure value of a
6922e4b17023SJohn Marino conditional expression, and this has undefined behavior
6923e4b17023SJohn Marino only on execution, so create a temporary if an lvalue is
6924e4b17023SJohn Marino required. */
6925e4b17023SJohn Marino if (fallback == fb_lvalue)
6926e4b17023SJohn Marino {
6927e4b17023SJohn Marino *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
6928e4b17023SJohn Marino mark_addressable (*expr_p);
6929e4b17023SJohn Marino ret = GS_OK;
6930e4b17023SJohn Marino }
6931e4b17023SJohn Marino break;
6932e4b17023SJohn Marino
6933e4b17023SJohn Marino case CALL_EXPR:
6934e4b17023SJohn Marino ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
6935e4b17023SJohn Marino
6936e4b17023SJohn Marino /* C99 code may assign to an array in a structure returned
6937e4b17023SJohn Marino from a function, and this has undefined behavior only on
6938e4b17023SJohn Marino execution, so create a temporary if an lvalue is
6939e4b17023SJohn Marino required. */
6940e4b17023SJohn Marino if (fallback == fb_lvalue)
6941e4b17023SJohn Marino {
6942e4b17023SJohn Marino *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
6943e4b17023SJohn Marino mark_addressable (*expr_p);
6944e4b17023SJohn Marino ret = GS_OK;
6945e4b17023SJohn Marino }
6946e4b17023SJohn Marino break;
6947e4b17023SJohn Marino
6948e4b17023SJohn Marino case TREE_LIST:
6949e4b17023SJohn Marino gcc_unreachable ();
6950e4b17023SJohn Marino
6951e4b17023SJohn Marino case COMPOUND_EXPR:
6952e4b17023SJohn Marino ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
6953e4b17023SJohn Marino break;
6954e4b17023SJohn Marino
6955e4b17023SJohn Marino case COMPOUND_LITERAL_EXPR:
6956e4b17023SJohn Marino ret = gimplify_compound_literal_expr (expr_p, pre_p);
6957e4b17023SJohn Marino break;
6958e4b17023SJohn Marino
6959e4b17023SJohn Marino case MODIFY_EXPR:
6960e4b17023SJohn Marino case INIT_EXPR:
6961e4b17023SJohn Marino ret = gimplify_modify_expr (expr_p, pre_p, post_p,
6962e4b17023SJohn Marino fallback != fb_none);
6963e4b17023SJohn Marino break;
6964e4b17023SJohn Marino
6965e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
6966e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
6967e4b17023SJohn Marino {
6968e4b17023SJohn Marino /* Preserve the original type of the expression and the
6969e4b17023SJohn Marino source location of the outer expression. */
6970e4b17023SJohn Marino tree org_type = TREE_TYPE (*expr_p);
6971e4b17023SJohn Marino *expr_p = gimple_boolify (*expr_p);
6972e4b17023SJohn Marino *expr_p = build3_loc (input_location, COND_EXPR,
6973e4b17023SJohn Marino org_type, *expr_p,
6974e4b17023SJohn Marino fold_convert_loc
6975e4b17023SJohn Marino (input_location,
6976e4b17023SJohn Marino org_type, boolean_true_node),
6977e4b17023SJohn Marino fold_convert_loc
6978e4b17023SJohn Marino (input_location,
6979e4b17023SJohn Marino org_type, boolean_false_node));
6980e4b17023SJohn Marino ret = GS_OK;
6981e4b17023SJohn Marino break;
6982e4b17023SJohn Marino }
6983e4b17023SJohn Marino
6984e4b17023SJohn Marino case TRUTH_NOT_EXPR:
6985e4b17023SJohn Marino {
6986e4b17023SJohn Marino tree type = TREE_TYPE (*expr_p);
6987e4b17023SJohn Marino /* The parsers are careful to generate TRUTH_NOT_EXPR
6988e4b17023SJohn Marino only with operands that are always zero or one.
6989e4b17023SJohn Marino We do not fold here but handle the only interesting case
6990e4b17023SJohn Marino manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
6991e4b17023SJohn Marino *expr_p = gimple_boolify (*expr_p);
6992e4b17023SJohn Marino if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
6993e4b17023SJohn Marino *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
6994e4b17023SJohn Marino TREE_TYPE (*expr_p),
6995e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0));
6996e4b17023SJohn Marino else
6997e4b17023SJohn Marino *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
6998e4b17023SJohn Marino TREE_TYPE (*expr_p),
6999e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0),
7000e4b17023SJohn Marino build_int_cst (TREE_TYPE (*expr_p), 1));
7001e4b17023SJohn Marino if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
7002e4b17023SJohn Marino *expr_p = fold_convert_loc (input_location, type, *expr_p);
7003e4b17023SJohn Marino ret = GS_OK;
7004e4b17023SJohn Marino break;
7005e4b17023SJohn Marino }
7006e4b17023SJohn Marino
7007e4b17023SJohn Marino case ADDR_EXPR:
7008e4b17023SJohn Marino ret = gimplify_addr_expr (expr_p, pre_p, post_p);
7009e4b17023SJohn Marino break;
7010e4b17023SJohn Marino
7011e4b17023SJohn Marino case VA_ARG_EXPR:
7012e4b17023SJohn Marino ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
7013e4b17023SJohn Marino break;
7014e4b17023SJohn Marino
7015e4b17023SJohn Marino CASE_CONVERT:
7016e4b17023SJohn Marino if (IS_EMPTY_STMT (*expr_p))
7017e4b17023SJohn Marino {
7018e4b17023SJohn Marino ret = GS_ALL_DONE;
7019e4b17023SJohn Marino break;
7020e4b17023SJohn Marino }
7021e4b17023SJohn Marino
7022e4b17023SJohn Marino if (VOID_TYPE_P (TREE_TYPE (*expr_p))
7023e4b17023SJohn Marino || fallback == fb_none)
7024e4b17023SJohn Marino {
7025e4b17023SJohn Marino /* Just strip a conversion to void (or in void context) and
7026e4b17023SJohn Marino try again. */
7027e4b17023SJohn Marino *expr_p = TREE_OPERAND (*expr_p, 0);
7028e4b17023SJohn Marino ret = GS_OK;
7029e4b17023SJohn Marino break;
7030e4b17023SJohn Marino }
7031e4b17023SJohn Marino
7032e4b17023SJohn Marino ret = gimplify_conversion (expr_p);
7033e4b17023SJohn Marino if (ret == GS_ERROR)
7034e4b17023SJohn Marino break;
7035e4b17023SJohn Marino if (*expr_p != save_expr)
7036e4b17023SJohn Marino break;
7037e4b17023SJohn Marino /* FALLTHRU */
7038e4b17023SJohn Marino
7039e4b17023SJohn Marino case FIX_TRUNC_EXPR:
7040e4b17023SJohn Marino /* unary_expr: ... | '(' cast ')' val | ... */
7041e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7042e4b17023SJohn Marino is_gimple_val, fb_rvalue);
7043e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7044e4b17023SJohn Marino break;
7045e4b17023SJohn Marino
7046e4b17023SJohn Marino case INDIRECT_REF:
7047e4b17023SJohn Marino {
7048e4b17023SJohn Marino bool volatilep = TREE_THIS_VOLATILE (*expr_p);
7049e4b17023SJohn Marino bool notrap = TREE_THIS_NOTRAP (*expr_p);
7050e4b17023SJohn Marino tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
7051e4b17023SJohn Marino
7052e4b17023SJohn Marino *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
7053e4b17023SJohn Marino if (*expr_p != save_expr)
7054e4b17023SJohn Marino {
7055e4b17023SJohn Marino ret = GS_OK;
7056e4b17023SJohn Marino break;
7057e4b17023SJohn Marino }
7058e4b17023SJohn Marino
7059e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7060e4b17023SJohn Marino is_gimple_reg, fb_rvalue);
7061e4b17023SJohn Marino if (ret == GS_ERROR)
7062e4b17023SJohn Marino break;
7063e4b17023SJohn Marino
7064e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7065e4b17023SJohn Marino *expr_p = fold_build2_loc (input_location, MEM_REF,
7066e4b17023SJohn Marino TREE_TYPE (*expr_p),
7067e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0),
7068e4b17023SJohn Marino build_int_cst (saved_ptr_type, 0));
7069e4b17023SJohn Marino TREE_THIS_VOLATILE (*expr_p) = volatilep;
7070e4b17023SJohn Marino TREE_THIS_NOTRAP (*expr_p) = notrap;
7071e4b17023SJohn Marino ret = GS_OK;
7072e4b17023SJohn Marino break;
7073e4b17023SJohn Marino }
7074e4b17023SJohn Marino
7075e4b17023SJohn Marino /* We arrive here through the various re-gimplifcation paths. */
7076e4b17023SJohn Marino case MEM_REF:
7077e4b17023SJohn Marino /* First try re-folding the whole thing. */
7078e4b17023SJohn Marino tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
7079e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0),
7080e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1));
7081e4b17023SJohn Marino if (tmp)
7082e4b17023SJohn Marino {
7083e4b17023SJohn Marino *expr_p = tmp;
7084e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7085e4b17023SJohn Marino ret = GS_OK;
7086e4b17023SJohn Marino break;
7087e4b17023SJohn Marino }
7088e4b17023SJohn Marino /* Avoid re-gimplifying the address operand if it is already
7089e4b17023SJohn Marino in suitable form. Re-gimplifying would mark the address
7090e4b17023SJohn Marino operand addressable. Always gimplify when not in SSA form
7091e4b17023SJohn Marino as we still may have to gimplify decls with value-exprs. */
7092e4b17023SJohn Marino if (!gimplify_ctxp || !gimplify_ctxp->into_ssa
7093e4b17023SJohn Marino || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
7094e4b17023SJohn Marino {
7095e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7096e4b17023SJohn Marino is_gimple_mem_ref_addr, fb_rvalue);
7097e4b17023SJohn Marino if (ret == GS_ERROR)
7098e4b17023SJohn Marino break;
7099e4b17023SJohn Marino }
7100e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7101e4b17023SJohn Marino ret = GS_ALL_DONE;
7102e4b17023SJohn Marino break;
7103e4b17023SJohn Marino
7104e4b17023SJohn Marino /* Constants need not be gimplified. */
7105e4b17023SJohn Marino case INTEGER_CST:
7106e4b17023SJohn Marino case REAL_CST:
7107e4b17023SJohn Marino case FIXED_CST:
7108e4b17023SJohn Marino case STRING_CST:
7109e4b17023SJohn Marino case COMPLEX_CST:
7110e4b17023SJohn Marino case VECTOR_CST:
7111e4b17023SJohn Marino ret = GS_ALL_DONE;
7112e4b17023SJohn Marino break;
7113e4b17023SJohn Marino
7114e4b17023SJohn Marino case CONST_DECL:
7115e4b17023SJohn Marino /* If we require an lvalue, such as for ADDR_EXPR, retain the
7116e4b17023SJohn Marino CONST_DECL node. Otherwise the decl is replaceable by its
7117e4b17023SJohn Marino value. */
7118e4b17023SJohn Marino /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
7119e4b17023SJohn Marino if (fallback & fb_lvalue)
7120e4b17023SJohn Marino ret = GS_ALL_DONE;
7121e4b17023SJohn Marino else
7122e4b17023SJohn Marino {
7123e4b17023SJohn Marino *expr_p = DECL_INITIAL (*expr_p);
7124e4b17023SJohn Marino ret = GS_OK;
7125e4b17023SJohn Marino }
7126e4b17023SJohn Marino break;
7127e4b17023SJohn Marino
7128e4b17023SJohn Marino case DECL_EXPR:
7129e4b17023SJohn Marino ret = gimplify_decl_expr (expr_p, pre_p);
7130e4b17023SJohn Marino break;
7131e4b17023SJohn Marino
7132e4b17023SJohn Marino case BIND_EXPR:
7133e4b17023SJohn Marino ret = gimplify_bind_expr (expr_p, pre_p);
7134e4b17023SJohn Marino break;
7135e4b17023SJohn Marino
7136e4b17023SJohn Marino case LOOP_EXPR:
7137e4b17023SJohn Marino ret = gimplify_loop_expr (expr_p, pre_p);
7138e4b17023SJohn Marino break;
7139e4b17023SJohn Marino
7140e4b17023SJohn Marino case SWITCH_EXPR:
7141e4b17023SJohn Marino ret = gimplify_switch_expr (expr_p, pre_p);
7142e4b17023SJohn Marino break;
7143e4b17023SJohn Marino
7144e4b17023SJohn Marino case EXIT_EXPR:
7145e4b17023SJohn Marino ret = gimplify_exit_expr (expr_p);
7146e4b17023SJohn Marino break;
7147e4b17023SJohn Marino
7148e4b17023SJohn Marino case GOTO_EXPR:
7149e4b17023SJohn Marino /* If the target is not LABEL, then it is a computed jump
7150e4b17023SJohn Marino and the target needs to be gimplified. */
7151e4b17023SJohn Marino if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
7152e4b17023SJohn Marino {
7153e4b17023SJohn Marino ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
7154e4b17023SJohn Marino NULL, is_gimple_val, fb_rvalue);
7155e4b17023SJohn Marino if (ret == GS_ERROR)
7156e4b17023SJohn Marino break;
7157e4b17023SJohn Marino }
7158e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p,
7159e4b17023SJohn Marino gimple_build_goto (GOTO_DESTINATION (*expr_p)));
7160e4b17023SJohn Marino ret = GS_ALL_DONE;
7161e4b17023SJohn Marino break;
7162e4b17023SJohn Marino
7163e4b17023SJohn Marino case PREDICT_EXPR:
7164e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p,
7165e4b17023SJohn Marino gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
7166e4b17023SJohn Marino PREDICT_EXPR_OUTCOME (*expr_p)));
7167e4b17023SJohn Marino ret = GS_ALL_DONE;
7168e4b17023SJohn Marino break;
7169e4b17023SJohn Marino
7170e4b17023SJohn Marino case LABEL_EXPR:
7171e4b17023SJohn Marino ret = GS_ALL_DONE;
7172e4b17023SJohn Marino gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
7173e4b17023SJohn Marino == current_function_decl);
7174e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p,
7175e4b17023SJohn Marino gimple_build_label (LABEL_EXPR_LABEL (*expr_p)));
7176e4b17023SJohn Marino break;
7177e4b17023SJohn Marino
7178e4b17023SJohn Marino case CASE_LABEL_EXPR:
7179e4b17023SJohn Marino ret = gimplify_case_label_expr (expr_p, pre_p);
7180e4b17023SJohn Marino break;
7181e4b17023SJohn Marino
7182e4b17023SJohn Marino case RETURN_EXPR:
7183e4b17023SJohn Marino ret = gimplify_return_expr (*expr_p, pre_p);
7184e4b17023SJohn Marino break;
7185e4b17023SJohn Marino
7186e4b17023SJohn Marino case CONSTRUCTOR:
7187e4b17023SJohn Marino /* Don't reduce this in place; let gimplify_init_constructor work its
7188e4b17023SJohn Marino magic. Buf if we're just elaborating this for side effects, just
7189e4b17023SJohn Marino gimplify any element that has side-effects. */
7190e4b17023SJohn Marino if (fallback == fb_none)
7191e4b17023SJohn Marino {
7192e4b17023SJohn Marino unsigned HOST_WIDE_INT ix;
7193e4b17023SJohn Marino tree val;
7194e4b17023SJohn Marino tree temp = NULL_TREE;
7195e4b17023SJohn Marino FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
7196e4b17023SJohn Marino if (TREE_SIDE_EFFECTS (val))
7197e4b17023SJohn Marino append_to_statement_list (val, &temp);
7198e4b17023SJohn Marino
7199e4b17023SJohn Marino *expr_p = temp;
7200e4b17023SJohn Marino ret = temp ? GS_OK : GS_ALL_DONE;
7201e4b17023SJohn Marino }
7202e4b17023SJohn Marino /* C99 code may assign to an array in a constructed
7203e4b17023SJohn Marino structure or union, and this has undefined behavior only
7204e4b17023SJohn Marino on execution, so create a temporary if an lvalue is
7205e4b17023SJohn Marino required. */
7206e4b17023SJohn Marino else if (fallback == fb_lvalue)
7207e4b17023SJohn Marino {
7208e4b17023SJohn Marino *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
7209e4b17023SJohn Marino mark_addressable (*expr_p);
7210e4b17023SJohn Marino ret = GS_OK;
7211e4b17023SJohn Marino }
7212e4b17023SJohn Marino else
7213e4b17023SJohn Marino ret = GS_ALL_DONE;
7214e4b17023SJohn Marino break;
7215e4b17023SJohn Marino
7216e4b17023SJohn Marino /* The following are special cases that are not handled by the
7217e4b17023SJohn Marino original GIMPLE grammar. */
7218e4b17023SJohn Marino
7219e4b17023SJohn Marino /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
7220e4b17023SJohn Marino eliminated. */
7221e4b17023SJohn Marino case SAVE_EXPR:
7222e4b17023SJohn Marino ret = gimplify_save_expr (expr_p, pre_p, post_p);
7223e4b17023SJohn Marino break;
7224e4b17023SJohn Marino
7225e4b17023SJohn Marino case BIT_FIELD_REF:
7226e4b17023SJohn Marino {
7227e4b17023SJohn Marino enum gimplify_status r0, r1, r2;
7228e4b17023SJohn Marino
7229e4b17023SJohn Marino r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7230e4b17023SJohn Marino post_p, is_gimple_lvalue, fb_either);
7231e4b17023SJohn Marino r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
7232e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7233e4b17023SJohn Marino r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
7234e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7235e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7236e4b17023SJohn Marino
7237e4b17023SJohn Marino ret = MIN (r0, MIN (r1, r2));
7238e4b17023SJohn Marino }
7239e4b17023SJohn Marino break;
7240e4b17023SJohn Marino
7241e4b17023SJohn Marino case TARGET_MEM_REF:
7242e4b17023SJohn Marino {
7243e4b17023SJohn Marino enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
7244e4b17023SJohn Marino
7245e4b17023SJohn Marino if (TMR_BASE (*expr_p))
7246e4b17023SJohn Marino r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
7247e4b17023SJohn Marino post_p, is_gimple_mem_ref_addr, fb_either);
7248e4b17023SJohn Marino if (TMR_INDEX (*expr_p))
7249e4b17023SJohn Marino r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
7250e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7251e4b17023SJohn Marino if (TMR_INDEX2 (*expr_p))
7252e4b17023SJohn Marino r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
7253e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7254e4b17023SJohn Marino /* TMR_STEP and TMR_OFFSET are always integer constants. */
7255e4b17023SJohn Marino ret = MIN (r0, r1);
7256e4b17023SJohn Marino }
7257e4b17023SJohn Marino break;
7258e4b17023SJohn Marino
7259e4b17023SJohn Marino case NON_LVALUE_EXPR:
7260e4b17023SJohn Marino /* This should have been stripped above. */
7261e4b17023SJohn Marino gcc_unreachable ();
7262e4b17023SJohn Marino
7263e4b17023SJohn Marino case ASM_EXPR:
7264e4b17023SJohn Marino ret = gimplify_asm_expr (expr_p, pre_p, post_p);
7265e4b17023SJohn Marino break;
7266e4b17023SJohn Marino
7267e4b17023SJohn Marino case TRY_FINALLY_EXPR:
7268e4b17023SJohn Marino case TRY_CATCH_EXPR:
7269e4b17023SJohn Marino {
7270e4b17023SJohn Marino gimple_seq eval, cleanup;
7271e4b17023SJohn Marino gimple try_;
7272e4b17023SJohn Marino
7273e4b17023SJohn Marino eval = cleanup = NULL;
7274e4b17023SJohn Marino gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
7275e4b17023SJohn Marino gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
7276e4b17023SJohn Marino /* Don't create bogus GIMPLE_TRY with empty cleanup. */
7277e4b17023SJohn Marino if (gimple_seq_empty_p (cleanup))
7278e4b17023SJohn Marino {
7279e4b17023SJohn Marino gimple_seq_add_seq (pre_p, eval);
7280e4b17023SJohn Marino ret = GS_ALL_DONE;
7281e4b17023SJohn Marino break;
7282e4b17023SJohn Marino }
7283e4b17023SJohn Marino try_ = gimple_build_try (eval, cleanup,
7284e4b17023SJohn Marino TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
7285e4b17023SJohn Marino ? GIMPLE_TRY_FINALLY
7286e4b17023SJohn Marino : GIMPLE_TRY_CATCH);
7287e4b17023SJohn Marino if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
7288e4b17023SJohn Marino gimple_try_set_catch_is_cleanup (try_,
7289e4b17023SJohn Marino TRY_CATCH_IS_CLEANUP (*expr_p));
7290e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, try_);
7291e4b17023SJohn Marino ret = GS_ALL_DONE;
7292e4b17023SJohn Marino break;
7293e4b17023SJohn Marino }
7294e4b17023SJohn Marino
7295e4b17023SJohn Marino case CLEANUP_POINT_EXPR:
7296e4b17023SJohn Marino ret = gimplify_cleanup_point_expr (expr_p, pre_p);
7297e4b17023SJohn Marino break;
7298e4b17023SJohn Marino
7299e4b17023SJohn Marino case TARGET_EXPR:
7300e4b17023SJohn Marino ret = gimplify_target_expr (expr_p, pre_p, post_p);
7301e4b17023SJohn Marino break;
7302e4b17023SJohn Marino
7303e4b17023SJohn Marino case CATCH_EXPR:
7304e4b17023SJohn Marino {
7305e4b17023SJohn Marino gimple c;
7306e4b17023SJohn Marino gimple_seq handler = NULL;
7307e4b17023SJohn Marino gimplify_and_add (CATCH_BODY (*expr_p), &handler);
7308e4b17023SJohn Marino c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
7309e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, c);
7310e4b17023SJohn Marino ret = GS_ALL_DONE;
7311e4b17023SJohn Marino break;
7312e4b17023SJohn Marino }
7313e4b17023SJohn Marino
7314e4b17023SJohn Marino case EH_FILTER_EXPR:
7315e4b17023SJohn Marino {
7316e4b17023SJohn Marino gimple ehf;
7317e4b17023SJohn Marino gimple_seq failure = NULL;
7318e4b17023SJohn Marino
7319e4b17023SJohn Marino gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
7320e4b17023SJohn Marino ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
7321e4b17023SJohn Marino gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p));
7322e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, ehf);
7323e4b17023SJohn Marino ret = GS_ALL_DONE;
7324e4b17023SJohn Marino break;
7325e4b17023SJohn Marino }
7326e4b17023SJohn Marino
7327e4b17023SJohn Marino case OBJ_TYPE_REF:
7328e4b17023SJohn Marino {
7329e4b17023SJohn Marino enum gimplify_status r0, r1;
7330e4b17023SJohn Marino r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
7331e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7332e4b17023SJohn Marino r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
7333e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7334e4b17023SJohn Marino TREE_SIDE_EFFECTS (*expr_p) = 0;
7335e4b17023SJohn Marino ret = MIN (r0, r1);
7336e4b17023SJohn Marino }
7337e4b17023SJohn Marino break;
7338e4b17023SJohn Marino
7339e4b17023SJohn Marino case LABEL_DECL:
7340e4b17023SJohn Marino /* We get here when taking the address of a label. We mark
7341e4b17023SJohn Marino the label as "forced"; meaning it can never be removed and
7342e4b17023SJohn Marino it is a potential target for any computed goto. */
7343e4b17023SJohn Marino FORCED_LABEL (*expr_p) = 1;
7344e4b17023SJohn Marino ret = GS_ALL_DONE;
7345e4b17023SJohn Marino break;
7346e4b17023SJohn Marino
7347e4b17023SJohn Marino case STATEMENT_LIST:
7348e4b17023SJohn Marino ret = gimplify_statement_list (expr_p, pre_p);
7349e4b17023SJohn Marino break;
7350e4b17023SJohn Marino
7351e4b17023SJohn Marino case WITH_SIZE_EXPR:
7352e4b17023SJohn Marino {
7353e4b17023SJohn Marino gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7354e4b17023SJohn Marino post_p == &internal_post ? NULL : post_p,
7355e4b17023SJohn Marino gimple_test_f, fallback);
7356e4b17023SJohn Marino gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
7357e4b17023SJohn Marino is_gimple_val, fb_rvalue);
7358e4b17023SJohn Marino ret = GS_ALL_DONE;
7359e4b17023SJohn Marino }
7360e4b17023SJohn Marino break;
7361e4b17023SJohn Marino
7362e4b17023SJohn Marino case VAR_DECL:
7363e4b17023SJohn Marino case PARM_DECL:
7364e4b17023SJohn Marino ret = gimplify_var_or_parm_decl (expr_p);
7365e4b17023SJohn Marino break;
7366e4b17023SJohn Marino
7367e4b17023SJohn Marino case RESULT_DECL:
7368e4b17023SJohn Marino /* When within an OpenMP context, notice uses of variables. */
7369e4b17023SJohn Marino if (gimplify_omp_ctxp)
7370e4b17023SJohn Marino omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
7371e4b17023SJohn Marino ret = GS_ALL_DONE;
7372e4b17023SJohn Marino break;
7373e4b17023SJohn Marino
7374e4b17023SJohn Marino case SSA_NAME:
7375e4b17023SJohn Marino /* Allow callbacks into the gimplifier during optimization. */
7376e4b17023SJohn Marino ret = GS_ALL_DONE;
7377e4b17023SJohn Marino break;
7378e4b17023SJohn Marino
7379e4b17023SJohn Marino case OMP_PARALLEL:
7380e4b17023SJohn Marino gimplify_omp_parallel (expr_p, pre_p);
7381e4b17023SJohn Marino ret = GS_ALL_DONE;
7382e4b17023SJohn Marino break;
7383e4b17023SJohn Marino
7384e4b17023SJohn Marino case OMP_TASK:
7385e4b17023SJohn Marino gimplify_omp_task (expr_p, pre_p);
7386e4b17023SJohn Marino ret = GS_ALL_DONE;
7387e4b17023SJohn Marino break;
7388e4b17023SJohn Marino
7389e4b17023SJohn Marino case OMP_FOR:
7390e4b17023SJohn Marino ret = gimplify_omp_for (expr_p, pre_p);
7391e4b17023SJohn Marino break;
7392e4b17023SJohn Marino
7393e4b17023SJohn Marino case OMP_SECTIONS:
7394e4b17023SJohn Marino case OMP_SINGLE:
7395e4b17023SJohn Marino gimplify_omp_workshare (expr_p, pre_p);
7396e4b17023SJohn Marino ret = GS_ALL_DONE;
7397e4b17023SJohn Marino break;
7398e4b17023SJohn Marino
7399e4b17023SJohn Marino case OMP_SECTION:
7400e4b17023SJohn Marino case OMP_MASTER:
7401e4b17023SJohn Marino case OMP_ORDERED:
7402e4b17023SJohn Marino case OMP_CRITICAL:
7403e4b17023SJohn Marino {
7404e4b17023SJohn Marino gimple_seq body = NULL;
7405e4b17023SJohn Marino gimple g;
7406e4b17023SJohn Marino
7407e4b17023SJohn Marino gimplify_and_add (OMP_BODY (*expr_p), &body);
7408e4b17023SJohn Marino switch (TREE_CODE (*expr_p))
7409e4b17023SJohn Marino {
7410e4b17023SJohn Marino case OMP_SECTION:
7411e4b17023SJohn Marino g = gimple_build_omp_section (body);
7412e4b17023SJohn Marino break;
7413e4b17023SJohn Marino case OMP_MASTER:
7414e4b17023SJohn Marino g = gimple_build_omp_master (body);
7415e4b17023SJohn Marino break;
7416e4b17023SJohn Marino case OMP_ORDERED:
7417e4b17023SJohn Marino g = gimple_build_omp_ordered (body);
7418e4b17023SJohn Marino break;
7419e4b17023SJohn Marino case OMP_CRITICAL:
7420e4b17023SJohn Marino g = gimple_build_omp_critical (body,
7421e4b17023SJohn Marino OMP_CRITICAL_NAME (*expr_p));
7422e4b17023SJohn Marino break;
7423e4b17023SJohn Marino default:
7424e4b17023SJohn Marino gcc_unreachable ();
7425e4b17023SJohn Marino }
7426e4b17023SJohn Marino gimplify_seq_add_stmt (pre_p, g);
7427e4b17023SJohn Marino ret = GS_ALL_DONE;
7428e4b17023SJohn Marino break;
7429e4b17023SJohn Marino }
7430e4b17023SJohn Marino
7431e4b17023SJohn Marino case OMP_ATOMIC:
7432e4b17023SJohn Marino case OMP_ATOMIC_READ:
7433e4b17023SJohn Marino case OMP_ATOMIC_CAPTURE_OLD:
7434e4b17023SJohn Marino case OMP_ATOMIC_CAPTURE_NEW:
7435e4b17023SJohn Marino ret = gimplify_omp_atomic (expr_p, pre_p);
7436e4b17023SJohn Marino break;
7437e4b17023SJohn Marino
7438e4b17023SJohn Marino case TRANSACTION_EXPR:
7439e4b17023SJohn Marino ret = gimplify_transaction (expr_p, pre_p);
7440e4b17023SJohn Marino break;
7441e4b17023SJohn Marino
7442e4b17023SJohn Marino case TRUTH_AND_EXPR:
7443e4b17023SJohn Marino case TRUTH_OR_EXPR:
7444e4b17023SJohn Marino case TRUTH_XOR_EXPR:
7445e4b17023SJohn Marino {
7446e4b17023SJohn Marino tree orig_type = TREE_TYPE (*expr_p);
7447e4b17023SJohn Marino tree new_type, xop0, xop1;
7448e4b17023SJohn Marino *expr_p = gimple_boolify (*expr_p);
7449e4b17023SJohn Marino new_type = TREE_TYPE (*expr_p);
7450e4b17023SJohn Marino if (!useless_type_conversion_p (orig_type, new_type))
7451e4b17023SJohn Marino {
7452e4b17023SJohn Marino *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
7453e4b17023SJohn Marino ret = GS_OK;
7454e4b17023SJohn Marino break;
7455e4b17023SJohn Marino }
7456e4b17023SJohn Marino
7457e4b17023SJohn Marino /* Boolified binary truth expressions are semantically equivalent
7458e4b17023SJohn Marino to bitwise binary expressions. Canonicalize them to the
7459e4b17023SJohn Marino bitwise variant. */
7460e4b17023SJohn Marino switch (TREE_CODE (*expr_p))
7461e4b17023SJohn Marino {
7462e4b17023SJohn Marino case TRUTH_AND_EXPR:
7463e4b17023SJohn Marino TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
7464e4b17023SJohn Marino break;
7465e4b17023SJohn Marino case TRUTH_OR_EXPR:
7466e4b17023SJohn Marino TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
7467e4b17023SJohn Marino break;
7468e4b17023SJohn Marino case TRUTH_XOR_EXPR:
7469e4b17023SJohn Marino TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
7470e4b17023SJohn Marino break;
7471e4b17023SJohn Marino default:
7472e4b17023SJohn Marino break;
7473e4b17023SJohn Marino }
7474e4b17023SJohn Marino /* Now make sure that operands have compatible type to
7475e4b17023SJohn Marino expression's new_type. */
7476e4b17023SJohn Marino xop0 = TREE_OPERAND (*expr_p, 0);
7477e4b17023SJohn Marino xop1 = TREE_OPERAND (*expr_p, 1);
7478e4b17023SJohn Marino if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
7479e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
7480e4b17023SJohn Marino new_type,
7481e4b17023SJohn Marino xop0);
7482e4b17023SJohn Marino if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
7483e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
7484e4b17023SJohn Marino new_type,
7485e4b17023SJohn Marino xop1);
7486e4b17023SJohn Marino /* Continue classified as tcc_binary. */
7487e4b17023SJohn Marino goto expr_2;
7488e4b17023SJohn Marino }
7489e4b17023SJohn Marino
7490e4b17023SJohn Marino case FMA_EXPR:
7491e4b17023SJohn Marino case VEC_PERM_EXPR:
7492e4b17023SJohn Marino /* Classified as tcc_expression. */
7493e4b17023SJohn Marino goto expr_3;
7494e4b17023SJohn Marino
7495e4b17023SJohn Marino case POINTER_PLUS_EXPR:
7496e4b17023SJohn Marino {
7497e4b17023SJohn Marino enum gimplify_status r0, r1;
7498e4b17023SJohn Marino r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7499e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7500e4b17023SJohn Marino r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
7501e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7502e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7503e4b17023SJohn Marino ret = MIN (r0, r1);
7504e4b17023SJohn Marino /* Convert &X + CST to invariant &MEM[&X, CST]. Do this
7505e4b17023SJohn Marino after gimplifying operands - this is similar to how
7506e4b17023SJohn Marino it would be folding all gimplified stmts on creation
7507e4b17023SJohn Marino to have them canonicalized, which is what we eventually
7508e4b17023SJohn Marino should do anyway. */
7509e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
7510e4b17023SJohn Marino && is_gimple_min_invariant (TREE_OPERAND (*expr_p, 0)))
7511e4b17023SJohn Marino {
7512e4b17023SJohn Marino *expr_p = build_fold_addr_expr_with_type_loc
7513e4b17023SJohn Marino (input_location,
7514e4b17023SJohn Marino fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (*expr_p)),
7515e4b17023SJohn Marino TREE_OPERAND (*expr_p, 0),
7516e4b17023SJohn Marino fold_convert (ptr_type_node,
7517e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1))),
7518e4b17023SJohn Marino TREE_TYPE (*expr_p));
7519e4b17023SJohn Marino ret = MIN (ret, GS_OK);
7520e4b17023SJohn Marino }
7521e4b17023SJohn Marino break;
7522e4b17023SJohn Marino }
7523e4b17023SJohn Marino
7524e4b17023SJohn Marino default:
7525e4b17023SJohn Marino switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
7526e4b17023SJohn Marino {
7527e4b17023SJohn Marino case tcc_comparison:
7528e4b17023SJohn Marino /* Handle comparison of objects of non scalar mode aggregates
7529e4b17023SJohn Marino with a call to memcmp. It would be nice to only have to do
7530e4b17023SJohn Marino this for variable-sized objects, but then we'd have to allow
7531e4b17023SJohn Marino the same nest of reference nodes we allow for MODIFY_EXPR and
7532e4b17023SJohn Marino that's too complex.
7533e4b17023SJohn Marino
7534e4b17023SJohn Marino Compare scalar mode aggregates as scalar mode values. Using
7535e4b17023SJohn Marino memcmp for them would be very inefficient at best, and is
7536e4b17023SJohn Marino plain wrong if bitfields are involved. */
7537e4b17023SJohn Marino {
7538e4b17023SJohn Marino tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
7539e4b17023SJohn Marino
7540e4b17023SJohn Marino /* Vector comparisons need no boolification. */
7541e4b17023SJohn Marino if (TREE_CODE (type) == VECTOR_TYPE)
7542e4b17023SJohn Marino goto expr_2;
7543e4b17023SJohn Marino else if (!AGGREGATE_TYPE_P (type))
7544e4b17023SJohn Marino {
7545e4b17023SJohn Marino tree org_type = TREE_TYPE (*expr_p);
7546e4b17023SJohn Marino *expr_p = gimple_boolify (*expr_p);
7547e4b17023SJohn Marino if (!useless_type_conversion_p (org_type,
7548e4b17023SJohn Marino TREE_TYPE (*expr_p)))
7549e4b17023SJohn Marino {
7550e4b17023SJohn Marino *expr_p = fold_convert_loc (input_location,
7551e4b17023SJohn Marino org_type, *expr_p);
7552e4b17023SJohn Marino ret = GS_OK;
7553e4b17023SJohn Marino }
7554e4b17023SJohn Marino else
7555e4b17023SJohn Marino goto expr_2;
7556e4b17023SJohn Marino }
7557e4b17023SJohn Marino else if (TYPE_MODE (type) != BLKmode)
7558e4b17023SJohn Marino ret = gimplify_scalar_mode_aggregate_compare (expr_p);
7559e4b17023SJohn Marino else
7560e4b17023SJohn Marino ret = gimplify_variable_sized_compare (expr_p);
7561e4b17023SJohn Marino
7562e4b17023SJohn Marino break;
7563e4b17023SJohn Marino }
7564e4b17023SJohn Marino
7565e4b17023SJohn Marino /* If *EXPR_P does not need to be special-cased, handle it
7566e4b17023SJohn Marino according to its class. */
7567e4b17023SJohn Marino case tcc_unary:
7568e4b17023SJohn Marino ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7569e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7570e4b17023SJohn Marino break;
7571e4b17023SJohn Marino
7572e4b17023SJohn Marino case tcc_binary:
7573e4b17023SJohn Marino expr_2:
7574e4b17023SJohn Marino {
7575e4b17023SJohn Marino enum gimplify_status r0, r1;
7576e4b17023SJohn Marino
7577e4b17023SJohn Marino r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7578e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7579e4b17023SJohn Marino r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
7580e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7581e4b17023SJohn Marino
7582e4b17023SJohn Marino ret = MIN (r0, r1);
7583e4b17023SJohn Marino break;
7584e4b17023SJohn Marino }
7585e4b17023SJohn Marino
7586e4b17023SJohn Marino expr_3:
7587e4b17023SJohn Marino {
7588e4b17023SJohn Marino enum gimplify_status r0, r1, r2;
7589e4b17023SJohn Marino
7590e4b17023SJohn Marino r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
7591e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7592e4b17023SJohn Marino r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
7593e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7594e4b17023SJohn Marino r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
7595e4b17023SJohn Marino post_p, is_gimple_val, fb_rvalue);
7596e4b17023SJohn Marino
7597e4b17023SJohn Marino ret = MIN (MIN (r0, r1), r2);
7598e4b17023SJohn Marino break;
7599e4b17023SJohn Marino }
7600e4b17023SJohn Marino
7601e4b17023SJohn Marino case tcc_declaration:
7602e4b17023SJohn Marino case tcc_constant:
7603e4b17023SJohn Marino ret = GS_ALL_DONE;
7604e4b17023SJohn Marino goto dont_recalculate;
7605e4b17023SJohn Marino
7606e4b17023SJohn Marino default:
7607e4b17023SJohn Marino gcc_unreachable ();
7608e4b17023SJohn Marino }
7609e4b17023SJohn Marino
7610e4b17023SJohn Marino recalculate_side_effects (*expr_p);
7611e4b17023SJohn Marino
7612e4b17023SJohn Marino dont_recalculate:
7613e4b17023SJohn Marino break;
7614e4b17023SJohn Marino }
7615e4b17023SJohn Marino
7616e4b17023SJohn Marino gcc_assert (*expr_p || ret != GS_OK);
7617e4b17023SJohn Marino }
7618e4b17023SJohn Marino while (ret == GS_OK);
7619e4b17023SJohn Marino
7620e4b17023SJohn Marino /* If we encountered an error_mark somewhere nested inside, either
7621e4b17023SJohn Marino stub out the statement or propagate the error back out. */
7622e4b17023SJohn Marino if (ret == GS_ERROR)
7623e4b17023SJohn Marino {
7624e4b17023SJohn Marino if (is_statement)
7625e4b17023SJohn Marino *expr_p = NULL;
7626e4b17023SJohn Marino goto out;
7627e4b17023SJohn Marino }
7628e4b17023SJohn Marino
7629e4b17023SJohn Marino /* This was only valid as a return value from the langhook, which
7630e4b17023SJohn Marino we handled. Make sure it doesn't escape from any other context. */
7631e4b17023SJohn Marino gcc_assert (ret != GS_UNHANDLED);
7632e4b17023SJohn Marino
7633e4b17023SJohn Marino if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
7634e4b17023SJohn Marino {
7635e4b17023SJohn Marino /* We aren't looking for a value, and we don't have a valid
7636e4b17023SJohn Marino statement. If it doesn't have side-effects, throw it away. */
7637e4b17023SJohn Marino if (!TREE_SIDE_EFFECTS (*expr_p))
7638e4b17023SJohn Marino *expr_p = NULL;
7639e4b17023SJohn Marino else if (!TREE_THIS_VOLATILE (*expr_p))
7640e4b17023SJohn Marino {
7641e4b17023SJohn Marino /* This is probably a _REF that contains something nested that
7642e4b17023SJohn Marino has side effects. Recurse through the operands to find it. */
7643e4b17023SJohn Marino enum tree_code code = TREE_CODE (*expr_p);
7644e4b17023SJohn Marino
7645e4b17023SJohn Marino switch (code)
7646e4b17023SJohn Marino {
7647e4b17023SJohn Marino case COMPONENT_REF:
7648e4b17023SJohn Marino case REALPART_EXPR:
7649e4b17023SJohn Marino case IMAGPART_EXPR:
7650e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
7651e4b17023SJohn Marino gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7652e4b17023SJohn Marino gimple_test_f, fallback);
7653e4b17023SJohn Marino break;
7654e4b17023SJohn Marino
7655e4b17023SJohn Marino case ARRAY_REF:
7656e4b17023SJohn Marino case ARRAY_RANGE_REF:
7657e4b17023SJohn Marino gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7658e4b17023SJohn Marino gimple_test_f, fallback);
7659e4b17023SJohn Marino gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
7660e4b17023SJohn Marino gimple_test_f, fallback);
7661e4b17023SJohn Marino break;
7662e4b17023SJohn Marino
7663e4b17023SJohn Marino default:
7664e4b17023SJohn Marino /* Anything else with side-effects must be converted to
7665e4b17023SJohn Marino a valid statement before we get here. */
7666e4b17023SJohn Marino gcc_unreachable ();
7667e4b17023SJohn Marino }
7668e4b17023SJohn Marino
7669e4b17023SJohn Marino *expr_p = NULL;
7670e4b17023SJohn Marino }
7671e4b17023SJohn Marino else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
7672e4b17023SJohn Marino && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode)
7673e4b17023SJohn Marino {
7674e4b17023SJohn Marino /* Historically, the compiler has treated a bare reference
7675e4b17023SJohn Marino to a non-BLKmode volatile lvalue as forcing a load. */
7676e4b17023SJohn Marino tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
7677e4b17023SJohn Marino
7678e4b17023SJohn Marino /* Normally, we do not want to create a temporary for a
7679e4b17023SJohn Marino TREE_ADDRESSABLE type because such a type should not be
7680e4b17023SJohn Marino copied by bitwise-assignment. However, we make an
7681e4b17023SJohn Marino exception here, as all we are doing here is ensuring that
7682e4b17023SJohn Marino we read the bytes that make up the type. We use
7683e4b17023SJohn Marino create_tmp_var_raw because create_tmp_var will abort when
7684e4b17023SJohn Marino given a TREE_ADDRESSABLE type. */
7685e4b17023SJohn Marino tree tmp = create_tmp_var_raw (type, "vol");
7686e4b17023SJohn Marino gimple_add_tmp_var (tmp);
7687e4b17023SJohn Marino gimplify_assign (tmp, *expr_p, pre_p);
7688e4b17023SJohn Marino *expr_p = NULL;
7689e4b17023SJohn Marino }
7690e4b17023SJohn Marino else
7691e4b17023SJohn Marino /* We can't do anything useful with a volatile reference to
7692e4b17023SJohn Marino an incomplete type, so just throw it away. Likewise for
7693e4b17023SJohn Marino a BLKmode type, since any implicit inner load should
7694e4b17023SJohn Marino already have been turned into an explicit one by the
7695e4b17023SJohn Marino gimplification process. */
7696e4b17023SJohn Marino *expr_p = NULL;
7697e4b17023SJohn Marino }
7698e4b17023SJohn Marino
7699e4b17023SJohn Marino /* If we are gimplifying at the statement level, we're done. Tack
7700e4b17023SJohn Marino everything together and return. */
7701e4b17023SJohn Marino if (fallback == fb_none || is_statement)
7702e4b17023SJohn Marino {
7703e4b17023SJohn Marino /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
7704e4b17023SJohn Marino it out for GC to reclaim it. */
7705e4b17023SJohn Marino *expr_p = NULL_TREE;
7706e4b17023SJohn Marino
7707e4b17023SJohn Marino if (!gimple_seq_empty_p (internal_pre)
7708e4b17023SJohn Marino || !gimple_seq_empty_p (internal_post))
7709e4b17023SJohn Marino {
7710e4b17023SJohn Marino gimplify_seq_add_seq (&internal_pre, internal_post);
7711e4b17023SJohn Marino gimplify_seq_add_seq (pre_p, internal_pre);
7712e4b17023SJohn Marino }
7713e4b17023SJohn Marino
7714e4b17023SJohn Marino /* The result of gimplifying *EXPR_P is going to be the last few
7715e4b17023SJohn Marino statements in *PRE_P and *POST_P. Add location information
7716e4b17023SJohn Marino to all the statements that were added by the gimplification
7717e4b17023SJohn Marino helpers. */
7718e4b17023SJohn Marino if (!gimple_seq_empty_p (*pre_p))
7719e4b17023SJohn Marino annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
7720e4b17023SJohn Marino
7721e4b17023SJohn Marino if (!gimple_seq_empty_p (*post_p))
7722e4b17023SJohn Marino annotate_all_with_location_after (*post_p, post_last_gsi,
7723e4b17023SJohn Marino input_location);
7724e4b17023SJohn Marino
7725e4b17023SJohn Marino goto out;
7726e4b17023SJohn Marino }
7727e4b17023SJohn Marino
7728e4b17023SJohn Marino #ifdef ENABLE_GIMPLE_CHECKING
7729e4b17023SJohn Marino if (*expr_p)
7730e4b17023SJohn Marino {
7731e4b17023SJohn Marino enum tree_code code = TREE_CODE (*expr_p);
7732e4b17023SJohn Marino /* These expressions should already be in gimple IR form. */
7733e4b17023SJohn Marino gcc_assert (code != MODIFY_EXPR
7734e4b17023SJohn Marino && code != ASM_EXPR
7735e4b17023SJohn Marino && code != BIND_EXPR
7736e4b17023SJohn Marino && code != CATCH_EXPR
7737e4b17023SJohn Marino && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
7738e4b17023SJohn Marino && code != EH_FILTER_EXPR
7739e4b17023SJohn Marino && code != GOTO_EXPR
7740e4b17023SJohn Marino && code != LABEL_EXPR
7741e4b17023SJohn Marino && code != LOOP_EXPR
7742e4b17023SJohn Marino && code != SWITCH_EXPR
7743e4b17023SJohn Marino && code != TRY_FINALLY_EXPR
7744e4b17023SJohn Marino && code != OMP_CRITICAL
7745e4b17023SJohn Marino && code != OMP_FOR
7746e4b17023SJohn Marino && code != OMP_MASTER
7747e4b17023SJohn Marino && code != OMP_ORDERED
7748e4b17023SJohn Marino && code != OMP_PARALLEL
7749e4b17023SJohn Marino && code != OMP_SECTIONS
7750e4b17023SJohn Marino && code != OMP_SECTION
7751e4b17023SJohn Marino && code != OMP_SINGLE);
7752e4b17023SJohn Marino }
7753e4b17023SJohn Marino #endif
7754e4b17023SJohn Marino
7755e4b17023SJohn Marino /* Otherwise we're gimplifying a subexpression, so the resulting
7756e4b17023SJohn Marino value is interesting. If it's a valid operand that matches
7757e4b17023SJohn Marino GIMPLE_TEST_F, we're done. Unless we are handling some
7758e4b17023SJohn Marino post-effects internally; if that's the case, we need to copy into
7759e4b17023SJohn Marino a temporary before adding the post-effects to POST_P. */
7760e4b17023SJohn Marino if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
7761e4b17023SJohn Marino goto out;
7762e4b17023SJohn Marino
7763e4b17023SJohn Marino /* Otherwise, we need to create a new temporary for the gimplified
7764e4b17023SJohn Marino expression. */
7765e4b17023SJohn Marino
7766e4b17023SJohn Marino /* We can't return an lvalue if we have an internal postqueue. The
7767e4b17023SJohn Marino object the lvalue refers to would (probably) be modified by the
7768e4b17023SJohn Marino postqueue; we need to copy the value out first, which means an
7769e4b17023SJohn Marino rvalue. */
7770e4b17023SJohn Marino if ((fallback & fb_lvalue)
7771e4b17023SJohn Marino && gimple_seq_empty_p (internal_post)
7772e4b17023SJohn Marino && is_gimple_addressable (*expr_p))
7773e4b17023SJohn Marino {
7774e4b17023SJohn Marino /* An lvalue will do. Take the address of the expression, store it
7775e4b17023SJohn Marino in a temporary, and replace the expression with an INDIRECT_REF of
7776e4b17023SJohn Marino that temporary. */
7777e4b17023SJohn Marino tmp = build_fold_addr_expr_loc (input_location, *expr_p);
7778e4b17023SJohn Marino gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
7779e4b17023SJohn Marino *expr_p = build_simple_mem_ref (tmp);
7780e4b17023SJohn Marino }
7781e4b17023SJohn Marino else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
7782e4b17023SJohn Marino {
7783e4b17023SJohn Marino /* An rvalue will do. Assign the gimplified expression into a
7784e4b17023SJohn Marino new temporary TMP and replace the original expression with
7785e4b17023SJohn Marino TMP. First, make sure that the expression has a type so that
7786e4b17023SJohn Marino it can be assigned into a temporary. */
7787e4b17023SJohn Marino gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
7788e4b17023SJohn Marino
7789e4b17023SJohn Marino if (!gimple_seq_empty_p (internal_post) || (fallback & fb_lvalue))
7790e4b17023SJohn Marino /* The postqueue might change the value of the expression between
7791e4b17023SJohn Marino the initialization and use of the temporary, so we can't use a
7792e4b17023SJohn Marino formal temp. FIXME do we care? */
7793e4b17023SJohn Marino {
7794e4b17023SJohn Marino *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
7795e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (*expr_p)) == COMPLEX_TYPE
7796e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (*expr_p)) == VECTOR_TYPE)
7797e4b17023SJohn Marino DECL_GIMPLE_REG_P (*expr_p) = 1;
7798e4b17023SJohn Marino }
7799e4b17023SJohn Marino else
7800e4b17023SJohn Marino *expr_p = get_formal_tmp_var (*expr_p, pre_p);
7801e4b17023SJohn Marino }
7802e4b17023SJohn Marino else
7803e4b17023SJohn Marino {
7804e4b17023SJohn Marino #ifdef ENABLE_GIMPLE_CHECKING
7805e4b17023SJohn Marino if (!(fallback & fb_mayfail))
7806e4b17023SJohn Marino {
7807e4b17023SJohn Marino fprintf (stderr, "gimplification failed:\n");
7808e4b17023SJohn Marino print_generic_expr (stderr, *expr_p, 0);
7809e4b17023SJohn Marino debug_tree (*expr_p);
7810e4b17023SJohn Marino internal_error ("gimplification failed");
7811e4b17023SJohn Marino }
7812e4b17023SJohn Marino #endif
7813e4b17023SJohn Marino gcc_assert (fallback & fb_mayfail);
7814e4b17023SJohn Marino
7815e4b17023SJohn Marino /* If this is an asm statement, and the user asked for the
7816e4b17023SJohn Marino impossible, don't die. Fail and let gimplify_asm_expr
7817e4b17023SJohn Marino issue an error. */
7818e4b17023SJohn Marino ret = GS_ERROR;
7819e4b17023SJohn Marino goto out;
7820e4b17023SJohn Marino }
7821e4b17023SJohn Marino
7822e4b17023SJohn Marino /* Make sure the temporary matches our predicate. */
7823e4b17023SJohn Marino gcc_assert ((*gimple_test_f) (*expr_p));
7824e4b17023SJohn Marino
7825e4b17023SJohn Marino if (!gimple_seq_empty_p (internal_post))
7826e4b17023SJohn Marino {
7827e4b17023SJohn Marino annotate_all_with_location (internal_post, input_location);
7828e4b17023SJohn Marino gimplify_seq_add_seq (pre_p, internal_post);
7829e4b17023SJohn Marino }
7830e4b17023SJohn Marino
7831e4b17023SJohn Marino out:
7832e4b17023SJohn Marino input_location = saved_location;
7833e4b17023SJohn Marino return ret;
7834e4b17023SJohn Marino }
7835e4b17023SJohn Marino
7836e4b17023SJohn Marino /* Look through TYPE for variable-sized objects and gimplify each such
7837e4b17023SJohn Marino size that we find. Add to LIST_P any statements generated. */
7838e4b17023SJohn Marino
7839e4b17023SJohn Marino void
gimplify_type_sizes(tree type,gimple_seq * list_p)7840e4b17023SJohn Marino gimplify_type_sizes (tree type, gimple_seq *list_p)
7841e4b17023SJohn Marino {
7842e4b17023SJohn Marino tree field, t;
7843e4b17023SJohn Marino
7844e4b17023SJohn Marino if (type == NULL || type == error_mark_node)
7845e4b17023SJohn Marino return;
7846e4b17023SJohn Marino
7847e4b17023SJohn Marino /* We first do the main variant, then copy into any other variants. */
7848e4b17023SJohn Marino type = TYPE_MAIN_VARIANT (type);
7849e4b17023SJohn Marino
7850e4b17023SJohn Marino /* Avoid infinite recursion. */
7851e4b17023SJohn Marino if (TYPE_SIZES_GIMPLIFIED (type))
7852e4b17023SJohn Marino return;
7853e4b17023SJohn Marino
7854e4b17023SJohn Marino TYPE_SIZES_GIMPLIFIED (type) = 1;
7855e4b17023SJohn Marino
7856e4b17023SJohn Marino switch (TREE_CODE (type))
7857e4b17023SJohn Marino {
7858e4b17023SJohn Marino case INTEGER_TYPE:
7859e4b17023SJohn Marino case ENUMERAL_TYPE:
7860e4b17023SJohn Marino case BOOLEAN_TYPE:
7861e4b17023SJohn Marino case REAL_TYPE:
7862e4b17023SJohn Marino case FIXED_POINT_TYPE:
7863e4b17023SJohn Marino gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
7864e4b17023SJohn Marino gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
7865e4b17023SJohn Marino
7866e4b17023SJohn Marino for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
7867e4b17023SJohn Marino {
7868e4b17023SJohn Marino TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
7869e4b17023SJohn Marino TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
7870e4b17023SJohn Marino }
7871e4b17023SJohn Marino break;
7872e4b17023SJohn Marino
7873e4b17023SJohn Marino case ARRAY_TYPE:
7874e4b17023SJohn Marino /* These types may not have declarations, so handle them here. */
7875e4b17023SJohn Marino gimplify_type_sizes (TREE_TYPE (type), list_p);
7876e4b17023SJohn Marino gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
7877e4b17023SJohn Marino /* Ensure VLA bounds aren't removed, for -O0 they should be variables
7878e4b17023SJohn Marino with assigned stack slots, for -O1+ -g they should be tracked
7879e4b17023SJohn Marino by VTA. */
7880e4b17023SJohn Marino if (!(TYPE_NAME (type)
7881e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
7882e4b17023SJohn Marino && DECL_IGNORED_P (TYPE_NAME (type)))
7883e4b17023SJohn Marino && TYPE_DOMAIN (type)
7884e4b17023SJohn Marino && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
7885e4b17023SJohn Marino {
7886e4b17023SJohn Marino t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
7887e4b17023SJohn Marino if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
7888e4b17023SJohn Marino DECL_IGNORED_P (t) = 0;
7889e4b17023SJohn Marino t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
7890e4b17023SJohn Marino if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
7891e4b17023SJohn Marino DECL_IGNORED_P (t) = 0;
7892e4b17023SJohn Marino }
7893e4b17023SJohn Marino break;
7894e4b17023SJohn Marino
7895e4b17023SJohn Marino case RECORD_TYPE:
7896e4b17023SJohn Marino case UNION_TYPE:
7897e4b17023SJohn Marino case QUAL_UNION_TYPE:
7898e4b17023SJohn Marino for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
7899e4b17023SJohn Marino if (TREE_CODE (field) == FIELD_DECL)
7900e4b17023SJohn Marino {
7901e4b17023SJohn Marino gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
7902e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE (field), list_p);
7903e4b17023SJohn Marino gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
7904e4b17023SJohn Marino gimplify_type_sizes (TREE_TYPE (field), list_p);
7905e4b17023SJohn Marino }
7906e4b17023SJohn Marino break;
7907e4b17023SJohn Marino
7908e4b17023SJohn Marino case POINTER_TYPE:
7909e4b17023SJohn Marino case REFERENCE_TYPE:
7910e4b17023SJohn Marino /* We used to recurse on the pointed-to type here, which turned out to
7911e4b17023SJohn Marino be incorrect because its definition might refer to variables not
7912e4b17023SJohn Marino yet initialized at this point if a forward declaration is involved.
7913e4b17023SJohn Marino
7914e4b17023SJohn Marino It was actually useful for anonymous pointed-to types to ensure
7915e4b17023SJohn Marino that the sizes evaluation dominates every possible later use of the
7916e4b17023SJohn Marino values. Restricting to such types here would be safe since there
7917e4b17023SJohn Marino is no possible forward declaration around, but would introduce an
7918e4b17023SJohn Marino undesirable middle-end semantic to anonymity. We then defer to
7919e4b17023SJohn Marino front-ends the responsibility of ensuring that the sizes are
7920e4b17023SJohn Marino evaluated both early and late enough, e.g. by attaching artificial
7921e4b17023SJohn Marino type declarations to the tree. */
7922e4b17023SJohn Marino break;
7923e4b17023SJohn Marino
7924e4b17023SJohn Marino default:
7925e4b17023SJohn Marino break;
7926e4b17023SJohn Marino }
7927e4b17023SJohn Marino
7928e4b17023SJohn Marino gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
7929e4b17023SJohn Marino gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
7930e4b17023SJohn Marino
7931e4b17023SJohn Marino for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
7932e4b17023SJohn Marino {
7933e4b17023SJohn Marino TYPE_SIZE (t) = TYPE_SIZE (type);
7934e4b17023SJohn Marino TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
7935e4b17023SJohn Marino TYPE_SIZES_GIMPLIFIED (t) = 1;
7936e4b17023SJohn Marino }
7937e4b17023SJohn Marino }
7938e4b17023SJohn Marino
7939e4b17023SJohn Marino /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
7940e4b17023SJohn Marino a size or position, has had all of its SAVE_EXPRs evaluated.
7941e4b17023SJohn Marino We add any required statements to *STMT_P. */
7942e4b17023SJohn Marino
7943e4b17023SJohn Marino void
gimplify_one_sizepos(tree * expr_p,gimple_seq * stmt_p)7944e4b17023SJohn Marino gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
7945e4b17023SJohn Marino {
7946e4b17023SJohn Marino tree type, expr = *expr_p;
7947e4b17023SJohn Marino
7948e4b17023SJohn Marino /* We don't do anything if the value isn't there, is constant, or contains
7949e4b17023SJohn Marino A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
7950e4b17023SJohn Marino a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
7951e4b17023SJohn Marino will want to replace it with a new variable, but that will cause problems
7952e4b17023SJohn Marino if this type is from outside the function. It's OK to have that here. */
79535ce9237cSJohn Marino if (is_gimple_sizepos (expr))
7954e4b17023SJohn Marino return;
7955e4b17023SJohn Marino
7956e4b17023SJohn Marino type = TREE_TYPE (expr);
7957e4b17023SJohn Marino *expr_p = unshare_expr (expr);
7958e4b17023SJohn Marino
7959e4b17023SJohn Marino gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue);
7960e4b17023SJohn Marino expr = *expr_p;
7961e4b17023SJohn Marino
7962e4b17023SJohn Marino /* Verify that we've an exact type match with the original expression.
7963e4b17023SJohn Marino In particular, we do not wish to drop a "sizetype" in favour of a
7964e4b17023SJohn Marino type of similar dimensions. We don't want to pollute the generic
7965e4b17023SJohn Marino type-stripping code with this knowledge because it doesn't matter
7966e4b17023SJohn Marino for the bulk of GENERIC/GIMPLE. It only matters that TYPE_SIZE_UNIT
7967e4b17023SJohn Marino and friends retain their "sizetype-ness". */
7968e4b17023SJohn Marino if (TREE_TYPE (expr) != type
7969e4b17023SJohn Marino && TREE_CODE (type) == INTEGER_TYPE
7970e4b17023SJohn Marino && TYPE_IS_SIZETYPE (type))
7971e4b17023SJohn Marino {
7972e4b17023SJohn Marino tree tmp;
7973e4b17023SJohn Marino gimple stmt;
7974e4b17023SJohn Marino
7975e4b17023SJohn Marino *expr_p = create_tmp_var (type, NULL);
7976e4b17023SJohn Marino tmp = build1 (NOP_EXPR, type, expr);
7977e4b17023SJohn Marino stmt = gimplify_assign (*expr_p, tmp, stmt_p);
7978e4b17023SJohn Marino gimple_set_location (stmt, EXPR_LOC_OR_HERE (expr));
7979e4b17023SJohn Marino }
7980e4b17023SJohn Marino }
7981e4b17023SJohn Marino
7982e4b17023SJohn Marino /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
7983e4b17023SJohn Marino containing the sequence of corresponding GIMPLE statements. If DO_PARMS
7984e4b17023SJohn Marino is true, also gimplify the parameters. */
7985e4b17023SJohn Marino
7986e4b17023SJohn Marino gimple
gimplify_body(tree fndecl,bool do_parms)7987e4b17023SJohn Marino gimplify_body (tree fndecl, bool do_parms)
7988e4b17023SJohn Marino {
7989e4b17023SJohn Marino location_t saved_location = input_location;
7990e4b17023SJohn Marino gimple_seq parm_stmts, seq;
7991e4b17023SJohn Marino gimple outer_bind;
7992e4b17023SJohn Marino struct gimplify_ctx gctx;
7993e4b17023SJohn Marino struct cgraph_node *cgn;
7994e4b17023SJohn Marino
7995e4b17023SJohn Marino timevar_push (TV_TREE_GIMPLIFY);
7996e4b17023SJohn Marino
7997e4b17023SJohn Marino /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
7998e4b17023SJohn Marino gimplification. */
7999e4b17023SJohn Marino default_rtl_profile ();
8000e4b17023SJohn Marino
8001e4b17023SJohn Marino gcc_assert (gimplify_ctxp == NULL);
8002e4b17023SJohn Marino push_gimplify_context (&gctx);
8003e4b17023SJohn Marino
8004e4b17023SJohn Marino /* Unshare most shared trees in the body and in that of any nested functions.
8005e4b17023SJohn Marino It would seem we don't have to do this for nested functions because
8006e4b17023SJohn Marino they are supposed to be output and then the outer function gimplified
8007e4b17023SJohn Marino first, but the g++ front end doesn't always do it that way. */
8008e4b17023SJohn Marino unshare_body (fndecl);
8009e4b17023SJohn Marino unvisit_body (fndecl);
8010e4b17023SJohn Marino
8011e4b17023SJohn Marino cgn = cgraph_get_node (fndecl);
8012e4b17023SJohn Marino if (cgn && cgn->origin)
8013e4b17023SJohn Marino nonlocal_vlas = pointer_set_create ();
8014e4b17023SJohn Marino
8015e4b17023SJohn Marino /* Make sure input_location isn't set to something weird. */
8016e4b17023SJohn Marino input_location = DECL_SOURCE_LOCATION (fndecl);
8017e4b17023SJohn Marino
8018e4b17023SJohn Marino /* Resolve callee-copies. This has to be done before processing
8019e4b17023SJohn Marino the body so that DECL_VALUE_EXPR gets processed correctly. */
8020e4b17023SJohn Marino parm_stmts = do_parms ? gimplify_parameters () : NULL;
8021e4b17023SJohn Marino
8022e4b17023SJohn Marino /* Gimplify the function's body. */
8023e4b17023SJohn Marino seq = NULL;
8024e4b17023SJohn Marino gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
8025e4b17023SJohn Marino outer_bind = gimple_seq_first_stmt (seq);
8026e4b17023SJohn Marino if (!outer_bind)
8027e4b17023SJohn Marino {
8028e4b17023SJohn Marino outer_bind = gimple_build_nop ();
8029e4b17023SJohn Marino gimplify_seq_add_stmt (&seq, outer_bind);
8030e4b17023SJohn Marino }
8031e4b17023SJohn Marino
8032e4b17023SJohn Marino /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
8033e4b17023SJohn Marino not the case, wrap everything in a GIMPLE_BIND to make it so. */
8034e4b17023SJohn Marino if (gimple_code (outer_bind) == GIMPLE_BIND
8035e4b17023SJohn Marino && gimple_seq_first (seq) == gimple_seq_last (seq))
8036e4b17023SJohn Marino ;
8037e4b17023SJohn Marino else
8038e4b17023SJohn Marino outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
8039e4b17023SJohn Marino
8040e4b17023SJohn Marino DECL_SAVED_TREE (fndecl) = NULL_TREE;
8041e4b17023SJohn Marino
8042e4b17023SJohn Marino /* If we had callee-copies statements, insert them at the beginning
8043e4b17023SJohn Marino of the function and clear DECL_VALUE_EXPR_P on the parameters. */
8044e4b17023SJohn Marino if (!gimple_seq_empty_p (parm_stmts))
8045e4b17023SJohn Marino {
8046e4b17023SJohn Marino tree parm;
8047e4b17023SJohn Marino
8048e4b17023SJohn Marino gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
8049e4b17023SJohn Marino gimple_bind_set_body (outer_bind, parm_stmts);
8050e4b17023SJohn Marino
8051e4b17023SJohn Marino for (parm = DECL_ARGUMENTS (current_function_decl);
8052e4b17023SJohn Marino parm; parm = DECL_CHAIN (parm))
8053e4b17023SJohn Marino if (DECL_HAS_VALUE_EXPR_P (parm))
8054e4b17023SJohn Marino {
8055e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (parm) = 0;
8056e4b17023SJohn Marino DECL_IGNORED_P (parm) = 0;
8057e4b17023SJohn Marino }
8058e4b17023SJohn Marino }
8059e4b17023SJohn Marino
8060e4b17023SJohn Marino if (nonlocal_vlas)
8061e4b17023SJohn Marino {
8062*95d28233SJohn Marino if (nonlocal_vla_vars)
8063*95d28233SJohn Marino {
8064*95d28233SJohn Marino /* tree-nested.c may later on call declare_vars (..., true);
8065*95d28233SJohn Marino which relies on BLOCK_VARS chain to be the tail of the
8066*95d28233SJohn Marino gimple_bind_vars chain. Ensure we don't violate that
8067*95d28233SJohn Marino assumption. */
8068*95d28233SJohn Marino if (gimple_bind_block (outer_bind)
8069*95d28233SJohn Marino == DECL_INITIAL (current_function_decl))
8070*95d28233SJohn Marino declare_vars (nonlocal_vla_vars, outer_bind, true);
8071*95d28233SJohn Marino else
8072*95d28233SJohn Marino BLOCK_VARS (DECL_INITIAL (current_function_decl))
8073*95d28233SJohn Marino = chainon (BLOCK_VARS (DECL_INITIAL (current_function_decl)),
8074*95d28233SJohn Marino nonlocal_vla_vars);
8075*95d28233SJohn Marino nonlocal_vla_vars = NULL_TREE;
8076*95d28233SJohn Marino }
8077e4b17023SJohn Marino pointer_set_destroy (nonlocal_vlas);
8078e4b17023SJohn Marino nonlocal_vlas = NULL;
8079e4b17023SJohn Marino }
8080e4b17023SJohn Marino
8081e4b17023SJohn Marino pop_gimplify_context (outer_bind);
8082e4b17023SJohn Marino gcc_assert (gimplify_ctxp == NULL);
8083e4b17023SJohn Marino
8084e4b17023SJohn Marino if (!seen_error ())
8085e4b17023SJohn Marino verify_gimple_in_seq (gimple_bind_body (outer_bind));
8086e4b17023SJohn Marino
8087e4b17023SJohn Marino timevar_pop (TV_TREE_GIMPLIFY);
8088e4b17023SJohn Marino input_location = saved_location;
8089e4b17023SJohn Marino
8090e4b17023SJohn Marino return outer_bind;
8091e4b17023SJohn Marino }
8092e4b17023SJohn Marino
8093e4b17023SJohn Marino typedef char *char_p; /* For DEF_VEC_P. */
8094e4b17023SJohn Marino DEF_VEC_P(char_p);
8095e4b17023SJohn Marino DEF_VEC_ALLOC_P(char_p,heap);
8096e4b17023SJohn Marino
8097e4b17023SJohn Marino /* Return whether we should exclude FNDECL from instrumentation. */
8098e4b17023SJohn Marino
8099e4b17023SJohn Marino static bool
flag_instrument_functions_exclude_p(tree fndecl)8100e4b17023SJohn Marino flag_instrument_functions_exclude_p (tree fndecl)
8101e4b17023SJohn Marino {
8102e4b17023SJohn Marino VEC(char_p,heap) *vec;
8103e4b17023SJohn Marino
8104e4b17023SJohn Marino vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_functions;
8105e4b17023SJohn Marino if (VEC_length (char_p, vec) > 0)
8106e4b17023SJohn Marino {
8107e4b17023SJohn Marino const char *name;
8108e4b17023SJohn Marino int i;
8109e4b17023SJohn Marino char *s;
8110e4b17023SJohn Marino
8111e4b17023SJohn Marino name = lang_hooks.decl_printable_name (fndecl, 0);
8112e4b17023SJohn Marino FOR_EACH_VEC_ELT (char_p, vec, i, s)
8113e4b17023SJohn Marino if (strstr (name, s) != NULL)
8114e4b17023SJohn Marino return true;
8115e4b17023SJohn Marino }
8116e4b17023SJohn Marino
8117e4b17023SJohn Marino vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_files;
8118e4b17023SJohn Marino if (VEC_length (char_p, vec) > 0)
8119e4b17023SJohn Marino {
8120e4b17023SJohn Marino const char *name;
8121e4b17023SJohn Marino int i;
8122e4b17023SJohn Marino char *s;
8123e4b17023SJohn Marino
8124e4b17023SJohn Marino name = DECL_SOURCE_FILE (fndecl);
8125e4b17023SJohn Marino FOR_EACH_VEC_ELT (char_p, vec, i, s)
8126e4b17023SJohn Marino if (strstr (name, s) != NULL)
8127e4b17023SJohn Marino return true;
8128e4b17023SJohn Marino }
8129e4b17023SJohn Marino
8130e4b17023SJohn Marino return false;
8131e4b17023SJohn Marino }
8132e4b17023SJohn Marino
8133e4b17023SJohn Marino /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
8134e4b17023SJohn Marino node for the function we want to gimplify.
8135e4b17023SJohn Marino
8136e4b17023SJohn Marino Return the sequence of GIMPLE statements corresponding to the body
8137e4b17023SJohn Marino of FNDECL. */
8138e4b17023SJohn Marino
8139e4b17023SJohn Marino void
gimplify_function_tree(tree fndecl)8140e4b17023SJohn Marino gimplify_function_tree (tree fndecl)
8141e4b17023SJohn Marino {
8142e4b17023SJohn Marino tree oldfn, parm, ret;
8143e4b17023SJohn Marino gimple_seq seq;
8144e4b17023SJohn Marino gimple bind;
8145e4b17023SJohn Marino
8146e4b17023SJohn Marino gcc_assert (!gimple_body (fndecl));
8147e4b17023SJohn Marino
8148e4b17023SJohn Marino oldfn = current_function_decl;
8149e4b17023SJohn Marino current_function_decl = fndecl;
8150e4b17023SJohn Marino if (DECL_STRUCT_FUNCTION (fndecl))
8151e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (fndecl));
8152e4b17023SJohn Marino else
8153e4b17023SJohn Marino push_struct_function (fndecl);
8154e4b17023SJohn Marino
8155e4b17023SJohn Marino for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
8156e4b17023SJohn Marino {
8157e4b17023SJohn Marino /* Preliminarily mark non-addressed complex variables as eligible
8158e4b17023SJohn Marino for promotion to gimple registers. We'll transform their uses
8159e4b17023SJohn Marino as we find them. */
8160e4b17023SJohn Marino if ((TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
8161e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (parm)) == VECTOR_TYPE)
8162e4b17023SJohn Marino && !TREE_THIS_VOLATILE (parm)
8163e4b17023SJohn Marino && !needs_to_live_in_memory (parm))
8164e4b17023SJohn Marino DECL_GIMPLE_REG_P (parm) = 1;
8165e4b17023SJohn Marino }
8166e4b17023SJohn Marino
8167e4b17023SJohn Marino ret = DECL_RESULT (fndecl);
8168e4b17023SJohn Marino if ((TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE
8169e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (ret)) == VECTOR_TYPE)
8170e4b17023SJohn Marino && !needs_to_live_in_memory (ret))
8171e4b17023SJohn Marino DECL_GIMPLE_REG_P (ret) = 1;
8172e4b17023SJohn Marino
8173e4b17023SJohn Marino bind = gimplify_body (fndecl, true);
8174e4b17023SJohn Marino
8175e4b17023SJohn Marino /* The tree body of the function is no longer needed, replace it
8176e4b17023SJohn Marino with the new GIMPLE body. */
8177e4b17023SJohn Marino seq = gimple_seq_alloc ();
8178e4b17023SJohn Marino gimple_seq_add_stmt (&seq, bind);
8179e4b17023SJohn Marino gimple_set_body (fndecl, seq);
8180e4b17023SJohn Marino
8181e4b17023SJohn Marino /* If we're instrumenting function entry/exit, then prepend the call to
8182e4b17023SJohn Marino the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
8183e4b17023SJohn Marino catch the exit hook. */
8184e4b17023SJohn Marino /* ??? Add some way to ignore exceptions for this TFE. */
8185e4b17023SJohn Marino if (flag_instrument_function_entry_exit
8186e4b17023SJohn Marino && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
8187e4b17023SJohn Marino && !flag_instrument_functions_exclude_p (fndecl))
8188e4b17023SJohn Marino {
8189e4b17023SJohn Marino tree x;
8190e4b17023SJohn Marino gimple new_bind;
8191e4b17023SJohn Marino gimple tf;
8192e4b17023SJohn Marino gimple_seq cleanup = NULL, body = NULL;
8193e4b17023SJohn Marino tree tmp_var;
8194e4b17023SJohn Marino gimple call;
8195e4b17023SJohn Marino
8196e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
8197e4b17023SJohn Marino call = gimple_build_call (x, 1, integer_zero_node);
8198e4b17023SJohn Marino tmp_var = create_tmp_var (ptr_type_node, "return_addr");
8199e4b17023SJohn Marino gimple_call_set_lhs (call, tmp_var);
8200e4b17023SJohn Marino gimplify_seq_add_stmt (&cleanup, call);
8201e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
8202e4b17023SJohn Marino call = gimple_build_call (x, 2,
8203e4b17023SJohn Marino build_fold_addr_expr (current_function_decl),
8204e4b17023SJohn Marino tmp_var);
8205e4b17023SJohn Marino gimplify_seq_add_stmt (&cleanup, call);
8206e4b17023SJohn Marino tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
8207e4b17023SJohn Marino
8208e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
8209e4b17023SJohn Marino call = gimple_build_call (x, 1, integer_zero_node);
8210e4b17023SJohn Marino tmp_var = create_tmp_var (ptr_type_node, "return_addr");
8211e4b17023SJohn Marino gimple_call_set_lhs (call, tmp_var);
8212e4b17023SJohn Marino gimplify_seq_add_stmt (&body, call);
8213e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
8214e4b17023SJohn Marino call = gimple_build_call (x, 2,
8215e4b17023SJohn Marino build_fold_addr_expr (current_function_decl),
8216e4b17023SJohn Marino tmp_var);
8217e4b17023SJohn Marino gimplify_seq_add_stmt (&body, call);
8218e4b17023SJohn Marino gimplify_seq_add_stmt (&body, tf);
8219e4b17023SJohn Marino new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind));
8220e4b17023SJohn Marino /* Clear the block for BIND, since it is no longer directly inside
8221e4b17023SJohn Marino the function, but within a try block. */
8222e4b17023SJohn Marino gimple_bind_set_block (bind, NULL);
8223e4b17023SJohn Marino
8224e4b17023SJohn Marino /* Replace the current function body with the body
8225e4b17023SJohn Marino wrapped in the try/finally TF. */
8226e4b17023SJohn Marino seq = gimple_seq_alloc ();
8227e4b17023SJohn Marino gimple_seq_add_stmt (&seq, new_bind);
8228e4b17023SJohn Marino gimple_set_body (fndecl, seq);
8229e4b17023SJohn Marino }
8230e4b17023SJohn Marino
8231e4b17023SJohn Marino DECL_SAVED_TREE (fndecl) = NULL_TREE;
8232e4b17023SJohn Marino cfun->curr_properties = PROP_gimple_any;
8233e4b17023SJohn Marino
8234e4b17023SJohn Marino current_function_decl = oldfn;
8235e4b17023SJohn Marino pop_cfun ();
8236e4b17023SJohn Marino }
8237e4b17023SJohn Marino
8238e4b17023SJohn Marino /* Some transformations like inlining may invalidate the GIMPLE form
8239e4b17023SJohn Marino for operands. This function traverses all the operands in STMT and
8240e4b17023SJohn Marino gimplifies anything that is not a valid gimple operand. Any new
8241e4b17023SJohn Marino GIMPLE statements are inserted before *GSI_P. */
8242e4b17023SJohn Marino
8243e4b17023SJohn Marino void
gimple_regimplify_operands(gimple stmt,gimple_stmt_iterator * gsi_p)8244e4b17023SJohn Marino gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
8245e4b17023SJohn Marino {
8246e4b17023SJohn Marino size_t i, num_ops;
8247e4b17023SJohn Marino tree orig_lhs = NULL_TREE, lhs, t;
8248e4b17023SJohn Marino gimple_seq pre = NULL;
8249e4b17023SJohn Marino gimple post_stmt = NULL;
8250e4b17023SJohn Marino struct gimplify_ctx gctx;
8251e4b17023SJohn Marino
8252e4b17023SJohn Marino push_gimplify_context (&gctx);
8253e4b17023SJohn Marino gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun);
8254e4b17023SJohn Marino
8255e4b17023SJohn Marino switch (gimple_code (stmt))
8256e4b17023SJohn Marino {
8257e4b17023SJohn Marino case GIMPLE_COND:
8258e4b17023SJohn Marino gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL,
8259e4b17023SJohn Marino is_gimple_val, fb_rvalue);
8260e4b17023SJohn Marino gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
8261e4b17023SJohn Marino is_gimple_val, fb_rvalue);
8262e4b17023SJohn Marino break;
8263e4b17023SJohn Marino case GIMPLE_SWITCH:
8264e4b17023SJohn Marino gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL,
8265e4b17023SJohn Marino is_gimple_val, fb_rvalue);
8266e4b17023SJohn Marino break;
8267e4b17023SJohn Marino case GIMPLE_OMP_ATOMIC_LOAD:
8268e4b17023SJohn Marino gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
8269e4b17023SJohn Marino is_gimple_val, fb_rvalue);
8270e4b17023SJohn Marino break;
8271e4b17023SJohn Marino case GIMPLE_ASM:
8272e4b17023SJohn Marino {
8273e4b17023SJohn Marino size_t i, noutputs = gimple_asm_noutputs (stmt);
8274e4b17023SJohn Marino const char *constraint, **oconstraints;
8275e4b17023SJohn Marino bool allows_mem, allows_reg, is_inout;
8276e4b17023SJohn Marino
8277e4b17023SJohn Marino oconstraints
8278e4b17023SJohn Marino = (const char **) alloca ((noutputs) * sizeof (const char *));
8279e4b17023SJohn Marino for (i = 0; i < noutputs; i++)
8280e4b17023SJohn Marino {
8281e4b17023SJohn Marino tree op = gimple_asm_output_op (stmt, i);
8282e4b17023SJohn Marino constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
8283e4b17023SJohn Marino oconstraints[i] = constraint;
8284e4b17023SJohn Marino parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
8285e4b17023SJohn Marino &allows_reg, &is_inout);
8286e4b17023SJohn Marino gimplify_expr (&TREE_VALUE (op), &pre, NULL,
8287e4b17023SJohn Marino is_inout ? is_gimple_min_lval : is_gimple_lvalue,
8288e4b17023SJohn Marino fb_lvalue | fb_mayfail);
8289e4b17023SJohn Marino }
8290e4b17023SJohn Marino for (i = 0; i < gimple_asm_ninputs (stmt); i++)
8291e4b17023SJohn Marino {
8292e4b17023SJohn Marino tree op = gimple_asm_input_op (stmt, i);
8293e4b17023SJohn Marino constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
8294e4b17023SJohn Marino parse_input_constraint (&constraint, 0, 0, noutputs, 0,
8295e4b17023SJohn Marino oconstraints, &allows_mem, &allows_reg);
8296e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
8297e4b17023SJohn Marino allows_reg = 0;
8298e4b17023SJohn Marino if (!allows_reg && allows_mem)
8299e4b17023SJohn Marino gimplify_expr (&TREE_VALUE (op), &pre, NULL,
8300e4b17023SJohn Marino is_gimple_lvalue, fb_lvalue | fb_mayfail);
8301e4b17023SJohn Marino else
8302e4b17023SJohn Marino gimplify_expr (&TREE_VALUE (op), &pre, NULL,
8303e4b17023SJohn Marino is_gimple_asm_val, fb_rvalue);
8304e4b17023SJohn Marino }
8305e4b17023SJohn Marino }
8306e4b17023SJohn Marino break;
8307e4b17023SJohn Marino default:
8308e4b17023SJohn Marino /* NOTE: We start gimplifying operands from last to first to
8309e4b17023SJohn Marino make sure that side-effects on the RHS of calls, assignments
8310e4b17023SJohn Marino and ASMs are executed before the LHS. The ordering is not
8311e4b17023SJohn Marino important for other statements. */
8312e4b17023SJohn Marino num_ops = gimple_num_ops (stmt);
8313e4b17023SJohn Marino orig_lhs = gimple_get_lhs (stmt);
8314e4b17023SJohn Marino for (i = num_ops; i > 0; i--)
8315e4b17023SJohn Marino {
8316e4b17023SJohn Marino tree op = gimple_op (stmt, i - 1);
8317e4b17023SJohn Marino if (op == NULL_TREE)
8318e4b17023SJohn Marino continue;
8319e4b17023SJohn Marino if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
8320e4b17023SJohn Marino gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
8321e4b17023SJohn Marino else if (i == 2
8322e4b17023SJohn Marino && is_gimple_assign (stmt)
8323e4b17023SJohn Marino && num_ops == 2
8324e4b17023SJohn Marino && get_gimple_rhs_class (gimple_expr_code (stmt))
8325e4b17023SJohn Marino == GIMPLE_SINGLE_RHS)
8326e4b17023SJohn Marino gimplify_expr (&op, &pre, NULL,
8327e4b17023SJohn Marino rhs_predicate_for (gimple_assign_lhs (stmt)),
8328e4b17023SJohn Marino fb_rvalue);
8329e4b17023SJohn Marino else if (i == 2 && is_gimple_call (stmt))
8330e4b17023SJohn Marino {
8331e4b17023SJohn Marino if (TREE_CODE (op) == FUNCTION_DECL)
8332e4b17023SJohn Marino continue;
8333e4b17023SJohn Marino gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
8334e4b17023SJohn Marino }
8335e4b17023SJohn Marino else
8336e4b17023SJohn Marino gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
8337e4b17023SJohn Marino gimple_set_op (stmt, i - 1, op);
8338e4b17023SJohn Marino }
8339e4b17023SJohn Marino
8340e4b17023SJohn Marino lhs = gimple_get_lhs (stmt);
8341e4b17023SJohn Marino /* If the LHS changed it in a way that requires a simple RHS,
8342e4b17023SJohn Marino create temporary. */
8343e4b17023SJohn Marino if (lhs && !is_gimple_reg (lhs))
8344e4b17023SJohn Marino {
8345e4b17023SJohn Marino bool need_temp = false;
8346e4b17023SJohn Marino
8347e4b17023SJohn Marino if (is_gimple_assign (stmt)
8348e4b17023SJohn Marino && num_ops == 2
8349e4b17023SJohn Marino && get_gimple_rhs_class (gimple_expr_code (stmt))
8350e4b17023SJohn Marino == GIMPLE_SINGLE_RHS)
8351e4b17023SJohn Marino gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
8352e4b17023SJohn Marino rhs_predicate_for (gimple_assign_lhs (stmt)),
8353e4b17023SJohn Marino fb_rvalue);
8354e4b17023SJohn Marino else if (is_gimple_reg (lhs))
8355e4b17023SJohn Marino {
8356e4b17023SJohn Marino if (is_gimple_reg_type (TREE_TYPE (lhs)))
8357e4b17023SJohn Marino {
8358e4b17023SJohn Marino if (is_gimple_call (stmt))
8359e4b17023SJohn Marino {
8360e4b17023SJohn Marino i = gimple_call_flags (stmt);
8361e4b17023SJohn Marino if ((i & ECF_LOOPING_CONST_OR_PURE)
8362e4b17023SJohn Marino || !(i & (ECF_CONST | ECF_PURE)))
8363e4b17023SJohn Marino need_temp = true;
8364e4b17023SJohn Marino }
8365e4b17023SJohn Marino if (stmt_can_throw_internal (stmt))
8366e4b17023SJohn Marino need_temp = true;
8367e4b17023SJohn Marino }
8368e4b17023SJohn Marino }
8369e4b17023SJohn Marino else
8370e4b17023SJohn Marino {
8371e4b17023SJohn Marino if (is_gimple_reg_type (TREE_TYPE (lhs)))
8372e4b17023SJohn Marino need_temp = true;
8373e4b17023SJohn Marino else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
8374e4b17023SJohn Marino {
8375e4b17023SJohn Marino if (is_gimple_call (stmt))
8376e4b17023SJohn Marino {
8377e4b17023SJohn Marino tree fndecl = gimple_call_fndecl (stmt);
8378e4b17023SJohn Marino
8379e4b17023SJohn Marino if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
8380e4b17023SJohn Marino && !(fndecl && DECL_RESULT (fndecl)
8381e4b17023SJohn Marino && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
8382e4b17023SJohn Marino need_temp = true;
8383e4b17023SJohn Marino }
8384e4b17023SJohn Marino else
8385e4b17023SJohn Marino need_temp = true;
8386e4b17023SJohn Marino }
8387e4b17023SJohn Marino }
8388e4b17023SJohn Marino if (need_temp)
8389e4b17023SJohn Marino {
8390e4b17023SJohn Marino tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL);
8391e4b17023SJohn Marino
8392e4b17023SJohn Marino if (TREE_CODE (orig_lhs) == SSA_NAME)
8393e4b17023SJohn Marino orig_lhs = SSA_NAME_VAR (orig_lhs);
8394e4b17023SJohn Marino
8395e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
8396e4b17023SJohn Marino temp = make_ssa_name (temp, NULL);
8397e4b17023SJohn Marino gimple_set_lhs (stmt, temp);
8398e4b17023SJohn Marino post_stmt = gimple_build_assign (lhs, temp);
8399e4b17023SJohn Marino if (TREE_CODE (lhs) == SSA_NAME)
8400e4b17023SJohn Marino SSA_NAME_DEF_STMT (lhs) = post_stmt;
8401e4b17023SJohn Marino }
8402e4b17023SJohn Marino }
8403e4b17023SJohn Marino break;
8404e4b17023SJohn Marino }
8405e4b17023SJohn Marino
8406e4b17023SJohn Marino if (gimple_referenced_vars (cfun))
8407e4b17023SJohn Marino for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
8408e4b17023SJohn Marino add_referenced_var (t);
8409e4b17023SJohn Marino
8410e4b17023SJohn Marino if (!gimple_seq_empty_p (pre))
8411e4b17023SJohn Marino {
8412e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
8413e4b17023SJohn Marino {
8414e4b17023SJohn Marino gimple_stmt_iterator i;
8415e4b17023SJohn Marino
8416e4b17023SJohn Marino for (i = gsi_start (pre); !gsi_end_p (i); gsi_next (&i))
8417e4b17023SJohn Marino mark_symbols_for_renaming (gsi_stmt (i));
8418e4b17023SJohn Marino }
8419e4b17023SJohn Marino gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
8420e4b17023SJohn Marino }
8421e4b17023SJohn Marino if (post_stmt)
8422e4b17023SJohn Marino gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
8423e4b17023SJohn Marino
8424e4b17023SJohn Marino pop_gimplify_context (NULL);
8425e4b17023SJohn Marino }
8426e4b17023SJohn Marino
8427e4b17023SJohn Marino /* Expand EXPR to list of gimple statements STMTS. GIMPLE_TEST_F specifies
8428e4b17023SJohn Marino the predicate that will hold for the result. If VAR is not NULL, make the
8429e4b17023SJohn Marino base variable of the final destination be VAR if suitable. */
8430e4b17023SJohn Marino
8431e4b17023SJohn Marino tree
force_gimple_operand_1(tree expr,gimple_seq * stmts,gimple_predicate gimple_test_f,tree var)8432e4b17023SJohn Marino force_gimple_operand_1 (tree expr, gimple_seq *stmts,
8433e4b17023SJohn Marino gimple_predicate gimple_test_f, tree var)
8434e4b17023SJohn Marino {
8435e4b17023SJohn Marino tree t;
8436e4b17023SJohn Marino enum gimplify_status ret;
8437e4b17023SJohn Marino struct gimplify_ctx gctx;
8438e4b17023SJohn Marino
8439e4b17023SJohn Marino *stmts = NULL;
8440e4b17023SJohn Marino
8441e4b17023SJohn Marino /* gimple_test_f might be more strict than is_gimple_val, make
8442e4b17023SJohn Marino sure we pass both. Just checking gimple_test_f doesn't work
8443e4b17023SJohn Marino because most gimple predicates do not work recursively. */
8444e4b17023SJohn Marino if (is_gimple_val (expr)
8445e4b17023SJohn Marino && (*gimple_test_f) (expr))
8446e4b17023SJohn Marino return expr;
8447e4b17023SJohn Marino
8448e4b17023SJohn Marino push_gimplify_context (&gctx);
8449e4b17023SJohn Marino gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun);
8450e4b17023SJohn Marino gimplify_ctxp->allow_rhs_cond_expr = true;
8451e4b17023SJohn Marino
8452e4b17023SJohn Marino if (var)
8453e4b17023SJohn Marino expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
8454e4b17023SJohn Marino
8455e4b17023SJohn Marino if (TREE_CODE (expr) != MODIFY_EXPR
8456e4b17023SJohn Marino && TREE_TYPE (expr) == void_type_node)
8457e4b17023SJohn Marino {
8458e4b17023SJohn Marino gimplify_and_add (expr, stmts);
8459e4b17023SJohn Marino expr = NULL_TREE;
8460e4b17023SJohn Marino }
8461e4b17023SJohn Marino else
8462e4b17023SJohn Marino {
8463e4b17023SJohn Marino ret = gimplify_expr (&expr, stmts, NULL, gimple_test_f, fb_rvalue);
8464e4b17023SJohn Marino gcc_assert (ret != GS_ERROR);
8465e4b17023SJohn Marino }
8466e4b17023SJohn Marino
8467e4b17023SJohn Marino if (gimple_referenced_vars (cfun))
8468e4b17023SJohn Marino for (t = gimplify_ctxp->temps; t ; t = DECL_CHAIN (t))
8469e4b17023SJohn Marino add_referenced_var (t);
8470e4b17023SJohn Marino
8471e4b17023SJohn Marino pop_gimplify_context (NULL);
8472e4b17023SJohn Marino
8473e4b17023SJohn Marino return expr;
8474e4b17023SJohn Marino }
8475e4b17023SJohn Marino
8476e4b17023SJohn Marino /* Expand EXPR to list of gimple statements STMTS. If SIMPLE is true,
8477e4b17023SJohn Marino force the result to be either ssa_name or an invariant, otherwise
8478e4b17023SJohn Marino just force it to be a rhs expression. If VAR is not NULL, make the
8479e4b17023SJohn Marino base variable of the final destination be VAR if suitable. */
8480e4b17023SJohn Marino
8481e4b17023SJohn Marino tree
force_gimple_operand(tree expr,gimple_seq * stmts,bool simple,tree var)8482e4b17023SJohn Marino force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
8483e4b17023SJohn Marino {
8484e4b17023SJohn Marino return force_gimple_operand_1 (expr, stmts,
8485e4b17023SJohn Marino simple ? is_gimple_val : is_gimple_reg_rhs,
8486e4b17023SJohn Marino var);
8487e4b17023SJohn Marino }
8488e4b17023SJohn Marino
8489e4b17023SJohn Marino /* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
8490e4b17023SJohn Marino and VAR. If some statements are produced, emits them at GSI.
8491e4b17023SJohn Marino If BEFORE is true. the statements are appended before GSI, otherwise
8492e4b17023SJohn Marino they are appended after it. M specifies the way GSI moves after
8493e4b17023SJohn Marino insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values). */
8494e4b17023SJohn Marino
8495e4b17023SJohn Marino tree
force_gimple_operand_gsi_1(gimple_stmt_iterator * gsi,tree expr,gimple_predicate gimple_test_f,tree var,bool before,enum gsi_iterator_update m)8496e4b17023SJohn Marino force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
8497e4b17023SJohn Marino gimple_predicate gimple_test_f,
8498e4b17023SJohn Marino tree var, bool before,
8499e4b17023SJohn Marino enum gsi_iterator_update m)
8500e4b17023SJohn Marino {
8501e4b17023SJohn Marino gimple_seq stmts;
8502e4b17023SJohn Marino
8503e4b17023SJohn Marino expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
8504e4b17023SJohn Marino
8505e4b17023SJohn Marino if (!gimple_seq_empty_p (stmts))
8506e4b17023SJohn Marino {
8507e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
8508e4b17023SJohn Marino {
8509e4b17023SJohn Marino gimple_stmt_iterator i;
8510e4b17023SJohn Marino
8511e4b17023SJohn Marino for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
8512e4b17023SJohn Marino mark_symbols_for_renaming (gsi_stmt (i));
8513e4b17023SJohn Marino }
8514e4b17023SJohn Marino
8515e4b17023SJohn Marino if (before)
8516e4b17023SJohn Marino gsi_insert_seq_before (gsi, stmts, m);
8517e4b17023SJohn Marino else
8518e4b17023SJohn Marino gsi_insert_seq_after (gsi, stmts, m);
8519e4b17023SJohn Marino }
8520e4b17023SJohn Marino
8521e4b17023SJohn Marino return expr;
8522e4b17023SJohn Marino }
8523e4b17023SJohn Marino
8524e4b17023SJohn Marino /* Invoke force_gimple_operand_1 for EXPR with parameter VAR.
8525e4b17023SJohn Marino If SIMPLE is true, force the result to be either ssa_name or an invariant,
8526e4b17023SJohn Marino otherwise just force it to be a rhs expression. If some statements are
8527e4b17023SJohn Marino produced, emits them at GSI. If BEFORE is true, the statements are
8528e4b17023SJohn Marino appended before GSI, otherwise they are appended after it. M specifies
8529e4b17023SJohn Marino the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
8530e4b17023SJohn Marino are the usual values). */
8531e4b17023SJohn Marino
8532e4b17023SJohn Marino tree
force_gimple_operand_gsi(gimple_stmt_iterator * gsi,tree expr,bool simple_p,tree var,bool before,enum gsi_iterator_update m)8533e4b17023SJohn Marino force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
8534e4b17023SJohn Marino bool simple_p, tree var, bool before,
8535e4b17023SJohn Marino enum gsi_iterator_update m)
8536e4b17023SJohn Marino {
8537e4b17023SJohn Marino return force_gimple_operand_gsi_1 (gsi, expr,
8538e4b17023SJohn Marino simple_p
8539e4b17023SJohn Marino ? is_gimple_val : is_gimple_reg_rhs,
8540e4b17023SJohn Marino var, before, m);
8541e4b17023SJohn Marino }
8542e4b17023SJohn Marino
8543e4b17023SJohn Marino
8544e4b17023SJohn Marino #include "gt-gimplify.h"
8545