Additions to gdb_mpz

In preparation for adding more 128-bit support to gdb, a few additions
to gdb_mpz are needed.

First, this adds a new 'as_integer_truncate' method.  This method
works like 'as_integer' but does not require the value to fit in the
target type -- it just truncates.

Second, gdb_mpz::export_bits is changed to handle the somewhat unusual
situation of zero-length types.  This can happen for a Rust '()' type;
but I think other languages have zero-bit integer types as well.

Finally, this adds some operator== overloads.
This commit is contained in:
Tom Tromey 2023-03-27 14:35:17 -06:00
parent c53c6186c8
commit 767c4b92bc
2 changed files with 52 additions and 6 deletions

View File

@ -69,19 +69,21 @@ void
gdb_mpz::export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
bool safe) const
{
gdb_assert (buf.size () > 0);
int sign = mpz_sgn (m_val);
if (sign == 0)
{
/* Our value is zero, so no need to call mpz_export to do the work,
especially since mpz_export's documentation explicitly says
that the function is a noop in this case. Just write zero to
BUF ourselves. */
memset (buf.data (), 0, buf.size ());
BUF ourselves, if it is non-empty. In some languages, a
zero-bit type can exist and this is also fine. */
if (buf.size () > 0)
memset (buf.data (), 0, buf.size ());
return;
}
gdb_assert (buf.size () > 0);
if (safe)
{
/* Determine the maximum range of values that our buffer can

View File

@ -119,11 +119,17 @@ struct gdb_mpz
return result;
}
/* Convert VAL to an integer of the given type.
/* Convert this value to an integer of the given type.
The return type can signed or unsigned, with no size restriction. */
template<typename T> T as_integer () const;
/* Convert this value to an integer of the given type. If this
value is too large, it is truncated.
The return type can signed or unsigned, with no size restriction. */
template<typename T> T as_integer_truncate () const;
/* Set VAL by importing the number stored in the byte array (BUF),
using the given BYTE_ORDER. The size of the data to read is
the byte array's size.
@ -312,7 +318,7 @@ struct gdb_mpz
return mpz_cmp (m_val, other.m_val) <= 0;
}
bool operator< (int other) const
bool operator< (long other) const
{
return mpz_cmp_si (m_val, other) < 0;
}
@ -322,6 +328,28 @@ struct gdb_mpz
return mpz_cmp_si (m_val, other) == 0;
}
bool operator== (long other) const
{
return mpz_cmp_si (m_val, other) == 0;
}
bool operator== (unsigned long other) const
{
return mpz_cmp_ui (m_val, other) == 0;
}
template<typename T,
typename = gdb::Requires<
gdb::And<std::is_integral<T>,
std::integral_constant<bool,
(sizeof (T) > sizeof (long))>>
>
>
bool operator== (T src)
{
return *this == gdb_mpz (src);
}
bool operator== (const gdb_mpz &other) const
{
return mpz_cmp (m_val, other.m_val) == 0;
@ -612,4 +640,20 @@ gdb_mpz::as_integer () const
return result;
}
/* See declaration above. */
template<typename T>
T
gdb_mpz::as_integer_truncate () const
{
T result;
this->export_bits ({(gdb_byte *) &result, sizeof (result)},
0 /* endian (0 = native) */,
!std::is_signed<T>::value /* unsigned_p */,
false /* safe */);
return result;
}
#endif