GCC v8.2
[gcc.git] / gcc / ada / gcc-interface / cuintp.c
1 /****************************************************************************
2  *                                                                          *
3  *                        GNAT COMPILER COMPONENTS                          *
4  *                                                                          *
5  *                               C U I N T P                                *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 1992-2016, Free Software Foundation, Inc.         *
10  *                                                                          *
11  * GNAT is free software;  you can  redistribute it  and/or modify it under *
12  * terms of the  GNU General Public License as published  by the Free Soft- *
13  * ware  Foundation;  either version 3,  or (at your option) any later ver- *
14  * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15  * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
17  * for  more details.  You should have received a copy of the GNU General   *
18  * Public License along with GCC; see the file COPYING3.  If not see        *
19  * <http://www.gnu.org/licenses/>.                                          *
20  *                                                                          *
21  * GNAT was originally developed  by the GNAT team at  New York University. *
22  * Extensive contributions were provided by Ada Core Technologies Inc.      *
23  *                                                                          *
24  ****************************************************************************/
25
26 /* This file corresponds to the Ada package body Uintp.  It was created
27    manually from the files uintp.ads and uintp.adb.  */
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "vec.h"
34 #include "alias.h"
35 #include "tree.h"
36 #include "inchash.h"
37 #include "fold-const.h"
38
39 #include "ada.h"
40 #include "types.h"
41 #include "uintp.h"
42 #include "ada-tree.h"
43 #include "gigi.h"
44
45 /* Universal integers are represented by the Uint type which is an index into
46    the Uints_Ptr table containing Uint_Entry values.  A Uint_Entry contains an
47    index and length for getting the "digits" of the universal integer from the
48    Udigits_Ptr table.
49
50    For efficiency, this method is used only for integer values larger than the
51    constant Uint_Bias.  If a Uint is less than this constant, then it contains
52    the integer value itself.  The origin of the Uints_Ptr table is adjusted so
53    that a Uint value of Uint_Bias indexes the first element.
54
55    First define a utility function that is build_int_cst for integral types and
56    does a conversion for floating-point types.  */
57
58 static tree
59 build_cst_from_int (tree type, HOST_WIDE_INT low)
60 {
61   if (SCALAR_FLOAT_TYPE_P (type))
62     return convert (type, build_int_cst (gnat_type_for_size (32, 0), low));
63   else
64     return build_int_cst (type, low);
65 }
66
67 /* Similar to UI_To_Int, but return a GCC INTEGER_CST or REAL_CST node,
68    depending on whether TYPE is an integral or real type.  Overflow is tested
69    by the constant-folding used to build the node.  TYPE is the GCC type of
70    the resulting node.  */
71
72 tree
73 UI_To_gnu (Uint Input, tree type)
74 {
75   /* We might have a TYPE with biased representation and be passed an unbiased
76      value that doesn't fit.  We always use an unbiased type to be able to hold
77      any such possible value for intermediate computations and then rely on a
78      conversion back to TYPE to perform the bias adjustment when need be.  */
79   tree comp_type
80     = TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)
81       ? get_base_type (type) : type;
82   tree gnu_ret;
83
84   if (Input <= Uint_Direct_Last)
85     gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias);
86   else
87     {
88       Int Idx = Uints_Ptr[Input].Loc;
89       Pos Length = Uints_Ptr[Input].Length;
90       Int First = Udigits_Ptr[Idx];
91       tree gnu_base;
92
93       gcc_assert (Length > 0);
94
95       /* The computations we perform below always require a type at least as
96          large as an integer not to overflow.  FP types are always fine, but
97          INTEGER or ENUMERAL types we are handed may be too short.  We use a
98          base integer type node for the computations in this case and will
99          convert the final result back to the incoming type later on.  */
100       if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32)
101         comp_type = gnat_type_for_size (32, 0);
102
103       gnu_base = build_cst_from_int (comp_type, Base);
104
105       gnu_ret = build_cst_from_int (comp_type, First);
106       if (First < 0)
107         for (Idx++, Length--; Length; Idx++, Length--)
108           gnu_ret = fold_build2 (MINUS_EXPR, comp_type,
109                                  fold_build2 (MULT_EXPR, comp_type,
110                                               gnu_ret, gnu_base),
111                                  build_cst_from_int (comp_type,
112                                                      Udigits_Ptr[Idx]));
113       else
114         for (Idx++, Length--; Length; Idx++, Length--)
115           gnu_ret = fold_build2 (PLUS_EXPR, comp_type,
116                                  fold_build2 (MULT_EXPR, comp_type,
117                                               gnu_ret, gnu_base),
118                                  build_cst_from_int (comp_type,
119                                                      Udigits_Ptr[Idx]));
120     }
121
122   gnu_ret = convert (type, gnu_ret);
123
124   /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET.  */
125   while ((TREE_CODE (gnu_ret) == NOP_EXPR
126           || TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
127          && TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
128     gnu_ret = TREE_OPERAND (gnu_ret, 0);
129
130   return gnu_ret;
131 }
132
133 /* Similar to UI_From_Int, but take a GCC INTEGER_CST.  We use UI_From_Int
134    when possible, i.e. for a 32-bit signed value, to take advantage of its
135    built-in caching mechanism.  For values of larger magnitude, we compute
136    digits into a vector and call Vector_To_Uint.  */
137
138 Uint
139 UI_From_gnu (tree Input)
140 {
141   tree gnu_type = TREE_TYPE (Input), gnu_base, gnu_temp;
142   /* UI_Base is defined so that 5 Uint digits is sufficient to hold the
143      largest possible signed 64-bit value.  */
144   const int Max_For_Dint = 5;
145   int v[Max_For_Dint], i;
146   Vector_Template temp;
147   Int_Vector vec;
148
149 #if HOST_BITS_PER_WIDE_INT == 64
150   /* On 64-bit hosts, tree_fits_shwi_p tells whether the input fits in a
151      signed 64-bit integer.  Then a truncation tells whether it fits
152      in a signed 32-bit integer.  */
153   if (tree_fits_shwi_p (Input))
154     {
155       HOST_WIDE_INT hw_input = tree_to_shwi (Input);
156       if (hw_input == (int) hw_input)
157         return UI_From_Int (hw_input);
158     }
159   else
160     return No_Uint;
161 #else
162   /* On 32-bit hosts, tree_fits_shwi_p tells whether the input fits in a
163      signed 32-bit integer.  Then a sign test tells whether it fits
164      in a signed 64-bit integer.  */
165   if (tree_fits_shwi_p (Input))
166     return UI_From_Int (tree_to_shwi (Input));
167
168   gcc_assert (TYPE_PRECISION (gnu_type) <= 64);
169   if (TYPE_UNSIGNED (gnu_type)
170       && TYPE_PRECISION (gnu_type) == 64
171       && wi::neg_p (Input, SIGNED))
172     return No_Uint;
173 #endif
174
175   gnu_base = build_int_cst (gnu_type, UI_Base);
176   gnu_temp = Input;
177
178   for (i = Max_For_Dint - 1; i >= 0; i--)
179     {
180       v[i] = tree_to_shwi (fold_build1 (ABS_EXPR, gnu_type,
181                                         fold_build2 (TRUNC_MOD_EXPR, gnu_type,
182                                                      gnu_temp, gnu_base)));
183       gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base);
184     }
185
186   temp.Low_Bound = 1;
187   temp.High_Bound = Max_For_Dint;
188   vec.Bounds = &temp;
189   vec.Array = v;
190   return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0);
191 }