1/****************************************************************************
2 *                                                                          *
3 *                        GNAT COMPILER COMPONENTS                          *
4 *                                                                          *
5 *                               C U I N T P                                *
6 *                                                                          *
7 *                          C Implementation File                           *
8 *                                                                          *
9 *          Copyright (C) 1992-2015, 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 "hash-set.h"
34#include "machmode.h"
35#include "vec.h"
36#include "double-int.h"
37#include "input.h"
38#include "alias.h"
39#include "symtab.h"
40#include "wide-int.h"
41#include "inchash.h"
42#include "tree.h"
43#include "fold-const.h"
44
45#include "ada.h"
46#include "types.h"
47#include "uintp.h"
48#include "ada-tree.h"
49#include "gigi.h"
50
51/* Universal integers are represented by the Uint type which is an index into
52   the Uints_Ptr table containing Uint_Entry values.  A Uint_Entry contains an
53   index and length for getting the "digits" of the universal integer from the
54   Udigits_Ptr table.
55
56   For efficiency, this method is used only for integer values larger than the
57   constant Uint_Bias.  If a Uint is less than this constant, then it contains
58   the integer value itself.  The origin of the Uints_Ptr table is adjusted so
59   that a Uint value of Uint_Bias indexes the first element.
60
61   First define a utility function that operates like build_int_cst_type for
62   integral types and does a conversion for floating-point types.  */
63
64static tree
65build_cst_from_int (tree type, HOST_WIDE_INT low)
66{
67  if (SCALAR_FLOAT_TYPE_P (type))
68    return convert (type, build_int_cst (gnat_type_for_size (32, 0), low));
69  else
70    return build_int_cst_type (type, low);
71}
72
73/* Similar to UI_To_Int, but return a GCC INTEGER_CST or REAL_CST node,
74   depending on whether TYPE is an integral or real type.  Overflow is tested
75   by the constant-folding used to build the node.  TYPE is the GCC type of
76   the resulting node.  */
77
78tree
79UI_To_gnu (Uint Input, tree type)
80{
81  /* We might have a TYPE with biased representation and be passed an unbiased
82     value that doesn't fit.  We always use an unbiased type to be able to hold
83     any such possible value for intermediate computations and then rely on a
84     conversion back to TYPE to perform the bias adjustment when need be.  */
85  tree comp_type
86    = TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)
87      ? get_base_type (type) : type;
88  tree gnu_ret;
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
144Uint
145UI_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, tree_fits_shwi_p 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 (tree_fits_shwi_p (Input))
160    {
161      HOST_WIDE_INT hw_input = tree_to_shwi (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, tree_fits_shwi_p 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 (tree_fits_shwi_p (Input))
172    return UI_From_Int (tree_to_shwi (Input));
173
174  gcc_assert (TYPE_PRECISION (gnu_type) <= 64);
175  if (TYPE_UNSIGNED (gnu_type)
176      && TYPE_PRECISION (gnu_type) == 64
177      && wi::neg_p (Input, SIGNED))
178    return No_Uint;
179#endif
180
181  gnu_base = build_int_cst (gnu_type, UI_Base);
182  gnu_temp = Input;
183
184  for (i = Max_For_Dint - 1; i >= 0; i--)
185    {
186      v[i] = tree_to_shwi (fold_build1 (ABS_EXPR, gnu_type,
187					fold_build2 (TRUNC_MOD_EXPR, gnu_type,
188						     gnu_temp, gnu_base)));
189      gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base);
190    }
191
192  temp.Low_Bound = 1;
193  temp.High_Bound = Max_For_Dint;
194  vec.Bounds = &temp;
195  vec.Array = v;
196  return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0);
197}
198