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