1169689Skan/* Tree lowering pass.  Lowers GIMPLE into unstructured form.
2169689Skan
3169689Skan   Copyright (C) 2003, 2005 Free Software Foundation, Inc.
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21169689Skan
22169689Skan#include "config.h"
23169689Skan#include "system.h"
24169689Skan#include "coretypes.h"
25169689Skan#include "tm.h"
26169689Skan#include "tree.h"
27169689Skan#include "rtl.h"
28169689Skan#include "varray.h"
29169689Skan#include "tree-gimple.h"
30169689Skan#include "tree-inline.h"
31169689Skan#include "diagnostic.h"
32169689Skan#include "langhooks.h"
33169689Skan#include "langhooks-def.h"
34169689Skan#include "tree-flow.h"
35169689Skan#include "timevar.h"
36169689Skan#include "except.h"
37169689Skan#include "hashtab.h"
38169689Skan#include "flags.h"
39169689Skan#include "function.h"
40169689Skan#include "expr.h"
41169689Skan#include "toplev.h"
42169689Skan#include "tree-pass.h"
43169689Skan
44169689Skanstruct lower_data
45169689Skan{
46169689Skan  /* Block the current statement belongs to.  */
47169689Skan  tree block;
48169689Skan
49169689Skan  /* A TREE_LIST of label and return statements to be moved to the end
50169689Skan     of the function.  */
51169689Skan  tree return_statements;
52169689Skan
53169689Skan  /* True if the function calls __builtin_setjmp.  */
54169689Skan  bool calls_builtin_setjmp;
55169689Skan};
56169689Skan
57169689Skanstatic void lower_stmt (tree_stmt_iterator *, struct lower_data *);
58169689Skanstatic void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
59169689Skanstatic void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
60169689Skanstatic void lower_return_expr (tree_stmt_iterator *, struct lower_data *);
61169689Skanstatic void lower_builtin_setjmp (tree_stmt_iterator *);
62169689Skan
63169689Skan/* Lower the body of current_function_decl.  */
64169689Skan
65169689Skanstatic unsigned int
66169689Skanlower_function_body (void)
67169689Skan{
68169689Skan  struct lower_data data;
69169689Skan  tree *body_p = &DECL_SAVED_TREE (current_function_decl);
70169689Skan  tree bind = *body_p;
71169689Skan  tree_stmt_iterator i;
72169689Skan  tree t, x;
73169689Skan
74169689Skan  gcc_assert (TREE_CODE (bind) == BIND_EXPR);
75169689Skan
76169689Skan  memset (&data, 0, sizeof (data));
77169689Skan  data.block = DECL_INITIAL (current_function_decl);
78169689Skan  BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
79169689Skan  BLOCK_CHAIN (data.block) = NULL_TREE;
80169689Skan  TREE_ASM_WRITTEN (data.block) = 1;
81169689Skan
82169689Skan  *body_p = alloc_stmt_list ();
83169689Skan  i = tsi_start (*body_p);
84169689Skan  tsi_link_after (&i, bind, TSI_NEW_STMT);
85169689Skan  lower_bind_expr (&i, &data);
86169689Skan
87169689Skan  i = tsi_last (*body_p);
88169689Skan
89169689Skan  /* If the function falls off the end, we need a null return statement.
90169689Skan     If we've already got one in the return_statements list, we don't
91169689Skan     need to do anything special.  Otherwise build one by hand.  */
92169689Skan  if (block_may_fallthru (*body_p)
93169689Skan      && (data.return_statements == NULL
94169689Skan          || TREE_OPERAND (TREE_VALUE (data.return_statements), 0) != NULL))
95169689Skan    {
96169689Skan      x = build1 (RETURN_EXPR, void_type_node, NULL);
97169689Skan      SET_EXPR_LOCATION (x, cfun->function_end_locus);
98169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
99169689Skan    }
100169689Skan
101169689Skan  /* If we lowered any return statements, emit the representative
102169689Skan     at the end of the function.  */
103169689Skan  for (t = data.return_statements ; t ; t = TREE_CHAIN (t))
104169689Skan    {
105169689Skan      x = build1 (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
106169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
107169689Skan
108169689Skan      /* Remove the line number from the representative return statement.
109169689Skan	 It now fills in for many such returns.  Failure to remove this
110169689Skan	 will result in incorrect results for coverage analysis.  */
111169689Skan      x = TREE_VALUE (t);
112169689Skan#ifdef USE_MAPPED_LOCATION
113169689Skan      SET_EXPR_LOCATION (x, UNKNOWN_LOCATION);
114169689Skan#else
115169689Skan      SET_EXPR_LOCUS (x, NULL);
116169689Skan#endif
117169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
118169689Skan    }
119169689Skan
120169689Skan  /* If the function calls __builtin_setjmp, we need to emit the computed
121169689Skan     goto that will serve as the unique dispatcher for all the receivers.  */
122169689Skan  if (data.calls_builtin_setjmp)
123169689Skan    {
124169689Skan      tree disp_label, disp_var, arg;
125169689Skan
126169689Skan      /* Build 'DISP_LABEL:' and insert.  */
127169689Skan      disp_label = create_artificial_label ();
128169689Skan      /* This mark will create forward edges from every call site.  */
129169689Skan      DECL_NONLOCAL (disp_label) = 1;
130169689Skan      current_function_has_nonlocal_label = 1;
131169689Skan      x = build1 (LABEL_EXPR, void_type_node, disp_label);
132169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
133169689Skan
134169689Skan      /* Build 'DISP_VAR = __builtin_setjmp_dispatcher (DISP_LABEL);'
135169689Skan	 and insert.  */
136169689Skan      disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
137169689Skan      t = build_addr (disp_label, current_function_decl);
138169689Skan      arg = tree_cons (NULL, t, NULL);
139169689Skan      t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER];
140169689Skan      t = build_function_call_expr (t,arg);
141169689Skan      x = build2 (MODIFY_EXPR, void_type_node, disp_var, t);
142169689Skan
143169689Skan      /* Build 'goto DISP_VAR;' and insert.  */
144169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
145169689Skan      x = build1 (GOTO_EXPR, void_type_node, disp_var);
146169689Skan      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
147169689Skan    }
148169689Skan
149169689Skan  gcc_assert (data.block == DECL_INITIAL (current_function_decl));
150169689Skan  BLOCK_SUBBLOCKS (data.block)
151169689Skan    = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
152169689Skan
153169689Skan  clear_block_marks (data.block);
154169689Skan  return 0;
155169689Skan}
156169689Skan
157169689Skanstruct tree_opt_pass pass_lower_cf =
158169689Skan{
159169689Skan  "lower",				/* name */
160169689Skan  NULL,					/* gate */
161169689Skan  lower_function_body,			/* execute */
162169689Skan  NULL,					/* sub */
163169689Skan  NULL,					/* next */
164169689Skan  0,					/* static_pass_number */
165169689Skan  0,					/* tv_id */
166169689Skan  PROP_gimple_any,			/* properties_required */
167169689Skan  PROP_gimple_lcf,			/* properties_provided */
168169689Skan  0,					/* properties_destroyed */
169169689Skan  0,					/* todo_flags_start */
170169689Skan  TODO_dump_func,			/* todo_flags_finish */
171169689Skan  0					/* letter */
172169689Skan};
173169689Skan
174169689Skan
175169689Skan/* Lower the EXPR.  Unlike gimplification the statements are not relowered
176169689Skan   when they are changed -- if this has to be done, the lowering routine must
177169689Skan   do it explicitly.  DATA is passed through the recursion.  */
178169689Skan
179169689Skanstatic void
180169689Skanlower_stmt_body (tree expr, struct lower_data *data)
181169689Skan{
182169689Skan  tree_stmt_iterator tsi;
183169689Skan
184169689Skan  for (tsi = tsi_start (expr); !tsi_end_p (tsi); )
185169689Skan    lower_stmt (&tsi, data);
186169689Skan}
187169689Skan
188169689Skan
189169689Skan/* Lower the OpenMP directive statement pointed by TSI.  DATA is
190169689Skan   passed through the recursion.  */
191169689Skan
192169689Skanstatic void
193169689Skanlower_omp_directive (tree_stmt_iterator *tsi, struct lower_data *data)
194169689Skan{
195169689Skan  tree stmt;
196169689Skan
197169689Skan  stmt = tsi_stmt (*tsi);
198169689Skan
199169689Skan  lower_stmt_body (OMP_BODY (stmt), data);
200169689Skan  tsi_link_before (tsi, stmt, TSI_SAME_STMT);
201169689Skan  tsi_link_before (tsi, OMP_BODY (stmt), TSI_SAME_STMT);
202169689Skan  OMP_BODY (stmt) = NULL_TREE;
203169689Skan  tsi_delink (tsi);
204169689Skan}
205169689Skan
206169689Skan
207169689Skan/* Lower statement TSI.  DATA is passed through the recursion.  */
208169689Skan
209169689Skanstatic void
210169689Skanlower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
211169689Skan{
212169689Skan  tree stmt = tsi_stmt (*tsi);
213169689Skan
214169689Skan  if (EXPR_HAS_LOCATION (stmt) && data)
215169689Skan    TREE_BLOCK (stmt) = data->block;
216169689Skan
217169689Skan  switch (TREE_CODE (stmt))
218169689Skan    {
219169689Skan    case BIND_EXPR:
220169689Skan      lower_bind_expr (tsi, data);
221169689Skan      return;
222169689Skan    case COND_EXPR:
223169689Skan      lower_cond_expr (tsi, data);
224169689Skan      return;
225169689Skan    case RETURN_EXPR:
226169689Skan      lower_return_expr (tsi, data);
227169689Skan      return;
228169689Skan
229169689Skan    case TRY_FINALLY_EXPR:
230169689Skan    case TRY_CATCH_EXPR:
231169689Skan      lower_stmt_body (TREE_OPERAND (stmt, 0), data);
232169689Skan      lower_stmt_body (TREE_OPERAND (stmt, 1), data);
233169689Skan      break;
234169689Skan    case CATCH_EXPR:
235169689Skan      lower_stmt_body (CATCH_BODY (stmt), data);
236169689Skan      break;
237169689Skan    case EH_FILTER_EXPR:
238169689Skan      lower_stmt_body (EH_FILTER_FAILURE (stmt), data);
239169689Skan      break;
240169689Skan
241169689Skan    case NOP_EXPR:
242169689Skan    case ASM_EXPR:
243169689Skan    case GOTO_EXPR:
244169689Skan    case LABEL_EXPR:
245169689Skan    case SWITCH_EXPR:
246169689Skan    case OMP_FOR:
247169689Skan    case OMP_SECTIONS:
248169689Skan    case OMP_SECTION:
249169689Skan    case OMP_SINGLE:
250169689Skan    case OMP_MASTER:
251169689Skan    case OMP_ORDERED:
252169689Skan    case OMP_CRITICAL:
253169689Skan    case OMP_RETURN:
254169689Skan    case OMP_CONTINUE:
255169689Skan      break;
256169689Skan
257169689Skan    case MODIFY_EXPR:
258169689Skan      if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
259169689Skan	stmt = TREE_OPERAND (stmt, 1);
260169689Skan      else
261169689Skan	break;
262169689Skan      /* FALLTHRU */
263169689Skan
264169689Skan    case CALL_EXPR:
265169689Skan      {
266169689Skan	tree decl = get_callee_fndecl (stmt);
267169689Skan	if (decl
268169689Skan	    && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
269169689Skan	    && DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
270169689Skan	  {
271169689Skan	    data->calls_builtin_setjmp = true;
272169689Skan	    lower_builtin_setjmp (tsi);
273169689Skan	    return;
274169689Skan	  }
275169689Skan      }
276169689Skan      break;
277169689Skan
278169689Skan    case OMP_PARALLEL:
279169689Skan      lower_omp_directive (tsi, data);
280169689Skan      return;
281169689Skan
282169689Skan    default:
283169689Skan      gcc_unreachable ();
284169689Skan    }
285169689Skan
286169689Skan  tsi_next (tsi);
287169689Skan}
288169689Skan
289169689Skan/* Lower a bind_expr TSI.  DATA is passed through the recursion.  */
290169689Skan
291169689Skanstatic void
292169689Skanlower_bind_expr (tree_stmt_iterator *tsi, struct lower_data *data)
293169689Skan{
294169689Skan  tree old_block = data->block;
295169689Skan  tree stmt = tsi_stmt (*tsi);
296169689Skan  tree new_block = BIND_EXPR_BLOCK (stmt);
297169689Skan
298169689Skan  if (new_block)
299169689Skan    {
300169689Skan      if (new_block == old_block)
301169689Skan	{
302169689Skan	  /* The outermost block of the original function may not be the
303169689Skan	     outermost statement chain of the gimplified function.  So we
304169689Skan	     may see the outermost block just inside the function.  */
305169689Skan	  gcc_assert (new_block == DECL_INITIAL (current_function_decl));
306169689Skan	  new_block = NULL;
307169689Skan	}
308169689Skan      else
309169689Skan	{
310169689Skan	  /* We do not expect to handle duplicate blocks.  */
311169689Skan	  gcc_assert (!TREE_ASM_WRITTEN (new_block));
312169689Skan	  TREE_ASM_WRITTEN (new_block) = 1;
313169689Skan
314169689Skan	  /* Block tree may get clobbered by inlining.  Normally this would
315169689Skan	     be fixed in rest_of_decl_compilation using block notes, but
316169689Skan	     since we are not going to emit them, it is up to us.  */
317169689Skan	  BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block);
318169689Skan	  BLOCK_SUBBLOCKS (old_block) = new_block;
319169689Skan	  BLOCK_SUBBLOCKS (new_block) = NULL_TREE;
320169689Skan	  BLOCK_SUPERCONTEXT (new_block) = old_block;
321169689Skan
322169689Skan	  data->block = new_block;
323169689Skan	}
324169689Skan    }
325169689Skan
326169689Skan  record_vars (BIND_EXPR_VARS (stmt));
327169689Skan  lower_stmt_body (BIND_EXPR_BODY (stmt), data);
328169689Skan
329169689Skan  if (new_block)
330169689Skan    {
331169689Skan      gcc_assert (data->block == new_block);
332169689Skan
333169689Skan      BLOCK_SUBBLOCKS (new_block)
334169689Skan	= blocks_nreverse (BLOCK_SUBBLOCKS (new_block));
335169689Skan      data->block = old_block;
336169689Skan    }
337169689Skan
338169689Skan  /* The BIND_EXPR no longer carries any useful information -- kill it.  */
339169689Skan  tsi_link_before (tsi, BIND_EXPR_BODY (stmt), TSI_SAME_STMT);
340169689Skan  tsi_delink (tsi);
341169689Skan}
342169689Skan
343169689Skan/* Try to determine whether a TRY_CATCH expression can fall through.
344169689Skan   This is a subroutine of block_may_fallthru.  */
345169689Skan
346169689Skanstatic bool
347169689Skantry_catch_may_fallthru (tree stmt)
348169689Skan{
349169689Skan  tree_stmt_iterator i;
350169689Skan
351169689Skan  /* If the TRY block can fall through, the whole TRY_CATCH can
352169689Skan     fall through.  */
353169689Skan  if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
354169689Skan    return true;
355169689Skan
356169689Skan  i = tsi_start (TREE_OPERAND (stmt, 1));
357169689Skan  switch (TREE_CODE (tsi_stmt (i)))
358169689Skan    {
359169689Skan    case CATCH_EXPR:
360169689Skan      /* We expect to see a sequence of CATCH_EXPR trees, each with a
361169689Skan	 catch expression and a body.  The whole TRY_CATCH may fall
362169689Skan	 through iff any of the catch bodies falls through.  */
363169689Skan      for (; !tsi_end_p (i); tsi_next (&i))
364169689Skan	{
365169689Skan	  if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
366169689Skan	    return true;
367169689Skan	}
368169689Skan      return false;
369169689Skan
370169689Skan    case EH_FILTER_EXPR:
371169689Skan      /* The exception filter expression only matters if there is an
372169689Skan	 exception.  If the exception does not match EH_FILTER_TYPES,
373169689Skan	 we will execute EH_FILTER_FAILURE, and we will fall through
374169689Skan	 if that falls through.  If the exception does match
375169689Skan	 EH_FILTER_TYPES, the stack unwinder will continue up the
376169689Skan	 stack, so we will not fall through.  We don't know whether we
377169689Skan	 will throw an exception which matches EH_FILTER_TYPES or not,
378169689Skan	 so we just ignore EH_FILTER_TYPES and assume that we might
379169689Skan	 throw an exception which doesn't match.  */
380169689Skan      return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
381169689Skan
382169689Skan    default:
383169689Skan      /* This case represents statements to be executed when an
384169689Skan	 exception occurs.  Those statements are implicitly followed
385169689Skan	 by a RESX_EXPR to resume execution after the exception.  So
386169689Skan	 in this case the TRY_CATCH never falls through.  */
387169689Skan      return false;
388169689Skan    }
389169689Skan}
390169689Skan
391169689Skan/* Try to determine if we can fall out of the bottom of BLOCK.  This guess
392169689Skan   need not be 100% accurate; simply be conservative and return true if we
393169689Skan   don't know.  This is used only to avoid stupidly generating extra code.
394169689Skan   If we're wrong, we'll just delete the extra code later.  */
395169689Skan
396169689Skanbool
397169689Skanblock_may_fallthru (tree block)
398169689Skan{
399169689Skan  tree stmt = expr_last (block);
400169689Skan
401169689Skan  switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
402169689Skan    {
403169689Skan    case GOTO_EXPR:
404169689Skan    case RETURN_EXPR:
405169689Skan    case RESX_EXPR:
406169689Skan      /* Easy cases.  If the last statement of the block implies
407169689Skan	 control transfer, then we can't fall through.  */
408169689Skan      return false;
409169689Skan
410169689Skan    case SWITCH_EXPR:
411169689Skan      /* If SWITCH_LABELS is set, this is lowered, and represents a
412169689Skan	 branch to a selected label and hence can not fall through.
413169689Skan	 Otherwise SWITCH_BODY is set, and the switch can fall
414169689Skan	 through.  */
415169689Skan      return SWITCH_LABELS (stmt) == NULL_TREE;
416169689Skan
417169689Skan    case COND_EXPR:
418169689Skan      if (block_may_fallthru (COND_EXPR_THEN (stmt)))
419169689Skan	return true;
420169689Skan      return block_may_fallthru (COND_EXPR_ELSE (stmt));
421169689Skan
422169689Skan    case BIND_EXPR:
423169689Skan      return block_may_fallthru (BIND_EXPR_BODY (stmt));
424169689Skan
425169689Skan    case TRY_CATCH_EXPR:
426169689Skan      return try_catch_may_fallthru (stmt);
427169689Skan
428169689Skan    case TRY_FINALLY_EXPR:
429169689Skan      /* The finally clause is always executed after the try clause,
430169689Skan	 so if it does not fall through, then the try-finally will not
431169689Skan	 fall through.  Otherwise, if the try clause does not fall
432169689Skan	 through, then when the finally clause falls through it will
433169689Skan	 resume execution wherever the try clause was going.  So the
434169689Skan	 whole try-finally will only fall through if both the try
435169689Skan	 clause and the finally clause fall through.  */
436169689Skan      return (block_may_fallthru (TREE_OPERAND (stmt, 0))
437169689Skan	      && block_may_fallthru (TREE_OPERAND (stmt, 1)));
438169689Skan
439169689Skan    case MODIFY_EXPR:
440169689Skan      if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
441169689Skan	stmt = TREE_OPERAND (stmt, 1);
442169689Skan      else
443169689Skan	return true;
444169689Skan      /* FALLTHRU */
445169689Skan
446169689Skan    case CALL_EXPR:
447169689Skan      /* Functions that do not return do not fall through.  */
448169689Skan      return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
449169689Skan
450169689Skan    case CLEANUP_POINT_EXPR:
451169689Skan      return block_may_fallthru (TREE_OPERAND (stmt, 0));
452169689Skan
453169689Skan    default:
454169689Skan      return true;
455169689Skan    }
456169689Skan}
457169689Skan
458169689Skan/* Lower a cond_expr TSI.  DATA is passed through the recursion.  */
459169689Skan
460169689Skanstatic void
461169689Skanlower_cond_expr (tree_stmt_iterator *tsi, struct lower_data *data)
462169689Skan{
463169689Skan  tree stmt = tsi_stmt (*tsi);
464169689Skan  bool then_is_goto, else_is_goto;
465169689Skan  tree then_branch, else_branch;
466169689Skan  tree then_goto, else_goto;
467169689Skan
468169689Skan  then_branch = COND_EXPR_THEN (stmt);
469169689Skan  else_branch = COND_EXPR_ELSE (stmt);
470169689Skan
471169689Skan  lower_stmt_body (then_branch, data);
472169689Skan  lower_stmt_body (else_branch, data);
473169689Skan
474169689Skan  then_goto = expr_only (then_branch);
475169689Skan  then_is_goto = then_goto && simple_goto_p (then_goto);
476169689Skan
477169689Skan  else_goto = expr_only (else_branch);
478169689Skan  else_is_goto = else_goto && simple_goto_p (else_goto);
479169689Skan
480169689Skan  if (!then_is_goto || !else_is_goto)
481169689Skan    {
482169689Skan      tree then_label, else_label, end_label, t;
483169689Skan
484169689Skan      then_label = NULL_TREE;
485169689Skan      else_label = NULL_TREE;
486169689Skan      end_label = NULL_TREE;
487169689Skan
488169689Skan      /* Replace the cond_expr with explicit gotos.  */
489169689Skan      if (!then_is_goto)
490169689Skan	{
491169689Skan	  t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
492169689Skan	  if (TREE_SIDE_EFFECTS (then_branch))
493169689Skan	    then_label = t;
494169689Skan	  else
495169689Skan	    end_label = t;
496169689Skan	  then_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
497169689Skan	}
498169689Skan
499169689Skan      if (!else_is_goto)
500169689Skan	{
501169689Skan	  t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
502169689Skan	  if (TREE_SIDE_EFFECTS (else_branch))
503169689Skan	    else_label = t;
504169689Skan	  else
505169689Skan	    {
506169689Skan	      /* Both THEN and ELSE can be no-ops if one or both contained an
507169689Skan	         empty BIND_EXPR that was associated with the toplevel block
508169689Skan	         of an inlined function.  In that case remove_useless_stmts
509169689Skan	         can't have cleaned things up for us; kill the whole
510169689Skan	         conditional now.  */
511169689Skan	      if (end_label)
512169689Skan		{
513169689Skan		  tsi_delink (tsi);
514169689Skan		  return;
515169689Skan		}
516169689Skan	      else
517169689Skan		end_label = t;
518169689Skan	    }
519169689Skan	  else_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
520169689Skan	}
521169689Skan
522169689Skan      if (then_label)
523169689Skan	{
524169689Skan	  bool may_fallthru = block_may_fallthru (then_branch);
525169689Skan
526169689Skan	  tsi_link_after (tsi, then_label, TSI_CONTINUE_LINKING);
527169689Skan	  tsi_link_after (tsi, then_branch, TSI_CONTINUE_LINKING);
528169689Skan
529169689Skan	  if (else_label && may_fallthru)
530169689Skan	    {
531169689Skan	      end_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
532169689Skan	      t = build_and_jump (&LABEL_EXPR_LABEL (end_label));
533169689Skan	      tsi_link_after (tsi, t, TSI_CONTINUE_LINKING);
534169689Skan	    }
535169689Skan	}
536169689Skan
537169689Skan      if (else_label)
538169689Skan	{
539169689Skan	  tsi_link_after (tsi, else_label, TSI_CONTINUE_LINKING);
540169689Skan	  tsi_link_after (tsi, else_branch, TSI_CONTINUE_LINKING);
541169689Skan	}
542169689Skan
543169689Skan      if (end_label)
544169689Skan	tsi_link_after (tsi, end_label, TSI_CONTINUE_LINKING);
545169689Skan    }
546169689Skan
547169689Skan  COND_EXPR_THEN (stmt) = then_goto;
548169689Skan  COND_EXPR_ELSE (stmt) = else_goto;
549169689Skan
550169689Skan  tsi_next (tsi);
551169689Skan}
552169689Skan
553169689Skan/* Lower a return_expr TSI.  DATA is passed through the recursion.  */
554169689Skan
555169689Skanstatic void
556169689Skanlower_return_expr (tree_stmt_iterator *tsi, struct lower_data *data)
557169689Skan{
558169689Skan  tree stmt = tsi_stmt (*tsi);
559169689Skan  tree value, t, label;
560169689Skan
561169689Skan  /* Extract the value being returned.  */
562169689Skan  value = TREE_OPERAND (stmt, 0);
563169689Skan  if (value && TREE_CODE (value) == MODIFY_EXPR)
564169689Skan    value = TREE_OPERAND (value, 1);
565169689Skan
566169689Skan  /* Match this up with an existing return statement that's been created.  */
567169689Skan  for (t = data->return_statements; t ; t = TREE_CHAIN (t))
568169689Skan    {
569169689Skan      tree tvalue = TREE_OPERAND (TREE_VALUE (t), 0);
570169689Skan      if (tvalue && TREE_CODE (tvalue) == MODIFY_EXPR)
571169689Skan	tvalue = TREE_OPERAND (tvalue, 1);
572169689Skan
573169689Skan      if (value == tvalue)
574169689Skan	{
575169689Skan	  label = TREE_PURPOSE (t);
576169689Skan	  goto found;
577169689Skan	}
578169689Skan    }
579169689Skan
580169689Skan  /* Not found.  Create a new label and record the return statement.  */
581169689Skan  label = create_artificial_label ();
582169689Skan  data->return_statements = tree_cons (label, stmt, data->return_statements);
583169689Skan
584169689Skan  /* Generate a goto statement and remove the return statement.  */
585169689Skan found:
586169689Skan  t = build1 (GOTO_EXPR, void_type_node, label);
587169689Skan  SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
588169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
589169689Skan  tsi_delink (tsi);
590169689Skan}
591169689Skan
592169689Skan/* Lower a __builtin_setjmp TSI.
593169689Skan
594169689Skan   __builtin_setjmp is passed a pointer to an array of five words (not
595169689Skan   all will be used on all machines).  It operates similarly to the C
596169689Skan   library function of the same name, but is more efficient.
597169689Skan
598169689Skan   It is lowered into 3 other builtins, namely __builtin_setjmp_setup,
599169689Skan   __builtin_setjmp_dispatcher and __builtin_setjmp_receiver, but with
600169689Skan   __builtin_setjmp_dispatcher shared among all the instances; that's
601169689Skan   why it is only emitted at the end by lower_function_body.
602169689Skan
603169689Skan   After full lowering, the body of the function should look like:
604169689Skan
605169689Skan    {
606169689Skan      void * setjmpvar.0;
607169689Skan      int D.1844;
608169689Skan      int D.2844;
609169689Skan
610169689Skan      [...]
611169689Skan
612169689Skan      __builtin_setjmp_setup (&buf, &<D1847>);
613169689Skan      D.1844 = 0;
614169689Skan      goto <D1846>;
615169689Skan      <D1847>:;
616169689Skan      __builtin_setjmp_receiver (&<D1847>);
617169689Skan      D.1844 = 1;
618169689Skan      <D1846>:;
619169689Skan      if (D.1844 == 0) goto <D1848>; else goto <D1849>;
620169689Skan
621169689Skan      [...]
622169689Skan
623169689Skan      __builtin_setjmp_setup (&buf, &<D2847>);
624169689Skan      D.2844 = 0;
625169689Skan      goto <D2846>;
626169689Skan      <D2847>:;
627169689Skan      __builtin_setjmp_receiver (&<D2847>);
628169689Skan      D.2844 = 1;
629169689Skan      <D2846>:;
630169689Skan      if (D.2844 == 0) goto <D2848>; else goto <D2849>;
631169689Skan
632169689Skan      [...]
633169689Skan
634169689Skan      <D3850>:;
635169689Skan      return;
636169689Skan      <D3853>: [non-local];
637169689Skan      setjmpvar.0 = __builtin_setjmp_dispatcher (&<D3853>);
638169689Skan      goto setjmpvar.0;
639169689Skan    }
640169689Skan
641169689Skan   The dispatcher block will be both the unique destination of all the
642169689Skan   abnormal call edges and the unique source of all the abnormal edges
643169689Skan   to the receivers, thus keeping the complexity explosion localized.  */
644169689Skan
645169689Skanstatic void
646169689Skanlower_builtin_setjmp (tree_stmt_iterator *tsi)
647169689Skan{
648169689Skan  tree stmt = tsi_stmt (*tsi);
649169689Skan  tree cont_label = create_artificial_label ();
650169689Skan  tree next_label = create_artificial_label ();
651169689Skan  tree dest, t, arg;
652169689Skan
653169689Skan  /* NEXT_LABEL is the label __builtin_longjmp will jump to.  Its address is
654169689Skan     passed to both __builtin_setjmp_setup and __builtin_setjmp_receiver.  */
655169689Skan  FORCED_LABEL (next_label) = 1;
656169689Skan
657169689Skan  if (TREE_CODE (stmt) == MODIFY_EXPR)
658169689Skan    {
659169689Skan      dest = TREE_OPERAND (stmt, 0);
660169689Skan      stmt = TREE_OPERAND (stmt, 1);
661169689Skan    }
662169689Skan  else
663169689Skan    dest = NULL_TREE;
664169689Skan
665169689Skan  /* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert.  */
666169689Skan  t = build_addr (next_label, current_function_decl);
667169689Skan  arg = tree_cons (NULL, t, NULL);
668169689Skan  t = TREE_VALUE (TREE_OPERAND (stmt, 1));
669169689Skan  arg = tree_cons (NULL, t, arg);
670169689Skan  t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP];
671169689Skan  t = build_function_call_expr (t, arg);
672169689Skan  SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
673169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
674169689Skan
675169689Skan  /* Build 'DEST = 0' and insert.  */
676169689Skan  if (dest)
677169689Skan    {
678169689Skan      t = build2 (MODIFY_EXPR, void_type_node, dest, integer_zero_node);
679169689Skan      SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
680169689Skan      tsi_link_before (tsi, t, TSI_SAME_STMT);
681169689Skan    }
682169689Skan
683169689Skan  /* Build 'goto CONT_LABEL' and insert.  */
684169689Skan  t = build1 (GOTO_EXPR, void_type_node, cont_label);
685169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
686169689Skan
687169689Skan  /* Build 'NEXT_LABEL:' and insert.  */
688169689Skan  t = build1 (LABEL_EXPR, void_type_node, next_label);
689169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
690169689Skan
691169689Skan  /* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert.  */
692169689Skan  t = build_addr (next_label, current_function_decl);
693169689Skan  arg = tree_cons (NULL, t, NULL);
694169689Skan  t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER];
695169689Skan  t = build_function_call_expr (t, arg);
696169689Skan  SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
697169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
698169689Skan
699169689Skan  /* Build 'DEST = 1' and insert.  */
700169689Skan  if (dest)
701169689Skan    {
702169689Skan      t = build2 (MODIFY_EXPR, void_type_node, dest, integer_one_node);
703169689Skan      SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
704169689Skan      tsi_link_before (tsi, t, TSI_SAME_STMT);
705169689Skan    }
706169689Skan
707169689Skan  /* Build 'CONT_LABEL:' and insert.  */
708169689Skan  t = build1 (LABEL_EXPR, void_type_node, cont_label);
709169689Skan  tsi_link_before (tsi, t, TSI_SAME_STMT);
710169689Skan
711169689Skan  /* Remove the call to __builtin_setjmp.  */
712169689Skan  tsi_delink (tsi);
713169689Skan}
714169689Skan
715169689Skan
716169689Skan/* Record the variables in VARS into function FN.  */
717169689Skan
718169689Skanvoid
719169689Skanrecord_vars_into (tree vars, tree fn)
720169689Skan{
721169689Skan  struct function *saved_cfun = cfun;
722169689Skan
723169689Skan  if (fn != current_function_decl)
724169689Skan    cfun = DECL_STRUCT_FUNCTION (fn);
725169689Skan
726169689Skan  for (; vars; vars = TREE_CHAIN (vars))
727169689Skan    {
728169689Skan      tree var = vars;
729169689Skan
730169689Skan      /* BIND_EXPRs contains also function/type/constant declarations
731169689Skan         we don't need to care about.  */
732169689Skan      if (TREE_CODE (var) != VAR_DECL)
733169689Skan	continue;
734169689Skan
735169689Skan      /* Nothing to do in this case.  */
736169689Skan      if (DECL_EXTERNAL (var))
737169689Skan	continue;
738169689Skan
739169689Skan      /* Record the variable.  */
740169689Skan      cfun->unexpanded_var_list = tree_cons (NULL_TREE, var,
741169689Skan					     cfun->unexpanded_var_list);
742169689Skan    }
743169689Skan
744169689Skan  if (fn != current_function_decl)
745169689Skan    cfun = saved_cfun;
746169689Skan}
747169689Skan
748169689Skan
749169689Skan/* Record the variables in VARS into current_function_decl.  */
750169689Skan
751169689Skanvoid
752169689Skanrecord_vars (tree vars)
753169689Skan{
754169689Skan  record_vars_into (vars, current_function_decl);
755169689Skan}
756169689Skan
757169689Skan
758169689Skan/* Mark BLOCK used if it has a used variable in it, then recurse over its
759169689Skan   subblocks.  */
760169689Skan
761169689Skanstatic void
762169689Skanmark_blocks_with_used_vars (tree block)
763169689Skan{
764169689Skan  tree var;
765169689Skan  tree subblock;
766169689Skan
767169689Skan  if (!TREE_USED (block))
768169689Skan    {
769169689Skan      for (var = BLOCK_VARS (block);
770169689Skan	   var;
771169689Skan	   var = TREE_CHAIN (var))
772169689Skan	{
773169689Skan	  if (TREE_USED (var))
774169689Skan	    {
775169689Skan	      TREE_USED (block) = true;
776169689Skan	      break;
777169689Skan	    }
778169689Skan	}
779169689Skan    }
780169689Skan  for (subblock = BLOCK_SUBBLOCKS (block);
781169689Skan       subblock;
782169689Skan       subblock = BLOCK_CHAIN (subblock))
783169689Skan    mark_blocks_with_used_vars (subblock);
784169689Skan}
785169689Skan
786169689Skan/* Mark the used attribute on blocks correctly.  */
787169689Skan
788169689Skanstatic unsigned int
789169689Skanmark_used_blocks (void)
790169689Skan{
791169689Skan  mark_blocks_with_used_vars (DECL_INITIAL (current_function_decl));
792169689Skan  return 0;
793169689Skan}
794169689Skan
795169689Skan
796169689Skanstruct tree_opt_pass pass_mark_used_blocks =
797169689Skan{
798169689Skan  "blocks",				/* name */
799169689Skan  NULL,					/* gate */
800169689Skan  mark_used_blocks,			/* execute */
801169689Skan  NULL,					/* sub */
802169689Skan  NULL,					/* next */
803169689Skan  0,					/* static_pass_number */
804169689Skan  0,					/* tv_id */
805169689Skan  0,					/* properties_required */
806169689Skan  0,					/* properties_provided */
807169689Skan  0,					/* properties_destroyed */
808169689Skan  0,					/* todo_flags_start */
809169689Skan  TODO_dump_func,			/* todo_flags_finish */
810169689Skan  0					/* letter */
811169689Skan};
812