/* Translation of constants
   Copyright (C) 2002-2022 Free Software Foundation, Inc.
   Contributed by Paul Brook

This file is part of GCC.

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/>.  */

/* trans-const.cc -- convert constant values */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "gfortran.h"
#include "options.h"
#include "trans.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "realmpfr.h"
#include "trans-const.h"
#include "trans-types.h"
#include "target-memory.h"

tree gfc_rank_cst[GFC_MAX_DIMENSIONS + 1];

/* Build a constant with given type from an int_cst.  */

tree
gfc_build_const (tree type, tree intval)
{
  tree val;
  tree zero;

  switch (TREE_CODE (type))
    {
    case INTEGER_TYPE:
      val = convert (type, intval);
      break;

    case REAL_TYPE:
      val = build_real_from_int_cst (type, intval);
      break;

    case COMPLEX_TYPE:
      val = build_real_from_int_cst (TREE_TYPE (type), intval);
      zero = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
      val = build_complex (type, val, zero);
      break;

    default:
      gcc_unreachable ();
    }
  return val;
}

/* Build a string constant with C char type.  */

tree
gfc_build_string_const (size_t length, const char *s)
{
  tree str;
  tree len;

  str = build_string (length, s);
  len = size_int (length);
  TREE_TYPE (str) =
    build_array_type (gfc_character1_type_node,
		      build_range_type (gfc_charlen_type_node,
					size_one_node, len));
  TYPE_STRING_FLAG (TREE_TYPE (str)) = 1;
  return str;
}


/* Build a string constant with a type given by its kind; take care of
   non-default character kinds.  */

tree
gfc_build_wide_string_const (int kind, size_t length, const gfc_char_t *string)
{
  int i;
  tree str, len;
  size_t size;
  char *s;

  i = gfc_validate_kind (BT_CHARACTER, kind, false);
  size = length * gfc_character_kinds[i].bit_size / 8;

  s = XCNEWVAR (char, size);
  gfc_encode_character (kind, length, string, (unsigned char *) s, size);

  str = build_string (size, s);
  free (s);

  len = size_int (length);
  TREE_TYPE (str) =
    build_array_type (gfc_get_char_type (kind),
		      build_range_type (gfc_charlen_type_node,
					size_one_node, len));
  TYPE_STRING_FLAG (TREE_TYPE (str)) = 1;
  return str;
}


/* Build a Fortran character constant from a zero-terminated string.
   There a two version of this function, one that translates the string
   and one that doesn't.  */
tree
gfc_build_cstring_const (const char *string)
{
  return gfc_build_string_const (strlen (string) + 1, string);
}

tree
gfc_build_localized_cstring_const (const char *msgid)
{
  const char *localized = _(msgid);
  return gfc_build_string_const (strlen (localized) + 1, localized);
}


/* Return a string constant with the given length.  Used for static
   initializers.  The constant will be padded or truncated to match
   length.  */

tree
gfc_conv_string_init (tree length, gfc_expr * expr)
{
  gfc_char_t *s;
  HOST_WIDE_INT len;
  gfc_charlen_t slen;
  tree str;
  bool free_s = false;

  gcc_assert (expr->expr_type == EXPR_CONSTANT);
  gcc_assert (expr->ts.type == BT_CHARACTER);
  gcc_assert (tree_fits_uhwi_p (length));

  len = TREE_INT_CST_LOW (length);
  slen = expr->value.character.length;

  if (len > slen)
    {
      s = gfc_get_wide_string (len);
      memcpy (s, expr->value.character.string, slen * sizeof (gfc_char_t));
      gfc_wide_memset (&s[slen], ' ', len - slen);
      free_s = true;
    }
  else
    s = expr->value.character.string;

  str = gfc_build_wide_string_const (expr->ts.kind, len, s);

  if (free_s)
    free (s);

  return str;
}


/* Create a tree node for the string length if it is constant.  */

void
gfc_conv_const_charlen (gfc_charlen * cl)
{
  if (!cl || cl->backend_decl)
    return;

  if (cl->length && cl->length->expr_type == EXPR_CONSTANT)
    {
      cl->backend_decl = gfc_conv_mpz_to_tree (cl->length->value.integer,
					       cl->length->ts.kind);
      cl->backend_decl = fold_convert (gfc_charlen_type_node,
					cl->backend_decl);
    }
}

void
gfc_init_constants (void)
{
  int n;

  for (n = 0; n <= GFC_MAX_DIMENSIONS; n++)
    gfc_rank_cst[n] = build_int_cst (gfc_array_index_type, n);
}

/* Converts a GMP integer into a backend tree node.  */

tree
gfc_conv_mpz_to_tree (mpz_t i, int kind)
{
  wide_int val = wi::from_mpz (gfc_get_int_type (kind), i, true);
  return wide_int_to_tree (gfc_get_int_type (kind), val);
}


/* Convert a GMP integer into a tree node of type given by the type
   argument.  */

tree
gfc_conv_mpz_to_tree_type (mpz_t i, const tree type)
{
  const wide_int val = wi::from_mpz (type, i, true);
  return wide_int_to_tree (type, val);
}


/* Converts a backend tree into a GMP integer.  */

void
gfc_conv_tree_to_mpz (mpz_t i, tree source)
{
  wi::to_mpz (wi::to_wide (source), i, TYPE_SIGN (TREE_TYPE (source)));
}

/* Converts a real constant into backend form.  */

tree
gfc_conv_mpfr_to_tree (mpfr_t f, int kind, int is_snan)
{
  tree type;
  int n;
  REAL_VALUE_TYPE real;

  n = gfc_validate_kind (BT_REAL, kind, false);
  gcc_assert (gfc_real_kinds[n].radix == 2);

  type = gfc_get_real_type (kind);
  if (mpfr_nan_p (f) && is_snan)
     real_from_string (&real, "SNaN");
  else
    real_from_mpfr (&real, f, type, GFC_RND_MODE);

  return build_real (type, real);
}

/* Returns a real constant that is +Infinity if the target
   supports infinities for this floating-point mode, and
   +HUGE_VAL otherwise (the largest representable number).  */

tree
gfc_build_inf_or_huge (tree type, int kind)
{
  if (HONOR_INFINITIES (TYPE_MODE (type)))
    {
      REAL_VALUE_TYPE real;
      real_inf (&real);
      return build_real (type, real);
    }
  else
    {
      int k = gfc_validate_kind (BT_REAL, kind, false);
      return gfc_conv_mpfr_to_tree (gfc_real_kinds[k].huge, kind, 0);
    }
}

/* Returns a floating-point NaN of a given type.  */

tree
gfc_build_nan (tree type, const char *str)
{
  REAL_VALUE_TYPE real;
  real_nan (&real, str, 1, TYPE_MODE (type));
  return build_real (type, real);
}

/* Converts a backend tree into a real constant.  */

void
gfc_conv_tree_to_mpfr (mpfr_ptr f, tree source)
{
  mpfr_from_real (f, TREE_REAL_CST_PTR (source), GFC_RND_MODE);
}

/* Translate any literal constant to a tree.  Constants never have
   pre or post chains.  Character literal constants are special
   special because they have a value and a length, so they cannot be
   returned as a single tree.  It is up to the caller to set the
   length somewhere if necessary.

   Returns the translated constant, or aborts if it gets a type it
   can't handle.  */

tree
gfc_conv_constant_to_tree (gfc_expr * expr)
{
  tree res;

  gcc_assert (expr->expr_type == EXPR_CONSTANT);

  /* If it is has a prescribed memory representation, we build a string
     constant and VIEW_CONVERT to its type.  */

  switch (expr->ts.type)
    {
    case BT_INTEGER:
      if (expr->representation.string)
	return fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
			 gfc_get_int_type (expr->ts.kind),
			 gfc_build_string_const (expr->representation.length,
						 expr->representation.string));
      else
	return gfc_conv_mpz_to_tree (expr->value.integer, expr->ts.kind);

    case BT_REAL:
      if (expr->representation.string)
	return fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
			 gfc_get_real_type (expr->ts.kind),
			 gfc_build_string_const (expr->representation.length,
						 expr->representation.string));
      else
	return gfc_conv_mpfr_to_tree (expr->value.real, expr->ts.kind, expr->is_snan);

    case BT_LOGICAL:
      if (expr->representation.string)
	{
	  tree tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
			gfc_get_int_type (expr->ts.kind),
			gfc_build_string_const (expr->representation.length,
						expr->representation.string));
	  if (!integer_zerop (tmp) && !integer_onep (tmp))
	    gfc_warning (flag_dec_char_conversions ? OPT_Wsurprising : 0,
			 "Assigning value other than 0 or 1 to LOGICAL has "
			 "undefined result at %L", &expr->where);
	  return fold_convert (gfc_get_logical_type (expr->ts.kind), tmp);
	}
      else
	return build_int_cst (gfc_get_logical_type (expr->ts.kind),
			      expr->value.logical);

    case BT_COMPLEX:
      if (expr->representation.string)
	return fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
			 gfc_get_complex_type (expr->ts.kind),
			 gfc_build_string_const (expr->representation.length,
						 expr->representation.string));
      else
	{
	  tree real = gfc_conv_mpfr_to_tree (mpc_realref (expr->value.complex),
					  expr->ts.kind, expr->is_snan);
	  tree imag = gfc_conv_mpfr_to_tree (mpc_imagref (expr->value.complex),
					  expr->ts.kind, expr->is_snan);

	  return build_complex (gfc_typenode_for_spec (&expr->ts),
				real, imag);
	}

    case BT_CHARACTER:
      res = gfc_build_wide_string_const (expr->ts.kind,
					 expr->value.character.length,
					 expr->value.character.string);
      return res;

    case BT_HOLLERITH:
      return gfc_build_string_const (expr->representation.length,
				     expr->representation.string);

    default:
      gcc_unreachable ();
    }
}


/* Like gfc_conv_constant_to_tree, but for a simplified expression.
   We can handle character literal constants here as well.  */

void
gfc_conv_constant (gfc_se * se, gfc_expr * expr)
{
  gfc_ss *ss;

  /* We may be receiving an expression for C_NULL_PTR or C_NULL_FUNPTR.  If
     so, the expr_type will not yet be an EXPR_CONSTANT.  We need to make
     it so here.  */
  if (expr->ts.type == BT_DERIVED && expr->ts.u.derived
      && expr->ts.u.derived->attr.is_iso_c)
    {
      if (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR
	  || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_FUNPTR)
	{
	  /* Create a new EXPR_CONSTANT expression for our local uses.  */
	  expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
	}
    }

  if (expr->expr_type != EXPR_CONSTANT)
    {
      gfc_expr *e = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
      gfc_error ("non-constant initialization expression at %L", &expr->where);
      se->expr = gfc_conv_constant_to_tree (e);
      return;
    }

  ss = se->ss;
  if (ss != NULL)
    {
      gfc_ss_info *ss_info;

      ss_info = ss->info;
      gcc_assert (ss != gfc_ss_terminator);
      gcc_assert (ss_info->type == GFC_SS_SCALAR);
      gcc_assert (ss_info->expr == expr);

      se->expr = ss_info->data.scalar.value;
      se->string_length = ss_info->string_length;
      gfc_advance_se_ss_chain (se);
      return;
    }

  /* Translate the constant and put it in the simplifier structure.  */
  se->expr = gfc_conv_constant_to_tree (expr);

  /* If this is a CHARACTER string, set its length in the simplifier
     structure, too.  */
  if (expr->ts.type == BT_CHARACTER)
    se->string_length = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (se->expr)));
}
