xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/d-gimplify.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* D-specific tree lowering bits; see also gimple.cc.
2    Copyright (C) 2020-2022 Free Software Foundation, Inc.
3 
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8 
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along 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 
34 static bool
empty_modify_p(tree type,tree op)35 empty_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 
67 static bool
bit_field_ref(const_tree expr)68 bit_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 
79 static gimplify_status
d_gimplify_modify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)80 d_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 
124 static gimplify_status
d_gimplify_addr_expr(tree * expr_p)125 d_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 
140 static gimplify_status
d_gimplify_call_expr(tree * expr_p,gimple_seq * pre_p)141 d_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 
188 static gimplify_status
d_gimplify_unsigned_rshift_expr(tree * expr_p)189 d_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 
203 static gimplify_status
d_gimplify_unary_expr(tree * expr_p)204 d_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 
224 static gimplify_status
d_gimplify_binary_expr(tree * expr_p)225 d_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 
252 int
d_gimplify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)253 d_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