diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-10-23 12:12:09 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-10-23 12:12:09 +0000 |
commit | cc5bf44923387bd79ed1834707b6462ad3d9b022 (patch) | |
tree | 57bcca6fb68e7c0a7b2adddcdc4cfc3e5b6cb1c6 /gcc/wide-int.h | |
parent | 5b2cae25833ee97389f5271a777b44f0cafea204 (diff) | |
download | gcc-cc5bf44923387bd79ed1834707b6462ad3d9b022.tar.gz |
Always treat trees as having their native precision by default.
Add wi::extend() and wi::address() to convert them to max_wide_int
and addr_wide_int.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@203961 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/wide-int.h')
-rw-r--r-- | gcc/wide-int.h | 298 |
1 files changed, 147 insertions, 151 deletions
diff --git a/gcc/wide-int.h b/gcc/wide-int.h index 3baba18677b..e7cff0f8c1e 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -251,6 +251,46 @@ along with GCC; see the file COPYING3. If not see #define ADDR_MAX_PRECISION \ ((ADDR_MAX_BITSIZE + 4 + HOST_BITS_PER_WIDE_INT - 1) & ~(HOST_BITS_PER_WIDE_INT - 1)) +/* The type of result produced by a binary operation on types T1 and T2. + Defined purely for brevity. */ +#define WI_BINARY_RESULT(T1, T2) \ + typename wi::binary_traits <T1, T2>::result_type + +/* The type of result produced by a unary operation on type T. */ +#define WI_UNARY_RESULT(T) \ + typename wi::unary_traits <T>::result_type + +/* Define a variable RESULT to hold the result of a binary operation on + X and Y, which have types T1 and T2 respectively. Define VAR to + point to the blocks of RESULT. Once the user of the macro has + filled in VAR, it should call RESULT.set_len to set the number + of initialized blocks. */ +#define WI_BINARY_RESULT_VAR(RESULT, VAL, T1, X, T2, Y) \ + WI_BINARY_RESULT (T1, T2) RESULT = \ + wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_result (X, Y); \ + HOST_WIDE_INT *VAL = RESULT.write_val () + +/* Similar for the result of a unary operation on X, which has type T. */ +#define WI_UNARY_RESULT_VAR(RESULT, VAL, T, X) \ + WI_UNARY_RESULT (T) RESULT = \ + wi::int_traits <WI_UNARY_RESULT (T)>::get_binary_result (X, X); \ + HOST_WIDE_INT *VAL = RESULT.write_val () + +template <typename T> struct generic_wide_int; +template <int N> struct fixed_wide_int_storage; +struct wide_int_storage; + +/* An N-bit integer. Until we can use typedef templates, use this instead. */ +#define FIXED_WIDE_INT(N) \ + generic_wide_int < fixed_wide_int_storage <N> > + +typedef generic_wide_int <wide_int_storage> wide_int; +typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) addr_wide_int; +typedef FIXED_WIDE_INT (MAX_BITSIZE_MODE_ANY_INT) max_wide_int; + +struct wide_int_ref_storage; +typedef generic_wide_int <wide_int_ref_storage> wide_int_ref; + namespace wi { /* Classifies an integer based on its precision. */ @@ -303,40 +343,70 @@ namespace wi a binary operation on two values of type T. */ template <typename T> struct unary_traits : public binary_traits <T, T> {}; -} -/* The type of result produced by a binary operation on types T1 and T2. - Defined purely for brevity. */ -#define WI_BINARY_RESULT(T1, T2) \ - typename wi::binary_traits <T1, T2>::result_type + /* Specify the result type for each supported combination of binary + inputs. Note that CONST_PRECISION and VAR_PRECISION cannot be + mixed, in order to give stronger type checking. When both inputs + are CONST_PRECISION, they must have the same precision. */ + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION> + { + typedef max_wide_int result_type; + }; -/* The type of result produced by a unary operation on type T. */ -#define WI_UNARY_RESULT(T) \ - typename wi::unary_traits <T>::result_type + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, FLEXIBLE_PRECISION, VAR_PRECISION> + { + typedef wide_int result_type; + }; -/* Define a variable RESULT to hold the result of a binary operation on - X and Y, which have types T1 and T2 respectively. Define VAR to - point to the blocks of RESULT. Once the user of the macro has - filled in VAR, it should call RESULT.set_len to set the number - of initialized blocks. */ -#define WI_BINARY_RESULT_VAR(RESULT, VAL, T1, X, T2, Y) \ - WI_BINARY_RESULT (T1, T2) RESULT = \ - wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_result (X, Y); \ - HOST_WIDE_INT *VAL = RESULT.write_val () + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION> + { + /* Spelled out explicitly (rather than through FIXED_WIDE_INT) + so as not to confuse gengtype. */ + typedef generic_wide_int < fixed_wide_int_storage + <int_traits <T2>::precision> > result_type; + }; -/* Similar for the result of a unary operation on X, which has type T. */ -#define WI_UNARY_RESULT_VAR(RESULT, VAL, T, X) \ - WI_UNARY_RESULT (T) RESULT = \ - wi::int_traits <WI_UNARY_RESULT (T)>::get_binary_result (X, X); \ - HOST_WIDE_INT *VAL = RESULT.write_val () + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, VAR_PRECISION, FLEXIBLE_PRECISION> + { + typedef wide_int result_type; + }; -template <typename T> struct generic_wide_int; + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION> + { + /* Spelled out explicitly (rather than through FIXED_WIDE_INT) + so as not to confuse gengtype. */ + typedef generic_wide_int < fixed_wide_int_storage + <int_traits <T1>::precision> > result_type; + }; -struct wide_int_storage; -typedef generic_wide_int <wide_int_storage> wide_int; + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION> + { + /* Spelled out explicitly (rather than through FIXED_WIDE_INT) + so as not to confuse gengtype. */ + STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision); + typedef generic_wide_int < fixed_wide_int_storage + <int_traits <T1>::precision> > result_type; + }; -struct wide_int_ref_storage; -typedef generic_wide_int <wide_int_ref_storage> wide_int_ref; + template <> + template <typename T1, typename T2> + struct binary_traits <T1, T2, VAR_PRECISION, VAR_PRECISION> + { + typedef wide_int result_type; + }; +} /* Public functions for querying and operating on integers. */ namespace wi @@ -572,38 +642,39 @@ public: bool OP (const T &c) const { return wi::F (*this, c); } #define UNARY_OPERATOR(OP, F) \ - generic_wide_int OP () const { return wi::F (*this); } + WI_UNARY_RESULT (generic_wide_int) OP () const { return wi::F (*this); } #define BINARY_OPERATOR(OP, F) \ template <typename T> \ - generic_wide_int OP (const T &c) const { return wi::F (*this, c); } + WI_BINARY_RESULT (generic_wide_int, T) \ + OP (const T &c) const { return wi::F (*this, c); } #define ASSIGNMENT_OPERATOR(OP, F) \ template <typename T> \ - generic_wide_int &OP (const T &c) { return (*this = wi::F (*this, c)); } + generic_wide_int &OP (const T &c) { return (*this = wi::F (*this, c)); } #define INCDEC_OPERATOR(OP, DELTA) \ generic_wide_int &OP () { *this += DELTA; return *this; } - UNARY_OPERATOR (operator ~, bit_not) \ - UNARY_OPERATOR (operator -, neg) \ - BINARY_PREDICATE (operator ==, eq_p) \ - BINARY_PREDICATE (operator !=, ne_p) \ - BINARY_OPERATOR (operator &, bit_and) \ - BINARY_OPERATOR (and_not, bit_and_not) \ - BINARY_OPERATOR (operator |, bit_or) \ - BINARY_OPERATOR (or_not, bit_or_not) \ - BINARY_OPERATOR (operator ^, bit_xor) \ - BINARY_OPERATOR (operator +, add) \ - BINARY_OPERATOR (operator -, sub) \ - BINARY_OPERATOR (operator *, mul) \ - ASSIGNMENT_OPERATOR (operator &=, bit_and) \ - ASSIGNMENT_OPERATOR (operator |=, bit_or) \ - ASSIGNMENT_OPERATOR (operator ^=, bit_xor) \ - ASSIGNMENT_OPERATOR (operator +=, add) \ - ASSIGNMENT_OPERATOR (operator -=, sub) \ - ASSIGNMENT_OPERATOR (operator *=, mul) \ - INCDEC_OPERATOR (operator ++, 1) \ + UNARY_OPERATOR (operator ~, bit_not) + UNARY_OPERATOR (operator -, neg) + BINARY_PREDICATE (operator ==, eq_p) + BINARY_PREDICATE (operator !=, ne_p) + BINARY_OPERATOR (operator &, bit_and) + BINARY_OPERATOR (and_not, bit_and_not) + BINARY_OPERATOR (operator |, bit_or) + BINARY_OPERATOR (or_not, bit_or_not) + BINARY_OPERATOR (operator ^, bit_xor) + BINARY_OPERATOR (operator +, add) + BINARY_OPERATOR (operator -, sub) + BINARY_OPERATOR (operator *, mul) + ASSIGNMENT_OPERATOR (operator &=, bit_and) + ASSIGNMENT_OPERATOR (operator |=, bit_or) + ASSIGNMENT_OPERATOR (operator ^=, bit_xor) + ASSIGNMENT_OPERATOR (operator +=, add) + ASSIGNMENT_OPERATOR (operator -=, sub) + ASSIGNMENT_OPERATOR (operator *=, mul) + INCDEC_OPERATOR (operator ++, 1) INCDEC_OPERATOR (operator --, -1) #undef BINARY_PREDICATE @@ -848,6 +919,19 @@ public: wide_int bswap () const; }; +namespace wi +{ + template <> + struct int_traits <wide_int_storage> + { + static const enum precision_type precision_type = VAR_PRECISION; + /* Guaranteed by a static assert in the wide_int_storage constructor. */ + static const bool host_dependent_precision = false; + template <typename T1, typename T2> + static wide_int get_binary_result (const T1 &, const T2 &); + }; +} + inline wide_int_storage::wide_int_storage () {} /* Initialize the storage from integer X, in its natural precision. @@ -933,19 +1017,6 @@ wide_int_storage::create (unsigned int precision) return x; } -namespace wi -{ - template <> - struct int_traits <wide_int_storage> - { - static const enum precision_type precision_type = VAR_PRECISION; - /* Guaranteed by a static assert in the wide_int_storage constructor. */ - static const bool host_dependent_precision = false; - template <typename T1, typename T2> - static wide_int get_binary_result (const T1 &, const T2 &); - }; -} - template <typename T1, typename T2> inline wide_int wi::int_traits <wide_int_storage>::get_binary_result (const T1 &x, const T2 &y) @@ -959,10 +1030,6 @@ wi::int_traits <wide_int_storage>::get_binary_result (const T1 &x, const T2 &y) return wide_int::create (wi::get_precision (x)); } -/* An N-bit integer. Until we can use typedef templates, use this instead. */ -#define FIXED_WIDE_INT(N) \ - generic_wide_int < fixed_wide_int_storage <N> > - /* The storage used by FIXED_WIDE_INT (N). */ template <int N> class GTY(()) fixed_wide_int_storage @@ -988,8 +1055,19 @@ public: bool = true); }; -typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) addr_wide_int; -typedef FIXED_WIDE_INT (MAX_BITSIZE_MODE_ANY_INT) max_wide_int; +namespace wi +{ + template <> + template <int N> + struct int_traits < fixed_wide_int_storage <N> > + { + static const enum precision_type precision_type = CONST_PRECISION; + static const bool host_dependent_precision = false; + static const unsigned int precision = N; + template <typename T1, typename T2> + static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &); + }; +} template <int N> inline fixed_wide_int_storage <N>::fixed_wide_int_storage () {} @@ -1071,20 +1149,6 @@ fixed_wide_int_storage <N>::from_array (const HOST_WIDE_INT *val, return result; } -namespace wi -{ - template <> - template <int N> - struct int_traits < fixed_wide_int_storage <N> > - { - static const enum precision_type precision_type = CONST_PRECISION; - static const bool host_dependent_precision = false; - static const unsigned int precision = N; - template <typename T1, typename T2> - static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &); - }; -} - template <int N> template <typename T1, typename T2> inline FIXED_WIDE_INT (N) @@ -1094,72 +1158,6 @@ get_binary_result (const T1 &, const T2 &) return FIXED_WIDE_INT (N) (); } -/* Specify the result type for each supported combination of binary - inputs. Note that CONST_PRECISION and VAR_PRECISION cannot be - mixed, in order to give stronger type checking. When both inputs - are CONST_PRECISION, they must have the same precision. */ -namespace wi -{ - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION> - { - typedef max_wide_int result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, FLEXIBLE_PRECISION, VAR_PRECISION> - { - typedef wide_int result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION> - { - /* Spelled out explicitly (rather than through FIXED_WIDE_INT) - so as not to confuse gengtype. */ - typedef generic_wide_int < fixed_wide_int_storage - <int_traits <T2>::precision> > result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, VAR_PRECISION, FLEXIBLE_PRECISION> - { - typedef wide_int result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION> - { - /* Spelled out explicitly (rather than through FIXED_WIDE_INT) - so as not to confuse gengtype. */ - typedef generic_wide_int < fixed_wide_int_storage - <int_traits <T1>::precision> > result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION> - { - /* Spelled out explicitly (rather than through FIXED_WIDE_INT) - so as not to confuse gengtype. */ - STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision); - typedef generic_wide_int < fixed_wide_int_storage - <int_traits <T1>::precision> > result_type; - }; - - template <> - template <typename T1, typename T2> - struct binary_traits <T1, T2, VAR_PRECISION, VAR_PRECISION> - { - typedef wide_int result_type; - }; -} - namespace wi { /* Implementation of int_traits for primitive integer types like "int". */ @@ -1288,9 +1286,7 @@ namespace wi template <> struct int_traits <wi::hwi_with_prec> { - /* Since we have a sign, we can extend or truncate the integer to - other precisions where necessary. */ - static const enum precision_type precision_type = FLEXIBLE_PRECISION; + static const enum precision_type precision_type = VAR_PRECISION; /* hwi_with_prec has an explicitly-given precision, rather than the precision of HOST_WIDE_INT. */ static const bool host_dependent_precision = false; |