/* D-specific tree lowering bits; see also gimple.cc.
   Copyright (C) 2020-2023 Free Software Foundation, Inc.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"

#include "dmd/globals.h"

#include "tree.h"
#include "gimple-expr.h"
#include "gimplify.h"

#include "d-tree.h"


/* Return TRUE if an operand OP of a given TYPE being copied has no data.
   The middle-end does a similar check with zero sized types.  */

static bool
empty_modify_p (tree type, tree op)
{
  tree_code code = TREE_CODE (op);
  switch (code)
    {
    case COMPOUND_EXPR:
      return empty_modify_p (type, TREE_OPERAND (op, 1));

    case CONSTRUCTOR:
      /* Non-empty construcors are valid.  */
      if (CONSTRUCTOR_NELTS (op) != 0 || TREE_CLOBBER_P (op))
	return false;
      break;

    case CALL_EXPR:
      /* Leave nrvo alone because it isn't a copy.  */
      if (CALL_EXPR_RETURN_SLOT_OPT (op))
	return false;
      break;

    default:
      /* If the operand doesn't have a simple form.  */
      if (!is_gimple_lvalue (op) && !INDIRECT_REF_P (op))
	return false;
      break;
    }

  return empty_aggregate_p (type);
}

/* Return TRUE if EXPR is a COMPONENT_REF to a bit-field declaration.  */

static bool
bit_field_ref (const_tree expr)
{
  if (TREE_CODE (expr) == COMPONENT_REF
      && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
    return true;

  return false;
}

/* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR.  */

static gimplify_status
d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
{
  tree op0 = TREE_OPERAND (*expr_p, 0);
  tree op1 = TREE_OPERAND (*expr_p, 1);

  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))
    {
      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);

      *expr_p = TREE_OPERAND (*expr_p, 0);
      return GS_OK;
    }

  /* 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;
    }

  /* Same as above, but for bit-field assignments.  */
  if ((bit_field_ref (op0) || bit_field_ref (op1))
      && TREE_TYPE (op0) != TREE_TYPE (op1))
    {
      TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (op0), op1);
      return GS_OK;
    }

  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)
{
  /* 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++)
    {
      if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
	{
	  has_side_effects = true;
	  break;
	}
    }

  if (!has_side_effects)
    return GS_UNHANDLED;

  /* Evaluate the callee before calling it.  */
  tree new_call_fn = CALL_EXPR_FN (*expr_p);

  if (gimplify_expr (&new_call_fn, pre_p, NULL,
		     is_gimple_call_addr, fb_rvalue) == GS_ERROR)
    return GS_ERROR;

  CALL_EXPR_FN (*expr_p) = new_call_fn;

  /* 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);

      /* If argument has a side-effect, gimplify_arg will handle it.  */
      if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
	return GS_ERROR;

      /* 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);

      CALL_EXPR_ARG (*expr_p, i) = new_arg;
    }

  return GS_OK;
}

/* Gimplify an UNSIGNED_RSHIFT_EXPR node.  */

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;
}

/* Gimplify an unary expression node.  */

static gimplify_status
d_gimplify_unary_expr (tree *expr_p)
{
  tree op0 = TREE_OPERAND (*expr_p, 0);

  if (error_operand_p (op0))
    return GS_UNHANDLED;

  /* Front end doesn't know that bit-field types are really different
     from basic types, add an explicit conversion in unary expressions.  */
  if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (*expr_p))
    {
      TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
      return GS_OK;
    }

  return GS_UNHANDLED;
}

/* Gimplify a binary expression node.  */

static gimplify_status
d_gimplify_binary_expr (tree *expr_p)
{
  tree op0 = TREE_OPERAND (*expr_p, 0);
  tree op1 = TREE_OPERAND (*expr_p, 1);

  if (error_operand_p (op0) || error_operand_p (op1))
    return GS_UNHANDLED;

  /* Front end doesn't know that bit-field types are really different
     from basic types, add an explicit conversion in binary expressions.  */
  if (bit_field_ref (op0) || bit_field_ref (op1))
    {
      if (TREE_TYPE (op0) != TREE_TYPE (*expr_p))
	TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);

      if (TREE_TYPE (op1) != TREE_TYPE (*expr_p))
	TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (*expr_p), op1);

      return GS_OK;
    }

  return GS_UNHANDLED;
}

/* Implements the lang_hooks.gimplify_expr routine for language D.
   Do gimplification of D specific expression trees in EXPR_P.  */

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);

    case ADDR_EXPR:
      return d_gimplify_addr_expr (expr_p);

    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 ();

    default:
      if (UNARY_CLASS_P (*expr_p) && !CONVERT_EXPR_P (*expr_p))
	return d_gimplify_unary_expr (expr_p);
      if (BINARY_CLASS_P (*expr_p))
	return d_gimplify_binary_expr (expr_p);
      break;
    }

  return GS_UNHANDLED;
}
