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