blob: 7e91f51668eb48f280741f10e9004152a76c7516 [file]
/* Arbitrary precision integers.
Copyright (C) 2026 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_ANALYZER_INTEGER_H
#define GCC_ANALYZER_INTEGER_H
#include "pretty-print-markup.h"
namespace ana {
/* A class for arbitrary precision integers.
This is a C++ wrapper around gmp's mpz_t, with integration with
pretty_printer.
We don't use gmp's gmpxx.h: it uses exceptions, which we can't use. */
class integer
{
public:
static constexpr const char *dump_type_name = "integer";
integer ()
{
mpz_init (m_mpz);
}
integer (int i)
{
mpz_init_set_si (m_mpz, i);
}
~integer ()
{
mpz_clear (m_mpz);
}
integer (const integer &other)
{
mpz_init_set (m_mpz, other.m_mpz);
}
integer (integer &&other)
{
mpz_init (m_mpz);
std::swap (m_mpz, other.m_mpz);
}
/* Make it easier to use either integer or integer_with_unit
in a single template. */
const integer &
get_integer () const { return *this; }
bool
is_zero_p () const
{
return mpz_cmp_si (m_mpz, 0) == 0;
}
bool
is_one_p () const
{
return mpz_cmp_si (m_mpz, 1) == 0;
}
integer &
operator= (const integer &other)
{
mpz_set (m_mpz, other.m_mpz);
return *this;
}
integer &
operator= (integer &&other)
{
std::swap (m_mpz, other.m_mpz);
return *this;
}
static int
cmp (const integer &lhs, const integer &rhs)
{
return mpz_cmp (lhs.m_mpz, rhs.m_mpz);
}
void
dump_to_pp (pretty_printer *pp) const;
void
dump () const;
std::unique_ptr<json::value>
to_json () const;
std::unique_ptr<diagnostics::markup::node>
make_markup_node () const;
/* Overloaded operators. */
/* Comparison. */
bool
operator== (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) == 0;
}
bool
operator== (int i) const
{
return mpz_cmp_si (m_mpz, i) == 0;
}
bool
operator!= (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) != 0;
}
bool
operator!= (int i) const
{
return mpz_cmp_si (m_mpz, i) != 0;
}
bool
operator< (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) < 0;
}
bool
operator< (int i) const
{
return mpz_cmp_si (m_mpz, i) < 0;
}
bool
operator<= (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) <= 0;
}
bool
operator> (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) > 0;
}
bool
operator>= (const integer &other) const
{
return mpz_cmp (m_mpz, other.m_mpz) >= 0;
}
/* Addition. */
integer
operator+ (const integer &other) const
{
integer result;
mpz_add (result.m_mpz, m_mpz, other.m_mpz);
return result;
}
integer &
operator+= (const integer &other)
{
integer tmp = *this + other;
*this = std::move (tmp);
return *this;
}
/* Subtraction. */
integer
operator- (const integer &other) const
{
integer result;
mpz_sub (result.m_mpz, m_mpz, other.m_mpz);
return result;
}
integer
operator- () const
{
integer result;
mpz_neg (result.m_mpz, m_mpz);
return result;
}
integer &
operator-= (const integer &other)
{
integer tmp = *this - other;
*this = std::move (tmp);
return *this;
}
/* Multiplication. */
integer
operator* (const integer &other) const
{
integer result;
mpz_mul (result.m_mpz, m_mpz, other.m_mpz);
return result;
}
/* Division. */
integer
floor_div (const integer &other) const
{
gcc_assert (other != 0);
integer result;
mpz_fdiv_q (result.m_mpz, m_mpz, other.m_mpz);
return result;
}
/* Modulus. */
integer
floor_mod (const integer &other) const
{
gcc_assert (other != 0);
integer result;
mpz_fdiv_r (result.m_mpz, m_mpz, other.m_mpz);
return result;
}
long
as_long () const
{
return mpz_get_si (m_mpz);
}
unsigned long
as_unsigned_long () const
{
return mpz_get_ui (m_mpz);
}
mpz_t &
access_mpz () { return m_mpz; }
private:
mpz_t m_mpz;
};
integer
convert_from_integer_cst (const_tree int_cst);
tree
make_integer_cst_from_integer (tree type, const integer &value, bool wrap);
using concrete_integer = integer;
class pp_element_integer : public pp_element
{
public:
pp_element_integer (integer val)
: m_val (std::move (val))
{
}
void add_to_phase_2 (pp_markup::context &ctxt) final override
{
m_val.dump_to_pp (&ctxt.m_pp);
}
private:
integer m_val;
};
} // namespace ana
#endif /* GCC_ANALYZER_INTEGER_H */