Line data Source code
1 : /* Pretty print support for value ranges.
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by Aldy Hernandez <aldyh@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along 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 :
33 : static void
34 82416 : print_int_bound (pretty_printer *pp, const wide_int &bound, tree type)
35 : {
36 82416 : wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
37 82416 : wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
38 :
39 82416 : if (INTEGRAL_TYPE_P (type)
40 79732 : && !TYPE_UNSIGNED (type)
41 23684 : && bound == type_min
42 82801 : && TYPE_PRECISION (type) != 1)
43 385 : pp_string (pp, "-INF");
44 82031 : else if (bound == type_max && TYPE_PRECISION (type) != 1)
45 12435 : pp_string (pp, "+INF");
46 : else
47 69596 : pp_wide_int (pp, bound, TYPE_SIGN (type));
48 82416 : }
49 :
50 : static void
51 38421 : print_irange_bitmasks (pretty_printer *pp, const irange_bitmask &bm)
52 : {
53 38421 : if (bm.unknown_p ())
54 30770 : return;
55 :
56 7651 : pp_string (pp, " MASK ");
57 7651 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
58 7651 : unsigned len_mask, len_val;
59 15302 : if (print_hex_buf_size (bm.mask (), &len_mask)
60 7651 : | print_hex_buf_size (bm.value (), &len_val))
61 0 : p = XALLOCAVEC (char, MAX (len_mask, len_val));
62 : else
63 : p = buf;
64 7651 : print_hex (bm.mask (), p);
65 7651 : pp_string (pp, p);
66 7651 : pp_string (pp, " VALUE ");
67 7651 : print_hex (bm.value (), p);
68 7651 : pp_string (pp, p);
69 : }
70 :
71 : void
72 575 : vrange_printer::visit (const unsupported_range &r) const
73 : {
74 575 : pp_string (pp, "[unsupported_range] ");
75 575 : if (r.undefined_p ())
76 : {
77 0 : pp_string (pp, "UNDEFINED");
78 0 : return;
79 : }
80 575 : if (r.varying_p ())
81 : {
82 575 : pp_string (pp, "VARYING");
83 575 : return;
84 : }
85 0 : gcc_unreachable ();
86 : }
87 :
88 : void
89 38072 : vrange_printer::visit (const irange &r) const
90 : {
91 38072 : pp_string (pp, "[irange] ");
92 38072 : if (r.undefined_p ())
93 : {
94 16 : pp_string (pp, "UNDEFINED");
95 16 : return;
96 : }
97 38056 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
98 38056 : pp_character (pp, ' ');
99 38056 : if (r.varying_p ())
100 : {
101 977 : pp_string (pp, "VARYING");
102 977 : return;
103 : }
104 76945 : for (unsigned i = 0; i < r.num_pairs (); ++i)
105 : {
106 39866 : pp_character (pp, '[');
107 39866 : print_int_bound (pp, r.lower_bound (i), r.type ());
108 39866 : pp_string (pp, ", ");
109 39866 : print_int_bound (pp, r.upper_bound (i), r.type ());
110 39866 : pp_character (pp, ']');
111 : }
112 37079 : print_irange_bitmasks (pp, r.m_bitmask);
113 : }
114 :
115 : void
116 1450 : vrange_printer::visit (const prange &r) const
117 : {
118 1450 : pp_string (pp, "[prange] ");
119 1450 : if (r.undefined_p ())
120 : {
121 6 : pp_string (pp, "UNDEFINED");
122 6 : return;
123 : }
124 1444 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
125 1444 : pp_character (pp, ' ');
126 1444 : if (r.varying_p ())
127 : {
128 102 : pp_string (pp, "VARYING");
129 102 : return;
130 : }
131 :
132 1342 : pp_character (pp, '[');
133 1342 : print_int_bound (pp, r.lower_bound (), r.type ());
134 1342 : pp_string (pp, ", ");
135 1342 : print_int_bound (pp, r.upper_bound (), r.type ());
136 1342 : pp_character (pp, ']');
137 1342 : print_irange_bitmasks (pp, r.m_bitmask);
138 : }
139 :
140 : void
141 248 : vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
142 : {
143 248 : char s[100];
144 248 : real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
145 248 : pp_string (pp, s);
146 248 : if (!DECIMAL_FLOAT_TYPE_P (type)
147 : // real_to_hexadecimal prints infinities and NAN as text. No
148 : // need to print them twice.
149 248 : && !real_isinf (&r)
150 432 : && !real_isnan (&r))
151 : {
152 184 : real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
153 184 : pp_printf (pp, " (%s)", s);
154 : }
155 248 : }
156 :
157 : // Print an frange.
158 :
159 : void
160 199 : vrange_printer::visit (const frange &r) const
161 : {
162 199 : pp_string (pp, "[frange] ");
163 199 : if (r.undefined_p ())
164 : {
165 5 : pp_string (pp, "UNDEFINED");
166 5 : return;
167 : }
168 194 : tree type = r.type ();
169 194 : dump_generic_node (pp, type, 0, TDF_NONE, false);
170 194 : pp_string (pp, " ");
171 194 : if (r.varying_p ())
172 : {
173 67 : pp_string (pp, "VARYING");
174 67 : print_frange_nan (r);
175 67 : return;
176 : }
177 127 : pp_character (pp, '[');
178 127 : bool has_endpoints = !r.known_isnan ();
179 127 : if (has_endpoints)
180 : {
181 124 : print_real_value (type, r.lower_bound ());
182 124 : pp_string (pp, ", ");
183 124 : print_real_value (type, r.upper_bound ());
184 : }
185 127 : pp_character (pp, ']');
186 127 : print_frange_nan (r);
187 : }
188 :
189 : // Print the NAN info for an frange.
190 :
191 : void
192 194 : vrange_printer::print_frange_nan (const frange &r) const
193 : {
194 321 : if (r.maybe_isnan ())
195 : {
196 67 : if (r.m_pos_nan && r.m_neg_nan)
197 : {
198 54 : pp_string (pp, " +-NAN");
199 54 : return;
200 : }
201 13 : bool nan_sign = r.m_neg_nan;
202 13 : if (nan_sign)
203 0 : pp_string (pp, " -NAN");
204 : else
205 13 : pp_string (pp, " +NAN");
206 : }
207 : }
|