Remove path name from test case
[binutils-gdb.git] / gdb / gmp-utils.h
1 /* Miscellaneous routines making it easier to use GMP within GDB's framework.
2
3 Copyright (C) 2019-2023 Free Software Foundation, Inc.
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
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
30 /* Same as gmp_asprintf, but returning an std::string. */
31
32 std::string gmp_string_printf (const char *fmt, ...);
33
34 struct gdb_mpq;
35 struct gdb_mpf;
36
37 /* A class to make it easier to use GMP's mpz_t values within GDB. */
38
39 struct gdb_mpz
40 {
41 /* Constructors. */
42 gdb_mpz () { mpz_init (m_val); }
43
44 explicit gdb_mpz (const mpz_t &from_val)
45 {
46 mpz_init (m_val);
47 mpz_set (m_val, from_val);
48 }
49
50 gdb_mpz (const gdb_mpz &from)
51 {
52 mpz_init (m_val);
53 mpz_set (m_val, from.m_val);
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 {
63 mpz_init (m_val);
64 set (src);
65 }
66
67 explicit gdb_mpz (gdb_mpz &&from)
68 {
69 mpz_init (m_val);
70 mpz_swap (m_val, from.m_val);
71 }
72
73
74 gdb_mpz &operator= (const gdb_mpz &from)
75 {
76 mpz_set (m_val, from.m_val);
77 return *this;
78 }
79
80 gdb_mpz &operator= (gdb_mpz &&other)
81 {
82 mpz_swap (m_val, other.m_val);
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
93 gdb_mpz &operator= (bool src)
94 {
95 mpz_set_ui (m_val, (unsigned long) src);
96 return *this;
97 }
98
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 {
103 return mpz_set_str (m_val, str, base) != -1;
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;
110 mpz_ui_pow_ui (result.m_val, base, exp);
111 return result;
112 }
113
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
122 /* Convert this value to an integer of the given type.
123
124 The return type can signed or unsigned, with no size restriction. */
125 template<typename T> T as_integer () const;
126
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
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.
136
137 UNSIGNED_P indicates whether the number has an unsigned type. */
138 void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order,
139 bool unsigned_p);
140
141 /* Write VAL into BUF as a number whose byte size is the size of BUF,
142 using the given BYTE_ORDER.
143
144 UNSIGNED_P indicates whether the number has an unsigned type. */
145 void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
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 }
160
161 /* Return a string containing VAL. */
162 std::string str () const { return gmp_string_printf ("%Zd", m_val); }
163
164 /* The destructor. */
165 ~gdb_mpz () { mpz_clear (m_val); }
166
167 /* Negate this value in place. */
168 void negate ()
169 {
170 mpz_neg (m_val, m_val);
171 }
172
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
189 gdb_mpz &operator*= (long other)
190 {
191 mpz_mul_si (m_val, m_val, other);
192 return *this;
193 }
194
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
216 gdb_mpz &operator+= (unsigned long other)
217 {
218 mpz_add_ui (m_val, m_val, other);
219 return *this;
220 }
221
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
235 gdb_mpz &operator-= (unsigned long other)
236 {
237 mpz_sub_ui (m_val, m_val, other);
238 return *this;
239 }
240
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
254 gdb_mpz &operator<<= (unsigned long nbits)
255 {
256 mpz_mul_2exp (m_val, m_val, nbits);
257 return *this;
258 }
259
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
301 bool operator> (const gdb_mpz &other) const
302 {
303 return mpz_cmp (m_val, other.m_val) > 0;
304 }
305
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
321 bool operator< (long other) const
322 {
323 return mpz_cmp_si (m_val, other) < 0;
324 }
325
326 /* We want an operator== that can handle all integer types. For
327 types that are 'long' or narrower, we can use a GMP function and
328 avoid boxing the RHS. But, because overloading based on integer
329 type is a pain in C++, we accept all such types here and check
330 the size in the body. */
331 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
332 bool operator== (T other) const
333 {
334 if (std::is_signed<T>::value)
335 {
336 if (sizeof (T) <= sizeof (long))
337 return mpz_cmp_si (m_val, other) == 0;
338 }
339 else
340 {
341 if (sizeof (T) <= sizeof (unsigned long))
342 return mpz_cmp_ui (m_val, other) == 0;
343 }
344 return *this == gdb_mpz (other);
345 }
346
347 bool operator== (const gdb_mpz &other) const
348 {
349 return mpz_cmp (m_val, other.m_val) == 0;
350 }
351
352 bool operator!= (const gdb_mpz &other) const
353 {
354 return mpz_cmp (m_val, other.m_val) != 0;
355 }
356
357 private:
358
359 /* Helper template for constructor and operator=. */
360 template<typename T> void set (T src);
361
362 /* Low-level function to export VAL into BUF as a number whose byte size
363 is the size of BUF.
364
365 If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
366 Otherwise, export it as a signed value.
367
368 The API is inspired from GMP's mpz_export, hence the naming and types
369 of the following parameter:
370 - ENDIAN should be:
371 . 1 for most significant byte first; or
372 . -1 for least significant byte first; or
373 . 0 for native endianness.
374
375 If SAFE is true, an error is raised if BUF is not large enough to
376 contain the value being exported. If SAFE is false, the value is
377 truncated to fit in BUF. */
378 void export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
379 bool safe) const;
380
381 friend struct gdb_mpq;
382 friend struct gdb_mpf;
383
384 mpz_t m_val;
385 };
386
387 /* A class to make it easier to use GMP's mpq_t values within GDB. */
388
389 struct gdb_mpq
390 {
391 /* Constructors. */
392 gdb_mpq () { mpq_init (m_val); }
393
394 explicit gdb_mpq (const mpq_t &from_val)
395 {
396 mpq_init (m_val);
397 mpq_set (m_val, from_val);
398 }
399
400 gdb_mpq (const gdb_mpq &from)
401 {
402 mpq_init (m_val);
403 mpq_set (m_val, from.m_val);
404 }
405
406 explicit gdb_mpq (gdb_mpq &&from)
407 {
408 mpq_init (m_val);
409 mpq_swap (m_val, from.m_val);
410 }
411
412 gdb_mpq (const gdb_mpz &num, const gdb_mpz &denom)
413 {
414 mpq_init (m_val);
415 mpz_set (mpq_numref (m_val), num.m_val);
416 mpz_set (mpq_denref (m_val), denom.m_val);
417 mpq_canonicalize (m_val);
418 }
419
420 gdb_mpq (long num, long denom)
421 {
422 mpq_init (m_val);
423 mpq_set_si (m_val, num, denom);
424 mpq_canonicalize (m_val);
425 }
426
427 /* Copy assignment operator. */
428 gdb_mpq &operator= (const gdb_mpq &from)
429 {
430 mpq_set (m_val, from.m_val);
431 return *this;
432 }
433
434 gdb_mpq &operator= (gdb_mpq &&from)
435 {
436 mpq_swap (m_val, from.m_val);
437 return *this;
438 }
439
440 gdb_mpq &operator= (const gdb_mpz &from)
441 {
442 mpq_set_z (m_val, from.m_val);
443 return *this;
444 }
445
446 gdb_mpq &operator= (double d)
447 {
448 mpq_set_d (m_val, d);
449 return *this;
450 }
451
452 /* Return the sign of this value. This returns -1 for a negative
453 value, 0 if the value is 0, and 1 for a positive value. */
454 int sgn () const
455 { return mpq_sgn (m_val); }
456
457 gdb_mpq operator+ (const gdb_mpq &other) const
458 {
459 gdb_mpq result;
460 mpq_add (result.m_val, m_val, other.m_val);
461 return result;
462 }
463
464 gdb_mpq operator- (const gdb_mpq &other) const
465 {
466 gdb_mpq result;
467 mpq_sub (result.m_val, m_val, other.m_val);
468 return result;
469 }
470
471 gdb_mpq operator* (const gdb_mpq &other) const
472 {
473 gdb_mpq result;
474 mpq_mul (result.m_val, m_val, other.m_val);
475 return result;
476 }
477
478 gdb_mpq operator/ (const gdb_mpq &other) const
479 {
480 gdb_mpq result;
481 mpq_div (result.m_val, m_val, other.m_val);
482 return result;
483 }
484
485 gdb_mpq &operator*= (const gdb_mpq &other)
486 {
487 mpq_mul (m_val, m_val, other.m_val);
488 return *this;
489 }
490
491 gdb_mpq &operator/= (const gdb_mpq &other)
492 {
493 mpq_div (m_val, m_val, other.m_val);
494 return *this;
495 }
496
497 bool operator== (const gdb_mpq &other) const
498 {
499 return mpq_cmp (m_val, other.m_val) == 0;
500 }
501
502 bool operator< (const gdb_mpq &other) const
503 {
504 return mpq_cmp (m_val, other.m_val) < 0;
505 }
506
507 /* Return a string representing VAL as "<numerator> / <denominator>". */
508 std::string str () const { return gmp_string_printf ("%Qd", m_val); }
509
510 /* Return VAL rounded to the nearest integer. */
511 gdb_mpz get_rounded () const;
512
513 /* Return this value as an integer, rounded toward zero. */
514 gdb_mpz as_integer () const
515 {
516 gdb_mpz result;
517 mpz_tdiv_q (result.m_val, mpq_numref (m_val), mpq_denref (m_val));
518 return result;
519 }
520
521 /* Return this value converted to a host double. */
522 double as_double () const
523 { return mpq_get_d (m_val); }
524
525 /* Set VAL from the contents of the given byte array (BUF), which
526 contains the unscaled value of a fixed point type object.
527 The byte size of the data is the size of BUF.
528
529 BYTE_ORDER provides the byte_order to use when reading the data.
530
531 UNSIGNED_P indicates whether the number has an unsigned type.
532 SCALING_FACTOR is the scaling factor to apply after having
533 read the unscaled value from our buffer. */
534 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
535 enum bfd_endian byte_order, bool unsigned_p,
536 const gdb_mpq &scaling_factor);
537
538 /* Write VAL into BUF as fixed point value following the given BYTE_ORDER.
539 The size of BUF is used as the length to write the value into.
540
541 UNSIGNED_P indicates whether the number has an unsigned type.
542 SCALING_FACTOR is the scaling factor to apply before writing
543 the unscaled value to our buffer. */
544 void write_fixed_point (gdb::array_view<gdb_byte> buf,
545 enum bfd_endian byte_order, bool unsigned_p,
546 const gdb_mpq &scaling_factor) const;
547
548 /* The destructor. */
549 ~gdb_mpq () { mpq_clear (m_val); }
550
551 private:
552
553 friend struct gdb_mpf;
554
555 mpq_t m_val;
556 };
557
558 /* A class to make it easier to use GMP's mpf_t values within GDB.
559
560 Should MPFR become a required dependency, we should probably
561 drop this class in favor of using MPFR. */
562
563 struct gdb_mpf
564 {
565 /* Constructors. */
566 gdb_mpf () { mpf_init (m_val); }
567
568 DISABLE_COPY_AND_ASSIGN (gdb_mpf);
569
570 /* Set VAL from the contents of the given buffer (BUF), which
571 contains the unscaled value of a fixed point type object
572 with the given size (LEN) and byte order (BYTE_ORDER).
573
574 UNSIGNED_P indicates whether the number has an unsigned type.
575 SCALING_FACTOR is the scaling factor to apply after having
576 read the unscaled value from our buffer. */
577 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
578 enum bfd_endian byte_order, bool unsigned_p,
579 const gdb_mpq &scaling_factor)
580 {
581 gdb_mpq tmp_q;
582
583 tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor);
584 mpf_set_q (m_val, tmp_q.m_val);
585 }
586
587 /* Convert this value to a string. FMT is the format to use, and
588 should have a single '%' substitution. */
589 std::string str (const char *fmt) const
590 { return gmp_string_printf (fmt, m_val); }
591
592 /* The destructor. */
593 ~gdb_mpf () { mpf_clear (m_val); }
594
595 private:
596
597 mpf_t m_val;
598 };
599
600 /* See declaration above. */
601
602 template<typename T>
603 void
604 gdb_mpz::set (T src)
605 {
606 mpz_import (m_val, 1 /* count */, -1 /* order */,
607 sizeof (T) /* size */, 0 /* endian (0 = native) */,
608 0 /* nails */, &src /* op */);
609 if (std::is_signed<T>::value && src < 0)
610 {
611 /* mpz_import does not handle the sign, so our value was imported
612 as an unsigned. Adjust that imported value so as to make it
613 the correct negative value. */
614 gdb_mpz neg_offset;
615
616 mpz_ui_pow_ui (neg_offset.m_val, 2, sizeof (T) * HOST_CHAR_BIT);
617 mpz_sub (m_val, m_val, neg_offset.m_val);
618 }
619 }
620
621 /* See declaration above. */
622
623 template<typename T>
624 T
625 gdb_mpz::as_integer () const
626 {
627 T result;
628
629 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
630 0 /* endian (0 = native) */,
631 !std::is_signed<T>::value /* unsigned_p */,
632 true /* safe */);
633
634 return result;
635 }
636
637 /* See declaration above. */
638
639 template<typename T>
640 T
641 gdb_mpz::as_integer_truncate () const
642 {
643 T result;
644
645 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
646 0 /* endian (0 = native) */,
647 !std::is_signed<T>::value /* unsigned_p */,
648 false /* safe */);
649
650 return result;
651 }
652
653 #endif