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