1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/****************************************************************************/
/* */
/* GNAT COMPILER COMPONENTS */
/* */
/* A - U I N T P */
/* */
/* C Implementation File */
/* */
/* $Revision: 1.23 $ */
/* */
/* Copyright (C) 1992,1993,1994,1995,1996 Free Software Foundation, Inc. */
/* */
/* GNAT is free software; you can redistribute it and/or modify it under */
/* terms of the GNU General Public License as published by the Free Soft- */
/* ware Foundation; either version 2, or (at your option) any later ver- */
/* sion. GNAT is distributed in the hope that it will be useful, but WITH- */
/* OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY */
/* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License */
/* for more details. You should have received a copy of the GNU General */
/* Public License distributed with GNAT; see file COPYING. If not, write */
/* to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, */
/* MA 02111-1307, USA. */
/* */
/* GNAT was originally developed by the GNAT team at New York University. */
/* It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). */
/* */
/****************************************************************************/
/* This file corresponds to the Ada package body Uintp. It was created
manually from the files uintp.ads and uintp.adb. */
#include "config.h"
#include "tree.h"
#include "a-ada.h"
#include "a-types.h"
#include "a-atree.h"
#include "a-nlists.h"
#include "a-elists.h"
#include "a-sinfo.h"
#include "a-einfo.h"
#include "a-namet.h"
#include "a-string.h"
#include "a-uintp.h"
/* Universal integers are represented by the Uint type which is an index into
the Uints_Ptr table containing Uint_Entry values. A Uint_Entry contains an
index and length for getting the "digits" of the universal integer from the
Udigits_Ptr table.
For efficiency, this method is used only for integer values larger than the
constant Uint_Bias. If a Uint is less than this constant, then it contains
the integer value itself. The origin of the Uints_Ptr table is adjusted so
that a Uint value of Uint_Bias indexes the first element. */
/* Similarly to UI_To_Int, but return a GCC INTEGER_CST. Overflow is tested
by the constant-folding used to build the node. TYPE is the GCC type of the
resulting node. */
tree
UI_To_gnu (Input, type)
Uint Input;
tree type;
{
tree gnu_ret;
if (Input <= Uint_Direct_Last)
gnu_ret = convert (type, build_int_2 (Input - Uint_Direct_Bias,
Input < Uint_Direct_Bias ? -1 : 0));
else
{
Int Idx = Uints_Ptr[Input].Loc;
Pos Length = Uints_Ptr[Input].Length;
Int First = Udigits_Ptr[Idx];
/* Do computations in integer type or TYPE whichever is wider, then
convert later. This avoid overflow if type is short integer. */
tree comp_type
= (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)
? type : integer_type_node);
tree gnu_base = convert (comp_type, build_int_2 (Base, 0));
if (Length <= 0)
gigi_abort (601);
gnu_ret = convert (comp_type, build_int_2 (First, First < 0 ? -1 : 0));
if (First < 0)
for (Idx++, Length--; Length; Idx++, Length--)
gnu_ret = fold (build (MINUS_EXPR, comp_type,
fold (build (MULT_EXPR, comp_type,
gnu_ret, gnu_base)),
convert (comp_type,
build_int_2 (Udigits_Ptr[Idx], 0))));
else
for (Idx++, Length--; Length; Idx++, Length--)
gnu_ret = fold (build (PLUS_EXPR, comp_type,
fold (build (MULT_EXPR, comp_type,
gnu_ret, gnu_base)),
convert (comp_type,
build_int_2 (Udigits_Ptr[Idx], 0))));
}
gnu_ret = convert (type, gnu_ret);
/* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET. */
while ((TREE_CODE (gnu_ret) == NOP_EXPR
|| TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
&& TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
gnu_ret = TREE_OPERAND (gnu_ret, 0);
return gnu_ret;
}
|