xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-nested.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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