aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/gcc/fortran/simplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/gcc/fortran/simplify.c')
-rw-r--r--gcc-4.8.1/gcc/fortran/simplify.c6727
1 files changed, 0 insertions, 6727 deletions
diff --git a/gcc-4.8.1/gcc/fortran/simplify.c b/gcc-4.8.1/gcc/fortran/simplify.c
deleted file mode 100644
index 6cc5c4dd4..000000000
--- a/gcc-4.8.1/gcc/fortran/simplify.c
+++ /dev/null
@@ -1,6727 +0,0 @@
-/* Simplify intrinsic functions at compile-time.
- Copyright (C) 2000-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught & Katherine Holcomb
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT 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
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "flags.h"
-#include "gfortran.h"
-#include "arith.h"
-#include "intrinsic.h"
-#include "target-memory.h"
-#include "constructor.h"
-#include "version.h" /* For version_string. */
-
-
-gfc_expr gfc_bad_expr;
-
-static gfc_expr *simplify_size (gfc_expr *, gfc_expr *, int);
-
-
-/* Note that 'simplification' is not just transforming expressions.
- For functions that are not simplified at compile time, range
- checking is done if possible.
-
- The return convention is that each simplification function returns:
-
- A new expression node corresponding to the simplified arguments.
- The original arguments are destroyed by the caller, and must not
- be a part of the new expression.
-
- NULL pointer indicating that no simplification was possible and
- the original expression should remain intact.
-
- An expression pointer to gfc_bad_expr (a static placeholder)
- indicating that some error has prevented simplification. The
- error is generated within the function and should be propagated
- upwards
-
- By the time a simplification function gets control, it has been
- decided that the function call is really supposed to be the
- intrinsic. No type checking is strictly necessary, since only
- valid types will be passed on. On the other hand, a simplification
- subroutine may have to look at the type of an argument as part of
- its processing.
-
- Array arguments are only passed to these subroutines that implement
- the simplification of transformational intrinsics.
-
- The functions in this file don't have much comment with them, but
- everything is reasonably straight-forward. The Standard, chapter 13
- is the best comment you'll find for this file anyway. */
-
-/* Range checks an expression node. If all goes well, returns the
- node, otherwise returns &gfc_bad_expr and frees the node. */
-
-static gfc_expr *
-range_check (gfc_expr *result, const char *name)
-{
- if (result == NULL)
- return &gfc_bad_expr;
-
- if (result->expr_type != EXPR_CONSTANT)
- return result;
-
- switch (gfc_range_check (result))
- {
- case ARITH_OK:
- return result;
-
- case ARITH_OVERFLOW:
- gfc_error ("Result of %s overflows its kind at %L", name,
- &result->where);
- break;
-
- case ARITH_UNDERFLOW:
- gfc_error ("Result of %s underflows its kind at %L", name,
- &result->where);
- break;
-
- case ARITH_NAN:
- gfc_error ("Result of %s is NaN at %L", name, &result->where);
- break;
-
- default:
- gfc_error ("Result of %s gives range error for its kind at %L", name,
- &result->where);
- break;
- }
-
- gfc_free_expr (result);
- return &gfc_bad_expr;
-}
-
-
-/* A helper function that gets an optional and possibly missing
- kind parameter. Returns the kind, -1 if something went wrong. */
-
-static int
-get_kind (bt type, gfc_expr *k, const char *name, int default_kind)
-{
- int kind;
-
- if (k == NULL)
- return default_kind;
-
- if (k->expr_type != EXPR_CONSTANT)
- {
- gfc_error ("KIND parameter of %s at %L must be an initialization "
- "expression", name, &k->where);
- return -1;
- }
-
- if (gfc_extract_int (k, &kind) != NULL
- || gfc_validate_kind (type, kind, true) < 0)
- {
- gfc_error ("Invalid KIND parameter of %s at %L", name, &k->where);
- return -1;
- }
-
- return kind;
-}
-
-
-/* Converts an mpz_t signed variable into an unsigned one, assuming
- two's complement representations and a binary width of bitsize.
- The conversion is a no-op unless x is negative; otherwise, it can
- be accomplished by masking out the high bits. */
-
-static void
-convert_mpz_to_unsigned (mpz_t x, int bitsize)
-{
- mpz_t mask;
-
- if (mpz_sgn (x) < 0)
- {
- /* Confirm that no bits above the signed range are unset. */
- gcc_assert (mpz_scan0 (x, bitsize-1) == ULONG_MAX);
-
- mpz_init_set_ui (mask, 1);
- mpz_mul_2exp (mask, mask, bitsize);
- mpz_sub_ui (mask, mask, 1);
-
- mpz_and (x, x, mask);
-
- mpz_clear (mask);
- }
- else
- {
- /* Confirm that no bits above the signed range are set. */
- gcc_assert (mpz_scan1 (x, bitsize-1) == ULONG_MAX);
- }
-}
-
-
-/* Converts an mpz_t unsigned variable into a signed one, assuming
- two's complement representations and a binary width of bitsize.
- If the bitsize-1 bit is set, this is taken as a sign bit and
- the number is converted to the corresponding negative number. */
-
-static void
-convert_mpz_to_signed (mpz_t x, int bitsize)
-{
- mpz_t mask;
-
- /* Confirm that no bits above the unsigned range are set. */
- gcc_assert (mpz_scan1 (x, bitsize) == ULONG_MAX);
-
- if (mpz_tstbit (x, bitsize - 1) == 1)
- {
- mpz_init_set_ui (mask, 1);
- mpz_mul_2exp (mask, mask, bitsize);
- mpz_sub_ui (mask, mask, 1);
-
- /* We negate the number by hand, zeroing the high bits, that is
- make it the corresponding positive number, and then have it
- negated by GMP, giving the correct representation of the
- negative number. */
- mpz_com (x, x);
- mpz_add_ui (x, x, 1);
- mpz_and (x, x, mask);
-
- mpz_neg (x, x);
-
- mpz_clear (mask);
- }
-}
-
-
-/* In-place convert BOZ to REAL of the specified kind. */
-
-static gfc_expr *
-convert_boz (gfc_expr *x, int kind)
-{
- if (x && x->ts.type == BT_INTEGER && x->is_boz)
- {
- gfc_typespec ts;
- gfc_clear_ts (&ts);
- ts.type = BT_REAL;
- ts.kind = kind;
-
- if (!gfc_convert_boz (x, &ts))
- return &gfc_bad_expr;
- }
-
- return x;
-}
-
-
-/* Test that the expression is an constant array. */
-
-static bool
-is_constant_array_expr (gfc_expr *e)
-{
- gfc_constructor *c;
-
- if (e == NULL)
- return true;
-
- if (e->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (e))
- return false;
-
- for (c = gfc_constructor_first (e->value.constructor);
- c; c = gfc_constructor_next (c))
- if (c->expr->expr_type != EXPR_CONSTANT
- && c->expr->expr_type != EXPR_STRUCTURE)
- return false;
-
- return true;
-}
-
-
-/* Initialize a transformational result expression with a given value. */
-
-static void
-init_result_expr (gfc_expr *e, int init, gfc_expr *array)
-{
- if (e && e->expr_type == EXPR_ARRAY)
- {
- gfc_constructor *ctor = gfc_constructor_first (e->value.constructor);
- while (ctor)
- {
- init_result_expr (ctor->expr, init, array);
- ctor = gfc_constructor_next (ctor);
- }
- }
- else if (e && e->expr_type == EXPR_CONSTANT)
- {
- int i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- int length;
- gfc_char_t *string;
-
- switch (e->ts.type)
- {
- case BT_LOGICAL:
- e->value.logical = (init ? 1 : 0);
- break;
-
- case BT_INTEGER:
- if (init == INT_MIN)
- mpz_set (e->value.integer, gfc_integer_kinds[i].min_int);
- else if (init == INT_MAX)
- mpz_set (e->value.integer, gfc_integer_kinds[i].huge);
- else
- mpz_set_si (e->value.integer, init);
- break;
-
- case BT_REAL:
- if (init == INT_MIN)
- {
- mpfr_set (e->value.real, gfc_real_kinds[i].huge, GFC_RND_MODE);
- mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
- }
- else if (init == INT_MAX)
- mpfr_set (e->value.real, gfc_real_kinds[i].huge, GFC_RND_MODE);
- else
- mpfr_set_si (e->value.real, init, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_set_si (e->value.complex, init, GFC_MPC_RND_MODE);
- break;
-
- case BT_CHARACTER:
- if (init == INT_MIN)
- {
- gfc_expr *len = gfc_simplify_len (array, NULL);
- gfc_extract_int (len, &length);
- string = gfc_get_wide_string (length + 1);
- gfc_wide_memset (string, 0, length);
- }
- else if (init == INT_MAX)
- {
- gfc_expr *len = gfc_simplify_len (array, NULL);
- gfc_extract_int (len, &length);
- string = gfc_get_wide_string (length + 1);
- gfc_wide_memset (string, 255, length);
- }
- else
- {
- length = 0;
- string = gfc_get_wide_string (1);
- }
-
- string[length] = '\0';
- e->value.character.length = length;
- e->value.character.string = string;
- break;
-
- default:
- gcc_unreachable();
- }
- }
- else
- gcc_unreachable();
-}
-
-
-/* Helper function for gfc_simplify_dot_product() and gfc_simplify_matmul. */
-
-static gfc_expr *
-compute_dot_product (gfc_expr *matrix_a, int stride_a, int offset_a,
- gfc_expr *matrix_b, int stride_b, int offset_b)
-{
- gfc_expr *result, *a, *b;
-
- result = gfc_get_constant_expr (matrix_a->ts.type, matrix_a->ts.kind,
- &matrix_a->where);
- init_result_expr (result, 0, NULL);
-
- a = gfc_constructor_lookup_expr (matrix_a->value.constructor, offset_a);
- b = gfc_constructor_lookup_expr (matrix_b->value.constructor, offset_b);
- while (a && b)
- {
- /* Copying of expressions is required as operands are free'd
- by the gfc_arith routines. */
- switch (result->ts.type)
- {
- case BT_LOGICAL:
- result = gfc_or (result,
- gfc_and (gfc_copy_expr (a),
- gfc_copy_expr (b)));
- break;
-
- case BT_INTEGER:
- case BT_REAL:
- case BT_COMPLEX:
- result = gfc_add (result,
- gfc_multiply (gfc_copy_expr (a),
- gfc_copy_expr (b)));
- break;
-
- default:
- gcc_unreachable();
- }
-
- offset_a += stride_a;
- a = gfc_constructor_lookup_expr (matrix_a->value.constructor, offset_a);
-
- offset_b += stride_b;
- b = gfc_constructor_lookup_expr (matrix_b->value.constructor, offset_b);
- }
-
- return result;
-}
-
-
-/* Build a result expression for transformational intrinsics,
- depending on DIM. */
-
-static gfc_expr *
-transformational_result (gfc_expr *array, gfc_expr *dim, bt type,
- int kind, locus* where)
-{
- gfc_expr *result;
- int i, nelem;
-
- if (!dim || array->rank == 1)
- return gfc_get_constant_expr (type, kind, where);
-
- result = gfc_get_array_expr (type, kind, where);
- result->shape = gfc_copy_shape_excluding (array->shape, array->rank, dim);
- result->rank = array->rank - 1;
-
- /* gfc_array_size() would count the number of elements in the constructor,
- we have not built those yet. */
- nelem = 1;
- for (i = 0; i < result->rank; ++i)
- nelem *= mpz_get_ui (result->shape[i]);
-
- for (i = 0; i < nelem; ++i)
- {
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_get_constant_expr (type, kind, where),
- NULL);
- }
-
- return result;
-}
-
-
-typedef gfc_expr* (*transformational_op)(gfc_expr*, gfc_expr*);
-
-/* Wrapper function, implements 'op1 += 1'. Only called if MASK
- of COUNT intrinsic is .TRUE..
-
- Interface and implementation mimics arith functions as
- gfc_add, gfc_multiply, etc. */
-
-static gfc_expr* gfc_count (gfc_expr *op1, gfc_expr *op2)
-{
- gfc_expr *result;
-
- gcc_assert (op1->ts.type == BT_INTEGER);
- gcc_assert (op2->ts.type == BT_LOGICAL);
- gcc_assert (op2->value.logical);
-
- result = gfc_copy_expr (op1);
- mpz_add_ui (result->value.integer, result->value.integer, 1);
-
- gfc_free_expr (op1);
- gfc_free_expr (op2);
- return result;
-}
-
-
-/* Transforms an ARRAY with operation OP, according to MASK, to a
- scalar RESULT. E.g. called if
-
- REAL, PARAMETER :: array(n, m) = ...
- REAL, PARAMETER :: s = SUM(array)
-
- where OP == gfc_add(). */
-
-static gfc_expr *
-simplify_transformation_to_scalar (gfc_expr *result, gfc_expr *array, gfc_expr *mask,
- transformational_op op)
-{
- gfc_expr *a, *m;
- gfc_constructor *array_ctor, *mask_ctor;
-
- /* Shortcut for constant .FALSE. MASK. */
- if (mask
- && mask->expr_type == EXPR_CONSTANT
- && !mask->value.logical)
- return result;
-
- array_ctor = gfc_constructor_first (array->value.constructor);
- mask_ctor = NULL;
- if (mask && mask->expr_type == EXPR_ARRAY)
- mask_ctor = gfc_constructor_first (mask->value.constructor);
-
- while (array_ctor)
- {
- a = array_ctor->expr;
- array_ctor = gfc_constructor_next (array_ctor);
-
- /* A constant MASK equals .TRUE. here and can be ignored. */
- if (mask_ctor)
- {
- m = mask_ctor->expr;
- mask_ctor = gfc_constructor_next (mask_ctor);
- if (!m->value.logical)
- continue;
- }
-
- result = op (result, gfc_copy_expr (a));
- }
-
- return result;
-}
-
-/* Transforms an ARRAY with operation OP, according to MASK, to an
- array RESULT. E.g. called if
-
- REAL, PARAMETER :: array(n, m) = ...
- REAL, PARAMETER :: s(n) = PROD(array, DIM=1)
-
- where OP == gfc_multiply(). The result might be post processed using post_op. */
-
-static gfc_expr *
-simplify_transformation_to_array (gfc_expr *result, gfc_expr *array, gfc_expr *dim,
- gfc_expr *mask, transformational_op op,
- transformational_op post_op)
-{
- mpz_t size;
- int done, i, n, arraysize, resultsize, dim_index, dim_extent, dim_stride;
- gfc_expr **arrayvec, **resultvec, **base, **src, **dest;
- gfc_constructor *array_ctor, *mask_ctor, *result_ctor;
-
- int count[GFC_MAX_DIMENSIONS], extent[GFC_MAX_DIMENSIONS],
- sstride[GFC_MAX_DIMENSIONS], dstride[GFC_MAX_DIMENSIONS],
- tmpstride[GFC_MAX_DIMENSIONS];
-
- /* Shortcut for constant .FALSE. MASK. */
- if (mask
- && mask->expr_type == EXPR_CONSTANT
- && !mask->value.logical)
- return result;
-
- /* Build an indexed table for array element expressions to minimize
- linked-list traversal. Masked elements are set to NULL. */
- gfc_array_size (array, &size);
- arraysize = mpz_get_ui (size);
- mpz_clear (size);
-
- arrayvec = XCNEWVEC (gfc_expr*, arraysize);
-
- array_ctor = gfc_constructor_first (array->value.constructor);
- mask_ctor = NULL;
- if (mask && mask->expr_type == EXPR_ARRAY)
- mask_ctor = gfc_constructor_first (mask->value.constructor);
-
- for (i = 0; i < arraysize; ++i)
- {
- arrayvec[i] = array_ctor->expr;
- array_ctor = gfc_constructor_next (array_ctor);
-
- if (mask_ctor)
- {
- if (!mask_ctor->expr->value.logical)
- arrayvec[i] = NULL;
-
- mask_ctor = gfc_constructor_next (mask_ctor);
- }
- }
-
- /* Same for the result expression. */
- gfc_array_size (result, &size);
- resultsize = mpz_get_ui (size);
- mpz_clear (size);
-
- resultvec = XCNEWVEC (gfc_expr*, resultsize);
- result_ctor = gfc_constructor_first (result->value.constructor);
- for (i = 0; i < resultsize; ++i)
- {
- resultvec[i] = result_ctor->expr;
- result_ctor = gfc_constructor_next (result_ctor);
- }
-
- gfc_extract_int (dim, &dim_index);
- dim_index -= 1; /* zero-base index */
- dim_extent = 0;
- dim_stride = 0;
-
- for (i = 0, n = 0; i < array->rank; ++i)
- {
- count[i] = 0;
- tmpstride[i] = (i == 0) ? 1 : tmpstride[i-1] * mpz_get_si (array->shape[i-1]);
- if (i == dim_index)
- {
- dim_extent = mpz_get_si (array->shape[i]);
- dim_stride = tmpstride[i];
- continue;
- }
-
- extent[n] = mpz_get_si (array->shape[i]);
- sstride[n] = tmpstride[i];
- dstride[n] = (n == 0) ? 1 : dstride[n-1] * extent[n-1];
- n += 1;
- }
-
- done = false;
- base = arrayvec;
- dest = resultvec;
- while (!done)
- {
- for (src = base, n = 0; n < dim_extent; src += dim_stride, ++n)
- if (*src)
- *dest = op (*dest, gfc_copy_expr (*src));
-
- count[0]++;
- base += sstride[0];
- dest += dstride[0];
-
- n = 0;
- while (!done && count[n] == extent[n])
- {
- count[n] = 0;
- base -= sstride[n] * extent[n];
- dest -= dstride[n] * extent[n];
-
- n++;
- if (n < result->rank)
- {
- count [n]++;
- base += sstride[n];
- dest += dstride[n];
- }
- else
- done = true;
- }
- }
-
- /* Place updated expression in result constructor. */
- result_ctor = gfc_constructor_first (result->value.constructor);
- for (i = 0; i < resultsize; ++i)
- {
- if (post_op)
- result_ctor->expr = post_op (result_ctor->expr, resultvec[i]);
- else
- result_ctor->expr = resultvec[i];
- result_ctor = gfc_constructor_next (result_ctor);
- }
-
- free (arrayvec);
- free (resultvec);
- return result;
-}
-
-
-static gfc_expr *
-simplify_transformation (gfc_expr *array, gfc_expr *dim, gfc_expr *mask,
- int init_val, transformational_op op)
-{
- gfc_expr *result;
-
- if (!is_constant_array_expr (array)
- || !gfc_is_constant_expr (dim))
- return NULL;
-
- if (mask
- && !is_constant_array_expr (mask)
- && mask->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = transformational_result (array, dim, array->ts.type,
- array->ts.kind, &array->where);
- init_result_expr (result, init_val, NULL);
-
- return !dim || array->rank == 1 ?
- simplify_transformation_to_scalar (result, array, mask, op) :
- simplify_transformation_to_array (result, array, dim, mask, op, NULL);
-}
-
-
-/********************** Simplification functions *****************************/
-
-gfc_expr *
-gfc_simplify_abs (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (e->ts.type)
- {
- case BT_INTEGER:
- result = gfc_get_constant_expr (BT_INTEGER, e->ts.kind, &e->where);
- mpz_abs (result->value.integer, e->value.integer);
- return range_check (result, "IABS");
-
- case BT_REAL:
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpfr_abs (result->value.real, e->value.real, GFC_RND_MODE);
- return range_check (result, "ABS");
-
- case BT_COMPLEX:
- gfc_set_model_kind (e->ts.kind);
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpc_abs (result->value.real, e->value.complex, GFC_RND_MODE);
- return range_check (result, "CABS");
-
- default:
- gfc_internal_error ("gfc_simplify_abs(): Bad type");
- }
-}
-
-
-static gfc_expr *
-simplify_achar_char (gfc_expr *e, gfc_expr *k, const char *name, bool ascii)
-{
- gfc_expr *result;
- int kind;
- bool too_large = false;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = get_kind (BT_CHARACTER, k, name, gfc_default_character_kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (mpz_cmp_si (e->value.integer, 0) < 0)
- {
- gfc_error ("Argument of %s function at %L is negative", name,
- &e->where);
- return &gfc_bad_expr;
- }
-
- if (ascii && gfc_option.warn_surprising
- && mpz_cmp_si (e->value.integer, 127) > 0)
- gfc_warning ("Argument of %s function at %L outside of range [0,127]",
- name, &e->where);
-
- if (kind == 1 && mpz_cmp_si (e->value.integer, 255) > 0)
- too_large = true;
- else if (kind == 4)
- {
- mpz_t t;
- mpz_init_set_ui (t, 2);
- mpz_pow_ui (t, t, 32);
- mpz_sub_ui (t, t, 1);
- if (mpz_cmp (e->value.integer, t) > 0)
- too_large = true;
- mpz_clear (t);
- }
-
- if (too_large)
- {
- gfc_error ("Argument of %s function at %L is too large for the "
- "collating sequence of kind %d", name, &e->where, kind);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_character_expr (kind, &e->where, NULL, 1);
- result->value.character.string[0] = mpz_get_ui (e->value.integer);
-
- return result;
-}
-
-
-
-/* We use the processor's collating sequence, because all
- systems that gfortran currently works on are ASCII. */
-
-gfc_expr *
-gfc_simplify_achar (gfc_expr *e, gfc_expr *k)
-{
- return simplify_achar_char (e, k, "ACHAR", true);
-}
-
-
-gfc_expr *
-gfc_simplify_acos (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (x->ts.type)
- {
- case BT_REAL:
- if (mpfr_cmp_si (x->value.real, 1) > 0
- || mpfr_cmp_si (x->value.real, -1) < 0)
- {
- gfc_error ("Argument of ACOS at %L must be between -1 and 1",
- &x->where);
- return &gfc_bad_expr;
- }
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_acos (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpc_acos (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_acos(): Bad type");
- }
-
- return range_check (result, "ACOS");
-}
-
-gfc_expr *
-gfc_simplify_acosh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (x->ts.type)
- {
- case BT_REAL:
- if (mpfr_cmp_si (x->value.real, 1) < 0)
- {
- gfc_error ("Argument of ACOSH at %L must not be less than 1",
- &x->where);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_acosh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpc_acosh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_acosh(): Bad type");
- }
-
- return range_check (result, "ACOSH");
-}
-
-gfc_expr *
-gfc_simplify_adjustl (gfc_expr *e)
-{
- gfc_expr *result;
- int count, i, len;
- gfc_char_t ch;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- len = e->value.character.length;
-
- for (count = 0, i = 0; i < len; ++i)
- {
- ch = e->value.character.string[i];
- if (ch != ' ')
- break;
- ++count;
- }
-
- result = gfc_get_character_expr (e->ts.kind, &e->where, NULL, len);
- for (i = 0; i < len - count; ++i)
- result->value.character.string[i] = e->value.character.string[count + i];
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_adjustr (gfc_expr *e)
-{
- gfc_expr *result;
- int count, i, len;
- gfc_char_t ch;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- len = e->value.character.length;
-
- for (count = 0, i = len - 1; i >= 0; --i)
- {
- ch = e->value.character.string[i];
- if (ch != ' ')
- break;
- ++count;
- }
-
- result = gfc_get_character_expr (e->ts.kind, &e->where, NULL, len);
- for (i = 0; i < count; ++i)
- result->value.character.string[i] = ' ';
-
- for (i = count; i < len; ++i)
- result->value.character.string[i] = e->value.character.string[i - count];
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_aimag (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpfr_set (result->value.real, mpc_imagref (e->value.complex), GFC_RND_MODE);
-
- return range_check (result, "AIMAG");
-}
-
-
-gfc_expr *
-gfc_simplify_aint (gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *rtrunc, *result;
- int kind;
-
- kind = get_kind (BT_REAL, k, "AINT", e->ts.kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- rtrunc = gfc_copy_expr (e);
- mpfr_trunc (rtrunc->value.real, e->value.real);
-
- result = gfc_real2real (rtrunc, kind);
-
- gfc_free_expr (rtrunc);
-
- return range_check (result, "AINT");
-}
-
-
-gfc_expr *
-gfc_simplify_all (gfc_expr *mask, gfc_expr *dim)
-{
- return simplify_transformation (mask, dim, NULL, true, gfc_and);
-}
-
-
-gfc_expr *
-gfc_simplify_dint (gfc_expr *e)
-{
- gfc_expr *rtrunc, *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- rtrunc = gfc_copy_expr (e);
- mpfr_trunc (rtrunc->value.real, e->value.real);
-
- result = gfc_real2real (rtrunc, gfc_default_double_kind);
-
- gfc_free_expr (rtrunc);
-
- return range_check (result, "DINT");
-}
-
-
-gfc_expr *
-gfc_simplify_dreal (gfc_expr *e)
-{
- gfc_expr *result = NULL;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpc_real (result->value.real, e->value.complex, GFC_RND_MODE);
-
- return range_check (result, "DREAL");
-}
-
-
-gfc_expr *
-gfc_simplify_anint (gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *result;
- int kind;
-
- kind = get_kind (BT_REAL, k, "ANINT", e->ts.kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (e->ts.type, kind, &e->where);
- mpfr_round (result->value.real, e->value.real);
-
- return range_check (result, "ANINT");
-}
-
-
-gfc_expr *
-gfc_simplify_and (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int kind;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind;
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- result = gfc_get_constant_expr (BT_INTEGER, kind, &x->where);
- mpz_and (result->value.integer, x->value.integer, y->value.integer);
- return range_check (result, "AND");
-
- case BT_LOGICAL:
- return gfc_get_logical_expr (kind, &x->where,
- x->value.logical && y->value.logical);
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-gfc_expr *
-gfc_simplify_any (gfc_expr *mask, gfc_expr *dim)
-{
- return simplify_transformation (mask, dim, NULL, false, gfc_or);
-}
-
-
-gfc_expr *
-gfc_simplify_dnint (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, gfc_default_double_kind, &e->where);
- mpfr_round (result->value.real, e->value.real);
-
- return range_check (result, "DNINT");
-}
-
-
-gfc_expr *
-gfc_simplify_asin (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (x->ts.type)
- {
- case BT_REAL:
- if (mpfr_cmp_si (x->value.real, 1) > 0
- || mpfr_cmp_si (x->value.real, -1) < 0)
- {
- gfc_error ("Argument of ASIN at %L must be between -1 and 1",
- &x->where);
- return &gfc_bad_expr;
- }
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_asin (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpc_asin (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_asin(): Bad type");
- }
-
- return range_check (result, "ASIN");
-}
-
-
-gfc_expr *
-gfc_simplify_asinh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_asinh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_asinh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_asinh(): Bad type");
- }
-
- return range_check (result, "ASINH");
-}
-
-
-gfc_expr *
-gfc_simplify_atan (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_atan (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_atan (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_atan(): Bad type");
- }
-
- return range_check (result, "ATAN");
-}
-
-
-gfc_expr *
-gfc_simplify_atanh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (x->ts.type)
- {
- case BT_REAL:
- if (mpfr_cmp_si (x->value.real, 1) >= 0
- || mpfr_cmp_si (x->value.real, -1) <= 0)
- {
- gfc_error ("Argument of ATANH at %L must be inside the range -1 "
- "to 1", &x->where);
- return &gfc_bad_expr;
- }
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_atanh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpc_atanh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_atanh(): Bad type");
- }
-
- return range_check (result, "ATANH");
-}
-
-
-gfc_expr *
-gfc_simplify_atan2 (gfc_expr *y, gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (mpfr_sgn (y->value.real) == 0 && mpfr_sgn (x->value.real) == 0)
- {
- gfc_error ("If first argument of ATAN2 %L is zero, then the "
- "second argument must not be zero", &x->where);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_atan2 (result->value.real, y->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "ATAN2");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_j0 (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_j0 (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_J0");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_j1 (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_j1 (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_J1");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_jn (gfc_expr *order, gfc_expr *x)
-{
- gfc_expr *result;
- long n;
-
- if (x->expr_type != EXPR_CONSTANT || order->expr_type != EXPR_CONSTANT)
- return NULL;
-
- n = mpz_get_si (order->value.integer);
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_jn (result->value.real, n, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_JN");
-}
-
-
-/* Simplify transformational form of JN and YN. */
-
-static gfc_expr *
-gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x,
- bool jn)
-{
- gfc_expr *result;
- gfc_expr *e;
- long n1, n2;
- int i;
- mpfr_t x2rev, last1, last2;
-
- if (x->expr_type != EXPR_CONSTANT || order1->expr_type != EXPR_CONSTANT
- || order2->expr_type != EXPR_CONSTANT)
- return NULL;
-
- n1 = mpz_get_si (order1->value.integer);
- n2 = mpz_get_si (order2->value.integer);
- result = gfc_get_array_expr (x->ts.type, x->ts.kind, &x->where);
- result->rank = 1;
- result->shape = gfc_get_shape (1);
- mpz_init_set_ui (result->shape[0], MAX (n2-n1+1, 0));
-
- if (n2 < n1)
- return result;
-
- /* Special case: x == 0; it is J0(0.0) == 1, JN(N > 0, 0.0) == 0; and
- YN(N, 0.0) = -Inf. */
-
- if (mpfr_cmp_ui (x->value.real, 0.0) == 0)
- {
- if (!jn && gfc_option.flag_range_check)
- {
- gfc_error ("Result of BESSEL_YN is -INF at %L", &result->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- if (jn && n1 == 0)
- {
- e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_set_ui (e->value.real, 1, GFC_RND_MODE);
- gfc_constructor_append_expr (&result->value.constructor, e,
- &x->where);
- n1++;
- }
-
- for (i = n1; i <= n2; i++)
- {
- e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- if (jn)
- mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
- else
- mpfr_set_inf (e->value.real, -1);
- gfc_constructor_append_expr (&result->value.constructor, e,
- &x->where);
- }
-
- return result;
- }
-
- /* Use the faster but more verbose recurrence algorithm. Bessel functions
- are stable for downward recursion and Neumann functions are stable
- for upward recursion. It is
- x2rev = 2.0/x,
- J(N-1, x) = x2rev * N * J(N, x) - J(N+1, x),
- Y(N+1, x) = x2rev * N * Y(N, x) - Y(N-1, x).
- Cf. http://dlmf.nist.gov/10.74#iv and http://dlmf.nist.gov/10.6#E1 */
-
- gfc_set_model_kind (x->ts.kind);
-
- /* Get first recursion anchor. */
-
- mpfr_init (last1);
- if (jn)
- mpfr_jn (last1, n2, x->value.real, GFC_RND_MODE);
- else
- mpfr_yn (last1, n1, x->value.real, GFC_RND_MODE);
-
- e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_set (e->value.real, last1, GFC_RND_MODE);
- if (range_check (e, jn ? "BESSEL_JN" : "BESSEL_YN") == &gfc_bad_expr)
- {
- mpfr_clear (last1);
- gfc_free_expr (e);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
- gfc_constructor_append_expr (&result->value.constructor, e, &x->where);
-
- if (n1 == n2)
- {
- mpfr_clear (last1);
- return result;
- }
-
- /* Get second recursion anchor. */
-
- mpfr_init (last2);
- if (jn)
- mpfr_jn (last2, n2-1, x->value.real, GFC_RND_MODE);
- else
- mpfr_yn (last2, n1+1, x->value.real, GFC_RND_MODE);
-
- e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_set (e->value.real, last2, GFC_RND_MODE);
- if (range_check (e, jn ? "BESSEL_JN" : "BESSEL_YN") == &gfc_bad_expr)
- {
- mpfr_clear (last1);
- mpfr_clear (last2);
- gfc_free_expr (e);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
- if (jn)
- gfc_constructor_insert_expr (&result->value.constructor, e, &x->where, -2);
- else
- gfc_constructor_append_expr (&result->value.constructor, e, &x->where);
-
- if (n1 + 1 == n2)
- {
- mpfr_clear (last1);
- mpfr_clear (last2);
- return result;
- }
-
- /* Start actual recursion. */
-
- mpfr_init (x2rev);
- mpfr_ui_div (x2rev, 2, x->value.real, GFC_RND_MODE);
-
- for (i = 2; i <= n2-n1; i++)
- {
- e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- /* Special case: For YN, if the previous N gave -INF, set
- also N+1 to -INF. */
- if (!jn && !gfc_option.flag_range_check && mpfr_inf_p (last2))
- {
- mpfr_set_inf (e->value.real, -1);
- gfc_constructor_append_expr (&result->value.constructor, e,
- &x->where);
- continue;
- }
-
- mpfr_mul_si (e->value.real, x2rev, jn ? (n2-i+1) : (n1+i-1),
- GFC_RND_MODE);
- mpfr_mul (e->value.real, e->value.real, last2, GFC_RND_MODE);
- mpfr_sub (e->value.real, e->value.real, last1, GFC_RND_MODE);
-
- if (range_check (e, jn ? "BESSEL_JN" : "BESSEL_YN") == &gfc_bad_expr)
- {
- /* Range_check frees "e" in that case. */
- e = NULL;
- goto error;
- }
-
- if (jn)
- gfc_constructor_insert_expr (&result->value.constructor, e, &x->where,
- -i-1);
- else
- gfc_constructor_append_expr (&result->value.constructor, e, &x->where);
-
- mpfr_set (last1, last2, GFC_RND_MODE);
- mpfr_set (last2, e->value.real, GFC_RND_MODE);
- }
-
- mpfr_clear (last1);
- mpfr_clear (last2);
- mpfr_clear (x2rev);
- return result;
-
-error:
- mpfr_clear (last1);
- mpfr_clear (last2);
- mpfr_clear (x2rev);
- gfc_free_expr (e);
- gfc_free_expr (result);
- return &gfc_bad_expr;
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_jn2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x)
-{
- return gfc_simplify_bessel_n2 (order1, order2, x, true);
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_y0 (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_y0 (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_Y0");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_y1 (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_y1 (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_Y1");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_yn (gfc_expr *order, gfc_expr *x)
-{
- gfc_expr *result;
- long n;
-
- if (x->expr_type != EXPR_CONSTANT || order->expr_type != EXPR_CONSTANT)
- return NULL;
-
- n = mpz_get_si (order->value.integer);
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_yn (result->value.real, n, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "BESSEL_YN");
-}
-
-
-gfc_expr *
-gfc_simplify_bessel_yn2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x)
-{
- return gfc_simplify_bessel_n2 (order1, order2, x, false);
-}
-
-
-gfc_expr *
-gfc_simplify_bit_size (gfc_expr *e)
-{
- int i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- return gfc_get_int_expr (e->ts.kind, &e->where,
- gfc_integer_kinds[i].bit_size);
-}
-
-
-gfc_expr *
-gfc_simplify_btest (gfc_expr *e, gfc_expr *bit)
-{
- int b;
-
- if (e->expr_type != EXPR_CONSTANT || bit->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (gfc_extract_int (bit, &b) != NULL || b < 0)
- return gfc_get_logical_expr (gfc_default_logical_kind, &e->where, false);
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &e->where,
- mpz_tstbit (e->value.integer, b));
-}
-
-
-static int
-compare_bitwise (gfc_expr *i, gfc_expr *j)
-{
- mpz_t x, y;
- int k, res;
-
- gcc_assert (i->ts.type == BT_INTEGER);
- gcc_assert (j->ts.type == BT_INTEGER);
-
- mpz_init_set (x, i->value.integer);
- k = gfc_validate_kind (i->ts.type, i->ts.kind, false);
- convert_mpz_to_unsigned (x, gfc_integer_kinds[k].bit_size);
-
- mpz_init_set (y, j->value.integer);
- k = gfc_validate_kind (j->ts.type, j->ts.kind, false);
- convert_mpz_to_unsigned (y, gfc_integer_kinds[k].bit_size);
-
- res = mpz_cmp (x, y);
- mpz_clear (x);
- mpz_clear (y);
- return res;
-}
-
-
-gfc_expr *
-gfc_simplify_bge (gfc_expr *i, gfc_expr *j)
-{
- if (i->expr_type != EXPR_CONSTANT || j->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &i->where,
- compare_bitwise (i, j) >= 0);
-}
-
-
-gfc_expr *
-gfc_simplify_bgt (gfc_expr *i, gfc_expr *j)
-{
- if (i->expr_type != EXPR_CONSTANT || j->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &i->where,
- compare_bitwise (i, j) > 0);
-}
-
-
-gfc_expr *
-gfc_simplify_ble (gfc_expr *i, gfc_expr *j)
-{
- if (i->expr_type != EXPR_CONSTANT || j->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &i->where,
- compare_bitwise (i, j) <= 0);
-}
-
-
-gfc_expr *
-gfc_simplify_blt (gfc_expr *i, gfc_expr *j)
-{
- if (i->expr_type != EXPR_CONSTANT || j->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &i->where,
- compare_bitwise (i, j) < 0);
-}
-
-
-gfc_expr *
-gfc_simplify_ceiling (gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *ceil, *result;
- int kind;
-
- kind = get_kind (BT_INTEGER, k, "CEILING", gfc_default_integer_kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- ceil = gfc_copy_expr (e);
- mpfr_ceil (ceil->value.real, e->value.real);
-
- result = gfc_get_constant_expr (BT_INTEGER, kind, &e->where);
- gfc_mpfr_to_mpz (result->value.integer, ceil->value.real, &e->where);
-
- gfc_free_expr (ceil);
-
- return range_check (result, "CEILING");
-}
-
-
-gfc_expr *
-gfc_simplify_char (gfc_expr *e, gfc_expr *k)
-{
- return simplify_achar_char (e, k, "CHAR", false);
-}
-
-
-/* Common subroutine for simplifying CMPLX, COMPLEX and DCMPLX. */
-
-static gfc_expr *
-simplify_cmplx (const char *name, gfc_expr *x, gfc_expr *y, int kind)
-{
- gfc_expr *result;
-
- if (convert_boz (x, kind) == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- if (convert_boz (y, kind) == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- if (x->expr_type != EXPR_CONSTANT
- || (y != NULL && y->expr_type != EXPR_CONSTANT))
- return NULL;
-
- result = gfc_get_constant_expr (BT_COMPLEX, kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- mpc_set_z (result->value.complex, x->value.integer, GFC_MPC_RND_MODE);
- break;
-
- case BT_REAL:
- mpc_set_fr (result->value.complex, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_set (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_dcmplx(): Bad type (x)");
- }
-
- if (!y)
- return range_check (result, name);
-
- switch (y->ts.type)
- {
- case BT_INTEGER:
- mpfr_set_z (mpc_imagref (result->value.complex),
- y->value.integer, GFC_RND_MODE);
- break;
-
- case BT_REAL:
- mpfr_set (mpc_imagref (result->value.complex),
- y->value.real, GFC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_dcmplx(): Bad type (y)");
- }
-
- return range_check (result, name);
-}
-
-
-gfc_expr *
-gfc_simplify_cmplx (gfc_expr *x, gfc_expr *y, gfc_expr *k)
-{
- int kind;
-
- kind = get_kind (BT_REAL, k, "CMPLX", gfc_default_complex_kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- return simplify_cmplx ("CMPLX", x, y, kind);
-}
-
-
-gfc_expr *
-gfc_simplify_complex (gfc_expr *x, gfc_expr *y)
-{
- int kind;
-
- if (x->ts.type == BT_INTEGER && y->ts.type == BT_INTEGER)
- kind = gfc_default_complex_kind;
- else if (x->ts.type == BT_REAL || y->ts.type == BT_INTEGER)
- kind = x->ts.kind;
- else if (x->ts.type == BT_INTEGER || y->ts.type == BT_REAL)
- kind = y->ts.kind;
- else if (x->ts.type == BT_REAL && y->ts.type == BT_REAL)
- kind = (x->ts.kind > y->ts.kind) ? x->ts.kind : y->ts.kind;
- else
- gcc_unreachable ();
-
- return simplify_cmplx ("COMPLEX", x, y, kind);
-}
-
-
-gfc_expr *
-gfc_simplify_conjg (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_copy_expr (e);
- mpc_conj (result->value.complex, result->value.complex, GFC_MPC_RND_MODE);
-
- return range_check (result, "CONJG");
-}
-
-
-gfc_expr *
-gfc_simplify_cos (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_cos (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- gfc_set_model_kind (x->ts.kind);
- mpc_cos (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_cos(): Bad type");
- }
-
- return range_check (result, "COS");
-}
-
-
-gfc_expr *
-gfc_simplify_cosh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_cosh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_cosh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return range_check (result, "COSH");
-}
-
-
-gfc_expr *
-gfc_simplify_count (gfc_expr *mask, gfc_expr *dim, gfc_expr *kind)
-{
- gfc_expr *result;
-
- if (!is_constant_array_expr (mask)
- || !gfc_is_constant_expr (dim)
- || !gfc_is_constant_expr (kind))
- return NULL;
-
- result = transformational_result (mask, dim,
- BT_INTEGER,
- get_kind (BT_INTEGER, kind, "COUNT",
- gfc_default_integer_kind),
- &mask->where);
-
- init_result_expr (result, 0, NULL);
-
- /* Passing MASK twice, once as data array, once as mask.
- Whenever gfc_count is called, '1' is added to the result. */
- return !dim || mask->rank == 1 ?
- simplify_transformation_to_scalar (result, mask, mask, gfc_count) :
- simplify_transformation_to_array (result, mask, dim, mask, gfc_count, NULL);
-}
-
-
-gfc_expr *
-gfc_simplify_dcmplx (gfc_expr *x, gfc_expr *y)
-{
- return simplify_cmplx ("DCMPLX", x, y, gfc_default_double_kind);
-}
-
-
-gfc_expr *
-gfc_simplify_dble (gfc_expr *e)
-{
- gfc_expr *result = NULL;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (convert_boz (e, gfc_default_double_kind) == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- result = gfc_convert_constant (e, BT_REAL, gfc_default_double_kind);
- if (result == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- return range_check (result, "DBLE");
-}
-
-
-gfc_expr *
-gfc_simplify_digits (gfc_expr *x)
-{
- int i, digits;
-
- i = gfc_validate_kind (x->ts.type, x->ts.kind, false);
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- digits = gfc_integer_kinds[i].digits;
- break;
-
- case BT_REAL:
- case BT_COMPLEX:
- digits = gfc_real_kinds[i].digits;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return gfc_get_int_expr (gfc_default_integer_kind, NULL, digits);
-}
-
-
-gfc_expr *
-gfc_simplify_dim (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int kind;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind;
- result = gfc_get_constant_expr (x->ts.type, kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- if (mpz_cmp (x->value.integer, y->value.integer) > 0)
- mpz_sub (result->value.integer, x->value.integer, y->value.integer);
- else
- mpz_set_ui (result->value.integer, 0);
-
- break;
-
- case BT_REAL:
- if (mpfr_cmp (x->value.real, y->value.real) > 0)
- mpfr_sub (result->value.real, x->value.real, y->value.real,
- GFC_RND_MODE);
- else
- mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
-
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_dim(): Bad type");
- }
-
- return range_check (result, "DIM");
-}
-
-
-gfc_expr*
-gfc_simplify_dot_product (gfc_expr *vector_a, gfc_expr *vector_b)
-{
- if (!is_constant_array_expr (vector_a)
- || !is_constant_array_expr (vector_b))
- return NULL;
-
- gcc_assert (vector_a->rank == 1);
- gcc_assert (vector_b->rank == 1);
- gcc_assert (gfc_compare_types (&vector_a->ts, &vector_b->ts));
-
- return compute_dot_product (vector_a, 1, 0, vector_b, 1, 0);
-}
-
-
-gfc_expr *
-gfc_simplify_dprod (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *a1, *a2, *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- a1 = gfc_real2real (x, gfc_default_double_kind);
- a2 = gfc_real2real (y, gfc_default_double_kind);
-
- result = gfc_get_constant_expr (BT_REAL, gfc_default_double_kind, &x->where);
- mpfr_mul (result->value.real, a1->value.real, a2->value.real, GFC_RND_MODE);
-
- gfc_free_expr (a2);
- gfc_free_expr (a1);
-
- return range_check (result, "DPROD");
-}
-
-
-static gfc_expr *
-simplify_dshift (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg,
- bool right)
-{
- gfc_expr *result;
- int i, k, size, shift;
-
- if (arg1->expr_type != EXPR_CONSTANT || arg2->expr_type != EXPR_CONSTANT
- || shiftarg->expr_type != EXPR_CONSTANT)
- return NULL;
-
- k = gfc_validate_kind (BT_INTEGER, arg1->ts.kind, false);
- size = gfc_integer_kinds[k].bit_size;
-
- gfc_extract_int (shiftarg, &shift);
-
- /* DSHIFTR(I,J,SHIFT) = DSHIFTL(I,J,SIZE-SHIFT). */
- if (right)
- shift = size - shift;
-
- result = gfc_get_constant_expr (BT_INTEGER, arg1->ts.kind, &arg1->where);
- mpz_set_ui (result->value.integer, 0);
-
- for (i = 0; i < shift; i++)
- if (mpz_tstbit (arg2->value.integer, size - shift + i))
- mpz_setbit (result->value.integer, i);
-
- for (i = 0; i < size - shift; i++)
- if (mpz_tstbit (arg1->value.integer, i))
- mpz_setbit (result->value.integer, shift + i);
-
- /* Convert to a signed value. */
- convert_mpz_to_signed (result->value.integer, size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_dshiftr (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg)
-{
- return simplify_dshift (arg1, arg2, shiftarg, true);
-}
-
-
-gfc_expr *
-gfc_simplify_dshiftl (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg)
-{
- return simplify_dshift (arg1, arg2, shiftarg, false);
-}
-
-
-gfc_expr *
-gfc_simplify_erf (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_erf (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "ERF");
-}
-
-
-gfc_expr *
-gfc_simplify_erfc (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_erfc (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "ERFC");
-}
-
-
-/* Helper functions to simplify ERFC_SCALED(x) = ERFC(x) * EXP(X**2). */
-
-#define MAX_ITER 200
-#define ARG_LIMIT 12
-
-/* Calculate ERFC_SCALED directly by its definition:
-
- ERFC_SCALED(x) = ERFC(x) * EXP(X**2)
-
- using a large precision for intermediate results. This is used for all
- but large values of the argument. */
-static void
-fullprec_erfc_scaled (mpfr_t res, mpfr_t arg)
-{
- mp_prec_t prec;
- mpfr_t a, b;
-
- prec = mpfr_get_default_prec ();
- mpfr_set_default_prec (10 * prec);
-
- mpfr_init (a);
- mpfr_init (b);
-
- mpfr_set (a, arg, GFC_RND_MODE);
- mpfr_sqr (b, a, GFC_RND_MODE);
- mpfr_exp (b, b, GFC_RND_MODE);
- mpfr_erfc (a, a, GFC_RND_MODE);
- mpfr_mul (a, a, b, GFC_RND_MODE);
-
- mpfr_set (res, a, GFC_RND_MODE);
- mpfr_set_default_prec (prec);
-
- mpfr_clear (a);
- mpfr_clear (b);
-}
-
-/* Calculate ERFC_SCALED using a power series expansion in 1/arg:
-
- ERFC_SCALED(x) = 1 / (x * sqrt(pi))
- * (1 + Sum_n (-1)**n * (1 * 3 * 5 * ... * (2n-1))
- / (2 * x**2)**n)
-
- This is used for large values of the argument. Intermediate calculations
- are performed with twice the precision. We don't do a fixed number of
- iterations of the sum, but stop when it has converged to the required
- precision. */
-static void
-asympt_erfc_scaled (mpfr_t res, mpfr_t arg)
-{
- mpfr_t sum, x, u, v, w, oldsum, sumtrunc;
- mpz_t num;
- mp_prec_t prec;
- unsigned i;
-
- prec = mpfr_get_default_prec ();
- mpfr_set_default_prec (2 * prec);
-
- mpfr_init (sum);
- mpfr_init (x);
- mpfr_init (u);
- mpfr_init (v);
- mpfr_init (w);
- mpz_init (num);
-
- mpfr_init (oldsum);
- mpfr_init (sumtrunc);
- mpfr_set_prec (oldsum, prec);
- mpfr_set_prec (sumtrunc, prec);
-
- mpfr_set (x, arg, GFC_RND_MODE);
- mpfr_set_ui (sum, 1, GFC_RND_MODE);
- mpz_set_ui (num, 1);
-
- mpfr_set (u, x, GFC_RND_MODE);
- mpfr_sqr (u, u, GFC_RND_MODE);
- mpfr_mul_ui (u, u, 2, GFC_RND_MODE);
- mpfr_pow_si (u, u, -1, GFC_RND_MODE);
-
- for (i = 1; i < MAX_ITER; i++)
- {
- mpfr_set (oldsum, sum, GFC_RND_MODE);
-
- mpz_mul_ui (num, num, 2 * i - 1);
- mpz_neg (num, num);
-
- mpfr_set (w, u, GFC_RND_MODE);
- mpfr_pow_ui (w, w, i, GFC_RND_MODE);
-
- mpfr_set_z (v, num, GFC_RND_MODE);
- mpfr_mul (v, v, w, GFC_RND_MODE);
-
- mpfr_add (sum, sum, v, GFC_RND_MODE);
-
- mpfr_set (sumtrunc, sum, GFC_RND_MODE);
- if (mpfr_cmp (sumtrunc, oldsum) == 0)
- break;
- }
-
- /* We should have converged by now; otherwise, ARG_LIMIT is probably
- set too low. */
- gcc_assert (i < MAX_ITER);
-
- /* Divide by x * sqrt(Pi). */
- mpfr_const_pi (u, GFC_RND_MODE);
- mpfr_sqrt (u, u, GFC_RND_MODE);
- mpfr_mul (u, u, x, GFC_RND_MODE);
- mpfr_div (sum, sum, u, GFC_RND_MODE);
-
- mpfr_set (res, sum, GFC_RND_MODE);
- mpfr_set_default_prec (prec);
-
- mpfr_clears (sum, x, u, v, w, oldsum, sumtrunc, NULL);
- mpz_clear (num);
-}
-
-
-gfc_expr *
-gfc_simplify_erfc_scaled (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- if (mpfr_cmp_d (x->value.real, ARG_LIMIT) >= 0)
- asympt_erfc_scaled (result->value.real, x->value.real);
- else
- fullprec_erfc_scaled (result->value.real, x->value.real);
-
- return range_check (result, "ERFC_SCALED");
-}
-
-#undef MAX_ITER
-#undef ARG_LIMIT
-
-
-gfc_expr *
-gfc_simplify_epsilon (gfc_expr *e)
-{
- gfc_expr *result;
- int i;
-
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
-
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpfr_set (result->value.real, gfc_real_kinds[i].epsilon, GFC_RND_MODE);
-
- return range_check (result, "EPSILON");
-}
-
-
-gfc_expr *
-gfc_simplify_exp (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_exp (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- gfc_set_model_kind (x->ts.kind);
- mpc_exp (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_exp(): Bad type");
- }
-
- return range_check (result, "EXP");
-}
-
-
-gfc_expr *
-gfc_simplify_exponent (gfc_expr *x)
-{
- int i;
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &x->where);
-
- gfc_set_model (x->value.real);
-
- if (mpfr_sgn (x->value.real) == 0)
- {
- mpz_set_ui (result->value.integer, 0);
- return result;
- }
-
- i = (int) mpfr_get_exp (x->value.real);
- mpz_set_si (result->value.integer, i);
-
- return range_check (result, "EXPONENT");
-}
-
-
-gfc_expr *
-gfc_simplify_float (gfc_expr *a)
-{
- gfc_expr *result;
-
- if (a->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (a->is_boz)
- {
- if (convert_boz (a, gfc_default_real_kind) == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- result = gfc_copy_expr (a);
- }
- else
- result = gfc_int2real (a, gfc_default_real_kind);
-
- return range_check (result, "FLOAT");
-}
-
-
-static bool
-is_last_ref_vtab (gfc_expr *e)
-{
- gfc_ref *ref;
- gfc_component *comp = NULL;
-
- if (e->expr_type != EXPR_VARIABLE)
- return false;
-
- for (ref = e->ref; ref; ref = ref->next)
- if (ref->type == REF_COMPONENT)
- comp = ref->u.c.component;
-
- if (!e->ref || !comp)
- return e->symtree->n.sym->attr.vtab;
-
- if (comp->name[0] == '_' && strcmp (comp->name, "_vptr") == 0)
- return true;
-
- return false;
-}
-
-
-gfc_expr *
-gfc_simplify_extends_type_of (gfc_expr *a, gfc_expr *mold)
-{
- /* Avoid simplification of resolved symbols. */
- if (is_last_ref_vtab (a) || is_last_ref_vtab (mold))
- return NULL;
-
- if (a->ts.type == BT_DERIVED && mold->ts.type == BT_DERIVED)
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_type_is_extension_of (mold->ts.u.derived,
- a->ts.u.derived));
-
- if (UNLIMITED_POLY (a) || UNLIMITED_POLY (mold))
- return NULL;
-
- /* Return .false. if the dynamic type can never be the same. */
- if ((a->ts.type == BT_CLASS && mold->ts.type == BT_CLASS
- && !gfc_type_is_extension_of
- (mold->ts.u.derived->components->ts.u.derived,
- a->ts.u.derived->components->ts.u.derived)
- && !gfc_type_is_extension_of
- (a->ts.u.derived->components->ts.u.derived,
- mold->ts.u.derived->components->ts.u.derived))
- || (a->ts.type == BT_DERIVED && mold->ts.type == BT_CLASS
- && !gfc_type_is_extension_of
- (a->ts.u.derived,
- mold->ts.u.derived->components->ts.u.derived)
- && !gfc_type_is_extension_of
- (mold->ts.u.derived->components->ts.u.derived,
- a->ts.u.derived))
- || (a->ts.type == BT_CLASS && mold->ts.type == BT_DERIVED
- && !gfc_type_is_extension_of
- (mold->ts.u.derived,
- a->ts.u.derived->components->ts.u.derived)))
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where, false);
-
- if (mold->ts.type == BT_DERIVED
- && gfc_type_is_extension_of (mold->ts.u.derived,
- a->ts.u.derived->components->ts.u.derived))
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where, true);
-
- return NULL;
-}
-
-
-gfc_expr *
-gfc_simplify_same_type_as (gfc_expr *a, gfc_expr *b)
-{
- /* Avoid simplification of resolved symbols. */
- if (is_last_ref_vtab (a) || is_last_ref_vtab (b))
- return NULL;
-
- /* Return .false. if the dynamic type can never be the
- same. */
- if ((a->ts.type == BT_CLASS || b->ts.type == BT_CLASS)
- && !gfc_type_compatible (&a->ts, &b->ts)
- && !gfc_type_compatible (&b->ts, &a->ts))
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where, false);
-
- if (a->ts.type != BT_DERIVED || b->ts.type != BT_DERIVED)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_compare_derived_types (a->ts.u.derived,
- b->ts.u.derived));
-}
-
-
-gfc_expr *
-gfc_simplify_floor (gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *result;
- mpfr_t floor;
- int kind;
-
- kind = get_kind (BT_INTEGER, k, "FLOOR", gfc_default_integer_kind);
- if (kind == -1)
- gfc_internal_error ("gfc_simplify_floor(): Bad kind");
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_set_model_kind (kind);
-
- mpfr_init (floor);
- mpfr_floor (floor, e->value.real);
-
- result = gfc_get_constant_expr (BT_INTEGER, kind, &e->where);
- gfc_mpfr_to_mpz (result->value.integer, floor, &e->where);
-
- mpfr_clear (floor);
-
- return range_check (result, "FLOOR");
-}
-
-
-gfc_expr *
-gfc_simplify_fraction (gfc_expr *x)
-{
- gfc_expr *result;
- mpfr_t absv, exp, pow2;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, x->ts.kind, &x->where);
-
- if (mpfr_sgn (x->value.real) == 0)
- {
- mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
- return result;
- }
-
- gfc_set_model_kind (x->ts.kind);
- mpfr_init (exp);
- mpfr_init (absv);
- mpfr_init (pow2);
-
- mpfr_abs (absv, x->value.real, GFC_RND_MODE);
- mpfr_log2 (exp, absv, GFC_RND_MODE);
-
- mpfr_trunc (exp, exp);
- mpfr_add_ui (exp, exp, 1, GFC_RND_MODE);
-
- mpfr_ui_pow (pow2, 2, exp, GFC_RND_MODE);
-
- mpfr_div (result->value.real, absv, pow2, GFC_RND_MODE);
-
- mpfr_clears (exp, absv, pow2, NULL);
-
- return range_check (result, "FRACTION");
-}
-
-
-gfc_expr *
-gfc_simplify_gamma (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_gamma (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "GAMMA");
-}
-
-
-gfc_expr *
-gfc_simplify_huge (gfc_expr *e)
-{
- gfc_expr *result;
- int i;
-
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
-
- switch (e->ts.type)
- {
- case BT_INTEGER:
- mpz_set (result->value.integer, gfc_integer_kinds[i].huge);
- break;
-
- case BT_REAL:
- mpfr_set (result->value.real, gfc_real_kinds[i].huge, GFC_RND_MODE);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_hypot (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_hypot (result->value.real, x->value.real, y->value.real, GFC_RND_MODE);
- return range_check (result, "HYPOT");
-}
-
-
-/* We use the processor's collating sequence, because all
- systems that gfortran currently works on are ASCII. */
-
-gfc_expr *
-gfc_simplify_iachar (gfc_expr *e, gfc_expr *kind)
-{
- gfc_expr *result;
- gfc_char_t index;
- int k;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (e->value.character.length != 1)
- {
- gfc_error ("Argument of IACHAR at %L must be of length one", &e->where);
- return &gfc_bad_expr;
- }
-
- index = e->value.character.string[0];
-
- if (gfc_option.warn_surprising && index > 127)
- gfc_warning ("Argument of IACHAR function at %L outside of range 0..127",
- &e->where);
-
- k = get_kind (BT_INTEGER, kind, "IACHAR", gfc_default_integer_kind);
- if (k == -1)
- return &gfc_bad_expr;
-
- result = gfc_get_int_expr (k, &e->where, index);
-
- return range_check (result, "IACHAR");
-}
-
-
-static gfc_expr *
-do_bit_and (gfc_expr *result, gfc_expr *e)
-{
- gcc_assert (e->ts.type == BT_INTEGER && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_INTEGER
- && result->expr_type == EXPR_CONSTANT);
-
- mpz_and (result->value.integer, result->value.integer, e->value.integer);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_iall (gfc_expr *array, gfc_expr *dim, gfc_expr *mask)
-{
- return simplify_transformation (array, dim, mask, -1, do_bit_and);
-}
-
-
-static gfc_expr *
-do_bit_ior (gfc_expr *result, gfc_expr *e)
-{
- gcc_assert (e->ts.type == BT_INTEGER && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_INTEGER
- && result->expr_type == EXPR_CONSTANT);
-
- mpz_ior (result->value.integer, result->value.integer, e->value.integer);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_iany (gfc_expr *array, gfc_expr *dim, gfc_expr *mask)
-{
- return simplify_transformation (array, dim, mask, 0, do_bit_ior);
-}
-
-
-gfc_expr *
-gfc_simplify_iand (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, x->ts.kind, &x->where);
- mpz_and (result->value.integer, x->value.integer, y->value.integer);
-
- return range_check (result, "IAND");
-}
-
-
-gfc_expr *
-gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int k, pos;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (y, &pos);
-
- k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
-
- result = gfc_copy_expr (x);
-
- convert_mpz_to_unsigned (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- mpz_clrbit (result->value.integer, pos);
-
- convert_mpz_to_signed (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_ibits (gfc_expr *x, gfc_expr *y, gfc_expr *z)
-{
- gfc_expr *result;
- int pos, len;
- int i, k, bitsize;
- int *bits;
-
- if (x->expr_type != EXPR_CONSTANT
- || y->expr_type != EXPR_CONSTANT
- || z->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (y, &pos);
- gfc_extract_int (z, &len);
-
- k = gfc_validate_kind (BT_INTEGER, x->ts.kind, false);
-
- bitsize = gfc_integer_kinds[k].bit_size;
-
- if (pos + len > bitsize)
- {
- gfc_error ("Sum of second and third arguments of IBITS exceeds "
- "bit size at %L", &y->where);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- convert_mpz_to_unsigned (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- bits = XCNEWVEC (int, bitsize);
-
- for (i = 0; i < bitsize; i++)
- bits[i] = 0;
-
- for (i = 0; i < len; i++)
- bits[i] = mpz_tstbit (x->value.integer, i + pos);
-
- for (i = 0; i < bitsize; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i);
- else if (bits[i] == 1)
- mpz_setbit (result->value.integer, i);
- else
- gfc_internal_error ("IBITS: Bad bit");
- }
-
- free (bits);
-
- convert_mpz_to_signed (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_ibset (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int k, pos;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (y, &pos);
-
- k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
-
- result = gfc_copy_expr (x);
-
- convert_mpz_to_unsigned (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- mpz_setbit (result->value.integer, pos);
-
- convert_mpz_to_signed (result->value.integer,
- gfc_integer_kinds[k].bit_size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_ichar (gfc_expr *e, gfc_expr *kind)
-{
- gfc_expr *result;
- gfc_char_t index;
- int k;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (e->value.character.length != 1)
- {
- gfc_error ("Argument of ICHAR at %L must be of length one", &e->where);
- return &gfc_bad_expr;
- }
-
- index = e->value.character.string[0];
-
- k = get_kind (BT_INTEGER, kind, "ICHAR", gfc_default_integer_kind);
- if (k == -1)
- return &gfc_bad_expr;
-
- result = gfc_get_int_expr (k, &e->where, index);
-
- return range_check (result, "ICHAR");
-}
-
-
-gfc_expr *
-gfc_simplify_ieor (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, x->ts.kind, &x->where);
- mpz_xor (result->value.integer, x->value.integer, y->value.integer);
-
- return range_check (result, "IEOR");
-}
-
-
-gfc_expr *
-gfc_simplify_index (gfc_expr *x, gfc_expr *y, gfc_expr *b, gfc_expr *kind)
-{
- gfc_expr *result;
- int back, len, lensub;
- int i, j, k, count, index = 0, start;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT
- || ( b != NULL && b->expr_type != EXPR_CONSTANT))
- return NULL;
-
- if (b != NULL && b->value.logical != 0)
- back = 1;
- else
- back = 0;
-
- k = get_kind (BT_INTEGER, kind, "INDEX", gfc_default_integer_kind);
- if (k == -1)
- return &gfc_bad_expr;
-
- result = gfc_get_constant_expr (BT_INTEGER, k, &x->where);
-
- len = x->value.character.length;
- lensub = y->value.character.length;
-
- if (len < lensub)
- {
- mpz_set_si (result->value.integer, 0);
- return result;
- }
-
- if (back == 0)
- {
- if (lensub == 0)
- {
- mpz_set_si (result->value.integer, 1);
- return result;
- }
- else if (lensub == 1)
- {
- for (i = 0; i < len; i++)
- {
- for (j = 0; j < lensub; j++)
- {
- if (y->value.character.string[j]
- == x->value.character.string[i])
- {
- index = i + 1;
- goto done;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < len; i++)
- {
- for (j = 0; j < lensub; j++)
- {
- if (y->value.character.string[j]
- == x->value.character.string[i])
- {
- start = i;
- count = 0;
-
- for (k = 0; k < lensub; k++)
- {
- if (y->value.character.string[k]
- == x->value.character.string[k + start])
- count++;
- }
-
- if (count == lensub)
- {
- index = start + 1;
- goto done;
- }
- }
- }
- }
- }
-
- }
- else
- {
- if (lensub == 0)
- {
- mpz_set_si (result->value.integer, len + 1);
- return result;
- }
- else if (lensub == 1)
- {
- for (i = 0; i < len; i++)
- {
- for (j = 0; j < lensub; j++)
- {
- if (y->value.character.string[j]
- == x->value.character.string[len - i])
- {
- index = len - i + 1;
- goto done;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < len; i++)
- {
- for (j = 0; j < lensub; j++)
- {
- if (y->value.character.string[j]
- == x->value.character.string[len - i])
- {
- start = len - i;
- if (start <= len - lensub)
- {
- count = 0;
- for (k = 0; k < lensub; k++)
- if (y->value.character.string[k]
- == x->value.character.string[k + start])
- count++;
-
- if (count == lensub)
- {
- index = start + 1;
- goto done;
- }
- }
- else
- {
- continue;
- }
- }
- }
- }
- }
- }
-
-done:
- mpz_set_si (result->value.integer, index);
- return range_check (result, "INDEX");
-}
-
-
-static gfc_expr *
-simplify_intconv (gfc_expr *e, int kind, const char *name)
-{
- gfc_expr *result = NULL;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_convert_constant (e, BT_INTEGER, kind);
- if (result == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- return range_check (result, name);
-}
-
-
-gfc_expr *
-gfc_simplify_int (gfc_expr *e, gfc_expr *k)
-{
- int kind;
-
- kind = get_kind (BT_INTEGER, k, "INT", gfc_default_integer_kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- return simplify_intconv (e, kind, "INT");
-}
-
-gfc_expr *
-gfc_simplify_int2 (gfc_expr *e)
-{
- return simplify_intconv (e, 2, "INT2");
-}
-
-
-gfc_expr *
-gfc_simplify_int8 (gfc_expr *e)
-{
- return simplify_intconv (e, 8, "INT8");
-}
-
-
-gfc_expr *
-gfc_simplify_long (gfc_expr *e)
-{
- return simplify_intconv (e, 4, "LONG");
-}
-
-
-gfc_expr *
-gfc_simplify_ifix (gfc_expr *e)
-{
- gfc_expr *rtrunc, *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- rtrunc = gfc_copy_expr (e);
- mpfr_trunc (rtrunc->value.real, e->value.real);
-
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &e->where);
- gfc_mpfr_to_mpz (result->value.integer, rtrunc->value.real, &e->where);
-
- gfc_free_expr (rtrunc);
-
- return range_check (result, "IFIX");
-}
-
-
-gfc_expr *
-gfc_simplify_idint (gfc_expr *e)
-{
- gfc_expr *rtrunc, *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- rtrunc = gfc_copy_expr (e);
- mpfr_trunc (rtrunc->value.real, e->value.real);
-
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &e->where);
- gfc_mpfr_to_mpz (result->value.integer, rtrunc->value.real, &e->where);
-
- gfc_free_expr (rtrunc);
-
- return range_check (result, "IDINT");
-}
-
-
-gfc_expr *
-gfc_simplify_ior (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, x->ts.kind, &x->where);
- mpz_ior (result->value.integer, x->value.integer, y->value.integer);
-
- return range_check (result, "IOR");
-}
-
-
-static gfc_expr *
-do_bit_xor (gfc_expr *result, gfc_expr *e)
-{
- gcc_assert (e->ts.type == BT_INTEGER && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_INTEGER
- && result->expr_type == EXPR_CONSTANT);
-
- mpz_xor (result->value.integer, result->value.integer, e->value.integer);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_iparity (gfc_expr *array, gfc_expr *dim, gfc_expr *mask)
-{
- return simplify_transformation (array, dim, mask, 0, do_bit_xor);
-}
-
-
-gfc_expr *
-gfc_simplify_is_iostat_end (gfc_expr *x)
-{
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &x->where,
- mpz_cmp_si (x->value.integer,
- LIBERROR_END) == 0);
-}
-
-
-gfc_expr *
-gfc_simplify_is_iostat_eor (gfc_expr *x)
-{
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &x->where,
- mpz_cmp_si (x->value.integer,
- LIBERROR_EOR) == 0);
-}
-
-
-gfc_expr *
-gfc_simplify_isnan (gfc_expr *x)
-{
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &x->where,
- mpfr_nan_p (x->value.real));
-}
-
-
-/* Performs a shift on its first argument. Depending on the last
- argument, the shift can be arithmetic, i.e. with filling from the
- left like in the SHIFTA intrinsic. */
-static gfc_expr *
-simplify_shift (gfc_expr *e, gfc_expr *s, const char *name,
- bool arithmetic, int direction)
-{
- gfc_expr *result;
- int ashift, *bits, i, k, bitsize, shift;
-
- if (e->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (s, &shift);
-
- k = gfc_validate_kind (BT_INTEGER, e->ts.kind, false);
- bitsize = gfc_integer_kinds[k].bit_size;
-
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
-
- if (shift == 0)
- {
- mpz_set (result->value.integer, e->value.integer);
- return result;
- }
-
- if (direction > 0 && shift < 0)
- {
- /* Left shift, as in SHIFTL. */
- gfc_error ("Second argument of %s is negative at %L", name, &e->where);
- return &gfc_bad_expr;
- }
- else if (direction < 0)
- {
- /* Right shift, as in SHIFTR or SHIFTA. */
- if (shift < 0)
- {
- gfc_error ("Second argument of %s is negative at %L",
- name, &e->where);
- return &gfc_bad_expr;
- }
-
- shift = -shift;
- }
-
- ashift = (shift >= 0 ? shift : -shift);
-
- if (ashift > bitsize)
- {
- gfc_error ("Magnitude of second argument of %s exceeds bit size "
- "at %L", name, &e->where);
- return &gfc_bad_expr;
- }
-
- bits = XCNEWVEC (int, bitsize);
-
- for (i = 0; i < bitsize; i++)
- bits[i] = mpz_tstbit (e->value.integer, i);
-
- if (shift > 0)
- {
- /* Left shift. */
- for (i = 0; i < shift; i++)
- mpz_clrbit (result->value.integer, i);
-
- for (i = 0; i < bitsize - shift; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i + shift);
- else
- mpz_setbit (result->value.integer, i + shift);
- }
- }
- else
- {
- /* Right shift. */
- if (arithmetic && bits[bitsize - 1])
- for (i = bitsize - 1; i >= bitsize - ashift; i--)
- mpz_setbit (result->value.integer, i);
- else
- for (i = bitsize - 1; i >= bitsize - ashift; i--)
- mpz_clrbit (result->value.integer, i);
-
- for (i = bitsize - 1; i >= ashift; i--)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i - ashift);
- else
- mpz_setbit (result->value.integer, i - ashift);
- }
- }
-
- convert_mpz_to_signed (result->value.integer, bitsize);
- free (bits);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_ishft (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "ISHFT", false, 0);
-}
-
-
-gfc_expr *
-gfc_simplify_lshift (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "LSHIFT", false, 1);
-}
-
-
-gfc_expr *
-gfc_simplify_rshift (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "RSHIFT", true, -1);
-}
-
-
-gfc_expr *
-gfc_simplify_shifta (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "SHIFTA", true, -1);
-}
-
-
-gfc_expr *
-gfc_simplify_shiftl (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "SHIFTL", false, 1);
-}
-
-
-gfc_expr *
-gfc_simplify_shiftr (gfc_expr *e, gfc_expr *s)
-{
- return simplify_shift (e, s, "SHIFTR", false, -1);
-}
-
-
-gfc_expr *
-gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
-{
- gfc_expr *result;
- int shift, ashift, isize, ssize, delta, k;
- int i, *bits;
-
- if (e->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (s, &shift);
-
- k = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- isize = gfc_integer_kinds[k].bit_size;
-
- if (sz != NULL)
- {
- if (sz->expr_type != EXPR_CONSTANT)
- return NULL;
-
- gfc_extract_int (sz, &ssize);
-
- }
- else
- ssize = isize;
-
- if (shift >= 0)
- ashift = shift;
- else
- ashift = -shift;
-
- if (ashift > ssize)
- {
- if (sz == NULL)
- gfc_error ("Magnitude of second argument of ISHFTC exceeds "
- "BIT_SIZE of first argument at %L", &s->where);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
-
- mpz_set (result->value.integer, e->value.integer);
-
- if (shift == 0)
- return result;
-
- convert_mpz_to_unsigned (result->value.integer, isize);
-
- bits = XCNEWVEC (int, ssize);
-
- for (i = 0; i < ssize; i++)
- bits[i] = mpz_tstbit (e->value.integer, i);
-
- delta = ssize - ashift;
-
- if (shift > 0)
- {
- for (i = 0; i < delta; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i + shift);
- else
- mpz_setbit (result->value.integer, i + shift);
- }
-
- for (i = delta; i < ssize; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i - delta);
- else
- mpz_setbit (result->value.integer, i - delta);
- }
- }
- else
- {
- for (i = 0; i < ashift; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i + delta);
- else
- mpz_setbit (result->value.integer, i + delta);
- }
-
- for (i = ashift; i < ssize; i++)
- {
- if (bits[i] == 0)
- mpz_clrbit (result->value.integer, i + shift);
- else
- mpz_setbit (result->value.integer, i + shift);
- }
- }
-
- convert_mpz_to_signed (result->value.integer, isize);
-
- free (bits);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_kind (gfc_expr *e)
-{
- return gfc_get_int_expr (gfc_default_integer_kind, NULL, e->ts.kind);
-}
-
-
-static gfc_expr *
-simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper,
- gfc_array_spec *as, gfc_ref *ref, bool coarray)
-{
- gfc_expr *l, *u, *result;
- int k;
-
- k = get_kind (BT_INTEGER, kind, upper ? "UBOUND" : "LBOUND",
- gfc_default_integer_kind);
- if (k == -1)
- return &gfc_bad_expr;
-
- result = gfc_get_constant_expr (BT_INTEGER, k, &array->where);
-
- /* For non-variables, LBOUND(expr, DIM=n) = 1 and
- UBOUND(expr, DIM=n) = SIZE(expr, DIM=n). */
- if (!coarray && array->expr_type != EXPR_VARIABLE)
- {
- if (upper)
- {
- gfc_expr* dim = result;
- mpz_set_si (dim->value.integer, d);
-
- result = simplify_size (array, dim, k);
- gfc_free_expr (dim);
- if (!result)
- goto returnNull;
- }
- else
- mpz_set_si (result->value.integer, 1);
-
- goto done;
- }
-
- /* Otherwise, we have a variable expression. */
- gcc_assert (array->expr_type == EXPR_VARIABLE);
- gcc_assert (as);
-
- if (gfc_resolve_array_spec (as, 0) == FAILURE)
- return NULL;
-
- /* The last dimension of an assumed-size array is special. */
- if ((!coarray && d == as->rank && as->type == AS_ASSUMED_SIZE && !upper)
- || (coarray && d == as->rank + as->corank
- && (!upper || gfc_option.coarray == GFC_FCOARRAY_SINGLE)))
- {
- if (as->lower[d-1]->expr_type == EXPR_CONSTANT)
- {
- gfc_free_expr (result);
- return gfc_copy_expr (as->lower[d-1]);
- }
-
- goto returnNull;
- }
-
- result = gfc_get_constant_expr (BT_INTEGER, k, &array->where);
-
- /* Then, we need to know the extent of the given dimension. */
- if (coarray || ref->u.ar.type == AR_FULL)
- {
- l = as->lower[d-1];
- u = as->upper[d-1];
-
- if (l->expr_type != EXPR_CONSTANT || u == NULL
- || u->expr_type != EXPR_CONSTANT)
- goto returnNull;
-
- if (mpz_cmp (l->value.integer, u->value.integer) > 0)
- {
- /* Zero extent. */
- if (upper)
- mpz_set_si (result->value.integer, 0);
- else
- mpz_set_si (result->value.integer, 1);
- }
- else
- {
- /* Nonzero extent. */
- if (upper)
- mpz_set (result->value.integer, u->value.integer);
- else
- mpz_set (result->value.integer, l->value.integer);
- }
- }
- else
- {
- if (upper)
- {
- if (gfc_ref_dimen_size (&ref->u.ar, d-1, &result->value.integer, NULL)
- != SUCCESS)
- goto returnNull;
- }
- else
- mpz_set_si (result->value.integer, (long int) 1);
- }
-
-done:
- return range_check (result, upper ? "UBOUND" : "LBOUND");
-
-returnNull:
- gfc_free_expr (result);
- return NULL;
-}
-
-
-static gfc_expr *
-simplify_bound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
-{
- gfc_ref *ref;
- gfc_array_spec *as;
- int d;
-
- if (array->ts.type == BT_CLASS)
- return NULL;
-
- if (array->expr_type != EXPR_VARIABLE)
- {
- as = NULL;
- ref = NULL;
- goto done;
- }
-
- /* Follow any component references. */
- as = array->symtree->n.sym->as;
- for (ref = array->ref; ref; ref = ref->next)
- {
- switch (ref->type)
- {
- case REF_ARRAY:
- switch (ref->u.ar.type)
- {
- case AR_ELEMENT:
- as = NULL;
- continue;
-
- case AR_FULL:
- /* We're done because 'as' has already been set in the
- previous iteration. */
- if (!ref->next)
- goto done;
-
- /* Fall through. */
-
- case AR_UNKNOWN:
- return NULL;
-
- case AR_SECTION:
- as = ref->u.ar.as;
- goto done;
- }
-
- gcc_unreachable ();
-
- case REF_COMPONENT:
- as = ref->u.c.component->as;
- continue;
-
- case REF_SUBSTRING:
- continue;
- }
- }
-
- gcc_unreachable ();
-
- done:
-
- if (as && (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE
- || as->type == AS_ASSUMED_RANK))
- return NULL;
-
- if (dim == NULL)
- {
- /* Multi-dimensional bounds. */
- gfc_expr *bounds[GFC_MAX_DIMENSIONS];
- gfc_expr *e;
- int k;
-
- /* UBOUND(ARRAY) is not valid for an assumed-size array. */
- if (upper && as && as->type == AS_ASSUMED_SIZE)
- {
- /* An error message will be emitted in
- check_assumed_size_reference (resolve.c). */
- return &gfc_bad_expr;
- }
-
- /* Simplify the bounds for each dimension. */
- for (d = 0; d < array->rank; d++)
- {
- bounds[d] = simplify_bound_dim (array, kind, d + 1, upper, as, ref,
- false);
- if (bounds[d] == NULL || bounds[d] == &gfc_bad_expr)
- {
- int j;
-
- for (j = 0; j < d; j++)
- gfc_free_expr (bounds[j]);
- return bounds[d];
- }
- }
-
- /* Allocate the result expression. */
- k = get_kind (BT_INTEGER, kind, upper ? "UBOUND" : "LBOUND",
- gfc_default_integer_kind);
- if (k == -1)
- return &gfc_bad_expr;
-
- e = gfc_get_array_expr (BT_INTEGER, k, &array->where);
-
- /* The result is a rank 1 array; its size is the rank of the first
- argument to {L,U}BOUND. */
- e->rank = 1;
- e->shape = gfc_get_shape (1);
- mpz_init_set_ui (e->shape[0], array->rank);
-
- /* Create the constructor for this array. */
- for (d = 0; d < array->rank; d++)
- gfc_constructor_append_expr (&e->value.constructor,
- bounds[d], &e->where);
-
- return e;
- }
- else
- {
- /* A DIM argument is specified. */
- if (dim->expr_type != EXPR_CONSTANT)
- return NULL;
-
- d = mpz_get_si (dim->value.integer);
-
- if ((d < 1 || d > array->rank)
- || (d == array->rank && as && as->type == AS_ASSUMED_SIZE && upper))
- {
- gfc_error ("DIM argument at %L is out of bounds", &dim->where);
- return &gfc_bad_expr;
- }
-
- if (as && as->type == AS_ASSUMED_RANK)
- return NULL;
-
- return simplify_bound_dim (array, kind, d, upper, as, ref, false);
- }
-}
-
-
-static gfc_expr *
-simplify_cobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
-{
- gfc_ref *ref;
- gfc_array_spec *as;
- int d;
-
- if (array->expr_type != EXPR_VARIABLE)
- return NULL;
-
- /* Follow any component references. */
- as = (array->ts.type == BT_CLASS && array->ts.u.derived->components)
- ? array->ts.u.derived->components->as
- : array->symtree->n.sym->as;
- for (ref = array->ref; ref; ref = ref->next)
- {
- switch (ref->type)
- {
- case REF_ARRAY:
- switch (ref->u.ar.type)
- {
- case AR_ELEMENT:
- if (ref->u.ar.as->corank > 0)
- {
- gcc_assert (as == ref->u.ar.as);
- goto done;
- }
- as = NULL;
- continue;
-
- case AR_FULL:
- /* We're done because 'as' has already been set in the
- previous iteration. */
- if (!ref->next)
- goto done;
-
- /* Fall through. */
-
- case AR_UNKNOWN:
- return NULL;
-
- case AR_SECTION:
- as = ref->u.ar.as;
- goto done;
- }
-
- gcc_unreachable ();
-
- case REF_COMPONENT:
- as = ref->u.c.component->as;
- continue;
-
- case REF_SUBSTRING:
- continue;
- }
- }
-
- if (!as)
- gcc_unreachable ();
-
- done:
-
- if (as->cotype == AS_DEFERRED || as->cotype == AS_ASSUMED_SHAPE)
- return NULL;
-
- if (dim == NULL)
- {
- /* Multi-dimensional cobounds. */
- gfc_expr *bounds[GFC_MAX_DIMENSIONS];
- gfc_expr *e;
- int k;
-
- /* Simplify the cobounds for each dimension. */
- for (d = 0; d < as->corank; d++)
- {
- bounds[d] = simplify_bound_dim (array, kind, d + 1 + as->rank,
- upper, as, ref, true);
- if (bounds[d] == NULL || bounds[d] == &gfc_bad_expr)
- {
- int j;
-
- for (j = 0; j < d; j++)
- gfc_free_expr (bounds[j]);
- return bounds[d];
- }
- }
-
- /* Allocate the result expression. */
- e = gfc_get_expr ();
- e->where = array->where;
- e->expr_type = EXPR_ARRAY;
- e->ts.type = BT_INTEGER;
- k = get_kind (BT_INTEGER, kind, upper ? "UCOBOUND" : "LCOBOUND",
- gfc_default_integer_kind);
- if (k == -1)
- {
- gfc_free_expr (e);
- return &gfc_bad_expr;
- }
- e->ts.kind = k;
-
- /* The result is a rank 1 array; its size is the rank of the first
- argument to {L,U}COBOUND. */
- e->rank = 1;
- e->shape = gfc_get_shape (1);
- mpz_init_set_ui (e->shape[0], as->corank);
-
- /* Create the constructor for this array. */
- for (d = 0; d < as->corank; d++)
- gfc_constructor_append_expr (&e->value.constructor,
- bounds[d], &e->where);
- return e;
- }
- else
- {
- /* A DIM argument is specified. */
- if (dim->expr_type != EXPR_CONSTANT)
- return NULL;
-
- d = mpz_get_si (dim->value.integer);
-
- if (d < 1 || d > as->corank)
- {
- gfc_error ("DIM argument at %L is out of bounds", &dim->where);
- return &gfc_bad_expr;
- }
-
- return simplify_bound_dim (array, kind, d+as->rank, upper, as, ref, true);
- }
-}
-
-
-gfc_expr *
-gfc_simplify_lbound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
-{
- return simplify_bound (array, dim, kind, 0);
-}
-
-
-gfc_expr *
-gfc_simplify_lcobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
-{
- return simplify_cobound (array, dim, kind, 0);
-}
-
-gfc_expr *
-gfc_simplify_leadz (gfc_expr *e)
-{
- unsigned long lz, bs;
- int i;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- bs = gfc_integer_kinds[i].bit_size;
- if (mpz_cmp_si (e->value.integer, 0) == 0)
- lz = bs;
- else if (mpz_cmp_si (e->value.integer, 0) < 0)
- lz = 0;
- else
- lz = bs - mpz_sizeinbase (e->value.integer, 2);
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, lz);
-}
-
-
-gfc_expr *
-gfc_simplify_len (gfc_expr *e, gfc_expr *kind)
-{
- gfc_expr *result;
- int k = get_kind (BT_INTEGER, kind, "LEN", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type == EXPR_CONSTANT)
- {
- result = gfc_get_constant_expr (BT_INTEGER, k, &e->where);
- mpz_set_si (result->value.integer, e->value.character.length);
- return range_check (result, "LEN");
- }
- else if (e->ts.u.cl != NULL && e->ts.u.cl->length != NULL
- && e->ts.u.cl->length->expr_type == EXPR_CONSTANT
- && e->ts.u.cl->length->ts.type == BT_INTEGER)
- {
- result = gfc_get_constant_expr (BT_INTEGER, k, &e->where);
- mpz_set (result->value.integer, e->ts.u.cl->length->value.integer);
- return range_check (result, "LEN");
- }
- else
- return NULL;
-}
-
-
-gfc_expr *
-gfc_simplify_len_trim (gfc_expr *e, gfc_expr *kind)
-{
- gfc_expr *result;
- int count, len, i;
- int k = get_kind (BT_INTEGER, kind, "LEN_TRIM", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- len = e->value.character.length;
- for (count = 0, i = 1; i <= len; i++)
- if (e->value.character.string[len - i] == ' ')
- count++;
- else
- break;
-
- result = gfc_get_int_expr (k, &e->where, len - count);
- return range_check (result, "LEN_TRIM");
-}
-
-gfc_expr *
-gfc_simplify_lgamma (gfc_expr *x)
-{
- gfc_expr *result;
- int sg;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_lgamma (result->value.real, &sg, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "LGAMMA");
-}
-
-
-gfc_expr *
-gfc_simplify_lge (gfc_expr *a, gfc_expr *b)
-{
- if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_compare_string (a, b) >= 0);
-}
-
-
-gfc_expr *
-gfc_simplify_lgt (gfc_expr *a, gfc_expr *b)
-{
- if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_compare_string (a, b) > 0);
-}
-
-
-gfc_expr *
-gfc_simplify_lle (gfc_expr *a, gfc_expr *b)
-{
- if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_compare_string (a, b) <= 0);
-}
-
-
-gfc_expr *
-gfc_simplify_llt (gfc_expr *a, gfc_expr *b)
-{
- if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
- gfc_compare_string (a, b) < 0);
-}
-
-
-gfc_expr *
-gfc_simplify_log (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- if (mpfr_sgn (x->value.real) <= 0)
- {
- gfc_error ("Argument of LOG at %L cannot be less than or equal "
- "to zero", &x->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- mpfr_log (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- if ((mpfr_sgn (mpc_realref (x->value.complex)) == 0)
- && (mpfr_sgn (mpc_imagref (x->value.complex)) == 0))
- {
- gfc_error ("Complex argument of LOG at %L cannot be zero",
- &x->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- gfc_set_model_kind (x->ts.kind);
- mpc_log (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_log: bad type");
- }
-
- return range_check (result, "LOG");
-}
-
-
-gfc_expr *
-gfc_simplify_log10 (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (mpfr_sgn (x->value.real) <= 0)
- {
- gfc_error ("Argument of LOG10 at %L cannot be less than or equal "
- "to zero", &x->where);
- return &gfc_bad_expr;
- }
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
- mpfr_log10 (result->value.real, x->value.real, GFC_RND_MODE);
-
- return range_check (result, "LOG10");
-}
-
-
-gfc_expr *
-gfc_simplify_logical (gfc_expr *e, gfc_expr *k)
-{
- int kind;
-
- kind = get_kind (BT_LOGICAL, k, "LOGICAL", gfc_default_logical_kind);
- if (kind < 0)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_get_logical_expr (kind, &e->where, e->value.logical);
-}
-
-
-gfc_expr*
-gfc_simplify_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b)
-{
- gfc_expr *result;
- int row, result_rows, col, result_columns;
- int stride_a, offset_a, stride_b, offset_b;
-
- if (!is_constant_array_expr (matrix_a)
- || !is_constant_array_expr (matrix_b))
- return NULL;
-
- gcc_assert (gfc_compare_types (&matrix_a->ts, &matrix_b->ts));
- result = gfc_get_array_expr (matrix_a->ts.type,
- matrix_a->ts.kind,
- &matrix_a->where);
-
- if (matrix_a->rank == 1 && matrix_b->rank == 2)
- {
- result_rows = 1;
- result_columns = mpz_get_si (matrix_b->shape[1]);
- stride_a = 1;
- stride_b = mpz_get_si (matrix_b->shape[0]);
-
- result->rank = 1;
- result->shape = gfc_get_shape (result->rank);
- mpz_init_set_si (result->shape[0], result_columns);
- }
- else if (matrix_a->rank == 2 && matrix_b->rank == 1)
- {
- result_rows = mpz_get_si (matrix_a->shape[0]);
- result_columns = 1;
- stride_a = mpz_get_si (matrix_a->shape[0]);
- stride_b = 1;
-
- result->rank = 1;
- result->shape = gfc_get_shape (result->rank);
- mpz_init_set_si (result->shape[0], result_rows);
- }
- else if (matrix_a->rank == 2 && matrix_b->rank == 2)
- {
- result_rows = mpz_get_si (matrix_a->shape[0]);
- result_columns = mpz_get_si (matrix_b->shape[1]);
- stride_a = mpz_get_si (matrix_a->shape[0]);
- stride_b = mpz_get_si (matrix_b->shape[0]);
-
- result->rank = 2;
- result->shape = gfc_get_shape (result->rank);
- mpz_init_set_si (result->shape[0], result_rows);
- mpz_init_set_si (result->shape[1], result_columns);
- }
- else
- gcc_unreachable();
-
- offset_a = offset_b = 0;
- for (col = 0; col < result_columns; ++col)
- {
- offset_a = 0;
-
- for (row = 0; row < result_rows; ++row)
- {
- gfc_expr *e = compute_dot_product (matrix_a, stride_a, offset_a,
- matrix_b, 1, offset_b);
- gfc_constructor_append_expr (&result->value.constructor,
- e, NULL);
-
- offset_a += 1;
- }
-
- offset_b += stride_b;
- }
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_maskr (gfc_expr *i, gfc_expr *kind_arg)
-{
- gfc_expr *result;
- int kind, arg, k;
- const char *s;
-
- if (i->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = get_kind (BT_INTEGER, kind_arg, "MASKR", gfc_default_integer_kind);
- if (kind == -1)
- return &gfc_bad_expr;
- k = gfc_validate_kind (BT_INTEGER, kind, false);
-
- s = gfc_extract_int (i, &arg);
- gcc_assert (!s);
-
- result = gfc_get_constant_expr (BT_INTEGER, kind, &i->where);
-
- /* MASKR(n) = 2^n - 1 */
- mpz_set_ui (result->value.integer, 1);
- mpz_mul_2exp (result->value.integer, result->value.integer, arg);
- mpz_sub_ui (result->value.integer, result->value.integer, 1);
-
- convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_maskl (gfc_expr *i, gfc_expr *kind_arg)
-{
- gfc_expr *result;
- int kind, arg, k;
- const char *s;
- mpz_t z;
-
- if (i->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = get_kind (BT_INTEGER, kind_arg, "MASKL", gfc_default_integer_kind);
- if (kind == -1)
- return &gfc_bad_expr;
- k = gfc_validate_kind (BT_INTEGER, kind, false);
-
- s = gfc_extract_int (i, &arg);
- gcc_assert (!s);
-
- result = gfc_get_constant_expr (BT_INTEGER, kind, &i->where);
-
- /* MASKL(n) = 2^bit_size - 2^(bit_size - n) */
- mpz_init_set_ui (z, 1);
- mpz_mul_2exp (z, z, gfc_integer_kinds[k].bit_size);
- mpz_set_ui (result->value.integer, 1);
- mpz_mul_2exp (result->value.integer, result->value.integer,
- gfc_integer_kinds[k].bit_size - arg);
- mpz_sub (result->value.integer, z, result->value.integer);
- mpz_clear (z);
-
- convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_merge (gfc_expr *tsource, gfc_expr *fsource, gfc_expr *mask)
-{
- if (tsource->expr_type != EXPR_CONSTANT
- || fsource->expr_type != EXPR_CONSTANT
- || mask->expr_type != EXPR_CONSTANT)
- return NULL;
-
- return gfc_copy_expr (mask->value.logical ? tsource : fsource);
-}
-
-
-gfc_expr *
-gfc_simplify_merge_bits (gfc_expr *i, gfc_expr *j, gfc_expr *mask_expr)
-{
- mpz_t arg1, arg2, mask;
- gfc_expr *result;
-
- if (i->expr_type != EXPR_CONSTANT || j->expr_type != EXPR_CONSTANT
- || mask_expr->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, i->ts.kind, &i->where);
-
- /* Convert all argument to unsigned. */
- mpz_init_set (arg1, i->value.integer);
- mpz_init_set (arg2, j->value.integer);
- mpz_init_set (mask, mask_expr->value.integer);
-
- /* MERGE_BITS(I,J,MASK) = IOR (IAND (I, MASK), IAND (J, NOT (MASK))). */
- mpz_and (arg1, arg1, mask);
- mpz_com (mask, mask);
- mpz_and (arg2, arg2, mask);
- mpz_ior (result->value.integer, arg1, arg2);
-
- mpz_clear (arg1);
- mpz_clear (arg2);
- mpz_clear (mask);
-
- return result;
-}
-
-
-/* Selects between current value and extremum for simplify_min_max
- and simplify_minval_maxval. */
-static void
-min_max_choose (gfc_expr *arg, gfc_expr *extremum, int sign)
-{
- switch (arg->ts.type)
- {
- case BT_INTEGER:
- if (mpz_cmp (arg->value.integer,
- extremum->value.integer) * sign > 0)
- mpz_set (extremum->value.integer, arg->value.integer);
- break;
-
- case BT_REAL:
- /* We need to use mpfr_min and mpfr_max to treat NaN properly. */
- if (sign > 0)
- mpfr_max (extremum->value.real, extremum->value.real,
- arg->value.real, GFC_RND_MODE);
- else
- mpfr_min (extremum->value.real, extremum->value.real,
- arg->value.real, GFC_RND_MODE);
- break;
-
- case BT_CHARACTER:
-#define LENGTH(x) ((x)->value.character.length)
-#define STRING(x) ((x)->value.character.string)
- if (LENGTH(extremum) < LENGTH(arg))
- {
- gfc_char_t *tmp = STRING(extremum);
-
- STRING(extremum) = gfc_get_wide_string (LENGTH(arg) + 1);
- memcpy (STRING(extremum), tmp,
- LENGTH(extremum) * sizeof (gfc_char_t));
- gfc_wide_memset (&STRING(extremum)[LENGTH(extremum)], ' ',
- LENGTH(arg) - LENGTH(extremum));
- STRING(extremum)[LENGTH(arg)] = '\0'; /* For debugger */
- LENGTH(extremum) = LENGTH(arg);
- free (tmp);
- }
-
- if (gfc_compare_string (arg, extremum) * sign > 0)
- {
- free (STRING(extremum));
- STRING(extremum) = gfc_get_wide_string (LENGTH(extremum) + 1);
- memcpy (STRING(extremum), STRING(arg),
- LENGTH(arg) * sizeof (gfc_char_t));
- gfc_wide_memset (&STRING(extremum)[LENGTH(arg)], ' ',
- LENGTH(extremum) - LENGTH(arg));
- STRING(extremum)[LENGTH(extremum)] = '\0'; /* For debugger */
- }
-#undef LENGTH
-#undef STRING
- break;
-
- default:
- gfc_internal_error ("simplify_min_max(): Bad type in arglist");
- }
-}
-
-
-/* This function is special since MAX() can take any number of
- arguments. The simplified expression is a rewritten version of the
- argument list containing at most one constant element. Other
- constant elements are deleted. Because the argument list has
- already been checked, this function always succeeds. sign is 1 for
- MAX(), -1 for MIN(). */
-
-static gfc_expr *
-simplify_min_max (gfc_expr *expr, int sign)
-{
- gfc_actual_arglist *arg, *last, *extremum;
- gfc_intrinsic_sym * specific;
-
- last = NULL;
- extremum = NULL;
- specific = expr->value.function.isym;
-
- arg = expr->value.function.actual;
-
- for (; arg; last = arg, arg = arg->next)
- {
- if (arg->expr->expr_type != EXPR_CONSTANT)
- continue;
-
- if (extremum == NULL)
- {
- extremum = arg;
- continue;
- }
-
- min_max_choose (arg->expr, extremum->expr, sign);
-
- /* Delete the extra constant argument. */
- last->next = arg->next;
-
- arg->next = NULL;
- gfc_free_actual_arglist (arg);
- arg = last;
- }
-
- /* If there is one value left, replace the function call with the
- expression. */
- if (expr->value.function.actual->next != NULL)
- return NULL;
-
- /* Convert to the correct type and kind. */
- if (expr->ts.type != BT_UNKNOWN)
- return gfc_convert_constant (expr->value.function.actual->expr,
- expr->ts.type, expr->ts.kind);
-
- if (specific->ts.type != BT_UNKNOWN)
- return gfc_convert_constant (expr->value.function.actual->expr,
- specific->ts.type, specific->ts.kind);
-
- return gfc_copy_expr (expr->value.function.actual->expr);
-}
-
-
-gfc_expr *
-gfc_simplify_min (gfc_expr *e)
-{
- return simplify_min_max (e, -1);
-}
-
-
-gfc_expr *
-gfc_simplify_max (gfc_expr *e)
-{
- return simplify_min_max (e, 1);
-}
-
-
-/* This is a simplified version of simplify_min_max to provide
- simplification of minval and maxval for a vector. */
-
-static gfc_expr *
-simplify_minval_maxval (gfc_expr *expr, int sign)
-{
- gfc_constructor *c, *extremum;
- gfc_intrinsic_sym * specific;
-
- extremum = NULL;
- specific = expr->value.function.isym;
-
- for (c = gfc_constructor_first (expr->value.constructor);
- c; c = gfc_constructor_next (c))
- {
- if (c->expr->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (extremum == NULL)
- {
- extremum = c;
- continue;
- }
-
- min_max_choose (c->expr, extremum->expr, sign);
- }
-
- if (extremum == NULL)
- return NULL;
-
- /* Convert to the correct type and kind. */
- if (expr->ts.type != BT_UNKNOWN)
- return gfc_convert_constant (extremum->expr,
- expr->ts.type, expr->ts.kind);
-
- if (specific->ts.type != BT_UNKNOWN)
- return gfc_convert_constant (extremum->expr,
- specific->ts.type, specific->ts.kind);
-
- return gfc_copy_expr (extremum->expr);
-}
-
-
-gfc_expr *
-gfc_simplify_minval (gfc_expr *array, gfc_expr* dim, gfc_expr *mask)
-{
- if (array->expr_type != EXPR_ARRAY || array->rank != 1 || dim || mask)
- return NULL;
-
- return simplify_minval_maxval (array, -1);
-}
-
-
-gfc_expr *
-gfc_simplify_maxval (gfc_expr *array, gfc_expr* dim, gfc_expr *mask)
-{
- if (array->expr_type != EXPR_ARRAY || array->rank != 1 || dim || mask)
- return NULL;
-
- return simplify_minval_maxval (array, 1);
-}
-
-
-gfc_expr *
-gfc_simplify_maxexponent (gfc_expr *x)
-{
- int i = gfc_validate_kind (BT_REAL, x->ts.kind, false);
- return gfc_get_int_expr (gfc_default_integer_kind, &x->where,
- gfc_real_kinds[i].max_exponent);
-}
-
-
-gfc_expr *
-gfc_simplify_minexponent (gfc_expr *x)
-{
- int i = gfc_validate_kind (BT_REAL, x->ts.kind, false);
- return gfc_get_int_expr (gfc_default_integer_kind, &x->where,
- gfc_real_kinds[i].min_exponent);
-}
-
-
-gfc_expr *
-gfc_simplify_mod (gfc_expr *a, gfc_expr *p)
-{
- gfc_expr *result;
- int kind;
-
- if (a->expr_type != EXPR_CONSTANT || p->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind;
- result = gfc_get_constant_expr (a->ts.type, kind, &a->where);
-
- switch (a->ts.type)
- {
- case BT_INTEGER:
- if (mpz_cmp_ui (p->value.integer, 0) == 0)
- {
- /* Result is processor-dependent. */
- gfc_error ("Second argument MOD at %L is zero", &a->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
- mpz_tdiv_r (result->value.integer, a->value.integer, p->value.integer);
- break;
-
- case BT_REAL:
- if (mpfr_cmp_ui (p->value.real, 0) == 0)
- {
- /* Result is processor-dependent. */
- gfc_error ("Second argument of MOD at %L is zero", &p->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- gfc_set_model_kind (kind);
- mpfr_fmod (result->value.real, a->value.real, p->value.real,
- GFC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_mod(): Bad arguments");
- }
-
- return range_check (result, "MOD");
-}
-
-
-gfc_expr *
-gfc_simplify_modulo (gfc_expr *a, gfc_expr *p)
-{
- gfc_expr *result;
- int kind;
-
- if (a->expr_type != EXPR_CONSTANT || p->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind;
- result = gfc_get_constant_expr (a->ts.type, kind, &a->where);
-
- switch (a->ts.type)
- {
- case BT_INTEGER:
- if (mpz_cmp_ui (p->value.integer, 0) == 0)
- {
- /* Result is processor-dependent. This processor just opts
- to not handle it at all. */
- gfc_error ("Second argument of MODULO at %L is zero", &a->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
- mpz_fdiv_r (result->value.integer, a->value.integer, p->value.integer);
-
- break;
-
- case BT_REAL:
- if (mpfr_cmp_ui (p->value.real, 0) == 0)
- {
- /* Result is processor-dependent. */
- gfc_error ("Second argument of MODULO at %L is zero", &p->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- gfc_set_model_kind (kind);
- mpfr_fmod (result->value.real, a->value.real, p->value.real,
- GFC_RND_MODE);
- if (mpfr_cmp_ui (result->value.real, 0) != 0)
- {
- if (mpfr_signbit (a->value.real) != mpfr_signbit (p->value.real))
- mpfr_add (result->value.real, result->value.real, p->value.real,
- GFC_RND_MODE);
- }
- else
- mpfr_copysign (result->value.real, result->value.real,
- p->value.real, GFC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("gfc_simplify_modulo(): Bad arguments");
- }
-
- return range_check (result, "MODULO");
-}
-
-
-/* Exists for the sole purpose of consistency with other intrinsics. */
-gfc_expr *
-gfc_simplify_mvbits (gfc_expr *f ATTRIBUTE_UNUSED,
- gfc_expr *fp ATTRIBUTE_UNUSED,
- gfc_expr *l ATTRIBUTE_UNUSED,
- gfc_expr *to ATTRIBUTE_UNUSED,
- gfc_expr *tp ATTRIBUTE_UNUSED)
-{
- return NULL;
-}
-
-
-gfc_expr *
-gfc_simplify_nearest (gfc_expr *x, gfc_expr *s)
-{
- gfc_expr *result;
- mp_exp_t emin, emax;
- int kind;
-
- if (x->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_copy_expr (x);
-
- /* Save current values of emin and emax. */
- emin = mpfr_get_emin ();
- emax = mpfr_get_emax ();
-
- /* Set emin and emax for the current model number. */
- kind = gfc_validate_kind (BT_REAL, x->ts.kind, 0);
- mpfr_set_emin ((mp_exp_t) gfc_real_kinds[kind].min_exponent -
- mpfr_get_prec(result->value.real) + 1);
- mpfr_set_emax ((mp_exp_t) gfc_real_kinds[kind].max_exponent - 1);
- mpfr_check_range (result->value.real, 0, GMP_RNDU);
-
- if (mpfr_sgn (s->value.real) > 0)
- {
- mpfr_nextabove (result->value.real);
- mpfr_subnormalize (result->value.real, 0, GMP_RNDU);
- }
- else
- {
- mpfr_nextbelow (result->value.real);
- mpfr_subnormalize (result->value.real, 0, GMP_RNDD);
- }
-
- mpfr_set_emin (emin);
- mpfr_set_emax (emax);
-
- /* Only NaN can occur. Do not use range check as it gives an
- error for denormal numbers. */
- if (mpfr_nan_p (result->value.real) && gfc_option.flag_range_check)
- {
- gfc_error ("Result of NEAREST is NaN at %L", &result->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- return result;
-}
-
-
-static gfc_expr *
-simplify_nint (const char *name, gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *itrunc, *result;
- int kind;
-
- kind = get_kind (BT_INTEGER, k, name, gfc_default_integer_kind);
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- itrunc = gfc_copy_expr (e);
- mpfr_round (itrunc->value.real, e->value.real);
-
- result = gfc_get_constant_expr (BT_INTEGER, kind, &e->where);
- gfc_mpfr_to_mpz (result->value.integer, itrunc->value.real, &e->where);
-
- gfc_free_expr (itrunc);
-
- return range_check (result, name);
-}
-
-
-gfc_expr *
-gfc_simplify_new_line (gfc_expr *e)
-{
- gfc_expr *result;
-
- result = gfc_get_character_expr (e->ts.kind, &e->where, NULL, 1);
- result->value.character.string[0] = '\n';
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_nint (gfc_expr *e, gfc_expr *k)
-{
- return simplify_nint ("NINT", e, k);
-}
-
-
-gfc_expr *
-gfc_simplify_idnint (gfc_expr *e)
-{
- return simplify_nint ("IDNINT", e, NULL);
-}
-
-
-static gfc_expr *
-add_squared (gfc_expr *result, gfc_expr *e)
-{
- mpfr_t tmp;
-
- gcc_assert (e->ts.type == BT_REAL && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_REAL
- && result->expr_type == EXPR_CONSTANT);
-
- gfc_set_model_kind (result->ts.kind);
- mpfr_init (tmp);
- mpfr_pow_ui (tmp, e->value.real, 2, GFC_RND_MODE);
- mpfr_add (result->value.real, result->value.real, tmp,
- GFC_RND_MODE);
- mpfr_clear (tmp);
-
- return result;
-}
-
-
-static gfc_expr *
-do_sqrt (gfc_expr *result, gfc_expr *e)
-{
- gcc_assert (e->ts.type == BT_REAL && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_REAL
- && result->expr_type == EXPR_CONSTANT);
-
- mpfr_set (result->value.real, e->value.real, GFC_RND_MODE);
- mpfr_sqrt (result->value.real, result->value.real, GFC_RND_MODE);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_norm2 (gfc_expr *e, gfc_expr *dim)
-{
- gfc_expr *result;
-
- if (!is_constant_array_expr (e)
- || (dim != NULL && !gfc_is_constant_expr (dim)))
- return NULL;
-
- result = transformational_result (e, dim, e->ts.type, e->ts.kind, &e->where);
- init_result_expr (result, 0, NULL);
-
- if (!dim || e->rank == 1)
- {
- result = simplify_transformation_to_scalar (result, e, NULL,
- add_squared);
- mpfr_sqrt (result->value.real, result->value.real, GFC_RND_MODE);
- }
- else
- result = simplify_transformation_to_array (result, e, dim, NULL,
- add_squared, &do_sqrt);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_not (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
- mpz_com (result->value.integer, e->value.integer);
-
- return range_check (result, "NOT");
-}
-
-
-gfc_expr *
-gfc_simplify_null (gfc_expr *mold)
-{
- gfc_expr *result;
-
- if (mold)
- {
- result = gfc_copy_expr (mold);
- result->expr_type = EXPR_NULL;
- }
- else
- result = gfc_get_null_expr (NULL);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_num_images (void)
-{
- gfc_expr *result;
-
- if (gfc_option.coarray == GFC_FCOARRAY_NONE)
- {
- gfc_fatal_error ("Coarrays disabled at %C, use -fcoarray= to enable");
- return &gfc_bad_expr;
- }
-
- if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
- return NULL;
-
- /* FIXME: gfc_current_locus is wrong. */
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &gfc_current_locus);
- mpz_set_si (result->value.integer, 1);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_or (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int kind;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind;
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- result = gfc_get_constant_expr (BT_INTEGER, kind, &x->where);
- mpz_ior (result->value.integer, x->value.integer, y->value.integer);
- return range_check (result, "OR");
-
- case BT_LOGICAL:
- return gfc_get_logical_expr (kind, &x->where,
- x->value.logical || y->value.logical);
- default:
- gcc_unreachable();
- }
-}
-
-
-gfc_expr *
-gfc_simplify_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector)
-{
- gfc_expr *result;
- gfc_constructor *array_ctor, *mask_ctor, *vector_ctor;
-
- if (!is_constant_array_expr(array)
- || !is_constant_array_expr(vector)
- || (!gfc_is_constant_expr (mask)
- && !is_constant_array_expr(mask)))
- return NULL;
-
- result = gfc_get_array_expr (array->ts.type, array->ts.kind, &array->where);
- if (array->ts.type == BT_DERIVED)
- result->ts.u.derived = array->ts.u.derived;
-
- array_ctor = gfc_constructor_first (array->value.constructor);
- vector_ctor = vector
- ? gfc_constructor_first (vector->value.constructor)
- : NULL;
-
- if (mask->expr_type == EXPR_CONSTANT
- && mask->value.logical)
- {
- /* Copy all elements of ARRAY to RESULT. */
- while (array_ctor)
- {
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_copy_expr (array_ctor->expr),
- NULL);
-
- array_ctor = gfc_constructor_next (array_ctor);
- vector_ctor = gfc_constructor_next (vector_ctor);
- }
- }
- else if (mask->expr_type == EXPR_ARRAY)
- {
- /* Copy only those elements of ARRAY to RESULT whose
- MASK equals .TRUE.. */
- mask_ctor = gfc_constructor_first (mask->value.constructor);
- while (mask_ctor)
- {
- if (mask_ctor->expr->value.logical)
- {
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_copy_expr (array_ctor->expr),
- NULL);
- vector_ctor = gfc_constructor_next (vector_ctor);
- }
-
- array_ctor = gfc_constructor_next (array_ctor);
- mask_ctor = gfc_constructor_next (mask_ctor);
- }
- }
-
- /* Append any left-over elements from VECTOR to RESULT. */
- while (vector_ctor)
- {
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_copy_expr (vector_ctor->expr),
- NULL);
- vector_ctor = gfc_constructor_next (vector_ctor);
- }
-
- result->shape = gfc_get_shape (1);
- gfc_array_size (result, &result->shape[0]);
-
- if (array->ts.type == BT_CHARACTER)
- result->ts.u.cl = array->ts.u.cl;
-
- return result;
-}
-
-
-static gfc_expr *
-do_xor (gfc_expr *result, gfc_expr *e)
-{
- gcc_assert (e->ts.type == BT_LOGICAL && e->expr_type == EXPR_CONSTANT);
- gcc_assert (result->ts.type == BT_LOGICAL
- && result->expr_type == EXPR_CONSTANT);
-
- result->value.logical = result->value.logical != e->value.logical;
- return result;
-}
-
-
-
-gfc_expr *
-gfc_simplify_parity (gfc_expr *e, gfc_expr *dim)
-{
- return simplify_transformation (e, dim, NULL, 0, do_xor);
-}
-
-
-gfc_expr *
-gfc_simplify_popcnt (gfc_expr *e)
-{
- int res, k;
- mpz_t x;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- k = gfc_validate_kind (e->ts.type, e->ts.kind, false);
-
- /* Convert argument to unsigned, then count the '1' bits. */
- mpz_init_set (x, e->value.integer);
- convert_mpz_to_unsigned (x, gfc_integer_kinds[k].bit_size);
- res = mpz_popcount (x);
- mpz_clear (x);
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, res);
-}
-
-
-gfc_expr *
-gfc_simplify_poppar (gfc_expr *e)
-{
- gfc_expr *popcnt;
- const char *s;
- int i;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- popcnt = gfc_simplify_popcnt (e);
- gcc_assert (popcnt);
-
- s = gfc_extract_int (popcnt, &i);
- gcc_assert (!s);
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, i % 2);
-}
-
-
-gfc_expr *
-gfc_simplify_precision (gfc_expr *e)
-{
- int i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where,
- gfc_real_kinds[i].precision);
-}
-
-
-gfc_expr *
-gfc_simplify_product (gfc_expr *array, gfc_expr *dim, gfc_expr *mask)
-{
- return simplify_transformation (array, dim, mask, 1, gfc_multiply);
-}
-
-
-gfc_expr *
-gfc_simplify_radix (gfc_expr *e)
-{
- int i;
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
-
- switch (e->ts.type)
- {
- case BT_INTEGER:
- i = gfc_integer_kinds[i].radix;
- break;
-
- case BT_REAL:
- i = gfc_real_kinds[i].radix;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, i);
-}
-
-
-gfc_expr *
-gfc_simplify_range (gfc_expr *e)
-{
- int i;
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
-
- switch (e->ts.type)
- {
- case BT_INTEGER:
- i = gfc_integer_kinds[i].range;
- break;
-
- case BT_REAL:
- case BT_COMPLEX:
- i = gfc_real_kinds[i].range;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, i);
-}
-
-
-gfc_expr *
-gfc_simplify_rank (gfc_expr *e)
-{
- /* Assumed rank. */
- if (e->rank == -1)
- return NULL;
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, e->rank);
-}
-
-
-gfc_expr *
-gfc_simplify_real (gfc_expr *e, gfc_expr *k)
-{
- gfc_expr *result = NULL;
- int kind;
-
- if (e->ts.type == BT_COMPLEX)
- kind = get_kind (BT_REAL, k, "REAL", e->ts.kind);
- else
- kind = get_kind (BT_REAL, k, "REAL", gfc_default_real_kind);
-
- if (kind == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (convert_boz (e, kind) == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- result = gfc_convert_constant (e, BT_REAL, kind);
- if (result == &gfc_bad_expr)
- return &gfc_bad_expr;
-
- return range_check (result, "REAL");
-}
-
-
-gfc_expr *
-gfc_simplify_realpart (gfc_expr *e)
-{
- gfc_expr *result;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpc_real (result->value.real, e->value.complex, GFC_RND_MODE);
-
- return range_check (result, "REALPART");
-}
-
-gfc_expr *
-gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
-{
- gfc_expr *result;
- int i, j, len, ncop, nlen;
- mpz_t ncopies;
- bool have_length = false;
-
- /* If NCOPIES isn't a constant, there's nothing we can do. */
- if (n->expr_type != EXPR_CONSTANT)
- return NULL;
-
- /* If NCOPIES is negative, it's an error. */
- if (mpz_sgn (n->value.integer) < 0)
- {
- gfc_error ("Argument NCOPIES of REPEAT intrinsic is negative at %L",
- &n->where);
- return &gfc_bad_expr;
- }
-
- /* If we don't know the character length, we can do no more. */
- if (e->ts.u.cl && e->ts.u.cl->length
- && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
- {
- len = mpz_get_si (e->ts.u.cl->length->value.integer);
- have_length = true;
- }
- else if (e->expr_type == EXPR_CONSTANT
- && (e->ts.u.cl == NULL || e->ts.u.cl->length == NULL))
- {
- len = e->value.character.length;
- }
- else
- return NULL;
-
- /* If the source length is 0, any value of NCOPIES is valid
- and everything behaves as if NCOPIES == 0. */
- mpz_init (ncopies);
- if (len == 0)
- mpz_set_ui (ncopies, 0);
- else
- mpz_set (ncopies, n->value.integer);
-
- /* Check that NCOPIES isn't too large. */
- if (len)
- {
- mpz_t max, mlen;
- int i;
-
- /* Compute the maximum value allowed for NCOPIES: huge(cl) / len. */
- mpz_init (max);
- i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
-
- if (have_length)
- {
- mpz_tdiv_q (max, gfc_integer_kinds[i].huge,
- e->ts.u.cl->length->value.integer);
- }
- else
- {
- mpz_init_set_si (mlen, len);
- mpz_tdiv_q (max, gfc_integer_kinds[i].huge, mlen);
- mpz_clear (mlen);
- }
-
- /* The check itself. */
- if (mpz_cmp (ncopies, max) > 0)
- {
- mpz_clear (max);
- mpz_clear (ncopies);
- gfc_error ("Argument NCOPIES of REPEAT intrinsic is too large at %L",
- &n->where);
- return &gfc_bad_expr;
- }
-
- mpz_clear (max);
- }
- mpz_clear (ncopies);
-
- /* For further simplification, we need the character string to be
- constant. */
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (len ||
- (e->ts.u.cl->length &&
- mpz_sgn (e->ts.u.cl->length->value.integer)) != 0)
- {
- const char *res = gfc_extract_int (n, &ncop);
- gcc_assert (res == NULL);
- }
- else
- ncop = 0;
-
- if (ncop == 0)
- return gfc_get_character_expr (e->ts.kind, &e->where, NULL, 0);
-
- len = e->value.character.length;
- nlen = ncop * len;
-
- result = gfc_get_character_expr (e->ts.kind, &e->where, NULL, nlen);
- for (i = 0; i < ncop; i++)
- for (j = 0; j < len; j++)
- result->value.character.string[j+i*len]= e->value.character.string[j];
-
- result->value.character.string[nlen] = '\0'; /* For debugger */
- return result;
-}
-
-
-/* This one is a bear, but mainly has to do with shuffling elements. */
-
-gfc_expr *
-gfc_simplify_reshape (gfc_expr *source, gfc_expr *shape_exp,
- gfc_expr *pad, gfc_expr *order_exp)
-{
- int order[GFC_MAX_DIMENSIONS], shape[GFC_MAX_DIMENSIONS];
- int i, rank, npad, x[GFC_MAX_DIMENSIONS];
- mpz_t index, size;
- unsigned long j;
- size_t nsource;
- gfc_expr *e, *result;
-
- /* Check that argument expression types are OK. */
- if (!is_constant_array_expr (source)
- || !is_constant_array_expr (shape_exp)
- || !is_constant_array_expr (pad)
- || !is_constant_array_expr (order_exp))
- return NULL;
-
- /* Proceed with simplification, unpacking the array. */
-
- mpz_init (index);
- rank = 0;
-
- for (;;)
- {
- e = gfc_constructor_lookup_expr (shape_exp->value.constructor, rank);
- if (e == NULL)
- break;
-
- gfc_extract_int (e, &shape[rank]);
-
- gcc_assert (rank >= 0 && rank < GFC_MAX_DIMENSIONS);
- gcc_assert (shape[rank] >= 0);
-
- rank++;
- }
-
- gcc_assert (rank > 0);
-
- /* Now unpack the order array if present. */
- if (order_exp == NULL)
- {
- for (i = 0; i < rank; i++)
- order[i] = i;
- }
- else
- {
- for (i = 0; i < rank; i++)
- x[i] = 0;
-
- for (i = 0; i < rank; i++)
- {
- e = gfc_constructor_lookup_expr (order_exp->value.constructor, i);
- gcc_assert (e);
-
- gfc_extract_int (e, &order[i]);
-
- gcc_assert (order[i] >= 1 && order[i] <= rank);
- order[i]--;
- gcc_assert (x[order[i]] == 0);
- x[order[i]] = 1;
- }
- }
-
- /* Count the elements in the source and padding arrays. */
-
- npad = 0;
- if (pad != NULL)
- {
- gfc_array_size (pad, &size);
- npad = mpz_get_ui (size);
- mpz_clear (size);
- }
-
- gfc_array_size (source, &size);
- nsource = mpz_get_ui (size);
- mpz_clear (size);
-
- /* If it weren't for that pesky permutation we could just loop
- through the source and round out any shortage with pad elements.
- But no, someone just had to have the compiler do something the
- user should be doing. */
-
- for (i = 0; i < rank; i++)
- x[i] = 0;
-
- result = gfc_get_array_expr (source->ts.type, source->ts.kind,
- &source->where);
- if (source->ts.type == BT_DERIVED)
- result->ts.u.derived = source->ts.u.derived;
- result->rank = rank;
- result->shape = gfc_get_shape (rank);
- for (i = 0; i < rank; i++)
- mpz_init_set_ui (result->shape[i], shape[i]);
-
- while (nsource > 0 || npad > 0)
- {
- /* Figure out which element to extract. */
- mpz_set_ui (index, 0);
-
- for (i = rank - 1; i >= 0; i--)
- {
- mpz_add_ui (index, index, x[order[i]]);
- if (i != 0)
- mpz_mul_ui (index, index, shape[order[i - 1]]);
- }
-
- if (mpz_cmp_ui (index, INT_MAX) > 0)
- gfc_internal_error ("Reshaped array too large at %C");
-
- j = mpz_get_ui (index);
-
- if (j < nsource)
- e = gfc_constructor_lookup_expr (source->value.constructor, j);
- else
- {
- gcc_assert (npad > 0);
-
- j = j - nsource;
- j = j % npad;
- e = gfc_constructor_lookup_expr (pad->value.constructor, j);
- }
- gcc_assert (e);
-
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_copy_expr (e), &e->where);
-
- /* Calculate the next element. */
- i = 0;
-
-inc:
- if (++x[i] < shape[i])
- continue;
- x[i++] = 0;
- if (i < rank)
- goto inc;
-
- break;
- }
-
- mpz_clear (index);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_rrspacing (gfc_expr *x)
-{
- gfc_expr *result;
- int i;
- long int e, p;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- i = gfc_validate_kind (x->ts.type, x->ts.kind, false);
-
- result = gfc_get_constant_expr (BT_REAL, x->ts.kind, &x->where);
- mpfr_abs (result->value.real, x->value.real, GFC_RND_MODE);
-
- /* Special case x = -0 and 0. */
- if (mpfr_sgn (result->value.real) == 0)
- {
- mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
- return result;
- }
-
- /* | x * 2**(-e) | * 2**p. */
- e = - (long int) mpfr_get_exp (x->value.real);
- mpfr_mul_2si (result->value.real, result->value.real, e, GFC_RND_MODE);
-
- p = (long int) gfc_real_kinds[i].digits;
- mpfr_mul_2si (result->value.real, result->value.real, p, GFC_RND_MODE);
-
- return range_check (result, "RRSPACING");
-}
-
-
-gfc_expr *
-gfc_simplify_scale (gfc_expr *x, gfc_expr *i)
-{
- int k, neg_flag, power, exp_range;
- mpfr_t scale, radix;
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || i->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, x->ts.kind, &x->where);
-
- if (mpfr_sgn (x->value.real) == 0)
- {
- mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
- return result;
- }
-
- k = gfc_validate_kind (BT_REAL, x->ts.kind, false);
-
- exp_range = gfc_real_kinds[k].max_exponent - gfc_real_kinds[k].min_exponent;
-
- /* This check filters out values of i that would overflow an int. */
- if (mpz_cmp_si (i->value.integer, exp_range + 2) > 0
- || mpz_cmp_si (i->value.integer, -exp_range - 2) < 0)
- {
- gfc_error ("Result of SCALE overflows its kind at %L", &result->where);
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- /* Compute scale = radix ** power. */
- power = mpz_get_si (i->value.integer);
-
- if (power >= 0)
- neg_flag = 0;
- else
- {
- neg_flag = 1;
- power = -power;
- }
-
- gfc_set_model_kind (x->ts.kind);
- mpfr_init (scale);
- mpfr_init (radix);
- mpfr_set_ui (radix, gfc_real_kinds[k].radix, GFC_RND_MODE);
- mpfr_pow_ui (scale, radix, power, GFC_RND_MODE);
-
- if (neg_flag)
- mpfr_div (result->value.real, x->value.real, scale, GFC_RND_MODE);
- else
- mpfr_mul (result->value.real, x->value.real, scale, GFC_RND_MODE);
-
- mpfr_clears (scale, radix, NULL);
-
- return range_check (result, "SCALE");
-}
-
-
-/* Variants of strspn and strcspn that operate on wide characters. */
-
-static size_t
-wide_strspn (const gfc_char_t *s1, const gfc_char_t *s2)
-{
- size_t i = 0;
- const gfc_char_t *c;
-
- while (s1[i])
- {
- for (c = s2; *c; c++)
- {
- if (s1[i] == *c)
- break;
- }
- if (*c == '\0')
- break;
- i++;
- }
-
- return i;
-}
-
-static size_t
-wide_strcspn (const gfc_char_t *s1, const gfc_char_t *s2)
-{
- size_t i = 0;
- const gfc_char_t *c;
-
- while (s1[i])
- {
- for (c = s2; *c; c++)
- {
- if (s1[i] == *c)
- break;
- }
- if (*c)
- break;
- i++;
- }
-
- return i;
-}
-
-
-gfc_expr *
-gfc_simplify_scan (gfc_expr *e, gfc_expr *c, gfc_expr *b, gfc_expr *kind)
-{
- gfc_expr *result;
- int back;
- size_t i;
- size_t indx, len, lenc;
- int k = get_kind (BT_INTEGER, kind, "SCAN", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
-
- if (e->expr_type != EXPR_CONSTANT || c->expr_type != EXPR_CONSTANT
- || ( b != NULL && b->expr_type != EXPR_CONSTANT))
- return NULL;
-
- if (b != NULL && b->value.logical != 0)
- back = 1;
- else
- back = 0;
-
- len = e->value.character.length;
- lenc = c->value.character.length;
-
- if (len == 0 || lenc == 0)
- {
- indx = 0;
- }
- else
- {
- if (back == 0)
- {
- indx = wide_strcspn (e->value.character.string,
- c->value.character.string) + 1;
- if (indx > len)
- indx = 0;
- }
- else
- {
- i = 0;
- for (indx = len; indx > 0; indx--)
- {
- for (i = 0; i < lenc; i++)
- {
- if (c->value.character.string[i]
- == e->value.character.string[indx - 1])
- break;
- }
- if (i < lenc)
- break;
- }
- }
- }
-
- result = gfc_get_int_expr (k, &e->where, indx);
- return range_check (result, "SCAN");
-}
-
-
-gfc_expr *
-gfc_simplify_selected_char_kind (gfc_expr *e)
-{
- int kind;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- if (gfc_compare_with_Cstring (e, "ascii", false) == 0
- || gfc_compare_with_Cstring (e, "default", false) == 0)
- kind = 1;
- else if (gfc_compare_with_Cstring (e, "iso_10646", false) == 0)
- kind = 4;
- else
- kind = -1;
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, kind);
-}
-
-
-gfc_expr *
-gfc_simplify_selected_int_kind (gfc_expr *e)
-{
- int i, kind, range;
-
- if (e->expr_type != EXPR_CONSTANT || gfc_extract_int (e, &range) != NULL)
- return NULL;
-
- kind = INT_MAX;
-
- for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
- if (gfc_integer_kinds[i].range >= range
- && gfc_integer_kinds[i].kind < kind)
- kind = gfc_integer_kinds[i].kind;
-
- if (kind == INT_MAX)
- kind = -1;
-
- return gfc_get_int_expr (gfc_default_integer_kind, &e->where, kind);
-}
-
-
-gfc_expr *
-gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q, gfc_expr *rdx)
-{
- int range, precision, radix, i, kind, found_precision, found_range,
- found_radix;
- locus *loc = &gfc_current_locus;
-
- if (p == NULL)
- precision = 0;
- else
- {
- if (p->expr_type != EXPR_CONSTANT
- || gfc_extract_int (p, &precision) != NULL)
- return NULL;
- loc = &p->where;
- }
-
- if (q == NULL)
- range = 0;
- else
- {
- if (q->expr_type != EXPR_CONSTANT
- || gfc_extract_int (q, &range) != NULL)
- return NULL;
-
- if (!loc)
- loc = &q->where;
- }
-
- if (rdx == NULL)
- radix = 0;
- else
- {
- if (rdx->expr_type != EXPR_CONSTANT
- || gfc_extract_int (rdx, &radix) != NULL)
- return NULL;
-
- if (!loc)
- loc = &rdx->where;
- }
-
- kind = INT_MAX;
- found_precision = 0;
- found_range = 0;
- found_radix = 0;
-
- for (i = 0; gfc_real_kinds[i].kind != 0; i++)
- {
- if (gfc_real_kinds[i].precision >= precision)
- found_precision = 1;
-
- if (gfc_real_kinds[i].range >= range)
- found_range = 1;
-
- if (gfc_real_kinds[i].radix >= radix)
- found_radix = 1;
-
- if (gfc_real_kinds[i].precision >= precision
- && gfc_real_kinds[i].range >= range
- && gfc_real_kinds[i].radix >= radix && gfc_real_kinds[i].kind < kind)
- kind = gfc_real_kinds[i].kind;
- }
-
- if (kind == INT_MAX)
- {
- if (found_radix && found_range && !found_precision)
- kind = -1;
- else if (found_radix && found_precision && !found_range)
- kind = -2;
- else if (found_radix && !found_precision && !found_range)
- kind = -3;
- else if (found_radix)
- kind = -4;
- else
- kind = -5;
- }
-
- return gfc_get_int_expr (gfc_default_integer_kind, loc, kind);
-}
-
-
-gfc_expr *
-gfc_simplify_set_exponent (gfc_expr *x, gfc_expr *i)
-{
- gfc_expr *result;
- mpfr_t exp, absv, log2, pow2, frac;
- unsigned long exp2;
-
- if (x->expr_type != EXPR_CONSTANT || i->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (BT_REAL, x->ts.kind, &x->where);
-
- if (mpfr_sgn (x->value.real) == 0)
- {
- mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
- return result;
- }
-
- gfc_set_model_kind (x->ts.kind);
- mpfr_init (absv);
- mpfr_init (log2);
- mpfr_init (exp);
- mpfr_init (pow2);
- mpfr_init (frac);
-
- mpfr_abs (absv, x->value.real, GFC_RND_MODE);
- mpfr_log2 (log2, absv, GFC_RND_MODE);
-
- mpfr_trunc (log2, log2);
- mpfr_add_ui (exp, log2, 1, GFC_RND_MODE);
-
- /* Old exponent value, and fraction. */
- mpfr_ui_pow (pow2, 2, exp, GFC_RND_MODE);
-
- mpfr_div (frac, absv, pow2, GFC_RND_MODE);
-
- /* New exponent. */
- exp2 = (unsigned long) mpz_get_d (i->value.integer);
- mpfr_mul_2exp (result->value.real, frac, exp2, GFC_RND_MODE);
-
- mpfr_clears (absv, log2, pow2, frac, NULL);
-
- return range_check (result, "SET_EXPONENT");
-}
-
-
-gfc_expr *
-gfc_simplify_shape (gfc_expr *source, gfc_expr *kind)
-{
- mpz_t shape[GFC_MAX_DIMENSIONS];
- gfc_expr *result, *e, *f;
- gfc_array_ref *ar;
- int n;
- gfc_try t;
- int k = get_kind (BT_INTEGER, kind, "SHAPE", gfc_default_integer_kind);
-
- if (source->rank == -1)
- return NULL;
-
- result = gfc_get_array_expr (BT_INTEGER, k, &source->where);
-
- if (source->rank == 0)
- return result;
-
- if (source->expr_type == EXPR_VARIABLE)
- {
- ar = gfc_find_array_ref (source);
- t = gfc_array_ref_shape (ar, shape);
- }
- else if (source->shape)
- {
- t = SUCCESS;
- for (n = 0; n < source->rank; n++)
- {
- mpz_init (shape[n]);
- mpz_set (shape[n], source->shape[n]);
- }
- }
- else
- t = FAILURE;
-
- for (n = 0; n < source->rank; n++)
- {
- e = gfc_get_constant_expr (BT_INTEGER, k, &source->where);
-
- if (t == SUCCESS)
- mpz_set (e->value.integer, shape[n]);
- else
- {
- mpz_set_ui (e->value.integer, n + 1);
-
- f = simplify_size (source, e, k);
- gfc_free_expr (e);
- if (f == NULL)
- {
- gfc_free_expr (result);
- return NULL;
- }
- else
- e = f;
- }
-
- if (e == &gfc_bad_expr || range_check (e, "SHAPE") == &gfc_bad_expr)
- {
- gfc_free_expr (result);
- if (t)
- gfc_clear_shape (shape, source->rank);
- return &gfc_bad_expr;
- }
-
- gfc_constructor_append_expr (&result->value.constructor, e, NULL);
- }
-
- if (t)
- gfc_clear_shape (shape, source->rank);
-
- return result;
-}
-
-
-static gfc_expr *
-simplify_size (gfc_expr *array, gfc_expr *dim, int k)
-{
- mpz_t size;
- gfc_expr *return_value;
- int d;
-
- /* For unary operations, the size of the result is given by the size
- of the operand. For binary ones, it's the size of the first operand
- unless it is scalar, then it is the size of the second. */
- if (array->expr_type == EXPR_OP && !array->value.op.uop)
- {
- gfc_expr* replacement;
- gfc_expr* simplified;
-
- switch (array->value.op.op)
- {
- /* Unary operations. */
- case INTRINSIC_NOT:
- case INTRINSIC_UPLUS:
- case INTRINSIC_UMINUS:
- case INTRINSIC_PARENTHESES:
- replacement = array->value.op.op1;
- break;
-
- /* Binary operations. If any one of the operands is scalar, take
- the other one's size. If both of them are arrays, it does not
- matter -- try to find one with known shape, if possible. */
- default:
- if (array->value.op.op1->rank == 0)
- replacement = array->value.op.op2;
- else if (array->value.op.op2->rank == 0)
- replacement = array->value.op.op1;
- else
- {
- simplified = simplify_size (array->value.op.op1, dim, k);
- if (simplified)
- return simplified;
-
- replacement = array->value.op.op2;
- }
- break;
- }
-
- /* Try to reduce it directly if possible. */
- simplified = simplify_size (replacement, dim, k);
-
- /* Otherwise, we build a new SIZE call. This is hopefully at least
- simpler than the original one. */
- if (!simplified)
- {
- gfc_expr *kind = gfc_get_int_expr (gfc_default_integer_kind, NULL, k);
- simplified = gfc_build_intrinsic_call (gfc_current_ns,
- GFC_ISYM_SIZE, "size",
- array->where, 3,
- gfc_copy_expr (replacement),
- gfc_copy_expr (dim),
- kind);
- }
- return simplified;
- }
-
- if (dim == NULL)
- {
- if (gfc_array_size (array, &size) == FAILURE)
- return NULL;
- }
- else
- {
- if (dim->expr_type != EXPR_CONSTANT)
- return NULL;
-
- d = mpz_get_ui (dim->value.integer) - 1;
- if (gfc_array_dimen_size (array, d, &size) == FAILURE)
- return NULL;
- }
-
- return_value = gfc_get_constant_expr (BT_INTEGER, k, &array->where);
- mpz_set (return_value->value.integer, size);
- mpz_clear (size);
-
- return return_value;
-}
-
-
-gfc_expr *
-gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
-{
- gfc_expr *result;
- int k = get_kind (BT_INTEGER, kind, "SIZE", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
-
- result = simplify_size (array, dim, k);
- if (result == NULL || result == &gfc_bad_expr)
- return result;
-
- return range_check (result, "SIZE");
-}
-
-
-gfc_expr *
-gfc_simplify_sign (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- mpz_abs (result->value.integer, x->value.integer);
- if (mpz_sgn (y->value.integer) < 0)
- mpz_neg (result->value.integer, result->value.integer);
- break;
-
- case BT_REAL:
- if (gfc_option.flag_sign_zero)
- mpfr_copysign (result->value.real, x->value.real, y->value.real,
- GFC_RND_MODE);
- else
- mpfr_setsign (result->value.real, x->value.real,
- mpfr_sgn (y->value.real) < 0 ? 1 : 0, GFC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("Bad type in gfc_simplify_sign");
- }
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_sin (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_sin (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- gfc_set_model (x->value.real);
- mpc_sin (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("in gfc_simplify_sin(): Bad type");
- }
-
- return range_check (result, "SIN");
-}
-
-
-gfc_expr *
-gfc_simplify_sinh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_sinh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_sinh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return range_check (result, "SINH");
-}
-
-
-/* The argument is always a double precision real that is converted to
- single precision. TODO: Rounding! */
-
-gfc_expr *
-gfc_simplify_sngl (gfc_expr *a)
-{
- gfc_expr *result;
-
- if (a->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_real2real (a, gfc_default_real_kind);
- return range_check (result, "SNGL");
-}
-
-
-gfc_expr *
-gfc_simplify_spacing (gfc_expr *x)
-{
- gfc_expr *result;
- int i;
- long int en, ep;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- i = gfc_validate_kind (x->ts.type, x->ts.kind, false);
-
- result = gfc_get_constant_expr (BT_REAL, x->ts.kind, &x->where);
-
- /* Special case x = 0 and -0. */
- mpfr_abs (result->value.real, x->value.real, GFC_RND_MODE);
- if (mpfr_sgn (result->value.real) == 0)
- {
- mpfr_set (result->value.real, gfc_real_kinds[i].tiny, GFC_RND_MODE);
- return result;
- }
-
- /* In the Fortran 95 standard, the result is b**(e - p) where b, e, and p
- are the radix, exponent of x, and precision. This excludes the
- possibility of subnormal numbers. Fortran 2003 states the result is
- b**max(e - p, emin - 1). */
-
- ep = (long int) mpfr_get_exp (x->value.real) - gfc_real_kinds[i].digits;
- en = (long int) gfc_real_kinds[i].min_exponent - 1;
- en = en > ep ? en : ep;
-
- mpfr_set_ui (result->value.real, 1, GFC_RND_MODE);
- mpfr_mul_2si (result->value.real, result->value.real, en, GFC_RND_MODE);
-
- return range_check (result, "SPACING");
-}
-
-
-gfc_expr *
-gfc_simplify_spread (gfc_expr *source, gfc_expr *dim_expr, gfc_expr *ncopies_expr)
-{
- gfc_expr *result = 0L;
- int i, j, dim, ncopies;
- mpz_t size;
-
- if ((!gfc_is_constant_expr (source)
- && !is_constant_array_expr (source))
- || !gfc_is_constant_expr (dim_expr)
- || !gfc_is_constant_expr (ncopies_expr))
- return NULL;
-
- gcc_assert (dim_expr->ts.type == BT_INTEGER);
- gfc_extract_int (dim_expr, &dim);
- dim -= 1; /* zero-base DIM */
-
- gcc_assert (ncopies_expr->ts.type == BT_INTEGER);
- gfc_extract_int (ncopies_expr, &ncopies);
- ncopies = MAX (ncopies, 0);
-
- /* Do not allow the array size to exceed the limit for an array
- constructor. */
- if (source->expr_type == EXPR_ARRAY)
- {
- if (gfc_array_size (source, &size) == FAILURE)
- gfc_internal_error ("Failure getting length of a constant array.");
- }
- else
- mpz_init_set_ui (size, 1);
-
- if (mpz_get_si (size)*ncopies > gfc_option.flag_max_array_constructor)
- return NULL;
-
- if (source->expr_type == EXPR_CONSTANT)
- {
- gcc_assert (dim == 0);
-
- result = gfc_get_array_expr (source->ts.type, source->ts.kind,
- &source->where);
- if (source->ts.type == BT_DERIVED)
- result->ts.u.derived = source->ts.u.derived;
- result->rank = 1;
- result->shape = gfc_get_shape (result->rank);
- mpz_init_set_si (result->shape[0], ncopies);
-
- for (i = 0; i < ncopies; ++i)
- gfc_constructor_append_expr (&result->value.constructor,
- gfc_copy_expr (source), NULL);
- }
- else if (source->expr_type == EXPR_ARRAY)
- {
- int offset, rstride[GFC_MAX_DIMENSIONS], extent[GFC_MAX_DIMENSIONS];
- gfc_constructor *source_ctor;
-
- gcc_assert (source->rank < GFC_MAX_DIMENSIONS);
- gcc_assert (dim >= 0 && dim <= source->rank);
-
- result = gfc_get_array_expr (source->ts.type, source->ts.kind,
- &source->where);
- if (source->ts.type == BT_DERIVED)
- result->ts.u.derived = source->ts.u.derived;
- result->rank = source->rank + 1;
- result->shape = gfc_get_shape (result->rank);
-
- for (i = 0, j = 0; i < result->rank; ++i)
- {
- if (i != dim)
- mpz_init_set (result->shape[i], source->shape[j++]);
- else
- mpz_init_set_si (result->shape[i], ncopies);
-
- extent[i] = mpz_get_si (result->shape[i]);
- rstride[i] = (i == 0) ? 1 : rstride[i-1] * extent[i-1];
- }
-
- offset = 0;
- for (source_ctor = gfc_constructor_first (source->value.constructor);
- source_ctor; source_ctor = gfc_constructor_next (source_ctor))
- {
- for (i = 0; i < ncopies; ++i)
- gfc_constructor_insert_expr (&result->value.constructor,
- gfc_copy_expr (source_ctor->expr),
- NULL, offset + i * rstride[dim]);
-
- offset += (dim == 0 ? ncopies : 1);
- }
- }
- else
- /* FIXME: Returning here avoids a regression in array_simplify_1.f90.
- Replace NULL with gcc_unreachable() after implementing
- gfc_simplify_cshift(). */
- return NULL;
-
- if (source->ts.type == BT_CHARACTER)
- result->ts.u.cl = source->ts.u.cl;
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_sqrt (gfc_expr *e)
-{
- gfc_expr *result = NULL;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- switch (e->ts.type)
- {
- case BT_REAL:
- if (mpfr_cmp_si (e->value.real, 0) < 0)
- {
- gfc_error ("Argument of SQRT at %L has a negative value",
- &e->where);
- return &gfc_bad_expr;
- }
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
- mpfr_sqrt (result->value.real, e->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- gfc_set_model (e->value.real);
-
- result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
- mpc_sqrt (result->value.complex, e->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gfc_internal_error ("invalid argument of SQRT at %L", &e->where);
- }
-
- return range_check (result, "SQRT");
-}
-
-
-gfc_expr *
-gfc_simplify_sum (gfc_expr *array, gfc_expr *dim, gfc_expr *mask)
-{
- return simplify_transformation (array, dim, mask, 0, gfc_add);
-}
-
-
-gfc_expr *
-gfc_simplify_tan (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_tan (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_tan (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return range_check (result, "TAN");
-}
-
-
-gfc_expr *
-gfc_simplify_tanh (gfc_expr *x)
-{
- gfc_expr *result;
-
- if (x->expr_type != EXPR_CONSTANT)
- return NULL;
-
- result = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
-
- switch (x->ts.type)
- {
- case BT_REAL:
- mpfr_tanh (result->value.real, x->value.real, GFC_RND_MODE);
- break;
-
- case BT_COMPLEX:
- mpc_tanh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return range_check (result, "TANH");
-}
-
-
-gfc_expr *
-gfc_simplify_tiny (gfc_expr *e)
-{
- gfc_expr *result;
- int i;
-
- i = gfc_validate_kind (BT_REAL, e->ts.kind, false);
-
- result = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
- mpfr_set (result->value.real, gfc_real_kinds[i].tiny, GFC_RND_MODE);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_trailz (gfc_expr *e)
-{
- unsigned long tz, bs;
- int i;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- i = gfc_validate_kind (e->ts.type, e->ts.kind, false);
- bs = gfc_integer_kinds[i].bit_size;
- tz = mpz_scan1 (e->value.integer, 0);
-
- return gfc_get_int_expr (gfc_default_integer_kind,
- &e->where, MIN (tz, bs));
-}
-
-
-gfc_expr *
-gfc_simplify_transfer (gfc_expr *source, gfc_expr *mold, gfc_expr *size)
-{
- gfc_expr *result;
- gfc_expr *mold_element;
- size_t source_size;
- size_t result_size;
- size_t buffer_size;
- mpz_t tmp;
- unsigned char *buffer;
- size_t result_length;
-
-
- if (!gfc_is_constant_expr (source)
- || (gfc_init_expr_flag && !gfc_is_constant_expr (mold))
- || !gfc_is_constant_expr (size))
- return NULL;
-
- if (gfc_calculate_transfer_sizes (source, mold, size, &source_size,
- &result_size, &result_length) == FAILURE)
- return NULL;
-
- /* Calculate the size of the source. */
- if (source->expr_type == EXPR_ARRAY
- && gfc_array_size (source, &tmp) == FAILURE)
- gfc_internal_error ("Failure getting length of a constant array.");
-
- /* Create an empty new expression with the appropriate characteristics. */
- result = gfc_get_constant_expr (mold->ts.type, mold->ts.kind,
- &source->where);
- result->ts = mold->ts;
-
- mold_element = mold->expr_type == EXPR_ARRAY
- ? gfc_constructor_first (mold->value.constructor)->expr
- : mold;
-
- /* Set result character length, if needed. Note that this needs to be
- set even for array expressions, in order to pass this information into
- gfc_target_interpret_expr. */
- if (result->ts.type == BT_CHARACTER && gfc_is_constant_expr (mold_element))
- result->value.character.length = mold_element->value.character.length;
-
- /* Set the number of elements in the result, and determine its size. */
-
- if (mold->expr_type == EXPR_ARRAY || mold->rank || size)
- {
- result->expr_type = EXPR_ARRAY;
- result->rank = 1;
- result->shape = gfc_get_shape (1);
- mpz_init_set_ui (result->shape[0], result_length);
- }
- else
- result->rank = 0;
-
- /* Allocate the buffer to store the binary version of the source. */
- buffer_size = MAX (source_size, result_size);
- buffer = (unsigned char*)alloca (buffer_size);
- memset (buffer, 0, buffer_size);
-
- /* Now write source to the buffer. */
- gfc_target_encode_expr (source, buffer, buffer_size);
-
- /* And read the buffer back into the new expression. */
- gfc_target_interpret_expr (buffer, buffer_size, result, false);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_transpose (gfc_expr *matrix)
-{
- int row, matrix_rows, col, matrix_cols;
- gfc_expr *result;
-
- if (!is_constant_array_expr (matrix))
- return NULL;
-
- gcc_assert (matrix->rank == 2);
-
- result = gfc_get_array_expr (matrix->ts.type, matrix->ts.kind,
- &matrix->where);
- result->rank = 2;
- result->shape = gfc_get_shape (result->rank);
- mpz_set (result->shape[0], matrix->shape[1]);
- mpz_set (result->shape[1], matrix->shape[0]);
-
- if (matrix->ts.type == BT_CHARACTER)
- result->ts.u.cl = matrix->ts.u.cl;
- else if (matrix->ts.type == BT_DERIVED)
- result->ts.u.derived = matrix->ts.u.derived;
-
- matrix_rows = mpz_get_si (matrix->shape[0]);
- matrix_cols = mpz_get_si (matrix->shape[1]);
- for (row = 0; row < matrix_rows; ++row)
- for (col = 0; col < matrix_cols; ++col)
- {
- gfc_expr *e = gfc_constructor_lookup_expr (matrix->value.constructor,
- col * matrix_rows + row);
- gfc_constructor_insert_expr (&result->value.constructor,
- gfc_copy_expr (e), &matrix->where,
- row * matrix_cols + col);
- }
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_trim (gfc_expr *e)
-{
- gfc_expr *result;
- int count, i, len, lentrim;
-
- if (e->expr_type != EXPR_CONSTANT)
- return NULL;
-
- len = e->value.character.length;
- for (count = 0, i = 1; i <= len; ++i)
- {
- if (e->value.character.string[len - i] == ' ')
- count++;
- else
- break;
- }
-
- lentrim = len - count;
-
- result = gfc_get_character_expr (e->ts.kind, &e->where, NULL, lentrim);
- for (i = 0; i < lentrim; i++)
- result->value.character.string[i] = e->value.character.string[i];
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_image_index (gfc_expr *coarray, gfc_expr *sub)
-{
- gfc_expr *result;
- gfc_ref *ref;
- gfc_array_spec *as;
- gfc_constructor *sub_cons;
- bool first_image;
- int d;
-
- if (!is_constant_array_expr (sub))
- return NULL;
-
- /* Follow any component references. */
- as = coarray->symtree->n.sym->as;
- for (ref = coarray->ref; ref; ref = ref->next)
- if (ref->type == REF_COMPONENT)
- as = ref->u.ar.as;
-
- if (as->type == AS_DEFERRED)
- return NULL;
-
- /* "valid sequence of cosubscripts" are required; thus, return 0 unless
- the cosubscript addresses the first image. */
-
- sub_cons = gfc_constructor_first (sub->value.constructor);
- first_image = true;
-
- for (d = 1; d <= as->corank; d++)
- {
- gfc_expr *ca_bound;
- int cmp;
-
- gcc_assert (sub_cons != NULL);
-
- ca_bound = simplify_bound_dim (coarray, NULL, d + as->rank, 0, as,
- NULL, true);
- if (ca_bound == NULL)
- return NULL;
-
- if (ca_bound == &gfc_bad_expr)
- return ca_bound;
-
- cmp = mpz_cmp (ca_bound->value.integer, sub_cons->expr->value.integer);
-
- if (cmp == 0)
- {
- gfc_free_expr (ca_bound);
- sub_cons = gfc_constructor_next (sub_cons);
- continue;
- }
-
- first_image = false;
-
- if (cmp > 0)
- {
- gfc_error ("Out of bounds in IMAGE_INDEX at %L for dimension %d, "
- "SUB has %ld and COARRAY lower bound is %ld)",
- &coarray->where, d,
- mpz_get_si (sub_cons->expr->value.integer),
- mpz_get_si (ca_bound->value.integer));
- gfc_free_expr (ca_bound);
- return &gfc_bad_expr;
- }
-
- gfc_free_expr (ca_bound);
-
- /* Check whether upperbound is valid for the multi-images case. */
- if (d < as->corank)
- {
- ca_bound = simplify_bound_dim (coarray, NULL, d + as->rank, 1, as,
- NULL, true);
- if (ca_bound == &gfc_bad_expr)
- return ca_bound;
-
- if (ca_bound && ca_bound->expr_type == EXPR_CONSTANT
- && mpz_cmp (ca_bound->value.integer,
- sub_cons->expr->value.integer) < 0)
- {
- gfc_error ("Out of bounds in IMAGE_INDEX at %L for dimension %d, "
- "SUB has %ld and COARRAY upper bound is %ld)",
- &coarray->where, d,
- mpz_get_si (sub_cons->expr->value.integer),
- mpz_get_si (ca_bound->value.integer));
- gfc_free_expr (ca_bound);
- return &gfc_bad_expr;
- }
-
- if (ca_bound)
- gfc_free_expr (ca_bound);
- }
-
- sub_cons = gfc_constructor_next (sub_cons);
- }
-
- gcc_assert (sub_cons == NULL);
-
- if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && !first_image)
- return NULL;
-
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &gfc_current_locus);
- if (first_image)
- mpz_set_si (result->value.integer, 1);
- else
- mpz_set_si (result->value.integer, 0);
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_this_image (gfc_expr *coarray, gfc_expr *dim)
-{
- if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
- return NULL;
-
- if (coarray == NULL)
- {
- gfc_expr *result;
- /* FIXME: gfc_current_locus is wrong. */
- result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
- &gfc_current_locus);
- mpz_set_si (result->value.integer, 1);
- return result;
- }
-
- /* For -fcoarray=single, this_image(A) is the same as lcobound(A). */
- return simplify_cobound (coarray, dim, NULL, 0);
-}
-
-
-gfc_expr *
-gfc_simplify_ubound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
-{
- return simplify_bound (array, dim, kind, 1);
-}
-
-gfc_expr *
-gfc_simplify_ucobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
-{
- return simplify_cobound (array, dim, kind, 1);
-}
-
-
-gfc_expr *
-gfc_simplify_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field)
-{
- gfc_expr *result, *e;
- gfc_constructor *vector_ctor, *mask_ctor, *field_ctor;
-
- if (!is_constant_array_expr (vector)
- || !is_constant_array_expr (mask)
- || (!gfc_is_constant_expr (field)
- && !is_constant_array_expr(field)))
- return NULL;
-
- result = gfc_get_array_expr (vector->ts.type, vector->ts.kind,
- &vector->where);
- if (vector->ts.type == BT_DERIVED)
- result->ts.u.derived = vector->ts.u.derived;
- result->rank = mask->rank;
- result->shape = gfc_copy_shape (mask->shape, mask->rank);
-
- if (vector->ts.type == BT_CHARACTER)
- result->ts.u.cl = vector->ts.u.cl;
-
- vector_ctor = gfc_constructor_first (vector->value.constructor);
- mask_ctor = gfc_constructor_first (mask->value.constructor);
- field_ctor
- = field->expr_type == EXPR_ARRAY
- ? gfc_constructor_first (field->value.constructor)
- : NULL;
-
- while (mask_ctor)
- {
- if (mask_ctor->expr->value.logical)
- {
- gcc_assert (vector_ctor);
- e = gfc_copy_expr (vector_ctor->expr);
- vector_ctor = gfc_constructor_next (vector_ctor);
- }
- else if (field->expr_type == EXPR_ARRAY)
- e = gfc_copy_expr (field_ctor->expr);
- else
- e = gfc_copy_expr (field);
-
- gfc_constructor_append_expr (&result->value.constructor, e, NULL);
-
- mask_ctor = gfc_constructor_next (mask_ctor);
- field_ctor = gfc_constructor_next (field_ctor);
- }
-
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_verify (gfc_expr *s, gfc_expr *set, gfc_expr *b, gfc_expr *kind)
-{
- gfc_expr *result;
- int back;
- size_t index, len, lenset;
- size_t i;
- int k = get_kind (BT_INTEGER, kind, "VERIFY", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
-
- if (s->expr_type != EXPR_CONSTANT || set->expr_type != EXPR_CONSTANT
- || ( b != NULL && b->expr_type != EXPR_CONSTANT))
- return NULL;
-
- if (b != NULL && b->value.logical != 0)
- back = 1;
- else
- back = 0;
-
- result = gfc_get_constant_expr (BT_INTEGER, k, &s->where);
-
- len = s->value.character.length;
- lenset = set->value.character.length;
-
- if (len == 0)
- {
- mpz_set_ui (result->value.integer, 0);
- return result;
- }
-
- if (back == 0)
- {
- if (lenset == 0)
- {
- mpz_set_ui (result->value.integer, 1);
- return result;
- }
-
- index = wide_strspn (s->value.character.string,
- set->value.character.string) + 1;
- if (index > len)
- index = 0;
-
- }
- else
- {
- if (lenset == 0)
- {
- mpz_set_ui (result->value.integer, len);
- return result;
- }
- for (index = len; index > 0; index --)
- {
- for (i = 0; i < lenset; i++)
- {
- if (s->value.character.string[index - 1]
- == set->value.character.string[i])
- break;
- }
- if (i == lenset)
- break;
- }
- }
-
- mpz_set_ui (result->value.integer, index);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_xor (gfc_expr *x, gfc_expr *y)
-{
- gfc_expr *result;
- int kind;
-
- if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
- return NULL;
-
- kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind;
-
- switch (x->ts.type)
- {
- case BT_INTEGER:
- result = gfc_get_constant_expr (BT_INTEGER, kind, &x->where);
- mpz_xor (result->value.integer, x->value.integer, y->value.integer);
- return range_check (result, "XOR");
-
- case BT_LOGICAL:
- return gfc_get_logical_expr (kind, &x->where,
- (x->value.logical && !y->value.logical)
- || (!x->value.logical && y->value.logical));
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/****************** Constant simplification *****************/
-
-/* Master function to convert one constant to another. While this is
- used as a simplification function, it requires the destination type
- and kind information which is supplied by a special case in
- do_simplify(). */
-
-gfc_expr *
-gfc_convert_constant (gfc_expr *e, bt type, int kind)
-{
- gfc_expr *g, *result, *(*f) (gfc_expr *, int);
- gfc_constructor *c;
-
- switch (e->ts.type)
- {
- case BT_INTEGER:
- switch (type)
- {
- case BT_INTEGER:
- f = gfc_int2int;
- break;
- case BT_REAL:
- f = gfc_int2real;
- break;
- case BT_COMPLEX:
- f = gfc_int2complex;
- break;
- case BT_LOGICAL:
- f = gfc_int2log;
- break;
- default:
- goto oops;
- }
- break;
-
- case BT_REAL:
- switch (type)
- {
- case BT_INTEGER:
- f = gfc_real2int;
- break;
- case BT_REAL:
- f = gfc_real2real;
- break;
- case BT_COMPLEX:
- f = gfc_real2complex;
- break;
- default:
- goto oops;
- }
- break;
-
- case BT_COMPLEX:
- switch (type)
- {
- case BT_INTEGER:
- f = gfc_complex2int;
- break;
- case BT_REAL:
- f = gfc_complex2real;
- break;
- case BT_COMPLEX:
- f = gfc_complex2complex;
- break;
-
- default:
- goto oops;
- }
- break;
-
- case BT_LOGICAL:
- switch (type)
- {
- case BT_INTEGER:
- f = gfc_log2int;
- break;
- case BT_LOGICAL:
- f = gfc_log2log;
- break;
- default:
- goto oops;
- }
- break;
-
- case BT_HOLLERITH:
- switch (type)
- {
- case BT_INTEGER:
- f = gfc_hollerith2int;
- break;
-
- case BT_REAL:
- f = gfc_hollerith2real;
- break;
-
- case BT_COMPLEX:
- f = gfc_hollerith2complex;
- break;
-
- case BT_CHARACTER:
- f = gfc_hollerith2character;
- break;
-
- case BT_LOGICAL:
- f = gfc_hollerith2logical;
- break;
-
- default:
- goto oops;
- }
- break;
-
- default:
- oops:
- gfc_internal_error ("gfc_convert_constant(): Unexpected type");
- }
-
- result = NULL;
-
- switch (e->expr_type)
- {
- case EXPR_CONSTANT:
- result = f (e, kind);
- if (result == NULL)
- return &gfc_bad_expr;
- break;
-
- case EXPR_ARRAY:
- if (!gfc_is_constant_expr (e))
- break;
-
- result = gfc_get_array_expr (type, kind, &e->where);
- result->shape = gfc_copy_shape (e->shape, e->rank);
- result->rank = e->rank;
-
- for (c = gfc_constructor_first (e->value.constructor);
- c; c = gfc_constructor_next (c))
- {
- gfc_expr *tmp;
- if (c->iterator == NULL)
- tmp = f (c->expr, kind);
- else
- {
- g = gfc_convert_constant (c->expr, type, kind);
- if (g == &gfc_bad_expr)
- {
- gfc_free_expr (result);
- return g;
- }
- tmp = g;
- }
-
- if (tmp == NULL)
- {
- gfc_free_expr (result);
- return NULL;
- }
-
- gfc_constructor_append_expr (&result->value.constructor,
- tmp, &c->where);
- }
-
- break;
-
- default:
- break;
- }
-
- return result;
-}
-
-
-/* Function for converting character constants. */
-gfc_expr *
-gfc_convert_char_constant (gfc_expr *e, bt type ATTRIBUTE_UNUSED, int kind)
-{
- gfc_expr *result;
- int i;
-
- if (!gfc_is_constant_expr (e))
- return NULL;
-
- if (e->expr_type == EXPR_CONSTANT)
- {
- /* Simple case of a scalar. */
- result = gfc_get_constant_expr (BT_CHARACTER, kind, &e->where);
- if (result == NULL)
- return &gfc_bad_expr;
-
- result->value.character.length = e->value.character.length;
- result->value.character.string
- = gfc_get_wide_string (e->value.character.length + 1);
- memcpy (result->value.character.string, e->value.character.string,
- (e->value.character.length + 1) * sizeof (gfc_char_t));
-
- /* Check we only have values representable in the destination kind. */
- for (i = 0; i < result->value.character.length; i++)
- if (!gfc_check_character_range (result->value.character.string[i],
- kind))
- {
- gfc_error ("Character '%s' in string at %L cannot be converted "
- "into character kind %d",
- gfc_print_wide_char (result->value.character.string[i]),
- &e->where, kind);
- return &gfc_bad_expr;
- }
-
- return result;
- }
- else if (e->expr_type == EXPR_ARRAY)
- {
- /* For an array constructor, we convert each constructor element. */
- gfc_constructor *c;
-
- result = gfc_get_array_expr (type, kind, &e->where);
- result->shape = gfc_copy_shape (e->shape, e->rank);
- result->rank = e->rank;
- result->ts.u.cl = e->ts.u.cl;
-
- for (c = gfc_constructor_first (e->value.constructor);
- c; c = gfc_constructor_next (c))
- {
- gfc_expr *tmp = gfc_convert_char_constant (c->expr, type, kind);
- if (tmp == &gfc_bad_expr)
- {
- gfc_free_expr (result);
- return &gfc_bad_expr;
- }
-
- if (tmp == NULL)
- {
- gfc_free_expr (result);
- return NULL;
- }
-
- gfc_constructor_append_expr (&result->value.constructor,
- tmp, &c->where);
- }
-
- return result;
- }
- else
- return NULL;
-}
-
-
-gfc_expr *
-gfc_simplify_compiler_options (void)
-{
- char *str;
- gfc_expr *result;
-
- str = gfc_get_option_string ();
- result = gfc_get_character_expr (gfc_default_character_kind,
- &gfc_current_locus, str, strlen (str));
- free (str);
- return result;
-}
-
-
-gfc_expr *
-gfc_simplify_compiler_version (void)
-{
- char *buffer;
- size_t len;
-
- len = strlen ("GCC version ") + strlen (version_string);
- buffer = XALLOCAVEC (char, len + 1);
- snprintf (buffer, len + 1, "GCC version %s", version_string);
- return gfc_get_character_expr (gfc_default_character_kind,
- &gfc_current_locus, buffer, len);
-}