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 82462 : print_int_bound (pretty_printer *pp, const wide_int &bound, tree type)
35 : {
36 82462 : wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
37 82462 : wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
38 :
39 82462 : if (INTEGRAL_TYPE_P (type)
40 79780 : && !TYPE_UNSIGNED (type)
41 23702 : && bound == type_min
42 82847 : && TYPE_PRECISION (type) != 1)
43 385 : pp_string (pp, "-INF");
44 82077 : else if (bound == type_max && TYPE_PRECISION (type) != 1)
45 12436 : pp_string (pp, "+INF");
46 : else
47 69641 : pp_wide_int (pp, bound, TYPE_SIGN (type));
48 82462 : }
49 :
50 : static void
51 38414 : print_irange_bitmasks (pretty_printer *pp, const irange_bitmask &bm)
52 : {
53 38414 : if (bm.unknown_p ())
54 30754 : return;
55 :
56 7660 : pp_string (pp, " MASK ");
57 7660 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
58 7660 : unsigned len_mask, len_val;
59 15320 : if (print_hex_buf_size (bm.mask (), &len_mask)
60 7660 : | print_hex_buf_size (bm.value (), &len_val))
61 0 : p = XALLOCAVEC (char, MAX (len_mask, len_val));
62 : else
63 : p = buf;
64 7660 : print_hex (bm.mask (), p);
65 7660 : pp_string (pp, p);
66 7660 : pp_string (pp, " VALUE ");
67 7660 : print_hex (bm.value (), p);
68 7660 : 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 38066 : vrange_printer::visit (const irange &r) const
90 : {
91 38066 : pp_string (pp, "[irange] ");
92 38066 : if (r.undefined_p ())
93 : {
94 16 : pp_string (pp, "UNDEFINED");
95 16 : return;
96 : }
97 38050 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
98 38050 : pp_character (pp, ' ');
99 38050 : if (r.varying_p ())
100 : {
101 977 : pp_string (pp, "VARYING");
102 977 : return;
103 : }
104 76963 : for (unsigned i = 0; i < r.num_pairs (); ++i)
105 : {
106 39890 : pp_character (pp, '[');
107 39890 : print_int_bound (pp, r.lower_bound (i), r.type ());
108 39890 : pp_string (pp, ", ");
109 39890 : print_int_bound (pp, r.upper_bound (i), r.type ());
110 39890 : pp_character (pp, ']');
111 : }
112 37073 : print_irange_bitmasks (pp, r.m_bitmask);
113 : }
114 :
115 : void
116 1449 : vrange_printer::visit (const prange &r) const
117 : {
118 1449 : pp_string (pp, "[prange] ");
119 1449 : if (r.undefined_p ())
120 : {
121 6 : pp_string (pp, "UNDEFINED");
122 6 : return;
123 : }
124 1443 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
125 1443 : pp_character (pp, ' ');
126 1443 : if (r.varying_p ())
127 : {
128 102 : pp_string (pp, "VARYING");
129 102 : return;
130 : }
131 :
132 1341 : pp_character (pp, '[');
133 1341 : print_int_bound (pp, r.lower_bound (), r.type ());
134 1341 : pp_string (pp, ", ");
135 1341 : print_int_bound (pp, r.upper_bound (), r.type ());
136 1341 : pp_character (pp, ']');
137 1341 : print_irange_bitmasks (pp, r.m_bitmask);
138 : }
139 :
140 : void
141 746 : vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
142 : {
143 746 : char s[100];
144 746 : real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
145 746 : pp_string (pp, s);
146 746 : if (!DECIMAL_FLOAT_TYPE_P (type)
147 : // real_to_hexadecimal prints infinities and NAN as text. No
148 : // need to print them twice.
149 746 : && !real_isinf (&r)
150 1179 : && !real_isnan (&r))
151 : {
152 433 : real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
153 433 : pp_printf (pp, " (%s)", s);
154 : }
155 746 : }
156 :
157 : // Print an frange.
158 :
159 : void
160 448 : vrange_printer::visit (const frange &r) const
161 : {
162 448 : pp_string (pp, "[frange] ");
163 448 : if (r.undefined_p ())
164 : {
165 5 : pp_string (pp, "UNDEFINED");
166 5 : return;
167 : }
168 443 : tree type = r.type ();
169 443 : dump_generic_node (pp, type, 0, TDF_NONE, false);
170 443 : pp_string (pp, " ");
171 443 : if (r.varying_p ())
172 : {
173 67 : pp_string (pp, "VARYING");
174 67 : print_frange_nan (r);
175 67 : return;
176 : }
177 376 : pp_character (pp, '[');
178 376 : bool has_endpoints = !r.known_isnan ();
179 376 : if (has_endpoints)
180 : {
181 373 : print_real_value (type, r.lower_bound ());
182 373 : pp_string (pp, ", ");
183 373 : print_real_value (type, r.upper_bound ());
184 : }
185 376 : pp_character (pp, ']');
186 376 : print_frange_nan (r);
187 : }
188 :
189 : // Print the NAN info for an frange.
190 :
191 : void
192 443 : vrange_printer::print_frange_nan (const frange &r) const
193 : {
194 570 : if (r.maybe_isnan ())
195 : {
196 316 : if (r.m_pos_nan && r.m_neg_nan)
197 : {
198 150 : pp_string (pp, " +-NAN");
199 150 : return;
200 : }
201 166 : bool nan_sign = r.m_neg_nan;
202 166 : if (nan_sign)
203 0 : pp_string (pp, " -NAN");
204 : else
205 166 : pp_string (pp, " +NAN");
206 : }
207 : }
|