analyzer: fix feasibility false +ve on jumps through function ptrs [PR107582]
[platform/upstream/gcc.git] / gcc / gimplify-me.cc
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-2022 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
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along 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
43 tree
44 force_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
93 tree
94 force_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
107 tree
108 force_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
136 tree
137 force_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
152 void
153 gimple_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                    && gimple_assign_single_p (stmt)
234                    && num_ops == 2)
235             gimplify_expr (&op, &pre, NULL,
236                            rhs_predicate_for (gimple_assign_lhs (stmt)),
237                            fb_rvalue);
238           else if (i == 2 && is_gimple_call (stmt))
239             {
240               if (TREE_CODE (op) == FUNCTION_DECL)
241                 continue;
242               gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
243             }
244           else
245             gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
246           gimple_set_op (stmt, i - 1, op);
247         }
248
249       lhs = gimple_get_lhs (stmt);
250       /* If the LHS changed it in a way that requires a simple RHS,
251          create temporary.  */
252       if (lhs && !is_gimple_reg (lhs))
253         {
254           bool need_temp = false;
255
256           if (gimple_assign_single_p (stmt)
257               && num_ops == 2)
258             gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
259                            rhs_predicate_for (gimple_assign_lhs (stmt)),
260                            fb_rvalue);
261           else if (is_gimple_reg (lhs))
262             {
263               if (is_gimple_reg_type (TREE_TYPE (lhs)))
264                 {
265                   if (is_gimple_call (stmt))
266                     {
267                       i = gimple_call_flags (stmt);
268                       if ((i & ECF_LOOPING_CONST_OR_PURE)
269                           || !(i & (ECF_CONST | ECF_PURE)))
270                         need_temp = true;
271                     }
272                   if (stmt_can_throw_internal (cfun, stmt))
273                     need_temp = true;
274                 }
275             }
276           else
277             {
278               if (is_gimple_reg_type (TREE_TYPE (lhs)))
279                 need_temp = true;
280               else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
281                 {
282                   if (is_gimple_call (stmt))
283                     {
284                       tree fndecl = gimple_call_fndecl (stmt);
285
286                       if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
287                           && !(fndecl && DECL_RESULT (fndecl)
288                                && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
289                         need_temp = true;
290                     }
291                   else
292                     need_temp = true;
293                 }
294             }
295           if (need_temp)
296             {
297               tree temp = create_tmp_reg (TREE_TYPE (lhs));
298               if (gimple_in_ssa_p (cfun)
299                   && is_gimple_reg_type (TREE_TYPE (lhs)))
300                 temp = make_ssa_name (temp);
301               gimple_set_lhs (stmt, temp);
302               post_stmt = gimple_build_assign (lhs, temp);
303             }
304         }
305       break;
306     }
307
308   if (!gimple_seq_empty_p (pre))
309     gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
310   if (post_stmt)
311     gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
312
313   pop_gimplify_context (NULL);
314
315   update_stmt (stmt);
316 }
317
318