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 ();
break;
}
- return ret;
+ return GS_UNHANDLED;
}