Home | History | Annotate | Line # | Download | only in d
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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