Branch data Line data Source code
1 : : /* Pretty print support for value ranges.
2 : : Copyright (C) 2019-2025 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 : 19830 : print_int_bound (pretty_printer *pp, const wide_int &bound, tree type)
35 : : {
36 : 19830 : wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
37 : 19830 : wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
38 : :
39 : 19830 : if (INTEGRAL_TYPE_P (type)
40 : 17482 : && !TYPE_UNSIGNED (type)
41 : 7184 : && bound == type_min
42 : 20094 : && TYPE_PRECISION (type) != 1)
43 : 264 : pp_string (pp, "-INF");
44 : 19566 : else if (bound == type_max && TYPE_PRECISION (type) != 1)
45 : 2625 : pp_string (pp, "+INF");
46 : : else
47 : 16941 : pp_wide_int (pp, bound, TYPE_SIGN (type));
48 : 19830 : }
49 : :
50 : : static void
51 : 9014 : print_irange_bitmasks (pretty_printer *pp, const irange_bitmask &bm)
52 : : {
53 : 9014 : if (bm.unknown_p ())
54 : 6541 : return;
55 : :
56 : 2473 : pp_string (pp, " MASK ");
57 : 2473 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
58 : 2473 : unsigned len_mask, len_val;
59 : 4946 : if (print_hex_buf_size (bm.mask (), &len_mask)
60 : 2473 : | print_hex_buf_size (bm.value (), &len_val))
61 : 0 : p = XALLOCAVEC (char, MAX (len_mask, len_val));
62 : : else
63 : : p = buf;
64 : 2473 : print_hex (bm.mask (), p);
65 : 2473 : pp_string (pp, p);
66 : 2473 : pp_string (pp, " VALUE ");
67 : 2473 : print_hex (bm.value (), p);
68 : 2473 : pp_string (pp, p);
69 : : }
70 : :
71 : : void
72 : 714 : vrange_printer::visit (const unsupported_range &r) const
73 : : {
74 : 714 : pp_string (pp, "[unsupported_range] ");
75 : 714 : if (r.undefined_p ())
76 : : {
77 : 0 : pp_string (pp, "UNDEFINED");
78 : 0 : return;
79 : : }
80 : 714 : if (r.varying_p ())
81 : : {
82 : 714 : pp_string (pp, "VARYING");
83 : 714 : return;
84 : : }
85 : 0 : gcc_unreachable ();
86 : : }
87 : :
88 : : void
89 : 8103 : vrange_printer::visit (const irange &r) const
90 : : {
91 : 8103 : pp_string (pp, "[irange] ");
92 : 8103 : if (r.undefined_p ())
93 : : {
94 : 12 : pp_string (pp, "UNDEFINED");
95 : 12 : return;
96 : : }
97 : 8091 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
98 : 8091 : pp_character (pp, ' ');
99 : 8091 : if (r.varying_p ())
100 : : {
101 : 251 : pp_string (pp, "VARYING");
102 : 251 : return;
103 : : }
104 : 16581 : for (unsigned i = 0; i < r.num_pairs (); ++i)
105 : : {
106 : 8741 : pp_character (pp, '[');
107 : 8741 : print_int_bound (pp, r.lower_bound (i), r.type ());
108 : 8741 : pp_string (pp, ", ");
109 : 8741 : print_int_bound (pp, r.upper_bound (i), r.type ());
110 : 8741 : pp_character (pp, ']');
111 : : }
112 : 7840 : print_irange_bitmasks (pp, r.m_bitmask);
113 : : }
114 : :
115 : : void
116 : 1246 : vrange_printer::visit (const prange &r) const
117 : : {
118 : 1246 : pp_string (pp, "[prange] ");
119 : 1246 : if (r.undefined_p ())
120 : : {
121 : 6 : pp_string (pp, "UNDEFINED");
122 : 6 : return;
123 : : }
124 : 1240 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
125 : 1240 : pp_character (pp, ' ');
126 : 1240 : if (r.varying_p ())
127 : : {
128 : 66 : pp_string (pp, "VARYING");
129 : 66 : return;
130 : : }
131 : :
132 : 1174 : pp_character (pp, '[');
133 : 1174 : print_int_bound (pp, r.lower_bound (), r.type ());
134 : 1174 : pp_string (pp, ", ");
135 : 1174 : print_int_bound (pp, r.upper_bound (), r.type ());
136 : 1174 : pp_character (pp, ']');
137 : 1174 : print_irange_bitmasks (pp, r.m_bitmask);
138 : : }
139 : :
140 : : void
141 : 932 : vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
142 : : {
143 : 932 : char s[100];
144 : 932 : real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
145 : 932 : pp_string (pp, s);
146 : 932 : if (!DECIMAL_FLOAT_TYPE_P (type)
147 : : // real_to_hexadecimal prints infinities and NAN as text. No
148 : : // need to print them twice.
149 : 932 : && !real_isinf (&r)
150 : 1424 : && !real_isnan (&r))
151 : : {
152 : 492 : real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
153 : 492 : pp_printf (pp, " (%s)", s);
154 : : }
155 : 932 : }
156 : :
157 : : // Print an frange.
158 : :
159 : : void
160 : 546 : vrange_printer::visit (const frange &r) const
161 : : {
162 : 546 : pp_string (pp, "[frange] ");
163 : 546 : if (r.undefined_p ())
164 : : {
165 : 5 : pp_string (pp, "UNDEFINED");
166 : 5 : return;
167 : : }
168 : 541 : tree type = r.type ();
169 : 541 : dump_generic_node (pp, type, 0, TDF_NONE, false);
170 : 541 : pp_string (pp, " ");
171 : 541 : if (r.varying_p ())
172 : : {
173 : 72 : pp_string (pp, "VARYING");
174 : 72 : print_frange_nan (r);
175 : 72 : return;
176 : : }
177 : 469 : pp_character (pp, '[');
178 : 469 : bool has_endpoints = !r.known_isnan ();
179 : 469 : if (has_endpoints)
180 : : {
181 : 466 : print_real_value (type, r.lower_bound ());
182 : 466 : pp_string (pp, ", ");
183 : 466 : print_real_value (type, r.upper_bound ());
184 : : }
185 : 469 : pp_character (pp, ']');
186 : 469 : print_frange_nan (r);
187 : : }
188 : :
189 : : // Print the NAN info for an frange.
190 : :
191 : : void
192 : 541 : vrange_printer::print_frange_nan (const frange &r) const
193 : : {
194 : 642 : if (r.maybe_isnan ())
195 : : {
196 : 440 : if (r.m_pos_nan && r.m_neg_nan)
197 : : {
198 : 193 : pp_string (pp, " +-NAN");
199 : 193 : return;
200 : : }
201 : 247 : bool nan_sign = r.m_neg_nan;
202 : 247 : if (nan_sign)
203 : 0 : pp_string (pp, " -NAN");
204 : : else
205 : 247 : pp_string (pp, " +NAN");
206 : : }
207 : : }
|