Line data Source code
1 : /* Printing operations with very long integers.
2 : Copyright (C) 2012-2026 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 355986 : print_dec (const wide_int_ref &wi, char *buf, signop sgn)
35 : {
36 355986 : if (sgn == SIGNED)
37 29853 : print_decs (wi, buf);
38 : else
39 326133 : print_decu (wi, buf);
40 355986 : }
41 :
42 : void
43 3555 : print_dec (const wide_int_ref &wi, FILE *file, signop sgn)
44 : {
45 3555 : if (sgn == SIGNED)
46 3222 : print_decs (wi, file);
47 : else
48 333 : print_decu (wi, file);
49 3555 : }
50 :
51 :
52 : /* Try to print the signed self in decimal to BUF. */
53 :
54 : void
55 33694 : print_decs (const wide_int_ref &wi, char *buf)
56 : {
57 33694 : if (wi.get_precision () <= HOST_BITS_PER_WIDE_INT || wi.get_len () == 1)
58 : {
59 33661 : if (wi::neg_p (wi))
60 4149 : sprintf (buf, "-" HOST_WIDE_INT_PRINT_UNSIGNED,
61 4149 : -(unsigned HOST_WIDE_INT) wi.to_shwi ());
62 : else
63 29512 : sprintf (buf, HOST_WIDE_INT_PRINT_DEC, wi.to_shwi ());
64 : }
65 33 : else if (wi::neg_p (wi))
66 : {
67 17 : widest2_int w = widest2_int::from (wi, SIGNED);
68 17 : *buf = '-';
69 17 : print_decu (-w, buf + 1);
70 17 : }
71 : else
72 16 : print_decu (wi, buf);
73 33694 : }
74 :
75 : /* Try to print the signed self in decimal to FILE. */
76 :
77 : void
78 3841 : print_decs (const wide_int_ref &wi, FILE *file)
79 : {
80 3841 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
81 3841 : unsigned len;
82 3841 : if (print_decs_buf_size (wi, &len))
83 0 : p = XALLOCAVEC (char, len);
84 3841 : print_decs (wi, p);
85 3841 : fputs (p, file);
86 3841 : }
87 :
88 : /* Try to print the unsigned self in decimal to BUF. */
89 :
90 : void
91 442872 : print_decu (const wide_int_ref &wi, char *buf)
92 : {
93 442872 : if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT)
94 442872 : || (wi.get_len () == 1 && !wi::neg_p (wi)))
95 440870 : sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, wi.to_uhwi ());
96 : else
97 : {
98 2002 : widest2_int w = widest2_int::from (wi, UNSIGNED), r;
99 2002 : widest2_int ten19 = HOST_WIDE_INT_UC (10000000000000000000);
100 2002 : char buf2[20], next1[19], next2[19];
101 2002 : 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 4688 : while (wi::gtu_p (w, ten19))
106 : {
107 2686 : w = wi::divmod_trunc (w, ten19, UNSIGNED, &r);
108 2686 : sprintf (buf + c * 19, "%019" PRIu64, r.to_uhwi ());
109 2686 : ++c;
110 : }
111 2002 : l = sprintf (buf2, HOST_WIDE_INT_PRINT_UNSIGNED, w.to_uhwi ());
112 2002 : buf[c * 19 + l] = '\0';
113 2002 : memcpy (next1, buf, 19);
114 2002 : memcpy (buf, buf2, l);
115 2686 : for (i = 0; i < c / 2; ++i)
116 : {
117 684 : memcpy (next2, buf + (c - i - 1) * 19, 19);
118 684 : memcpy (buf + l + (c - i - 1) * 19, next1, 19);
119 684 : memcpy (next1, buf + (i + 1) * 19, 19);
120 684 : memcpy (buf + l + i * 19, next2, 19);
121 : }
122 2002 : if (c & 1)
123 1318 : memcpy (buf + l + i * 19, next1, 19);
124 2002 : }
125 442872 : }
126 :
127 : /* Try to print the signed self in decimal to FILE. */
128 :
129 : void
130 116682 : print_decu (const wide_int_ref &wi, FILE *file)
131 : {
132 116682 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
133 116682 : unsigned len;
134 116682 : if (print_decu_buf_size (wi, &len))
135 0 : p = XALLOCAVEC (char, len);
136 116682 : print_decu (wi, p);
137 116682 : fputs (p, file);
138 116682 : }
139 :
140 : void
141 209862 : print_hex (const wide_int_ref &val, char *buf)
142 : {
143 209862 : if (val == 0)
144 56027 : buf += sprintf (buf, "0x0");
145 : else
146 : {
147 153835 : buf += sprintf (buf, "0x");
148 153835 : int start = ROUND_DOWN (val.get_precision (), HOST_BITS_PER_WIDE_INT);
149 153835 : int width = val.get_precision () - start;
150 153835 : bool first_p = true;
151 2205134 : for (int i = start; i >= 0; i -= HOST_BITS_PER_WIDE_INT)
152 : {
153 2051299 : unsigned HOST_WIDE_INT uhwi = wi::extract_uhwi (val, i, width);
154 2051299 : if (!first_p)
155 989 : buf += sprintf (buf, HOST_WIDE_INT_PRINT_PADDED_HEX, uhwi);
156 2050310 : else if (uhwi != 0)
157 : {
158 153835 : buf += sprintf (buf, HOST_WIDE_INT_PRINT_HEX_PURE, uhwi);
159 153835 : first_p = false;
160 : }
161 2051299 : width = HOST_BITS_PER_WIDE_INT;
162 : }
163 : }
164 209862 : }
165 :
166 : /* Print one big hex number to FILE. Note that some assemblers may not
167 : accept this for large modes. */
168 : void
169 193563 : print_hex (const wide_int_ref &wi, FILE *file)
170 : {
171 193563 : char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
172 193563 : unsigned len;
173 193563 : if (print_hex_buf_size (wi, &len))
174 0 : p = XALLOCAVEC (char, len);
175 193563 : print_hex (wi, p);
176 193563 : fputs (p, file);
177 193563 : }
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 : }
|