annotate gcc/ada/gcc-interface/cuintp.c @ 111:04ced10e8804

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