Home | History | Annotate | Line # | Download | only in fortran
trans-intrinsic.cc revision 1.1
      1  1.1  mrg /* Intrinsic translation
      2  1.1  mrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Paul Brook <paul (at) nowt.org>
      4  1.1  mrg    and Steven Bosscher <s.bosscher (at) student.tudelft.nl>
      5  1.1  mrg 
      6  1.1  mrg This file is part of GCC.
      7  1.1  mrg 
      8  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      9  1.1  mrg the terms of the GNU General Public License as published by the Free
     10  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     11  1.1  mrg version.
     12  1.1  mrg 
     13  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16  1.1  mrg for more details.
     17  1.1  mrg 
     18  1.1  mrg You should have received a copy of the GNU General Public License
     19  1.1  mrg along with GCC; see the file COPYING3.  If not see
     20  1.1  mrg <http://www.gnu.org/licenses/>.  */
     21  1.1  mrg 
     22  1.1  mrg /* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics.  */
     23  1.1  mrg 
     24  1.1  mrg #include "config.h"
     25  1.1  mrg #include "system.h"
     26  1.1  mrg #include "coretypes.h"
     27  1.1  mrg #include "memmodel.h"
     28  1.1  mrg #include "tm.h"		/* For UNITS_PER_WORD.  */
     29  1.1  mrg #include "tree.h"
     30  1.1  mrg #include "gfortran.h"
     31  1.1  mrg #include "trans.h"
     32  1.1  mrg #include "stringpool.h"
     33  1.1  mrg #include "fold-const.h"
     34  1.1  mrg #include "internal-fn.h"
     35  1.1  mrg #include "tree-nested.h"
     36  1.1  mrg #include "stor-layout.h"
     37  1.1  mrg #include "toplev.h"	/* For rest_of_decl_compilation.  */
     38  1.1  mrg #include "arith.h"
     39  1.1  mrg #include "trans-const.h"
     40  1.1  mrg #include "trans-types.h"
     41  1.1  mrg #include "trans-array.h"
     42  1.1  mrg #include "dependency.h"	/* For CAF array alias analysis.  */
     43  1.1  mrg #include "attribs.h"
     44  1.1  mrg #include "realmpfr.h"
     45  1.1  mrg 
     46  1.1  mrg /* Only for gfc_trans_assign and gfc_trans_pointer_assign.  */
     47  1.1  mrg 
     48  1.1  mrg /* This maps Fortran intrinsic math functions to external library or GCC
     49  1.1  mrg    builtin functions.  */
     50  1.1  mrg typedef struct GTY(()) gfc_intrinsic_map_t {
     51  1.1  mrg   /* The explicit enum is required to work around inadequacies in the
     52  1.1  mrg      garbage collection/gengtype parsing mechanism.  */
     53  1.1  mrg   enum gfc_isym_id id;
     54  1.1  mrg 
     55  1.1  mrg   /* Enum value from the "language-independent", aka C-centric, part
     56  1.1  mrg      of gcc, or END_BUILTINS of no such value set.  */
     57  1.1  mrg   enum built_in_function float_built_in;
     58  1.1  mrg   enum built_in_function double_built_in;
     59  1.1  mrg   enum built_in_function long_double_built_in;
     60  1.1  mrg   enum built_in_function complex_float_built_in;
     61  1.1  mrg   enum built_in_function complex_double_built_in;
     62  1.1  mrg   enum built_in_function complex_long_double_built_in;
     63  1.1  mrg 
     64  1.1  mrg   /* True if the naming pattern is to prepend "c" for complex and
     65  1.1  mrg      append "f" for kind=4.  False if the naming pattern is to
     66  1.1  mrg      prepend "_gfortran_" and append "[rc](4|8|10|16)".  */
     67  1.1  mrg   bool libm_name;
     68  1.1  mrg 
     69  1.1  mrg   /* True if a complex version of the function exists.  */
     70  1.1  mrg   bool complex_available;
     71  1.1  mrg 
     72  1.1  mrg   /* True if the function should be marked const.  */
     73  1.1  mrg   bool is_constant;
     74  1.1  mrg 
     75  1.1  mrg   /* The base library name of this function.  */
     76  1.1  mrg   const char *name;
     77  1.1  mrg 
     78  1.1  mrg   /* Cache decls created for the various operand types.  */
     79  1.1  mrg   tree real4_decl;
     80  1.1  mrg   tree real8_decl;
     81  1.1  mrg   tree real10_decl;
     82  1.1  mrg   tree real16_decl;
     83  1.1  mrg   tree complex4_decl;
     84  1.1  mrg   tree complex8_decl;
     85  1.1  mrg   tree complex10_decl;
     86  1.1  mrg   tree complex16_decl;
     87  1.1  mrg }
     88  1.1  mrg gfc_intrinsic_map_t;
     89  1.1  mrg 
     90  1.1  mrg /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
     91  1.1  mrg    defines complex variants of all of the entries in mathbuiltins.def
     92  1.1  mrg    except for atan2.  */
     93  1.1  mrg #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
     94  1.1  mrg   { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
     95  1.1  mrg     BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
     96  1.1  mrg     true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
     97  1.1  mrg     NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
     98  1.1  mrg 
     99  1.1  mrg #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
    100  1.1  mrg   { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
    101  1.1  mrg     BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
    102  1.1  mrg     BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
    103  1.1  mrg     NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
    104  1.1  mrg 
    105  1.1  mrg #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
    106  1.1  mrg   { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
    107  1.1  mrg     END_BUILTINS, END_BUILTINS, END_BUILTINS, \
    108  1.1  mrg     false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
    109  1.1  mrg     NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
    110  1.1  mrg 
    111  1.1  mrg #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
    112  1.1  mrg   { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
    113  1.1  mrg     BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
    114  1.1  mrg     true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
    115  1.1  mrg     NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
    116  1.1  mrg 
    117  1.1  mrg static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
    118  1.1  mrg {
    119  1.1  mrg   /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
    120  1.1  mrg      DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
    121  1.1  mrg      to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro.  */
    122  1.1  mrg #include "mathbuiltins.def"
    123  1.1  mrg 
    124  1.1  mrg   /* Functions in libgfortran.  */
    125  1.1  mrg   LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
    126  1.1  mrg   LIB_FUNCTION (SIND, "sind", false),
    127  1.1  mrg   LIB_FUNCTION (COSD, "cosd", false),
    128  1.1  mrg   LIB_FUNCTION (TAND, "tand", false),
    129  1.1  mrg 
    130  1.1  mrg   /* End the list.  */
    131  1.1  mrg   LIB_FUNCTION (NONE, NULL, false)
    132  1.1  mrg 
    133  1.1  mrg };
    134  1.1  mrg #undef OTHER_BUILTIN
    135  1.1  mrg #undef LIB_FUNCTION
    136  1.1  mrg #undef DEFINE_MATH_BUILTIN
    137  1.1  mrg #undef DEFINE_MATH_BUILTIN_C
    138  1.1  mrg 
    139  1.1  mrg 
    140  1.1  mrg enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
    141  1.1  mrg 
    142  1.1  mrg 
    143  1.1  mrg /* Find the correct variant of a given builtin from its argument.  */
    144  1.1  mrg static tree
    145  1.1  mrg builtin_decl_for_precision (enum built_in_function base_built_in,
    146  1.1  mrg 			    int precision)
    147  1.1  mrg {
    148  1.1  mrg   enum built_in_function i = END_BUILTINS;
    149  1.1  mrg 
    150  1.1  mrg   gfc_intrinsic_map_t *m;
    151  1.1  mrg   for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
    152  1.1  mrg     ;
    153  1.1  mrg 
    154  1.1  mrg   if (precision == TYPE_PRECISION (float_type_node))
    155  1.1  mrg     i = m->float_built_in;
    156  1.1  mrg   else if (precision == TYPE_PRECISION (double_type_node))
    157  1.1  mrg     i = m->double_built_in;
    158  1.1  mrg   else if (precision == TYPE_PRECISION (long_double_type_node)
    159  1.1  mrg 	   && (!gfc_real16_is_float128
    160  1.1  mrg 	       || long_double_type_node != gfc_float128_type_node))
    161  1.1  mrg     i = m->long_double_built_in;
    162  1.1  mrg   else if (precision == TYPE_PRECISION (gfc_float128_type_node))
    163  1.1  mrg     {
    164  1.1  mrg       /* Special treatment, because it is not exactly a built-in, but
    165  1.1  mrg 	 a library function.  */
    166  1.1  mrg       return m->real16_decl;
    167  1.1  mrg     }
    168  1.1  mrg 
    169  1.1  mrg   return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
    170  1.1  mrg }
    171  1.1  mrg 
    172  1.1  mrg 
    173  1.1  mrg tree
    174  1.1  mrg gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
    175  1.1  mrg 				 int kind)
    176  1.1  mrg {
    177  1.1  mrg   int i = gfc_validate_kind (BT_REAL, kind, false);
    178  1.1  mrg 
    179  1.1  mrg   if (gfc_real_kinds[i].c_float128)
    180  1.1  mrg     {
    181  1.1  mrg       /* For _Float128, the story is a bit different, because we return
    182  1.1  mrg 	 a decl to a library function rather than a built-in.  */
    183  1.1  mrg       gfc_intrinsic_map_t *m;
    184  1.1  mrg       for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
    185  1.1  mrg 	;
    186  1.1  mrg 
    187  1.1  mrg       return m->real16_decl;
    188  1.1  mrg     }
    189  1.1  mrg 
    190  1.1  mrg   return builtin_decl_for_precision (double_built_in,
    191  1.1  mrg 				     gfc_real_kinds[i].mode_precision);
    192  1.1  mrg }
    193  1.1  mrg 
    194  1.1  mrg 
    195  1.1  mrg /* Evaluate the arguments to an intrinsic function.  The value
    196  1.1  mrg    of NARGS may be less than the actual number of arguments in EXPR
    197  1.1  mrg    to allow optional "KIND" arguments that are not included in the
    198  1.1  mrg    generated code to be ignored.  */
    199  1.1  mrg 
    200  1.1  mrg static void
    201  1.1  mrg gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
    202  1.1  mrg 				  tree *argarray, int nargs)
    203  1.1  mrg {
    204  1.1  mrg   gfc_actual_arglist *actual;
    205  1.1  mrg   gfc_expr *e;
    206  1.1  mrg   gfc_intrinsic_arg  *formal;
    207  1.1  mrg   gfc_se argse;
    208  1.1  mrg   int curr_arg;
    209  1.1  mrg 
    210  1.1  mrg   formal = expr->value.function.isym->formal;
    211  1.1  mrg   actual = expr->value.function.actual;
    212  1.1  mrg 
    213  1.1  mrg    for (curr_arg = 0; curr_arg < nargs; curr_arg++,
    214  1.1  mrg 	actual = actual->next,
    215  1.1  mrg 	formal = formal ? formal->next : NULL)
    216  1.1  mrg     {
    217  1.1  mrg       gcc_assert (actual);
    218  1.1  mrg       e = actual->expr;
    219  1.1  mrg       /* Skip omitted optional arguments.  */
    220  1.1  mrg       if (!e)
    221  1.1  mrg 	{
    222  1.1  mrg 	  --curr_arg;
    223  1.1  mrg 	  continue;
    224  1.1  mrg 	}
    225  1.1  mrg 
    226  1.1  mrg       /* Evaluate the parameter.  This will substitute scalarized
    227  1.1  mrg          references automatically.  */
    228  1.1  mrg       gfc_init_se (&argse, se);
    229  1.1  mrg 
    230  1.1  mrg       if (e->ts.type == BT_CHARACTER)
    231  1.1  mrg 	{
    232  1.1  mrg 	  gfc_conv_expr (&argse, e);
    233  1.1  mrg 	  gfc_conv_string_parameter (&argse);
    234  1.1  mrg           argarray[curr_arg++] = argse.string_length;
    235  1.1  mrg 	  gcc_assert (curr_arg < nargs);
    236  1.1  mrg 	}
    237  1.1  mrg       else
    238  1.1  mrg         gfc_conv_expr_val (&argse, e);
    239  1.1  mrg 
    240  1.1  mrg       /* If an optional argument is itself an optional dummy argument,
    241  1.1  mrg 	 check its presence and substitute a null if absent.  */
    242  1.1  mrg       if (e->expr_type == EXPR_VARIABLE
    243  1.1  mrg 	    && e->symtree->n.sym->attr.optional
    244  1.1  mrg 	    && formal
    245  1.1  mrg 	    && formal->optional)
    246  1.1  mrg 	gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
    247  1.1  mrg 
    248  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
    249  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
    250  1.1  mrg       argarray[curr_arg] = argse.expr;
    251  1.1  mrg     }
    252  1.1  mrg }
    253  1.1  mrg 
    254  1.1  mrg /* Count the number of actual arguments to the intrinsic function EXPR
    255  1.1  mrg    including any "hidden" string length arguments.  */
    256  1.1  mrg 
    257  1.1  mrg static unsigned int
    258  1.1  mrg gfc_intrinsic_argument_list_length (gfc_expr *expr)
    259  1.1  mrg {
    260  1.1  mrg   int n = 0;
    261  1.1  mrg   gfc_actual_arglist *actual;
    262  1.1  mrg 
    263  1.1  mrg   for (actual = expr->value.function.actual; actual; actual = actual->next)
    264  1.1  mrg     {
    265  1.1  mrg       if (!actual->expr)
    266  1.1  mrg 	continue;
    267  1.1  mrg 
    268  1.1  mrg       if (actual->expr->ts.type == BT_CHARACTER)
    269  1.1  mrg 	n += 2;
    270  1.1  mrg       else
    271  1.1  mrg 	n++;
    272  1.1  mrg     }
    273  1.1  mrg 
    274  1.1  mrg   return n;
    275  1.1  mrg }
    276  1.1  mrg 
    277  1.1  mrg 
    278  1.1  mrg /* Conversions between different types are output by the frontend as
    279  1.1  mrg    intrinsic functions.  We implement these directly with inline code.  */
    280  1.1  mrg 
    281  1.1  mrg static void
    282  1.1  mrg gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
    283  1.1  mrg {
    284  1.1  mrg   tree type;
    285  1.1  mrg   tree *args;
    286  1.1  mrg   int nargs;
    287  1.1  mrg 
    288  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
    289  1.1  mrg   args = XALLOCAVEC (tree, nargs);
    290  1.1  mrg 
    291  1.1  mrg   /* Evaluate all the arguments passed. Whilst we're only interested in the
    292  1.1  mrg      first one here, there are other parts of the front-end that assume this
    293  1.1  mrg      and will trigger an ICE if it's not the case.  */
    294  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
    295  1.1  mrg   gcc_assert (expr->value.function.actual->expr);
    296  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, nargs);
    297  1.1  mrg 
    298  1.1  mrg   /* Conversion between character kinds involves a call to a library
    299  1.1  mrg      function.  */
    300  1.1  mrg   if (expr->ts.type == BT_CHARACTER)
    301  1.1  mrg     {
    302  1.1  mrg       tree fndecl, var, addr, tmp;
    303  1.1  mrg 
    304  1.1  mrg       if (expr->ts.kind == 1
    305  1.1  mrg 	  && expr->value.function.actual->expr->ts.kind == 4)
    306  1.1  mrg 	fndecl = gfor_fndecl_convert_char4_to_char1;
    307  1.1  mrg       else if (expr->ts.kind == 4
    308  1.1  mrg 	       && expr->value.function.actual->expr->ts.kind == 1)
    309  1.1  mrg 	fndecl = gfor_fndecl_convert_char1_to_char4;
    310  1.1  mrg       else
    311  1.1  mrg 	gcc_unreachable ();
    312  1.1  mrg 
    313  1.1  mrg       /* Create the variable storing the converted value.  */
    314  1.1  mrg       type = gfc_get_pchar_type (expr->ts.kind);
    315  1.1  mrg       var = gfc_create_var (type, "str");
    316  1.1  mrg       addr = gfc_build_addr_expr (build_pointer_type (type), var);
    317  1.1  mrg 
    318  1.1  mrg       /* Call the library function that will perform the conversion.  */
    319  1.1  mrg       gcc_assert (nargs >= 2);
    320  1.1  mrg       tmp = build_call_expr_loc (input_location,
    321  1.1  mrg 			     fndecl, 3, addr, args[0], args[1]);
    322  1.1  mrg       gfc_add_expr_to_block (&se->pre, tmp);
    323  1.1  mrg 
    324  1.1  mrg       /* Free the temporary afterwards.  */
    325  1.1  mrg       tmp = gfc_call_free (var);
    326  1.1  mrg       gfc_add_expr_to_block (&se->post, tmp);
    327  1.1  mrg 
    328  1.1  mrg       se->expr = var;
    329  1.1  mrg       se->string_length = args[0];
    330  1.1  mrg 
    331  1.1  mrg       return;
    332  1.1  mrg     }
    333  1.1  mrg 
    334  1.1  mrg   /* Conversion from complex to non-complex involves taking the real
    335  1.1  mrg      component of the value.  */
    336  1.1  mrg   if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
    337  1.1  mrg       && expr->ts.type != BT_COMPLEX)
    338  1.1  mrg     {
    339  1.1  mrg       tree artype;
    340  1.1  mrg 
    341  1.1  mrg       artype = TREE_TYPE (TREE_TYPE (args[0]));
    342  1.1  mrg       args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
    343  1.1  mrg 				 args[0]);
    344  1.1  mrg     }
    345  1.1  mrg 
    346  1.1  mrg   se->expr = convert (type, args[0]);
    347  1.1  mrg }
    348  1.1  mrg 
    349  1.1  mrg /* This is needed because the gcc backend only implements
    350  1.1  mrg    FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
    351  1.1  mrg    FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
    352  1.1  mrg    Similarly for CEILING.  */
    353  1.1  mrg 
    354  1.1  mrg static tree
    355  1.1  mrg build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
    356  1.1  mrg {
    357  1.1  mrg   tree tmp;
    358  1.1  mrg   tree cond;
    359  1.1  mrg   tree argtype;
    360  1.1  mrg   tree intval;
    361  1.1  mrg 
    362  1.1  mrg   argtype = TREE_TYPE (arg);
    363  1.1  mrg   arg = gfc_evaluate_now (arg, pblock);
    364  1.1  mrg 
    365  1.1  mrg   intval = convert (type, arg);
    366  1.1  mrg   intval = gfc_evaluate_now (intval, pblock);
    367  1.1  mrg 
    368  1.1  mrg   tmp = convert (argtype, intval);
    369  1.1  mrg   cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
    370  1.1  mrg 			  logical_type_node, tmp, arg);
    371  1.1  mrg 
    372  1.1  mrg   tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
    373  1.1  mrg 			 intval, build_int_cst (type, 1));
    374  1.1  mrg   tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
    375  1.1  mrg   return tmp;
    376  1.1  mrg }
    377  1.1  mrg 
    378  1.1  mrg 
    379  1.1  mrg /* Round to nearest integer, away from zero.  */
    380  1.1  mrg 
    381  1.1  mrg static tree
    382  1.1  mrg build_round_expr (tree arg, tree restype)
    383  1.1  mrg {
    384  1.1  mrg   tree argtype;
    385  1.1  mrg   tree fn;
    386  1.1  mrg   int argprec, resprec;
    387  1.1  mrg 
    388  1.1  mrg   argtype = TREE_TYPE (arg);
    389  1.1  mrg   argprec = TYPE_PRECISION (argtype);
    390  1.1  mrg   resprec = TYPE_PRECISION (restype);
    391  1.1  mrg 
    392  1.1  mrg   /* Depending on the type of the result, choose the int intrinsic (iround,
    393  1.1  mrg      available only as a builtin, therefore cannot use it for _Float128), long
    394  1.1  mrg      int intrinsic (lround family) or long long intrinsic (llround).  If we
    395  1.1  mrg      don't have an appropriate function that converts directly to the integer
    396  1.1  mrg      type (such as kind == 16), just use ROUND, and then convert the result to
    397  1.1  mrg      an integer.  We might also need to convert the result afterwards.  */
    398  1.1  mrg   if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
    399  1.1  mrg     fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
    400  1.1  mrg   else if (resprec <= LONG_TYPE_SIZE)
    401  1.1  mrg     fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
    402  1.1  mrg   else if (resprec <= LONG_LONG_TYPE_SIZE)
    403  1.1  mrg     fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
    404  1.1  mrg   else if (resprec >= argprec)
    405  1.1  mrg     fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
    406  1.1  mrg   else
    407  1.1  mrg     gcc_unreachable ();
    408  1.1  mrg 
    409  1.1  mrg   return convert (restype, build_call_expr_loc (input_location,
    410  1.1  mrg 						fn, 1, arg));
    411  1.1  mrg }
    412  1.1  mrg 
    413  1.1  mrg 
    414  1.1  mrg /* Convert a real to an integer using a specific rounding mode.
    415  1.1  mrg    Ideally we would just build the corresponding GENERIC node,
    416  1.1  mrg    however the RTL expander only actually supports FIX_TRUNC_EXPR.  */
    417  1.1  mrg 
    418  1.1  mrg static tree
    419  1.1  mrg build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
    420  1.1  mrg                enum rounding_mode op)
    421  1.1  mrg {
    422  1.1  mrg   switch (op)
    423  1.1  mrg     {
    424  1.1  mrg     case RND_FLOOR:
    425  1.1  mrg       return build_fixbound_expr (pblock, arg, type, 0);
    426  1.1  mrg 
    427  1.1  mrg     case RND_CEIL:
    428  1.1  mrg       return build_fixbound_expr (pblock, arg, type, 1);
    429  1.1  mrg 
    430  1.1  mrg     case RND_ROUND:
    431  1.1  mrg       return build_round_expr (arg, type);
    432  1.1  mrg 
    433  1.1  mrg     case RND_TRUNC:
    434  1.1  mrg       return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
    435  1.1  mrg 
    436  1.1  mrg     default:
    437  1.1  mrg       gcc_unreachable ();
    438  1.1  mrg     }
    439  1.1  mrg }
    440  1.1  mrg 
    441  1.1  mrg 
    442  1.1  mrg /* Round a real value using the specified rounding mode.
    443  1.1  mrg    We use a temporary integer of that same kind size as the result.
    444  1.1  mrg    Values larger than those that can be represented by this kind are
    445  1.1  mrg    unchanged, as they will not be accurate enough to represent the
    446  1.1  mrg    rounding.
    447  1.1  mrg     huge = HUGE (KIND (a))
    448  1.1  mrg     aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
    449  1.1  mrg    */
    450  1.1  mrg 
    451  1.1  mrg static void
    452  1.1  mrg gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
    453  1.1  mrg {
    454  1.1  mrg   tree type;
    455  1.1  mrg   tree itype;
    456  1.1  mrg   tree arg[2];
    457  1.1  mrg   tree tmp;
    458  1.1  mrg   tree cond;
    459  1.1  mrg   tree decl;
    460  1.1  mrg   mpfr_t huge;
    461  1.1  mrg   int n, nargs;
    462  1.1  mrg   int kind;
    463  1.1  mrg 
    464  1.1  mrg   kind = expr->ts.kind;
    465  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
    466  1.1  mrg 
    467  1.1  mrg   decl = NULL_TREE;
    468  1.1  mrg   /* We have builtin functions for some cases.  */
    469  1.1  mrg   switch (op)
    470  1.1  mrg     {
    471  1.1  mrg     case RND_ROUND:
    472  1.1  mrg       decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
    473  1.1  mrg       break;
    474  1.1  mrg 
    475  1.1  mrg     case RND_TRUNC:
    476  1.1  mrg       decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
    477  1.1  mrg       break;
    478  1.1  mrg 
    479  1.1  mrg     default:
    480  1.1  mrg       gcc_unreachable ();
    481  1.1  mrg     }
    482  1.1  mrg 
    483  1.1  mrg   /* Evaluate the argument.  */
    484  1.1  mrg   gcc_assert (expr->value.function.actual->expr);
    485  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
    486  1.1  mrg 
    487  1.1  mrg   /* Use a builtin function if one exists.  */
    488  1.1  mrg   if (decl != NULL_TREE)
    489  1.1  mrg     {
    490  1.1  mrg       se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
    491  1.1  mrg       return;
    492  1.1  mrg     }
    493  1.1  mrg 
    494  1.1  mrg   /* This code is probably redundant, but we'll keep it lying around just
    495  1.1  mrg      in case.  */
    496  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
    497  1.1  mrg   arg[0] = gfc_evaluate_now (arg[0], &se->pre);
    498  1.1  mrg 
    499  1.1  mrg   /* Test if the value is too large to handle sensibly.  */
    500  1.1  mrg   gfc_set_model_kind (kind);
    501  1.1  mrg   mpfr_init (huge);
    502  1.1  mrg   n = gfc_validate_kind (BT_INTEGER, kind, false);
    503  1.1  mrg   mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
    504  1.1  mrg   tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
    505  1.1  mrg   cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
    506  1.1  mrg 			  tmp);
    507  1.1  mrg 
    508  1.1  mrg   mpfr_neg (huge, huge, GFC_RND_MODE);
    509  1.1  mrg   tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
    510  1.1  mrg   tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
    511  1.1  mrg 			 tmp);
    512  1.1  mrg   cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
    513  1.1  mrg 			  cond, tmp);
    514  1.1  mrg   itype = gfc_get_int_type (kind);
    515  1.1  mrg 
    516  1.1  mrg   tmp = build_fix_expr (&se->pre, arg[0], itype, op);
    517  1.1  mrg   tmp = convert (type, tmp);
    518  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
    519  1.1  mrg 			      arg[0]);
    520  1.1  mrg   mpfr_clear (huge);
    521  1.1  mrg }
    522  1.1  mrg 
    523  1.1  mrg 
    524  1.1  mrg /* Convert to an integer using the specified rounding mode.  */
    525  1.1  mrg 
    526  1.1  mrg static void
    527  1.1  mrg gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
    528  1.1  mrg {
    529  1.1  mrg   tree type;
    530  1.1  mrg   tree *args;
    531  1.1  mrg   int nargs;
    532  1.1  mrg 
    533  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
    534  1.1  mrg   args = XALLOCAVEC (tree, nargs);
    535  1.1  mrg 
    536  1.1  mrg   /* Evaluate the argument, we process all arguments even though we only
    537  1.1  mrg      use the first one for code generation purposes.  */
    538  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
    539  1.1  mrg   gcc_assert (expr->value.function.actual->expr);
    540  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, nargs);
    541  1.1  mrg 
    542  1.1  mrg   if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
    543  1.1  mrg     {
    544  1.1  mrg       /* Conversion to a different integer kind.  */
    545  1.1  mrg       se->expr = convert (type, args[0]);
    546  1.1  mrg     }
    547  1.1  mrg   else
    548  1.1  mrg     {
    549  1.1  mrg       /* Conversion from complex to non-complex involves taking the real
    550  1.1  mrg          component of the value.  */
    551  1.1  mrg       if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
    552  1.1  mrg 	  && expr->ts.type != BT_COMPLEX)
    553  1.1  mrg 	{
    554  1.1  mrg 	  tree artype;
    555  1.1  mrg 
    556  1.1  mrg 	  artype = TREE_TYPE (TREE_TYPE (args[0]));
    557  1.1  mrg 	  args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
    558  1.1  mrg 				     args[0]);
    559  1.1  mrg 	}
    560  1.1  mrg 
    561  1.1  mrg       se->expr = build_fix_expr (&se->pre, args[0], type, op);
    562  1.1  mrg     }
    563  1.1  mrg }
    564  1.1  mrg 
    565  1.1  mrg 
    566  1.1  mrg /* Get the imaginary component of a value.  */
    567  1.1  mrg 
    568  1.1  mrg static void
    569  1.1  mrg gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
    570  1.1  mrg {
    571  1.1  mrg   tree arg;
    572  1.1  mrg 
    573  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
    574  1.1  mrg   se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
    575  1.1  mrg 			      TREE_TYPE (TREE_TYPE (arg)), arg);
    576  1.1  mrg }
    577  1.1  mrg 
    578  1.1  mrg 
    579  1.1  mrg /* Get the complex conjugate of a value.  */
    580  1.1  mrg 
    581  1.1  mrg static void
    582  1.1  mrg gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
    583  1.1  mrg {
    584  1.1  mrg   tree arg;
    585  1.1  mrg 
    586  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
    587  1.1  mrg   se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
    588  1.1  mrg }
    589  1.1  mrg 
    590  1.1  mrg 
    591  1.1  mrg 
    592  1.1  mrg static tree
    593  1.1  mrg define_quad_builtin (const char *name, tree type, bool is_const)
    594  1.1  mrg {
    595  1.1  mrg   tree fndecl;
    596  1.1  mrg   fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
    597  1.1  mrg 		       type);
    598  1.1  mrg 
    599  1.1  mrg   /* Mark the decl as external.  */
    600  1.1  mrg   DECL_EXTERNAL (fndecl) = 1;
    601  1.1  mrg   TREE_PUBLIC (fndecl) = 1;
    602  1.1  mrg 
    603  1.1  mrg   /* Mark it __attribute__((const)).  */
    604  1.1  mrg   TREE_READONLY (fndecl) = is_const;
    605  1.1  mrg 
    606  1.1  mrg   rest_of_decl_compilation (fndecl, 1, 0);
    607  1.1  mrg 
    608  1.1  mrg   return fndecl;
    609  1.1  mrg }
    610  1.1  mrg 
    611  1.1  mrg /* Add SIMD attribute for FNDECL built-in if the built-in
    612  1.1  mrg    name is in VECTORIZED_BUILTINS.  */
    613  1.1  mrg 
    614  1.1  mrg static void
    615  1.1  mrg add_simd_flag_for_built_in (tree fndecl)
    616  1.1  mrg {
    617  1.1  mrg   if (gfc_vectorized_builtins == NULL
    618  1.1  mrg       || fndecl == NULL_TREE)
    619  1.1  mrg     return;
    620  1.1  mrg 
    621  1.1  mrg   const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
    622  1.1  mrg   int *clauses = gfc_vectorized_builtins->get (name);
    623  1.1  mrg   if (clauses)
    624  1.1  mrg     {
    625  1.1  mrg       for (unsigned i = 0; i < 3; i++)
    626  1.1  mrg 	if (*clauses & (1 << i))
    627  1.1  mrg 	  {
    628  1.1  mrg 	    gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
    629  1.1  mrg 	    tree omp_clause = NULL_TREE;
    630  1.1  mrg 	    if (simd_type == SIMD_NONE)
    631  1.1  mrg 	      ; /* No SIMD clause.  */
    632  1.1  mrg 	    else
    633  1.1  mrg 	      {
    634  1.1  mrg 		omp_clause_code code
    635  1.1  mrg 		  = (simd_type == SIMD_INBRANCH
    636  1.1  mrg 		     ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
    637  1.1  mrg 		omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
    638  1.1  mrg 		omp_clause = build_tree_list (NULL_TREE, omp_clause);
    639  1.1  mrg 	      }
    640  1.1  mrg 
    641  1.1  mrg 	    DECL_ATTRIBUTES (fndecl)
    642  1.1  mrg 	      = tree_cons (get_identifier ("omp declare simd"), omp_clause,
    643  1.1  mrg 			   DECL_ATTRIBUTES (fndecl));
    644  1.1  mrg 	  }
    645  1.1  mrg     }
    646  1.1  mrg }
    647  1.1  mrg 
    648  1.1  mrg   /* Set SIMD attribute to all built-in functions that are mentioned
    649  1.1  mrg      in gfc_vectorized_builtins vector.  */
    650  1.1  mrg 
    651  1.1  mrg void
    652  1.1  mrg gfc_adjust_builtins (void)
    653  1.1  mrg {
    654  1.1  mrg   gfc_intrinsic_map_t *m;
    655  1.1  mrg   for (m = gfc_intrinsic_map;
    656  1.1  mrg        m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
    657  1.1  mrg     {
    658  1.1  mrg       add_simd_flag_for_built_in (m->real4_decl);
    659  1.1  mrg       add_simd_flag_for_built_in (m->complex4_decl);
    660  1.1  mrg       add_simd_flag_for_built_in (m->real8_decl);
    661  1.1  mrg       add_simd_flag_for_built_in (m->complex8_decl);
    662  1.1  mrg       add_simd_flag_for_built_in (m->real10_decl);
    663  1.1  mrg       add_simd_flag_for_built_in (m->complex10_decl);
    664  1.1  mrg       add_simd_flag_for_built_in (m->real16_decl);
    665  1.1  mrg       add_simd_flag_for_built_in (m->complex16_decl);
    666  1.1  mrg       add_simd_flag_for_built_in (m->real16_decl);
    667  1.1  mrg       add_simd_flag_for_built_in (m->complex16_decl);
    668  1.1  mrg     }
    669  1.1  mrg 
    670  1.1  mrg   /* Release all strings.  */
    671  1.1  mrg   if (gfc_vectorized_builtins != NULL)
    672  1.1  mrg     {
    673  1.1  mrg       for (hash_map<nofree_string_hash, int>::iterator it
    674  1.1  mrg 	   = gfc_vectorized_builtins->begin ();
    675  1.1  mrg 	   it != gfc_vectorized_builtins->end (); ++it)
    676  1.1  mrg 	free (CONST_CAST (char *, (*it).first));
    677  1.1  mrg 
    678  1.1  mrg       delete gfc_vectorized_builtins;
    679  1.1  mrg       gfc_vectorized_builtins = NULL;
    680  1.1  mrg     }
    681  1.1  mrg }
    682  1.1  mrg 
    683  1.1  mrg /* Initialize function decls for library functions.  The external functions
    684  1.1  mrg    are created as required.  Builtin functions are added here.  */
    685  1.1  mrg 
    686  1.1  mrg void
    687  1.1  mrg gfc_build_intrinsic_lib_fndecls (void)
    688  1.1  mrg {
    689  1.1  mrg   gfc_intrinsic_map_t *m;
    690  1.1  mrg   tree quad_decls[END_BUILTINS + 1];
    691  1.1  mrg 
    692  1.1  mrg   if (gfc_real16_is_float128)
    693  1.1  mrg   {
    694  1.1  mrg     /* If we have soft-float types, we create the decls for their
    695  1.1  mrg        C99-like library functions.  For now, we only handle _Float128
    696  1.1  mrg        q-suffixed functions.  */
    697  1.1  mrg 
    698  1.1  mrg     tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
    699  1.1  mrg     tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
    700  1.1  mrg 
    701  1.1  mrg     memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
    702  1.1  mrg 
    703  1.1  mrg     type = gfc_float128_type_node;
    704  1.1  mrg     complex_type = gfc_complex_float128_type_node;
    705  1.1  mrg     /* type (*) (type) */
    706  1.1  mrg     func_1 = build_function_type_list (type, type, NULL_TREE);
    707  1.1  mrg     /* int (*) (type) */
    708  1.1  mrg     func_iround = build_function_type_list (integer_type_node,
    709  1.1  mrg 					    type, NULL_TREE);
    710  1.1  mrg     /* long (*) (type) */
    711  1.1  mrg     func_lround = build_function_type_list (long_integer_type_node,
    712  1.1  mrg 					    type, NULL_TREE);
    713  1.1  mrg     /* long long (*) (type) */
    714  1.1  mrg     func_llround = build_function_type_list (long_long_integer_type_node,
    715  1.1  mrg 					     type, NULL_TREE);
    716  1.1  mrg     /* type (*) (type, type) */
    717  1.1  mrg     func_2 = build_function_type_list (type, type, type, NULL_TREE);
    718  1.1  mrg     /* type (*) (type, &int) */
    719  1.1  mrg     func_frexp
    720  1.1  mrg       = build_function_type_list (type,
    721  1.1  mrg 				  type,
    722  1.1  mrg 				  build_pointer_type (integer_type_node),
    723  1.1  mrg 				  NULL_TREE);
    724  1.1  mrg     /* type (*) (type, int) */
    725  1.1  mrg     func_scalbn = build_function_type_list (type,
    726  1.1  mrg 					    type, integer_type_node, NULL_TREE);
    727  1.1  mrg     /* type (*) (complex type) */
    728  1.1  mrg     func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
    729  1.1  mrg     /* complex type (*) (complex type, complex type) */
    730  1.1  mrg     func_cpow
    731  1.1  mrg       = build_function_type_list (complex_type,
    732  1.1  mrg 				  complex_type, complex_type, NULL_TREE);
    733  1.1  mrg 
    734  1.1  mrg #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
    735  1.1  mrg #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
    736  1.1  mrg #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
    737  1.1  mrg 
    738  1.1  mrg     /* Only these built-ins are actually needed here. These are used directly
    739  1.1  mrg        from the code, when calling builtin_decl_for_precision() or
    740  1.1  mrg        builtin_decl_for_float_type(). The others are all constructed by
    741  1.1  mrg        gfc_get_intrinsic_lib_fndecl().  */
    742  1.1  mrg #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
    743  1.1  mrg   quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
    744  1.1  mrg 
    745  1.1  mrg #include "mathbuiltins.def"
    746  1.1  mrg 
    747  1.1  mrg #undef OTHER_BUILTIN
    748  1.1  mrg #undef LIB_FUNCTION
    749  1.1  mrg #undef DEFINE_MATH_BUILTIN
    750  1.1  mrg #undef DEFINE_MATH_BUILTIN_C
    751  1.1  mrg 
    752  1.1  mrg     /* There is one built-in we defined manually, because it gets called
    753  1.1  mrg        with builtin_decl_for_precision() or builtin_decl_for_float_type()
    754  1.1  mrg        even though it is not an OTHER_BUILTIN: it is SQRT.  */
    755  1.1  mrg     quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
    756  1.1  mrg 
    757  1.1  mrg   }
    758  1.1  mrg 
    759  1.1  mrg   /* Add GCC builtin functions.  */
    760  1.1  mrg   for (m = gfc_intrinsic_map;
    761  1.1  mrg        m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
    762  1.1  mrg     {
    763  1.1  mrg       if (m->float_built_in != END_BUILTINS)
    764  1.1  mrg 	m->real4_decl = builtin_decl_explicit (m->float_built_in);
    765  1.1  mrg       if (m->complex_float_built_in != END_BUILTINS)
    766  1.1  mrg 	m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
    767  1.1  mrg       if (m->double_built_in != END_BUILTINS)
    768  1.1  mrg 	m->real8_decl = builtin_decl_explicit (m->double_built_in);
    769  1.1  mrg       if (m->complex_double_built_in != END_BUILTINS)
    770  1.1  mrg 	m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
    771  1.1  mrg 
    772  1.1  mrg       /* If real(kind=10) exists, it is always long double.  */
    773  1.1  mrg       if (m->long_double_built_in != END_BUILTINS)
    774  1.1  mrg 	m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
    775  1.1  mrg       if (m->complex_long_double_built_in != END_BUILTINS)
    776  1.1  mrg 	m->complex10_decl
    777  1.1  mrg 	  = builtin_decl_explicit (m->complex_long_double_built_in);
    778  1.1  mrg 
    779  1.1  mrg       if (!gfc_real16_is_float128)
    780  1.1  mrg 	{
    781  1.1  mrg 	  if (m->long_double_built_in != END_BUILTINS)
    782  1.1  mrg 	    m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
    783  1.1  mrg 	  if (m->complex_long_double_built_in != END_BUILTINS)
    784  1.1  mrg 	    m->complex16_decl
    785  1.1  mrg 	      = builtin_decl_explicit (m->complex_long_double_built_in);
    786  1.1  mrg 	}
    787  1.1  mrg       else if (quad_decls[m->double_built_in] != NULL_TREE)
    788  1.1  mrg         {
    789  1.1  mrg 	  /* Quad-precision function calls are constructed when first
    790  1.1  mrg 	     needed by builtin_decl_for_precision(), except for those
    791  1.1  mrg 	     that will be used directly (define by OTHER_BUILTIN).  */
    792  1.1  mrg 	  m->real16_decl = quad_decls[m->double_built_in];
    793  1.1  mrg 	}
    794  1.1  mrg       else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
    795  1.1  mrg         {
    796  1.1  mrg 	  /* Same thing for the complex ones.  */
    797  1.1  mrg 	  m->complex16_decl = quad_decls[m->double_built_in];
    798  1.1  mrg 	}
    799  1.1  mrg     }
    800  1.1  mrg }
    801  1.1  mrg 
    802  1.1  mrg 
    803  1.1  mrg /* Create a fndecl for a simple intrinsic library function.  */
    804  1.1  mrg 
    805  1.1  mrg static tree
    806  1.1  mrg gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
    807  1.1  mrg {
    808  1.1  mrg   tree type;
    809  1.1  mrg   vec<tree, va_gc> *argtypes;
    810  1.1  mrg   tree fndecl;
    811  1.1  mrg   gfc_actual_arglist *actual;
    812  1.1  mrg   tree *pdecl;
    813  1.1  mrg   gfc_typespec *ts;
    814  1.1  mrg   char name[GFC_MAX_SYMBOL_LEN + 3];
    815  1.1  mrg 
    816  1.1  mrg   ts = &expr->ts;
    817  1.1  mrg   if (ts->type == BT_REAL)
    818  1.1  mrg     {
    819  1.1  mrg       switch (ts->kind)
    820  1.1  mrg 	{
    821  1.1  mrg 	case 4:
    822  1.1  mrg 	  pdecl = &m->real4_decl;
    823  1.1  mrg 	  break;
    824  1.1  mrg 	case 8:
    825  1.1  mrg 	  pdecl = &m->real8_decl;
    826  1.1  mrg 	  break;
    827  1.1  mrg 	case 10:
    828  1.1  mrg 	  pdecl = &m->real10_decl;
    829  1.1  mrg 	  break;
    830  1.1  mrg 	case 16:
    831  1.1  mrg 	  pdecl = &m->real16_decl;
    832  1.1  mrg 	  break;
    833  1.1  mrg 	default:
    834  1.1  mrg 	  gcc_unreachable ();
    835  1.1  mrg 	}
    836  1.1  mrg     }
    837  1.1  mrg   else if (ts->type == BT_COMPLEX)
    838  1.1  mrg     {
    839  1.1  mrg       gcc_assert (m->complex_available);
    840  1.1  mrg 
    841  1.1  mrg       switch (ts->kind)
    842  1.1  mrg 	{
    843  1.1  mrg 	case 4:
    844  1.1  mrg 	  pdecl = &m->complex4_decl;
    845  1.1  mrg 	  break;
    846  1.1  mrg 	case 8:
    847  1.1  mrg 	  pdecl = &m->complex8_decl;
    848  1.1  mrg 	  break;
    849  1.1  mrg 	case 10:
    850  1.1  mrg 	  pdecl = &m->complex10_decl;
    851  1.1  mrg 	  break;
    852  1.1  mrg 	case 16:
    853  1.1  mrg 	  pdecl = &m->complex16_decl;
    854  1.1  mrg 	  break;
    855  1.1  mrg 	default:
    856  1.1  mrg 	  gcc_unreachable ();
    857  1.1  mrg 	}
    858  1.1  mrg     }
    859  1.1  mrg   else
    860  1.1  mrg     gcc_unreachable ();
    861  1.1  mrg 
    862  1.1  mrg   if (*pdecl)
    863  1.1  mrg     return *pdecl;
    864  1.1  mrg 
    865  1.1  mrg   if (m->libm_name)
    866  1.1  mrg     {
    867  1.1  mrg       int n = gfc_validate_kind (BT_REAL, ts->kind, false);
    868  1.1  mrg       if (gfc_real_kinds[n].c_float)
    869  1.1  mrg 	snprintf (name, sizeof (name), "%s%s%s",
    870  1.1  mrg 		  ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
    871  1.1  mrg       else if (gfc_real_kinds[n].c_double)
    872  1.1  mrg 	snprintf (name, sizeof (name), "%s%s",
    873  1.1  mrg 		  ts->type == BT_COMPLEX ? "c" : "", m->name);
    874  1.1  mrg       else if (gfc_real_kinds[n].c_long_double)
    875  1.1  mrg 	snprintf (name, sizeof (name), "%s%s%s",
    876  1.1  mrg 		  ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
    877  1.1  mrg       else if (gfc_real_kinds[n].c_float128)
    878  1.1  mrg 	snprintf (name, sizeof (name), "%s%s%s",
    879  1.1  mrg 		  ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
    880  1.1  mrg       else
    881  1.1  mrg 	gcc_unreachable ();
    882  1.1  mrg     }
    883  1.1  mrg   else
    884  1.1  mrg     {
    885  1.1  mrg       snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
    886  1.1  mrg 		ts->type == BT_COMPLEX ? 'c' : 'r',
    887  1.1  mrg 		gfc_type_abi_kind (ts));
    888  1.1  mrg     }
    889  1.1  mrg 
    890  1.1  mrg   argtypes = NULL;
    891  1.1  mrg   for (actual = expr->value.function.actual; actual; actual = actual->next)
    892  1.1  mrg     {
    893  1.1  mrg       type = gfc_typenode_for_spec (&actual->expr->ts);
    894  1.1  mrg       vec_safe_push (argtypes, type);
    895  1.1  mrg     }
    896  1.1  mrg   type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
    897  1.1  mrg   fndecl = build_decl (input_location,
    898  1.1  mrg 		       FUNCTION_DECL, get_identifier (name), type);
    899  1.1  mrg 
    900  1.1  mrg   /* Mark the decl as external.  */
    901  1.1  mrg   DECL_EXTERNAL (fndecl) = 1;
    902  1.1  mrg   TREE_PUBLIC (fndecl) = 1;
    903  1.1  mrg 
    904  1.1  mrg   /* Mark it __attribute__((const)), if possible.  */
    905  1.1  mrg   TREE_READONLY (fndecl) = m->is_constant;
    906  1.1  mrg 
    907  1.1  mrg   rest_of_decl_compilation (fndecl, 1, 0);
    908  1.1  mrg 
    909  1.1  mrg   (*pdecl) = fndecl;
    910  1.1  mrg   return fndecl;
    911  1.1  mrg }
    912  1.1  mrg 
    913  1.1  mrg 
    914  1.1  mrg /* Convert an intrinsic function into an external or builtin call.  */
    915  1.1  mrg 
    916  1.1  mrg static void
    917  1.1  mrg gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
    918  1.1  mrg {
    919  1.1  mrg   gfc_intrinsic_map_t *m;
    920  1.1  mrg   tree fndecl;
    921  1.1  mrg   tree rettype;
    922  1.1  mrg   tree *args;
    923  1.1  mrg   unsigned int num_args;
    924  1.1  mrg   gfc_isym_id id;
    925  1.1  mrg 
    926  1.1  mrg   id = expr->value.function.isym->id;
    927  1.1  mrg   /* Find the entry for this function.  */
    928  1.1  mrg   for (m = gfc_intrinsic_map;
    929  1.1  mrg        m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
    930  1.1  mrg     {
    931  1.1  mrg       if (id == m->id)
    932  1.1  mrg 	break;
    933  1.1  mrg     }
    934  1.1  mrg 
    935  1.1  mrg   if (m->id == GFC_ISYM_NONE)
    936  1.1  mrg     {
    937  1.1  mrg       gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
    938  1.1  mrg 			  expr->value.function.name, id);
    939  1.1  mrg     }
    940  1.1  mrg 
    941  1.1  mrg   /* Get the decl and generate the call.  */
    942  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
    943  1.1  mrg   args = XALLOCAVEC (tree, num_args);
    944  1.1  mrg 
    945  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
    946  1.1  mrg   fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
    947  1.1  mrg   rettype = TREE_TYPE (TREE_TYPE (fndecl));
    948  1.1  mrg 
    949  1.1  mrg   fndecl = build_addr (fndecl);
    950  1.1  mrg   se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
    951  1.1  mrg }
    952  1.1  mrg 
    953  1.1  mrg 
    954  1.1  mrg /* If bounds-checking is enabled, create code to verify at runtime that the
    955  1.1  mrg    string lengths for both expressions are the same (needed for e.g. MERGE).
    956  1.1  mrg    If bounds-checking is not enabled, does nothing.  */
    957  1.1  mrg 
    958  1.1  mrg void
    959  1.1  mrg gfc_trans_same_strlen_check (const char* intr_name, locus* where,
    960  1.1  mrg 			     tree a, tree b, stmtblock_t* target)
    961  1.1  mrg {
    962  1.1  mrg   tree cond;
    963  1.1  mrg   tree name;
    964  1.1  mrg 
    965  1.1  mrg   /* If bounds-checking is disabled, do nothing.  */
    966  1.1  mrg   if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
    967  1.1  mrg     return;
    968  1.1  mrg 
    969  1.1  mrg   /* Compare the two string lengths.  */
    970  1.1  mrg   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
    971  1.1  mrg 
    972  1.1  mrg   /* Output the runtime-check.  */
    973  1.1  mrg   name = gfc_build_cstring_const (intr_name);
    974  1.1  mrg   name = gfc_build_addr_expr (pchar_type_node, name);
    975  1.1  mrg   gfc_trans_runtime_check (true, false, cond, target, where,
    976  1.1  mrg 			   "Unequal character lengths (%ld/%ld) in %s",
    977  1.1  mrg 			   fold_convert (long_integer_type_node, a),
    978  1.1  mrg 			   fold_convert (long_integer_type_node, b), name);
    979  1.1  mrg }
    980  1.1  mrg 
    981  1.1  mrg 
    982  1.1  mrg /* The EXPONENT(X) intrinsic function is translated into
    983  1.1  mrg        int ret;
    984  1.1  mrg        return isfinite(X) ? (frexp (X, &ret) , ret) : huge
    985  1.1  mrg    so that if X is a NaN or infinity, the result is HUGE(0).
    986  1.1  mrg  */
    987  1.1  mrg 
    988  1.1  mrg static void
    989  1.1  mrg gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
    990  1.1  mrg {
    991  1.1  mrg   tree arg, type, res, tmp, frexp, cond, huge;
    992  1.1  mrg   int i;
    993  1.1  mrg 
    994  1.1  mrg   frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
    995  1.1  mrg 				       expr->value.function.actual->expr->ts.kind);
    996  1.1  mrg 
    997  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
    998  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
    999  1.1  mrg 
   1000  1.1  mrg   i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
   1001  1.1  mrg   huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
   1002  1.1  mrg   cond = build_call_expr_loc (input_location,
   1003  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_ISFINITE),
   1004  1.1  mrg 			      1, arg);
   1005  1.1  mrg 
   1006  1.1  mrg   res = gfc_create_var (integer_type_node, NULL);
   1007  1.1  mrg   tmp = build_call_expr_loc (input_location, frexp, 2, arg,
   1008  1.1  mrg 			     gfc_build_addr_expr (NULL_TREE, res));
   1009  1.1  mrg   tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
   1010  1.1  mrg 			 tmp, res);
   1011  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
   1012  1.1  mrg 			      cond, tmp, huge);
   1013  1.1  mrg 
   1014  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   1015  1.1  mrg   se->expr = fold_convert (type, se->expr);
   1016  1.1  mrg }
   1017  1.1  mrg 
   1018  1.1  mrg 
   1019  1.1  mrg /* Fill in the following structure
   1020  1.1  mrg      struct caf_vector_t {
   1021  1.1  mrg        size_t nvec;  // size of the vector
   1022  1.1  mrg        union {
   1023  1.1  mrg          struct {
   1024  1.1  mrg            void *vector;
   1025  1.1  mrg            int kind;
   1026  1.1  mrg          } v;
   1027  1.1  mrg          struct {
   1028  1.1  mrg            ptrdiff_t lower_bound;
   1029  1.1  mrg            ptrdiff_t upper_bound;
   1030  1.1  mrg            ptrdiff_t stride;
   1031  1.1  mrg          } triplet;
   1032  1.1  mrg        } u;
   1033  1.1  mrg      }  */
   1034  1.1  mrg 
   1035  1.1  mrg static void
   1036  1.1  mrg conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
   1037  1.1  mrg 				tree lower, tree upper, tree stride,
   1038  1.1  mrg 				tree vector, int kind, tree nvec)
   1039  1.1  mrg {
   1040  1.1  mrg   tree field, type, tmp;
   1041  1.1  mrg 
   1042  1.1  mrg   desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
   1043  1.1  mrg   type = TREE_TYPE (desc);
   1044  1.1  mrg 
   1045  1.1  mrg   field = gfc_advance_chain (TYPE_FIELDS (type), 0);
   1046  1.1  mrg   tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1047  1.1  mrg 			 desc, field, NULL_TREE);
   1048  1.1  mrg   gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
   1049  1.1  mrg 
   1050  1.1  mrg   /* Access union.  */
   1051  1.1  mrg   field = gfc_advance_chain (TYPE_FIELDS (type), 1);
   1052  1.1  mrg   desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1053  1.1  mrg 			  desc, field, NULL_TREE);
   1054  1.1  mrg   type = TREE_TYPE (desc);
   1055  1.1  mrg 
   1056  1.1  mrg   /* Access the inner struct.  */
   1057  1.1  mrg   field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
   1058  1.1  mrg   desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1059  1.1  mrg 		      desc, field, NULL_TREE);
   1060  1.1  mrg   type = TREE_TYPE (desc);
   1061  1.1  mrg 
   1062  1.1  mrg   if (vector != NULL_TREE)
   1063  1.1  mrg     {
   1064  1.1  mrg       /* Set vector and kind.  */
   1065  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (type), 0);
   1066  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1067  1.1  mrg 			 desc, field, NULL_TREE);
   1068  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
   1069  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (type), 1);
   1070  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1071  1.1  mrg 			 desc, field, NULL_TREE);
   1072  1.1  mrg       gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
   1073  1.1  mrg     }
   1074  1.1  mrg   else
   1075  1.1  mrg     {
   1076  1.1  mrg       /* Set dim.lower/upper/stride.  */
   1077  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (type), 0);
   1078  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1079  1.1  mrg 			     desc, field, NULL_TREE);
   1080  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
   1081  1.1  mrg 
   1082  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (type), 1);
   1083  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1084  1.1  mrg 			     desc, field, NULL_TREE);
   1085  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
   1086  1.1  mrg 
   1087  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (type), 2);
   1088  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1089  1.1  mrg 			     desc, field, NULL_TREE);
   1090  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
   1091  1.1  mrg     }
   1092  1.1  mrg }
   1093  1.1  mrg 
   1094  1.1  mrg 
   1095  1.1  mrg static tree
   1096  1.1  mrg conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
   1097  1.1  mrg {
   1098  1.1  mrg   gfc_se argse;
   1099  1.1  mrg   tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
   1100  1.1  mrg   tree lbound, ubound, tmp;
   1101  1.1  mrg   int i;
   1102  1.1  mrg 
   1103  1.1  mrg   var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
   1104  1.1  mrg 
   1105  1.1  mrg   for (i = 0; i < ar->dimen; i++)
   1106  1.1  mrg     switch (ar->dimen_type[i])
   1107  1.1  mrg       {
   1108  1.1  mrg       case DIMEN_RANGE:
   1109  1.1  mrg         if (ar->end[i])
   1110  1.1  mrg 	  {
   1111  1.1  mrg 	    gfc_init_se (&argse, NULL);
   1112  1.1  mrg 	    gfc_conv_expr (&argse, ar->end[i]);
   1113  1.1  mrg 	    gfc_add_block_to_block (block, &argse.pre);
   1114  1.1  mrg 	    upper = gfc_evaluate_now (argse.expr, block);
   1115  1.1  mrg 	  }
   1116  1.1  mrg         else
   1117  1.1  mrg 	  upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
   1118  1.1  mrg 	if (ar->stride[i])
   1119  1.1  mrg 	  {
   1120  1.1  mrg 	    gfc_init_se (&argse, NULL);
   1121  1.1  mrg 	    gfc_conv_expr (&argse, ar->stride[i]);
   1122  1.1  mrg 	    gfc_add_block_to_block (block, &argse.pre);
   1123  1.1  mrg 	    stride = gfc_evaluate_now (argse.expr, block);
   1124  1.1  mrg 	  }
   1125  1.1  mrg 	else
   1126  1.1  mrg 	  stride = gfc_index_one_node;
   1127  1.1  mrg 
   1128  1.1  mrg 	/* Fall through.  */
   1129  1.1  mrg       case DIMEN_ELEMENT:
   1130  1.1  mrg 	if (ar->start[i])
   1131  1.1  mrg 	  {
   1132  1.1  mrg 	    gfc_init_se (&argse, NULL);
   1133  1.1  mrg 	    gfc_conv_expr (&argse, ar->start[i]);
   1134  1.1  mrg 	    gfc_add_block_to_block (block, &argse.pre);
   1135  1.1  mrg 	    lower = gfc_evaluate_now (argse.expr, block);
   1136  1.1  mrg 	  }
   1137  1.1  mrg 	else
   1138  1.1  mrg 	  lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
   1139  1.1  mrg 	if (ar->dimen_type[i] == DIMEN_ELEMENT)
   1140  1.1  mrg 	  {
   1141  1.1  mrg 	    upper = lower;
   1142  1.1  mrg 	    stride = gfc_index_one_node;
   1143  1.1  mrg 	  }
   1144  1.1  mrg 	vector = NULL_TREE;
   1145  1.1  mrg 	nvec = size_zero_node;
   1146  1.1  mrg 	conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
   1147  1.1  mrg 					vector, 0, nvec);
   1148  1.1  mrg 	break;
   1149  1.1  mrg 
   1150  1.1  mrg       case DIMEN_VECTOR:
   1151  1.1  mrg 	gfc_init_se (&argse, NULL);
   1152  1.1  mrg 	argse.descriptor_only = 1;
   1153  1.1  mrg 	gfc_conv_expr_descriptor (&argse, ar->start[i]);
   1154  1.1  mrg 	gfc_add_block_to_block (block, &argse.pre);
   1155  1.1  mrg 	vector = argse.expr;
   1156  1.1  mrg 	lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
   1157  1.1  mrg 	ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
   1158  1.1  mrg 	nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   1159  1.1  mrg         tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
   1160  1.1  mrg 	nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
   1161  1.1  mrg 				TREE_TYPE (nvec), nvec, tmp);
   1162  1.1  mrg 	lower = gfc_index_zero_node;
   1163  1.1  mrg 	upper = gfc_index_zero_node;
   1164  1.1  mrg 	stride = gfc_index_zero_node;
   1165  1.1  mrg 	vector = gfc_conv_descriptor_data_get (vector);
   1166  1.1  mrg 	conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
   1167  1.1  mrg 					vector, ar->start[i]->ts.kind, nvec);
   1168  1.1  mrg 	break;
   1169  1.1  mrg       default:
   1170  1.1  mrg 	gcc_unreachable();
   1171  1.1  mrg     }
   1172  1.1  mrg   return gfc_build_addr_expr (NULL_TREE, var);
   1173  1.1  mrg }
   1174  1.1  mrg 
   1175  1.1  mrg 
   1176  1.1  mrg static tree
   1177  1.1  mrg compute_component_offset (tree field, tree type)
   1178  1.1  mrg {
   1179  1.1  mrg   tree tmp;
   1180  1.1  mrg   if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
   1181  1.1  mrg       && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
   1182  1.1  mrg     {
   1183  1.1  mrg       tmp = fold_build2 (TRUNC_DIV_EXPR, type,
   1184  1.1  mrg 			 DECL_FIELD_BIT_OFFSET (field),
   1185  1.1  mrg 			 bitsize_unit_node);
   1186  1.1  mrg       return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
   1187  1.1  mrg     }
   1188  1.1  mrg   else
   1189  1.1  mrg     return DECL_FIELD_OFFSET (field);
   1190  1.1  mrg }
   1191  1.1  mrg 
   1192  1.1  mrg 
   1193  1.1  mrg static tree
   1194  1.1  mrg conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
   1195  1.1  mrg {
   1196  1.1  mrg   gfc_ref *ref = expr->ref, *last_comp_ref;
   1197  1.1  mrg   tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
   1198  1.1  mrg       field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
   1199  1.1  mrg       start, end, stride, vector, nvec;
   1200  1.1  mrg   gfc_se se;
   1201  1.1  mrg   bool ref_static_array = false;
   1202  1.1  mrg   tree last_component_ref_tree = NULL_TREE;
   1203  1.1  mrg   int i, last_type_n;
   1204  1.1  mrg 
   1205  1.1  mrg   if (expr->symtree)
   1206  1.1  mrg     {
   1207  1.1  mrg       last_component_ref_tree = expr->symtree->n.sym->backend_decl;
   1208  1.1  mrg       ref_static_array = !expr->symtree->n.sym->attr.allocatable
   1209  1.1  mrg 	  && !expr->symtree->n.sym->attr.pointer;
   1210  1.1  mrg     }
   1211  1.1  mrg 
   1212  1.1  mrg   /* Prevent uninit-warning.  */
   1213  1.1  mrg   reference_type = NULL_TREE;
   1214  1.1  mrg 
   1215  1.1  mrg   /* Skip refs upto the first coarray-ref.  */
   1216  1.1  mrg   last_comp_ref = NULL;
   1217  1.1  mrg   while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
   1218  1.1  mrg     {
   1219  1.1  mrg       /* Remember the type of components skipped.  */
   1220  1.1  mrg       if (ref->type == REF_COMPONENT)
   1221  1.1  mrg 	last_comp_ref = ref;
   1222  1.1  mrg       ref = ref->next;
   1223  1.1  mrg     }
   1224  1.1  mrg   /* When a component was skipped, get the type information of the last
   1225  1.1  mrg      component ref, else get the type from the symbol.  */
   1226  1.1  mrg   if (last_comp_ref)
   1227  1.1  mrg     {
   1228  1.1  mrg       last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
   1229  1.1  mrg       last_type_n = last_comp_ref->u.c.component->ts.type;
   1230  1.1  mrg     }
   1231  1.1  mrg   else
   1232  1.1  mrg     {
   1233  1.1  mrg       last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
   1234  1.1  mrg       last_type_n = expr->symtree->n.sym->ts.type;
   1235  1.1  mrg     }
   1236  1.1  mrg 
   1237  1.1  mrg   while (ref)
   1238  1.1  mrg     {
   1239  1.1  mrg       if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
   1240  1.1  mrg 	  && ref->u.ar.dimen == 0)
   1241  1.1  mrg 	{
   1242  1.1  mrg 	  /* Skip pure coindexes.  */
   1243  1.1  mrg 	  ref = ref->next;
   1244  1.1  mrg 	  continue;
   1245  1.1  mrg 	}
   1246  1.1  mrg       tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
   1247  1.1  mrg       reference_type = TREE_TYPE (tmp);
   1248  1.1  mrg 
   1249  1.1  mrg       if (caf_ref == NULL_TREE)
   1250  1.1  mrg 	caf_ref = tmp;
   1251  1.1  mrg 
   1252  1.1  mrg       /* Construct the chain of refs.  */
   1253  1.1  mrg       if (prev_caf_ref != NULL_TREE)
   1254  1.1  mrg 	{
   1255  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
   1256  1.1  mrg 	  tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1257  1.1  mrg 				  TREE_TYPE (field), prev_caf_ref, field,
   1258  1.1  mrg 				  NULL_TREE);
   1259  1.1  mrg 	  gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
   1260  1.1  mrg 							    tmp));
   1261  1.1  mrg 	}
   1262  1.1  mrg       prev_caf_ref = tmp;
   1263  1.1  mrg 
   1264  1.1  mrg       switch (ref->type)
   1265  1.1  mrg 	{
   1266  1.1  mrg 	case REF_COMPONENT:
   1267  1.1  mrg 	  last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
   1268  1.1  mrg 	  last_type_n = ref->u.c.component->ts.type;
   1269  1.1  mrg 	  /* Set the type of the ref.  */
   1270  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
   1271  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1272  1.1  mrg 				 TREE_TYPE (field), prev_caf_ref, field,
   1273  1.1  mrg 				 NULL_TREE);
   1274  1.1  mrg 	  gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
   1275  1.1  mrg 						     GFC_CAF_REF_COMPONENT));
   1276  1.1  mrg 
   1277  1.1  mrg 	  /* Ref the c in union u.  */
   1278  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
   1279  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1280  1.1  mrg 				 TREE_TYPE (field), prev_caf_ref, field,
   1281  1.1  mrg 				 NULL_TREE);
   1282  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
   1283  1.1  mrg 	  inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
   1284  1.1  mrg 				       TREE_TYPE (field), tmp, field,
   1285  1.1  mrg 				       NULL_TREE);
   1286  1.1  mrg 
   1287  1.1  mrg 	  /* Set the offset.  */
   1288  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
   1289  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1290  1.1  mrg 				 TREE_TYPE (field), inner_struct, field,
   1291  1.1  mrg 				 NULL_TREE);
   1292  1.1  mrg 	  /* Computing the offset is somewhat harder.  The bit_offset has to be
   1293  1.1  mrg 	     taken into account.  When the bit_offset in the field_decl is non-
   1294  1.1  mrg 	     null, divide it by the bitsize_unit and add it to the regular
   1295  1.1  mrg 	     offset.  */
   1296  1.1  mrg 	  tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
   1297  1.1  mrg 					   TREE_TYPE (tmp));
   1298  1.1  mrg 	  gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
   1299  1.1  mrg 
   1300  1.1  mrg 	  /* Set caf_token_offset.  */
   1301  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
   1302  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1303  1.1  mrg 				 TREE_TYPE (field), inner_struct, field,
   1304  1.1  mrg 				 NULL_TREE);
   1305  1.1  mrg 	  if ((ref->u.c.component->attr.allocatable
   1306  1.1  mrg 	       || ref->u.c.component->attr.pointer)
   1307  1.1  mrg 	      && ref->u.c.component->attr.dimension)
   1308  1.1  mrg 	    {
   1309  1.1  mrg 	      tree arr_desc_token_offset;
   1310  1.1  mrg 	      /* Get the token field from the descriptor.  */
   1311  1.1  mrg 	      arr_desc_token_offset = TREE_OPERAND (
   1312  1.1  mrg 		    gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
   1313  1.1  mrg 	      arr_desc_token_offset
   1314  1.1  mrg 		  = compute_component_offset (arr_desc_token_offset,
   1315  1.1  mrg 					      TREE_TYPE (tmp));
   1316  1.1  mrg 	      tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
   1317  1.1  mrg 				      TREE_TYPE (tmp2), tmp2,
   1318  1.1  mrg 				      arr_desc_token_offset);
   1319  1.1  mrg 	    }
   1320  1.1  mrg 	  else if (ref->u.c.component->caf_token)
   1321  1.1  mrg 	    tmp2 = compute_component_offset (ref->u.c.component->caf_token,
   1322  1.1  mrg 					     TREE_TYPE (tmp));
   1323  1.1  mrg 	  else
   1324  1.1  mrg 	    tmp2 = integer_zero_node;
   1325  1.1  mrg 	  gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
   1326  1.1  mrg 
   1327  1.1  mrg 	  /* Remember whether this ref was to a non-allocatable/non-pointer
   1328  1.1  mrg 	     component so the next array ref can be tailored correctly.  */
   1329  1.1  mrg 	  ref_static_array = !ref->u.c.component->attr.allocatable
   1330  1.1  mrg 	      && !ref->u.c.component->attr.pointer;
   1331  1.1  mrg 	  last_component_ref_tree = ref_static_array
   1332  1.1  mrg 	      ? ref->u.c.component->backend_decl : NULL_TREE;
   1333  1.1  mrg 	  break;
   1334  1.1  mrg 	case REF_ARRAY:
   1335  1.1  mrg 	  if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
   1336  1.1  mrg 	    ref_static_array = false;
   1337  1.1  mrg 	  /* Set the type of the ref.  */
   1338  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
   1339  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1340  1.1  mrg 				 TREE_TYPE (field), prev_caf_ref, field,
   1341  1.1  mrg 				 NULL_TREE);
   1342  1.1  mrg 	  gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
   1343  1.1  mrg 						     ref_static_array
   1344  1.1  mrg 						     ? GFC_CAF_REF_STATIC_ARRAY
   1345  1.1  mrg 						     : GFC_CAF_REF_ARRAY));
   1346  1.1  mrg 
   1347  1.1  mrg 	  /* Ref the a in union u.  */
   1348  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
   1349  1.1  mrg 	  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1350  1.1  mrg 				 TREE_TYPE (field), prev_caf_ref, field,
   1351  1.1  mrg 				 NULL_TREE);
   1352  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
   1353  1.1  mrg 	  inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
   1354  1.1  mrg 				       TREE_TYPE (field), tmp, field,
   1355  1.1  mrg 				       NULL_TREE);
   1356  1.1  mrg 
   1357  1.1  mrg 	  /* Set the static_array_type in a for static arrays.  */
   1358  1.1  mrg 	  if (ref_static_array)
   1359  1.1  mrg 	    {
   1360  1.1  mrg 	      field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
   1361  1.1  mrg 					 1);
   1362  1.1  mrg 	      tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1363  1.1  mrg 				     TREE_TYPE (field), inner_struct, field,
   1364  1.1  mrg 				     NULL_TREE);
   1365  1.1  mrg 	      gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
   1366  1.1  mrg 							 last_type_n));
   1367  1.1  mrg 	    }
   1368  1.1  mrg 	  /* Ref the mode in the inner_struct.  */
   1369  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
   1370  1.1  mrg 	  mode = fold_build3_loc (input_location, COMPONENT_REF,
   1371  1.1  mrg 				  TREE_TYPE (field), inner_struct, field,
   1372  1.1  mrg 				  NULL_TREE);
   1373  1.1  mrg 	  /* Ref the dim in the inner_struct.  */
   1374  1.1  mrg 	  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
   1375  1.1  mrg 	  dim_array = fold_build3_loc (input_location, COMPONENT_REF,
   1376  1.1  mrg 				       TREE_TYPE (field), inner_struct, field,
   1377  1.1  mrg 				       NULL_TREE);
   1378  1.1  mrg 	  for (i = 0; i < ref->u.ar.dimen; ++i)
   1379  1.1  mrg 	    {
   1380  1.1  mrg 	      /* Ref dim i.  */
   1381  1.1  mrg 	      dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
   1382  1.1  mrg 	      dim_type = TREE_TYPE (dim);
   1383  1.1  mrg 	      mode_rhs = start = end = stride = NULL_TREE;
   1384  1.1  mrg 	      switch (ref->u.ar.dimen_type[i])
   1385  1.1  mrg 		{
   1386  1.1  mrg 		case DIMEN_RANGE:
   1387  1.1  mrg 		  if (ref->u.ar.end[i])
   1388  1.1  mrg 		    {
   1389  1.1  mrg 		      gfc_init_se (&se, NULL);
   1390  1.1  mrg 		      gfc_conv_expr (&se, ref->u.ar.end[i]);
   1391  1.1  mrg 		      gfc_add_block_to_block (block, &se.pre);
   1392  1.1  mrg 		      if (ref_static_array)
   1393  1.1  mrg 			{
   1394  1.1  mrg 			  /* Make the index zero-based, when reffing a static
   1395  1.1  mrg 			     array.  */
   1396  1.1  mrg 			  end = se.expr;
   1397  1.1  mrg 			  gfc_init_se (&se, NULL);
   1398  1.1  mrg 			  gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
   1399  1.1  mrg 			  gfc_add_block_to_block (block, &se.pre);
   1400  1.1  mrg 			  se.expr = fold_build2 (MINUS_EXPR,
   1401  1.1  mrg 						 gfc_array_index_type,
   1402  1.1  mrg 						 end, fold_convert (
   1403  1.1  mrg 						   gfc_array_index_type,
   1404  1.1  mrg 						   se.expr));
   1405  1.1  mrg 			}
   1406  1.1  mrg 		      end = gfc_evaluate_now (fold_convert (
   1407  1.1  mrg 						gfc_array_index_type,
   1408  1.1  mrg 						se.expr),
   1409  1.1  mrg 					      block);
   1410  1.1  mrg 		    }
   1411  1.1  mrg 		  else if (ref_static_array)
   1412  1.1  mrg 		    end = fold_build2 (MINUS_EXPR,
   1413  1.1  mrg 				       gfc_array_index_type,
   1414  1.1  mrg 				       gfc_conv_array_ubound (
   1415  1.1  mrg 					 last_component_ref_tree, i),
   1416  1.1  mrg 				       gfc_conv_array_lbound (
   1417  1.1  mrg 					 last_component_ref_tree, i));
   1418  1.1  mrg 		  else
   1419  1.1  mrg 		    {
   1420  1.1  mrg 		      end = NULL_TREE;
   1421  1.1  mrg 		      mode_rhs = build_int_cst (unsigned_char_type_node,
   1422  1.1  mrg 						GFC_CAF_ARR_REF_OPEN_END);
   1423  1.1  mrg 		    }
   1424  1.1  mrg 		  if (ref->u.ar.stride[i])
   1425  1.1  mrg 		    {
   1426  1.1  mrg 		      gfc_init_se (&se, NULL);
   1427  1.1  mrg 		      gfc_conv_expr (&se, ref->u.ar.stride[i]);
   1428  1.1  mrg 		      gfc_add_block_to_block (block, &se.pre);
   1429  1.1  mrg 		      stride = gfc_evaluate_now (fold_convert (
   1430  1.1  mrg 						   gfc_array_index_type,
   1431  1.1  mrg 						   se.expr),
   1432  1.1  mrg 						 block);
   1433  1.1  mrg 		      if (ref_static_array)
   1434  1.1  mrg 			{
   1435  1.1  mrg 			  /* Make the index zero-based, when reffing a static
   1436  1.1  mrg 			     array.  */
   1437  1.1  mrg 			  stride = fold_build2 (MULT_EXPR,
   1438  1.1  mrg 						gfc_array_index_type,
   1439  1.1  mrg 						gfc_conv_array_stride (
   1440  1.1  mrg 						  last_component_ref_tree,
   1441  1.1  mrg 						  i),
   1442  1.1  mrg 						stride);
   1443  1.1  mrg 			  gcc_assert (end != NULL_TREE);
   1444  1.1  mrg 			  /* Multiply with the product of array's stride and
   1445  1.1  mrg 			     the step of the ref to a virtual upper bound.
   1446  1.1  mrg 			     We cannot compute the actual upper bound here or
   1447  1.1  mrg 			     the caflib would compute the extend
   1448  1.1  mrg 			     incorrectly.  */
   1449  1.1  mrg 			  end = fold_build2 (MULT_EXPR, gfc_array_index_type,
   1450  1.1  mrg 					     end, gfc_conv_array_stride (
   1451  1.1  mrg 					       last_component_ref_tree,
   1452  1.1  mrg 					       i));
   1453  1.1  mrg 			  end = gfc_evaluate_now (end, block);
   1454  1.1  mrg 			  stride = gfc_evaluate_now (stride, block);
   1455  1.1  mrg 			}
   1456  1.1  mrg 		    }
   1457  1.1  mrg 		  else if (ref_static_array)
   1458  1.1  mrg 		    {
   1459  1.1  mrg 		      stride = gfc_conv_array_stride (last_component_ref_tree,
   1460  1.1  mrg 						      i);
   1461  1.1  mrg 		      end = fold_build2 (MULT_EXPR, gfc_array_index_type,
   1462  1.1  mrg 					 end, stride);
   1463  1.1  mrg 		      end = gfc_evaluate_now (end, block);
   1464  1.1  mrg 		    }
   1465  1.1  mrg 		  else
   1466  1.1  mrg 		    /* Always set a ref stride of one to make caflib's
   1467  1.1  mrg 		       handling easier.  */
   1468  1.1  mrg 		    stride = gfc_index_one_node;
   1469  1.1  mrg 
   1470  1.1  mrg 		  /* Fall through.  */
   1471  1.1  mrg 		case DIMEN_ELEMENT:
   1472  1.1  mrg 		  if (ref->u.ar.start[i])
   1473  1.1  mrg 		    {
   1474  1.1  mrg 		      gfc_init_se (&se, NULL);
   1475  1.1  mrg 		      gfc_conv_expr (&se, ref->u.ar.start[i]);
   1476  1.1  mrg 		      gfc_add_block_to_block (block, &se.pre);
   1477  1.1  mrg 		      if (ref_static_array)
   1478  1.1  mrg 			{
   1479  1.1  mrg 			  /* Make the index zero-based, when reffing a static
   1480  1.1  mrg 			     array.  */
   1481  1.1  mrg 			  start = fold_convert (gfc_array_index_type, se.expr);
   1482  1.1  mrg 			  gfc_init_se (&se, NULL);
   1483  1.1  mrg 			  gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
   1484  1.1  mrg 			  gfc_add_block_to_block (block, &se.pre);
   1485  1.1  mrg 			  se.expr = fold_build2 (MINUS_EXPR,
   1486  1.1  mrg 						 gfc_array_index_type,
   1487  1.1  mrg 						 start, fold_convert (
   1488  1.1  mrg 						   gfc_array_index_type,
   1489  1.1  mrg 						   se.expr));
   1490  1.1  mrg 			  /* Multiply with the stride.  */
   1491  1.1  mrg 			  se.expr = fold_build2 (MULT_EXPR,
   1492  1.1  mrg 						 gfc_array_index_type,
   1493  1.1  mrg 						 se.expr,
   1494  1.1  mrg 						 gfc_conv_array_stride (
   1495  1.1  mrg 						   last_component_ref_tree,
   1496  1.1  mrg 						   i));
   1497  1.1  mrg 			}
   1498  1.1  mrg 		      start = gfc_evaluate_now (fold_convert (
   1499  1.1  mrg 						  gfc_array_index_type,
   1500  1.1  mrg 						  se.expr),
   1501  1.1  mrg 						block);
   1502  1.1  mrg 		      if (mode_rhs == NULL_TREE)
   1503  1.1  mrg 			mode_rhs = build_int_cst (unsigned_char_type_node,
   1504  1.1  mrg 						  ref->u.ar.dimen_type[i]
   1505  1.1  mrg 						  == DIMEN_ELEMENT
   1506  1.1  mrg 						  ? GFC_CAF_ARR_REF_SINGLE
   1507  1.1  mrg 						  : GFC_CAF_ARR_REF_RANGE);
   1508  1.1  mrg 		    }
   1509  1.1  mrg 		  else if (ref_static_array)
   1510  1.1  mrg 		    {
   1511  1.1  mrg 		      start = integer_zero_node;
   1512  1.1  mrg 		      mode_rhs = build_int_cst (unsigned_char_type_node,
   1513  1.1  mrg 						ref->u.ar.start[i] == NULL
   1514  1.1  mrg 						? GFC_CAF_ARR_REF_FULL
   1515  1.1  mrg 						: GFC_CAF_ARR_REF_RANGE);
   1516  1.1  mrg 		    }
   1517  1.1  mrg 		  else if (end == NULL_TREE)
   1518  1.1  mrg 		    mode_rhs = build_int_cst (unsigned_char_type_node,
   1519  1.1  mrg 					      GFC_CAF_ARR_REF_FULL);
   1520  1.1  mrg 		  else
   1521  1.1  mrg 		    mode_rhs = build_int_cst (unsigned_char_type_node,
   1522  1.1  mrg 					      GFC_CAF_ARR_REF_OPEN_START);
   1523  1.1  mrg 
   1524  1.1  mrg 		  /* Ref the s in dim.  */
   1525  1.1  mrg 		  field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
   1526  1.1  mrg 		  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1527  1.1  mrg 					 TREE_TYPE (field), dim, field,
   1528  1.1  mrg 					 NULL_TREE);
   1529  1.1  mrg 
   1530  1.1  mrg 		  /* Set start in s.  */
   1531  1.1  mrg 		  if (start != NULL_TREE)
   1532  1.1  mrg 		    {
   1533  1.1  mrg 		      field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
   1534  1.1  mrg 						 0);
   1535  1.1  mrg 		      tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1536  1.1  mrg 					      TREE_TYPE (field), tmp, field,
   1537  1.1  mrg 					      NULL_TREE);
   1538  1.1  mrg 		      gfc_add_modify (block, tmp2,
   1539  1.1  mrg 				      fold_convert (TREE_TYPE (tmp2), start));
   1540  1.1  mrg 		    }
   1541  1.1  mrg 
   1542  1.1  mrg 		  /* Set end in s.  */
   1543  1.1  mrg 		  if (end != NULL_TREE)
   1544  1.1  mrg 		    {
   1545  1.1  mrg 		      field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
   1546  1.1  mrg 						 1);
   1547  1.1  mrg 		      tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1548  1.1  mrg 					      TREE_TYPE (field), tmp, field,
   1549  1.1  mrg 					      NULL_TREE);
   1550  1.1  mrg 		      gfc_add_modify (block, tmp2,
   1551  1.1  mrg 				      fold_convert (TREE_TYPE (tmp2), end));
   1552  1.1  mrg 		    }
   1553  1.1  mrg 
   1554  1.1  mrg 		  /* Set end in s.  */
   1555  1.1  mrg 		  if (stride != NULL_TREE)
   1556  1.1  mrg 		    {
   1557  1.1  mrg 		      field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
   1558  1.1  mrg 						 2);
   1559  1.1  mrg 		      tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1560  1.1  mrg 					      TREE_TYPE (field), tmp, field,
   1561  1.1  mrg 					      NULL_TREE);
   1562  1.1  mrg 		      gfc_add_modify (block, tmp2,
   1563  1.1  mrg 				      fold_convert (TREE_TYPE (tmp2), stride));
   1564  1.1  mrg 		    }
   1565  1.1  mrg 		  break;
   1566  1.1  mrg 		case DIMEN_VECTOR:
   1567  1.1  mrg 		  /* TODO: In case of static array.  */
   1568  1.1  mrg 		  gcc_assert (!ref_static_array);
   1569  1.1  mrg 		  mode_rhs = build_int_cst (unsigned_char_type_node,
   1570  1.1  mrg 					    GFC_CAF_ARR_REF_VECTOR);
   1571  1.1  mrg 		  gfc_init_se (&se, NULL);
   1572  1.1  mrg 		  se.descriptor_only = 1;
   1573  1.1  mrg 		  gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
   1574  1.1  mrg 		  gfc_add_block_to_block (block, &se.pre);
   1575  1.1  mrg 		  vector = se.expr;
   1576  1.1  mrg 		  tmp = gfc_conv_descriptor_lbound_get (vector,
   1577  1.1  mrg 							gfc_rank_cst[0]);
   1578  1.1  mrg 		  tmp2 = gfc_conv_descriptor_ubound_get (vector,
   1579  1.1  mrg 							 gfc_rank_cst[0]);
   1580  1.1  mrg 		  nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
   1581  1.1  mrg 		  tmp = gfc_conv_descriptor_stride_get (vector,
   1582  1.1  mrg 							gfc_rank_cst[0]);
   1583  1.1  mrg 		  nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
   1584  1.1  mrg 					  TREE_TYPE (nvec), nvec, tmp);
   1585  1.1  mrg 		  vector = gfc_conv_descriptor_data_get (vector);
   1586  1.1  mrg 
   1587  1.1  mrg 		  /* Ref the v in dim.  */
   1588  1.1  mrg 		  field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
   1589  1.1  mrg 		  tmp = fold_build3_loc (input_location, COMPONENT_REF,
   1590  1.1  mrg 					 TREE_TYPE (field), dim, field,
   1591  1.1  mrg 					 NULL_TREE);
   1592  1.1  mrg 
   1593  1.1  mrg 		  /* Set vector in v.  */
   1594  1.1  mrg 		  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
   1595  1.1  mrg 		  tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1596  1.1  mrg 					  TREE_TYPE (field), tmp, field,
   1597  1.1  mrg 					  NULL_TREE);
   1598  1.1  mrg 		  gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
   1599  1.1  mrg 							     vector));
   1600  1.1  mrg 
   1601  1.1  mrg 		  /* Set nvec in v.  */
   1602  1.1  mrg 		  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
   1603  1.1  mrg 		  tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1604  1.1  mrg 					  TREE_TYPE (field), tmp, field,
   1605  1.1  mrg 					  NULL_TREE);
   1606  1.1  mrg 		  gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
   1607  1.1  mrg 							     nvec));
   1608  1.1  mrg 
   1609  1.1  mrg 		  /* Set kind in v.  */
   1610  1.1  mrg 		  field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
   1611  1.1  mrg 		  tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
   1612  1.1  mrg 					  TREE_TYPE (field), tmp, field,
   1613  1.1  mrg 					  NULL_TREE);
   1614  1.1  mrg 		  gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
   1615  1.1  mrg 						  ref->u.ar.start[i]->ts.kind));
   1616  1.1  mrg 		  break;
   1617  1.1  mrg 		default:
   1618  1.1  mrg 		  gcc_unreachable ();
   1619  1.1  mrg 		}
   1620  1.1  mrg 	      /* Set the mode for dim i.  */
   1621  1.1  mrg 	      tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
   1622  1.1  mrg 	      gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
   1623  1.1  mrg 							mode_rhs));
   1624  1.1  mrg 	    }
   1625  1.1  mrg 
   1626  1.1  mrg 	  /* Set the mode for dim i+1 to GFC_ARR_REF_NONE.  */
   1627  1.1  mrg 	  if (i < GFC_MAX_DIMENSIONS)
   1628  1.1  mrg 	    {
   1629  1.1  mrg 	      tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
   1630  1.1  mrg 	      gfc_add_modify (block, tmp,
   1631  1.1  mrg 			      build_int_cst (unsigned_char_type_node,
   1632  1.1  mrg 					     GFC_CAF_ARR_REF_NONE));
   1633  1.1  mrg 	    }
   1634  1.1  mrg 	  break;
   1635  1.1  mrg 	default:
   1636  1.1  mrg 	  gcc_unreachable ();
   1637  1.1  mrg 	}
   1638  1.1  mrg 
   1639  1.1  mrg       /* Set the size of the current type.  */
   1640  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
   1641  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1642  1.1  mrg 			     prev_caf_ref, field, NULL_TREE);
   1643  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
   1644  1.1  mrg 						TYPE_SIZE_UNIT (last_type)));
   1645  1.1  mrg 
   1646  1.1  mrg       ref = ref->next;
   1647  1.1  mrg     }
   1648  1.1  mrg 
   1649  1.1  mrg   if (prev_caf_ref != NULL_TREE)
   1650  1.1  mrg     {
   1651  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
   1652  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   1653  1.1  mrg 			     prev_caf_ref, field, NULL_TREE);
   1654  1.1  mrg       gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
   1655  1.1  mrg 						  null_pointer_node));
   1656  1.1  mrg     }
   1657  1.1  mrg   return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
   1658  1.1  mrg 			      : NULL_TREE;
   1659  1.1  mrg }
   1660  1.1  mrg 
   1661  1.1  mrg /* Get data from a remote coarray.  */
   1662  1.1  mrg 
   1663  1.1  mrg static void
   1664  1.1  mrg gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
   1665  1.1  mrg 			    tree may_require_tmp, bool may_realloc,
   1666  1.1  mrg 			    symbol_attribute *caf_attr)
   1667  1.1  mrg {
   1668  1.1  mrg   gfc_expr *array_expr, *tmp_stat;
   1669  1.1  mrg   gfc_se argse;
   1670  1.1  mrg   tree caf_decl, token, offset, image_index, tmp;
   1671  1.1  mrg   tree res_var, dst_var, type, kind, vec, stat;
   1672  1.1  mrg   tree caf_reference;
   1673  1.1  mrg   symbol_attribute caf_attr_store;
   1674  1.1  mrg 
   1675  1.1  mrg   gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
   1676  1.1  mrg 
   1677  1.1  mrg   if (se->ss && se->ss->info->useflags)
   1678  1.1  mrg     {
   1679  1.1  mrg        /* Access the previously obtained result.  */
   1680  1.1  mrg        gfc_conv_tmp_array_ref (se);
   1681  1.1  mrg        return;
   1682  1.1  mrg     }
   1683  1.1  mrg 
   1684  1.1  mrg   /* If lhs is set, the CAF_GET intrinsic has already been stripped.  */
   1685  1.1  mrg   array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
   1686  1.1  mrg   type = gfc_typenode_for_spec (&array_expr->ts);
   1687  1.1  mrg 
   1688  1.1  mrg   if (caf_attr == NULL)
   1689  1.1  mrg     {
   1690  1.1  mrg       caf_attr_store = gfc_caf_attr (array_expr);
   1691  1.1  mrg       caf_attr = &caf_attr_store;
   1692  1.1  mrg     }
   1693  1.1  mrg 
   1694  1.1  mrg   res_var = lhs;
   1695  1.1  mrg   dst_var = lhs;
   1696  1.1  mrg 
   1697  1.1  mrg   vec = null_pointer_node;
   1698  1.1  mrg   tmp_stat = gfc_find_stat_co (expr);
   1699  1.1  mrg 
   1700  1.1  mrg   if (tmp_stat)
   1701  1.1  mrg     {
   1702  1.1  mrg       gfc_se stat_se;
   1703  1.1  mrg       gfc_init_se (&stat_se, NULL);
   1704  1.1  mrg       gfc_conv_expr_reference (&stat_se, tmp_stat);
   1705  1.1  mrg       stat = stat_se.expr;
   1706  1.1  mrg       gfc_add_block_to_block (&se->pre, &stat_se.pre);
   1707  1.1  mrg       gfc_add_block_to_block (&se->post, &stat_se.post);
   1708  1.1  mrg     }
   1709  1.1  mrg   else
   1710  1.1  mrg     stat = null_pointer_node;
   1711  1.1  mrg 
   1712  1.1  mrg   /* Only use the new get_by_ref () where it is necessary.  I.e., when the lhs
   1713  1.1  mrg      is reallocatable or the right-hand side has allocatable components.  */
   1714  1.1  mrg   if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
   1715  1.1  mrg     {
   1716  1.1  mrg       /* Get using caf_get_by_ref.  */
   1717  1.1  mrg       caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
   1718  1.1  mrg 
   1719  1.1  mrg       if (caf_reference != NULL_TREE)
   1720  1.1  mrg 	{
   1721  1.1  mrg 	  if (lhs == NULL_TREE)
   1722  1.1  mrg 	    {
   1723  1.1  mrg 	      if (array_expr->ts.type == BT_CHARACTER)
   1724  1.1  mrg 		gfc_init_se (&argse, NULL);
   1725  1.1  mrg 	      if (array_expr->rank == 0)
   1726  1.1  mrg 		{
   1727  1.1  mrg 		  symbol_attribute attr;
   1728  1.1  mrg 		  gfc_clear_attr (&attr);
   1729  1.1  mrg 		  if (array_expr->ts.type == BT_CHARACTER)
   1730  1.1  mrg 		    {
   1731  1.1  mrg 		      res_var = gfc_conv_string_tmp (se,
   1732  1.1  mrg 						     build_pointer_type (type),
   1733  1.1  mrg 					     array_expr->ts.u.cl->backend_decl);
   1734  1.1  mrg 		      argse.string_length = array_expr->ts.u.cl->backend_decl;
   1735  1.1  mrg 		    }
   1736  1.1  mrg 		  else
   1737  1.1  mrg 		    res_var = gfc_create_var (type, "caf_res");
   1738  1.1  mrg 		  dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
   1739  1.1  mrg 		  dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
   1740  1.1  mrg 		}
   1741  1.1  mrg 	      else
   1742  1.1  mrg 		{
   1743  1.1  mrg 		  /* Create temporary.  */
   1744  1.1  mrg 		  if (array_expr->ts.type == BT_CHARACTER)
   1745  1.1  mrg 		    gfc_conv_expr_descriptor (&argse, array_expr);
   1746  1.1  mrg 		  may_realloc = gfc_trans_create_temp_array (&se->pre,
   1747  1.1  mrg 							     &se->post,
   1748  1.1  mrg 							     se->ss, type,
   1749  1.1  mrg 							     NULL_TREE, false,
   1750  1.1  mrg 							     false, false,
   1751  1.1  mrg 							     &array_expr->where)
   1752  1.1  mrg 		      == NULL_TREE;
   1753  1.1  mrg 		  res_var = se->ss->info->data.array.descriptor;
   1754  1.1  mrg 		  dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
   1755  1.1  mrg 		  if (may_realloc)
   1756  1.1  mrg 		    {
   1757  1.1  mrg 		      tmp = gfc_conv_descriptor_data_get (res_var);
   1758  1.1  mrg 		      tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
   1759  1.1  mrg 							NULL_TREE, NULL_TREE,
   1760  1.1  mrg 							NULL_TREE, true,
   1761  1.1  mrg 							NULL,
   1762  1.1  mrg 						     GFC_CAF_COARRAY_NOCOARRAY);
   1763  1.1  mrg 		      gfc_add_expr_to_block (&se->post, tmp);
   1764  1.1  mrg 		    }
   1765  1.1  mrg 		}
   1766  1.1  mrg 	    }
   1767  1.1  mrg 
   1768  1.1  mrg 	  kind = build_int_cst (integer_type_node, expr->ts.kind);
   1769  1.1  mrg 	  if (lhs_kind == NULL_TREE)
   1770  1.1  mrg 	    lhs_kind = kind;
   1771  1.1  mrg 
   1772  1.1  mrg 	  caf_decl = gfc_get_tree_for_caf_expr (array_expr);
   1773  1.1  mrg 	  if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   1774  1.1  mrg 	    caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   1775  1.1  mrg 	  image_index = gfc_caf_get_image_index (&se->pre, array_expr,
   1776  1.1  mrg 						 caf_decl);
   1777  1.1  mrg 	  gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
   1778  1.1  mrg 				    array_expr);
   1779  1.1  mrg 
   1780  1.1  mrg 	  /* No overlap possible as we have generated a temporary.  */
   1781  1.1  mrg 	  if (lhs == NULL_TREE)
   1782  1.1  mrg 	    may_require_tmp = boolean_false_node;
   1783  1.1  mrg 
   1784  1.1  mrg 	  /* It guarantees memory consistency within the same segment.  */
   1785  1.1  mrg 	  tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
   1786  1.1  mrg 	  tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
   1787  1.1  mrg 			    gfc_build_string_const (1, ""), NULL_TREE,
   1788  1.1  mrg 			    NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
   1789  1.1  mrg 			    NULL_TREE);
   1790  1.1  mrg 	  ASM_VOLATILE_P (tmp) = 1;
   1791  1.1  mrg 	  gfc_add_expr_to_block (&se->pre, tmp);
   1792  1.1  mrg 
   1793  1.1  mrg 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
   1794  1.1  mrg 				     10, token, image_index, dst_var,
   1795  1.1  mrg 				     caf_reference, lhs_kind, kind,
   1796  1.1  mrg 				     may_require_tmp,
   1797  1.1  mrg 				     may_realloc ? boolean_true_node :
   1798  1.1  mrg 						   boolean_false_node,
   1799  1.1  mrg 				     stat, build_int_cst (integer_type_node,
   1800  1.1  mrg 							  array_expr->ts.type));
   1801  1.1  mrg 
   1802  1.1  mrg 	  gfc_add_expr_to_block (&se->pre, tmp);
   1803  1.1  mrg 
   1804  1.1  mrg 	  if (se->ss)
   1805  1.1  mrg 	    gfc_advance_se_ss_chain (se);
   1806  1.1  mrg 
   1807  1.1  mrg 	  se->expr = res_var;
   1808  1.1  mrg 	  if (array_expr->ts.type == BT_CHARACTER)
   1809  1.1  mrg 	    se->string_length = argse.string_length;
   1810  1.1  mrg 
   1811  1.1  mrg 	  return;
   1812  1.1  mrg 	}
   1813  1.1  mrg     }
   1814  1.1  mrg 
   1815  1.1  mrg   gfc_init_se (&argse, NULL);
   1816  1.1  mrg   if (array_expr->rank == 0)
   1817  1.1  mrg     {
   1818  1.1  mrg       symbol_attribute attr;
   1819  1.1  mrg 
   1820  1.1  mrg       gfc_clear_attr (&attr);
   1821  1.1  mrg       gfc_conv_expr (&argse, array_expr);
   1822  1.1  mrg 
   1823  1.1  mrg       if (lhs == NULL_TREE)
   1824  1.1  mrg 	{
   1825  1.1  mrg 	  gfc_clear_attr (&attr);
   1826  1.1  mrg 	  if (array_expr->ts.type == BT_CHARACTER)
   1827  1.1  mrg 	    res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
   1828  1.1  mrg 					   argse.string_length);
   1829  1.1  mrg 	  else
   1830  1.1  mrg 	    res_var = gfc_create_var (type, "caf_res");
   1831  1.1  mrg 	  dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
   1832  1.1  mrg 	  dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
   1833  1.1  mrg 	}
   1834  1.1  mrg       argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
   1835  1.1  mrg       argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
   1836  1.1  mrg     }
   1837  1.1  mrg   else
   1838  1.1  mrg     {
   1839  1.1  mrg       /* If has_vector, pass descriptor for whole array and the
   1840  1.1  mrg          vector bounds separately.  */
   1841  1.1  mrg       gfc_array_ref *ar, ar2;
   1842  1.1  mrg       bool has_vector = false;
   1843  1.1  mrg 
   1844  1.1  mrg       if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
   1845  1.1  mrg 	{
   1846  1.1  mrg           has_vector = true;
   1847  1.1  mrg           ar = gfc_find_array_ref (expr);
   1848  1.1  mrg 	  ar2 = *ar;
   1849  1.1  mrg 	  memset (ar, '\0', sizeof (*ar));
   1850  1.1  mrg 	  ar->as = ar2.as;
   1851  1.1  mrg 	  ar->type = AR_FULL;
   1852  1.1  mrg 	}
   1853  1.1  mrg       // TODO: Check whether argse.want_coarray = 1 can help with the below.
   1854  1.1  mrg       gfc_conv_expr_descriptor (&argse, array_expr);
   1855  1.1  mrg       /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
   1856  1.1  mrg 	 has the wrong type if component references are done.  */
   1857  1.1  mrg       gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
   1858  1.1  mrg 		      gfc_get_dtype_rank_type (has_vector ? ar2.dimen
   1859  1.1  mrg 							  : array_expr->rank,
   1860  1.1  mrg 					       type));
   1861  1.1  mrg       if (has_vector)
   1862  1.1  mrg 	{
   1863  1.1  mrg 	  vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
   1864  1.1  mrg 	  *ar = ar2;
   1865  1.1  mrg 	}
   1866  1.1  mrg 
   1867  1.1  mrg       if (lhs == NULL_TREE)
   1868  1.1  mrg 	{
   1869  1.1  mrg 	  /* Create temporary.  */
   1870  1.1  mrg 	  for (int n = 0; n < se->ss->loop->dimen; n++)
   1871  1.1  mrg 	    if (se->loop->to[n] == NULL_TREE)
   1872  1.1  mrg 	      {
   1873  1.1  mrg 		se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
   1874  1.1  mrg 							       gfc_rank_cst[n]);
   1875  1.1  mrg 		se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
   1876  1.1  mrg 							       gfc_rank_cst[n]);
   1877  1.1  mrg 	      }
   1878  1.1  mrg 	  gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
   1879  1.1  mrg 				       NULL_TREE, false, true, false,
   1880  1.1  mrg 				       &array_expr->where);
   1881  1.1  mrg 	  res_var = se->ss->info->data.array.descriptor;
   1882  1.1  mrg 	  dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
   1883  1.1  mrg 	}
   1884  1.1  mrg       argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
   1885  1.1  mrg     }
   1886  1.1  mrg 
   1887  1.1  mrg   kind = build_int_cst (integer_type_node, expr->ts.kind);
   1888  1.1  mrg   if (lhs_kind == NULL_TREE)
   1889  1.1  mrg     lhs_kind = kind;
   1890  1.1  mrg 
   1891  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   1892  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   1893  1.1  mrg 
   1894  1.1  mrg   caf_decl = gfc_get_tree_for_caf_expr (array_expr);
   1895  1.1  mrg   if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   1896  1.1  mrg     caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   1897  1.1  mrg   image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
   1898  1.1  mrg   gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
   1899  1.1  mrg 			    array_expr);
   1900  1.1  mrg 
   1901  1.1  mrg   /* No overlap possible as we have generated a temporary.  */
   1902  1.1  mrg   if (lhs == NULL_TREE)
   1903  1.1  mrg     may_require_tmp = boolean_false_node;
   1904  1.1  mrg 
   1905  1.1  mrg   /* It guarantees memory consistency within the same segment.  */
   1906  1.1  mrg   tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
   1907  1.1  mrg   tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
   1908  1.1  mrg 		    gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
   1909  1.1  mrg 		    tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
   1910  1.1  mrg   ASM_VOLATILE_P (tmp) = 1;
   1911  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   1912  1.1  mrg 
   1913  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
   1914  1.1  mrg 			     token, offset, image_index, argse.expr, vec,
   1915  1.1  mrg 			     dst_var, kind, lhs_kind, may_require_tmp, stat);
   1916  1.1  mrg 
   1917  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   1918  1.1  mrg 
   1919  1.1  mrg   if (se->ss)
   1920  1.1  mrg     gfc_advance_se_ss_chain (se);
   1921  1.1  mrg 
   1922  1.1  mrg   se->expr = res_var;
   1923  1.1  mrg   if (array_expr->ts.type == BT_CHARACTER)
   1924  1.1  mrg     se->string_length = argse.string_length;
   1925  1.1  mrg }
   1926  1.1  mrg 
   1927  1.1  mrg 
   1928  1.1  mrg /* Send data to a remote coarray.  */
   1929  1.1  mrg 
   1930  1.1  mrg static tree
   1931  1.1  mrg conv_caf_send (gfc_code *code) {
   1932  1.1  mrg   gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
   1933  1.1  mrg   gfc_se lhs_se, rhs_se;
   1934  1.1  mrg   stmtblock_t block;
   1935  1.1  mrg   tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
   1936  1.1  mrg   tree may_require_tmp, src_stat, dst_stat, dst_team;
   1937  1.1  mrg   tree lhs_type = NULL_TREE;
   1938  1.1  mrg   tree vec = null_pointer_node, rhs_vec = null_pointer_node;
   1939  1.1  mrg   symbol_attribute lhs_caf_attr, rhs_caf_attr;
   1940  1.1  mrg 
   1941  1.1  mrg   gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
   1942  1.1  mrg 
   1943  1.1  mrg   lhs_expr = code->ext.actual->expr;
   1944  1.1  mrg   rhs_expr = code->ext.actual->next->expr;
   1945  1.1  mrg   may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
   1946  1.1  mrg 		    ? boolean_false_node : boolean_true_node;
   1947  1.1  mrg   gfc_init_block (&block);
   1948  1.1  mrg 
   1949  1.1  mrg   lhs_caf_attr = gfc_caf_attr (lhs_expr);
   1950  1.1  mrg   rhs_caf_attr = gfc_caf_attr (rhs_expr);
   1951  1.1  mrg   src_stat = dst_stat = null_pointer_node;
   1952  1.1  mrg   dst_team = null_pointer_node;
   1953  1.1  mrg 
   1954  1.1  mrg   /* LHS.  */
   1955  1.1  mrg   gfc_init_se (&lhs_se, NULL);
   1956  1.1  mrg   if (lhs_expr->rank == 0)
   1957  1.1  mrg     {
   1958  1.1  mrg       if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
   1959  1.1  mrg 	{
   1960  1.1  mrg 	  lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
   1961  1.1  mrg 	  lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
   1962  1.1  mrg 	}
   1963  1.1  mrg       else
   1964  1.1  mrg 	{
   1965  1.1  mrg 	  symbol_attribute attr;
   1966  1.1  mrg 	  gfc_clear_attr (&attr);
   1967  1.1  mrg 	  gfc_conv_expr (&lhs_se, lhs_expr);
   1968  1.1  mrg 	  lhs_type = TREE_TYPE (lhs_se.expr);
   1969  1.1  mrg 	  lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
   1970  1.1  mrg 						       attr);
   1971  1.1  mrg 	  lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
   1972  1.1  mrg 	}
   1973  1.1  mrg     }
   1974  1.1  mrg   else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
   1975  1.1  mrg 	   && lhs_caf_attr.codimension)
   1976  1.1  mrg     {
   1977  1.1  mrg       lhs_se.want_pointer = 1;
   1978  1.1  mrg       gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
   1979  1.1  mrg       /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
   1980  1.1  mrg 	 has the wrong type if component references are done.  */
   1981  1.1  mrg       lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
   1982  1.1  mrg       tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
   1983  1.1  mrg       gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
   1984  1.1  mrg 		      gfc_get_dtype_rank_type (
   1985  1.1  mrg 			gfc_has_vector_subscript (lhs_expr)
   1986  1.1  mrg 			? gfc_find_array_ref (lhs_expr)->dimen
   1987  1.1  mrg 			: lhs_expr->rank,
   1988  1.1  mrg 		      lhs_type));
   1989  1.1  mrg     }
   1990  1.1  mrg   else
   1991  1.1  mrg     {
   1992  1.1  mrg       bool has_vector = gfc_has_vector_subscript (lhs_expr);
   1993  1.1  mrg 
   1994  1.1  mrg       if (gfc_is_coindexed (lhs_expr) || !has_vector)
   1995  1.1  mrg 	{
   1996  1.1  mrg 	  /* If has_vector, pass descriptor for whole array and the
   1997  1.1  mrg 	     vector bounds separately.  */
   1998  1.1  mrg 	  gfc_array_ref *ar, ar2;
   1999  1.1  mrg 	  bool has_tmp_lhs_array = false;
   2000  1.1  mrg 	  if (has_vector)
   2001  1.1  mrg 	    {
   2002  1.1  mrg 	      has_tmp_lhs_array = true;
   2003  1.1  mrg 	      ar = gfc_find_array_ref (lhs_expr);
   2004  1.1  mrg 	      ar2 = *ar;
   2005  1.1  mrg 	      memset (ar, '\0', sizeof (*ar));
   2006  1.1  mrg 	      ar->as = ar2.as;
   2007  1.1  mrg 	      ar->type = AR_FULL;
   2008  1.1  mrg 	    }
   2009  1.1  mrg 	  lhs_se.want_pointer = 1;
   2010  1.1  mrg 	  gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
   2011  1.1  mrg 	  /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
   2012  1.1  mrg 	     that has the wrong type if component references are done.  */
   2013  1.1  mrg 	  lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
   2014  1.1  mrg 	  tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
   2015  1.1  mrg 	  gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
   2016  1.1  mrg 			  gfc_get_dtype_rank_type (has_vector ? ar2.dimen
   2017  1.1  mrg 							      : lhs_expr->rank,
   2018  1.1  mrg 						   lhs_type));
   2019  1.1  mrg 	  if (has_tmp_lhs_array)
   2020  1.1  mrg 	    {
   2021  1.1  mrg 	      vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
   2022  1.1  mrg 	      *ar = ar2;
   2023  1.1  mrg 	    }
   2024  1.1  mrg 	}
   2025  1.1  mrg       else
   2026  1.1  mrg 	{
   2027  1.1  mrg 	  /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
   2028  1.1  mrg 	     indexed array expression.  This is rewritten to:
   2029  1.1  mrg 
   2030  1.1  mrg 	     tmp_array = arr2[...]
   2031  1.1  mrg 	     arr1 ([...]) = tmp_array
   2032  1.1  mrg 
   2033  1.1  mrg 	     because using the standard gfc_conv_expr (lhs_expr) did the
   2034  1.1  mrg 	     assignment with lhs and rhs exchanged.  */
   2035  1.1  mrg 
   2036  1.1  mrg 	  gfc_ss *lss_for_tmparray, *lss_real;
   2037  1.1  mrg 	  gfc_loopinfo loop;
   2038  1.1  mrg 	  gfc_se se;
   2039  1.1  mrg 	  stmtblock_t body;
   2040  1.1  mrg 	  tree tmparr_desc, src;
   2041  1.1  mrg 	  tree index = gfc_index_zero_node;
   2042  1.1  mrg 	  tree stride = gfc_index_zero_node;
   2043  1.1  mrg 	  int n;
   2044  1.1  mrg 
   2045  1.1  mrg 	  /* Walk both sides of the assignment, once to get the shape of the
   2046  1.1  mrg 	     temporary array to create right.  */
   2047  1.1  mrg 	  lss_for_tmparray = gfc_walk_expr (lhs_expr);
   2048  1.1  mrg 	  /* And a second time to be able to create an assignment of the
   2049  1.1  mrg 	     temporary to the lhs_expr.  gfc_trans_create_temp_array replaces
   2050  1.1  mrg 	     the tree in the descriptor with the one for the temporary
   2051  1.1  mrg 	     array.  */
   2052  1.1  mrg 	  lss_real = gfc_walk_expr (lhs_expr);
   2053  1.1  mrg 	  gfc_init_loopinfo (&loop);
   2054  1.1  mrg 	  gfc_add_ss_to_loop (&loop, lss_for_tmparray);
   2055  1.1  mrg 	  gfc_add_ss_to_loop (&loop, lss_real);
   2056  1.1  mrg 	  gfc_conv_ss_startstride (&loop);
   2057  1.1  mrg 	  gfc_conv_loop_setup (&loop, &lhs_expr->where);
   2058  1.1  mrg 	  lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
   2059  1.1  mrg 	  gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
   2060  1.1  mrg 				       lss_for_tmparray, lhs_type, NULL_TREE,
   2061  1.1  mrg 				       false, true, false,
   2062  1.1  mrg 				       &lhs_expr->where);
   2063  1.1  mrg 	  tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
   2064  1.1  mrg 	  gfc_start_scalarized_body (&loop, &body);
   2065  1.1  mrg 	  gfc_init_se (&se, NULL);
   2066  1.1  mrg 	  gfc_copy_loopinfo_to_se (&se, &loop);
   2067  1.1  mrg 	  se.ss = lss_real;
   2068  1.1  mrg 	  gfc_conv_expr (&se, lhs_expr);
   2069  1.1  mrg 	  gfc_add_block_to_block (&body, &se.pre);
   2070  1.1  mrg 
   2071  1.1  mrg 	  /* Walk over all indexes of the loop.  */
   2072  1.1  mrg 	  for (n = loop.dimen - 1; n > 0; --n)
   2073  1.1  mrg 	    {
   2074  1.1  mrg 	      tmp = loop.loopvar[n];
   2075  1.1  mrg 	      tmp = fold_build2_loc (input_location, MINUS_EXPR,
   2076  1.1  mrg 				     gfc_array_index_type, tmp, loop.from[n]);
   2077  1.1  mrg 	      tmp = fold_build2_loc (input_location, PLUS_EXPR,
   2078  1.1  mrg 				     gfc_array_index_type, tmp, index);
   2079  1.1  mrg 
   2080  1.1  mrg 	      stride = fold_build2_loc (input_location, MINUS_EXPR,
   2081  1.1  mrg 					gfc_array_index_type,
   2082  1.1  mrg 					loop.to[n - 1], loop.from[n - 1]);
   2083  1.1  mrg 	      stride = fold_build2_loc (input_location, PLUS_EXPR,
   2084  1.1  mrg 					gfc_array_index_type,
   2085  1.1  mrg 					stride, gfc_index_one_node);
   2086  1.1  mrg 
   2087  1.1  mrg 	      index = fold_build2_loc (input_location, MULT_EXPR,
   2088  1.1  mrg 				       gfc_array_index_type, tmp, stride);
   2089  1.1  mrg 	    }
   2090  1.1  mrg 
   2091  1.1  mrg 	  index = fold_build2_loc (input_location, MINUS_EXPR,
   2092  1.1  mrg 				   gfc_array_index_type,
   2093  1.1  mrg 				   index, loop.from[0]);
   2094  1.1  mrg 
   2095  1.1  mrg 	  index = fold_build2_loc (input_location, PLUS_EXPR,
   2096  1.1  mrg 				   gfc_array_index_type,
   2097  1.1  mrg 				   loop.loopvar[0], index);
   2098  1.1  mrg 
   2099  1.1  mrg 	  src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
   2100  1.1  mrg 	  src = gfc_build_array_ref (src, index, NULL);
   2101  1.1  mrg 	  /* Now create the assignment of lhs_expr = tmp_array.  */
   2102  1.1  mrg 	  gfc_add_modify (&body, se.expr, src);
   2103  1.1  mrg 	  gfc_add_block_to_block (&body, &se.post);
   2104  1.1  mrg 	  lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
   2105  1.1  mrg 	  gfc_trans_scalarizing_loops (&loop, &body);
   2106  1.1  mrg 	  gfc_add_block_to_block (&loop.pre, &loop.post);
   2107  1.1  mrg 	  gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
   2108  1.1  mrg 	  gfc_free_ss (lss_for_tmparray);
   2109  1.1  mrg 	  gfc_free_ss (lss_real);
   2110  1.1  mrg 	}
   2111  1.1  mrg     }
   2112  1.1  mrg 
   2113  1.1  mrg   lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
   2114  1.1  mrg 
   2115  1.1  mrg   /* Special case: RHS is a coarray but LHS is not; this code path avoids a
   2116  1.1  mrg      temporary and a loop.  */
   2117  1.1  mrg   if (!gfc_is_coindexed (lhs_expr)
   2118  1.1  mrg       && (!lhs_caf_attr.codimension
   2119  1.1  mrg 	  || !(lhs_expr->rank > 0
   2120  1.1  mrg 	       && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
   2121  1.1  mrg     {
   2122  1.1  mrg       bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
   2123  1.1  mrg       gcc_assert (gfc_is_coindexed (rhs_expr));
   2124  1.1  mrg       gfc_init_se (&rhs_se, NULL);
   2125  1.1  mrg       if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
   2126  1.1  mrg 	{
   2127  1.1  mrg 	  gfc_se scal_se;
   2128  1.1  mrg 	  gfc_init_se (&scal_se, NULL);
   2129  1.1  mrg 	  scal_se.want_pointer = 1;
   2130  1.1  mrg 	  gfc_conv_expr (&scal_se, lhs_expr);
   2131  1.1  mrg 	  /* Ensure scalar on lhs is allocated.  */
   2132  1.1  mrg 	  gfc_add_block_to_block (&block, &scal_se.pre);
   2133  1.1  mrg 
   2134  1.1  mrg 	  gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
   2135  1.1  mrg 				    TYPE_SIZE_UNIT (
   2136  1.1  mrg 				       gfc_typenode_for_spec (&lhs_expr->ts)),
   2137  1.1  mrg 				    NULL_TREE);
   2138  1.1  mrg 	  tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
   2139  1.1  mrg 			     null_pointer_node);
   2140  1.1  mrg 	  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
   2141  1.1  mrg 				 tmp, gfc_finish_block (&scal_se.pre),
   2142  1.1  mrg 				 build_empty_stmt (input_location));
   2143  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   2144  1.1  mrg 	}
   2145  1.1  mrg       else
   2146  1.1  mrg 	lhs_may_realloc = lhs_may_realloc
   2147  1.1  mrg 	    && gfc_full_array_ref_p (lhs_expr->ref, NULL);
   2148  1.1  mrg       gfc_add_block_to_block (&block, &lhs_se.pre);
   2149  1.1  mrg       gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
   2150  1.1  mrg 				  may_require_tmp, lhs_may_realloc,
   2151  1.1  mrg 				  &rhs_caf_attr);
   2152  1.1  mrg       gfc_add_block_to_block (&block, &rhs_se.pre);
   2153  1.1  mrg       gfc_add_block_to_block (&block, &rhs_se.post);
   2154  1.1  mrg       gfc_add_block_to_block (&block, &lhs_se.post);
   2155  1.1  mrg       return gfc_finish_block (&block);
   2156  1.1  mrg     }
   2157  1.1  mrg 
   2158  1.1  mrg   gfc_add_block_to_block (&block, &lhs_se.pre);
   2159  1.1  mrg 
   2160  1.1  mrg   /* Obtain token, offset and image index for the LHS.  */
   2161  1.1  mrg   caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
   2162  1.1  mrg   if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   2163  1.1  mrg     caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   2164  1.1  mrg   image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
   2165  1.1  mrg   tmp = lhs_se.expr;
   2166  1.1  mrg   if (lhs_caf_attr.alloc_comp)
   2167  1.1  mrg     gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
   2168  1.1  mrg 			      NULL);
   2169  1.1  mrg   else
   2170  1.1  mrg     gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
   2171  1.1  mrg 			      lhs_expr);
   2172  1.1  mrg   lhs_se.expr = tmp;
   2173  1.1  mrg 
   2174  1.1  mrg   /* RHS.  */
   2175  1.1  mrg   gfc_init_se (&rhs_se, NULL);
   2176  1.1  mrg   if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
   2177  1.1  mrg       && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
   2178  1.1  mrg     rhs_expr = rhs_expr->value.function.actual->expr;
   2179  1.1  mrg   if (rhs_expr->rank == 0)
   2180  1.1  mrg     {
   2181  1.1  mrg       symbol_attribute attr;
   2182  1.1  mrg       gfc_clear_attr (&attr);
   2183  1.1  mrg       gfc_conv_expr (&rhs_se, rhs_expr);
   2184  1.1  mrg       rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
   2185  1.1  mrg       rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
   2186  1.1  mrg     }
   2187  1.1  mrg   else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
   2188  1.1  mrg 	   && rhs_caf_attr.codimension)
   2189  1.1  mrg     {
   2190  1.1  mrg       tree tmp2;
   2191  1.1  mrg       rhs_se.want_pointer = 1;
   2192  1.1  mrg       gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
   2193  1.1  mrg       /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
   2194  1.1  mrg 	 has the wrong type if component references are done.  */
   2195  1.1  mrg       tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
   2196  1.1  mrg       tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
   2197  1.1  mrg       gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
   2198  1.1  mrg 		      gfc_get_dtype_rank_type (
   2199  1.1  mrg 			gfc_has_vector_subscript (rhs_expr)
   2200  1.1  mrg 			? gfc_find_array_ref (rhs_expr)->dimen
   2201  1.1  mrg 			: rhs_expr->rank,
   2202  1.1  mrg 		      tmp2));
   2203  1.1  mrg     }
   2204  1.1  mrg   else
   2205  1.1  mrg     {
   2206  1.1  mrg       /* If has_vector, pass descriptor for whole array and the
   2207  1.1  mrg          vector bounds separately.  */
   2208  1.1  mrg       gfc_array_ref *ar, ar2;
   2209  1.1  mrg       bool has_vector = false;
   2210  1.1  mrg       tree tmp2;
   2211  1.1  mrg 
   2212  1.1  mrg       if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
   2213  1.1  mrg 	{
   2214  1.1  mrg           has_vector = true;
   2215  1.1  mrg           ar = gfc_find_array_ref (rhs_expr);
   2216  1.1  mrg 	  ar2 = *ar;
   2217  1.1  mrg 	  memset (ar, '\0', sizeof (*ar));
   2218  1.1  mrg 	  ar->as = ar2.as;
   2219  1.1  mrg 	  ar->type = AR_FULL;
   2220  1.1  mrg 	}
   2221  1.1  mrg       rhs_se.want_pointer = 1;
   2222  1.1  mrg       gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
   2223  1.1  mrg       /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
   2224  1.1  mrg          has the wrong type if component references are done.  */
   2225  1.1  mrg       tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
   2226  1.1  mrg       tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
   2227  1.1  mrg       gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
   2228  1.1  mrg                       gfc_get_dtype_rank_type (has_vector ? ar2.dimen
   2229  1.1  mrg 							  : rhs_expr->rank,
   2230  1.1  mrg 		      tmp2));
   2231  1.1  mrg       if (has_vector)
   2232  1.1  mrg 	{
   2233  1.1  mrg 	  rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
   2234  1.1  mrg 	  *ar = ar2;
   2235  1.1  mrg 	}
   2236  1.1  mrg     }
   2237  1.1  mrg 
   2238  1.1  mrg   gfc_add_block_to_block (&block, &rhs_se.pre);
   2239  1.1  mrg 
   2240  1.1  mrg   rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
   2241  1.1  mrg 
   2242  1.1  mrg   tmp_stat = gfc_find_stat_co (lhs_expr);
   2243  1.1  mrg 
   2244  1.1  mrg   if (tmp_stat)
   2245  1.1  mrg     {
   2246  1.1  mrg       gfc_se stat_se;
   2247  1.1  mrg       gfc_init_se (&stat_se, NULL);
   2248  1.1  mrg       gfc_conv_expr_reference (&stat_se, tmp_stat);
   2249  1.1  mrg       dst_stat = stat_se.expr;
   2250  1.1  mrg       gfc_add_block_to_block (&block, &stat_se.pre);
   2251  1.1  mrg       gfc_add_block_to_block (&block, &stat_se.post);
   2252  1.1  mrg     }
   2253  1.1  mrg 
   2254  1.1  mrg   tmp_team = gfc_find_team_co (lhs_expr);
   2255  1.1  mrg 
   2256  1.1  mrg   if (tmp_team)
   2257  1.1  mrg     {
   2258  1.1  mrg       gfc_se team_se;
   2259  1.1  mrg       gfc_init_se (&team_se, NULL);
   2260  1.1  mrg       gfc_conv_expr_reference (&team_se, tmp_team);
   2261  1.1  mrg       dst_team = team_se.expr;
   2262  1.1  mrg       gfc_add_block_to_block (&block, &team_se.pre);
   2263  1.1  mrg       gfc_add_block_to_block (&block, &team_se.post);
   2264  1.1  mrg     }
   2265  1.1  mrg 
   2266  1.1  mrg   if (!gfc_is_coindexed (rhs_expr))
   2267  1.1  mrg     {
   2268  1.1  mrg       if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
   2269  1.1  mrg 	{
   2270  1.1  mrg 	  tree reference, dst_realloc;
   2271  1.1  mrg 	  reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
   2272  1.1  mrg 	  dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
   2273  1.1  mrg 					     : boolean_false_node;
   2274  1.1  mrg 	  tmp = build_call_expr_loc (input_location,
   2275  1.1  mrg 				     gfor_fndecl_caf_send_by_ref,
   2276  1.1  mrg 				     10, token, image_index, rhs_se.expr,
   2277  1.1  mrg 				     reference, lhs_kind, rhs_kind,
   2278  1.1  mrg 				     may_require_tmp, dst_realloc, src_stat,
   2279  1.1  mrg 				     build_int_cst (integer_type_node,
   2280  1.1  mrg 						    lhs_expr->ts.type));
   2281  1.1  mrg 	  }
   2282  1.1  mrg       else
   2283  1.1  mrg 	tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
   2284  1.1  mrg 				   token, offset, image_index, lhs_se.expr, vec,
   2285  1.1  mrg 				   rhs_se.expr, lhs_kind, rhs_kind,
   2286  1.1  mrg 				   may_require_tmp, src_stat, dst_team);
   2287  1.1  mrg     }
   2288  1.1  mrg   else
   2289  1.1  mrg     {
   2290  1.1  mrg       tree rhs_token, rhs_offset, rhs_image_index;
   2291  1.1  mrg 
   2292  1.1  mrg       /* It guarantees memory consistency within the same segment.  */
   2293  1.1  mrg       tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
   2294  1.1  mrg       tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
   2295  1.1  mrg 			  gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
   2296  1.1  mrg 			  tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
   2297  1.1  mrg       ASM_VOLATILE_P (tmp) = 1;
   2298  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   2299  1.1  mrg 
   2300  1.1  mrg       caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
   2301  1.1  mrg       if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   2302  1.1  mrg 	caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   2303  1.1  mrg       rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
   2304  1.1  mrg       tmp = rhs_se.expr;
   2305  1.1  mrg       if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
   2306  1.1  mrg 	{
   2307  1.1  mrg 	  tmp_stat = gfc_find_stat_co (lhs_expr);
   2308  1.1  mrg 
   2309  1.1  mrg 	  if (tmp_stat)
   2310  1.1  mrg 	    {
   2311  1.1  mrg 	      gfc_se stat_se;
   2312  1.1  mrg 	      gfc_init_se (&stat_se, NULL);
   2313  1.1  mrg 	      gfc_conv_expr_reference (&stat_se, tmp_stat);
   2314  1.1  mrg 	      src_stat = stat_se.expr;
   2315  1.1  mrg 	      gfc_add_block_to_block (&block, &stat_se.pre);
   2316  1.1  mrg 	      gfc_add_block_to_block (&block, &stat_se.post);
   2317  1.1  mrg 	    }
   2318  1.1  mrg 
   2319  1.1  mrg 	  gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
   2320  1.1  mrg 				    NULL_TREE, NULL);
   2321  1.1  mrg 	  tree lhs_reference, rhs_reference;
   2322  1.1  mrg 	  lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
   2323  1.1  mrg 	  rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
   2324  1.1  mrg 	  tmp = build_call_expr_loc (input_location,
   2325  1.1  mrg 				     gfor_fndecl_caf_sendget_by_ref, 13,
   2326  1.1  mrg 				     token, image_index, lhs_reference,
   2327  1.1  mrg 				     rhs_token, rhs_image_index, rhs_reference,
   2328  1.1  mrg 				     lhs_kind, rhs_kind, may_require_tmp,
   2329  1.1  mrg 				     dst_stat, src_stat,
   2330  1.1  mrg 				     build_int_cst (integer_type_node,
   2331  1.1  mrg 						    lhs_expr->ts.type),
   2332  1.1  mrg 				     build_int_cst (integer_type_node,
   2333  1.1  mrg 						    rhs_expr->ts.type));
   2334  1.1  mrg 	}
   2335  1.1  mrg       else
   2336  1.1  mrg 	{
   2337  1.1  mrg 	  gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
   2338  1.1  mrg 				    tmp, rhs_expr);
   2339  1.1  mrg 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
   2340  1.1  mrg 				     14, token, offset, image_index,
   2341  1.1  mrg 				     lhs_se.expr, vec, rhs_token, rhs_offset,
   2342  1.1  mrg 				     rhs_image_index, tmp, rhs_vec, lhs_kind,
   2343  1.1  mrg 				     rhs_kind, may_require_tmp, src_stat);
   2344  1.1  mrg 	}
   2345  1.1  mrg     }
   2346  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   2347  1.1  mrg   gfc_add_block_to_block (&block, &lhs_se.post);
   2348  1.1  mrg   gfc_add_block_to_block (&block, &rhs_se.post);
   2349  1.1  mrg 
   2350  1.1  mrg   /* It guarantees memory consistency within the same segment.  */
   2351  1.1  mrg   tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
   2352  1.1  mrg   tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
   2353  1.1  mrg 		    gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
   2354  1.1  mrg 		    tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
   2355  1.1  mrg   ASM_VOLATILE_P (tmp) = 1;
   2356  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   2357  1.1  mrg 
   2358  1.1  mrg   return gfc_finish_block (&block);
   2359  1.1  mrg }
   2360  1.1  mrg 
   2361  1.1  mrg 
   2362  1.1  mrg static void
   2363  1.1  mrg trans_this_image (gfc_se * se, gfc_expr *expr)
   2364  1.1  mrg {
   2365  1.1  mrg   stmtblock_t loop;
   2366  1.1  mrg   tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
   2367  1.1  mrg        lbound, ubound, extent, ml;
   2368  1.1  mrg   gfc_se argse;
   2369  1.1  mrg   int rank, corank;
   2370  1.1  mrg   gfc_expr *distance = expr->value.function.actual->next->next->expr;
   2371  1.1  mrg 
   2372  1.1  mrg   if (expr->value.function.actual->expr
   2373  1.1  mrg       && !gfc_is_coarray (expr->value.function.actual->expr))
   2374  1.1  mrg     distance = expr->value.function.actual->expr;
   2375  1.1  mrg 
   2376  1.1  mrg   /* The case -fcoarray=single is handled elsewhere.  */
   2377  1.1  mrg   gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
   2378  1.1  mrg 
   2379  1.1  mrg   /* Argument-free version: THIS_IMAGE().  */
   2380  1.1  mrg   if (distance || expr->value.function.actual->expr == NULL)
   2381  1.1  mrg     {
   2382  1.1  mrg       if (distance)
   2383  1.1  mrg 	{
   2384  1.1  mrg 	  gfc_init_se (&argse, NULL);
   2385  1.1  mrg 	  gfc_conv_expr_val (&argse, distance);
   2386  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &argse.pre);
   2387  1.1  mrg 	  gfc_add_block_to_block (&se->post, &argse.post);
   2388  1.1  mrg 	  tmp = fold_convert (integer_type_node, argse.expr);
   2389  1.1  mrg 	}
   2390  1.1  mrg       else
   2391  1.1  mrg 	tmp = integer_zero_node;
   2392  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
   2393  1.1  mrg 				 tmp);
   2394  1.1  mrg       se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
   2395  1.1  mrg 			       tmp);
   2396  1.1  mrg       return;
   2397  1.1  mrg     }
   2398  1.1  mrg 
   2399  1.1  mrg   /* Coarray-argument version: THIS_IMAGE(coarray [, dim]).  */
   2400  1.1  mrg 
   2401  1.1  mrg   type = gfc_get_int_type (gfc_default_integer_kind);
   2402  1.1  mrg   corank = gfc_get_corank (expr->value.function.actual->expr);
   2403  1.1  mrg   rank = expr->value.function.actual->expr->rank;
   2404  1.1  mrg 
   2405  1.1  mrg   /* Obtain the descriptor of the COARRAY.  */
   2406  1.1  mrg   gfc_init_se (&argse, NULL);
   2407  1.1  mrg   argse.want_coarray = 1;
   2408  1.1  mrg   gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
   2409  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   2410  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   2411  1.1  mrg   desc = argse.expr;
   2412  1.1  mrg 
   2413  1.1  mrg   if (se->ss)
   2414  1.1  mrg     {
   2415  1.1  mrg       /* Create an implicit second parameter from the loop variable.  */
   2416  1.1  mrg       gcc_assert (!expr->value.function.actual->next->expr);
   2417  1.1  mrg       gcc_assert (corank > 0);
   2418  1.1  mrg       gcc_assert (se->loop->dimen == 1);
   2419  1.1  mrg       gcc_assert (se->ss->info->expr == expr);
   2420  1.1  mrg 
   2421  1.1  mrg       dim_arg = se->loop->loopvar[0];
   2422  1.1  mrg       dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
   2423  1.1  mrg 				 gfc_array_index_type, dim_arg,
   2424  1.1  mrg 				 build_int_cst (TREE_TYPE (dim_arg), 1));
   2425  1.1  mrg       gfc_advance_se_ss_chain (se);
   2426  1.1  mrg     }
   2427  1.1  mrg   else
   2428  1.1  mrg     {
   2429  1.1  mrg       /* Use the passed DIM= argument.  */
   2430  1.1  mrg       gcc_assert (expr->value.function.actual->next->expr);
   2431  1.1  mrg       gfc_init_se (&argse, NULL);
   2432  1.1  mrg       gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
   2433  1.1  mrg 			  gfc_array_index_type);
   2434  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2435  1.1  mrg       dim_arg = argse.expr;
   2436  1.1  mrg 
   2437  1.1  mrg       if (INTEGER_CST_P (dim_arg))
   2438  1.1  mrg 	{
   2439  1.1  mrg 	  if (wi::ltu_p (wi::to_wide (dim_arg), 1)
   2440  1.1  mrg 	      || wi::gtu_p (wi::to_wide (dim_arg),
   2441  1.1  mrg 			    GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
   2442  1.1  mrg 	    gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
   2443  1.1  mrg 		       "dimension index", expr->value.function.isym->name,
   2444  1.1  mrg 		       &expr->where);
   2445  1.1  mrg 	}
   2446  1.1  mrg      else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
   2447  1.1  mrg 	{
   2448  1.1  mrg 	  dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
   2449  1.1  mrg 	  cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   2450  1.1  mrg 				  dim_arg,
   2451  1.1  mrg 				  build_int_cst (TREE_TYPE (dim_arg), 1));
   2452  1.1  mrg 	  tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
   2453  1.1  mrg 	  tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   2454  1.1  mrg 				 dim_arg, tmp);
   2455  1.1  mrg 	  cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   2456  1.1  mrg 				  logical_type_node, cond, tmp);
   2457  1.1  mrg 	  gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
   2458  1.1  mrg 			           gfc_msg_fault);
   2459  1.1  mrg 	}
   2460  1.1  mrg     }
   2461  1.1  mrg 
   2462  1.1  mrg   /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
   2463  1.1  mrg      one always has a dim_arg argument.
   2464  1.1  mrg 
   2465  1.1  mrg      m = this_image() - 1
   2466  1.1  mrg      if (corank == 1)
   2467  1.1  mrg        {
   2468  1.1  mrg 	 sub(1) = m + lcobound(corank)
   2469  1.1  mrg 	 return;
   2470  1.1  mrg        }
   2471  1.1  mrg      i = rank
   2472  1.1  mrg      min_var = min (rank + corank - 2, rank + dim_arg - 1)
   2473  1.1  mrg      for (;;)
   2474  1.1  mrg        {
   2475  1.1  mrg 	 extent = gfc_extent(i)
   2476  1.1  mrg 	 ml = m
   2477  1.1  mrg 	 m  = m/extent
   2478  1.1  mrg 	 if (i >= min_var)
   2479  1.1  mrg 	   goto exit_label
   2480  1.1  mrg 	 i++
   2481  1.1  mrg        }
   2482  1.1  mrg      exit_label:
   2483  1.1  mrg      sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
   2484  1.1  mrg 				       : m + lcobound(corank)
   2485  1.1  mrg   */
   2486  1.1  mrg 
   2487  1.1  mrg   /* this_image () - 1.  */
   2488  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
   2489  1.1  mrg 			     integer_zero_node);
   2490  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
   2491  1.1  mrg 			 fold_convert (type, tmp), build_int_cst (type, 1));
   2492  1.1  mrg   if (corank == 1)
   2493  1.1  mrg     {
   2494  1.1  mrg       /* sub(1) = m + lcobound(corank).  */
   2495  1.1  mrg       lbound = gfc_conv_descriptor_lbound_get (desc,
   2496  1.1  mrg 			build_int_cst (TREE_TYPE (gfc_array_index_type),
   2497  1.1  mrg 				       corank+rank-1));
   2498  1.1  mrg       lbound = fold_convert (type, lbound);
   2499  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
   2500  1.1  mrg 
   2501  1.1  mrg       se->expr = tmp;
   2502  1.1  mrg       return;
   2503  1.1  mrg     }
   2504  1.1  mrg 
   2505  1.1  mrg   m = gfc_create_var (type, NULL);
   2506  1.1  mrg   ml = gfc_create_var (type, NULL);
   2507  1.1  mrg   loop_var = gfc_create_var (integer_type_node, NULL);
   2508  1.1  mrg   min_var = gfc_create_var (integer_type_node, NULL);
   2509  1.1  mrg 
   2510  1.1  mrg   /* m = this_image () - 1.  */
   2511  1.1  mrg   gfc_add_modify (&se->pre, m, tmp);
   2512  1.1  mrg 
   2513  1.1  mrg   /* min_var = min (rank + corank-2, rank + dim_arg - 1).  */
   2514  1.1  mrg   tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
   2515  1.1  mrg 			 fold_convert (integer_type_node, dim_arg),
   2516  1.1  mrg 			 build_int_cst (integer_type_node, rank - 1));
   2517  1.1  mrg   tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
   2518  1.1  mrg 			 build_int_cst (integer_type_node, rank + corank - 2),
   2519  1.1  mrg 			 tmp);
   2520  1.1  mrg   gfc_add_modify (&se->pre, min_var, tmp);
   2521  1.1  mrg 
   2522  1.1  mrg   /* i = rank.  */
   2523  1.1  mrg   tmp = build_int_cst (integer_type_node, rank);
   2524  1.1  mrg   gfc_add_modify (&se->pre, loop_var, tmp);
   2525  1.1  mrg 
   2526  1.1  mrg   exit_label = gfc_build_label_decl (NULL_TREE);
   2527  1.1  mrg   TREE_USED (exit_label) = 1;
   2528  1.1  mrg 
   2529  1.1  mrg   /* Loop body.  */
   2530  1.1  mrg   gfc_init_block (&loop);
   2531  1.1  mrg 
   2532  1.1  mrg   /* ml = m.  */
   2533  1.1  mrg   gfc_add_modify (&loop, ml, m);
   2534  1.1  mrg 
   2535  1.1  mrg   /* extent = ...  */
   2536  1.1  mrg   lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
   2537  1.1  mrg   ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
   2538  1.1  mrg   extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   2539  1.1  mrg   extent = fold_convert (type, extent);
   2540  1.1  mrg 
   2541  1.1  mrg   /* m = m/extent.  */
   2542  1.1  mrg   gfc_add_modify (&loop, m,
   2543  1.1  mrg 		  fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
   2544  1.1  mrg 			  m, extent));
   2545  1.1  mrg 
   2546  1.1  mrg   /* Exit condition:  if (i >= min_var) goto exit_label.  */
   2547  1.1  mrg   cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
   2548  1.1  mrg 		  min_var);
   2549  1.1  mrg   tmp = build1_v (GOTO_EXPR, exit_label);
   2550  1.1  mrg   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
   2551  1.1  mrg                          build_empty_stmt (input_location));
   2552  1.1  mrg   gfc_add_expr_to_block (&loop, tmp);
   2553  1.1  mrg 
   2554  1.1  mrg   /* Increment loop variable: i++.  */
   2555  1.1  mrg   gfc_add_modify (&loop, loop_var,
   2556  1.1  mrg                   fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
   2557  1.1  mrg 				   loop_var,
   2558  1.1  mrg 				   build_int_cst (integer_type_node, 1)));
   2559  1.1  mrg 
   2560  1.1  mrg   /* Making the loop... actually loop!  */
   2561  1.1  mrg   tmp = gfc_finish_block (&loop);
   2562  1.1  mrg   tmp = build1_v (LOOP_EXPR, tmp);
   2563  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   2564  1.1  mrg 
   2565  1.1  mrg   /* The exit label.  */
   2566  1.1  mrg   tmp = build1_v (LABEL_EXPR, exit_label);
   2567  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   2568  1.1  mrg 
   2569  1.1  mrg   /*  sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
   2570  1.1  mrg 				      : m + lcobound(corank) */
   2571  1.1  mrg 
   2572  1.1  mrg   cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
   2573  1.1  mrg 			  build_int_cst (TREE_TYPE (dim_arg), corank));
   2574  1.1  mrg 
   2575  1.1  mrg   lbound = gfc_conv_descriptor_lbound_get (desc,
   2576  1.1  mrg 		fold_build2_loc (input_location, PLUS_EXPR,
   2577  1.1  mrg 				 gfc_array_index_type, dim_arg,
   2578  1.1  mrg 				 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
   2579  1.1  mrg   lbound = fold_convert (type, lbound);
   2580  1.1  mrg 
   2581  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
   2582  1.1  mrg 			 fold_build2_loc (input_location, MULT_EXPR, type,
   2583  1.1  mrg 					  m, extent));
   2584  1.1  mrg   tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
   2585  1.1  mrg 
   2586  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
   2587  1.1  mrg 			      fold_build2_loc (input_location, PLUS_EXPR, type,
   2588  1.1  mrg 					       m, lbound));
   2589  1.1  mrg }
   2590  1.1  mrg 
   2591  1.1  mrg 
   2592  1.1  mrg /* Convert a call to image_status.  */
   2593  1.1  mrg 
   2594  1.1  mrg static void
   2595  1.1  mrg conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
   2596  1.1  mrg {
   2597  1.1  mrg   unsigned int num_args;
   2598  1.1  mrg   tree *args, tmp;
   2599  1.1  mrg 
   2600  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   2601  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   2602  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   2603  1.1  mrg   /* In args[0] the number of the image the status is desired for has to be
   2604  1.1  mrg      given.  */
   2605  1.1  mrg 
   2606  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_SINGLE)
   2607  1.1  mrg     {
   2608  1.1  mrg       tree arg;
   2609  1.1  mrg       arg = gfc_evaluate_now (args[0], &se->pre);
   2610  1.1  mrg       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   2611  1.1  mrg 			     fold_convert (integer_type_node, arg),
   2612  1.1  mrg 			     integer_one_node);
   2613  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
   2614  1.1  mrg 			     tmp, integer_zero_node,
   2615  1.1  mrg 			     build_int_cst (integer_type_node,
   2616  1.1  mrg 					    GFC_STAT_STOPPED_IMAGE));
   2617  1.1  mrg     }
   2618  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   2619  1.1  mrg     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
   2620  1.1  mrg 			       args[0], build_int_cst (integer_type_node, -1));
   2621  1.1  mrg   else
   2622  1.1  mrg     gcc_unreachable ();
   2623  1.1  mrg 
   2624  1.1  mrg   se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
   2625  1.1  mrg }
   2626  1.1  mrg 
   2627  1.1  mrg static void
   2628  1.1  mrg conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
   2629  1.1  mrg {
   2630  1.1  mrg   unsigned int num_args;
   2631  1.1  mrg 
   2632  1.1  mrg   tree *args, tmp;
   2633  1.1  mrg 
   2634  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   2635  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   2636  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   2637  1.1  mrg 
   2638  1.1  mrg   if (flag_coarray ==
   2639  1.1  mrg       GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
   2640  1.1  mrg     {
   2641  1.1  mrg       tree arg;
   2642  1.1  mrg 
   2643  1.1  mrg       arg = gfc_evaluate_now (args[0], &se->pre);
   2644  1.1  mrg       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   2645  1.1  mrg       			     fold_convert (integer_type_node, arg),
   2646  1.1  mrg       			     integer_one_node);
   2647  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
   2648  1.1  mrg       			     tmp, integer_zero_node,
   2649  1.1  mrg       			     build_int_cst (integer_type_node,
   2650  1.1  mrg       					    GFC_STAT_STOPPED_IMAGE));
   2651  1.1  mrg     }
   2652  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_SINGLE)
   2653  1.1  mrg     {
   2654  1.1  mrg       // the value -1 represents that no team has been created yet
   2655  1.1  mrg       tmp = build_int_cst (integer_type_node, -1);
   2656  1.1  mrg     }
   2657  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
   2658  1.1  mrg     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
   2659  1.1  mrg 			       args[0], build_int_cst (integer_type_node, -1));
   2660  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   2661  1.1  mrg     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
   2662  1.1  mrg 		integer_zero_node, build_int_cst (integer_type_node, -1));
   2663  1.1  mrg   else
   2664  1.1  mrg     gcc_unreachable ();
   2665  1.1  mrg 
   2666  1.1  mrg   se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
   2667  1.1  mrg }
   2668  1.1  mrg 
   2669  1.1  mrg 
   2670  1.1  mrg static void
   2671  1.1  mrg trans_image_index (gfc_se * se, gfc_expr *expr)
   2672  1.1  mrg {
   2673  1.1  mrg   tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
   2674  1.1  mrg        tmp, invalid_bound;
   2675  1.1  mrg   gfc_se argse, subse;
   2676  1.1  mrg   int rank, corank, codim;
   2677  1.1  mrg 
   2678  1.1  mrg   type = gfc_get_int_type (gfc_default_integer_kind);
   2679  1.1  mrg   corank = gfc_get_corank (expr->value.function.actual->expr);
   2680  1.1  mrg   rank = expr->value.function.actual->expr->rank;
   2681  1.1  mrg 
   2682  1.1  mrg   /* Obtain the descriptor of the COARRAY.  */
   2683  1.1  mrg   gfc_init_se (&argse, NULL);
   2684  1.1  mrg   argse.want_coarray = 1;
   2685  1.1  mrg   gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
   2686  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   2687  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   2688  1.1  mrg   desc = argse.expr;
   2689  1.1  mrg 
   2690  1.1  mrg   /* Obtain a handle to the SUB argument.  */
   2691  1.1  mrg   gfc_init_se (&subse, NULL);
   2692  1.1  mrg   gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
   2693  1.1  mrg   gfc_add_block_to_block (&se->pre, &subse.pre);
   2694  1.1  mrg   gfc_add_block_to_block (&se->post, &subse.post);
   2695  1.1  mrg   subdesc = build_fold_indirect_ref_loc (input_location,
   2696  1.1  mrg 			gfc_conv_descriptor_data_get (subse.expr));
   2697  1.1  mrg 
   2698  1.1  mrg   /* Fortran 2008 does not require that the values remain in the cobounds,
   2699  1.1  mrg      thus we need explicitly check this - and return 0 if they are exceeded.  */
   2700  1.1  mrg 
   2701  1.1  mrg   lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
   2702  1.1  mrg   tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
   2703  1.1  mrg   invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   2704  1.1  mrg 				 fold_convert (gfc_array_index_type, tmp),
   2705  1.1  mrg 				 lbound);
   2706  1.1  mrg 
   2707  1.1  mrg   for (codim = corank + rank - 2; codim >= rank; codim--)
   2708  1.1  mrg     {
   2709  1.1  mrg       lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
   2710  1.1  mrg       ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
   2711  1.1  mrg       tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
   2712  1.1  mrg       cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   2713  1.1  mrg 			      fold_convert (gfc_array_index_type, tmp),
   2714  1.1  mrg 			      lbound);
   2715  1.1  mrg       invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
   2716  1.1  mrg 				       logical_type_node, invalid_bound, cond);
   2717  1.1  mrg       cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   2718  1.1  mrg 			      fold_convert (gfc_array_index_type, tmp),
   2719  1.1  mrg 			      ubound);
   2720  1.1  mrg       invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
   2721  1.1  mrg 				       logical_type_node, invalid_bound, cond);
   2722  1.1  mrg     }
   2723  1.1  mrg 
   2724  1.1  mrg   invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
   2725  1.1  mrg 
   2726  1.1  mrg   /* See Fortran 2008, C.10 for the following algorithm.  */
   2727  1.1  mrg 
   2728  1.1  mrg   /* coindex = sub(corank) - lcobound(n).  */
   2729  1.1  mrg   coindex = fold_convert (gfc_array_index_type,
   2730  1.1  mrg 			  gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
   2731  1.1  mrg 					       NULL));
   2732  1.1  mrg   lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
   2733  1.1  mrg   coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   2734  1.1  mrg 			     fold_convert (gfc_array_index_type, coindex),
   2735  1.1  mrg 			     lbound);
   2736  1.1  mrg 
   2737  1.1  mrg   for (codim = corank + rank - 2; codim >= rank; codim--)
   2738  1.1  mrg     {
   2739  1.1  mrg       tree extent, ubound;
   2740  1.1  mrg 
   2741  1.1  mrg       /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim).  */
   2742  1.1  mrg       lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
   2743  1.1  mrg       ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
   2744  1.1  mrg       extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   2745  1.1  mrg 
   2746  1.1  mrg       /* coindex *= extent.  */
   2747  1.1  mrg       coindex = fold_build2_loc (input_location, MULT_EXPR,
   2748  1.1  mrg 				 gfc_array_index_type, coindex, extent);
   2749  1.1  mrg 
   2750  1.1  mrg       /* coindex += sub(codim).  */
   2751  1.1  mrg       tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
   2752  1.1  mrg       coindex = fold_build2_loc (input_location, PLUS_EXPR,
   2753  1.1  mrg 				 gfc_array_index_type, coindex,
   2754  1.1  mrg 				 fold_convert (gfc_array_index_type, tmp));
   2755  1.1  mrg 
   2756  1.1  mrg       /* coindex -= lbound(codim).  */
   2757  1.1  mrg       lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
   2758  1.1  mrg       coindex = fold_build2_loc (input_location, MINUS_EXPR,
   2759  1.1  mrg 				 gfc_array_index_type, coindex, lbound);
   2760  1.1  mrg     }
   2761  1.1  mrg 
   2762  1.1  mrg   coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
   2763  1.1  mrg 			     fold_convert(type, coindex),
   2764  1.1  mrg 			     build_int_cst (type, 1));
   2765  1.1  mrg 
   2766  1.1  mrg   /* Return 0 if "coindex" exceeds num_images().  */
   2767  1.1  mrg 
   2768  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_SINGLE)
   2769  1.1  mrg     num_images = build_int_cst (type, 1);
   2770  1.1  mrg   else
   2771  1.1  mrg     {
   2772  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
   2773  1.1  mrg 				 integer_zero_node,
   2774  1.1  mrg 				 build_int_cst (integer_type_node, -1));
   2775  1.1  mrg       num_images = fold_convert (type, tmp);
   2776  1.1  mrg     }
   2777  1.1  mrg 
   2778  1.1  mrg   tmp = gfc_create_var (type, NULL);
   2779  1.1  mrg   gfc_add_modify (&se->pre, tmp, coindex);
   2780  1.1  mrg 
   2781  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
   2782  1.1  mrg 			  num_images);
   2783  1.1  mrg   cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
   2784  1.1  mrg 			  cond,
   2785  1.1  mrg 			  fold_convert (logical_type_node, invalid_bound));
   2786  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
   2787  1.1  mrg 			      build_int_cst (type, 0), tmp);
   2788  1.1  mrg }
   2789  1.1  mrg 
   2790  1.1  mrg static void
   2791  1.1  mrg trans_num_images (gfc_se * se, gfc_expr *expr)
   2792  1.1  mrg {
   2793  1.1  mrg   tree tmp, distance, failed;
   2794  1.1  mrg   gfc_se argse;
   2795  1.1  mrg 
   2796  1.1  mrg   if (expr->value.function.actual->expr)
   2797  1.1  mrg     {
   2798  1.1  mrg       gfc_init_se (&argse, NULL);
   2799  1.1  mrg       gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
   2800  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2801  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   2802  1.1  mrg       distance = fold_convert (integer_type_node, argse.expr);
   2803  1.1  mrg     }
   2804  1.1  mrg   else
   2805  1.1  mrg     distance = integer_zero_node;
   2806  1.1  mrg 
   2807  1.1  mrg   if (expr->value.function.actual->next->expr)
   2808  1.1  mrg     {
   2809  1.1  mrg       gfc_init_se (&argse, NULL);
   2810  1.1  mrg       gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
   2811  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2812  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   2813  1.1  mrg       failed = fold_convert (integer_type_node, argse.expr);
   2814  1.1  mrg     }
   2815  1.1  mrg   else
   2816  1.1  mrg     failed = build_int_cst (integer_type_node, -1);
   2817  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
   2818  1.1  mrg 			     distance, failed);
   2819  1.1  mrg   se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
   2820  1.1  mrg }
   2821  1.1  mrg 
   2822  1.1  mrg 
   2823  1.1  mrg static void
   2824  1.1  mrg gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
   2825  1.1  mrg {
   2826  1.1  mrg   gfc_se argse;
   2827  1.1  mrg 
   2828  1.1  mrg   gfc_init_se (&argse, NULL);
   2829  1.1  mrg   argse.data_not_needed = 1;
   2830  1.1  mrg   argse.descriptor_only = 1;
   2831  1.1  mrg 
   2832  1.1  mrg   gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
   2833  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   2834  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   2835  1.1  mrg 
   2836  1.1  mrg   se->expr = gfc_conv_descriptor_rank (argse.expr);
   2837  1.1  mrg   se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
   2838  1.1  mrg 			   se->expr);
   2839  1.1  mrg }
   2840  1.1  mrg 
   2841  1.1  mrg 
   2842  1.1  mrg static void
   2843  1.1  mrg gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
   2844  1.1  mrg {
   2845  1.1  mrg   gfc_expr *arg;
   2846  1.1  mrg   arg = expr->value.function.actual->expr;
   2847  1.1  mrg   gfc_conv_is_contiguous_expr (se, arg);
   2848  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   2849  1.1  mrg }
   2850  1.1  mrg 
   2851  1.1  mrg /* This function does the work for gfc_conv_intrinsic_is_contiguous,
   2852  1.1  mrg    plus it can be called directly.  */
   2853  1.1  mrg 
   2854  1.1  mrg void
   2855  1.1  mrg gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
   2856  1.1  mrg {
   2857  1.1  mrg   gfc_ss *ss;
   2858  1.1  mrg   gfc_se argse;
   2859  1.1  mrg   tree desc, tmp, stride, extent, cond;
   2860  1.1  mrg   int i;
   2861  1.1  mrg   tree fncall0;
   2862  1.1  mrg   gfc_array_spec *as;
   2863  1.1  mrg 
   2864  1.1  mrg   if (arg->ts.type == BT_CLASS)
   2865  1.1  mrg     gfc_add_class_array_ref (arg);
   2866  1.1  mrg 
   2867  1.1  mrg   ss = gfc_walk_expr (arg);
   2868  1.1  mrg   gcc_assert (ss != gfc_ss_terminator);
   2869  1.1  mrg   gfc_init_se (&argse, NULL);
   2870  1.1  mrg   argse.data_not_needed = 1;
   2871  1.1  mrg   gfc_conv_expr_descriptor (&argse, arg);
   2872  1.1  mrg 
   2873  1.1  mrg   as = gfc_get_full_arrayspec_from_expr (arg);
   2874  1.1  mrg 
   2875  1.1  mrg   /* Create:  stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
   2876  1.1  mrg      Note in addition that zero-sized arrays don't count as contiguous.  */
   2877  1.1  mrg 
   2878  1.1  mrg   if (as && as->type == AS_ASSUMED_RANK)
   2879  1.1  mrg     {
   2880  1.1  mrg       /* Build the call to is_contiguous0.  */
   2881  1.1  mrg       argse.want_pointer = 1;
   2882  1.1  mrg       gfc_conv_expr_descriptor (&argse, arg);
   2883  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2884  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   2885  1.1  mrg       desc = gfc_evaluate_now (argse.expr, &se->pre);
   2886  1.1  mrg       fncall0 = build_call_expr_loc (input_location,
   2887  1.1  mrg 				     gfor_fndecl_is_contiguous0, 1, desc);
   2888  1.1  mrg       se->expr = fncall0;
   2889  1.1  mrg       se->expr = convert (logical_type_node, se->expr);
   2890  1.1  mrg     }
   2891  1.1  mrg   else
   2892  1.1  mrg     {
   2893  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2894  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   2895  1.1  mrg       desc = gfc_evaluate_now (argse.expr, &se->pre);
   2896  1.1  mrg 
   2897  1.1  mrg       stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
   2898  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
   2899  1.1  mrg 			      stride, build_int_cst (TREE_TYPE (stride), 1));
   2900  1.1  mrg 
   2901  1.1  mrg       for (i = 0; i < arg->rank - 1; i++)
   2902  1.1  mrg 	{
   2903  1.1  mrg 	  tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
   2904  1.1  mrg 	  extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
   2905  1.1  mrg 	  extent = fold_build2_loc (input_location, MINUS_EXPR,
   2906  1.1  mrg 				    gfc_array_index_type, extent, tmp);
   2907  1.1  mrg 	  extent = fold_build2_loc (input_location, PLUS_EXPR,
   2908  1.1  mrg 				    gfc_array_index_type, extent,
   2909  1.1  mrg 				    gfc_index_one_node);
   2910  1.1  mrg 	  tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
   2911  1.1  mrg 	  tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
   2912  1.1  mrg 				 tmp, extent);
   2913  1.1  mrg 	  stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
   2914  1.1  mrg 	  tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
   2915  1.1  mrg 				 stride, tmp);
   2916  1.1  mrg 	  cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   2917  1.1  mrg 				  boolean_type_node, cond, tmp);
   2918  1.1  mrg 	}
   2919  1.1  mrg       se->expr = cond;
   2920  1.1  mrg     }
   2921  1.1  mrg }
   2922  1.1  mrg 
   2923  1.1  mrg 
   2924  1.1  mrg /* Evaluate a single upper or lower bound.  */
   2925  1.1  mrg /* TODO: bound intrinsic generates way too much unnecessary code.  */
   2926  1.1  mrg 
   2927  1.1  mrg static void
   2928  1.1  mrg gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
   2929  1.1  mrg {
   2930  1.1  mrg   gfc_actual_arglist *arg;
   2931  1.1  mrg   gfc_actual_arglist *arg2;
   2932  1.1  mrg   tree desc;
   2933  1.1  mrg   tree type;
   2934  1.1  mrg   tree bound;
   2935  1.1  mrg   tree tmp;
   2936  1.1  mrg   tree cond, cond1;
   2937  1.1  mrg   tree ubound;
   2938  1.1  mrg   tree lbound;
   2939  1.1  mrg   tree size;
   2940  1.1  mrg   gfc_se argse;
   2941  1.1  mrg   gfc_array_spec * as;
   2942  1.1  mrg   bool assumed_rank_lb_one;
   2943  1.1  mrg 
   2944  1.1  mrg   arg = expr->value.function.actual;
   2945  1.1  mrg   arg2 = arg->next;
   2946  1.1  mrg 
   2947  1.1  mrg   if (se->ss)
   2948  1.1  mrg     {
   2949  1.1  mrg       /* Create an implicit second parameter from the loop variable.  */
   2950  1.1  mrg       gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE);
   2951  1.1  mrg       gcc_assert (se->loop->dimen == 1);
   2952  1.1  mrg       gcc_assert (se->ss->info->expr == expr);
   2953  1.1  mrg       gfc_advance_se_ss_chain (se);
   2954  1.1  mrg       bound = se->loop->loopvar[0];
   2955  1.1  mrg       bound = fold_build2_loc (input_location, MINUS_EXPR,
   2956  1.1  mrg 			       gfc_array_index_type, bound,
   2957  1.1  mrg 			       se->loop->from[0]);
   2958  1.1  mrg     }
   2959  1.1  mrg   else
   2960  1.1  mrg     {
   2961  1.1  mrg       /* use the passed argument.  */
   2962  1.1  mrg       gcc_assert (arg2->expr);
   2963  1.1  mrg       gfc_init_se (&argse, NULL);
   2964  1.1  mrg       gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
   2965  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   2966  1.1  mrg       bound = argse.expr;
   2967  1.1  mrg       /* Convert from one based to zero based.  */
   2968  1.1  mrg       bound = fold_build2_loc (input_location, MINUS_EXPR,
   2969  1.1  mrg 			       gfc_array_index_type, bound,
   2970  1.1  mrg 			       gfc_index_one_node);
   2971  1.1  mrg     }
   2972  1.1  mrg 
   2973  1.1  mrg   /* TODO: don't re-evaluate the descriptor on each iteration.  */
   2974  1.1  mrg   /* Get a descriptor for the first parameter.  */
   2975  1.1  mrg   gfc_init_se (&argse, NULL);
   2976  1.1  mrg   gfc_conv_expr_descriptor (&argse, arg->expr);
   2977  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   2978  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   2979  1.1  mrg 
   2980  1.1  mrg   desc = argse.expr;
   2981  1.1  mrg 
   2982  1.1  mrg   as = gfc_get_full_arrayspec_from_expr (arg->expr);
   2983  1.1  mrg 
   2984  1.1  mrg   if (INTEGER_CST_P (bound))
   2985  1.1  mrg     {
   2986  1.1  mrg       gcc_assert (op != GFC_ISYM_SHAPE);
   2987  1.1  mrg       if (((!as || as->type != AS_ASSUMED_RANK)
   2988  1.1  mrg 	   && wi::geu_p (wi::to_wide (bound),
   2989  1.1  mrg 			 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
   2990  1.1  mrg 	  || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
   2991  1.1  mrg 	gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
   2992  1.1  mrg 		   "dimension index",
   2993  1.1  mrg 		   (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
   2994  1.1  mrg 		   &expr->where);
   2995  1.1  mrg     }
   2996  1.1  mrg 
   2997  1.1  mrg   if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
   2998  1.1  mrg     {
   2999  1.1  mrg       if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
   3000  1.1  mrg         {
   3001  1.1  mrg           bound = gfc_evaluate_now (bound, &se->pre);
   3002  1.1  mrg           cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3003  1.1  mrg 				  bound, build_int_cst (TREE_TYPE (bound), 0));
   3004  1.1  mrg 	  if (as && as->type == AS_ASSUMED_RANK)
   3005  1.1  mrg 	    tmp = gfc_conv_descriptor_rank (desc);
   3006  1.1  mrg 	  else
   3007  1.1  mrg 	    tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
   3008  1.1  mrg           tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
   3009  1.1  mrg 				 bound, fold_convert(TREE_TYPE (bound), tmp));
   3010  1.1  mrg           cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   3011  1.1  mrg 				  logical_type_node, cond, tmp);
   3012  1.1  mrg           gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
   3013  1.1  mrg 				   gfc_msg_fault);
   3014  1.1  mrg         }
   3015  1.1  mrg     }
   3016  1.1  mrg 
   3017  1.1  mrg   /* Take care of the lbound shift for assumed-rank arrays that are
   3018  1.1  mrg      nonallocatable and nonpointers. Those have a lbound of 1.  */
   3019  1.1  mrg   assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
   3020  1.1  mrg 			&& ((arg->expr->ts.type != BT_CLASS
   3021  1.1  mrg 			     && !arg->expr->symtree->n.sym->attr.allocatable
   3022  1.1  mrg 			     && !arg->expr->symtree->n.sym->attr.pointer)
   3023  1.1  mrg 			    || (arg->expr->ts.type == BT_CLASS
   3024  1.1  mrg 			     && !CLASS_DATA (arg->expr)->attr.allocatable
   3025  1.1  mrg 			     && !CLASS_DATA (arg->expr)->attr.class_pointer));
   3026  1.1  mrg 
   3027  1.1  mrg   ubound = gfc_conv_descriptor_ubound_get (desc, bound);
   3028  1.1  mrg   lbound = gfc_conv_descriptor_lbound_get (desc, bound);
   3029  1.1  mrg   size = fold_build2_loc (input_location, MINUS_EXPR,
   3030  1.1  mrg 			  gfc_array_index_type, ubound, lbound);
   3031  1.1  mrg   size = fold_build2_loc (input_location, PLUS_EXPR,
   3032  1.1  mrg 			  gfc_array_index_type, size, gfc_index_one_node);
   3033  1.1  mrg 
   3034  1.1  mrg   /* 13.14.53: Result value for LBOUND
   3035  1.1  mrg 
   3036  1.1  mrg      Case (i): For an array section or for an array expression other than a
   3037  1.1  mrg                whole array or array structure component, LBOUND(ARRAY, DIM)
   3038  1.1  mrg                has the value 1.  For a whole array or array structure
   3039  1.1  mrg                component, LBOUND(ARRAY, DIM) has the value:
   3040  1.1  mrg                  (a) equal to the lower bound for subscript DIM of ARRAY if
   3041  1.1  mrg                      dimension DIM of ARRAY does not have extent zero
   3042  1.1  mrg                      or if ARRAY is an assumed-size array of rank DIM,
   3043  1.1  mrg               or (b) 1 otherwise.
   3044  1.1  mrg 
   3045  1.1  mrg      13.14.113: Result value for UBOUND
   3046  1.1  mrg 
   3047  1.1  mrg      Case (i): For an array section or for an array expression other than a
   3048  1.1  mrg                whole array or array structure component, UBOUND(ARRAY, DIM)
   3049  1.1  mrg                has the value equal to the number of elements in the given
   3050  1.1  mrg                dimension; otherwise, it has a value equal to the upper bound
   3051  1.1  mrg                for subscript DIM of ARRAY if dimension DIM of ARRAY does
   3052  1.1  mrg                not have size zero and has value zero if dimension DIM has
   3053  1.1  mrg                size zero.  */
   3054  1.1  mrg 
   3055  1.1  mrg   if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
   3056  1.1  mrg     se->expr = gfc_index_one_node;
   3057  1.1  mrg   else if (as)
   3058  1.1  mrg     {
   3059  1.1  mrg       if (op == GFC_ISYM_UBOUND)
   3060  1.1  mrg 	{
   3061  1.1  mrg 	  cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   3062  1.1  mrg 				  size, gfc_index_zero_node);
   3063  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR,
   3064  1.1  mrg 				      gfc_array_index_type, cond,
   3065  1.1  mrg 				      (assumed_rank_lb_one ? size : ubound),
   3066  1.1  mrg 				      gfc_index_zero_node);
   3067  1.1  mrg 	}
   3068  1.1  mrg       else if (op == GFC_ISYM_LBOUND)
   3069  1.1  mrg 	{
   3070  1.1  mrg 	  cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   3071  1.1  mrg 				  size, gfc_index_zero_node);
   3072  1.1  mrg 	  if (as->type == AS_ASSUMED_SIZE)
   3073  1.1  mrg 	    {
   3074  1.1  mrg 	      cond1 = fold_build2_loc (input_location, EQ_EXPR,
   3075  1.1  mrg 				       logical_type_node, bound,
   3076  1.1  mrg 				       build_int_cst (TREE_TYPE (bound),
   3077  1.1  mrg 						      arg->expr->rank - 1));
   3078  1.1  mrg 	      cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
   3079  1.1  mrg 				      logical_type_node, cond, cond1);
   3080  1.1  mrg 	    }
   3081  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR,
   3082  1.1  mrg 				      gfc_array_index_type, cond,
   3083  1.1  mrg 				      lbound, gfc_index_one_node);
   3084  1.1  mrg 	}
   3085  1.1  mrg       else if (op == GFC_ISYM_SHAPE)
   3086  1.1  mrg 	se->expr = fold_build2_loc (input_location, MAX_EXPR,
   3087  1.1  mrg 				    gfc_array_index_type, size,
   3088  1.1  mrg 				    gfc_index_zero_node);
   3089  1.1  mrg       else
   3090  1.1  mrg 	gcc_unreachable ();
   3091  1.1  mrg 
   3092  1.1  mrg       /* According to F2018 16.9.172, para 5, an assumed rank object,
   3093  1.1  mrg 	 argument associated with and assumed size array, has the ubound
   3094  1.1  mrg 	 of the final dimension set to -1 and UBOUND must return this.
   3095  1.1  mrg 	 Similarly for the SHAPE intrinsic.  */
   3096  1.1  mrg       if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
   3097  1.1  mrg 	{
   3098  1.1  mrg 	  tree minus_one = build_int_cst (gfc_array_index_type, -1);
   3099  1.1  mrg 	  tree rank = fold_convert (gfc_array_index_type,
   3100  1.1  mrg 				    gfc_conv_descriptor_rank (desc));
   3101  1.1  mrg 	  rank = fold_build2_loc (input_location, PLUS_EXPR,
   3102  1.1  mrg 				  gfc_array_index_type, rank, minus_one);
   3103  1.1  mrg 
   3104  1.1  mrg 	  /* Fix the expression to stop it from becoming even more
   3105  1.1  mrg 	     complicated.  */
   3106  1.1  mrg 	  se->expr = gfc_evaluate_now (se->expr, &se->pre);
   3107  1.1  mrg 
   3108  1.1  mrg 	  /* Descriptors for assumed-size arrays have ubound = -1
   3109  1.1  mrg 	     in the last dimension.  */
   3110  1.1  mrg 	  cond1 = fold_build2_loc (input_location, EQ_EXPR,
   3111  1.1  mrg 				   logical_type_node, ubound, minus_one);
   3112  1.1  mrg 	  cond = fold_build2_loc (input_location, EQ_EXPR,
   3113  1.1  mrg 				  logical_type_node, bound, rank);
   3114  1.1  mrg 	  cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   3115  1.1  mrg 				  logical_type_node, cond, cond1);
   3116  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR,
   3117  1.1  mrg 				      gfc_array_index_type, cond,
   3118  1.1  mrg 				      minus_one, se->expr);
   3119  1.1  mrg 	}
   3120  1.1  mrg     }
   3121  1.1  mrg   else   /* as is null; this is an old-fashioned 1-based array.  */
   3122  1.1  mrg     {
   3123  1.1  mrg       if (op != GFC_ISYM_LBOUND)
   3124  1.1  mrg         {
   3125  1.1  mrg 	  se->expr = fold_build2_loc (input_location, MAX_EXPR,
   3126  1.1  mrg 				      gfc_array_index_type, size,
   3127  1.1  mrg 				      gfc_index_zero_node);
   3128  1.1  mrg 	}
   3129  1.1  mrg       else
   3130  1.1  mrg 	se->expr = gfc_index_one_node;
   3131  1.1  mrg     }
   3132  1.1  mrg 
   3133  1.1  mrg 
   3134  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   3135  1.1  mrg   se->expr = convert (type, se->expr);
   3136  1.1  mrg }
   3137  1.1  mrg 
   3138  1.1  mrg 
   3139  1.1  mrg static void
   3140  1.1  mrg conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
   3141  1.1  mrg {
   3142  1.1  mrg   gfc_actual_arglist *arg;
   3143  1.1  mrg   gfc_actual_arglist *arg2;
   3144  1.1  mrg   gfc_se argse;
   3145  1.1  mrg   tree bound, resbound, resbound2, desc, cond, tmp;
   3146  1.1  mrg   tree type;
   3147  1.1  mrg   int corank;
   3148  1.1  mrg 
   3149  1.1  mrg   gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
   3150  1.1  mrg 	      || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
   3151  1.1  mrg 	      || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
   3152  1.1  mrg 
   3153  1.1  mrg   arg = expr->value.function.actual;
   3154  1.1  mrg   arg2 = arg->next;
   3155  1.1  mrg 
   3156  1.1  mrg   gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
   3157  1.1  mrg   corank = gfc_get_corank (arg->expr);
   3158  1.1  mrg 
   3159  1.1  mrg   gfc_init_se (&argse, NULL);
   3160  1.1  mrg   argse.want_coarray = 1;
   3161  1.1  mrg 
   3162  1.1  mrg   gfc_conv_expr_descriptor (&argse, arg->expr);
   3163  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   3164  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   3165  1.1  mrg   desc = argse.expr;
   3166  1.1  mrg 
   3167  1.1  mrg   if (se->ss)
   3168  1.1  mrg     {
   3169  1.1  mrg       /* Create an implicit second parameter from the loop variable.  */
   3170  1.1  mrg       gcc_assert (!arg2->expr);
   3171  1.1  mrg       gcc_assert (corank > 0);
   3172  1.1  mrg       gcc_assert (se->loop->dimen == 1);
   3173  1.1  mrg       gcc_assert (se->ss->info->expr == expr);
   3174  1.1  mrg 
   3175  1.1  mrg       bound = se->loop->loopvar[0];
   3176  1.1  mrg       bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
   3177  1.1  mrg 			       bound, gfc_rank_cst[arg->expr->rank]);
   3178  1.1  mrg       gfc_advance_se_ss_chain (se);
   3179  1.1  mrg     }
   3180  1.1  mrg   else
   3181  1.1  mrg     {
   3182  1.1  mrg       /* use the passed argument.  */
   3183  1.1  mrg       gcc_assert (arg2->expr);
   3184  1.1  mrg       gfc_init_se (&argse, NULL);
   3185  1.1  mrg       gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
   3186  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   3187  1.1  mrg       bound = argse.expr;
   3188  1.1  mrg 
   3189  1.1  mrg       if (INTEGER_CST_P (bound))
   3190  1.1  mrg 	{
   3191  1.1  mrg 	  if (wi::ltu_p (wi::to_wide (bound), 1)
   3192  1.1  mrg 	      || wi::gtu_p (wi::to_wide (bound),
   3193  1.1  mrg 			    GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
   3194  1.1  mrg 	    gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
   3195  1.1  mrg 		       "dimension index", expr->value.function.isym->name,
   3196  1.1  mrg 		       &expr->where);
   3197  1.1  mrg 	}
   3198  1.1  mrg       else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
   3199  1.1  mrg         {
   3200  1.1  mrg 	  bound = gfc_evaluate_now (bound, &se->pre);
   3201  1.1  mrg 	  cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3202  1.1  mrg 				  bound, build_int_cst (TREE_TYPE (bound), 1));
   3203  1.1  mrg 	  tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
   3204  1.1  mrg 	  tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   3205  1.1  mrg 				 bound, tmp);
   3206  1.1  mrg 	  cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   3207  1.1  mrg 				  logical_type_node, cond, tmp);
   3208  1.1  mrg 	  gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
   3209  1.1  mrg 				   gfc_msg_fault);
   3210  1.1  mrg 	}
   3211  1.1  mrg 
   3212  1.1  mrg 
   3213  1.1  mrg       /* Subtract 1 to get to zero based and add dimensions.  */
   3214  1.1  mrg       switch (arg->expr->rank)
   3215  1.1  mrg 	{
   3216  1.1  mrg 	case 0:
   3217  1.1  mrg 	  bound = fold_build2_loc (input_location, MINUS_EXPR,
   3218  1.1  mrg 				   gfc_array_index_type, bound,
   3219  1.1  mrg 				   gfc_index_one_node);
   3220  1.1  mrg 	case 1:
   3221  1.1  mrg 	  break;
   3222  1.1  mrg 	default:
   3223  1.1  mrg 	  bound = fold_build2_loc (input_location, PLUS_EXPR,
   3224  1.1  mrg 				   gfc_array_index_type, bound,
   3225  1.1  mrg 				   gfc_rank_cst[arg->expr->rank - 1]);
   3226  1.1  mrg 	}
   3227  1.1  mrg     }
   3228  1.1  mrg 
   3229  1.1  mrg   resbound = gfc_conv_descriptor_lbound_get (desc, bound);
   3230  1.1  mrg 
   3231  1.1  mrg   /* Handle UCOBOUND with special handling of the last codimension.  */
   3232  1.1  mrg   if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
   3233  1.1  mrg     {
   3234  1.1  mrg       /* Last codimension: For -fcoarray=single just return
   3235  1.1  mrg 	 the lcobound - otherwise add
   3236  1.1  mrg 	   ceiling (real (num_images ()) / real (size)) - 1
   3237  1.1  mrg 	 = (num_images () + size - 1) / size - 1
   3238  1.1  mrg 	 = (num_images - 1) / size(),
   3239  1.1  mrg          where size is the product of the extent of all but the last
   3240  1.1  mrg 	 codimension.  */
   3241  1.1  mrg 
   3242  1.1  mrg       if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
   3243  1.1  mrg 	{
   3244  1.1  mrg           tree cosize;
   3245  1.1  mrg 
   3246  1.1  mrg 	  cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
   3247  1.1  mrg 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
   3248  1.1  mrg 				     2, integer_zero_node,
   3249  1.1  mrg 				     build_int_cst (integer_type_node, -1));
   3250  1.1  mrg 	  tmp = fold_build2_loc (input_location, MINUS_EXPR,
   3251  1.1  mrg 				 gfc_array_index_type,
   3252  1.1  mrg 				 fold_convert (gfc_array_index_type, tmp),
   3253  1.1  mrg 				 build_int_cst (gfc_array_index_type, 1));
   3254  1.1  mrg 	  tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
   3255  1.1  mrg 				 gfc_array_index_type, tmp,
   3256  1.1  mrg 				 fold_convert (gfc_array_index_type, cosize));
   3257  1.1  mrg 	  resbound = fold_build2_loc (input_location, PLUS_EXPR,
   3258  1.1  mrg 				      gfc_array_index_type, resbound, tmp);
   3259  1.1  mrg 	}
   3260  1.1  mrg       else if (flag_coarray != GFC_FCOARRAY_SINGLE)
   3261  1.1  mrg 	{
   3262  1.1  mrg 	  /* ubound = lbound + num_images() - 1.  */
   3263  1.1  mrg 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
   3264  1.1  mrg 				     2, integer_zero_node,
   3265  1.1  mrg 				     build_int_cst (integer_type_node, -1));
   3266  1.1  mrg 	  tmp = fold_build2_loc (input_location, MINUS_EXPR,
   3267  1.1  mrg 				 gfc_array_index_type,
   3268  1.1  mrg 				 fold_convert (gfc_array_index_type, tmp),
   3269  1.1  mrg 				 build_int_cst (gfc_array_index_type, 1));
   3270  1.1  mrg 	  resbound = fold_build2_loc (input_location, PLUS_EXPR,
   3271  1.1  mrg 				      gfc_array_index_type, resbound, tmp);
   3272  1.1  mrg 	}
   3273  1.1  mrg 
   3274  1.1  mrg       if (corank > 1)
   3275  1.1  mrg 	{
   3276  1.1  mrg 	  cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   3277  1.1  mrg 				  bound,
   3278  1.1  mrg 				  build_int_cst (TREE_TYPE (bound),
   3279  1.1  mrg 						 arg->expr->rank + corank - 1));
   3280  1.1  mrg 
   3281  1.1  mrg 	  resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
   3282  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR,
   3283  1.1  mrg 				      gfc_array_index_type, cond,
   3284  1.1  mrg 				      resbound, resbound2);
   3285  1.1  mrg 	}
   3286  1.1  mrg       else
   3287  1.1  mrg 	se->expr = resbound;
   3288  1.1  mrg     }
   3289  1.1  mrg   else
   3290  1.1  mrg     se->expr = resbound;
   3291  1.1  mrg 
   3292  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   3293  1.1  mrg   se->expr = convert (type, se->expr);
   3294  1.1  mrg }
   3295  1.1  mrg 
   3296  1.1  mrg 
   3297  1.1  mrg static void
   3298  1.1  mrg conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
   3299  1.1  mrg {
   3300  1.1  mrg   gfc_actual_arglist *array_arg;
   3301  1.1  mrg   gfc_actual_arglist *dim_arg;
   3302  1.1  mrg   gfc_se argse;
   3303  1.1  mrg   tree desc, tmp;
   3304  1.1  mrg 
   3305  1.1  mrg   array_arg = expr->value.function.actual;
   3306  1.1  mrg   dim_arg = array_arg->next;
   3307  1.1  mrg 
   3308  1.1  mrg   gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
   3309  1.1  mrg 
   3310  1.1  mrg   gfc_init_se (&argse, NULL);
   3311  1.1  mrg   gfc_conv_expr_descriptor (&argse, array_arg->expr);
   3312  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   3313  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   3314  1.1  mrg   desc = argse.expr;
   3315  1.1  mrg 
   3316  1.1  mrg   gcc_assert (dim_arg->expr);
   3317  1.1  mrg   gfc_init_se (&argse, NULL);
   3318  1.1  mrg   gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
   3319  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   3320  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   3321  1.1  mrg 			 argse.expr, gfc_index_one_node);
   3322  1.1  mrg   se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
   3323  1.1  mrg }
   3324  1.1  mrg 
   3325  1.1  mrg static void
   3326  1.1  mrg gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
   3327  1.1  mrg {
   3328  1.1  mrg   tree arg, cabs;
   3329  1.1  mrg 
   3330  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   3331  1.1  mrg 
   3332  1.1  mrg   switch (expr->value.function.actual->expr->ts.type)
   3333  1.1  mrg     {
   3334  1.1  mrg     case BT_INTEGER:
   3335  1.1  mrg     case BT_REAL:
   3336  1.1  mrg       se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
   3337  1.1  mrg 				  arg);
   3338  1.1  mrg       break;
   3339  1.1  mrg 
   3340  1.1  mrg     case BT_COMPLEX:
   3341  1.1  mrg       cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
   3342  1.1  mrg       se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
   3343  1.1  mrg       break;
   3344  1.1  mrg 
   3345  1.1  mrg     default:
   3346  1.1  mrg       gcc_unreachable ();
   3347  1.1  mrg     }
   3348  1.1  mrg }
   3349  1.1  mrg 
   3350  1.1  mrg 
   3351  1.1  mrg /* Create a complex value from one or two real components.  */
   3352  1.1  mrg 
   3353  1.1  mrg static void
   3354  1.1  mrg gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
   3355  1.1  mrg {
   3356  1.1  mrg   tree real;
   3357  1.1  mrg   tree imag;
   3358  1.1  mrg   tree type;
   3359  1.1  mrg   tree *args;
   3360  1.1  mrg   unsigned int num_args;
   3361  1.1  mrg 
   3362  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   3363  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   3364  1.1  mrg 
   3365  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   3366  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   3367  1.1  mrg   real = convert (TREE_TYPE (type), args[0]);
   3368  1.1  mrg   if (both)
   3369  1.1  mrg     imag = convert (TREE_TYPE (type), args[1]);
   3370  1.1  mrg   else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
   3371  1.1  mrg     {
   3372  1.1  mrg       imag = fold_build1_loc (input_location, IMAGPART_EXPR,
   3373  1.1  mrg 			      TREE_TYPE (TREE_TYPE (args[0])), args[0]);
   3374  1.1  mrg       imag = convert (TREE_TYPE (type), imag);
   3375  1.1  mrg     }
   3376  1.1  mrg   else
   3377  1.1  mrg     imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
   3378  1.1  mrg 
   3379  1.1  mrg   se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
   3380  1.1  mrg }
   3381  1.1  mrg 
   3382  1.1  mrg 
   3383  1.1  mrg /* Remainder function MOD(A, P) = A - INT(A / P) * P
   3384  1.1  mrg                       MODULO(A, P) = A - FLOOR (A / P) * P
   3385  1.1  mrg 
   3386  1.1  mrg    The obvious algorithms above are numerically instable for large
   3387  1.1  mrg    arguments, hence these intrinsics are instead implemented via calls
   3388  1.1  mrg    to the fmod family of functions.  It is the responsibility of the
   3389  1.1  mrg    user to ensure that the second argument is non-zero.  */
   3390  1.1  mrg 
   3391  1.1  mrg static void
   3392  1.1  mrg gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
   3393  1.1  mrg {
   3394  1.1  mrg   tree type;
   3395  1.1  mrg   tree tmp;
   3396  1.1  mrg   tree test;
   3397  1.1  mrg   tree test2;
   3398  1.1  mrg   tree fmod;
   3399  1.1  mrg   tree zero;
   3400  1.1  mrg   tree args[2];
   3401  1.1  mrg 
   3402  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   3403  1.1  mrg 
   3404  1.1  mrg   switch (expr->ts.type)
   3405  1.1  mrg     {
   3406  1.1  mrg     case BT_INTEGER:
   3407  1.1  mrg       /* Integer case is easy, we've got a builtin op.  */
   3408  1.1  mrg       type = TREE_TYPE (args[0]);
   3409  1.1  mrg 
   3410  1.1  mrg       if (modulo)
   3411  1.1  mrg        se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
   3412  1.1  mrg 				   args[0], args[1]);
   3413  1.1  mrg       else
   3414  1.1  mrg        se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
   3415  1.1  mrg 				   args[0], args[1]);
   3416  1.1  mrg       break;
   3417  1.1  mrg 
   3418  1.1  mrg     case BT_REAL:
   3419  1.1  mrg       fmod = NULL_TREE;
   3420  1.1  mrg       /* Check if we have a builtin fmod.  */
   3421  1.1  mrg       fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
   3422  1.1  mrg 
   3423  1.1  mrg       /* The builtin should always be available.  */
   3424  1.1  mrg       gcc_assert (fmod != NULL_TREE);
   3425  1.1  mrg 
   3426  1.1  mrg       tmp = build_addr (fmod);
   3427  1.1  mrg       se->expr = build_call_array_loc (input_location,
   3428  1.1  mrg 				       TREE_TYPE (TREE_TYPE (fmod)),
   3429  1.1  mrg                                        tmp, 2, args);
   3430  1.1  mrg       if (modulo == 0)
   3431  1.1  mrg 	return;
   3432  1.1  mrg 
   3433  1.1  mrg       type = TREE_TYPE (args[0]);
   3434  1.1  mrg 
   3435  1.1  mrg       args[0] = gfc_evaluate_now (args[0], &se->pre);
   3436  1.1  mrg       args[1] = gfc_evaluate_now (args[1], &se->pre);
   3437  1.1  mrg 
   3438  1.1  mrg       /* Definition:
   3439  1.1  mrg 	 modulo = arg - floor (arg/arg2) * arg2
   3440  1.1  mrg 
   3441  1.1  mrg 	 In order to calculate the result accurately, we use the fmod
   3442  1.1  mrg 	 function as follows.
   3443  1.1  mrg 
   3444  1.1  mrg 	 res = fmod (arg, arg2);
   3445  1.1  mrg 	 if (res)
   3446  1.1  mrg 	   {
   3447  1.1  mrg 	     if ((arg < 0) xor (arg2 < 0))
   3448  1.1  mrg 	       res += arg2;
   3449  1.1  mrg 	   }
   3450  1.1  mrg 	 else
   3451  1.1  mrg 	   res = copysign (0., arg2);
   3452  1.1  mrg 
   3453  1.1  mrg 	 => As two nested ternary exprs:
   3454  1.1  mrg 
   3455  1.1  mrg 	 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
   3456  1.1  mrg 	       : copysign (0., arg2);
   3457  1.1  mrg 
   3458  1.1  mrg       */
   3459  1.1  mrg 
   3460  1.1  mrg       zero = gfc_build_const (type, integer_zero_node);
   3461  1.1  mrg       tmp = gfc_evaluate_now (se->expr, &se->pre);
   3462  1.1  mrg       if (!flag_signed_zeros)
   3463  1.1  mrg 	{
   3464  1.1  mrg 	  test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3465  1.1  mrg 				  args[0], zero);
   3466  1.1  mrg 	  test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3467  1.1  mrg 				   args[1], zero);
   3468  1.1  mrg 	  test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
   3469  1.1  mrg 				   logical_type_node, test, test2);
   3470  1.1  mrg 	  test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   3471  1.1  mrg 				  tmp, zero);
   3472  1.1  mrg 	  test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   3473  1.1  mrg 				  logical_type_node, test, test2);
   3474  1.1  mrg 	  test = gfc_evaluate_now (test, &se->pre);
   3475  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
   3476  1.1  mrg 				      fold_build2_loc (input_location,
   3477  1.1  mrg 						       PLUS_EXPR,
   3478  1.1  mrg 						       type, tmp, args[1]),
   3479  1.1  mrg 				      tmp);
   3480  1.1  mrg 	}
   3481  1.1  mrg       else
   3482  1.1  mrg 	{
   3483  1.1  mrg 	  tree expr1, copysign, cscall;
   3484  1.1  mrg 	  copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
   3485  1.1  mrg 						      expr->ts.kind);
   3486  1.1  mrg 	  test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3487  1.1  mrg 				  args[0], zero);
   3488  1.1  mrg 	  test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   3489  1.1  mrg 				   args[1], zero);
   3490  1.1  mrg 	  test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
   3491  1.1  mrg 				   logical_type_node, test, test2);
   3492  1.1  mrg 	  expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
   3493  1.1  mrg 				   fold_build2_loc (input_location,
   3494  1.1  mrg 						    PLUS_EXPR,
   3495  1.1  mrg 						    type, tmp, args[1]),
   3496  1.1  mrg 				   tmp);
   3497  1.1  mrg 	  test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   3498  1.1  mrg 				  tmp, zero);
   3499  1.1  mrg 	  cscall = build_call_expr_loc (input_location, copysign, 2, zero,
   3500  1.1  mrg 					args[1]);
   3501  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
   3502  1.1  mrg 				      expr1, cscall);
   3503  1.1  mrg 	}
   3504  1.1  mrg       return;
   3505  1.1  mrg 
   3506  1.1  mrg     default:
   3507  1.1  mrg       gcc_unreachable ();
   3508  1.1  mrg     }
   3509  1.1  mrg }
   3510  1.1  mrg 
   3511  1.1  mrg /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
   3512  1.1  mrg    DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
   3513  1.1  mrg    where the right shifts are logical (i.e. 0's are shifted in).
   3514  1.1  mrg    Because SHIFT_EXPR's want shifts strictly smaller than the integral
   3515  1.1  mrg    type width, we have to special-case both S == 0 and S == BITSIZE(J):
   3516  1.1  mrg      DSHIFTL(I,J,0) = I
   3517  1.1  mrg      DSHIFTL(I,J,BITSIZE) = J
   3518  1.1  mrg      DSHIFTR(I,J,0) = J
   3519  1.1  mrg      DSHIFTR(I,J,BITSIZE) = I.  */
   3520  1.1  mrg 
   3521  1.1  mrg static void
   3522  1.1  mrg gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
   3523  1.1  mrg {
   3524  1.1  mrg   tree type, utype, stype, arg1, arg2, shift, res, left, right;
   3525  1.1  mrg   tree args[3], cond, tmp;
   3526  1.1  mrg   int bitsize;
   3527  1.1  mrg 
   3528  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 3);
   3529  1.1  mrg 
   3530  1.1  mrg   gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
   3531  1.1  mrg   type = TREE_TYPE (args[0]);
   3532  1.1  mrg   bitsize = TYPE_PRECISION (type);
   3533  1.1  mrg   utype = unsigned_type_for (type);
   3534  1.1  mrg   stype = TREE_TYPE (args[2]);
   3535  1.1  mrg 
   3536  1.1  mrg   arg1 = gfc_evaluate_now (args[0], &se->pre);
   3537  1.1  mrg   arg2 = gfc_evaluate_now (args[1], &se->pre);
   3538  1.1  mrg   shift = gfc_evaluate_now (args[2], &se->pre);
   3539  1.1  mrg 
   3540  1.1  mrg   /* The generic case.  */
   3541  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
   3542  1.1  mrg 			 build_int_cst (stype, bitsize), shift);
   3543  1.1  mrg   left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   3544  1.1  mrg 			  arg1, dshiftl ? shift : tmp);
   3545  1.1  mrg 
   3546  1.1  mrg   right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
   3547  1.1  mrg 			   fold_convert (utype, arg2), dshiftl ? tmp : shift);
   3548  1.1  mrg   right = fold_convert (type, right);
   3549  1.1  mrg 
   3550  1.1  mrg   res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
   3551  1.1  mrg 
   3552  1.1  mrg   /* Special cases.  */
   3553  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
   3554  1.1  mrg 			  build_int_cst (stype, 0));
   3555  1.1  mrg   res = fold_build3_loc (input_location, COND_EXPR, type, cond,
   3556  1.1  mrg 			 dshiftl ? arg1 : arg2, res);
   3557  1.1  mrg 
   3558  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
   3559  1.1  mrg 			  build_int_cst (stype, bitsize));
   3560  1.1  mrg   res = fold_build3_loc (input_location, COND_EXPR, type, cond,
   3561  1.1  mrg 			 dshiftl ? arg2 : arg1, res);
   3562  1.1  mrg 
   3563  1.1  mrg   se->expr = res;
   3564  1.1  mrg }
   3565  1.1  mrg 
   3566  1.1  mrg 
   3567  1.1  mrg /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y.  */
   3568  1.1  mrg 
   3569  1.1  mrg static void
   3570  1.1  mrg gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
   3571  1.1  mrg {
   3572  1.1  mrg   tree val;
   3573  1.1  mrg   tree tmp;
   3574  1.1  mrg   tree type;
   3575  1.1  mrg   tree zero;
   3576  1.1  mrg   tree args[2];
   3577  1.1  mrg 
   3578  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   3579  1.1  mrg   type = TREE_TYPE (args[0]);
   3580  1.1  mrg 
   3581  1.1  mrg   val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
   3582  1.1  mrg   val = gfc_evaluate_now (val, &se->pre);
   3583  1.1  mrg 
   3584  1.1  mrg   zero = gfc_build_const (type, integer_zero_node);
   3585  1.1  mrg   tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
   3586  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
   3587  1.1  mrg }
   3588  1.1  mrg 
   3589  1.1  mrg 
   3590  1.1  mrg /* SIGN(A, B) is absolute value of A times sign of B.
   3591  1.1  mrg    The real value versions use library functions to ensure the correct
   3592  1.1  mrg    handling of negative zero.  Integer case implemented as:
   3593  1.1  mrg    SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
   3594  1.1  mrg   */
   3595  1.1  mrg 
   3596  1.1  mrg static void
   3597  1.1  mrg gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
   3598  1.1  mrg {
   3599  1.1  mrg   tree tmp;
   3600  1.1  mrg   tree type;
   3601  1.1  mrg   tree args[2];
   3602  1.1  mrg 
   3603  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   3604  1.1  mrg   if (expr->ts.type == BT_REAL)
   3605  1.1  mrg     {
   3606  1.1  mrg       tree abs;
   3607  1.1  mrg 
   3608  1.1  mrg       tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
   3609  1.1  mrg       abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
   3610  1.1  mrg 
   3611  1.1  mrg       /* We explicitly have to ignore the minus sign. We do so by using
   3612  1.1  mrg 	 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1).  */
   3613  1.1  mrg       if (!flag_sign_zero
   3614  1.1  mrg 	  && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
   3615  1.1  mrg 	{
   3616  1.1  mrg 	  tree cond, zero;
   3617  1.1  mrg 	  zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
   3618  1.1  mrg 	  cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   3619  1.1  mrg 				  args[1], zero);
   3620  1.1  mrg 	  se->expr = fold_build3_loc (input_location, COND_EXPR,
   3621  1.1  mrg 				  TREE_TYPE (args[0]), cond,
   3622  1.1  mrg 				  build_call_expr_loc (input_location, abs, 1,
   3623  1.1  mrg 						       args[0]),
   3624  1.1  mrg 				  build_call_expr_loc (input_location, tmp, 2,
   3625  1.1  mrg 						       args[0], args[1]));
   3626  1.1  mrg 	}
   3627  1.1  mrg       else
   3628  1.1  mrg         se->expr = build_call_expr_loc (input_location, tmp, 2,
   3629  1.1  mrg 					args[0], args[1]);
   3630  1.1  mrg       return;
   3631  1.1  mrg     }
   3632  1.1  mrg 
   3633  1.1  mrg   /* Having excluded floating point types, we know we are now dealing
   3634  1.1  mrg      with signed integer types.  */
   3635  1.1  mrg   type = TREE_TYPE (args[0]);
   3636  1.1  mrg 
   3637  1.1  mrg   /* Args[0] is used multiple times below.  */
   3638  1.1  mrg   args[0] = gfc_evaluate_now (args[0], &se->pre);
   3639  1.1  mrg 
   3640  1.1  mrg   /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
   3641  1.1  mrg      the signs of A and B are the same, and of all ones if they differ.  */
   3642  1.1  mrg   tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
   3643  1.1  mrg   tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
   3644  1.1  mrg 			 build_int_cst (type, TYPE_PRECISION (type) - 1));
   3645  1.1  mrg   tmp = gfc_evaluate_now (tmp, &se->pre);
   3646  1.1  mrg 
   3647  1.1  mrg   /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
   3648  1.1  mrg      is all ones (i.e. -1).  */
   3649  1.1  mrg   se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
   3650  1.1  mrg 			      fold_build2_loc (input_location, PLUS_EXPR,
   3651  1.1  mrg 					       type, args[0], tmp), tmp);
   3652  1.1  mrg }
   3653  1.1  mrg 
   3654  1.1  mrg 
   3655  1.1  mrg /* Test for the presence of an optional argument.  */
   3656  1.1  mrg 
   3657  1.1  mrg static void
   3658  1.1  mrg gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
   3659  1.1  mrg {
   3660  1.1  mrg   gfc_expr *arg;
   3661  1.1  mrg 
   3662  1.1  mrg   arg = expr->value.function.actual->expr;
   3663  1.1  mrg   gcc_assert (arg->expr_type == EXPR_VARIABLE);
   3664  1.1  mrg   se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
   3665  1.1  mrg   se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   3666  1.1  mrg }
   3667  1.1  mrg 
   3668  1.1  mrg 
   3669  1.1  mrg /* Calculate the double precision product of two single precision values.  */
   3670  1.1  mrg 
   3671  1.1  mrg static void
   3672  1.1  mrg gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
   3673  1.1  mrg {
   3674  1.1  mrg   tree type;
   3675  1.1  mrg   tree args[2];
   3676  1.1  mrg 
   3677  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   3678  1.1  mrg 
   3679  1.1  mrg   /* Convert the args to double precision before multiplying.  */
   3680  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   3681  1.1  mrg   args[0] = convert (type, args[0]);
   3682  1.1  mrg   args[1] = convert (type, args[1]);
   3683  1.1  mrg   se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
   3684  1.1  mrg 			      args[1]);
   3685  1.1  mrg }
   3686  1.1  mrg 
   3687  1.1  mrg 
   3688  1.1  mrg /* Return a length one character string containing an ascii character.  */
   3689  1.1  mrg 
   3690  1.1  mrg static void
   3691  1.1  mrg gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
   3692  1.1  mrg {
   3693  1.1  mrg   tree arg[2];
   3694  1.1  mrg   tree var;
   3695  1.1  mrg   tree type;
   3696  1.1  mrg   unsigned int num_args;
   3697  1.1  mrg 
   3698  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   3699  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
   3700  1.1  mrg 
   3701  1.1  mrg   type = gfc_get_char_type (expr->ts.kind);
   3702  1.1  mrg   var = gfc_create_var (type, "char");
   3703  1.1  mrg 
   3704  1.1  mrg   arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
   3705  1.1  mrg   gfc_add_modify (&se->pre, var, arg[0]);
   3706  1.1  mrg   se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
   3707  1.1  mrg   se->string_length = build_int_cst (gfc_charlen_type_node, 1);
   3708  1.1  mrg }
   3709  1.1  mrg 
   3710  1.1  mrg 
   3711  1.1  mrg static void
   3712  1.1  mrg gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
   3713  1.1  mrg {
   3714  1.1  mrg   tree var;
   3715  1.1  mrg   tree len;
   3716  1.1  mrg   tree tmp;
   3717  1.1  mrg   tree cond;
   3718  1.1  mrg   tree fndecl;
   3719  1.1  mrg   tree *args;
   3720  1.1  mrg   unsigned int num_args;
   3721  1.1  mrg 
   3722  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr) + 2;
   3723  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   3724  1.1  mrg 
   3725  1.1  mrg   var = gfc_create_var (pchar_type_node, "pstr");
   3726  1.1  mrg   len = gfc_create_var (gfc_charlen_type_node, "len");
   3727  1.1  mrg 
   3728  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
   3729  1.1  mrg   args[0] = gfc_build_addr_expr (NULL_TREE, var);
   3730  1.1  mrg   args[1] = gfc_build_addr_expr (NULL_TREE, len);
   3731  1.1  mrg 
   3732  1.1  mrg   fndecl = build_addr (gfor_fndecl_ctime);
   3733  1.1  mrg   tmp = build_call_array_loc (input_location,
   3734  1.1  mrg 			  TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
   3735  1.1  mrg 			  fndecl, num_args, args);
   3736  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   3737  1.1  mrg 
   3738  1.1  mrg   /* Free the temporary afterwards, if necessary.  */
   3739  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   3740  1.1  mrg 			  len, build_int_cst (TREE_TYPE (len), 0));
   3741  1.1  mrg   tmp = gfc_call_free (var);
   3742  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   3743  1.1  mrg   gfc_add_expr_to_block (&se->post, tmp);
   3744  1.1  mrg 
   3745  1.1  mrg   se->expr = var;
   3746  1.1  mrg   se->string_length = len;
   3747  1.1  mrg }
   3748  1.1  mrg 
   3749  1.1  mrg 
   3750  1.1  mrg static void
   3751  1.1  mrg gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
   3752  1.1  mrg {
   3753  1.1  mrg   tree var;
   3754  1.1  mrg   tree len;
   3755  1.1  mrg   tree tmp;
   3756  1.1  mrg   tree cond;
   3757  1.1  mrg   tree fndecl;
   3758  1.1  mrg   tree *args;
   3759  1.1  mrg   unsigned int num_args;
   3760  1.1  mrg 
   3761  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr) + 2;
   3762  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   3763  1.1  mrg 
   3764  1.1  mrg   var = gfc_create_var (pchar_type_node, "pstr");
   3765  1.1  mrg   len = gfc_create_var (gfc_charlen_type_node, "len");
   3766  1.1  mrg 
   3767  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
   3768  1.1  mrg   args[0] = gfc_build_addr_expr (NULL_TREE, var);
   3769  1.1  mrg   args[1] = gfc_build_addr_expr (NULL_TREE, len);
   3770  1.1  mrg 
   3771  1.1  mrg   fndecl = build_addr (gfor_fndecl_fdate);
   3772  1.1  mrg   tmp = build_call_array_loc (input_location,
   3773  1.1  mrg 			  TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
   3774  1.1  mrg 			  fndecl, num_args, args);
   3775  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   3776  1.1  mrg 
   3777  1.1  mrg   /* Free the temporary afterwards, if necessary.  */
   3778  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   3779  1.1  mrg 			  len, build_int_cst (TREE_TYPE (len), 0));
   3780  1.1  mrg   tmp = gfc_call_free (var);
   3781  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   3782  1.1  mrg   gfc_add_expr_to_block (&se->post, tmp);
   3783  1.1  mrg 
   3784  1.1  mrg   se->expr = var;
   3785  1.1  mrg   se->string_length = len;
   3786  1.1  mrg }
   3787  1.1  mrg 
   3788  1.1  mrg 
   3789  1.1  mrg /* Generate a direct call to free() for the FREE subroutine.  */
   3790  1.1  mrg 
   3791  1.1  mrg static tree
   3792  1.1  mrg conv_intrinsic_free (gfc_code *code)
   3793  1.1  mrg {
   3794  1.1  mrg   stmtblock_t block;
   3795  1.1  mrg   gfc_se argse;
   3796  1.1  mrg   tree arg, call;
   3797  1.1  mrg 
   3798  1.1  mrg   gfc_init_se (&argse, NULL);
   3799  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->expr);
   3800  1.1  mrg   arg = fold_convert (ptr_type_node, argse.expr);
   3801  1.1  mrg 
   3802  1.1  mrg   gfc_init_block (&block);
   3803  1.1  mrg   call = build_call_expr_loc (input_location,
   3804  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
   3805  1.1  mrg   gfc_add_expr_to_block (&block, call);
   3806  1.1  mrg   return gfc_finish_block (&block);
   3807  1.1  mrg }
   3808  1.1  mrg 
   3809  1.1  mrg 
   3810  1.1  mrg /* Call the RANDOM_INIT library subroutine with a hidden argument for
   3811  1.1  mrg    handling seeding on coarray images.  */
   3812  1.1  mrg 
   3813  1.1  mrg static tree
   3814  1.1  mrg conv_intrinsic_random_init (gfc_code *code)
   3815  1.1  mrg {
   3816  1.1  mrg   stmtblock_t block;
   3817  1.1  mrg   gfc_se se;
   3818  1.1  mrg   tree arg1, arg2, tmp;
   3819  1.1  mrg   /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL.  */
   3820  1.1  mrg   tree used_bool_type_node = flag_coarray == GFC_FCOARRAY_LIB
   3821  1.1  mrg 			     ? logical_type_node
   3822  1.1  mrg 			     : gfc_get_logical_type (4);
   3823  1.1  mrg 
   3824  1.1  mrg   /* Make the function call.  */
   3825  1.1  mrg   gfc_init_block (&block);
   3826  1.1  mrg   gfc_init_se (&se, NULL);
   3827  1.1  mrg 
   3828  1.1  mrg   /* Convert REPEATABLE to the desired LOGICAL entity.  */
   3829  1.1  mrg   gfc_conv_expr (&se, code->ext.actual->expr);
   3830  1.1  mrg   gfc_add_block_to_block (&block, &se.pre);
   3831  1.1  mrg   arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
   3832  1.1  mrg   gfc_add_block_to_block (&block, &se.post);
   3833  1.1  mrg 
   3834  1.1  mrg   /* Convert IMAGE_DISTINCT to the desired LOGICAL entity.  */
   3835  1.1  mrg   gfc_conv_expr (&se, code->ext.actual->next->expr);
   3836  1.1  mrg   gfc_add_block_to_block (&block, &se.pre);
   3837  1.1  mrg   arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
   3838  1.1  mrg   gfc_add_block_to_block (&block, &se.post);
   3839  1.1  mrg 
   3840  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   3841  1.1  mrg     {
   3842  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
   3843  1.1  mrg 				 2, arg1, arg2);
   3844  1.1  mrg     }
   3845  1.1  mrg   else
   3846  1.1  mrg     {
   3847  1.1  mrg       /* The ABI for libgfortran needs to be maintained, so a hidden
   3848  1.1  mrg 	 argument must be include if code is compiled with -fcoarray=single
   3849  1.1  mrg 	 or without the option.  Set to 0.  */
   3850  1.1  mrg       tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
   3851  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
   3852  1.1  mrg 				 3, arg1, arg2, arg3);
   3853  1.1  mrg     }
   3854  1.1  mrg 
   3855  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   3856  1.1  mrg 
   3857  1.1  mrg   return gfc_finish_block (&block);
   3858  1.1  mrg }
   3859  1.1  mrg 
   3860  1.1  mrg 
   3861  1.1  mrg /* Call the SYSTEM_CLOCK library functions, handling the type and kind
   3862  1.1  mrg    conversions.  */
   3863  1.1  mrg 
   3864  1.1  mrg static tree
   3865  1.1  mrg conv_intrinsic_system_clock (gfc_code *code)
   3866  1.1  mrg {
   3867  1.1  mrg   stmtblock_t block;
   3868  1.1  mrg   gfc_se count_se, count_rate_se, count_max_se;
   3869  1.1  mrg   tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
   3870  1.1  mrg   tree tmp;
   3871  1.1  mrg   int least;
   3872  1.1  mrg 
   3873  1.1  mrg   gfc_expr *count = code->ext.actual->expr;
   3874  1.1  mrg   gfc_expr *count_rate = code->ext.actual->next->expr;
   3875  1.1  mrg   gfc_expr *count_max = code->ext.actual->next->next->expr;
   3876  1.1  mrg 
   3877  1.1  mrg   /* Evaluate our arguments.  */
   3878  1.1  mrg   if (count)
   3879  1.1  mrg     {
   3880  1.1  mrg       gfc_init_se (&count_se, NULL);
   3881  1.1  mrg       gfc_conv_expr (&count_se, count);
   3882  1.1  mrg     }
   3883  1.1  mrg 
   3884  1.1  mrg   if (count_rate)
   3885  1.1  mrg     {
   3886  1.1  mrg       gfc_init_se (&count_rate_se, NULL);
   3887  1.1  mrg       gfc_conv_expr (&count_rate_se, count_rate);
   3888  1.1  mrg     }
   3889  1.1  mrg 
   3890  1.1  mrg   if (count_max)
   3891  1.1  mrg     {
   3892  1.1  mrg       gfc_init_se (&count_max_se, NULL);
   3893  1.1  mrg       gfc_conv_expr (&count_max_se, count_max);
   3894  1.1  mrg     }
   3895  1.1  mrg 
   3896  1.1  mrg   /* Find the smallest kind found of the arguments.  */
   3897  1.1  mrg   least = 16;
   3898  1.1  mrg   least = (count && count->ts.kind < least) ? count->ts.kind : least;
   3899  1.1  mrg   least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
   3900  1.1  mrg 						      : least;
   3901  1.1  mrg   least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
   3902  1.1  mrg 						    : least;
   3903  1.1  mrg 
   3904  1.1  mrg   /* Prepare temporary variables.  */
   3905  1.1  mrg 
   3906  1.1  mrg   if (count)
   3907  1.1  mrg     {
   3908  1.1  mrg       if (least >= 8)
   3909  1.1  mrg 	arg1 = gfc_create_var (gfc_get_int_type (8), "count");
   3910  1.1  mrg       else if (least == 4)
   3911  1.1  mrg 	arg1 = gfc_create_var (gfc_get_int_type (4), "count");
   3912  1.1  mrg       else if (count->ts.kind == 1)
   3913  1.1  mrg         arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
   3914  1.1  mrg 				     count->ts.kind);
   3915  1.1  mrg       else
   3916  1.1  mrg         arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
   3917  1.1  mrg 				     count->ts.kind);
   3918  1.1  mrg     }
   3919  1.1  mrg 
   3920  1.1  mrg   if (count_rate)
   3921  1.1  mrg     {
   3922  1.1  mrg       if (least >= 8)
   3923  1.1  mrg 	arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
   3924  1.1  mrg       else if (least == 4)
   3925  1.1  mrg 	arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
   3926  1.1  mrg       else
   3927  1.1  mrg         arg2 = integer_zero_node;
   3928  1.1  mrg     }
   3929  1.1  mrg 
   3930  1.1  mrg   if (count_max)
   3931  1.1  mrg     {
   3932  1.1  mrg       if (least >= 8)
   3933  1.1  mrg 	arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
   3934  1.1  mrg       else if (least == 4)
   3935  1.1  mrg 	arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
   3936  1.1  mrg       else
   3937  1.1  mrg         arg3 = integer_zero_node;
   3938  1.1  mrg     }
   3939  1.1  mrg 
   3940  1.1  mrg   /* Make the function call.  */
   3941  1.1  mrg   gfc_init_block (&block);
   3942  1.1  mrg 
   3943  1.1  mrg if (least <= 2)
   3944  1.1  mrg   {
   3945  1.1  mrg     if (least == 1)
   3946  1.1  mrg       {
   3947  1.1  mrg 	arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
   3948  1.1  mrg 	       : null_pointer_node;
   3949  1.1  mrg 	arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
   3950  1.1  mrg 	       : null_pointer_node;
   3951  1.1  mrg 	arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
   3952  1.1  mrg 	       : null_pointer_node;
   3953  1.1  mrg       }
   3954  1.1  mrg 
   3955  1.1  mrg     if (least == 2)
   3956  1.1  mrg       {
   3957  1.1  mrg 	arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
   3958  1.1  mrg 	       : null_pointer_node;
   3959  1.1  mrg 	arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
   3960  1.1  mrg 	       : null_pointer_node;
   3961  1.1  mrg 	arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
   3962  1.1  mrg 	       : null_pointer_node;
   3963  1.1  mrg       }
   3964  1.1  mrg   }
   3965  1.1  mrg else
   3966  1.1  mrg   {
   3967  1.1  mrg     if (least == 4)
   3968  1.1  mrg       {
   3969  1.1  mrg 	tmp = build_call_expr_loc (input_location,
   3970  1.1  mrg 		gfor_fndecl_system_clock4, 3,
   3971  1.1  mrg 		arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
   3972  1.1  mrg 		       : null_pointer_node,
   3973  1.1  mrg 		arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
   3974  1.1  mrg 		       : null_pointer_node,
   3975  1.1  mrg 		arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
   3976  1.1  mrg 		       : null_pointer_node);
   3977  1.1  mrg 	gfc_add_expr_to_block (&block, tmp);
   3978  1.1  mrg       }
   3979  1.1  mrg     /* Handle kind>=8, 10, or 16 arguments */
   3980  1.1  mrg     if (least >= 8)
   3981  1.1  mrg       {
   3982  1.1  mrg 	tmp = build_call_expr_loc (input_location,
   3983  1.1  mrg 		gfor_fndecl_system_clock8, 3,
   3984  1.1  mrg 		arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
   3985  1.1  mrg 		       : null_pointer_node,
   3986  1.1  mrg 		arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
   3987  1.1  mrg 		       : null_pointer_node,
   3988  1.1  mrg 		arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
   3989  1.1  mrg 		       : null_pointer_node);
   3990  1.1  mrg 	gfc_add_expr_to_block (&block, tmp);
   3991  1.1  mrg       }
   3992  1.1  mrg   }
   3993  1.1  mrg 
   3994  1.1  mrg   /* And store values back if needed.  */
   3995  1.1  mrg   if (arg1 && arg1 != count_se.expr)
   3996  1.1  mrg     gfc_add_modify (&block, count_se.expr,
   3997  1.1  mrg 		    fold_convert (TREE_TYPE (count_se.expr), arg1));
   3998  1.1  mrg   if (arg2 && arg2 != count_rate_se.expr)
   3999  1.1  mrg     gfc_add_modify (&block, count_rate_se.expr,
   4000  1.1  mrg 		    fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
   4001  1.1  mrg   if (arg3 && arg3 != count_max_se.expr)
   4002  1.1  mrg     gfc_add_modify (&block, count_max_se.expr,
   4003  1.1  mrg 		    fold_convert (TREE_TYPE (count_max_se.expr), arg3));
   4004  1.1  mrg 
   4005  1.1  mrg   return gfc_finish_block (&block);
   4006  1.1  mrg }
   4007  1.1  mrg 
   4008  1.1  mrg 
   4009  1.1  mrg /* Return a character string containing the tty name.  */
   4010  1.1  mrg 
   4011  1.1  mrg static void
   4012  1.1  mrg gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
   4013  1.1  mrg {
   4014  1.1  mrg   tree var;
   4015  1.1  mrg   tree len;
   4016  1.1  mrg   tree tmp;
   4017  1.1  mrg   tree cond;
   4018  1.1  mrg   tree fndecl;
   4019  1.1  mrg   tree *args;
   4020  1.1  mrg   unsigned int num_args;
   4021  1.1  mrg 
   4022  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr) + 2;
   4023  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   4024  1.1  mrg 
   4025  1.1  mrg   var = gfc_create_var (pchar_type_node, "pstr");
   4026  1.1  mrg   len = gfc_create_var (gfc_charlen_type_node, "len");
   4027  1.1  mrg 
   4028  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
   4029  1.1  mrg   args[0] = gfc_build_addr_expr (NULL_TREE, var);
   4030  1.1  mrg   args[1] = gfc_build_addr_expr (NULL_TREE, len);
   4031  1.1  mrg 
   4032  1.1  mrg   fndecl = build_addr (gfor_fndecl_ttynam);
   4033  1.1  mrg   tmp = build_call_array_loc (input_location,
   4034  1.1  mrg 			  TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
   4035  1.1  mrg 			  fndecl, num_args, args);
   4036  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   4037  1.1  mrg 
   4038  1.1  mrg   /* Free the temporary afterwards, if necessary.  */
   4039  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   4040  1.1  mrg 			  len, build_int_cst (TREE_TYPE (len), 0));
   4041  1.1  mrg   tmp = gfc_call_free (var);
   4042  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   4043  1.1  mrg   gfc_add_expr_to_block (&se->post, tmp);
   4044  1.1  mrg 
   4045  1.1  mrg   se->expr = var;
   4046  1.1  mrg   se->string_length = len;
   4047  1.1  mrg }
   4048  1.1  mrg 
   4049  1.1  mrg 
   4050  1.1  mrg /* Get the minimum/maximum value of all the parameters.
   4051  1.1  mrg     minmax (a1, a2, a3, ...)
   4052  1.1  mrg     {
   4053  1.1  mrg       mvar = a1;
   4054  1.1  mrg       mvar = COMP (mvar, a2)
   4055  1.1  mrg       mvar = COMP (mvar, a3)
   4056  1.1  mrg       ...
   4057  1.1  mrg       return mvar;
   4058  1.1  mrg     }
   4059  1.1  mrg     Where COMP is MIN/MAX_EXPR for integral types or when we don't
   4060  1.1  mrg     care about NaNs, or IFN_FMIN/MAX when the target has support for
   4061  1.1  mrg     fast NaN-honouring min/max.  When neither holds expand a sequence
   4062  1.1  mrg     of explicit comparisons.  */
   4063  1.1  mrg 
   4064  1.1  mrg /* TODO: Mismatching types can occur when specific names are used.
   4065  1.1  mrg    These should be handled during resolution.  */
   4066  1.1  mrg static void
   4067  1.1  mrg gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
   4068  1.1  mrg {
   4069  1.1  mrg   tree tmp;
   4070  1.1  mrg   tree mvar;
   4071  1.1  mrg   tree val;
   4072  1.1  mrg   tree *args;
   4073  1.1  mrg   tree type;
   4074  1.1  mrg   tree argtype;
   4075  1.1  mrg   gfc_actual_arglist *argexpr;
   4076  1.1  mrg   unsigned int i, nargs;
   4077  1.1  mrg 
   4078  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
   4079  1.1  mrg   args = XALLOCAVEC (tree, nargs);
   4080  1.1  mrg 
   4081  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, nargs);
   4082  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4083  1.1  mrg 
   4084  1.1  mrg   /* Only evaluate the argument once.  */
   4085  1.1  mrg   if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
   4086  1.1  mrg     args[0] = gfc_evaluate_now (args[0], &se->pre);
   4087  1.1  mrg 
   4088  1.1  mrg   /* Determine suitable type of temporary, as a GNU extension allows
   4089  1.1  mrg      different argument kinds.  */
   4090  1.1  mrg   argtype = TREE_TYPE (args[0]);
   4091  1.1  mrg   argexpr = expr->value.function.actual;
   4092  1.1  mrg   for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
   4093  1.1  mrg     {
   4094  1.1  mrg       tree tmptype = TREE_TYPE (args[i]);
   4095  1.1  mrg       if (TYPE_PRECISION (tmptype) > TYPE_PRECISION (argtype))
   4096  1.1  mrg 	argtype = tmptype;
   4097  1.1  mrg     }
   4098  1.1  mrg   mvar = gfc_create_var (argtype, "M");
   4099  1.1  mrg   gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
   4100  1.1  mrg 
   4101  1.1  mrg   argexpr = expr->value.function.actual;
   4102  1.1  mrg   for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
   4103  1.1  mrg     {
   4104  1.1  mrg       tree cond = NULL_TREE;
   4105  1.1  mrg       val = args[i];
   4106  1.1  mrg 
   4107  1.1  mrg       /* Handle absent optional arguments by ignoring the comparison.  */
   4108  1.1  mrg       if (argexpr->expr->expr_type == EXPR_VARIABLE
   4109  1.1  mrg 	  && argexpr->expr->symtree->n.sym->attr.optional
   4110  1.1  mrg 	  && TREE_CODE (val) == INDIRECT_REF)
   4111  1.1  mrg 	{
   4112  1.1  mrg 	  cond = fold_build2_loc (input_location,
   4113  1.1  mrg 				NE_EXPR, logical_type_node,
   4114  1.1  mrg 				TREE_OPERAND (val, 0),
   4115  1.1  mrg 			build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
   4116  1.1  mrg 	}
   4117  1.1  mrg       else if (!VAR_P (val) && !TREE_CONSTANT (val))
   4118  1.1  mrg 	/* Only evaluate the argument once.  */
   4119  1.1  mrg 	val = gfc_evaluate_now (val, &se->pre);
   4120  1.1  mrg 
   4121  1.1  mrg       tree calc;
   4122  1.1  mrg       /* For floating point types, the question is what MAX(a, NaN) or
   4123  1.1  mrg 	 MIN(a, NaN) should return (where "a" is a normal number).
   4124  1.1  mrg 	 There are valid usecase for returning either one, but the
   4125  1.1  mrg 	 Fortran standard doesn't specify which one should be chosen.
   4126  1.1  mrg 	 Also, there is no consensus among other tested compilers.  In
   4127  1.1  mrg 	 short, it's a mess.  So lets just do whatever is fastest.  */
   4128  1.1  mrg       tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
   4129  1.1  mrg       calc = fold_build2_loc (input_location, code, argtype,
   4130  1.1  mrg 			      convert (argtype, val), mvar);
   4131  1.1  mrg       tmp = build2_v (MODIFY_EXPR, mvar, calc);
   4132  1.1  mrg 
   4133  1.1  mrg       if (cond != NULL_TREE)
   4134  1.1  mrg 	tmp = build3_v (COND_EXPR, cond, tmp,
   4135  1.1  mrg 			build_empty_stmt (input_location));
   4136  1.1  mrg       gfc_add_expr_to_block (&se->pre, tmp);
   4137  1.1  mrg     }
   4138  1.1  mrg   se->expr = convert (type, mvar);
   4139  1.1  mrg }
   4140  1.1  mrg 
   4141  1.1  mrg 
   4142  1.1  mrg /* Generate library calls for MIN and MAX intrinsics for character
   4143  1.1  mrg    variables.  */
   4144  1.1  mrg static void
   4145  1.1  mrg gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
   4146  1.1  mrg {
   4147  1.1  mrg   tree *args;
   4148  1.1  mrg   tree var, len, fndecl, tmp, cond, function;
   4149  1.1  mrg   unsigned int nargs;
   4150  1.1  mrg 
   4151  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
   4152  1.1  mrg   args = XALLOCAVEC (tree, nargs + 4);
   4153  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
   4154  1.1  mrg 
   4155  1.1  mrg   /* Create the result variables.  */
   4156  1.1  mrg   len = gfc_create_var (gfc_charlen_type_node, "len");
   4157  1.1  mrg   args[0] = gfc_build_addr_expr (NULL_TREE, len);
   4158  1.1  mrg   var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
   4159  1.1  mrg   args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
   4160  1.1  mrg   args[2] = build_int_cst (integer_type_node, op);
   4161  1.1  mrg   args[3] = build_int_cst (integer_type_node, nargs / 2);
   4162  1.1  mrg 
   4163  1.1  mrg   if (expr->ts.kind == 1)
   4164  1.1  mrg     function = gfor_fndecl_string_minmax;
   4165  1.1  mrg   else if (expr->ts.kind == 4)
   4166  1.1  mrg     function = gfor_fndecl_string_minmax_char4;
   4167  1.1  mrg   else
   4168  1.1  mrg     gcc_unreachable ();
   4169  1.1  mrg 
   4170  1.1  mrg   /* Make the function call.  */
   4171  1.1  mrg   fndecl = build_addr (function);
   4172  1.1  mrg   tmp = build_call_array_loc (input_location,
   4173  1.1  mrg 			  TREE_TYPE (TREE_TYPE (function)), fndecl,
   4174  1.1  mrg 			  nargs + 4, args);
   4175  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   4176  1.1  mrg 
   4177  1.1  mrg   /* Free the temporary afterwards, if necessary.  */
   4178  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   4179  1.1  mrg 			  len, build_int_cst (TREE_TYPE (len), 0));
   4180  1.1  mrg   tmp = gfc_call_free (var);
   4181  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   4182  1.1  mrg   gfc_add_expr_to_block (&se->post, tmp);
   4183  1.1  mrg 
   4184  1.1  mrg   se->expr = var;
   4185  1.1  mrg   se->string_length = len;
   4186  1.1  mrg }
   4187  1.1  mrg 
   4188  1.1  mrg 
   4189  1.1  mrg /* Create a symbol node for this intrinsic.  The symbol from the frontend
   4190  1.1  mrg    has the generic name.  */
   4191  1.1  mrg 
   4192  1.1  mrg static gfc_symbol *
   4193  1.1  mrg gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
   4194  1.1  mrg {
   4195  1.1  mrg   gfc_symbol *sym;
   4196  1.1  mrg 
   4197  1.1  mrg   /* TODO: Add symbols for intrinsic function to the global namespace.  */
   4198  1.1  mrg   gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
   4199  1.1  mrg   sym = gfc_new_symbol (expr->value.function.name, NULL);
   4200  1.1  mrg 
   4201  1.1  mrg   sym->ts = expr->ts;
   4202  1.1  mrg   sym->attr.external = 1;
   4203  1.1  mrg   sym->attr.function = 1;
   4204  1.1  mrg   sym->attr.always_explicit = 1;
   4205  1.1  mrg   sym->attr.proc = PROC_INTRINSIC;
   4206  1.1  mrg   sym->attr.flavor = FL_PROCEDURE;
   4207  1.1  mrg   sym->result = sym;
   4208  1.1  mrg   if (expr->rank > 0)
   4209  1.1  mrg     {
   4210  1.1  mrg       sym->attr.dimension = 1;
   4211  1.1  mrg       sym->as = gfc_get_array_spec ();
   4212  1.1  mrg       sym->as->type = AS_ASSUMED_SHAPE;
   4213  1.1  mrg       sym->as->rank = expr->rank;
   4214  1.1  mrg     }
   4215  1.1  mrg 
   4216  1.1  mrg   gfc_copy_formal_args_intr (sym, expr->value.function.isym,
   4217  1.1  mrg 			     ignore_optional ? expr->value.function.actual
   4218  1.1  mrg 					     : NULL);
   4219  1.1  mrg 
   4220  1.1  mrg   return sym;
   4221  1.1  mrg }
   4222  1.1  mrg 
   4223  1.1  mrg /* Remove empty actual arguments.  */
   4224  1.1  mrg 
   4225  1.1  mrg static void
   4226  1.1  mrg remove_empty_actual_arguments (gfc_actual_arglist **ap)
   4227  1.1  mrg {
   4228  1.1  mrg   while (*ap)
   4229  1.1  mrg     {
   4230  1.1  mrg       if ((*ap)->expr == NULL)
   4231  1.1  mrg 	{
   4232  1.1  mrg 	  gfc_actual_arglist *r = *ap;
   4233  1.1  mrg 	  *ap = r->next;
   4234  1.1  mrg 	  r->next = NULL;
   4235  1.1  mrg 	  gfc_free_actual_arglist (r);
   4236  1.1  mrg 	}
   4237  1.1  mrg       else
   4238  1.1  mrg 	ap = &((*ap)->next);
   4239  1.1  mrg     }
   4240  1.1  mrg }
   4241  1.1  mrg 
   4242  1.1  mrg #define MAX_SPEC_ARG 12
   4243  1.1  mrg 
   4244  1.1  mrg /* Make up an fn spec that's right for intrinsic functions that we
   4245  1.1  mrg    want to call.  */
   4246  1.1  mrg 
   4247  1.1  mrg static char *
   4248  1.1  mrg intrinsic_fnspec (gfc_expr *expr)
   4249  1.1  mrg {
   4250  1.1  mrg   static char fnspec_buf[MAX_SPEC_ARG*2+1];
   4251  1.1  mrg   char *fp;
   4252  1.1  mrg   int i;
   4253  1.1  mrg   int num_char_args;
   4254  1.1  mrg 
   4255  1.1  mrg #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
   4256  1.1  mrg 
   4257  1.1  mrg   /* Set the fndecl.  */
   4258  1.1  mrg   fp = fnspec_buf;
   4259  1.1  mrg   /* Function return value.  FIXME: Check if the second letter could
   4260  1.1  mrg      be something other than a space, for further optimization.  */
   4261  1.1  mrg   ADD_CHAR ('.');
   4262  1.1  mrg   if (expr->rank == 0)
   4263  1.1  mrg     {
   4264  1.1  mrg       if (expr->ts.type == BT_CHARACTER)
   4265  1.1  mrg 	{
   4266  1.1  mrg 	  ADD_CHAR ('w');  /* Address of character.  */
   4267  1.1  mrg 	  ADD_CHAR ('.');  /* Length of character.  */
   4268  1.1  mrg 	}
   4269  1.1  mrg     }
   4270  1.1  mrg   else
   4271  1.1  mrg     ADD_CHAR ('w');  /* Return value is a descriptor.  */
   4272  1.1  mrg 
   4273  1.1  mrg   num_char_args = 0;
   4274  1.1  mrg   for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
   4275  1.1  mrg     {
   4276  1.1  mrg       if (a->expr == NULL)
   4277  1.1  mrg 	continue;
   4278  1.1  mrg 
   4279  1.1  mrg       if (a->name && strcmp (a->name,"%VAL") == 0)
   4280  1.1  mrg 	ADD_CHAR ('.');
   4281  1.1  mrg       else
   4282  1.1  mrg 	{
   4283  1.1  mrg 	  if (a->expr->rank > 0)
   4284  1.1  mrg 	    ADD_CHAR ('r');
   4285  1.1  mrg 	  else
   4286  1.1  mrg 	    ADD_CHAR ('R');
   4287  1.1  mrg 	}
   4288  1.1  mrg       num_char_args += a->expr->ts.type == BT_CHARACTER;
   4289  1.1  mrg       gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
   4290  1.1  mrg     }
   4291  1.1  mrg 
   4292  1.1  mrg   for (i = 0; i < num_char_args; i++)
   4293  1.1  mrg     ADD_CHAR ('.');
   4294  1.1  mrg 
   4295  1.1  mrg   *fp = '\0';
   4296  1.1  mrg   return fnspec_buf;
   4297  1.1  mrg }
   4298  1.1  mrg 
   4299  1.1  mrg #undef MAX_SPEC_ARG
   4300  1.1  mrg #undef ADD_CHAR
   4301  1.1  mrg 
   4302  1.1  mrg /* Generate the right symbol for the specific intrinsic function and
   4303  1.1  mrg  modify the expr accordingly.  This assumes that absent optional
   4304  1.1  mrg  arguments should be removed.  */
   4305  1.1  mrg 
   4306  1.1  mrg gfc_symbol *
   4307  1.1  mrg specific_intrinsic_symbol (gfc_expr *expr)
   4308  1.1  mrg {
   4309  1.1  mrg   gfc_symbol *sym;
   4310  1.1  mrg 
   4311  1.1  mrg   sym = gfc_find_intrinsic_symbol (expr);
   4312  1.1  mrg   if (sym == NULL)
   4313  1.1  mrg     {
   4314  1.1  mrg       sym = gfc_get_intrinsic_function_symbol (expr);
   4315  1.1  mrg       sym->ts = expr->ts;
   4316  1.1  mrg       if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
   4317  1.1  mrg 	sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
   4318  1.1  mrg 
   4319  1.1  mrg       gfc_copy_formal_args_intr (sym, expr->value.function.isym,
   4320  1.1  mrg 				 expr->value.function.actual, true);
   4321  1.1  mrg       sym->backend_decl
   4322  1.1  mrg 	= gfc_get_extern_function_decl (sym, expr->value.function.actual,
   4323  1.1  mrg 					intrinsic_fnspec (expr));
   4324  1.1  mrg     }
   4325  1.1  mrg 
   4326  1.1  mrg   remove_empty_actual_arguments (&(expr->value.function.actual));
   4327  1.1  mrg 
   4328  1.1  mrg   return sym;
   4329  1.1  mrg }
   4330  1.1  mrg 
   4331  1.1  mrg /* Generate a call to an external intrinsic function.  FIXME: So far,
   4332  1.1  mrg    this only works for functions which are called with well-defined
   4333  1.1  mrg    types; CSHIFT and friends will come later.  */
   4334  1.1  mrg 
   4335  1.1  mrg static void
   4336  1.1  mrg gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
   4337  1.1  mrg {
   4338  1.1  mrg   gfc_symbol *sym;
   4339  1.1  mrg   vec<tree, va_gc> *append_args;
   4340  1.1  mrg   bool specific_symbol;
   4341  1.1  mrg 
   4342  1.1  mrg   gcc_assert (!se->ss || se->ss->info->expr == expr);
   4343  1.1  mrg 
   4344  1.1  mrg   if (se->ss)
   4345  1.1  mrg     gcc_assert (expr->rank > 0);
   4346  1.1  mrg   else
   4347  1.1  mrg     gcc_assert (expr->rank == 0);
   4348  1.1  mrg 
   4349  1.1  mrg   switch (expr->value.function.isym->id)
   4350  1.1  mrg     {
   4351  1.1  mrg     case GFC_ISYM_ANY:
   4352  1.1  mrg     case GFC_ISYM_ALL:
   4353  1.1  mrg     case GFC_ISYM_FINDLOC:
   4354  1.1  mrg     case GFC_ISYM_MAXLOC:
   4355  1.1  mrg     case GFC_ISYM_MINLOC:
   4356  1.1  mrg     case GFC_ISYM_MAXVAL:
   4357  1.1  mrg     case GFC_ISYM_MINVAL:
   4358  1.1  mrg     case GFC_ISYM_NORM2:
   4359  1.1  mrg     case GFC_ISYM_PRODUCT:
   4360  1.1  mrg     case GFC_ISYM_SUM:
   4361  1.1  mrg       specific_symbol = true;
   4362  1.1  mrg       break;
   4363  1.1  mrg     default:
   4364  1.1  mrg       specific_symbol = false;
   4365  1.1  mrg     }
   4366  1.1  mrg 
   4367  1.1  mrg   if (specific_symbol)
   4368  1.1  mrg     {
   4369  1.1  mrg       /* Need to copy here because specific_intrinsic_symbol modifies
   4370  1.1  mrg 	 expr to omit the absent optional arguments.  */
   4371  1.1  mrg       expr = gfc_copy_expr (expr);
   4372  1.1  mrg       sym = specific_intrinsic_symbol (expr);
   4373  1.1  mrg     }
   4374  1.1  mrg   else
   4375  1.1  mrg     sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
   4376  1.1  mrg 
   4377  1.1  mrg   /* Calls to libgfortran_matmul need to be appended special arguments,
   4378  1.1  mrg      to be able to call the BLAS ?gemm functions if required and possible.  */
   4379  1.1  mrg   append_args = NULL;
   4380  1.1  mrg   if (expr->value.function.isym->id == GFC_ISYM_MATMUL
   4381  1.1  mrg       && !expr->external_blas
   4382  1.1  mrg       && sym->ts.type != BT_LOGICAL)
   4383  1.1  mrg     {
   4384  1.1  mrg       tree cint = gfc_get_int_type (gfc_c_int_kind);
   4385  1.1  mrg 
   4386  1.1  mrg       if (flag_external_blas
   4387  1.1  mrg 	  && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
   4388  1.1  mrg 	  && (sym->ts.kind == 4 || sym->ts.kind == 8))
   4389  1.1  mrg 	{
   4390  1.1  mrg 	  tree gemm_fndecl;
   4391  1.1  mrg 
   4392  1.1  mrg 	  if (sym->ts.type == BT_REAL)
   4393  1.1  mrg 	    {
   4394  1.1  mrg 	      if (sym->ts.kind == 4)
   4395  1.1  mrg 		gemm_fndecl = gfor_fndecl_sgemm;
   4396  1.1  mrg 	      else
   4397  1.1  mrg 		gemm_fndecl = gfor_fndecl_dgemm;
   4398  1.1  mrg 	    }
   4399  1.1  mrg 	  else
   4400  1.1  mrg 	    {
   4401  1.1  mrg 	      if (sym->ts.kind == 4)
   4402  1.1  mrg 		gemm_fndecl = gfor_fndecl_cgemm;
   4403  1.1  mrg 	      else
   4404  1.1  mrg 		gemm_fndecl = gfor_fndecl_zgemm;
   4405  1.1  mrg 	    }
   4406  1.1  mrg 
   4407  1.1  mrg 	  vec_alloc (append_args, 3);
   4408  1.1  mrg 	  append_args->quick_push (build_int_cst (cint, 1));
   4409  1.1  mrg 	  append_args->quick_push (build_int_cst (cint,
   4410  1.1  mrg 						  flag_blas_matmul_limit));
   4411  1.1  mrg 	  append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
   4412  1.1  mrg 							gemm_fndecl));
   4413  1.1  mrg 	}
   4414  1.1  mrg       else
   4415  1.1  mrg 	{
   4416  1.1  mrg 	  vec_alloc (append_args, 3);
   4417  1.1  mrg 	  append_args->quick_push (build_int_cst (cint, 0));
   4418  1.1  mrg 	  append_args->quick_push (build_int_cst (cint, 0));
   4419  1.1  mrg 	  append_args->quick_push (null_pointer_node);
   4420  1.1  mrg 	}
   4421  1.1  mrg     }
   4422  1.1  mrg 
   4423  1.1  mrg   gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
   4424  1.1  mrg 			  append_args);
   4425  1.1  mrg 
   4426  1.1  mrg   if (specific_symbol)
   4427  1.1  mrg     gfc_free_expr (expr);
   4428  1.1  mrg   else
   4429  1.1  mrg     gfc_free_symbol (sym);
   4430  1.1  mrg }
   4431  1.1  mrg 
   4432  1.1  mrg /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
   4433  1.1  mrg    Implemented as
   4434  1.1  mrg     any(a)
   4435  1.1  mrg     {
   4436  1.1  mrg       forall (i=...)
   4437  1.1  mrg         if (a[i] != 0)
   4438  1.1  mrg           return 1
   4439  1.1  mrg       end forall
   4440  1.1  mrg       return 0
   4441  1.1  mrg     }
   4442  1.1  mrg     all(a)
   4443  1.1  mrg     {
   4444  1.1  mrg       forall (i=...)
   4445  1.1  mrg         if (a[i] == 0)
   4446  1.1  mrg           return 0
   4447  1.1  mrg       end forall
   4448  1.1  mrg       return 1
   4449  1.1  mrg     }
   4450  1.1  mrg  */
   4451  1.1  mrg static void
   4452  1.1  mrg gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
   4453  1.1  mrg {
   4454  1.1  mrg   tree resvar;
   4455  1.1  mrg   stmtblock_t block;
   4456  1.1  mrg   stmtblock_t body;
   4457  1.1  mrg   tree type;
   4458  1.1  mrg   tree tmp;
   4459  1.1  mrg   tree found;
   4460  1.1  mrg   gfc_loopinfo loop;
   4461  1.1  mrg   gfc_actual_arglist *actual;
   4462  1.1  mrg   gfc_ss *arrayss;
   4463  1.1  mrg   gfc_se arrayse;
   4464  1.1  mrg   tree exit_label;
   4465  1.1  mrg 
   4466  1.1  mrg   if (se->ss)
   4467  1.1  mrg     {
   4468  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   4469  1.1  mrg       return;
   4470  1.1  mrg     }
   4471  1.1  mrg 
   4472  1.1  mrg   actual = expr->value.function.actual;
   4473  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4474  1.1  mrg   /* Initialize the result.  */
   4475  1.1  mrg   resvar = gfc_create_var (type, "test");
   4476  1.1  mrg   if (op == EQ_EXPR)
   4477  1.1  mrg     tmp = convert (type, boolean_true_node);
   4478  1.1  mrg   else
   4479  1.1  mrg     tmp = convert (type, boolean_false_node);
   4480  1.1  mrg   gfc_add_modify (&se->pre, resvar, tmp);
   4481  1.1  mrg 
   4482  1.1  mrg   /* Walk the arguments.  */
   4483  1.1  mrg   arrayss = gfc_walk_expr (actual->expr);
   4484  1.1  mrg   gcc_assert (arrayss != gfc_ss_terminator);
   4485  1.1  mrg 
   4486  1.1  mrg   /* Initialize the scalarizer.  */
   4487  1.1  mrg   gfc_init_loopinfo (&loop);
   4488  1.1  mrg   exit_label = gfc_build_label_decl (NULL_TREE);
   4489  1.1  mrg   TREE_USED (exit_label) = 1;
   4490  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss);
   4491  1.1  mrg 
   4492  1.1  mrg   /* Initialize the loop.  */
   4493  1.1  mrg   gfc_conv_ss_startstride (&loop);
   4494  1.1  mrg   gfc_conv_loop_setup (&loop, &expr->where);
   4495  1.1  mrg 
   4496  1.1  mrg   gfc_mark_ss_chain_used (arrayss, 1);
   4497  1.1  mrg   /* Generate the loop body.  */
   4498  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   4499  1.1  mrg 
   4500  1.1  mrg   /* If the condition matches then set the return value.  */
   4501  1.1  mrg   gfc_start_block (&block);
   4502  1.1  mrg   if (op == EQ_EXPR)
   4503  1.1  mrg     tmp = convert (type, boolean_false_node);
   4504  1.1  mrg   else
   4505  1.1  mrg     tmp = convert (type, boolean_true_node);
   4506  1.1  mrg   gfc_add_modify (&block, resvar, tmp);
   4507  1.1  mrg 
   4508  1.1  mrg   /* And break out of the loop.  */
   4509  1.1  mrg   tmp = build1_v (GOTO_EXPR, exit_label);
   4510  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   4511  1.1  mrg 
   4512  1.1  mrg   found = gfc_finish_block (&block);
   4513  1.1  mrg 
   4514  1.1  mrg   /* Check this element.  */
   4515  1.1  mrg   gfc_init_se (&arrayse, NULL);
   4516  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   4517  1.1  mrg   arrayse.ss = arrayss;
   4518  1.1  mrg   gfc_conv_expr_val (&arrayse, actual->expr);
   4519  1.1  mrg 
   4520  1.1  mrg   gfc_add_block_to_block (&body, &arrayse.pre);
   4521  1.1  mrg   tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
   4522  1.1  mrg 			 build_int_cst (TREE_TYPE (arrayse.expr), 0));
   4523  1.1  mrg   tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
   4524  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   4525  1.1  mrg   gfc_add_block_to_block (&body, &arrayse.post);
   4526  1.1  mrg 
   4527  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   4528  1.1  mrg 
   4529  1.1  mrg   /* Add the exit label.  */
   4530  1.1  mrg   tmp = build1_v (LABEL_EXPR, exit_label);
   4531  1.1  mrg   gfc_add_expr_to_block (&loop.pre, tmp);
   4532  1.1  mrg 
   4533  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.pre);
   4534  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.post);
   4535  1.1  mrg   gfc_cleanup_loop (&loop);
   4536  1.1  mrg 
   4537  1.1  mrg   se->expr = resvar;
   4538  1.1  mrg }
   4539  1.1  mrg 
   4540  1.1  mrg 
   4541  1.1  mrg /* Generate the constant 180 / pi, which is used in the conversion
   4542  1.1  mrg    of acosd(), asind(), atand(), atan2d().  */
   4543  1.1  mrg 
   4544  1.1  mrg static tree
   4545  1.1  mrg rad2deg (int kind)
   4546  1.1  mrg {
   4547  1.1  mrg   tree retval;
   4548  1.1  mrg   mpfr_t pi, t0;
   4549  1.1  mrg 
   4550  1.1  mrg   gfc_set_model_kind (kind);
   4551  1.1  mrg   mpfr_init (pi);
   4552  1.1  mrg   mpfr_init (t0);
   4553  1.1  mrg   mpfr_set_si (t0, 180, GFC_RND_MODE);
   4554  1.1  mrg   mpfr_const_pi (pi, GFC_RND_MODE);
   4555  1.1  mrg   mpfr_div (t0, t0, pi, GFC_RND_MODE);
   4556  1.1  mrg   retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
   4557  1.1  mrg   mpfr_clear (t0);
   4558  1.1  mrg   mpfr_clear (pi);
   4559  1.1  mrg   return retval;
   4560  1.1  mrg }
   4561  1.1  mrg 
   4562  1.1  mrg 
   4563  1.1  mrg static gfc_intrinsic_map_t *
   4564  1.1  mrg gfc_lookup_intrinsic (gfc_isym_id id)
   4565  1.1  mrg {
   4566  1.1  mrg   gfc_intrinsic_map_t *m = gfc_intrinsic_map;
   4567  1.1  mrg   for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
   4568  1.1  mrg     if (id == m->id)
   4569  1.1  mrg       break;
   4570  1.1  mrg   gcc_assert (id == m->id);
   4571  1.1  mrg   return m;
   4572  1.1  mrg }
   4573  1.1  mrg 
   4574  1.1  mrg 
   4575  1.1  mrg /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
   4576  1.1  mrg    ASIND(x) is translated into ASIN(x) * 180 / pi.
   4577  1.1  mrg    ATAND(x) is translated into ATAN(x) * 180 / pi.  */
   4578  1.1  mrg 
   4579  1.1  mrg static void
   4580  1.1  mrg gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
   4581  1.1  mrg {
   4582  1.1  mrg   tree arg;
   4583  1.1  mrg   tree atrigd;
   4584  1.1  mrg   tree type;
   4585  1.1  mrg   gfc_intrinsic_map_t *m;
   4586  1.1  mrg 
   4587  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4588  1.1  mrg 
   4589  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   4590  1.1  mrg 
   4591  1.1  mrg   switch (id)
   4592  1.1  mrg     {
   4593  1.1  mrg     case GFC_ISYM_ACOSD:
   4594  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
   4595  1.1  mrg       break;
   4596  1.1  mrg     case GFC_ISYM_ASIND:
   4597  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
   4598  1.1  mrg       break;
   4599  1.1  mrg     case GFC_ISYM_ATAND:
   4600  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
   4601  1.1  mrg       break;
   4602  1.1  mrg     default:
   4603  1.1  mrg       gcc_unreachable ();
   4604  1.1  mrg     }
   4605  1.1  mrg   atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
   4606  1.1  mrg   atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
   4607  1.1  mrg 
   4608  1.1  mrg   se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
   4609  1.1  mrg 			      fold_convert (type, rad2deg (expr->ts.kind)));
   4610  1.1  mrg }
   4611  1.1  mrg 
   4612  1.1  mrg 
   4613  1.1  mrg /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
   4614  1.1  mrg    COS(X) / SIN(X) for COMPLEX argument.  */
   4615  1.1  mrg 
   4616  1.1  mrg static void
   4617  1.1  mrg gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
   4618  1.1  mrg {
   4619  1.1  mrg   gfc_intrinsic_map_t *m;
   4620  1.1  mrg   tree arg;
   4621  1.1  mrg   tree type;
   4622  1.1  mrg 
   4623  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4624  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   4625  1.1  mrg 
   4626  1.1  mrg   if (expr->ts.type == BT_REAL)
   4627  1.1  mrg     {
   4628  1.1  mrg       tree tan;
   4629  1.1  mrg       tree tmp;
   4630  1.1  mrg       mpfr_t pio2;
   4631  1.1  mrg 
   4632  1.1  mrg       /* Create pi/2.  */
   4633  1.1  mrg       gfc_set_model_kind (expr->ts.kind);
   4634  1.1  mrg       mpfr_init (pio2);
   4635  1.1  mrg       mpfr_const_pi (pio2, GFC_RND_MODE);
   4636  1.1  mrg       mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODE);
   4637  1.1  mrg       tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
   4638  1.1  mrg       mpfr_clear (pio2);
   4639  1.1  mrg 
   4640  1.1  mrg       /* Find tan builtin function.  */
   4641  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
   4642  1.1  mrg       tan = gfc_get_intrinsic_lib_fndecl (m, expr);
   4643  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
   4644  1.1  mrg       tan = build_call_expr_loc (input_location, tan, 1, tmp);
   4645  1.1  mrg       se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
   4646  1.1  mrg     }
   4647  1.1  mrg   else
   4648  1.1  mrg     {
   4649  1.1  mrg       tree sin;
   4650  1.1  mrg       tree cos;
   4651  1.1  mrg 
   4652  1.1  mrg       /* Find cos builtin function.  */
   4653  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_COS);
   4654  1.1  mrg       cos = gfc_get_intrinsic_lib_fndecl (m, expr);
   4655  1.1  mrg       cos = build_call_expr_loc (input_location, cos, 1, arg);
   4656  1.1  mrg 
   4657  1.1  mrg       /* Find sin builtin function.  */
   4658  1.1  mrg       m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
   4659  1.1  mrg       sin = gfc_get_intrinsic_lib_fndecl (m, expr);
   4660  1.1  mrg       sin = build_call_expr_loc (input_location, sin, 1, arg);
   4661  1.1  mrg 
   4662  1.1  mrg       /* Divide cos by sin. */
   4663  1.1  mrg       se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
   4664  1.1  mrg    }
   4665  1.1  mrg }
   4666  1.1  mrg 
   4667  1.1  mrg 
   4668  1.1  mrg /* COTAND(X) is translated into -TAND(X+90) for REAL argument.  */
   4669  1.1  mrg 
   4670  1.1  mrg static void
   4671  1.1  mrg gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
   4672  1.1  mrg {
   4673  1.1  mrg   tree arg;
   4674  1.1  mrg   tree type;
   4675  1.1  mrg   tree ninety_tree;
   4676  1.1  mrg   mpfr_t ninety;
   4677  1.1  mrg 
   4678  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4679  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   4680  1.1  mrg 
   4681  1.1  mrg   gfc_set_model_kind (expr->ts.kind);
   4682  1.1  mrg 
   4683  1.1  mrg   /* Build the tree for x + 90.  */
   4684  1.1  mrg   mpfr_init_set_ui (ninety, 90, GFC_RND_MODE);
   4685  1.1  mrg   ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
   4686  1.1  mrg   arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
   4687  1.1  mrg   mpfr_clear (ninety);
   4688  1.1  mrg 
   4689  1.1  mrg   /* Find tand.  */
   4690  1.1  mrg   gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
   4691  1.1  mrg   tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
   4692  1.1  mrg   tand = build_call_expr_loc (input_location, tand, 1, arg);
   4693  1.1  mrg 
   4694  1.1  mrg   se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
   4695  1.1  mrg }
   4696  1.1  mrg 
   4697  1.1  mrg 
   4698  1.1  mrg /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
   4699  1.1  mrg 
   4700  1.1  mrg static void
   4701  1.1  mrg gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
   4702  1.1  mrg {
   4703  1.1  mrg   tree args[2];
   4704  1.1  mrg   tree atan2d;
   4705  1.1  mrg   tree type;
   4706  1.1  mrg 
   4707  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   4708  1.1  mrg   type = TREE_TYPE (args[0]);
   4709  1.1  mrg 
   4710  1.1  mrg   gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
   4711  1.1  mrg   atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
   4712  1.1  mrg   atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
   4713  1.1  mrg 
   4714  1.1  mrg   se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
   4715  1.1  mrg 			      rad2deg (expr->ts.kind));
   4716  1.1  mrg }
   4717  1.1  mrg 
   4718  1.1  mrg 
   4719  1.1  mrg /* COUNT(A) = Number of true elements in A.  */
   4720  1.1  mrg static void
   4721  1.1  mrg gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
   4722  1.1  mrg {
   4723  1.1  mrg   tree resvar;
   4724  1.1  mrg   tree type;
   4725  1.1  mrg   stmtblock_t body;
   4726  1.1  mrg   tree tmp;
   4727  1.1  mrg   gfc_loopinfo loop;
   4728  1.1  mrg   gfc_actual_arglist *actual;
   4729  1.1  mrg   gfc_ss *arrayss;
   4730  1.1  mrg   gfc_se arrayse;
   4731  1.1  mrg 
   4732  1.1  mrg   if (se->ss)
   4733  1.1  mrg     {
   4734  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   4735  1.1  mrg       return;
   4736  1.1  mrg     }
   4737  1.1  mrg 
   4738  1.1  mrg   actual = expr->value.function.actual;
   4739  1.1  mrg 
   4740  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4741  1.1  mrg   /* Initialize the result.  */
   4742  1.1  mrg   resvar = gfc_create_var (type, "count");
   4743  1.1  mrg   gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
   4744  1.1  mrg 
   4745  1.1  mrg   /* Walk the arguments.  */
   4746  1.1  mrg   arrayss = gfc_walk_expr (actual->expr);
   4747  1.1  mrg   gcc_assert (arrayss != gfc_ss_terminator);
   4748  1.1  mrg 
   4749  1.1  mrg   /* Initialize the scalarizer.  */
   4750  1.1  mrg   gfc_init_loopinfo (&loop);
   4751  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss);
   4752  1.1  mrg 
   4753  1.1  mrg   /* Initialize the loop.  */
   4754  1.1  mrg   gfc_conv_ss_startstride (&loop);
   4755  1.1  mrg   gfc_conv_loop_setup (&loop, &expr->where);
   4756  1.1  mrg 
   4757  1.1  mrg   gfc_mark_ss_chain_used (arrayss, 1);
   4758  1.1  mrg   /* Generate the loop body.  */
   4759  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   4760  1.1  mrg 
   4761  1.1  mrg   tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
   4762  1.1  mrg 			 resvar, build_int_cst (TREE_TYPE (resvar), 1));
   4763  1.1  mrg   tmp = build2_v (MODIFY_EXPR, resvar, tmp);
   4764  1.1  mrg 
   4765  1.1  mrg   gfc_init_se (&arrayse, NULL);
   4766  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   4767  1.1  mrg   arrayse.ss = arrayss;
   4768  1.1  mrg   gfc_conv_expr_val (&arrayse, actual->expr);
   4769  1.1  mrg   tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
   4770  1.1  mrg 		  build_empty_stmt (input_location));
   4771  1.1  mrg 
   4772  1.1  mrg   gfc_add_block_to_block (&body, &arrayse.pre);
   4773  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   4774  1.1  mrg   gfc_add_block_to_block (&body, &arrayse.post);
   4775  1.1  mrg 
   4776  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   4777  1.1  mrg 
   4778  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.pre);
   4779  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.post);
   4780  1.1  mrg   gfc_cleanup_loop (&loop);
   4781  1.1  mrg 
   4782  1.1  mrg   se->expr = resvar;
   4783  1.1  mrg }
   4784  1.1  mrg 
   4785  1.1  mrg 
   4786  1.1  mrg /* Update given gfc_se to have ss component pointing to the nested gfc_ss
   4787  1.1  mrg    struct and return the corresponding loopinfo.  */
   4788  1.1  mrg 
   4789  1.1  mrg static gfc_loopinfo *
   4790  1.1  mrg enter_nested_loop (gfc_se *se)
   4791  1.1  mrg {
   4792  1.1  mrg   se->ss = se->ss->nested_ss;
   4793  1.1  mrg   gcc_assert (se->ss == se->ss->loop->ss);
   4794  1.1  mrg 
   4795  1.1  mrg   return se->ss->loop;
   4796  1.1  mrg }
   4797  1.1  mrg 
   4798  1.1  mrg /* Build the condition for a mask, which may be optional.  */
   4799  1.1  mrg 
   4800  1.1  mrg static tree
   4801  1.1  mrg conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
   4802  1.1  mrg 			 bool optional_mask)
   4803  1.1  mrg {
   4804  1.1  mrg   tree present;
   4805  1.1  mrg   tree type;
   4806  1.1  mrg 
   4807  1.1  mrg   if (optional_mask)
   4808  1.1  mrg     {
   4809  1.1  mrg       type = TREE_TYPE (maskse->expr);
   4810  1.1  mrg       present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
   4811  1.1  mrg       present = convert (type, present);
   4812  1.1  mrg       present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
   4813  1.1  mrg 				 present);
   4814  1.1  mrg       return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   4815  1.1  mrg 			      type, present, maskse->expr);
   4816  1.1  mrg     }
   4817  1.1  mrg   else
   4818  1.1  mrg     return maskse->expr;
   4819  1.1  mrg }
   4820  1.1  mrg 
   4821  1.1  mrg /* Inline implementation of the sum and product intrinsics.  */
   4822  1.1  mrg static void
   4823  1.1  mrg gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
   4824  1.1  mrg 			  bool norm2)
   4825  1.1  mrg {
   4826  1.1  mrg   tree resvar;
   4827  1.1  mrg   tree scale = NULL_TREE;
   4828  1.1  mrg   tree type;
   4829  1.1  mrg   stmtblock_t body;
   4830  1.1  mrg   stmtblock_t block;
   4831  1.1  mrg   tree tmp;
   4832  1.1  mrg   gfc_loopinfo loop, *ploop;
   4833  1.1  mrg   gfc_actual_arglist *arg_array, *arg_mask;
   4834  1.1  mrg   gfc_ss *arrayss = NULL;
   4835  1.1  mrg   gfc_ss *maskss = NULL;
   4836  1.1  mrg   gfc_se arrayse;
   4837  1.1  mrg   gfc_se maskse;
   4838  1.1  mrg   gfc_se *parent_se;
   4839  1.1  mrg   gfc_expr *arrayexpr;
   4840  1.1  mrg   gfc_expr *maskexpr;
   4841  1.1  mrg   bool optional_mask;
   4842  1.1  mrg 
   4843  1.1  mrg   if (expr->rank > 0)
   4844  1.1  mrg     {
   4845  1.1  mrg       gcc_assert (gfc_inline_intrinsic_function_p (expr));
   4846  1.1  mrg       parent_se = se;
   4847  1.1  mrg     }
   4848  1.1  mrg   else
   4849  1.1  mrg     parent_se = NULL;
   4850  1.1  mrg 
   4851  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   4852  1.1  mrg   /* Initialize the result.  */
   4853  1.1  mrg   resvar = gfc_create_var (type, "val");
   4854  1.1  mrg   if (norm2)
   4855  1.1  mrg     {
   4856  1.1  mrg       /* result = 0.0;
   4857  1.1  mrg 	 scale = 1.0.  */
   4858  1.1  mrg       scale = gfc_create_var (type, "scale");
   4859  1.1  mrg       gfc_add_modify (&se->pre, scale,
   4860  1.1  mrg 		      gfc_build_const (type, integer_one_node));
   4861  1.1  mrg       tmp = gfc_build_const (type, integer_zero_node);
   4862  1.1  mrg     }
   4863  1.1  mrg   else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
   4864  1.1  mrg     tmp = gfc_build_const (type, integer_zero_node);
   4865  1.1  mrg   else if (op == NE_EXPR)
   4866  1.1  mrg     /* PARITY.  */
   4867  1.1  mrg     tmp = convert (type, boolean_false_node);
   4868  1.1  mrg   else if (op == BIT_AND_EXPR)
   4869  1.1  mrg     tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
   4870  1.1  mrg 						  type, integer_one_node));
   4871  1.1  mrg   else
   4872  1.1  mrg     tmp = gfc_build_const (type, integer_one_node);
   4873  1.1  mrg 
   4874  1.1  mrg   gfc_add_modify (&se->pre, resvar, tmp);
   4875  1.1  mrg 
   4876  1.1  mrg   arg_array = expr->value.function.actual;
   4877  1.1  mrg 
   4878  1.1  mrg   arrayexpr = arg_array->expr;
   4879  1.1  mrg 
   4880  1.1  mrg   if (op == NE_EXPR || norm2)
   4881  1.1  mrg     {
   4882  1.1  mrg       /* PARITY and NORM2.  */
   4883  1.1  mrg       maskexpr = NULL;
   4884  1.1  mrg       optional_mask = false;
   4885  1.1  mrg     }
   4886  1.1  mrg   else
   4887  1.1  mrg     {
   4888  1.1  mrg       arg_mask  = arg_array->next->next;
   4889  1.1  mrg       gcc_assert (arg_mask != NULL);
   4890  1.1  mrg       maskexpr = arg_mask->expr;
   4891  1.1  mrg       optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
   4892  1.1  mrg 	&& maskexpr->symtree->n.sym->attr.dummy
   4893  1.1  mrg 	&& maskexpr->symtree->n.sym->attr.optional;
   4894  1.1  mrg     }
   4895  1.1  mrg 
   4896  1.1  mrg   if (expr->rank == 0)
   4897  1.1  mrg     {
   4898  1.1  mrg       /* Walk the arguments.  */
   4899  1.1  mrg       arrayss = gfc_walk_expr (arrayexpr);
   4900  1.1  mrg       gcc_assert (arrayss != gfc_ss_terminator);
   4901  1.1  mrg 
   4902  1.1  mrg       if (maskexpr && maskexpr->rank > 0)
   4903  1.1  mrg 	{
   4904  1.1  mrg 	  maskss = gfc_walk_expr (maskexpr);
   4905  1.1  mrg 	  gcc_assert (maskss != gfc_ss_terminator);
   4906  1.1  mrg 	}
   4907  1.1  mrg       else
   4908  1.1  mrg 	maskss = NULL;
   4909  1.1  mrg 
   4910  1.1  mrg       /* Initialize the scalarizer.  */
   4911  1.1  mrg       gfc_init_loopinfo (&loop);
   4912  1.1  mrg 
   4913  1.1  mrg       /* We add the mask first because the number of iterations is
   4914  1.1  mrg 	 taken from the last ss, and this breaks if an absent
   4915  1.1  mrg 	 optional argument is used for mask.  */
   4916  1.1  mrg 
   4917  1.1  mrg       if (maskexpr && maskexpr->rank > 0)
   4918  1.1  mrg 	gfc_add_ss_to_loop (&loop, maskss);
   4919  1.1  mrg       gfc_add_ss_to_loop (&loop, arrayss);
   4920  1.1  mrg 
   4921  1.1  mrg       /* Initialize the loop.  */
   4922  1.1  mrg       gfc_conv_ss_startstride (&loop);
   4923  1.1  mrg       gfc_conv_loop_setup (&loop, &expr->where);
   4924  1.1  mrg 
   4925  1.1  mrg       if (maskexpr && maskexpr->rank > 0)
   4926  1.1  mrg 	gfc_mark_ss_chain_used (maskss, 1);
   4927  1.1  mrg       gfc_mark_ss_chain_used (arrayss, 1);
   4928  1.1  mrg 
   4929  1.1  mrg       ploop = &loop;
   4930  1.1  mrg     }
   4931  1.1  mrg   else
   4932  1.1  mrg     /* All the work has been done in the parent loops.  */
   4933  1.1  mrg     ploop = enter_nested_loop (se);
   4934  1.1  mrg 
   4935  1.1  mrg   gcc_assert (ploop);
   4936  1.1  mrg 
   4937  1.1  mrg   /* Generate the loop body.  */
   4938  1.1  mrg   gfc_start_scalarized_body (ploop, &body);
   4939  1.1  mrg 
   4940  1.1  mrg   /* If we have a mask, only add this element if the mask is set.  */
   4941  1.1  mrg   if (maskexpr && maskexpr->rank > 0)
   4942  1.1  mrg     {
   4943  1.1  mrg       gfc_init_se (&maskse, parent_se);
   4944  1.1  mrg       gfc_copy_loopinfo_to_se (&maskse, ploop);
   4945  1.1  mrg       if (expr->rank == 0)
   4946  1.1  mrg 	maskse.ss = maskss;
   4947  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   4948  1.1  mrg       gfc_add_block_to_block (&body, &maskse.pre);
   4949  1.1  mrg 
   4950  1.1  mrg       gfc_start_block (&block);
   4951  1.1  mrg     }
   4952  1.1  mrg   else
   4953  1.1  mrg     gfc_init_block (&block);
   4954  1.1  mrg 
   4955  1.1  mrg   /* Do the actual summation/product.  */
   4956  1.1  mrg   gfc_init_se (&arrayse, parent_se);
   4957  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse, ploop);
   4958  1.1  mrg   if (expr->rank == 0)
   4959  1.1  mrg     arrayse.ss = arrayss;
   4960  1.1  mrg   gfc_conv_expr_val (&arrayse, arrayexpr);
   4961  1.1  mrg   gfc_add_block_to_block (&block, &arrayse.pre);
   4962  1.1  mrg 
   4963  1.1  mrg   if (norm2)
   4964  1.1  mrg     {
   4965  1.1  mrg       /* if (x (i) != 0.0)
   4966  1.1  mrg 	   {
   4967  1.1  mrg 	     absX = abs(x(i))
   4968  1.1  mrg 	     if (absX > scale)
   4969  1.1  mrg 	       {
   4970  1.1  mrg                  val = scale/absX;
   4971  1.1  mrg 		 result = 1.0 + result * val * val;
   4972  1.1  mrg 		 scale = absX;
   4973  1.1  mrg 	       }
   4974  1.1  mrg 	     else
   4975  1.1  mrg 	       {
   4976  1.1  mrg                  val = absX/scale;
   4977  1.1  mrg 	         result += val * val;
   4978  1.1  mrg 	       }
   4979  1.1  mrg 	   }  */
   4980  1.1  mrg       tree res1, res2, cond, absX, val;
   4981  1.1  mrg       stmtblock_t ifblock1, ifblock2, ifblock3;
   4982  1.1  mrg 
   4983  1.1  mrg       gfc_init_block (&ifblock1);
   4984  1.1  mrg 
   4985  1.1  mrg       absX = gfc_create_var (type, "absX");
   4986  1.1  mrg       gfc_add_modify (&ifblock1, absX,
   4987  1.1  mrg 		      fold_build1_loc (input_location, ABS_EXPR, type,
   4988  1.1  mrg 				       arrayse.expr));
   4989  1.1  mrg       val = gfc_create_var (type, "val");
   4990  1.1  mrg       gfc_add_expr_to_block (&ifblock1, val);
   4991  1.1  mrg 
   4992  1.1  mrg       gfc_init_block (&ifblock2);
   4993  1.1  mrg       gfc_add_modify (&ifblock2, val,
   4994  1.1  mrg 		      fold_build2_loc (input_location, RDIV_EXPR, type, scale,
   4995  1.1  mrg 				       absX));
   4996  1.1  mrg       res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
   4997  1.1  mrg       res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
   4998  1.1  mrg       res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
   4999  1.1  mrg 			      gfc_build_const (type, integer_one_node));
   5000  1.1  mrg       gfc_add_modify (&ifblock2, resvar, res1);
   5001  1.1  mrg       gfc_add_modify (&ifblock2, scale, absX);
   5002  1.1  mrg       res1 = gfc_finish_block (&ifblock2);
   5003  1.1  mrg 
   5004  1.1  mrg       gfc_init_block (&ifblock3);
   5005  1.1  mrg       gfc_add_modify (&ifblock3, val,
   5006  1.1  mrg 		      fold_build2_loc (input_location, RDIV_EXPR, type, absX,
   5007  1.1  mrg 				       scale));
   5008  1.1  mrg       res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
   5009  1.1  mrg       res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
   5010  1.1  mrg       gfc_add_modify (&ifblock3, resvar, res2);
   5011  1.1  mrg       res2 = gfc_finish_block (&ifblock3);
   5012  1.1  mrg 
   5013  1.1  mrg       cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   5014  1.1  mrg 			      absX, scale);
   5015  1.1  mrg       tmp = build3_v (COND_EXPR, cond, res1, res2);
   5016  1.1  mrg       gfc_add_expr_to_block (&ifblock1, tmp);
   5017  1.1  mrg       tmp = gfc_finish_block (&ifblock1);
   5018  1.1  mrg 
   5019  1.1  mrg       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   5020  1.1  mrg 			      arrayse.expr,
   5021  1.1  mrg 			      gfc_build_const (type, integer_zero_node));
   5022  1.1  mrg 
   5023  1.1  mrg       tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   5024  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5025  1.1  mrg     }
   5026  1.1  mrg   else
   5027  1.1  mrg     {
   5028  1.1  mrg       tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
   5029  1.1  mrg       gfc_add_modify (&block, resvar, tmp);
   5030  1.1  mrg     }
   5031  1.1  mrg 
   5032  1.1  mrg   gfc_add_block_to_block (&block, &arrayse.post);
   5033  1.1  mrg 
   5034  1.1  mrg   if (maskexpr && maskexpr->rank > 0)
   5035  1.1  mrg     {
   5036  1.1  mrg       /* We enclose the above in if (mask) {...} .  If the mask is an
   5037  1.1  mrg 	 optional argument, generate
   5038  1.1  mrg 	 IF (.NOT. PRESENT(MASK) .OR. MASK(I)).  */
   5039  1.1  mrg       tree ifmask;
   5040  1.1  mrg       tmp = gfc_finish_block (&block);
   5041  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5042  1.1  mrg       tmp = build3_v (COND_EXPR, ifmask, tmp,
   5043  1.1  mrg 		      build_empty_stmt (input_location));
   5044  1.1  mrg     }
   5045  1.1  mrg   else
   5046  1.1  mrg     tmp = gfc_finish_block (&block);
   5047  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   5048  1.1  mrg 
   5049  1.1  mrg   gfc_trans_scalarizing_loops (ploop, &body);
   5050  1.1  mrg 
   5051  1.1  mrg   /* For a scalar mask, enclose the loop in an if statement.  */
   5052  1.1  mrg   if (maskexpr && maskexpr->rank == 0)
   5053  1.1  mrg     {
   5054  1.1  mrg       gfc_init_block (&block);
   5055  1.1  mrg       gfc_add_block_to_block (&block, &ploop->pre);
   5056  1.1  mrg       gfc_add_block_to_block (&block, &ploop->post);
   5057  1.1  mrg       tmp = gfc_finish_block (&block);
   5058  1.1  mrg 
   5059  1.1  mrg       if (expr->rank > 0)
   5060  1.1  mrg 	{
   5061  1.1  mrg 	  tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
   5062  1.1  mrg 			  build_empty_stmt (input_location));
   5063  1.1  mrg 	  gfc_advance_se_ss_chain (se);
   5064  1.1  mrg 	}
   5065  1.1  mrg       else
   5066  1.1  mrg 	{
   5067  1.1  mrg 	  tree ifmask;
   5068  1.1  mrg 
   5069  1.1  mrg 	  gcc_assert (expr->rank == 0);
   5070  1.1  mrg 	  gfc_init_se (&maskse, NULL);
   5071  1.1  mrg 	  gfc_conv_expr_val (&maskse, maskexpr);
   5072  1.1  mrg 	  ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5073  1.1  mrg 	  tmp = build3_v (COND_EXPR, ifmask, tmp,
   5074  1.1  mrg 			  build_empty_stmt (input_location));
   5075  1.1  mrg 	}
   5076  1.1  mrg 
   5077  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5078  1.1  mrg       gfc_add_block_to_block (&se->pre, &block);
   5079  1.1  mrg       gcc_assert (se->post.head == NULL);
   5080  1.1  mrg     }
   5081  1.1  mrg   else
   5082  1.1  mrg     {
   5083  1.1  mrg       gfc_add_block_to_block (&se->pre, &ploop->pre);
   5084  1.1  mrg       gfc_add_block_to_block (&se->pre, &ploop->post);
   5085  1.1  mrg     }
   5086  1.1  mrg 
   5087  1.1  mrg   if (expr->rank == 0)
   5088  1.1  mrg     gfc_cleanup_loop (ploop);
   5089  1.1  mrg 
   5090  1.1  mrg   if (norm2)
   5091  1.1  mrg     {
   5092  1.1  mrg       /* result = scale * sqrt(result).  */
   5093  1.1  mrg       tree sqrt;
   5094  1.1  mrg       sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
   5095  1.1  mrg       resvar = build_call_expr_loc (input_location,
   5096  1.1  mrg 				    sqrt, 1, resvar);
   5097  1.1  mrg       resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
   5098  1.1  mrg     }
   5099  1.1  mrg 
   5100  1.1  mrg   se->expr = resvar;
   5101  1.1  mrg }
   5102  1.1  mrg 
   5103  1.1  mrg 
   5104  1.1  mrg /* Inline implementation of the dot_product intrinsic. This function
   5105  1.1  mrg    is based on gfc_conv_intrinsic_arith (the previous function).  */
   5106  1.1  mrg static void
   5107  1.1  mrg gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
   5108  1.1  mrg {
   5109  1.1  mrg   tree resvar;
   5110  1.1  mrg   tree type;
   5111  1.1  mrg   stmtblock_t body;
   5112  1.1  mrg   stmtblock_t block;
   5113  1.1  mrg   tree tmp;
   5114  1.1  mrg   gfc_loopinfo loop;
   5115  1.1  mrg   gfc_actual_arglist *actual;
   5116  1.1  mrg   gfc_ss *arrayss1, *arrayss2;
   5117  1.1  mrg   gfc_se arrayse1, arrayse2;
   5118  1.1  mrg   gfc_expr *arrayexpr1, *arrayexpr2;
   5119  1.1  mrg 
   5120  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   5121  1.1  mrg 
   5122  1.1  mrg   /* Initialize the result.  */
   5123  1.1  mrg   resvar = gfc_create_var (type, "val");
   5124  1.1  mrg   if (expr->ts.type == BT_LOGICAL)
   5125  1.1  mrg     tmp = build_int_cst (type, 0);
   5126  1.1  mrg   else
   5127  1.1  mrg     tmp = gfc_build_const (type, integer_zero_node);
   5128  1.1  mrg 
   5129  1.1  mrg   gfc_add_modify (&se->pre, resvar, tmp);
   5130  1.1  mrg 
   5131  1.1  mrg   /* Walk argument #1.  */
   5132  1.1  mrg   actual = expr->value.function.actual;
   5133  1.1  mrg   arrayexpr1 = actual->expr;
   5134  1.1  mrg   arrayss1 = gfc_walk_expr (arrayexpr1);
   5135  1.1  mrg   gcc_assert (arrayss1 != gfc_ss_terminator);
   5136  1.1  mrg 
   5137  1.1  mrg   /* Walk argument #2.  */
   5138  1.1  mrg   actual = actual->next;
   5139  1.1  mrg   arrayexpr2 = actual->expr;
   5140  1.1  mrg   arrayss2 = gfc_walk_expr (arrayexpr2);
   5141  1.1  mrg   gcc_assert (arrayss2 != gfc_ss_terminator);
   5142  1.1  mrg 
   5143  1.1  mrg   /* Initialize the scalarizer.  */
   5144  1.1  mrg   gfc_init_loopinfo (&loop);
   5145  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss1);
   5146  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss2);
   5147  1.1  mrg 
   5148  1.1  mrg   /* Initialize the loop.  */
   5149  1.1  mrg   gfc_conv_ss_startstride (&loop);
   5150  1.1  mrg   gfc_conv_loop_setup (&loop, &expr->where);
   5151  1.1  mrg 
   5152  1.1  mrg   gfc_mark_ss_chain_used (arrayss1, 1);
   5153  1.1  mrg   gfc_mark_ss_chain_used (arrayss2, 1);
   5154  1.1  mrg 
   5155  1.1  mrg   /* Generate the loop body.  */
   5156  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   5157  1.1  mrg   gfc_init_block (&block);
   5158  1.1  mrg 
   5159  1.1  mrg   /* Make the tree expression for [conjg(]array1[)].  */
   5160  1.1  mrg   gfc_init_se (&arrayse1, NULL);
   5161  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse1, &loop);
   5162  1.1  mrg   arrayse1.ss = arrayss1;
   5163  1.1  mrg   gfc_conv_expr_val (&arrayse1, arrayexpr1);
   5164  1.1  mrg   if (expr->ts.type == BT_COMPLEX)
   5165  1.1  mrg     arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
   5166  1.1  mrg 				     arrayse1.expr);
   5167  1.1  mrg   gfc_add_block_to_block (&block, &arrayse1.pre);
   5168  1.1  mrg 
   5169  1.1  mrg   /* Make the tree expression for array2.  */
   5170  1.1  mrg   gfc_init_se (&arrayse2, NULL);
   5171  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse2, &loop);
   5172  1.1  mrg   arrayse2.ss = arrayss2;
   5173  1.1  mrg   gfc_conv_expr_val (&arrayse2, arrayexpr2);
   5174  1.1  mrg   gfc_add_block_to_block (&block, &arrayse2.pre);
   5175  1.1  mrg 
   5176  1.1  mrg   /* Do the actual product and sum.  */
   5177  1.1  mrg   if (expr->ts.type == BT_LOGICAL)
   5178  1.1  mrg     {
   5179  1.1  mrg       tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
   5180  1.1  mrg 			     arrayse1.expr, arrayse2.expr);
   5181  1.1  mrg       tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
   5182  1.1  mrg     }
   5183  1.1  mrg   else
   5184  1.1  mrg     {
   5185  1.1  mrg       tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
   5186  1.1  mrg 			     arrayse2.expr);
   5187  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
   5188  1.1  mrg     }
   5189  1.1  mrg   gfc_add_modify (&block, resvar, tmp);
   5190  1.1  mrg 
   5191  1.1  mrg   /* Finish up the loop block and the loop.  */
   5192  1.1  mrg   tmp = gfc_finish_block (&block);
   5193  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   5194  1.1  mrg 
   5195  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   5196  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.pre);
   5197  1.1  mrg   gfc_add_block_to_block (&se->pre, &loop.post);
   5198  1.1  mrg   gfc_cleanup_loop (&loop);
   5199  1.1  mrg 
   5200  1.1  mrg   se->expr = resvar;
   5201  1.1  mrg }
   5202  1.1  mrg 
   5203  1.1  mrg 
   5204  1.1  mrg /* Emit code for minloc or maxloc intrinsic.  There are many different cases
   5205  1.1  mrg    we need to handle.  For performance reasons we sometimes create two
   5206  1.1  mrg    loops instead of one, where the second one is much simpler.
   5207  1.1  mrg    Examples for minloc intrinsic:
   5208  1.1  mrg    1) Result is an array, a call is generated
   5209  1.1  mrg    2) Array mask is used and NaNs need to be supported:
   5210  1.1  mrg       limit = Infinity;
   5211  1.1  mrg       pos = 0;
   5212  1.1  mrg       S = from;
   5213  1.1  mrg       while (S <= to) {
   5214  1.1  mrg 	if (mask[S]) {
   5215  1.1  mrg 	  if (pos == 0) pos = S + (1 - from);
   5216  1.1  mrg 	  if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
   5217  1.1  mrg 	}
   5218  1.1  mrg 	S++;
   5219  1.1  mrg       }
   5220  1.1  mrg       goto lab2;
   5221  1.1  mrg       lab1:;
   5222  1.1  mrg       while (S <= to) {
   5223  1.1  mrg 	if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
   5224  1.1  mrg 	S++;
   5225  1.1  mrg       }
   5226  1.1  mrg       lab2:;
   5227  1.1  mrg    3) NaNs need to be supported, but it is known at compile time or cheaply
   5228  1.1  mrg       at runtime whether array is nonempty or not:
   5229  1.1  mrg       limit = Infinity;
   5230  1.1  mrg       pos = 0;
   5231  1.1  mrg       S = from;
   5232  1.1  mrg       while (S <= to) {
   5233  1.1  mrg 	if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
   5234  1.1  mrg 	S++;
   5235  1.1  mrg       }
   5236  1.1  mrg       if (from <= to) pos = 1;
   5237  1.1  mrg       goto lab2;
   5238  1.1  mrg       lab1:;
   5239  1.1  mrg       while (S <= to) {
   5240  1.1  mrg 	if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
   5241  1.1  mrg 	S++;
   5242  1.1  mrg       }
   5243  1.1  mrg       lab2:;
   5244  1.1  mrg    4) NaNs aren't supported, array mask is used:
   5245  1.1  mrg       limit = infinities_supported ? Infinity : huge (limit);
   5246  1.1  mrg       pos = 0;
   5247  1.1  mrg       S = from;
   5248  1.1  mrg       while (S <= to) {
   5249  1.1  mrg 	if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
   5250  1.1  mrg 	S++;
   5251  1.1  mrg       }
   5252  1.1  mrg       goto lab2;
   5253  1.1  mrg       lab1:;
   5254  1.1  mrg       while (S <= to) {
   5255  1.1  mrg 	if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
   5256  1.1  mrg 	S++;
   5257  1.1  mrg       }
   5258  1.1  mrg       lab2:;
   5259  1.1  mrg    5) Same without array mask:
   5260  1.1  mrg       limit = infinities_supported ? Infinity : huge (limit);
   5261  1.1  mrg       pos = (from <= to) ? 1 : 0;
   5262  1.1  mrg       S = from;
   5263  1.1  mrg       while (S <= to) {
   5264  1.1  mrg 	if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
   5265  1.1  mrg 	S++;
   5266  1.1  mrg       }
   5267  1.1  mrg    For 3) and 5), if mask is scalar, this all goes into a conditional,
   5268  1.1  mrg    setting pos = 0; in the else branch.
   5269  1.1  mrg 
   5270  1.1  mrg    Since we now also support the BACK argument, instead of using
   5271  1.1  mrg    if (a[S] < limit), we now use
   5272  1.1  mrg 
   5273  1.1  mrg    if (back)
   5274  1.1  mrg      cond = a[S] <= limit;
   5275  1.1  mrg    else
   5276  1.1  mrg      cond = a[S] < limit;
   5277  1.1  mrg    if (cond) {
   5278  1.1  mrg      ....
   5279  1.1  mrg 
   5280  1.1  mrg      The optimizer is smart enough to move the condition out of the loop.
   5281  1.1  mrg      The are now marked as unlikely to for further speedup.  */
   5282  1.1  mrg 
   5283  1.1  mrg static void
   5284  1.1  mrg gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
   5285  1.1  mrg {
   5286  1.1  mrg   stmtblock_t body;
   5287  1.1  mrg   stmtblock_t block;
   5288  1.1  mrg   stmtblock_t ifblock;
   5289  1.1  mrg   stmtblock_t elseblock;
   5290  1.1  mrg   tree limit;
   5291  1.1  mrg   tree type;
   5292  1.1  mrg   tree tmp;
   5293  1.1  mrg   tree cond;
   5294  1.1  mrg   tree elsetmp;
   5295  1.1  mrg   tree ifbody;
   5296  1.1  mrg   tree offset;
   5297  1.1  mrg   tree nonempty;
   5298  1.1  mrg   tree lab1, lab2;
   5299  1.1  mrg   tree b_if, b_else;
   5300  1.1  mrg   gfc_loopinfo loop;
   5301  1.1  mrg   gfc_actual_arglist *array_arg, *dim_arg, *mask_arg, *kind_arg;
   5302  1.1  mrg   gfc_actual_arglist *back_arg;
   5303  1.1  mrg   gfc_ss *arrayss;
   5304  1.1  mrg   gfc_ss *maskss;
   5305  1.1  mrg   gfc_se arrayse;
   5306  1.1  mrg   gfc_se maskse;
   5307  1.1  mrg   gfc_expr *arrayexpr;
   5308  1.1  mrg   gfc_expr *maskexpr;
   5309  1.1  mrg   gfc_expr *backexpr;
   5310  1.1  mrg   gfc_se backse;
   5311  1.1  mrg   tree pos;
   5312  1.1  mrg   int n;
   5313  1.1  mrg   bool optional_mask;
   5314  1.1  mrg 
   5315  1.1  mrg   array_arg = expr->value.function.actual;
   5316  1.1  mrg   dim_arg = array_arg->next;
   5317  1.1  mrg   mask_arg = dim_arg->next;
   5318  1.1  mrg   kind_arg = mask_arg->next;
   5319  1.1  mrg   back_arg = kind_arg->next;
   5320  1.1  mrg 
   5321  1.1  mrg   /* Remove kind.  */
   5322  1.1  mrg   if (kind_arg->expr)
   5323  1.1  mrg     {
   5324  1.1  mrg       gfc_free_expr (kind_arg->expr);
   5325  1.1  mrg       kind_arg->expr = NULL;
   5326  1.1  mrg     }
   5327  1.1  mrg 
   5328  1.1  mrg   /* Pass BACK argument by value.  */
   5329  1.1  mrg   back_arg->name = "%VAL";
   5330  1.1  mrg 
   5331  1.1  mrg   if (se->ss)
   5332  1.1  mrg     {
   5333  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   5334  1.1  mrg       return;
   5335  1.1  mrg     }
   5336  1.1  mrg 
   5337  1.1  mrg   arrayexpr = array_arg->expr;
   5338  1.1  mrg 
   5339  1.1  mrg   /* Special case for character maxloc.  Remove unneeded "dim" actual
   5340  1.1  mrg      argument, then call a library function.  */
   5341  1.1  mrg 
   5342  1.1  mrg   if (arrayexpr->ts.type == BT_CHARACTER)
   5343  1.1  mrg     {
   5344  1.1  mrg       if (dim_arg->expr)
   5345  1.1  mrg 	{
   5346  1.1  mrg 	  gfc_free_expr (dim_arg->expr);
   5347  1.1  mrg 	  dim_arg->expr = NULL;
   5348  1.1  mrg 	}
   5349  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   5350  1.1  mrg       return;
   5351  1.1  mrg     }
   5352  1.1  mrg 
   5353  1.1  mrg   /* Initialize the result.  */
   5354  1.1  mrg   pos = gfc_create_var (gfc_array_index_type, "pos");
   5355  1.1  mrg   offset = gfc_create_var (gfc_array_index_type, "offset");
   5356  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   5357  1.1  mrg 
   5358  1.1  mrg   /* Walk the arguments.  */
   5359  1.1  mrg   arrayss = gfc_walk_expr (arrayexpr);
   5360  1.1  mrg   gcc_assert (arrayss != gfc_ss_terminator);
   5361  1.1  mrg 
   5362  1.1  mrg   maskexpr = mask_arg->expr;
   5363  1.1  mrg   optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
   5364  1.1  mrg     && maskexpr->symtree->n.sym->attr.dummy
   5365  1.1  mrg     && maskexpr->symtree->n.sym->attr.optional;
   5366  1.1  mrg   backexpr = back_arg->expr;
   5367  1.1  mrg   nonempty = NULL;
   5368  1.1  mrg   if (maskexpr && maskexpr->rank != 0)
   5369  1.1  mrg     {
   5370  1.1  mrg       maskss = gfc_walk_expr (maskexpr);
   5371  1.1  mrg       gcc_assert (maskss != gfc_ss_terminator);
   5372  1.1  mrg     }
   5373  1.1  mrg   else
   5374  1.1  mrg     {
   5375  1.1  mrg       mpz_t asize;
   5376  1.1  mrg       if (gfc_array_size (arrayexpr, &asize))
   5377  1.1  mrg 	{
   5378  1.1  mrg 	  nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
   5379  1.1  mrg 	  mpz_clear (asize);
   5380  1.1  mrg 	  nonempty = fold_build2_loc (input_location, GT_EXPR,
   5381  1.1  mrg 				      logical_type_node, nonempty,
   5382  1.1  mrg 				      gfc_index_zero_node);
   5383  1.1  mrg 	}
   5384  1.1  mrg       maskss = NULL;
   5385  1.1  mrg     }
   5386  1.1  mrg 
   5387  1.1  mrg   limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
   5388  1.1  mrg   switch (arrayexpr->ts.type)
   5389  1.1  mrg     {
   5390  1.1  mrg     case BT_REAL:
   5391  1.1  mrg       tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
   5392  1.1  mrg       break;
   5393  1.1  mrg 
   5394  1.1  mrg     case BT_INTEGER:
   5395  1.1  mrg       n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
   5396  1.1  mrg       tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
   5397  1.1  mrg 				  arrayexpr->ts.kind);
   5398  1.1  mrg       break;
   5399  1.1  mrg 
   5400  1.1  mrg     default:
   5401  1.1  mrg       gcc_unreachable ();
   5402  1.1  mrg     }
   5403  1.1  mrg 
   5404  1.1  mrg   /* We start with the most negative possible value for MAXLOC, and the most
   5405  1.1  mrg      positive possible value for MINLOC. The most negative possible value is
   5406  1.1  mrg      -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
   5407  1.1  mrg      possible value is HUGE in both cases.  */
   5408  1.1  mrg   if (op == GT_EXPR)
   5409  1.1  mrg     tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
   5410  1.1  mrg   if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
   5411  1.1  mrg     tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
   5412  1.1  mrg 			   build_int_cst (TREE_TYPE (tmp), 1));
   5413  1.1  mrg 
   5414  1.1  mrg   gfc_add_modify (&se->pre, limit, tmp);
   5415  1.1  mrg 
   5416  1.1  mrg   /* Initialize the scalarizer.  */
   5417  1.1  mrg   gfc_init_loopinfo (&loop);
   5418  1.1  mrg 
   5419  1.1  mrg   /* We add the mask first because the number of iterations is taken
   5420  1.1  mrg      from the last ss, and this breaks if an absent optional argument
   5421  1.1  mrg      is used for mask.  */
   5422  1.1  mrg 
   5423  1.1  mrg   if (maskss)
   5424  1.1  mrg     gfc_add_ss_to_loop (&loop, maskss);
   5425  1.1  mrg 
   5426  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss);
   5427  1.1  mrg 
   5428  1.1  mrg   /* Initialize the loop.  */
   5429  1.1  mrg   gfc_conv_ss_startstride (&loop);
   5430  1.1  mrg 
   5431  1.1  mrg   /* The code generated can have more than one loop in sequence (see the
   5432  1.1  mrg      comment at the function header).  This doesn't work well with the
   5433  1.1  mrg      scalarizer, which changes arrays' offset when the scalarization loops
   5434  1.1  mrg      are generated (see gfc_trans_preloop_setup).  Fortunately, {min,max}loc
   5435  1.1  mrg      are  currently inlined in the scalar case only (for which loop is of rank
   5436  1.1  mrg      one).  As there is no dependency to care about in that case, there is no
   5437  1.1  mrg      temporary, so that we can use the scalarizer temporary code to handle
   5438  1.1  mrg      multiple loops.  Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
   5439  1.1  mrg      with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
   5440  1.1  mrg      to restore offset.
   5441  1.1  mrg      TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
   5442  1.1  mrg      should eventually go away.  We could either create two loops properly,
   5443  1.1  mrg      or find another way to save/restore the array offsets between the two
   5444  1.1  mrg      loops (without conflicting with temporary management), or use a single
   5445  1.1  mrg      loop minmaxloc implementation.  See PR 31067.  */
   5446  1.1  mrg   loop.temp_dim = loop.dimen;
   5447  1.1  mrg   gfc_conv_loop_setup (&loop, &expr->where);
   5448  1.1  mrg 
   5449  1.1  mrg   gcc_assert (loop.dimen == 1);
   5450  1.1  mrg   if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
   5451  1.1  mrg     nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
   5452  1.1  mrg 				loop.from[0], loop.to[0]);
   5453  1.1  mrg 
   5454  1.1  mrg   lab1 = NULL;
   5455  1.1  mrg   lab2 = NULL;
   5456  1.1  mrg   /* Initialize the position to zero, following Fortran 2003.  We are free
   5457  1.1  mrg      to do this because Fortran 95 allows the result of an entirely false
   5458  1.1  mrg      mask to be processor dependent.  If we know at compile time the array
   5459  1.1  mrg      is non-empty and no MASK is used, we can initialize to 1 to simplify
   5460  1.1  mrg      the inner loop.  */
   5461  1.1  mrg   if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
   5462  1.1  mrg     gfc_add_modify (&loop.pre, pos,
   5463  1.1  mrg 		    fold_build3_loc (input_location, COND_EXPR,
   5464  1.1  mrg 				     gfc_array_index_type,
   5465  1.1  mrg 				     nonempty, gfc_index_one_node,
   5466  1.1  mrg 				     gfc_index_zero_node));
   5467  1.1  mrg   else
   5468  1.1  mrg     {
   5469  1.1  mrg       gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
   5470  1.1  mrg       lab1 = gfc_build_label_decl (NULL_TREE);
   5471  1.1  mrg       TREE_USED (lab1) = 1;
   5472  1.1  mrg       lab2 = gfc_build_label_decl (NULL_TREE);
   5473  1.1  mrg       TREE_USED (lab2) = 1;
   5474  1.1  mrg     }
   5475  1.1  mrg 
   5476  1.1  mrg   /* An offset must be added to the loop
   5477  1.1  mrg      counter to obtain the required position.  */
   5478  1.1  mrg   gcc_assert (loop.from[0]);
   5479  1.1  mrg 
   5480  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   5481  1.1  mrg 			 gfc_index_one_node, loop.from[0]);
   5482  1.1  mrg   gfc_add_modify (&loop.pre, offset, tmp);
   5483  1.1  mrg 
   5484  1.1  mrg   gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
   5485  1.1  mrg   if (maskss)
   5486  1.1  mrg     gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
   5487  1.1  mrg   /* Generate the loop body.  */
   5488  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   5489  1.1  mrg 
   5490  1.1  mrg   /* If we have a mask, only check this element if the mask is set.  */
   5491  1.1  mrg   if (maskss)
   5492  1.1  mrg     {
   5493  1.1  mrg       gfc_init_se (&maskse, NULL);
   5494  1.1  mrg       gfc_copy_loopinfo_to_se (&maskse, &loop);
   5495  1.1  mrg       maskse.ss = maskss;
   5496  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   5497  1.1  mrg       gfc_add_block_to_block (&body, &maskse.pre);
   5498  1.1  mrg 
   5499  1.1  mrg       gfc_start_block (&block);
   5500  1.1  mrg     }
   5501  1.1  mrg   else
   5502  1.1  mrg     gfc_init_block (&block);
   5503  1.1  mrg 
   5504  1.1  mrg   /* Compare with the current limit.  */
   5505  1.1  mrg   gfc_init_se (&arrayse, NULL);
   5506  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   5507  1.1  mrg   arrayse.ss = arrayss;
   5508  1.1  mrg   gfc_conv_expr_val (&arrayse, arrayexpr);
   5509  1.1  mrg   gfc_add_block_to_block (&block, &arrayse.pre);
   5510  1.1  mrg 
   5511  1.1  mrg   gfc_init_se (&backse, NULL);
   5512  1.1  mrg   gfc_conv_expr_val (&backse, backexpr);
   5513  1.1  mrg   gfc_add_block_to_block (&block, &backse.pre);
   5514  1.1  mrg 
   5515  1.1  mrg   /* We do the following if this is a more extreme value.  */
   5516  1.1  mrg   gfc_start_block (&ifblock);
   5517  1.1  mrg 
   5518  1.1  mrg   /* Assign the value to the limit...  */
   5519  1.1  mrg   gfc_add_modify (&ifblock, limit, arrayse.expr);
   5520  1.1  mrg 
   5521  1.1  mrg   if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
   5522  1.1  mrg     {
   5523  1.1  mrg       stmtblock_t ifblock2;
   5524  1.1  mrg       tree ifbody2;
   5525  1.1  mrg 
   5526  1.1  mrg       gfc_start_block (&ifblock2);
   5527  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
   5528  1.1  mrg 			     loop.loopvar[0], offset);
   5529  1.1  mrg       gfc_add_modify (&ifblock2, pos, tmp);
   5530  1.1  mrg       ifbody2 = gfc_finish_block (&ifblock2);
   5531  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
   5532  1.1  mrg 			      gfc_index_zero_node);
   5533  1.1  mrg       tmp = build3_v (COND_EXPR, cond, ifbody2,
   5534  1.1  mrg 		      build_empty_stmt (input_location));
   5535  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5536  1.1  mrg     }
   5537  1.1  mrg 
   5538  1.1  mrg   tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
   5539  1.1  mrg 			 loop.loopvar[0], offset);
   5540  1.1  mrg   gfc_add_modify (&ifblock, pos, tmp);
   5541  1.1  mrg 
   5542  1.1  mrg   if (lab1)
   5543  1.1  mrg     gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
   5544  1.1  mrg 
   5545  1.1  mrg   ifbody = gfc_finish_block (&ifblock);
   5546  1.1  mrg 
   5547  1.1  mrg   if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
   5548  1.1  mrg     {
   5549  1.1  mrg       if (lab1)
   5550  1.1  mrg 	cond = fold_build2_loc (input_location,
   5551  1.1  mrg 				op == GT_EXPR ? GE_EXPR : LE_EXPR,
   5552  1.1  mrg 				logical_type_node, arrayse.expr, limit);
   5553  1.1  mrg       else
   5554  1.1  mrg 	{
   5555  1.1  mrg 	  tree ifbody2, elsebody2;
   5556  1.1  mrg 
   5557  1.1  mrg 	  /* We switch to > or >= depending on the value of the BACK argument. */
   5558  1.1  mrg 	  cond = gfc_create_var (logical_type_node, "cond");
   5559  1.1  mrg 
   5560  1.1  mrg 	  gfc_start_block (&ifblock);
   5561  1.1  mrg 	  b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
   5562  1.1  mrg 				  logical_type_node, arrayse.expr, limit);
   5563  1.1  mrg 
   5564  1.1  mrg 	  gfc_add_modify (&ifblock, cond, b_if);
   5565  1.1  mrg 	  ifbody2 = gfc_finish_block (&ifblock);
   5566  1.1  mrg 
   5567  1.1  mrg 	  gfc_start_block (&elseblock);
   5568  1.1  mrg 	  b_else = fold_build2_loc (input_location, op, logical_type_node,
   5569  1.1  mrg 				    arrayse.expr, limit);
   5570  1.1  mrg 
   5571  1.1  mrg 	  gfc_add_modify (&elseblock, cond, b_else);
   5572  1.1  mrg 	  elsebody2 = gfc_finish_block (&elseblock);
   5573  1.1  mrg 
   5574  1.1  mrg 	  tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
   5575  1.1  mrg 				 backse.expr, ifbody2, elsebody2);
   5576  1.1  mrg 
   5577  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   5578  1.1  mrg 	}
   5579  1.1  mrg 
   5580  1.1  mrg       cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
   5581  1.1  mrg       ifbody = build3_v (COND_EXPR, cond, ifbody,
   5582  1.1  mrg 			 build_empty_stmt (input_location));
   5583  1.1  mrg     }
   5584  1.1  mrg   gfc_add_expr_to_block (&block, ifbody);
   5585  1.1  mrg 
   5586  1.1  mrg   if (maskss)
   5587  1.1  mrg     {
   5588  1.1  mrg       /* We enclose the above in if (mask) {...}.  If the mask is an
   5589  1.1  mrg 	 optional argument, generate IF (.NOT. PRESENT(MASK)
   5590  1.1  mrg 	 .OR. MASK(I)). */
   5591  1.1  mrg 
   5592  1.1  mrg       tree ifmask;
   5593  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5594  1.1  mrg       tmp = gfc_finish_block (&block);
   5595  1.1  mrg       tmp = build3_v (COND_EXPR, ifmask, tmp,
   5596  1.1  mrg 		      build_empty_stmt (input_location));
   5597  1.1  mrg     }
   5598  1.1  mrg   else
   5599  1.1  mrg     tmp = gfc_finish_block (&block);
   5600  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   5601  1.1  mrg 
   5602  1.1  mrg   if (lab1)
   5603  1.1  mrg     {
   5604  1.1  mrg       gfc_trans_scalarized_loop_boundary (&loop, &body);
   5605  1.1  mrg 
   5606  1.1  mrg       if (HONOR_NANS (DECL_MODE (limit)))
   5607  1.1  mrg 	{
   5608  1.1  mrg 	  if (nonempty != NULL)
   5609  1.1  mrg 	    {
   5610  1.1  mrg 	      ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
   5611  1.1  mrg 	      tmp = build3_v (COND_EXPR, nonempty, ifbody,
   5612  1.1  mrg 			      build_empty_stmt (input_location));
   5613  1.1  mrg 	      gfc_add_expr_to_block (&loop.code[0], tmp);
   5614  1.1  mrg 	    }
   5615  1.1  mrg 	}
   5616  1.1  mrg 
   5617  1.1  mrg       gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
   5618  1.1  mrg       gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
   5619  1.1  mrg 
   5620  1.1  mrg       /* If we have a mask, only check this element if the mask is set.  */
   5621  1.1  mrg       if (maskss)
   5622  1.1  mrg 	{
   5623  1.1  mrg 	  gfc_init_se (&maskse, NULL);
   5624  1.1  mrg 	  gfc_copy_loopinfo_to_se (&maskse, &loop);
   5625  1.1  mrg 	  maskse.ss = maskss;
   5626  1.1  mrg 	  gfc_conv_expr_val (&maskse, maskexpr);
   5627  1.1  mrg 	  gfc_add_block_to_block (&body, &maskse.pre);
   5628  1.1  mrg 
   5629  1.1  mrg 	  gfc_start_block (&block);
   5630  1.1  mrg 	}
   5631  1.1  mrg       else
   5632  1.1  mrg 	gfc_init_block (&block);
   5633  1.1  mrg 
   5634  1.1  mrg       /* Compare with the current limit.  */
   5635  1.1  mrg       gfc_init_se (&arrayse, NULL);
   5636  1.1  mrg       gfc_copy_loopinfo_to_se (&arrayse, &loop);
   5637  1.1  mrg       arrayse.ss = arrayss;
   5638  1.1  mrg       gfc_conv_expr_val (&arrayse, arrayexpr);
   5639  1.1  mrg       gfc_add_block_to_block (&block, &arrayse.pre);
   5640  1.1  mrg 
   5641  1.1  mrg       /* We do the following if this is a more extreme value.  */
   5642  1.1  mrg       gfc_start_block (&ifblock);
   5643  1.1  mrg 
   5644  1.1  mrg       /* Assign the value to the limit...  */
   5645  1.1  mrg       gfc_add_modify (&ifblock, limit, arrayse.expr);
   5646  1.1  mrg 
   5647  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
   5648  1.1  mrg 			     loop.loopvar[0], offset);
   5649  1.1  mrg       gfc_add_modify (&ifblock, pos, tmp);
   5650  1.1  mrg 
   5651  1.1  mrg       ifbody = gfc_finish_block (&ifblock);
   5652  1.1  mrg 
   5653  1.1  mrg       /* We switch to > or >= depending on the value of the BACK argument. */
   5654  1.1  mrg       {
   5655  1.1  mrg 	tree ifbody2, elsebody2;
   5656  1.1  mrg 
   5657  1.1  mrg 	cond = gfc_create_var (logical_type_node, "cond");
   5658  1.1  mrg 
   5659  1.1  mrg 	gfc_start_block (&ifblock);
   5660  1.1  mrg 	b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
   5661  1.1  mrg 				logical_type_node, arrayse.expr, limit);
   5662  1.1  mrg 
   5663  1.1  mrg 	gfc_add_modify (&ifblock, cond, b_if);
   5664  1.1  mrg 	ifbody2 = gfc_finish_block (&ifblock);
   5665  1.1  mrg 
   5666  1.1  mrg 	gfc_start_block (&elseblock);
   5667  1.1  mrg 	b_else = fold_build2_loc (input_location, op, logical_type_node,
   5668  1.1  mrg 				  arrayse.expr, limit);
   5669  1.1  mrg 
   5670  1.1  mrg 	gfc_add_modify (&elseblock, cond, b_else);
   5671  1.1  mrg 	elsebody2 = gfc_finish_block (&elseblock);
   5672  1.1  mrg 
   5673  1.1  mrg 	tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
   5674  1.1  mrg 			       backse.expr, ifbody2, elsebody2);
   5675  1.1  mrg       }
   5676  1.1  mrg 
   5677  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5678  1.1  mrg       cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
   5679  1.1  mrg       tmp = build3_v (COND_EXPR, cond, ifbody,
   5680  1.1  mrg 		      build_empty_stmt (input_location));
   5681  1.1  mrg 
   5682  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5683  1.1  mrg 
   5684  1.1  mrg       if (maskss)
   5685  1.1  mrg 	{
   5686  1.1  mrg 	  /* We enclose the above in if (mask) {...}.  If the mask is
   5687  1.1  mrg 	 an optional argument, generate IF (.NOT. PRESENT(MASK)
   5688  1.1  mrg 	 .OR. MASK(I)).*/
   5689  1.1  mrg 
   5690  1.1  mrg 	  tree ifmask;
   5691  1.1  mrg 	  ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5692  1.1  mrg 	  tmp = gfc_finish_block (&block);
   5693  1.1  mrg 	  tmp = build3_v (COND_EXPR, ifmask, tmp,
   5694  1.1  mrg 			  build_empty_stmt (input_location));
   5695  1.1  mrg 	}
   5696  1.1  mrg       else
   5697  1.1  mrg 	tmp = gfc_finish_block (&block);
   5698  1.1  mrg       gfc_add_expr_to_block (&body, tmp);
   5699  1.1  mrg       /* Avoid initializing loopvar[0] again, it should be left where
   5700  1.1  mrg 	 it finished by the first loop.  */
   5701  1.1  mrg       loop.from[0] = loop.loopvar[0];
   5702  1.1  mrg     }
   5703  1.1  mrg 
   5704  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   5705  1.1  mrg 
   5706  1.1  mrg   if (lab2)
   5707  1.1  mrg     gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
   5708  1.1  mrg 
   5709  1.1  mrg   /* For a scalar mask, enclose the loop in an if statement.  */
   5710  1.1  mrg   if (maskexpr && maskss == NULL)
   5711  1.1  mrg     {
   5712  1.1  mrg       tree ifmask;
   5713  1.1  mrg 
   5714  1.1  mrg       gfc_init_se (&maskse, NULL);
   5715  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   5716  1.1  mrg       gfc_init_block (&block);
   5717  1.1  mrg       gfc_add_block_to_block (&block, &loop.pre);
   5718  1.1  mrg       gfc_add_block_to_block (&block, &loop.post);
   5719  1.1  mrg       tmp = gfc_finish_block (&block);
   5720  1.1  mrg 
   5721  1.1  mrg       /* For the else part of the scalar mask, just initialize
   5722  1.1  mrg 	 the pos variable the same way as above.  */
   5723  1.1  mrg 
   5724  1.1  mrg       gfc_init_block (&elseblock);
   5725  1.1  mrg       gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
   5726  1.1  mrg       elsetmp = gfc_finish_block (&elseblock);
   5727  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5728  1.1  mrg       tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
   5729  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5730  1.1  mrg       gfc_add_block_to_block (&se->pre, &block);
   5731  1.1  mrg     }
   5732  1.1  mrg   else
   5733  1.1  mrg     {
   5734  1.1  mrg       gfc_add_block_to_block (&se->pre, &loop.pre);
   5735  1.1  mrg       gfc_add_block_to_block (&se->pre, &loop.post);
   5736  1.1  mrg     }
   5737  1.1  mrg   gfc_cleanup_loop (&loop);
   5738  1.1  mrg 
   5739  1.1  mrg   se->expr = convert (type, pos);
   5740  1.1  mrg }
   5741  1.1  mrg 
   5742  1.1  mrg /* Emit code for findloc.  */
   5743  1.1  mrg 
   5744  1.1  mrg static void
   5745  1.1  mrg gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
   5746  1.1  mrg {
   5747  1.1  mrg   gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
   5748  1.1  mrg     *kind_arg, *back_arg;
   5749  1.1  mrg   gfc_expr *value_expr;
   5750  1.1  mrg   int ikind;
   5751  1.1  mrg   tree resvar;
   5752  1.1  mrg   stmtblock_t block;
   5753  1.1  mrg   stmtblock_t body;
   5754  1.1  mrg   stmtblock_t loopblock;
   5755  1.1  mrg   tree type;
   5756  1.1  mrg   tree tmp;
   5757  1.1  mrg   tree found;
   5758  1.1  mrg   tree forward_branch = NULL_TREE;
   5759  1.1  mrg   tree back_branch;
   5760  1.1  mrg   gfc_loopinfo loop;
   5761  1.1  mrg   gfc_ss *arrayss;
   5762  1.1  mrg   gfc_ss *maskss;
   5763  1.1  mrg   gfc_se arrayse;
   5764  1.1  mrg   gfc_se valuese;
   5765  1.1  mrg   gfc_se maskse;
   5766  1.1  mrg   gfc_se backse;
   5767  1.1  mrg   tree exit_label;
   5768  1.1  mrg   gfc_expr *maskexpr;
   5769  1.1  mrg   tree offset;
   5770  1.1  mrg   int i;
   5771  1.1  mrg   bool optional_mask;
   5772  1.1  mrg 
   5773  1.1  mrg   array_arg = expr->value.function.actual;
   5774  1.1  mrg   value_arg = array_arg->next;
   5775  1.1  mrg   dim_arg   = value_arg->next;
   5776  1.1  mrg   mask_arg  = dim_arg->next;
   5777  1.1  mrg   kind_arg  = mask_arg->next;
   5778  1.1  mrg   back_arg  = kind_arg->next;
   5779  1.1  mrg 
   5780  1.1  mrg   /* Remove kind and set ikind.  */
   5781  1.1  mrg   if (kind_arg->expr)
   5782  1.1  mrg     {
   5783  1.1  mrg       ikind = mpz_get_si (kind_arg->expr->value.integer);
   5784  1.1  mrg       gfc_free_expr (kind_arg->expr);
   5785  1.1  mrg       kind_arg->expr = NULL;
   5786  1.1  mrg     }
   5787  1.1  mrg   else
   5788  1.1  mrg     ikind = gfc_default_integer_kind;
   5789  1.1  mrg 
   5790  1.1  mrg   value_expr = value_arg->expr;
   5791  1.1  mrg 
   5792  1.1  mrg   /* Unless it's a string, pass VALUE by value.  */
   5793  1.1  mrg   if (value_expr->ts.type != BT_CHARACTER)
   5794  1.1  mrg     value_arg->name = "%VAL";
   5795  1.1  mrg 
   5796  1.1  mrg   /* Pass BACK argument by value.  */
   5797  1.1  mrg   back_arg->name = "%VAL";
   5798  1.1  mrg 
   5799  1.1  mrg   /* Call the library if we have a character function or if
   5800  1.1  mrg      rank > 0.  */
   5801  1.1  mrg   if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
   5802  1.1  mrg     {
   5803  1.1  mrg       se->ignore_optional = 1;
   5804  1.1  mrg       if (expr->rank == 0)
   5805  1.1  mrg 	{
   5806  1.1  mrg 	  /* Remove dim argument.  */
   5807  1.1  mrg 	  gfc_free_expr (dim_arg->expr);
   5808  1.1  mrg 	  dim_arg->expr = NULL;
   5809  1.1  mrg 	}
   5810  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   5811  1.1  mrg       return;
   5812  1.1  mrg     }
   5813  1.1  mrg 
   5814  1.1  mrg   type = gfc_get_int_type (ikind);
   5815  1.1  mrg 
   5816  1.1  mrg   /* Initialize the result.  */
   5817  1.1  mrg   resvar = gfc_create_var (gfc_array_index_type, "pos");
   5818  1.1  mrg   gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
   5819  1.1  mrg   offset = gfc_create_var (gfc_array_index_type, "offset");
   5820  1.1  mrg 
   5821  1.1  mrg   maskexpr = mask_arg->expr;
   5822  1.1  mrg   optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
   5823  1.1  mrg     && maskexpr->symtree->n.sym->attr.dummy
   5824  1.1  mrg     && maskexpr->symtree->n.sym->attr.optional;
   5825  1.1  mrg 
   5826  1.1  mrg   /*  Generate two loops, one for BACK=.true. and one for BACK=.false.  */
   5827  1.1  mrg 
   5828  1.1  mrg   for (i = 0 ; i < 2; i++)
   5829  1.1  mrg     {
   5830  1.1  mrg       /* Walk the arguments.  */
   5831  1.1  mrg       arrayss = gfc_walk_expr (array_arg->expr);
   5832  1.1  mrg       gcc_assert (arrayss != gfc_ss_terminator);
   5833  1.1  mrg 
   5834  1.1  mrg       if (maskexpr && maskexpr->rank != 0)
   5835  1.1  mrg 	{
   5836  1.1  mrg 	  maskss = gfc_walk_expr (maskexpr);
   5837  1.1  mrg 	  gcc_assert (maskss != gfc_ss_terminator);
   5838  1.1  mrg 	}
   5839  1.1  mrg       else
   5840  1.1  mrg 	maskss = NULL;
   5841  1.1  mrg 
   5842  1.1  mrg       /* Initialize the scalarizer.  */
   5843  1.1  mrg       gfc_init_loopinfo (&loop);
   5844  1.1  mrg       exit_label = gfc_build_label_decl (NULL_TREE);
   5845  1.1  mrg       TREE_USED (exit_label) = 1;
   5846  1.1  mrg 
   5847  1.1  mrg       /* We add the mask first because the number of iterations is
   5848  1.1  mrg 	 taken from the last ss, and this breaks if an absent
   5849  1.1  mrg 	 optional argument is used for mask.  */
   5850  1.1  mrg 
   5851  1.1  mrg       if (maskss)
   5852  1.1  mrg 	gfc_add_ss_to_loop (&loop, maskss);
   5853  1.1  mrg       gfc_add_ss_to_loop (&loop, arrayss);
   5854  1.1  mrg 
   5855  1.1  mrg       /* Initialize the loop.  */
   5856  1.1  mrg       gfc_conv_ss_startstride (&loop);
   5857  1.1  mrg       gfc_conv_loop_setup (&loop, &expr->where);
   5858  1.1  mrg 
   5859  1.1  mrg       /* Calculate the offset.  */
   5860  1.1  mrg       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   5861  1.1  mrg 			     gfc_index_one_node, loop.from[0]);
   5862  1.1  mrg       gfc_add_modify (&loop.pre, offset, tmp);
   5863  1.1  mrg 
   5864  1.1  mrg       gfc_mark_ss_chain_used (arrayss, 1);
   5865  1.1  mrg       if (maskss)
   5866  1.1  mrg 	gfc_mark_ss_chain_used (maskss, 1);
   5867  1.1  mrg 
   5868  1.1  mrg       /* The first loop is for BACK=.true.  */
   5869  1.1  mrg       if (i == 0)
   5870  1.1  mrg 	loop.reverse[0] = GFC_REVERSE_SET;
   5871  1.1  mrg 
   5872  1.1  mrg       /* Generate the loop body.  */
   5873  1.1  mrg       gfc_start_scalarized_body (&loop, &body);
   5874  1.1  mrg 
   5875  1.1  mrg       /* If we have an array mask, only add the element if it is
   5876  1.1  mrg 	 set.  */
   5877  1.1  mrg       if (maskss)
   5878  1.1  mrg 	{
   5879  1.1  mrg 	  gfc_init_se (&maskse, NULL);
   5880  1.1  mrg 	  gfc_copy_loopinfo_to_se (&maskse, &loop);
   5881  1.1  mrg 	  maskse.ss = maskss;
   5882  1.1  mrg 	  gfc_conv_expr_val (&maskse, maskexpr);
   5883  1.1  mrg 	  gfc_add_block_to_block (&body, &maskse.pre);
   5884  1.1  mrg 	}
   5885  1.1  mrg 
   5886  1.1  mrg       /* If the condition matches then set the return value.  */
   5887  1.1  mrg       gfc_start_block (&block);
   5888  1.1  mrg 
   5889  1.1  mrg       /* Add the offset.  */
   5890  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR,
   5891  1.1  mrg 			     TREE_TYPE (resvar),
   5892  1.1  mrg 			     loop.loopvar[0], offset);
   5893  1.1  mrg       gfc_add_modify (&block, resvar, tmp);
   5894  1.1  mrg       /* And break out of the loop.  */
   5895  1.1  mrg       tmp = build1_v (GOTO_EXPR, exit_label);
   5896  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   5897  1.1  mrg 
   5898  1.1  mrg       found = gfc_finish_block (&block);
   5899  1.1  mrg 
   5900  1.1  mrg       /* Check this element.  */
   5901  1.1  mrg       gfc_init_se (&arrayse, NULL);
   5902  1.1  mrg       gfc_copy_loopinfo_to_se (&arrayse, &loop);
   5903  1.1  mrg       arrayse.ss = arrayss;
   5904  1.1  mrg       gfc_conv_expr_val (&arrayse, array_arg->expr);
   5905  1.1  mrg       gfc_add_block_to_block (&body, &arrayse.pre);
   5906  1.1  mrg 
   5907  1.1  mrg       gfc_init_se (&valuese, NULL);
   5908  1.1  mrg       gfc_conv_expr_val (&valuese, value_arg->expr);
   5909  1.1  mrg       gfc_add_block_to_block (&body, &valuese.pre);
   5910  1.1  mrg 
   5911  1.1  mrg       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   5912  1.1  mrg 			     arrayse.expr, valuese.expr);
   5913  1.1  mrg 
   5914  1.1  mrg       tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
   5915  1.1  mrg       if (maskss)
   5916  1.1  mrg 	{
   5917  1.1  mrg 	  /* We enclose the above in if (mask) {...}.  If the mask is
   5918  1.1  mrg 	     an optional argument, generate IF (.NOT. PRESENT(MASK)
   5919  1.1  mrg 	     .OR. MASK(I)). */
   5920  1.1  mrg 
   5921  1.1  mrg 	  tree ifmask;
   5922  1.1  mrg 	  ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5923  1.1  mrg 	  tmp = build3_v (COND_EXPR, ifmask, tmp,
   5924  1.1  mrg 			  build_empty_stmt (input_location));
   5925  1.1  mrg 	}
   5926  1.1  mrg 
   5927  1.1  mrg       gfc_add_expr_to_block (&body, tmp);
   5928  1.1  mrg       gfc_add_block_to_block (&body, &arrayse.post);
   5929  1.1  mrg 
   5930  1.1  mrg       gfc_trans_scalarizing_loops (&loop, &body);
   5931  1.1  mrg 
   5932  1.1  mrg       /* Add the exit label.  */
   5933  1.1  mrg       tmp = build1_v (LABEL_EXPR, exit_label);
   5934  1.1  mrg       gfc_add_expr_to_block (&loop.pre, tmp);
   5935  1.1  mrg       gfc_start_block (&loopblock);
   5936  1.1  mrg       gfc_add_block_to_block (&loopblock, &loop.pre);
   5937  1.1  mrg       gfc_add_block_to_block (&loopblock, &loop.post);
   5938  1.1  mrg       if (i == 0)
   5939  1.1  mrg 	forward_branch = gfc_finish_block (&loopblock);
   5940  1.1  mrg       else
   5941  1.1  mrg 	back_branch = gfc_finish_block (&loopblock);
   5942  1.1  mrg 
   5943  1.1  mrg       gfc_cleanup_loop (&loop);
   5944  1.1  mrg     }
   5945  1.1  mrg 
   5946  1.1  mrg   /* Enclose the two loops in an IF statement.  */
   5947  1.1  mrg 
   5948  1.1  mrg   gfc_init_se (&backse, NULL);
   5949  1.1  mrg   gfc_conv_expr_val (&backse, back_arg->expr);
   5950  1.1  mrg   gfc_add_block_to_block (&se->pre, &backse.pre);
   5951  1.1  mrg   tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
   5952  1.1  mrg 
   5953  1.1  mrg   /* For a scalar mask, enclose the loop in an if statement.  */
   5954  1.1  mrg   if (maskexpr && maskss == NULL)
   5955  1.1  mrg     {
   5956  1.1  mrg       tree ifmask;
   5957  1.1  mrg       tree if_stmt;
   5958  1.1  mrg 
   5959  1.1  mrg       gfc_init_se (&maskse, NULL);
   5960  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   5961  1.1  mrg       gfc_init_block (&block);
   5962  1.1  mrg       gfc_add_expr_to_block (&block, maskse.expr);
   5963  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   5964  1.1  mrg       if_stmt = build3_v (COND_EXPR, ifmask, tmp,
   5965  1.1  mrg 			  build_empty_stmt (input_location));
   5966  1.1  mrg       gfc_add_expr_to_block (&block, if_stmt);
   5967  1.1  mrg       tmp = gfc_finish_block (&block);
   5968  1.1  mrg     }
   5969  1.1  mrg 
   5970  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   5971  1.1  mrg   se->expr = convert (type, resvar);
   5972  1.1  mrg 
   5973  1.1  mrg }
   5974  1.1  mrg 
   5975  1.1  mrg /* Emit code for minval or maxval intrinsic.  There are many different cases
   5976  1.1  mrg    we need to handle.  For performance reasons we sometimes create two
   5977  1.1  mrg    loops instead of one, where the second one is much simpler.
   5978  1.1  mrg    Examples for minval intrinsic:
   5979  1.1  mrg    1) Result is an array, a call is generated
   5980  1.1  mrg    2) Array mask is used and NaNs need to be supported, rank 1:
   5981  1.1  mrg       limit = Infinity;
   5982  1.1  mrg       nonempty = false;
   5983  1.1  mrg       S = from;
   5984  1.1  mrg       while (S <= to) {
   5985  1.1  mrg 	if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
   5986  1.1  mrg 	S++;
   5987  1.1  mrg       }
   5988  1.1  mrg       limit = nonempty ? NaN : huge (limit);
   5989  1.1  mrg       lab:
   5990  1.1  mrg       while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
   5991  1.1  mrg    3) NaNs need to be supported, but it is known at compile time or cheaply
   5992  1.1  mrg       at runtime whether array is nonempty or not, rank 1:
   5993  1.1  mrg       limit = Infinity;
   5994  1.1  mrg       S = from;
   5995  1.1  mrg       while (S <= to) { if (a[S] <= limit) goto lab; S++; }
   5996  1.1  mrg       limit = (from <= to) ? NaN : huge (limit);
   5997  1.1  mrg       lab:
   5998  1.1  mrg       while (S <= to) { limit = min (a[S], limit); S++; }
   5999  1.1  mrg    4) Array mask is used and NaNs need to be supported, rank > 1:
   6000  1.1  mrg       limit = Infinity;
   6001  1.1  mrg       nonempty = false;
   6002  1.1  mrg       fast = false;
   6003  1.1  mrg       S1 = from1;
   6004  1.1  mrg       while (S1 <= to1) {
   6005  1.1  mrg 	S2 = from2;
   6006  1.1  mrg 	while (S2 <= to2) {
   6007  1.1  mrg 	  if (mask[S1][S2]) {
   6008  1.1  mrg 	    if (fast) limit = min (a[S1][S2], limit);
   6009  1.1  mrg 	    else {
   6010  1.1  mrg 	      nonempty = true;
   6011  1.1  mrg 	      if (a[S1][S2] <= limit) {
   6012  1.1  mrg 		limit = a[S1][S2];
   6013  1.1  mrg 		fast = true;
   6014  1.1  mrg 	      }
   6015  1.1  mrg 	    }
   6016  1.1  mrg 	  }
   6017  1.1  mrg 	  S2++;
   6018  1.1  mrg 	}
   6019  1.1  mrg 	S1++;
   6020  1.1  mrg       }
   6021  1.1  mrg       if (!fast)
   6022  1.1  mrg 	limit = nonempty ? NaN : huge (limit);
   6023  1.1  mrg    5) NaNs need to be supported, but it is known at compile time or cheaply
   6024  1.1  mrg       at runtime whether array is nonempty or not, rank > 1:
   6025  1.1  mrg       limit = Infinity;
   6026  1.1  mrg       fast = false;
   6027  1.1  mrg       S1 = from1;
   6028  1.1  mrg       while (S1 <= to1) {
   6029  1.1  mrg 	S2 = from2;
   6030  1.1  mrg 	while (S2 <= to2) {
   6031  1.1  mrg 	  if (fast) limit = min (a[S1][S2], limit);
   6032  1.1  mrg 	  else {
   6033  1.1  mrg 	    if (a[S1][S2] <= limit) {
   6034  1.1  mrg 	      limit = a[S1][S2];
   6035  1.1  mrg 	      fast = true;
   6036  1.1  mrg 	    }
   6037  1.1  mrg 	  }
   6038  1.1  mrg 	  S2++;
   6039  1.1  mrg 	}
   6040  1.1  mrg 	S1++;
   6041  1.1  mrg       }
   6042  1.1  mrg       if (!fast)
   6043  1.1  mrg 	limit = (nonempty_array) ? NaN : huge (limit);
   6044  1.1  mrg    6) NaNs aren't supported, but infinities are.  Array mask is used:
   6045  1.1  mrg       limit = Infinity;
   6046  1.1  mrg       nonempty = false;
   6047  1.1  mrg       S = from;
   6048  1.1  mrg       while (S <= to) {
   6049  1.1  mrg 	if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
   6050  1.1  mrg 	S++;
   6051  1.1  mrg       }
   6052  1.1  mrg       limit = nonempty ? limit : huge (limit);
   6053  1.1  mrg    7) Same without array mask:
   6054  1.1  mrg       limit = Infinity;
   6055  1.1  mrg       S = from;
   6056  1.1  mrg       while (S <= to) { limit = min (a[S], limit); S++; }
   6057  1.1  mrg       limit = (from <= to) ? limit : huge (limit);
   6058  1.1  mrg    8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
   6059  1.1  mrg       limit = huge (limit);
   6060  1.1  mrg       S = from;
   6061  1.1  mrg       while (S <= to) { limit = min (a[S], limit); S++); }
   6062  1.1  mrg       (or
   6063  1.1  mrg       while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
   6064  1.1  mrg       with array mask instead).
   6065  1.1  mrg    For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
   6066  1.1  mrg    setting limit = huge (limit); in the else branch.  */
   6067  1.1  mrg 
   6068  1.1  mrg static void
   6069  1.1  mrg gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
   6070  1.1  mrg {
   6071  1.1  mrg   tree limit;
   6072  1.1  mrg   tree type;
   6073  1.1  mrg   tree tmp;
   6074  1.1  mrg   tree ifbody;
   6075  1.1  mrg   tree nonempty;
   6076  1.1  mrg   tree nonempty_var;
   6077  1.1  mrg   tree lab;
   6078  1.1  mrg   tree fast;
   6079  1.1  mrg   tree huge_cst = NULL, nan_cst = NULL;
   6080  1.1  mrg   stmtblock_t body;
   6081  1.1  mrg   stmtblock_t block, block2;
   6082  1.1  mrg   gfc_loopinfo loop;
   6083  1.1  mrg   gfc_actual_arglist *actual;
   6084  1.1  mrg   gfc_ss *arrayss;
   6085  1.1  mrg   gfc_ss *maskss;
   6086  1.1  mrg   gfc_se arrayse;
   6087  1.1  mrg   gfc_se maskse;
   6088  1.1  mrg   gfc_expr *arrayexpr;
   6089  1.1  mrg   gfc_expr *maskexpr;
   6090  1.1  mrg   int n;
   6091  1.1  mrg   bool optional_mask;
   6092  1.1  mrg 
   6093  1.1  mrg   if (se->ss)
   6094  1.1  mrg     {
   6095  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   6096  1.1  mrg       return;
   6097  1.1  mrg     }
   6098  1.1  mrg 
   6099  1.1  mrg   actual = expr->value.function.actual;
   6100  1.1  mrg   arrayexpr = actual->expr;
   6101  1.1  mrg 
   6102  1.1  mrg   if (arrayexpr->ts.type == BT_CHARACTER)
   6103  1.1  mrg     {
   6104  1.1  mrg       gfc_actual_arglist *dim = actual->next;
   6105  1.1  mrg       if (expr->rank == 0 && dim->expr != 0)
   6106  1.1  mrg 	{
   6107  1.1  mrg 	  gfc_free_expr (dim->expr);
   6108  1.1  mrg 	  dim->expr = NULL;
   6109  1.1  mrg 	}
   6110  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   6111  1.1  mrg       return;
   6112  1.1  mrg     }
   6113  1.1  mrg 
   6114  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   6115  1.1  mrg   /* Initialize the result.  */
   6116  1.1  mrg   limit = gfc_create_var (type, "limit");
   6117  1.1  mrg   n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
   6118  1.1  mrg   switch (expr->ts.type)
   6119  1.1  mrg     {
   6120  1.1  mrg     case BT_REAL:
   6121  1.1  mrg       huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
   6122  1.1  mrg 					expr->ts.kind, 0);
   6123  1.1  mrg       if (HONOR_INFINITIES (DECL_MODE (limit)))
   6124  1.1  mrg 	{
   6125  1.1  mrg 	  REAL_VALUE_TYPE real;
   6126  1.1  mrg 	  real_inf (&real);
   6127  1.1  mrg 	  tmp = build_real (type, real);
   6128  1.1  mrg 	}
   6129  1.1  mrg       else
   6130  1.1  mrg 	tmp = huge_cst;
   6131  1.1  mrg       if (HONOR_NANS (DECL_MODE (limit)))
   6132  1.1  mrg 	nan_cst = gfc_build_nan (type, "");
   6133  1.1  mrg       break;
   6134  1.1  mrg 
   6135  1.1  mrg     case BT_INTEGER:
   6136  1.1  mrg       tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
   6137  1.1  mrg       break;
   6138  1.1  mrg 
   6139  1.1  mrg     default:
   6140  1.1  mrg       gcc_unreachable ();
   6141  1.1  mrg     }
   6142  1.1  mrg 
   6143  1.1  mrg   /* We start with the most negative possible value for MAXVAL, and the most
   6144  1.1  mrg      positive possible value for MINVAL. The most negative possible value is
   6145  1.1  mrg      -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
   6146  1.1  mrg      possible value is HUGE in both cases.  */
   6147  1.1  mrg   if (op == GT_EXPR)
   6148  1.1  mrg     {
   6149  1.1  mrg       tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
   6150  1.1  mrg       if (huge_cst)
   6151  1.1  mrg 	huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
   6152  1.1  mrg 				    TREE_TYPE (huge_cst), huge_cst);
   6153  1.1  mrg     }
   6154  1.1  mrg 
   6155  1.1  mrg   if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
   6156  1.1  mrg     tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
   6157  1.1  mrg 			   tmp, build_int_cst (type, 1));
   6158  1.1  mrg 
   6159  1.1  mrg   gfc_add_modify (&se->pre, limit, tmp);
   6160  1.1  mrg 
   6161  1.1  mrg   /* Walk the arguments.  */
   6162  1.1  mrg   arrayss = gfc_walk_expr (arrayexpr);
   6163  1.1  mrg   gcc_assert (arrayss != gfc_ss_terminator);
   6164  1.1  mrg 
   6165  1.1  mrg   actual = actual->next->next;
   6166  1.1  mrg   gcc_assert (actual);
   6167  1.1  mrg   maskexpr = actual->expr;
   6168  1.1  mrg   optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
   6169  1.1  mrg     && maskexpr->symtree->n.sym->attr.dummy
   6170  1.1  mrg     && maskexpr->symtree->n.sym->attr.optional;
   6171  1.1  mrg   nonempty = NULL;
   6172  1.1  mrg   if (maskexpr && maskexpr->rank != 0)
   6173  1.1  mrg     {
   6174  1.1  mrg       maskss = gfc_walk_expr (maskexpr);
   6175  1.1  mrg       gcc_assert (maskss != gfc_ss_terminator);
   6176  1.1  mrg     }
   6177  1.1  mrg   else
   6178  1.1  mrg     {
   6179  1.1  mrg       mpz_t asize;
   6180  1.1  mrg       if (gfc_array_size (arrayexpr, &asize))
   6181  1.1  mrg 	{
   6182  1.1  mrg 	  nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
   6183  1.1  mrg 	  mpz_clear (asize);
   6184  1.1  mrg 	  nonempty = fold_build2_loc (input_location, GT_EXPR,
   6185  1.1  mrg 				      logical_type_node, nonempty,
   6186  1.1  mrg 				      gfc_index_zero_node);
   6187  1.1  mrg 	}
   6188  1.1  mrg       maskss = NULL;
   6189  1.1  mrg     }
   6190  1.1  mrg 
   6191  1.1  mrg   /* Initialize the scalarizer.  */
   6192  1.1  mrg   gfc_init_loopinfo (&loop);
   6193  1.1  mrg 
   6194  1.1  mrg   /* We add the mask first because the number of iterations is taken
   6195  1.1  mrg      from the last ss, and this breaks if an absent optional argument
   6196  1.1  mrg      is used for mask.  */
   6197  1.1  mrg 
   6198  1.1  mrg   if (maskss)
   6199  1.1  mrg     gfc_add_ss_to_loop (&loop, maskss);
   6200  1.1  mrg   gfc_add_ss_to_loop (&loop, arrayss);
   6201  1.1  mrg 
   6202  1.1  mrg   /* Initialize the loop.  */
   6203  1.1  mrg   gfc_conv_ss_startstride (&loop);
   6204  1.1  mrg 
   6205  1.1  mrg   /* The code generated can have more than one loop in sequence (see the
   6206  1.1  mrg      comment at the function header).  This doesn't work well with the
   6207  1.1  mrg      scalarizer, which changes arrays' offset when the scalarization loops
   6208  1.1  mrg      are generated (see gfc_trans_preloop_setup).  Fortunately, {min,max}val
   6209  1.1  mrg      are  currently inlined in the scalar case only.  As there is no dependency
   6210  1.1  mrg      to care about in that case, there is no temporary, so that we can use the
   6211  1.1  mrg      scalarizer temporary code to handle multiple loops.  Thus, we set temp_dim
   6212  1.1  mrg      here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
   6213  1.1  mrg      gfc_trans_scalarized_loop_boundary even later to restore offset.
   6214  1.1  mrg      TODO: this prevents inlining of rank > 0 minmaxval calls, so this
   6215  1.1  mrg      should eventually go away.  We could either create two loops properly,
   6216  1.1  mrg      or find another way to save/restore the array offsets between the two
   6217  1.1  mrg      loops (without conflicting with temporary management), or use a single
   6218  1.1  mrg      loop minmaxval implementation.  See PR 31067.  */
   6219  1.1  mrg   loop.temp_dim = loop.dimen;
   6220  1.1  mrg   gfc_conv_loop_setup (&loop, &expr->where);
   6221  1.1  mrg 
   6222  1.1  mrg   if (nonempty == NULL && maskss == NULL
   6223  1.1  mrg       && loop.dimen == 1 && loop.from[0] && loop.to[0])
   6224  1.1  mrg     nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
   6225  1.1  mrg 				loop.from[0], loop.to[0]);
   6226  1.1  mrg   nonempty_var = NULL;
   6227  1.1  mrg   if (nonempty == NULL
   6228  1.1  mrg       && (HONOR_INFINITIES (DECL_MODE (limit))
   6229  1.1  mrg 	  || HONOR_NANS (DECL_MODE (limit))))
   6230  1.1  mrg     {
   6231  1.1  mrg       nonempty_var = gfc_create_var (logical_type_node, "nonempty");
   6232  1.1  mrg       gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
   6233  1.1  mrg       nonempty = nonempty_var;
   6234  1.1  mrg     }
   6235  1.1  mrg   lab = NULL;
   6236  1.1  mrg   fast = NULL;
   6237  1.1  mrg   if (HONOR_NANS (DECL_MODE (limit)))
   6238  1.1  mrg     {
   6239  1.1  mrg       if (loop.dimen == 1)
   6240  1.1  mrg 	{
   6241  1.1  mrg 	  lab = gfc_build_label_decl (NULL_TREE);
   6242  1.1  mrg 	  TREE_USED (lab) = 1;
   6243  1.1  mrg 	}
   6244  1.1  mrg       else
   6245  1.1  mrg 	{
   6246  1.1  mrg 	  fast = gfc_create_var (logical_type_node, "fast");
   6247  1.1  mrg 	  gfc_add_modify (&se->pre, fast, logical_false_node);
   6248  1.1  mrg 	}
   6249  1.1  mrg     }
   6250  1.1  mrg 
   6251  1.1  mrg   gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
   6252  1.1  mrg   if (maskss)
   6253  1.1  mrg     gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
   6254  1.1  mrg   /* Generate the loop body.  */
   6255  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   6256  1.1  mrg 
   6257  1.1  mrg   /* If we have a mask, only add this element if the mask is set.  */
   6258  1.1  mrg   if (maskss)
   6259  1.1  mrg     {
   6260  1.1  mrg       gfc_init_se (&maskse, NULL);
   6261  1.1  mrg       gfc_copy_loopinfo_to_se (&maskse, &loop);
   6262  1.1  mrg       maskse.ss = maskss;
   6263  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   6264  1.1  mrg       gfc_add_block_to_block (&body, &maskse.pre);
   6265  1.1  mrg 
   6266  1.1  mrg       gfc_start_block (&block);
   6267  1.1  mrg     }
   6268  1.1  mrg   else
   6269  1.1  mrg     gfc_init_block (&block);
   6270  1.1  mrg 
   6271  1.1  mrg   /* Compare with the current limit.  */
   6272  1.1  mrg   gfc_init_se (&arrayse, NULL);
   6273  1.1  mrg   gfc_copy_loopinfo_to_se (&arrayse, &loop);
   6274  1.1  mrg   arrayse.ss = arrayss;
   6275  1.1  mrg   gfc_conv_expr_val (&arrayse, arrayexpr);
   6276  1.1  mrg   gfc_add_block_to_block (&block, &arrayse.pre);
   6277  1.1  mrg 
   6278  1.1  mrg   gfc_init_block (&block2);
   6279  1.1  mrg 
   6280  1.1  mrg   if (nonempty_var)
   6281  1.1  mrg     gfc_add_modify (&block2, nonempty_var, logical_true_node);
   6282  1.1  mrg 
   6283  1.1  mrg   if (HONOR_NANS (DECL_MODE (limit)))
   6284  1.1  mrg     {
   6285  1.1  mrg       tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
   6286  1.1  mrg 			     logical_type_node, arrayse.expr, limit);
   6287  1.1  mrg       if (lab)
   6288  1.1  mrg 	ifbody = build1_v (GOTO_EXPR, lab);
   6289  1.1  mrg       else
   6290  1.1  mrg 	{
   6291  1.1  mrg 	  stmtblock_t ifblock;
   6292  1.1  mrg 
   6293  1.1  mrg 	  gfc_init_block (&ifblock);
   6294  1.1  mrg 	  gfc_add_modify (&ifblock, limit, arrayse.expr);
   6295  1.1  mrg 	  gfc_add_modify (&ifblock, fast, logical_true_node);
   6296  1.1  mrg 	  ifbody = gfc_finish_block (&ifblock);
   6297  1.1  mrg 	}
   6298  1.1  mrg       tmp = build3_v (COND_EXPR, tmp, ifbody,
   6299  1.1  mrg 		      build_empty_stmt (input_location));
   6300  1.1  mrg       gfc_add_expr_to_block (&block2, tmp);
   6301  1.1  mrg     }
   6302  1.1  mrg   else
   6303  1.1  mrg     {
   6304  1.1  mrg       /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
   6305  1.1  mrg 	 signed zeros.  */
   6306  1.1  mrg       tmp = fold_build2_loc (input_location,
   6307  1.1  mrg 			     op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
   6308  1.1  mrg 			     type, arrayse.expr, limit);
   6309  1.1  mrg       gfc_add_modify (&block2, limit, tmp);
   6310  1.1  mrg     }
   6311  1.1  mrg 
   6312  1.1  mrg   if (fast)
   6313  1.1  mrg     {
   6314  1.1  mrg       tree elsebody = gfc_finish_block (&block2);
   6315  1.1  mrg 
   6316  1.1  mrg       /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
   6317  1.1  mrg 	 signed zeros.  */
   6318  1.1  mrg       if (HONOR_NANS (DECL_MODE (limit)))
   6319  1.1  mrg 	{
   6320  1.1  mrg 	  tmp = fold_build2_loc (input_location, op, logical_type_node,
   6321  1.1  mrg 				 arrayse.expr, limit);
   6322  1.1  mrg 	  ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
   6323  1.1  mrg 	  ifbody = build3_v (COND_EXPR, tmp, ifbody,
   6324  1.1  mrg 			     build_empty_stmt (input_location));
   6325  1.1  mrg 	}
   6326  1.1  mrg       else
   6327  1.1  mrg 	{
   6328  1.1  mrg 	  tmp = fold_build2_loc (input_location,
   6329  1.1  mrg 				 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
   6330  1.1  mrg 				 type, arrayse.expr, limit);
   6331  1.1  mrg 	  ifbody = build2_v (MODIFY_EXPR, limit, tmp);
   6332  1.1  mrg 	}
   6333  1.1  mrg       tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
   6334  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   6335  1.1  mrg     }
   6336  1.1  mrg   else
   6337  1.1  mrg     gfc_add_block_to_block (&block, &block2);
   6338  1.1  mrg 
   6339  1.1  mrg   gfc_add_block_to_block (&block, &arrayse.post);
   6340  1.1  mrg 
   6341  1.1  mrg   tmp = gfc_finish_block (&block);
   6342  1.1  mrg   if (maskss)
   6343  1.1  mrg     {
   6344  1.1  mrg       /* We enclose the above in if (mask) {...}.  If the mask is an
   6345  1.1  mrg 	 optional argument, generate IF (.NOT. PRESENT(MASK)
   6346  1.1  mrg 	 .OR. MASK(I)).  */
   6347  1.1  mrg       tree ifmask;
   6348  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   6349  1.1  mrg       tmp = build3_v (COND_EXPR, ifmask, tmp,
   6350  1.1  mrg 		      build_empty_stmt (input_location));
   6351  1.1  mrg     }
   6352  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   6353  1.1  mrg 
   6354  1.1  mrg   if (lab)
   6355  1.1  mrg     {
   6356  1.1  mrg       gfc_trans_scalarized_loop_boundary (&loop, &body);
   6357  1.1  mrg 
   6358  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
   6359  1.1  mrg 			     nan_cst, huge_cst);
   6360  1.1  mrg       gfc_add_modify (&loop.code[0], limit, tmp);
   6361  1.1  mrg       gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
   6362  1.1  mrg 
   6363  1.1  mrg       /* If we have a mask, only add this element if the mask is set.  */
   6364  1.1  mrg       if (maskss)
   6365  1.1  mrg 	{
   6366  1.1  mrg 	  gfc_init_se (&maskse, NULL);
   6367  1.1  mrg 	  gfc_copy_loopinfo_to_se (&maskse, &loop);
   6368  1.1  mrg 	  maskse.ss = maskss;
   6369  1.1  mrg 	  gfc_conv_expr_val (&maskse, maskexpr);
   6370  1.1  mrg 	  gfc_add_block_to_block (&body, &maskse.pre);
   6371  1.1  mrg 
   6372  1.1  mrg 	  gfc_start_block (&block);
   6373  1.1  mrg 	}
   6374  1.1  mrg       else
   6375  1.1  mrg 	gfc_init_block (&block);
   6376  1.1  mrg 
   6377  1.1  mrg       /* Compare with the current limit.  */
   6378  1.1  mrg       gfc_init_se (&arrayse, NULL);
   6379  1.1  mrg       gfc_copy_loopinfo_to_se (&arrayse, &loop);
   6380  1.1  mrg       arrayse.ss = arrayss;
   6381  1.1  mrg       gfc_conv_expr_val (&arrayse, arrayexpr);
   6382  1.1  mrg       gfc_add_block_to_block (&block, &arrayse.pre);
   6383  1.1  mrg 
   6384  1.1  mrg       /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
   6385  1.1  mrg 	 signed zeros.  */
   6386  1.1  mrg       if (HONOR_NANS (DECL_MODE (limit)))
   6387  1.1  mrg 	{
   6388  1.1  mrg 	  tmp = fold_build2_loc (input_location, op, logical_type_node,
   6389  1.1  mrg 				 arrayse.expr, limit);
   6390  1.1  mrg 	  ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
   6391  1.1  mrg 	  tmp = build3_v (COND_EXPR, tmp, ifbody,
   6392  1.1  mrg 			  build_empty_stmt (input_location));
   6393  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   6394  1.1  mrg 	}
   6395  1.1  mrg       else
   6396  1.1  mrg 	{
   6397  1.1  mrg 	  tmp = fold_build2_loc (input_location,
   6398  1.1  mrg 				 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
   6399  1.1  mrg 				 type, arrayse.expr, limit);
   6400  1.1  mrg 	  gfc_add_modify (&block, limit, tmp);
   6401  1.1  mrg 	}
   6402  1.1  mrg 
   6403  1.1  mrg       gfc_add_block_to_block (&block, &arrayse.post);
   6404  1.1  mrg 
   6405  1.1  mrg       tmp = gfc_finish_block (&block);
   6406  1.1  mrg       if (maskss)
   6407  1.1  mrg 	/* We enclose the above in if (mask) {...}.  */
   6408  1.1  mrg 	{
   6409  1.1  mrg 	  tree ifmask;
   6410  1.1  mrg 	  ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   6411  1.1  mrg 	  tmp = build3_v (COND_EXPR, ifmask, tmp,
   6412  1.1  mrg 			  build_empty_stmt (input_location));
   6413  1.1  mrg 	}
   6414  1.1  mrg 
   6415  1.1  mrg       gfc_add_expr_to_block (&body, tmp);
   6416  1.1  mrg       /* Avoid initializing loopvar[0] again, it should be left where
   6417  1.1  mrg 	 it finished by the first loop.  */
   6418  1.1  mrg       loop.from[0] = loop.loopvar[0];
   6419  1.1  mrg     }
   6420  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   6421  1.1  mrg 
   6422  1.1  mrg   if (fast)
   6423  1.1  mrg     {
   6424  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
   6425  1.1  mrg 			     nan_cst, huge_cst);
   6426  1.1  mrg       ifbody = build2_v (MODIFY_EXPR, limit, tmp);
   6427  1.1  mrg       tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
   6428  1.1  mrg 		      ifbody);
   6429  1.1  mrg       gfc_add_expr_to_block (&loop.pre, tmp);
   6430  1.1  mrg     }
   6431  1.1  mrg   else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
   6432  1.1  mrg     {
   6433  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
   6434  1.1  mrg 			     huge_cst);
   6435  1.1  mrg       gfc_add_modify (&loop.pre, limit, tmp);
   6436  1.1  mrg     }
   6437  1.1  mrg 
   6438  1.1  mrg   /* For a scalar mask, enclose the loop in an if statement.  */
   6439  1.1  mrg   if (maskexpr && maskss == NULL)
   6440  1.1  mrg     {
   6441  1.1  mrg       tree else_stmt;
   6442  1.1  mrg       tree ifmask;
   6443  1.1  mrg 
   6444  1.1  mrg       gfc_init_se (&maskse, NULL);
   6445  1.1  mrg       gfc_conv_expr_val (&maskse, maskexpr);
   6446  1.1  mrg       gfc_init_block (&block);
   6447  1.1  mrg       gfc_add_block_to_block (&block, &loop.pre);
   6448  1.1  mrg       gfc_add_block_to_block (&block, &loop.post);
   6449  1.1  mrg       tmp = gfc_finish_block (&block);
   6450  1.1  mrg 
   6451  1.1  mrg       if (HONOR_INFINITIES (DECL_MODE (limit)))
   6452  1.1  mrg 	else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
   6453  1.1  mrg       else
   6454  1.1  mrg 	else_stmt = build_empty_stmt (input_location);
   6455  1.1  mrg 
   6456  1.1  mrg       ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
   6457  1.1  mrg       tmp = build3_v (COND_EXPR, ifmask, tmp, else_stmt);
   6458  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   6459  1.1  mrg       gfc_add_block_to_block (&se->pre, &block);
   6460  1.1  mrg     }
   6461  1.1  mrg   else
   6462  1.1  mrg     {
   6463  1.1  mrg       gfc_add_block_to_block (&se->pre, &loop.pre);
   6464  1.1  mrg       gfc_add_block_to_block (&se->pre, &loop.post);
   6465  1.1  mrg     }
   6466  1.1  mrg 
   6467  1.1  mrg   gfc_cleanup_loop (&loop);
   6468  1.1  mrg 
   6469  1.1  mrg   se->expr = limit;
   6470  1.1  mrg }
   6471  1.1  mrg 
   6472  1.1  mrg /* BTEST (i, pos) = (i & (1 << pos)) != 0.  */
   6473  1.1  mrg static void
   6474  1.1  mrg gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
   6475  1.1  mrg {
   6476  1.1  mrg   tree args[2];
   6477  1.1  mrg   tree type;
   6478  1.1  mrg   tree tmp;
   6479  1.1  mrg 
   6480  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6481  1.1  mrg   type = TREE_TYPE (args[0]);
   6482  1.1  mrg 
   6483  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6484  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6485  1.1  mrg     {
   6486  1.1  mrg       tree below = fold_build2_loc (input_location, LT_EXPR,
   6487  1.1  mrg 				    logical_type_node, args[1],
   6488  1.1  mrg 				    build_int_cst (TREE_TYPE (args[1]), 0));
   6489  1.1  mrg       tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
   6490  1.1  mrg       tree above = fold_build2_loc (input_location, GE_EXPR,
   6491  1.1  mrg 				    logical_type_node, args[1], nbits);
   6492  1.1  mrg       tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6493  1.1  mrg 				    logical_type_node, below, above);
   6494  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6495  1.1  mrg 			       "POS argument (%ld) out of range 0:%ld "
   6496  1.1  mrg 			       "in intrinsic BTEST",
   6497  1.1  mrg 			       fold_convert (long_integer_type_node, args[1]),
   6498  1.1  mrg 			       fold_convert (long_integer_type_node, nbits));
   6499  1.1  mrg     }
   6500  1.1  mrg 
   6501  1.1  mrg   tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   6502  1.1  mrg 			 build_int_cst (type, 1), args[1]);
   6503  1.1  mrg   tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
   6504  1.1  mrg   tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
   6505  1.1  mrg 			 build_int_cst (type, 0));
   6506  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   6507  1.1  mrg   se->expr = convert (type, tmp);
   6508  1.1  mrg }
   6509  1.1  mrg 
   6510  1.1  mrg 
   6511  1.1  mrg /* Generate code for BGE, BGT, BLE and BLT intrinsics.  */
   6512  1.1  mrg static void
   6513  1.1  mrg gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
   6514  1.1  mrg {
   6515  1.1  mrg   tree args[2];
   6516  1.1  mrg 
   6517  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6518  1.1  mrg 
   6519  1.1  mrg   /* Convert both arguments to the unsigned type of the same size.  */
   6520  1.1  mrg   args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
   6521  1.1  mrg   args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
   6522  1.1  mrg 
   6523  1.1  mrg   /* If they have unequal type size, convert to the larger one.  */
   6524  1.1  mrg   if (TYPE_PRECISION (TREE_TYPE (args[0]))
   6525  1.1  mrg       > TYPE_PRECISION (TREE_TYPE (args[1])))
   6526  1.1  mrg     args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
   6527  1.1  mrg   else if (TYPE_PRECISION (TREE_TYPE (args[1]))
   6528  1.1  mrg 	   > TYPE_PRECISION (TREE_TYPE (args[0])))
   6529  1.1  mrg     args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
   6530  1.1  mrg 
   6531  1.1  mrg   /* Now, we compare them.  */
   6532  1.1  mrg   se->expr = fold_build2_loc (input_location, op, logical_type_node,
   6533  1.1  mrg 			      args[0], args[1]);
   6534  1.1  mrg }
   6535  1.1  mrg 
   6536  1.1  mrg 
   6537  1.1  mrg /* Generate code to perform the specified operation.  */
   6538  1.1  mrg static void
   6539  1.1  mrg gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
   6540  1.1  mrg {
   6541  1.1  mrg   tree args[2];
   6542  1.1  mrg 
   6543  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6544  1.1  mrg   se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
   6545  1.1  mrg 			      args[0], args[1]);
   6546  1.1  mrg }
   6547  1.1  mrg 
   6548  1.1  mrg /* Bitwise not.  */
   6549  1.1  mrg static void
   6550  1.1  mrg gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
   6551  1.1  mrg {
   6552  1.1  mrg   tree arg;
   6553  1.1  mrg 
   6554  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   6555  1.1  mrg   se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
   6556  1.1  mrg 			      TREE_TYPE (arg), arg);
   6557  1.1  mrg }
   6558  1.1  mrg 
   6559  1.1  mrg /* Set or clear a single bit.  */
   6560  1.1  mrg static void
   6561  1.1  mrg gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
   6562  1.1  mrg {
   6563  1.1  mrg   tree args[2];
   6564  1.1  mrg   tree type;
   6565  1.1  mrg   tree tmp;
   6566  1.1  mrg   enum tree_code op;
   6567  1.1  mrg 
   6568  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6569  1.1  mrg   type = TREE_TYPE (args[0]);
   6570  1.1  mrg 
   6571  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6572  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6573  1.1  mrg     {
   6574  1.1  mrg       tree below = fold_build2_loc (input_location, LT_EXPR,
   6575  1.1  mrg 				    logical_type_node, args[1],
   6576  1.1  mrg 				    build_int_cst (TREE_TYPE (args[1]), 0));
   6577  1.1  mrg       tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
   6578  1.1  mrg       tree above = fold_build2_loc (input_location, GE_EXPR,
   6579  1.1  mrg 				    logical_type_node, args[1], nbits);
   6580  1.1  mrg       tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6581  1.1  mrg 				    logical_type_node, below, above);
   6582  1.1  mrg       size_t len_name = strlen (expr->value.function.isym->name);
   6583  1.1  mrg       char *name = XALLOCAVEC (char, len_name + 1);
   6584  1.1  mrg       for (size_t i = 0; i < len_name; i++)
   6585  1.1  mrg 	name[i] = TOUPPER (expr->value.function.isym->name[i]);
   6586  1.1  mrg       name[len_name] = '\0';
   6587  1.1  mrg       tree iname = gfc_build_addr_expr (pchar_type_node,
   6588  1.1  mrg 					gfc_build_cstring_const (name));
   6589  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6590  1.1  mrg 			       "POS argument (%ld) out of range 0:%ld "
   6591  1.1  mrg 			       "in intrinsic %s",
   6592  1.1  mrg 			       fold_convert (long_integer_type_node, args[1]),
   6593  1.1  mrg 			       fold_convert (long_integer_type_node, nbits),
   6594  1.1  mrg 			       iname);
   6595  1.1  mrg     }
   6596  1.1  mrg 
   6597  1.1  mrg   tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   6598  1.1  mrg 			 build_int_cst (type, 1), args[1]);
   6599  1.1  mrg   if (set)
   6600  1.1  mrg     op = BIT_IOR_EXPR;
   6601  1.1  mrg   else
   6602  1.1  mrg     {
   6603  1.1  mrg       op = BIT_AND_EXPR;
   6604  1.1  mrg       tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
   6605  1.1  mrg     }
   6606  1.1  mrg   se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
   6607  1.1  mrg }
   6608  1.1  mrg 
   6609  1.1  mrg /* Extract a sequence of bits.
   6610  1.1  mrg     IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN).  */
   6611  1.1  mrg static void
   6612  1.1  mrg gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
   6613  1.1  mrg {
   6614  1.1  mrg   tree args[3];
   6615  1.1  mrg   tree type;
   6616  1.1  mrg   tree tmp;
   6617  1.1  mrg   tree mask;
   6618  1.1  mrg   tree num_bits, cond;
   6619  1.1  mrg 
   6620  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 3);
   6621  1.1  mrg   type = TREE_TYPE (args[0]);
   6622  1.1  mrg 
   6623  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6624  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6625  1.1  mrg     {
   6626  1.1  mrg       tree tmp1 = fold_convert (long_integer_type_node, args[1]);
   6627  1.1  mrg       tree tmp2 = fold_convert (long_integer_type_node, args[2]);
   6628  1.1  mrg       tree nbits = build_int_cst (long_integer_type_node,
   6629  1.1  mrg 				  TYPE_PRECISION (type));
   6630  1.1  mrg       tree below = fold_build2_loc (input_location, LT_EXPR,
   6631  1.1  mrg 				    logical_type_node, args[1],
   6632  1.1  mrg 				    build_int_cst (TREE_TYPE (args[1]), 0));
   6633  1.1  mrg       tree above = fold_build2_loc (input_location, GT_EXPR,
   6634  1.1  mrg 				    logical_type_node, tmp1, nbits);
   6635  1.1  mrg       tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6636  1.1  mrg 				    logical_type_node, below, above);
   6637  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6638  1.1  mrg 			       "POS argument (%ld) out of range 0:%ld "
   6639  1.1  mrg 			       "in intrinsic IBITS", tmp1, nbits);
   6640  1.1  mrg       below = fold_build2_loc (input_location, LT_EXPR,
   6641  1.1  mrg 			       logical_type_node, args[2],
   6642  1.1  mrg 			       build_int_cst (TREE_TYPE (args[2]), 0));
   6643  1.1  mrg       above = fold_build2_loc (input_location, GT_EXPR,
   6644  1.1  mrg 			       logical_type_node, tmp2, nbits);
   6645  1.1  mrg       scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6646  1.1  mrg 			       logical_type_node, below, above);
   6647  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6648  1.1  mrg 			       "LEN argument (%ld) out of range 0:%ld "
   6649  1.1  mrg 			       "in intrinsic IBITS", tmp2, nbits);
   6650  1.1  mrg       above = fold_build2_loc (input_location, PLUS_EXPR,
   6651  1.1  mrg 			       long_integer_type_node, tmp1, tmp2);
   6652  1.1  mrg       scond = fold_build2_loc (input_location, GT_EXPR,
   6653  1.1  mrg 			       logical_type_node, above, nbits);
   6654  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6655  1.1  mrg 			       "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
   6656  1.1  mrg 			       "in intrinsic IBITS", tmp1, tmp2, nbits);
   6657  1.1  mrg     }
   6658  1.1  mrg 
   6659  1.1  mrg   /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
   6660  1.1  mrg      gcc requires a shift width < BIT_SIZE(I), so we have to catch this
   6661  1.1  mrg      special case.  See also gfc_conv_intrinsic_ishft ().  */
   6662  1.1  mrg   num_bits = build_int_cst (TREE_TYPE (args[2]), TYPE_PRECISION (type));
   6663  1.1  mrg 
   6664  1.1  mrg   mask = build_int_cst (type, -1);
   6665  1.1  mrg   mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
   6666  1.1  mrg   cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[2],
   6667  1.1  mrg 			  num_bits);
   6668  1.1  mrg   mask = fold_build3_loc (input_location, COND_EXPR, type, cond,
   6669  1.1  mrg 			  build_int_cst (type, 0), mask);
   6670  1.1  mrg   mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
   6671  1.1  mrg 
   6672  1.1  mrg   tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
   6673  1.1  mrg 
   6674  1.1  mrg   se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
   6675  1.1  mrg }
   6676  1.1  mrg 
   6677  1.1  mrg static void
   6678  1.1  mrg gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
   6679  1.1  mrg 			  bool arithmetic)
   6680  1.1  mrg {
   6681  1.1  mrg   tree args[2], type, num_bits, cond;
   6682  1.1  mrg   tree bigshift;
   6683  1.1  mrg 
   6684  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6685  1.1  mrg 
   6686  1.1  mrg   args[0] = gfc_evaluate_now (args[0], &se->pre);
   6687  1.1  mrg   args[1] = gfc_evaluate_now (args[1], &se->pre);
   6688  1.1  mrg   type = TREE_TYPE (args[0]);
   6689  1.1  mrg 
   6690  1.1  mrg   if (!arithmetic)
   6691  1.1  mrg     args[0] = fold_convert (unsigned_type_for (type), args[0]);
   6692  1.1  mrg   else
   6693  1.1  mrg     gcc_assert (right_shift);
   6694  1.1  mrg 
   6695  1.1  mrg   se->expr = fold_build2_loc (input_location,
   6696  1.1  mrg 			      right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
   6697  1.1  mrg 			      TREE_TYPE (args[0]), args[0], args[1]);
   6698  1.1  mrg 
   6699  1.1  mrg   if (!arithmetic)
   6700  1.1  mrg     se->expr = fold_convert (type, se->expr);
   6701  1.1  mrg 
   6702  1.1  mrg   if (!arithmetic)
   6703  1.1  mrg     bigshift = build_int_cst (type, 0);
   6704  1.1  mrg   else
   6705  1.1  mrg     {
   6706  1.1  mrg       tree nonneg = fold_build2_loc (input_location, GE_EXPR,
   6707  1.1  mrg 				     logical_type_node, args[0],
   6708  1.1  mrg 				     build_int_cst (TREE_TYPE (args[0]), 0));
   6709  1.1  mrg       bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
   6710  1.1  mrg 				  build_int_cst (type, 0),
   6711  1.1  mrg 				  build_int_cst (type, -1));
   6712  1.1  mrg     }
   6713  1.1  mrg 
   6714  1.1  mrg   /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
   6715  1.1  mrg      gcc requires a shift width < BIT_SIZE(I), so we have to catch this
   6716  1.1  mrg      special case.  */
   6717  1.1  mrg   num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
   6718  1.1  mrg 
   6719  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6720  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6721  1.1  mrg     {
   6722  1.1  mrg       tree below = fold_build2_loc (input_location, LT_EXPR,
   6723  1.1  mrg 				    logical_type_node, args[1],
   6724  1.1  mrg 				    build_int_cst (TREE_TYPE (args[1]), 0));
   6725  1.1  mrg       tree above = fold_build2_loc (input_location, GT_EXPR,
   6726  1.1  mrg 				    logical_type_node, args[1], num_bits);
   6727  1.1  mrg       tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6728  1.1  mrg 				    logical_type_node, below, above);
   6729  1.1  mrg       size_t len_name = strlen (expr->value.function.isym->name);
   6730  1.1  mrg       char *name = XALLOCAVEC (char, len_name + 1);
   6731  1.1  mrg       for (size_t i = 0; i < len_name; i++)
   6732  1.1  mrg 	name[i] = TOUPPER (expr->value.function.isym->name[i]);
   6733  1.1  mrg       name[len_name] = '\0';
   6734  1.1  mrg       tree iname = gfc_build_addr_expr (pchar_type_node,
   6735  1.1  mrg 					gfc_build_cstring_const (name));
   6736  1.1  mrg       gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6737  1.1  mrg 			       "SHIFT argument (%ld) out of range 0:%ld "
   6738  1.1  mrg 			       "in intrinsic %s",
   6739  1.1  mrg 			       fold_convert (long_integer_type_node, args[1]),
   6740  1.1  mrg 			       fold_convert (long_integer_type_node, num_bits),
   6741  1.1  mrg 			       iname);
   6742  1.1  mrg     }
   6743  1.1  mrg 
   6744  1.1  mrg   cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
   6745  1.1  mrg 			  args[1], num_bits);
   6746  1.1  mrg 
   6747  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
   6748  1.1  mrg 			      bigshift, se->expr);
   6749  1.1  mrg }
   6750  1.1  mrg 
   6751  1.1  mrg /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
   6752  1.1  mrg                         ? 0
   6753  1.1  mrg 	 	        : ((shift >= 0) ? i << shift : i >> -shift)
   6754  1.1  mrg    where all shifts are logical shifts.  */
   6755  1.1  mrg static void
   6756  1.1  mrg gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
   6757  1.1  mrg {
   6758  1.1  mrg   tree args[2];
   6759  1.1  mrg   tree type;
   6760  1.1  mrg   tree utype;
   6761  1.1  mrg   tree tmp;
   6762  1.1  mrg   tree width;
   6763  1.1  mrg   tree num_bits;
   6764  1.1  mrg   tree cond;
   6765  1.1  mrg   tree lshift;
   6766  1.1  mrg   tree rshift;
   6767  1.1  mrg 
   6768  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   6769  1.1  mrg 
   6770  1.1  mrg   args[0] = gfc_evaluate_now (args[0], &se->pre);
   6771  1.1  mrg   args[1] = gfc_evaluate_now (args[1], &se->pre);
   6772  1.1  mrg 
   6773  1.1  mrg   type = TREE_TYPE (args[0]);
   6774  1.1  mrg   utype = unsigned_type_for (type);
   6775  1.1  mrg 
   6776  1.1  mrg   width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
   6777  1.1  mrg 			   args[1]);
   6778  1.1  mrg 
   6779  1.1  mrg   /* Left shift if positive.  */
   6780  1.1  mrg   lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
   6781  1.1  mrg 
   6782  1.1  mrg   /* Right shift if negative.
   6783  1.1  mrg      We convert to an unsigned type because we want a logical shift.
   6784  1.1  mrg      The standard doesn't define the case of shifting negative
   6785  1.1  mrg      numbers, and we try to be compatible with other compilers, most
   6786  1.1  mrg      notably g77, here.  */
   6787  1.1  mrg   rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
   6788  1.1  mrg 				    utype, convert (utype, args[0]), width));
   6789  1.1  mrg 
   6790  1.1  mrg   tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
   6791  1.1  mrg 			 build_int_cst (TREE_TYPE (args[1]), 0));
   6792  1.1  mrg   tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
   6793  1.1  mrg 
   6794  1.1  mrg   /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
   6795  1.1  mrg      gcc requires a shift width < BIT_SIZE(I), so we have to catch this
   6796  1.1  mrg      special case.  */
   6797  1.1  mrg   num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
   6798  1.1  mrg 
   6799  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6800  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6801  1.1  mrg     {
   6802  1.1  mrg       tree outside = fold_build2_loc (input_location, GT_EXPR,
   6803  1.1  mrg 				    logical_type_node, width, num_bits);
   6804  1.1  mrg       gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
   6805  1.1  mrg 			       "SHIFT argument (%ld) out of range -%ld:%ld "
   6806  1.1  mrg 			       "in intrinsic ISHFT",
   6807  1.1  mrg 			       fold_convert (long_integer_type_node, args[1]),
   6808  1.1  mrg 			       fold_convert (long_integer_type_node, num_bits),
   6809  1.1  mrg 			       fold_convert (long_integer_type_node, num_bits));
   6810  1.1  mrg     }
   6811  1.1  mrg 
   6812  1.1  mrg   cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
   6813  1.1  mrg 			  num_bits);
   6814  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
   6815  1.1  mrg 			      build_int_cst (type, 0), tmp);
   6816  1.1  mrg }
   6817  1.1  mrg 
   6818  1.1  mrg 
   6819  1.1  mrg /* Circular shift.  AKA rotate or barrel shift.  */
   6820  1.1  mrg 
   6821  1.1  mrg static void
   6822  1.1  mrg gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
   6823  1.1  mrg {
   6824  1.1  mrg   tree *args;
   6825  1.1  mrg   tree type;
   6826  1.1  mrg   tree tmp;
   6827  1.1  mrg   tree lrot;
   6828  1.1  mrg   tree rrot;
   6829  1.1  mrg   tree zero;
   6830  1.1  mrg   tree nbits;
   6831  1.1  mrg   unsigned int num_args;
   6832  1.1  mrg 
   6833  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   6834  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   6835  1.1  mrg 
   6836  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   6837  1.1  mrg 
   6838  1.1  mrg   type = TREE_TYPE (args[0]);
   6839  1.1  mrg   nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type));
   6840  1.1  mrg 
   6841  1.1  mrg   if (num_args == 3)
   6842  1.1  mrg     {
   6843  1.1  mrg       /* Use a library function for the 3 parameter version.  */
   6844  1.1  mrg       tree int4type = gfc_get_int_type (4);
   6845  1.1  mrg 
   6846  1.1  mrg       /* We convert the first argument to at least 4 bytes, and
   6847  1.1  mrg 	 convert back afterwards.  This removes the need for library
   6848  1.1  mrg 	 functions for all argument sizes, and function will be
   6849  1.1  mrg 	 aligned to at least 32 bits, so there's no loss.  */
   6850  1.1  mrg       if (expr->ts.kind < 4)
   6851  1.1  mrg 	args[0] = convert (int4type, args[0]);
   6852  1.1  mrg 
   6853  1.1  mrg       /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
   6854  1.1  mrg          need loads of library  functions.  They cannot have values >
   6855  1.1  mrg 	 BIT_SIZE (I) so the conversion is safe.  */
   6856  1.1  mrg       args[1] = convert (int4type, args[1]);
   6857  1.1  mrg       args[2] = convert (int4type, args[2]);
   6858  1.1  mrg 
   6859  1.1  mrg       /* Optionally generate code for runtime argument check.  */
   6860  1.1  mrg       if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6861  1.1  mrg 	{
   6862  1.1  mrg 	  tree size = fold_convert (long_integer_type_node, args[2]);
   6863  1.1  mrg 	  tree below = fold_build2_loc (input_location, LE_EXPR,
   6864  1.1  mrg 					logical_type_node, size,
   6865  1.1  mrg 					build_int_cst (TREE_TYPE (args[1]), 0));
   6866  1.1  mrg 	  tree above = fold_build2_loc (input_location, GT_EXPR,
   6867  1.1  mrg 					logical_type_node, size, nbits);
   6868  1.1  mrg 	  tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   6869  1.1  mrg 					logical_type_node, below, above);
   6870  1.1  mrg 	  gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6871  1.1  mrg 				   "SIZE argument (%ld) out of range 1:%ld "
   6872  1.1  mrg 				   "in intrinsic ISHFTC", size, nbits);
   6873  1.1  mrg 	  tree width = fold_convert (long_integer_type_node, args[1]);
   6874  1.1  mrg 	  width = fold_build1_loc (input_location, ABS_EXPR,
   6875  1.1  mrg 				   long_integer_type_node, width);
   6876  1.1  mrg 	  scond = fold_build2_loc (input_location, GT_EXPR,
   6877  1.1  mrg 				   logical_type_node, width, size);
   6878  1.1  mrg 	  gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
   6879  1.1  mrg 				   "SHIFT argument (%ld) out of range -%ld:%ld "
   6880  1.1  mrg 				   "in intrinsic ISHFTC",
   6881  1.1  mrg 				   fold_convert (long_integer_type_node, args[1]),
   6882  1.1  mrg 				   size, size);
   6883  1.1  mrg 	}
   6884  1.1  mrg 
   6885  1.1  mrg       switch (expr->ts.kind)
   6886  1.1  mrg 	{
   6887  1.1  mrg 	case 1:
   6888  1.1  mrg 	case 2:
   6889  1.1  mrg 	case 4:
   6890  1.1  mrg 	  tmp = gfor_fndecl_math_ishftc4;
   6891  1.1  mrg 	  break;
   6892  1.1  mrg 	case 8:
   6893  1.1  mrg 	  tmp = gfor_fndecl_math_ishftc8;
   6894  1.1  mrg 	  break;
   6895  1.1  mrg 	case 16:
   6896  1.1  mrg 	  tmp = gfor_fndecl_math_ishftc16;
   6897  1.1  mrg 	  break;
   6898  1.1  mrg 	default:
   6899  1.1  mrg 	  gcc_unreachable ();
   6900  1.1  mrg 	}
   6901  1.1  mrg       se->expr = build_call_expr_loc (input_location,
   6902  1.1  mrg 				      tmp, 3, args[0], args[1], args[2]);
   6903  1.1  mrg       /* Convert the result back to the original type, if we extended
   6904  1.1  mrg 	 the first argument's width above.  */
   6905  1.1  mrg       if (expr->ts.kind < 4)
   6906  1.1  mrg 	se->expr = convert (type, se->expr);
   6907  1.1  mrg 
   6908  1.1  mrg       return;
   6909  1.1  mrg     }
   6910  1.1  mrg 
   6911  1.1  mrg   /* Evaluate arguments only once.  */
   6912  1.1  mrg   args[0] = gfc_evaluate_now (args[0], &se->pre);
   6913  1.1  mrg   args[1] = gfc_evaluate_now (args[1], &se->pre);
   6914  1.1  mrg 
   6915  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   6916  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   6917  1.1  mrg     {
   6918  1.1  mrg       tree width = fold_convert (long_integer_type_node, args[1]);
   6919  1.1  mrg       width = fold_build1_loc (input_location, ABS_EXPR,
   6920  1.1  mrg 			       long_integer_type_node, width);
   6921  1.1  mrg       tree outside = fold_build2_loc (input_location, GT_EXPR,
   6922  1.1  mrg 				      logical_type_node, width, nbits);
   6923  1.1  mrg       gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
   6924  1.1  mrg 			       "SHIFT argument (%ld) out of range -%ld:%ld "
   6925  1.1  mrg 			       "in intrinsic ISHFTC",
   6926  1.1  mrg 			       fold_convert (long_integer_type_node, args[1]),
   6927  1.1  mrg 			       nbits, nbits);
   6928  1.1  mrg     }
   6929  1.1  mrg 
   6930  1.1  mrg   /* Rotate left if positive.  */
   6931  1.1  mrg   lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
   6932  1.1  mrg 
   6933  1.1  mrg   /* Rotate right if negative.  */
   6934  1.1  mrg   tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
   6935  1.1  mrg 			 args[1]);
   6936  1.1  mrg   rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
   6937  1.1  mrg 
   6938  1.1  mrg   zero = build_int_cst (TREE_TYPE (args[1]), 0);
   6939  1.1  mrg   tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
   6940  1.1  mrg 			 zero);
   6941  1.1  mrg   rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
   6942  1.1  mrg 
   6943  1.1  mrg   /* Do nothing if shift == 0.  */
   6944  1.1  mrg   tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
   6945  1.1  mrg 			 zero);
   6946  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
   6947  1.1  mrg 			      rrot);
   6948  1.1  mrg }
   6949  1.1  mrg 
   6950  1.1  mrg 
   6951  1.1  mrg /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
   6952  1.1  mrg 			: __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
   6953  1.1  mrg 
   6954  1.1  mrg    The conditional expression is necessary because the result of LEADZ(0)
   6955  1.1  mrg    is defined, but the result of __builtin_clz(0) is undefined for most
   6956  1.1  mrg    targets.
   6957  1.1  mrg 
   6958  1.1  mrg    For INTEGER kinds smaller than the C 'int' type, we have to subtract the
   6959  1.1  mrg    difference in bit size between the argument of LEADZ and the C int.  */
   6960  1.1  mrg 
   6961  1.1  mrg static void
   6962  1.1  mrg gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
   6963  1.1  mrg {
   6964  1.1  mrg   tree arg;
   6965  1.1  mrg   tree arg_type;
   6966  1.1  mrg   tree cond;
   6967  1.1  mrg   tree result_type;
   6968  1.1  mrg   tree leadz;
   6969  1.1  mrg   tree bit_size;
   6970  1.1  mrg   tree tmp;
   6971  1.1  mrg   tree func;
   6972  1.1  mrg   int s, argsize;
   6973  1.1  mrg 
   6974  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   6975  1.1  mrg   argsize = TYPE_PRECISION (TREE_TYPE (arg));
   6976  1.1  mrg 
   6977  1.1  mrg   /* Which variant of __builtin_clz* should we call?  */
   6978  1.1  mrg   if (argsize <= INT_TYPE_SIZE)
   6979  1.1  mrg     {
   6980  1.1  mrg       arg_type = unsigned_type_node;
   6981  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CLZ);
   6982  1.1  mrg     }
   6983  1.1  mrg   else if (argsize <= LONG_TYPE_SIZE)
   6984  1.1  mrg     {
   6985  1.1  mrg       arg_type = long_unsigned_type_node;
   6986  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CLZL);
   6987  1.1  mrg     }
   6988  1.1  mrg   else if (argsize <= LONG_LONG_TYPE_SIZE)
   6989  1.1  mrg     {
   6990  1.1  mrg       arg_type = long_long_unsigned_type_node;
   6991  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CLZLL);
   6992  1.1  mrg     }
   6993  1.1  mrg   else
   6994  1.1  mrg     {
   6995  1.1  mrg       gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
   6996  1.1  mrg       arg_type = gfc_build_uint_type (argsize);
   6997  1.1  mrg       func = NULL_TREE;
   6998  1.1  mrg     }
   6999  1.1  mrg 
   7000  1.1  mrg   /* Convert the actual argument twice: first, to the unsigned type of the
   7001  1.1  mrg      same size; then, to the proper argument type for the built-in
   7002  1.1  mrg      function.  But the return type is of the default INTEGER kind.  */
   7003  1.1  mrg   arg = fold_convert (gfc_build_uint_type (argsize), arg);
   7004  1.1  mrg   arg = fold_convert (arg_type, arg);
   7005  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7006  1.1  mrg   result_type = gfc_get_int_type (gfc_default_integer_kind);
   7007  1.1  mrg 
   7008  1.1  mrg   /* Compute LEADZ for the case i .ne. 0.  */
   7009  1.1  mrg   if (func)
   7010  1.1  mrg     {
   7011  1.1  mrg       s = TYPE_PRECISION (arg_type) - argsize;
   7012  1.1  mrg       tmp = fold_convert (result_type,
   7013  1.1  mrg 			  build_call_expr_loc (input_location, func,
   7014  1.1  mrg 					       1, arg));
   7015  1.1  mrg       leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
   7016  1.1  mrg 			       tmp, build_int_cst (result_type, s));
   7017  1.1  mrg     }
   7018  1.1  mrg   else
   7019  1.1  mrg     {
   7020  1.1  mrg       /* We end up here if the argument type is larger than 'long long'.
   7021  1.1  mrg 	 We generate this code:
   7022  1.1  mrg 
   7023  1.1  mrg 	    if (x & (ULL_MAX << ULL_SIZE) != 0)
   7024  1.1  mrg 	      return clzll ((unsigned long long) (x >> ULLSIZE));
   7025  1.1  mrg 	    else
   7026  1.1  mrg 	      return ULL_SIZE + clzll ((unsigned long long) x);
   7027  1.1  mrg 	 where ULL_MAX is the largest value that a ULL_MAX can hold
   7028  1.1  mrg 	 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
   7029  1.1  mrg 	 is the bit-size of the long long type (64 in this example).  */
   7030  1.1  mrg       tree ullsize, ullmax, tmp1, tmp2, btmp;
   7031  1.1  mrg 
   7032  1.1  mrg       ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
   7033  1.1  mrg       ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
   7034  1.1  mrg 				long_long_unsigned_type_node,
   7035  1.1  mrg 				build_int_cst (long_long_unsigned_type_node,
   7036  1.1  mrg 					       0));
   7037  1.1  mrg 
   7038  1.1  mrg       cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
   7039  1.1  mrg 			      fold_convert (arg_type, ullmax), ullsize);
   7040  1.1  mrg       cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
   7041  1.1  mrg 			      arg, cond);
   7042  1.1  mrg       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   7043  1.1  mrg 			      cond, build_int_cst (arg_type, 0));
   7044  1.1  mrg 
   7045  1.1  mrg       tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
   7046  1.1  mrg 			      arg, ullsize);
   7047  1.1  mrg       tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
   7048  1.1  mrg       btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
   7049  1.1  mrg       tmp1 = fold_convert (result_type,
   7050  1.1  mrg 			   build_call_expr_loc (input_location, btmp, 1, tmp1));
   7051  1.1  mrg 
   7052  1.1  mrg       tmp2 = fold_convert (long_long_unsigned_type_node, arg);
   7053  1.1  mrg       btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
   7054  1.1  mrg       tmp2 = fold_convert (result_type,
   7055  1.1  mrg 			   build_call_expr_loc (input_location, btmp, 1, tmp2));
   7056  1.1  mrg       tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
   7057  1.1  mrg 			      tmp2, ullsize);
   7058  1.1  mrg 
   7059  1.1  mrg       leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
   7060  1.1  mrg 			       cond, tmp1, tmp2);
   7061  1.1  mrg     }
   7062  1.1  mrg 
   7063  1.1  mrg   /* Build BIT_SIZE.  */
   7064  1.1  mrg   bit_size = build_int_cst (result_type, argsize);
   7065  1.1  mrg 
   7066  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   7067  1.1  mrg 			  arg, build_int_cst (arg_type, 0));
   7068  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
   7069  1.1  mrg 			      bit_size, leadz);
   7070  1.1  mrg }
   7071  1.1  mrg 
   7072  1.1  mrg 
   7073  1.1  mrg /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
   7074  1.1  mrg 
   7075  1.1  mrg    The conditional expression is necessary because the result of TRAILZ(0)
   7076  1.1  mrg    is defined, but the result of __builtin_ctz(0) is undefined for most
   7077  1.1  mrg    targets.  */
   7078  1.1  mrg 
   7079  1.1  mrg static void
   7080  1.1  mrg gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
   7081  1.1  mrg {
   7082  1.1  mrg   tree arg;
   7083  1.1  mrg   tree arg_type;
   7084  1.1  mrg   tree cond;
   7085  1.1  mrg   tree result_type;
   7086  1.1  mrg   tree trailz;
   7087  1.1  mrg   tree bit_size;
   7088  1.1  mrg   tree func;
   7089  1.1  mrg   int argsize;
   7090  1.1  mrg 
   7091  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7092  1.1  mrg   argsize = TYPE_PRECISION (TREE_TYPE (arg));
   7093  1.1  mrg 
   7094  1.1  mrg   /* Which variant of __builtin_ctz* should we call?  */
   7095  1.1  mrg   if (argsize <= INT_TYPE_SIZE)
   7096  1.1  mrg     {
   7097  1.1  mrg       arg_type = unsigned_type_node;
   7098  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CTZ);
   7099  1.1  mrg     }
   7100  1.1  mrg   else if (argsize <= LONG_TYPE_SIZE)
   7101  1.1  mrg     {
   7102  1.1  mrg       arg_type = long_unsigned_type_node;
   7103  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CTZL);
   7104  1.1  mrg     }
   7105  1.1  mrg   else if (argsize <= LONG_LONG_TYPE_SIZE)
   7106  1.1  mrg     {
   7107  1.1  mrg       arg_type = long_long_unsigned_type_node;
   7108  1.1  mrg       func = builtin_decl_explicit (BUILT_IN_CTZLL);
   7109  1.1  mrg     }
   7110  1.1  mrg   else
   7111  1.1  mrg     {
   7112  1.1  mrg       gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
   7113  1.1  mrg       arg_type = gfc_build_uint_type (argsize);
   7114  1.1  mrg       func = NULL_TREE;
   7115  1.1  mrg     }
   7116  1.1  mrg 
   7117  1.1  mrg   /* Convert the actual argument twice: first, to the unsigned type of the
   7118  1.1  mrg      same size; then, to the proper argument type for the built-in
   7119  1.1  mrg      function.  But the return type is of the default INTEGER kind.  */
   7120  1.1  mrg   arg = fold_convert (gfc_build_uint_type (argsize), arg);
   7121  1.1  mrg   arg = fold_convert (arg_type, arg);
   7122  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7123  1.1  mrg   result_type = gfc_get_int_type (gfc_default_integer_kind);
   7124  1.1  mrg 
   7125  1.1  mrg   /* Compute TRAILZ for the case i .ne. 0.  */
   7126  1.1  mrg   if (func)
   7127  1.1  mrg     trailz = fold_convert (result_type, build_call_expr_loc (input_location,
   7128  1.1  mrg 							     func, 1, arg));
   7129  1.1  mrg   else
   7130  1.1  mrg     {
   7131  1.1  mrg       /* We end up here if the argument type is larger than 'long long'.
   7132  1.1  mrg 	 We generate this code:
   7133  1.1  mrg 
   7134  1.1  mrg 	    if ((x & ULL_MAX) == 0)
   7135  1.1  mrg 	      return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
   7136  1.1  mrg 	    else
   7137  1.1  mrg 	      return ctzll ((unsigned long long) x);
   7138  1.1  mrg 
   7139  1.1  mrg 	 where ULL_MAX is the largest value that a ULL_MAX can hold
   7140  1.1  mrg 	 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
   7141  1.1  mrg 	 is the bit-size of the long long type (64 in this example).  */
   7142  1.1  mrg       tree ullsize, ullmax, tmp1, tmp2, btmp;
   7143  1.1  mrg 
   7144  1.1  mrg       ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
   7145  1.1  mrg       ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
   7146  1.1  mrg 				long_long_unsigned_type_node,
   7147  1.1  mrg 				build_int_cst (long_long_unsigned_type_node, 0));
   7148  1.1  mrg 
   7149  1.1  mrg       cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
   7150  1.1  mrg 			      fold_convert (arg_type, ullmax));
   7151  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
   7152  1.1  mrg 			      build_int_cst (arg_type, 0));
   7153  1.1  mrg 
   7154  1.1  mrg       tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
   7155  1.1  mrg 			      arg, ullsize);
   7156  1.1  mrg       tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
   7157  1.1  mrg       btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
   7158  1.1  mrg       tmp1 = fold_convert (result_type,
   7159  1.1  mrg 			   build_call_expr_loc (input_location, btmp, 1, tmp1));
   7160  1.1  mrg       tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
   7161  1.1  mrg 			      tmp1, ullsize);
   7162  1.1  mrg 
   7163  1.1  mrg       tmp2 = fold_convert (long_long_unsigned_type_node, arg);
   7164  1.1  mrg       btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
   7165  1.1  mrg       tmp2 = fold_convert (result_type,
   7166  1.1  mrg 			   build_call_expr_loc (input_location, btmp, 1, tmp2));
   7167  1.1  mrg 
   7168  1.1  mrg       trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
   7169  1.1  mrg 				cond, tmp1, tmp2);
   7170  1.1  mrg     }
   7171  1.1  mrg 
   7172  1.1  mrg   /* Build BIT_SIZE.  */
   7173  1.1  mrg   bit_size = build_int_cst (result_type, argsize);
   7174  1.1  mrg 
   7175  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   7176  1.1  mrg 			  arg, build_int_cst (arg_type, 0));
   7177  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
   7178  1.1  mrg 			      bit_size, trailz);
   7179  1.1  mrg }
   7180  1.1  mrg 
   7181  1.1  mrg /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
   7182  1.1  mrg    for types larger than "long long", we call the long long built-in for
   7183  1.1  mrg    the lower and higher bits and combine the result.  */
   7184  1.1  mrg 
   7185  1.1  mrg static void
   7186  1.1  mrg gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
   7187  1.1  mrg {
   7188  1.1  mrg   tree arg;
   7189  1.1  mrg   tree arg_type;
   7190  1.1  mrg   tree result_type;
   7191  1.1  mrg   tree func;
   7192  1.1  mrg   int argsize;
   7193  1.1  mrg 
   7194  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7195  1.1  mrg   argsize = TYPE_PRECISION (TREE_TYPE (arg));
   7196  1.1  mrg   result_type = gfc_get_int_type (gfc_default_integer_kind);
   7197  1.1  mrg 
   7198  1.1  mrg   /* Which variant of the builtin should we call?  */
   7199  1.1  mrg   if (argsize <= INT_TYPE_SIZE)
   7200  1.1  mrg     {
   7201  1.1  mrg       arg_type = unsigned_type_node;
   7202  1.1  mrg       func = builtin_decl_explicit (parity
   7203  1.1  mrg 				    ? BUILT_IN_PARITY
   7204  1.1  mrg 				    : BUILT_IN_POPCOUNT);
   7205  1.1  mrg     }
   7206  1.1  mrg   else if (argsize <= LONG_TYPE_SIZE)
   7207  1.1  mrg     {
   7208  1.1  mrg       arg_type = long_unsigned_type_node;
   7209  1.1  mrg       func = builtin_decl_explicit (parity
   7210  1.1  mrg 				    ? BUILT_IN_PARITYL
   7211  1.1  mrg 				    : BUILT_IN_POPCOUNTL);
   7212  1.1  mrg     }
   7213  1.1  mrg   else if (argsize <= LONG_LONG_TYPE_SIZE)
   7214  1.1  mrg     {
   7215  1.1  mrg       arg_type = long_long_unsigned_type_node;
   7216  1.1  mrg       func = builtin_decl_explicit (parity
   7217  1.1  mrg 				    ? BUILT_IN_PARITYLL
   7218  1.1  mrg 				    : BUILT_IN_POPCOUNTLL);
   7219  1.1  mrg     }
   7220  1.1  mrg   else
   7221  1.1  mrg     {
   7222  1.1  mrg       /* Our argument type is larger than 'long long', which mean none
   7223  1.1  mrg 	 of the POPCOUNT builtins covers it.  We thus call the 'long long'
   7224  1.1  mrg 	 variant multiple times, and add the results.  */
   7225  1.1  mrg       tree utype, arg2, call1, call2;
   7226  1.1  mrg 
   7227  1.1  mrg       /* For now, we only cover the case where argsize is twice as large
   7228  1.1  mrg 	 as 'long long'.  */
   7229  1.1  mrg       gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
   7230  1.1  mrg 
   7231  1.1  mrg       func = builtin_decl_explicit (parity
   7232  1.1  mrg 				    ? BUILT_IN_PARITYLL
   7233  1.1  mrg 				    : BUILT_IN_POPCOUNTLL);
   7234  1.1  mrg 
   7235  1.1  mrg       /* Convert it to an integer, and store into a variable.  */
   7236  1.1  mrg       utype = gfc_build_uint_type (argsize);
   7237  1.1  mrg       arg = fold_convert (utype, arg);
   7238  1.1  mrg       arg = gfc_evaluate_now (arg, &se->pre);
   7239  1.1  mrg 
   7240  1.1  mrg       /* Call the builtin twice.  */
   7241  1.1  mrg       call1 = build_call_expr_loc (input_location, func, 1,
   7242  1.1  mrg 				   fold_convert (long_long_unsigned_type_node,
   7243  1.1  mrg 						 arg));
   7244  1.1  mrg 
   7245  1.1  mrg       arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
   7246  1.1  mrg 			      build_int_cst (utype, LONG_LONG_TYPE_SIZE));
   7247  1.1  mrg       call2 = build_call_expr_loc (input_location, func, 1,
   7248  1.1  mrg 				   fold_convert (long_long_unsigned_type_node,
   7249  1.1  mrg 						 arg2));
   7250  1.1  mrg 
   7251  1.1  mrg       /* Combine the results.  */
   7252  1.1  mrg       if (parity)
   7253  1.1  mrg 	se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR,
   7254  1.1  mrg 				    integer_type_node, call1, call2);
   7255  1.1  mrg       else
   7256  1.1  mrg 	se->expr = fold_build2_loc (input_location, PLUS_EXPR,
   7257  1.1  mrg 				    integer_type_node, call1, call2);
   7258  1.1  mrg 
   7259  1.1  mrg       se->expr = convert (result_type, se->expr);
   7260  1.1  mrg       return;
   7261  1.1  mrg     }
   7262  1.1  mrg 
   7263  1.1  mrg   /* Convert the actual argument twice: first, to the unsigned type of the
   7264  1.1  mrg      same size; then, to the proper argument type for the built-in
   7265  1.1  mrg      function.  */
   7266  1.1  mrg   arg = fold_convert (gfc_build_uint_type (argsize), arg);
   7267  1.1  mrg   arg = fold_convert (arg_type, arg);
   7268  1.1  mrg 
   7269  1.1  mrg   se->expr = fold_convert (result_type,
   7270  1.1  mrg 			   build_call_expr_loc (input_location, func, 1, arg));
   7271  1.1  mrg }
   7272  1.1  mrg 
   7273  1.1  mrg 
   7274  1.1  mrg /* Process an intrinsic with unspecified argument-types that has an optional
   7275  1.1  mrg    argument (which could be of type character), e.g. EOSHIFT.  For those, we
   7276  1.1  mrg    need to append the string length of the optional argument if it is not
   7277  1.1  mrg    present and the type is really character.
   7278  1.1  mrg    primary specifies the position (starting at 1) of the non-optional argument
   7279  1.1  mrg    specifying the type and optional gives the position of the optional
   7280  1.1  mrg    argument in the arglist.  */
   7281  1.1  mrg 
   7282  1.1  mrg static void
   7283  1.1  mrg conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
   7284  1.1  mrg 				     unsigned primary, unsigned optional)
   7285  1.1  mrg {
   7286  1.1  mrg   gfc_actual_arglist* prim_arg;
   7287  1.1  mrg   gfc_actual_arglist* opt_arg;
   7288  1.1  mrg   unsigned cur_pos;
   7289  1.1  mrg   gfc_actual_arglist* arg;
   7290  1.1  mrg   gfc_symbol* sym;
   7291  1.1  mrg   vec<tree, va_gc> *append_args;
   7292  1.1  mrg 
   7293  1.1  mrg   /* Find the two arguments given as position.  */
   7294  1.1  mrg   cur_pos = 0;
   7295  1.1  mrg   prim_arg = NULL;
   7296  1.1  mrg   opt_arg = NULL;
   7297  1.1  mrg   for (arg = expr->value.function.actual; arg; arg = arg->next)
   7298  1.1  mrg     {
   7299  1.1  mrg       ++cur_pos;
   7300  1.1  mrg 
   7301  1.1  mrg       if (cur_pos == primary)
   7302  1.1  mrg 	prim_arg = arg;
   7303  1.1  mrg       if (cur_pos == optional)
   7304  1.1  mrg 	opt_arg = arg;
   7305  1.1  mrg 
   7306  1.1  mrg       if (cur_pos >= primary && cur_pos >= optional)
   7307  1.1  mrg 	break;
   7308  1.1  mrg     }
   7309  1.1  mrg   gcc_assert (prim_arg);
   7310  1.1  mrg   gcc_assert (prim_arg->expr);
   7311  1.1  mrg   gcc_assert (opt_arg);
   7312  1.1  mrg 
   7313  1.1  mrg   /* If we do have type CHARACTER and the optional argument is really absent,
   7314  1.1  mrg      append a dummy 0 as string length.  */
   7315  1.1  mrg   append_args = NULL;
   7316  1.1  mrg   if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
   7317  1.1  mrg     {
   7318  1.1  mrg       tree dummy;
   7319  1.1  mrg 
   7320  1.1  mrg       dummy = build_int_cst (gfc_charlen_type_node, 0);
   7321  1.1  mrg       vec_alloc (append_args, 1);
   7322  1.1  mrg       append_args->quick_push (dummy);
   7323  1.1  mrg     }
   7324  1.1  mrg 
   7325  1.1  mrg   /* Build the call itself.  */
   7326  1.1  mrg   gcc_assert (!se->ignore_optional);
   7327  1.1  mrg   sym = gfc_get_symbol_for_expr (expr, false);
   7328  1.1  mrg   gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
   7329  1.1  mrg 			  append_args);
   7330  1.1  mrg   gfc_free_symbol (sym);
   7331  1.1  mrg }
   7332  1.1  mrg 
   7333  1.1  mrg /* The length of a character string.  */
   7334  1.1  mrg static void
   7335  1.1  mrg gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
   7336  1.1  mrg {
   7337  1.1  mrg   tree len;
   7338  1.1  mrg   tree type;
   7339  1.1  mrg   tree decl;
   7340  1.1  mrg   gfc_symbol *sym;
   7341  1.1  mrg   gfc_se argse;
   7342  1.1  mrg   gfc_expr *arg;
   7343  1.1  mrg 
   7344  1.1  mrg   gcc_assert (!se->ss);
   7345  1.1  mrg 
   7346  1.1  mrg   arg = expr->value.function.actual->expr;
   7347  1.1  mrg 
   7348  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7349  1.1  mrg   switch (arg->expr_type)
   7350  1.1  mrg     {
   7351  1.1  mrg     case EXPR_CONSTANT:
   7352  1.1  mrg       len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
   7353  1.1  mrg       break;
   7354  1.1  mrg 
   7355  1.1  mrg     case EXPR_ARRAY:
   7356  1.1  mrg       /* Obtain the string length from the function used by
   7357  1.1  mrg          trans-array.cc(gfc_trans_array_constructor).  */
   7358  1.1  mrg       len = NULL_TREE;
   7359  1.1  mrg       get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
   7360  1.1  mrg       break;
   7361  1.1  mrg 
   7362  1.1  mrg     case EXPR_VARIABLE:
   7363  1.1  mrg       if (arg->ref == NULL
   7364  1.1  mrg 	    || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
   7365  1.1  mrg 	{
   7366  1.1  mrg 	  /* This doesn't catch all cases.
   7367  1.1  mrg 	     See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
   7368  1.1  mrg 	     and the surrounding thread.  */
   7369  1.1  mrg 	  sym = arg->symtree->n.sym;
   7370  1.1  mrg 	  decl = gfc_get_symbol_decl (sym);
   7371  1.1  mrg 	  if (decl == current_function_decl && sym->attr.function
   7372  1.1  mrg 		&& (sym->result == sym))
   7373  1.1  mrg 	    decl = gfc_get_fake_result_decl (sym, 0);
   7374  1.1  mrg 
   7375  1.1  mrg 	  len = sym->ts.u.cl->backend_decl;
   7376  1.1  mrg 	  gcc_assert (len);
   7377  1.1  mrg 	  break;
   7378  1.1  mrg 	}
   7379  1.1  mrg 
   7380  1.1  mrg       /* Fall through.  */
   7381  1.1  mrg 
   7382  1.1  mrg     default:
   7383  1.1  mrg       gfc_init_se (&argse, se);
   7384  1.1  mrg       if (arg->rank == 0)
   7385  1.1  mrg 	gfc_conv_expr (&argse, arg);
   7386  1.1  mrg       else
   7387  1.1  mrg 	gfc_conv_expr_descriptor (&argse, arg);
   7388  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   7389  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   7390  1.1  mrg       len = argse.string_length;
   7391  1.1  mrg       break;
   7392  1.1  mrg     }
   7393  1.1  mrg   se->expr = convert (type, len);
   7394  1.1  mrg }
   7395  1.1  mrg 
   7396  1.1  mrg /* The length of a character string not including trailing blanks.  */
   7397  1.1  mrg static void
   7398  1.1  mrg gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
   7399  1.1  mrg {
   7400  1.1  mrg   int kind = expr->value.function.actual->expr->ts.kind;
   7401  1.1  mrg   tree args[2], type, fndecl;
   7402  1.1  mrg 
   7403  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   7404  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7405  1.1  mrg 
   7406  1.1  mrg   if (kind == 1)
   7407  1.1  mrg     fndecl = gfor_fndecl_string_len_trim;
   7408  1.1  mrg   else if (kind == 4)
   7409  1.1  mrg     fndecl = gfor_fndecl_string_len_trim_char4;
   7410  1.1  mrg   else
   7411  1.1  mrg     gcc_unreachable ();
   7412  1.1  mrg 
   7413  1.1  mrg   se->expr = build_call_expr_loc (input_location,
   7414  1.1  mrg 			      fndecl, 2, args[0], args[1]);
   7415  1.1  mrg   se->expr = convert (type, se->expr);
   7416  1.1  mrg }
   7417  1.1  mrg 
   7418  1.1  mrg 
   7419  1.1  mrg /* Returns the starting position of a substring within a string.  */
   7420  1.1  mrg 
   7421  1.1  mrg static void
   7422  1.1  mrg gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
   7423  1.1  mrg 				      tree function)
   7424  1.1  mrg {
   7425  1.1  mrg   tree logical4_type_node = gfc_get_logical_type (4);
   7426  1.1  mrg   tree type;
   7427  1.1  mrg   tree fndecl;
   7428  1.1  mrg   tree *args;
   7429  1.1  mrg   unsigned int num_args;
   7430  1.1  mrg 
   7431  1.1  mrg   args = XALLOCAVEC (tree, 5);
   7432  1.1  mrg 
   7433  1.1  mrg   /* Get number of arguments; characters count double due to the
   7434  1.1  mrg      string length argument. Kind= is not passed to the library
   7435  1.1  mrg      and thus ignored.  */
   7436  1.1  mrg   if (expr->value.function.actual->next->next->expr == NULL)
   7437  1.1  mrg     num_args = 4;
   7438  1.1  mrg   else
   7439  1.1  mrg     num_args = 5;
   7440  1.1  mrg 
   7441  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   7442  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7443  1.1  mrg 
   7444  1.1  mrg   if (num_args == 4)
   7445  1.1  mrg     args[4] = build_int_cst (logical4_type_node, 0);
   7446  1.1  mrg   else
   7447  1.1  mrg     args[4] = convert (logical4_type_node, args[4]);
   7448  1.1  mrg 
   7449  1.1  mrg   fndecl = build_addr (function);
   7450  1.1  mrg   se->expr = build_call_array_loc (input_location,
   7451  1.1  mrg 			       TREE_TYPE (TREE_TYPE (function)), fndecl,
   7452  1.1  mrg 			       5, args);
   7453  1.1  mrg   se->expr = convert (type, se->expr);
   7454  1.1  mrg 
   7455  1.1  mrg }
   7456  1.1  mrg 
   7457  1.1  mrg /* The ascii value for a single character.  */
   7458  1.1  mrg static void
   7459  1.1  mrg gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
   7460  1.1  mrg {
   7461  1.1  mrg   tree args[3], type, pchartype;
   7462  1.1  mrg   int nargs;
   7463  1.1  mrg 
   7464  1.1  mrg   nargs = gfc_intrinsic_argument_list_length (expr);
   7465  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, nargs);
   7466  1.1  mrg   gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
   7467  1.1  mrg   pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
   7468  1.1  mrg   args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
   7469  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7470  1.1  mrg 
   7471  1.1  mrg   se->expr = build_fold_indirect_ref_loc (input_location,
   7472  1.1  mrg 				      args[1]);
   7473  1.1  mrg   se->expr = convert (type, se->expr);
   7474  1.1  mrg }
   7475  1.1  mrg 
   7476  1.1  mrg 
   7477  1.1  mrg /* Intrinsic ISNAN calls __builtin_isnan.  */
   7478  1.1  mrg 
   7479  1.1  mrg static void
   7480  1.1  mrg gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
   7481  1.1  mrg {
   7482  1.1  mrg   tree arg;
   7483  1.1  mrg 
   7484  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7485  1.1  mrg   se->expr = build_call_expr_loc (input_location,
   7486  1.1  mrg 				  builtin_decl_explicit (BUILT_IN_ISNAN),
   7487  1.1  mrg 				  1, arg);
   7488  1.1  mrg   STRIP_TYPE_NOPS (se->expr);
   7489  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   7490  1.1  mrg }
   7491  1.1  mrg 
   7492  1.1  mrg 
   7493  1.1  mrg /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
   7494  1.1  mrg    their argument against a constant integer value.  */
   7495  1.1  mrg 
   7496  1.1  mrg static void
   7497  1.1  mrg gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
   7498  1.1  mrg {
   7499  1.1  mrg   tree arg;
   7500  1.1  mrg 
   7501  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7502  1.1  mrg   se->expr = fold_build2_loc (input_location, EQ_EXPR,
   7503  1.1  mrg 			      gfc_typenode_for_spec (&expr->ts),
   7504  1.1  mrg 			      arg, build_int_cst (TREE_TYPE (arg), value));
   7505  1.1  mrg }
   7506  1.1  mrg 
   7507  1.1  mrg 
   7508  1.1  mrg 
   7509  1.1  mrg /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource.  */
   7510  1.1  mrg 
   7511  1.1  mrg static void
   7512  1.1  mrg gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
   7513  1.1  mrg {
   7514  1.1  mrg   tree tsource;
   7515  1.1  mrg   tree fsource;
   7516  1.1  mrg   tree mask;
   7517  1.1  mrg   tree type;
   7518  1.1  mrg   tree len, len2;
   7519  1.1  mrg   tree *args;
   7520  1.1  mrg   unsigned int num_args;
   7521  1.1  mrg 
   7522  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   7523  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   7524  1.1  mrg 
   7525  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   7526  1.1  mrg   if (expr->ts.type != BT_CHARACTER)
   7527  1.1  mrg     {
   7528  1.1  mrg       tsource = args[0];
   7529  1.1  mrg       fsource = args[1];
   7530  1.1  mrg       mask = args[2];
   7531  1.1  mrg     }
   7532  1.1  mrg   else
   7533  1.1  mrg     {
   7534  1.1  mrg       /* We do the same as in the non-character case, but the argument
   7535  1.1  mrg 	 list is different because of the string length arguments. We
   7536  1.1  mrg 	 also have to set the string length for the result.  */
   7537  1.1  mrg       len = args[0];
   7538  1.1  mrg       tsource = args[1];
   7539  1.1  mrg       len2 = args[2];
   7540  1.1  mrg       fsource = args[3];
   7541  1.1  mrg       mask = args[4];
   7542  1.1  mrg 
   7543  1.1  mrg       gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
   7544  1.1  mrg 				   &se->pre);
   7545  1.1  mrg       se->string_length = len;
   7546  1.1  mrg     }
   7547  1.1  mrg   type = TREE_TYPE (tsource);
   7548  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
   7549  1.1  mrg 			      fold_convert (type, fsource));
   7550  1.1  mrg }
   7551  1.1  mrg 
   7552  1.1  mrg 
   7553  1.1  mrg /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)).  */
   7554  1.1  mrg 
   7555  1.1  mrg static void
   7556  1.1  mrg gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
   7557  1.1  mrg {
   7558  1.1  mrg   tree args[3], mask, type;
   7559  1.1  mrg 
   7560  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 3);
   7561  1.1  mrg   mask = gfc_evaluate_now (args[2], &se->pre);
   7562  1.1  mrg 
   7563  1.1  mrg   type = TREE_TYPE (args[0]);
   7564  1.1  mrg   gcc_assert (TREE_TYPE (args[1]) == type);
   7565  1.1  mrg   gcc_assert (TREE_TYPE (mask) == type);
   7566  1.1  mrg 
   7567  1.1  mrg   args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
   7568  1.1  mrg   args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
   7569  1.1  mrg 			     fold_build1_loc (input_location, BIT_NOT_EXPR,
   7570  1.1  mrg 					      type, mask));
   7571  1.1  mrg   se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
   7572  1.1  mrg 			      args[0], args[1]);
   7573  1.1  mrg }
   7574  1.1  mrg 
   7575  1.1  mrg 
   7576  1.1  mrg /* MASKL(n)  =  n == 0 ? 0 : (~0) << (BIT_SIZE - n)
   7577  1.1  mrg    MASKR(n)  =  n == BIT_SIZE ? ~0 : ~((~0) << n)  */
   7578  1.1  mrg 
   7579  1.1  mrg static void
   7580  1.1  mrg gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
   7581  1.1  mrg {
   7582  1.1  mrg   tree arg, allones, type, utype, res, cond, bitsize;
   7583  1.1  mrg   int i;
   7584  1.1  mrg 
   7585  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7586  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7587  1.1  mrg 
   7588  1.1  mrg   type = gfc_get_int_type (expr->ts.kind);
   7589  1.1  mrg   utype = unsigned_type_for (type);
   7590  1.1  mrg 
   7591  1.1  mrg   i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
   7592  1.1  mrg   bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
   7593  1.1  mrg 
   7594  1.1  mrg   allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
   7595  1.1  mrg 			     build_int_cst (utype, 0));
   7596  1.1  mrg 
   7597  1.1  mrg   if (left)
   7598  1.1  mrg     {
   7599  1.1  mrg       /* Left-justified mask.  */
   7600  1.1  mrg       res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
   7601  1.1  mrg 			     bitsize, arg);
   7602  1.1  mrg       res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
   7603  1.1  mrg 			     fold_convert (utype, res));
   7604  1.1  mrg 
   7605  1.1  mrg       /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
   7606  1.1  mrg 	 smaller than type width.  */
   7607  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
   7608  1.1  mrg 			      build_int_cst (TREE_TYPE (arg), 0));
   7609  1.1  mrg       res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
   7610  1.1  mrg 			     build_int_cst (utype, 0), res);
   7611  1.1  mrg     }
   7612  1.1  mrg   else
   7613  1.1  mrg     {
   7614  1.1  mrg       /* Right-justified mask.  */
   7615  1.1  mrg       res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
   7616  1.1  mrg 			     fold_convert (utype, arg));
   7617  1.1  mrg       res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
   7618  1.1  mrg 
   7619  1.1  mrg       /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
   7620  1.1  mrg 	 strictly smaller than type width.  */
   7621  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   7622  1.1  mrg 			      arg, bitsize);
   7623  1.1  mrg       res = fold_build3_loc (input_location, COND_EXPR, utype,
   7624  1.1  mrg 			     cond, allones, res);
   7625  1.1  mrg     }
   7626  1.1  mrg 
   7627  1.1  mrg   se->expr = fold_convert (type, res);
   7628  1.1  mrg }
   7629  1.1  mrg 
   7630  1.1  mrg 
   7631  1.1  mrg /* FRACTION (s) is translated into:
   7632  1.1  mrg      isfinite (s) ? frexp (s, &dummy_int) : NaN  */
   7633  1.1  mrg static void
   7634  1.1  mrg gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
   7635  1.1  mrg {
   7636  1.1  mrg   tree arg, type, tmp, res, frexp, cond;
   7637  1.1  mrg 
   7638  1.1  mrg   frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
   7639  1.1  mrg 
   7640  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7641  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7642  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7643  1.1  mrg 
   7644  1.1  mrg   cond = build_call_expr_loc (input_location,
   7645  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_ISFINITE),
   7646  1.1  mrg 			      1, arg);
   7647  1.1  mrg 
   7648  1.1  mrg   tmp = gfc_create_var (integer_type_node, NULL);
   7649  1.1  mrg   res = build_call_expr_loc (input_location, frexp, 2,
   7650  1.1  mrg 			     fold_convert (type, arg),
   7651  1.1  mrg 			     gfc_build_addr_expr (NULL_TREE, tmp));
   7652  1.1  mrg   res = fold_convert (type, res);
   7653  1.1  mrg 
   7654  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type,
   7655  1.1  mrg 			      cond, res, gfc_build_nan (type, ""));
   7656  1.1  mrg }
   7657  1.1  mrg 
   7658  1.1  mrg 
   7659  1.1  mrg /* NEAREST (s, dir) is translated into
   7660  1.1  mrg      tmp = copysign (HUGE_VAL, dir);
   7661  1.1  mrg      return nextafter (s, tmp);
   7662  1.1  mrg  */
   7663  1.1  mrg static void
   7664  1.1  mrg gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
   7665  1.1  mrg {
   7666  1.1  mrg   tree args[2], type, tmp, nextafter, copysign, huge_val;
   7667  1.1  mrg 
   7668  1.1  mrg   nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
   7669  1.1  mrg   copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
   7670  1.1  mrg 
   7671  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7672  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   7673  1.1  mrg 
   7674  1.1  mrg   huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
   7675  1.1  mrg   tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
   7676  1.1  mrg 			     fold_convert (type, args[1]));
   7677  1.1  mrg   se->expr = build_call_expr_loc (input_location, nextafter, 2,
   7678  1.1  mrg 				  fold_convert (type, args[0]), tmp);
   7679  1.1  mrg   se->expr = fold_convert (type, se->expr);
   7680  1.1  mrg }
   7681  1.1  mrg 
   7682  1.1  mrg 
   7683  1.1  mrg /* SPACING (s) is translated into
   7684  1.1  mrg     int e;
   7685  1.1  mrg     if (!isfinite (s))
   7686  1.1  mrg       res = NaN;
   7687  1.1  mrg     else if (s == 0)
   7688  1.1  mrg       res = tiny;
   7689  1.1  mrg     else
   7690  1.1  mrg     {
   7691  1.1  mrg       frexp (s, &e);
   7692  1.1  mrg       e = e - prec;
   7693  1.1  mrg       e = MAX_EXPR (e, emin);
   7694  1.1  mrg       res = scalbn (1., e);
   7695  1.1  mrg     }
   7696  1.1  mrg     return res;
   7697  1.1  mrg 
   7698  1.1  mrg  where prec is the precision of s, gfc_real_kinds[k].digits,
   7699  1.1  mrg        emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
   7700  1.1  mrg    and tiny is tiny(s), gfc_real_kinds[k].tiny.  */
   7701  1.1  mrg 
   7702  1.1  mrg static void
   7703  1.1  mrg gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
   7704  1.1  mrg {
   7705  1.1  mrg   tree arg, type, prec, emin, tiny, res, e;
   7706  1.1  mrg   tree cond, nan, tmp, frexp, scalbn;
   7707  1.1  mrg   int k;
   7708  1.1  mrg   stmtblock_t block;
   7709  1.1  mrg 
   7710  1.1  mrg   k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
   7711  1.1  mrg   prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
   7712  1.1  mrg   emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
   7713  1.1  mrg   tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
   7714  1.1  mrg 
   7715  1.1  mrg   frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
   7716  1.1  mrg   scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
   7717  1.1  mrg 
   7718  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7719  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7720  1.1  mrg 
   7721  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7722  1.1  mrg   e = gfc_create_var (integer_type_node, NULL);
   7723  1.1  mrg   res = gfc_create_var (type, NULL);
   7724  1.1  mrg 
   7725  1.1  mrg 
   7726  1.1  mrg   /* Build the block for s /= 0.  */
   7727  1.1  mrg   gfc_start_block (&block);
   7728  1.1  mrg   tmp = build_call_expr_loc (input_location, frexp, 2, arg,
   7729  1.1  mrg 			     gfc_build_addr_expr (NULL_TREE, e));
   7730  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   7731  1.1  mrg 
   7732  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
   7733  1.1  mrg 			 prec);
   7734  1.1  mrg   gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
   7735  1.1  mrg 					      integer_type_node, tmp, emin));
   7736  1.1  mrg 
   7737  1.1  mrg   tmp = build_call_expr_loc (input_location, scalbn, 2,
   7738  1.1  mrg 			 build_real_from_int_cst (type, integer_one_node), e);
   7739  1.1  mrg   gfc_add_modify (&block, res, tmp);
   7740  1.1  mrg 
   7741  1.1  mrg   /* Finish by building the IF statement for value zero.  */
   7742  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
   7743  1.1  mrg 			  build_real_from_int_cst (type, integer_zero_node));
   7744  1.1  mrg   tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
   7745  1.1  mrg 		  gfc_finish_block (&block));
   7746  1.1  mrg 
   7747  1.1  mrg   /* And deal with infinities and NaNs.  */
   7748  1.1  mrg   cond = build_call_expr_loc (input_location,
   7749  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_ISFINITE),
   7750  1.1  mrg 			      1, arg);
   7751  1.1  mrg   nan = gfc_build_nan (type, "");
   7752  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
   7753  1.1  mrg 
   7754  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   7755  1.1  mrg   se->expr = res;
   7756  1.1  mrg }
   7757  1.1  mrg 
   7758  1.1  mrg 
   7759  1.1  mrg /* RRSPACING (s) is translated into
   7760  1.1  mrg       int e;
   7761  1.1  mrg       real x;
   7762  1.1  mrg       x = fabs (s);
   7763  1.1  mrg       if (isfinite (x))
   7764  1.1  mrg       {
   7765  1.1  mrg 	if (x != 0)
   7766  1.1  mrg 	{
   7767  1.1  mrg 	  frexp (s, &e);
   7768  1.1  mrg 	  x = scalbn (x, precision - e);
   7769  1.1  mrg 	}
   7770  1.1  mrg       }
   7771  1.1  mrg       else
   7772  1.1  mrg         x = NaN;
   7773  1.1  mrg       return x;
   7774  1.1  mrg 
   7775  1.1  mrg  where precision is gfc_real_kinds[k].digits.  */
   7776  1.1  mrg 
   7777  1.1  mrg static void
   7778  1.1  mrg gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
   7779  1.1  mrg {
   7780  1.1  mrg   tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
   7781  1.1  mrg   int prec, k;
   7782  1.1  mrg   stmtblock_t block;
   7783  1.1  mrg 
   7784  1.1  mrg   k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
   7785  1.1  mrg   prec = gfc_real_kinds[k].digits;
   7786  1.1  mrg 
   7787  1.1  mrg   frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
   7788  1.1  mrg   scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
   7789  1.1  mrg   fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
   7790  1.1  mrg 
   7791  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7792  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   7793  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   7794  1.1  mrg 
   7795  1.1  mrg   e = gfc_create_var (integer_type_node, NULL);
   7796  1.1  mrg   x = gfc_create_var (type, NULL);
   7797  1.1  mrg   gfc_add_modify (&se->pre, x,
   7798  1.1  mrg 		  build_call_expr_loc (input_location, fabs, 1, arg));
   7799  1.1  mrg 
   7800  1.1  mrg 
   7801  1.1  mrg   gfc_start_block (&block);
   7802  1.1  mrg   tmp = build_call_expr_loc (input_location, frexp, 2, arg,
   7803  1.1  mrg 			     gfc_build_addr_expr (NULL_TREE, e));
   7804  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   7805  1.1  mrg 
   7806  1.1  mrg   tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
   7807  1.1  mrg 			 build_int_cst (integer_type_node, prec), e);
   7808  1.1  mrg   tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
   7809  1.1  mrg   gfc_add_modify (&block, x, tmp);
   7810  1.1  mrg   stmt = gfc_finish_block (&block);
   7811  1.1  mrg 
   7812  1.1  mrg   /* if (x != 0) */
   7813  1.1  mrg   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
   7814  1.1  mrg 			  build_real_from_int_cst (type, integer_zero_node));
   7815  1.1  mrg   tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
   7816  1.1  mrg 
   7817  1.1  mrg   /* And deal with infinities and NaNs.  */
   7818  1.1  mrg   cond = build_call_expr_loc (input_location,
   7819  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_ISFINITE),
   7820  1.1  mrg 			      1, x);
   7821  1.1  mrg   nan = gfc_build_nan (type, "");
   7822  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
   7823  1.1  mrg 
   7824  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   7825  1.1  mrg   se->expr = fold_convert (type, x);
   7826  1.1  mrg }
   7827  1.1  mrg 
   7828  1.1  mrg 
   7829  1.1  mrg /* SCALE (s, i) is translated into scalbn (s, i).  */
   7830  1.1  mrg static void
   7831  1.1  mrg gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
   7832  1.1  mrg {
   7833  1.1  mrg   tree args[2], type, scalbn;
   7834  1.1  mrg 
   7835  1.1  mrg   scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
   7836  1.1  mrg 
   7837  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7838  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   7839  1.1  mrg   se->expr = build_call_expr_loc (input_location, scalbn, 2,
   7840  1.1  mrg 				  fold_convert (type, args[0]),
   7841  1.1  mrg 				  fold_convert (integer_type_node, args[1]));
   7842  1.1  mrg   se->expr = fold_convert (type, se->expr);
   7843  1.1  mrg }
   7844  1.1  mrg 
   7845  1.1  mrg 
   7846  1.1  mrg /* SET_EXPONENT (s, i) is translated into
   7847  1.1  mrg    isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN  */
   7848  1.1  mrg static void
   7849  1.1  mrg gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
   7850  1.1  mrg {
   7851  1.1  mrg   tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
   7852  1.1  mrg 
   7853  1.1  mrg   frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
   7854  1.1  mrg   scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
   7855  1.1  mrg 
   7856  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   7857  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   7858  1.1  mrg   args[0] = gfc_evaluate_now (args[0], &se->pre);
   7859  1.1  mrg 
   7860  1.1  mrg   tmp = gfc_create_var (integer_type_node, NULL);
   7861  1.1  mrg   tmp = build_call_expr_loc (input_location, frexp, 2,
   7862  1.1  mrg 			     fold_convert (type, args[0]),
   7863  1.1  mrg 			     gfc_build_addr_expr (NULL_TREE, tmp));
   7864  1.1  mrg   res = build_call_expr_loc (input_location, scalbn, 2, tmp,
   7865  1.1  mrg 			     fold_convert (integer_type_node, args[1]));
   7866  1.1  mrg   res = fold_convert (type, res);
   7867  1.1  mrg 
   7868  1.1  mrg   /* Call to isfinite */
   7869  1.1  mrg   cond = build_call_expr_loc (input_location,
   7870  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_ISFINITE),
   7871  1.1  mrg 			      1, args[0]);
   7872  1.1  mrg   nan = gfc_build_nan (type, "");
   7873  1.1  mrg 
   7874  1.1  mrg   se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
   7875  1.1  mrg 			      res, nan);
   7876  1.1  mrg }
   7877  1.1  mrg 
   7878  1.1  mrg 
   7879  1.1  mrg static void
   7880  1.1  mrg gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
   7881  1.1  mrg {
   7882  1.1  mrg   gfc_actual_arglist *actual;
   7883  1.1  mrg   tree arg1;
   7884  1.1  mrg   tree type;
   7885  1.1  mrg   tree size;
   7886  1.1  mrg   gfc_se argse;
   7887  1.1  mrg   gfc_expr *e;
   7888  1.1  mrg   gfc_symbol *sym = NULL;
   7889  1.1  mrg 
   7890  1.1  mrg   gfc_init_se (&argse, NULL);
   7891  1.1  mrg   actual = expr->value.function.actual;
   7892  1.1  mrg 
   7893  1.1  mrg   if (actual->expr->ts.type == BT_CLASS)
   7894  1.1  mrg     gfc_add_class_array_ref (actual->expr);
   7895  1.1  mrg 
   7896  1.1  mrg   e = actual->expr;
   7897  1.1  mrg 
   7898  1.1  mrg   /* These are emerging from the interface mapping, when a class valued
   7899  1.1  mrg      function appears as the rhs in a realloc on assign statement, where
   7900  1.1  mrg      the size of the result is that of one of the actual arguments.  */
   7901  1.1  mrg   if (e->expr_type == EXPR_VARIABLE
   7902  1.1  mrg       && e->symtree->n.sym->ns == NULL /* This is distinctive!  */
   7903  1.1  mrg       && e->symtree->n.sym->ts.type == BT_CLASS
   7904  1.1  mrg       && e->ref && e->ref->type == REF_COMPONENT
   7905  1.1  mrg       && strcmp (e->ref->u.c.component->name, "_data") == 0)
   7906  1.1  mrg     sym = e->symtree->n.sym;
   7907  1.1  mrg 
   7908  1.1  mrg   if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
   7909  1.1  mrg       && e
   7910  1.1  mrg       && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
   7911  1.1  mrg     {
   7912  1.1  mrg       symbol_attribute attr;
   7913  1.1  mrg       char *msg;
   7914  1.1  mrg       tree temp;
   7915  1.1  mrg       tree cond;
   7916  1.1  mrg 
   7917  1.1  mrg       if (e->symtree->n.sym && IS_CLASS_ARRAY (e->symtree->n.sym))
   7918  1.1  mrg 	{
   7919  1.1  mrg 	  attr = CLASS_DATA (e->symtree->n.sym)->attr;
   7920  1.1  mrg 	  attr.pointer = attr.class_pointer;
   7921  1.1  mrg 	}
   7922  1.1  mrg       else
   7923  1.1  mrg 	attr = gfc_expr_attr (e);
   7924  1.1  mrg 
   7925  1.1  mrg       if (attr.allocatable)
   7926  1.1  mrg 	msg = xasprintf ("Allocatable argument '%s' is not allocated",
   7927  1.1  mrg 			 e->symtree->n.sym->name);
   7928  1.1  mrg       else if (attr.pointer)
   7929  1.1  mrg 	msg = xasprintf ("Pointer argument '%s' is not associated",
   7930  1.1  mrg 			 e->symtree->n.sym->name);
   7931  1.1  mrg       else
   7932  1.1  mrg 	goto end_arg_check;
   7933  1.1  mrg 
   7934  1.1  mrg       if (sym)
   7935  1.1  mrg 	{
   7936  1.1  mrg 	  temp = gfc_class_data_get (sym->backend_decl);
   7937  1.1  mrg 	  temp = gfc_conv_descriptor_data_get (temp);
   7938  1.1  mrg 	}
   7939  1.1  mrg       else
   7940  1.1  mrg 	{
   7941  1.1  mrg 	  argse.descriptor_only = 1;
   7942  1.1  mrg 	  gfc_conv_expr_descriptor (&argse, actual->expr);
   7943  1.1  mrg 	  temp = gfc_conv_descriptor_data_get (argse.expr);
   7944  1.1  mrg 	}
   7945  1.1  mrg 
   7946  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR,
   7947  1.1  mrg 			      logical_type_node, temp,
   7948  1.1  mrg 			      fold_convert (TREE_TYPE (temp),
   7949  1.1  mrg 					    null_pointer_node));
   7950  1.1  mrg       gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
   7951  1.1  mrg 
   7952  1.1  mrg       free (msg);
   7953  1.1  mrg     }
   7954  1.1  mrg  end_arg_check:
   7955  1.1  mrg 
   7956  1.1  mrg   argse.data_not_needed = 1;
   7957  1.1  mrg   if (gfc_is_class_array_function (e))
   7958  1.1  mrg     {
   7959  1.1  mrg       /* For functions that return a class array conv_expr_descriptor is not
   7960  1.1  mrg 	 able to get the descriptor right.  Therefore this special case.  */
   7961  1.1  mrg       gfc_conv_expr_reference (&argse, e);
   7962  1.1  mrg       argse.expr = gfc_class_data_get (argse.expr);
   7963  1.1  mrg     }
   7964  1.1  mrg   else if (sym && sym->backend_decl)
   7965  1.1  mrg     {
   7966  1.1  mrg       gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
   7967  1.1  mrg       argse.expr = gfc_class_data_get (sym->backend_decl);
   7968  1.1  mrg     }
   7969  1.1  mrg   else
   7970  1.1  mrg     gfc_conv_expr_descriptor (&argse, actual->expr);
   7971  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   7972  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   7973  1.1  mrg   arg1 = argse.expr;
   7974  1.1  mrg 
   7975  1.1  mrg   actual = actual->next;
   7976  1.1  mrg   if (actual->expr)
   7977  1.1  mrg     {
   7978  1.1  mrg       stmtblock_t block;
   7979  1.1  mrg       gfc_init_block (&block);
   7980  1.1  mrg       gfc_init_se (&argse, NULL);
   7981  1.1  mrg       gfc_conv_expr_type (&argse, actual->expr,
   7982  1.1  mrg 			  gfc_array_index_type);
   7983  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   7984  1.1  mrg       tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   7985  1.1  mrg 			     argse.expr, gfc_index_one_node);
   7986  1.1  mrg       size = gfc_tree_array_size (&block, arg1, e, tmp);
   7987  1.1  mrg 
   7988  1.1  mrg       /* Unusually, for an intrinsic, size does not exclude
   7989  1.1  mrg 	 an optional arg2, so we must test for it.  */
   7990  1.1  mrg       if (actual->expr->expr_type == EXPR_VARIABLE
   7991  1.1  mrg 	    && actual->expr->symtree->n.sym->attr.dummy
   7992  1.1  mrg 	    && actual->expr->symtree->n.sym->attr.optional)
   7993  1.1  mrg 	{
   7994  1.1  mrg 	  tree cond;
   7995  1.1  mrg 	  stmtblock_t block2;
   7996  1.1  mrg 	  gfc_init_block (&block2);
   7997  1.1  mrg 	  gfc_init_se (&argse, NULL);
   7998  1.1  mrg 	  argse.want_pointer = 1;
   7999  1.1  mrg 	  argse.data_not_needed = 1;
   8000  1.1  mrg 	  gfc_conv_expr (&argse, actual->expr);
   8001  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &argse.pre);
   8002  1.1  mrg 	  cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   8003  1.1  mrg 				  argse.expr, null_pointer_node);
   8004  1.1  mrg 	  cond = gfc_evaluate_now (cond, &se->pre);
   8005  1.1  mrg 	  /* 'block2' contains the arg2 absent case, 'block' the arg2 present
   8006  1.1  mrg 	      case; size_var can be used in both blocks. */
   8007  1.1  mrg 	  tree size_var = gfc_create_var (TREE_TYPE (size), "size");
   8008  1.1  mrg 	  tmp = fold_build2_loc (input_location, MODIFY_EXPR,
   8009  1.1  mrg 				 TREE_TYPE (size_var), size_var, size);
   8010  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   8011  1.1  mrg 	  size = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
   8012  1.1  mrg 	  tmp = fold_build2_loc (input_location, MODIFY_EXPR,
   8013  1.1  mrg 				 TREE_TYPE (size_var), size_var, size);
   8014  1.1  mrg 	  gfc_add_expr_to_block (&block2, tmp);
   8015  1.1  mrg 	  tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
   8016  1.1  mrg 			  gfc_finish_block (&block2));
   8017  1.1  mrg 	  gfc_add_expr_to_block (&se->pre, tmp);
   8018  1.1  mrg 	  size = size_var;
   8019  1.1  mrg 	}
   8020  1.1  mrg       else
   8021  1.1  mrg 	gfc_add_block_to_block (&se->pre, &block);
   8022  1.1  mrg     }
   8023  1.1  mrg   else
   8024  1.1  mrg     size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
   8025  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   8026  1.1  mrg   se->expr = convert (type, size);
   8027  1.1  mrg }
   8028  1.1  mrg 
   8029  1.1  mrg 
   8030  1.1  mrg /* Helper function to compute the size of a character variable,
   8031  1.1  mrg    excluding the terminating null characters.  The result has
   8032  1.1  mrg    gfc_array_index_type type.  */
   8033  1.1  mrg 
   8034  1.1  mrg tree
   8035  1.1  mrg size_of_string_in_bytes (int kind, tree string_length)
   8036  1.1  mrg {
   8037  1.1  mrg   tree bytesize;
   8038  1.1  mrg   int i = gfc_validate_kind (BT_CHARACTER, kind, false);
   8039  1.1  mrg 
   8040  1.1  mrg   bytesize = build_int_cst (gfc_array_index_type,
   8041  1.1  mrg 			    gfc_character_kinds[i].bit_size / 8);
   8042  1.1  mrg 
   8043  1.1  mrg   return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
   8044  1.1  mrg 			  bytesize,
   8045  1.1  mrg 			  fold_convert (gfc_array_index_type, string_length));
   8046  1.1  mrg }
   8047  1.1  mrg 
   8048  1.1  mrg 
   8049  1.1  mrg static void
   8050  1.1  mrg gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
   8051  1.1  mrg {
   8052  1.1  mrg   gfc_expr *arg;
   8053  1.1  mrg   gfc_se argse;
   8054  1.1  mrg   tree source_bytes;
   8055  1.1  mrg   tree tmp;
   8056  1.1  mrg   tree lower;
   8057  1.1  mrg   tree upper;
   8058  1.1  mrg   tree byte_size;
   8059  1.1  mrg   tree field;
   8060  1.1  mrg   int n;
   8061  1.1  mrg 
   8062  1.1  mrg   gfc_init_se (&argse, NULL);
   8063  1.1  mrg   arg = expr->value.function.actual->expr;
   8064  1.1  mrg 
   8065  1.1  mrg   if (arg->rank || arg->ts.type == BT_ASSUMED)
   8066  1.1  mrg     gfc_conv_expr_descriptor (&argse, arg);
   8067  1.1  mrg   else
   8068  1.1  mrg     gfc_conv_expr_reference (&argse, arg);
   8069  1.1  mrg 
   8070  1.1  mrg   if (arg->ts.type == BT_ASSUMED)
   8071  1.1  mrg     {
   8072  1.1  mrg       /* This only works if an array descriptor has been passed; thus, extract
   8073  1.1  mrg 	 the size from the descriptor.  */
   8074  1.1  mrg       gcc_assert (TYPE_PRECISION (gfc_array_index_type)
   8075  1.1  mrg 		  == TYPE_PRECISION (size_type_node));
   8076  1.1  mrg       tmp = arg->symtree->n.sym->backend_decl;
   8077  1.1  mrg       tmp = DECL_LANG_SPECIFIC (tmp)
   8078  1.1  mrg 	    && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
   8079  1.1  mrg 	    ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
   8080  1.1  mrg       if (POINTER_TYPE_P (TREE_TYPE (tmp)))
   8081  1.1  mrg 	tmp = build_fold_indirect_ref_loc (input_location, tmp);
   8082  1.1  mrg 
   8083  1.1  mrg       tmp = gfc_conv_descriptor_dtype (tmp);
   8084  1.1  mrg       field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
   8085  1.1  mrg 				 GFC_DTYPE_ELEM_LEN);
   8086  1.1  mrg       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   8087  1.1  mrg 			     tmp, field, NULL_TREE);
   8088  1.1  mrg 
   8089  1.1  mrg       byte_size = fold_convert (gfc_array_index_type, tmp);
   8090  1.1  mrg     }
   8091  1.1  mrg   else if (arg->ts.type == BT_CLASS)
   8092  1.1  mrg     {
   8093  1.1  mrg       /* Conv_expr_descriptor returns a component_ref to _data component of the
   8094  1.1  mrg 	 class object.  The class object may be a non-pointer object, e.g.
   8095  1.1  mrg 	 located on the stack, or a memory location pointed to, e.g. a
   8096  1.1  mrg 	 parameter, i.e., an indirect_ref.  */
   8097  1.1  mrg       if (POINTER_TYPE_P (TREE_TYPE (argse.expr))
   8098  1.1  mrg 	  && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse.expr))))
   8099  1.1  mrg 	byte_size
   8100  1.1  mrg 	  = gfc_class_vtab_size_get (build_fold_indirect_ref (argse.expr));
   8101  1.1  mrg       else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse.expr)))
   8102  1.1  mrg 	byte_size = gfc_class_vtab_size_get (argse.expr);
   8103  1.1  mrg       else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse.expr))
   8104  1.1  mrg 	       && TREE_CODE (argse.expr) == COMPONENT_REF)
   8105  1.1  mrg 	byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
   8106  1.1  mrg       else if (arg->rank > 0
   8107  1.1  mrg 	       || (arg->rank == 0
   8108  1.1  mrg 		   && arg->ref && arg->ref->type == REF_COMPONENT))
   8109  1.1  mrg 	/* The scalarizer added an additional temp.  To get the class' vptr
   8110  1.1  mrg 	   one has to look at the original backend_decl.  */
   8111  1.1  mrg 	byte_size = gfc_class_vtab_size_get (
   8112  1.1  mrg 	      GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
   8113  1.1  mrg       else
   8114  1.1  mrg 	gcc_unreachable ();
   8115  1.1  mrg     }
   8116  1.1  mrg   else
   8117  1.1  mrg     {
   8118  1.1  mrg       if (arg->ts.type == BT_CHARACTER)
   8119  1.1  mrg 	byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
   8120  1.1  mrg       else
   8121  1.1  mrg 	{
   8122  1.1  mrg 	  if (arg->rank == 0)
   8123  1.1  mrg 	    byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
   8124  1.1  mrg 								argse.expr));
   8125  1.1  mrg 	  else
   8126  1.1  mrg 	    byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
   8127  1.1  mrg 	  byte_size = fold_convert (gfc_array_index_type,
   8128  1.1  mrg 				    size_in_bytes (byte_size));
   8129  1.1  mrg 	}
   8130  1.1  mrg     }
   8131  1.1  mrg 
   8132  1.1  mrg   if (arg->rank == 0)
   8133  1.1  mrg     se->expr = byte_size;
   8134  1.1  mrg   else
   8135  1.1  mrg     {
   8136  1.1  mrg       source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
   8137  1.1  mrg       gfc_add_modify (&argse.pre, source_bytes, byte_size);
   8138  1.1  mrg 
   8139  1.1  mrg       if (arg->rank == -1)
   8140  1.1  mrg 	{
   8141  1.1  mrg 	  tree cond, loop_var, exit_label;
   8142  1.1  mrg           stmtblock_t body;
   8143  1.1  mrg 
   8144  1.1  mrg 	  tmp = fold_convert (gfc_array_index_type,
   8145  1.1  mrg 			      gfc_conv_descriptor_rank (argse.expr));
   8146  1.1  mrg 	  loop_var = gfc_create_var (gfc_array_index_type, "i");
   8147  1.1  mrg 	  gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
   8148  1.1  mrg           exit_label = gfc_build_label_decl (NULL_TREE);
   8149  1.1  mrg 
   8150  1.1  mrg 	  /* Create loop:
   8151  1.1  mrg 	     for (;;)
   8152  1.1  mrg 		{
   8153  1.1  mrg 		  if (i >= rank)
   8154  1.1  mrg 		    goto exit;
   8155  1.1  mrg 		  source_bytes = source_bytes * array.dim[i].extent;
   8156  1.1  mrg 		  i = i + 1;
   8157  1.1  mrg 		}
   8158  1.1  mrg 	      exit:  */
   8159  1.1  mrg 	  gfc_start_block (&body);
   8160  1.1  mrg 	  cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
   8161  1.1  mrg 				  loop_var, tmp);
   8162  1.1  mrg 	  tmp = build1_v (GOTO_EXPR, exit_label);
   8163  1.1  mrg 	  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
   8164  1.1  mrg 				 cond, tmp, build_empty_stmt (input_location));
   8165  1.1  mrg 	  gfc_add_expr_to_block (&body, tmp);
   8166  1.1  mrg 
   8167  1.1  mrg 	  lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
   8168  1.1  mrg 	  upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
   8169  1.1  mrg 	  tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
   8170  1.1  mrg 	  tmp = fold_build2_loc (input_location, MULT_EXPR,
   8171  1.1  mrg 				 gfc_array_index_type, tmp, source_bytes);
   8172  1.1  mrg 	  gfc_add_modify (&body, source_bytes, tmp);
   8173  1.1  mrg 
   8174  1.1  mrg 	  tmp = fold_build2_loc (input_location, PLUS_EXPR,
   8175  1.1  mrg 				 gfc_array_index_type, loop_var,
   8176  1.1  mrg 				 gfc_index_one_node);
   8177  1.1  mrg 	  gfc_add_modify_loc (input_location, &body, loop_var, tmp);
   8178  1.1  mrg 
   8179  1.1  mrg 	  tmp = gfc_finish_block (&body);
   8180  1.1  mrg 
   8181  1.1  mrg 	  tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
   8182  1.1  mrg 				 tmp);
   8183  1.1  mrg 	  gfc_add_expr_to_block (&argse.pre, tmp);
   8184  1.1  mrg 
   8185  1.1  mrg 	  tmp = build1_v (LABEL_EXPR, exit_label);
   8186  1.1  mrg 	  gfc_add_expr_to_block (&argse.pre, tmp);
   8187  1.1  mrg 	}
   8188  1.1  mrg       else
   8189  1.1  mrg 	{
   8190  1.1  mrg 	  /* Obtain the size of the array in bytes.  */
   8191  1.1  mrg 	  for (n = 0; n < arg->rank; n++)
   8192  1.1  mrg 	    {
   8193  1.1  mrg 	      tree idx;
   8194  1.1  mrg 	      idx = gfc_rank_cst[n];
   8195  1.1  mrg 	      lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
   8196  1.1  mrg 	      upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
   8197  1.1  mrg 	      tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
   8198  1.1  mrg 	      tmp = fold_build2_loc (input_location, MULT_EXPR,
   8199  1.1  mrg 				     gfc_array_index_type, tmp, source_bytes);
   8200  1.1  mrg 	      gfc_add_modify (&argse.pre, source_bytes, tmp);
   8201  1.1  mrg 	    }
   8202  1.1  mrg 	}
   8203  1.1  mrg       se->expr = source_bytes;
   8204  1.1  mrg     }
   8205  1.1  mrg 
   8206  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   8207  1.1  mrg }
   8208  1.1  mrg 
   8209  1.1  mrg 
   8210  1.1  mrg static void
   8211  1.1  mrg gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
   8212  1.1  mrg {
   8213  1.1  mrg   gfc_expr *arg;
   8214  1.1  mrg   gfc_se argse;
   8215  1.1  mrg   tree type, result_type, tmp;
   8216  1.1  mrg 
   8217  1.1  mrg   arg = expr->value.function.actual->expr;
   8218  1.1  mrg 
   8219  1.1  mrg   gfc_init_se (&argse, NULL);
   8220  1.1  mrg   result_type = gfc_get_int_type (expr->ts.kind);
   8221  1.1  mrg 
   8222  1.1  mrg   if (arg->rank == 0)
   8223  1.1  mrg     {
   8224  1.1  mrg       if (arg->ts.type == BT_CLASS)
   8225  1.1  mrg 	{
   8226  1.1  mrg 	  gfc_add_vptr_component (arg);
   8227  1.1  mrg 	  gfc_add_size_component (arg);
   8228  1.1  mrg 	  gfc_conv_expr (&argse, arg);
   8229  1.1  mrg 	  tmp = fold_convert (result_type, argse.expr);
   8230  1.1  mrg 	  goto done;
   8231  1.1  mrg 	}
   8232  1.1  mrg 
   8233  1.1  mrg       gfc_conv_expr_reference (&argse, arg);
   8234  1.1  mrg       type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
   8235  1.1  mrg 						     argse.expr));
   8236  1.1  mrg     }
   8237  1.1  mrg   else
   8238  1.1  mrg     {
   8239  1.1  mrg       argse.want_pointer = 0;
   8240  1.1  mrg       gfc_conv_expr_descriptor (&argse, arg);
   8241  1.1  mrg       if (arg->ts.type == BT_CLASS)
   8242  1.1  mrg 	{
   8243  1.1  mrg 	  if (arg->rank > 0)
   8244  1.1  mrg 	    tmp = gfc_class_vtab_size_get (
   8245  1.1  mrg 		 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
   8246  1.1  mrg 	  else
   8247  1.1  mrg 	    tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
   8248  1.1  mrg 	  tmp = fold_convert (result_type, tmp);
   8249  1.1  mrg 	  goto done;
   8250  1.1  mrg 	}
   8251  1.1  mrg       type = gfc_get_element_type (TREE_TYPE (argse.expr));
   8252  1.1  mrg     }
   8253  1.1  mrg 
   8254  1.1  mrg   /* Obtain the argument's word length.  */
   8255  1.1  mrg   if (arg->ts.type == BT_CHARACTER)
   8256  1.1  mrg     tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
   8257  1.1  mrg   else
   8258  1.1  mrg     tmp = size_in_bytes (type);
   8259  1.1  mrg   tmp = fold_convert (result_type, tmp);
   8260  1.1  mrg 
   8261  1.1  mrg done:
   8262  1.1  mrg   se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
   8263  1.1  mrg 			      build_int_cst (result_type, BITS_PER_UNIT));
   8264  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   8265  1.1  mrg }
   8266  1.1  mrg 
   8267  1.1  mrg 
   8268  1.1  mrg /* Intrinsic string comparison functions.  */
   8269  1.1  mrg 
   8270  1.1  mrg static void
   8271  1.1  mrg gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
   8272  1.1  mrg {
   8273  1.1  mrg   tree args[4];
   8274  1.1  mrg 
   8275  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 4);
   8276  1.1  mrg 
   8277  1.1  mrg   se->expr
   8278  1.1  mrg     = gfc_build_compare_string (args[0], args[1], args[2], args[3],
   8279  1.1  mrg 				expr->value.function.actual->expr->ts.kind,
   8280  1.1  mrg 				op);
   8281  1.1  mrg   se->expr = fold_build2_loc (input_location, op,
   8282  1.1  mrg 			      gfc_typenode_for_spec (&expr->ts), se->expr,
   8283  1.1  mrg 			      build_int_cst (TREE_TYPE (se->expr), 0));
   8284  1.1  mrg }
   8285  1.1  mrg 
   8286  1.1  mrg /* Generate a call to the adjustl/adjustr library function.  */
   8287  1.1  mrg static void
   8288  1.1  mrg gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
   8289  1.1  mrg {
   8290  1.1  mrg   tree args[3];
   8291  1.1  mrg   tree len;
   8292  1.1  mrg   tree type;
   8293  1.1  mrg   tree var;
   8294  1.1  mrg   tree tmp;
   8295  1.1  mrg 
   8296  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
   8297  1.1  mrg   len = args[1];
   8298  1.1  mrg 
   8299  1.1  mrg   type = TREE_TYPE (args[2]);
   8300  1.1  mrg   var = gfc_conv_string_tmp (se, type, len);
   8301  1.1  mrg   args[0] = var;
   8302  1.1  mrg 
   8303  1.1  mrg   tmp = build_call_expr_loc (input_location,
   8304  1.1  mrg 			 fndecl, 3, args[0], args[1], args[2]);
   8305  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   8306  1.1  mrg   se->expr = var;
   8307  1.1  mrg   se->string_length = len;
   8308  1.1  mrg }
   8309  1.1  mrg 
   8310  1.1  mrg 
   8311  1.1  mrg /* Generate code for the TRANSFER intrinsic:
   8312  1.1  mrg 	For scalar results:
   8313  1.1  mrg 	  DEST = TRANSFER (SOURCE, MOLD)
   8314  1.1  mrg 	where:
   8315  1.1  mrg 	  typeof<DEST> = typeof<MOLD>
   8316  1.1  mrg 	and:
   8317  1.1  mrg 	  MOLD is scalar.
   8318  1.1  mrg 
   8319  1.1  mrg 	For array results:
   8320  1.1  mrg 	  DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
   8321  1.1  mrg 	where:
   8322  1.1  mrg 	  typeof<DEST> = typeof<MOLD>
   8323  1.1  mrg 	and:
   8324  1.1  mrg 	  N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
   8325  1.1  mrg 	      sizeof (DEST(0) * SIZE).  */
   8326  1.1  mrg static void
   8327  1.1  mrg gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
   8328  1.1  mrg {
   8329  1.1  mrg   tree tmp;
   8330  1.1  mrg   tree tmpdecl;
   8331  1.1  mrg   tree ptr;
   8332  1.1  mrg   tree extent;
   8333  1.1  mrg   tree source;
   8334  1.1  mrg   tree source_type;
   8335  1.1  mrg   tree source_bytes;
   8336  1.1  mrg   tree mold_type;
   8337  1.1  mrg   tree dest_word_len;
   8338  1.1  mrg   tree size_words;
   8339  1.1  mrg   tree size_bytes;
   8340  1.1  mrg   tree upper;
   8341  1.1  mrg   tree lower;
   8342  1.1  mrg   tree stmt;
   8343  1.1  mrg   tree class_ref = NULL_TREE;
   8344  1.1  mrg   gfc_actual_arglist *arg;
   8345  1.1  mrg   gfc_se argse;
   8346  1.1  mrg   gfc_array_info *info;
   8347  1.1  mrg   stmtblock_t block;
   8348  1.1  mrg   int n;
   8349  1.1  mrg   bool scalar_mold;
   8350  1.1  mrg   gfc_expr *source_expr, *mold_expr, *class_expr;
   8351  1.1  mrg 
   8352  1.1  mrg   info = NULL;
   8353  1.1  mrg   if (se->loop)
   8354  1.1  mrg     info = &se->ss->info->data.array;
   8355  1.1  mrg 
   8356  1.1  mrg   /* Convert SOURCE.  The output from this stage is:-
   8357  1.1  mrg 	source_bytes = length of the source in bytes
   8358  1.1  mrg 	source = pointer to the source data.  */
   8359  1.1  mrg   arg = expr->value.function.actual;
   8360  1.1  mrg   source_expr = arg->expr;
   8361  1.1  mrg 
   8362  1.1  mrg   /* Ensure double transfer through LOGICAL preserves all
   8363  1.1  mrg      the needed bits.  */
   8364  1.1  mrg   if (arg->expr->expr_type == EXPR_FUNCTION
   8365  1.1  mrg 	&& arg->expr->value.function.esym == NULL
   8366  1.1  mrg 	&& arg->expr->value.function.isym != NULL
   8367  1.1  mrg 	&& arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
   8368  1.1  mrg 	&& arg->expr->ts.type == BT_LOGICAL
   8369  1.1  mrg 	&& expr->ts.type != arg->expr->ts.type)
   8370  1.1  mrg     arg->expr->value.function.name = "__transfer_in_transfer";
   8371  1.1  mrg 
   8372  1.1  mrg   gfc_init_se (&argse, NULL);
   8373  1.1  mrg 
   8374  1.1  mrg   source_bytes = gfc_create_var (gfc_array_index_type, NULL);
   8375  1.1  mrg 
   8376  1.1  mrg   /* Obtain the pointer to source and the length of source in bytes.  */
   8377  1.1  mrg   if (arg->expr->rank == 0)
   8378  1.1  mrg     {
   8379  1.1  mrg       gfc_conv_expr_reference (&argse, arg->expr);
   8380  1.1  mrg       if (arg->expr->ts.type == BT_CLASS)
   8381  1.1  mrg 	{
   8382  1.1  mrg 	  tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
   8383  1.1  mrg 	  if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
   8384  1.1  mrg 	    source = gfc_class_data_get (tmp);
   8385  1.1  mrg 	  else
   8386  1.1  mrg 	    {
   8387  1.1  mrg 	      /* Array elements are evaluated as a reference to the data.
   8388  1.1  mrg 		 To obtain the vptr for the element size, the argument
   8389  1.1  mrg 		 expression must be stripped to the class reference and
   8390  1.1  mrg 		 re-evaluated. The pre and post blocks are not needed.  */
   8391  1.1  mrg 	      gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
   8392  1.1  mrg 	      source = argse.expr;
   8393  1.1  mrg 	      class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
   8394  1.1  mrg 	      gfc_init_se (&argse, NULL);
   8395  1.1  mrg 	      gfc_conv_expr (&argse, class_expr);
   8396  1.1  mrg 	      class_ref = argse.expr;
   8397  1.1  mrg 	    }
   8398  1.1  mrg 	}
   8399  1.1  mrg       else
   8400  1.1  mrg 	source = argse.expr;
   8401  1.1  mrg 
   8402  1.1  mrg       /* Obtain the source word length.  */
   8403  1.1  mrg       switch (arg->expr->ts.type)
   8404  1.1  mrg 	{
   8405  1.1  mrg 	case BT_CHARACTER:
   8406  1.1  mrg 	  tmp = size_of_string_in_bytes (arg->expr->ts.kind,
   8407  1.1  mrg 					 argse.string_length);
   8408  1.1  mrg 	  break;
   8409  1.1  mrg 	case BT_CLASS:
   8410  1.1  mrg 	  if (class_ref != NULL_TREE)
   8411  1.1  mrg 	    tmp = gfc_class_vtab_size_get (class_ref);
   8412  1.1  mrg 	  else
   8413  1.1  mrg 	    tmp = gfc_class_vtab_size_get (argse.expr);
   8414  1.1  mrg 	  break;
   8415  1.1  mrg 	default:
   8416  1.1  mrg 	  source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
   8417  1.1  mrg 								source));
   8418  1.1  mrg 	  tmp = fold_convert (gfc_array_index_type,
   8419  1.1  mrg 			      size_in_bytes (source_type));
   8420  1.1  mrg 	  break;
   8421  1.1  mrg 	}
   8422  1.1  mrg     }
   8423  1.1  mrg   else
   8424  1.1  mrg     {
   8425  1.1  mrg       argse.want_pointer = 0;
   8426  1.1  mrg       gfc_conv_expr_descriptor (&argse, arg->expr);
   8427  1.1  mrg       source = gfc_conv_descriptor_data_get (argse.expr);
   8428  1.1  mrg       source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
   8429  1.1  mrg 
   8430  1.1  mrg       /* Repack the source if not simply contiguous.  */
   8431  1.1  mrg       if (!gfc_is_simply_contiguous (arg->expr, false, true))
   8432  1.1  mrg 	{
   8433  1.1  mrg 	  tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
   8434  1.1  mrg 
   8435  1.1  mrg 	  if (warn_array_temporaries)
   8436  1.1  mrg 	    gfc_warning (OPT_Warray_temporaries,
   8437  1.1  mrg 			 "Creating array temporary at %L", &expr->where);
   8438  1.1  mrg 
   8439  1.1  mrg 	  source = build_call_expr_loc (input_location,
   8440  1.1  mrg 				    gfor_fndecl_in_pack, 1, tmp);
   8441  1.1  mrg 	  source = gfc_evaluate_now (source, &argse.pre);
   8442  1.1  mrg 
   8443  1.1  mrg 	  /* Free the temporary.  */
   8444  1.1  mrg 	  gfc_start_block (&block);
   8445  1.1  mrg 	  tmp = gfc_call_free (source);
   8446  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   8447  1.1  mrg 	  stmt = gfc_finish_block (&block);
   8448  1.1  mrg 
   8449  1.1  mrg 	  /* Clean up if it was repacked.  */
   8450  1.1  mrg 	  gfc_init_block (&block);
   8451  1.1  mrg 	  tmp = gfc_conv_array_data (argse.expr);
   8452  1.1  mrg 	  tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   8453  1.1  mrg 				 source, tmp);
   8454  1.1  mrg 	  tmp = build3_v (COND_EXPR, tmp, stmt,
   8455  1.1  mrg 			  build_empty_stmt (input_location));
   8456  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   8457  1.1  mrg 	  gfc_add_block_to_block (&block, &se->post);
   8458  1.1  mrg 	  gfc_init_block (&se->post);
   8459  1.1  mrg 	  gfc_add_block_to_block (&se->post, &block);
   8460  1.1  mrg 	}
   8461  1.1  mrg 
   8462  1.1  mrg       /* Obtain the source word length.  */
   8463  1.1  mrg       if (arg->expr->ts.type == BT_CHARACTER)
   8464  1.1  mrg 	tmp = size_of_string_in_bytes (arg->expr->ts.kind,
   8465  1.1  mrg 				       argse.string_length);
   8466  1.1  mrg       else
   8467  1.1  mrg 	tmp = fold_convert (gfc_array_index_type,
   8468  1.1  mrg 			    size_in_bytes (source_type));
   8469  1.1  mrg 
   8470  1.1  mrg       /* Obtain the size of the array in bytes.  */
   8471  1.1  mrg       extent = gfc_create_var (gfc_array_index_type, NULL);
   8472  1.1  mrg       for (n = 0; n < arg->expr->rank; n++)
   8473  1.1  mrg 	{
   8474  1.1  mrg 	  tree idx;
   8475  1.1  mrg 	  idx = gfc_rank_cst[n];
   8476  1.1  mrg 	  gfc_add_modify (&argse.pre, source_bytes, tmp);
   8477  1.1  mrg 	  lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
   8478  1.1  mrg 	  upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
   8479  1.1  mrg 	  tmp = fold_build2_loc (input_location, MINUS_EXPR,
   8480  1.1  mrg 				 gfc_array_index_type, upper, lower);
   8481  1.1  mrg 	  gfc_add_modify (&argse.pre, extent, tmp);
   8482  1.1  mrg 	  tmp = fold_build2_loc (input_location, PLUS_EXPR,
   8483  1.1  mrg 				 gfc_array_index_type, extent,
   8484  1.1  mrg 				 gfc_index_one_node);
   8485  1.1  mrg 	  tmp = fold_build2_loc (input_location, MULT_EXPR,
   8486  1.1  mrg 				 gfc_array_index_type, tmp, source_bytes);
   8487  1.1  mrg 	}
   8488  1.1  mrg     }
   8489  1.1  mrg 
   8490  1.1  mrg   gfc_add_modify (&argse.pre, source_bytes, tmp);
   8491  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   8492  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   8493  1.1  mrg 
   8494  1.1  mrg   /* Now convert MOLD.  The outputs are:
   8495  1.1  mrg 	mold_type = the TREE type of MOLD
   8496  1.1  mrg 	dest_word_len = destination word length in bytes.  */
   8497  1.1  mrg   arg = arg->next;
   8498  1.1  mrg   mold_expr = arg->expr;
   8499  1.1  mrg 
   8500  1.1  mrg   gfc_init_se (&argse, NULL);
   8501  1.1  mrg 
   8502  1.1  mrg   scalar_mold = arg->expr->rank == 0;
   8503  1.1  mrg 
   8504  1.1  mrg   if (arg->expr->rank == 0)
   8505  1.1  mrg     {
   8506  1.1  mrg       gfc_conv_expr_reference (&argse, arg->expr);
   8507  1.1  mrg       mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
   8508  1.1  mrg 							  argse.expr));
   8509  1.1  mrg     }
   8510  1.1  mrg   else
   8511  1.1  mrg     {
   8512  1.1  mrg       gfc_init_se (&argse, NULL);
   8513  1.1  mrg       argse.want_pointer = 0;
   8514  1.1  mrg       gfc_conv_expr_descriptor (&argse, arg->expr);
   8515  1.1  mrg       mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
   8516  1.1  mrg     }
   8517  1.1  mrg 
   8518  1.1  mrg   gfc_add_block_to_block (&se->pre, &argse.pre);
   8519  1.1  mrg   gfc_add_block_to_block (&se->post, &argse.post);
   8520  1.1  mrg 
   8521  1.1  mrg   if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
   8522  1.1  mrg     {
   8523  1.1  mrg       /* If this TRANSFER is nested in another TRANSFER, use a type
   8524  1.1  mrg 	 that preserves all bits.  */
   8525  1.1  mrg       if (arg->expr->ts.type == BT_LOGICAL)
   8526  1.1  mrg 	mold_type = gfc_get_int_type (arg->expr->ts.kind);
   8527  1.1  mrg     }
   8528  1.1  mrg 
   8529  1.1  mrg   /* Obtain the destination word length.  */
   8530  1.1  mrg   switch (arg->expr->ts.type)
   8531  1.1  mrg     {
   8532  1.1  mrg     case BT_CHARACTER:
   8533  1.1  mrg       tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
   8534  1.1  mrg       mold_type = gfc_get_character_type_len (arg->expr->ts.kind,
   8535  1.1  mrg 					      argse.string_length);
   8536  1.1  mrg       break;
   8537  1.1  mrg     case BT_CLASS:
   8538  1.1  mrg       tmp = gfc_class_vtab_size_get (argse.expr);
   8539  1.1  mrg       break;
   8540  1.1  mrg     default:
   8541  1.1  mrg       tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
   8542  1.1  mrg       break;
   8543  1.1  mrg     }
   8544  1.1  mrg   dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
   8545  1.1  mrg   gfc_add_modify (&se->pre, dest_word_len, tmp);
   8546  1.1  mrg 
   8547  1.1  mrg   /* Finally convert SIZE, if it is present.  */
   8548  1.1  mrg   arg = arg->next;
   8549  1.1  mrg   size_words = gfc_create_var (gfc_array_index_type, NULL);
   8550  1.1  mrg 
   8551  1.1  mrg   if (arg->expr)
   8552  1.1  mrg     {
   8553  1.1  mrg       gfc_init_se (&argse, NULL);
   8554  1.1  mrg       gfc_conv_expr_reference (&argse, arg->expr);
   8555  1.1  mrg       tmp = convert (gfc_array_index_type,
   8556  1.1  mrg 		     build_fold_indirect_ref_loc (input_location,
   8557  1.1  mrg 					      argse.expr));
   8558  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   8559  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   8560  1.1  mrg     }
   8561  1.1  mrg   else
   8562  1.1  mrg     tmp = NULL_TREE;
   8563  1.1  mrg 
   8564  1.1  mrg   /* Separate array and scalar results.  */
   8565  1.1  mrg   if (scalar_mold && tmp == NULL_TREE)
   8566  1.1  mrg     goto scalar_transfer;
   8567  1.1  mrg 
   8568  1.1  mrg   size_bytes = gfc_create_var (gfc_array_index_type, NULL);
   8569  1.1  mrg   if (tmp != NULL_TREE)
   8570  1.1  mrg     tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
   8571  1.1  mrg 			   tmp, dest_word_len);
   8572  1.1  mrg   else
   8573  1.1  mrg     tmp = source_bytes;
   8574  1.1  mrg 
   8575  1.1  mrg   gfc_add_modify (&se->pre, size_bytes, tmp);
   8576  1.1  mrg   gfc_add_modify (&se->pre, size_words,
   8577  1.1  mrg 		       fold_build2_loc (input_location, CEIL_DIV_EXPR,
   8578  1.1  mrg 					gfc_array_index_type,
   8579  1.1  mrg 					size_bytes, dest_word_len));
   8580  1.1  mrg 
   8581  1.1  mrg   /* Evaluate the bounds of the result.  If the loop range exists, we have
   8582  1.1  mrg      to check if it is too large.  If so, we modify loop->to be consistent
   8583  1.1  mrg      with min(size, size(source)).  Otherwise, size is made consistent with
   8584  1.1  mrg      the loop range, so that the right number of bytes is transferred.*/
   8585  1.1  mrg   n = se->loop->order[0];
   8586  1.1  mrg   if (se->loop->to[n] != NULL_TREE)
   8587  1.1  mrg     {
   8588  1.1  mrg       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   8589  1.1  mrg 			     se->loop->to[n], se->loop->from[n]);
   8590  1.1  mrg       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
   8591  1.1  mrg 			     tmp, gfc_index_one_node);
   8592  1.1  mrg       tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
   8593  1.1  mrg 			 tmp, size_words);
   8594  1.1  mrg       gfc_add_modify (&se->pre, size_words, tmp);
   8595  1.1  mrg       gfc_add_modify (&se->pre, size_bytes,
   8596  1.1  mrg 			   fold_build2_loc (input_location, MULT_EXPR,
   8597  1.1  mrg 					    gfc_array_index_type,
   8598  1.1  mrg 					    size_words, dest_word_len));
   8599  1.1  mrg       upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
   8600  1.1  mrg 			       size_words, se->loop->from[n]);
   8601  1.1  mrg       upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   8602  1.1  mrg 			       upper, gfc_index_one_node);
   8603  1.1  mrg     }
   8604  1.1  mrg   else
   8605  1.1  mrg     {
   8606  1.1  mrg       upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   8607  1.1  mrg 			       size_words, gfc_index_one_node);
   8608  1.1  mrg       se->loop->from[n] = gfc_index_zero_node;
   8609  1.1  mrg     }
   8610  1.1  mrg 
   8611  1.1  mrg   se->loop->to[n] = upper;
   8612  1.1  mrg 
   8613  1.1  mrg   /* Build a destination descriptor, using the pointer, source, as the
   8614  1.1  mrg      data field.  */
   8615  1.1  mrg   gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
   8616  1.1  mrg 			       NULL_TREE, false, true, false, &expr->where);
   8617  1.1  mrg 
   8618  1.1  mrg   /* Cast the pointer to the result.  */
   8619  1.1  mrg   tmp = gfc_conv_descriptor_data_get (info->descriptor);
   8620  1.1  mrg   tmp = fold_convert (pvoid_type_node, tmp);
   8621  1.1  mrg 
   8622  1.1  mrg   /* Use memcpy to do the transfer.  */
   8623  1.1  mrg   tmp
   8624  1.1  mrg     = build_call_expr_loc (input_location,
   8625  1.1  mrg 			   builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
   8626  1.1  mrg 			   fold_convert (pvoid_type_node, source),
   8627  1.1  mrg 			   fold_convert (size_type_node,
   8628  1.1  mrg 					 fold_build2_loc (input_location,
   8629  1.1  mrg 							  MIN_EXPR,
   8630  1.1  mrg 							  gfc_array_index_type,
   8631  1.1  mrg 							  size_bytes,
   8632  1.1  mrg 							  source_bytes)));
   8633  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   8634  1.1  mrg 
   8635  1.1  mrg   se->expr = info->descriptor;
   8636  1.1  mrg   if (expr->ts.type == BT_CHARACTER)
   8637  1.1  mrg     {
   8638  1.1  mrg       tmp = fold_convert (gfc_charlen_type_node,
   8639  1.1  mrg 			  TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
   8640  1.1  mrg       se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
   8641  1.1  mrg 					   gfc_charlen_type_node,
   8642  1.1  mrg 					   dest_word_len, tmp);
   8643  1.1  mrg     }
   8644  1.1  mrg 
   8645  1.1  mrg   return;
   8646  1.1  mrg 
   8647  1.1  mrg /* Deal with scalar results.  */
   8648  1.1  mrg scalar_transfer:
   8649  1.1  mrg   extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
   8650  1.1  mrg 			    dest_word_len, source_bytes);
   8651  1.1  mrg   extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
   8652  1.1  mrg 			    extent, gfc_index_zero_node);
   8653  1.1  mrg 
   8654  1.1  mrg   if (expr->ts.type == BT_CHARACTER)
   8655  1.1  mrg     {
   8656  1.1  mrg       tree direct, indirect, free;
   8657  1.1  mrg 
   8658  1.1  mrg       ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
   8659  1.1  mrg       tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
   8660  1.1  mrg 				"transfer");
   8661  1.1  mrg 
   8662  1.1  mrg       /* If source is longer than the destination, use a pointer to
   8663  1.1  mrg 	 the source directly.  */
   8664  1.1  mrg       gfc_init_block (&block);
   8665  1.1  mrg       gfc_add_modify (&block, tmpdecl, ptr);
   8666  1.1  mrg       direct = gfc_finish_block (&block);
   8667  1.1  mrg 
   8668  1.1  mrg       /* Otherwise, allocate a string with the length of the destination
   8669  1.1  mrg 	 and copy the source into it.  */
   8670  1.1  mrg       gfc_init_block (&block);
   8671  1.1  mrg       tmp = gfc_get_pchar_type (expr->ts.kind);
   8672  1.1  mrg       tmp = gfc_call_malloc (&block, tmp, dest_word_len);
   8673  1.1  mrg       gfc_add_modify (&block, tmpdecl,
   8674  1.1  mrg 		      fold_convert (TREE_TYPE (ptr), tmp));
   8675  1.1  mrg       tmp = build_call_expr_loc (input_location,
   8676  1.1  mrg 			     builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
   8677  1.1  mrg 			     fold_convert (pvoid_type_node, tmpdecl),
   8678  1.1  mrg 			     fold_convert (pvoid_type_node, ptr),
   8679  1.1  mrg 			     fold_convert (size_type_node, extent));
   8680  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   8681  1.1  mrg       indirect = gfc_finish_block (&block);
   8682  1.1  mrg 
   8683  1.1  mrg       /* Wrap it up with the condition.  */
   8684  1.1  mrg       tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
   8685  1.1  mrg 			     dest_word_len, source_bytes);
   8686  1.1  mrg       tmp = build3_v (COND_EXPR, tmp, direct, indirect);
   8687  1.1  mrg       gfc_add_expr_to_block (&se->pre, tmp);
   8688  1.1  mrg 
   8689  1.1  mrg       /* Free the temporary string, if necessary.  */
   8690  1.1  mrg       free = gfc_call_free (tmpdecl);
   8691  1.1  mrg       tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   8692  1.1  mrg 			     dest_word_len, source_bytes);
   8693  1.1  mrg       tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
   8694  1.1  mrg       gfc_add_expr_to_block (&se->post, tmp);
   8695  1.1  mrg 
   8696  1.1  mrg       se->expr = tmpdecl;
   8697  1.1  mrg       tmp = fold_convert (gfc_charlen_type_node,
   8698  1.1  mrg 			  TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
   8699  1.1  mrg       se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
   8700  1.1  mrg 					   gfc_charlen_type_node,
   8701  1.1  mrg 					   dest_word_len, tmp);
   8702  1.1  mrg     }
   8703  1.1  mrg   else
   8704  1.1  mrg     {
   8705  1.1  mrg       tmpdecl = gfc_create_var (mold_type, "transfer");
   8706  1.1  mrg 
   8707  1.1  mrg       ptr = convert (build_pointer_type (mold_type), source);
   8708  1.1  mrg 
   8709  1.1  mrg       /* For CLASS results, allocate the needed memory first.  */
   8710  1.1  mrg       if (mold_expr->ts.type == BT_CLASS)
   8711  1.1  mrg 	{
   8712  1.1  mrg 	  tree cdata;
   8713  1.1  mrg 	  cdata = gfc_class_data_get (tmpdecl);
   8714  1.1  mrg 	  tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
   8715  1.1  mrg 	  gfc_add_modify (&se->pre, cdata, tmp);
   8716  1.1  mrg 	}
   8717  1.1  mrg 
   8718  1.1  mrg       /* Use memcpy to do the transfer.  */
   8719  1.1  mrg       if (mold_expr->ts.type == BT_CLASS)
   8720  1.1  mrg 	tmp = gfc_class_data_get (tmpdecl);
   8721  1.1  mrg       else
   8722  1.1  mrg 	tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
   8723  1.1  mrg 
   8724  1.1  mrg       tmp = build_call_expr_loc (input_location,
   8725  1.1  mrg 			     builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
   8726  1.1  mrg 			     fold_convert (pvoid_type_node, tmp),
   8727  1.1  mrg 			     fold_convert (pvoid_type_node, ptr),
   8728  1.1  mrg 			     fold_convert (size_type_node, extent));
   8729  1.1  mrg       gfc_add_expr_to_block (&se->pre, tmp);
   8730  1.1  mrg 
   8731  1.1  mrg       /* For CLASS results, set the _vptr.  */
   8732  1.1  mrg       if (mold_expr->ts.type == BT_CLASS)
   8733  1.1  mrg 	{
   8734  1.1  mrg 	  tree vptr;
   8735  1.1  mrg 	  gfc_symbol *vtab;
   8736  1.1  mrg 	  vptr = gfc_class_vptr_get (tmpdecl);
   8737  1.1  mrg 	  vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
   8738  1.1  mrg 	  gcc_assert (vtab);
   8739  1.1  mrg 	  tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
   8740  1.1  mrg 	  gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
   8741  1.1  mrg 	}
   8742  1.1  mrg 
   8743  1.1  mrg       se->expr = tmpdecl;
   8744  1.1  mrg     }
   8745  1.1  mrg }
   8746  1.1  mrg 
   8747  1.1  mrg 
   8748  1.1  mrg /* Generate a call to caf_is_present.  */
   8749  1.1  mrg 
   8750  1.1  mrg static tree
   8751  1.1  mrg trans_caf_is_present (gfc_se *se, gfc_expr *expr)
   8752  1.1  mrg {
   8753  1.1  mrg   tree caf_reference, caf_decl, token, image_index;
   8754  1.1  mrg 
   8755  1.1  mrg   /* Compile the reference chain.  */
   8756  1.1  mrg   caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
   8757  1.1  mrg   gcc_assert (caf_reference != NULL_TREE);
   8758  1.1  mrg 
   8759  1.1  mrg   caf_decl = gfc_get_tree_for_caf_expr (expr);
   8760  1.1  mrg   if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   8761  1.1  mrg     caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   8762  1.1  mrg   image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
   8763  1.1  mrg   gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
   8764  1.1  mrg 			    expr);
   8765  1.1  mrg 
   8766  1.1  mrg   return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
   8767  1.1  mrg 			      3, token, image_index, caf_reference);
   8768  1.1  mrg }
   8769  1.1  mrg 
   8770  1.1  mrg 
   8771  1.1  mrg /* Test whether this ref-chain refs this image only.  */
   8772  1.1  mrg 
   8773  1.1  mrg static bool
   8774  1.1  mrg caf_this_image_ref (gfc_ref *ref)
   8775  1.1  mrg {
   8776  1.1  mrg   for ( ; ref; ref = ref->next)
   8777  1.1  mrg     if (ref->type == REF_ARRAY && ref->u.ar.codimen)
   8778  1.1  mrg       return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
   8779  1.1  mrg 
   8780  1.1  mrg   return false;
   8781  1.1  mrg }
   8782  1.1  mrg 
   8783  1.1  mrg 
   8784  1.1  mrg /* Generate code for the ALLOCATED intrinsic.
   8785  1.1  mrg    Generate inline code that directly check the address of the argument.  */
   8786  1.1  mrg 
   8787  1.1  mrg static void
   8788  1.1  mrg gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
   8789  1.1  mrg {
   8790  1.1  mrg   gfc_se arg1se;
   8791  1.1  mrg   tree tmp;
   8792  1.1  mrg   bool coindexed_caf_comp = false;
   8793  1.1  mrg   gfc_expr *e = expr->value.function.actual->expr;
   8794  1.1  mrg 
   8795  1.1  mrg   gfc_init_se (&arg1se, NULL);
   8796  1.1  mrg   if (e->ts.type == BT_CLASS)
   8797  1.1  mrg     {
   8798  1.1  mrg       /* Make sure that class array expressions have both a _data
   8799  1.1  mrg 	 component reference and an array reference....  */
   8800  1.1  mrg       if (CLASS_DATA (e)->attr.dimension)
   8801  1.1  mrg 	gfc_add_class_array_ref (e);
   8802  1.1  mrg       /* .... whilst scalars only need the _data component.  */
   8803  1.1  mrg       else
   8804  1.1  mrg 	gfc_add_data_component (e);
   8805  1.1  mrg     }
   8806  1.1  mrg 
   8807  1.1  mrg   /* When 'e' references an allocatable component in a coarray, then call
   8808  1.1  mrg      the caf-library function caf_is_present ().  */
   8809  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
   8810  1.1  mrg       && e->value.function.isym
   8811  1.1  mrg       && e->value.function.isym->id == GFC_ISYM_CAF_GET)
   8812  1.1  mrg     {
   8813  1.1  mrg       e = e->value.function.actual->expr;
   8814  1.1  mrg       if (gfc_expr_attr (e).codimension)
   8815  1.1  mrg 	{
   8816  1.1  mrg 	  /* Last partref is the coindexed coarray. As coarrays are collectively
   8817  1.1  mrg 	     (de)allocated, the allocation status must be the same as the one of
   8818  1.1  mrg 	     the local allocation.  Convert to local access. */
   8819  1.1  mrg 	  for (gfc_ref *ref = e->ref; ref; ref = ref->next)
   8820  1.1  mrg 	    if (ref->type == REF_ARRAY && ref->u.ar.codimen)
   8821  1.1  mrg 	      {
   8822  1.1  mrg 		for (int i = ref->u.ar.dimen;
   8823  1.1  mrg 		     i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
   8824  1.1  mrg 		ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
   8825  1.1  mrg 		break;
   8826  1.1  mrg 	      }
   8827  1.1  mrg 	}
   8828  1.1  mrg       else if (!caf_this_image_ref (e->ref))
   8829  1.1  mrg 	coindexed_caf_comp = true;
   8830  1.1  mrg     }
   8831  1.1  mrg   if (coindexed_caf_comp)
   8832  1.1  mrg     tmp = trans_caf_is_present (se, e);
   8833  1.1  mrg   else
   8834  1.1  mrg     {
   8835  1.1  mrg       if (e->rank == 0)
   8836  1.1  mrg 	{
   8837  1.1  mrg 	  /* Allocatable scalar.  */
   8838  1.1  mrg 	  arg1se.want_pointer = 1;
   8839  1.1  mrg 	  gfc_conv_expr (&arg1se, e);
   8840  1.1  mrg 	  tmp = arg1se.expr;
   8841  1.1  mrg 	}
   8842  1.1  mrg       else
   8843  1.1  mrg 	{
   8844  1.1  mrg 	  /* Allocatable array.  */
   8845  1.1  mrg 	  arg1se.descriptor_only = 1;
   8846  1.1  mrg 	  gfc_conv_expr_descriptor (&arg1se, e);
   8847  1.1  mrg 	  tmp = gfc_conv_descriptor_data_get (arg1se.expr);
   8848  1.1  mrg 	}
   8849  1.1  mrg 
   8850  1.1  mrg       tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
   8851  1.1  mrg 			     fold_convert (TREE_TYPE (tmp), null_pointer_node));
   8852  1.1  mrg     }
   8853  1.1  mrg 
   8854  1.1  mrg   /* Components of pointer array references sometimes come back with a pre block.  */
   8855  1.1  mrg   if (arg1se.pre.head)
   8856  1.1  mrg     gfc_add_block_to_block (&se->pre, &arg1se.pre);
   8857  1.1  mrg 
   8858  1.1  mrg   se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
   8859  1.1  mrg }
   8860  1.1  mrg 
   8861  1.1  mrg 
   8862  1.1  mrg /* Generate code for the ASSOCIATED intrinsic.
   8863  1.1  mrg    If both POINTER and TARGET are arrays, generate a call to library function
   8864  1.1  mrg    _gfor_associated, and pass descriptors of POINTER and TARGET to it.
   8865  1.1  mrg    In other cases, generate inline code that directly compare the address of
   8866  1.1  mrg    POINTER with the address of TARGET.  */
   8867  1.1  mrg 
   8868  1.1  mrg static void
   8869  1.1  mrg gfc_conv_associated (gfc_se *se, gfc_expr *expr)
   8870  1.1  mrg {
   8871  1.1  mrg   gfc_actual_arglist *arg1;
   8872  1.1  mrg   gfc_actual_arglist *arg2;
   8873  1.1  mrg   gfc_se arg1se;
   8874  1.1  mrg   gfc_se arg2se;
   8875  1.1  mrg   tree tmp2;
   8876  1.1  mrg   tree tmp;
   8877  1.1  mrg   tree nonzero_arraylen = NULL_TREE;
   8878  1.1  mrg   gfc_ss *ss;
   8879  1.1  mrg   bool scalar;
   8880  1.1  mrg 
   8881  1.1  mrg   gfc_init_se (&arg1se, NULL);
   8882  1.1  mrg   gfc_init_se (&arg2se, NULL);
   8883  1.1  mrg   arg1 = expr->value.function.actual;
   8884  1.1  mrg   arg2 = arg1->next;
   8885  1.1  mrg 
   8886  1.1  mrg   /* Check whether the expression is a scalar or not; we cannot use
   8887  1.1  mrg      arg1->expr->rank as it can be nonzero for proc pointers.  */
   8888  1.1  mrg   ss = gfc_walk_expr (arg1->expr);
   8889  1.1  mrg   scalar = ss == gfc_ss_terminator;
   8890  1.1  mrg   if (!scalar)
   8891  1.1  mrg     gfc_free_ss_chain (ss);
   8892  1.1  mrg 
   8893  1.1  mrg   if (!arg2->expr)
   8894  1.1  mrg     {
   8895  1.1  mrg       /* No optional target.  */
   8896  1.1  mrg       if (scalar)
   8897  1.1  mrg         {
   8898  1.1  mrg 	  /* A pointer to a scalar.  */
   8899  1.1  mrg 	  arg1se.want_pointer = 1;
   8900  1.1  mrg 	  gfc_conv_expr (&arg1se, arg1->expr);
   8901  1.1  mrg 	  if (arg1->expr->symtree->n.sym->attr.proc_pointer
   8902  1.1  mrg 	      && arg1->expr->symtree->n.sym->attr.dummy)
   8903  1.1  mrg 	    arg1se.expr = build_fold_indirect_ref_loc (input_location,
   8904  1.1  mrg 						       arg1se.expr);
   8905  1.1  mrg   	  if (arg1->expr->ts.type == BT_CLASS)
   8906  1.1  mrg 	    {
   8907  1.1  mrg 	      tmp2 = gfc_class_data_get (arg1se.expr);
   8908  1.1  mrg 	      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
   8909  1.1  mrg 		tmp2 = gfc_conv_descriptor_data_get (tmp2);
   8910  1.1  mrg 	    }
   8911  1.1  mrg 	  else
   8912  1.1  mrg 	    tmp2 = arg1se.expr;
   8913  1.1  mrg         }
   8914  1.1  mrg       else
   8915  1.1  mrg         {
   8916  1.1  mrg           /* A pointer to an array.  */
   8917  1.1  mrg           gfc_conv_expr_descriptor (&arg1se, arg1->expr);
   8918  1.1  mrg           tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
   8919  1.1  mrg         }
   8920  1.1  mrg       gfc_add_block_to_block (&se->pre, &arg1se.pre);
   8921  1.1  mrg       gfc_add_block_to_block (&se->post, &arg1se.post);
   8922  1.1  mrg       tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
   8923  1.1  mrg 			     fold_convert (TREE_TYPE (tmp2), null_pointer_node));
   8924  1.1  mrg       se->expr = tmp;
   8925  1.1  mrg     }
   8926  1.1  mrg   else
   8927  1.1  mrg     {
   8928  1.1  mrg       /* An optional target.  */
   8929  1.1  mrg       if (arg2->expr->ts.type == BT_CLASS
   8930  1.1  mrg 	  && arg2->expr->expr_type != EXPR_FUNCTION)
   8931  1.1  mrg 	gfc_add_data_component (arg2->expr);
   8932  1.1  mrg 
   8933  1.1  mrg       if (scalar)
   8934  1.1  mrg         {
   8935  1.1  mrg 	  /* A pointer to a scalar.  */
   8936  1.1  mrg 	  arg1se.want_pointer = 1;
   8937  1.1  mrg 	  gfc_conv_expr (&arg1se, arg1->expr);
   8938  1.1  mrg 	  if (arg1->expr->symtree->n.sym->attr.proc_pointer
   8939  1.1  mrg 	      && arg1->expr->symtree->n.sym->attr.dummy)
   8940  1.1  mrg 	    arg1se.expr = build_fold_indirect_ref_loc (input_location,
   8941  1.1  mrg 						       arg1se.expr);
   8942  1.1  mrg 	  if (arg1->expr->ts.type == BT_CLASS)
   8943  1.1  mrg 	    arg1se.expr = gfc_class_data_get (arg1se.expr);
   8944  1.1  mrg 
   8945  1.1  mrg 	  arg2se.want_pointer = 1;
   8946  1.1  mrg 	  gfc_conv_expr (&arg2se, arg2->expr);
   8947  1.1  mrg 	  if (arg2->expr->symtree->n.sym->attr.proc_pointer
   8948  1.1  mrg 	      && arg2->expr->symtree->n.sym->attr.dummy)
   8949  1.1  mrg 	    arg2se.expr = build_fold_indirect_ref_loc (input_location,
   8950  1.1  mrg 						       arg2se.expr);
   8951  1.1  mrg 	  if (arg2->expr->ts.type == BT_CLASS)
   8952  1.1  mrg 	    {
   8953  1.1  mrg 	      arg2se.expr = gfc_evaluate_now (arg2se.expr, &arg2se.pre);
   8954  1.1  mrg 	      arg2se.expr = gfc_class_data_get (arg2se.expr);
   8955  1.1  mrg 	    }
   8956  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &arg1se.pre);
   8957  1.1  mrg 	  gfc_add_block_to_block (&se->post, &arg1se.post);
   8958  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &arg2se.pre);
   8959  1.1  mrg 	  gfc_add_block_to_block (&se->post, &arg2se.post);
   8960  1.1  mrg           tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   8961  1.1  mrg 				 arg1se.expr, arg2se.expr);
   8962  1.1  mrg           tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   8963  1.1  mrg 				  arg1se.expr, null_pointer_node);
   8964  1.1  mrg           se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   8965  1.1  mrg 				      logical_type_node, tmp, tmp2);
   8966  1.1  mrg         }
   8967  1.1  mrg       else
   8968  1.1  mrg         {
   8969  1.1  mrg 	  /* An array pointer of zero length is not associated if target is
   8970  1.1  mrg 	     present.  */
   8971  1.1  mrg 	  arg1se.descriptor_only = 1;
   8972  1.1  mrg 	  gfc_conv_expr_lhs (&arg1se, arg1->expr);
   8973  1.1  mrg 	  if (arg1->expr->rank == -1)
   8974  1.1  mrg 	    {
   8975  1.1  mrg 	      tmp = gfc_conv_descriptor_rank (arg1se.expr);
   8976  1.1  mrg 	      tmp = fold_build2_loc (input_location, MINUS_EXPR,
   8977  1.1  mrg 				     TREE_TYPE (tmp), tmp,
   8978  1.1  mrg 				     build_int_cst (TREE_TYPE (tmp), 1));
   8979  1.1  mrg 	    }
   8980  1.1  mrg 	  else
   8981  1.1  mrg 	    tmp = gfc_rank_cst[arg1->expr->rank - 1];
   8982  1.1  mrg 	  tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
   8983  1.1  mrg 	  if (arg2->expr->rank != 0)
   8984  1.1  mrg 	    nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
   8985  1.1  mrg 						logical_type_node, tmp,
   8986  1.1  mrg 						build_int_cst (TREE_TYPE (tmp), 0));
   8987  1.1  mrg 
   8988  1.1  mrg 	  /* A pointer to an array, call library function _gfor_associated.  */
   8989  1.1  mrg 	  arg1se.want_pointer = 1;
   8990  1.1  mrg 	  gfc_conv_expr_descriptor (&arg1se, arg1->expr);
   8991  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &arg1se.pre);
   8992  1.1  mrg 	  gfc_add_block_to_block (&se->post, &arg1se.post);
   8993  1.1  mrg 
   8994  1.1  mrg 	  arg2se.want_pointer = 1;
   8995  1.1  mrg 	  arg2se.force_no_tmp = 1;
   8996  1.1  mrg 	  if (arg2->expr->rank != 0)
   8997  1.1  mrg 	    gfc_conv_expr_descriptor (&arg2se, arg2->expr);
   8998  1.1  mrg 	  else
   8999  1.1  mrg 	    {
   9000  1.1  mrg 	      gfc_conv_expr (&arg2se, arg2->expr);
   9001  1.1  mrg 	      arg2se.expr
   9002  1.1  mrg 		= gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
   9003  1.1  mrg 						 gfc_expr_attr (arg2->expr));
   9004  1.1  mrg 	      arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
   9005  1.1  mrg 	    }
   9006  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &arg2se.pre);
   9007  1.1  mrg 	  gfc_add_block_to_block (&se->post, &arg2se.post);
   9008  1.1  mrg 	  se->expr = build_call_expr_loc (input_location,
   9009  1.1  mrg 				      gfor_fndecl_associated, 2,
   9010  1.1  mrg 				      arg1se.expr, arg2se.expr);
   9011  1.1  mrg 	  se->expr = convert (logical_type_node, se->expr);
   9012  1.1  mrg 	  if (arg2->expr->rank != 0)
   9013  1.1  mrg 	    se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   9014  1.1  mrg 					logical_type_node, se->expr,
   9015  1.1  mrg 					nonzero_arraylen);
   9016  1.1  mrg         }
   9017  1.1  mrg 
   9018  1.1  mrg       /* If target is present zero character length pointers cannot
   9019  1.1  mrg 	 be associated.  */
   9020  1.1  mrg       if (arg1->expr->ts.type == BT_CHARACTER)
   9021  1.1  mrg 	{
   9022  1.1  mrg 	  tmp = arg1se.string_length;
   9023  1.1  mrg 	  tmp = fold_build2_loc (input_location, NE_EXPR,
   9024  1.1  mrg 				 logical_type_node, tmp,
   9025  1.1  mrg 				 build_zero_cst (TREE_TYPE (tmp)));
   9026  1.1  mrg 	  se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   9027  1.1  mrg 				      logical_type_node, se->expr, tmp);
   9028  1.1  mrg 	}
   9029  1.1  mrg     }
   9030  1.1  mrg 
   9031  1.1  mrg   se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   9032  1.1  mrg }
   9033  1.1  mrg 
   9034  1.1  mrg 
   9035  1.1  mrg /* Generate code for the SAME_TYPE_AS intrinsic.
   9036  1.1  mrg    Generate inline code that directly checks the vindices.  */
   9037  1.1  mrg 
   9038  1.1  mrg static void
   9039  1.1  mrg gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
   9040  1.1  mrg {
   9041  1.1  mrg   gfc_expr *a, *b;
   9042  1.1  mrg   gfc_se se1, se2;
   9043  1.1  mrg   tree tmp;
   9044  1.1  mrg   tree conda = NULL_TREE, condb = NULL_TREE;
   9045  1.1  mrg 
   9046  1.1  mrg   gfc_init_se (&se1, NULL);
   9047  1.1  mrg   gfc_init_se (&se2, NULL);
   9048  1.1  mrg 
   9049  1.1  mrg   a = expr->value.function.actual->expr;
   9050  1.1  mrg   b = expr->value.function.actual->next->expr;
   9051  1.1  mrg 
   9052  1.1  mrg   bool unlimited_poly_a = UNLIMITED_POLY (a);
   9053  1.1  mrg   bool unlimited_poly_b = UNLIMITED_POLY (b);
   9054  1.1  mrg   if (unlimited_poly_a)
   9055  1.1  mrg     {
   9056  1.1  mrg       se1.want_pointer = 1;
   9057  1.1  mrg       gfc_add_vptr_component (a);
   9058  1.1  mrg     }
   9059  1.1  mrg   else if (a->ts.type == BT_CLASS)
   9060  1.1  mrg     {
   9061  1.1  mrg       gfc_add_vptr_component (a);
   9062  1.1  mrg       gfc_add_hash_component (a);
   9063  1.1  mrg     }
   9064  1.1  mrg   else if (a->ts.type == BT_DERIVED)
   9065  1.1  mrg     a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
   9066  1.1  mrg 			  a->ts.u.derived->hash_value);
   9067  1.1  mrg 
   9068  1.1  mrg   if (unlimited_poly_b)
   9069  1.1  mrg     {
   9070  1.1  mrg       se2.want_pointer = 1;
   9071  1.1  mrg       gfc_add_vptr_component (b);
   9072  1.1  mrg     }
   9073  1.1  mrg   else if (b->ts.type == BT_CLASS)
   9074  1.1  mrg     {
   9075  1.1  mrg       gfc_add_vptr_component (b);
   9076  1.1  mrg       gfc_add_hash_component (b);
   9077  1.1  mrg     }
   9078  1.1  mrg   else if (b->ts.type == BT_DERIVED)
   9079  1.1  mrg     b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
   9080  1.1  mrg 			  b->ts.u.derived->hash_value);
   9081  1.1  mrg 
   9082  1.1  mrg   gfc_conv_expr (&se1, a);
   9083  1.1  mrg   gfc_conv_expr (&se2, b);
   9084  1.1  mrg 
   9085  1.1  mrg   if (unlimited_poly_a)
   9086  1.1  mrg     {
   9087  1.1  mrg       conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   9088  1.1  mrg 			       se1.expr,
   9089  1.1  mrg 			       build_int_cst (TREE_TYPE (se1.expr), 0));
   9090  1.1  mrg       se1.expr = gfc_vptr_hash_get (se1.expr);
   9091  1.1  mrg     }
   9092  1.1  mrg 
   9093  1.1  mrg   if (unlimited_poly_b)
   9094  1.1  mrg     {
   9095  1.1  mrg       condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   9096  1.1  mrg 			       se2.expr,
   9097  1.1  mrg 			       build_int_cst (TREE_TYPE (se2.expr), 0));
   9098  1.1  mrg       se2.expr = gfc_vptr_hash_get (se2.expr);
   9099  1.1  mrg     }
   9100  1.1  mrg 
   9101  1.1  mrg   tmp = fold_build2_loc (input_location, EQ_EXPR,
   9102  1.1  mrg 			 logical_type_node, se1.expr,
   9103  1.1  mrg 			 fold_convert (TREE_TYPE (se1.expr), se2.expr));
   9104  1.1  mrg 
   9105  1.1  mrg   if (conda)
   9106  1.1  mrg     tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   9107  1.1  mrg 			   logical_type_node, conda, tmp);
   9108  1.1  mrg 
   9109  1.1  mrg   if (condb)
   9110  1.1  mrg     tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
   9111  1.1  mrg 			   logical_type_node, condb, tmp);
   9112  1.1  mrg 
   9113  1.1  mrg   se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
   9114  1.1  mrg }
   9115  1.1  mrg 
   9116  1.1  mrg 
   9117  1.1  mrg /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function.  */
   9118  1.1  mrg 
   9119  1.1  mrg static void
   9120  1.1  mrg gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
   9121  1.1  mrg {
   9122  1.1  mrg   tree args[2];
   9123  1.1  mrg 
   9124  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 2);
   9125  1.1  mrg   se->expr = build_call_expr_loc (input_location,
   9126  1.1  mrg 			      gfor_fndecl_sc_kind, 2, args[0], args[1]);
   9127  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   9128  1.1  mrg }
   9129  1.1  mrg 
   9130  1.1  mrg 
   9131  1.1  mrg /* Generate code for SELECTED_INT_KIND (R) intrinsic function.  */
   9132  1.1  mrg 
   9133  1.1  mrg static void
   9134  1.1  mrg gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
   9135  1.1  mrg {
   9136  1.1  mrg   tree arg, type;
   9137  1.1  mrg 
   9138  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   9139  1.1  mrg 
   9140  1.1  mrg   /* The argument to SELECTED_INT_KIND is INTEGER(4).  */
   9141  1.1  mrg   type = gfc_get_int_type (4);
   9142  1.1  mrg   arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
   9143  1.1  mrg 
   9144  1.1  mrg   /* Convert it to the required type.  */
   9145  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   9146  1.1  mrg   se->expr = build_call_expr_loc (input_location,
   9147  1.1  mrg 			      gfor_fndecl_si_kind, 1, arg);
   9148  1.1  mrg   se->expr = fold_convert (type, se->expr);
   9149  1.1  mrg }
   9150  1.1  mrg 
   9151  1.1  mrg 
   9152  1.1  mrg /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function.  */
   9153  1.1  mrg 
   9154  1.1  mrg static void
   9155  1.1  mrg gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
   9156  1.1  mrg {
   9157  1.1  mrg   gfc_actual_arglist *actual;
   9158  1.1  mrg   tree type;
   9159  1.1  mrg   gfc_se argse;
   9160  1.1  mrg   vec<tree, va_gc> *args = NULL;
   9161  1.1  mrg 
   9162  1.1  mrg   for (actual = expr->value.function.actual; actual; actual = actual->next)
   9163  1.1  mrg     {
   9164  1.1  mrg       gfc_init_se (&argse, se);
   9165  1.1  mrg 
   9166  1.1  mrg       /* Pass a NULL pointer for an absent arg.  */
   9167  1.1  mrg       if (actual->expr == NULL)
   9168  1.1  mrg         argse.expr = null_pointer_node;
   9169  1.1  mrg       else
   9170  1.1  mrg 	{
   9171  1.1  mrg 	  gfc_typespec ts;
   9172  1.1  mrg           gfc_clear_ts (&ts);
   9173  1.1  mrg 
   9174  1.1  mrg 	  if (actual->expr->ts.kind != gfc_c_int_kind)
   9175  1.1  mrg 	    {
   9176  1.1  mrg   	      /* The arguments to SELECTED_REAL_KIND are INTEGER(4).  */
   9177  1.1  mrg 	      ts.type = BT_INTEGER;
   9178  1.1  mrg 	      ts.kind = gfc_c_int_kind;
   9179  1.1  mrg 	      gfc_convert_type (actual->expr, &ts, 2);
   9180  1.1  mrg 	    }
   9181  1.1  mrg 	  gfc_conv_expr_reference (&argse, actual->expr);
   9182  1.1  mrg 	}
   9183  1.1  mrg 
   9184  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   9185  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   9186  1.1  mrg       vec_safe_push (args, argse.expr);
   9187  1.1  mrg     }
   9188  1.1  mrg 
   9189  1.1  mrg   /* Convert it to the required type.  */
   9190  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   9191  1.1  mrg   se->expr = build_call_expr_loc_vec (input_location,
   9192  1.1  mrg 				      gfor_fndecl_sr_kind, args);
   9193  1.1  mrg   se->expr = fold_convert (type, se->expr);
   9194  1.1  mrg }
   9195  1.1  mrg 
   9196  1.1  mrg 
   9197  1.1  mrg /* Generate code for TRIM (A) intrinsic function.  */
   9198  1.1  mrg 
   9199  1.1  mrg static void
   9200  1.1  mrg gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
   9201  1.1  mrg {
   9202  1.1  mrg   tree var;
   9203  1.1  mrg   tree len;
   9204  1.1  mrg   tree addr;
   9205  1.1  mrg   tree tmp;
   9206  1.1  mrg   tree cond;
   9207  1.1  mrg   tree fndecl;
   9208  1.1  mrg   tree function;
   9209  1.1  mrg   tree *args;
   9210  1.1  mrg   unsigned int num_args;
   9211  1.1  mrg 
   9212  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr) + 2;
   9213  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   9214  1.1  mrg 
   9215  1.1  mrg   var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
   9216  1.1  mrg   addr = gfc_build_addr_expr (ppvoid_type_node, var);
   9217  1.1  mrg   len = gfc_create_var (gfc_charlen_type_node, "len");
   9218  1.1  mrg 
   9219  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
   9220  1.1  mrg   args[0] = gfc_build_addr_expr (NULL_TREE, len);
   9221  1.1  mrg   args[1] = addr;
   9222  1.1  mrg 
   9223  1.1  mrg   if (expr->ts.kind == 1)
   9224  1.1  mrg     function = gfor_fndecl_string_trim;
   9225  1.1  mrg   else if (expr->ts.kind == 4)
   9226  1.1  mrg     function = gfor_fndecl_string_trim_char4;
   9227  1.1  mrg   else
   9228  1.1  mrg     gcc_unreachable ();
   9229  1.1  mrg 
   9230  1.1  mrg   fndecl = build_addr (function);
   9231  1.1  mrg   tmp = build_call_array_loc (input_location,
   9232  1.1  mrg 			  TREE_TYPE (TREE_TYPE (function)), fndecl,
   9233  1.1  mrg 			  num_args, args);
   9234  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   9235  1.1  mrg 
   9236  1.1  mrg   /* Free the temporary afterwards, if necessary.  */
   9237  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   9238  1.1  mrg 			  len, build_int_cst (TREE_TYPE (len), 0));
   9239  1.1  mrg   tmp = gfc_call_free (var);
   9240  1.1  mrg   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
   9241  1.1  mrg   gfc_add_expr_to_block (&se->post, tmp);
   9242  1.1  mrg 
   9243  1.1  mrg   se->expr = var;
   9244  1.1  mrg   se->string_length = len;
   9245  1.1  mrg }
   9246  1.1  mrg 
   9247  1.1  mrg 
   9248  1.1  mrg /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function.  */
   9249  1.1  mrg 
   9250  1.1  mrg static void
   9251  1.1  mrg gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
   9252  1.1  mrg {
   9253  1.1  mrg   tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
   9254  1.1  mrg   tree type, cond, tmp, count, exit_label, n, max, largest;
   9255  1.1  mrg   tree size;
   9256  1.1  mrg   stmtblock_t block, body;
   9257  1.1  mrg   int i;
   9258  1.1  mrg 
   9259  1.1  mrg   /* We store in charsize the size of a character.  */
   9260  1.1  mrg   i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
   9261  1.1  mrg   size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
   9262  1.1  mrg 
   9263  1.1  mrg   /* Get the arguments.  */
   9264  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, 3);
   9265  1.1  mrg   slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
   9266  1.1  mrg   src = args[1];
   9267  1.1  mrg   ncopies = gfc_evaluate_now (args[2], &se->pre);
   9268  1.1  mrg   ncopies_type = TREE_TYPE (ncopies);
   9269  1.1  mrg 
   9270  1.1  mrg   /* Check that NCOPIES is not negative.  */
   9271  1.1  mrg   cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
   9272  1.1  mrg 			  build_int_cst (ncopies_type, 0));
   9273  1.1  mrg   gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
   9274  1.1  mrg 			   "Argument NCOPIES of REPEAT intrinsic is negative "
   9275  1.1  mrg 			   "(its value is %ld)",
   9276  1.1  mrg 			   fold_convert (long_integer_type_node, ncopies));
   9277  1.1  mrg 
   9278  1.1  mrg   /* If the source length is zero, any non negative value of NCOPIES
   9279  1.1  mrg      is valid, and nothing happens.  */
   9280  1.1  mrg   n = gfc_create_var (ncopies_type, "ncopies");
   9281  1.1  mrg   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
   9282  1.1  mrg 			  size_zero_node);
   9283  1.1  mrg   tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
   9284  1.1  mrg 			 build_int_cst (ncopies_type, 0), ncopies);
   9285  1.1  mrg   gfc_add_modify (&se->pre, n, tmp);
   9286  1.1  mrg   ncopies = n;
   9287  1.1  mrg 
   9288  1.1  mrg   /* Check that ncopies is not too large: ncopies should be less than
   9289  1.1  mrg      (or equal to) MAX / slen, where MAX is the maximal integer of
   9290  1.1  mrg      the gfc_charlen_type_node type.  If slen == 0, we need a special
   9291  1.1  mrg      case to avoid the division by zero.  */
   9292  1.1  mrg   max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
   9293  1.1  mrg 			 fold_convert (sizetype,
   9294  1.1  mrg 				       TYPE_MAX_VALUE (gfc_charlen_type_node)),
   9295  1.1  mrg 			 slen);
   9296  1.1  mrg   largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
   9297  1.1  mrg 	      ? sizetype : ncopies_type;
   9298  1.1  mrg   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
   9299  1.1  mrg 			  fold_convert (largest, ncopies),
   9300  1.1  mrg 			  fold_convert (largest, max));
   9301  1.1  mrg   tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
   9302  1.1  mrg 			 size_zero_node);
   9303  1.1  mrg   cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
   9304  1.1  mrg 			  logical_false_node, cond);
   9305  1.1  mrg   gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
   9306  1.1  mrg 			   "Argument NCOPIES of REPEAT intrinsic is too large");
   9307  1.1  mrg 
   9308  1.1  mrg   /* Compute the destination length.  */
   9309  1.1  mrg   dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
   9310  1.1  mrg 			  fold_convert (gfc_charlen_type_node, slen),
   9311  1.1  mrg 			  fold_convert (gfc_charlen_type_node, ncopies));
   9312  1.1  mrg   type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
   9313  1.1  mrg   dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
   9314  1.1  mrg 
   9315  1.1  mrg   /* Generate the code to do the repeat operation:
   9316  1.1  mrg        for (i = 0; i < ncopies; i++)
   9317  1.1  mrg          memmove (dest + (i * slen * size), src, slen*size);  */
   9318  1.1  mrg   gfc_start_block (&block);
   9319  1.1  mrg   count = gfc_create_var (sizetype, "count");
   9320  1.1  mrg   gfc_add_modify (&block, count, size_zero_node);
   9321  1.1  mrg   exit_label = gfc_build_label_decl (NULL_TREE);
   9322  1.1  mrg 
   9323  1.1  mrg   /* Start the loop body.  */
   9324  1.1  mrg   gfc_start_block (&body);
   9325  1.1  mrg 
   9326  1.1  mrg   /* Exit the loop if count >= ncopies.  */
   9327  1.1  mrg   cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
   9328  1.1  mrg 			  fold_convert (sizetype, ncopies));
   9329  1.1  mrg   tmp = build1_v (GOTO_EXPR, exit_label);
   9330  1.1  mrg   TREE_USED (exit_label) = 1;
   9331  1.1  mrg   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
   9332  1.1  mrg 			 build_empty_stmt (input_location));
   9333  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   9334  1.1  mrg 
   9335  1.1  mrg   /* Call memmove (dest + (i*slen*size), src, slen*size).  */
   9336  1.1  mrg   tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
   9337  1.1  mrg 			 count);
   9338  1.1  mrg   tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
   9339  1.1  mrg 			 size);
   9340  1.1  mrg   tmp = fold_build_pointer_plus_loc (input_location,
   9341  1.1  mrg 				     fold_convert (pvoid_type_node, dest), tmp);
   9342  1.1  mrg   tmp = build_call_expr_loc (input_location,
   9343  1.1  mrg 			     builtin_decl_explicit (BUILT_IN_MEMMOVE),
   9344  1.1  mrg 			     3, tmp, src,
   9345  1.1  mrg 			     fold_build2_loc (input_location, MULT_EXPR,
   9346  1.1  mrg 					      size_type_node, slen, size));
   9347  1.1  mrg   gfc_add_expr_to_block (&body, tmp);
   9348  1.1  mrg 
   9349  1.1  mrg   /* Increment count.  */
   9350  1.1  mrg   tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
   9351  1.1  mrg 			 count, size_one_node);
   9352  1.1  mrg   gfc_add_modify (&body, count, tmp);
   9353  1.1  mrg 
   9354  1.1  mrg   /* Build the loop.  */
   9355  1.1  mrg   tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
   9356  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   9357  1.1  mrg 
   9358  1.1  mrg   /* Add the exit label.  */
   9359  1.1  mrg   tmp = build1_v (LABEL_EXPR, exit_label);
   9360  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   9361  1.1  mrg 
   9362  1.1  mrg   /* Finish the block.  */
   9363  1.1  mrg   tmp = gfc_finish_block (&block);
   9364  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   9365  1.1  mrg 
   9366  1.1  mrg   /* Set the result value.  */
   9367  1.1  mrg   se->expr = dest;
   9368  1.1  mrg   se->string_length = dlen;
   9369  1.1  mrg }
   9370  1.1  mrg 
   9371  1.1  mrg 
   9372  1.1  mrg /* Generate code for the IARGC intrinsic.  */
   9373  1.1  mrg 
   9374  1.1  mrg static void
   9375  1.1  mrg gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
   9376  1.1  mrg {
   9377  1.1  mrg   tree tmp;
   9378  1.1  mrg   tree fndecl;
   9379  1.1  mrg   tree type;
   9380  1.1  mrg 
   9381  1.1  mrg   /* Call the library function.  This always returns an INTEGER(4).  */
   9382  1.1  mrg   fndecl = gfor_fndecl_iargc;
   9383  1.1  mrg   tmp = build_call_expr_loc (input_location,
   9384  1.1  mrg 			 fndecl, 0);
   9385  1.1  mrg 
   9386  1.1  mrg   /* Convert it to the required type.  */
   9387  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   9388  1.1  mrg   tmp = fold_convert (type, tmp);
   9389  1.1  mrg 
   9390  1.1  mrg   se->expr = tmp;
   9391  1.1  mrg }
   9392  1.1  mrg 
   9393  1.1  mrg 
   9394  1.1  mrg /* Generate code for the KILL intrinsic.  */
   9395  1.1  mrg 
   9396  1.1  mrg static void
   9397  1.1  mrg conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
   9398  1.1  mrg {
   9399  1.1  mrg   tree *args;
   9400  1.1  mrg   tree int4_type_node = gfc_get_int_type (4);
   9401  1.1  mrg   tree pid;
   9402  1.1  mrg   tree sig;
   9403  1.1  mrg   tree tmp;
   9404  1.1  mrg   unsigned int num_args;
   9405  1.1  mrg 
   9406  1.1  mrg   num_args = gfc_intrinsic_argument_list_length (expr);
   9407  1.1  mrg   args = XALLOCAVEC (tree, num_args);
   9408  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, args, num_args);
   9409  1.1  mrg 
   9410  1.1  mrg   /* Convert PID to a INTEGER(4) entity.  */
   9411  1.1  mrg   pid = convert (int4_type_node, args[0]);
   9412  1.1  mrg 
   9413  1.1  mrg   /* Convert SIG to a INTEGER(4) entity.  */
   9414  1.1  mrg   sig = convert (int4_type_node, args[1]);
   9415  1.1  mrg 
   9416  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
   9417  1.1  mrg 
   9418  1.1  mrg   se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
   9419  1.1  mrg }
   9420  1.1  mrg 
   9421  1.1  mrg 
   9422  1.1  mrg static tree
   9423  1.1  mrg conv_intrinsic_kill_sub (gfc_code *code)
   9424  1.1  mrg {
   9425  1.1  mrg   stmtblock_t block;
   9426  1.1  mrg   gfc_se se, se_stat;
   9427  1.1  mrg   tree int4_type_node = gfc_get_int_type (4);
   9428  1.1  mrg   tree pid;
   9429  1.1  mrg   tree sig;
   9430  1.1  mrg   tree statp;
   9431  1.1  mrg   tree tmp;
   9432  1.1  mrg 
   9433  1.1  mrg   /* Make the function call.  */
   9434  1.1  mrg   gfc_init_block (&block);
   9435  1.1  mrg   gfc_init_se (&se, NULL);
   9436  1.1  mrg 
   9437  1.1  mrg   /* Convert PID to a INTEGER(4) entity.  */
   9438  1.1  mrg   gfc_conv_expr (&se, code->ext.actual->expr);
   9439  1.1  mrg   gfc_add_block_to_block (&block, &se.pre);
   9440  1.1  mrg   pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
   9441  1.1  mrg   gfc_add_block_to_block (&block, &se.post);
   9442  1.1  mrg 
   9443  1.1  mrg   /* Convert SIG to a INTEGER(4) entity.  */
   9444  1.1  mrg   gfc_conv_expr (&se, code->ext.actual->next->expr);
   9445  1.1  mrg   gfc_add_block_to_block (&block, &se.pre);
   9446  1.1  mrg   sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
   9447  1.1  mrg   gfc_add_block_to_block (&block, &se.post);
   9448  1.1  mrg 
   9449  1.1  mrg   /* Deal with an optional STATUS.  */
   9450  1.1  mrg   if (code->ext.actual->next->next->expr)
   9451  1.1  mrg     {
   9452  1.1  mrg       gfc_init_se (&se_stat, NULL);
   9453  1.1  mrg       gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
   9454  1.1  mrg       statp = gfc_create_var (gfc_get_int_type (4), "_statp");
   9455  1.1  mrg     }
   9456  1.1  mrg   else
   9457  1.1  mrg     statp = NULL_TREE;
   9458  1.1  mrg 
   9459  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
   9460  1.1  mrg 	statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
   9461  1.1  mrg 
   9462  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   9463  1.1  mrg 
   9464  1.1  mrg   if (statp && statp != se_stat.expr)
   9465  1.1  mrg     gfc_add_modify (&block, se_stat.expr,
   9466  1.1  mrg 		    fold_convert (TREE_TYPE (se_stat.expr), statp));
   9467  1.1  mrg 
   9468  1.1  mrg   return gfc_finish_block (&block);
   9469  1.1  mrg }
   9470  1.1  mrg 
   9471  1.1  mrg 
   9472  1.1  mrg 
   9473  1.1  mrg /* The loc intrinsic returns the address of its argument as
   9474  1.1  mrg    gfc_index_integer_kind integer.  */
   9475  1.1  mrg 
   9476  1.1  mrg static void
   9477  1.1  mrg gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
   9478  1.1  mrg {
   9479  1.1  mrg   tree temp_var;
   9480  1.1  mrg   gfc_expr *arg_expr;
   9481  1.1  mrg 
   9482  1.1  mrg   gcc_assert (!se->ss);
   9483  1.1  mrg 
   9484  1.1  mrg   arg_expr = expr->value.function.actual->expr;
   9485  1.1  mrg   if (arg_expr->rank == 0)
   9486  1.1  mrg     {
   9487  1.1  mrg       if (arg_expr->ts.type == BT_CLASS)
   9488  1.1  mrg 	gfc_add_data_component (arg_expr);
   9489  1.1  mrg       gfc_conv_expr_reference (se, arg_expr);
   9490  1.1  mrg     }
   9491  1.1  mrg   else
   9492  1.1  mrg     gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
   9493  1.1  mrg   se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
   9494  1.1  mrg 
   9495  1.1  mrg   /* Create a temporary variable for loc return value.  Without this,
   9496  1.1  mrg      we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1).  */
   9497  1.1  mrg   temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
   9498  1.1  mrg   gfc_add_modify (&se->pre, temp_var, se->expr);
   9499  1.1  mrg   se->expr = temp_var;
   9500  1.1  mrg }
   9501  1.1  mrg 
   9502  1.1  mrg 
   9503  1.1  mrg /* The following routine generates code for the intrinsic
   9504  1.1  mrg    functions from the ISO_C_BINDING module:
   9505  1.1  mrg     * C_LOC
   9506  1.1  mrg     * C_FUNLOC
   9507  1.1  mrg     * C_ASSOCIATED  */
   9508  1.1  mrg 
   9509  1.1  mrg static void
   9510  1.1  mrg conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
   9511  1.1  mrg {
   9512  1.1  mrg   gfc_actual_arglist *arg = expr->value.function.actual;
   9513  1.1  mrg 
   9514  1.1  mrg   if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
   9515  1.1  mrg     {
   9516  1.1  mrg       if (arg->expr->rank == 0)
   9517  1.1  mrg 	gfc_conv_expr_reference (se, arg->expr);
   9518  1.1  mrg       else if (gfc_is_simply_contiguous (arg->expr, false, false))
   9519  1.1  mrg 	gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
   9520  1.1  mrg       else
   9521  1.1  mrg 	{
   9522  1.1  mrg 	  gfc_conv_expr_descriptor (se, arg->expr);
   9523  1.1  mrg 	  se->expr = gfc_conv_descriptor_data_get (se->expr);
   9524  1.1  mrg 	}
   9525  1.1  mrg 
   9526  1.1  mrg       /* TODO -- the following two lines shouldn't be necessary, but if
   9527  1.1  mrg 	 they're removed, a bug is exposed later in the code path.
   9528  1.1  mrg 	 This workaround was thus introduced, but will have to be
   9529  1.1  mrg 	 removed; please see PR 35150 for details about the issue.  */
   9530  1.1  mrg       se->expr = convert (pvoid_type_node, se->expr);
   9531  1.1  mrg       se->expr = gfc_evaluate_now (se->expr, &se->pre);
   9532  1.1  mrg     }
   9533  1.1  mrg   else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
   9534  1.1  mrg     gfc_conv_expr_reference (se, arg->expr);
   9535  1.1  mrg   else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
   9536  1.1  mrg     {
   9537  1.1  mrg       gfc_se arg1se;
   9538  1.1  mrg       gfc_se arg2se;
   9539  1.1  mrg 
   9540  1.1  mrg       /* Build the addr_expr for the first argument.  The argument is
   9541  1.1  mrg 	 already an *address* so we don't need to set want_pointer in
   9542  1.1  mrg 	 the gfc_se.  */
   9543  1.1  mrg       gfc_init_se (&arg1se, NULL);
   9544  1.1  mrg       gfc_conv_expr (&arg1se, arg->expr);
   9545  1.1  mrg       gfc_add_block_to_block (&se->pre, &arg1se.pre);
   9546  1.1  mrg       gfc_add_block_to_block (&se->post, &arg1se.post);
   9547  1.1  mrg 
   9548  1.1  mrg       /* See if we were given two arguments.  */
   9549  1.1  mrg       if (arg->next->expr == NULL)
   9550  1.1  mrg 	/* Only given one arg so generate a null and do a
   9551  1.1  mrg 	   not-equal comparison against the first arg.  */
   9552  1.1  mrg 	se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   9553  1.1  mrg 				    arg1se.expr,
   9554  1.1  mrg 				    fold_convert (TREE_TYPE (arg1se.expr),
   9555  1.1  mrg 						  null_pointer_node));
   9556  1.1  mrg       else
   9557  1.1  mrg 	{
   9558  1.1  mrg 	  tree eq_expr;
   9559  1.1  mrg 	  tree not_null_expr;
   9560  1.1  mrg 
   9561  1.1  mrg 	  /* Given two arguments so build the arg2se from second arg.  */
   9562  1.1  mrg 	  gfc_init_se (&arg2se, NULL);
   9563  1.1  mrg 	  gfc_conv_expr (&arg2se, arg->next->expr);
   9564  1.1  mrg 	  gfc_add_block_to_block (&se->pre, &arg2se.pre);
   9565  1.1  mrg 	  gfc_add_block_to_block (&se->post, &arg2se.post);
   9566  1.1  mrg 
   9567  1.1  mrg 	  /* Generate test to compare that the two args are equal.  */
   9568  1.1  mrg 	  eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   9569  1.1  mrg 				     arg1se.expr, arg2se.expr);
   9570  1.1  mrg 	  /* Generate test to ensure that the first arg is not null.  */
   9571  1.1  mrg 	  not_null_expr = fold_build2_loc (input_location, NE_EXPR,
   9572  1.1  mrg 					   logical_type_node,
   9573  1.1  mrg 					   arg1se.expr, null_pointer_node);
   9574  1.1  mrg 
   9575  1.1  mrg 	  /* Finally, the generated test must check that both arg1 is not
   9576  1.1  mrg 	     NULL and that it is equal to the second arg.  */
   9577  1.1  mrg 	  se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   9578  1.1  mrg 				      logical_type_node,
   9579  1.1  mrg 				      not_null_expr, eq_expr);
   9580  1.1  mrg 	}
   9581  1.1  mrg     }
   9582  1.1  mrg   else
   9583  1.1  mrg     gcc_unreachable ();
   9584  1.1  mrg }
   9585  1.1  mrg 
   9586  1.1  mrg 
   9587  1.1  mrg /* The following routine generates code for the intrinsic
   9588  1.1  mrg    subroutines from the ISO_C_BINDING module:
   9589  1.1  mrg     * C_F_POINTER
   9590  1.1  mrg     * C_F_PROCPOINTER.  */
   9591  1.1  mrg 
   9592  1.1  mrg static tree
   9593  1.1  mrg conv_isocbinding_subroutine (gfc_code *code)
   9594  1.1  mrg {
   9595  1.1  mrg   gfc_se se;
   9596  1.1  mrg   gfc_se cptrse;
   9597  1.1  mrg   gfc_se fptrse;
   9598  1.1  mrg   gfc_se shapese;
   9599  1.1  mrg   gfc_ss *shape_ss;
   9600  1.1  mrg   tree desc, dim, tmp, stride, offset;
   9601  1.1  mrg   stmtblock_t body, block;
   9602  1.1  mrg   gfc_loopinfo loop;
   9603  1.1  mrg   gfc_actual_arglist *arg = code->ext.actual;
   9604  1.1  mrg 
   9605  1.1  mrg   gfc_init_se (&se, NULL);
   9606  1.1  mrg   gfc_init_se (&cptrse, NULL);
   9607  1.1  mrg   gfc_conv_expr (&cptrse, arg->expr);
   9608  1.1  mrg   gfc_add_block_to_block (&se.pre, &cptrse.pre);
   9609  1.1  mrg   gfc_add_block_to_block (&se.post, &cptrse.post);
   9610  1.1  mrg 
   9611  1.1  mrg   gfc_init_se (&fptrse, NULL);
   9612  1.1  mrg   if (arg->next->expr->rank == 0)
   9613  1.1  mrg     {
   9614  1.1  mrg       fptrse.want_pointer = 1;
   9615  1.1  mrg       gfc_conv_expr (&fptrse, arg->next->expr);
   9616  1.1  mrg       gfc_add_block_to_block (&se.pre, &fptrse.pre);
   9617  1.1  mrg       gfc_add_block_to_block (&se.post, &fptrse.post);
   9618  1.1  mrg       if (arg->next->expr->symtree->n.sym->attr.proc_pointer
   9619  1.1  mrg 	  && arg->next->expr->symtree->n.sym->attr.dummy)
   9620  1.1  mrg 	fptrse.expr = build_fold_indirect_ref_loc (input_location,
   9621  1.1  mrg 						       fptrse.expr);
   9622  1.1  mrg       se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
   9623  1.1  mrg 				 TREE_TYPE (fptrse.expr),
   9624  1.1  mrg 				 fptrse.expr,
   9625  1.1  mrg 				 fold_convert (TREE_TYPE (fptrse.expr),
   9626  1.1  mrg 					       cptrse.expr));
   9627  1.1  mrg       gfc_add_expr_to_block (&se.pre, se.expr);
   9628  1.1  mrg       gfc_add_block_to_block (&se.pre, &se.post);
   9629  1.1  mrg       return gfc_finish_block (&se.pre);
   9630  1.1  mrg     }
   9631  1.1  mrg 
   9632  1.1  mrg   gfc_start_block (&block);
   9633  1.1  mrg 
   9634  1.1  mrg   /* Get the descriptor of the Fortran pointer.  */
   9635  1.1  mrg   fptrse.descriptor_only = 1;
   9636  1.1  mrg   gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
   9637  1.1  mrg   gfc_add_block_to_block (&block, &fptrse.pre);
   9638  1.1  mrg   desc = fptrse.expr;
   9639  1.1  mrg 
   9640  1.1  mrg   /* Set the span field.  */
   9641  1.1  mrg   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
   9642  1.1  mrg   tmp = fold_convert (gfc_array_index_type, tmp);
   9643  1.1  mrg   gfc_conv_descriptor_span_set (&block, desc, tmp);
   9644  1.1  mrg 
   9645  1.1  mrg   /* Set data value, dtype, and offset.  */
   9646  1.1  mrg   tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
   9647  1.1  mrg   gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
   9648  1.1  mrg   gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
   9649  1.1  mrg 		  gfc_get_dtype (TREE_TYPE (desc)));
   9650  1.1  mrg 
   9651  1.1  mrg   /* Start scalarization of the bounds, using the shape argument.  */
   9652  1.1  mrg 
   9653  1.1  mrg   shape_ss = gfc_walk_expr (arg->next->next->expr);
   9654  1.1  mrg   gcc_assert (shape_ss != gfc_ss_terminator);
   9655  1.1  mrg   gfc_init_se (&shapese, NULL);
   9656  1.1  mrg 
   9657  1.1  mrg   gfc_init_loopinfo (&loop);
   9658  1.1  mrg   gfc_add_ss_to_loop (&loop, shape_ss);
   9659  1.1  mrg   gfc_conv_ss_startstride (&loop);
   9660  1.1  mrg   gfc_conv_loop_setup (&loop, &arg->next->expr->where);
   9661  1.1  mrg   gfc_mark_ss_chain_used (shape_ss, 1);
   9662  1.1  mrg 
   9663  1.1  mrg   gfc_copy_loopinfo_to_se (&shapese, &loop);
   9664  1.1  mrg   shapese.ss = shape_ss;
   9665  1.1  mrg 
   9666  1.1  mrg   stride = gfc_create_var (gfc_array_index_type, "stride");
   9667  1.1  mrg   offset = gfc_create_var (gfc_array_index_type, "offset");
   9668  1.1  mrg   gfc_add_modify (&block, stride, gfc_index_one_node);
   9669  1.1  mrg   gfc_add_modify (&block, offset, gfc_index_zero_node);
   9670  1.1  mrg 
   9671  1.1  mrg   /* Loop body.  */
   9672  1.1  mrg   gfc_start_scalarized_body (&loop, &body);
   9673  1.1  mrg 
   9674  1.1  mrg   dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
   9675  1.1  mrg 			     loop.loopvar[0], loop.from[0]);
   9676  1.1  mrg 
   9677  1.1  mrg   /* Set bounds and stride.  */
   9678  1.1  mrg   gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
   9679  1.1  mrg   gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
   9680  1.1  mrg 
   9681  1.1  mrg   gfc_conv_expr (&shapese, arg->next->next->expr);
   9682  1.1  mrg   gfc_add_block_to_block (&body, &shapese.pre);
   9683  1.1  mrg   gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
   9684  1.1  mrg   gfc_add_block_to_block (&body, &shapese.post);
   9685  1.1  mrg 
   9686  1.1  mrg   /* Calculate offset.  */
   9687  1.1  mrg   gfc_add_modify (&body, offset,
   9688  1.1  mrg 		  fold_build2_loc (input_location, PLUS_EXPR,
   9689  1.1  mrg 				   gfc_array_index_type, offset, stride));
   9690  1.1  mrg   /* Update stride.  */
   9691  1.1  mrg   gfc_add_modify (&body, stride,
   9692  1.1  mrg 		  fold_build2_loc (input_location, MULT_EXPR,
   9693  1.1  mrg 				   gfc_array_index_type, stride,
   9694  1.1  mrg 				   fold_convert (gfc_array_index_type,
   9695  1.1  mrg 						 shapese.expr)));
   9696  1.1  mrg   /* Finish scalarization loop.  */
   9697  1.1  mrg   gfc_trans_scalarizing_loops (&loop, &body);
   9698  1.1  mrg   gfc_add_block_to_block (&block, &loop.pre);
   9699  1.1  mrg   gfc_add_block_to_block (&block, &loop.post);
   9700  1.1  mrg   gfc_add_block_to_block (&block, &fptrse.post);
   9701  1.1  mrg   gfc_cleanup_loop (&loop);
   9702  1.1  mrg 
   9703  1.1  mrg   gfc_add_modify (&block, offset,
   9704  1.1  mrg 		  fold_build1_loc (input_location, NEGATE_EXPR,
   9705  1.1  mrg 				   gfc_array_index_type, offset));
   9706  1.1  mrg   gfc_conv_descriptor_offset_set (&block, desc, offset);
   9707  1.1  mrg 
   9708  1.1  mrg   gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
   9709  1.1  mrg   gfc_add_block_to_block (&se.pre, &se.post);
   9710  1.1  mrg   return gfc_finish_block (&se.pre);
   9711  1.1  mrg }
   9712  1.1  mrg 
   9713  1.1  mrg 
   9714  1.1  mrg /* Save and restore floating-point state.  */
   9715  1.1  mrg 
   9716  1.1  mrg tree
   9717  1.1  mrg gfc_save_fp_state (stmtblock_t *block)
   9718  1.1  mrg {
   9719  1.1  mrg   tree type, fpstate, tmp;
   9720  1.1  mrg 
   9721  1.1  mrg   type = build_array_type (char_type_node,
   9722  1.1  mrg 	                   build_range_type (size_type_node, size_zero_node,
   9723  1.1  mrg 					     size_int (GFC_FPE_STATE_BUFFER_SIZE)));
   9724  1.1  mrg   fpstate = gfc_create_var (type, "fpstate");
   9725  1.1  mrg   fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
   9726  1.1  mrg 
   9727  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
   9728  1.1  mrg 			     1, fpstate);
   9729  1.1  mrg   gfc_add_expr_to_block (block, tmp);
   9730  1.1  mrg 
   9731  1.1  mrg   return fpstate;
   9732  1.1  mrg }
   9733  1.1  mrg 
   9734  1.1  mrg 
   9735  1.1  mrg void
   9736  1.1  mrg gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
   9737  1.1  mrg {
   9738  1.1  mrg   tree tmp;
   9739  1.1  mrg 
   9740  1.1  mrg   tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
   9741  1.1  mrg 			     1, fpstate);
   9742  1.1  mrg   gfc_add_expr_to_block (block, tmp);
   9743  1.1  mrg }
   9744  1.1  mrg 
   9745  1.1  mrg 
   9746  1.1  mrg /* Generate code for arguments of IEEE functions.  */
   9747  1.1  mrg 
   9748  1.1  mrg static void
   9749  1.1  mrg conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
   9750  1.1  mrg 			 int nargs)
   9751  1.1  mrg {
   9752  1.1  mrg   gfc_actual_arglist *actual;
   9753  1.1  mrg   gfc_expr *e;
   9754  1.1  mrg   gfc_se argse;
   9755  1.1  mrg   int arg;
   9756  1.1  mrg 
   9757  1.1  mrg   actual = expr->value.function.actual;
   9758  1.1  mrg   for (arg = 0; arg < nargs; arg++, actual = actual->next)
   9759  1.1  mrg     {
   9760  1.1  mrg       gcc_assert (actual);
   9761  1.1  mrg       e = actual->expr;
   9762  1.1  mrg 
   9763  1.1  mrg       gfc_init_se (&argse, se);
   9764  1.1  mrg       gfc_conv_expr_val (&argse, e);
   9765  1.1  mrg 
   9766  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse.pre);
   9767  1.1  mrg       gfc_add_block_to_block (&se->post, &argse.post);
   9768  1.1  mrg       argarray[arg] = argse.expr;
   9769  1.1  mrg     }
   9770  1.1  mrg }
   9771  1.1  mrg 
   9772  1.1  mrg 
   9773  1.1  mrg /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
   9774  1.1  mrg    and IEEE_UNORDERED, which translate directly to GCC type-generic
   9775  1.1  mrg    built-ins.  */
   9776  1.1  mrg 
   9777  1.1  mrg static void
   9778  1.1  mrg conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
   9779  1.1  mrg 			     enum built_in_function code, int nargs)
   9780  1.1  mrg {
   9781  1.1  mrg   tree args[2];
   9782  1.1  mrg   gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
   9783  1.1  mrg 
   9784  1.1  mrg   conv_ieee_function_args (se, expr, args, nargs);
   9785  1.1  mrg   se->expr = build_call_expr_loc_array (input_location,
   9786  1.1  mrg 					builtin_decl_explicit (code),
   9787  1.1  mrg 					nargs, args);
   9788  1.1  mrg   STRIP_TYPE_NOPS (se->expr);
   9789  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   9790  1.1  mrg }
   9791  1.1  mrg 
   9792  1.1  mrg 
   9793  1.1  mrg /* Generate code for IEEE_IS_NORMAL intrinsic:
   9794  1.1  mrg      IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0)  */
   9795  1.1  mrg 
   9796  1.1  mrg static void
   9797  1.1  mrg conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
   9798  1.1  mrg {
   9799  1.1  mrg   tree arg, isnormal, iszero;
   9800  1.1  mrg 
   9801  1.1  mrg   /* Convert arg, evaluate it only once.  */
   9802  1.1  mrg   conv_ieee_function_args (se, expr, &arg, 1);
   9803  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   9804  1.1  mrg 
   9805  1.1  mrg   isnormal = build_call_expr_loc (input_location,
   9806  1.1  mrg 				  builtin_decl_explicit (BUILT_IN_ISNORMAL),
   9807  1.1  mrg 				  1, arg);
   9808  1.1  mrg   iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
   9809  1.1  mrg 			    build_real_from_int_cst (TREE_TYPE (arg),
   9810  1.1  mrg 						     integer_zero_node));
   9811  1.1  mrg   se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
   9812  1.1  mrg 			      logical_type_node, isnormal, iszero);
   9813  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   9814  1.1  mrg }
   9815  1.1  mrg 
   9816  1.1  mrg 
   9817  1.1  mrg /* Generate code for IEEE_IS_NEGATIVE intrinsic:
   9818  1.1  mrg      IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x))  */
   9819  1.1  mrg 
   9820  1.1  mrg static void
   9821  1.1  mrg conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
   9822  1.1  mrg {
   9823  1.1  mrg   tree arg, signbit, isnan;
   9824  1.1  mrg 
   9825  1.1  mrg   /* Convert arg, evaluate it only once.  */
   9826  1.1  mrg   conv_ieee_function_args (se, expr, &arg, 1);
   9827  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   9828  1.1  mrg 
   9829  1.1  mrg   isnan = build_call_expr_loc (input_location,
   9830  1.1  mrg 			       builtin_decl_explicit (BUILT_IN_ISNAN),
   9831  1.1  mrg 			       1, arg);
   9832  1.1  mrg   STRIP_TYPE_NOPS (isnan);
   9833  1.1  mrg 
   9834  1.1  mrg   signbit = build_call_expr_loc (input_location,
   9835  1.1  mrg 				 builtin_decl_explicit (BUILT_IN_SIGNBIT),
   9836  1.1  mrg 				 1, arg);
   9837  1.1  mrg   signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   9838  1.1  mrg 			     signbit, integer_zero_node);
   9839  1.1  mrg 
   9840  1.1  mrg   se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   9841  1.1  mrg 			      logical_type_node, signbit,
   9842  1.1  mrg 			      fold_build1_loc (input_location, TRUTH_NOT_EXPR,
   9843  1.1  mrg 					       TREE_TYPE(isnan), isnan));
   9844  1.1  mrg 
   9845  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
   9846  1.1  mrg }
   9847  1.1  mrg 
   9848  1.1  mrg 
   9849  1.1  mrg /* Generate code for IEEE_LOGB and IEEE_RINT.  */
   9850  1.1  mrg 
   9851  1.1  mrg static void
   9852  1.1  mrg conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
   9853  1.1  mrg 			       enum built_in_function code)
   9854  1.1  mrg {
   9855  1.1  mrg   tree arg, decl, call, fpstate;
   9856  1.1  mrg   int argprec;
   9857  1.1  mrg 
   9858  1.1  mrg   conv_ieee_function_args (se, expr, &arg, 1);
   9859  1.1  mrg   argprec = TYPE_PRECISION (TREE_TYPE (arg));
   9860  1.1  mrg   decl = builtin_decl_for_precision (code, argprec);
   9861  1.1  mrg 
   9862  1.1  mrg   /* Save floating-point state.  */
   9863  1.1  mrg   fpstate = gfc_save_fp_state (&se->pre);
   9864  1.1  mrg 
   9865  1.1  mrg   /* Make the function call.  */
   9866  1.1  mrg   call = build_call_expr_loc (input_location, decl, 1, arg);
   9867  1.1  mrg   se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
   9868  1.1  mrg 
   9869  1.1  mrg   /* Restore floating-point state.  */
   9870  1.1  mrg   gfc_restore_fp_state (&se->post, fpstate);
   9871  1.1  mrg }
   9872  1.1  mrg 
   9873  1.1  mrg 
   9874  1.1  mrg /* Generate code for IEEE_REM.  */
   9875  1.1  mrg 
   9876  1.1  mrg static void
   9877  1.1  mrg conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
   9878  1.1  mrg {
   9879  1.1  mrg   tree args[2], decl, call, fpstate;
   9880  1.1  mrg   int argprec;
   9881  1.1  mrg 
   9882  1.1  mrg   conv_ieee_function_args (se, expr, args, 2);
   9883  1.1  mrg 
   9884  1.1  mrg   /* If arguments have unequal size, convert them to the larger.  */
   9885  1.1  mrg   if (TYPE_PRECISION (TREE_TYPE (args[0]))
   9886  1.1  mrg       > TYPE_PRECISION (TREE_TYPE (args[1])))
   9887  1.1  mrg     args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
   9888  1.1  mrg   else if (TYPE_PRECISION (TREE_TYPE (args[1]))
   9889  1.1  mrg 	   > TYPE_PRECISION (TREE_TYPE (args[0])))
   9890  1.1  mrg     args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
   9891  1.1  mrg 
   9892  1.1  mrg   argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
   9893  1.1  mrg   decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
   9894  1.1  mrg 
   9895  1.1  mrg   /* Save floating-point state.  */
   9896  1.1  mrg   fpstate = gfc_save_fp_state (&se->pre);
   9897  1.1  mrg 
   9898  1.1  mrg   /* Make the function call.  */
   9899  1.1  mrg   call = build_call_expr_loc_array (input_location, decl, 2, args);
   9900  1.1  mrg   se->expr = fold_convert (TREE_TYPE (args[0]), call);
   9901  1.1  mrg 
   9902  1.1  mrg   /* Restore floating-point state.  */
   9903  1.1  mrg   gfc_restore_fp_state (&se->post, fpstate);
   9904  1.1  mrg }
   9905  1.1  mrg 
   9906  1.1  mrg 
   9907  1.1  mrg /* Generate code for IEEE_NEXT_AFTER.  */
   9908  1.1  mrg 
   9909  1.1  mrg static void
   9910  1.1  mrg conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
   9911  1.1  mrg {
   9912  1.1  mrg   tree args[2], decl, call, fpstate;
   9913  1.1  mrg   int argprec;
   9914  1.1  mrg 
   9915  1.1  mrg   conv_ieee_function_args (se, expr, args, 2);
   9916  1.1  mrg 
   9917  1.1  mrg   /* Result has the characteristics of first argument.  */
   9918  1.1  mrg   args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
   9919  1.1  mrg   argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
   9920  1.1  mrg   decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
   9921  1.1  mrg 
   9922  1.1  mrg   /* Save floating-point state.  */
   9923  1.1  mrg   fpstate = gfc_save_fp_state (&se->pre);
   9924  1.1  mrg 
   9925  1.1  mrg   /* Make the function call.  */
   9926  1.1  mrg   call = build_call_expr_loc_array (input_location, decl, 2, args);
   9927  1.1  mrg   se->expr = fold_convert (TREE_TYPE (args[0]), call);
   9928  1.1  mrg 
   9929  1.1  mrg   /* Restore floating-point state.  */
   9930  1.1  mrg   gfc_restore_fp_state (&se->post, fpstate);
   9931  1.1  mrg }
   9932  1.1  mrg 
   9933  1.1  mrg 
   9934  1.1  mrg /* Generate code for IEEE_SCALB.  */
   9935  1.1  mrg 
   9936  1.1  mrg static void
   9937  1.1  mrg conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
   9938  1.1  mrg {
   9939  1.1  mrg   tree args[2], decl, call, huge, type;
   9940  1.1  mrg   int argprec, n;
   9941  1.1  mrg 
   9942  1.1  mrg   conv_ieee_function_args (se, expr, args, 2);
   9943  1.1  mrg 
   9944  1.1  mrg   /* Result has the characteristics of first argument.  */
   9945  1.1  mrg   argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
   9946  1.1  mrg   decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
   9947  1.1  mrg 
   9948  1.1  mrg   if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
   9949  1.1  mrg     {
   9950  1.1  mrg       /* We need to fold the integer into the range of a C int.  */
   9951  1.1  mrg       args[1] = gfc_evaluate_now (args[1], &se->pre);
   9952  1.1  mrg       type = TREE_TYPE (args[1]);
   9953  1.1  mrg 
   9954  1.1  mrg       n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
   9955  1.1  mrg       huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
   9956  1.1  mrg 				   gfc_c_int_kind);
   9957  1.1  mrg       huge = fold_convert (type, huge);
   9958  1.1  mrg       args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
   9959  1.1  mrg 				 huge);
   9960  1.1  mrg       args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
   9961  1.1  mrg 				 fold_build1_loc (input_location, NEGATE_EXPR,
   9962  1.1  mrg 						  type, huge));
   9963  1.1  mrg     }
   9964  1.1  mrg 
   9965  1.1  mrg   args[1] = fold_convert (integer_type_node, args[1]);
   9966  1.1  mrg 
   9967  1.1  mrg   /* Make the function call.  */
   9968  1.1  mrg   call = build_call_expr_loc_array (input_location, decl, 2, args);
   9969  1.1  mrg   se->expr = fold_convert (TREE_TYPE (args[0]), call);
   9970  1.1  mrg }
   9971  1.1  mrg 
   9972  1.1  mrg 
   9973  1.1  mrg /* Generate code for IEEE_COPY_SIGN.  */
   9974  1.1  mrg 
   9975  1.1  mrg static void
   9976  1.1  mrg conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
   9977  1.1  mrg {
   9978  1.1  mrg   tree args[2], decl, sign;
   9979  1.1  mrg   int argprec;
   9980  1.1  mrg 
   9981  1.1  mrg   conv_ieee_function_args (se, expr, args, 2);
   9982  1.1  mrg 
   9983  1.1  mrg   /* Get the sign of the second argument.  */
   9984  1.1  mrg   sign = build_call_expr_loc (input_location,
   9985  1.1  mrg 			      builtin_decl_explicit (BUILT_IN_SIGNBIT),
   9986  1.1  mrg 			      1, args[1]);
   9987  1.1  mrg   sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   9988  1.1  mrg 			  sign, integer_zero_node);
   9989  1.1  mrg 
   9990  1.1  mrg   /* Create a value of one, with the right sign.  */
   9991  1.1  mrg   sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
   9992  1.1  mrg 			  sign,
   9993  1.1  mrg 			  fold_build1_loc (input_location, NEGATE_EXPR,
   9994  1.1  mrg 					   integer_type_node,
   9995  1.1  mrg 					   integer_one_node),
   9996  1.1  mrg 			  integer_one_node);
   9997  1.1  mrg   args[1] = fold_convert (TREE_TYPE (args[0]), sign);
   9998  1.1  mrg 
   9999  1.1  mrg   argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
   10000  1.1  mrg   decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
   10001  1.1  mrg 
   10002  1.1  mrg   se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
   10003  1.1  mrg }
   10004  1.1  mrg 
   10005  1.1  mrg 
   10006  1.1  mrg /* Generate code for IEEE_CLASS.  */
   10007  1.1  mrg 
   10008  1.1  mrg static bool
   10009  1.1  mrg conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
   10010  1.1  mrg {
   10011  1.1  mrg   tree arg, c, t1, t2, t3, t4;
   10012  1.1  mrg 
   10013  1.1  mrg   /* In GCC 12, handle inline only the powerpc64le-linux IEEE quad
   10014  1.1  mrg      real(kind=16) and nothing else.  */
   10015  1.1  mrg   if (gfc_type_abi_kind (&expr->value.function.actual->expr->ts) != 17)
   10016  1.1  mrg     return false;
   10017  1.1  mrg 
   10018  1.1  mrg   /* Convert arg, evaluate it only once.  */
   10019  1.1  mrg   conv_ieee_function_args (se, expr, &arg, 1);
   10020  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   10021  1.1  mrg 
   10022  1.1  mrg   c = build_call_expr_loc (input_location,
   10023  1.1  mrg 			   builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
   10024  1.1  mrg 			   build_int_cst (integer_type_node, IEEE_QUIET_NAN),
   10025  1.1  mrg 			   build_int_cst (integer_type_node,
   10026  1.1  mrg 					  IEEE_POSITIVE_INF),
   10027  1.1  mrg 			   build_int_cst (integer_type_node,
   10028  1.1  mrg 					  IEEE_POSITIVE_NORMAL),
   10029  1.1  mrg 			   build_int_cst (integer_type_node,
   10030  1.1  mrg 					  IEEE_POSITIVE_DENORMAL),
   10031  1.1  mrg 			   build_int_cst (integer_type_node,
   10032  1.1  mrg 					  IEEE_POSITIVE_ZERO),
   10033  1.1  mrg 			   arg);
   10034  1.1  mrg   c = gfc_evaluate_now (c, &se->pre);
   10035  1.1  mrg   t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   10036  1.1  mrg 			c, build_int_cst (integer_type_node,
   10037  1.1  mrg 					  IEEE_QUIET_NAN));
   10038  1.1  mrg   /* In GCC 12, we don't have __builtin_issignaling but above we made
   10039  1.1  mrg      sure arg is powerpc64le-linux IEEE quad real(kind=16).
   10040  1.1  mrg      When we check it is some kind of NaN by fpclassify, all we need
   10041  1.1  mrg      is check the ((__int128) 1) << 111 bit, if it is zero, it is a sNaN,
   10042  1.1  mrg      if it is set, it is a qNaN.  */
   10043  1.1  mrg   t2 = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
   10044  1.1  mrg 			build_nonstandard_integer_type (128, 1), arg);
   10045  1.1  mrg   t2 = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (t2), t2,
   10046  1.1  mrg 			build_int_cst (integer_type_node, 111));
   10047  1.1  mrg   t2 = fold_convert (integer_type_node, t2);
   10048  1.1  mrg   t2 = fold_build2_loc (input_location, BIT_AND_EXPR, integer_type_node,
   10049  1.1  mrg 			t2, integer_one_node);
   10050  1.1  mrg   t2 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   10051  1.1  mrg 			t2, build_zero_cst (TREE_TYPE (t2)));
   10052  1.1  mrg   t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   10053  1.1  mrg 			logical_type_node, t1, t2);
   10054  1.1  mrg   t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
   10055  1.1  mrg 			c, build_int_cst (integer_type_node,
   10056  1.1  mrg 					  IEEE_POSITIVE_ZERO));
   10057  1.1  mrg   t4 = build_call_expr_loc (input_location,
   10058  1.1  mrg 			    builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
   10059  1.1  mrg 			    arg);
   10060  1.1  mrg   t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   10061  1.1  mrg 			t4, build_zero_cst (TREE_TYPE (t4)));
   10062  1.1  mrg   t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
   10063  1.1  mrg 			logical_type_node, t3, t4);
   10064  1.1  mrg   int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
   10065  1.1  mrg   gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
   10066  1.1  mrg   gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
   10067  1.1  mrg   gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
   10068  1.1  mrg   gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
   10069  1.1  mrg   gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
   10070  1.1  mrg   t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
   10071  1.1  mrg 			build_int_cst (TREE_TYPE (c), s), c);
   10072  1.1  mrg   t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
   10073  1.1  mrg 			t3, t4, c);
   10074  1.1  mrg   t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
   10075  1.1  mrg 			build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
   10076  1.1  mrg 			t3);
   10077  1.1  mrg   tree type = gfc_typenode_for_spec (&expr->ts);
   10078  1.1  mrg   /* Perform a quick sanity check that the return type is
   10079  1.1  mrg      IEEE_CLASS_TYPE derived type defined in
   10080  1.1  mrg      libgfortran/ieee/ieee_arithmetic.F90
   10081  1.1  mrg      Primarily check that it is a derived type with a single
   10082  1.1  mrg      member in it.  */
   10083  1.1  mrg   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
   10084  1.1  mrg   tree field = NULL_TREE;
   10085  1.1  mrg   for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
   10086  1.1  mrg     if (TREE_CODE (f) == FIELD_DECL)
   10087  1.1  mrg       {
   10088  1.1  mrg 	gcc_assert (field == NULL_TREE);
   10089  1.1  mrg 	field = f;
   10090  1.1  mrg       }
   10091  1.1  mrg   gcc_assert (field);
   10092  1.1  mrg   t1 = fold_convert (TREE_TYPE (field), t1);
   10093  1.1  mrg   se->expr = build_constructor_single (type, field, t1);
   10094  1.1  mrg   return true;
   10095  1.1  mrg }
   10096  1.1  mrg 
   10097  1.1  mrg 
   10098  1.1  mrg /* Generate code for IEEE_VALUE.  */
   10099  1.1  mrg 
   10100  1.1  mrg static bool
   10101  1.1  mrg conv_intrinsic_ieee_value (gfc_se *se, gfc_expr *expr)
   10102  1.1  mrg {
   10103  1.1  mrg   tree args[2], arg, ret, tmp;
   10104  1.1  mrg   stmtblock_t body;
   10105  1.1  mrg 
   10106  1.1  mrg   /* In GCC 12, handle inline only the powerpc64le-linux IEEE quad
   10107  1.1  mrg      real(kind=16) and nothing else.  */
   10108  1.1  mrg   if (gfc_type_abi_kind (&expr->ts) != 17)
   10109  1.1  mrg     return false;
   10110  1.1  mrg 
   10111  1.1  mrg   /* Convert args, evaluate the second one only once.  */
   10112  1.1  mrg   conv_ieee_function_args (se, expr, args, 2);
   10113  1.1  mrg   arg = gfc_evaluate_now (args[1], &se->pre);
   10114  1.1  mrg 
   10115  1.1  mrg   tree type = TREE_TYPE (arg);
   10116  1.1  mrg   /* Perform a quick sanity check that the second argument's type is
   10117  1.1  mrg      IEEE_CLASS_TYPE derived type defined in
   10118  1.1  mrg      libgfortran/ieee/ieee_arithmetic.F90
   10119  1.1  mrg      Primarily check that it is a derived type with a single
   10120  1.1  mrg      member in it.  */
   10121  1.1  mrg   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
   10122  1.1  mrg   tree field = NULL_TREE;
   10123  1.1  mrg   for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
   10124  1.1  mrg     if (TREE_CODE (f) == FIELD_DECL)
   10125  1.1  mrg       {
   10126  1.1  mrg 	gcc_assert (field == NULL_TREE);
   10127  1.1  mrg 	field = f;
   10128  1.1  mrg       }
   10129  1.1  mrg   gcc_assert (field);
   10130  1.1  mrg   arg = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   10131  1.1  mrg 			 arg, field, NULL_TREE);
   10132  1.1  mrg   arg = gfc_evaluate_now (arg, &se->pre);
   10133  1.1  mrg 
   10134  1.1  mrg   type = gfc_typenode_for_spec (&expr->ts);
   10135  1.1  mrg   gcc_assert (TREE_CODE (type) == REAL_TYPE);
   10136  1.1  mrg   ret = gfc_create_var (type, NULL);
   10137  1.1  mrg 
   10138  1.1  mrg   gfc_init_block (&body);
   10139  1.1  mrg 
   10140  1.1  mrg   tree end_label = gfc_build_label_decl (NULL_TREE);
   10141  1.1  mrg   for (int c = IEEE_SIGNALING_NAN; c <= IEEE_POSITIVE_INF; ++c)
   10142  1.1  mrg     {
   10143  1.1  mrg       tree label = gfc_build_label_decl (NULL_TREE);
   10144  1.1  mrg       tree low = build_int_cst (TREE_TYPE (arg), c);
   10145  1.1  mrg       tmp = build_case_label (low, low, label);
   10146  1.1  mrg       gfc_add_expr_to_block (&body, tmp);
   10147  1.1  mrg 
   10148  1.1  mrg       REAL_VALUE_TYPE real;
   10149  1.1  mrg       int k;
   10150  1.1  mrg       switch (c)
   10151  1.1  mrg 	{
   10152  1.1  mrg 	case IEEE_SIGNALING_NAN:
   10153  1.1  mrg 	  real_nan (&real, "", 0, TYPE_MODE (type));
   10154  1.1  mrg 	  break;
   10155  1.1  mrg 	case IEEE_QUIET_NAN:
   10156  1.1  mrg 	  real_nan (&real, "", 1, TYPE_MODE (type));
   10157  1.1  mrg 	  break;
   10158  1.1  mrg 	case IEEE_NEGATIVE_INF:
   10159  1.1  mrg 	  real_inf (&real);
   10160  1.1  mrg 	  real = real_value_negate (&real);
   10161  1.1  mrg 	  break;
   10162  1.1  mrg 	case IEEE_NEGATIVE_NORMAL:
   10163  1.1  mrg 	  real_from_integer (&real, TYPE_MODE (type), -42, SIGNED);
   10164  1.1  mrg 	  break;
   10165  1.1  mrg 	case IEEE_NEGATIVE_DENORMAL:
   10166  1.1  mrg 	  k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
   10167  1.1  mrg 	  real_from_mpfr (&real, gfc_real_kinds[k].tiny,
   10168  1.1  mrg 			  type, GFC_RND_MODE);
   10169  1.1  mrg 	  real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
   10170  1.1  mrg 	  real = real_value_negate (&real);
   10171  1.1  mrg 	  break;
   10172  1.1  mrg 	case IEEE_NEGATIVE_ZERO:
   10173  1.1  mrg 	  real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
   10174  1.1  mrg 	  real = real_value_negate (&real);
   10175  1.1  mrg 	  break;
   10176  1.1  mrg 	case IEEE_POSITIVE_ZERO:
   10177  1.1  mrg 	  /* Make this also the default: label.  The other possibility
   10178  1.1  mrg 	     would be to add a separate default: label followed by
   10179  1.1  mrg 	     __builtin_unreachable ().  */
   10180  1.1  mrg 	  label = gfc_build_label_decl (NULL_TREE);
   10181  1.1  mrg 	  tmp = build_case_label (NULL_TREE, NULL_TREE, label);
   10182  1.1  mrg 	  gfc_add_expr_to_block (&body, tmp);
   10183  1.1  mrg 	  real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
   10184  1.1  mrg 	  break;
   10185  1.1  mrg 	case IEEE_POSITIVE_DENORMAL:
   10186  1.1  mrg 	  k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
   10187  1.1  mrg 	  real_from_mpfr (&real, gfc_real_kinds[k].tiny,
   10188  1.1  mrg 			  type, GFC_RND_MODE);
   10189  1.1  mrg 	  real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
   10190  1.1  mrg 	  break;
   10191  1.1  mrg 	case IEEE_POSITIVE_NORMAL:
   10192  1.1  mrg 	  real_from_integer (&real, TYPE_MODE (type), 42, SIGNED);
   10193  1.1  mrg 	  break;
   10194  1.1  mrg 	case IEEE_POSITIVE_INF:
   10195  1.1  mrg 	  real_inf (&real);
   10196  1.1  mrg 	  break;
   10197  1.1  mrg 	default:
   10198  1.1  mrg 	  gcc_unreachable ();
   10199  1.1  mrg 	}
   10200  1.1  mrg 
   10201  1.1  mrg       tree val = build_real (type, real);
   10202  1.1  mrg       gfc_add_modify (&body, ret, val);
   10203  1.1  mrg 
   10204  1.1  mrg       tmp = build1_v (GOTO_EXPR, end_label);
   10205  1.1  mrg       gfc_add_expr_to_block (&body, tmp);
   10206  1.1  mrg     }
   10207  1.1  mrg 
   10208  1.1  mrg   tmp = gfc_finish_block (&body);
   10209  1.1  mrg   tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, arg, tmp);
   10210  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   10211  1.1  mrg 
   10212  1.1  mrg   tmp = build1_v (LABEL_EXPR, end_label);
   10213  1.1  mrg   gfc_add_expr_to_block (&se->pre, tmp);
   10214  1.1  mrg 
   10215  1.1  mrg   se->expr = ret;
   10216  1.1  mrg   return true;
   10217  1.1  mrg }
   10218  1.1  mrg 
   10219  1.1  mrg 
   10220  1.1  mrg /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
   10221  1.1  mrg    module.  */
   10222  1.1  mrg 
   10223  1.1  mrg bool
   10224  1.1  mrg gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
   10225  1.1  mrg {
   10226  1.1  mrg   const char *name = expr->value.function.name;
   10227  1.1  mrg 
   10228  1.1  mrg   if (startswith (name, "_gfortran_ieee_is_nan"))
   10229  1.1  mrg     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
   10230  1.1  mrg   else if (startswith (name, "_gfortran_ieee_is_finite"))
   10231  1.1  mrg     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
   10232  1.1  mrg   else if (startswith (name, "_gfortran_ieee_unordered"))
   10233  1.1  mrg     conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
   10234  1.1  mrg   else if (startswith (name, "_gfortran_ieee_is_normal"))
   10235  1.1  mrg     conv_intrinsic_ieee_is_normal (se, expr);
   10236  1.1  mrg   else if (startswith (name, "_gfortran_ieee_is_negative"))
   10237  1.1  mrg     conv_intrinsic_ieee_is_negative (se, expr);
   10238  1.1  mrg   else if (startswith (name, "_gfortran_ieee_copy_sign"))
   10239  1.1  mrg     conv_intrinsic_ieee_copy_sign (se, expr);
   10240  1.1  mrg   else if (startswith (name, "_gfortran_ieee_scalb"))
   10241  1.1  mrg     conv_intrinsic_ieee_scalb (se, expr);
   10242  1.1  mrg   else if (startswith (name, "_gfortran_ieee_next_after"))
   10243  1.1  mrg     conv_intrinsic_ieee_next_after (se, expr);
   10244  1.1  mrg   else if (startswith (name, "_gfortran_ieee_rem"))
   10245  1.1  mrg     conv_intrinsic_ieee_rem (se, expr);
   10246  1.1  mrg   else if (startswith (name, "_gfortran_ieee_logb"))
   10247  1.1  mrg     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
   10248  1.1  mrg   else if (startswith (name, "_gfortran_ieee_rint"))
   10249  1.1  mrg     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
   10250  1.1  mrg   else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
   10251  1.1  mrg     return conv_intrinsic_ieee_class (se, expr);
   10252  1.1  mrg   else if (startswith (name, "ieee_value_") && ISDIGIT (name[11]))
   10253  1.1  mrg     return conv_intrinsic_ieee_value (se, expr);
   10254  1.1  mrg   else
   10255  1.1  mrg     /* It is not among the functions we translate directly.  We return
   10256  1.1  mrg        false, so a library function call is emitted.  */
   10257  1.1  mrg     return false;
   10258  1.1  mrg 
   10259  1.1  mrg   return true;
   10260  1.1  mrg }
   10261  1.1  mrg 
   10262  1.1  mrg 
   10263  1.1  mrg /* Generate a direct call to malloc() for the MALLOC intrinsic.  */
   10264  1.1  mrg 
   10265  1.1  mrg static void
   10266  1.1  mrg gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
   10267  1.1  mrg {
   10268  1.1  mrg   tree arg, res, restype;
   10269  1.1  mrg 
   10270  1.1  mrg   gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
   10271  1.1  mrg   arg = fold_convert (size_type_node, arg);
   10272  1.1  mrg   res = build_call_expr_loc (input_location,
   10273  1.1  mrg 			     builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
   10274  1.1  mrg   restype = gfc_typenode_for_spec (&expr->ts);
   10275  1.1  mrg   se->expr = fold_convert (restype, res);
   10276  1.1  mrg }
   10277  1.1  mrg 
   10278  1.1  mrg 
   10279  1.1  mrg /* Generate code for an intrinsic function.  Some map directly to library
   10280  1.1  mrg    calls, others get special handling.  In some cases the name of the function
   10281  1.1  mrg    used depends on the type specifiers.  */
   10282  1.1  mrg 
   10283  1.1  mrg void
   10284  1.1  mrg gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
   10285  1.1  mrg {
   10286  1.1  mrg   const char *name;
   10287  1.1  mrg   int lib, kind;
   10288  1.1  mrg   tree fndecl;
   10289  1.1  mrg 
   10290  1.1  mrg   name = &expr->value.function.name[2];
   10291  1.1  mrg 
   10292  1.1  mrg   if (expr->rank > 0)
   10293  1.1  mrg     {
   10294  1.1  mrg       lib = gfc_is_intrinsic_libcall (expr);
   10295  1.1  mrg       if (lib != 0)
   10296  1.1  mrg 	{
   10297  1.1  mrg 	  if (lib == 1)
   10298  1.1  mrg 	    se->ignore_optional = 1;
   10299  1.1  mrg 
   10300  1.1  mrg 	  switch (expr->value.function.isym->id)
   10301  1.1  mrg 	    {
   10302  1.1  mrg 	    case GFC_ISYM_EOSHIFT:
   10303  1.1  mrg 	    case GFC_ISYM_PACK:
   10304  1.1  mrg 	    case GFC_ISYM_RESHAPE:
   10305  1.1  mrg 	      /* For all of those the first argument specifies the type and the
   10306  1.1  mrg 		 third is optional.  */
   10307  1.1  mrg 	      conv_generic_with_optional_char_arg (se, expr, 1, 3);
   10308  1.1  mrg 	      break;
   10309  1.1  mrg 
   10310  1.1  mrg 	    case GFC_ISYM_FINDLOC:
   10311  1.1  mrg 	      gfc_conv_intrinsic_findloc (se, expr);
   10312  1.1  mrg 	      break;
   10313  1.1  mrg 
   10314  1.1  mrg 	    case GFC_ISYM_MINLOC:
   10315  1.1  mrg 	      gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
   10316  1.1  mrg 	      break;
   10317  1.1  mrg 
   10318  1.1  mrg 	    case GFC_ISYM_MAXLOC:
   10319  1.1  mrg 	      gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
   10320  1.1  mrg 	      break;
   10321  1.1  mrg 
   10322  1.1  mrg 	    default:
   10323  1.1  mrg 	      gfc_conv_intrinsic_funcall (se, expr);
   10324  1.1  mrg 	      break;
   10325  1.1  mrg 	    }
   10326  1.1  mrg 
   10327  1.1  mrg 	  return;
   10328  1.1  mrg 	}
   10329  1.1  mrg     }
   10330  1.1  mrg 
   10331  1.1  mrg   switch (expr->value.function.isym->id)
   10332  1.1  mrg     {
   10333  1.1  mrg     case GFC_ISYM_NONE:
   10334  1.1  mrg       gcc_unreachable ();
   10335  1.1  mrg 
   10336  1.1  mrg     case GFC_ISYM_REPEAT:
   10337  1.1  mrg       gfc_conv_intrinsic_repeat (se, expr);
   10338  1.1  mrg       break;
   10339  1.1  mrg 
   10340  1.1  mrg     case GFC_ISYM_TRIM:
   10341  1.1  mrg       gfc_conv_intrinsic_trim (se, expr);
   10342  1.1  mrg       break;
   10343  1.1  mrg 
   10344  1.1  mrg     case GFC_ISYM_SC_KIND:
   10345  1.1  mrg       gfc_conv_intrinsic_sc_kind (se, expr);
   10346  1.1  mrg       break;
   10347  1.1  mrg 
   10348  1.1  mrg     case GFC_ISYM_SI_KIND:
   10349  1.1  mrg       gfc_conv_intrinsic_si_kind (se, expr);
   10350  1.1  mrg       break;
   10351  1.1  mrg 
   10352  1.1  mrg     case GFC_ISYM_SR_KIND:
   10353  1.1  mrg       gfc_conv_intrinsic_sr_kind (se, expr);
   10354  1.1  mrg       break;
   10355  1.1  mrg 
   10356  1.1  mrg     case GFC_ISYM_EXPONENT:
   10357  1.1  mrg       gfc_conv_intrinsic_exponent (se, expr);
   10358  1.1  mrg       break;
   10359  1.1  mrg 
   10360  1.1  mrg     case GFC_ISYM_SCAN:
   10361  1.1  mrg       kind = expr->value.function.actual->expr->ts.kind;
   10362  1.1  mrg       if (kind == 1)
   10363  1.1  mrg        fndecl = gfor_fndecl_string_scan;
   10364  1.1  mrg       else if (kind == 4)
   10365  1.1  mrg        fndecl = gfor_fndecl_string_scan_char4;
   10366  1.1  mrg       else
   10367  1.1  mrg        gcc_unreachable ();
   10368  1.1  mrg 
   10369  1.1  mrg       gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
   10370  1.1  mrg       break;
   10371  1.1  mrg 
   10372  1.1  mrg     case GFC_ISYM_VERIFY:
   10373  1.1  mrg       kind = expr->value.function.actual->expr->ts.kind;
   10374  1.1  mrg       if (kind == 1)
   10375  1.1  mrg        fndecl = gfor_fndecl_string_verify;
   10376  1.1  mrg       else if (kind == 4)
   10377  1.1  mrg        fndecl = gfor_fndecl_string_verify_char4;
   10378  1.1  mrg       else
   10379  1.1  mrg        gcc_unreachable ();
   10380  1.1  mrg 
   10381  1.1  mrg       gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
   10382  1.1  mrg       break;
   10383  1.1  mrg 
   10384  1.1  mrg     case GFC_ISYM_ALLOCATED:
   10385  1.1  mrg       gfc_conv_allocated (se, expr);
   10386  1.1  mrg       break;
   10387  1.1  mrg 
   10388  1.1  mrg     case GFC_ISYM_ASSOCIATED:
   10389  1.1  mrg       gfc_conv_associated(se, expr);
   10390  1.1  mrg       break;
   10391  1.1  mrg 
   10392  1.1  mrg     case GFC_ISYM_SAME_TYPE_AS:
   10393  1.1  mrg       gfc_conv_same_type_as (se, expr);
   10394  1.1  mrg       break;
   10395  1.1  mrg 
   10396  1.1  mrg     case GFC_ISYM_ABS:
   10397  1.1  mrg       gfc_conv_intrinsic_abs (se, expr);
   10398  1.1  mrg       break;
   10399  1.1  mrg 
   10400  1.1  mrg     case GFC_ISYM_ADJUSTL:
   10401  1.1  mrg       if (expr->ts.kind == 1)
   10402  1.1  mrg        fndecl = gfor_fndecl_adjustl;
   10403  1.1  mrg       else if (expr->ts.kind == 4)
   10404  1.1  mrg        fndecl = gfor_fndecl_adjustl_char4;
   10405  1.1  mrg       else
   10406  1.1  mrg        gcc_unreachable ();
   10407  1.1  mrg 
   10408  1.1  mrg       gfc_conv_intrinsic_adjust (se, expr, fndecl);
   10409  1.1  mrg       break;
   10410  1.1  mrg 
   10411  1.1  mrg     case GFC_ISYM_ADJUSTR:
   10412  1.1  mrg       if (expr->ts.kind == 1)
   10413  1.1  mrg        fndecl = gfor_fndecl_adjustr;
   10414  1.1  mrg       else if (expr->ts.kind == 4)
   10415  1.1  mrg        fndecl = gfor_fndecl_adjustr_char4;
   10416  1.1  mrg       else
   10417  1.1  mrg        gcc_unreachable ();
   10418  1.1  mrg 
   10419  1.1  mrg       gfc_conv_intrinsic_adjust (se, expr, fndecl);
   10420  1.1  mrg       break;
   10421  1.1  mrg 
   10422  1.1  mrg     case GFC_ISYM_AIMAG:
   10423  1.1  mrg       gfc_conv_intrinsic_imagpart (se, expr);
   10424  1.1  mrg       break;
   10425  1.1  mrg 
   10426  1.1  mrg     case GFC_ISYM_AINT:
   10427  1.1  mrg       gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
   10428  1.1  mrg       break;
   10429  1.1  mrg 
   10430  1.1  mrg     case GFC_ISYM_ALL:
   10431  1.1  mrg       gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
   10432  1.1  mrg       break;
   10433  1.1  mrg 
   10434  1.1  mrg     case GFC_ISYM_ANINT:
   10435  1.1  mrg       gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
   10436  1.1  mrg       break;
   10437  1.1  mrg 
   10438  1.1  mrg     case GFC_ISYM_AND:
   10439  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
   10440  1.1  mrg       break;
   10441  1.1  mrg 
   10442  1.1  mrg     case GFC_ISYM_ANY:
   10443  1.1  mrg       gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
   10444  1.1  mrg       break;
   10445  1.1  mrg 
   10446  1.1  mrg     case GFC_ISYM_ACOSD:
   10447  1.1  mrg     case GFC_ISYM_ASIND:
   10448  1.1  mrg     case GFC_ISYM_ATAND:
   10449  1.1  mrg       gfc_conv_intrinsic_atrigd (se, expr, expr->value.function.isym->id);
   10450  1.1  mrg       break;
   10451  1.1  mrg 
   10452  1.1  mrg     case GFC_ISYM_COTAN:
   10453  1.1  mrg       gfc_conv_intrinsic_cotan (se, expr);
   10454  1.1  mrg       break;
   10455  1.1  mrg 
   10456  1.1  mrg     case GFC_ISYM_COTAND:
   10457  1.1  mrg       gfc_conv_intrinsic_cotand (se, expr);
   10458  1.1  mrg       break;
   10459  1.1  mrg 
   10460  1.1  mrg     case GFC_ISYM_ATAN2D:
   10461  1.1  mrg       gfc_conv_intrinsic_atan2d (se, expr);
   10462  1.1  mrg       break;
   10463  1.1  mrg 
   10464  1.1  mrg     case GFC_ISYM_BTEST:
   10465  1.1  mrg       gfc_conv_intrinsic_btest (se, expr);
   10466  1.1  mrg       break;
   10467  1.1  mrg 
   10468  1.1  mrg     case GFC_ISYM_BGE:
   10469  1.1  mrg       gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
   10470  1.1  mrg       break;
   10471  1.1  mrg 
   10472  1.1  mrg     case GFC_ISYM_BGT:
   10473  1.1  mrg       gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
   10474  1.1  mrg       break;
   10475  1.1  mrg 
   10476  1.1  mrg     case GFC_ISYM_BLE:
   10477  1.1  mrg       gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
   10478  1.1  mrg       break;
   10479  1.1  mrg 
   10480  1.1  mrg     case GFC_ISYM_BLT:
   10481  1.1  mrg       gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
   10482  1.1  mrg       break;
   10483  1.1  mrg 
   10484  1.1  mrg     case GFC_ISYM_C_ASSOCIATED:
   10485  1.1  mrg     case GFC_ISYM_C_FUNLOC:
   10486  1.1  mrg     case GFC_ISYM_C_LOC:
   10487  1.1  mrg       conv_isocbinding_function (se, expr);
   10488  1.1  mrg       break;
   10489  1.1  mrg 
   10490  1.1  mrg     case GFC_ISYM_ACHAR:
   10491  1.1  mrg     case GFC_ISYM_CHAR:
   10492  1.1  mrg       gfc_conv_intrinsic_char (se, expr);
   10493  1.1  mrg       break;
   10494  1.1  mrg 
   10495  1.1  mrg     case GFC_ISYM_CONVERSION:
   10496  1.1  mrg     case GFC_ISYM_DBLE:
   10497  1.1  mrg     case GFC_ISYM_DFLOAT:
   10498  1.1  mrg     case GFC_ISYM_FLOAT:
   10499  1.1  mrg     case GFC_ISYM_LOGICAL:
   10500  1.1  mrg     case GFC_ISYM_REAL:
   10501  1.1  mrg     case GFC_ISYM_REALPART:
   10502  1.1  mrg     case GFC_ISYM_SNGL:
   10503  1.1  mrg       gfc_conv_intrinsic_conversion (se, expr);
   10504  1.1  mrg       break;
   10505  1.1  mrg 
   10506  1.1  mrg       /* Integer conversions are handled separately to make sure we get the
   10507  1.1  mrg          correct rounding mode.  */
   10508  1.1  mrg     case GFC_ISYM_INT:
   10509  1.1  mrg     case GFC_ISYM_INT2:
   10510  1.1  mrg     case GFC_ISYM_INT8:
   10511  1.1  mrg     case GFC_ISYM_LONG:
   10512  1.1  mrg       gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
   10513  1.1  mrg       break;
   10514  1.1  mrg 
   10515  1.1  mrg     case GFC_ISYM_NINT:
   10516  1.1  mrg       gfc_conv_intrinsic_int (se, expr, RND_ROUND);
   10517  1.1  mrg       break;
   10518  1.1  mrg 
   10519  1.1  mrg     case GFC_ISYM_CEILING:
   10520  1.1  mrg       gfc_conv_intrinsic_int (se, expr, RND_CEIL);
   10521  1.1  mrg       break;
   10522  1.1  mrg 
   10523  1.1  mrg     case GFC_ISYM_FLOOR:
   10524  1.1  mrg       gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
   10525  1.1  mrg       break;
   10526  1.1  mrg 
   10527  1.1  mrg     case GFC_ISYM_MOD:
   10528  1.1  mrg       gfc_conv_intrinsic_mod (se, expr, 0);
   10529  1.1  mrg       break;
   10530  1.1  mrg 
   10531  1.1  mrg     case GFC_ISYM_MODULO:
   10532  1.1  mrg       gfc_conv_intrinsic_mod (se, expr, 1);
   10533  1.1  mrg       break;
   10534  1.1  mrg 
   10535  1.1  mrg     case GFC_ISYM_CAF_GET:
   10536  1.1  mrg       gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
   10537  1.1  mrg 				  false, NULL);
   10538  1.1  mrg       break;
   10539  1.1  mrg 
   10540  1.1  mrg     case GFC_ISYM_CMPLX:
   10541  1.1  mrg       gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
   10542  1.1  mrg       break;
   10543  1.1  mrg 
   10544  1.1  mrg     case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
   10545  1.1  mrg       gfc_conv_intrinsic_iargc (se, expr);
   10546  1.1  mrg       break;
   10547  1.1  mrg 
   10548  1.1  mrg     case GFC_ISYM_COMPLEX:
   10549  1.1  mrg       gfc_conv_intrinsic_cmplx (se, expr, 1);
   10550  1.1  mrg       break;
   10551  1.1  mrg 
   10552  1.1  mrg     case GFC_ISYM_CONJG:
   10553  1.1  mrg       gfc_conv_intrinsic_conjg (se, expr);
   10554  1.1  mrg       break;
   10555  1.1  mrg 
   10556  1.1  mrg     case GFC_ISYM_COUNT:
   10557  1.1  mrg       gfc_conv_intrinsic_count (se, expr);
   10558  1.1  mrg       break;
   10559  1.1  mrg 
   10560  1.1  mrg     case GFC_ISYM_CTIME:
   10561  1.1  mrg       gfc_conv_intrinsic_ctime (se, expr);
   10562  1.1  mrg       break;
   10563  1.1  mrg 
   10564  1.1  mrg     case GFC_ISYM_DIM:
   10565  1.1  mrg       gfc_conv_intrinsic_dim (se, expr);
   10566  1.1  mrg       break;
   10567  1.1  mrg 
   10568  1.1  mrg     case GFC_ISYM_DOT_PRODUCT:
   10569  1.1  mrg       gfc_conv_intrinsic_dot_product (se, expr);
   10570  1.1  mrg       break;
   10571  1.1  mrg 
   10572  1.1  mrg     case GFC_ISYM_DPROD:
   10573  1.1  mrg       gfc_conv_intrinsic_dprod (se, expr);
   10574  1.1  mrg       break;
   10575  1.1  mrg 
   10576  1.1  mrg     case GFC_ISYM_DSHIFTL:
   10577  1.1  mrg       gfc_conv_intrinsic_dshift (se, expr, true);
   10578  1.1  mrg       break;
   10579  1.1  mrg 
   10580  1.1  mrg     case GFC_ISYM_DSHIFTR:
   10581  1.1  mrg       gfc_conv_intrinsic_dshift (se, expr, false);
   10582  1.1  mrg       break;
   10583  1.1  mrg 
   10584  1.1  mrg     case GFC_ISYM_FDATE:
   10585  1.1  mrg       gfc_conv_intrinsic_fdate (se, expr);
   10586  1.1  mrg       break;
   10587  1.1  mrg 
   10588  1.1  mrg     case GFC_ISYM_FRACTION:
   10589  1.1  mrg       gfc_conv_intrinsic_fraction (se, expr);
   10590  1.1  mrg       break;
   10591  1.1  mrg 
   10592  1.1  mrg     case GFC_ISYM_IALL:
   10593  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
   10594  1.1  mrg       break;
   10595  1.1  mrg 
   10596  1.1  mrg     case GFC_ISYM_IAND:
   10597  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
   10598  1.1  mrg       break;
   10599  1.1  mrg 
   10600  1.1  mrg     case GFC_ISYM_IANY:
   10601  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
   10602  1.1  mrg       break;
   10603  1.1  mrg 
   10604  1.1  mrg     case GFC_ISYM_IBCLR:
   10605  1.1  mrg       gfc_conv_intrinsic_singlebitop (se, expr, 0);
   10606  1.1  mrg       break;
   10607  1.1  mrg 
   10608  1.1  mrg     case GFC_ISYM_IBITS:
   10609  1.1  mrg       gfc_conv_intrinsic_ibits (se, expr);
   10610  1.1  mrg       break;
   10611  1.1  mrg 
   10612  1.1  mrg     case GFC_ISYM_IBSET:
   10613  1.1  mrg       gfc_conv_intrinsic_singlebitop (se, expr, 1);
   10614  1.1  mrg       break;
   10615  1.1  mrg 
   10616  1.1  mrg     case GFC_ISYM_IACHAR:
   10617  1.1  mrg     case GFC_ISYM_ICHAR:
   10618  1.1  mrg       /* We assume ASCII character sequence.  */
   10619  1.1  mrg       gfc_conv_intrinsic_ichar (se, expr);
   10620  1.1  mrg       break;
   10621  1.1  mrg 
   10622  1.1  mrg     case GFC_ISYM_IARGC:
   10623  1.1  mrg       gfc_conv_intrinsic_iargc (se, expr);
   10624  1.1  mrg       break;
   10625  1.1  mrg 
   10626  1.1  mrg     case GFC_ISYM_IEOR:
   10627  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
   10628  1.1  mrg       break;
   10629  1.1  mrg 
   10630  1.1  mrg     case GFC_ISYM_INDEX:
   10631  1.1  mrg       kind = expr->value.function.actual->expr->ts.kind;
   10632  1.1  mrg       if (kind == 1)
   10633  1.1  mrg        fndecl = gfor_fndecl_string_index;
   10634  1.1  mrg       else if (kind == 4)
   10635  1.1  mrg        fndecl = gfor_fndecl_string_index_char4;
   10636  1.1  mrg       else
   10637  1.1  mrg        gcc_unreachable ();
   10638  1.1  mrg 
   10639  1.1  mrg       gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
   10640  1.1  mrg       break;
   10641  1.1  mrg 
   10642  1.1  mrg     case GFC_ISYM_IOR:
   10643  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
   10644  1.1  mrg       break;
   10645  1.1  mrg 
   10646  1.1  mrg     case GFC_ISYM_IPARITY:
   10647  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
   10648  1.1  mrg       break;
   10649  1.1  mrg 
   10650  1.1  mrg     case GFC_ISYM_IS_IOSTAT_END:
   10651  1.1  mrg       gfc_conv_has_intvalue (se, expr, LIBERROR_END);
   10652  1.1  mrg       break;
   10653  1.1  mrg 
   10654  1.1  mrg     case GFC_ISYM_IS_IOSTAT_EOR:
   10655  1.1  mrg       gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
   10656  1.1  mrg       break;
   10657  1.1  mrg 
   10658  1.1  mrg     case GFC_ISYM_IS_CONTIGUOUS:
   10659  1.1  mrg       gfc_conv_intrinsic_is_contiguous (se, expr);
   10660  1.1  mrg       break;
   10661  1.1  mrg 
   10662  1.1  mrg     case GFC_ISYM_ISNAN:
   10663  1.1  mrg       gfc_conv_intrinsic_isnan (se, expr);
   10664  1.1  mrg       break;
   10665  1.1  mrg 
   10666  1.1  mrg     case GFC_ISYM_KILL:
   10667  1.1  mrg       conv_intrinsic_kill (se, expr);
   10668  1.1  mrg       break;
   10669  1.1  mrg 
   10670  1.1  mrg     case GFC_ISYM_LSHIFT:
   10671  1.1  mrg       gfc_conv_intrinsic_shift (se, expr, false, false);
   10672  1.1  mrg       break;
   10673  1.1  mrg 
   10674  1.1  mrg     case GFC_ISYM_RSHIFT:
   10675  1.1  mrg       gfc_conv_intrinsic_shift (se, expr, true, true);
   10676  1.1  mrg       break;
   10677  1.1  mrg 
   10678  1.1  mrg     case GFC_ISYM_SHIFTA:
   10679  1.1  mrg       gfc_conv_intrinsic_shift (se, expr, true, true);
   10680  1.1  mrg       break;
   10681  1.1  mrg 
   10682  1.1  mrg     case GFC_ISYM_SHIFTL:
   10683  1.1  mrg       gfc_conv_intrinsic_shift (se, expr, false, false);
   10684  1.1  mrg       break;
   10685  1.1  mrg 
   10686  1.1  mrg     case GFC_ISYM_SHIFTR:
   10687  1.1  mrg       gfc_conv_intrinsic_shift (se, expr, true, false);
   10688  1.1  mrg       break;
   10689  1.1  mrg 
   10690  1.1  mrg     case GFC_ISYM_ISHFT:
   10691  1.1  mrg       gfc_conv_intrinsic_ishft (se, expr);
   10692  1.1  mrg       break;
   10693  1.1  mrg 
   10694  1.1  mrg     case GFC_ISYM_ISHFTC:
   10695  1.1  mrg       gfc_conv_intrinsic_ishftc (se, expr);
   10696  1.1  mrg       break;
   10697  1.1  mrg 
   10698  1.1  mrg     case GFC_ISYM_LEADZ:
   10699  1.1  mrg       gfc_conv_intrinsic_leadz (se, expr);
   10700  1.1  mrg       break;
   10701  1.1  mrg 
   10702  1.1  mrg     case GFC_ISYM_TRAILZ:
   10703  1.1  mrg       gfc_conv_intrinsic_trailz (se, expr);
   10704  1.1  mrg       break;
   10705  1.1  mrg 
   10706  1.1  mrg     case GFC_ISYM_POPCNT:
   10707  1.1  mrg       gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
   10708  1.1  mrg       break;
   10709  1.1  mrg 
   10710  1.1  mrg     case GFC_ISYM_POPPAR:
   10711  1.1  mrg       gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
   10712  1.1  mrg       break;
   10713  1.1  mrg 
   10714  1.1  mrg     case GFC_ISYM_LBOUND:
   10715  1.1  mrg       gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND);
   10716  1.1  mrg       break;
   10717  1.1  mrg 
   10718  1.1  mrg     case GFC_ISYM_LCOBOUND:
   10719  1.1  mrg       conv_intrinsic_cobound (se, expr);
   10720  1.1  mrg       break;
   10721  1.1  mrg 
   10722  1.1  mrg     case GFC_ISYM_TRANSPOSE:
   10723  1.1  mrg       /* The scalarizer has already been set up for reversed dimension access
   10724  1.1  mrg 	 order ; now we just get the argument value normally.  */
   10725  1.1  mrg       gfc_conv_expr (se, expr->value.function.actual->expr);
   10726  1.1  mrg       break;
   10727  1.1  mrg 
   10728  1.1  mrg     case GFC_ISYM_LEN:
   10729  1.1  mrg       gfc_conv_intrinsic_len (se, expr);
   10730  1.1  mrg       break;
   10731  1.1  mrg 
   10732  1.1  mrg     case GFC_ISYM_LEN_TRIM:
   10733  1.1  mrg       gfc_conv_intrinsic_len_trim (se, expr);
   10734  1.1  mrg       break;
   10735  1.1  mrg 
   10736  1.1  mrg     case GFC_ISYM_LGE:
   10737  1.1  mrg       gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
   10738  1.1  mrg       break;
   10739  1.1  mrg 
   10740  1.1  mrg     case GFC_ISYM_LGT:
   10741  1.1  mrg       gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
   10742  1.1  mrg       break;
   10743  1.1  mrg 
   10744  1.1  mrg     case GFC_ISYM_LLE:
   10745  1.1  mrg       gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
   10746  1.1  mrg       break;
   10747  1.1  mrg 
   10748  1.1  mrg     case GFC_ISYM_LLT:
   10749  1.1  mrg       gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
   10750  1.1  mrg       break;
   10751  1.1  mrg 
   10752  1.1  mrg     case GFC_ISYM_MALLOC:
   10753  1.1  mrg       gfc_conv_intrinsic_malloc (se, expr);
   10754  1.1  mrg       break;
   10755  1.1  mrg 
   10756  1.1  mrg     case GFC_ISYM_MASKL:
   10757  1.1  mrg       gfc_conv_intrinsic_mask (se, expr, 1);
   10758  1.1  mrg       break;
   10759  1.1  mrg 
   10760  1.1  mrg     case GFC_ISYM_MASKR:
   10761  1.1  mrg       gfc_conv_intrinsic_mask (se, expr, 0);
   10762  1.1  mrg       break;
   10763  1.1  mrg 
   10764  1.1  mrg     case GFC_ISYM_MAX:
   10765  1.1  mrg       if (expr->ts.type == BT_CHARACTER)
   10766  1.1  mrg 	gfc_conv_intrinsic_minmax_char (se, expr, 1);
   10767  1.1  mrg       else
   10768  1.1  mrg 	gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
   10769  1.1  mrg       break;
   10770  1.1  mrg 
   10771  1.1  mrg     case GFC_ISYM_MAXLOC:
   10772  1.1  mrg       gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
   10773  1.1  mrg       break;
   10774  1.1  mrg 
   10775  1.1  mrg     case GFC_ISYM_FINDLOC:
   10776  1.1  mrg       gfc_conv_intrinsic_findloc (se, expr);
   10777  1.1  mrg       break;
   10778  1.1  mrg 
   10779  1.1  mrg     case GFC_ISYM_MAXVAL:
   10780  1.1  mrg       gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
   10781  1.1  mrg       break;
   10782  1.1  mrg 
   10783  1.1  mrg     case GFC_ISYM_MERGE:
   10784  1.1  mrg       gfc_conv_intrinsic_merge (se, expr);
   10785  1.1  mrg       break;
   10786  1.1  mrg 
   10787  1.1  mrg     case GFC_ISYM_MERGE_BITS:
   10788  1.1  mrg       gfc_conv_intrinsic_merge_bits (se, expr);
   10789  1.1  mrg       break;
   10790  1.1  mrg 
   10791  1.1  mrg     case GFC_ISYM_MIN:
   10792  1.1  mrg       if (expr->ts.type == BT_CHARACTER)
   10793  1.1  mrg 	gfc_conv_intrinsic_minmax_char (se, expr, -1);
   10794  1.1  mrg       else
   10795  1.1  mrg 	gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
   10796  1.1  mrg       break;
   10797  1.1  mrg 
   10798  1.1  mrg     case GFC_ISYM_MINLOC:
   10799  1.1  mrg       gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
   10800  1.1  mrg       break;
   10801  1.1  mrg 
   10802  1.1  mrg     case GFC_ISYM_MINVAL:
   10803  1.1  mrg       gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
   10804  1.1  mrg       break;
   10805  1.1  mrg 
   10806  1.1  mrg     case GFC_ISYM_NEAREST:
   10807  1.1  mrg       gfc_conv_intrinsic_nearest (se, expr);
   10808  1.1  mrg       break;
   10809  1.1  mrg 
   10810  1.1  mrg     case GFC_ISYM_NORM2:
   10811  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
   10812  1.1  mrg       break;
   10813  1.1  mrg 
   10814  1.1  mrg     case GFC_ISYM_NOT:
   10815  1.1  mrg       gfc_conv_intrinsic_not (se, expr);
   10816  1.1  mrg       break;
   10817  1.1  mrg 
   10818  1.1  mrg     case GFC_ISYM_OR:
   10819  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
   10820  1.1  mrg       break;
   10821  1.1  mrg 
   10822  1.1  mrg     case GFC_ISYM_PARITY:
   10823  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
   10824  1.1  mrg       break;
   10825  1.1  mrg 
   10826  1.1  mrg     case GFC_ISYM_PRESENT:
   10827  1.1  mrg       gfc_conv_intrinsic_present (se, expr);
   10828  1.1  mrg       break;
   10829  1.1  mrg 
   10830  1.1  mrg     case GFC_ISYM_PRODUCT:
   10831  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
   10832  1.1  mrg       break;
   10833  1.1  mrg 
   10834  1.1  mrg     case GFC_ISYM_RANK:
   10835  1.1  mrg       gfc_conv_intrinsic_rank (se, expr);
   10836  1.1  mrg       break;
   10837  1.1  mrg 
   10838  1.1  mrg     case GFC_ISYM_RRSPACING:
   10839  1.1  mrg       gfc_conv_intrinsic_rrspacing (se, expr);
   10840  1.1  mrg       break;
   10841  1.1  mrg 
   10842  1.1  mrg     case GFC_ISYM_SET_EXPONENT:
   10843  1.1  mrg       gfc_conv_intrinsic_set_exponent (se, expr);
   10844  1.1  mrg       break;
   10845  1.1  mrg 
   10846  1.1  mrg     case GFC_ISYM_SCALE:
   10847  1.1  mrg       gfc_conv_intrinsic_scale (se, expr);
   10848  1.1  mrg       break;
   10849  1.1  mrg 
   10850  1.1  mrg     case GFC_ISYM_SHAPE:
   10851  1.1  mrg       gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE);
   10852  1.1  mrg       break;
   10853  1.1  mrg 
   10854  1.1  mrg     case GFC_ISYM_SIGN:
   10855  1.1  mrg       gfc_conv_intrinsic_sign (se, expr);
   10856  1.1  mrg       break;
   10857  1.1  mrg 
   10858  1.1  mrg     case GFC_ISYM_SIZE:
   10859  1.1  mrg       gfc_conv_intrinsic_size (se, expr);
   10860  1.1  mrg       break;
   10861  1.1  mrg 
   10862  1.1  mrg     case GFC_ISYM_SIZEOF:
   10863  1.1  mrg     case GFC_ISYM_C_SIZEOF:
   10864  1.1  mrg       gfc_conv_intrinsic_sizeof (se, expr);
   10865  1.1  mrg       break;
   10866  1.1  mrg 
   10867  1.1  mrg     case GFC_ISYM_STORAGE_SIZE:
   10868  1.1  mrg       gfc_conv_intrinsic_storage_size (se, expr);
   10869  1.1  mrg       break;
   10870  1.1  mrg 
   10871  1.1  mrg     case GFC_ISYM_SPACING:
   10872  1.1  mrg       gfc_conv_intrinsic_spacing (se, expr);
   10873  1.1  mrg       break;
   10874  1.1  mrg 
   10875  1.1  mrg     case GFC_ISYM_STRIDE:
   10876  1.1  mrg       conv_intrinsic_stride (se, expr);
   10877  1.1  mrg       break;
   10878  1.1  mrg 
   10879  1.1  mrg     case GFC_ISYM_SUM:
   10880  1.1  mrg       gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
   10881  1.1  mrg       break;
   10882  1.1  mrg 
   10883  1.1  mrg     case GFC_ISYM_TEAM_NUMBER:
   10884  1.1  mrg       conv_intrinsic_team_number (se, expr);
   10885  1.1  mrg       break;
   10886  1.1  mrg 
   10887  1.1  mrg     case GFC_ISYM_TRANSFER:
   10888  1.1  mrg       if (se->ss && se->ss->info->useflags)
   10889  1.1  mrg 	/* Access the previously obtained result.  */
   10890  1.1  mrg 	gfc_conv_tmp_array_ref (se);
   10891  1.1  mrg       else
   10892  1.1  mrg 	gfc_conv_intrinsic_transfer (se, expr);
   10893  1.1  mrg       break;
   10894  1.1  mrg 
   10895  1.1  mrg     case GFC_ISYM_TTYNAM:
   10896  1.1  mrg       gfc_conv_intrinsic_ttynam (se, expr);
   10897  1.1  mrg       break;
   10898  1.1  mrg 
   10899  1.1  mrg     case GFC_ISYM_UBOUND:
   10900  1.1  mrg       gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND);
   10901  1.1  mrg       break;
   10902  1.1  mrg 
   10903  1.1  mrg     case GFC_ISYM_UCOBOUND:
   10904  1.1  mrg       conv_intrinsic_cobound (se, expr);
   10905  1.1  mrg       break;
   10906  1.1  mrg 
   10907  1.1  mrg     case GFC_ISYM_XOR:
   10908  1.1  mrg       gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
   10909  1.1  mrg       break;
   10910  1.1  mrg 
   10911  1.1  mrg     case GFC_ISYM_LOC:
   10912  1.1  mrg       gfc_conv_intrinsic_loc (se, expr);
   10913  1.1  mrg       break;
   10914  1.1  mrg 
   10915  1.1  mrg     case GFC_ISYM_THIS_IMAGE:
   10916  1.1  mrg       /* For num_images() == 1, handle as LCOBOUND.  */
   10917  1.1  mrg       if (expr->value.function.actual->expr
   10918  1.1  mrg 	  && flag_coarray == GFC_FCOARRAY_SINGLE)
   10919  1.1  mrg 	conv_intrinsic_cobound (se, expr);
   10920  1.1  mrg       else
   10921  1.1  mrg 	trans_this_image (se, expr);
   10922  1.1  mrg       break;
   10923  1.1  mrg 
   10924  1.1  mrg     case GFC_ISYM_IMAGE_INDEX:
   10925  1.1  mrg       trans_image_index (se, expr);
   10926  1.1  mrg       break;
   10927  1.1  mrg 
   10928  1.1  mrg     case GFC_ISYM_IMAGE_STATUS:
   10929  1.1  mrg       conv_intrinsic_image_status (se, expr);
   10930  1.1  mrg       break;
   10931  1.1  mrg 
   10932  1.1  mrg     case GFC_ISYM_NUM_IMAGES:
   10933  1.1  mrg       trans_num_images (se, expr);
   10934  1.1  mrg       break;
   10935  1.1  mrg 
   10936  1.1  mrg     case GFC_ISYM_ACCESS:
   10937  1.1  mrg     case GFC_ISYM_CHDIR:
   10938  1.1  mrg     case GFC_ISYM_CHMOD:
   10939  1.1  mrg     case GFC_ISYM_DTIME:
   10940  1.1  mrg     case GFC_ISYM_ETIME:
   10941  1.1  mrg     case GFC_ISYM_EXTENDS_TYPE_OF:
   10942  1.1  mrg     case GFC_ISYM_FGET:
   10943  1.1  mrg     case GFC_ISYM_FGETC:
   10944  1.1  mrg     case GFC_ISYM_FNUM:
   10945  1.1  mrg     case GFC_ISYM_FPUT:
   10946  1.1  mrg     case GFC_ISYM_FPUTC:
   10947  1.1  mrg     case GFC_ISYM_FSTAT:
   10948  1.1  mrg     case GFC_ISYM_FTELL:
   10949  1.1  mrg     case GFC_ISYM_GETCWD:
   10950  1.1  mrg     case GFC_ISYM_GETGID:
   10951  1.1  mrg     case GFC_ISYM_GETPID:
   10952  1.1  mrg     case GFC_ISYM_GETUID:
   10953  1.1  mrg     case GFC_ISYM_HOSTNM:
   10954  1.1  mrg     case GFC_ISYM_IERRNO:
   10955  1.1  mrg     case GFC_ISYM_IRAND:
   10956  1.1  mrg     case GFC_ISYM_ISATTY:
   10957  1.1  mrg     case GFC_ISYM_JN2:
   10958  1.1  mrg     case GFC_ISYM_LINK:
   10959  1.1  mrg     case GFC_ISYM_LSTAT:
   10960  1.1  mrg     case GFC_ISYM_MATMUL:
   10961  1.1  mrg     case GFC_ISYM_MCLOCK:
   10962  1.1  mrg     case GFC_ISYM_MCLOCK8:
   10963  1.1  mrg     case GFC_ISYM_RAND:
   10964  1.1  mrg     case GFC_ISYM_RENAME:
   10965  1.1  mrg     case GFC_ISYM_SECOND:
   10966  1.1  mrg     case GFC_ISYM_SECNDS:
   10967  1.1  mrg     case GFC_ISYM_SIGNAL:
   10968  1.1  mrg     case GFC_ISYM_STAT:
   10969  1.1  mrg     case GFC_ISYM_SYMLNK:
   10970  1.1  mrg     case GFC_ISYM_SYSTEM:
   10971  1.1  mrg     case GFC_ISYM_TIME:
   10972  1.1  mrg     case GFC_ISYM_TIME8:
   10973  1.1  mrg     case GFC_ISYM_UMASK:
   10974  1.1  mrg     case GFC_ISYM_UNLINK:
   10975  1.1  mrg     case GFC_ISYM_YN2:
   10976  1.1  mrg       gfc_conv_intrinsic_funcall (se, expr);
   10977  1.1  mrg       break;
   10978  1.1  mrg 
   10979  1.1  mrg     case GFC_ISYM_EOSHIFT:
   10980  1.1  mrg     case GFC_ISYM_PACK:
   10981  1.1  mrg     case GFC_ISYM_RESHAPE:
   10982  1.1  mrg       /* For those, expr->rank should always be >0 and thus the if above the
   10983  1.1  mrg 	 switch should have matched.  */
   10984  1.1  mrg       gcc_unreachable ();
   10985  1.1  mrg       break;
   10986  1.1  mrg 
   10987  1.1  mrg     default:
   10988  1.1  mrg       gfc_conv_intrinsic_lib_function (se, expr);
   10989  1.1  mrg       break;
   10990  1.1  mrg     }
   10991  1.1  mrg }
   10992  1.1  mrg 
   10993  1.1  mrg 
   10994  1.1  mrg static gfc_ss *
   10995  1.1  mrg walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
   10996  1.1  mrg {
   10997  1.1  mrg   gfc_ss *arg_ss, *tmp_ss;
   10998  1.1  mrg   gfc_actual_arglist *arg;
   10999  1.1  mrg 
   11000  1.1  mrg   arg = expr->value.function.actual;
   11001  1.1  mrg 
   11002  1.1  mrg   gcc_assert (arg->expr);
   11003  1.1  mrg 
   11004  1.1  mrg   arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
   11005  1.1  mrg   gcc_assert (arg_ss != gfc_ss_terminator);
   11006  1.1  mrg 
   11007  1.1  mrg   for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
   11008  1.1  mrg     {
   11009  1.1  mrg       if (tmp_ss->info->type != GFC_SS_SCALAR
   11010  1.1  mrg 	  && tmp_ss->info->type != GFC_SS_REFERENCE)
   11011  1.1  mrg 	{
   11012  1.1  mrg 	  gcc_assert (tmp_ss->dimen == 2);
   11013  1.1  mrg 
   11014  1.1  mrg 	  /* We just invert dimensions.  */
   11015  1.1  mrg 	  std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
   11016  1.1  mrg 	}
   11017  1.1  mrg 
   11018  1.1  mrg       /* Stop when tmp_ss points to the last valid element of the chain...  */
   11019  1.1  mrg       if (tmp_ss->next == gfc_ss_terminator)
   11020  1.1  mrg 	break;
   11021  1.1  mrg     }
   11022  1.1  mrg 
   11023  1.1  mrg   /* ... so that we can attach the rest of the chain to it.  */
   11024  1.1  mrg   tmp_ss->next = ss;
   11025  1.1  mrg 
   11026  1.1  mrg   return arg_ss;
   11027  1.1  mrg }
   11028  1.1  mrg 
   11029  1.1  mrg 
   11030  1.1  mrg /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
   11031  1.1  mrg    This has the side effect of reversing the nested list, so there is no
   11032  1.1  mrg    need to call gfc_reverse_ss on it (the given list is assumed not to be
   11033  1.1  mrg    reversed yet).   */
   11034  1.1  mrg 
   11035  1.1  mrg static gfc_ss *
   11036  1.1  mrg nest_loop_dimension (gfc_ss *ss, int dim)
   11037  1.1  mrg {
   11038  1.1  mrg   int ss_dim, i;
   11039  1.1  mrg   gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
   11040  1.1  mrg   gfc_loopinfo *new_loop;
   11041  1.1  mrg 
   11042  1.1  mrg   gcc_assert (ss != gfc_ss_terminator);
   11043  1.1  mrg 
   11044  1.1  mrg   for (; ss != gfc_ss_terminator; ss = ss->next)
   11045  1.1  mrg     {
   11046  1.1  mrg       new_ss = gfc_get_ss ();
   11047  1.1  mrg       new_ss->next = prev_ss;
   11048  1.1  mrg       new_ss->parent = ss;
   11049  1.1  mrg       new_ss->info = ss->info;
   11050  1.1  mrg       new_ss->info->refcount++;
   11051  1.1  mrg       if (ss->dimen != 0)
   11052  1.1  mrg 	{
   11053  1.1  mrg 	  gcc_assert (ss->info->type != GFC_SS_SCALAR
   11054  1.1  mrg 		      && ss->info->type != GFC_SS_REFERENCE);
   11055  1.1  mrg 
   11056  1.1  mrg 	  new_ss->dimen = 1;
   11057  1.1  mrg 	  new_ss->dim[0] = ss->dim[dim];
   11058  1.1  mrg 
   11059  1.1  mrg 	  gcc_assert (dim < ss->dimen);
   11060  1.1  mrg 
   11061  1.1  mrg 	  ss_dim = --ss->dimen;
   11062  1.1  mrg 	  for (i = dim; i < ss_dim; i++)
   11063  1.1  mrg 	    ss->dim[i] = ss->dim[i + 1];
   11064  1.1  mrg 
   11065  1.1  mrg 	  ss->dim[ss_dim] = 0;
   11066  1.1  mrg 	}
   11067  1.1  mrg       prev_ss = new_ss;
   11068  1.1  mrg 
   11069  1.1  mrg       if (ss->nested_ss)
   11070  1.1  mrg 	{
   11071  1.1  mrg 	  ss->nested_ss->parent = new_ss;
   11072  1.1  mrg 	  new_ss->nested_ss = ss->nested_ss;
   11073  1.1  mrg 	}
   11074  1.1  mrg       ss->nested_ss = new_ss;
   11075  1.1  mrg     }
   11076  1.1  mrg 
   11077  1.1  mrg   new_loop = gfc_get_loopinfo ();
   11078  1.1  mrg   gfc_init_loopinfo (new_loop);
   11079  1.1  mrg 
   11080  1.1  mrg   gcc_assert (prev_ss != NULL);
   11081  1.1  mrg   gcc_assert (prev_ss != gfc_ss_terminator);
   11082  1.1  mrg   gfc_add_ss_to_loop (new_loop, prev_ss);
   11083  1.1  mrg   return new_ss->parent;
   11084  1.1  mrg }
   11085  1.1  mrg 
   11086  1.1  mrg 
   11087  1.1  mrg /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
   11088  1.1  mrg    is to be inlined.  */
   11089  1.1  mrg 
   11090  1.1  mrg static gfc_ss *
   11091  1.1  mrg walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
   11092  1.1  mrg {
   11093  1.1  mrg   gfc_ss *tmp_ss, *tail, *array_ss;
   11094  1.1  mrg   gfc_actual_arglist *arg1, *arg2, *arg3;
   11095  1.1  mrg   int sum_dim;
   11096  1.1  mrg   bool scalar_mask = false;
   11097  1.1  mrg 
   11098  1.1  mrg   /* The rank of the result will be determined later.  */
   11099  1.1  mrg   arg1 = expr->value.function.actual;
   11100  1.1  mrg   arg2 = arg1->next;
   11101  1.1  mrg   arg3 = arg2->next;
   11102  1.1  mrg   gcc_assert (arg3 != NULL);
   11103  1.1  mrg 
   11104  1.1  mrg   if (expr->rank == 0)
   11105  1.1  mrg     return ss;
   11106  1.1  mrg 
   11107  1.1  mrg   tmp_ss = gfc_ss_terminator;
   11108  1.1  mrg 
   11109  1.1  mrg   if (arg3->expr)
   11110  1.1  mrg     {
   11111  1.1  mrg       gfc_ss *mask_ss;
   11112  1.1  mrg 
   11113  1.1  mrg       mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
   11114  1.1  mrg       if (mask_ss == tmp_ss)
   11115  1.1  mrg 	scalar_mask = 1;
   11116  1.1  mrg 
   11117  1.1  mrg       tmp_ss = mask_ss;
   11118  1.1  mrg     }
   11119  1.1  mrg 
   11120  1.1  mrg   array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
   11121  1.1  mrg   gcc_assert (array_ss != tmp_ss);
   11122  1.1  mrg 
   11123  1.1  mrg   /* Odd thing: If the mask is scalar, it is used by the frontend after
   11124  1.1  mrg      the array (to make an if around the nested loop). Thus it shall
   11125  1.1  mrg      be after array_ss once the gfc_ss list is reversed.  */
   11126  1.1  mrg   if (scalar_mask)
   11127  1.1  mrg     tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
   11128  1.1  mrg   else
   11129  1.1  mrg     tmp_ss = array_ss;
   11130  1.1  mrg 
   11131  1.1  mrg   /* "Hide" the dimension on which we will sum in the first arg's scalarization
   11132  1.1  mrg      chain.  */
   11133  1.1  mrg   sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
   11134  1.1  mrg   tail = nest_loop_dimension (tmp_ss, sum_dim);
   11135  1.1  mrg   tail->next = ss;
   11136  1.1  mrg 
   11137  1.1  mrg   return tmp_ss;
   11138  1.1  mrg }
   11139  1.1  mrg 
   11140  1.1  mrg 
   11141  1.1  mrg static gfc_ss *
   11142  1.1  mrg walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
   11143  1.1  mrg {
   11144  1.1  mrg 
   11145  1.1  mrg   switch (expr->value.function.isym->id)
   11146  1.1  mrg     {
   11147  1.1  mrg       case GFC_ISYM_PRODUCT:
   11148  1.1  mrg       case GFC_ISYM_SUM:
   11149  1.1  mrg 	return walk_inline_intrinsic_arith (ss, expr);
   11150  1.1  mrg 
   11151  1.1  mrg       case GFC_ISYM_TRANSPOSE:
   11152  1.1  mrg 	return walk_inline_intrinsic_transpose (ss, expr);
   11153  1.1  mrg 
   11154  1.1  mrg       default:
   11155  1.1  mrg 	gcc_unreachable ();
   11156  1.1  mrg     }
   11157  1.1  mrg   gcc_unreachable ();
   11158  1.1  mrg }
   11159  1.1  mrg 
   11160  1.1  mrg 
   11161  1.1  mrg /* This generates code to execute before entering the scalarization loop.
   11162  1.1  mrg    Currently does nothing.  */
   11163  1.1  mrg 
   11164  1.1  mrg void
   11165  1.1  mrg gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
   11166  1.1  mrg {
   11167  1.1  mrg   switch (ss->info->expr->value.function.isym->id)
   11168  1.1  mrg     {
   11169  1.1  mrg     case GFC_ISYM_UBOUND:
   11170  1.1  mrg     case GFC_ISYM_LBOUND:
   11171  1.1  mrg     case GFC_ISYM_UCOBOUND:
   11172  1.1  mrg     case GFC_ISYM_LCOBOUND:
   11173  1.1  mrg     case GFC_ISYM_THIS_IMAGE:
   11174  1.1  mrg     case GFC_ISYM_SHAPE:
   11175  1.1  mrg       break;
   11176  1.1  mrg 
   11177  1.1  mrg     default:
   11178  1.1  mrg       gcc_unreachable ();
   11179  1.1  mrg     }
   11180  1.1  mrg }
   11181  1.1  mrg 
   11182  1.1  mrg 
   11183  1.1  mrg /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
   11184  1.1  mrg    one parameter are expanded into code inside the scalarization loop.  */
   11185  1.1  mrg 
   11186  1.1  mrg static gfc_ss *
   11187  1.1  mrg gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
   11188  1.1  mrg {
   11189  1.1  mrg   if (expr->value.function.actual->expr->ts.type == BT_CLASS)
   11190  1.1  mrg     gfc_add_class_array_ref (expr->value.function.actual->expr);
   11191  1.1  mrg 
   11192  1.1  mrg   /* The two argument version returns a scalar.  */
   11193  1.1  mrg   if (expr->value.function.isym->id != GFC_ISYM_SHAPE
   11194  1.1  mrg       && expr->value.function.actual->next->expr)
   11195  1.1  mrg     return ss;
   11196  1.1  mrg 
   11197  1.1  mrg   return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
   11198  1.1  mrg }
   11199  1.1  mrg 
   11200  1.1  mrg 
   11201  1.1  mrg /* Walk an intrinsic array libcall.  */
   11202  1.1  mrg 
   11203  1.1  mrg static gfc_ss *
   11204  1.1  mrg gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
   11205  1.1  mrg {
   11206  1.1  mrg   gcc_assert (expr->rank > 0);
   11207  1.1  mrg   return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
   11208  1.1  mrg }
   11209  1.1  mrg 
   11210  1.1  mrg 
   11211  1.1  mrg /* Return whether the function call expression EXPR will be expanded
   11212  1.1  mrg    inline by gfc_conv_intrinsic_function.  */
   11213  1.1  mrg 
   11214  1.1  mrg bool
   11215  1.1  mrg gfc_inline_intrinsic_function_p (gfc_expr *expr)
   11216  1.1  mrg {
   11217  1.1  mrg   gfc_actual_arglist *args, *dim_arg, *mask_arg;
   11218  1.1  mrg   gfc_expr *maskexpr;
   11219  1.1  mrg 
   11220  1.1  mrg   if (!expr->value.function.isym)
   11221  1.1  mrg     return false;
   11222  1.1  mrg 
   11223  1.1  mrg   switch (expr->value.function.isym->id)
   11224  1.1  mrg     {
   11225  1.1  mrg     case GFC_ISYM_PRODUCT:
   11226  1.1  mrg     case GFC_ISYM_SUM:
   11227  1.1  mrg       /* Disable inline expansion if code size matters.  */
   11228  1.1  mrg       if (optimize_size)
   11229  1.1  mrg 	return false;
   11230  1.1  mrg 
   11231  1.1  mrg       args = expr->value.function.actual;
   11232  1.1  mrg       dim_arg = args->next;
   11233  1.1  mrg 
   11234  1.1  mrg       /* We need to be able to subset the SUM argument at compile-time.  */
   11235  1.1  mrg       if (dim_arg->expr && dim_arg->expr->expr_type != EXPR_CONSTANT)
   11236  1.1  mrg 	return false;
   11237  1.1  mrg 
   11238  1.1  mrg       /* FIXME: If MASK is optional for a more than two-dimensional
   11239  1.1  mrg 	 argument, the scalarizer gets confused if the mask is
   11240  1.1  mrg 	 absent.  See PR 82995.  For now, fall back to the library
   11241  1.1  mrg 	 function.  */
   11242  1.1  mrg 
   11243  1.1  mrg       mask_arg = dim_arg->next;
   11244  1.1  mrg       maskexpr = mask_arg->expr;
   11245  1.1  mrg 
   11246  1.1  mrg       if (expr->rank > 0 && maskexpr && maskexpr->expr_type == EXPR_VARIABLE
   11247  1.1  mrg 	  && maskexpr->symtree->n.sym->attr.dummy
   11248  1.1  mrg 	  && maskexpr->symtree->n.sym->attr.optional)
   11249  1.1  mrg 	return false;
   11250  1.1  mrg 
   11251  1.1  mrg       return true;
   11252  1.1  mrg 
   11253  1.1  mrg     case GFC_ISYM_TRANSPOSE:
   11254  1.1  mrg       return true;
   11255  1.1  mrg 
   11256  1.1  mrg     default:
   11257  1.1  mrg       return false;
   11258  1.1  mrg     }
   11259  1.1  mrg }
   11260  1.1  mrg 
   11261  1.1  mrg 
   11262  1.1  mrg /* Returns nonzero if the specified intrinsic function call maps directly to
   11263  1.1  mrg    an external library call.  Should only be used for functions that return
   11264  1.1  mrg    arrays.  */
   11265  1.1  mrg 
   11266  1.1  mrg int
   11267  1.1  mrg gfc_is_intrinsic_libcall (gfc_expr * expr)
   11268  1.1  mrg {
   11269  1.1  mrg   gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
   11270  1.1  mrg   gcc_assert (expr->rank > 0);
   11271  1.1  mrg 
   11272  1.1  mrg   if (gfc_inline_intrinsic_function_p (expr))
   11273  1.1  mrg     return 0;
   11274  1.1  mrg 
   11275  1.1  mrg   switch (expr->value.function.isym->id)
   11276  1.1  mrg     {
   11277  1.1  mrg     case GFC_ISYM_ALL:
   11278  1.1  mrg     case GFC_ISYM_ANY:
   11279  1.1  mrg     case GFC_ISYM_COUNT:
   11280  1.1  mrg     case GFC_ISYM_FINDLOC:
   11281  1.1  mrg     case GFC_ISYM_JN2:
   11282  1.1  mrg     case GFC_ISYM_IANY:
   11283  1.1  mrg     case GFC_ISYM_IALL:
   11284  1.1  mrg     case GFC_ISYM_IPARITY:
   11285  1.1  mrg     case GFC_ISYM_MATMUL:
   11286  1.1  mrg     case GFC_ISYM_MAXLOC:
   11287  1.1  mrg     case GFC_ISYM_MAXVAL:
   11288  1.1  mrg     case GFC_ISYM_MINLOC:
   11289  1.1  mrg     case GFC_ISYM_MINVAL:
   11290  1.1  mrg     case GFC_ISYM_NORM2:
   11291  1.1  mrg     case GFC_ISYM_PARITY:
   11292  1.1  mrg     case GFC_ISYM_PRODUCT:
   11293  1.1  mrg     case GFC_ISYM_SUM:
   11294  1.1  mrg     case GFC_ISYM_SPREAD:
   11295  1.1  mrg     case GFC_ISYM_YN2:
   11296  1.1  mrg       /* Ignore absent optional parameters.  */
   11297  1.1  mrg       return 1;
   11298  1.1  mrg 
   11299  1.1  mrg     case GFC_ISYM_CSHIFT:
   11300  1.1  mrg     case GFC_ISYM_EOSHIFT:
   11301  1.1  mrg     case GFC_ISYM_GET_TEAM:
   11302  1.1  mrg     case GFC_ISYM_FAILED_IMAGES:
   11303  1.1  mrg     case GFC_ISYM_STOPPED_IMAGES:
   11304  1.1  mrg     case GFC_ISYM_PACK:
   11305  1.1  mrg     case GFC_ISYM_RESHAPE:
   11306  1.1  mrg     case GFC_ISYM_UNPACK:
   11307  1.1  mrg       /* Pass absent optional parameters.  */
   11308  1.1  mrg       return 2;
   11309  1.1  mrg 
   11310  1.1  mrg     default:
   11311  1.1  mrg       return 0;
   11312  1.1  mrg     }
   11313  1.1  mrg }
   11314  1.1  mrg 
   11315  1.1  mrg /* Walk an intrinsic function.  */
   11316  1.1  mrg gfc_ss *
   11317  1.1  mrg gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
   11318  1.1  mrg 			     gfc_intrinsic_sym * isym)
   11319  1.1  mrg {
   11320  1.1  mrg   gcc_assert (isym);
   11321  1.1  mrg 
   11322  1.1  mrg   if (isym->elemental)
   11323  1.1  mrg     return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
   11324  1.1  mrg 					     expr->value.function.isym,
   11325  1.1  mrg 					     GFC_SS_SCALAR);
   11326  1.1  mrg 
   11327  1.1  mrg   if (expr->rank == 0)
   11328  1.1  mrg     return ss;
   11329  1.1  mrg 
   11330  1.1  mrg   if (gfc_inline_intrinsic_function_p (expr))
   11331  1.1  mrg     return walk_inline_intrinsic_function (ss, expr);
   11332  1.1  mrg 
   11333  1.1  mrg   if (gfc_is_intrinsic_libcall (expr))
   11334  1.1  mrg     return gfc_walk_intrinsic_libfunc (ss, expr);
   11335  1.1  mrg 
   11336  1.1  mrg   /* Special cases.  */
   11337  1.1  mrg   switch (isym->id)
   11338  1.1  mrg     {
   11339  1.1  mrg     case GFC_ISYM_LBOUND:
   11340  1.1  mrg     case GFC_ISYM_LCOBOUND:
   11341  1.1  mrg     case GFC_ISYM_UBOUND:
   11342  1.1  mrg     case GFC_ISYM_UCOBOUND:
   11343  1.1  mrg     case GFC_ISYM_THIS_IMAGE:
   11344  1.1  mrg     case GFC_ISYM_SHAPE:
   11345  1.1  mrg       return gfc_walk_intrinsic_bound (ss, expr);
   11346  1.1  mrg 
   11347  1.1  mrg     case GFC_ISYM_TRANSFER:
   11348  1.1  mrg     case GFC_ISYM_CAF_GET:
   11349  1.1  mrg       return gfc_walk_intrinsic_libfunc (ss, expr);
   11350  1.1  mrg 
   11351  1.1  mrg     default:
   11352  1.1  mrg       /* This probably meant someone forgot to add an intrinsic to the above
   11353  1.1  mrg          list(s) when they implemented it, or something's gone horribly
   11354  1.1  mrg 	 wrong.  */
   11355  1.1  mrg       gcc_unreachable ();
   11356  1.1  mrg     }
   11357  1.1  mrg }
   11358  1.1  mrg 
   11359  1.1  mrg static tree
   11360  1.1  mrg conv_co_collective (gfc_code *code)
   11361  1.1  mrg {
   11362  1.1  mrg   gfc_se argse;
   11363  1.1  mrg   stmtblock_t block, post_block;
   11364  1.1  mrg   tree fndecl, array = NULL_TREE, strlen, image_index, stat, errmsg, errmsg_len;
   11365  1.1  mrg   gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
   11366  1.1  mrg 
   11367  1.1  mrg   gfc_start_block (&block);
   11368  1.1  mrg   gfc_init_block (&post_block);
   11369  1.1  mrg 
   11370  1.1  mrg   if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
   11371  1.1  mrg     {
   11372  1.1  mrg       opr_expr = code->ext.actual->next->expr;
   11373  1.1  mrg       image_idx_expr = code->ext.actual->next->next->expr;
   11374  1.1  mrg       stat_expr = code->ext.actual->next->next->next->expr;
   11375  1.1  mrg       errmsg_expr = code->ext.actual->next->next->next->next->expr;
   11376  1.1  mrg     }
   11377  1.1  mrg   else
   11378  1.1  mrg     {
   11379  1.1  mrg       opr_expr = NULL;
   11380  1.1  mrg       image_idx_expr = code->ext.actual->next->expr;
   11381  1.1  mrg       stat_expr = code->ext.actual->next->next->expr;
   11382  1.1  mrg       errmsg_expr = code->ext.actual->next->next->next->expr;
   11383  1.1  mrg     }
   11384  1.1  mrg 
   11385  1.1  mrg   /* stat.  */
   11386  1.1  mrg   if (stat_expr)
   11387  1.1  mrg     {
   11388  1.1  mrg       gfc_init_se (&argse, NULL);
   11389  1.1  mrg       gfc_conv_expr (&argse, stat_expr);
   11390  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11391  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11392  1.1  mrg       stat = argse.expr;
   11393  1.1  mrg       if (flag_coarray != GFC_FCOARRAY_SINGLE)
   11394  1.1  mrg 	stat = gfc_build_addr_expr (NULL_TREE, stat);
   11395  1.1  mrg     }
   11396  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_SINGLE)
   11397  1.1  mrg     stat = NULL_TREE;
   11398  1.1  mrg   else
   11399  1.1  mrg     stat = null_pointer_node;
   11400  1.1  mrg 
   11401  1.1  mrg   /* Early exit for GFC_FCOARRAY_SINGLE.  */
   11402  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_SINGLE)
   11403  1.1  mrg     {
   11404  1.1  mrg       if (stat != NULL_TREE)
   11405  1.1  mrg 	{
   11406  1.1  mrg 	  /* For optional stats, check the pointer is valid before zero'ing.  */
   11407  1.1  mrg 	  if (gfc_expr_attr (stat_expr).optional)
   11408  1.1  mrg 	    {
   11409  1.1  mrg 	      tree tmp;
   11410  1.1  mrg 	      stmtblock_t ass_block;
   11411  1.1  mrg 	      gfc_start_block (&ass_block);
   11412  1.1  mrg 	      gfc_add_modify (&ass_block, stat,
   11413  1.1  mrg 			      fold_convert (TREE_TYPE (stat),
   11414  1.1  mrg 					    integer_zero_node));
   11415  1.1  mrg 	      tmp = fold_build2 (NE_EXPR, logical_type_node,
   11416  1.1  mrg 				 gfc_build_addr_expr (NULL_TREE, stat),
   11417  1.1  mrg 				 null_pointer_node);
   11418  1.1  mrg 	      tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
   11419  1.1  mrg 				 gfc_finish_block (&ass_block),
   11420  1.1  mrg 				 build_empty_stmt (input_location));
   11421  1.1  mrg 	      gfc_add_expr_to_block (&block, tmp);
   11422  1.1  mrg 	    }
   11423  1.1  mrg 	  else
   11424  1.1  mrg 	    gfc_add_modify (&block, stat,
   11425  1.1  mrg 			    fold_convert (TREE_TYPE (stat), integer_zero_node));
   11426  1.1  mrg 	}
   11427  1.1  mrg       return gfc_finish_block (&block);
   11428  1.1  mrg     }
   11429  1.1  mrg 
   11430  1.1  mrg   gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED
   11431  1.1  mrg     ? code->ext.actual->expr->ts.u.derived : NULL;
   11432  1.1  mrg 
   11433  1.1  mrg   /* Handle the array.  */
   11434  1.1  mrg   gfc_init_se (&argse, NULL);
   11435  1.1  mrg   if (!derived || !derived->attr.alloc_comp
   11436  1.1  mrg       || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST)
   11437  1.1  mrg     {
   11438  1.1  mrg       if (code->ext.actual->expr->rank == 0)
   11439  1.1  mrg 	{
   11440  1.1  mrg 	  symbol_attribute attr;
   11441  1.1  mrg 	  gfc_clear_attr (&attr);
   11442  1.1  mrg 	  gfc_init_se (&argse, NULL);
   11443  1.1  mrg 	  gfc_conv_expr (&argse, code->ext.actual->expr);
   11444  1.1  mrg 	  gfc_add_block_to_block (&block, &argse.pre);
   11445  1.1  mrg 	  gfc_add_block_to_block (&post_block, &argse.post);
   11446  1.1  mrg 	  array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
   11447  1.1  mrg 	  array = gfc_build_addr_expr (NULL_TREE, array);
   11448  1.1  mrg 	}
   11449  1.1  mrg       else
   11450  1.1  mrg 	{
   11451  1.1  mrg 	  argse.want_pointer = 1;
   11452  1.1  mrg 	  gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
   11453  1.1  mrg 	  array = argse.expr;
   11454  1.1  mrg 	}
   11455  1.1  mrg     }
   11456  1.1  mrg 
   11457  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11458  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11459  1.1  mrg 
   11460  1.1  mrg   if (code->ext.actual->expr->ts.type == BT_CHARACTER)
   11461  1.1  mrg     strlen = argse.string_length;
   11462  1.1  mrg   else
   11463  1.1  mrg     strlen = integer_zero_node;
   11464  1.1  mrg 
   11465  1.1  mrg   /* image_index.  */
   11466  1.1  mrg   if (image_idx_expr)
   11467  1.1  mrg     {
   11468  1.1  mrg       gfc_init_se (&argse, NULL);
   11469  1.1  mrg       gfc_conv_expr (&argse, image_idx_expr);
   11470  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11471  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11472  1.1  mrg       image_index = fold_convert (integer_type_node, argse.expr);
   11473  1.1  mrg     }
   11474  1.1  mrg   else
   11475  1.1  mrg     image_index = integer_zero_node;
   11476  1.1  mrg 
   11477  1.1  mrg   /* errmsg.  */
   11478  1.1  mrg   if (errmsg_expr)
   11479  1.1  mrg     {
   11480  1.1  mrg       gfc_init_se (&argse, NULL);
   11481  1.1  mrg       gfc_conv_expr (&argse, errmsg_expr);
   11482  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11483  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11484  1.1  mrg       errmsg = argse.expr;
   11485  1.1  mrg       errmsg_len = fold_convert (size_type_node, argse.string_length);
   11486  1.1  mrg     }
   11487  1.1  mrg   else
   11488  1.1  mrg     {
   11489  1.1  mrg       errmsg = null_pointer_node;
   11490  1.1  mrg       errmsg_len = build_zero_cst (size_type_node);
   11491  1.1  mrg     }
   11492  1.1  mrg 
   11493  1.1  mrg   /* Generate the function call.  */
   11494  1.1  mrg   switch (code->resolved_isym->id)
   11495  1.1  mrg     {
   11496  1.1  mrg     case GFC_ISYM_CO_BROADCAST:
   11497  1.1  mrg       fndecl = gfor_fndecl_co_broadcast;
   11498  1.1  mrg       break;
   11499  1.1  mrg     case GFC_ISYM_CO_MAX:
   11500  1.1  mrg       fndecl = gfor_fndecl_co_max;
   11501  1.1  mrg       break;
   11502  1.1  mrg     case GFC_ISYM_CO_MIN:
   11503  1.1  mrg       fndecl = gfor_fndecl_co_min;
   11504  1.1  mrg       break;
   11505  1.1  mrg     case GFC_ISYM_CO_REDUCE:
   11506  1.1  mrg       fndecl = gfor_fndecl_co_reduce;
   11507  1.1  mrg       break;
   11508  1.1  mrg     case GFC_ISYM_CO_SUM:
   11509  1.1  mrg       fndecl = gfor_fndecl_co_sum;
   11510  1.1  mrg       break;
   11511  1.1  mrg     default:
   11512  1.1  mrg       gcc_unreachable ();
   11513  1.1  mrg     }
   11514  1.1  mrg 
   11515  1.1  mrg   if (derived && derived->attr.alloc_comp
   11516  1.1  mrg       && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
   11517  1.1  mrg     /* The derived type has the attribute 'alloc_comp'.  */
   11518  1.1  mrg     {
   11519  1.1  mrg       tree tmp = gfc_bcast_alloc_comp (derived, code->ext.actual->expr,
   11520  1.1  mrg 				       code->ext.actual->expr->rank,
   11521  1.1  mrg 				       image_index, stat, errmsg, errmsg_len);
   11522  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   11523  1.1  mrg     }
   11524  1.1  mrg   else
   11525  1.1  mrg     {
   11526  1.1  mrg       if (code->resolved_isym->id == GFC_ISYM_CO_SUM
   11527  1.1  mrg 	  || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
   11528  1.1  mrg 	fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
   11529  1.1  mrg 				      image_index, stat, errmsg, errmsg_len);
   11530  1.1  mrg       else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
   11531  1.1  mrg 	fndecl = build_call_expr_loc (input_location, fndecl, 6, array,
   11532  1.1  mrg 				      image_index, stat, errmsg,
   11533  1.1  mrg 				      strlen, errmsg_len);
   11534  1.1  mrg       else
   11535  1.1  mrg 	{
   11536  1.1  mrg 	  tree opr, opr_flags;
   11537  1.1  mrg 
   11538  1.1  mrg 	  // FIXME: Handle TS29113's bind(C) strings with descriptor.
   11539  1.1  mrg 	  int opr_flag_int;
   11540  1.1  mrg 	  if (gfc_is_proc_ptr_comp (opr_expr))
   11541  1.1  mrg 	    {
   11542  1.1  mrg 	      gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
   11543  1.1  mrg 	      opr_flag_int = sym->attr.dimension
   11544  1.1  mrg 		|| (sym->ts.type == BT_CHARACTER
   11545  1.1  mrg 		    && !sym->attr.is_bind_c)
   11546  1.1  mrg 		? GFC_CAF_BYREF : 0;
   11547  1.1  mrg 	      opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
   11548  1.1  mrg 		&& !sym->attr.is_bind_c
   11549  1.1  mrg 		? GFC_CAF_HIDDENLEN : 0;
   11550  1.1  mrg 	      opr_flag_int |= sym->formal->sym->attr.value
   11551  1.1  mrg 		? GFC_CAF_ARG_VALUE : 0;
   11552  1.1  mrg 	    }
   11553  1.1  mrg 	  else
   11554  1.1  mrg 	    {
   11555  1.1  mrg 	      opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
   11556  1.1  mrg 		? GFC_CAF_BYREF : 0;
   11557  1.1  mrg 	      opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
   11558  1.1  mrg 		&& !opr_expr->symtree->n.sym->attr.is_bind_c
   11559  1.1  mrg 		? GFC_CAF_HIDDENLEN : 0;
   11560  1.1  mrg 	      opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
   11561  1.1  mrg 		? GFC_CAF_ARG_VALUE : 0;
   11562  1.1  mrg 	    }
   11563  1.1  mrg 	  opr_flags = build_int_cst (integer_type_node, opr_flag_int);
   11564  1.1  mrg 	  gfc_conv_expr (&argse, opr_expr);
   11565  1.1  mrg 	  opr = argse.expr;
   11566  1.1  mrg 	  fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr,
   11567  1.1  mrg 					opr_flags, image_index, stat, errmsg,
   11568  1.1  mrg 					strlen, errmsg_len);
   11569  1.1  mrg 	}
   11570  1.1  mrg     }
   11571  1.1  mrg 
   11572  1.1  mrg   gfc_add_expr_to_block (&block, fndecl);
   11573  1.1  mrg   gfc_add_block_to_block (&block, &post_block);
   11574  1.1  mrg 
   11575  1.1  mrg   return gfc_finish_block (&block);
   11576  1.1  mrg }
   11577  1.1  mrg 
   11578  1.1  mrg 
   11579  1.1  mrg static tree
   11580  1.1  mrg conv_intrinsic_atomic_op (gfc_code *code)
   11581  1.1  mrg {
   11582  1.1  mrg   gfc_se argse;
   11583  1.1  mrg   tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
   11584  1.1  mrg   stmtblock_t block, post_block;
   11585  1.1  mrg   gfc_expr *atom_expr = code->ext.actual->expr;
   11586  1.1  mrg   gfc_expr *stat_expr;
   11587  1.1  mrg   built_in_function fn;
   11588  1.1  mrg 
   11589  1.1  mrg   if (atom_expr->expr_type == EXPR_FUNCTION
   11590  1.1  mrg       && atom_expr->value.function.isym
   11591  1.1  mrg       && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
   11592  1.1  mrg     atom_expr = atom_expr->value.function.actual->expr;
   11593  1.1  mrg 
   11594  1.1  mrg   gfc_start_block (&block);
   11595  1.1  mrg   gfc_init_block (&post_block);
   11596  1.1  mrg 
   11597  1.1  mrg   gfc_init_se (&argse, NULL);
   11598  1.1  mrg   argse.want_pointer = 1;
   11599  1.1  mrg   gfc_conv_expr (&argse, atom_expr);
   11600  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11601  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11602  1.1  mrg   atom = argse.expr;
   11603  1.1  mrg 
   11604  1.1  mrg   gfc_init_se (&argse, NULL);
   11605  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB
   11606  1.1  mrg       && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
   11607  1.1  mrg     argse.want_pointer = 1;
   11608  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->next->expr);
   11609  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11610  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11611  1.1  mrg   value = argse.expr;
   11612  1.1  mrg 
   11613  1.1  mrg   switch (code->resolved_isym->id)
   11614  1.1  mrg     {
   11615  1.1  mrg     case GFC_ISYM_ATOMIC_ADD:
   11616  1.1  mrg     case GFC_ISYM_ATOMIC_AND:
   11617  1.1  mrg     case GFC_ISYM_ATOMIC_DEF:
   11618  1.1  mrg     case GFC_ISYM_ATOMIC_OR:
   11619  1.1  mrg     case GFC_ISYM_ATOMIC_XOR:
   11620  1.1  mrg       stat_expr = code->ext.actual->next->next->expr;
   11621  1.1  mrg       if (flag_coarray == GFC_FCOARRAY_LIB)
   11622  1.1  mrg 	old = null_pointer_node;
   11623  1.1  mrg       break;
   11624  1.1  mrg     default:
   11625  1.1  mrg       gfc_init_se (&argse, NULL);
   11626  1.1  mrg       if (flag_coarray == GFC_FCOARRAY_LIB)
   11627  1.1  mrg 	argse.want_pointer = 1;
   11628  1.1  mrg       gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
   11629  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11630  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11631  1.1  mrg       old = argse.expr;
   11632  1.1  mrg       stat_expr = code->ext.actual->next->next->next->expr;
   11633  1.1  mrg     }
   11634  1.1  mrg 
   11635  1.1  mrg   /* STAT=  */
   11636  1.1  mrg   if (stat_expr != NULL)
   11637  1.1  mrg     {
   11638  1.1  mrg       gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
   11639  1.1  mrg       gfc_init_se (&argse, NULL);
   11640  1.1  mrg       if (flag_coarray == GFC_FCOARRAY_LIB)
   11641  1.1  mrg 	argse.want_pointer = 1;
   11642  1.1  mrg       gfc_conv_expr_val (&argse, stat_expr);
   11643  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11644  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11645  1.1  mrg       stat = argse.expr;
   11646  1.1  mrg     }
   11647  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   11648  1.1  mrg     stat = null_pointer_node;
   11649  1.1  mrg 
   11650  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   11651  1.1  mrg     {
   11652  1.1  mrg       tree image_index, caf_decl, offset, token;
   11653  1.1  mrg       int op;
   11654  1.1  mrg 
   11655  1.1  mrg       switch (code->resolved_isym->id)
   11656  1.1  mrg 	{
   11657  1.1  mrg 	case GFC_ISYM_ATOMIC_ADD:
   11658  1.1  mrg 	case GFC_ISYM_ATOMIC_FETCH_ADD:
   11659  1.1  mrg 	  op = (int) GFC_CAF_ATOMIC_ADD;
   11660  1.1  mrg 	  break;
   11661  1.1  mrg 	case GFC_ISYM_ATOMIC_AND:
   11662  1.1  mrg 	case GFC_ISYM_ATOMIC_FETCH_AND:
   11663  1.1  mrg 	  op = (int) GFC_CAF_ATOMIC_AND;
   11664  1.1  mrg 	  break;
   11665  1.1  mrg 	case GFC_ISYM_ATOMIC_OR:
   11666  1.1  mrg 	case GFC_ISYM_ATOMIC_FETCH_OR:
   11667  1.1  mrg 	  op = (int) GFC_CAF_ATOMIC_OR;
   11668  1.1  mrg 	  break;
   11669  1.1  mrg 	case GFC_ISYM_ATOMIC_XOR:
   11670  1.1  mrg 	case GFC_ISYM_ATOMIC_FETCH_XOR:
   11671  1.1  mrg 	  op = (int) GFC_CAF_ATOMIC_XOR;
   11672  1.1  mrg 	  break;
   11673  1.1  mrg 	case GFC_ISYM_ATOMIC_DEF:
   11674  1.1  mrg 	  op = 0;  /* Unused.  */
   11675  1.1  mrg 	  break;
   11676  1.1  mrg 	default:
   11677  1.1  mrg 	  gcc_unreachable ();
   11678  1.1  mrg 	}
   11679  1.1  mrg 
   11680  1.1  mrg       caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
   11681  1.1  mrg       if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   11682  1.1  mrg 	caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   11683  1.1  mrg 
   11684  1.1  mrg       if (gfc_is_coindexed (atom_expr))
   11685  1.1  mrg 	image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
   11686  1.1  mrg       else
   11687  1.1  mrg 	image_index = integer_zero_node;
   11688  1.1  mrg 
   11689  1.1  mrg       if (!POINTER_TYPE_P (TREE_TYPE (value)))
   11690  1.1  mrg 	{
   11691  1.1  mrg 	  tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
   11692  1.1  mrg 	  gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
   11693  1.1  mrg           value = gfc_build_addr_expr (NULL_TREE, tmp);
   11694  1.1  mrg 	}
   11695  1.1  mrg 
   11696  1.1  mrg       gfc_init_se (&argse, NULL);
   11697  1.1  mrg       gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
   11698  1.1  mrg 				atom_expr);
   11699  1.1  mrg 
   11700  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11701  1.1  mrg       if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
   11702  1.1  mrg 	tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
   11703  1.1  mrg 				   token, offset, image_index, value, stat,
   11704  1.1  mrg 				   build_int_cst (integer_type_node,
   11705  1.1  mrg 						  (int) atom_expr->ts.type),
   11706  1.1  mrg 				   build_int_cst (integer_type_node,
   11707  1.1  mrg 						  (int) atom_expr->ts.kind));
   11708  1.1  mrg       else
   11709  1.1  mrg 	tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
   11710  1.1  mrg 				   build_int_cst (integer_type_node, op),
   11711  1.1  mrg 				   token, offset, image_index, value, old, stat,
   11712  1.1  mrg 				   build_int_cst (integer_type_node,
   11713  1.1  mrg 						  (int) atom_expr->ts.type),
   11714  1.1  mrg 				   build_int_cst (integer_type_node,
   11715  1.1  mrg 						  (int) atom_expr->ts.kind));
   11716  1.1  mrg 
   11717  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   11718  1.1  mrg       gfc_add_block_to_block (&block, &argse.post);
   11719  1.1  mrg       gfc_add_block_to_block (&block, &post_block);
   11720  1.1  mrg       return gfc_finish_block (&block);
   11721  1.1  mrg     }
   11722  1.1  mrg 
   11723  1.1  mrg 
   11724  1.1  mrg   switch (code->resolved_isym->id)
   11725  1.1  mrg     {
   11726  1.1  mrg     case GFC_ISYM_ATOMIC_ADD:
   11727  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_ADD:
   11728  1.1  mrg       fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
   11729  1.1  mrg       break;
   11730  1.1  mrg     case GFC_ISYM_ATOMIC_AND:
   11731  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_AND:
   11732  1.1  mrg       fn = BUILT_IN_ATOMIC_FETCH_AND_N;
   11733  1.1  mrg       break;
   11734  1.1  mrg     case GFC_ISYM_ATOMIC_DEF:
   11735  1.1  mrg       fn = BUILT_IN_ATOMIC_STORE_N;
   11736  1.1  mrg       break;
   11737  1.1  mrg     case GFC_ISYM_ATOMIC_OR:
   11738  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_OR:
   11739  1.1  mrg       fn = BUILT_IN_ATOMIC_FETCH_OR_N;
   11740  1.1  mrg       break;
   11741  1.1  mrg     case GFC_ISYM_ATOMIC_XOR:
   11742  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_XOR:
   11743  1.1  mrg       fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
   11744  1.1  mrg       break;
   11745  1.1  mrg     default:
   11746  1.1  mrg       gcc_unreachable ();
   11747  1.1  mrg     }
   11748  1.1  mrg 
   11749  1.1  mrg   tmp = TREE_TYPE (TREE_TYPE (atom));
   11750  1.1  mrg   fn = (built_in_function) ((int) fn
   11751  1.1  mrg 			    + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
   11752  1.1  mrg 			    + 1);
   11753  1.1  mrg   tree itype = TREE_TYPE (TREE_TYPE (atom));
   11754  1.1  mrg   tmp = builtin_decl_explicit (fn);
   11755  1.1  mrg 
   11756  1.1  mrg   switch (code->resolved_isym->id)
   11757  1.1  mrg     {
   11758  1.1  mrg     case GFC_ISYM_ATOMIC_ADD:
   11759  1.1  mrg     case GFC_ISYM_ATOMIC_AND:
   11760  1.1  mrg     case GFC_ISYM_ATOMIC_DEF:
   11761  1.1  mrg     case GFC_ISYM_ATOMIC_OR:
   11762  1.1  mrg     case GFC_ISYM_ATOMIC_XOR:
   11763  1.1  mrg       tmp = build_call_expr_loc (input_location, tmp, 3, atom,
   11764  1.1  mrg 				 fold_convert (itype, value),
   11765  1.1  mrg 				 build_int_cst (NULL, MEMMODEL_RELAXED));
   11766  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   11767  1.1  mrg       break;
   11768  1.1  mrg     default:
   11769  1.1  mrg       tmp = build_call_expr_loc (input_location, tmp, 3, atom,
   11770  1.1  mrg 				 fold_convert (itype, value),
   11771  1.1  mrg 				 build_int_cst (NULL, MEMMODEL_RELAXED));
   11772  1.1  mrg       gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
   11773  1.1  mrg       break;
   11774  1.1  mrg     }
   11775  1.1  mrg 
   11776  1.1  mrg   if (stat != NULL_TREE)
   11777  1.1  mrg     gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
   11778  1.1  mrg   gfc_add_block_to_block (&block, &post_block);
   11779  1.1  mrg   return gfc_finish_block (&block);
   11780  1.1  mrg }
   11781  1.1  mrg 
   11782  1.1  mrg 
   11783  1.1  mrg static tree
   11784  1.1  mrg conv_intrinsic_atomic_ref (gfc_code *code)
   11785  1.1  mrg {
   11786  1.1  mrg   gfc_se argse;
   11787  1.1  mrg   tree tmp, atom, value, stat = NULL_TREE;
   11788  1.1  mrg   stmtblock_t block, post_block;
   11789  1.1  mrg   built_in_function fn;
   11790  1.1  mrg   gfc_expr *atom_expr = code->ext.actual->next->expr;
   11791  1.1  mrg 
   11792  1.1  mrg   if (atom_expr->expr_type == EXPR_FUNCTION
   11793  1.1  mrg       && atom_expr->value.function.isym
   11794  1.1  mrg       && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
   11795  1.1  mrg     atom_expr = atom_expr->value.function.actual->expr;
   11796  1.1  mrg 
   11797  1.1  mrg   gfc_start_block (&block);
   11798  1.1  mrg   gfc_init_block (&post_block);
   11799  1.1  mrg   gfc_init_se (&argse, NULL);
   11800  1.1  mrg   argse.want_pointer = 1;
   11801  1.1  mrg   gfc_conv_expr (&argse, atom_expr);
   11802  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11803  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11804  1.1  mrg   atom = argse.expr;
   11805  1.1  mrg 
   11806  1.1  mrg   gfc_init_se (&argse, NULL);
   11807  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB
   11808  1.1  mrg       && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
   11809  1.1  mrg     argse.want_pointer = 1;
   11810  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->expr);
   11811  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11812  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11813  1.1  mrg   value = argse.expr;
   11814  1.1  mrg 
   11815  1.1  mrg   /* STAT=  */
   11816  1.1  mrg   if (code->ext.actual->next->next->expr != NULL)
   11817  1.1  mrg     {
   11818  1.1  mrg       gcc_assert (code->ext.actual->next->next->expr->expr_type
   11819  1.1  mrg 		  == EXPR_VARIABLE);
   11820  1.1  mrg       gfc_init_se (&argse, NULL);
   11821  1.1  mrg       if (flag_coarray == GFC_FCOARRAY_LIB)
   11822  1.1  mrg 	argse.want_pointer = 1;
   11823  1.1  mrg       gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
   11824  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11825  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11826  1.1  mrg       stat = argse.expr;
   11827  1.1  mrg     }
   11828  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   11829  1.1  mrg     stat = null_pointer_node;
   11830  1.1  mrg 
   11831  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   11832  1.1  mrg     {
   11833  1.1  mrg       tree image_index, caf_decl, offset, token;
   11834  1.1  mrg       tree orig_value = NULL_TREE, vardecl = NULL_TREE;
   11835  1.1  mrg 
   11836  1.1  mrg       caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
   11837  1.1  mrg       if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   11838  1.1  mrg 	caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   11839  1.1  mrg 
   11840  1.1  mrg       if (gfc_is_coindexed (atom_expr))
   11841  1.1  mrg 	image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
   11842  1.1  mrg       else
   11843  1.1  mrg 	image_index = integer_zero_node;
   11844  1.1  mrg 
   11845  1.1  mrg       gfc_init_se (&argse, NULL);
   11846  1.1  mrg       gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
   11847  1.1  mrg 				atom_expr);
   11848  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11849  1.1  mrg 
   11850  1.1  mrg       /* Different type, need type conversion.  */
   11851  1.1  mrg       if (!POINTER_TYPE_P (TREE_TYPE (value)))
   11852  1.1  mrg 	{
   11853  1.1  mrg 	  vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
   11854  1.1  mrg           orig_value = value;
   11855  1.1  mrg           value = gfc_build_addr_expr (NULL_TREE, vardecl);
   11856  1.1  mrg 	}
   11857  1.1  mrg 
   11858  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
   11859  1.1  mrg 				 token, offset, image_index, value, stat,
   11860  1.1  mrg 				 build_int_cst (integer_type_node,
   11861  1.1  mrg 						(int) atom_expr->ts.type),
   11862  1.1  mrg 				 build_int_cst (integer_type_node,
   11863  1.1  mrg 						(int) atom_expr->ts.kind));
   11864  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   11865  1.1  mrg       if (vardecl != NULL_TREE)
   11866  1.1  mrg 	gfc_add_modify (&block, orig_value,
   11867  1.1  mrg 			fold_convert (TREE_TYPE (orig_value), vardecl));
   11868  1.1  mrg       gfc_add_block_to_block (&block, &argse.post);
   11869  1.1  mrg       gfc_add_block_to_block (&block, &post_block);
   11870  1.1  mrg       return gfc_finish_block (&block);
   11871  1.1  mrg     }
   11872  1.1  mrg 
   11873  1.1  mrg   tmp = TREE_TYPE (TREE_TYPE (atom));
   11874  1.1  mrg   fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
   11875  1.1  mrg 			    + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
   11876  1.1  mrg 			    + 1);
   11877  1.1  mrg   tmp = builtin_decl_explicit (fn);
   11878  1.1  mrg   tmp = build_call_expr_loc (input_location, tmp, 2, atom,
   11879  1.1  mrg 			     build_int_cst (integer_type_node,
   11880  1.1  mrg 					    MEMMODEL_RELAXED));
   11881  1.1  mrg   gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
   11882  1.1  mrg 
   11883  1.1  mrg   if (stat != NULL_TREE)
   11884  1.1  mrg     gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
   11885  1.1  mrg   gfc_add_block_to_block (&block, &post_block);
   11886  1.1  mrg   return gfc_finish_block (&block);
   11887  1.1  mrg }
   11888  1.1  mrg 
   11889  1.1  mrg 
   11890  1.1  mrg static tree
   11891  1.1  mrg conv_intrinsic_atomic_cas (gfc_code *code)
   11892  1.1  mrg {
   11893  1.1  mrg   gfc_se argse;
   11894  1.1  mrg   tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
   11895  1.1  mrg   stmtblock_t block, post_block;
   11896  1.1  mrg   built_in_function fn;
   11897  1.1  mrg   gfc_expr *atom_expr = code->ext.actual->expr;
   11898  1.1  mrg 
   11899  1.1  mrg   if (atom_expr->expr_type == EXPR_FUNCTION
   11900  1.1  mrg       && atom_expr->value.function.isym
   11901  1.1  mrg       && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
   11902  1.1  mrg     atom_expr = atom_expr->value.function.actual->expr;
   11903  1.1  mrg 
   11904  1.1  mrg   gfc_init_block (&block);
   11905  1.1  mrg   gfc_init_block (&post_block);
   11906  1.1  mrg   gfc_init_se (&argse, NULL);
   11907  1.1  mrg   argse.want_pointer = 1;
   11908  1.1  mrg   gfc_conv_expr (&argse, atom_expr);
   11909  1.1  mrg   atom = argse.expr;
   11910  1.1  mrg 
   11911  1.1  mrg   gfc_init_se (&argse, NULL);
   11912  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   11913  1.1  mrg     argse.want_pointer = 1;
   11914  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->next->expr);
   11915  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11916  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11917  1.1  mrg   old = argse.expr;
   11918  1.1  mrg 
   11919  1.1  mrg   gfc_init_se (&argse, NULL);
   11920  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   11921  1.1  mrg     argse.want_pointer = 1;
   11922  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
   11923  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11924  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11925  1.1  mrg   comp = argse.expr;
   11926  1.1  mrg 
   11927  1.1  mrg   gfc_init_se (&argse, NULL);
   11928  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB
   11929  1.1  mrg       && code->ext.actual->next->next->next->expr->ts.kind
   11930  1.1  mrg 	 == atom_expr->ts.kind)
   11931  1.1  mrg     argse.want_pointer = 1;
   11932  1.1  mrg   gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
   11933  1.1  mrg   gfc_add_block_to_block (&block, &argse.pre);
   11934  1.1  mrg   gfc_add_block_to_block (&post_block, &argse.post);
   11935  1.1  mrg   new_val = argse.expr;
   11936  1.1  mrg 
   11937  1.1  mrg   /* STAT=  */
   11938  1.1  mrg   if (code->ext.actual->next->next->next->next->expr != NULL)
   11939  1.1  mrg     {
   11940  1.1  mrg       gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
   11941  1.1  mrg 		  == EXPR_VARIABLE);
   11942  1.1  mrg       gfc_init_se (&argse, NULL);
   11943  1.1  mrg       if (flag_coarray == GFC_FCOARRAY_LIB)
   11944  1.1  mrg 	argse.want_pointer = 1;
   11945  1.1  mrg       gfc_conv_expr_val (&argse,
   11946  1.1  mrg 			 code->ext.actual->next->next->next->next->expr);
   11947  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11948  1.1  mrg       gfc_add_block_to_block (&post_block, &argse.post);
   11949  1.1  mrg       stat = argse.expr;
   11950  1.1  mrg     }
   11951  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   11952  1.1  mrg     stat = null_pointer_node;
   11953  1.1  mrg 
   11954  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   11955  1.1  mrg     {
   11956  1.1  mrg       tree image_index, caf_decl, offset, token;
   11957  1.1  mrg 
   11958  1.1  mrg       caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
   11959  1.1  mrg       if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
   11960  1.1  mrg 	caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
   11961  1.1  mrg 
   11962  1.1  mrg       if (gfc_is_coindexed (atom_expr))
   11963  1.1  mrg 	image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
   11964  1.1  mrg       else
   11965  1.1  mrg 	image_index = integer_zero_node;
   11966  1.1  mrg 
   11967  1.1  mrg       if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
   11968  1.1  mrg 	{
   11969  1.1  mrg 	  tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
   11970  1.1  mrg 	  gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
   11971  1.1  mrg           new_val = gfc_build_addr_expr (NULL_TREE, tmp);
   11972  1.1  mrg 	}
   11973  1.1  mrg 
   11974  1.1  mrg       /* Convert a constant to a pointer.  */
   11975  1.1  mrg       if (!POINTER_TYPE_P (TREE_TYPE (comp)))
   11976  1.1  mrg 	{
   11977  1.1  mrg 	  tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
   11978  1.1  mrg 	  gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
   11979  1.1  mrg           comp = gfc_build_addr_expr (NULL_TREE, tmp);
   11980  1.1  mrg 	}
   11981  1.1  mrg 
   11982  1.1  mrg       gfc_init_se (&argse, NULL);
   11983  1.1  mrg       gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
   11984  1.1  mrg 				atom_expr);
   11985  1.1  mrg       gfc_add_block_to_block (&block, &argse.pre);
   11986  1.1  mrg 
   11987  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
   11988  1.1  mrg 				 token, offset, image_index, old, comp, new_val,
   11989  1.1  mrg 				 stat, build_int_cst (integer_type_node,
   11990  1.1  mrg 						      (int) atom_expr->ts.type),
   11991  1.1  mrg 				 build_int_cst (integer_type_node,
   11992  1.1  mrg 						(int) atom_expr->ts.kind));
   11993  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   11994  1.1  mrg       gfc_add_block_to_block (&block, &argse.post);
   11995  1.1  mrg       gfc_add_block_to_block (&block, &post_block);
   11996  1.1  mrg       return gfc_finish_block (&block);
   11997  1.1  mrg     }
   11998  1.1  mrg 
   11999  1.1  mrg   tmp = TREE_TYPE (TREE_TYPE (atom));
   12000  1.1  mrg   fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
   12001  1.1  mrg 			    + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
   12002  1.1  mrg 			    + 1);
   12003  1.1  mrg   tmp = builtin_decl_explicit (fn);
   12004  1.1  mrg 
   12005  1.1  mrg   gfc_add_modify (&block, old, comp);
   12006  1.1  mrg   tmp = build_call_expr_loc (input_location, tmp, 6, atom,
   12007  1.1  mrg 			     gfc_build_addr_expr (NULL, old),
   12008  1.1  mrg 			     fold_convert (TREE_TYPE (old), new_val),
   12009  1.1  mrg 			     boolean_false_node,
   12010  1.1  mrg 			     build_int_cst (NULL, MEMMODEL_RELAXED),
   12011  1.1  mrg 			     build_int_cst (NULL, MEMMODEL_RELAXED));
   12012  1.1  mrg   gfc_add_expr_to_block (&block, tmp);
   12013  1.1  mrg 
   12014  1.1  mrg   if (stat != NULL_TREE)
   12015  1.1  mrg     gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
   12016  1.1  mrg   gfc_add_block_to_block (&block, &post_block);
   12017  1.1  mrg   return gfc_finish_block (&block);
   12018  1.1  mrg }
   12019  1.1  mrg 
   12020  1.1  mrg static tree
   12021  1.1  mrg conv_intrinsic_event_query (gfc_code *code)
   12022  1.1  mrg {
   12023  1.1  mrg   gfc_se se, argse;
   12024  1.1  mrg   tree stat = NULL_TREE, stat2 = NULL_TREE;
   12025  1.1  mrg   tree count = NULL_TREE, count2 = NULL_TREE;
   12026  1.1  mrg 
   12027  1.1  mrg   gfc_expr *event_expr = code->ext.actual->expr;
   12028  1.1  mrg 
   12029  1.1  mrg   if (code->ext.actual->next->next->expr)
   12030  1.1  mrg     {
   12031  1.1  mrg       gcc_assert (code->ext.actual->next->next->expr->expr_type
   12032  1.1  mrg 		  == EXPR_VARIABLE);
   12033  1.1  mrg       gfc_init_se (&argse, NULL);
   12034  1.1  mrg       gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
   12035  1.1  mrg       stat = argse.expr;
   12036  1.1  mrg     }
   12037  1.1  mrg   else if (flag_coarray == GFC_FCOARRAY_LIB)
   12038  1.1  mrg     stat = null_pointer_node;
   12039  1.1  mrg 
   12040  1.1  mrg   if (code->ext.actual->next->expr)
   12041  1.1  mrg     {
   12042  1.1  mrg       gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
   12043  1.1  mrg       gfc_init_se (&argse, NULL);
   12044  1.1  mrg       gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
   12045  1.1  mrg       count = argse.expr;
   12046  1.1  mrg     }
   12047  1.1  mrg 
   12048  1.1  mrg   gfc_start_block (&se.pre);
   12049  1.1  mrg   if (flag_coarray == GFC_FCOARRAY_LIB)
   12050  1.1  mrg     {
   12051  1.1  mrg       tree tmp, token, image_index;
   12052  1.1  mrg       tree index = build_zero_cst (gfc_array_index_type);
   12053  1.1  mrg 
   12054  1.1  mrg       if (event_expr->expr_type == EXPR_FUNCTION
   12055  1.1  mrg 	  && event_expr->value.function.isym
   12056  1.1  mrg 	  && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
   12057  1.1  mrg 	event_expr = event_expr->value.function.actual->expr;
   12058  1.1  mrg 
   12059  1.1  mrg       tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
   12060  1.1  mrg 
   12061  1.1  mrg       if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
   12062  1.1  mrg 	  || event_expr->symtree->n.sym->ts.u.derived->from_intmod
   12063  1.1  mrg 	     != INTMOD_ISO_FORTRAN_ENV
   12064  1.1  mrg 	  || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
   12065  1.1  mrg 	     != ISOFORTRAN_EVENT_TYPE)
   12066  1.1  mrg 	{
   12067  1.1  mrg 	  gfc_error ("Sorry, the event component of derived type at %L is not "
   12068  1.1  mrg 		     "yet supported", &event_expr->where);
   12069  1.1  mrg 	  return NULL_TREE;
   12070  1.1  mrg 	}
   12071  1.1  mrg 
   12072  1.1  mrg       if (gfc_is_coindexed (event_expr))
   12073  1.1  mrg 	{
   12074  1.1  mrg 	  gfc_error ("The event variable at %L shall not be coindexed",
   12075  1.1  mrg 		     &event_expr->where);
   12076  1.1  mrg           return NULL_TREE;
   12077  1.1  mrg 	}
   12078  1.1  mrg 
   12079  1.1  mrg       image_index = integer_zero_node;
   12080  1.1  mrg 
   12081  1.1  mrg       gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
   12082  1.1  mrg 				event_expr);
   12083  1.1  mrg 
   12084  1.1  mrg       /* For arrays, obtain the array index.  */
   12085  1.1  mrg       if (gfc_expr_attr (event_expr).dimension)
   12086  1.1  mrg 	{
   12087  1.1  mrg 	  tree desc, tmp, extent, lbound, ubound;
   12088  1.1  mrg           gfc_array_ref *ar, ar2;
   12089  1.1  mrg           int i;
   12090  1.1  mrg 
   12091  1.1  mrg 	  /* TODO: Extend this, once DT components are supported.  */
   12092  1.1  mrg 	  ar = &event_expr->ref->u.ar;
   12093  1.1  mrg 	  ar2 = *ar;
   12094  1.1  mrg 	  memset (ar, '\0', sizeof (*ar));
   12095  1.1  mrg 	  ar->as = ar2.as;
   12096  1.1  mrg 	  ar->type = AR_FULL;
   12097  1.1  mrg 
   12098  1.1  mrg 	  gfc_init_se (&argse, NULL);
   12099  1.1  mrg 	  argse.descriptor_only = 1;
   12100  1.1  mrg 	  gfc_conv_expr_descriptor (&argse, event_expr);
   12101  1.1  mrg 	  gfc_add_block_to_block (&se.pre, &argse.pre);
   12102  1.1  mrg 	  desc = argse.expr;
   12103  1.1  mrg 	  *ar = ar2;
   12104  1.1  mrg 
   12105  1.1  mrg 	  extent = build_one_cst (gfc_array_index_type);
   12106  1.1  mrg 	  for (i = 0; i < ar->dimen; i++)
   12107  1.1  mrg 	    {
   12108  1.1  mrg 	      gfc_init_se (&argse, NULL);
   12109  1.1  mrg 	      gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
   12110  1.1  mrg 	      gfc_add_block_to_block (&argse.pre, &argse.pre);
   12111  1.1  mrg 	      lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
   12112  1.1  mrg 	      tmp = fold_build2_loc (input_location, MINUS_EXPR,
   12113  1.1  mrg 				     TREE_TYPE (lbound), argse.expr, lbound);
   12114  1.1  mrg 	      tmp = fold_build2_loc (input_location, MULT_EXPR,
   12115  1.1  mrg 				     TREE_TYPE (tmp), extent, tmp);
   12116  1.1  mrg 	      index = fold_build2_loc (input_location, PLUS_EXPR,
   12117  1.1  mrg 				       TREE_TYPE (tmp), index, tmp);
   12118  1.1  mrg 	      if (i < ar->dimen - 1)
   12119  1.1  mrg 		{
   12120  1.1  mrg 		  ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
   12121  1.1  mrg 		  tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   12122  1.1  mrg 		  extent = fold_build2_loc (input_location, MULT_EXPR,
   12123  1.1  mrg 					    TREE_TYPE (tmp), extent, tmp);
   12124  1.1  mrg 		}
   12125  1.1  mrg 	    }
   12126  1.1  mrg 	}
   12127  1.1  mrg 
   12128  1.1  mrg       if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
   12129  1.1  mrg 	{
   12130  1.1  mrg 	  count2 = count;
   12131  1.1  mrg 	  count = gfc_create_var (integer_type_node, "count");
   12132  1.1  mrg 	}
   12133  1.1  mrg 
   12134  1.1  mrg       if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
   12135  1.1  mrg 	{
   12136  1.1  mrg 	  stat2 = stat;
   12137  1.1  mrg 	  stat = gfc_create_var (integer_type_node, "stat");
   12138  1.1  mrg 	}
   12139  1.1  mrg 
   12140  1.1  mrg       index = fold_convert (size_type_node, index);
   12141  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
   12142  1.1  mrg                                    token, index, image_index, count
   12143  1.1  mrg 				   ? gfc_build_addr_expr (NULL, count) : count,
   12144  1.1  mrg 				   stat != null_pointer_node
   12145  1.1  mrg 				   ? gfc_build_addr_expr (NULL, stat) : stat);
   12146  1.1  mrg       gfc_add_expr_to_block (&se.pre, tmp);
   12147  1.1  mrg 
   12148  1.1  mrg       if (count2 != NULL_TREE)
   12149  1.1  mrg 	gfc_add_modify (&se.pre, count2,
   12150  1.1  mrg 			fold_convert (TREE_TYPE (count2), count));
   12151  1.1  mrg 
   12152  1.1  mrg       if (stat2 != NULL_TREE)
   12153  1.1  mrg 	gfc_add_modify (&se.pre, stat2,
   12154  1.1  mrg 			fold_convert (TREE_TYPE (stat2), stat));
   12155  1.1  mrg 
   12156  1.1  mrg       return gfc_finish_block (&se.pre);
   12157  1.1  mrg     }
   12158  1.1  mrg 
   12159  1.1  mrg   gfc_init_se (&argse, NULL);
   12160  1.1  mrg   gfc_conv_expr_val (&argse, code->ext.actual->expr);
   12161  1.1  mrg   gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
   12162  1.1  mrg 
   12163  1.1  mrg   if (stat != NULL_TREE)
   12164  1.1  mrg     gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
   12165  1.1  mrg 
   12166  1.1  mrg   return gfc_finish_block (&se.pre);
   12167  1.1  mrg }
   12168  1.1  mrg 
   12169  1.1  mrg 
   12170  1.1  mrg /* This is a peculiar case because of the need to do dependency checking.
   12171  1.1  mrg    It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
   12172  1.1  mrg    a special case and this function called instead of
   12173  1.1  mrg    gfc_conv_procedure_call.  */
   12174  1.1  mrg void
   12175  1.1  mrg gfc_conv_intrinsic_mvbits (gfc_se *se, gfc_actual_arglist *actual_args,
   12176  1.1  mrg 			   gfc_loopinfo *loop)
   12177  1.1  mrg {
   12178  1.1  mrg   gfc_actual_arglist *actual;
   12179  1.1  mrg   gfc_se argse[5];
   12180  1.1  mrg   gfc_expr *arg[5];
   12181  1.1  mrg   gfc_ss *lss;
   12182  1.1  mrg   int n;
   12183  1.1  mrg 
   12184  1.1  mrg   tree from, frompos, len, to, topos;
   12185  1.1  mrg   tree lenmask, oldbits, newbits, bitsize;
   12186  1.1  mrg   tree type, utype, above, mask1, mask2;
   12187  1.1  mrg 
   12188  1.1  mrg   if (loop)
   12189  1.1  mrg     lss = loop->ss;
   12190  1.1  mrg   else
   12191  1.1  mrg     lss = gfc_ss_terminator;
   12192  1.1  mrg 
   12193  1.1  mrg   actual = actual_args;
   12194  1.1  mrg   for (n = 0; n < 5; n++, actual = actual->next)
   12195  1.1  mrg     {
   12196  1.1  mrg       arg[n] = actual->expr;
   12197  1.1  mrg       gfc_init_se (&argse[n], NULL);
   12198  1.1  mrg 
   12199  1.1  mrg       if (lss != gfc_ss_terminator)
   12200  1.1  mrg 	{
   12201  1.1  mrg 	  gfc_copy_loopinfo_to_se (&argse[n], loop);
   12202  1.1  mrg 	  /* Find the ss for the expression if it is there.  */
   12203  1.1  mrg 	  argse[n].ss = lss;
   12204  1.1  mrg 	  gfc_mark_ss_chain_used (lss, 1);
   12205  1.1  mrg 	}
   12206  1.1  mrg 
   12207  1.1  mrg       gfc_conv_expr (&argse[n], arg[n]);
   12208  1.1  mrg 
   12209  1.1  mrg       if (loop)
   12210  1.1  mrg 	lss = argse[n].ss;
   12211  1.1  mrg     }
   12212  1.1  mrg 
   12213  1.1  mrg   from    = argse[0].expr;
   12214  1.1  mrg   frompos = argse[1].expr;
   12215  1.1  mrg   len     = argse[2].expr;
   12216  1.1  mrg   to      = argse[3].expr;
   12217  1.1  mrg   topos   = argse[4].expr;
   12218  1.1  mrg 
   12219  1.1  mrg   /* The type of the result (TO).  */
   12220  1.1  mrg   type    = TREE_TYPE (to);
   12221  1.1  mrg   bitsize = build_int_cst (integer_type_node, TYPE_PRECISION (type));
   12222  1.1  mrg 
   12223  1.1  mrg   /* Optionally generate code for runtime argument check.  */
   12224  1.1  mrg   if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
   12225  1.1  mrg     {
   12226  1.1  mrg       tree nbits, below, ccond;
   12227  1.1  mrg       tree fp = fold_convert (long_integer_type_node, frompos);
   12228  1.1  mrg       tree ln = fold_convert (long_integer_type_node, len);
   12229  1.1  mrg       tree tp = fold_convert (long_integer_type_node, topos);
   12230  1.1  mrg       below = fold_build2_loc (input_location, LT_EXPR,
   12231  1.1  mrg 			       logical_type_node, frompos,
   12232  1.1  mrg 			       build_int_cst (TREE_TYPE (frompos), 0));
   12233  1.1  mrg       above = fold_build2_loc (input_location, GT_EXPR,
   12234  1.1  mrg 			       logical_type_node, frompos,
   12235  1.1  mrg 			       fold_convert (TREE_TYPE (frompos), bitsize));
   12236  1.1  mrg       ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   12237  1.1  mrg 			       logical_type_node, below, above);
   12238  1.1  mrg       gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
   12239  1.1  mrg 			       &arg[1]->where,
   12240  1.1  mrg 			       "FROMPOS argument (%ld) out of range 0:%d "
   12241  1.1  mrg 			       "in intrinsic MVBITS", fp, bitsize);
   12242  1.1  mrg       below = fold_build2_loc (input_location, LT_EXPR,
   12243  1.1  mrg 			       logical_type_node, len,
   12244  1.1  mrg 			       build_int_cst (TREE_TYPE (len), 0));
   12245  1.1  mrg       above = fold_build2_loc (input_location, GT_EXPR,
   12246  1.1  mrg 			       logical_type_node, len,
   12247  1.1  mrg 			       fold_convert (TREE_TYPE (len), bitsize));
   12248  1.1  mrg       ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   12249  1.1  mrg 			       logical_type_node, below, above);
   12250  1.1  mrg       gfc_trans_runtime_check (true, false, ccond, &argse[2].pre,
   12251  1.1  mrg 			       &arg[2]->where,
   12252  1.1  mrg 			       "LEN argument (%ld) out of range 0:%d "
   12253  1.1  mrg 			       "in intrinsic MVBITS", ln, bitsize);
   12254  1.1  mrg       below = fold_build2_loc (input_location, LT_EXPR,
   12255  1.1  mrg 			       logical_type_node, topos,
   12256  1.1  mrg 			       build_int_cst (TREE_TYPE (topos), 0));
   12257  1.1  mrg       above = fold_build2_loc (input_location, GT_EXPR,
   12258  1.1  mrg 			       logical_type_node, topos,
   12259  1.1  mrg 			       fold_convert (TREE_TYPE (topos), bitsize));
   12260  1.1  mrg       ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
   12261  1.1  mrg 			       logical_type_node, below, above);
   12262  1.1  mrg       gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
   12263  1.1  mrg 			       &arg[4]->where,
   12264  1.1  mrg 			       "TOPOS argument (%ld) out of range 0:%d "
   12265  1.1  mrg 			       "in intrinsic MVBITS", tp, bitsize);
   12266  1.1  mrg 
   12267  1.1  mrg       /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
   12268  1.1  mrg 	 integers.  Additions below cannot overflow.  */
   12269  1.1  mrg       nbits = fold_convert (long_integer_type_node, bitsize);
   12270  1.1  mrg       above = fold_build2_loc (input_location, PLUS_EXPR,
   12271  1.1  mrg 			       long_integer_type_node, fp, ln);
   12272  1.1  mrg       ccond = fold_build2_loc (input_location, GT_EXPR,
   12273  1.1  mrg 			       logical_type_node, above, nbits);
   12274  1.1  mrg       gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
   12275  1.1  mrg 			       &arg[1]->where,
   12276  1.1  mrg 			       "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
   12277  1.1  mrg 			       "in intrinsic MVBITS", fp, ln, bitsize);
   12278  1.1  mrg       above = fold_build2_loc (input_location, PLUS_EXPR,
   12279  1.1  mrg 			       long_integer_type_node, tp, ln);
   12280  1.1  mrg       ccond = fold_build2_loc (input_location, GT_EXPR,
   12281  1.1  mrg 			       logical_type_node, above, nbits);
   12282  1.1  mrg       gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
   12283  1.1  mrg 			       &arg[4]->where,
   12284  1.1  mrg 			       "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
   12285  1.1  mrg 			       "in intrinsic MVBITS", tp, ln, bitsize);
   12286  1.1  mrg     }
   12287  1.1  mrg 
   12288  1.1  mrg   for (n = 0; n < 5; n++)
   12289  1.1  mrg     {
   12290  1.1  mrg       gfc_add_block_to_block (&se->pre, &argse[n].pre);
   12291  1.1  mrg       gfc_add_block_to_block (&se->post, &argse[n].post);
   12292  1.1  mrg     }
   12293  1.1  mrg 
   12294  1.1  mrg   /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1  */
   12295  1.1  mrg   above = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
   12296  1.1  mrg 			   len, fold_convert (TREE_TYPE (len), bitsize));
   12297  1.1  mrg   mask1 = build_int_cst (type, -1);
   12298  1.1  mrg   mask2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   12299  1.1  mrg 			   build_int_cst (type, 1), len);
   12300  1.1  mrg   mask2 = fold_build2_loc (input_location, MINUS_EXPR, type,
   12301  1.1  mrg 			   mask2, build_int_cst (type, 1));
   12302  1.1  mrg   lenmask = fold_build3_loc (input_location, COND_EXPR, type,
   12303  1.1  mrg 			     above, mask1, mask2);
   12304  1.1  mrg 
   12305  1.1  mrg   /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
   12306  1.1  mrg    * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
   12307  1.1  mrg    * not strictly necessary; artificial bits from rshift will be masked.  */
   12308  1.1  mrg   utype = unsigned_type_for (type);
   12309  1.1  mrg   newbits = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
   12310  1.1  mrg 			     fold_convert (utype, from), frompos);
   12311  1.1  mrg   newbits = fold_build2_loc (input_location, BIT_AND_EXPR, type,
   12312  1.1  mrg 			     fold_convert (type, newbits), lenmask);
   12313  1.1  mrg   newbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   12314  1.1  mrg 			     newbits, topos);
   12315  1.1  mrg 
   12316  1.1  mrg   /* oldbits = TO & (~(lenmask << TOPOS)).  */
   12317  1.1  mrg   oldbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
   12318  1.1  mrg 			     lenmask, topos);
   12319  1.1  mrg   oldbits = fold_build1_loc (input_location, BIT_NOT_EXPR, type, oldbits);
   12320  1.1  mrg   oldbits = fold_build2_loc (input_location, BIT_AND_EXPR, type, oldbits, to);
   12321  1.1  mrg 
   12322  1.1  mrg   /* TO = newbits | oldbits.  */
   12323  1.1  mrg   se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
   12324  1.1  mrg 			      oldbits, newbits);
   12325  1.1  mrg 
   12326  1.1  mrg   /* Return the assignment.  */
   12327  1.1  mrg   se->expr = fold_build2_loc (input_location, MODIFY_EXPR,
   12328  1.1  mrg 			      void_type_node, to, se->expr);
   12329  1.1  mrg }
   12330  1.1  mrg 
   12331  1.1  mrg 
   12332  1.1  mrg static tree
   12333  1.1  mrg conv_intrinsic_move_alloc (gfc_code *code)
   12334  1.1  mrg {
   12335  1.1  mrg   stmtblock_t block;
   12336  1.1  mrg   gfc_expr *from_expr, *to_expr;
   12337  1.1  mrg   gfc_expr *to_expr2, *from_expr2 = NULL;
   12338  1.1  mrg   gfc_se from_se, to_se;
   12339  1.1  mrg   tree tmp;
   12340  1.1  mrg   bool coarray;
   12341  1.1  mrg 
   12342  1.1  mrg   gfc_start_block (&block);
   12343  1.1  mrg 
   12344  1.1  mrg   from_expr = code->ext.actual->expr;
   12345  1.1  mrg   to_expr = code->ext.actual->next->expr;
   12346  1.1  mrg 
   12347  1.1  mrg   gfc_init_se (&from_se, NULL);
   12348  1.1  mrg   gfc_init_se (&to_se, NULL);
   12349  1.1  mrg 
   12350  1.1  mrg   gcc_assert (from_expr->ts.type != BT_CLASS
   12351  1.1  mrg 	      || to_expr->ts.type == BT_CLASS);
   12352  1.1  mrg   coarray = gfc_get_corank (from_expr) != 0;
   12353  1.1  mrg 
   12354  1.1  mrg   if (from_expr->rank == 0 && !coarray)
   12355  1.1  mrg     {
   12356  1.1  mrg       if (from_expr->ts.type != BT_CLASS)
   12357  1.1  mrg 	from_expr2 = from_expr;
   12358  1.1  mrg       else
   12359  1.1  mrg 	{
   12360  1.1  mrg 	  from_expr2 = gfc_copy_expr (from_expr);
   12361  1.1  mrg 	  gfc_add_data_component (from_expr2);
   12362  1.1  mrg 	}
   12363  1.1  mrg 
   12364  1.1  mrg       if (to_expr->ts.type != BT_CLASS)
   12365  1.1  mrg 	to_expr2 = to_expr;
   12366  1.1  mrg       else
   12367  1.1  mrg 	{
   12368  1.1  mrg 	  to_expr2 = gfc_copy_expr (to_expr);
   12369  1.1  mrg 	  gfc_add_data_component (to_expr2);
   12370  1.1  mrg 	}
   12371  1.1  mrg 
   12372  1.1  mrg       from_se.want_pointer = 1;
   12373  1.1  mrg       to_se.want_pointer = 1;
   12374  1.1  mrg       gfc_conv_expr (&from_se, from_expr2);
   12375  1.1  mrg       gfc_conv_expr (&to_se, to_expr2);
   12376  1.1  mrg       gfc_add_block_to_block (&block, &from_se.pre);
   12377  1.1  mrg       gfc_add_block_to_block (&block, &to_se.pre);
   12378  1.1  mrg 
   12379  1.1  mrg       /* Deallocate "to".  */
   12380  1.1  mrg       tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
   12381  1.1  mrg 					       true, to_expr, to_expr->ts);
   12382  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   12383  1.1  mrg 
   12384  1.1  mrg       /* Assign (_data) pointers.  */
   12385  1.1  mrg       gfc_add_modify_loc (input_location, &block, to_se.expr,
   12386  1.1  mrg 			  fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
   12387  1.1  mrg 
   12388  1.1  mrg       /* Set "from" to NULL.  */
   12389  1.1  mrg       gfc_add_modify_loc (input_location, &block, from_se.expr,
   12390  1.1  mrg 			  fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
   12391  1.1  mrg 
   12392  1.1  mrg       gfc_add_block_to_block (&block, &from_se.post);
   12393  1.1  mrg       gfc_add_block_to_block (&block, &to_se.post);
   12394  1.1  mrg 
   12395  1.1  mrg       /* Set _vptr.  */
   12396  1.1  mrg       if (to_expr->ts.type == BT_CLASS)
   12397  1.1  mrg 	{
   12398  1.1  mrg 	  gfc_symbol *vtab;
   12399  1.1  mrg 
   12400  1.1  mrg 	  gfc_free_expr (to_expr2);
   12401  1.1  mrg 	  gfc_init_se (&to_se, NULL);
   12402  1.1  mrg 	  to_se.want_pointer = 1;
   12403  1.1  mrg 	  gfc_add_vptr_component (to_expr);
   12404  1.1  mrg 	  gfc_conv_expr (&to_se, to_expr);
   12405  1.1  mrg 
   12406  1.1  mrg 	  if (from_expr->ts.type == BT_CLASS)
   12407  1.1  mrg 	    {
   12408  1.1  mrg 	      if (UNLIMITED_POLY (from_expr))
   12409  1.1  mrg 		vtab = NULL;
   12410  1.1  mrg 	      else
   12411  1.1  mrg 		{
   12412  1.1  mrg 		  vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
   12413  1.1  mrg 		  gcc_assert (vtab);
   12414  1.1  mrg 		}
   12415  1.1  mrg 
   12416  1.1  mrg 	      gfc_free_expr (from_expr2);
   12417  1.1  mrg 	      gfc_init_se (&from_se, NULL);
   12418  1.1  mrg 	      from_se.want_pointer = 1;
   12419  1.1  mrg 	      gfc_add_vptr_component (from_expr);
   12420  1.1  mrg 	      gfc_conv_expr (&from_se, from_expr);
   12421  1.1  mrg 	      gfc_add_modify_loc (input_location, &block, to_se.expr,
   12422  1.1  mrg 				  fold_convert (TREE_TYPE (to_se.expr),
   12423  1.1  mrg 				  from_se.expr));
   12424  1.1  mrg 
   12425  1.1  mrg               /* Reset _vptr component to declared type.  */
   12426  1.1  mrg 	      if (vtab == NULL)
   12427  1.1  mrg 		/* Unlimited polymorphic.  */
   12428  1.1  mrg 		gfc_add_modify_loc (input_location, &block, from_se.expr,
   12429  1.1  mrg 				    fold_convert (TREE_TYPE (from_se.expr),
   12430  1.1  mrg 						  null_pointer_node));
   12431  1.1  mrg 	      else
   12432  1.1  mrg 		{
   12433  1.1  mrg 		  tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
   12434  1.1  mrg 		  gfc_add_modify_loc (input_location, &block, from_se.expr,
   12435  1.1  mrg 				      fold_convert (TREE_TYPE (from_se.expr), tmp));
   12436  1.1  mrg 		}
   12437  1.1  mrg 	    }
   12438  1.1  mrg 	  else
   12439  1.1  mrg 	    {
   12440  1.1  mrg 	      vtab = gfc_find_vtab (&from_expr->ts);
   12441  1.1  mrg 	      gcc_assert (vtab);
   12442  1.1  mrg 	      tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
   12443  1.1  mrg 	      gfc_add_modify_loc (input_location, &block, to_se.expr,
   12444  1.1  mrg 				  fold_convert (TREE_TYPE (to_se.expr), tmp));
   12445  1.1  mrg 	    }
   12446  1.1  mrg 	}
   12447  1.1  mrg 
   12448  1.1  mrg       if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
   12449  1.1  mrg 	{
   12450  1.1  mrg 	  gfc_add_modify_loc (input_location, &block, to_se.string_length,
   12451  1.1  mrg 			      fold_convert (TREE_TYPE (to_se.string_length),
   12452  1.1  mrg 					    from_se.string_length));
   12453  1.1  mrg 	  if (from_expr->ts.deferred)
   12454  1.1  mrg 	    gfc_add_modify_loc (input_location, &block, from_se.string_length,
   12455  1.1  mrg 			build_int_cst (TREE_TYPE (from_se.string_length), 0));
   12456  1.1  mrg 	}
   12457  1.1  mrg 
   12458  1.1  mrg       return gfc_finish_block (&block);
   12459  1.1  mrg     }
   12460  1.1  mrg 
   12461  1.1  mrg   /* Update _vptr component.  */
   12462  1.1  mrg   if (to_expr->ts.type == BT_CLASS)
   12463  1.1  mrg     {
   12464  1.1  mrg       gfc_symbol *vtab;
   12465  1.1  mrg 
   12466  1.1  mrg       to_se.want_pointer = 1;
   12467  1.1  mrg       to_expr2 = gfc_copy_expr (to_expr);
   12468  1.1  mrg       gfc_add_vptr_component (to_expr2);
   12469  1.1  mrg       gfc_conv_expr (&to_se, to_expr2);
   12470  1.1  mrg 
   12471  1.1  mrg       if (from_expr->ts.type == BT_CLASS)
   12472  1.1  mrg 	{
   12473  1.1  mrg 	  if (UNLIMITED_POLY (from_expr))
   12474  1.1  mrg 	    vtab = NULL;
   12475  1.1  mrg 	  else
   12476  1.1  mrg 	    {
   12477  1.1  mrg 	      vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
   12478  1.1  mrg 	      gcc_assert (vtab);
   12479  1.1  mrg 	    }
   12480  1.1  mrg 
   12481  1.1  mrg 	  from_se.want_pointer = 1;
   12482  1.1  mrg 	  from_expr2 = gfc_copy_expr (from_expr);
   12483  1.1  mrg 	  gfc_add_vptr_component (from_expr2);
   12484  1.1  mrg 	  gfc_conv_expr (&from_se, from_expr2);
   12485  1.1  mrg 	  gfc_add_modify_loc (input_location, &block, to_se.expr,
   12486  1.1  mrg 			      fold_convert (TREE_TYPE (to_se.expr),
   12487  1.1  mrg 			      from_se.expr));
   12488  1.1  mrg 
   12489  1.1  mrg 	  /* Reset _vptr component to declared type.  */
   12490  1.1  mrg 	  if (vtab == NULL)
   12491  1.1  mrg 	    /* Unlimited polymorphic.  */
   12492  1.1  mrg 	    gfc_add_modify_loc (input_location, &block, from_se.expr,
   12493  1.1  mrg 				fold_convert (TREE_TYPE (from_se.expr),
   12494  1.1  mrg 					      null_pointer_node));
   12495  1.1  mrg 	  else
   12496  1.1  mrg 	    {
   12497  1.1  mrg 	      tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
   12498  1.1  mrg 	      gfc_add_modify_loc (input_location, &block, from_se.expr,
   12499  1.1  mrg 				  fold_convert (TREE_TYPE (from_se.expr), tmp));
   12500  1.1  mrg 	    }
   12501  1.1  mrg 	}
   12502  1.1  mrg       else
   12503  1.1  mrg 	{
   12504  1.1  mrg 	  vtab = gfc_find_vtab (&from_expr->ts);
   12505  1.1  mrg 	  gcc_assert (vtab);
   12506  1.1  mrg 	  tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
   12507  1.1  mrg 	  gfc_add_modify_loc (input_location, &block, to_se.expr,
   12508  1.1  mrg 			      fold_convert (TREE_TYPE (to_se.expr), tmp));
   12509  1.1  mrg 	}
   12510  1.1  mrg 
   12511  1.1  mrg       gfc_free_expr (to_expr2);
   12512  1.1  mrg       gfc_init_se (&to_se, NULL);
   12513  1.1  mrg 
   12514  1.1  mrg       if (from_expr->ts.type == BT_CLASS)
   12515  1.1  mrg 	{
   12516  1.1  mrg 	  gfc_free_expr (from_expr2);
   12517  1.1  mrg 	  gfc_init_se (&from_se, NULL);
   12518  1.1  mrg 	}
   12519  1.1  mrg     }
   12520  1.1  mrg 
   12521  1.1  mrg 
   12522  1.1  mrg   /* Deallocate "to".  */
   12523  1.1  mrg   if (from_expr->rank == 0)
   12524  1.1  mrg     {
   12525  1.1  mrg       to_se.want_coarray = 1;
   12526  1.1  mrg       from_se.want_coarray = 1;
   12527  1.1  mrg     }
   12528  1.1  mrg   gfc_conv_expr_descriptor (&to_se, to_expr);
   12529  1.1  mrg   gfc_conv_expr_descriptor (&from_se, from_expr);
   12530  1.1  mrg 
   12531  1.1  mrg   /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
   12532  1.1  mrg      is an image control "statement", cf. IR F08/0040 in 12-006A.  */
   12533  1.1  mrg   if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
   12534  1.1  mrg     {
   12535  1.1  mrg       tree cond;
   12536  1.1  mrg 
   12537  1.1  mrg       tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
   12538  1.1  mrg 					NULL_TREE, NULL_TREE, true, to_expr,
   12539  1.1  mrg 					GFC_CAF_COARRAY_DEALLOCATE_ONLY);
   12540  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   12541  1.1  mrg 
   12542  1.1  mrg       tmp = gfc_conv_descriptor_data_get (to_se.expr);
   12543  1.1  mrg       cond = fold_build2_loc (input_location, EQ_EXPR,
   12544  1.1  mrg 			      logical_type_node, tmp,
   12545  1.1  mrg 			      fold_convert (TREE_TYPE (tmp),
   12546  1.1  mrg 					    null_pointer_node));
   12547  1.1  mrg       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
   12548  1.1  mrg 				 3, null_pointer_node, null_pointer_node,
   12549  1.1  mrg 				 build_int_cst (integer_type_node, 0));
   12550  1.1  mrg 
   12551  1.1  mrg       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
   12552  1.1  mrg 			     tmp, build_empty_stmt (input_location));
   12553  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   12554  1.1  mrg     }
   12555  1.1  mrg   else
   12556  1.1  mrg     {
   12557  1.1  mrg       if (to_expr->ts.type == BT_DERIVED
   12558  1.1  mrg 	  && to_expr->ts.u.derived->attr.alloc_comp)
   12559  1.1  mrg 	{
   12560  1.1  mrg 	  tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
   12561  1.1  mrg 					   to_se.expr, to_expr->rank);
   12562  1.1  mrg 	  gfc_add_expr_to_block (&block, tmp);
   12563  1.1  mrg 	}
   12564  1.1  mrg 
   12565  1.1  mrg       tmp = gfc_conv_descriptor_data_get (to_se.expr);
   12566  1.1  mrg       tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
   12567  1.1  mrg 					NULL_TREE, true, to_expr,
   12568  1.1  mrg 					GFC_CAF_COARRAY_NOCOARRAY);
   12569  1.1  mrg       gfc_add_expr_to_block (&block, tmp);
   12570  1.1  mrg     }
   12571  1.1  mrg 
   12572  1.1  mrg   /* Move the pointer and update the array descriptor data.  */
   12573  1.1  mrg   gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
   12574  1.1  mrg 
   12575  1.1  mrg   /* Set "from" to NULL.  */
   12576  1.1  mrg   tmp = gfc_conv_descriptor_data_get (from_se.expr);
   12577  1.1  mrg   gfc_add_modify_loc (input_location, &block, tmp,
   12578  1.1  mrg 		      fold_convert (TREE_TYPE (tmp), null_pointer_node));
   12579  1.1  mrg 
   12580  1.1  mrg 
   12581  1.1  mrg   if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
   12582  1.1  mrg     {
   12583  1.1  mrg       gfc_add_modify_loc (input_location, &block, to_se.string_length,
   12584  1.1  mrg 			  fold_convert (TREE_TYPE (to_se.string_length),
   12585  1.1  mrg 					from_se.string_length));
   12586  1.1  mrg       if (from_expr->ts.deferred)
   12587  1.1  mrg         gfc_add_modify_loc (input_location, &block, from_se.string_length,
   12588  1.1  mrg 			build_int_cst (TREE_TYPE (from_se.string_length), 0));
   12589  1.1  mrg     }
   12590  1.1  mrg 
   12591  1.1  mrg   return gfc_finish_block (&block);
   12592  1.1  mrg }
   12593  1.1  mrg 
   12594  1.1  mrg 
   12595  1.1  mrg tree
   12596  1.1  mrg gfc_conv_intrinsic_subroutine (gfc_code *code)
   12597  1.1  mrg {
   12598  1.1  mrg   tree res;
   12599  1.1  mrg 
   12600  1.1  mrg   gcc_assert (code->resolved_isym);
   12601  1.1  mrg 
   12602  1.1  mrg   switch (code->resolved_isym->id)
   12603  1.1  mrg     {
   12604  1.1  mrg     case GFC_ISYM_MOVE_ALLOC:
   12605  1.1  mrg       res = conv_intrinsic_move_alloc (code);
   12606  1.1  mrg       break;
   12607  1.1  mrg 
   12608  1.1  mrg     case GFC_ISYM_ATOMIC_CAS:
   12609  1.1  mrg       res = conv_intrinsic_atomic_cas (code);
   12610  1.1  mrg       break;
   12611  1.1  mrg 
   12612  1.1  mrg     case GFC_ISYM_ATOMIC_ADD:
   12613  1.1  mrg     case GFC_ISYM_ATOMIC_AND:
   12614  1.1  mrg     case GFC_ISYM_ATOMIC_DEF:
   12615  1.1  mrg     case GFC_ISYM_ATOMIC_OR:
   12616  1.1  mrg     case GFC_ISYM_ATOMIC_XOR:
   12617  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_ADD:
   12618  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_AND:
   12619  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_OR:
   12620  1.1  mrg     case GFC_ISYM_ATOMIC_FETCH_XOR:
   12621  1.1  mrg       res = conv_intrinsic_atomic_op (code);
   12622  1.1  mrg       break;
   12623  1.1  mrg 
   12624  1.1  mrg     case GFC_ISYM_ATOMIC_REF:
   12625  1.1  mrg       res = conv_intrinsic_atomic_ref (code);
   12626  1.1  mrg       break;
   12627  1.1  mrg 
   12628  1.1  mrg     case GFC_ISYM_EVENT_QUERY:
   12629  1.1  mrg       res = conv_intrinsic_event_query (code);
   12630  1.1  mrg       break;
   12631  1.1  mrg 
   12632  1.1  mrg     case GFC_ISYM_C_F_POINTER:
   12633  1.1  mrg     case GFC_ISYM_C_F_PROCPOINTER:
   12634  1.1  mrg       res = conv_isocbinding_subroutine (code);
   12635  1.1  mrg       break;
   12636  1.1  mrg 
   12637  1.1  mrg     case GFC_ISYM_CAF_SEND:
   12638  1.1  mrg       res = conv_caf_send (code);
   12639  1.1  mrg       break;
   12640  1.1  mrg 
   12641  1.1  mrg     case GFC_ISYM_CO_BROADCAST:
   12642  1.1  mrg     case GFC_ISYM_CO_MIN:
   12643  1.1  mrg     case GFC_ISYM_CO_MAX:
   12644  1.1  mrg     case GFC_ISYM_CO_REDUCE:
   12645  1.1  mrg     case GFC_ISYM_CO_SUM:
   12646  1.1  mrg       res = conv_co_collective (code);
   12647  1.1  mrg       break;
   12648  1.1  mrg 
   12649  1.1  mrg     case GFC_ISYM_FREE:
   12650  1.1  mrg       res = conv_intrinsic_free (code);
   12651  1.1  mrg       break;
   12652  1.1  mrg 
   12653  1.1  mrg     case GFC_ISYM_RANDOM_INIT:
   12654  1.1  mrg       res = conv_intrinsic_random_init (code);
   12655  1.1  mrg       break;
   12656  1.1  mrg 
   12657  1.1  mrg     case GFC_ISYM_KILL:
   12658  1.1  mrg       res = conv_intrinsic_kill_sub (code);
   12659  1.1  mrg       break;
   12660  1.1  mrg 
   12661  1.1  mrg     case GFC_ISYM_MVBITS:
   12662  1.1  mrg       res = NULL_TREE;
   12663  1.1  mrg       break;
   12664  1.1  mrg 
   12665  1.1  mrg     case GFC_ISYM_SYSTEM_CLOCK:
   12666  1.1  mrg       res = conv_intrinsic_system_clock (code);
   12667  1.1  mrg       break;
   12668  1.1  mrg 
   12669  1.1  mrg     default:
   12670  1.1  mrg       res = NULL_TREE;
   12671  1.1  mrg       break;
   12672  1.1  mrg     }
   12673  1.1  mrg 
   12674  1.1  mrg   return res;
   12675  1.1  mrg }
   12676  1.1  mrg 
   12677  1.1  mrg #include "gt-fortran-trans-intrinsic.h"
   12678