]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gmp-utils.h
Additions to gdb_mpz
[thirdparty/binutils-gdb.git] / gdb / gmp-utils.h
CommitLineData
b34c74ab
JB
1/* Miscellaneous routines making it easier to use GMP within GDB's framework.
2
213516ef 3 Copyright (C) 2019-2023 Free Software Foundation, Inc.
b34c74ab
JB
4
5 This file is part of GDB.
6
7 This program 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 of the License, or
10 (at your option) any later version.
11
12 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef GMP_UTILS_H
21#define GMP_UTILS_H
22
b34c74ab
JB
23/* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get
24 access to GMP's various formatting functions. */
25#include <stdio.h>
26#include <stdarg.h>
27#include <gmp.h>
28#include "gdbsupport/traits.h"
29
987b6703 30/* Same as gmp_asprintf, but returning an std::string. */
b34c74ab 31
987b6703 32std::string gmp_string_printf (const char *fmt, ...);
b34c74ab 33
7aeae94f
TT
34struct gdb_mpq;
35struct gdb_mpf;
36
b34c74ab
JB
37/* A class to make it easier to use GMP's mpz_t values within GDB. */
38
39struct gdb_mpz
40{
b34c74ab 41 /* Constructors. */
7aeae94f 42 gdb_mpz () { mpz_init (m_val); }
b34c74ab
JB
43
44 explicit gdb_mpz (const mpz_t &from_val)
45 {
7aeae94f
TT
46 mpz_init (m_val);
47 mpz_set (m_val, from_val);
b34c74ab
JB
48 }
49
50 gdb_mpz (const gdb_mpz &from)
51 {
7aeae94f
TT
52 mpz_init (m_val);
53 mpz_set (m_val, from.m_val);
b34c74ab
JB
54 }
55
56 /* Initialize using the given integral value.
57
58 The main advantage of this method is that it handles both signed
59 and unsigned types, with no size restriction. */
60 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
61 explicit gdb_mpz (T src)
62 {
7aeae94f 63 mpz_init (m_val);
b34c74ab
JB
64 set (src);
65 }
66
67 explicit gdb_mpz (gdb_mpz &&from)
68 {
7aeae94f
TT
69 mpz_init (m_val);
70 mpz_swap (m_val, from.m_val);
b34c74ab
JB
71 }
72
73
74 gdb_mpz &operator= (const gdb_mpz &from)
75 {
7aeae94f 76 mpz_set (m_val, from.m_val);
b34c74ab
JB
77 return *this;
78 }
79
80 gdb_mpz &operator= (gdb_mpz &&other)
81 {
7aeae94f 82 mpz_swap (m_val, other.m_val);
b34c74ab
JB
83 return *this;
84 }
85
86 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
87 gdb_mpz &operator= (T src)
88 {
89 set (src);
90 return *this;
91 }
92
c225d6b8
TT
93 gdb_mpz &operator= (bool src)
94 {
95 mpz_set_ui (m_val, (unsigned long) src);
96 return *this;
97 }
98
302273ca
TT
99 /* Initialize this value from a string and a base. Returns true if
100 the string was parsed successfully, false otherwise. */
101 bool set (const char *str, int base)
102 {
7aeae94f 103 return mpz_set_str (m_val, str, base) != -1;
302273ca
TT
104 }
105
106 /* Return a new value that is BASE**EXP. */
107 static gdb_mpz pow (unsigned long base, unsigned long exp)
108 {
109 gdb_mpz result;
7aeae94f 110 mpz_ui_pow_ui (result.m_val, base, exp);
302273ca
TT
111 return result;
112 }
113
c225d6b8
TT
114 /* Return a new value that is this value raised to EXP. */
115 gdb_mpz pow (unsigned long exp) const
116 {
117 gdb_mpz result;
118 mpz_pow_ui (result.m_val, m_val, exp);
119 return result;
120 }
121
767c4b92 122 /* Convert this value to an integer of the given type.
b34c74ab
JB
123
124 The return type can signed or unsigned, with no size restriction. */
125 template<typename T> T as_integer () const;
126
767c4b92
TT
127 /* Convert this value to an integer of the given type. If this
128 value is too large, it is truncated.
129
130 The return type can signed or unsigned, with no size restriction. */
131 template<typename T> T as_integer_truncate () const;
132
c9f0b43f
JB
133 /* Set VAL by importing the number stored in the byte array (BUF),
134 using the given BYTE_ORDER. The size of the data to read is
135 the byte array's size.
b34c74ab
JB
136
137 UNSIGNED_P indicates whether the number has an unsigned type. */
c9f0b43f 138 void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order,
b34c74ab
JB
139 bool unsigned_p);
140
c9f0b43f
JB
141 /* Write VAL into BUF as a number whose byte size is the size of BUF,
142 using the given BYTE_ORDER.
b34c74ab
JB
143
144 UNSIGNED_P indicates whether the number has an unsigned type. */
c9f0b43f 145 void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
1c805ba0
TT
146 bool unsigned_p) const
147 {
148 export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
149 unsigned_p, true /* safe */);
150 }
151
152 /* Like write, but truncates the value to the desired number of
153 bytes. */
154 void truncate (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
155 bool unsigned_p) const
156 {
157 export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
158 unsigned_p, false /* safe */);
159 }
b34c74ab
JB
160
161 /* Return a string containing VAL. */
7aeae94f 162 std::string str () const { return gmp_string_printf ("%Zd", m_val); }
b34c74ab
JB
163
164 /* The destructor. */
7aeae94f 165 ~gdb_mpz () { mpz_clear (m_val); }
b34c74ab 166
302273ca
TT
167 /* Negate this value in place. */
168 void negate ()
169 {
7aeae94f 170 mpz_neg (m_val, m_val);
302273ca
TT
171 }
172
c225d6b8
TT
173 /* Take the one's complement in place. */
174 void complement ()
175 { mpz_com (m_val, m_val); }
176
177 /* Mask this value to N bits, in place. */
178 void mask (unsigned n)
179 { mpz_tdiv_r_2exp (m_val, m_val, n); }
180
181 /* Return the sign of this value. This returns -1 for a negative
182 value, 0 if the value is 0, and 1 for a positive value. */
183 int sgn () const
184 { return mpz_sgn (m_val); }
185
186 explicit operator bool () const
187 { return sgn () != 0; }
188
302273ca
TT
189 gdb_mpz &operator*= (long other)
190 {
7aeae94f 191 mpz_mul_si (m_val, m_val, other);
302273ca
TT
192 return *this;
193 }
194
c225d6b8
TT
195 gdb_mpz operator* (const gdb_mpz &other) const
196 {
197 gdb_mpz result;
198 mpz_mul (result.m_val, m_val, other.m_val);
199 return result;
200 }
201
202 gdb_mpz operator/ (const gdb_mpz &other) const
203 {
204 gdb_mpz result;
205 mpz_tdiv_q (result.m_val, m_val, other.m_val);
206 return result;
207 }
208
209 gdb_mpz operator% (const gdb_mpz &other) const
210 {
211 gdb_mpz result;
212 mpz_tdiv_r (result.m_val, m_val, other.m_val);
213 return result;
214 }
215
302273ca
TT
216 gdb_mpz &operator+= (unsigned long other)
217 {
7aeae94f 218 mpz_add_ui (m_val, m_val, other);
302273ca
TT
219 return *this;
220 }
221
c225d6b8
TT
222 gdb_mpz &operator+= (const gdb_mpz &other)
223 {
224 mpz_add (m_val, m_val, other.m_val);
225 return *this;
226 }
227
228 gdb_mpz operator+ (const gdb_mpz &other) const
229 {
230 gdb_mpz result;
231 mpz_add (result.m_val, m_val, other.m_val);
232 return result;
233 }
234
302273ca
TT
235 gdb_mpz &operator-= (unsigned long other)
236 {
7aeae94f 237 mpz_sub_ui (m_val, m_val, other);
302273ca
TT
238 return *this;
239 }
240
c225d6b8
TT
241 gdb_mpz &operator-= (const gdb_mpz &other)
242 {
243 mpz_sub (m_val, m_val, other.m_val);
244 return *this;
245 }
246
247 gdb_mpz operator- (const gdb_mpz &other) const
248 {
249 gdb_mpz result;
250 mpz_sub (result.m_val, m_val, other.m_val);
251 return result;
252 }
253
302273ca
TT
254 gdb_mpz &operator<<= (unsigned long nbits)
255 {
7aeae94f 256 mpz_mul_2exp (m_val, m_val, nbits);
302273ca
TT
257 return *this;
258 }
259
c225d6b8
TT
260 gdb_mpz operator<< (unsigned long nbits) const
261 {
262 gdb_mpz result;
263 mpz_mul_2exp (result.m_val, m_val, nbits);
264 return result;
265 }
266
267 gdb_mpz operator>> (unsigned long nbits) const
268 {
269 gdb_mpz result;
270 mpz_tdiv_q_2exp (result.m_val, m_val, nbits);
271 return result;
272 }
273
274 gdb_mpz &operator>>= (unsigned long nbits)
275 {
276 mpz_tdiv_q_2exp (m_val, m_val, nbits);
277 return *this;
278 }
279
280 gdb_mpz operator& (const gdb_mpz &other) const
281 {
282 gdb_mpz result;
283 mpz_and (result.m_val, m_val, other.m_val);
284 return result;
285 }
286
287 gdb_mpz operator| (const gdb_mpz &other) const
288 {
289 gdb_mpz result;
290 mpz_ior (result.m_val, m_val, other.m_val);
291 return result;
292 }
293
294 gdb_mpz operator^ (const gdb_mpz &other) const
295 {
296 gdb_mpz result;
297 mpz_xor (result.m_val, m_val, other.m_val);
298 return result;
299 }
300
302273ca
TT
301 bool operator> (const gdb_mpz &other) const
302 {
7aeae94f 303 return mpz_cmp (m_val, other.m_val) > 0;
302273ca
TT
304 }
305
c225d6b8
TT
306 bool operator>= (const gdb_mpz &other) const
307 {
308 return mpz_cmp (m_val, other.m_val) >= 0;
309 }
310
311 bool operator< (const gdb_mpz &other) const
312 {
313 return mpz_cmp (m_val, other.m_val) < 0;
314 }
315
316 bool operator<= (const gdb_mpz &other) const
317 {
318 return mpz_cmp (m_val, other.m_val) <= 0;
319 }
320
767c4b92 321 bool operator< (long other) const
302273ca 322 {
7aeae94f 323 return mpz_cmp_si (m_val, other) < 0;
302273ca
TT
324 }
325
326 bool operator== (int other) const
327 {
7aeae94f 328 return mpz_cmp_si (m_val, other) == 0;
302273ca
TT
329 }
330
767c4b92
TT
331 bool operator== (long other) const
332 {
333 return mpz_cmp_si (m_val, other) == 0;
334 }
335
336 bool operator== (unsigned long other) const
337 {
338 return mpz_cmp_ui (m_val, other) == 0;
339 }
340
341 template<typename T,
342 typename = gdb::Requires<
343 gdb::And<std::is_integral<T>,
344 std::integral_constant<bool,
345 (sizeof (T) > sizeof (long))>>
346 >
347 >
348 bool operator== (T src)
349 {
350 return *this == gdb_mpz (src);
351 }
352
302273ca
TT
353 bool operator== (const gdb_mpz &other) const
354 {
7aeae94f 355 return mpz_cmp (m_val, other.m_val) == 0;
302273ca
TT
356 }
357
c225d6b8
TT
358 bool operator!= (const gdb_mpz &other) const
359 {
360 return mpz_cmp (m_val, other.m_val) != 0;
361 }
362
b34c74ab
JB
363private:
364
365 /* Helper template for constructor and operator=. */
366 template<typename T> void set (T src);
63c457b9
JB
367
368 /* Low-level function to export VAL into BUF as a number whose byte size
369 is the size of BUF.
370
371 If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
372 Otherwise, export it as a signed value.
373
374 The API is inspired from GMP's mpz_export, hence the naming and types
375 of the following parameter:
376 - ENDIAN should be:
287de656 377 . 1 for most significant byte first; or
63c457b9
JB
378 . -1 for least significant byte first; or
379 . 0 for native endianness.
380
1c805ba0
TT
381 If SAFE is true, an error is raised if BUF is not large enough to
382 contain the value being exported. If SAFE is false, the value is
383 truncated to fit in BUF. */
384 void export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
385 bool safe) const;
7aeae94f
TT
386
387 friend struct gdb_mpq;
388 friend struct gdb_mpf;
389
390 mpz_t m_val;
b34c74ab
JB
391};
392
393/* A class to make it easier to use GMP's mpq_t values within GDB. */
394
395struct gdb_mpq
396{
b34c74ab 397 /* Constructors. */
81768386 398 gdb_mpq () { mpq_init (m_val); }
b34c74ab
JB
399
400 explicit gdb_mpq (const mpq_t &from_val)
401 {
81768386
TT
402 mpq_init (m_val);
403 mpq_set (m_val, from_val);
b34c74ab
JB
404 }
405
406 gdb_mpq (const gdb_mpq &from)
407 {
81768386
TT
408 mpq_init (m_val);
409 mpq_set (m_val, from.m_val);
b34c74ab
JB
410 }
411
412 explicit gdb_mpq (gdb_mpq &&from)
413 {
81768386
TT
414 mpq_init (m_val);
415 mpq_swap (m_val, from.m_val);
b34c74ab
JB
416 }
417
302273ca
TT
418 gdb_mpq (const gdb_mpz &num, const gdb_mpz &denom)
419 {
81768386
TT
420 mpq_init (m_val);
421 mpz_set (mpq_numref (m_val), num.m_val);
422 mpz_set (mpq_denref (m_val), denom.m_val);
423 mpq_canonicalize (m_val);
302273ca
TT
424 }
425
7607de94
TT
426 gdb_mpq (long num, long denom)
427 {
81768386
TT
428 mpq_init (m_val);
429 mpq_set_si (m_val, num, denom);
430 mpq_canonicalize (m_val);
7607de94
TT
431 }
432
b34c74ab
JB
433 /* Copy assignment operator. */
434 gdb_mpq &operator= (const gdb_mpq &from)
435 {
81768386 436 mpq_set (m_val, from.m_val);
b34c74ab
JB
437 return *this;
438 }
439
440 gdb_mpq &operator= (gdb_mpq &&from)
441 {
81768386 442 mpq_swap (m_val, from.m_val);
b34c74ab
JB
443 return *this;
444 }
445
302273ca
TT
446 gdb_mpq &operator= (const gdb_mpz &from)
447 {
81768386 448 mpq_set_z (m_val, from.m_val);
302273ca
TT
449 return *this;
450 }
451
7607de94
TT
452 gdb_mpq &operator= (double d)
453 {
81768386 454 mpq_set_d (m_val, d);
7607de94
TT
455 return *this;
456 }
457
458 /* Return the sign of this value. This returns -1 for a negative
459 value, 0 if the value is 0, and 1 for a positive value. */
460 int sgn () const
81768386 461 { return mpq_sgn (m_val); }
7607de94
TT
462
463 gdb_mpq operator+ (const gdb_mpq &other) const
464 {
465 gdb_mpq result;
81768386 466 mpq_add (result.m_val, m_val, other.m_val);
7607de94
TT
467 return result;
468 }
469
470 gdb_mpq operator- (const gdb_mpq &other) const
471 {
472 gdb_mpq result;
81768386 473 mpq_sub (result.m_val, m_val, other.m_val);
7607de94
TT
474 return result;
475 }
476
477 gdb_mpq operator* (const gdb_mpq &other) const
478 {
479 gdb_mpq result;
81768386 480 mpq_mul (result.m_val, m_val, other.m_val);
7607de94
TT
481 return result;
482 }
483
484 gdb_mpq operator/ (const gdb_mpq &other) const
485 {
486 gdb_mpq result;
81768386 487 mpq_div (result.m_val, m_val, other.m_val);
7607de94
TT
488 return result;
489 }
490
491 gdb_mpq &operator*= (const gdb_mpq &other)
492 {
81768386 493 mpq_mul (m_val, m_val, other.m_val);
7607de94
TT
494 return *this;
495 }
496
497 gdb_mpq &operator/= (const gdb_mpq &other)
498 {
81768386 499 mpq_div (m_val, m_val, other.m_val);
7607de94
TT
500 return *this;
501 }
502
503 bool operator== (const gdb_mpq &other) const
504 {
81768386 505 return mpq_cmp (m_val, other.m_val) == 0;
7607de94
TT
506 }
507
508 bool operator< (const gdb_mpq &other) const
509 {
81768386 510 return mpq_cmp (m_val, other.m_val) < 0;
7607de94
TT
511 }
512
b34c74ab 513 /* Return a string representing VAL as "<numerator> / <denominator>". */
81768386 514 std::string str () const { return gmp_string_printf ("%Qd", m_val); }
b34c74ab
JB
515
516 /* Return VAL rounded to the nearest integer. */
517 gdb_mpz get_rounded () const;
518
302273ca
TT
519 /* Return this value as an integer, rounded toward zero. */
520 gdb_mpz as_integer () const
521 {
522 gdb_mpz result;
81768386 523 mpz_tdiv_q (result.m_val, mpq_numref (m_val), mpq_denref (m_val));
302273ca
TT
524 return result;
525 }
526
7607de94
TT
527 /* Return this value converted to a host double. */
528 double as_double () const
81768386 529 { return mpq_get_d (m_val); }
7607de94 530
c9f0b43f
JB
531 /* Set VAL from the contents of the given byte array (BUF), which
532 contains the unscaled value of a fixed point type object.
533 The byte size of the data is the size of BUF.
534
535 BYTE_ORDER provides the byte_order to use when reading the data.
b34c74ab
JB
536
537 UNSIGNED_P indicates whether the number has an unsigned type.
538 SCALING_FACTOR is the scaling factor to apply after having
539 read the unscaled value from our buffer. */
c9f0b43f 540 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
b34c74ab
JB
541 enum bfd_endian byte_order, bool unsigned_p,
542 const gdb_mpq &scaling_factor);
543
c9f0b43f
JB
544 /* Write VAL into BUF as fixed point value following the given BYTE_ORDER.
545 The size of BUF is used as the length to write the value into.
b34c74ab
JB
546
547 UNSIGNED_P indicates whether the number has an unsigned type.
548 SCALING_FACTOR is the scaling factor to apply before writing
549 the unscaled value to our buffer. */
c9f0b43f 550 void write_fixed_point (gdb::array_view<gdb_byte> buf,
b34c74ab
JB
551 enum bfd_endian byte_order, bool unsigned_p,
552 const gdb_mpq &scaling_factor) const;
553
554 /* The destructor. */
81768386
TT
555 ~gdb_mpq () { mpq_clear (m_val); }
556
557private:
558
559 friend struct gdb_mpf;
560
561 mpq_t m_val;
b34c74ab
JB
562};
563
564/* A class to make it easier to use GMP's mpf_t values within GDB.
565
566 Should MPFR become a required dependency, we should probably
567 drop this class in favor of using MPFR. */
568
569struct gdb_mpf
570{
b34c74ab 571 /* Constructors. */
d0aa28e1 572 gdb_mpf () { mpf_init (m_val); }
b34c74ab
JB
573
574 DISABLE_COPY_AND_ASSIGN (gdb_mpf);
575
576 /* Set VAL from the contents of the given buffer (BUF), which
577 contains the unscaled value of a fixed point type object
578 with the given size (LEN) and byte order (BYTE_ORDER).
579
580 UNSIGNED_P indicates whether the number has an unsigned type.
581 SCALING_FACTOR is the scaling factor to apply after having
582 read the unscaled value from our buffer. */
c9f0b43f 583 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
b34c74ab
JB
584 enum bfd_endian byte_order, bool unsigned_p,
585 const gdb_mpq &scaling_factor)
586 {
587 gdb_mpq tmp_q;
588
c9f0b43f 589 tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor);
d0aa28e1 590 mpf_set_q (m_val, tmp_q.m_val);
b34c74ab
JB
591 }
592
d0aa28e1
TT
593 /* Convert this value to a string. FMT is the format to use, and
594 should have a single '%' substitution. */
595 std::string str (const char *fmt) const
596 { return gmp_string_printf (fmt, m_val); }
597
b34c74ab 598 /* The destructor. */
d0aa28e1
TT
599 ~gdb_mpf () { mpf_clear (m_val); }
600
601private:
602
603 mpf_t m_val;
b34c74ab
JB
604};
605
606/* See declaration above. */
607
608template<typename T>
609void
610gdb_mpz::set (T src)
611{
7aeae94f 612 mpz_import (m_val, 1 /* count */, -1 /* order */,
b34c74ab
JB
613 sizeof (T) /* size */, 0 /* endian (0 = native) */,
614 0 /* nails */, &src /* op */);
615 if (std::is_signed<T>::value && src < 0)
616 {
617 /* mpz_import does not handle the sign, so our value was imported
618 as an unsigned. Adjust that imported value so as to make it
619 the correct negative value. */
620 gdb_mpz neg_offset;
621
7aeae94f
TT
622 mpz_ui_pow_ui (neg_offset.m_val, 2, sizeof (T) * HOST_CHAR_BIT);
623 mpz_sub (m_val, m_val, neg_offset.m_val);
b34c74ab
JB
624 }
625}
626
627/* See declaration above. */
628
629template<typename T>
630T
631gdb_mpz::as_integer () const
632{
63c457b9 633 T result;
b34c74ab 634
1c805ba0 635 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
63c457b9 636 0 /* endian (0 = native) */,
1c805ba0
TT
637 !std::is_signed<T>::value /* unsigned_p */,
638 true /* safe */);
b34c74ab 639
b34c74ab
JB
640 return result;
641}
642
767c4b92
TT
643/* See declaration above. */
644
645template<typename T>
646T
647gdb_mpz::as_integer_truncate () const
648{
649 T result;
650
651 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
652 0 /* endian (0 = native) */,
653 !std::is_signed<T>::value /* unsigned_p */,
654 false /* safe */);
655
656 return result;
657}
658
b34c74ab 659#endif