1/* Tree lowering to gimple for middle end use only.
2   This converts the GENERIC functions-as-trees tree representation into
3   the GIMPLE form.
4   Copyright (C) 2013-2020 Free Software Foundation, Inc.
5   Major work done by Sebastian Pop <s.pop@laposte.net>,
6   Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
12Software Foundation; either version 3, or (at your option) any later
13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
21along with GCC; see the file COPYING3.  If not see
22<http://www.gnu.org/licenses/>.  */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "backend.h"
28#include "tree.h"
29#include "gimple.h"
30#include "ssa.h"
31#include "stmt.h"
32#include "stor-layout.h"
33#include "tree-eh.h"
34#include "gimple-iterator.h"
35#include "gimplify.h"
36#include "gimplify-me.h"
37
38
39/* Expand EXPR to list of gimple statements STMTS.  GIMPLE_TEST_F specifies
40   the predicate that will hold for the result.  If VAR is not NULL, make the
41   base variable of the final destination be VAR if suitable.  */
42
43tree
44force_gimple_operand_1 (tree expr, gimple_seq *stmts,
45			gimple_predicate gimple_test_f, tree var)
46{
47  enum gimplify_status ret;
48  location_t saved_location;
49
50  *stmts = NULL;
51
52  /* gimple_test_f might be more strict than is_gimple_val, make
53     sure we pass both.  Just checking gimple_test_f doesn't work
54     because most gimple predicates do not work recursively.  */
55  if (is_gimple_val (expr)
56      && (*gimple_test_f) (expr))
57    return expr;
58
59  push_gimplify_context (gimple_in_ssa_p (cfun), true);
60  saved_location = input_location;
61  input_location = UNKNOWN_LOCATION;
62
63  if (var)
64    {
65      if (gimple_in_ssa_p (cfun) && is_gimple_reg (var))
66	var = make_ssa_name (var);
67      expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
68    }
69
70  if (TREE_CODE (expr) != MODIFY_EXPR
71      && TREE_TYPE (expr) == void_type_node)
72    {
73      gimplify_and_add (expr, stmts);
74      expr = NULL_TREE;
75    }
76  else
77    {
78      ret = gimplify_expr (&expr, stmts, NULL, gimple_test_f, fb_rvalue);
79      gcc_assert (ret != GS_ERROR);
80    }
81
82  input_location = saved_location;
83  pop_gimplify_context (NULL);
84
85  return expr;
86}
87
88/* Expand EXPR to list of gimple statements STMTS.  If SIMPLE is true,
89   force the result to be either ssa_name or an invariant, otherwise
90   just force it to be a rhs expression.  If VAR is not NULL, make the
91   base variable of the final destination be VAR if suitable.  */
92
93tree
94force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
95{
96  return force_gimple_operand_1 (expr, stmts,
97				 simple ? is_gimple_val : is_gimple_reg_rhs,
98				 var);
99}
100
101/* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
102   and VAR.  If some statements are produced, emits them at GSI.
103   If BEFORE is true.  the statements are appended before GSI, otherwise
104   they are appended after it.  M specifies the way GSI moves after
105   insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values).  */
106
107tree
108force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
109			    gimple_predicate gimple_test_f,
110			    tree var, bool before,
111			    enum gsi_iterator_update m)
112{
113  gimple_seq stmts;
114
115  expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
116
117  if (!gimple_seq_empty_p (stmts))
118    {
119      if (before)
120	gsi_insert_seq_before (gsi, stmts, m);
121      else
122	gsi_insert_seq_after (gsi, stmts, m);
123    }
124
125  return expr;
126}
127
128/* Invoke force_gimple_operand_1 for EXPR with parameter VAR.
129   If SIMPLE is true, force the result to be either ssa_name or an invariant,
130   otherwise just force it to be a rhs expression.  If some statements are
131   produced, emits them at GSI.  If BEFORE is true, the statements are
132   appended before GSI, otherwise they are appended after it.  M specifies
133   the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
134   are the usual values).  */
135
136tree
137force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
138			  bool simple_p, tree var, bool before,
139			  enum gsi_iterator_update m)
140{
141  return force_gimple_operand_gsi_1 (gsi, expr,
142				     simple_p
143				     ? is_gimple_val : is_gimple_reg_rhs,
144				     var, before, m);
145}
146
147/* Some transformations like inlining may invalidate the GIMPLE form
148   for operands.  This function traverses all the operands in STMT and
149   gimplifies anything that is not a valid gimple operand.  Any new
150   GIMPLE statements are inserted before *GSI_P.  */
151
152void
153gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
154{
155  size_t i, num_ops;
156  tree lhs;
157  gimple_seq pre = NULL;
158  gimple *post_stmt = NULL;
159
160  push_gimplify_context (gimple_in_ssa_p (cfun));
161
162  switch (gimple_code (stmt))
163    {
164    case GIMPLE_COND:
165      {
166	gcond *cond_stmt = as_a <gcond *> (stmt);
167	gimplify_expr (gimple_cond_lhs_ptr (cond_stmt), &pre, NULL,
168		       is_gimple_val, fb_rvalue);
169	gimplify_expr (gimple_cond_rhs_ptr (cond_stmt), &pre, NULL,
170		       is_gimple_val, fb_rvalue);
171      }
172      break;
173    case GIMPLE_SWITCH:
174      gimplify_expr (gimple_switch_index_ptr (as_a <gswitch *> (stmt)),
175		     &pre, NULL, is_gimple_val, fb_rvalue);
176      break;
177    case GIMPLE_OMP_ATOMIC_LOAD:
178      gimplify_expr (gimple_omp_atomic_load_rhs_ptr (
179		       as_a <gomp_atomic_load *> (stmt)),
180		     &pre, NULL, is_gimple_val, fb_rvalue);
181      break;
182    case GIMPLE_ASM:
183      {
184	gasm *asm_stmt = as_a <gasm *> (stmt);
185	size_t i, noutputs = gimple_asm_noutputs (asm_stmt);
186	const char *constraint, **oconstraints;
187	bool allows_mem, allows_reg, is_inout;
188
189	oconstraints
190	  = (const char **) alloca ((noutputs) * sizeof (const char *));
191	for (i = 0; i < noutputs; i++)
192	  {
193	    tree op = gimple_asm_output_op (asm_stmt, i);
194	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
195	    oconstraints[i] = constraint;
196	    parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
197				     &allows_reg, &is_inout);
198	    gimplify_expr (&TREE_VALUE (op), &pre, NULL,
199			   is_inout ? is_gimple_min_lval : is_gimple_lvalue,
200			   fb_lvalue | fb_mayfail);
201	  }
202	for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
203	  {
204	    tree op = gimple_asm_input_op (asm_stmt, i);
205	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
206	    parse_input_constraint (&constraint, 0, 0, noutputs, 0,
207				    oconstraints, &allows_mem, &allows_reg);
208	    if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
209	      allows_reg = 0;
210	    if (!allows_reg && allows_mem)
211	      gimplify_expr (&TREE_VALUE (op), &pre, NULL,
212			     is_gimple_lvalue, fb_lvalue | fb_mayfail);
213	    else
214	      gimplify_expr (&TREE_VALUE (op), &pre, NULL,
215			     is_gimple_asm_val, fb_rvalue);
216	  }
217      }
218      break;
219    default:
220      /* NOTE: We start gimplifying operands from last to first to
221	 make sure that side-effects on the RHS of calls, assignments
222	 and ASMs are executed before the LHS.  The ordering is not
223	 important for other statements.  */
224      num_ops = gimple_num_ops (stmt);
225      for (i = num_ops; i > 0; i--)
226	{
227	  tree op = gimple_op (stmt, i - 1);
228	  if (op == NULL_TREE)
229	    continue;
230	  if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
231	    gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
232	  else if (i == 2
233		   && is_gimple_assign (stmt)
234		   && num_ops == 2
235		   && get_gimple_rhs_class (gimple_expr_code (stmt))
236		      == GIMPLE_SINGLE_RHS)
237	    gimplify_expr (&op, &pre, NULL,
238			   rhs_predicate_for (gimple_assign_lhs (stmt)),
239			   fb_rvalue);
240	  else if (i == 2 && is_gimple_call (stmt))
241	    {
242	      if (TREE_CODE (op) == FUNCTION_DECL)
243		continue;
244	      gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
245	    }
246	  else
247	    gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
248	  gimple_set_op (stmt, i - 1, op);
249	}
250
251      lhs = gimple_get_lhs (stmt);
252      /* If the LHS changed it in a way that requires a simple RHS,
253	 create temporary.  */
254      if (lhs && !is_gimple_reg (lhs))
255	{
256	  bool need_temp = false;
257
258	  if (is_gimple_assign (stmt)
259	      && num_ops == 2
260	      && get_gimple_rhs_class (gimple_expr_code (stmt))
261		 == GIMPLE_SINGLE_RHS)
262	    gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
263			   rhs_predicate_for (gimple_assign_lhs (stmt)),
264			   fb_rvalue);
265	  else if (is_gimple_reg (lhs))
266	    {
267	      if (is_gimple_reg_type (TREE_TYPE (lhs)))
268		{
269		  if (is_gimple_call (stmt))
270		    {
271		      i = gimple_call_flags (stmt);
272		      if ((i & ECF_LOOPING_CONST_OR_PURE)
273			  || !(i & (ECF_CONST | ECF_PURE)))
274			need_temp = true;
275		    }
276		  if (stmt_can_throw_internal (cfun, stmt))
277		    need_temp = true;
278		}
279	    }
280	  else
281	    {
282	      if (is_gimple_reg_type (TREE_TYPE (lhs)))
283		need_temp = true;
284	      else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
285		{
286		  if (is_gimple_call (stmt))
287		    {
288		      tree fndecl = gimple_call_fndecl (stmt);
289
290		      if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
291			  && !(fndecl && DECL_RESULT (fndecl)
292			       && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
293			need_temp = true;
294		    }
295		  else
296		    need_temp = true;
297		}
298	    }
299	  if (need_temp)
300	    {
301	      tree temp = create_tmp_reg (TREE_TYPE (lhs));
302	      if (gimple_in_ssa_p (cfun)
303		  && is_gimple_reg_type (TREE_TYPE (lhs)))
304		temp = make_ssa_name (temp);
305	      gimple_set_lhs (stmt, temp);
306	      post_stmt = gimple_build_assign (lhs, temp);
307	    }
308	}
309      break;
310    }
311
312  if (!gimple_seq_empty_p (pre))
313    gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
314  if (post_stmt)
315    gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
316
317  pop_gimplify_context (NULL);
318
319  update_stmt (stmt);
320}
321
322
323