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