1/* Pretty print support for value ranges.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "backend.h"
25#include "tree.h"
26#include "gimple.h"
27#include "ssa.h"
28#include "tree-pretty-print.h"
29#include "fold-const.h"
30#include "gimple-range.h"
31#include "value-range-pretty-print.h"
32
33void
34vrange_printer::visit (const unsupported_range &r) const
35{
36 pp_string (pp, "[unsupported_range] ");
37 if (r.undefined_p ())
38 {
39 pp_string (pp, "UNDEFINED");
40 return;
41 }
42 if (r.varying_p ())
43 {
44 pp_string (pp, "VARYING");
45 return;
46 }
47 gcc_unreachable ();
48}
49
50void
51vrange_printer::visit (const irange &r) const
52{
53 pp_string (pp, "[irange] ");
54 if (r.undefined_p ())
55 {
56 pp_string (pp, "UNDEFINED");
57 return;
58 }
59 dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
60 pp_character (pp, ' ');
61 if (r.varying_p ())
62 {
63 pp_string (pp, "VARYING");
64 return;
65 }
66 for (unsigned i = 0; i < r.num_pairs (); ++i)
67 {
68 pp_character (pp, '[');
69 print_irange_bound (w: r.lower_bound (pair: i), type: r.type ());
70 pp_string (pp, ", ");
71 print_irange_bound (w: r.upper_bound (pair: i), type: r.type ());
72 pp_character (pp, ']');
73 }
74 print_irange_bitmasks (r);
75}
76
77void
78vrange_printer::print_irange_bound (const wide_int &bound, tree type) const
79{
80 wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
81 wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
82
83 if (INTEGRAL_TYPE_P (type)
84 && !TYPE_UNSIGNED (type)
85 && bound == type_min
86 && TYPE_PRECISION (type) != 1)
87 pp_string (pp, "-INF");
88 else if (bound == type_max && TYPE_PRECISION (type) != 1)
89 pp_string (pp, "+INF");
90 else
91 pp_wide_int (pp, w: bound, TYPE_SIGN (type));
92}
93
94void
95vrange_printer::print_irange_bitmasks (const irange &r) const
96{
97 irange_bitmask bm = r.m_bitmask;
98 if (bm.unknown_p ())
99 return;
100
101 pp_string (pp, " MASK ");
102 char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
103 unsigned len_mask, len_val;
104 if (print_hex_buf_size (wi: bm.mask (), len: &len_mask)
105 | print_hex_buf_size (wi: bm.value (), len: &len_val))
106 p = XALLOCAVEC (char, MAX (len_mask, len_val));
107 else
108 p = buf;
109 print_hex (wi: bm.mask (), buf: p);
110 pp_string (pp, p);
111 pp_string (pp, " VALUE ");
112 print_hex (wi: bm.value (), buf: p);
113 pp_string (pp, p);
114}
115
116void
117vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
118{
119 char s[100];
120 real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
121 pp_string (pp, s);
122 if (!DECIMAL_FLOAT_TYPE_P (type)
123 // real_to_hexadecimal prints infinities and NAN as text. No
124 // need to print them twice.
125 && !real_isinf (&r)
126 && !real_isnan (&r))
127 {
128 real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
129 pp_printf (pp, " (%s)", s);
130 }
131}
132
133// Print an frange.
134
135void
136vrange_printer::visit (const frange &r) const
137{
138 pp_string (pp, "[frange] ");
139 if (r.undefined_p ())
140 {
141 pp_string (pp, "UNDEFINED");
142 return;
143 }
144 tree type = r.type ();
145 dump_generic_node (pp, type, 0, TDF_NONE, false);
146 pp_string (pp, " ");
147 if (r.varying_p ())
148 {
149 pp_string (pp, "VARYING");
150 print_frange_nan (r);
151 return;
152 }
153 pp_character (pp, '[');
154 bool has_endpoints = !r.known_isnan ();
155 if (has_endpoints)
156 {
157 print_real_value (type, r: r.lower_bound ());
158 pp_string (pp, ", ");
159 print_real_value (type, r: r.upper_bound ());
160 }
161 pp_character (pp, ']');
162 print_frange_nan (r);
163}
164
165// Print the NAN info for an frange.
166
167void
168vrange_printer::print_frange_nan (const frange &r) const
169{
170 if (r.maybe_isnan ())
171 {
172 if (r.m_pos_nan && r.m_neg_nan)
173 {
174 pp_string (pp, " +-NAN");
175 return;
176 }
177 bool nan_sign = r.m_neg_nan;
178 if (nan_sign)
179 pp_string (pp, " -NAN");
180 else
181 pp_string (pp, " +NAN");
182 }
183}
184

source code of gcc/value-range-pretty-print.cc