]>
Commit | Line | Data |
---|---|---|
807e902e | 1 | /* Printing operations with very long integers. |
a945c346 | 2 | Copyright (C) 2012-2024 Free Software Foundation, Inc. |
807e902e KZ |
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" | |
6f7f7287 | 24 | #include "pretty-print.h" |
807e902e KZ |
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 | print_dec (const wide_int_ref &wi, char *buf, signop sgn) | |
35 | { | |
36 | if (sgn == SIGNED) | |
37 | print_decs (wi, buf); | |
38 | else | |
39 | print_decu (wi, buf); | |
40 | } | |
41 | ||
42 | void | |
43 | print_dec (const wide_int_ref &wi, FILE *file, signop sgn) | |
44 | { | |
45 | if (sgn == SIGNED) | |
46 | print_decs (wi, file); | |
47 | else | |
48 | print_decu (wi, file); | |
49 | } | |
50 | ||
51 | ||
fbdf88a1 | 52 | /* Try to print the signed self in decimal to BUF. */ |
807e902e KZ |
53 | |
54 | void | |
55 | print_decs (const wide_int_ref &wi, char *buf) | |
56 | { | |
fbdf88a1 | 57 | if (wi.get_precision () <= HOST_BITS_PER_WIDE_INT || wi.get_len () == 1) |
807e902e KZ |
58 | { |
59 | if (wi::neg_p (wi)) | |
00a7ba58 JJ |
60 | sprintf (buf, "-" HOST_WIDE_INT_PRINT_UNSIGNED, |
61 | -(unsigned HOST_WIDE_INT) wi.to_shwi ()); | |
807e902e KZ |
62 | else |
63 | sprintf (buf, HOST_WIDE_INT_PRINT_DEC, wi.to_shwi ()); | |
64 | } | |
fbdf88a1 JJ |
65 | else if (wi::neg_p (wi)) |
66 | { | |
67 | widest2_int w = widest2_int::from (wi, SIGNED); | |
68 | *buf = '-'; | |
69 | print_decu (-w, buf + 1); | |
70 | } | |
807e902e | 71 | else |
fbdf88a1 | 72 | print_decu (wi, buf); |
807e902e KZ |
73 | } |
74 | ||
fbdf88a1 | 75 | /* Try to print the signed self in decimal to FILE. */ |
807e902e KZ |
76 | |
77 | void | |
78 | print_decs (const wide_int_ref &wi, FILE *file) | |
79 | { | |
0d00385e | 80 | char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; |
3bcc10b9 JJ |
81 | unsigned len; |
82 | if (print_decs_buf_size (wi, &len)) | |
83 | p = XALLOCAVEC (char, len); | |
0d00385e JJ |
84 | print_decs (wi, p); |
85 | fputs (p, file); | |
807e902e KZ |
86 | } |
87 | ||
fbdf88a1 | 88 | /* Try to print the unsigned self in decimal to BUF. */ |
807e902e KZ |
89 | |
90 | void | |
91 | print_decu (const wide_int_ref &wi, char *buf) | |
92 | { | |
93 | if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT) | |
94 | || (wi.get_len () == 1 && !wi::neg_p (wi))) | |
95 | sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, wi.to_uhwi ()); | |
96 | else | |
fbdf88a1 JJ |
97 | { |
98 | widest2_int w = widest2_int::from (wi, UNSIGNED), r; | |
99 | widest2_int ten19 = HOST_WIDE_INT_UC (10000000000000000000); | |
100 | char buf2[20], next1[19], next2[19]; | |
101 | 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 | while (wi::gtu_p (w, ten19)) | |
106 | { | |
107 | w = wi::divmod_trunc (w, ten19, UNSIGNED, &r); | |
108 | sprintf (buf + c * 19, "%019" PRIu64, r.to_uhwi ()); | |
109 | ++c; | |
110 | } | |
111 | l = sprintf (buf2, HOST_WIDE_INT_PRINT_UNSIGNED, w.to_uhwi ()); | |
112 | buf[c * 19 + l] = '\0'; | |
113 | memcpy (next1, buf, 19); | |
114 | memcpy (buf, buf2, l); | |
115 | for (i = 0; i < c / 2; ++i) | |
116 | { | |
117 | memcpy (next2, buf + (c - i - 1) * 19, 19); | |
118 | memcpy (buf + l + (c - i - 1) * 19, next1, 19); | |
119 | memcpy (next1, buf + (i + 1) * 19, 19); | |
120 | memcpy (buf + l + i * 19, next2, 19); | |
121 | } | |
122 | if (c & 1) | |
123 | memcpy (buf + l + i * 19, next1, 19); | |
124 | } | |
807e902e KZ |
125 | } |
126 | ||
fbdf88a1 | 127 | /* Try to print the signed self in decimal to FILE. */ |
807e902e KZ |
128 | |
129 | void | |
130 | print_decu (const wide_int_ref &wi, FILE *file) | |
131 | { | |
0d00385e | 132 | char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; |
3bcc10b9 JJ |
133 | unsigned len; |
134 | if (print_decu_buf_size (wi, &len)) | |
135 | p = XALLOCAVEC (char, len); | |
0d00385e JJ |
136 | print_decu (wi, p); |
137 | fputs (p, file); | |
807e902e KZ |
138 | } |
139 | ||
140 | void | |
7984457f | 141 | print_hex (const wide_int_ref &val, char *buf) |
807e902e | 142 | { |
7984457f | 143 | if (val == 0) |
807e902e KZ |
144 | buf += sprintf (buf, "0x0"); |
145 | else | |
146 | { | |
7984457f RS |
147 | buf += sprintf (buf, "0x"); |
148 | int start = ROUND_DOWN (val.get_precision (), HOST_BITS_PER_WIDE_INT); | |
149 | int width = val.get_precision () - start; | |
150 | bool first_p = true; | |
151 | for (int i = start; i >= 0; i -= HOST_BITS_PER_WIDE_INT) | |
807e902e | 152 | { |
7984457f RS |
153 | unsigned HOST_WIDE_INT uhwi = wi::extract_uhwi (val, i, width); |
154 | if (!first_p) | |
155 | buf += sprintf (buf, HOST_WIDE_INT_PRINT_PADDED_HEX, uhwi); | |
156 | else if (uhwi != 0) | |
157 | { | |
158 | buf += sprintf (buf, HOST_WIDE_INT_PRINT_HEX_PURE, uhwi); | |
159 | first_p = false; | |
160 | } | |
161 | width = HOST_BITS_PER_WIDE_INT; | |
807e902e | 162 | } |
807e902e KZ |
163 | } |
164 | } | |
165 | ||
166 | /* Print one big hex number to FILE. Note that some assemblers may not | |
167 | accept this for large modes. */ | |
168 | void | |
169 | print_hex (const wide_int_ref &wi, FILE *file) | |
170 | { | |
0d00385e | 171 | char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; |
3bcc10b9 JJ |
172 | unsigned len; |
173 | if (print_hex_buf_size (wi, &len)) | |
174 | p = XALLOCAVEC (char, len); | |
0d00385e JJ |
175 | print_hex (wi, p); |
176 | fputs (p, file); | |
807e902e KZ |
177 | } |
178 | ||
6f7f7287 JJ |
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 | pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn) | |
184 | { | |
3bcc10b9 | 185 | unsigned int len; |
fbdf88a1 | 186 | print_dec_buf_size (w, sgn, &len); |
3bcc10b9 | 187 | char *buf = XALLOCAVEC (char, len); |
6f7f7287 JJ |
188 | print_dec (w, buf, sgn); |
189 | pp_string (pp, buf); | |
190 | } |