Branch data Line data Source code
1 : : /* Printing operations with very long integers.
2 : : Copyright (C) 2012-2025 Free Software Foundation, Inc.
3 : : Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it
8 : : under the terms of the GNU General Public License as published by the
9 : : Free Software Foundation; either version 3, or (at your option) any
10 : : later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT
13 : : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : 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 "pretty-print.h"
25 : :
26 : : /*
27 : : * public printing routines.
28 : : */
29 : :
30 : : #define BLOCKS_NEEDED(PREC) \
31 : : (((PREC) + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT)
32 : :
33 : : void
34 : 484224 : print_dec (const wide_int_ref &wi, char *buf, signop sgn)
35 : : {
36 : 484224 : if (sgn == SIGNED)
37 : 14417 : print_decs (wi, buf);
38 : : else
39 : 469807 : print_decu (wi, buf);
40 : 484224 : }
41 : :
42 : : void
43 : 3494 : print_dec (const wide_int_ref &wi, FILE *file, signop sgn)
44 : : {
45 : 3494 : if (sgn == SIGNED)
46 : 3161 : print_decs (wi, file);
47 : : else
48 : 333 : print_decu (wi, file);
49 : 3494 : }
50 : :
51 : :
52 : : /* Try to print the signed self in decimal to BUF. */
53 : :
54 : : void
55 : 18200 : print_decs (const wide_int_ref &wi, char *buf)
56 : : {
57 : 18200 : if (wi.get_precision () <= HOST_BITS_PER_WIDE_INT || wi.get_len () == 1)
58 : : {
59 : 18170 : if (wi::neg_p (wi))
60 : 3719 : sprintf (buf, "-" HOST_WIDE_INT_PRINT_UNSIGNED,
61 : 3719 : -(unsigned HOST_WIDE_INT) wi.to_shwi ());
62 : : else
63 : 14451 : sprintf (buf, HOST_WIDE_INT_PRINT_DEC, wi.to_shwi ());
64 : : }
65 : 30 : else if (wi::neg_p (wi))
66 : : {
67 : 14 : widest2_int w = widest2_int::from (wi, SIGNED);
68 : 14 : *buf = '-';
69 : 14 : print_decu (-w, buf + 1);
70 : 14 : }
71 : : else
72 : 16 : print_decu (wi, buf);
73 : 18200 : }
74 : :
75 : : /* Try to print the signed self in decimal to FILE. */
76 : :
77 : : void
78 : 3783 : print_decs (const wide_int_ref &wi, FILE *file)
79 : : {
80 : 3783 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
81 : 3783 : unsigned len;
82 : 3783 : if (print_decs_buf_size (wi, &len))
83 : 0 : p = XALLOCAVEC (char, len);
84 : 3783 : print_decs (wi, p);
85 : 3783 : fputs (p, file);
86 : 3783 : }
87 : :
88 : : /* Try to print the unsigned self in decimal to BUF. */
89 : :
90 : : void
91 : 567155 : print_decu (const wide_int_ref &wi, char *buf)
92 : : {
93 : 567155 : if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT)
94 : 567155 : || (wi.get_len () == 1 && !wi::neg_p (wi)))
95 : 565324 : sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, wi.to_uhwi ());
96 : : else
97 : : {
98 : 1831 : widest2_int w = widest2_int::from (wi, UNSIGNED), r;
99 : 1831 : widest2_int ten19 = HOST_WIDE_INT_UC (10000000000000000000);
100 : 1831 : char buf2[20], next1[19], next2[19];
101 : 1831 : size_t l, c = 0, i;
102 : : /* In order to avoid dividing this twice, print the 19 decimal
103 : : digit chunks in reverse order into buffer and then reorder
104 : : them in-place. */
105 : 4336 : while (wi::gtu_p (w, ten19))
106 : : {
107 : 2505 : w = wi::divmod_trunc (w, ten19, UNSIGNED, &r);
108 : 2505 : sprintf (buf + c * 19, "%019" PRIu64, r.to_uhwi ());
109 : 2505 : ++c;
110 : : }
111 : 1831 : l = sprintf (buf2, HOST_WIDE_INT_PRINT_UNSIGNED, w.to_uhwi ());
112 : 1831 : buf[c * 19 + l] = '\0';
113 : 1831 : memcpy (next1, buf, 19);
114 : 1831 : memcpy (buf, buf2, l);
115 : 2510 : for (i = 0; i < c / 2; ++i)
116 : : {
117 : 679 : memcpy (next2, buf + (c - i - 1) * 19, 19);
118 : 679 : memcpy (buf + l + (c - i - 1) * 19, next1, 19);
119 : 679 : memcpy (next1, buf + (i + 1) * 19, 19);
120 : 679 : memcpy (buf + l + i * 19, next2, 19);
121 : : }
122 : 1831 : if (c & 1)
123 : 1147 : memcpy (buf + l + i * 19, next1, 19);
124 : 1831 : }
125 : 567155 : }
126 : :
127 : : /* Try to print the signed self in decimal to FILE. */
128 : :
129 : : void
130 : 97294 : print_decu (const wide_int_ref &wi, FILE *file)
131 : : {
132 : 97294 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
133 : 97294 : unsigned len;
134 : 97294 : if (print_decu_buf_size (wi, &len))
135 : 0 : p = XALLOCAVEC (char, len);
136 : 97294 : print_decu (wi, p);
137 : 97294 : fputs (p, file);
138 : 97294 : }
139 : :
140 : : void
141 : 159661 : print_hex (const wide_int_ref &val, char *buf)
142 : : {
143 : 159661 : if (val == 0)
144 : 36020 : buf += sprintf (buf, "0x0");
145 : : else
146 : : {
147 : 123641 : buf += sprintf (buf, "0x");
148 : 123641 : int start = ROUND_DOWN (val.get_precision (), HOST_BITS_PER_WIDE_INT);
149 : 123641 : int width = val.get_precision () - start;
150 : 123641 : bool first_p = true;
151 : 1448288 : for (int i = start; i >= 0; i -= HOST_BITS_PER_WIDE_INT)
152 : : {
153 : 1324647 : unsigned HOST_WIDE_INT uhwi = wi::extract_uhwi (val, i, width);
154 : 1324647 : if (!first_p)
155 : 649 : buf += sprintf (buf, HOST_WIDE_INT_PRINT_PADDED_HEX, uhwi);
156 : 1323998 : else if (uhwi != 0)
157 : : {
158 : 123641 : buf += sprintf (buf, HOST_WIDE_INT_PRINT_HEX_PURE, uhwi);
159 : 123641 : first_p = false;
160 : : }
161 : 1324647 : width = HOST_BITS_PER_WIDE_INT;
162 : : }
163 : : }
164 : 159661 : }
165 : :
166 : : /* Print one big hex number to FILE. Note that some assemblers may not
167 : : accept this for large modes. */
168 : : void
169 : 154075 : print_hex (const wide_int_ref &wi, FILE *file)
170 : : {
171 : 154075 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
172 : 154075 : unsigned len;
173 : 154075 : if (print_hex_buf_size (wi, &len))
174 : 0 : p = XALLOCAVEC (char, len);
175 : 154075 : print_hex (wi, p);
176 : 154075 : fputs (p, file);
177 : 154075 : }
178 : :
179 : : /* Print larger precision wide_int. Not defined as inline in a header
180 : : together with pp_wide_int because XALLOCAVEC will make it uninlinable. */
181 : :
182 : : void
183 : 16 : pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn)
184 : : {
185 : 16 : unsigned int len;
186 : 16 : print_dec_buf_size (w, sgn, &len);
187 : 16 : char *buf = XALLOCAVEC (char, len);
188 : 16 : print_dec (w, buf, sgn);
189 : 16 : pp_string (pp, buf);
190 : 16 : }
|