d: Move lowering of each tree node to separate functions
authorIain Buclaw <ibuclaw@gdcproject.org>
Fri, 21 Aug 2020 10:24:20 +0000 (12:24 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Wed, 26 Aug 2020 08:03:54 +0000 (10:03 +0200)
gcc/d/ChangeLog:

* d-gimplify.cc (d_gimplify_expr): Move lowering of each tree node to
separate functions.
(d_gimplify_modify_expr): New function.
(d_gimplify_addr_expr): New function.
(d_gimplify_call_expr): New function.
(d_gimplify_unsigned_rshift_expr): New function.

gcc/d/d-gimplify.cc

index ed49e5f8dc4b56ce305d10014eb62930106fe8ae..569e82917f847f16a0865d5c26c8101c1a7ed0f3 100644 (file)
@@ -62,119 +62,147 @@ empty_modify_p (tree type, tree op)
   return empty_aggregate_p (type);
 }
 
-/* Implements the lang_hooks.gimplify_expr routine for language D.
-   Do gimplification of D specific expression trees in EXPR_P.  */
+/* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR.  */
 
-int
-d_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
-                gimple_seq *post_p ATTRIBUTE_UNUSED)
+static gimplify_status
+d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 {
-  tree_code code = TREE_CODE (*expr_p);
-  enum gimplify_status ret = GS_UNHANDLED;
-  tree op0, op1;
-  tree type;
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+  tree op1 = TREE_OPERAND (*expr_p, 1);
 
-  switch (code)
+  if (error_operand_p (op0) || error_operand_p (op1))
+    return GS_UNHANDLED;
+
+  /* Remove any copies of empty aggregates.  */
+  if (empty_modify_p (TREE_TYPE (op0), op1))
     {
-    case INIT_EXPR:
-    case MODIFY_EXPR:
-      op0 = TREE_OPERAND (*expr_p, 0);
-      op1 = TREE_OPERAND (*expr_p, 1);
+      gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                    is_gimple_lvalue, fb_lvalue);
 
-      if (!error_operand_p (op0) && !error_operand_p (op1)
-         && (AGGREGATE_TYPE_P (TREE_TYPE (op0))
-             || AGGREGATE_TYPE_P (TREE_TYPE (op1)))
-         && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
-       {
-         /* If the back end isn't clever enough to know that the lhs and rhs
-            types are the same, add an explicit conversion.  */
-         TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
-                                             TREE_TYPE (op0), op1);
-         ret = GS_OK;
-       }
-      else if (empty_modify_p (TREE_TYPE (op0), op1))
-       {
-         /* Remove any copies of empty aggregates.  */
-         gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                        is_gimple_lvalue, fb_lvalue);
+      if (TREE_SIDE_EFFECTS (op1))
+       gimplify_and_add (op1, pre_p);
 
-         if (TREE_SIDE_EFFECTS (op1))
-           gimplify_and_add (op1, pre_p);
+      *expr_p = TREE_OPERAND (*expr_p, 0);
+      return GS_OK;
+    }
 
-         *expr_p = TREE_OPERAND (*expr_p, 0);
-         ret = GS_OK;
-       }
-      break;
+  /* If the back end isn't clever enough to know that the lhs and rhs
+     types are the same, add an explicit conversion.  */
+  if ((AGGREGATE_TYPE_P (TREE_TYPE (op0)) || AGGREGATE_TYPE_P (TREE_TYPE (op1)))
+      && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
+    {
+      TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
+                                         TREE_TYPE (op0), op1);
+      return GS_OK;
+    }
 
-    case ADDR_EXPR:
-      op0 = TREE_OPERAND (*expr_p, 0);
-      /* Constructors are not lvalues, so make them one.  */
-      if (TREE_CODE (op0) == CONSTRUCTOR)
+  return GS_UNHANDLED;
+}
+
+/* Gimplify an ADDR_EXPR node.  */
+
+static gimplify_status
+d_gimplify_addr_expr (tree *expr_p)
+{
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+  /* Constructors are not lvalues, so make them one.  */
+  if (TREE_CODE (op0) == CONSTRUCTOR)
+    {
+      TREE_OPERAND (*expr_p, 0) = force_target_expr (op0);
+      return GS_OK;
+    }
+
+  return GS_UNHANDLED;
+}
+
+/* Gimplify a CALL_EXPR node.  */
+
+static gimplify_status
+d_gimplify_call_expr (tree *expr_p, gimple_seq *pre_p)
+{
+  if (CALL_EXPR_ARGS_ORDERED (*expr_p))
+    {
+      /* Strictly evaluate all arguments from left to right.  */
+      int nargs = call_expr_nargs (*expr_p);
+      location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
+
+      /* No need to enforce evaluation order if only one argument.  */
+      if (nargs < 2)
+       return GS_UNHANDLED;
+
+      /* Or if all arguments are already free of side-effects.  */
+      bool has_side_effects = false;
+      for (int i = 0; i < nargs; i++)
        {
-         TREE_OPERAND (*expr_p, 0) = force_target_expr (op0);
-         ret = GS_OK;
+         if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
+           {
+             has_side_effects = true;
+             break;
+           }
        }
-      break;
 
-    case CALL_EXPR:
-      if (CALL_EXPR_ARGS_ORDERED (*expr_p))
+      if (!has_side_effects)
+       return GS_UNHANDLED;
+
+      /* Leave the last argument for gimplify_call_expr.  */
+      for (int i = 0; i < nargs - 1; i++)
        {
-         /* Strictly evaluate all arguments from left to right.  */
-         int nargs = call_expr_nargs (*expr_p);
-         location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
+         tree new_arg = CALL_EXPR_ARG (*expr_p, i);
 
-         /* No need to enforce evaluation order if only one argument.  */
-         if (nargs < 2)
-           break;
+         /* If argument has a side-effect, gimplify_arg will handle it.  */
+         if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
+           return GS_ERROR;
 
-         /* Or if all arguments are already free of side-effects.  */
-         bool has_side_effects = false;
-         for (int i = 0; i < nargs; i++)
-           {
-             if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
-               {
-                 has_side_effects = true;
-                 break;
-               }
-           }
+         /* Even if an argument itself doesn't have any side-effects, it
+            might be altered by another argument in the list.  */
+         if (new_arg == CALL_EXPR_ARG (*expr_p, i)
+             && !really_constant_p (new_arg))
+           new_arg = get_formal_tmp_var (new_arg, pre_p);
 
-         if (!has_side_effects)
-           break;
+         CALL_EXPR_ARG (*expr_p, i) = new_arg;
+       }
 
-         /* Leave the last argument for gimplify_call_expr.  */
-         for (int i = 0; i < nargs - 1; i++)
-           {
-             tree new_arg = CALL_EXPR_ARG (*expr_p, i);
+      return GS_OK;
+    }
 
-             /* If argument has a side-effect, gimplify_arg will handle it.  */
-             if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
-               ret = GS_ERROR;
+  return GS_UNHANDLED;
+}
 
-             /* Even if an argument itself doesn't have any side-effects, it
-                might be altered by another argument in the list.  */
-             if (new_arg == CALL_EXPR_ARG (*expr_p, i)
-                 && !really_constant_p (new_arg))
-               new_arg = get_formal_tmp_var (new_arg, pre_p);
+/* Gimplify an UNSIGNED_RSHIFT_EXPR node.  */
 
-             CALL_EXPR_ARG (*expr_p, i) = new_arg;
-           }
+static gimplify_status
+d_gimplify_unsigned_rshift_expr (tree *expr_p)
+{
+  /* Convert op0 to an unsigned type.  */
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+  tree op1 = TREE_OPERAND (*expr_p, 1);
+  tree type = d_unsigned_type (TREE_TYPE (op0));
+
+  *expr_p = convert (TREE_TYPE (*expr_p),
+                    build2 (RSHIFT_EXPR, type, convert (type, op0), op1));
+  return GS_OK;
+}
 
-         if (ret != GS_ERROR)
-           ret = GS_OK;
-       }
-      break;
+/* Implements the lang_hooks.gimplify_expr routine for language D.
+   Do gimplification of D specific expression trees in EXPR_P.  */
 
-    case UNSIGNED_RSHIFT_EXPR:
-      /* Convert op0 to an unsigned type.  */
-      op0 = TREE_OPERAND (*expr_p, 0);
-      op1 = TREE_OPERAND (*expr_p, 1);
+int
+d_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
+{
+  switch (TREE_CODE (*expr_p))
+    {
+    case INIT_EXPR:
+    case MODIFY_EXPR:
+      return d_gimplify_modify_expr (expr_p, pre_p, post_p);
 
-      type = d_unsigned_type (TREE_TYPE (op0));
+    case ADDR_EXPR:
+      return d_gimplify_addr_expr (expr_p);
 
-      *expr_p = convert (TREE_TYPE (*expr_p),
-                        build2 (RSHIFT_EXPR, type, convert (type, op0), op1));
-      ret = GS_OK;
-      break;
+    case CALL_EXPR:
+      return d_gimplify_call_expr (expr_p, pre_p);
+
+    case UNSIGNED_RSHIFT_EXPR:
+      return d_gimplify_unsigned_rshift_expr (expr_p);
 
     case FLOAT_MOD_EXPR:
       gcc_unreachable ();
@@ -183,5 +211,5 @@ d_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
       break;
     }
 
-  return ret;
+  return GS_UNHANDLED;
 }