]>
Commit | Line | Data |
---|---|---|
e53b6e56 | 1 | /* D-specific tree lowering bits; see also gimple.cc. |
7adcbafe | 2 | Copyright (C) 2020-2022 Free Software Foundation, Inc. |
e966361c IB |
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 | |
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 | ||
747f01eb | 65 | /* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR. */ |
e966361c | 66 | |
747f01eb IB |
67 | static gimplify_status |
68 | d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) | |
e966361c | 69 | { |
747f01eb IB |
70 | tree op0 = TREE_OPERAND (*expr_p, 0); |
71 | tree op1 = TREE_OPERAND (*expr_p, 1); | |
e966361c | 72 | |
747f01eb IB |
73 | if (error_operand_p (op0) || error_operand_p (op1)) |
74 | return GS_UNHANDLED; | |
75 | ||
76 | /* Remove any copies of empty aggregates. */ | |
77 | if (empty_modify_p (TREE_TYPE (op0), op1)) | |
e966361c | 78 | { |
747f01eb IB |
79 | gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, |
80 | is_gimple_lvalue, fb_lvalue); | |
e966361c | 81 | |
747f01eb IB |
82 | if (TREE_SIDE_EFFECTS (op1)) |
83 | gimplify_and_add (op1, pre_p); | |
e966361c | 84 | |
747f01eb IB |
85 | *expr_p = TREE_OPERAND (*expr_p, 0); |
86 | return GS_OK; | |
87 | } | |
e966361c | 88 | |
747f01eb IB |
89 | /* If the back end isn't clever enough to know that the lhs and rhs |
90 | types are the same, add an explicit conversion. */ | |
91 | if ((AGGREGATE_TYPE_P (TREE_TYPE (op0)) || AGGREGATE_TYPE_P (TREE_TYPE (op1))) | |
92 | && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) | |
93 | { | |
94 | TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, | |
95 | TREE_TYPE (op0), op1); | |
96 | return GS_OK; | |
97 | } | |
e966361c | 98 | |
747f01eb IB |
99 | return GS_UNHANDLED; |
100 | } | |
101 | ||
102 | /* Gimplify an ADDR_EXPR node. */ | |
103 | ||
104 | static gimplify_status | |
105 | d_gimplify_addr_expr (tree *expr_p) | |
106 | { | |
107 | tree op0 = TREE_OPERAND (*expr_p, 0); | |
108 | /* Constructors are not lvalues, so make them one. */ | |
109 | if (TREE_CODE (op0) == CONSTRUCTOR) | |
110 | { | |
111 | TREE_OPERAND (*expr_p, 0) = force_target_expr (op0); | |
112 | return GS_OK; | |
113 | } | |
114 | ||
115 | return GS_UNHANDLED; | |
116 | } | |
117 | ||
118 | /* Gimplify a CALL_EXPR node. */ | |
119 | ||
120 | static gimplify_status | |
121 | d_gimplify_call_expr (tree *expr_p, gimple_seq *pre_p) | |
122 | { | |
0fb57034 IB |
123 | /* Strictly evaluate all arguments from left to right. */ |
124 | int nargs = call_expr_nargs (*expr_p); | |
125 | location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location); | |
747f01eb | 126 | |
0fb57034 IB |
127 | /* No need to enforce evaluation order if only one argument. */ |
128 | if (nargs < 2) | |
129 | return GS_UNHANDLED; | |
747f01eb | 130 | |
0fb57034 IB |
131 | /* Or if all arguments are already free of side-effects. */ |
132 | bool has_side_effects = false; | |
133 | for (int i = 0; i < nargs; i++) | |
134 | { | |
135 | if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i))) | |
e966361c | 136 | { |
0fb57034 IB |
137 | has_side_effects = true; |
138 | break; | |
e966361c | 139 | } |
0fb57034 | 140 | } |
e966361c | 141 | |
0fb57034 IB |
142 | if (!has_side_effects) |
143 | return GS_UNHANDLED; | |
e966361c | 144 | |
0fb57034 IB |
145 | /* Leave the last argument for gimplify_call_expr. */ |
146 | for (int i = 0; i < nargs - 1; i++) | |
147 | { | |
148 | tree new_arg = CALL_EXPR_ARG (*expr_p, i); | |
e966361c | 149 | |
0fb57034 IB |
150 | /* If argument has a side-effect, gimplify_arg will handle it. */ |
151 | if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR) | |
152 | return GS_ERROR; | |
e966361c | 153 | |
0fb57034 IB |
154 | /* Even if an argument itself doesn't have any side-effects, it |
155 | might be altered by another argument in the list. */ | |
156 | if (new_arg == CALL_EXPR_ARG (*expr_p, i) | |
157 | && !really_constant_p (new_arg)) | |
158 | new_arg = get_formal_tmp_var (new_arg, pre_p); | |
e966361c | 159 | |
0fb57034 | 160 | CALL_EXPR_ARG (*expr_p, i) = new_arg; |
747f01eb | 161 | } |
e966361c | 162 | |
0fb57034 | 163 | return GS_OK; |
747f01eb | 164 | } |
e966361c | 165 | |
747f01eb | 166 | /* Gimplify an UNSIGNED_RSHIFT_EXPR node. */ |
e966361c | 167 | |
747f01eb IB |
168 | static gimplify_status |
169 | d_gimplify_unsigned_rshift_expr (tree *expr_p) | |
170 | { | |
171 | /* Convert op0 to an unsigned type. */ | |
172 | tree op0 = TREE_OPERAND (*expr_p, 0); | |
173 | tree op1 = TREE_OPERAND (*expr_p, 1); | |
174 | tree type = d_unsigned_type (TREE_TYPE (op0)); | |
175 | ||
176 | *expr_p = convert (TREE_TYPE (*expr_p), | |
177 | build2 (RSHIFT_EXPR, type, convert (type, op0), op1)); | |
178 | return GS_OK; | |
179 | } | |
e966361c | 180 | |
747f01eb IB |
181 | /* Implements the lang_hooks.gimplify_expr routine for language D. |
182 | Do gimplification of D specific expression trees in EXPR_P. */ | |
e966361c | 183 | |
747f01eb IB |
184 | int |
185 | d_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) | |
186 | { | |
187 | switch (TREE_CODE (*expr_p)) | |
188 | { | |
189 | case INIT_EXPR: | |
190 | case MODIFY_EXPR: | |
191 | return d_gimplify_modify_expr (expr_p, pre_p, post_p); | |
e966361c | 192 | |
747f01eb IB |
193 | case ADDR_EXPR: |
194 | return d_gimplify_addr_expr (expr_p); | |
e966361c | 195 | |
747f01eb IB |
196 | case CALL_EXPR: |
197 | return d_gimplify_call_expr (expr_p, pre_p); | |
198 | ||
199 | case UNSIGNED_RSHIFT_EXPR: | |
200 | return d_gimplify_unsigned_rshift_expr (expr_p); | |
e966361c IB |
201 | |
202 | case FLOAT_MOD_EXPR: | |
203 | gcc_unreachable (); | |
204 | ||
205 | default: | |
206 | break; | |
207 | } | |
208 | ||
747f01eb | 209 | return GS_UNHANDLED; |
e966361c | 210 | } |