/* Pretty print support for value ranges.
   Copyright (C) 2019-2022 Free Software Foundation, Inc.
   Contributed by Aldy Hernandez <aldyh@redhat.com>.

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

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "tree-pretty-print.h"
#include "fold-const.h"
#include "gimple-range.h"
#include "value-range-pretty-print.h"

void
vrange_printer::visit (const unsupported_range &r) const
{
  pp_string (pp, "[unsupported_range] ");
  if (r.undefined_p ())
    {
      pp_string (pp, "UNDEFINED");
      return;
    }
  if (r.varying_p ())
    {
      pp_string (pp, "VARYING");
      return;
    }
  gcc_unreachable ();
}

void
vrange_printer::visit (const irange &r) const
{
  pp_string (pp, "[irange] ");
  if (r.undefined_p ())
    {
      pp_string (pp, "UNDEFINED");
      return;
    }
  dump_generic_node (pp, r.type (), 0, TDF_NONE, false);
  pp_character (pp, ' ');
  if (r.varying_p ())
    {
      pp_string (pp, "VARYING");
      return;
    }
  // Handle legacy symbolics.
  if (!r.constant_p ())
    {
      if (r.kind () == VR_ANTI_RANGE)
	pp_character (pp, '~');
      pp_character (pp, '[');
      dump_generic_node (pp, r.min (), 0, TDF_NONE, false);
      pp_string (pp, ", ");
      dump_generic_node (pp, r.max (), 0, TDF_NONE, false);
      pp_character (pp, ']');
      print_irange_bitmasks (r);
      return;
    }
  for (unsigned i = 0; i < r.num_pairs (); ++i)
    {
      pp_character (pp, '[');
      print_irange_bound (r.lower_bound (i), r.type ());
      pp_string (pp, ", ");
      print_irange_bound (r.upper_bound (i), r.type ());
      pp_character (pp, ']');
    }
 print_irange_bitmasks (r);
}

void
vrange_printer::print_irange_bound (const wide_int &bound, tree type) const
{
  wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
  wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));

  if (INTEGRAL_TYPE_P (type)
      && !TYPE_UNSIGNED (type)
      && bound == type_min
      && TYPE_PRECISION (type) != 1)
    pp_string (pp, "-INF");
  else if (bound == type_max && TYPE_PRECISION (type) != 1)
    pp_string (pp, "+INF");
  else
    pp_wide_int (pp, bound, TYPE_SIGN (type));
}

void
vrange_printer::print_irange_bitmasks (const irange &r) const
{
  wide_int nz = r.get_nonzero_bits ();
  if (nz == -1)
    return;

  pp_string (pp, " NONZERO ");
  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
  print_hex (nz, buf);
  pp_string (pp, buf);
}

void
vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
{
  char s[100];
  real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
  pp_string (pp, s);
  if (!DECIMAL_FLOAT_TYPE_P (type)
      // real_to_hexadecimal prints infinities and NAN as text.  No
      // need to print them twice.
      && !real_isinf (&r)
      && !real_isnan (&r))
    {
      real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
      pp_printf (pp, " (%s)", s);
    }
}

// Print an frange.

void
vrange_printer::visit (const frange &r) const
{
  pp_string (pp, "[frange] ");
  if (r.undefined_p ())
    {
      pp_string (pp, "UNDEFINED");
      return;
    }
  tree type = r.type ();
  dump_generic_node (pp, type, 0, TDF_NONE, false);
  pp_string (pp, " ");
  if (r.varying_p ())
    {
      pp_string (pp, "VARYING");
      print_frange_nan (r);
      return;
    }
  pp_character (pp, '[');
  bool has_endpoints = !r.known_isnan ();
  if (has_endpoints)
    {
      print_real_value (type, r.lower_bound ());
      pp_string (pp, ", ");
      print_real_value (type, r.upper_bound ());
    }
  pp_character (pp, ']');
  print_frange_nan (r);
}

// Print the NAN info for an frange.

void
vrange_printer::print_frange_nan (const frange &r) const
{
  if (r.maybe_isnan ())
    {
      if (r.m_pos_nan && r.m_neg_nan)
	{
	  pp_string (pp, " +-NAN");
	  return;
	}
      bool nan_sign = r.m_neg_nan;
      if (nan_sign)
	pp_string (pp, " -NAN");
      else
	pp_string (pp, " +NAN");
    }
}
