Commit 5f0ae953 by Richard Henderson Committed by Richard Henderson

trans-const.c (gfc_conv_mpz_to_tree): Use mpz_getlimbn instead of going through…

trans-const.c (gfc_conv_mpz_to_tree): Use mpz_getlimbn instead of going through an intermediate string.

        * trans-const.c (gfc_conv_mpz_to_tree): Use mpz_getlimbn instead
        of going through an intermediate string.  Fix 32/64 int/long bug.

From-SVN: r86464
parent 663790f8
2004-08-23 Richard Henderson <rth@redhat.com>
* trans-const.c (gfc_conv_mpz_to_tree): Use mpz_getlimbn instead
of going through an intermediate string. Fix 32/64 int/long bug.
2004-08-23 Eric Christopher <echristo@redhat.com> 2004-08-23 Eric Christopher <echristo@redhat.com>
* trans-types.c (gfc_type_for_mode): Remove VECTOR_TYPE_SUPPORTED_P * trans-types.c (gfc_type_for_mode): Remove VECTOR_TYPE_SUPPORTED_P
......
...@@ -161,71 +161,63 @@ gfc_init_constants (void) ...@@ -161,71 +161,63 @@ gfc_init_constants (void)
gfc_option.source); gfc_option.source);
} }
#define BITS_PER_HOST_WIDE_INT (8 * sizeof (HOST_WIDE_INT))
/* Converts a GMP integer into a backend tree node. */ /* Converts a GMP integer into a backend tree node. */
tree tree
gfc_conv_mpz_to_tree (mpz_t i, int kind) gfc_conv_mpz_to_tree (mpz_t i, int kind)
{ {
int val;
tree res;
HOST_WIDE_INT high; HOST_WIDE_INT high;
unsigned HOST_WIDE_INT low; unsigned HOST_WIDE_INT low;
int negate;
char buff[10];
char *p;
char *q;
int n;
/* TODO: could be wrong if sizeof(HOST_WIDE_INT) != SIZEOF (int). */
if (mpz_fits_slong_p (i)) if (mpz_fits_slong_p (i))
{ {
val = mpz_get_si (i); /* Note that HOST_WIDE_INT is never smaller than long. */
res = build_int_cst (gfc_get_int_type (kind), low = mpz_get_si (i);
val, (val < 0) ? (HOST_WIDE_INT)-1 : 0); high = mpz_sgn (i) < 0 ? -1 : 0;
return (res);
} }
n = mpz_sizeinbase (i, 16);
if (n > 8)
q = gfc_getmem (n + 2);
else else
q = buff;
low = 0;
high = 0;
p = mpz_get_str (q, 16, i);
if (p[0] == '-')
{ {
negate = 1; /* Note that mp_limb_t can be anywhere from short to long long,
p++; which gives us a nice variety of cases to choose from. */
}
else
negate = 0;
while (*p) if (sizeof (mp_limb_t) == sizeof (HOST_WIDE_INT))
{ {
n = *(p++); low = mpz_getlimbn (i, 0);
if (n >= '0' && n <= '9') high = mpz_getlimbn (i, 1);
n = n - '0'; }
else if (n >= 'a' && n <= 'z') else if (sizeof (mp_limb_t) == 2 * sizeof (HOST_WIDE_INT))
n = n + 10 - 'a'; {
else if (n >= 'A' && n <= 'Z') mp_limb_t limb0 = mpz_getlimbn (i, 0);
n = n + 10 - 'A'; int count = (sizeof (mp_limb_t) - sizeof (HOST_WIDE_INT)) * CHAR_BIT;
else low = limb0;
abort (); high = limb0 >> count;
}
else if (sizeof (mp_limb_t) < sizeof (HOST_WIDE_INT))
{
int n, count = sizeof (HOST_WIDE_INT) / sizeof (mp_limb_t);
for (low = n = 0; n < count; ++n)
{
low <<= sizeof (mp_limb_t) * CHAR_BIT;
low |= mpz_getlimbn (i, n);
}
for (high = 0; n < 2*count; ++n)
{
high <<= sizeof (mp_limb_t) * CHAR_BIT;
high |= mpz_getlimbn (i, n);
}
}
assert (n >= 0 && n < 16); /* By extracting limbs we constructed the absolute value of the
high = (high << 4) + (low >> (BITS_PER_HOST_WIDE_INT - 4)); desired number. Negate if necessary. */
low = (low << 4) + n; if (mpz_sgn (i) < 0)
{
if (low == 0)
high = -high;
else
low = -low, high = ~high;
}
} }
res = build_int_cst (gfc_get_int_type (kind), low, high);
if (negate)
res = fold (build1 (NEGATE_EXPR, TREE_TYPE (res), res));
if (q != buff) return build_int_cst (gfc_get_int_type (kind), low, high);
gfc_free (q);
return res;
} }
/* Converts a real constant into backend form. Uses an intermediate string /* Converts a real constant into backend form. Uses an intermediate string
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment