1/* D-specific tree lowering bits; see also gimple.cc.
2   Copyright (C) 2020-2022 Free Software Foundation, Inc.
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3.  If not see
16<http://www.gnu.org/licenses/>.  */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/globals.h"
23
24#include "tree.h"
25#include "gimple-expr.h"
26#include "gimplify.h"
27
28#include "d-tree.h"
29
30
31/* Return TRUE if an operand OP of a given TYPE being copied has no data.
32   The middle-end does a similar check with zero sized types.  */
33
34static bool
35empty_modify_p (tree type, tree op)
36{
37  tree_code code = TREE_CODE (op);
38  switch (code)
39    {
40    case COMPOUND_EXPR:
41      return empty_modify_p (type, TREE_OPERAND (op, 1));
42
43    case CONSTRUCTOR:
44      /* Non-empty construcors are valid.  */
45      if (CONSTRUCTOR_NELTS (op) != 0 || TREE_CLOBBER_P (op))
46	return false;
47      break;
48
49    case CALL_EXPR:
50      /* Leave nrvo alone because it isn't a copy.  */
51      if (CALL_EXPR_RETURN_SLOT_OPT (op))
52	return false;
53      break;
54
55    default:
56      /* If the operand doesn't have a simple form.  */
57      if (!is_gimple_lvalue (op) && !INDIRECT_REF_P (op))
58	return false;
59      break;
60    }
61
62  return empty_aggregate_p (type);
63}
64
65/* Return TRUE if EXPR is a COMPONENT_REF to a bit-field declaration.  */
66
67static bool
68bit_field_ref (const_tree expr)
69{
70  if (TREE_CODE (expr) == COMPONENT_REF
71      && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
72    return true;
73
74  return false;
75}
76
77/* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR.  */
78
79static gimplify_status
80d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
81{
82  tree op0 = TREE_OPERAND (*expr_p, 0);
83  tree op1 = TREE_OPERAND (*expr_p, 1);
84
85  if (error_operand_p (op0) || error_operand_p (op1))
86    return GS_UNHANDLED;
87
88  /* Remove any copies of empty aggregates.  */
89  if (empty_modify_p (TREE_TYPE (op0), op1))
90    {
91      gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
92		     is_gimple_lvalue, fb_lvalue);
93
94      if (TREE_SIDE_EFFECTS (op1))
95	gimplify_and_add (op1, pre_p);
96
97      *expr_p = TREE_OPERAND (*expr_p, 0);
98      return GS_OK;
99    }
100
101  /* If the back end isn't clever enough to know that the lhs and rhs
102     types are the same, add an explicit conversion.  */
103  if ((AGGREGATE_TYPE_P (TREE_TYPE (op0)) || AGGREGATE_TYPE_P (TREE_TYPE (op1)))
104      && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
105    {
106      TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
107					  TREE_TYPE (op0), op1);
108      return GS_OK;
109    }
110
111  /* Same as above, but for bit-field assignments.  */
112  if ((bit_field_ref (op0) || bit_field_ref (op1))
113      && TREE_TYPE (op0) != TREE_TYPE (op1))
114    {
115      TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (op0), op1);
116      return GS_OK;
117    }
118
119  return GS_UNHANDLED;
120}
121
122/* Gimplify an ADDR_EXPR node.  */
123
124static gimplify_status
125d_gimplify_addr_expr (tree *expr_p)
126{
127  tree op0 = TREE_OPERAND (*expr_p, 0);
128  /* Constructors are not lvalues, so make them one.  */
129  if (TREE_CODE (op0) == CONSTRUCTOR)
130    {
131      TREE_OPERAND (*expr_p, 0) = force_target_expr (op0);
132      return GS_OK;
133    }
134
135  return GS_UNHANDLED;
136}
137
138/* Gimplify a CALL_EXPR node.  */
139
140static gimplify_status
141d_gimplify_call_expr (tree *expr_p, gimple_seq *pre_p)
142{
143  /* Strictly evaluate all arguments from left to right.  */
144  int nargs = call_expr_nargs (*expr_p);
145  location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
146
147  /* No need to enforce evaluation order if only one argument.  */
148  if (nargs < 2)
149    return GS_UNHANDLED;
150
151  /* Or if all arguments are already free of side-effects.  */
152  bool has_side_effects = false;
153  for (int i = 0; i < nargs; i++)
154    {
155      if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
156	{
157	  has_side_effects = true;
158	  break;
159	}
160    }
161
162  if (!has_side_effects)
163    return GS_UNHANDLED;
164
165  /* Leave the last argument for gimplify_call_expr.  */
166  for (int i = 0; i < nargs - 1; i++)
167    {
168      tree new_arg = CALL_EXPR_ARG (*expr_p, i);
169
170      /* If argument has a side-effect, gimplify_arg will handle it.  */
171      if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
172	return GS_ERROR;
173
174      /* Even if an argument itself doesn't have any side-effects, it
175	 might be altered by another argument in the list.  */
176      if (new_arg == CALL_EXPR_ARG (*expr_p, i)
177	  && !really_constant_p (new_arg))
178	new_arg = get_formal_tmp_var (new_arg, pre_p);
179
180      CALL_EXPR_ARG (*expr_p, i) = new_arg;
181    }
182
183  return GS_OK;
184}
185
186/* Gimplify an UNSIGNED_RSHIFT_EXPR node.  */
187
188static gimplify_status
189d_gimplify_unsigned_rshift_expr (tree *expr_p)
190{
191  /* Convert op0 to an unsigned type.  */
192  tree op0 = TREE_OPERAND (*expr_p, 0);
193  tree op1 = TREE_OPERAND (*expr_p, 1);
194  tree type = d_unsigned_type (TREE_TYPE (op0));
195
196  *expr_p = convert (TREE_TYPE (*expr_p),
197		     build2 (RSHIFT_EXPR, type, convert (type, op0), op1));
198  return GS_OK;
199}
200
201/* Gimplify an unary expression node.  */
202
203static gimplify_status
204d_gimplify_unary_expr (tree *expr_p)
205{
206  tree op0 = TREE_OPERAND (*expr_p, 0);
207
208  if (error_operand_p (op0))
209    return GS_UNHANDLED;
210
211  /* Front end doesn't know that bit-field types are really different
212     from basic types, add an explicit conversion in unary expressions.  */
213  if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (*expr_p))
214    {
215      TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
216      return GS_OK;
217    }
218
219  return GS_UNHANDLED;
220}
221
222/* Gimplify a binary expression node.  */
223
224static gimplify_status
225d_gimplify_binary_expr (tree *expr_p)
226{
227  tree op0 = TREE_OPERAND (*expr_p, 0);
228  tree op1 = TREE_OPERAND (*expr_p, 1);
229
230  if (error_operand_p (op0) || error_operand_p (op1))
231    return GS_UNHANDLED;
232
233  /* Front end doesn't know that bit-field types are really different
234     from basic types, add an explicit conversion in binary expressions.  */
235  if (bit_field_ref (op0) || bit_field_ref (op1))
236    {
237      if (TREE_TYPE (op0) != TREE_TYPE (*expr_p))
238    	TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
239
240      if (TREE_TYPE (op1) != TREE_TYPE (*expr_p))
241    	TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (*expr_p), op1);
242
243      return GS_OK;
244    }
245
246  return GS_UNHANDLED;
247}
248
249/* Implements the lang_hooks.gimplify_expr routine for language D.
250   Do gimplification of D specific expression trees in EXPR_P.  */
251
252int
253d_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
254{
255  switch (TREE_CODE (*expr_p))
256    {
257    case INIT_EXPR:
258    case MODIFY_EXPR:
259      return d_gimplify_modify_expr (expr_p, pre_p, post_p);
260
261    case ADDR_EXPR:
262      return d_gimplify_addr_expr (expr_p);
263
264    case CALL_EXPR:
265      return d_gimplify_call_expr (expr_p, pre_p);
266
267    case UNSIGNED_RSHIFT_EXPR:
268      return d_gimplify_unsigned_rshift_expr (expr_p);
269
270    case FLOAT_MOD_EXPR:
271      gcc_unreachable ();
272
273    default:
274      if (UNARY_CLASS_P (*expr_p) && !CONVERT_EXPR_P (*expr_p))
275	return d_gimplify_unary_expr (expr_p);
276      if (BINARY_CLASS_P (*expr_p))
277	return d_gimplify_binary_expr (expr_p);
278      break;
279    }
280
281  return GS_UNHANDLED;
282}
283