Branch data Line data Source code
1 : : /* Pretty print support for value ranges.
2 : : Copyright (C) 2019-2024 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 : : void
34 : 858 : vrange_printer::visit (const unsupported_range &r) const
35 : : {
36 : 858 : pp_string (pp, "[unsupported_range] ");
37 : 858 : if (r.undefined_p ())
38 : : {
39 : 0 : pp_string (pp, "UNDEFINED");
40 : 0 : return;
41 : : }
42 : 858 : if (r.varying_p ())
43 : : {
44 : 858 : pp_string (pp, "VARYING");
45 : 858 : return;
46 : : }
47 : 0 : gcc_unreachable ();
48 : : }
49 : :
50 : : void
51 : 6539 : vrange_printer::visit (const irange &r) const
52 : : {
53 : 6539 : pp_string (pp, "[irange] ");
54 : 6539 : if (r.undefined_p ())
55 : : {
56 : 18 : pp_string (pp, "UNDEFINED");
57 : 18 : return;
58 : : }
59 : 6521 : dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
60 : 6521 : pp_character (pp, ' ');
61 : 6521 : if (r.varying_p ())
62 : : {
63 : 324 : pp_string (pp, "VARYING");
64 : 324 : return;
65 : : }
66 : 13093 : for (unsigned i = 0; i < r.num_pairs (); ++i)
67 : : {
68 : 6896 : pp_character (pp, '[');
69 : 6896 : print_irange_bound (r.lower_bound (i), r.type ());
70 : 6896 : pp_string (pp, ", ");
71 : 6896 : print_irange_bound (r.upper_bound (i), r.type ());
72 : 6896 : pp_character (pp, ']');
73 : : }
74 : 6197 : print_irange_bitmasks (r);
75 : : }
76 : :
77 : : void
78 : 13792 : vrange_printer::print_irange_bound (const wide_int &bound, tree type) const
79 : : {
80 : 13792 : wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
81 : 13792 : wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
82 : :
83 : 13792 : if (INTEGRAL_TYPE_P (type)
84 : 11464 : && !TYPE_UNSIGNED (type)
85 : 6882 : && bound == type_min
86 : 13986 : && TYPE_PRECISION (type) != 1)
87 : 194 : pp_string (pp, "-INF");
88 : 13598 : else if (bound == type_max && TYPE_PRECISION (type) != 1)
89 : 2260 : pp_string (pp, "+INF");
90 : : else
91 : 11338 : pp_wide_int (pp, bound, TYPE_SIGN (type));
92 : 13792 : }
93 : :
94 : : void
95 : 6197 : vrange_printer::print_irange_bitmasks (const irange &r) const
96 : : {
97 : 6197 : irange_bitmask bm = r.m_bitmask;
98 : 6197 : if (bm.unknown_p ())
99 : 3763 : return;
100 : :
101 : 2434 : pp_string (pp, " MASK ");
102 : 2434 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
103 : 2434 : unsigned len_mask, len_val;
104 : 4868 : if (print_hex_buf_size (bm.mask (), &len_mask)
105 : 2434 : | print_hex_buf_size (bm.value (), &len_val))
106 : 0 : p = XALLOCAVEC (char, MAX (len_mask, len_val));
107 : : else
108 : : p = buf;
109 : 2434 : print_hex (bm.mask (), p);
110 : 2434 : pp_string (pp, p);
111 : 2434 : pp_string (pp, " VALUE ");
112 : 2434 : print_hex (bm.value (), p);
113 : 2434 : pp_string (pp, p);
114 : 6197 : }
115 : :
116 : : void
117 : 168 : vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const
118 : : {
119 : 168 : char s[100];
120 : 168 : real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type));
121 : 168 : pp_string (pp, s);
122 : 168 : if (!DECIMAL_FLOAT_TYPE_P (type)
123 : : // real_to_hexadecimal prints infinities and NAN as text. No
124 : : // need to print them twice.
125 : 168 : && !real_isinf (&r)
126 : 279 : && !real_isnan (&r))
127 : : {
128 : 111 : real_to_hexadecimal (s, &r, sizeof (s), 0, 1);
129 : 111 : pp_printf (pp, " (%s)", s);
130 : : }
131 : 168 : }
132 : :
133 : : // Print an frange.
134 : :
135 : : void
136 : 164 : vrange_printer::visit (const frange &r) const
137 : : {
138 : 164 : pp_string (pp, "[frange] ");
139 : 164 : if (r.undefined_p ())
140 : : {
141 : 5 : pp_string (pp, "UNDEFINED");
142 : 5 : return;
143 : : }
144 : 159 : tree type = r.type ();
145 : 159 : dump_generic_node (pp, type, 0, TDF_NONE, false);
146 : 159 : pp_string (pp, " ");
147 : 159 : if (r.varying_p ())
148 : : {
149 : 72 : pp_string (pp, "VARYING");
150 : 72 : print_frange_nan (r);
151 : 72 : return;
152 : : }
153 : 87 : pp_character (pp, '[');
154 : 87 : bool has_endpoints = !r.known_isnan ();
155 : 87 : if (has_endpoints)
156 : : {
157 : 84 : print_real_value (type, r.lower_bound ());
158 : 84 : pp_string (pp, ", ");
159 : 84 : print_real_value (type, r.upper_bound ());
160 : : }
161 : 87 : pp_character (pp, ']');
162 : 87 : print_frange_nan (r);
163 : : }
164 : :
165 : : // Print the NAN info for an frange.
166 : :
167 : : void
168 : 159 : vrange_printer::print_frange_nan (const frange &r) const
169 : : {
170 : 255 : if (r.maybe_isnan ())
171 : : {
172 : 63 : if (r.m_pos_nan && r.m_neg_nan)
173 : : {
174 : 52 : pp_string (pp, " +-NAN");
175 : 52 : return;
176 : : }
177 : 11 : bool nan_sign = r.m_neg_nan;
178 : 11 : if (nan_sign)
179 : 0 : pp_string (pp, " -NAN");
180 : : else
181 : 11 : pp_string (pp, " +NAN");
182 : : }
183 : : }
|