1*e4b17023SJohn Marino /* Nested function decomposition for GIMPLE.
2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
8*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino any later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*e4b17023SJohn Marino GNU General Public License for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "tm_p.h"
27*e4b17023SJohn Marino #include "function.h"
28*e4b17023SJohn Marino #include "tree-dump.h"
29*e4b17023SJohn Marino #include "tree-inline.h"
30*e4b17023SJohn Marino #include "gimple.h"
31*e4b17023SJohn Marino #include "tree-iterator.h"
32*e4b17023SJohn Marino #include "tree-flow.h"
33*e4b17023SJohn Marino #include "cgraph.h"
34*e4b17023SJohn Marino #include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */
35*e4b17023SJohn Marino #include "langhooks.h"
36*e4b17023SJohn Marino #include "pointer-set.h"
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino
39*e4b17023SJohn Marino /* The object of this pass is to lower the representation of a set of nested
40*e4b17023SJohn Marino functions in order to expose all of the gory details of the various
41*e4b17023SJohn Marino nonlocal references. We want to do this sooner rather than later, in
42*e4b17023SJohn Marino order to give us more freedom in emitting all of the functions in question.
43*e4b17023SJohn Marino
44*e4b17023SJohn Marino Back in olden times, when gcc was young, we developed an insanely
45*e4b17023SJohn Marino complicated scheme whereby variables which were referenced nonlocally
46*e4b17023SJohn Marino were forced to live in the stack of the declaring function, and then
47*e4b17023SJohn Marino the nested functions magically discovered where these variables were
48*e4b17023SJohn Marino placed. In order for this scheme to function properly, it required
49*e4b17023SJohn Marino that the outer function be partially expanded, then we switch to
50*e4b17023SJohn Marino compiling the inner function, and once done with those we switch back
51*e4b17023SJohn Marino to compiling the outer function. Such delicate ordering requirements
52*e4b17023SJohn Marino makes it difficult to do whole translation unit optimizations
53*e4b17023SJohn Marino involving such functions.
54*e4b17023SJohn Marino
55*e4b17023SJohn Marino The implementation here is much more direct. Everything that can be
56*e4b17023SJohn Marino referenced by an inner function is a member of an explicitly created
57*e4b17023SJohn Marino structure herein called the "nonlocal frame struct". The incoming
58*e4b17023SJohn Marino static chain for a nested function is a pointer to this struct in
59*e4b17023SJohn Marino the parent. In this way, we settle on known offsets from a known
60*e4b17023SJohn Marino base, and so are decoupled from the logic that places objects in the
61*e4b17023SJohn Marino function's stack frame. More importantly, we don't have to wait for
62*e4b17023SJohn Marino that to happen -- since the compilation of the inner function is no
63*e4b17023SJohn Marino longer tied to a real stack frame, the nonlocal frame struct can be
64*e4b17023SJohn Marino allocated anywhere. Which means that the outer function is now
65*e4b17023SJohn Marino inlinable.
66*e4b17023SJohn Marino
67*e4b17023SJohn Marino Theory of operation here is very simple. Iterate over all the
68*e4b17023SJohn Marino statements in all the functions (depth first) several times,
69*e4b17023SJohn Marino allocating structures and fields on demand. In general we want to
70*e4b17023SJohn Marino examine inner functions first, so that we can avoid making changes
71*e4b17023SJohn Marino to outer functions which are unnecessary.
72*e4b17023SJohn Marino
73*e4b17023SJohn Marino The order of the passes matters a bit, in that later passes will be
74*e4b17023SJohn Marino skipped if it is discovered that the functions don't actually interact
75*e4b17023SJohn Marino at all. That is, they're nested in the lexical sense but could have
76*e4b17023SJohn Marino been written as independent functions without change. */
77*e4b17023SJohn Marino
78*e4b17023SJohn Marino
79*e4b17023SJohn Marino struct nesting_info
80*e4b17023SJohn Marino {
81*e4b17023SJohn Marino struct nesting_info *outer;
82*e4b17023SJohn Marino struct nesting_info *inner;
83*e4b17023SJohn Marino struct nesting_info *next;
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino struct pointer_map_t *field_map;
86*e4b17023SJohn Marino struct pointer_map_t *var_map;
87*e4b17023SJohn Marino struct pointer_set_t *mem_refs;
88*e4b17023SJohn Marino bitmap suppress_expansion;
89*e4b17023SJohn Marino
90*e4b17023SJohn Marino tree context;
91*e4b17023SJohn Marino tree new_local_var_chain;
92*e4b17023SJohn Marino tree debug_var_chain;
93*e4b17023SJohn Marino tree frame_type;
94*e4b17023SJohn Marino tree frame_decl;
95*e4b17023SJohn Marino tree chain_field;
96*e4b17023SJohn Marino tree chain_decl;
97*e4b17023SJohn Marino tree nl_goto_field;
98*e4b17023SJohn Marino
99*e4b17023SJohn Marino bool any_parm_remapped;
100*e4b17023SJohn Marino bool any_tramp_created;
101*e4b17023SJohn Marino char static_chain_added;
102*e4b17023SJohn Marino };
103*e4b17023SJohn Marino
104*e4b17023SJohn Marino
105*e4b17023SJohn Marino /* Iterate over the nesting tree, starting with ROOT, depth first. */
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino static inline struct nesting_info *
iter_nestinfo_start(struct nesting_info * root)108*e4b17023SJohn Marino iter_nestinfo_start (struct nesting_info *root)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino while (root->inner)
111*e4b17023SJohn Marino root = root->inner;
112*e4b17023SJohn Marino return root;
113*e4b17023SJohn Marino }
114*e4b17023SJohn Marino
115*e4b17023SJohn Marino static inline struct nesting_info *
iter_nestinfo_next(struct nesting_info * node)116*e4b17023SJohn Marino iter_nestinfo_next (struct nesting_info *node)
117*e4b17023SJohn Marino {
118*e4b17023SJohn Marino if (node->next)
119*e4b17023SJohn Marino return iter_nestinfo_start (node->next);
120*e4b17023SJohn Marino return node->outer;
121*e4b17023SJohn Marino }
122*e4b17023SJohn Marino
123*e4b17023SJohn Marino #define FOR_EACH_NEST_INFO(I, ROOT) \
124*e4b17023SJohn Marino for ((I) = iter_nestinfo_start (ROOT); (I); (I) = iter_nestinfo_next (I))
125*e4b17023SJohn Marino
126*e4b17023SJohn Marino /* Obstack used for the bitmaps in the struct above. */
127*e4b17023SJohn Marino static struct bitmap_obstack nesting_info_bitmap_obstack;
128*e4b17023SJohn Marino
129*e4b17023SJohn Marino
130*e4b17023SJohn Marino /* We're working in so many different function contexts simultaneously,
131*e4b17023SJohn Marino that create_tmp_var is dangerous. Prevent mishap. */
132*e4b17023SJohn Marino #define create_tmp_var cant_use_create_tmp_var_here_dummy
133*e4b17023SJohn Marino
134*e4b17023SJohn Marino /* Like create_tmp_var, except record the variable for registration at
135*e4b17023SJohn Marino the given nesting level. */
136*e4b17023SJohn Marino
137*e4b17023SJohn Marino static tree
create_tmp_var_for(struct nesting_info * info,tree type,const char * prefix)138*e4b17023SJohn Marino create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
139*e4b17023SJohn Marino {
140*e4b17023SJohn Marino tree tmp_var;
141*e4b17023SJohn Marino
142*e4b17023SJohn Marino /* If the type is of variable size or a type which must be created by the
143*e4b17023SJohn Marino frontend, something is wrong. Note that we explicitly allow
144*e4b17023SJohn Marino incomplete types here, since we create them ourselves here. */
145*e4b17023SJohn Marino gcc_assert (!TREE_ADDRESSABLE (type));
146*e4b17023SJohn Marino gcc_assert (!TYPE_SIZE_UNIT (type)
147*e4b17023SJohn Marino || TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
148*e4b17023SJohn Marino
149*e4b17023SJohn Marino tmp_var = create_tmp_var_raw (type, prefix);
150*e4b17023SJohn Marino DECL_CONTEXT (tmp_var) = info->context;
151*e4b17023SJohn Marino DECL_CHAIN (tmp_var) = info->new_local_var_chain;
152*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
153*e4b17023SJohn Marino if (TREE_CODE (type) == COMPLEX_TYPE
154*e4b17023SJohn Marino || TREE_CODE (type) == VECTOR_TYPE)
155*e4b17023SJohn Marino DECL_GIMPLE_REG_P (tmp_var) = 1;
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino info->new_local_var_chain = tmp_var;
158*e4b17023SJohn Marino
159*e4b17023SJohn Marino return tmp_var;
160*e4b17023SJohn Marino }
161*e4b17023SJohn Marino
162*e4b17023SJohn Marino /* Take the address of EXP to be used within function CONTEXT.
163*e4b17023SJohn Marino Mark it for addressability as necessary. */
164*e4b17023SJohn Marino
165*e4b17023SJohn Marino tree
build_addr(tree exp,tree context)166*e4b17023SJohn Marino build_addr (tree exp, tree context)
167*e4b17023SJohn Marino {
168*e4b17023SJohn Marino tree base = exp;
169*e4b17023SJohn Marino tree save_context;
170*e4b17023SJohn Marino tree retval;
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino while (handled_component_p (base))
173*e4b17023SJohn Marino base = TREE_OPERAND (base, 0);
174*e4b17023SJohn Marino
175*e4b17023SJohn Marino if (DECL_P (base))
176*e4b17023SJohn Marino TREE_ADDRESSABLE (base) = 1;
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino /* Building the ADDR_EXPR will compute a set of properties for
179*e4b17023SJohn Marino that ADDR_EXPR. Those properties are unfortunately context
180*e4b17023SJohn Marino specific, i.e., they are dependent on CURRENT_FUNCTION_DECL.
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino Temporarily set CURRENT_FUNCTION_DECL to the desired context,
183*e4b17023SJohn Marino build the ADDR_EXPR, then restore CURRENT_FUNCTION_DECL. That
184*e4b17023SJohn Marino way the properties are for the ADDR_EXPR are computed properly. */
185*e4b17023SJohn Marino save_context = current_function_decl;
186*e4b17023SJohn Marino current_function_decl = context;
187*e4b17023SJohn Marino retval = build_fold_addr_expr (exp);
188*e4b17023SJohn Marino current_function_decl = save_context;
189*e4b17023SJohn Marino return retval;
190*e4b17023SJohn Marino }
191*e4b17023SJohn Marino
192*e4b17023SJohn Marino /* Insert FIELD into TYPE, sorted by alignment requirements. */
193*e4b17023SJohn Marino
194*e4b17023SJohn Marino void
insert_field_into_struct(tree type,tree field)195*e4b17023SJohn Marino insert_field_into_struct (tree type, tree field)
196*e4b17023SJohn Marino {
197*e4b17023SJohn Marino tree *p;
198*e4b17023SJohn Marino
199*e4b17023SJohn Marino DECL_CONTEXT (field) = type;
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino for (p = &TYPE_FIELDS (type); *p ; p = &DECL_CHAIN (*p))
202*e4b17023SJohn Marino if (DECL_ALIGN (field) >= DECL_ALIGN (*p))
203*e4b17023SJohn Marino break;
204*e4b17023SJohn Marino
205*e4b17023SJohn Marino DECL_CHAIN (field) = *p;
206*e4b17023SJohn Marino *p = field;
207*e4b17023SJohn Marino
208*e4b17023SJohn Marino /* Set correct alignment for frame struct type. */
209*e4b17023SJohn Marino if (TYPE_ALIGN (type) < DECL_ALIGN (field))
210*e4b17023SJohn Marino TYPE_ALIGN (type) = DECL_ALIGN (field);
211*e4b17023SJohn Marino }
212*e4b17023SJohn Marino
213*e4b17023SJohn Marino /* Build or return the RECORD_TYPE that describes the frame state that is
214*e4b17023SJohn Marino shared between INFO->CONTEXT and its nested functions. This record will
215*e4b17023SJohn Marino not be complete until finalize_nesting_tree; up until that point we'll
216*e4b17023SJohn Marino be adding fields as necessary.
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino We also build the DECL that represents this frame in the function. */
219*e4b17023SJohn Marino
220*e4b17023SJohn Marino static tree
get_frame_type(struct nesting_info * info)221*e4b17023SJohn Marino get_frame_type (struct nesting_info *info)
222*e4b17023SJohn Marino {
223*e4b17023SJohn Marino tree type = info->frame_type;
224*e4b17023SJohn Marino if (!type)
225*e4b17023SJohn Marino {
226*e4b17023SJohn Marino char *name;
227*e4b17023SJohn Marino
228*e4b17023SJohn Marino type = make_node (RECORD_TYPE);
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino name = concat ("FRAME.",
231*e4b17023SJohn Marino IDENTIFIER_POINTER (DECL_NAME (info->context)),
232*e4b17023SJohn Marino NULL);
233*e4b17023SJohn Marino TYPE_NAME (type) = get_identifier (name);
234*e4b17023SJohn Marino free (name);
235*e4b17023SJohn Marino
236*e4b17023SJohn Marino info->frame_type = type;
237*e4b17023SJohn Marino info->frame_decl = create_tmp_var_for (info, type, "FRAME");
238*e4b17023SJohn Marino
239*e4b17023SJohn Marino /* ??? Always make it addressable for now, since it is meant to
240*e4b17023SJohn Marino be pointed to by the static chain pointer. This pessimizes
241*e4b17023SJohn Marino when it turns out that no static chains are needed because
242*e4b17023SJohn Marino the nested functions referencing non-local variables are not
243*e4b17023SJohn Marino reachable, but the true pessimization is to create the non-
244*e4b17023SJohn Marino local frame structure in the first place. */
245*e4b17023SJohn Marino TREE_ADDRESSABLE (info->frame_decl) = 1;
246*e4b17023SJohn Marino }
247*e4b17023SJohn Marino return type;
248*e4b17023SJohn Marino }
249*e4b17023SJohn Marino
250*e4b17023SJohn Marino /* Return true if DECL should be referenced by pointer in the non-local
251*e4b17023SJohn Marino frame structure. */
252*e4b17023SJohn Marino
253*e4b17023SJohn Marino static bool
use_pointer_in_frame(tree decl)254*e4b17023SJohn Marino use_pointer_in_frame (tree decl)
255*e4b17023SJohn Marino {
256*e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL)
257*e4b17023SJohn Marino {
258*e4b17023SJohn Marino /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable
259*e4b17023SJohn Marino sized decls, and inefficient to copy large aggregates. Don't bother
260*e4b17023SJohn Marino moving anything but scalar variables. */
261*e4b17023SJohn Marino return AGGREGATE_TYPE_P (TREE_TYPE (decl));
262*e4b17023SJohn Marino }
263*e4b17023SJohn Marino else
264*e4b17023SJohn Marino {
265*e4b17023SJohn Marino /* Variable sized types make things "interesting" in the frame. */
266*e4b17023SJohn Marino return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl));
267*e4b17023SJohn Marino }
268*e4b17023SJohn Marino }
269*e4b17023SJohn Marino
270*e4b17023SJohn Marino /* Given DECL, a non-locally accessed variable, find or create a field
271*e4b17023SJohn Marino in the non-local frame structure for the given nesting context. */
272*e4b17023SJohn Marino
273*e4b17023SJohn Marino static tree
lookup_field_for_decl(struct nesting_info * info,tree decl,enum insert_option insert)274*e4b17023SJohn Marino lookup_field_for_decl (struct nesting_info *info, tree decl,
275*e4b17023SJohn Marino enum insert_option insert)
276*e4b17023SJohn Marino {
277*e4b17023SJohn Marino void **slot;
278*e4b17023SJohn Marino
279*e4b17023SJohn Marino if (insert == NO_INSERT)
280*e4b17023SJohn Marino {
281*e4b17023SJohn Marino slot = pointer_map_contains (info->field_map, decl);
282*e4b17023SJohn Marino return slot ? (tree) *slot : NULL_TREE;
283*e4b17023SJohn Marino }
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino slot = pointer_map_insert (info->field_map, decl);
286*e4b17023SJohn Marino if (!*slot)
287*e4b17023SJohn Marino {
288*e4b17023SJohn Marino tree field = make_node (FIELD_DECL);
289*e4b17023SJohn Marino DECL_NAME (field) = DECL_NAME (decl);
290*e4b17023SJohn Marino
291*e4b17023SJohn Marino if (use_pointer_in_frame (decl))
292*e4b17023SJohn Marino {
293*e4b17023SJohn Marino TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
294*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
295*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = 1;
296*e4b17023SJohn Marino }
297*e4b17023SJohn Marino else
298*e4b17023SJohn Marino {
299*e4b17023SJohn Marino TREE_TYPE (field) = TREE_TYPE (decl);
300*e4b17023SJohn Marino DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (decl);
301*e4b17023SJohn Marino DECL_ALIGN (field) = DECL_ALIGN (decl);
302*e4b17023SJohn Marino DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
303*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl);
304*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
305*e4b17023SJohn Marino TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
306*e4b17023SJohn Marino }
307*e4b17023SJohn Marino
308*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field);
309*e4b17023SJohn Marino *slot = field;
310*e4b17023SJohn Marino
311*e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL)
312*e4b17023SJohn Marino info->any_parm_remapped = true;
313*e4b17023SJohn Marino }
314*e4b17023SJohn Marino
315*e4b17023SJohn Marino return (tree) *slot;
316*e4b17023SJohn Marino }
317*e4b17023SJohn Marino
318*e4b17023SJohn Marino /* Build or return the variable that holds the static chain within
319*e4b17023SJohn Marino INFO->CONTEXT. This variable may only be used within INFO->CONTEXT. */
320*e4b17023SJohn Marino
321*e4b17023SJohn Marino static tree
get_chain_decl(struct nesting_info * info)322*e4b17023SJohn Marino get_chain_decl (struct nesting_info *info)
323*e4b17023SJohn Marino {
324*e4b17023SJohn Marino tree decl = info->chain_decl;
325*e4b17023SJohn Marino
326*e4b17023SJohn Marino if (!decl)
327*e4b17023SJohn Marino {
328*e4b17023SJohn Marino tree type;
329*e4b17023SJohn Marino
330*e4b17023SJohn Marino type = get_frame_type (info->outer);
331*e4b17023SJohn Marino type = build_pointer_type (type);
332*e4b17023SJohn Marino
333*e4b17023SJohn Marino /* Note that this variable is *not* entered into any BIND_EXPR;
334*e4b17023SJohn Marino the construction of this variable is handled specially in
335*e4b17023SJohn Marino expand_function_start and initialize_inlined_parameters.
336*e4b17023SJohn Marino Note also that it's represented as a parameter. This is more
337*e4b17023SJohn Marino close to the truth, since the initial value does come from
338*e4b17023SJohn Marino the caller. */
339*e4b17023SJohn Marino decl = build_decl (DECL_SOURCE_LOCATION (info->context),
340*e4b17023SJohn Marino PARM_DECL, create_tmp_var_name ("CHAIN"), type);
341*e4b17023SJohn Marino DECL_ARTIFICIAL (decl) = 1;
342*e4b17023SJohn Marino DECL_IGNORED_P (decl) = 1;
343*e4b17023SJohn Marino TREE_USED (decl) = 1;
344*e4b17023SJohn Marino DECL_CONTEXT (decl) = info->context;
345*e4b17023SJohn Marino DECL_ARG_TYPE (decl) = type;
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino /* Tell tree-inline.c that we never write to this variable, so
348*e4b17023SJohn Marino it can copy-prop the replacement value immediately. */
349*e4b17023SJohn Marino TREE_READONLY (decl) = 1;
350*e4b17023SJohn Marino
351*e4b17023SJohn Marino info->chain_decl = decl;
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino if (dump_file
354*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS)
355*e4b17023SJohn Marino && !DECL_STATIC_CHAIN (info->context))
356*e4b17023SJohn Marino fprintf (dump_file, "Setting static-chain for %s\n",
357*e4b17023SJohn Marino lang_hooks.decl_printable_name (info->context, 2));
358*e4b17023SJohn Marino
359*e4b17023SJohn Marino DECL_STATIC_CHAIN (info->context) = 1;
360*e4b17023SJohn Marino }
361*e4b17023SJohn Marino return decl;
362*e4b17023SJohn Marino }
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino /* Build or return the field within the non-local frame state that holds
365*e4b17023SJohn Marino the static chain for INFO->CONTEXT. This is the way to walk back up
366*e4b17023SJohn Marino multiple nesting levels. */
367*e4b17023SJohn Marino
368*e4b17023SJohn Marino static tree
get_chain_field(struct nesting_info * info)369*e4b17023SJohn Marino get_chain_field (struct nesting_info *info)
370*e4b17023SJohn Marino {
371*e4b17023SJohn Marino tree field = info->chain_field;
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino if (!field)
374*e4b17023SJohn Marino {
375*e4b17023SJohn Marino tree type = build_pointer_type (get_frame_type (info->outer));
376*e4b17023SJohn Marino
377*e4b17023SJohn Marino field = make_node (FIELD_DECL);
378*e4b17023SJohn Marino DECL_NAME (field) = get_identifier ("__chain");
379*e4b17023SJohn Marino TREE_TYPE (field) = type;
380*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (type);
381*e4b17023SJohn Marino DECL_NONADDRESSABLE_P (field) = 1;
382*e4b17023SJohn Marino
383*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field);
384*e4b17023SJohn Marino
385*e4b17023SJohn Marino info->chain_field = field;
386*e4b17023SJohn Marino
387*e4b17023SJohn Marino if (dump_file
388*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS)
389*e4b17023SJohn Marino && !DECL_STATIC_CHAIN (info->context))
390*e4b17023SJohn Marino fprintf (dump_file, "Setting static-chain for %s\n",
391*e4b17023SJohn Marino lang_hooks.decl_printable_name (info->context, 2));
392*e4b17023SJohn Marino
393*e4b17023SJohn Marino DECL_STATIC_CHAIN (info->context) = 1;
394*e4b17023SJohn Marino }
395*e4b17023SJohn Marino return field;
396*e4b17023SJohn Marino }
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino /* Initialize a new temporary with the GIMPLE_CALL STMT. */
399*e4b17023SJohn Marino
400*e4b17023SJohn Marino static tree
init_tmp_var_with_call(struct nesting_info * info,gimple_stmt_iterator * gsi,gimple call)401*e4b17023SJohn Marino init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
402*e4b17023SJohn Marino gimple call)
403*e4b17023SJohn Marino {
404*e4b17023SJohn Marino tree t;
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino t = create_tmp_var_for (info, gimple_call_return_type (call), NULL);
407*e4b17023SJohn Marino gimple_call_set_lhs (call, t);
408*e4b17023SJohn Marino if (! gsi_end_p (*gsi))
409*e4b17023SJohn Marino gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
410*e4b17023SJohn Marino gsi_insert_before (gsi, call, GSI_SAME_STMT);
411*e4b17023SJohn Marino
412*e4b17023SJohn Marino return t;
413*e4b17023SJohn Marino }
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino
416*e4b17023SJohn Marino /* Copy EXP into a temporary. Allocate the temporary in the context of
417*e4b17023SJohn Marino INFO and insert the initialization statement before GSI. */
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino static tree
init_tmp_var(struct nesting_info * info,tree exp,gimple_stmt_iterator * gsi)420*e4b17023SJohn Marino init_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
421*e4b17023SJohn Marino {
422*e4b17023SJohn Marino tree t;
423*e4b17023SJohn Marino gimple stmt;
424*e4b17023SJohn Marino
425*e4b17023SJohn Marino t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
426*e4b17023SJohn Marino stmt = gimple_build_assign (t, exp);
427*e4b17023SJohn Marino if (! gsi_end_p (*gsi))
428*e4b17023SJohn Marino gimple_set_location (stmt, gimple_location (gsi_stmt (*gsi)));
429*e4b17023SJohn Marino gsi_insert_before_without_update (gsi, stmt, GSI_SAME_STMT);
430*e4b17023SJohn Marino
431*e4b17023SJohn Marino return t;
432*e4b17023SJohn Marino }
433*e4b17023SJohn Marino
434*e4b17023SJohn Marino
435*e4b17023SJohn Marino /* Similarly, but only do so to force EXP to satisfy is_gimple_val. */
436*e4b17023SJohn Marino
437*e4b17023SJohn Marino static tree
gsi_gimplify_val(struct nesting_info * info,tree exp,gimple_stmt_iterator * gsi)438*e4b17023SJohn Marino gsi_gimplify_val (struct nesting_info *info, tree exp,
439*e4b17023SJohn Marino gimple_stmt_iterator *gsi)
440*e4b17023SJohn Marino {
441*e4b17023SJohn Marino if (is_gimple_val (exp))
442*e4b17023SJohn Marino return exp;
443*e4b17023SJohn Marino else
444*e4b17023SJohn Marino return init_tmp_var (info, exp, gsi);
445*e4b17023SJohn Marino }
446*e4b17023SJohn Marino
447*e4b17023SJohn Marino /* Similarly, but copy from the temporary and insert the statement
448*e4b17023SJohn Marino after the iterator. */
449*e4b17023SJohn Marino
450*e4b17023SJohn Marino static tree
save_tmp_var(struct nesting_info * info,tree exp,gimple_stmt_iterator * gsi)451*e4b17023SJohn Marino save_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
452*e4b17023SJohn Marino {
453*e4b17023SJohn Marino tree t;
454*e4b17023SJohn Marino gimple stmt;
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
457*e4b17023SJohn Marino stmt = gimple_build_assign (exp, t);
458*e4b17023SJohn Marino if (! gsi_end_p (*gsi))
459*e4b17023SJohn Marino gimple_set_location (stmt, gimple_location (gsi_stmt (*gsi)));
460*e4b17023SJohn Marino gsi_insert_after_without_update (gsi, stmt, GSI_SAME_STMT);
461*e4b17023SJohn Marino
462*e4b17023SJohn Marino return t;
463*e4b17023SJohn Marino }
464*e4b17023SJohn Marino
465*e4b17023SJohn Marino /* Build or return the type used to represent a nested function trampoline. */
466*e4b17023SJohn Marino
467*e4b17023SJohn Marino static GTY(()) tree trampoline_type;
468*e4b17023SJohn Marino
469*e4b17023SJohn Marino static tree
get_trampoline_type(struct nesting_info * info)470*e4b17023SJohn Marino get_trampoline_type (struct nesting_info *info)
471*e4b17023SJohn Marino {
472*e4b17023SJohn Marino unsigned align, size;
473*e4b17023SJohn Marino tree t;
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino if (trampoline_type)
476*e4b17023SJohn Marino return trampoline_type;
477*e4b17023SJohn Marino
478*e4b17023SJohn Marino align = TRAMPOLINE_ALIGNMENT;
479*e4b17023SJohn Marino size = TRAMPOLINE_SIZE;
480*e4b17023SJohn Marino
481*e4b17023SJohn Marino /* If we won't be able to guarantee alignment simply via TYPE_ALIGN,
482*e4b17023SJohn Marino then allocate extra space so that we can do dynamic alignment. */
483*e4b17023SJohn Marino if (align > STACK_BOUNDARY)
484*e4b17023SJohn Marino {
485*e4b17023SJohn Marino size += ((align/BITS_PER_UNIT) - 1) & -(STACK_BOUNDARY/BITS_PER_UNIT);
486*e4b17023SJohn Marino align = STACK_BOUNDARY;
487*e4b17023SJohn Marino }
488*e4b17023SJohn Marino
489*e4b17023SJohn Marino t = build_index_type (size_int (size - 1));
490*e4b17023SJohn Marino t = build_array_type (char_type_node, t);
491*e4b17023SJohn Marino t = build_decl (DECL_SOURCE_LOCATION (info->context),
492*e4b17023SJohn Marino FIELD_DECL, get_identifier ("__data"), t);
493*e4b17023SJohn Marino DECL_ALIGN (t) = align;
494*e4b17023SJohn Marino DECL_USER_ALIGN (t) = 1;
495*e4b17023SJohn Marino
496*e4b17023SJohn Marino trampoline_type = make_node (RECORD_TYPE);
497*e4b17023SJohn Marino TYPE_NAME (trampoline_type) = get_identifier ("__builtin_trampoline");
498*e4b17023SJohn Marino TYPE_FIELDS (trampoline_type) = t;
499*e4b17023SJohn Marino layout_type (trampoline_type);
500*e4b17023SJohn Marino DECL_CONTEXT (t) = trampoline_type;
501*e4b17023SJohn Marino
502*e4b17023SJohn Marino return trampoline_type;
503*e4b17023SJohn Marino }
504*e4b17023SJohn Marino
505*e4b17023SJohn Marino /* Given DECL, a nested function, find or create a field in the non-local
506*e4b17023SJohn Marino frame structure for a trampoline for this function. */
507*e4b17023SJohn Marino
508*e4b17023SJohn Marino static tree
lookup_tramp_for_decl(struct nesting_info * info,tree decl,enum insert_option insert)509*e4b17023SJohn Marino lookup_tramp_for_decl (struct nesting_info *info, tree decl,
510*e4b17023SJohn Marino enum insert_option insert)
511*e4b17023SJohn Marino {
512*e4b17023SJohn Marino void **slot;
513*e4b17023SJohn Marino
514*e4b17023SJohn Marino if (insert == NO_INSERT)
515*e4b17023SJohn Marino {
516*e4b17023SJohn Marino slot = pointer_map_contains (info->var_map, decl);
517*e4b17023SJohn Marino return slot ? (tree) *slot : NULL_TREE;
518*e4b17023SJohn Marino }
519*e4b17023SJohn Marino
520*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl);
521*e4b17023SJohn Marino if (!*slot)
522*e4b17023SJohn Marino {
523*e4b17023SJohn Marino tree field = make_node (FIELD_DECL);
524*e4b17023SJohn Marino DECL_NAME (field) = DECL_NAME (decl);
525*e4b17023SJohn Marino TREE_TYPE (field) = get_trampoline_type (info);
526*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = 1;
527*e4b17023SJohn Marino
528*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field);
529*e4b17023SJohn Marino *slot = field;
530*e4b17023SJohn Marino
531*e4b17023SJohn Marino info->any_tramp_created = true;
532*e4b17023SJohn Marino }
533*e4b17023SJohn Marino
534*e4b17023SJohn Marino return (tree) *slot;
535*e4b17023SJohn Marino }
536*e4b17023SJohn Marino
537*e4b17023SJohn Marino /* Build or return the field within the non-local frame state that holds
538*e4b17023SJohn Marino the non-local goto "jmp_buf". The buffer itself is maintained by the
539*e4b17023SJohn Marino rtl middle-end as dynamic stack space is allocated. */
540*e4b17023SJohn Marino
541*e4b17023SJohn Marino static tree
get_nl_goto_field(struct nesting_info * info)542*e4b17023SJohn Marino get_nl_goto_field (struct nesting_info *info)
543*e4b17023SJohn Marino {
544*e4b17023SJohn Marino tree field = info->nl_goto_field;
545*e4b17023SJohn Marino if (!field)
546*e4b17023SJohn Marino {
547*e4b17023SJohn Marino unsigned size;
548*e4b17023SJohn Marino tree type;
549*e4b17023SJohn Marino
550*e4b17023SJohn Marino /* For __builtin_nonlocal_goto, we need N words. The first is the
551*e4b17023SJohn Marino frame pointer, the rest is for the target's stack pointer save
552*e4b17023SJohn Marino area. The number of words is controlled by STACK_SAVEAREA_MODE;
553*e4b17023SJohn Marino not the best interface, but it'll do for now. */
554*e4b17023SJohn Marino if (Pmode == ptr_mode)
555*e4b17023SJohn Marino type = ptr_type_node;
556*e4b17023SJohn Marino else
557*e4b17023SJohn Marino type = lang_hooks.types.type_for_mode (Pmode, 1);
558*e4b17023SJohn Marino
559*e4b17023SJohn Marino size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
560*e4b17023SJohn Marino size = size / GET_MODE_SIZE (Pmode);
561*e4b17023SJohn Marino size = size + 1;
562*e4b17023SJohn Marino
563*e4b17023SJohn Marino type = build_array_type
564*e4b17023SJohn Marino (type, build_index_type (size_int (size)));
565*e4b17023SJohn Marino
566*e4b17023SJohn Marino field = make_node (FIELD_DECL);
567*e4b17023SJohn Marino DECL_NAME (field) = get_identifier ("__nl_goto_buf");
568*e4b17023SJohn Marino TREE_TYPE (field) = type;
569*e4b17023SJohn Marino DECL_ALIGN (field) = TYPE_ALIGN (type);
570*e4b17023SJohn Marino TREE_ADDRESSABLE (field) = 1;
571*e4b17023SJohn Marino
572*e4b17023SJohn Marino insert_field_into_struct (get_frame_type (info), field);
573*e4b17023SJohn Marino
574*e4b17023SJohn Marino info->nl_goto_field = field;
575*e4b17023SJohn Marino }
576*e4b17023SJohn Marino
577*e4b17023SJohn Marino return field;
578*e4b17023SJohn Marino }
579*e4b17023SJohn Marino
580*e4b17023SJohn Marino /* Invoke CALLBACK on all statements of GIMPLE sequence SEQ. */
581*e4b17023SJohn Marino
582*e4b17023SJohn Marino static void
walk_body(walk_stmt_fn callback_stmt,walk_tree_fn callback_op,struct nesting_info * info,gimple_seq seq)583*e4b17023SJohn Marino walk_body (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
584*e4b17023SJohn Marino struct nesting_info *info, gimple_seq seq)
585*e4b17023SJohn Marino {
586*e4b17023SJohn Marino struct walk_stmt_info wi;
587*e4b17023SJohn Marino
588*e4b17023SJohn Marino memset (&wi, 0, sizeof (wi));
589*e4b17023SJohn Marino wi.info = info;
590*e4b17023SJohn Marino wi.val_only = true;
591*e4b17023SJohn Marino walk_gimple_seq (seq, callback_stmt, callback_op, &wi);
592*e4b17023SJohn Marino }
593*e4b17023SJohn Marino
594*e4b17023SJohn Marino
595*e4b17023SJohn Marino /* Invoke CALLBACK_STMT/CALLBACK_OP on all statements of INFO->CONTEXT. */
596*e4b17023SJohn Marino
597*e4b17023SJohn Marino static inline void
walk_function(walk_stmt_fn callback_stmt,walk_tree_fn callback_op,struct nesting_info * info)598*e4b17023SJohn Marino walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
599*e4b17023SJohn Marino struct nesting_info *info)
600*e4b17023SJohn Marino {
601*e4b17023SJohn Marino walk_body (callback_stmt, callback_op, info, gimple_body (info->context));
602*e4b17023SJohn Marino }
603*e4b17023SJohn Marino
604*e4b17023SJohn Marino /* Invoke CALLBACK on a GIMPLE_OMP_FOR's init, cond, incr and pre-body. */
605*e4b17023SJohn Marino
606*e4b17023SJohn Marino static void
walk_gimple_omp_for(gimple for_stmt,walk_stmt_fn callback_stmt,walk_tree_fn callback_op,struct nesting_info * info)607*e4b17023SJohn Marino walk_gimple_omp_for (gimple for_stmt,
608*e4b17023SJohn Marino walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
609*e4b17023SJohn Marino struct nesting_info *info)
610*e4b17023SJohn Marino {
611*e4b17023SJohn Marino struct walk_stmt_info wi;
612*e4b17023SJohn Marino gimple_seq seq;
613*e4b17023SJohn Marino tree t;
614*e4b17023SJohn Marino size_t i;
615*e4b17023SJohn Marino
616*e4b17023SJohn Marino walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body (for_stmt));
617*e4b17023SJohn Marino
618*e4b17023SJohn Marino seq = gimple_seq_alloc ();
619*e4b17023SJohn Marino memset (&wi, 0, sizeof (wi));
620*e4b17023SJohn Marino wi.info = info;
621*e4b17023SJohn Marino wi.gsi = gsi_last (seq);
622*e4b17023SJohn Marino
623*e4b17023SJohn Marino for (i = 0; i < gimple_omp_for_collapse (for_stmt); i++)
624*e4b17023SJohn Marino {
625*e4b17023SJohn Marino wi.val_only = false;
626*e4b17023SJohn Marino walk_tree (gimple_omp_for_index_ptr (for_stmt, i), callback_op,
627*e4b17023SJohn Marino &wi, NULL);
628*e4b17023SJohn Marino wi.val_only = true;
629*e4b17023SJohn Marino wi.is_lhs = false;
630*e4b17023SJohn Marino walk_tree (gimple_omp_for_initial_ptr (for_stmt, i), callback_op,
631*e4b17023SJohn Marino &wi, NULL);
632*e4b17023SJohn Marino
633*e4b17023SJohn Marino wi.val_only = true;
634*e4b17023SJohn Marino wi.is_lhs = false;
635*e4b17023SJohn Marino walk_tree (gimple_omp_for_final_ptr (for_stmt, i), callback_op,
636*e4b17023SJohn Marino &wi, NULL);
637*e4b17023SJohn Marino
638*e4b17023SJohn Marino t = gimple_omp_for_incr (for_stmt, i);
639*e4b17023SJohn Marino gcc_assert (BINARY_CLASS_P (t));
640*e4b17023SJohn Marino wi.val_only = false;
641*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), callback_op, &wi, NULL);
642*e4b17023SJohn Marino wi.val_only = true;
643*e4b17023SJohn Marino wi.is_lhs = false;
644*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), callback_op, &wi, NULL);
645*e4b17023SJohn Marino }
646*e4b17023SJohn Marino
647*e4b17023SJohn Marino if (gimple_seq_empty_p (seq))
648*e4b17023SJohn Marino gimple_seq_free (seq);
649*e4b17023SJohn Marino else
650*e4b17023SJohn Marino {
651*e4b17023SJohn Marino gimple_seq pre_body = gimple_omp_for_pre_body (for_stmt);
652*e4b17023SJohn Marino annotate_all_with_location (seq, gimple_location (for_stmt));
653*e4b17023SJohn Marino gimple_seq_add_seq (&pre_body, seq);
654*e4b17023SJohn Marino gimple_omp_for_set_pre_body (for_stmt, pre_body);
655*e4b17023SJohn Marino }
656*e4b17023SJohn Marino }
657*e4b17023SJohn Marino
658*e4b17023SJohn Marino /* Similarly for ROOT and all functions nested underneath, depth first. */
659*e4b17023SJohn Marino
660*e4b17023SJohn Marino static void
walk_all_functions(walk_stmt_fn callback_stmt,walk_tree_fn callback_op,struct nesting_info * root)661*e4b17023SJohn Marino walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
662*e4b17023SJohn Marino struct nesting_info *root)
663*e4b17023SJohn Marino {
664*e4b17023SJohn Marino struct nesting_info *n;
665*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root)
666*e4b17023SJohn Marino walk_function (callback_stmt, callback_op, n);
667*e4b17023SJohn Marino }
668*e4b17023SJohn Marino
669*e4b17023SJohn Marino
670*e4b17023SJohn Marino /* We have to check for a fairly pathological case. The operands of function
671*e4b17023SJohn Marino nested function are to be interpreted in the context of the enclosing
672*e4b17023SJohn Marino function. So if any are variably-sized, they will get remapped when the
673*e4b17023SJohn Marino enclosing function is inlined. But that remapping would also have to be
674*e4b17023SJohn Marino done in the types of the PARM_DECLs of the nested function, meaning the
675*e4b17023SJohn Marino argument types of that function will disagree with the arguments in the
676*e4b17023SJohn Marino calls to that function. So we'd either have to make a copy of the nested
677*e4b17023SJohn Marino function corresponding to each time the enclosing function was inlined or
678*e4b17023SJohn Marino add a VIEW_CONVERT_EXPR to each such operand for each call to the nested
679*e4b17023SJohn Marino function. The former is not practical. The latter would still require
680*e4b17023SJohn Marino detecting this case to know when to add the conversions. So, for now at
681*e4b17023SJohn Marino least, we don't inline such an enclosing function.
682*e4b17023SJohn Marino
683*e4b17023SJohn Marino We have to do that check recursively, so here return indicating whether
684*e4b17023SJohn Marino FNDECL has such a nested function. ORIG_FN is the function we were
685*e4b17023SJohn Marino trying to inline to use for checking whether any argument is variably
686*e4b17023SJohn Marino modified by anything in it.
687*e4b17023SJohn Marino
688*e4b17023SJohn Marino It would be better to do this in tree-inline.c so that we could give
689*e4b17023SJohn Marino the appropriate warning for why a function can't be inlined, but that's
690*e4b17023SJohn Marino too late since the nesting structure has already been flattened and
691*e4b17023SJohn Marino adding a flag just to record this fact seems a waste of a flag. */
692*e4b17023SJohn Marino
693*e4b17023SJohn Marino static bool
check_for_nested_with_variably_modified(tree fndecl,tree orig_fndecl)694*e4b17023SJohn Marino check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
695*e4b17023SJohn Marino {
696*e4b17023SJohn Marino struct cgraph_node *cgn = cgraph_get_node (fndecl);
697*e4b17023SJohn Marino tree arg;
698*e4b17023SJohn Marino
699*e4b17023SJohn Marino for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
700*e4b17023SJohn Marino {
701*e4b17023SJohn Marino for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg))
702*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl))
703*e4b17023SJohn Marino return true;
704*e4b17023SJohn Marino
705*e4b17023SJohn Marino if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl))
706*e4b17023SJohn Marino return true;
707*e4b17023SJohn Marino }
708*e4b17023SJohn Marino
709*e4b17023SJohn Marino return false;
710*e4b17023SJohn Marino }
711*e4b17023SJohn Marino
712*e4b17023SJohn Marino /* Construct our local datastructure describing the function nesting
713*e4b17023SJohn Marino tree rooted by CGN. */
714*e4b17023SJohn Marino
715*e4b17023SJohn Marino static struct nesting_info *
create_nesting_tree(struct cgraph_node * cgn)716*e4b17023SJohn Marino create_nesting_tree (struct cgraph_node *cgn)
717*e4b17023SJohn Marino {
718*e4b17023SJohn Marino struct nesting_info *info = XCNEW (struct nesting_info);
719*e4b17023SJohn Marino info->field_map = pointer_map_create ();
720*e4b17023SJohn Marino info->var_map = pointer_map_create ();
721*e4b17023SJohn Marino info->mem_refs = pointer_set_create ();
722*e4b17023SJohn Marino info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
723*e4b17023SJohn Marino info->context = cgn->decl;
724*e4b17023SJohn Marino
725*e4b17023SJohn Marino for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
726*e4b17023SJohn Marino {
727*e4b17023SJohn Marino struct nesting_info *sub = create_nesting_tree (cgn);
728*e4b17023SJohn Marino sub->outer = info;
729*e4b17023SJohn Marino sub->next = info->inner;
730*e4b17023SJohn Marino info->inner = sub;
731*e4b17023SJohn Marino }
732*e4b17023SJohn Marino
733*e4b17023SJohn Marino /* See discussion at check_for_nested_with_variably_modified for a
734*e4b17023SJohn Marino discussion of why this has to be here. */
735*e4b17023SJohn Marino if (check_for_nested_with_variably_modified (info->context, info->context))
736*e4b17023SJohn Marino DECL_UNINLINABLE (info->context) = true;
737*e4b17023SJohn Marino
738*e4b17023SJohn Marino return info;
739*e4b17023SJohn Marino }
740*e4b17023SJohn Marino
741*e4b17023SJohn Marino /* Return an expression computing the static chain for TARGET_CONTEXT
742*e4b17023SJohn Marino from INFO->CONTEXT. Insert any necessary computations before TSI. */
743*e4b17023SJohn Marino
744*e4b17023SJohn Marino static tree
get_static_chain(struct nesting_info * info,tree target_context,gimple_stmt_iterator * gsi)745*e4b17023SJohn Marino get_static_chain (struct nesting_info *info, tree target_context,
746*e4b17023SJohn Marino gimple_stmt_iterator *gsi)
747*e4b17023SJohn Marino {
748*e4b17023SJohn Marino struct nesting_info *i;
749*e4b17023SJohn Marino tree x;
750*e4b17023SJohn Marino
751*e4b17023SJohn Marino if (info->context == target_context)
752*e4b17023SJohn Marino {
753*e4b17023SJohn Marino x = build_addr (info->frame_decl, target_context);
754*e4b17023SJohn Marino }
755*e4b17023SJohn Marino else
756*e4b17023SJohn Marino {
757*e4b17023SJohn Marino x = get_chain_decl (info);
758*e4b17023SJohn Marino
759*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer)
760*e4b17023SJohn Marino {
761*e4b17023SJohn Marino tree field = get_chain_field (i);
762*e4b17023SJohn Marino
763*e4b17023SJohn Marino x = build_simple_mem_ref (x);
764*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
765*e4b17023SJohn Marino x = init_tmp_var (info, x, gsi);
766*e4b17023SJohn Marino }
767*e4b17023SJohn Marino }
768*e4b17023SJohn Marino
769*e4b17023SJohn Marino return x;
770*e4b17023SJohn Marino }
771*e4b17023SJohn Marino
772*e4b17023SJohn Marino
773*e4b17023SJohn Marino /* Return an expression referencing FIELD from TARGET_CONTEXT's non-local
774*e4b17023SJohn Marino frame as seen from INFO->CONTEXT. Insert any necessary computations
775*e4b17023SJohn Marino before GSI. */
776*e4b17023SJohn Marino
777*e4b17023SJohn Marino static tree
get_frame_field(struct nesting_info * info,tree target_context,tree field,gimple_stmt_iterator * gsi)778*e4b17023SJohn Marino get_frame_field (struct nesting_info *info, tree target_context,
779*e4b17023SJohn Marino tree field, gimple_stmt_iterator *gsi)
780*e4b17023SJohn Marino {
781*e4b17023SJohn Marino struct nesting_info *i;
782*e4b17023SJohn Marino tree x;
783*e4b17023SJohn Marino
784*e4b17023SJohn Marino if (info->context == target_context)
785*e4b17023SJohn Marino {
786*e4b17023SJohn Marino /* Make sure frame_decl gets created. */
787*e4b17023SJohn Marino (void) get_frame_type (info);
788*e4b17023SJohn Marino x = info->frame_decl;
789*e4b17023SJohn Marino }
790*e4b17023SJohn Marino else
791*e4b17023SJohn Marino {
792*e4b17023SJohn Marino x = get_chain_decl (info);
793*e4b17023SJohn Marino
794*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer)
795*e4b17023SJohn Marino {
796*e4b17023SJohn Marino tree field = get_chain_field (i);
797*e4b17023SJohn Marino
798*e4b17023SJohn Marino x = build_simple_mem_ref (x);
799*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
800*e4b17023SJohn Marino x = init_tmp_var (info, x, gsi);
801*e4b17023SJohn Marino }
802*e4b17023SJohn Marino
803*e4b17023SJohn Marino x = build_simple_mem_ref (x);
804*e4b17023SJohn Marino }
805*e4b17023SJohn Marino
806*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
807*e4b17023SJohn Marino return x;
808*e4b17023SJohn Marino }
809*e4b17023SJohn Marino
810*e4b17023SJohn Marino static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
811*e4b17023SJohn Marino
812*e4b17023SJohn Marino /* A subroutine of convert_nonlocal_reference_op. Create a local variable
813*e4b17023SJohn Marino in the nested function with DECL_VALUE_EXPR set to reference the true
814*e4b17023SJohn Marino variable in the parent function. This is used both for debug info
815*e4b17023SJohn Marino and in OpenMP lowering. */
816*e4b17023SJohn Marino
817*e4b17023SJohn Marino static tree
get_nonlocal_debug_decl(struct nesting_info * info,tree decl)818*e4b17023SJohn Marino get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
819*e4b17023SJohn Marino {
820*e4b17023SJohn Marino tree target_context;
821*e4b17023SJohn Marino struct nesting_info *i;
822*e4b17023SJohn Marino tree x, field, new_decl;
823*e4b17023SJohn Marino void **slot;
824*e4b17023SJohn Marino
825*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl);
826*e4b17023SJohn Marino
827*e4b17023SJohn Marino if (*slot)
828*e4b17023SJohn Marino return (tree) *slot;
829*e4b17023SJohn Marino
830*e4b17023SJohn Marino target_context = decl_function_context (decl);
831*e4b17023SJohn Marino
832*e4b17023SJohn Marino /* A copy of the code in get_frame_field, but without the temporaries. */
833*e4b17023SJohn Marino if (info->context == target_context)
834*e4b17023SJohn Marino {
835*e4b17023SJohn Marino /* Make sure frame_decl gets created. */
836*e4b17023SJohn Marino (void) get_frame_type (info);
837*e4b17023SJohn Marino x = info->frame_decl;
838*e4b17023SJohn Marino i = info;
839*e4b17023SJohn Marino }
840*e4b17023SJohn Marino else
841*e4b17023SJohn Marino {
842*e4b17023SJohn Marino x = get_chain_decl (info);
843*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer)
844*e4b17023SJohn Marino {
845*e4b17023SJohn Marino field = get_chain_field (i);
846*e4b17023SJohn Marino x = build_simple_mem_ref (x);
847*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
848*e4b17023SJohn Marino }
849*e4b17023SJohn Marino x = build_simple_mem_ref (x);
850*e4b17023SJohn Marino }
851*e4b17023SJohn Marino
852*e4b17023SJohn Marino field = lookup_field_for_decl (i, decl, INSERT);
853*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
854*e4b17023SJohn Marino if (use_pointer_in_frame (decl))
855*e4b17023SJohn Marino x = build_simple_mem_ref (x);
856*e4b17023SJohn Marino
857*e4b17023SJohn Marino /* ??? We should be remapping types as well, surely. */
858*e4b17023SJohn Marino new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
859*e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
860*e4b17023SJohn Marino DECL_CONTEXT (new_decl) = info->context;
861*e4b17023SJohn Marino DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl);
862*e4b17023SJohn Marino DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl);
863*e4b17023SJohn Marino TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl);
864*e4b17023SJohn Marino TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl);
865*e4b17023SJohn Marino TREE_READONLY (new_decl) = TREE_READONLY (decl);
866*e4b17023SJohn Marino TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
867*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
868*e4b17023SJohn Marino if ((TREE_CODE (decl) == PARM_DECL
869*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL
870*e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL)
871*e4b17023SJohn Marino && DECL_BY_REFERENCE (decl))
872*e4b17023SJohn Marino DECL_BY_REFERENCE (new_decl) = 1;
873*e4b17023SJohn Marino
874*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (new_decl, x);
875*e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
876*e4b17023SJohn Marino
877*e4b17023SJohn Marino *slot = new_decl;
878*e4b17023SJohn Marino DECL_CHAIN (new_decl) = info->debug_var_chain;
879*e4b17023SJohn Marino info->debug_var_chain = new_decl;
880*e4b17023SJohn Marino
881*e4b17023SJohn Marino if (!optimize
882*e4b17023SJohn Marino && info->context != target_context
883*e4b17023SJohn Marino && variably_modified_type_p (TREE_TYPE (decl), NULL))
884*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (decl));
885*e4b17023SJohn Marino
886*e4b17023SJohn Marino return new_decl;
887*e4b17023SJohn Marino }
888*e4b17023SJohn Marino
889*e4b17023SJohn Marino
890*e4b17023SJohn Marino /* Callback for walk_gimple_stmt, rewrite all references to VAR
891*e4b17023SJohn Marino and PARM_DECLs that belong to outer functions.
892*e4b17023SJohn Marino
893*e4b17023SJohn Marino The rewrite will involve some number of structure accesses back up
894*e4b17023SJohn Marino the static chain. E.g. for a variable FOO up one nesting level it'll
895*e4b17023SJohn Marino be CHAIN->FOO. For two levels it'll be CHAIN->__chain->FOO. Further
896*e4b17023SJohn Marino indirections apply to decls for which use_pointer_in_frame is true. */
897*e4b17023SJohn Marino
898*e4b17023SJohn Marino static tree
convert_nonlocal_reference_op(tree * tp,int * walk_subtrees,void * data)899*e4b17023SJohn Marino convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data)
900*e4b17023SJohn Marino {
901*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
902*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
903*e4b17023SJohn Marino tree t = *tp;
904*e4b17023SJohn Marino
905*e4b17023SJohn Marino *walk_subtrees = 0;
906*e4b17023SJohn Marino switch (TREE_CODE (t))
907*e4b17023SJohn Marino {
908*e4b17023SJohn Marino case VAR_DECL:
909*e4b17023SJohn Marino /* Non-automatic variables are never processed. */
910*e4b17023SJohn Marino if (TREE_STATIC (t) || DECL_EXTERNAL (t))
911*e4b17023SJohn Marino break;
912*e4b17023SJohn Marino /* FALLTHRU */
913*e4b17023SJohn Marino
914*e4b17023SJohn Marino case PARM_DECL:
915*e4b17023SJohn Marino if (decl_function_context (t) != info->context)
916*e4b17023SJohn Marino {
917*e4b17023SJohn Marino tree x;
918*e4b17023SJohn Marino wi->changed = true;
919*e4b17023SJohn Marino
920*e4b17023SJohn Marino x = get_nonlocal_debug_decl (info, t);
921*e4b17023SJohn Marino if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
922*e4b17023SJohn Marino {
923*e4b17023SJohn Marino tree target_context = decl_function_context (t);
924*e4b17023SJohn Marino struct nesting_info *i;
925*e4b17023SJohn Marino for (i = info->outer; i->context != target_context; i = i->outer)
926*e4b17023SJohn Marino continue;
927*e4b17023SJohn Marino x = lookup_field_for_decl (i, t, INSERT);
928*e4b17023SJohn Marino x = get_frame_field (info, target_context, x, &wi->gsi);
929*e4b17023SJohn Marino if (use_pointer_in_frame (t))
930*e4b17023SJohn Marino {
931*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi);
932*e4b17023SJohn Marino x = build_simple_mem_ref (x);
933*e4b17023SJohn Marino }
934*e4b17023SJohn Marino }
935*e4b17023SJohn Marino
936*e4b17023SJohn Marino if (wi->val_only)
937*e4b17023SJohn Marino {
938*e4b17023SJohn Marino if (wi->is_lhs)
939*e4b17023SJohn Marino x = save_tmp_var (info, x, &wi->gsi);
940*e4b17023SJohn Marino else
941*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi);
942*e4b17023SJohn Marino }
943*e4b17023SJohn Marino
944*e4b17023SJohn Marino *tp = x;
945*e4b17023SJohn Marino }
946*e4b17023SJohn Marino break;
947*e4b17023SJohn Marino
948*e4b17023SJohn Marino case LABEL_DECL:
949*e4b17023SJohn Marino /* We're taking the address of a label from a parent function, but
950*e4b17023SJohn Marino this is not itself a non-local goto. Mark the label such that it
951*e4b17023SJohn Marino will not be deleted, much as we would with a label address in
952*e4b17023SJohn Marino static storage. */
953*e4b17023SJohn Marino if (decl_function_context (t) != info->context)
954*e4b17023SJohn Marino FORCED_LABEL (t) = 1;
955*e4b17023SJohn Marino break;
956*e4b17023SJohn Marino
957*e4b17023SJohn Marino case ADDR_EXPR:
958*e4b17023SJohn Marino {
959*e4b17023SJohn Marino bool save_val_only = wi->val_only;
960*e4b17023SJohn Marino
961*e4b17023SJohn Marino wi->val_only = false;
962*e4b17023SJohn Marino wi->is_lhs = false;
963*e4b17023SJohn Marino wi->changed = false;
964*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference_op, wi, 0);
965*e4b17023SJohn Marino wi->val_only = true;
966*e4b17023SJohn Marino
967*e4b17023SJohn Marino if (wi->changed)
968*e4b17023SJohn Marino {
969*e4b17023SJohn Marino tree save_context;
970*e4b17023SJohn Marino
971*e4b17023SJohn Marino /* If we changed anything, we might no longer be directly
972*e4b17023SJohn Marino referencing a decl. */
973*e4b17023SJohn Marino save_context = current_function_decl;
974*e4b17023SJohn Marino current_function_decl = info->context;
975*e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (t);
976*e4b17023SJohn Marino current_function_decl = save_context;
977*e4b17023SJohn Marino
978*e4b17023SJohn Marino /* If the callback converted the address argument in a context
979*e4b17023SJohn Marino where we only accept variables (and min_invariant, presumably),
980*e4b17023SJohn Marino then compute the address into a temporary. */
981*e4b17023SJohn Marino if (save_val_only)
982*e4b17023SJohn Marino *tp = gsi_gimplify_val ((struct nesting_info *) wi->info,
983*e4b17023SJohn Marino t, &wi->gsi);
984*e4b17023SJohn Marino }
985*e4b17023SJohn Marino }
986*e4b17023SJohn Marino break;
987*e4b17023SJohn Marino
988*e4b17023SJohn Marino case REALPART_EXPR:
989*e4b17023SJohn Marino case IMAGPART_EXPR:
990*e4b17023SJohn Marino case COMPONENT_REF:
991*e4b17023SJohn Marino case ARRAY_REF:
992*e4b17023SJohn Marino case ARRAY_RANGE_REF:
993*e4b17023SJohn Marino case BIT_FIELD_REF:
994*e4b17023SJohn Marino /* Go down this entire nest and just look at the final prefix and
995*e4b17023SJohn Marino anything that describes the references. Otherwise, we lose track
996*e4b17023SJohn Marino of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */
997*e4b17023SJohn Marino wi->val_only = true;
998*e4b17023SJohn Marino wi->is_lhs = false;
999*e4b17023SJohn Marino for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
1000*e4b17023SJohn Marino {
1001*e4b17023SJohn Marino if (TREE_CODE (t) == COMPONENT_REF)
1002*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op, wi,
1003*e4b17023SJohn Marino NULL);
1004*e4b17023SJohn Marino else if (TREE_CODE (t) == ARRAY_REF
1005*e4b17023SJohn Marino || TREE_CODE (t) == ARRAY_RANGE_REF)
1006*e4b17023SJohn Marino {
1007*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
1008*e4b17023SJohn Marino wi, NULL);
1009*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
1010*e4b17023SJohn Marino wi, NULL);
1011*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference_op,
1012*e4b17023SJohn Marino wi, NULL);
1013*e4b17023SJohn Marino }
1014*e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF)
1015*e4b17023SJohn Marino {
1016*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
1017*e4b17023SJohn Marino wi, NULL);
1018*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
1019*e4b17023SJohn Marino wi, NULL);
1020*e4b17023SJohn Marino }
1021*e4b17023SJohn Marino }
1022*e4b17023SJohn Marino wi->val_only = false;
1023*e4b17023SJohn Marino walk_tree (tp, convert_nonlocal_reference_op, wi, NULL);
1024*e4b17023SJohn Marino break;
1025*e4b17023SJohn Marino
1026*e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
1027*e4b17023SJohn Marino /* Just request to look at the subtrees, leaving val_only and lhs
1028*e4b17023SJohn Marino untouched. This might actually be for !val_only + lhs, in which
1029*e4b17023SJohn Marino case we don't want to force a replacement by a temporary. */
1030*e4b17023SJohn Marino *walk_subtrees = 1;
1031*e4b17023SJohn Marino break;
1032*e4b17023SJohn Marino
1033*e4b17023SJohn Marino default:
1034*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t))
1035*e4b17023SJohn Marino {
1036*e4b17023SJohn Marino *walk_subtrees = 1;
1037*e4b17023SJohn Marino wi->val_only = true;
1038*e4b17023SJohn Marino wi->is_lhs = false;
1039*e4b17023SJohn Marino }
1040*e4b17023SJohn Marino break;
1041*e4b17023SJohn Marino }
1042*e4b17023SJohn Marino
1043*e4b17023SJohn Marino return NULL_TREE;
1044*e4b17023SJohn Marino }
1045*e4b17023SJohn Marino
1046*e4b17023SJohn Marino static tree convert_nonlocal_reference_stmt (gimple_stmt_iterator *, bool *,
1047*e4b17023SJohn Marino struct walk_stmt_info *);
1048*e4b17023SJohn Marino
1049*e4b17023SJohn Marino /* Helper for convert_nonlocal_references, rewrite all references to VAR
1050*e4b17023SJohn Marino and PARM_DECLs that belong to outer functions. */
1051*e4b17023SJohn Marino
1052*e4b17023SJohn Marino static bool
convert_nonlocal_omp_clauses(tree * pclauses,struct walk_stmt_info * wi)1053*e4b17023SJohn Marino convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
1054*e4b17023SJohn Marino {
1055*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
1056*e4b17023SJohn Marino bool need_chain = false, need_stmts = false;
1057*e4b17023SJohn Marino tree clause, decl;
1058*e4b17023SJohn Marino int dummy;
1059*e4b17023SJohn Marino bitmap new_suppress;
1060*e4b17023SJohn Marino
1061*e4b17023SJohn Marino new_suppress = BITMAP_GGC_ALLOC ();
1062*e4b17023SJohn Marino bitmap_copy (new_suppress, info->suppress_expansion);
1063*e4b17023SJohn Marino
1064*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
1065*e4b17023SJohn Marino {
1066*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause))
1067*e4b17023SJohn Marino {
1068*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
1069*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1070*e4b17023SJohn Marino need_stmts = true;
1071*e4b17023SJohn Marino goto do_decl_clause;
1072*e4b17023SJohn Marino
1073*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
1074*e4b17023SJohn Marino if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause))
1075*e4b17023SJohn Marino need_stmts = true;
1076*e4b17023SJohn Marino goto do_decl_clause;
1077*e4b17023SJohn Marino
1078*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
1079*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
1080*e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE:
1081*e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
1082*e4b17023SJohn Marino do_decl_clause:
1083*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (clause);
1084*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
1085*e4b17023SJohn Marino && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
1086*e4b17023SJohn Marino break;
1087*e4b17023SJohn Marino if (decl_function_context (decl) != info->context)
1088*e4b17023SJohn Marino {
1089*e4b17023SJohn Marino bitmap_set_bit (new_suppress, DECL_UID (decl));
1090*e4b17023SJohn Marino OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
1091*e4b17023SJohn Marino if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
1092*e4b17023SJohn Marino need_chain = true;
1093*e4b17023SJohn Marino }
1094*e4b17023SJohn Marino break;
1095*e4b17023SJohn Marino
1096*e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE:
1097*e4b17023SJohn Marino if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
1098*e4b17023SJohn Marino break;
1099*e4b17023SJohn Marino /* FALLTHRU */
1100*e4b17023SJohn Marino case OMP_CLAUSE_FINAL:
1101*e4b17023SJohn Marino case OMP_CLAUSE_IF:
1102*e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS:
1103*e4b17023SJohn Marino wi->val_only = true;
1104*e4b17023SJohn Marino wi->is_lhs = false;
1105*e4b17023SJohn Marino convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
1106*e4b17023SJohn Marino &dummy, wi);
1107*e4b17023SJohn Marino break;
1108*e4b17023SJohn Marino
1109*e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT:
1110*e4b17023SJohn Marino case OMP_CLAUSE_ORDERED:
1111*e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT:
1112*e4b17023SJohn Marino case OMP_CLAUSE_COPYIN:
1113*e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE:
1114*e4b17023SJohn Marino case OMP_CLAUSE_UNTIED:
1115*e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE:
1116*e4b17023SJohn Marino break;
1117*e4b17023SJohn Marino
1118*e4b17023SJohn Marino default:
1119*e4b17023SJohn Marino gcc_unreachable ();
1120*e4b17023SJohn Marino }
1121*e4b17023SJohn Marino }
1122*e4b17023SJohn Marino
1123*e4b17023SJohn Marino info->suppress_expansion = new_suppress;
1124*e4b17023SJohn Marino
1125*e4b17023SJohn Marino if (need_stmts)
1126*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
1127*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause))
1128*e4b17023SJohn Marino {
1129*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
1130*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1131*e4b17023SJohn Marino {
1132*e4b17023SJohn Marino tree old_context
1133*e4b17023SJohn Marino = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause));
1134*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1135*e4b17023SJohn Marino = info->context;
1136*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt,
1137*e4b17023SJohn Marino convert_nonlocal_reference_op, info,
1138*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
1139*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt,
1140*e4b17023SJohn Marino convert_nonlocal_reference_op, info,
1141*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
1142*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1143*e4b17023SJohn Marino = old_context;
1144*e4b17023SJohn Marino }
1145*e4b17023SJohn Marino break;
1146*e4b17023SJohn Marino
1147*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
1148*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt,
1149*e4b17023SJohn Marino convert_nonlocal_reference_op, info,
1150*e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
1151*e4b17023SJohn Marino break;
1152*e4b17023SJohn Marino
1153*e4b17023SJohn Marino default:
1154*e4b17023SJohn Marino break;
1155*e4b17023SJohn Marino }
1156*e4b17023SJohn Marino
1157*e4b17023SJohn Marino return need_chain;
1158*e4b17023SJohn Marino }
1159*e4b17023SJohn Marino
1160*e4b17023SJohn Marino /* Create nonlocal debug decls for nonlocal VLA array bounds. */
1161*e4b17023SJohn Marino
1162*e4b17023SJohn Marino static void
note_nonlocal_vla_type(struct nesting_info * info,tree type)1163*e4b17023SJohn Marino note_nonlocal_vla_type (struct nesting_info *info, tree type)
1164*e4b17023SJohn Marino {
1165*e4b17023SJohn Marino while (POINTER_TYPE_P (type) && !TYPE_NAME (type))
1166*e4b17023SJohn Marino type = TREE_TYPE (type);
1167*e4b17023SJohn Marino
1168*e4b17023SJohn Marino if (TYPE_NAME (type)
1169*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
1170*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
1171*e4b17023SJohn Marino type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
1172*e4b17023SJohn Marino
1173*e4b17023SJohn Marino while (POINTER_TYPE_P (type)
1174*e4b17023SJohn Marino || TREE_CODE (type) == VECTOR_TYPE
1175*e4b17023SJohn Marino || TREE_CODE (type) == FUNCTION_TYPE
1176*e4b17023SJohn Marino || TREE_CODE (type) == METHOD_TYPE)
1177*e4b17023SJohn Marino type = TREE_TYPE (type);
1178*e4b17023SJohn Marino
1179*e4b17023SJohn Marino if (TREE_CODE (type) == ARRAY_TYPE)
1180*e4b17023SJohn Marino {
1181*e4b17023SJohn Marino tree domain, t;
1182*e4b17023SJohn Marino
1183*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (type));
1184*e4b17023SJohn Marino domain = TYPE_DOMAIN (type);
1185*e4b17023SJohn Marino if (domain)
1186*e4b17023SJohn Marino {
1187*e4b17023SJohn Marino t = TYPE_MIN_VALUE (domain);
1188*e4b17023SJohn Marino if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
1189*e4b17023SJohn Marino && decl_function_context (t) != info->context)
1190*e4b17023SJohn Marino get_nonlocal_debug_decl (info, t);
1191*e4b17023SJohn Marino t = TYPE_MAX_VALUE (domain);
1192*e4b17023SJohn Marino if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
1193*e4b17023SJohn Marino && decl_function_context (t) != info->context)
1194*e4b17023SJohn Marino get_nonlocal_debug_decl (info, t);
1195*e4b17023SJohn Marino }
1196*e4b17023SJohn Marino }
1197*e4b17023SJohn Marino }
1198*e4b17023SJohn Marino
1199*e4b17023SJohn Marino /* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
1200*e4b17023SJohn Marino in BLOCK. */
1201*e4b17023SJohn Marino
1202*e4b17023SJohn Marino static void
note_nonlocal_block_vlas(struct nesting_info * info,tree block)1203*e4b17023SJohn Marino note_nonlocal_block_vlas (struct nesting_info *info, tree block)
1204*e4b17023SJohn Marino {
1205*e4b17023SJohn Marino tree var;
1206*e4b17023SJohn Marino
1207*e4b17023SJohn Marino for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
1208*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL
1209*e4b17023SJohn Marino && variably_modified_type_p (TREE_TYPE (var), NULL)
1210*e4b17023SJohn Marino && DECL_HAS_VALUE_EXPR_P (var)
1211*e4b17023SJohn Marino && decl_function_context (var) != info->context)
1212*e4b17023SJohn Marino note_nonlocal_vla_type (info, TREE_TYPE (var));
1213*e4b17023SJohn Marino }
1214*e4b17023SJohn Marino
1215*e4b17023SJohn Marino /* Callback for walk_gimple_stmt. Rewrite all references to VAR and
1216*e4b17023SJohn Marino PARM_DECLs that belong to outer functions. This handles statements
1217*e4b17023SJohn Marino that are not handled via the standard recursion done in
1218*e4b17023SJohn Marino walk_gimple_stmt. STMT is the statement to examine, DATA is as in
1219*e4b17023SJohn Marino convert_nonlocal_reference_op. Set *HANDLED_OPS_P to true if all the
1220*e4b17023SJohn Marino operands of STMT have been handled by this function. */
1221*e4b17023SJohn Marino
1222*e4b17023SJohn Marino static tree
convert_nonlocal_reference_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)1223*e4b17023SJohn Marino convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1224*e4b17023SJohn Marino struct walk_stmt_info *wi)
1225*e4b17023SJohn Marino {
1226*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info;
1227*e4b17023SJohn Marino tree save_local_var_chain;
1228*e4b17023SJohn Marino bitmap save_suppress;
1229*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
1230*e4b17023SJohn Marino
1231*e4b17023SJohn Marino switch (gimple_code (stmt))
1232*e4b17023SJohn Marino {
1233*e4b17023SJohn Marino case GIMPLE_GOTO:
1234*e4b17023SJohn Marino /* Don't walk non-local gotos for now. */
1235*e4b17023SJohn Marino if (TREE_CODE (gimple_goto_dest (stmt)) != LABEL_DECL)
1236*e4b17023SJohn Marino {
1237*e4b17023SJohn Marino wi->val_only = true;
1238*e4b17023SJohn Marino wi->is_lhs = false;
1239*e4b17023SJohn Marino *handled_ops_p = true;
1240*e4b17023SJohn Marino return NULL_TREE;
1241*e4b17023SJohn Marino }
1242*e4b17023SJohn Marino break;
1243*e4b17023SJohn Marino
1244*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL:
1245*e4b17023SJohn Marino case GIMPLE_OMP_TASK:
1246*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1247*e4b17023SJohn Marino if (convert_nonlocal_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt),
1248*e4b17023SJohn Marino wi))
1249*e4b17023SJohn Marino {
1250*e4b17023SJohn Marino tree c, decl;
1251*e4b17023SJohn Marino decl = get_chain_decl (info);
1252*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt),
1253*e4b17023SJohn Marino OMP_CLAUSE_FIRSTPRIVATE);
1254*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = decl;
1255*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
1256*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c);
1257*e4b17023SJohn Marino }
1258*e4b17023SJohn Marino
1259*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain;
1260*e4b17023SJohn Marino info->new_local_var_chain = NULL;
1261*e4b17023SJohn Marino
1262*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
1263*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1264*e4b17023SJohn Marino
1265*e4b17023SJohn Marino if (info->new_local_var_chain)
1266*e4b17023SJohn Marino declare_vars (info->new_local_var_chain,
1267*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)),
1268*e4b17023SJohn Marino false);
1269*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain;
1270*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1271*e4b17023SJohn Marino break;
1272*e4b17023SJohn Marino
1273*e4b17023SJohn Marino case GIMPLE_OMP_FOR:
1274*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1275*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
1276*e4b17023SJohn Marino walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt,
1277*e4b17023SJohn Marino convert_nonlocal_reference_op, info);
1278*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt,
1279*e4b17023SJohn Marino convert_nonlocal_reference_op, info, gimple_omp_body (stmt));
1280*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1281*e4b17023SJohn Marino break;
1282*e4b17023SJohn Marino
1283*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS:
1284*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1285*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
1286*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
1287*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1288*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1289*e4b17023SJohn Marino break;
1290*e4b17023SJohn Marino
1291*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE:
1292*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1293*e4b17023SJohn Marino convert_nonlocal_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
1294*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
1295*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1296*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1297*e4b17023SJohn Marino break;
1298*e4b17023SJohn Marino
1299*e4b17023SJohn Marino case GIMPLE_OMP_SECTION:
1300*e4b17023SJohn Marino case GIMPLE_OMP_MASTER:
1301*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED:
1302*e4b17023SJohn Marino walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
1303*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1304*e4b17023SJohn Marino break;
1305*e4b17023SJohn Marino
1306*e4b17023SJohn Marino case GIMPLE_BIND:
1307*e4b17023SJohn Marino if (!optimize && gimple_bind_block (stmt))
1308*e4b17023SJohn Marino note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
1309*e4b17023SJohn Marino
1310*e4b17023SJohn Marino *handled_ops_p = false;
1311*e4b17023SJohn Marino return NULL_TREE;
1312*e4b17023SJohn Marino
1313*e4b17023SJohn Marino case GIMPLE_COND:
1314*e4b17023SJohn Marino wi->val_only = true;
1315*e4b17023SJohn Marino wi->is_lhs = false;
1316*e4b17023SJohn Marino *handled_ops_p = false;
1317*e4b17023SJohn Marino return NULL_TREE;
1318*e4b17023SJohn Marino
1319*e4b17023SJohn Marino default:
1320*e4b17023SJohn Marino /* For every other statement that we are not interested in
1321*e4b17023SJohn Marino handling here, let the walker traverse the operands. */
1322*e4b17023SJohn Marino *handled_ops_p = false;
1323*e4b17023SJohn Marino return NULL_TREE;
1324*e4b17023SJohn Marino }
1325*e4b17023SJohn Marino
1326*e4b17023SJohn Marino /* We have handled all of STMT operands, no need to traverse the operands. */
1327*e4b17023SJohn Marino *handled_ops_p = true;
1328*e4b17023SJohn Marino return NULL_TREE;
1329*e4b17023SJohn Marino }
1330*e4b17023SJohn Marino
1331*e4b17023SJohn Marino
1332*e4b17023SJohn Marino /* A subroutine of convert_local_reference. Create a local variable
1333*e4b17023SJohn Marino in the parent function with DECL_VALUE_EXPR set to reference the
1334*e4b17023SJohn Marino field in FRAME. This is used both for debug info and in OpenMP
1335*e4b17023SJohn Marino lowering. */
1336*e4b17023SJohn Marino
1337*e4b17023SJohn Marino static tree
get_local_debug_decl(struct nesting_info * info,tree decl,tree field)1338*e4b17023SJohn Marino get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
1339*e4b17023SJohn Marino {
1340*e4b17023SJohn Marino tree x, new_decl;
1341*e4b17023SJohn Marino void **slot;
1342*e4b17023SJohn Marino
1343*e4b17023SJohn Marino slot = pointer_map_insert (info->var_map, decl);
1344*e4b17023SJohn Marino if (*slot)
1345*e4b17023SJohn Marino return (tree) *slot;
1346*e4b17023SJohn Marino
1347*e4b17023SJohn Marino /* Make sure frame_decl gets created. */
1348*e4b17023SJohn Marino (void) get_frame_type (info);
1349*e4b17023SJohn Marino x = info->frame_decl;
1350*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
1351*e4b17023SJohn Marino
1352*e4b17023SJohn Marino new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
1353*e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
1354*e4b17023SJohn Marino DECL_CONTEXT (new_decl) = info->context;
1355*e4b17023SJohn Marino DECL_ARTIFICIAL (new_decl) = DECL_ARTIFICIAL (decl);
1356*e4b17023SJohn Marino DECL_IGNORED_P (new_decl) = DECL_IGNORED_P (decl);
1357*e4b17023SJohn Marino TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (decl);
1358*e4b17023SJohn Marino TREE_SIDE_EFFECTS (new_decl) = TREE_SIDE_EFFECTS (decl);
1359*e4b17023SJohn Marino TREE_READONLY (new_decl) = TREE_READONLY (decl);
1360*e4b17023SJohn Marino TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
1361*e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
1362*e4b17023SJohn Marino if ((TREE_CODE (decl) == PARM_DECL
1363*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL
1364*e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL)
1365*e4b17023SJohn Marino && DECL_BY_REFERENCE (decl))
1366*e4b17023SJohn Marino DECL_BY_REFERENCE (new_decl) = 1;
1367*e4b17023SJohn Marino
1368*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (new_decl, x);
1369*e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1370*e4b17023SJohn Marino *slot = new_decl;
1371*e4b17023SJohn Marino
1372*e4b17023SJohn Marino DECL_CHAIN (new_decl) = info->debug_var_chain;
1373*e4b17023SJohn Marino info->debug_var_chain = new_decl;
1374*e4b17023SJohn Marino
1375*e4b17023SJohn Marino /* Do not emit debug info twice. */
1376*e4b17023SJohn Marino DECL_IGNORED_P (decl) = 1;
1377*e4b17023SJohn Marino
1378*e4b17023SJohn Marino return new_decl;
1379*e4b17023SJohn Marino }
1380*e4b17023SJohn Marino
1381*e4b17023SJohn Marino
1382*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR
1383*e4b17023SJohn Marino and PARM_DECLs that were referenced by inner nested functions.
1384*e4b17023SJohn Marino The rewrite will be a structure reference to the local frame variable. */
1385*e4b17023SJohn Marino
1386*e4b17023SJohn Marino static bool convert_local_omp_clauses (tree *, struct walk_stmt_info *);
1387*e4b17023SJohn Marino
1388*e4b17023SJohn Marino static tree
convert_local_reference_op(tree * tp,int * walk_subtrees,void * data)1389*e4b17023SJohn Marino convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
1390*e4b17023SJohn Marino {
1391*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1392*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
1393*e4b17023SJohn Marino tree t = *tp, field, x;
1394*e4b17023SJohn Marino bool save_val_only;
1395*e4b17023SJohn Marino
1396*e4b17023SJohn Marino *walk_subtrees = 0;
1397*e4b17023SJohn Marino switch (TREE_CODE (t))
1398*e4b17023SJohn Marino {
1399*e4b17023SJohn Marino case VAR_DECL:
1400*e4b17023SJohn Marino /* Non-automatic variables are never processed. */
1401*e4b17023SJohn Marino if (TREE_STATIC (t) || DECL_EXTERNAL (t))
1402*e4b17023SJohn Marino break;
1403*e4b17023SJohn Marino /* FALLTHRU */
1404*e4b17023SJohn Marino
1405*e4b17023SJohn Marino case PARM_DECL:
1406*e4b17023SJohn Marino if (decl_function_context (t) == info->context)
1407*e4b17023SJohn Marino {
1408*e4b17023SJohn Marino /* If we copied a pointer to the frame, then the original decl
1409*e4b17023SJohn Marino is used unchanged in the parent function. */
1410*e4b17023SJohn Marino if (use_pointer_in_frame (t))
1411*e4b17023SJohn Marino break;
1412*e4b17023SJohn Marino
1413*e4b17023SJohn Marino /* No need to transform anything if no child references the
1414*e4b17023SJohn Marino variable. */
1415*e4b17023SJohn Marino field = lookup_field_for_decl (info, t, NO_INSERT);
1416*e4b17023SJohn Marino if (!field)
1417*e4b17023SJohn Marino break;
1418*e4b17023SJohn Marino wi->changed = true;
1419*e4b17023SJohn Marino
1420*e4b17023SJohn Marino x = get_local_debug_decl (info, t, field);
1421*e4b17023SJohn Marino if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
1422*e4b17023SJohn Marino x = get_frame_field (info, info->context, field, &wi->gsi);
1423*e4b17023SJohn Marino
1424*e4b17023SJohn Marino if (wi->val_only)
1425*e4b17023SJohn Marino {
1426*e4b17023SJohn Marino if (wi->is_lhs)
1427*e4b17023SJohn Marino x = save_tmp_var (info, x, &wi->gsi);
1428*e4b17023SJohn Marino else
1429*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi);
1430*e4b17023SJohn Marino }
1431*e4b17023SJohn Marino
1432*e4b17023SJohn Marino *tp = x;
1433*e4b17023SJohn Marino }
1434*e4b17023SJohn Marino break;
1435*e4b17023SJohn Marino
1436*e4b17023SJohn Marino case ADDR_EXPR:
1437*e4b17023SJohn Marino save_val_only = wi->val_only;
1438*e4b17023SJohn Marino wi->val_only = false;
1439*e4b17023SJohn Marino wi->is_lhs = false;
1440*e4b17023SJohn Marino wi->changed = false;
1441*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op, wi, NULL);
1442*e4b17023SJohn Marino wi->val_only = save_val_only;
1443*e4b17023SJohn Marino
1444*e4b17023SJohn Marino /* If we converted anything ... */
1445*e4b17023SJohn Marino if (wi->changed)
1446*e4b17023SJohn Marino {
1447*e4b17023SJohn Marino tree save_context;
1448*e4b17023SJohn Marino
1449*e4b17023SJohn Marino /* Then the frame decl is now addressable. */
1450*e4b17023SJohn Marino TREE_ADDRESSABLE (info->frame_decl) = 1;
1451*e4b17023SJohn Marino
1452*e4b17023SJohn Marino save_context = current_function_decl;
1453*e4b17023SJohn Marino current_function_decl = info->context;
1454*e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (t);
1455*e4b17023SJohn Marino current_function_decl = save_context;
1456*e4b17023SJohn Marino
1457*e4b17023SJohn Marino /* If we are in a context where we only accept values, then
1458*e4b17023SJohn Marino compute the address into a temporary. */
1459*e4b17023SJohn Marino if (save_val_only)
1460*e4b17023SJohn Marino *tp = gsi_gimplify_val ((struct nesting_info *) wi->info,
1461*e4b17023SJohn Marino t, &wi->gsi);
1462*e4b17023SJohn Marino }
1463*e4b17023SJohn Marino break;
1464*e4b17023SJohn Marino
1465*e4b17023SJohn Marino case REALPART_EXPR:
1466*e4b17023SJohn Marino case IMAGPART_EXPR:
1467*e4b17023SJohn Marino case COMPONENT_REF:
1468*e4b17023SJohn Marino case ARRAY_REF:
1469*e4b17023SJohn Marino case ARRAY_RANGE_REF:
1470*e4b17023SJohn Marino case BIT_FIELD_REF:
1471*e4b17023SJohn Marino /* Go down this entire nest and just look at the final prefix and
1472*e4b17023SJohn Marino anything that describes the references. Otherwise, we lose track
1473*e4b17023SJohn Marino of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value. */
1474*e4b17023SJohn Marino save_val_only = wi->val_only;
1475*e4b17023SJohn Marino wi->val_only = true;
1476*e4b17023SJohn Marino wi->is_lhs = false;
1477*e4b17023SJohn Marino for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
1478*e4b17023SJohn Marino {
1479*e4b17023SJohn Marino if (TREE_CODE (t) == COMPONENT_REF)
1480*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
1481*e4b17023SJohn Marino NULL);
1482*e4b17023SJohn Marino else if (TREE_CODE (t) == ARRAY_REF
1483*e4b17023SJohn Marino || TREE_CODE (t) == ARRAY_RANGE_REF)
1484*e4b17023SJohn Marino {
1485*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
1486*e4b17023SJohn Marino NULL);
1487*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
1488*e4b17023SJohn Marino NULL);
1489*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 3), convert_local_reference_op, wi,
1490*e4b17023SJohn Marino NULL);
1491*e4b17023SJohn Marino }
1492*e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF)
1493*e4b17023SJohn Marino {
1494*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
1495*e4b17023SJohn Marino NULL);
1496*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
1497*e4b17023SJohn Marino NULL);
1498*e4b17023SJohn Marino }
1499*e4b17023SJohn Marino }
1500*e4b17023SJohn Marino wi->val_only = false;
1501*e4b17023SJohn Marino walk_tree (tp, convert_local_reference_op, wi, NULL);
1502*e4b17023SJohn Marino wi->val_only = save_val_only;
1503*e4b17023SJohn Marino break;
1504*e4b17023SJohn Marino
1505*e4b17023SJohn Marino case MEM_REF:
1506*e4b17023SJohn Marino save_val_only = wi->val_only;
1507*e4b17023SJohn Marino wi->val_only = true;
1508*e4b17023SJohn Marino wi->is_lhs = false;
1509*e4b17023SJohn Marino walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op,
1510*e4b17023SJohn Marino wi, NULL);
1511*e4b17023SJohn Marino /* We need to re-fold the MEM_REF as component references as
1512*e4b17023SJohn Marino part of a ADDR_EXPR address are not allowed. But we cannot
1513*e4b17023SJohn Marino fold here, as the chain record type is not yet finalized. */
1514*e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
1515*e4b17023SJohn Marino && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
1516*e4b17023SJohn Marino pointer_set_insert (info->mem_refs, tp);
1517*e4b17023SJohn Marino wi->val_only = save_val_only;
1518*e4b17023SJohn Marino break;
1519*e4b17023SJohn Marino
1520*e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
1521*e4b17023SJohn Marino /* Just request to look at the subtrees, leaving val_only and lhs
1522*e4b17023SJohn Marino untouched. This might actually be for !val_only + lhs, in which
1523*e4b17023SJohn Marino case we don't want to force a replacement by a temporary. */
1524*e4b17023SJohn Marino *walk_subtrees = 1;
1525*e4b17023SJohn Marino break;
1526*e4b17023SJohn Marino
1527*e4b17023SJohn Marino default:
1528*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t))
1529*e4b17023SJohn Marino {
1530*e4b17023SJohn Marino *walk_subtrees = 1;
1531*e4b17023SJohn Marino wi->val_only = true;
1532*e4b17023SJohn Marino wi->is_lhs = false;
1533*e4b17023SJohn Marino }
1534*e4b17023SJohn Marino break;
1535*e4b17023SJohn Marino }
1536*e4b17023SJohn Marino
1537*e4b17023SJohn Marino return NULL_TREE;
1538*e4b17023SJohn Marino }
1539*e4b17023SJohn Marino
1540*e4b17023SJohn Marino static tree convert_local_reference_stmt (gimple_stmt_iterator *, bool *,
1541*e4b17023SJohn Marino struct walk_stmt_info *);
1542*e4b17023SJohn Marino
1543*e4b17023SJohn Marino /* Helper for convert_local_reference. Convert all the references in
1544*e4b17023SJohn Marino the chain of clauses at *PCLAUSES. WI is as in convert_local_reference. */
1545*e4b17023SJohn Marino
1546*e4b17023SJohn Marino static bool
convert_local_omp_clauses(tree * pclauses,struct walk_stmt_info * wi)1547*e4b17023SJohn Marino convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
1548*e4b17023SJohn Marino {
1549*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
1550*e4b17023SJohn Marino bool need_frame = false, need_stmts = false;
1551*e4b17023SJohn Marino tree clause, decl;
1552*e4b17023SJohn Marino int dummy;
1553*e4b17023SJohn Marino bitmap new_suppress;
1554*e4b17023SJohn Marino
1555*e4b17023SJohn Marino new_suppress = BITMAP_GGC_ALLOC ();
1556*e4b17023SJohn Marino bitmap_copy (new_suppress, info->suppress_expansion);
1557*e4b17023SJohn Marino
1558*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
1559*e4b17023SJohn Marino {
1560*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause))
1561*e4b17023SJohn Marino {
1562*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
1563*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1564*e4b17023SJohn Marino need_stmts = true;
1565*e4b17023SJohn Marino goto do_decl_clause;
1566*e4b17023SJohn Marino
1567*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
1568*e4b17023SJohn Marino if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause))
1569*e4b17023SJohn Marino need_stmts = true;
1570*e4b17023SJohn Marino goto do_decl_clause;
1571*e4b17023SJohn Marino
1572*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
1573*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
1574*e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE:
1575*e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
1576*e4b17023SJohn Marino do_decl_clause:
1577*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (clause);
1578*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
1579*e4b17023SJohn Marino && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
1580*e4b17023SJohn Marino break;
1581*e4b17023SJohn Marino if (decl_function_context (decl) == info->context
1582*e4b17023SJohn Marino && !use_pointer_in_frame (decl))
1583*e4b17023SJohn Marino {
1584*e4b17023SJohn Marino tree field = lookup_field_for_decl (info, decl, NO_INSERT);
1585*e4b17023SJohn Marino if (field)
1586*e4b17023SJohn Marino {
1587*e4b17023SJohn Marino bitmap_set_bit (new_suppress, DECL_UID (decl));
1588*e4b17023SJohn Marino OMP_CLAUSE_DECL (clause)
1589*e4b17023SJohn Marino = get_local_debug_decl (info, decl, field);
1590*e4b17023SJohn Marino need_frame = true;
1591*e4b17023SJohn Marino }
1592*e4b17023SJohn Marino }
1593*e4b17023SJohn Marino break;
1594*e4b17023SJohn Marino
1595*e4b17023SJohn Marino case OMP_CLAUSE_SCHEDULE:
1596*e4b17023SJohn Marino if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
1597*e4b17023SJohn Marino break;
1598*e4b17023SJohn Marino /* FALLTHRU */
1599*e4b17023SJohn Marino case OMP_CLAUSE_FINAL:
1600*e4b17023SJohn Marino case OMP_CLAUSE_IF:
1601*e4b17023SJohn Marino case OMP_CLAUSE_NUM_THREADS:
1602*e4b17023SJohn Marino wi->val_only = true;
1603*e4b17023SJohn Marino wi->is_lhs = false;
1604*e4b17023SJohn Marino convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
1605*e4b17023SJohn Marino wi);
1606*e4b17023SJohn Marino break;
1607*e4b17023SJohn Marino
1608*e4b17023SJohn Marino case OMP_CLAUSE_NOWAIT:
1609*e4b17023SJohn Marino case OMP_CLAUSE_ORDERED:
1610*e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT:
1611*e4b17023SJohn Marino case OMP_CLAUSE_COPYIN:
1612*e4b17023SJohn Marino case OMP_CLAUSE_COLLAPSE:
1613*e4b17023SJohn Marino case OMP_CLAUSE_UNTIED:
1614*e4b17023SJohn Marino case OMP_CLAUSE_MERGEABLE:
1615*e4b17023SJohn Marino break;
1616*e4b17023SJohn Marino
1617*e4b17023SJohn Marino default:
1618*e4b17023SJohn Marino gcc_unreachable ();
1619*e4b17023SJohn Marino }
1620*e4b17023SJohn Marino }
1621*e4b17023SJohn Marino
1622*e4b17023SJohn Marino info->suppress_expansion = new_suppress;
1623*e4b17023SJohn Marino
1624*e4b17023SJohn Marino if (need_stmts)
1625*e4b17023SJohn Marino for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
1626*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (clause))
1627*e4b17023SJohn Marino {
1628*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
1629*e4b17023SJohn Marino if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1630*e4b17023SJohn Marino {
1631*e4b17023SJohn Marino tree old_context
1632*e4b17023SJohn Marino = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause));
1633*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1634*e4b17023SJohn Marino = info->context;
1635*e4b17023SJohn Marino walk_body (convert_local_reference_stmt,
1636*e4b17023SJohn Marino convert_local_reference_op, info,
1637*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
1638*e4b17023SJohn Marino walk_body (convert_local_reference_stmt,
1639*e4b17023SJohn Marino convert_local_reference_op, info,
1640*e4b17023SJohn Marino OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
1641*e4b17023SJohn Marino DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
1642*e4b17023SJohn Marino = old_context;
1643*e4b17023SJohn Marino }
1644*e4b17023SJohn Marino break;
1645*e4b17023SJohn Marino
1646*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
1647*e4b17023SJohn Marino walk_body (convert_local_reference_stmt,
1648*e4b17023SJohn Marino convert_local_reference_op, info,
1649*e4b17023SJohn Marino OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
1650*e4b17023SJohn Marino break;
1651*e4b17023SJohn Marino
1652*e4b17023SJohn Marino default:
1653*e4b17023SJohn Marino break;
1654*e4b17023SJohn Marino }
1655*e4b17023SJohn Marino
1656*e4b17023SJohn Marino return need_frame;
1657*e4b17023SJohn Marino }
1658*e4b17023SJohn Marino
1659*e4b17023SJohn Marino
1660*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR
1661*e4b17023SJohn Marino and PARM_DECLs that were referenced by inner nested functions.
1662*e4b17023SJohn Marino The rewrite will be a structure reference to the local frame variable. */
1663*e4b17023SJohn Marino
1664*e4b17023SJohn Marino static tree
convert_local_reference_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)1665*e4b17023SJohn Marino convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1666*e4b17023SJohn Marino struct walk_stmt_info *wi)
1667*e4b17023SJohn Marino {
1668*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info;
1669*e4b17023SJohn Marino tree save_local_var_chain;
1670*e4b17023SJohn Marino bitmap save_suppress;
1671*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
1672*e4b17023SJohn Marino
1673*e4b17023SJohn Marino switch (gimple_code (stmt))
1674*e4b17023SJohn Marino {
1675*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL:
1676*e4b17023SJohn Marino case GIMPLE_OMP_TASK:
1677*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1678*e4b17023SJohn Marino if (convert_local_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt),
1679*e4b17023SJohn Marino wi))
1680*e4b17023SJohn Marino {
1681*e4b17023SJohn Marino tree c;
1682*e4b17023SJohn Marino (void) get_frame_type (info);
1683*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt),
1684*e4b17023SJohn Marino OMP_CLAUSE_SHARED);
1685*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = info->frame_decl;
1686*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
1687*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c);
1688*e4b17023SJohn Marino }
1689*e4b17023SJohn Marino
1690*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain;
1691*e4b17023SJohn Marino info->new_local_var_chain = NULL;
1692*e4b17023SJohn Marino
1693*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
1694*e4b17023SJohn Marino gimple_omp_body (stmt));
1695*e4b17023SJohn Marino
1696*e4b17023SJohn Marino if (info->new_local_var_chain)
1697*e4b17023SJohn Marino declare_vars (info->new_local_var_chain,
1698*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
1699*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain;
1700*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1701*e4b17023SJohn Marino break;
1702*e4b17023SJohn Marino
1703*e4b17023SJohn Marino case GIMPLE_OMP_FOR:
1704*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1705*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
1706*e4b17023SJohn Marino walk_gimple_omp_for (stmt, convert_local_reference_stmt,
1707*e4b17023SJohn Marino convert_local_reference_op, info);
1708*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op,
1709*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1710*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1711*e4b17023SJohn Marino break;
1712*e4b17023SJohn Marino
1713*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS:
1714*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1715*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
1716*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op,
1717*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1718*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1719*e4b17023SJohn Marino break;
1720*e4b17023SJohn Marino
1721*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE:
1722*e4b17023SJohn Marino save_suppress = info->suppress_expansion;
1723*e4b17023SJohn Marino convert_local_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
1724*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op,
1725*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1726*e4b17023SJohn Marino info->suppress_expansion = save_suppress;
1727*e4b17023SJohn Marino break;
1728*e4b17023SJohn Marino
1729*e4b17023SJohn Marino case GIMPLE_OMP_SECTION:
1730*e4b17023SJohn Marino case GIMPLE_OMP_MASTER:
1731*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED:
1732*e4b17023SJohn Marino walk_body (convert_local_reference_stmt, convert_local_reference_op,
1733*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1734*e4b17023SJohn Marino break;
1735*e4b17023SJohn Marino
1736*e4b17023SJohn Marino case GIMPLE_COND:
1737*e4b17023SJohn Marino wi->val_only = true;
1738*e4b17023SJohn Marino wi->is_lhs = false;
1739*e4b17023SJohn Marino *handled_ops_p = false;
1740*e4b17023SJohn Marino return NULL_TREE;
1741*e4b17023SJohn Marino
1742*e4b17023SJohn Marino default:
1743*e4b17023SJohn Marino /* For every other statement that we are not interested in
1744*e4b17023SJohn Marino handling here, let the walker traverse the operands. */
1745*e4b17023SJohn Marino *handled_ops_p = false;
1746*e4b17023SJohn Marino return NULL_TREE;
1747*e4b17023SJohn Marino }
1748*e4b17023SJohn Marino
1749*e4b17023SJohn Marino /* Indicate that we have handled all the operands ourselves. */
1750*e4b17023SJohn Marino *handled_ops_p = true;
1751*e4b17023SJohn Marino return NULL_TREE;
1752*e4b17023SJohn Marino }
1753*e4b17023SJohn Marino
1754*e4b17023SJohn Marino
1755*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_GOTOs
1756*e4b17023SJohn Marino that reference labels from outer functions. The rewrite will be a
1757*e4b17023SJohn Marino call to __builtin_nonlocal_goto. */
1758*e4b17023SJohn Marino
1759*e4b17023SJohn Marino static tree
convert_nl_goto_reference(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)1760*e4b17023SJohn Marino convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1761*e4b17023SJohn Marino struct walk_stmt_info *wi)
1762*e4b17023SJohn Marino {
1763*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
1764*e4b17023SJohn Marino tree label, new_label, target_context, x, field;
1765*e4b17023SJohn Marino void **slot;
1766*e4b17023SJohn Marino gimple call;
1767*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
1768*e4b17023SJohn Marino
1769*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_GOTO)
1770*e4b17023SJohn Marino {
1771*e4b17023SJohn Marino *handled_ops_p = false;
1772*e4b17023SJohn Marino return NULL_TREE;
1773*e4b17023SJohn Marino }
1774*e4b17023SJohn Marino
1775*e4b17023SJohn Marino label = gimple_goto_dest (stmt);
1776*e4b17023SJohn Marino if (TREE_CODE (label) != LABEL_DECL)
1777*e4b17023SJohn Marino {
1778*e4b17023SJohn Marino *handled_ops_p = false;
1779*e4b17023SJohn Marino return NULL_TREE;
1780*e4b17023SJohn Marino }
1781*e4b17023SJohn Marino
1782*e4b17023SJohn Marino target_context = decl_function_context (label);
1783*e4b17023SJohn Marino if (target_context == info->context)
1784*e4b17023SJohn Marino {
1785*e4b17023SJohn Marino *handled_ops_p = false;
1786*e4b17023SJohn Marino return NULL_TREE;
1787*e4b17023SJohn Marino }
1788*e4b17023SJohn Marino
1789*e4b17023SJohn Marino for (i = info->outer; target_context != i->context; i = i->outer)
1790*e4b17023SJohn Marino continue;
1791*e4b17023SJohn Marino
1792*e4b17023SJohn Marino /* The original user label may also be use for a normal goto, therefore
1793*e4b17023SJohn Marino we must create a new label that will actually receive the abnormal
1794*e4b17023SJohn Marino control transfer. This new label will be marked LABEL_NONLOCAL; this
1795*e4b17023SJohn Marino mark will trigger proper behavior in the cfg, as well as cause the
1796*e4b17023SJohn Marino (hairy target-specific) non-local goto receiver code to be generated
1797*e4b17023SJohn Marino when we expand rtl. Enter this association into var_map so that we
1798*e4b17023SJohn Marino can insert the new label into the IL during a second pass. */
1799*e4b17023SJohn Marino slot = pointer_map_insert (i->var_map, label);
1800*e4b17023SJohn Marino if (*slot == NULL)
1801*e4b17023SJohn Marino {
1802*e4b17023SJohn Marino new_label = create_artificial_label (UNKNOWN_LOCATION);
1803*e4b17023SJohn Marino DECL_NONLOCAL (new_label) = 1;
1804*e4b17023SJohn Marino *slot = new_label;
1805*e4b17023SJohn Marino }
1806*e4b17023SJohn Marino else
1807*e4b17023SJohn Marino new_label = (tree) *slot;
1808*e4b17023SJohn Marino
1809*e4b17023SJohn Marino /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field). */
1810*e4b17023SJohn Marino field = get_nl_goto_field (i);
1811*e4b17023SJohn Marino x = get_frame_field (info, target_context, field, &wi->gsi);
1812*e4b17023SJohn Marino x = build_addr (x, target_context);
1813*e4b17023SJohn Marino x = gsi_gimplify_val (info, x, &wi->gsi);
1814*e4b17023SJohn Marino call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
1815*e4b17023SJohn Marino 2, build_addr (new_label, target_context), x);
1816*e4b17023SJohn Marino gsi_replace (&wi->gsi, call, false);
1817*e4b17023SJohn Marino
1818*e4b17023SJohn Marino /* We have handled all of STMT's operands, no need to keep going. */
1819*e4b17023SJohn Marino *handled_ops_p = true;
1820*e4b17023SJohn Marino return NULL_TREE;
1821*e4b17023SJohn Marino }
1822*e4b17023SJohn Marino
1823*e4b17023SJohn Marino
1824*e4b17023SJohn Marino /* Called via walk_function+walk_tree, rewrite all GIMPLE_LABELs whose labels
1825*e4b17023SJohn Marino are referenced via nonlocal goto from a nested function. The rewrite
1826*e4b17023SJohn Marino will involve installing a newly generated DECL_NONLOCAL label, and
1827*e4b17023SJohn Marino (potentially) a branch around the rtl gunk that is assumed to be
1828*e4b17023SJohn Marino attached to such a label. */
1829*e4b17023SJohn Marino
1830*e4b17023SJohn Marino static tree
convert_nl_goto_receiver(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)1831*e4b17023SJohn Marino convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1832*e4b17023SJohn Marino struct walk_stmt_info *wi)
1833*e4b17023SJohn Marino {
1834*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
1835*e4b17023SJohn Marino tree label, new_label;
1836*e4b17023SJohn Marino gimple_stmt_iterator tmp_gsi;
1837*e4b17023SJohn Marino void **slot;
1838*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
1839*e4b17023SJohn Marino
1840*e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
1841*e4b17023SJohn Marino {
1842*e4b17023SJohn Marino *handled_ops_p = false;
1843*e4b17023SJohn Marino return NULL_TREE;
1844*e4b17023SJohn Marino }
1845*e4b17023SJohn Marino
1846*e4b17023SJohn Marino label = gimple_label_label (stmt);
1847*e4b17023SJohn Marino
1848*e4b17023SJohn Marino slot = pointer_map_contains (info->var_map, label);
1849*e4b17023SJohn Marino if (!slot)
1850*e4b17023SJohn Marino {
1851*e4b17023SJohn Marino *handled_ops_p = false;
1852*e4b17023SJohn Marino return NULL_TREE;
1853*e4b17023SJohn Marino }
1854*e4b17023SJohn Marino
1855*e4b17023SJohn Marino /* If there's any possibility that the previous statement falls through,
1856*e4b17023SJohn Marino then we must branch around the new non-local label. */
1857*e4b17023SJohn Marino tmp_gsi = wi->gsi;
1858*e4b17023SJohn Marino gsi_prev (&tmp_gsi);
1859*e4b17023SJohn Marino if (gsi_end_p (tmp_gsi) || gimple_stmt_may_fallthru (gsi_stmt (tmp_gsi)))
1860*e4b17023SJohn Marino {
1861*e4b17023SJohn Marino gimple stmt = gimple_build_goto (label);
1862*e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1863*e4b17023SJohn Marino }
1864*e4b17023SJohn Marino
1865*e4b17023SJohn Marino new_label = (tree) *slot;
1866*e4b17023SJohn Marino stmt = gimple_build_label (new_label);
1867*e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1868*e4b17023SJohn Marino
1869*e4b17023SJohn Marino *handled_ops_p = true;
1870*e4b17023SJohn Marino return NULL_TREE;
1871*e4b17023SJohn Marino }
1872*e4b17023SJohn Marino
1873*e4b17023SJohn Marino
1874*e4b17023SJohn Marino /* Called via walk_function+walk_stmt, rewrite all references to addresses
1875*e4b17023SJohn Marino of nested functions that require the use of trampolines. The rewrite
1876*e4b17023SJohn Marino will involve a reference a trampoline generated for the occasion. */
1877*e4b17023SJohn Marino
1878*e4b17023SJohn Marino static tree
convert_tramp_reference_op(tree * tp,int * walk_subtrees,void * data)1879*e4b17023SJohn Marino convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
1880*e4b17023SJohn Marino {
1881*e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1882*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
1883*e4b17023SJohn Marino tree t = *tp, decl, target_context, x, builtin;
1884*e4b17023SJohn Marino gimple call;
1885*e4b17023SJohn Marino
1886*e4b17023SJohn Marino *walk_subtrees = 0;
1887*e4b17023SJohn Marino switch (TREE_CODE (t))
1888*e4b17023SJohn Marino {
1889*e4b17023SJohn Marino case ADDR_EXPR:
1890*e4b17023SJohn Marino /* Build
1891*e4b17023SJohn Marino T.1 = &CHAIN->tramp;
1892*e4b17023SJohn Marino T.2 = __builtin_adjust_trampoline (T.1);
1893*e4b17023SJohn Marino T.3 = (func_type)T.2;
1894*e4b17023SJohn Marino */
1895*e4b17023SJohn Marino
1896*e4b17023SJohn Marino decl = TREE_OPERAND (t, 0);
1897*e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL)
1898*e4b17023SJohn Marino break;
1899*e4b17023SJohn Marino
1900*e4b17023SJohn Marino /* Only need to process nested functions. */
1901*e4b17023SJohn Marino target_context = decl_function_context (decl);
1902*e4b17023SJohn Marino if (!target_context)
1903*e4b17023SJohn Marino break;
1904*e4b17023SJohn Marino
1905*e4b17023SJohn Marino /* If the nested function doesn't use a static chain, then
1906*e4b17023SJohn Marino it doesn't need a trampoline. */
1907*e4b17023SJohn Marino if (!DECL_STATIC_CHAIN (decl))
1908*e4b17023SJohn Marino break;
1909*e4b17023SJohn Marino
1910*e4b17023SJohn Marino /* If we don't want a trampoline, then don't build one. */
1911*e4b17023SJohn Marino if (TREE_NO_TRAMPOLINE (t))
1912*e4b17023SJohn Marino break;
1913*e4b17023SJohn Marino
1914*e4b17023SJohn Marino /* Lookup the immediate parent of the callee, as that's where
1915*e4b17023SJohn Marino we need to insert the trampoline. */
1916*e4b17023SJohn Marino for (i = info; i->context != target_context; i = i->outer)
1917*e4b17023SJohn Marino continue;
1918*e4b17023SJohn Marino x = lookup_tramp_for_decl (i, decl, INSERT);
1919*e4b17023SJohn Marino
1920*e4b17023SJohn Marino /* Compute the address of the field holding the trampoline. */
1921*e4b17023SJohn Marino x = get_frame_field (info, target_context, x, &wi->gsi);
1922*e4b17023SJohn Marino x = build_addr (x, target_context);
1923*e4b17023SJohn Marino x = gsi_gimplify_val (info, x, &wi->gsi);
1924*e4b17023SJohn Marino
1925*e4b17023SJohn Marino /* Do machine-specific ugliness. Normally this will involve
1926*e4b17023SJohn Marino computing extra alignment, but it can really be anything. */
1927*e4b17023SJohn Marino builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
1928*e4b17023SJohn Marino call = gimple_build_call (builtin, 1, x);
1929*e4b17023SJohn Marino x = init_tmp_var_with_call (info, &wi->gsi, call);
1930*e4b17023SJohn Marino
1931*e4b17023SJohn Marino /* Cast back to the proper function type. */
1932*e4b17023SJohn Marino x = build1 (NOP_EXPR, TREE_TYPE (t), x);
1933*e4b17023SJohn Marino x = init_tmp_var (info, x, &wi->gsi);
1934*e4b17023SJohn Marino
1935*e4b17023SJohn Marino *tp = x;
1936*e4b17023SJohn Marino break;
1937*e4b17023SJohn Marino
1938*e4b17023SJohn Marino default:
1939*e4b17023SJohn Marino if (!IS_TYPE_OR_DECL_P (t))
1940*e4b17023SJohn Marino *walk_subtrees = 1;
1941*e4b17023SJohn Marino break;
1942*e4b17023SJohn Marino }
1943*e4b17023SJohn Marino
1944*e4b17023SJohn Marino return NULL_TREE;
1945*e4b17023SJohn Marino }
1946*e4b17023SJohn Marino
1947*e4b17023SJohn Marino
1948*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all references
1949*e4b17023SJohn Marino to addresses of nested functions that require the use of
1950*e4b17023SJohn Marino trampolines. The rewrite will involve a reference a trampoline
1951*e4b17023SJohn Marino generated for the occasion. */
1952*e4b17023SJohn Marino
1953*e4b17023SJohn Marino static tree
convert_tramp_reference_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)1954*e4b17023SJohn Marino convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1955*e4b17023SJohn Marino struct walk_stmt_info *wi)
1956*e4b17023SJohn Marino {
1957*e4b17023SJohn Marino struct nesting_info *info = (struct nesting_info *) wi->info;
1958*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
1959*e4b17023SJohn Marino
1960*e4b17023SJohn Marino switch (gimple_code (stmt))
1961*e4b17023SJohn Marino {
1962*e4b17023SJohn Marino case GIMPLE_CALL:
1963*e4b17023SJohn Marino {
1964*e4b17023SJohn Marino /* Only walk call arguments, lest we generate trampolines for
1965*e4b17023SJohn Marino direct calls. */
1966*e4b17023SJohn Marino unsigned long i, nargs = gimple_call_num_args (stmt);
1967*e4b17023SJohn Marino for (i = 0; i < nargs; i++)
1968*e4b17023SJohn Marino walk_tree (gimple_call_arg_ptr (stmt, i), convert_tramp_reference_op,
1969*e4b17023SJohn Marino wi, NULL);
1970*e4b17023SJohn Marino break;
1971*e4b17023SJohn Marino }
1972*e4b17023SJohn Marino
1973*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL:
1974*e4b17023SJohn Marino case GIMPLE_OMP_TASK:
1975*e4b17023SJohn Marino {
1976*e4b17023SJohn Marino tree save_local_var_chain;
1977*e4b17023SJohn Marino walk_gimple_op (stmt, convert_tramp_reference_op, wi);
1978*e4b17023SJohn Marino save_local_var_chain = info->new_local_var_chain;
1979*e4b17023SJohn Marino info->new_local_var_chain = NULL;
1980*e4b17023SJohn Marino walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op,
1981*e4b17023SJohn Marino info, gimple_omp_body (stmt));
1982*e4b17023SJohn Marino if (info->new_local_var_chain)
1983*e4b17023SJohn Marino declare_vars (info->new_local_var_chain,
1984*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_omp_body (stmt)),
1985*e4b17023SJohn Marino false);
1986*e4b17023SJohn Marino info->new_local_var_chain = save_local_var_chain;
1987*e4b17023SJohn Marino }
1988*e4b17023SJohn Marino break;
1989*e4b17023SJohn Marino
1990*e4b17023SJohn Marino default:
1991*e4b17023SJohn Marino *handled_ops_p = false;
1992*e4b17023SJohn Marino return NULL_TREE;
1993*e4b17023SJohn Marino break;
1994*e4b17023SJohn Marino }
1995*e4b17023SJohn Marino
1996*e4b17023SJohn Marino *handled_ops_p = true;
1997*e4b17023SJohn Marino return NULL_TREE;
1998*e4b17023SJohn Marino }
1999*e4b17023SJohn Marino
2000*e4b17023SJohn Marino
2001*e4b17023SJohn Marino
2002*e4b17023SJohn Marino /* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_CALLs
2003*e4b17023SJohn Marino that reference nested functions to make sure that the static chain
2004*e4b17023SJohn Marino is set up properly for the call. */
2005*e4b17023SJohn Marino
2006*e4b17023SJohn Marino static tree
convert_gimple_call(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)2007*e4b17023SJohn Marino convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2008*e4b17023SJohn Marino struct walk_stmt_info *wi)
2009*e4b17023SJohn Marino {
2010*e4b17023SJohn Marino struct nesting_info *const info = (struct nesting_info *) wi->info;
2011*e4b17023SJohn Marino tree decl, target_context;
2012*e4b17023SJohn Marino char save_static_chain_added;
2013*e4b17023SJohn Marino int i;
2014*e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi);
2015*e4b17023SJohn Marino
2016*e4b17023SJohn Marino switch (gimple_code (stmt))
2017*e4b17023SJohn Marino {
2018*e4b17023SJohn Marino case GIMPLE_CALL:
2019*e4b17023SJohn Marino if (gimple_call_chain (stmt))
2020*e4b17023SJohn Marino break;
2021*e4b17023SJohn Marino decl = gimple_call_fndecl (stmt);
2022*e4b17023SJohn Marino if (!decl)
2023*e4b17023SJohn Marino break;
2024*e4b17023SJohn Marino target_context = decl_function_context (decl);
2025*e4b17023SJohn Marino if (target_context && DECL_STATIC_CHAIN (decl))
2026*e4b17023SJohn Marino {
2027*e4b17023SJohn Marino gimple_call_set_chain (stmt, get_static_chain (info, target_context,
2028*e4b17023SJohn Marino &wi->gsi));
2029*e4b17023SJohn Marino info->static_chain_added |= (1 << (info->context != target_context));
2030*e4b17023SJohn Marino }
2031*e4b17023SJohn Marino break;
2032*e4b17023SJohn Marino
2033*e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL:
2034*e4b17023SJohn Marino case GIMPLE_OMP_TASK:
2035*e4b17023SJohn Marino save_static_chain_added = info->static_chain_added;
2036*e4b17023SJohn Marino info->static_chain_added = 0;
2037*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
2038*e4b17023SJohn Marino for (i = 0; i < 2; i++)
2039*e4b17023SJohn Marino {
2040*e4b17023SJohn Marino tree c, decl;
2041*e4b17023SJohn Marino if ((info->static_chain_added & (1 << i)) == 0)
2042*e4b17023SJohn Marino continue;
2043*e4b17023SJohn Marino decl = i ? get_chain_decl (info) : info->frame_decl;
2044*e4b17023SJohn Marino /* Don't add CHAIN.* or FRAME.* twice. */
2045*e4b17023SJohn Marino for (c = gimple_omp_taskreg_clauses (stmt);
2046*e4b17023SJohn Marino c;
2047*e4b17023SJohn Marino c = OMP_CLAUSE_CHAIN (c))
2048*e4b17023SJohn Marino if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2049*e4b17023SJohn Marino || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2050*e4b17023SJohn Marino && OMP_CLAUSE_DECL (c) == decl)
2051*e4b17023SJohn Marino break;
2052*e4b17023SJohn Marino if (c == NULL)
2053*e4b17023SJohn Marino {
2054*e4b17023SJohn Marino c = build_omp_clause (gimple_location (stmt),
2055*e4b17023SJohn Marino i ? OMP_CLAUSE_FIRSTPRIVATE
2056*e4b17023SJohn Marino : OMP_CLAUSE_SHARED);
2057*e4b17023SJohn Marino OMP_CLAUSE_DECL (c) = decl;
2058*e4b17023SJohn Marino OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2059*e4b17023SJohn Marino gimple_omp_taskreg_set_clauses (stmt, c);
2060*e4b17023SJohn Marino }
2061*e4b17023SJohn Marino }
2062*e4b17023SJohn Marino info->static_chain_added |= save_static_chain_added;
2063*e4b17023SJohn Marino break;
2064*e4b17023SJohn Marino
2065*e4b17023SJohn Marino case GIMPLE_OMP_FOR:
2066*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info,
2067*e4b17023SJohn Marino gimple_omp_for_pre_body (stmt));
2068*e4b17023SJohn Marino /* FALLTHRU */
2069*e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS:
2070*e4b17023SJohn Marino case GIMPLE_OMP_SECTION:
2071*e4b17023SJohn Marino case GIMPLE_OMP_SINGLE:
2072*e4b17023SJohn Marino case GIMPLE_OMP_MASTER:
2073*e4b17023SJohn Marino case GIMPLE_OMP_ORDERED:
2074*e4b17023SJohn Marino case GIMPLE_OMP_CRITICAL:
2075*e4b17023SJohn Marino walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
2076*e4b17023SJohn Marino break;
2077*e4b17023SJohn Marino
2078*e4b17023SJohn Marino default:
2079*e4b17023SJohn Marino /* Keep looking for other operands. */
2080*e4b17023SJohn Marino *handled_ops_p = false;
2081*e4b17023SJohn Marino return NULL_TREE;
2082*e4b17023SJohn Marino }
2083*e4b17023SJohn Marino
2084*e4b17023SJohn Marino *handled_ops_p = true;
2085*e4b17023SJohn Marino return NULL_TREE;
2086*e4b17023SJohn Marino }
2087*e4b17023SJohn Marino
2088*e4b17023SJohn Marino /* Walk the nesting tree starting with ROOT. Convert all trampolines and
2089*e4b17023SJohn Marino call expressions. At the same time, determine if a nested function
2090*e4b17023SJohn Marino actually uses its static chain; if not, remember that. */
2091*e4b17023SJohn Marino
2092*e4b17023SJohn Marino static void
convert_all_function_calls(struct nesting_info * root)2093*e4b17023SJohn Marino convert_all_function_calls (struct nesting_info *root)
2094*e4b17023SJohn Marino {
2095*e4b17023SJohn Marino unsigned int chain_count = 0, old_chain_count, iter_count;
2096*e4b17023SJohn Marino struct nesting_info *n;
2097*e4b17023SJohn Marino
2098*e4b17023SJohn Marino /* First, optimistically clear static_chain for all decls that haven't
2099*e4b17023SJohn Marino used the static chain already for variable access. */
2100*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root)
2101*e4b17023SJohn Marino {
2102*e4b17023SJohn Marino tree decl = n->context;
2103*e4b17023SJohn Marino if (!n->outer || (!n->chain_decl && !n->chain_field))
2104*e4b17023SJohn Marino {
2105*e4b17023SJohn Marino DECL_STATIC_CHAIN (decl) = 0;
2106*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2107*e4b17023SJohn Marino fprintf (dump_file, "Guessing no static-chain for %s\n",
2108*e4b17023SJohn Marino lang_hooks.decl_printable_name (decl, 2));
2109*e4b17023SJohn Marino }
2110*e4b17023SJohn Marino else
2111*e4b17023SJohn Marino DECL_STATIC_CHAIN (decl) = 1;
2112*e4b17023SJohn Marino chain_count += DECL_STATIC_CHAIN (decl);
2113*e4b17023SJohn Marino }
2114*e4b17023SJohn Marino
2115*e4b17023SJohn Marino /* Walk the functions and perform transformations. Note that these
2116*e4b17023SJohn Marino transformations can induce new uses of the static chain, which in turn
2117*e4b17023SJohn Marino require re-examining all users of the decl. */
2118*e4b17023SJohn Marino /* ??? It would make sense to try to use the call graph to speed this up,
2119*e4b17023SJohn Marino but the call graph hasn't really been built yet. Even if it did, we
2120*e4b17023SJohn Marino would still need to iterate in this loop since address-of references
2121*e4b17023SJohn Marino wouldn't show up in the callgraph anyway. */
2122*e4b17023SJohn Marino iter_count = 0;
2123*e4b17023SJohn Marino do
2124*e4b17023SJohn Marino {
2125*e4b17023SJohn Marino old_chain_count = chain_count;
2126*e4b17023SJohn Marino chain_count = 0;
2127*e4b17023SJohn Marino iter_count++;
2128*e4b17023SJohn Marino
2129*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2130*e4b17023SJohn Marino fputc ('\n', dump_file);
2131*e4b17023SJohn Marino
2132*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root)
2133*e4b17023SJohn Marino {
2134*e4b17023SJohn Marino tree decl = n->context;
2135*e4b17023SJohn Marino walk_function (convert_tramp_reference_stmt,
2136*e4b17023SJohn Marino convert_tramp_reference_op, n);
2137*e4b17023SJohn Marino walk_function (convert_gimple_call, NULL, n);
2138*e4b17023SJohn Marino chain_count += DECL_STATIC_CHAIN (decl);
2139*e4b17023SJohn Marino }
2140*e4b17023SJohn Marino }
2141*e4b17023SJohn Marino while (chain_count != old_chain_count);
2142*e4b17023SJohn Marino
2143*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
2144*e4b17023SJohn Marino fprintf (dump_file, "convert_all_function_calls iterations: %u\n\n",
2145*e4b17023SJohn Marino iter_count);
2146*e4b17023SJohn Marino }
2147*e4b17023SJohn Marino
2148*e4b17023SJohn Marino struct nesting_copy_body_data
2149*e4b17023SJohn Marino {
2150*e4b17023SJohn Marino copy_body_data cb;
2151*e4b17023SJohn Marino struct nesting_info *root;
2152*e4b17023SJohn Marino };
2153*e4b17023SJohn Marino
2154*e4b17023SJohn Marino /* A helper subroutine for debug_var_chain type remapping. */
2155*e4b17023SJohn Marino
2156*e4b17023SJohn Marino static tree
nesting_copy_decl(tree decl,copy_body_data * id)2157*e4b17023SJohn Marino nesting_copy_decl (tree decl, copy_body_data *id)
2158*e4b17023SJohn Marino {
2159*e4b17023SJohn Marino struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id;
2160*e4b17023SJohn Marino void **slot = pointer_map_contains (nid->root->var_map, decl);
2161*e4b17023SJohn Marino
2162*e4b17023SJohn Marino if (slot)
2163*e4b17023SJohn Marino return (tree) *slot;
2164*e4b17023SJohn Marino
2165*e4b17023SJohn Marino if (TREE_CODE (decl) == TYPE_DECL && DECL_ORIGINAL_TYPE (decl))
2166*e4b17023SJohn Marino {
2167*e4b17023SJohn Marino tree new_decl = copy_decl_no_change (decl, id);
2168*e4b17023SJohn Marino DECL_ORIGINAL_TYPE (new_decl)
2169*e4b17023SJohn Marino = remap_type (DECL_ORIGINAL_TYPE (decl), id);
2170*e4b17023SJohn Marino return new_decl;
2171*e4b17023SJohn Marino }
2172*e4b17023SJohn Marino
2173*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
2174*e4b17023SJohn Marino || TREE_CODE (decl) == PARM_DECL
2175*e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL)
2176*e4b17023SJohn Marino return decl;
2177*e4b17023SJohn Marino
2178*e4b17023SJohn Marino return copy_decl_no_change (decl, id);
2179*e4b17023SJohn Marino }
2180*e4b17023SJohn Marino
2181*e4b17023SJohn Marino /* A helper function for remap_vla_decls. See if *TP contains
2182*e4b17023SJohn Marino some remapped variables. */
2183*e4b17023SJohn Marino
2184*e4b17023SJohn Marino static tree
contains_remapped_vars(tree * tp,int * walk_subtrees,void * data)2185*e4b17023SJohn Marino contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
2186*e4b17023SJohn Marino {
2187*e4b17023SJohn Marino struct nesting_info *root = (struct nesting_info *) data;
2188*e4b17023SJohn Marino tree t = *tp;
2189*e4b17023SJohn Marino void **slot;
2190*e4b17023SJohn Marino
2191*e4b17023SJohn Marino if (DECL_P (t))
2192*e4b17023SJohn Marino {
2193*e4b17023SJohn Marino *walk_subtrees = 0;
2194*e4b17023SJohn Marino slot = pointer_map_contains (root->var_map, t);
2195*e4b17023SJohn Marino
2196*e4b17023SJohn Marino if (slot)
2197*e4b17023SJohn Marino return (tree) *slot;
2198*e4b17023SJohn Marino }
2199*e4b17023SJohn Marino return NULL;
2200*e4b17023SJohn Marino }
2201*e4b17023SJohn Marino
2202*e4b17023SJohn Marino /* Remap VLA decls in BLOCK and subblocks if remapped variables are
2203*e4b17023SJohn Marino involved. */
2204*e4b17023SJohn Marino
2205*e4b17023SJohn Marino static void
remap_vla_decls(tree block,struct nesting_info * root)2206*e4b17023SJohn Marino remap_vla_decls (tree block, struct nesting_info *root)
2207*e4b17023SJohn Marino {
2208*e4b17023SJohn Marino tree var, subblock, val, type;
2209*e4b17023SJohn Marino struct nesting_copy_body_data id;
2210*e4b17023SJohn Marino
2211*e4b17023SJohn Marino for (subblock = BLOCK_SUBBLOCKS (block);
2212*e4b17023SJohn Marino subblock;
2213*e4b17023SJohn Marino subblock = BLOCK_CHAIN (subblock))
2214*e4b17023SJohn Marino remap_vla_decls (subblock, root);
2215*e4b17023SJohn Marino
2216*e4b17023SJohn Marino for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
2217*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
2218*e4b17023SJohn Marino {
2219*e4b17023SJohn Marino val = DECL_VALUE_EXPR (var);
2220*e4b17023SJohn Marino type = TREE_TYPE (var);
2221*e4b17023SJohn Marino
2222*e4b17023SJohn Marino if (!(TREE_CODE (val) == INDIRECT_REF
2223*e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
2224*e4b17023SJohn Marino && variably_modified_type_p (type, NULL)))
2225*e4b17023SJohn Marino continue;
2226*e4b17023SJohn Marino
2227*e4b17023SJohn Marino if (pointer_map_contains (root->var_map, TREE_OPERAND (val, 0))
2228*e4b17023SJohn Marino || walk_tree (&type, contains_remapped_vars, root, NULL))
2229*e4b17023SJohn Marino break;
2230*e4b17023SJohn Marino }
2231*e4b17023SJohn Marino
2232*e4b17023SJohn Marino if (var == NULL_TREE)
2233*e4b17023SJohn Marino return;
2234*e4b17023SJohn Marino
2235*e4b17023SJohn Marino memset (&id, 0, sizeof (id));
2236*e4b17023SJohn Marino id.cb.copy_decl = nesting_copy_decl;
2237*e4b17023SJohn Marino id.cb.decl_map = pointer_map_create ();
2238*e4b17023SJohn Marino id.root = root;
2239*e4b17023SJohn Marino
2240*e4b17023SJohn Marino for (; var; var = DECL_CHAIN (var))
2241*e4b17023SJohn Marino if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
2242*e4b17023SJohn Marino {
2243*e4b17023SJohn Marino struct nesting_info *i;
2244*e4b17023SJohn Marino tree newt, context;
2245*e4b17023SJohn Marino void **slot;
2246*e4b17023SJohn Marino
2247*e4b17023SJohn Marino val = DECL_VALUE_EXPR (var);
2248*e4b17023SJohn Marino type = TREE_TYPE (var);
2249*e4b17023SJohn Marino
2250*e4b17023SJohn Marino if (!(TREE_CODE (val) == INDIRECT_REF
2251*e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
2252*e4b17023SJohn Marino && variably_modified_type_p (type, NULL)))
2253*e4b17023SJohn Marino continue;
2254*e4b17023SJohn Marino
2255*e4b17023SJohn Marino slot = pointer_map_contains (root->var_map, TREE_OPERAND (val, 0));
2256*e4b17023SJohn Marino if (!slot && !walk_tree (&type, contains_remapped_vars, root, NULL))
2257*e4b17023SJohn Marino continue;
2258*e4b17023SJohn Marino
2259*e4b17023SJohn Marino context = decl_function_context (var);
2260*e4b17023SJohn Marino for (i = root; i; i = i->outer)
2261*e4b17023SJohn Marino if (i->context == context)
2262*e4b17023SJohn Marino break;
2263*e4b17023SJohn Marino
2264*e4b17023SJohn Marino if (i == NULL)
2265*e4b17023SJohn Marino continue;
2266*e4b17023SJohn Marino
2267*e4b17023SJohn Marino /* Fully expand value expressions. This avoids having debug variables
2268*e4b17023SJohn Marino only referenced from them and that can be swept during GC. */
2269*e4b17023SJohn Marino if (slot)
2270*e4b17023SJohn Marino {
2271*e4b17023SJohn Marino tree t = (tree) *slot;
2272*e4b17023SJohn Marino gcc_assert (DECL_P (t) && DECL_HAS_VALUE_EXPR_P (t));
2273*e4b17023SJohn Marino val = build1 (INDIRECT_REF, TREE_TYPE (val), DECL_VALUE_EXPR (t));
2274*e4b17023SJohn Marino }
2275*e4b17023SJohn Marino
2276*e4b17023SJohn Marino id.cb.src_fn = i->context;
2277*e4b17023SJohn Marino id.cb.dst_fn = i->context;
2278*e4b17023SJohn Marino id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
2279*e4b17023SJohn Marino
2280*e4b17023SJohn Marino TREE_TYPE (var) = newt = remap_type (type, &id.cb);
2281*e4b17023SJohn Marino while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
2282*e4b17023SJohn Marino {
2283*e4b17023SJohn Marino newt = TREE_TYPE (newt);
2284*e4b17023SJohn Marino type = TREE_TYPE (type);
2285*e4b17023SJohn Marino }
2286*e4b17023SJohn Marino if (TYPE_NAME (newt)
2287*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
2288*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
2289*e4b17023SJohn Marino && newt != type
2290*e4b17023SJohn Marino && TYPE_NAME (newt) == TYPE_NAME (type))
2291*e4b17023SJohn Marino TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
2292*e4b17023SJohn Marino
2293*e4b17023SJohn Marino walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
2294*e4b17023SJohn Marino if (val != DECL_VALUE_EXPR (var))
2295*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (var, val);
2296*e4b17023SJohn Marino }
2297*e4b17023SJohn Marino
2298*e4b17023SJohn Marino pointer_map_destroy (id.cb.decl_map);
2299*e4b17023SJohn Marino }
2300*e4b17023SJohn Marino
2301*e4b17023SJohn Marino /* Fold the MEM_REF *E. */
2302*e4b17023SJohn Marino static bool
fold_mem_refs(const void * e,void * data ATTRIBUTE_UNUSED)2303*e4b17023SJohn Marino fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
2304*e4b17023SJohn Marino {
2305*e4b17023SJohn Marino tree *ref_p = CONST_CAST2(tree *, const tree *, (const tree *)e);
2306*e4b17023SJohn Marino *ref_p = fold (*ref_p);
2307*e4b17023SJohn Marino return true;
2308*e4b17023SJohn Marino }
2309*e4b17023SJohn Marino
2310*e4b17023SJohn Marino /* Do "everything else" to clean up or complete state collected by the
2311*e4b17023SJohn Marino various walking passes -- lay out the types and decls, generate code
2312*e4b17023SJohn Marino to initialize the frame decl, store critical expressions in the
2313*e4b17023SJohn Marino struct function for rtl to find. */
2314*e4b17023SJohn Marino
2315*e4b17023SJohn Marino static void
finalize_nesting_tree_1(struct nesting_info * root)2316*e4b17023SJohn Marino finalize_nesting_tree_1 (struct nesting_info *root)
2317*e4b17023SJohn Marino {
2318*e4b17023SJohn Marino gimple_seq stmt_list;
2319*e4b17023SJohn Marino gimple stmt;
2320*e4b17023SJohn Marino tree context = root->context;
2321*e4b17023SJohn Marino struct function *sf;
2322*e4b17023SJohn Marino
2323*e4b17023SJohn Marino stmt_list = NULL;
2324*e4b17023SJohn Marino
2325*e4b17023SJohn Marino /* If we created a non-local frame type or decl, we need to lay them
2326*e4b17023SJohn Marino out at this time. */
2327*e4b17023SJohn Marino if (root->frame_type)
2328*e4b17023SJohn Marino {
2329*e4b17023SJohn Marino /* In some cases the frame type will trigger the -Wpadded warning.
2330*e4b17023SJohn Marino This is not helpful; suppress it. */
2331*e4b17023SJohn Marino int save_warn_padded = warn_padded;
2332*e4b17023SJohn Marino tree *adjust;
2333*e4b17023SJohn Marino
2334*e4b17023SJohn Marino warn_padded = 0;
2335*e4b17023SJohn Marino layout_type (root->frame_type);
2336*e4b17023SJohn Marino warn_padded = save_warn_padded;
2337*e4b17023SJohn Marino layout_decl (root->frame_decl, 0);
2338*e4b17023SJohn Marino
2339*e4b17023SJohn Marino /* Remove root->frame_decl from root->new_local_var_chain, so
2340*e4b17023SJohn Marino that we can declare it also in the lexical blocks, which
2341*e4b17023SJohn Marino helps ensure virtual regs that end up appearing in its RTL
2342*e4b17023SJohn Marino expression get substituted in instantiate_virtual_regs(). */
2343*e4b17023SJohn Marino for (adjust = &root->new_local_var_chain;
2344*e4b17023SJohn Marino *adjust != root->frame_decl;
2345*e4b17023SJohn Marino adjust = &DECL_CHAIN (*adjust))
2346*e4b17023SJohn Marino gcc_assert (DECL_CHAIN (*adjust));
2347*e4b17023SJohn Marino *adjust = DECL_CHAIN (*adjust);
2348*e4b17023SJohn Marino
2349*e4b17023SJohn Marino DECL_CHAIN (root->frame_decl) = NULL_TREE;
2350*e4b17023SJohn Marino declare_vars (root->frame_decl,
2351*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_body (context)), true);
2352*e4b17023SJohn Marino }
2353*e4b17023SJohn Marino
2354*e4b17023SJohn Marino /* If any parameters were referenced non-locally, then we need to
2355*e4b17023SJohn Marino insert a copy. Likewise, if any variables were referenced by
2356*e4b17023SJohn Marino pointer, we need to initialize the address. */
2357*e4b17023SJohn Marino if (root->any_parm_remapped)
2358*e4b17023SJohn Marino {
2359*e4b17023SJohn Marino tree p;
2360*e4b17023SJohn Marino for (p = DECL_ARGUMENTS (context); p ; p = DECL_CHAIN (p))
2361*e4b17023SJohn Marino {
2362*e4b17023SJohn Marino tree field, x, y;
2363*e4b17023SJohn Marino
2364*e4b17023SJohn Marino field = lookup_field_for_decl (root, p, NO_INSERT);
2365*e4b17023SJohn Marino if (!field)
2366*e4b17023SJohn Marino continue;
2367*e4b17023SJohn Marino
2368*e4b17023SJohn Marino if (use_pointer_in_frame (p))
2369*e4b17023SJohn Marino x = build_addr (p, context);
2370*e4b17023SJohn Marino else
2371*e4b17023SJohn Marino x = p;
2372*e4b17023SJohn Marino
2373*e4b17023SJohn Marino y = build3 (COMPONENT_REF, TREE_TYPE (field),
2374*e4b17023SJohn Marino root->frame_decl, field, NULL_TREE);
2375*e4b17023SJohn Marino stmt = gimple_build_assign (y, x);
2376*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt);
2377*e4b17023SJohn Marino /* If the assignment is from a non-register the stmt is
2378*e4b17023SJohn Marino not valid gimple. Make it so by using a temporary instead. */
2379*e4b17023SJohn Marino if (!is_gimple_reg (x)
2380*e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (x)))
2381*e4b17023SJohn Marino {
2382*e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last (stmt_list);
2383*e4b17023SJohn Marino x = init_tmp_var (root, x, &gsi);
2384*e4b17023SJohn Marino gimple_assign_set_rhs1 (stmt, x);
2385*e4b17023SJohn Marino }
2386*e4b17023SJohn Marino }
2387*e4b17023SJohn Marino }
2388*e4b17023SJohn Marino
2389*e4b17023SJohn Marino /* If a chain_field was created, then it needs to be initialized
2390*e4b17023SJohn Marino from chain_decl. */
2391*e4b17023SJohn Marino if (root->chain_field)
2392*e4b17023SJohn Marino {
2393*e4b17023SJohn Marino tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field),
2394*e4b17023SJohn Marino root->frame_decl, root->chain_field, NULL_TREE);
2395*e4b17023SJohn Marino stmt = gimple_build_assign (x, get_chain_decl (root));
2396*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt);
2397*e4b17023SJohn Marino }
2398*e4b17023SJohn Marino
2399*e4b17023SJohn Marino /* If trampolines were created, then we need to initialize them. */
2400*e4b17023SJohn Marino if (root->any_tramp_created)
2401*e4b17023SJohn Marino {
2402*e4b17023SJohn Marino struct nesting_info *i;
2403*e4b17023SJohn Marino for (i = root->inner; i ; i = i->next)
2404*e4b17023SJohn Marino {
2405*e4b17023SJohn Marino tree arg1, arg2, arg3, x, field;
2406*e4b17023SJohn Marino
2407*e4b17023SJohn Marino field = lookup_tramp_for_decl (root, i->context, NO_INSERT);
2408*e4b17023SJohn Marino if (!field)
2409*e4b17023SJohn Marino continue;
2410*e4b17023SJohn Marino
2411*e4b17023SJohn Marino gcc_assert (DECL_STATIC_CHAIN (i->context));
2412*e4b17023SJohn Marino arg3 = build_addr (root->frame_decl, context);
2413*e4b17023SJohn Marino
2414*e4b17023SJohn Marino arg2 = build_addr (i->context, context);
2415*e4b17023SJohn Marino
2416*e4b17023SJohn Marino x = build3 (COMPONENT_REF, TREE_TYPE (field),
2417*e4b17023SJohn Marino root->frame_decl, field, NULL_TREE);
2418*e4b17023SJohn Marino arg1 = build_addr (x, context);
2419*e4b17023SJohn Marino
2420*e4b17023SJohn Marino x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
2421*e4b17023SJohn Marino stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
2422*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt);
2423*e4b17023SJohn Marino }
2424*e4b17023SJohn Marino }
2425*e4b17023SJohn Marino
2426*e4b17023SJohn Marino /* If we created initialization statements, insert them. */
2427*e4b17023SJohn Marino if (stmt_list)
2428*e4b17023SJohn Marino {
2429*e4b17023SJohn Marino gimple bind;
2430*e4b17023SJohn Marino annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
2431*e4b17023SJohn Marino bind = gimple_seq_first_stmt (gimple_body (context));
2432*e4b17023SJohn Marino gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
2433*e4b17023SJohn Marino gimple_bind_set_body (bind, stmt_list);
2434*e4b17023SJohn Marino }
2435*e4b17023SJohn Marino
2436*e4b17023SJohn Marino /* If a chain_decl was created, then it needs to be registered with
2437*e4b17023SJohn Marino struct function so that it gets initialized from the static chain
2438*e4b17023SJohn Marino register at the beginning of the function. */
2439*e4b17023SJohn Marino sf = DECL_STRUCT_FUNCTION (root->context);
2440*e4b17023SJohn Marino sf->static_chain_decl = root->chain_decl;
2441*e4b17023SJohn Marino
2442*e4b17023SJohn Marino /* Similarly for the non-local goto save area. */
2443*e4b17023SJohn Marino if (root->nl_goto_field)
2444*e4b17023SJohn Marino {
2445*e4b17023SJohn Marino sf->nonlocal_goto_save_area
2446*e4b17023SJohn Marino = get_frame_field (root, context, root->nl_goto_field, NULL);
2447*e4b17023SJohn Marino sf->has_nonlocal_label = 1;
2448*e4b17023SJohn Marino }
2449*e4b17023SJohn Marino
2450*e4b17023SJohn Marino /* Make sure all new local variables get inserted into the
2451*e4b17023SJohn Marino proper BIND_EXPR. */
2452*e4b17023SJohn Marino if (root->new_local_var_chain)
2453*e4b17023SJohn Marino declare_vars (root->new_local_var_chain,
2454*e4b17023SJohn Marino gimple_seq_first_stmt (gimple_body (root->context)),
2455*e4b17023SJohn Marino false);
2456*e4b17023SJohn Marino
2457*e4b17023SJohn Marino if (root->debug_var_chain)
2458*e4b17023SJohn Marino {
2459*e4b17023SJohn Marino tree debug_var;
2460*e4b17023SJohn Marino gimple scope;
2461*e4b17023SJohn Marino
2462*e4b17023SJohn Marino remap_vla_decls (DECL_INITIAL (root->context), root);
2463*e4b17023SJohn Marino
2464*e4b17023SJohn Marino for (debug_var = root->debug_var_chain; debug_var;
2465*e4b17023SJohn Marino debug_var = DECL_CHAIN (debug_var))
2466*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
2467*e4b17023SJohn Marino break;
2468*e4b17023SJohn Marino
2469*e4b17023SJohn Marino /* If there are any debug decls with variable length types,
2470*e4b17023SJohn Marino remap those types using other debug_var_chain variables. */
2471*e4b17023SJohn Marino if (debug_var)
2472*e4b17023SJohn Marino {
2473*e4b17023SJohn Marino struct nesting_copy_body_data id;
2474*e4b17023SJohn Marino
2475*e4b17023SJohn Marino memset (&id, 0, sizeof (id));
2476*e4b17023SJohn Marino id.cb.copy_decl = nesting_copy_decl;
2477*e4b17023SJohn Marino id.cb.decl_map = pointer_map_create ();
2478*e4b17023SJohn Marino id.root = root;
2479*e4b17023SJohn Marino
2480*e4b17023SJohn Marino for (; debug_var; debug_var = DECL_CHAIN (debug_var))
2481*e4b17023SJohn Marino if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
2482*e4b17023SJohn Marino {
2483*e4b17023SJohn Marino tree type = TREE_TYPE (debug_var);
2484*e4b17023SJohn Marino tree newt, t = type;
2485*e4b17023SJohn Marino struct nesting_info *i;
2486*e4b17023SJohn Marino
2487*e4b17023SJohn Marino for (i = root; i; i = i->outer)
2488*e4b17023SJohn Marino if (variably_modified_type_p (type, i->context))
2489*e4b17023SJohn Marino break;
2490*e4b17023SJohn Marino
2491*e4b17023SJohn Marino if (i == NULL)
2492*e4b17023SJohn Marino continue;
2493*e4b17023SJohn Marino
2494*e4b17023SJohn Marino id.cb.src_fn = i->context;
2495*e4b17023SJohn Marino id.cb.dst_fn = i->context;
2496*e4b17023SJohn Marino id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
2497*e4b17023SJohn Marino
2498*e4b17023SJohn Marino TREE_TYPE (debug_var) = newt = remap_type (type, &id.cb);
2499*e4b17023SJohn Marino while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
2500*e4b17023SJohn Marino {
2501*e4b17023SJohn Marino newt = TREE_TYPE (newt);
2502*e4b17023SJohn Marino t = TREE_TYPE (t);
2503*e4b17023SJohn Marino }
2504*e4b17023SJohn Marino if (TYPE_NAME (newt)
2505*e4b17023SJohn Marino && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
2506*e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
2507*e4b17023SJohn Marino && newt != t
2508*e4b17023SJohn Marino && TYPE_NAME (newt) == TYPE_NAME (t))
2509*e4b17023SJohn Marino TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
2510*e4b17023SJohn Marino }
2511*e4b17023SJohn Marino
2512*e4b17023SJohn Marino pointer_map_destroy (id.cb.decl_map);
2513*e4b17023SJohn Marino }
2514*e4b17023SJohn Marino
2515*e4b17023SJohn Marino scope = gimple_seq_first_stmt (gimple_body (root->context));
2516*e4b17023SJohn Marino if (gimple_bind_block (scope))
2517*e4b17023SJohn Marino declare_vars (root->debug_var_chain, scope, true);
2518*e4b17023SJohn Marino else
2519*e4b17023SJohn Marino BLOCK_VARS (DECL_INITIAL (root->context))
2520*e4b17023SJohn Marino = chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
2521*e4b17023SJohn Marino root->debug_var_chain);
2522*e4b17023SJohn Marino }
2523*e4b17023SJohn Marino
2524*e4b17023SJohn Marino /* Fold the rewritten MEM_REF trees. */
2525*e4b17023SJohn Marino pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
2526*e4b17023SJohn Marino
2527*e4b17023SJohn Marino /* Dump the translated tree function. */
2528*e4b17023SJohn Marino if (dump_file)
2529*e4b17023SJohn Marino {
2530*e4b17023SJohn Marino fputs ("\n\n", dump_file);
2531*e4b17023SJohn Marino dump_function_to_file (root->context, dump_file, dump_flags);
2532*e4b17023SJohn Marino }
2533*e4b17023SJohn Marino }
2534*e4b17023SJohn Marino
2535*e4b17023SJohn Marino static void
finalize_nesting_tree(struct nesting_info * root)2536*e4b17023SJohn Marino finalize_nesting_tree (struct nesting_info *root)
2537*e4b17023SJohn Marino {
2538*e4b17023SJohn Marino struct nesting_info *n;
2539*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root)
2540*e4b17023SJohn Marino finalize_nesting_tree_1 (n);
2541*e4b17023SJohn Marino }
2542*e4b17023SJohn Marino
2543*e4b17023SJohn Marino /* Unnest the nodes and pass them to cgraph. */
2544*e4b17023SJohn Marino
2545*e4b17023SJohn Marino static void
unnest_nesting_tree_1(struct nesting_info * root)2546*e4b17023SJohn Marino unnest_nesting_tree_1 (struct nesting_info *root)
2547*e4b17023SJohn Marino {
2548*e4b17023SJohn Marino struct cgraph_node *node = cgraph_get_node (root->context);
2549*e4b17023SJohn Marino
2550*e4b17023SJohn Marino /* For nested functions update the cgraph to reflect unnesting.
2551*e4b17023SJohn Marino We also delay finalizing of these functions up to this point. */
2552*e4b17023SJohn Marino if (node->origin)
2553*e4b17023SJohn Marino {
2554*e4b17023SJohn Marino cgraph_unnest_node (node);
2555*e4b17023SJohn Marino cgraph_finalize_function (root->context, true);
2556*e4b17023SJohn Marino }
2557*e4b17023SJohn Marino }
2558*e4b17023SJohn Marino
2559*e4b17023SJohn Marino static void
unnest_nesting_tree(struct nesting_info * root)2560*e4b17023SJohn Marino unnest_nesting_tree (struct nesting_info *root)
2561*e4b17023SJohn Marino {
2562*e4b17023SJohn Marino struct nesting_info *n;
2563*e4b17023SJohn Marino FOR_EACH_NEST_INFO (n, root)
2564*e4b17023SJohn Marino unnest_nesting_tree_1 (n);
2565*e4b17023SJohn Marino }
2566*e4b17023SJohn Marino
2567*e4b17023SJohn Marino /* Free the data structures allocated during this pass. */
2568*e4b17023SJohn Marino
2569*e4b17023SJohn Marino static void
free_nesting_tree(struct nesting_info * root)2570*e4b17023SJohn Marino free_nesting_tree (struct nesting_info *root)
2571*e4b17023SJohn Marino {
2572*e4b17023SJohn Marino struct nesting_info *node, *next;
2573*e4b17023SJohn Marino
2574*e4b17023SJohn Marino node = iter_nestinfo_start (root);
2575*e4b17023SJohn Marino do
2576*e4b17023SJohn Marino {
2577*e4b17023SJohn Marino next = iter_nestinfo_next (node);
2578*e4b17023SJohn Marino pointer_map_destroy (node->var_map);
2579*e4b17023SJohn Marino pointer_map_destroy (node->field_map);
2580*e4b17023SJohn Marino pointer_set_destroy (node->mem_refs);
2581*e4b17023SJohn Marino free (node);
2582*e4b17023SJohn Marino node = next;
2583*e4b17023SJohn Marino }
2584*e4b17023SJohn Marino while (node);
2585*e4b17023SJohn Marino }
2586*e4b17023SJohn Marino
2587*e4b17023SJohn Marino /* Gimplify a function and all its nested functions. */
2588*e4b17023SJohn Marino static void
gimplify_all_functions(struct cgraph_node * root)2589*e4b17023SJohn Marino gimplify_all_functions (struct cgraph_node *root)
2590*e4b17023SJohn Marino {
2591*e4b17023SJohn Marino struct cgraph_node *iter;
2592*e4b17023SJohn Marino if (!gimple_body (root->decl))
2593*e4b17023SJohn Marino gimplify_function_tree (root->decl);
2594*e4b17023SJohn Marino for (iter = root->nested; iter; iter = iter->next_nested)
2595*e4b17023SJohn Marino gimplify_all_functions (iter);
2596*e4b17023SJohn Marino }
2597*e4b17023SJohn Marino
2598*e4b17023SJohn Marino /* Main entry point for this pass. Process FNDECL and all of its nested
2599*e4b17023SJohn Marino subroutines and turn them into something less tightly bound. */
2600*e4b17023SJohn Marino
2601*e4b17023SJohn Marino void
lower_nested_functions(tree fndecl)2602*e4b17023SJohn Marino lower_nested_functions (tree fndecl)
2603*e4b17023SJohn Marino {
2604*e4b17023SJohn Marino struct cgraph_node *cgn;
2605*e4b17023SJohn Marino struct nesting_info *root;
2606*e4b17023SJohn Marino
2607*e4b17023SJohn Marino /* If there are no nested functions, there's nothing to do. */
2608*e4b17023SJohn Marino cgn = cgraph_get_node (fndecl);
2609*e4b17023SJohn Marino if (!cgn->nested)
2610*e4b17023SJohn Marino return;
2611*e4b17023SJohn Marino
2612*e4b17023SJohn Marino gimplify_all_functions (cgn);
2613*e4b17023SJohn Marino
2614*e4b17023SJohn Marino dump_file = dump_begin (TDI_nested, &dump_flags);
2615*e4b17023SJohn Marino if (dump_file)
2616*e4b17023SJohn Marino fprintf (dump_file, "\n;; Function %s\n\n",
2617*e4b17023SJohn Marino lang_hooks.decl_printable_name (fndecl, 2));
2618*e4b17023SJohn Marino
2619*e4b17023SJohn Marino bitmap_obstack_initialize (&nesting_info_bitmap_obstack);
2620*e4b17023SJohn Marino root = create_nesting_tree (cgn);
2621*e4b17023SJohn Marino
2622*e4b17023SJohn Marino walk_all_functions (convert_nonlocal_reference_stmt,
2623*e4b17023SJohn Marino convert_nonlocal_reference_op,
2624*e4b17023SJohn Marino root);
2625*e4b17023SJohn Marino walk_all_functions (convert_local_reference_stmt,
2626*e4b17023SJohn Marino convert_local_reference_op,
2627*e4b17023SJohn Marino root);
2628*e4b17023SJohn Marino walk_all_functions (convert_nl_goto_reference, NULL, root);
2629*e4b17023SJohn Marino walk_all_functions (convert_nl_goto_receiver, NULL, root);
2630*e4b17023SJohn Marino
2631*e4b17023SJohn Marino convert_all_function_calls (root);
2632*e4b17023SJohn Marino finalize_nesting_tree (root);
2633*e4b17023SJohn Marino unnest_nesting_tree (root);
2634*e4b17023SJohn Marino
2635*e4b17023SJohn Marino free_nesting_tree (root);
2636*e4b17023SJohn Marino bitmap_obstack_release (&nesting_info_bitmap_obstack);
2637*e4b17023SJohn Marino
2638*e4b17023SJohn Marino if (dump_file)
2639*e4b17023SJohn Marino {
2640*e4b17023SJohn Marino dump_end (TDI_nested, dump_file);
2641*e4b17023SJohn Marino dump_file = NULL;
2642*e4b17023SJohn Marino }
2643*e4b17023SJohn Marino }
2644*e4b17023SJohn Marino
2645*e4b17023SJohn Marino #include "gt-tree-nested.h"
2646