1 /****************************************************************************
2  *                                                                          *
3  *                        GNAT COMPILER COMPONENTS                          *
4  *                                                                          *
5  *                               C U I N T P                                *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 1992-2014, 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 "tree.h"
34 
35 #include "ada.h"
36 #include "types.h"
37 #include "uintp.h"
38 #include "atree.h"
39 #include "elists.h"
40 #include "nlists.h"
41 #include "stringt.h"
42 #include "fe.h"
43 #include "ada-tree.h"
44 #include "gigi.h"
45 
46 /* Universal integers are represented by the Uint type which is an index into
47    the Uints_Ptr table containing Uint_Entry values.  A Uint_Entry contains an
48    index and length for getting the "digits" of the universal integer from the
49    Udigits_Ptr table.
50 
51    For efficiency, this method is used only for integer values larger than the
52    constant Uint_Bias.  If a Uint is less than this constant, then it contains
53    the integer value itself.  The origin of the Uints_Ptr table is adjusted so
54    that a Uint value of Uint_Bias indexes the first element.
55 
56    First define a utility function that operates like build_int_cst for
57    integral types and does a conversion to floating-point for real types.  */
58 
59 static tree
build_cst_from_int(tree type,HOST_WIDE_INT low)60 build_cst_from_int (tree type, HOST_WIDE_INT low)
61 {
62   if (SCALAR_FLOAT_TYPE_P (type))
63     return convert (type, build_int_cst (gnat_type_for_size (32, 0), low));
64   else
65     return build_int_cst_type (type, low);
66 }
67 
68 /* Similar to UI_To_Int, but return a GCC INTEGER_CST or REAL_CST node,
69    depending on whether TYPE is an integral or real type.  Overflow is tested
70    by the constant-folding used to build the node.  TYPE is the GCC type of
71    the resulting node.  */
72 
73 tree
UI_To_gnu(Uint Input,tree type)74 UI_To_gnu (Uint Input, tree type)
75 {
76   tree gnu_ret;
77 
78   /* We might have a TYPE with biased representation and be passed an
79      unbiased value that doesn't fit.  We always use an unbiased type able
80      to hold any such possible value for intermediate computations, and
81      then rely on a conversion back to TYPE to perform the bias adjustment
82      when need be.  */
83 
84   int biased_type_p
85     = (TREE_CODE (type) == INTEGER_TYPE
86        && TYPE_BIASED_REPRESENTATION_P (type));
87 
88   tree comp_type = biased_type_p ? get_base_type (type) : type;
89 
90   if (Input <= Uint_Direct_Last)
91     gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias);
92   else
93     {
94       Int Idx = Uints_Ptr[Input].Loc;
95       Pos Length = Uints_Ptr[Input].Length;
96       Int First = Udigits_Ptr[Idx];
97       tree gnu_base;
98 
99       gcc_assert (Length > 0);
100 
101       /* The computations we perform below always require a type at least as
102 	 large as an integer not to overflow.  FP types are always fine, but
103 	 INTEGER or ENUMERAL types we are handed may be too short.  We use a
104 	 base integer type node for the computations in this case and will
105 	 convert the final result back to the incoming type later on.  */
106       if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32)
107 	comp_type = gnat_type_for_size (32, 0);
108 
109       gnu_base = build_cst_from_int (comp_type, Base);
110 
111       gnu_ret = build_cst_from_int (comp_type, First);
112       if (First < 0)
113 	for (Idx++, Length--; Length; Idx++, Length--)
114 	  gnu_ret = fold_build2 (MINUS_EXPR, comp_type,
115 				 fold_build2 (MULT_EXPR, comp_type,
116 					      gnu_ret, gnu_base),
117 				 build_cst_from_int (comp_type,
118 						     Udigits_Ptr[Idx]));
119       else
120 	for (Idx++, Length--; Length; Idx++, Length--)
121 	  gnu_ret = fold_build2 (PLUS_EXPR, comp_type,
122 				 fold_build2 (MULT_EXPR, comp_type,
123 					      gnu_ret, gnu_base),
124 				 build_cst_from_int (comp_type,
125 						     Udigits_Ptr[Idx]));
126     }
127 
128   gnu_ret = convert (type, gnu_ret);
129 
130   /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET.  */
131   while ((TREE_CODE (gnu_ret) == NOP_EXPR
132 	  || TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
133 	 && TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
134     gnu_ret = TREE_OPERAND (gnu_ret, 0);
135 
136   return gnu_ret;
137 }
138 
139 /* Similar to UI_From_Int, but take a GCC INTEGER_CST.  We use UI_From_Int
140    when possible, i.e. for a 32-bit signed value, to take advantage of its
141    built-in caching mechanism.  For values of larger magnitude, we compute
142    digits into a vector and call Vector_To_Uint.  */
143 
144 Uint
UI_From_gnu(tree Input)145 UI_From_gnu (tree Input)
146 {
147   tree gnu_type = TREE_TYPE (Input), gnu_base, gnu_temp;
148   /* UI_Base is defined so that 5 Uint digits is sufficient to hold the
149      largest possible signed 64-bit value.  */
150   const int Max_For_Dint = 5;
151   int v[Max_For_Dint], i;
152   Vector_Template temp;
153   Int_Vector vec;
154 
155 #if HOST_BITS_PER_WIDE_INT == 64
156   /* On 64-bit hosts, host_integerp tells whether the input fits in a
157      signed 64-bit integer.  Then a truncation tells whether it fits
158      in a signed 32-bit integer.  */
159   if (host_integerp (Input, 0))
160     {
161       HOST_WIDE_INT hw_input = TREE_INT_CST_LOW (Input);
162       if (hw_input == (int) hw_input)
163 	return UI_From_Int (hw_input);
164     }
165   else
166     return No_Uint;
167 #else
168   /* On 32-bit hosts, host_integerp tells whether the input fits in a
169      signed 32-bit integer.  Then a sign test tells whether it fits
170      in a signed 64-bit integer.  */
171   if (host_integerp (Input, 0))
172     return UI_From_Int (TREE_INT_CST_LOW (Input));
173   else if (TREE_INT_CST_HIGH (Input) < 0 && TYPE_UNSIGNED (gnu_type))
174     return No_Uint;
175 #endif
176 
177   gnu_base = build_int_cst (gnu_type, UI_Base);
178   gnu_temp = Input;
179 
180   for (i = Max_For_Dint - 1; i >= 0; i--)
181     {
182       v[i] = tree_low_cst (fold_build1 (ABS_EXPR, gnu_type,
183 					fold_build2 (TRUNC_MOD_EXPR, gnu_type,
184 						     gnu_temp, gnu_base)),
185 			   0);
186       gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base);
187     }
188 
189   temp.Low_Bound = 1, temp.High_Bound = Max_For_Dint;
190   vec.Array = v, vec.Bounds = &temp;
191   return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0);
192 }
193