xref: /dflybsd-src/contrib/gcc-4.7/gcc/gimplify.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
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, &reg_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