aarch64: Fix sve/acle/general/ldff1_8.c failures
[official-gcc.git] / gcc / fortran / trans-intrinsic.cc
blob51237d0d3be6fd8c3e9d53ad8b5d00665109d7d0
1 /* Intrinsic translation
2 Copyright (C) 2002-2025 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "memmodel.h"
28 #include "tm.h" /* For UNITS_PER_WORD. */
29 #include "tree.h"
30 #include "gfortran.h"
31 #include "trans.h"
32 #include "stringpool.h"
33 #include "fold-const.h"
34 #include "internal-fn.h"
35 #include "tree-nested.h"
36 #include "stor-layout.h"
37 #include "toplev.h" /* For rest_of_decl_compilation. */
38 #include "arith.h"
39 #include "trans-const.h"
40 #include "trans-types.h"
41 #include "trans-array.h"
42 #include "dependency.h" /* For CAF array alias analysis. */
43 #include "attribs.h"
44 #include "realmpfr.h"
45 #include "constructor.h"
47 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
49 /* This maps Fortran intrinsic math functions to external library or GCC
50 builtin functions. */
51 typedef struct GTY(()) gfc_intrinsic_map_t {
52 /* The explicit enum is required to work around inadequacies in the
53 garbage collection/gengtype parsing mechanism. */
54 enum gfc_isym_id id;
56 /* Enum value from the "language-independent", aka C-centric, part
57 of gcc, or END_BUILTINS of no such value set. */
58 enum built_in_function float_built_in;
59 enum built_in_function double_built_in;
60 enum built_in_function long_double_built_in;
61 enum built_in_function complex_float_built_in;
62 enum built_in_function complex_double_built_in;
63 enum built_in_function complex_long_double_built_in;
65 /* True if the naming pattern is to prepend "c" for complex and
66 append "f" for kind=4. False if the naming pattern is to
67 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
68 bool libm_name;
70 /* True if a complex version of the function exists. */
71 bool complex_available;
73 /* True if the function should be marked const. */
74 bool is_constant;
76 /* The base library name of this function. */
77 const char *name;
79 /* Cache decls created for the various operand types. */
80 tree real4_decl;
81 tree real8_decl;
82 tree real10_decl;
83 tree real16_decl;
84 tree complex4_decl;
85 tree complex8_decl;
86 tree complex10_decl;
87 tree complex16_decl;
89 gfc_intrinsic_map_t;
91 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
92 defines complex variants of all of the entries in mathbuiltins.def
93 except for atan2. */
94 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
95 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
96 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
97 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
98 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
100 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
101 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
102 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
103 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
104 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
106 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
107 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
109 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
110 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
112 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
113 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
114 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
115 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
116 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
118 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
120 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
121 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
122 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
123 #include "mathbuiltins.def"
125 /* Functions in libgfortran. */
126 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
127 LIB_FUNCTION (SIND, "sind", false),
128 LIB_FUNCTION (COSD, "cosd", false),
129 LIB_FUNCTION (TAND, "tand", false),
131 /* End the list. */
132 LIB_FUNCTION (NONE, NULL, false)
135 #undef OTHER_BUILTIN
136 #undef LIB_FUNCTION
137 #undef DEFINE_MATH_BUILTIN
138 #undef DEFINE_MATH_BUILTIN_C
141 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
144 /* Find the correct variant of a given builtin from its argument. */
145 static tree
146 builtin_decl_for_precision (enum built_in_function base_built_in,
147 int precision)
149 enum built_in_function i = END_BUILTINS;
151 gfc_intrinsic_map_t *m;
152 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
155 if (precision == TYPE_PRECISION (float_type_node))
156 i = m->float_built_in;
157 else if (precision == TYPE_PRECISION (double_type_node))
158 i = m->double_built_in;
159 else if (precision == TYPE_PRECISION (long_double_type_node)
160 && (!gfc_real16_is_float128
161 || long_double_type_node != gfc_float128_type_node))
162 i = m->long_double_built_in;
163 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
165 /* Special treatment, because it is not exactly a built-in, but
166 a library function. */
167 return m->real16_decl;
170 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
174 tree
175 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
176 int kind)
178 int i = gfc_validate_kind (BT_REAL, kind, false);
180 if (gfc_real_kinds[i].c_float128)
182 /* For _Float128, the story is a bit different, because we return
183 a decl to a library function rather than a built-in. */
184 gfc_intrinsic_map_t *m;
185 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
188 return m->real16_decl;
191 return builtin_decl_for_precision (double_built_in,
192 gfc_real_kinds[i].mode_precision);
196 /* Evaluate the arguments to an intrinsic function. The value
197 of NARGS may be less than the actual number of arguments in EXPR
198 to allow optional "KIND" arguments that are not included in the
199 generated code to be ignored. */
201 static void
202 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
203 tree *argarray, int nargs)
205 gfc_actual_arglist *actual;
206 gfc_expr *e;
207 gfc_intrinsic_arg *formal;
208 gfc_se argse;
209 int curr_arg;
211 formal = expr->value.function.isym->formal;
212 actual = expr->value.function.actual;
214 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
215 actual = actual->next,
216 formal = formal ? formal->next : NULL)
218 gcc_assert (actual);
219 e = actual->expr;
220 /* Skip omitted optional arguments. */
221 if (!e)
223 --curr_arg;
224 continue;
227 /* Evaluate the parameter. This will substitute scalarized
228 references automatically. */
229 gfc_init_se (&argse, se);
231 if (e->ts.type == BT_CHARACTER)
233 gfc_conv_expr (&argse, e);
234 gfc_conv_string_parameter (&argse);
235 argarray[curr_arg++] = argse.string_length;
236 gcc_assert (curr_arg < nargs);
238 else
239 gfc_conv_expr_val (&argse, e);
241 /* If an optional argument is itself an optional dummy argument,
242 check its presence and substitute a null if absent. */
243 if (e->expr_type == EXPR_VARIABLE
244 && e->symtree->n.sym->attr.optional
245 && formal
246 && formal->optional)
247 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
249 gfc_add_block_to_block (&se->pre, &argse.pre);
250 gfc_add_block_to_block (&se->post, &argse.post);
251 argarray[curr_arg] = argse.expr;
255 /* Count the number of actual arguments to the intrinsic function EXPR
256 including any "hidden" string length arguments. */
258 static unsigned int
259 gfc_intrinsic_argument_list_length (gfc_expr *expr)
261 int n = 0;
262 gfc_actual_arglist *actual;
264 for (actual = expr->value.function.actual; actual; actual = actual->next)
266 if (!actual->expr)
267 continue;
269 if (actual->expr->ts.type == BT_CHARACTER)
270 n += 2;
271 else
272 n++;
275 return n;
279 /* Conversions between different types are output by the frontend as
280 intrinsic functions. We implement these directly with inline code. */
282 static void
283 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
285 tree type;
286 tree *args;
287 int nargs;
289 nargs = gfc_intrinsic_argument_list_length (expr);
290 args = XALLOCAVEC (tree, nargs);
292 /* Evaluate all the arguments passed. Whilst we're only interested in the
293 first one here, there are other parts of the front-end that assume this
294 and will trigger an ICE if it's not the case. */
295 type = gfc_typenode_for_spec (&expr->ts);
296 gcc_assert (expr->value.function.actual->expr);
297 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
299 /* Conversion between character kinds involves a call to a library
300 function. */
301 if (expr->ts.type == BT_CHARACTER)
303 tree fndecl, var, addr, tmp;
305 if (expr->ts.kind == 1
306 && expr->value.function.actual->expr->ts.kind == 4)
307 fndecl = gfor_fndecl_convert_char4_to_char1;
308 else if (expr->ts.kind == 4
309 && expr->value.function.actual->expr->ts.kind == 1)
310 fndecl = gfor_fndecl_convert_char1_to_char4;
311 else
312 gcc_unreachable ();
314 /* Create the variable storing the converted value. */
315 type = gfc_get_pchar_type (expr->ts.kind);
316 var = gfc_create_var (type, "str");
317 addr = gfc_build_addr_expr (build_pointer_type (type), var);
319 /* Call the library function that will perform the conversion. */
320 gcc_assert (nargs >= 2);
321 tmp = build_call_expr_loc (input_location,
322 fndecl, 3, addr, args[0], args[1]);
323 gfc_add_expr_to_block (&se->pre, tmp);
325 /* Free the temporary afterwards. */
326 tmp = gfc_call_free (var);
327 gfc_add_expr_to_block (&se->post, tmp);
329 se->expr = var;
330 se->string_length = args[0];
332 return;
335 /* Conversion from complex to non-complex involves taking the real
336 component of the value. */
337 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
338 && expr->ts.type != BT_COMPLEX)
340 tree artype;
342 artype = TREE_TYPE (TREE_TYPE (args[0]));
343 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
344 args[0]);
347 se->expr = convert (type, args[0]);
350 /* This is needed because the gcc backend only implements
351 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
352 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
353 Similarly for CEILING. */
355 static tree
356 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
358 tree tmp;
359 tree cond;
360 tree argtype;
361 tree intval;
363 argtype = TREE_TYPE (arg);
364 arg = gfc_evaluate_now (arg, pblock);
366 intval = convert (type, arg);
367 intval = gfc_evaluate_now (intval, pblock);
369 tmp = convert (argtype, intval);
370 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
371 logical_type_node, tmp, arg);
373 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
374 intval, build_int_cst (type, 1));
375 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
376 return tmp;
380 /* Round to nearest integer, away from zero. */
382 static tree
383 build_round_expr (tree arg, tree restype)
385 tree argtype;
386 tree fn;
387 int argprec, resprec;
389 argtype = TREE_TYPE (arg);
390 argprec = TYPE_PRECISION (argtype);
391 resprec = TYPE_PRECISION (restype);
393 /* Depending on the type of the result, choose the int intrinsic (iround,
394 available only as a builtin, therefore cannot use it for _Float128), long
395 int intrinsic (lround family) or long long intrinsic (llround). If we
396 don't have an appropriate function that converts directly to the integer
397 type (such as kind == 16), just use ROUND, and then convert the result to
398 an integer. We might also need to convert the result afterwards. */
399 if (resprec <= INT_TYPE_SIZE
400 && argprec <= TYPE_PRECISION (long_double_type_node))
401 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
402 else if (resprec <= LONG_TYPE_SIZE)
403 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
404 else if (resprec <= LONG_LONG_TYPE_SIZE)
405 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
406 else if (resprec >= argprec)
407 fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
408 else
409 gcc_unreachable ();
411 return convert (restype, build_call_expr_loc (input_location,
412 fn, 1, arg));
416 /* Convert a real to an integer using a specific rounding mode.
417 Ideally we would just build the corresponding GENERIC node,
418 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
420 static tree
421 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
422 enum rounding_mode op)
424 switch (op)
426 case RND_FLOOR:
427 return build_fixbound_expr (pblock, arg, type, 0);
429 case RND_CEIL:
430 return build_fixbound_expr (pblock, arg, type, 1);
432 case RND_ROUND:
433 return build_round_expr (arg, type);
435 case RND_TRUNC:
436 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
438 default:
439 gcc_unreachable ();
444 /* Round a real value using the specified rounding mode.
445 We use a temporary integer of that same kind size as the result.
446 Values larger than those that can be represented by this kind are
447 unchanged, as they will not be accurate enough to represent the
448 rounding.
449 huge = HUGE (KIND (a))
450 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
453 static void
454 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
456 tree type;
457 tree itype;
458 tree arg[2];
459 tree tmp;
460 tree cond;
461 tree decl;
462 mpfr_t huge;
463 int n, nargs;
464 int kind;
466 kind = expr->ts.kind;
467 nargs = gfc_intrinsic_argument_list_length (expr);
469 decl = NULL_TREE;
470 /* We have builtin functions for some cases. */
471 switch (op)
473 case RND_ROUND:
474 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
475 break;
477 case RND_TRUNC:
478 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
479 break;
481 default:
482 gcc_unreachable ();
485 /* Evaluate the argument. */
486 gcc_assert (expr->value.function.actual->expr);
487 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
489 /* Use a builtin function if one exists. */
490 if (decl != NULL_TREE)
492 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
493 return;
496 /* This code is probably redundant, but we'll keep it lying around just
497 in case. */
498 type = gfc_typenode_for_spec (&expr->ts);
499 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
501 /* Test if the value is too large to handle sensibly. */
502 gfc_set_model_kind (kind);
503 mpfr_init (huge);
504 n = gfc_validate_kind (BT_INTEGER, kind, false);
505 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
506 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
507 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
508 tmp);
510 mpfr_neg (huge, huge, GFC_RND_MODE);
511 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
512 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
513 tmp);
514 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
515 cond, tmp);
516 itype = gfc_get_int_type (kind);
518 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
519 tmp = convert (type, tmp);
520 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
521 arg[0]);
522 mpfr_clear (huge);
526 /* Convert to an integer using the specified rounding mode. */
528 static void
529 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
531 tree type;
532 tree *args;
533 int nargs;
535 nargs = gfc_intrinsic_argument_list_length (expr);
536 args = XALLOCAVEC (tree, nargs);
538 /* Evaluate the argument, we process all arguments even though we only
539 use the first one for code generation purposes. */
540 type = gfc_typenode_for_spec (&expr->ts);
541 gcc_assert (expr->value.function.actual->expr);
542 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
544 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
546 /* Conversion to a different integer kind. */
547 se->expr = convert (type, args[0]);
549 else
551 /* Conversion from complex to non-complex involves taking the real
552 component of the value. */
553 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
554 && expr->ts.type != BT_COMPLEX)
556 tree artype;
558 artype = TREE_TYPE (TREE_TYPE (args[0]));
559 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
560 args[0]);
563 se->expr = build_fix_expr (&se->pre, args[0], type, op);
568 /* Get the imaginary component of a value. */
570 static void
571 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
573 tree arg;
575 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
576 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
577 TREE_TYPE (TREE_TYPE (arg)), arg);
581 /* Get the complex conjugate of a value. */
583 static void
584 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
586 tree arg;
588 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
589 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
594 static tree
595 define_quad_builtin (const char *name, tree type, bool is_const)
597 tree fndecl;
598 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
599 type);
601 /* Mark the decl as external. */
602 DECL_EXTERNAL (fndecl) = 1;
603 TREE_PUBLIC (fndecl) = 1;
605 /* Mark it __attribute__((const)). */
606 TREE_READONLY (fndecl) = is_const;
608 rest_of_decl_compilation (fndecl, 1, 0);
610 return fndecl;
613 /* Add SIMD attribute for FNDECL built-in if the built-in
614 name is in VECTORIZED_BUILTINS. */
616 static void
617 add_simd_flag_for_built_in (tree fndecl)
619 if (gfc_vectorized_builtins == NULL
620 || fndecl == NULL_TREE)
621 return;
623 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
624 int *clauses = gfc_vectorized_builtins->get (name);
625 if (clauses)
627 for (unsigned i = 0; i < 3; i++)
628 if (*clauses & (1 << i))
630 gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
631 tree omp_clause = NULL_TREE;
632 if (simd_type == SIMD_NONE)
633 ; /* No SIMD clause. */
634 else
636 omp_clause_code code
637 = (simd_type == SIMD_INBRANCH
638 ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
639 omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
640 omp_clause = build_tree_list (NULL_TREE, omp_clause);
643 DECL_ATTRIBUTES (fndecl)
644 = tree_cons (get_identifier ("omp declare simd"), omp_clause,
645 DECL_ATTRIBUTES (fndecl));
650 /* Set SIMD attribute to all built-in functions that are mentioned
651 in gfc_vectorized_builtins vector. */
653 void
654 gfc_adjust_builtins (void)
656 gfc_intrinsic_map_t *m;
657 for (m = gfc_intrinsic_map;
658 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
660 add_simd_flag_for_built_in (m->real4_decl);
661 add_simd_flag_for_built_in (m->complex4_decl);
662 add_simd_flag_for_built_in (m->real8_decl);
663 add_simd_flag_for_built_in (m->complex8_decl);
664 add_simd_flag_for_built_in (m->real10_decl);
665 add_simd_flag_for_built_in (m->complex10_decl);
666 add_simd_flag_for_built_in (m->real16_decl);
667 add_simd_flag_for_built_in (m->complex16_decl);
668 add_simd_flag_for_built_in (m->real16_decl);
669 add_simd_flag_for_built_in (m->complex16_decl);
672 /* Release all strings. */
673 if (gfc_vectorized_builtins != NULL)
675 for (hash_map<nofree_string_hash, int>::iterator it
676 = gfc_vectorized_builtins->begin ();
677 it != gfc_vectorized_builtins->end (); ++it)
678 free (CONST_CAST (char *, (*it).first));
680 delete gfc_vectorized_builtins;
681 gfc_vectorized_builtins = NULL;
685 /* Initialize function decls for library functions. The external functions
686 are created as required. Builtin functions are added here. */
688 void
689 gfc_build_intrinsic_lib_fndecls (void)
691 gfc_intrinsic_map_t *m;
692 tree quad_decls[END_BUILTINS + 1];
694 if (gfc_real16_is_float128)
696 /* If we have soft-float types, we create the decls for their
697 C99-like library functions. For now, we only handle _Float128
698 q-suffixed or IEC 60559 f128-suffixed functions. */
700 tree type, complex_type, func_1, func_2, func_3, func_cabs, func_frexp;
701 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
703 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
705 type = gfc_float128_type_node;
706 complex_type = gfc_complex_float128_type_node;
707 /* type (*) (type) */
708 func_1 = build_function_type_list (type, type, NULL_TREE);
709 /* int (*) (type) */
710 func_iround = build_function_type_list (integer_type_node,
711 type, NULL_TREE);
712 /* long (*) (type) */
713 func_lround = build_function_type_list (long_integer_type_node,
714 type, NULL_TREE);
715 /* long long (*) (type) */
716 func_llround = build_function_type_list (long_long_integer_type_node,
717 type, NULL_TREE);
718 /* type (*) (type, type) */
719 func_2 = build_function_type_list (type, type, type, NULL_TREE);
720 /* type (*) (type, type, type) */
721 func_3 = build_function_type_list (type, type, type, type, NULL_TREE);
722 /* type (*) (type, &int) */
723 func_frexp
724 = build_function_type_list (type,
725 type,
726 build_pointer_type (integer_type_node),
727 NULL_TREE);
728 /* type (*) (type, int) */
729 func_scalbn = build_function_type_list (type,
730 type, integer_type_node, NULL_TREE);
731 /* type (*) (complex type) */
732 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
733 /* complex type (*) (complex type, complex type) */
734 func_cpow
735 = build_function_type_list (complex_type,
736 complex_type, complex_type, NULL_TREE);
738 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
739 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
740 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
742 /* Only these built-ins are actually needed here. These are used directly
743 from the code, when calling builtin_decl_for_precision() or
744 builtin_decl_for_float_type(). The others are all constructed by
745 gfc_get_intrinsic_lib_fndecl(). */
746 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
747 quad_decls[BUILT_IN_ ## ID] \
748 = define_quad_builtin (gfc_real16_use_iec_60559 \
749 ? NAME "f128" : NAME "q", func_ ## TYPE, \
750 CONST);
752 #include "mathbuiltins.def"
754 #undef OTHER_BUILTIN
755 #undef LIB_FUNCTION
756 #undef DEFINE_MATH_BUILTIN
757 #undef DEFINE_MATH_BUILTIN_C
759 /* There is one built-in we defined manually, because it gets called
760 with builtin_decl_for_precision() or builtin_decl_for_float_type()
761 even though it is not an OTHER_BUILTIN: it is SQRT. */
762 quad_decls[BUILT_IN_SQRT]
763 = define_quad_builtin (gfc_real16_use_iec_60559
764 ? "sqrtf128" : "sqrtq", func_1, true);
767 /* Add GCC builtin functions. */
768 for (m = gfc_intrinsic_map;
769 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
771 if (m->float_built_in != END_BUILTINS)
772 m->real4_decl = builtin_decl_explicit (m->float_built_in);
773 if (m->complex_float_built_in != END_BUILTINS)
774 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
775 if (m->double_built_in != END_BUILTINS)
776 m->real8_decl = builtin_decl_explicit (m->double_built_in);
777 if (m->complex_double_built_in != END_BUILTINS)
778 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
780 /* If real(kind=10) exists, it is always long double. */
781 if (m->long_double_built_in != END_BUILTINS)
782 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
783 if (m->complex_long_double_built_in != END_BUILTINS)
784 m->complex10_decl
785 = builtin_decl_explicit (m->complex_long_double_built_in);
787 if (!gfc_real16_is_float128)
789 if (m->long_double_built_in != END_BUILTINS)
790 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
791 if (m->complex_long_double_built_in != END_BUILTINS)
792 m->complex16_decl
793 = builtin_decl_explicit (m->complex_long_double_built_in);
795 else if (quad_decls[m->double_built_in] != NULL_TREE)
797 /* Quad-precision function calls are constructed when first
798 needed by builtin_decl_for_precision(), except for those
799 that will be used directly (define by OTHER_BUILTIN). */
800 m->real16_decl = quad_decls[m->double_built_in];
802 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
804 /* Same thing for the complex ones. */
805 m->complex16_decl = quad_decls[m->double_built_in];
811 /* Create a fndecl for a simple intrinsic library function. */
813 static tree
814 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
816 tree type;
817 vec<tree, va_gc> *argtypes;
818 tree fndecl;
819 gfc_actual_arglist *actual;
820 tree *pdecl;
821 gfc_typespec *ts;
822 char name[GFC_MAX_SYMBOL_LEN + 3];
824 ts = &expr->ts;
825 if (ts->type == BT_REAL)
827 switch (ts->kind)
829 case 4:
830 pdecl = &m->real4_decl;
831 break;
832 case 8:
833 pdecl = &m->real8_decl;
834 break;
835 case 10:
836 pdecl = &m->real10_decl;
837 break;
838 case 16:
839 pdecl = &m->real16_decl;
840 break;
841 default:
842 gcc_unreachable ();
845 else if (ts->type == BT_COMPLEX)
847 gcc_assert (m->complex_available);
849 switch (ts->kind)
851 case 4:
852 pdecl = &m->complex4_decl;
853 break;
854 case 8:
855 pdecl = &m->complex8_decl;
856 break;
857 case 10:
858 pdecl = &m->complex10_decl;
859 break;
860 case 16:
861 pdecl = &m->complex16_decl;
862 break;
863 default:
864 gcc_unreachable ();
867 else
868 gcc_unreachable ();
870 if (*pdecl)
871 return *pdecl;
873 if (m->libm_name)
875 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
876 if (gfc_real_kinds[n].c_float)
877 snprintf (name, sizeof (name), "%s%s%s",
878 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
879 else if (gfc_real_kinds[n].c_double)
880 snprintf (name, sizeof (name), "%s%s",
881 ts->type == BT_COMPLEX ? "c" : "", m->name);
882 else if (gfc_real_kinds[n].c_long_double)
883 snprintf (name, sizeof (name), "%s%s%s",
884 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
885 else if (gfc_real_kinds[n].c_float128)
886 snprintf (name, sizeof (name), "%s%s%s",
887 ts->type == BT_COMPLEX ? "c" : "", m->name,
888 gfc_real_kinds[n].use_iec_60559 ? "f128" : "q");
889 else
890 gcc_unreachable ();
892 else
894 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
895 ts->type == BT_COMPLEX ? 'c' : 'r',
896 gfc_type_abi_kind (ts));
899 argtypes = NULL;
900 for (actual = expr->value.function.actual; actual; actual = actual->next)
902 type = gfc_typenode_for_spec (&actual->expr->ts);
903 vec_safe_push (argtypes, type);
905 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
906 fndecl = build_decl (input_location,
907 FUNCTION_DECL, get_identifier (name), type);
909 /* Mark the decl as external. */
910 DECL_EXTERNAL (fndecl) = 1;
911 TREE_PUBLIC (fndecl) = 1;
913 /* Mark it __attribute__((const)), if possible. */
914 TREE_READONLY (fndecl) = m->is_constant;
916 rest_of_decl_compilation (fndecl, 1, 0);
918 (*pdecl) = fndecl;
919 return fndecl;
923 /* Convert an intrinsic function into an external or builtin call. */
925 static void
926 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
928 gfc_intrinsic_map_t *m;
929 tree fndecl;
930 tree rettype;
931 tree *args;
932 unsigned int num_args;
933 gfc_isym_id id;
935 id = expr->value.function.isym->id;
936 /* Find the entry for this function. */
937 for (m = gfc_intrinsic_map;
938 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
940 if (id == m->id)
941 break;
944 if (m->id == GFC_ISYM_NONE)
946 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
947 expr->value.function.name, id);
950 /* Get the decl and generate the call. */
951 num_args = gfc_intrinsic_argument_list_length (expr);
952 args = XALLOCAVEC (tree, num_args);
954 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
955 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
956 rettype = TREE_TYPE (TREE_TYPE (fndecl));
958 fndecl = build_addr (fndecl);
959 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
963 /* If bounds-checking is enabled, create code to verify at runtime that the
964 string lengths for both expressions are the same (needed for e.g. MERGE).
965 If bounds-checking is not enabled, does nothing. */
967 void
968 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
969 tree a, tree b, stmtblock_t* target)
971 tree cond;
972 tree name;
974 /* If bounds-checking is disabled, do nothing. */
975 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
976 return;
978 /* Compare the two string lengths. */
979 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
981 /* Output the runtime-check. */
982 name = gfc_build_cstring_const (intr_name);
983 name = gfc_build_addr_expr (pchar_type_node, name);
984 gfc_trans_runtime_check (true, false, cond, target, where,
985 "Unequal character lengths (%ld/%ld) in %s",
986 fold_convert (long_integer_type_node, a),
987 fold_convert (long_integer_type_node, b), name);
991 /* The EXPONENT(X) intrinsic function is translated into
992 int ret;
993 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
994 so that if X is a NaN or infinity, the result is HUGE(0).
997 static void
998 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
1000 tree arg, type, res, tmp, frexp, cond, huge;
1001 int i;
1003 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
1004 expr->value.function.actual->expr->ts.kind);
1006 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1007 arg = gfc_evaluate_now (arg, &se->pre);
1009 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
1010 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
1011 cond = build_call_expr_loc (input_location,
1012 builtin_decl_explicit (BUILT_IN_ISFINITE),
1013 1, arg);
1015 res = gfc_create_var (integer_type_node, NULL);
1016 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
1017 gfc_build_addr_expr (NULL_TREE, res));
1018 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
1019 tmp, res);
1020 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
1021 cond, tmp, huge);
1023 type = gfc_typenode_for_spec (&expr->ts);
1024 se->expr = fold_convert (type, se->expr);
1028 /* Fill in the following structure
1029 struct caf_vector_t {
1030 size_t nvec; // size of the vector
1031 union {
1032 struct {
1033 void *vector;
1034 int kind;
1035 } v;
1036 struct {
1037 ptrdiff_t lower_bound;
1038 ptrdiff_t upper_bound;
1039 ptrdiff_t stride;
1040 } triplet;
1041 } u;
1042 } */
1044 static void
1045 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1046 tree lower, tree upper, tree stride,
1047 tree vector, int kind, tree nvec)
1049 tree field, type, tmp;
1051 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
1052 type = TREE_TYPE (desc);
1054 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1055 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1056 desc, field, NULL_TREE);
1057 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
1059 /* Access union. */
1060 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1061 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1062 desc, field, NULL_TREE);
1063 type = TREE_TYPE (desc);
1065 /* Access the inner struct. */
1066 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
1067 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1068 desc, field, NULL_TREE);
1069 type = TREE_TYPE (desc);
1071 if (vector != NULL_TREE)
1073 /* Set vector and kind. */
1074 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1075 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1076 desc, field, NULL_TREE);
1077 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
1078 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1079 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1080 desc, field, NULL_TREE);
1081 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1083 else
1085 /* Set dim.lower/upper/stride. */
1086 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1087 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1088 desc, field, NULL_TREE);
1089 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1091 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1092 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1093 desc, field, NULL_TREE);
1094 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1096 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1097 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1098 desc, field, NULL_TREE);
1099 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1104 static tree
1105 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1107 gfc_se argse;
1108 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1109 tree lbound, ubound, tmp;
1110 int i;
1112 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1114 for (i = 0; i < ar->dimen; i++)
1115 switch (ar->dimen_type[i])
1117 case DIMEN_RANGE:
1118 if (ar->end[i])
1120 gfc_init_se (&argse, NULL);
1121 gfc_conv_expr (&argse, ar->end[i]);
1122 gfc_add_block_to_block (block, &argse.pre);
1123 upper = gfc_evaluate_now (argse.expr, block);
1125 else
1126 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1127 if (ar->stride[i])
1129 gfc_init_se (&argse, NULL);
1130 gfc_conv_expr (&argse, ar->stride[i]);
1131 gfc_add_block_to_block (block, &argse.pre);
1132 stride = gfc_evaluate_now (argse.expr, block);
1134 else
1135 stride = gfc_index_one_node;
1137 /* Fall through. */
1138 case DIMEN_ELEMENT:
1139 if (ar->start[i])
1141 gfc_init_se (&argse, NULL);
1142 gfc_conv_expr (&argse, ar->start[i]);
1143 gfc_add_block_to_block (block, &argse.pre);
1144 lower = gfc_evaluate_now (argse.expr, block);
1146 else
1147 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1148 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1150 upper = lower;
1151 stride = gfc_index_one_node;
1153 vector = NULL_TREE;
1154 nvec = size_zero_node;
1155 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1156 vector, 0, nvec);
1157 break;
1159 case DIMEN_VECTOR:
1160 gfc_init_se (&argse, NULL);
1161 argse.descriptor_only = 1;
1162 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1163 gfc_add_block_to_block (block, &argse.pre);
1164 vector = argse.expr;
1165 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1166 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1167 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1168 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1169 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1170 TREE_TYPE (nvec), nvec, tmp);
1171 lower = gfc_index_zero_node;
1172 upper = gfc_index_zero_node;
1173 stride = gfc_index_zero_node;
1174 vector = gfc_conv_descriptor_data_get (vector);
1175 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1176 vector, ar->start[i]->ts.kind, nvec);
1177 break;
1178 default:
1179 gcc_unreachable();
1181 return gfc_build_addr_expr (NULL_TREE, var);
1185 static tree
1186 compute_component_offset (tree field, tree type)
1188 tree tmp;
1189 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1190 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1192 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1193 DECL_FIELD_BIT_OFFSET (field),
1194 bitsize_unit_node);
1195 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1197 else
1198 return DECL_FIELD_OFFSET (field);
1202 static tree
1203 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1205 gfc_ref *ref = expr->ref, *last_comp_ref;
1206 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1207 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1208 start, end, stride, vector, nvec;
1209 gfc_se se;
1210 bool ref_static_array = false;
1211 tree last_component_ref_tree = NULL_TREE;
1212 int i, last_type_n;
1214 if (expr->symtree)
1216 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1217 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1218 && !expr->symtree->n.sym->attr.pointer;
1221 /* Prevent uninit-warning. */
1222 reference_type = NULL_TREE;
1224 /* Skip refs upto the first coarray-ref. */
1225 last_comp_ref = NULL;
1226 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1228 /* Remember the type of components skipped. */
1229 if (ref->type == REF_COMPONENT)
1230 last_comp_ref = ref;
1231 ref = ref->next;
1233 /* When a component was skipped, get the type information of the last
1234 component ref, else get the type from the symbol. */
1235 if (last_comp_ref)
1237 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1238 last_type_n = last_comp_ref->u.c.component->ts.type;
1240 else
1242 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1243 last_type_n = expr->symtree->n.sym->ts.type;
1246 while (ref)
1248 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1249 && ref->u.ar.dimen == 0)
1251 /* Skip pure coindexes. */
1252 ref = ref->next;
1253 continue;
1255 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1256 reference_type = TREE_TYPE (tmp);
1258 if (caf_ref == NULL_TREE)
1259 caf_ref = tmp;
1261 /* Construct the chain of refs. */
1262 if (prev_caf_ref != NULL_TREE)
1264 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1265 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1266 TREE_TYPE (field), prev_caf_ref, field,
1267 NULL_TREE);
1268 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1269 tmp));
1271 prev_caf_ref = tmp;
1273 switch (ref->type)
1275 case REF_COMPONENT:
1276 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1277 last_type_n = ref->u.c.component->ts.type;
1278 /* Set the type of the ref. */
1279 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1280 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1281 TREE_TYPE (field), prev_caf_ref, field,
1282 NULL_TREE);
1283 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1284 GFC_CAF_REF_COMPONENT));
1286 /* Ref the c in union u. */
1287 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1288 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1289 TREE_TYPE (field), prev_caf_ref, field,
1290 NULL_TREE);
1291 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1292 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1293 TREE_TYPE (field), tmp, field,
1294 NULL_TREE);
1296 /* Set the offset. */
1297 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1298 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1299 TREE_TYPE (field), inner_struct, field,
1300 NULL_TREE);
1301 /* Computing the offset is somewhat harder. The bit_offset has to be
1302 taken into account. When the bit_offset in the field_decl is non-
1303 null, divide it by the bitsize_unit and add it to the regular
1304 offset. */
1305 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1306 TREE_TYPE (tmp));
1307 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1309 /* Set caf_token_offset. */
1310 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1311 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1312 TREE_TYPE (field), inner_struct, field,
1313 NULL_TREE);
1314 if ((ref->u.c.component->attr.allocatable
1315 || ref->u.c.component->attr.pointer)
1316 && ref->u.c.component->attr.dimension)
1318 tree arr_desc_token_offset;
1319 /* Get the token field from the descriptor. */
1320 arr_desc_token_offset = TREE_OPERAND (
1321 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1322 arr_desc_token_offset
1323 = compute_component_offset (arr_desc_token_offset,
1324 TREE_TYPE (tmp));
1325 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1326 TREE_TYPE (tmp2), tmp2,
1327 arr_desc_token_offset);
1329 else if (ref->u.c.component->caf_token)
1330 tmp2 = compute_component_offset (gfc_comp_caf_token (
1331 ref->u.c.component),
1332 TREE_TYPE (tmp));
1333 else
1334 tmp2 = integer_zero_node;
1335 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1337 /* Remember whether this ref was to a non-allocatable/non-pointer
1338 component so the next array ref can be tailored correctly. */
1339 ref_static_array = !ref->u.c.component->attr.allocatable
1340 && !ref->u.c.component->attr.pointer;
1341 last_component_ref_tree = ref_static_array
1342 ? ref->u.c.component->backend_decl : NULL_TREE;
1343 break;
1344 case REF_ARRAY:
1345 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1346 ref_static_array = false;
1347 /* Set the type of the ref. */
1348 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1349 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1350 TREE_TYPE (field), prev_caf_ref, field,
1351 NULL_TREE);
1352 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1353 ref_static_array
1354 ? GFC_CAF_REF_STATIC_ARRAY
1355 : GFC_CAF_REF_ARRAY));
1357 /* Ref the a in union u. */
1358 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1359 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1360 TREE_TYPE (field), prev_caf_ref, field,
1361 NULL_TREE);
1362 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1363 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1364 TREE_TYPE (field), tmp, field,
1365 NULL_TREE);
1367 /* Set the static_array_type in a for static arrays. */
1368 if (ref_static_array)
1370 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1372 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1373 TREE_TYPE (field), inner_struct, field,
1374 NULL_TREE);
1375 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1376 last_type_n));
1378 /* Ref the mode in the inner_struct. */
1379 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1380 mode = fold_build3_loc (input_location, COMPONENT_REF,
1381 TREE_TYPE (field), inner_struct, field,
1382 NULL_TREE);
1383 /* Ref the dim in the inner_struct. */
1384 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1385 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1386 TREE_TYPE (field), inner_struct, field,
1387 NULL_TREE);
1388 for (i = 0; i < ref->u.ar.dimen; ++i)
1390 /* Ref dim i. */
1391 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1392 dim_type = TREE_TYPE (dim);
1393 mode_rhs = start = end = stride = NULL_TREE;
1394 switch (ref->u.ar.dimen_type[i])
1396 case DIMEN_RANGE:
1397 if (ref->u.ar.end[i])
1399 gfc_init_se (&se, NULL);
1400 gfc_conv_expr (&se, ref->u.ar.end[i]);
1401 gfc_add_block_to_block (block, &se.pre);
1402 if (ref_static_array)
1404 /* Make the index zero-based, when reffing a static
1405 array. */
1406 end = se.expr;
1407 gfc_init_se (&se, NULL);
1408 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1409 gfc_add_block_to_block (block, &se.pre);
1410 se.expr = fold_build2 (MINUS_EXPR,
1411 gfc_array_index_type,
1412 end, fold_convert (
1413 gfc_array_index_type,
1414 se.expr));
1416 end = gfc_evaluate_now (fold_convert (
1417 gfc_array_index_type,
1418 se.expr),
1419 block);
1421 else if (ref_static_array)
1422 end = fold_build2 (MINUS_EXPR,
1423 gfc_array_index_type,
1424 gfc_conv_array_ubound (
1425 last_component_ref_tree, i),
1426 gfc_conv_array_lbound (
1427 last_component_ref_tree, i));
1428 else
1430 end = NULL_TREE;
1431 mode_rhs = build_int_cst (unsigned_char_type_node,
1432 GFC_CAF_ARR_REF_OPEN_END);
1434 if (ref->u.ar.stride[i])
1436 gfc_init_se (&se, NULL);
1437 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1438 gfc_add_block_to_block (block, &se.pre);
1439 stride = gfc_evaluate_now (fold_convert (
1440 gfc_array_index_type,
1441 se.expr),
1442 block);
1443 if (ref_static_array)
1445 /* Make the index zero-based, when reffing a static
1446 array. */
1447 stride = fold_build2 (MULT_EXPR,
1448 gfc_array_index_type,
1449 gfc_conv_array_stride (
1450 last_component_ref_tree,
1452 stride);
1453 gcc_assert (end != NULL_TREE);
1454 /* Multiply with the product of array's stride and
1455 the step of the ref to a virtual upper bound.
1456 We cannot compute the actual upper bound here or
1457 the caflib would compute the extend
1458 incorrectly. */
1459 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1460 end, gfc_conv_array_stride (
1461 last_component_ref_tree,
1462 i));
1463 end = gfc_evaluate_now (end, block);
1464 stride = gfc_evaluate_now (stride, block);
1467 else if (ref_static_array)
1469 stride = gfc_conv_array_stride (last_component_ref_tree,
1471 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1472 end, stride);
1473 end = gfc_evaluate_now (end, block);
1475 else
1476 /* Always set a ref stride of one to make caflib's
1477 handling easier. */
1478 stride = gfc_index_one_node;
1480 /* Fall through. */
1481 case DIMEN_ELEMENT:
1482 if (ref->u.ar.start[i])
1484 gfc_init_se (&se, NULL);
1485 gfc_conv_expr (&se, ref->u.ar.start[i]);
1486 gfc_add_block_to_block (block, &se.pre);
1487 if (ref_static_array)
1489 /* Make the index zero-based, when reffing a static
1490 array. */
1491 start = fold_convert (gfc_array_index_type, se.expr);
1492 gfc_init_se (&se, NULL);
1493 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1494 gfc_add_block_to_block (block, &se.pre);
1495 se.expr = fold_build2 (MINUS_EXPR,
1496 gfc_array_index_type,
1497 start, fold_convert (
1498 gfc_array_index_type,
1499 se.expr));
1500 /* Multiply with the stride. */
1501 se.expr = fold_build2 (MULT_EXPR,
1502 gfc_array_index_type,
1503 se.expr,
1504 gfc_conv_array_stride (
1505 last_component_ref_tree,
1506 i));
1508 start = gfc_evaluate_now (fold_convert (
1509 gfc_array_index_type,
1510 se.expr),
1511 block);
1512 if (mode_rhs == NULL_TREE)
1513 mode_rhs = build_int_cst (unsigned_char_type_node,
1514 ref->u.ar.dimen_type[i]
1515 == DIMEN_ELEMENT
1516 ? GFC_CAF_ARR_REF_SINGLE
1517 : GFC_CAF_ARR_REF_RANGE);
1519 else if (ref_static_array)
1521 start = integer_zero_node;
1522 mode_rhs = build_int_cst (unsigned_char_type_node,
1523 ref->u.ar.start[i] == NULL
1524 ? GFC_CAF_ARR_REF_FULL
1525 : GFC_CAF_ARR_REF_RANGE);
1527 else if (end == NULL_TREE)
1528 mode_rhs = build_int_cst (unsigned_char_type_node,
1529 GFC_CAF_ARR_REF_FULL);
1530 else
1531 mode_rhs = build_int_cst (unsigned_char_type_node,
1532 GFC_CAF_ARR_REF_OPEN_START);
1534 /* Ref the s in dim. */
1535 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1536 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1537 TREE_TYPE (field), dim, field,
1538 NULL_TREE);
1540 /* Set start in s. */
1541 if (start != NULL_TREE)
1543 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1545 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1546 TREE_TYPE (field), tmp, field,
1547 NULL_TREE);
1548 gfc_add_modify (block, tmp2,
1549 fold_convert (TREE_TYPE (tmp2), start));
1552 /* Set end in s. */
1553 if (end != NULL_TREE)
1555 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1557 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1558 TREE_TYPE (field), tmp, field,
1559 NULL_TREE);
1560 gfc_add_modify (block, tmp2,
1561 fold_convert (TREE_TYPE (tmp2), end));
1564 /* Set end in s. */
1565 if (stride != NULL_TREE)
1567 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1569 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1570 TREE_TYPE (field), tmp, field,
1571 NULL_TREE);
1572 gfc_add_modify (block, tmp2,
1573 fold_convert (TREE_TYPE (tmp2), stride));
1575 break;
1576 case DIMEN_VECTOR:
1577 /* TODO: In case of static array. */
1578 gcc_assert (!ref_static_array);
1579 mode_rhs = build_int_cst (unsigned_char_type_node,
1580 GFC_CAF_ARR_REF_VECTOR);
1581 gfc_init_se (&se, NULL);
1582 se.descriptor_only = 1;
1583 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1584 gfc_add_block_to_block (block, &se.pre);
1585 vector = se.expr;
1586 tmp = gfc_conv_descriptor_lbound_get (vector,
1587 gfc_rank_cst[0]);
1588 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1589 gfc_rank_cst[0]);
1590 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1591 tmp = gfc_conv_descriptor_stride_get (vector,
1592 gfc_rank_cst[0]);
1593 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1594 TREE_TYPE (nvec), nvec, tmp);
1595 vector = gfc_conv_descriptor_data_get (vector);
1597 /* Ref the v in dim. */
1598 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1599 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1600 TREE_TYPE (field), dim, field,
1601 NULL_TREE);
1603 /* Set vector in v. */
1604 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1605 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1606 TREE_TYPE (field), tmp, field,
1607 NULL_TREE);
1608 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1609 vector));
1611 /* Set nvec in v. */
1612 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1613 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1614 TREE_TYPE (field), tmp, field,
1615 NULL_TREE);
1616 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1617 nvec));
1619 /* Set kind in v. */
1620 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1621 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1622 TREE_TYPE (field), tmp, field,
1623 NULL_TREE);
1624 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1625 ref->u.ar.start[i]->ts.kind));
1626 break;
1627 default:
1628 gcc_unreachable ();
1630 /* Set the mode for dim i. */
1631 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1632 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1633 mode_rhs));
1636 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1637 if (i < GFC_MAX_DIMENSIONS)
1639 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1640 gfc_add_modify (block, tmp,
1641 build_int_cst (unsigned_char_type_node,
1642 GFC_CAF_ARR_REF_NONE));
1644 break;
1645 default:
1646 gcc_unreachable ();
1649 /* Set the size of the current type. */
1650 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1651 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1652 prev_caf_ref, field, NULL_TREE);
1653 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1654 TYPE_SIZE_UNIT (last_type)));
1656 ref = ref->next;
1659 if (prev_caf_ref != NULL_TREE)
1661 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1662 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1663 prev_caf_ref, field, NULL_TREE);
1664 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1665 null_pointer_node));
1667 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1668 : NULL_TREE;
1671 static tree
1672 conv_shape_to_cst (gfc_expr *e)
1674 tree tmp = NULL;
1675 for (int d = 0; d < e->rank; ++d)
1677 if (!tmp)
1678 tmp = gfc_conv_mpz_to_tree (e->shape[d], gfc_size_kind);
1679 else
1680 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp,
1681 gfc_conv_mpz_to_tree (e->shape[d], gfc_size_kind));
1683 return fold_convert (size_type_node, tmp);
1686 /* Get data from a remote coarray. */
1688 static void
1689 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs,
1690 bool may_realloc, symbol_attribute *caf_attr)
1692 static int call_cnt = 0;
1693 gfc_expr *array_expr, *tmp_stat;
1694 gfc_se argse;
1695 tree caf_decl, token, image_index, tmp, res_var, type, stat, dest_size,
1696 dest_data, opt_dest_desc, rget_index_tree, rget_data_tree, rget_data_size,
1697 opt_src_desc, opt_src_charlen, opt_dest_charlen;
1698 symbol_attribute caf_attr_store;
1699 gfc_namespace *ns;
1700 gfc_expr *rget_hash = expr->value.function.actual->next->expr,
1701 *rget_fn_expr = expr->value.function.actual->next->next->expr;
1702 gfc_symbol *gdata_sym
1703 = rget_fn_expr->symtree->n.sym->formal->next->next->next->sym;
1704 gfc_expr rget_data, rget_data_init, rget_index;
1705 char *name;
1706 gfc_symtree *data_st, *index_st;
1707 gfc_constructor *con;
1708 stmtblock_t blk;
1710 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1712 if (se->ss && se->ss->info->useflags)
1714 /* Access the previously obtained result. */
1715 gfc_conv_tmp_array_ref (se);
1716 return;
1719 array_expr = expr->value.function.actual->expr;
1720 ns = array_expr->expr_type == EXPR_VARIABLE
1721 && !array_expr->symtree->n.sym->attr.associate_var
1722 ? array_expr->symtree->n.sym->ns
1723 : gfc_current_ns;
1724 type = gfc_typenode_for_spec (&array_expr->ts);
1726 if (caf_attr == NULL)
1728 caf_attr_store = gfc_caf_attr (array_expr);
1729 caf_attr = &caf_attr_store;
1732 res_var = lhs;
1734 tmp_stat = gfc_find_stat_co (expr);
1736 if (tmp_stat)
1738 gfc_se stat_se;
1739 gfc_init_se (&stat_se, NULL);
1740 gfc_conv_expr_reference (&stat_se, tmp_stat);
1741 stat = stat_se.expr;
1742 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1743 gfc_add_block_to_block (&se->post, &stat_se.post);
1745 else
1746 stat = null_pointer_node;
1748 memset (&rget_data, 0, sizeof (gfc_expr));
1749 gfc_clear_ts (&rget_data.ts);
1750 rget_data.expr_type = EXPR_VARIABLE;
1751 name = xasprintf ("__caf_rget_data_%d", call_cnt);
1752 gcc_assert (!gfc_get_sym_tree (name, ns, &data_st, false));
1753 name = xasprintf ("__caf_rget_index_%d", call_cnt);
1754 ++call_cnt;
1755 gcc_assert (!gfc_get_sym_tree (name, ns, &index_st, false));
1756 free (name);
1757 data_st->n.sym->attr.flavor = FL_VARIABLE;
1758 data_st->n.sym->ts = gdata_sym->ts;
1759 rget_data.symtree = data_st;
1760 gfc_set_sym_referenced (rget_data.symtree->n.sym);
1761 rget_data.ts = data_st->n.sym->ts;
1762 gfc_commit_symbol (data_st->n.sym);
1764 memset (&rget_data_init, 0, sizeof (gfc_expr));
1765 gfc_clear_ts (&rget_data_init.ts);
1766 rget_data_init.expr_type = EXPR_STRUCTURE;
1767 rget_data_init.ts = rget_data.ts;
1768 for (gfc_component *comp = rget_data.ts.u.derived->components; comp;
1769 comp = comp->next)
1771 con = gfc_constructor_get ();
1772 con->expr = comp->initializer;
1773 comp->initializer = NULL;
1774 gfc_constructor_append (&rget_data_init.value.constructor, con);
1777 index_st->n.sym->attr.flavor = FL_VARIABLE;
1778 index_st->n.sym->attr.save = SAVE_EXPLICIT;
1779 index_st->n.sym->value
1780 = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
1781 &gfc_current_locus);
1782 mpz_init_set_si (index_st->n.sym->value->value.integer, -1);
1783 index_st->n.sym->ts.type = BT_INTEGER;
1784 index_st->n.sym->ts.kind = gfc_default_integer_kind;
1785 gfc_set_sym_referenced (index_st->n.sym);
1786 memset (&rget_index, 0, sizeof (gfc_expr));
1787 gfc_clear_ts (&rget_index.ts);
1788 rget_index.expr_type = EXPR_VARIABLE;
1789 rget_index.symtree = index_st;
1790 rget_index.ts = index_st->n.sym->ts;
1791 gfc_commit_symbol (index_st->n.sym);
1793 gfc_init_se (&argse, NULL);
1794 gfc_conv_expr (&argse, &rget_index);
1795 gfc_add_block_to_block (&se->pre, &argse.pre);
1796 rget_index_tree = argse.expr;
1798 gfc_init_se (&argse, NULL);
1799 gfc_conv_expr (&argse, rget_hash);
1801 gfc_init_block (&blk);
1802 tmp = build_call_expr (gfor_fndecl_caf_get_remote_function_index, 1,
1803 argse.expr);
1805 gfc_add_modify (&blk, rget_index_tree, tmp);
1806 gfc_add_expr_to_block (
1807 &se->pre,
1808 build3 (COND_EXPR, void_type_node,
1809 gfc_likely (build2 (EQ_EXPR, logical_type_node, rget_index_tree,
1810 build_int_cst (integer_type_node, -1)),
1811 PRED_FIRST_MATCH),
1812 gfc_finish_block (&blk), NULL_TREE));
1814 if (rget_data.ts.u.derived->components)
1816 gfc_init_se (&argse, NULL);
1817 gfc_conv_expr (&argse, &rget_data);
1818 rget_data_tree = argse.expr;
1819 gfc_add_expr_to_block (&se->pre,
1820 gfc_trans_structure_assign (rget_data_tree,
1821 &rget_data_init, true,
1822 false));
1823 gfc_constructor_free (rget_data_init.value.constructor);
1824 rget_data_size = TREE_TYPE (rget_data_tree)->type_common.size_unit;
1825 rget_data_tree = gfc_build_addr_expr (pvoid_type_node, rget_data_tree);
1827 else
1829 rget_data_tree = build_zero_cst (pvoid_type_node);
1830 rget_data_size = build_zero_cst (size_type_node);
1833 if (array_expr->rank == 0)
1835 res_var = gfc_create_var (type, "caf_res");
1836 if (array_expr->ts.type == BT_CHARACTER)
1838 gfc_conv_string_length (array_expr->ts.u.cl, array_expr, &se->pre);
1839 argse.string_length = array_expr->ts.u.cl->backend_decl;
1840 opt_src_charlen = gfc_build_addr_expr (
1841 NULL_TREE, gfc_trans_force_lval (&se->pre, argse.string_length));
1842 dest_size = build_int_cstu (size_type_node, array_expr->ts.kind);
1844 else
1846 dest_size = res_var->typed.type->type_common.size_unit;
1847 opt_src_charlen
1848 = build_zero_cst (build_pointer_type (size_type_node));
1850 dest_data
1851 = gfc_evaluate_now (gfc_build_addr_expr (NULL_TREE, res_var), &se->pre);
1852 res_var = build_fold_indirect_ref (dest_data);
1853 dest_data = gfc_build_addr_expr (pvoid_type_node, dest_data);
1854 opt_dest_desc = build_zero_cst (pvoid_type_node);
1856 else
1858 /* Create temporary. */
1859 may_realloc = gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
1860 type, NULL_TREE, false, false,
1861 false, &array_expr->where)
1862 == NULL_TREE;
1863 res_var = se->ss->info->data.array.descriptor;
1864 if (array_expr->ts.type == BT_CHARACTER)
1866 argse.string_length = array_expr->ts.u.cl->backend_decl;
1867 opt_src_charlen = gfc_build_addr_expr (
1868 NULL_TREE, gfc_trans_force_lval (&se->pre, argse.string_length));
1869 dest_size = build_int_cstu (size_type_node, array_expr->ts.kind);
1871 else
1873 opt_src_charlen
1874 = build_zero_cst (build_pointer_type (size_type_node));
1875 dest_size = fold_build2 (
1876 MULT_EXPR, size_type_node,
1877 fold_convert (size_type_node,
1878 array_expr->shape
1879 ? conv_shape_to_cst (array_expr)
1880 : gfc_conv_descriptor_size (res_var,
1881 array_expr->rank)),
1882 fold_convert (size_type_node,
1883 gfc_conv_descriptor_span_get (res_var)));
1885 opt_dest_desc = res_var;
1886 dest_data = gfc_conv_descriptor_data_get (res_var);
1887 opt_dest_desc = gfc_build_addr_expr (NULL_TREE, opt_dest_desc);
1888 if (may_realloc)
1890 tmp = gfc_conv_descriptor_data_get (res_var);
1891 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
1892 NULL_TREE, NULL_TREE, true, NULL,
1893 GFC_CAF_COARRAY_NOCOARRAY);
1894 gfc_add_expr_to_block (&se->post, tmp);
1896 dest_data
1897 = gfc_build_addr_expr (NULL_TREE,
1898 gfc_trans_force_lval (&se->pre, dest_data));
1901 opt_dest_charlen = opt_src_charlen;
1902 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1903 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1904 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1906 if (!TYPE_LANG_SPECIFIC (TREE_TYPE (caf_decl))->rank
1907 || GFC_ARRAY_TYPE_P (TREE_TYPE (caf_decl)))
1908 opt_src_desc = build_zero_cst (pvoid_type_node);
1909 else
1910 opt_src_desc = gfc_build_addr_expr (pvoid_type_node, caf_decl);
1912 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1913 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL, array_expr);
1915 /* It guarantees memory consistency within the same segment. */
1916 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1917 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1918 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1919 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1920 ASM_VOLATILE_P (tmp) = 1;
1921 gfc_add_expr_to_block (&se->pre, tmp);
1923 tmp = build_call_expr_loc (
1924 input_location, gfor_fndecl_caf_get_by_ct, 15, token, opt_src_desc,
1925 opt_src_charlen, image_index, dest_size, dest_data, opt_dest_charlen,
1926 opt_dest_desc, constant_boolean_node (may_realloc, boolean_type_node),
1927 rget_index_tree, rget_data_tree, rget_data_size, stat, null_pointer_node,
1928 null_pointer_node);
1930 gfc_add_expr_to_block (&se->pre, tmp);
1932 if (se->ss)
1933 gfc_advance_se_ss_chain (se);
1935 se->expr = res_var;
1936 if (array_expr->ts.type == BT_CHARACTER)
1937 se->string_length = argse.string_length;
1939 return;
1942 static bool
1943 has_ref_after_cafref (gfc_expr *expr)
1945 for (gfc_ref *ref = expr->ref; ref; ref = ref->next)
1946 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
1947 return ref->next;
1948 return false;
1951 /* Send data to a remote coarray. */
1953 static tree
1954 conv_caf_send (gfc_code *code) {
1955 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1956 gfc_se lhs_se, rhs_se;
1957 stmtblock_t block;
1958 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1959 tree may_require_tmp, src_stat, dst_stat, dst_team;
1960 tree lhs_type = NULL_TREE;
1961 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1962 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1963 bool lhs_is_coindexed, rhs_is_coindexed;
1965 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1967 lhs_expr
1968 = code->ext.actual->expr->expr_type == EXPR_FUNCTION
1969 && code->ext.actual->expr->value.function.isym->id == GFC_ISYM_CAF_GET
1970 ? code->ext.actual->expr->value.function.actual->expr
1971 : code->ext.actual->expr;
1972 rhs_expr = code->ext.actual->next->expr->expr_type == EXPR_FUNCTION
1973 && code->ext.actual->next->expr->value.function.isym->id
1974 == GFC_ISYM_CAF_GET
1975 ? code->ext.actual->next->expr->value.function.actual->expr
1976 : code->ext.actual->next->expr;
1977 lhs_is_coindexed = gfc_is_coindexed (lhs_expr);
1978 rhs_is_coindexed = gfc_is_coindexed (rhs_expr);
1979 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1980 ? boolean_false_node : boolean_true_node;
1981 gfc_init_block (&block);
1983 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1984 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1985 src_stat = dst_stat = null_pointer_node;
1986 dst_team = null_pointer_node;
1988 /* LHS. */
1989 gfc_init_se (&lhs_se, NULL);
1990 if (lhs_expr->rank == 0)
1992 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1994 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1995 if (!POINTER_TYPE_P (TREE_TYPE (lhs_se.expr)))
1996 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1998 else
2000 symbol_attribute attr;
2001 gfc_clear_attr (&attr);
2002 gfc_conv_expr (&lhs_se, lhs_expr);
2003 lhs_type = TREE_TYPE (lhs_se.expr);
2004 if (lhs_is_coindexed)
2005 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
2006 attr);
2007 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
2010 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2011 && lhs_caf_attr.codimension)
2013 lhs_se.want_pointer = 1;
2014 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2015 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2016 has the wrong type if component references are done. */
2017 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2018 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2019 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2020 gfc_get_dtype_rank_type (
2021 gfc_has_vector_subscript (lhs_expr)
2022 ? gfc_find_array_ref (lhs_expr)->dimen
2023 : lhs_expr->rank,
2024 lhs_type));
2026 else
2028 bool has_vector = gfc_has_vector_subscript (lhs_expr);
2030 if (lhs_is_coindexed || !has_vector)
2032 /* If has_vector, pass descriptor for whole array and the
2033 vector bounds separately. */
2034 gfc_array_ref *ar, ar2;
2035 bool has_tmp_lhs_array = false;
2036 if (has_vector)
2038 has_tmp_lhs_array = true;
2039 ar = gfc_find_array_ref (lhs_expr);
2040 ar2 = *ar;
2041 memset (ar, '\0', sizeof (*ar));
2042 ar->as = ar2.as;
2043 ar->type = AR_FULL;
2045 lhs_se.want_pointer = 1;
2046 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2047 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2048 that has the wrong type if component references are done. */
2049 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2050 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2051 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2052 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2053 : lhs_expr->rank,
2054 lhs_type));
2055 if (has_tmp_lhs_array)
2057 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2058 *ar = ar2;
2061 else if (rhs_is_coindexed)
2063 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2064 indexed array expression. This is rewritten to:
2066 tmp_array = arr2[...]
2067 arr1 ([...]) = tmp_array
2069 because using the standard gfc_conv_expr (lhs_expr) did the
2070 assignment with lhs and rhs exchanged. */
2072 gfc_ss *lss_for_tmparray, *lss_real;
2073 gfc_loopinfo loop;
2074 gfc_se se;
2075 stmtblock_t body;
2076 tree tmparr_desc, src;
2077 tree index = gfc_index_zero_node;
2078 tree stride = gfc_index_zero_node;
2079 int n;
2081 /* Walk both sides of the assignment, once to get the shape of the
2082 temporary array to create right. */
2083 lss_for_tmparray = gfc_walk_expr (lhs_expr);
2084 /* And a second time to be able to create an assignment of the
2085 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2086 the tree in the descriptor with the one for the temporary
2087 array. */
2088 lss_real = gfc_walk_expr (lhs_expr);
2089 gfc_init_loopinfo (&loop);
2090 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2091 gfc_add_ss_to_loop (&loop, lss_real);
2092 gfc_conv_ss_startstride (&loop);
2093 gfc_conv_loop_setup (&loop, &lhs_expr->where);
2094 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2095 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2096 lss_for_tmparray, lhs_type, NULL_TREE,
2097 false, true, false,
2098 &lhs_expr->where);
2099 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2100 gfc_start_scalarized_body (&loop, &body);
2101 gfc_init_se (&se, NULL);
2102 gfc_copy_loopinfo_to_se (&se, &loop);
2103 se.ss = lss_real;
2104 gfc_conv_expr (&se, lhs_expr);
2105 gfc_add_block_to_block (&body, &se.pre);
2107 /* Walk over all indexes of the loop. */
2108 for (n = loop.dimen - 1; n > 0; --n)
2110 tmp = loop.loopvar[n];
2111 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2112 gfc_array_index_type, tmp, loop.from[n]);
2113 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2114 gfc_array_index_type, tmp, index);
2116 stride = fold_build2_loc (input_location, MINUS_EXPR,
2117 gfc_array_index_type,
2118 loop.to[n - 1], loop.from[n - 1]);
2119 stride = fold_build2_loc (input_location, PLUS_EXPR,
2120 gfc_array_index_type,
2121 stride, gfc_index_one_node);
2123 index = fold_build2_loc (input_location, MULT_EXPR,
2124 gfc_array_index_type, tmp, stride);
2127 index = fold_build2_loc (input_location, MINUS_EXPR,
2128 gfc_array_index_type,
2129 index, loop.from[0]);
2131 index = fold_build2_loc (input_location, PLUS_EXPR,
2132 gfc_array_index_type,
2133 loop.loopvar[0], index);
2135 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2136 src = gfc_build_array_ref (src, index, NULL);
2137 /* Now create the assignment of lhs_expr = tmp_array. */
2138 gfc_add_modify (&body, se.expr, src);
2139 gfc_add_block_to_block (&body, &se.post);
2140 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2141 gfc_trans_scalarizing_loops (&loop, &body);
2142 gfc_add_block_to_block (&loop.pre, &loop.post);
2143 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2144 gfc_free_ss (lss_for_tmparray);
2145 gfc_free_ss (lss_real);
2149 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2151 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2152 temporary and a loop. */
2153 if (!lhs_is_coindexed && rhs_is_coindexed
2154 && (!lhs_caf_attr.codimension
2155 || !(lhs_expr->rank > 0
2156 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2158 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2159 gfc_init_se (&rhs_se, NULL);
2160 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2162 gfc_se scal_se;
2163 gfc_init_se (&scal_se, NULL);
2164 scal_se.want_pointer = 1;
2165 gfc_conv_expr (&scal_se, lhs_expr);
2166 /* Ensure scalar on lhs is allocated. */
2167 gfc_add_block_to_block (&block, &scal_se.pre);
2169 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2170 TYPE_SIZE_UNIT (
2171 gfc_typenode_for_spec (&lhs_expr->ts)),
2172 NULL_TREE);
2173 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2174 null_pointer_node);
2175 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2176 tmp, gfc_finish_block (&scal_se.pre),
2177 build_empty_stmt (input_location));
2178 gfc_add_expr_to_block (&block, tmp);
2180 else
2181 lhs_may_realloc = lhs_may_realloc
2182 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2183 gfc_add_block_to_block (&block, &lhs_se.pre);
2184 gfc_conv_intrinsic_caf_get (&rhs_se, code->ext.actual->next->expr,
2185 lhs_se.expr, lhs_may_realloc, &rhs_caf_attr);
2186 gfc_add_block_to_block (&block, &rhs_se.pre);
2187 gfc_add_block_to_block (&block, &rhs_se.post);
2188 gfc_add_block_to_block (&block, &lhs_se.post);
2189 return gfc_finish_block (&block);
2192 gfc_add_block_to_block (&block, &lhs_se.pre);
2194 /* Obtain token, offset and image index for the LHS. */
2195 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2196 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2197 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2198 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2199 tmp = lhs_se.expr;
2200 if (lhs_caf_attr.alloc_comp)
2201 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2202 NULL);
2203 else
2204 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2205 lhs_expr);
2206 lhs_se.expr = tmp;
2208 /* RHS. */
2209 gfc_init_se (&rhs_se, NULL);
2210 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2211 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2212 rhs_expr = rhs_expr->value.function.actual->expr;
2213 if (rhs_expr->rank == 0)
2215 symbol_attribute attr;
2216 gfc_clear_attr (&attr);
2217 gfc_conv_expr (&rhs_se, rhs_expr);
2218 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2219 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2221 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2222 && rhs_caf_attr.codimension)
2224 tree tmp2;
2225 rhs_se.want_pointer = 1;
2226 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2227 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2228 has the wrong type if component references are done. */
2229 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2230 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2231 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2232 gfc_get_dtype_rank_type (
2233 gfc_has_vector_subscript (rhs_expr)
2234 ? gfc_find_array_ref (rhs_expr)->dimen
2235 : rhs_expr->rank,
2236 tmp2));
2238 else
2240 /* If has_vector, pass descriptor for whole array and the
2241 vector bounds separately. */
2242 gfc_array_ref *ar, ar2;
2243 bool has_vector = false;
2244 tree tmp2;
2246 if (rhs_is_coindexed && gfc_has_vector_subscript (rhs_expr))
2248 has_vector = true;
2249 ar = gfc_find_array_ref (rhs_expr);
2250 ar2 = *ar;
2251 memset (ar, '\0', sizeof (*ar));
2252 ar->as = ar2.as;
2253 ar->type = AR_FULL;
2255 rhs_se.want_pointer = 1;
2256 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2257 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2258 has the wrong type if component references are done. */
2259 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2260 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2261 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2262 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2263 : rhs_expr->rank,
2264 tmp2));
2265 if (has_vector)
2267 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2268 *ar = ar2;
2272 gfc_add_block_to_block (&block, &rhs_se.pre);
2274 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2276 tmp_stat = gfc_find_stat_co (lhs_expr);
2278 if (tmp_stat)
2280 gfc_se stat_se;
2281 gfc_init_se (&stat_se, NULL);
2282 gfc_conv_expr_reference (&stat_se, tmp_stat);
2283 dst_stat = stat_se.expr;
2284 gfc_add_block_to_block (&block, &stat_se.pre);
2285 gfc_add_block_to_block (&block, &stat_se.post);
2288 tmp_team = gfc_find_team_co (lhs_expr);
2290 if (tmp_team)
2292 gfc_se team_se;
2293 gfc_init_se (&team_se, NULL);
2294 gfc_conv_expr_reference (&team_se, tmp_team);
2295 dst_team = team_se.expr;
2296 gfc_add_block_to_block (&block, &team_se.pre);
2297 gfc_add_block_to_block (&block, &team_se.post);
2300 if (!rhs_is_coindexed)
2302 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp
2303 || has_ref_after_cafref (lhs_expr))
2305 tree reference, dst_realloc;
2306 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2307 dst_realloc
2308 = lhs_caf_attr.allocatable ? boolean_true_node : boolean_false_node;
2309 tmp = build_call_expr_loc (input_location,
2310 gfor_fndecl_caf_send_by_ref,
2311 10, token, image_index, rhs_se.expr,
2312 reference, lhs_kind, rhs_kind,
2313 may_require_tmp, dst_realloc, src_stat,
2314 build_int_cst (integer_type_node,
2315 lhs_expr->ts.type));
2317 else
2318 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2319 token, offset, image_index, lhs_se.expr, vec,
2320 rhs_se.expr, lhs_kind, rhs_kind,
2321 may_require_tmp, src_stat, dst_team);
2323 else
2325 tree rhs_token, rhs_offset, rhs_image_index;
2327 /* It guarantees memory consistency within the same segment. */
2328 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2329 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2330 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2331 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2332 ASM_VOLATILE_P (tmp) = 1;
2333 gfc_add_expr_to_block (&block, tmp);
2335 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2336 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2337 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2338 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2339 tmp = rhs_se.expr;
2340 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp
2341 || has_ref_after_cafref (lhs_expr))
2343 tmp_stat = gfc_find_stat_co (lhs_expr);
2345 if (tmp_stat)
2347 gfc_se stat_se;
2348 gfc_init_se (&stat_se, NULL);
2349 gfc_conv_expr_reference (&stat_se, tmp_stat);
2350 src_stat = stat_se.expr;
2351 gfc_add_block_to_block (&block, &stat_se.pre);
2352 gfc_add_block_to_block (&block, &stat_se.post);
2355 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2356 NULL_TREE, NULL);
2357 tree lhs_reference, rhs_reference;
2358 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2359 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2360 tmp = build_call_expr_loc (input_location,
2361 gfor_fndecl_caf_sendget_by_ref, 13,
2362 token, image_index, lhs_reference,
2363 rhs_token, rhs_image_index, rhs_reference,
2364 lhs_kind, rhs_kind, may_require_tmp,
2365 dst_stat, src_stat,
2366 build_int_cst (integer_type_node,
2367 lhs_expr->ts.type),
2368 build_int_cst (integer_type_node,
2369 rhs_expr->ts.type));
2371 else
2373 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2374 tmp, rhs_expr);
2375 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2376 14, token, offset, image_index,
2377 lhs_se.expr, vec, rhs_token, rhs_offset,
2378 rhs_image_index, tmp, rhs_vec, lhs_kind,
2379 rhs_kind, may_require_tmp, src_stat);
2382 gfc_add_expr_to_block (&block, tmp);
2383 gfc_add_block_to_block (&block, &lhs_se.post);
2384 gfc_add_block_to_block (&block, &rhs_se.post);
2386 /* It guarantees memory consistency within the same segment. */
2387 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2388 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2389 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2390 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2391 ASM_VOLATILE_P (tmp) = 1;
2392 gfc_add_expr_to_block (&block, tmp);
2394 return gfc_finish_block (&block);
2398 static void
2399 trans_this_image (gfc_se * se, gfc_expr *expr)
2401 stmtblock_t loop;
2402 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2403 lbound, ubound, extent, ml;
2404 gfc_se argse;
2405 int rank, corank;
2406 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2408 if (expr->value.function.actual->expr
2409 && !gfc_is_coarray (expr->value.function.actual->expr))
2410 distance = expr->value.function.actual->expr;
2412 /* The case -fcoarray=single is handled elsewhere. */
2413 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2415 /* Argument-free version: THIS_IMAGE(). */
2416 if (distance || expr->value.function.actual->expr == NULL)
2418 if (distance)
2420 gfc_init_se (&argse, NULL);
2421 gfc_conv_expr_val (&argse, distance);
2422 gfc_add_block_to_block (&se->pre, &argse.pre);
2423 gfc_add_block_to_block (&se->post, &argse.post);
2424 tmp = fold_convert (integer_type_node, argse.expr);
2426 else
2427 tmp = integer_zero_node;
2428 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2429 tmp);
2430 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2431 tmp);
2432 return;
2435 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2437 type = gfc_get_int_type (gfc_default_integer_kind);
2438 corank = expr->value.function.actual->expr->corank;
2439 rank = expr->value.function.actual->expr->rank;
2441 /* Obtain the descriptor of the COARRAY. */
2442 gfc_init_se (&argse, NULL);
2443 argse.want_coarray = 1;
2444 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2445 gfc_add_block_to_block (&se->pre, &argse.pre);
2446 gfc_add_block_to_block (&se->post, &argse.post);
2447 desc = argse.expr;
2449 if (se->ss)
2451 /* Create an implicit second parameter from the loop variable. */
2452 gcc_assert (!expr->value.function.actual->next->expr);
2453 gcc_assert (corank > 0);
2454 gcc_assert (se->loop->dimen == 1);
2455 gcc_assert (se->ss->info->expr == expr);
2457 dim_arg = se->loop->loopvar[0];
2458 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2459 gfc_array_index_type, dim_arg,
2460 build_int_cst (TREE_TYPE (dim_arg), 1));
2461 gfc_advance_se_ss_chain (se);
2463 else
2465 /* Use the passed DIM= argument. */
2466 gcc_assert (expr->value.function.actual->next->expr);
2467 gfc_init_se (&argse, NULL);
2468 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2469 gfc_array_index_type);
2470 gfc_add_block_to_block (&se->pre, &argse.pre);
2471 dim_arg = argse.expr;
2473 if (INTEGER_CST_P (dim_arg))
2475 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2476 || wi::gtu_p (wi::to_wide (dim_arg),
2477 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2478 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2479 "dimension index", expr->value.function.isym->name,
2480 &expr->where);
2482 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2484 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2485 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2486 dim_arg,
2487 build_int_cst (TREE_TYPE (dim_arg), 1));
2488 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2489 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2490 dim_arg, tmp);
2491 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2492 logical_type_node, cond, tmp);
2493 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2494 gfc_msg_fault);
2498 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2499 one always has a dim_arg argument.
2501 m = this_image() - 1
2502 if (corank == 1)
2504 sub(1) = m + lcobound(corank)
2505 return;
2507 i = rank
2508 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2509 for (;;)
2511 extent = gfc_extent(i)
2512 ml = m
2513 m = m/extent
2514 if (i >= min_var)
2515 goto exit_label
2518 exit_label:
2519 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2520 : m + lcobound(corank)
2523 /* this_image () - 1. */
2524 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2525 integer_zero_node);
2526 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2527 fold_convert (type, tmp), build_int_cst (type, 1));
2528 if (corank == 1)
2530 /* sub(1) = m + lcobound(corank). */
2531 lbound = gfc_conv_descriptor_lbound_get (desc,
2532 build_int_cst (TREE_TYPE (gfc_array_index_type),
2533 corank+rank-1));
2534 lbound = fold_convert (type, lbound);
2535 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2537 se->expr = tmp;
2538 return;
2541 m = gfc_create_var (type, NULL);
2542 ml = gfc_create_var (type, NULL);
2543 loop_var = gfc_create_var (integer_type_node, NULL);
2544 min_var = gfc_create_var (integer_type_node, NULL);
2546 /* m = this_image () - 1. */
2547 gfc_add_modify (&se->pre, m, tmp);
2549 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2550 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2551 fold_convert (integer_type_node, dim_arg),
2552 build_int_cst (integer_type_node, rank - 1));
2553 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2554 build_int_cst (integer_type_node, rank + corank - 2),
2555 tmp);
2556 gfc_add_modify (&se->pre, min_var, tmp);
2558 /* i = rank. */
2559 tmp = build_int_cst (integer_type_node, rank);
2560 gfc_add_modify (&se->pre, loop_var, tmp);
2562 exit_label = gfc_build_label_decl (NULL_TREE);
2563 TREE_USED (exit_label) = 1;
2565 /* Loop body. */
2566 gfc_init_block (&loop);
2568 /* ml = m. */
2569 gfc_add_modify (&loop, ml, m);
2571 /* extent = ... */
2572 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2573 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2574 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2575 extent = fold_convert (type, extent);
2577 /* m = m/extent. */
2578 gfc_add_modify (&loop, m,
2579 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2580 m, extent));
2582 /* Exit condition: if (i >= min_var) goto exit_label. */
2583 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2584 min_var);
2585 tmp = build1_v (GOTO_EXPR, exit_label);
2586 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2587 build_empty_stmt (input_location));
2588 gfc_add_expr_to_block (&loop, tmp);
2590 /* Increment loop variable: i++. */
2591 gfc_add_modify (&loop, loop_var,
2592 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2593 loop_var,
2594 integer_one_node));
2596 /* Making the loop... actually loop! */
2597 tmp = gfc_finish_block (&loop);
2598 tmp = build1_v (LOOP_EXPR, tmp);
2599 gfc_add_expr_to_block (&se->pre, tmp);
2601 /* The exit label. */
2602 tmp = build1_v (LABEL_EXPR, exit_label);
2603 gfc_add_expr_to_block (&se->pre, tmp);
2605 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2606 : m + lcobound(corank) */
2608 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2609 build_int_cst (TREE_TYPE (dim_arg), corank));
2611 lbound = gfc_conv_descriptor_lbound_get (desc,
2612 fold_build2_loc (input_location, PLUS_EXPR,
2613 gfc_array_index_type, dim_arg,
2614 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2615 lbound = fold_convert (type, lbound);
2617 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2618 fold_build2_loc (input_location, MULT_EXPR, type,
2619 m, extent));
2620 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2622 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2623 fold_build2_loc (input_location, PLUS_EXPR, type,
2624 m, lbound));
2628 /* Convert a call to image_status. */
2630 static void
2631 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2633 unsigned int num_args;
2634 tree *args, tmp;
2636 num_args = gfc_intrinsic_argument_list_length (expr);
2637 args = XALLOCAVEC (tree, num_args);
2638 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2639 /* In args[0] the number of the image the status is desired for has to be
2640 given. */
2642 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2644 tree arg;
2645 arg = gfc_evaluate_now (args[0], &se->pre);
2646 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2647 fold_convert (integer_type_node, arg),
2648 integer_one_node);
2649 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2650 tmp, integer_zero_node,
2651 build_int_cst (integer_type_node,
2652 GFC_STAT_STOPPED_IMAGE));
2654 else if (flag_coarray == GFC_FCOARRAY_LIB)
2655 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2656 args[0], build_int_cst (integer_type_node, -1));
2657 else
2658 gcc_unreachable ();
2660 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2663 static void
2664 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2666 unsigned int num_args;
2668 tree *args, tmp;
2670 num_args = gfc_intrinsic_argument_list_length (expr);
2671 args = XALLOCAVEC (tree, num_args);
2672 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2674 if (flag_coarray ==
2675 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2677 tree arg;
2679 arg = gfc_evaluate_now (args[0], &se->pre);
2680 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2681 fold_convert (integer_type_node, arg),
2682 integer_one_node);
2683 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2684 tmp, integer_zero_node,
2685 build_int_cst (integer_type_node,
2686 GFC_STAT_STOPPED_IMAGE));
2688 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2690 // the value -1 represents that no team has been created yet
2691 tmp = build_int_cst (integer_type_node, -1);
2693 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2694 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2695 args[0], build_int_cst (integer_type_node, -1));
2696 else if (flag_coarray == GFC_FCOARRAY_LIB)
2697 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2698 integer_zero_node, build_int_cst (integer_type_node, -1));
2699 else
2700 gcc_unreachable ();
2702 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2706 static void
2707 trans_image_index (gfc_se * se, gfc_expr *expr)
2709 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2710 tmp, invalid_bound;
2711 gfc_se argse, subse;
2712 int rank, corank, codim;
2714 type = gfc_get_int_type (gfc_default_integer_kind);
2715 corank = expr->value.function.actual->expr->corank;
2716 rank = expr->value.function.actual->expr->rank;
2718 /* Obtain the descriptor of the COARRAY. */
2719 gfc_init_se (&argse, NULL);
2720 argse.want_coarray = 1;
2721 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2722 gfc_add_block_to_block (&se->pre, &argse.pre);
2723 gfc_add_block_to_block (&se->post, &argse.post);
2724 desc = argse.expr;
2726 /* Obtain a handle to the SUB argument. */
2727 gfc_init_se (&subse, NULL);
2728 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2729 gfc_add_block_to_block (&se->pre, &subse.pre);
2730 gfc_add_block_to_block (&se->post, &subse.post);
2731 subdesc = build_fold_indirect_ref_loc (input_location,
2732 gfc_conv_descriptor_data_get (subse.expr));
2734 /* Fortran 2008 does not require that the values remain in the cobounds,
2735 thus we need explicitly check this - and return 0 if they are exceeded. */
2737 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2738 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2739 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2740 fold_convert (gfc_array_index_type, tmp),
2741 lbound);
2743 for (codim = corank + rank - 2; codim >= rank; codim--)
2745 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2746 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2747 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2748 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2749 fold_convert (gfc_array_index_type, tmp),
2750 lbound);
2751 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2752 logical_type_node, invalid_bound, cond);
2753 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2754 fold_convert (gfc_array_index_type, tmp),
2755 ubound);
2756 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2757 logical_type_node, invalid_bound, cond);
2760 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2762 /* See Fortran 2008, C.10 for the following algorithm. */
2764 /* coindex = sub(corank) - lcobound(n). */
2765 coindex = fold_convert (gfc_array_index_type,
2766 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2767 NULL));
2768 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2769 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2770 fold_convert (gfc_array_index_type, coindex),
2771 lbound);
2773 for (codim = corank + rank - 2; codim >= rank; codim--)
2775 tree extent, ubound;
2777 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2778 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2779 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2780 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2782 /* coindex *= extent. */
2783 coindex = fold_build2_loc (input_location, MULT_EXPR,
2784 gfc_array_index_type, coindex, extent);
2786 /* coindex += sub(codim). */
2787 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2788 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2789 gfc_array_index_type, coindex,
2790 fold_convert (gfc_array_index_type, tmp));
2792 /* coindex -= lbound(codim). */
2793 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2794 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2795 gfc_array_index_type, coindex, lbound);
2798 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2799 fold_convert(type, coindex),
2800 build_int_cst (type, 1));
2802 /* Return 0 if "coindex" exceeds num_images(). */
2804 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2805 num_images = build_int_cst (type, 1);
2806 else
2808 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2809 integer_zero_node,
2810 build_int_cst (integer_type_node, -1));
2811 num_images = fold_convert (type, tmp);
2814 tmp = gfc_create_var (type, NULL);
2815 gfc_add_modify (&se->pre, tmp, coindex);
2817 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2818 num_images);
2819 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2820 cond,
2821 fold_convert (logical_type_node, invalid_bound));
2822 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2823 build_int_cst (type, 0), tmp);
2826 static void
2827 trans_num_images (gfc_se * se, gfc_expr *expr)
2829 tree tmp, distance, failed;
2830 gfc_se argse;
2832 if (expr->value.function.actual->expr)
2834 gfc_init_se (&argse, NULL);
2835 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2836 gfc_add_block_to_block (&se->pre, &argse.pre);
2837 gfc_add_block_to_block (&se->post, &argse.post);
2838 distance = fold_convert (integer_type_node, argse.expr);
2840 else
2841 distance = integer_zero_node;
2843 if (expr->value.function.actual->next->expr)
2845 gfc_init_se (&argse, NULL);
2846 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2847 gfc_add_block_to_block (&se->pre, &argse.pre);
2848 gfc_add_block_to_block (&se->post, &argse.post);
2849 failed = fold_convert (integer_type_node, argse.expr);
2851 else
2852 failed = build_int_cst (integer_type_node, -1);
2853 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2854 distance, failed);
2855 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2859 static void
2860 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2862 gfc_se argse;
2864 gfc_init_se (&argse, NULL);
2865 argse.data_not_needed = 1;
2866 argse.descriptor_only = 1;
2868 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2869 gfc_add_block_to_block (&se->pre, &argse.pre);
2870 gfc_add_block_to_block (&se->post, &argse.post);
2872 se->expr = gfc_conv_descriptor_rank (argse.expr);
2873 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2874 se->expr);
2878 static void
2879 gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
2881 gfc_expr *arg;
2882 arg = expr->value.function.actual->expr;
2883 gfc_conv_is_contiguous_expr (se, arg);
2884 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2887 /* This function does the work for gfc_conv_intrinsic_is_contiguous,
2888 plus it can be called directly. */
2890 void
2891 gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
2893 gfc_ss *ss;
2894 gfc_se argse;
2895 tree desc, tmp, stride, extent, cond;
2896 int i;
2897 tree fncall0;
2898 gfc_array_spec *as;
2900 if (arg->ts.type == BT_CLASS)
2901 gfc_add_class_array_ref (arg);
2903 ss = gfc_walk_expr (arg);
2904 gcc_assert (ss != gfc_ss_terminator);
2905 gfc_init_se (&argse, NULL);
2906 argse.data_not_needed = 1;
2907 gfc_conv_expr_descriptor (&argse, arg);
2909 as = gfc_get_full_arrayspec_from_expr (arg);
2911 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2912 Note in addition that zero-sized arrays don't count as contiguous. */
2914 if (as && as->type == AS_ASSUMED_RANK)
2916 /* Build the call to is_contiguous0. */
2917 argse.want_pointer = 1;
2918 gfc_conv_expr_descriptor (&argse, arg);
2919 gfc_add_block_to_block (&se->pre, &argse.pre);
2920 gfc_add_block_to_block (&se->post, &argse.post);
2921 desc = gfc_evaluate_now (argse.expr, &se->pre);
2922 fncall0 = build_call_expr_loc (input_location,
2923 gfor_fndecl_is_contiguous0, 1, desc);
2924 se->expr = fncall0;
2925 se->expr = convert (logical_type_node, se->expr);
2927 else
2929 gfc_add_block_to_block (&se->pre, &argse.pre);
2930 gfc_add_block_to_block (&se->post, &argse.post);
2931 desc = gfc_evaluate_now (argse.expr, &se->pre);
2933 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
2934 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2935 stride, build_int_cst (TREE_TYPE (stride), 1));
2937 for (i = 0; i < arg->rank - 1; i++)
2939 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2940 extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2941 extent = fold_build2_loc (input_location, MINUS_EXPR,
2942 gfc_array_index_type, extent, tmp);
2943 extent = fold_build2_loc (input_location, PLUS_EXPR,
2944 gfc_array_index_type, extent,
2945 gfc_index_one_node);
2946 tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
2947 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2948 tmp, extent);
2949 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
2950 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2951 stride, tmp);
2952 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2953 boolean_type_node, cond, tmp);
2955 se->expr = cond;
2960 /* Evaluate a single upper or lower bound. */
2961 /* TODO: bound intrinsic generates way too much unnecessary code. */
2963 static void
2964 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
2966 gfc_actual_arglist *arg;
2967 gfc_actual_arglist *arg2;
2968 tree desc;
2969 tree type;
2970 tree bound;
2971 tree tmp;
2972 tree cond, cond1;
2973 tree ubound;
2974 tree lbound;
2975 tree size;
2976 gfc_se argse;
2977 gfc_array_spec * as;
2978 bool assumed_rank_lb_one;
2980 arg = expr->value.function.actual;
2981 arg2 = arg->next;
2983 if (se->ss)
2985 /* Create an implicit second parameter from the loop variable. */
2986 gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE);
2987 gcc_assert (se->loop->dimen == 1);
2988 gcc_assert (se->ss->info->expr == expr);
2989 gfc_advance_se_ss_chain (se);
2990 bound = se->loop->loopvar[0];
2991 bound = fold_build2_loc (input_location, MINUS_EXPR,
2992 gfc_array_index_type, bound,
2993 se->loop->from[0]);
2995 else
2997 /* use the passed argument. */
2998 gcc_assert (arg2->expr);
2999 gfc_init_se (&argse, NULL);
3000 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3001 gfc_add_block_to_block (&se->pre, &argse.pre);
3002 bound = argse.expr;
3003 /* Convert from one based to zero based. */
3004 bound = fold_build2_loc (input_location, MINUS_EXPR,
3005 gfc_array_index_type, bound,
3006 gfc_index_one_node);
3009 /* TODO: don't re-evaluate the descriptor on each iteration. */
3010 /* Get a descriptor for the first parameter. */
3011 gfc_init_se (&argse, NULL);
3012 gfc_conv_expr_descriptor (&argse, arg->expr);
3013 gfc_add_block_to_block (&se->pre, &argse.pre);
3014 gfc_add_block_to_block (&se->post, &argse.post);
3016 desc = argse.expr;
3018 as = gfc_get_full_arrayspec_from_expr (arg->expr);
3020 if (INTEGER_CST_P (bound))
3022 gcc_assert (op != GFC_ISYM_SHAPE);
3023 if (((!as || as->type != AS_ASSUMED_RANK)
3024 && wi::geu_p (wi::to_wide (bound),
3025 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
3026 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
3027 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3028 "dimension index",
3029 (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
3030 &expr->where);
3033 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
3035 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3037 bound = gfc_evaluate_now (bound, &se->pre);
3038 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3039 bound, build_int_cst (TREE_TYPE (bound), 0));
3040 if (as && as->type == AS_ASSUMED_RANK)
3041 tmp = gfc_conv_descriptor_rank (desc);
3042 else
3043 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
3044 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3045 bound, fold_convert(TREE_TYPE (bound), tmp));
3046 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3047 logical_type_node, cond, tmp);
3048 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3049 gfc_msg_fault);
3053 /* Take care of the lbound shift for assumed-rank arrays that are
3054 nonallocatable and nonpointers. Those have a lbound of 1. */
3055 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
3056 && ((arg->expr->ts.type != BT_CLASS
3057 && !arg->expr->symtree->n.sym->attr.allocatable
3058 && !arg->expr->symtree->n.sym->attr.pointer)
3059 || (arg->expr->ts.type == BT_CLASS
3060 && !CLASS_DATA (arg->expr)->attr.allocatable
3061 && !CLASS_DATA (arg->expr)->attr.class_pointer));
3063 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
3064 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
3065 size = fold_build2_loc (input_location, MINUS_EXPR,
3066 gfc_array_index_type, ubound, lbound);
3067 size = fold_build2_loc (input_location, PLUS_EXPR,
3068 gfc_array_index_type, size, gfc_index_one_node);
3070 /* 13.14.53: Result value for LBOUND
3072 Case (i): For an array section or for an array expression other than a
3073 whole array or array structure component, LBOUND(ARRAY, DIM)
3074 has the value 1. For a whole array or array structure
3075 component, LBOUND(ARRAY, DIM) has the value:
3076 (a) equal to the lower bound for subscript DIM of ARRAY if
3077 dimension DIM of ARRAY does not have extent zero
3078 or if ARRAY is an assumed-size array of rank DIM,
3079 or (b) 1 otherwise.
3081 13.14.113: Result value for UBOUND
3083 Case (i): For an array section or for an array expression other than a
3084 whole array or array structure component, UBOUND(ARRAY, DIM)
3085 has the value equal to the number of elements in the given
3086 dimension; otherwise, it has a value equal to the upper bound
3087 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3088 not have size zero and has value zero if dimension DIM has
3089 size zero. */
3091 if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
3092 se->expr = gfc_index_one_node;
3093 else if (as)
3095 if (op == GFC_ISYM_UBOUND)
3097 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3098 size, gfc_index_zero_node);
3099 se->expr = fold_build3_loc (input_location, COND_EXPR,
3100 gfc_array_index_type, cond,
3101 (assumed_rank_lb_one ? size : ubound),
3102 gfc_index_zero_node);
3104 else if (op == GFC_ISYM_LBOUND)
3106 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3107 size, gfc_index_zero_node);
3108 if (as->type == AS_ASSUMED_SIZE)
3110 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3111 logical_type_node, bound,
3112 build_int_cst (TREE_TYPE (bound),
3113 arg->expr->rank - 1));
3114 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3115 logical_type_node, cond, cond1);
3117 se->expr = fold_build3_loc (input_location, COND_EXPR,
3118 gfc_array_index_type, cond,
3119 lbound, gfc_index_one_node);
3121 else if (op == GFC_ISYM_SHAPE)
3122 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3123 gfc_array_index_type, size,
3124 gfc_index_zero_node);
3125 else
3126 gcc_unreachable ();
3128 /* According to F2018 16.9.172, para 5, an assumed rank object,
3129 argument associated with and assumed size array, has the ubound
3130 of the final dimension set to -1 and UBOUND must return this.
3131 Similarly for the SHAPE intrinsic. */
3132 if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
3134 tree minus_one = build_int_cst (gfc_array_index_type, -1);
3135 tree rank = fold_convert (gfc_array_index_type,
3136 gfc_conv_descriptor_rank (desc));
3137 rank = fold_build2_loc (input_location, PLUS_EXPR,
3138 gfc_array_index_type, rank, minus_one);
3140 /* Fix the expression to stop it from becoming even more
3141 complicated. */
3142 se->expr = gfc_evaluate_now (se->expr, &se->pre);
3144 /* Descriptors for assumed-size arrays have ubound = -1
3145 in the last dimension. */
3146 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3147 logical_type_node, ubound, minus_one);
3148 cond = fold_build2_loc (input_location, EQ_EXPR,
3149 logical_type_node, bound, rank);
3150 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3151 logical_type_node, cond, cond1);
3152 se->expr = fold_build3_loc (input_location, COND_EXPR,
3153 gfc_array_index_type, cond,
3154 minus_one, se->expr);
3157 else /* as is null; this is an old-fashioned 1-based array. */
3159 if (op != GFC_ISYM_LBOUND)
3161 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3162 gfc_array_index_type, size,
3163 gfc_index_zero_node);
3165 else
3166 se->expr = gfc_index_one_node;
3170 type = gfc_typenode_for_spec (&expr->ts);
3171 se->expr = convert (type, se->expr);
3175 static void
3176 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3178 gfc_actual_arglist *arg;
3179 gfc_actual_arglist *arg2;
3180 gfc_se argse;
3181 tree bound, resbound, resbound2, desc, cond, tmp;
3182 tree type;
3183 int corank;
3185 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
3186 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
3187 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
3189 arg = expr->value.function.actual;
3190 arg2 = arg->next;
3192 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
3193 corank = arg->expr->corank;
3195 gfc_init_se (&argse, NULL);
3196 argse.want_coarray = 1;
3198 gfc_conv_expr_descriptor (&argse, arg->expr);
3199 gfc_add_block_to_block (&se->pre, &argse.pre);
3200 gfc_add_block_to_block (&se->post, &argse.post);
3201 desc = argse.expr;
3203 if (se->ss)
3205 /* Create an implicit second parameter from the loop variable. */
3206 gcc_assert (!arg2->expr);
3207 gcc_assert (corank > 0);
3208 gcc_assert (se->loop->dimen == 1);
3209 gcc_assert (se->ss->info->expr == expr);
3211 bound = se->loop->loopvar[0];
3212 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3213 bound, gfc_rank_cst[arg->expr->rank]);
3214 gfc_advance_se_ss_chain (se);
3216 else
3218 /* use the passed argument. */
3219 gcc_assert (arg2->expr);
3220 gfc_init_se (&argse, NULL);
3221 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3222 gfc_add_block_to_block (&se->pre, &argse.pre);
3223 bound = argse.expr;
3225 if (INTEGER_CST_P (bound))
3227 if (wi::ltu_p (wi::to_wide (bound), 1)
3228 || wi::gtu_p (wi::to_wide (bound),
3229 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3230 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3231 "dimension index", expr->value.function.isym->name,
3232 &expr->where);
3234 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3236 bound = gfc_evaluate_now (bound, &se->pre);
3237 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3238 bound, build_int_cst (TREE_TYPE (bound), 1));
3239 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3240 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3241 bound, tmp);
3242 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3243 logical_type_node, cond, tmp);
3244 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3245 gfc_msg_fault);
3249 /* Subtract 1 to get to zero based and add dimensions. */
3250 switch (arg->expr->rank)
3252 case 0:
3253 bound = fold_build2_loc (input_location, MINUS_EXPR,
3254 gfc_array_index_type, bound,
3255 gfc_index_one_node);
3256 case 1:
3257 break;
3258 default:
3259 bound = fold_build2_loc (input_location, PLUS_EXPR,
3260 gfc_array_index_type, bound,
3261 gfc_rank_cst[arg->expr->rank - 1]);
3265 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3267 /* Handle UCOBOUND with special handling of the last codimension. */
3268 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3270 /* Last codimension: For -fcoarray=single just return
3271 the lcobound - otherwise add
3272 ceiling (real (num_images ()) / real (size)) - 1
3273 = (num_images () + size - 1) / size - 1
3274 = (num_images - 1) / size(),
3275 where size is the product of the extent of all but the last
3276 codimension. */
3278 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3280 tree cosize;
3282 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3283 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3284 2, integer_zero_node,
3285 build_int_cst (integer_type_node, -1));
3286 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3287 gfc_array_index_type,
3288 fold_convert (gfc_array_index_type, tmp),
3289 build_int_cst (gfc_array_index_type, 1));
3290 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3291 gfc_array_index_type, tmp,
3292 fold_convert (gfc_array_index_type, cosize));
3293 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3294 gfc_array_index_type, resbound, tmp);
3296 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3298 /* ubound = lbound + num_images() - 1. */
3299 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3300 2, integer_zero_node,
3301 build_int_cst (integer_type_node, -1));
3302 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3303 gfc_array_index_type,
3304 fold_convert (gfc_array_index_type, tmp),
3305 build_int_cst (gfc_array_index_type, 1));
3306 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3307 gfc_array_index_type, resbound, tmp);
3310 if (corank > 1)
3312 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3313 bound,
3314 build_int_cst (TREE_TYPE (bound),
3315 arg->expr->rank + corank - 1));
3317 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3318 se->expr = fold_build3_loc (input_location, COND_EXPR,
3319 gfc_array_index_type, cond,
3320 resbound, resbound2);
3322 else
3323 se->expr = resbound;
3325 else
3326 se->expr = resbound;
3328 type = gfc_typenode_for_spec (&expr->ts);
3329 se->expr = convert (type, se->expr);
3333 static void
3334 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3336 gfc_actual_arglist *array_arg;
3337 gfc_actual_arglist *dim_arg;
3338 gfc_se argse;
3339 tree desc, tmp;
3341 array_arg = expr->value.function.actual;
3342 dim_arg = array_arg->next;
3344 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3346 gfc_init_se (&argse, NULL);
3347 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3348 gfc_add_block_to_block (&se->pre, &argse.pre);
3349 gfc_add_block_to_block (&se->post, &argse.post);
3350 desc = argse.expr;
3352 gcc_assert (dim_arg->expr);
3353 gfc_init_se (&argse, NULL);
3354 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3355 gfc_add_block_to_block (&se->pre, &argse.pre);
3356 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3357 argse.expr, gfc_index_one_node);
3358 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3361 static void
3362 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3364 tree arg, cabs;
3366 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3368 switch (expr->value.function.actual->expr->ts.type)
3370 case BT_INTEGER:
3371 case BT_REAL:
3372 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3373 arg);
3374 break;
3376 case BT_COMPLEX:
3377 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3378 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3379 break;
3381 default:
3382 gcc_unreachable ();
3387 /* Create a complex value from one or two real components. */
3389 static void
3390 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3392 tree real;
3393 tree imag;
3394 tree type;
3395 tree *args;
3396 unsigned int num_args;
3398 num_args = gfc_intrinsic_argument_list_length (expr);
3399 args = XALLOCAVEC (tree, num_args);
3401 type = gfc_typenode_for_spec (&expr->ts);
3402 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3403 real = convert (TREE_TYPE (type), args[0]);
3404 if (both)
3405 imag = convert (TREE_TYPE (type), args[1]);
3406 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3408 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3409 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3410 imag = convert (TREE_TYPE (type), imag);
3412 else
3413 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3415 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3419 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3420 MODULO(A, P) = A - FLOOR (A / P) * P
3422 The obvious algorithms above are numerically instable for large
3423 arguments, hence these intrinsics are instead implemented via calls
3424 to the fmod family of functions. It is the responsibility of the
3425 user to ensure that the second argument is non-zero. */
3427 static void
3428 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3430 tree type;
3431 tree tmp;
3432 tree test;
3433 tree test2;
3434 tree fmod;
3435 tree zero;
3436 tree args[2];
3438 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3440 switch (expr->ts.type)
3442 case BT_INTEGER:
3443 /* Integer case is easy, we've got a builtin op. */
3444 type = TREE_TYPE (args[0]);
3446 if (modulo)
3447 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3448 args[0], args[1]);
3449 else
3450 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3451 args[0], args[1]);
3452 break;
3454 case BT_UNSIGNED:
3455 /* Even easier, we only need one. */
3456 type = TREE_TYPE (args[0]);
3457 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3458 args[0], args[1]);
3459 break;
3461 case BT_REAL:
3462 fmod = NULL_TREE;
3463 /* Check if we have a builtin fmod. */
3464 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3466 /* The builtin should always be available. */
3467 gcc_assert (fmod != NULL_TREE);
3469 tmp = build_addr (fmod);
3470 se->expr = build_call_array_loc (input_location,
3471 TREE_TYPE (TREE_TYPE (fmod)),
3472 tmp, 2, args);
3473 if (modulo == 0)
3474 return;
3476 type = TREE_TYPE (args[0]);
3478 args[0] = gfc_evaluate_now (args[0], &se->pre);
3479 args[1] = gfc_evaluate_now (args[1], &se->pre);
3481 /* Definition:
3482 modulo = arg - floor (arg/arg2) * arg2
3484 In order to calculate the result accurately, we use the fmod
3485 function as follows.
3487 res = fmod (arg, arg2);
3488 if (res)
3490 if ((arg < 0) xor (arg2 < 0))
3491 res += arg2;
3493 else
3494 res = copysign (0., arg2);
3496 => As two nested ternary exprs:
3498 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3499 : copysign (0., arg2);
3503 zero = gfc_build_const (type, integer_zero_node);
3504 tmp = gfc_evaluate_now (se->expr, &se->pre);
3505 if (!flag_signed_zeros)
3507 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3508 args[0], zero);
3509 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3510 args[1], zero);
3511 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3512 logical_type_node, test, test2);
3513 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3514 tmp, zero);
3515 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3516 logical_type_node, test, test2);
3517 test = gfc_evaluate_now (test, &se->pre);
3518 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3519 fold_build2_loc (input_location,
3520 PLUS_EXPR,
3521 type, tmp, args[1]),
3522 tmp);
3524 else
3526 tree expr1, copysign, cscall;
3527 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3528 expr->ts.kind);
3529 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3530 args[0], zero);
3531 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3532 args[1], zero);
3533 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3534 logical_type_node, test, test2);
3535 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3536 fold_build2_loc (input_location,
3537 PLUS_EXPR,
3538 type, tmp, args[1]),
3539 tmp);
3540 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3541 tmp, zero);
3542 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3543 args[1]);
3544 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3545 expr1, cscall);
3547 return;
3549 default:
3550 gcc_unreachable ();
3554 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3555 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3556 where the right shifts are logical (i.e. 0's are shifted in).
3557 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3558 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3559 DSHIFTL(I,J,0) = I
3560 DSHIFTL(I,J,BITSIZE) = J
3561 DSHIFTR(I,J,0) = J
3562 DSHIFTR(I,J,BITSIZE) = I. */
3564 static void
3565 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3567 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3568 tree args[3], cond, tmp;
3569 int bitsize;
3571 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3573 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3574 type = TREE_TYPE (args[0]);
3575 bitsize = TYPE_PRECISION (type);
3576 utype = unsigned_type_for (type);
3577 stype = TREE_TYPE (args[2]);
3579 arg1 = gfc_evaluate_now (args[0], &se->pre);
3580 arg2 = gfc_evaluate_now (args[1], &se->pre);
3581 shift = gfc_evaluate_now (args[2], &se->pre);
3583 /* The generic case. */
3584 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3585 build_int_cst (stype, bitsize), shift);
3586 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3587 arg1, dshiftl ? shift : tmp);
3589 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3590 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3591 right = fold_convert (type, right);
3593 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3595 /* Special cases. */
3596 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3597 build_int_cst (stype, 0));
3598 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3599 dshiftl ? arg1 : arg2, res);
3601 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3602 build_int_cst (stype, bitsize));
3603 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3604 dshiftl ? arg2 : arg1, res);
3606 se->expr = res;
3610 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3612 static void
3613 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3615 tree val;
3616 tree tmp;
3617 tree type;
3618 tree zero;
3619 tree args[2];
3621 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3622 type = TREE_TYPE (args[0]);
3624 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3625 val = gfc_evaluate_now (val, &se->pre);
3627 zero = gfc_build_const (type, integer_zero_node);
3628 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3629 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3633 /* SIGN(A, B) is absolute value of A times sign of B.
3634 The real value versions use library functions to ensure the correct
3635 handling of negative zero. Integer case implemented as:
3636 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3639 static void
3640 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3642 tree tmp;
3643 tree type;
3644 tree args[2];
3646 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3647 if (expr->ts.type == BT_REAL)
3649 tree abs;
3651 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3652 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3654 /* We explicitly have to ignore the minus sign. We do so by using
3655 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3656 if (!flag_sign_zero
3657 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3659 tree cond, zero;
3660 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3661 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3662 args[1], zero);
3663 se->expr = fold_build3_loc (input_location, COND_EXPR,
3664 TREE_TYPE (args[0]), cond,
3665 build_call_expr_loc (input_location, abs, 1,
3666 args[0]),
3667 build_call_expr_loc (input_location, tmp, 2,
3668 args[0], args[1]));
3670 else
3671 se->expr = build_call_expr_loc (input_location, tmp, 2,
3672 args[0], args[1]);
3673 return;
3676 /* Having excluded floating point types, we know we are now dealing
3677 with signed integer types. */
3678 type = TREE_TYPE (args[0]);
3680 /* Args[0] is used multiple times below. */
3681 args[0] = gfc_evaluate_now (args[0], &se->pre);
3683 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3684 the signs of A and B are the same, and of all ones if they differ. */
3685 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3686 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3687 build_int_cst (type, TYPE_PRECISION (type) - 1));
3688 tmp = gfc_evaluate_now (tmp, &se->pre);
3690 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3691 is all ones (i.e. -1). */
3692 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3693 fold_build2_loc (input_location, PLUS_EXPR,
3694 type, args[0], tmp), tmp);
3698 /* Test for the presence of an optional argument. */
3700 static void
3701 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3703 gfc_expr *arg;
3705 arg = expr->value.function.actual->expr;
3706 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3707 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3708 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3712 /* Calculate the double precision product of two single precision values. */
3714 static void
3715 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3717 tree type;
3718 tree args[2];
3720 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3722 /* Convert the args to double precision before multiplying. */
3723 type = gfc_typenode_for_spec (&expr->ts);
3724 args[0] = convert (type, args[0]);
3725 args[1] = convert (type, args[1]);
3726 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3727 args[1]);
3731 /* Return a length one character string containing an ascii character. */
3733 static void
3734 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3736 tree arg[2];
3737 tree var;
3738 tree type;
3739 unsigned int num_args;
3741 num_args = gfc_intrinsic_argument_list_length (expr);
3742 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3744 type = gfc_get_char_type (expr->ts.kind);
3745 var = gfc_create_var (type, "char");
3747 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3748 gfc_add_modify (&se->pre, var, arg[0]);
3749 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3750 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3754 static void
3755 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3757 tree var;
3758 tree len;
3759 tree tmp;
3760 tree cond;
3761 tree fndecl;
3762 tree *args;
3763 unsigned int num_args;
3765 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3766 args = XALLOCAVEC (tree, num_args);
3768 var = gfc_create_var (pchar_type_node, "pstr");
3769 len = gfc_create_var (gfc_charlen_type_node, "len");
3771 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3772 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3773 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3775 fndecl = build_addr (gfor_fndecl_ctime);
3776 tmp = build_call_array_loc (input_location,
3777 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3778 fndecl, num_args, args);
3779 gfc_add_expr_to_block (&se->pre, tmp);
3781 /* Free the temporary afterwards, if necessary. */
3782 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3783 len, build_int_cst (TREE_TYPE (len), 0));
3784 tmp = gfc_call_free (var);
3785 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3786 gfc_add_expr_to_block (&se->post, tmp);
3788 se->expr = var;
3789 se->string_length = len;
3793 static void
3794 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3796 tree var;
3797 tree len;
3798 tree tmp;
3799 tree cond;
3800 tree fndecl;
3801 tree *args;
3802 unsigned int num_args;
3804 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3805 args = XALLOCAVEC (tree, num_args);
3807 var = gfc_create_var (pchar_type_node, "pstr");
3808 len = gfc_create_var (gfc_charlen_type_node, "len");
3810 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3811 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3812 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3814 fndecl = build_addr (gfor_fndecl_fdate);
3815 tmp = build_call_array_loc (input_location,
3816 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3817 fndecl, num_args, args);
3818 gfc_add_expr_to_block (&se->pre, tmp);
3820 /* Free the temporary afterwards, if necessary. */
3821 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3822 len, build_int_cst (TREE_TYPE (len), 0));
3823 tmp = gfc_call_free (var);
3824 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3825 gfc_add_expr_to_block (&se->post, tmp);
3827 se->expr = var;
3828 se->string_length = len;
3832 /* Generate a direct call to free() for the FREE subroutine. */
3834 static tree
3835 conv_intrinsic_free (gfc_code *code)
3837 stmtblock_t block;
3838 gfc_se argse;
3839 tree arg, call;
3841 gfc_init_se (&argse, NULL);
3842 gfc_conv_expr (&argse, code->ext.actual->expr);
3843 arg = fold_convert (ptr_type_node, argse.expr);
3845 gfc_init_block (&block);
3846 call = build_call_expr_loc (input_location,
3847 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3848 gfc_add_expr_to_block (&block, call);
3849 return gfc_finish_block (&block);
3853 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3854 handling seeding on coarray images. */
3856 static tree
3857 conv_intrinsic_random_init (gfc_code *code)
3859 stmtblock_t block;
3860 gfc_se se;
3861 tree arg1, arg2, tmp;
3862 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3863 tree used_bool_type_node = flag_coarray == GFC_FCOARRAY_LIB
3864 ? logical_type_node
3865 : gfc_get_logical_type (4);
3867 /* Make the function call. */
3868 gfc_init_block (&block);
3869 gfc_init_se (&se, NULL);
3871 /* Convert REPEATABLE to the desired LOGICAL entity. */
3872 gfc_conv_expr (&se, code->ext.actual->expr);
3873 gfc_add_block_to_block (&block, &se.pre);
3874 arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3875 gfc_add_block_to_block (&block, &se.post);
3877 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3878 gfc_conv_expr (&se, code->ext.actual->next->expr);
3879 gfc_add_block_to_block (&block, &se.pre);
3880 arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3881 gfc_add_block_to_block (&block, &se.post);
3883 if (flag_coarray == GFC_FCOARRAY_LIB)
3885 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
3886 2, arg1, arg2);
3888 else
3890 /* The ABI for libgfortran needs to be maintained, so a hidden
3891 argument must be include if code is compiled with -fcoarray=single
3892 or without the option. Set to 0. */
3893 tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
3894 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
3895 3, arg1, arg2, arg3);
3898 gfc_add_expr_to_block (&block, tmp);
3900 return gfc_finish_block (&block);
3904 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3905 conversions. */
3907 static tree
3908 conv_intrinsic_system_clock (gfc_code *code)
3910 stmtblock_t block;
3911 gfc_se count_se, count_rate_se, count_max_se;
3912 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3913 tree tmp;
3914 int least;
3916 gfc_expr *count = code->ext.actual->expr;
3917 gfc_expr *count_rate = code->ext.actual->next->expr;
3918 gfc_expr *count_max = code->ext.actual->next->next->expr;
3920 /* Evaluate our arguments. */
3921 if (count)
3923 gfc_init_se (&count_se, NULL);
3924 gfc_conv_expr (&count_se, count);
3927 if (count_rate)
3929 gfc_init_se (&count_rate_se, NULL);
3930 gfc_conv_expr (&count_rate_se, count_rate);
3933 if (count_max)
3935 gfc_init_se (&count_max_se, NULL);
3936 gfc_conv_expr (&count_max_se, count_max);
3939 /* Find the smallest kind found of the arguments. */
3940 least = 16;
3941 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3942 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3943 : least;
3944 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3945 : least;
3947 /* Prepare temporary variables. */
3949 if (count)
3951 if (least >= 8)
3952 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3953 else if (least == 4)
3954 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3955 else if (count->ts.kind == 1)
3956 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3957 count->ts.kind);
3958 else
3959 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3960 count->ts.kind);
3963 if (count_rate)
3965 if (least >= 8)
3966 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3967 else if (least == 4)
3968 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3969 else
3970 arg2 = integer_zero_node;
3973 if (count_max)
3975 if (least >= 8)
3976 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3977 else if (least == 4)
3978 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3979 else
3980 arg3 = integer_zero_node;
3983 /* Make the function call. */
3984 gfc_init_block (&block);
3986 if (least <= 2)
3988 if (least == 1)
3990 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3991 : null_pointer_node;
3992 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3993 : null_pointer_node;
3994 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3995 : null_pointer_node;
3998 if (least == 2)
4000 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
4001 : null_pointer_node;
4002 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
4003 : null_pointer_node;
4004 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
4005 : null_pointer_node;
4008 else
4010 if (least == 4)
4012 tmp = build_call_expr_loc (input_location,
4013 gfor_fndecl_system_clock4, 3,
4014 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
4015 : null_pointer_node,
4016 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
4017 : null_pointer_node,
4018 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
4019 : null_pointer_node);
4020 gfc_add_expr_to_block (&block, tmp);
4022 /* Handle kind>=8, 10, or 16 arguments */
4023 if (least >= 8)
4025 tmp = build_call_expr_loc (input_location,
4026 gfor_fndecl_system_clock8, 3,
4027 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
4028 : null_pointer_node,
4029 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
4030 : null_pointer_node,
4031 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
4032 : null_pointer_node);
4033 gfc_add_expr_to_block (&block, tmp);
4037 /* And store values back if needed. */
4038 if (arg1 && arg1 != count_se.expr)
4039 gfc_add_modify (&block, count_se.expr,
4040 fold_convert (TREE_TYPE (count_se.expr), arg1));
4041 if (arg2 && arg2 != count_rate_se.expr)
4042 gfc_add_modify (&block, count_rate_se.expr,
4043 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
4044 if (arg3 && arg3 != count_max_se.expr)
4045 gfc_add_modify (&block, count_max_se.expr,
4046 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
4048 return gfc_finish_block (&block);
4052 /* Return a character string containing the tty name. */
4054 static void
4055 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
4057 tree var;
4058 tree len;
4059 tree tmp;
4060 tree cond;
4061 tree fndecl;
4062 tree *args;
4063 unsigned int num_args;
4065 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
4066 args = XALLOCAVEC (tree, num_args);
4068 var = gfc_create_var (pchar_type_node, "pstr");
4069 len = gfc_create_var (gfc_charlen_type_node, "len");
4071 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
4072 args[0] = gfc_build_addr_expr (NULL_TREE, var);
4073 args[1] = gfc_build_addr_expr (NULL_TREE, len);
4075 fndecl = build_addr (gfor_fndecl_ttynam);
4076 tmp = build_call_array_loc (input_location,
4077 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
4078 fndecl, num_args, args);
4079 gfc_add_expr_to_block (&se->pre, tmp);
4081 /* Free the temporary afterwards, if necessary. */
4082 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4083 len, build_int_cst (TREE_TYPE (len), 0));
4084 tmp = gfc_call_free (var);
4085 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4086 gfc_add_expr_to_block (&se->post, tmp);
4088 se->expr = var;
4089 se->string_length = len;
4093 /* Get the minimum/maximum value of all the parameters.
4094 minmax (a1, a2, a3, ...)
4096 mvar = a1;
4097 mvar = COMP (mvar, a2)
4098 mvar = COMP (mvar, a3)
4100 return mvar;
4102 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4103 care about NaNs, or IFN_FMIN/MAX when the target has support for
4104 fast NaN-honouring min/max. When neither holds expand a sequence
4105 of explicit comparisons. */
4107 /* TODO: Mismatching types can occur when specific names are used.
4108 These should be handled during resolution. */
4109 static void
4110 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4112 tree tmp;
4113 tree mvar;
4114 tree val;
4115 tree *args;
4116 tree type;
4117 tree argtype;
4118 gfc_actual_arglist *argexpr;
4119 unsigned int i, nargs;
4121 nargs = gfc_intrinsic_argument_list_length (expr);
4122 args = XALLOCAVEC (tree, nargs);
4124 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4125 type = gfc_typenode_for_spec (&expr->ts);
4127 /* Only evaluate the argument once. */
4128 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
4129 args[0] = gfc_evaluate_now (args[0], &se->pre);
4131 /* Determine suitable type of temporary, as a GNU extension allows
4132 different argument kinds. */
4133 argtype = TREE_TYPE (args[0]);
4134 argexpr = expr->value.function.actual;
4135 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4137 tree tmptype = TREE_TYPE (args[i]);
4138 if (TYPE_PRECISION (tmptype) > TYPE_PRECISION (argtype))
4139 argtype = tmptype;
4141 mvar = gfc_create_var (argtype, "M");
4142 gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
4144 argexpr = expr->value.function.actual;
4145 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4147 tree cond = NULL_TREE;
4148 val = args[i];
4150 /* Handle absent optional arguments by ignoring the comparison. */
4151 if (argexpr->expr->expr_type == EXPR_VARIABLE
4152 && argexpr->expr->symtree->n.sym->attr.optional
4153 && INDIRECT_REF_P (val))
4155 cond = fold_build2_loc (input_location,
4156 NE_EXPR, logical_type_node,
4157 TREE_OPERAND (val, 0),
4158 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
4160 else if (!VAR_P (val) && !TREE_CONSTANT (val))
4161 /* Only evaluate the argument once. */
4162 val = gfc_evaluate_now (val, &se->pre);
4164 tree calc;
4165 /* For floating point types, the question is what MAX(a, NaN) or
4166 MIN(a, NaN) should return (where "a" is a normal number).
4167 There are valid use case for returning either one, but the
4168 Fortran standard doesn't specify which one should be chosen.
4169 Also, there is no consensus among other tested compilers. In
4170 short, it's a mess. So lets just do whatever is fastest. */
4171 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
4172 calc = fold_build2_loc (input_location, code, argtype,
4173 convert (argtype, val), mvar);
4174 tmp = build2_v (MODIFY_EXPR, mvar, calc);
4176 if (cond != NULL_TREE)
4177 tmp = build3_v (COND_EXPR, cond, tmp,
4178 build_empty_stmt (input_location));
4179 gfc_add_expr_to_block (&se->pre, tmp);
4181 se->expr = convert (type, mvar);
4185 /* Generate library calls for MIN and MAX intrinsics for character
4186 variables. */
4187 static void
4188 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4190 tree *args;
4191 tree var, len, fndecl, tmp, cond, function;
4192 unsigned int nargs;
4194 nargs = gfc_intrinsic_argument_list_length (expr);
4195 args = XALLOCAVEC (tree, nargs + 4);
4196 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4198 /* Create the result variables. */
4199 len = gfc_create_var (gfc_charlen_type_node, "len");
4200 args[0] = gfc_build_addr_expr (NULL_TREE, len);
4201 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4202 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
4203 args[2] = build_int_cst (integer_type_node, op);
4204 args[3] = build_int_cst (integer_type_node, nargs / 2);
4206 if (expr->ts.kind == 1)
4207 function = gfor_fndecl_string_minmax;
4208 else if (expr->ts.kind == 4)
4209 function = gfor_fndecl_string_minmax_char4;
4210 else
4211 gcc_unreachable ();
4213 /* Make the function call. */
4214 fndecl = build_addr (function);
4215 tmp = build_call_array_loc (input_location,
4216 TREE_TYPE (TREE_TYPE (function)), fndecl,
4217 nargs + 4, args);
4218 gfc_add_expr_to_block (&se->pre, tmp);
4220 /* Free the temporary afterwards, if necessary. */
4221 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4222 len, build_int_cst (TREE_TYPE (len), 0));
4223 tmp = gfc_call_free (var);
4224 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4225 gfc_add_expr_to_block (&se->post, tmp);
4227 se->expr = var;
4228 se->string_length = len;
4232 /* Create a symbol node for this intrinsic. The symbol from the frontend
4233 has the generic name. */
4235 static gfc_symbol *
4236 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4238 gfc_symbol *sym;
4240 /* TODO: Add symbols for intrinsic function to the global namespace. */
4241 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4242 sym = gfc_new_symbol (expr->value.function.name, NULL);
4244 sym->ts = expr->ts;
4245 if (sym->ts.type == BT_CHARACTER)
4246 sym->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
4247 sym->attr.external = 1;
4248 sym->attr.function = 1;
4249 sym->attr.always_explicit = 1;
4250 sym->attr.proc = PROC_INTRINSIC;
4251 sym->attr.flavor = FL_PROCEDURE;
4252 sym->result = sym;
4253 if (expr->rank > 0)
4255 sym->attr.dimension = 1;
4256 sym->as = gfc_get_array_spec ();
4257 sym->as->type = AS_ASSUMED_SHAPE;
4258 sym->as->rank = expr->rank;
4261 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4262 ignore_optional ? expr->value.function.actual
4263 : NULL);
4265 return sym;
4268 /* Remove empty actual arguments. */
4270 static void
4271 remove_empty_actual_arguments (gfc_actual_arglist **ap)
4273 while (*ap)
4275 if ((*ap)->expr == NULL)
4277 gfc_actual_arglist *r = *ap;
4278 *ap = r->next;
4279 r->next = NULL;
4280 gfc_free_actual_arglist (r);
4282 else
4283 ap = &((*ap)->next);
4287 #define MAX_SPEC_ARG 12
4289 /* Make up an fn spec that's right for intrinsic functions that we
4290 want to call. */
4292 static char *
4293 intrinsic_fnspec (gfc_expr *expr)
4295 static char fnspec_buf[MAX_SPEC_ARG*2+1];
4296 char *fp;
4297 int i;
4298 int num_char_args;
4300 #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4302 /* Set the fndecl. */
4303 fp = fnspec_buf;
4304 /* Function return value. FIXME: Check if the second letter could
4305 be something other than a space, for further optimization. */
4306 ADD_CHAR ('.');
4307 if (expr->rank == 0)
4309 if (expr->ts.type == BT_CHARACTER)
4311 ADD_CHAR ('w'); /* Address of character. */
4312 ADD_CHAR ('.'); /* Length of character. */
4315 else
4316 ADD_CHAR ('w'); /* Return value is a descriptor. */
4318 num_char_args = 0;
4319 for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
4321 if (a->expr == NULL)
4322 continue;
4324 if (a->name && strcmp (a->name,"%VAL") == 0)
4325 ADD_CHAR ('.');
4326 else
4328 if (a->expr->rank > 0)
4329 ADD_CHAR ('r');
4330 else
4331 ADD_CHAR ('R');
4333 num_char_args += a->expr->ts.type == BT_CHARACTER;
4334 gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
4337 for (i = 0; i < num_char_args; i++)
4338 ADD_CHAR ('.');
4340 *fp = '\0';
4341 return fnspec_buf;
4344 #undef MAX_SPEC_ARG
4345 #undef ADD_CHAR
4347 /* Generate the right symbol for the specific intrinsic function and
4348 modify the expr accordingly. This assumes that absent optional
4349 arguments should be removed. */
4351 gfc_symbol *
4352 specific_intrinsic_symbol (gfc_expr *expr)
4354 gfc_symbol *sym;
4356 sym = gfc_find_intrinsic_symbol (expr);
4357 if (sym == NULL)
4359 sym = gfc_get_intrinsic_function_symbol (expr);
4360 sym->ts = expr->ts;
4361 if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
4362 sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
4364 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4365 expr->value.function.actual, true);
4366 sym->backend_decl
4367 = gfc_get_extern_function_decl (sym, expr->value.function.actual,
4368 intrinsic_fnspec (expr));
4371 remove_empty_actual_arguments (&(expr->value.function.actual));
4373 return sym;
4376 /* Generate a call to an external intrinsic function. FIXME: So far,
4377 this only works for functions which are called with well-defined
4378 types; CSHIFT and friends will come later. */
4380 static void
4381 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4383 gfc_symbol *sym;
4384 vec<tree, va_gc> *append_args;
4385 bool specific_symbol;
4387 gcc_assert (!se->ss || se->ss->info->expr == expr);
4389 if (se->ss)
4390 gcc_assert (expr->rank > 0);
4391 else
4392 gcc_assert (expr->rank == 0);
4394 switch (expr->value.function.isym->id)
4396 case GFC_ISYM_ANY:
4397 case GFC_ISYM_ALL:
4398 case GFC_ISYM_FINDLOC:
4399 case GFC_ISYM_MAXLOC:
4400 case GFC_ISYM_MINLOC:
4401 case GFC_ISYM_MAXVAL:
4402 case GFC_ISYM_MINVAL:
4403 case GFC_ISYM_NORM2:
4404 case GFC_ISYM_PRODUCT:
4405 case GFC_ISYM_SUM:
4406 specific_symbol = true;
4407 break;
4408 default:
4409 specific_symbol = false;
4412 if (specific_symbol)
4414 /* Need to copy here because specific_intrinsic_symbol modifies
4415 expr to omit the absent optional arguments. */
4416 expr = gfc_copy_expr (expr);
4417 sym = specific_intrinsic_symbol (expr);
4419 else
4420 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4422 /* Calls to libgfortran_matmul need to be appended special arguments,
4423 to be able to call the BLAS ?gemm functions if required and possible. */
4424 append_args = NULL;
4425 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4426 && !expr->external_blas
4427 && sym->ts.type != BT_LOGICAL)
4429 tree cint = gfc_get_int_type (gfc_c_int_kind);
4431 if (flag_external_blas
4432 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4433 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4435 tree gemm_fndecl;
4437 if (sym->ts.type == BT_REAL)
4439 if (sym->ts.kind == 4)
4440 gemm_fndecl = gfor_fndecl_sgemm;
4441 else
4442 gemm_fndecl = gfor_fndecl_dgemm;
4444 else
4446 if (sym->ts.kind == 4)
4447 gemm_fndecl = gfor_fndecl_cgemm;
4448 else
4449 gemm_fndecl = gfor_fndecl_zgemm;
4452 vec_alloc (append_args, 3);
4453 append_args->quick_push (build_int_cst (cint, 1));
4454 append_args->quick_push (build_int_cst (cint,
4455 flag_blas_matmul_limit));
4456 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4457 gemm_fndecl));
4459 else
4461 vec_alloc (append_args, 3);
4462 append_args->quick_push (build_int_cst (cint, 0));
4463 append_args->quick_push (build_int_cst (cint, 0));
4464 append_args->quick_push (null_pointer_node);
4468 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4469 append_args);
4471 if (specific_symbol)
4472 gfc_free_expr (expr);
4473 else
4474 gfc_free_symbol (sym);
4477 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4478 Implemented as
4479 any(a)
4481 forall (i=...)
4482 if (a[i] != 0)
4483 return 1
4484 end forall
4485 return 0
4487 all(a)
4489 forall (i=...)
4490 if (a[i] == 0)
4491 return 0
4492 end forall
4493 return 1
4496 static void
4497 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4499 tree resvar;
4500 stmtblock_t block;
4501 stmtblock_t body;
4502 tree type;
4503 tree tmp;
4504 tree found;
4505 gfc_loopinfo loop;
4506 gfc_actual_arglist *actual;
4507 gfc_ss *arrayss;
4508 gfc_se arrayse;
4509 tree exit_label;
4511 if (se->ss)
4513 gfc_conv_intrinsic_funcall (se, expr);
4514 return;
4517 actual = expr->value.function.actual;
4518 type = gfc_typenode_for_spec (&expr->ts);
4519 /* Initialize the result. */
4520 resvar = gfc_create_var (type, "test");
4521 if (op == EQ_EXPR)
4522 tmp = convert (type, boolean_true_node);
4523 else
4524 tmp = convert (type, boolean_false_node);
4525 gfc_add_modify (&se->pre, resvar, tmp);
4527 /* Walk the arguments. */
4528 arrayss = gfc_walk_expr (actual->expr);
4529 gcc_assert (arrayss != gfc_ss_terminator);
4531 /* Initialize the scalarizer. */
4532 gfc_init_loopinfo (&loop);
4533 exit_label = gfc_build_label_decl (NULL_TREE);
4534 TREE_USED (exit_label) = 1;
4535 gfc_add_ss_to_loop (&loop, arrayss);
4537 /* Initialize the loop. */
4538 gfc_conv_ss_startstride (&loop);
4539 gfc_conv_loop_setup (&loop, &expr->where);
4541 gfc_mark_ss_chain_used (arrayss, 1);
4542 /* Generate the loop body. */
4543 gfc_start_scalarized_body (&loop, &body);
4545 /* If the condition matches then set the return value. */
4546 gfc_start_block (&block);
4547 if (op == EQ_EXPR)
4548 tmp = convert (type, boolean_false_node);
4549 else
4550 tmp = convert (type, boolean_true_node);
4551 gfc_add_modify (&block, resvar, tmp);
4553 /* And break out of the loop. */
4554 tmp = build1_v (GOTO_EXPR, exit_label);
4555 gfc_add_expr_to_block (&block, tmp);
4557 found = gfc_finish_block (&block);
4559 /* Check this element. */
4560 gfc_init_se (&arrayse, NULL);
4561 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4562 arrayse.ss = arrayss;
4563 gfc_conv_expr_val (&arrayse, actual->expr);
4565 gfc_add_block_to_block (&body, &arrayse.pre);
4566 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4567 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4568 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4569 gfc_add_expr_to_block (&body, tmp);
4570 gfc_add_block_to_block (&body, &arrayse.post);
4572 gfc_trans_scalarizing_loops (&loop, &body);
4574 /* Add the exit label. */
4575 tmp = build1_v (LABEL_EXPR, exit_label);
4576 gfc_add_expr_to_block (&loop.pre, tmp);
4578 gfc_add_block_to_block (&se->pre, &loop.pre);
4579 gfc_add_block_to_block (&se->pre, &loop.post);
4580 gfc_cleanup_loop (&loop);
4582 se->expr = resvar;
4586 /* Generate the constant 180 / pi, which is used in the conversion
4587 of acosd(), asind(), atand(), atan2d(). */
4589 static tree
4590 rad2deg (int kind)
4592 tree retval;
4593 mpfr_t pi, t0;
4595 gfc_set_model_kind (kind);
4596 mpfr_init (pi);
4597 mpfr_init (t0);
4598 mpfr_set_si (t0, 180, GFC_RND_MODE);
4599 mpfr_const_pi (pi, GFC_RND_MODE);
4600 mpfr_div (t0, t0, pi, GFC_RND_MODE);
4601 retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
4602 mpfr_clear (t0);
4603 mpfr_clear (pi);
4604 return retval;
4608 static gfc_intrinsic_map_t *
4609 gfc_lookup_intrinsic (gfc_isym_id id)
4611 gfc_intrinsic_map_t *m = gfc_intrinsic_map;
4612 for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4613 if (id == m->id)
4614 break;
4615 gcc_assert (id == m->id);
4616 return m;
4620 /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4621 ASIND(x) is translated into ASIN(x) * 180 / pi.
4622 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4624 static void
4625 gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
4627 tree arg;
4628 tree atrigd;
4629 tree type;
4630 gfc_intrinsic_map_t *m;
4632 type = gfc_typenode_for_spec (&expr->ts);
4634 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4636 switch (id)
4638 case GFC_ISYM_ACOSD:
4639 m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
4640 break;
4641 case GFC_ISYM_ASIND:
4642 m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
4643 break;
4644 case GFC_ISYM_ATAND:
4645 m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
4646 break;
4647 default:
4648 gcc_unreachable ();
4650 atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
4651 atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
4653 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
4654 fold_convert (type, rad2deg (expr->ts.kind)));
4658 /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4659 COS(X) / SIN(X) for COMPLEX argument. */
4661 static void
4662 gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
4664 gfc_intrinsic_map_t *m;
4665 tree arg;
4666 tree type;
4668 type = gfc_typenode_for_spec (&expr->ts);
4669 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4671 if (expr->ts.type == BT_REAL)
4673 tree tan;
4674 tree tmp;
4675 mpfr_t pio2;
4677 /* Create pi/2. */
4678 gfc_set_model_kind (expr->ts.kind);
4679 mpfr_init (pio2);
4680 mpfr_const_pi (pio2, GFC_RND_MODE);
4681 mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODE);
4682 tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
4683 mpfr_clear (pio2);
4685 /* Find tan builtin function. */
4686 m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
4687 tan = gfc_get_intrinsic_lib_fndecl (m, expr);
4688 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
4689 tan = build_call_expr_loc (input_location, tan, 1, tmp);
4690 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
4692 else
4694 tree sin;
4695 tree cos;
4697 /* Find cos builtin function. */
4698 m = gfc_lookup_intrinsic (GFC_ISYM_COS);
4699 cos = gfc_get_intrinsic_lib_fndecl (m, expr);
4700 cos = build_call_expr_loc (input_location, cos, 1, arg);
4702 /* Find sin builtin function. */
4703 m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
4704 sin = gfc_get_intrinsic_lib_fndecl (m, expr);
4705 sin = build_call_expr_loc (input_location, sin, 1, arg);
4707 /* Divide cos by sin. */
4708 se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
4713 /* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4715 static void
4716 gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
4718 tree arg;
4719 tree type;
4720 tree ninety_tree;
4721 mpfr_t ninety;
4723 type = gfc_typenode_for_spec (&expr->ts);
4724 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4726 gfc_set_model_kind (expr->ts.kind);
4728 /* Build the tree for x + 90. */
4729 mpfr_init_set_ui (ninety, 90, GFC_RND_MODE);
4730 ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
4731 arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
4732 mpfr_clear (ninety);
4734 /* Find tand. */
4735 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
4736 tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
4737 tand = build_call_expr_loc (input_location, tand, 1, arg);
4739 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
4743 /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4745 static void
4746 gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
4748 tree args[2];
4749 tree atan2d;
4750 tree type;
4752 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4753 type = TREE_TYPE (args[0]);
4755 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
4756 atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
4757 atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
4759 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
4760 rad2deg (expr->ts.kind));
4764 /* COUNT(A) = Number of true elements in A. */
4765 static void
4766 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4768 tree resvar;
4769 tree type;
4770 stmtblock_t body;
4771 tree tmp;
4772 gfc_loopinfo loop;
4773 gfc_actual_arglist *actual;
4774 gfc_ss *arrayss;
4775 gfc_se arrayse;
4777 if (se->ss)
4779 gfc_conv_intrinsic_funcall (se, expr);
4780 return;
4783 actual = expr->value.function.actual;
4785 type = gfc_typenode_for_spec (&expr->ts);
4786 /* Initialize the result. */
4787 resvar = gfc_create_var (type, "count");
4788 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4790 /* Walk the arguments. */
4791 arrayss = gfc_walk_expr (actual->expr);
4792 gcc_assert (arrayss != gfc_ss_terminator);
4794 /* Initialize the scalarizer. */
4795 gfc_init_loopinfo (&loop);
4796 gfc_add_ss_to_loop (&loop, arrayss);
4798 /* Initialize the loop. */
4799 gfc_conv_ss_startstride (&loop);
4800 gfc_conv_loop_setup (&loop, &expr->where);
4802 gfc_mark_ss_chain_used (arrayss, 1);
4803 /* Generate the loop body. */
4804 gfc_start_scalarized_body (&loop, &body);
4806 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4807 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4808 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4810 gfc_init_se (&arrayse, NULL);
4811 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4812 arrayse.ss = arrayss;
4813 gfc_conv_expr_val (&arrayse, actual->expr);
4814 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4815 build_empty_stmt (input_location));
4817 gfc_add_block_to_block (&body, &arrayse.pre);
4818 gfc_add_expr_to_block (&body, tmp);
4819 gfc_add_block_to_block (&body, &arrayse.post);
4821 gfc_trans_scalarizing_loops (&loop, &body);
4823 gfc_add_block_to_block (&se->pre, &loop.pre);
4824 gfc_add_block_to_block (&se->pre, &loop.post);
4825 gfc_cleanup_loop (&loop);
4827 se->expr = resvar;
4831 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4832 struct and return the corresponding loopinfo. */
4834 static gfc_loopinfo *
4835 enter_nested_loop (gfc_se *se)
4837 se->ss = se->ss->nested_ss;
4838 gcc_assert (se->ss == se->ss->loop->ss);
4840 return se->ss->loop;
4843 /* Build the condition for a mask, which may be optional. */
4845 static tree
4846 conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
4847 bool optional_mask)
4849 tree present;
4850 tree type;
4852 if (optional_mask)
4854 type = TREE_TYPE (maskse->expr);
4855 present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
4856 present = convert (type, present);
4857 present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
4858 present);
4859 return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
4860 type, present, maskse->expr);
4862 else
4863 return maskse->expr;
4866 /* Inline implementation of the sum and product intrinsics. */
4867 static void
4868 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4869 bool norm2)
4871 tree resvar;
4872 tree scale = NULL_TREE;
4873 tree type;
4874 stmtblock_t body;
4875 stmtblock_t block;
4876 tree tmp;
4877 gfc_loopinfo loop, *ploop;
4878 gfc_actual_arglist *arg_array, *arg_mask;
4879 gfc_ss *arrayss = NULL;
4880 gfc_ss *maskss = NULL;
4881 gfc_se arrayse;
4882 gfc_se maskse;
4883 gfc_se *parent_se;
4884 gfc_expr *arrayexpr;
4885 gfc_expr *maskexpr;
4886 bool optional_mask;
4888 if (expr->rank > 0)
4890 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4891 parent_se = se;
4893 else
4894 parent_se = NULL;
4896 type = gfc_typenode_for_spec (&expr->ts);
4897 /* Initialize the result. */
4898 resvar = gfc_create_var (type, "val");
4899 if (norm2)
4901 /* result = 0.0;
4902 scale = 1.0. */
4903 scale = gfc_create_var (type, "scale");
4904 gfc_add_modify (&se->pre, scale,
4905 gfc_build_const (type, integer_one_node));
4906 tmp = gfc_build_const (type, integer_zero_node);
4908 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4909 tmp = gfc_build_const (type, integer_zero_node);
4910 else if (op == NE_EXPR)
4911 /* PARITY. */
4912 tmp = convert (type, boolean_false_node);
4913 else if (op == BIT_AND_EXPR)
4914 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4915 type, integer_one_node));
4916 else
4917 tmp = gfc_build_const (type, integer_one_node);
4919 gfc_add_modify (&se->pre, resvar, tmp);
4921 arg_array = expr->value.function.actual;
4923 arrayexpr = arg_array->expr;
4925 if (op == NE_EXPR || norm2)
4927 /* PARITY and NORM2. */
4928 maskexpr = NULL;
4929 optional_mask = false;
4931 else
4933 arg_mask = arg_array->next->next;
4934 gcc_assert (arg_mask != NULL);
4935 maskexpr = arg_mask->expr;
4936 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
4937 && maskexpr->symtree->n.sym->attr.dummy
4938 && maskexpr->symtree->n.sym->attr.optional;
4941 if (expr->rank == 0)
4943 /* Walk the arguments. */
4944 arrayss = gfc_walk_expr (arrayexpr);
4945 gcc_assert (arrayss != gfc_ss_terminator);
4947 if (maskexpr && maskexpr->rank > 0)
4949 maskss = gfc_walk_expr (maskexpr);
4950 gcc_assert (maskss != gfc_ss_terminator);
4952 else
4953 maskss = NULL;
4955 /* Initialize the scalarizer. */
4956 gfc_init_loopinfo (&loop);
4958 /* We add the mask first because the number of iterations is
4959 taken from the last ss, and this breaks if an absent
4960 optional argument is used for mask. */
4962 if (maskexpr && maskexpr->rank > 0)
4963 gfc_add_ss_to_loop (&loop, maskss);
4964 gfc_add_ss_to_loop (&loop, arrayss);
4966 /* Initialize the loop. */
4967 gfc_conv_ss_startstride (&loop);
4968 gfc_conv_loop_setup (&loop, &expr->where);
4970 if (maskexpr && maskexpr->rank > 0)
4971 gfc_mark_ss_chain_used (maskss, 1);
4972 gfc_mark_ss_chain_used (arrayss, 1);
4974 ploop = &loop;
4976 else
4977 /* All the work has been done in the parent loops. */
4978 ploop = enter_nested_loop (se);
4980 gcc_assert (ploop);
4982 /* Generate the loop body. */
4983 gfc_start_scalarized_body (ploop, &body);
4985 /* If we have a mask, only add this element if the mask is set. */
4986 if (maskexpr && maskexpr->rank > 0)
4988 gfc_init_se (&maskse, parent_se);
4989 gfc_copy_loopinfo_to_se (&maskse, ploop);
4990 if (expr->rank == 0)
4991 maskse.ss = maskss;
4992 gfc_conv_expr_val (&maskse, maskexpr);
4993 gfc_add_block_to_block (&body, &maskse.pre);
4995 gfc_start_block (&block);
4997 else
4998 gfc_init_block (&block);
5000 /* Do the actual summation/product. */
5001 gfc_init_se (&arrayse, parent_se);
5002 gfc_copy_loopinfo_to_se (&arrayse, ploop);
5003 if (expr->rank == 0)
5004 arrayse.ss = arrayss;
5005 gfc_conv_expr_val (&arrayse, arrayexpr);
5006 gfc_add_block_to_block (&block, &arrayse.pre);
5008 if (norm2)
5010 /* if (x (i) != 0.0)
5012 absX = abs(x(i))
5013 if (absX > scale)
5015 val = scale/absX;
5016 result = 1.0 + result * val * val;
5017 scale = absX;
5019 else
5021 val = absX/scale;
5022 result += val * val;
5024 } */
5025 tree res1, res2, cond, absX, val;
5026 stmtblock_t ifblock1, ifblock2, ifblock3;
5028 gfc_init_block (&ifblock1);
5030 absX = gfc_create_var (type, "absX");
5031 gfc_add_modify (&ifblock1, absX,
5032 fold_build1_loc (input_location, ABS_EXPR, type,
5033 arrayse.expr));
5034 val = gfc_create_var (type, "val");
5035 gfc_add_expr_to_block (&ifblock1, val);
5037 gfc_init_block (&ifblock2);
5038 gfc_add_modify (&ifblock2, val,
5039 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
5040 absX));
5041 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5042 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
5043 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
5044 gfc_build_const (type, integer_one_node));
5045 gfc_add_modify (&ifblock2, resvar, res1);
5046 gfc_add_modify (&ifblock2, scale, absX);
5047 res1 = gfc_finish_block (&ifblock2);
5049 gfc_init_block (&ifblock3);
5050 gfc_add_modify (&ifblock3, val,
5051 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
5052 scale));
5053 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5054 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
5055 gfc_add_modify (&ifblock3, resvar, res2);
5056 res2 = gfc_finish_block (&ifblock3);
5058 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
5059 absX, scale);
5060 tmp = build3_v (COND_EXPR, cond, res1, res2);
5061 gfc_add_expr_to_block (&ifblock1, tmp);
5062 tmp = gfc_finish_block (&ifblock1);
5064 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5065 arrayse.expr,
5066 gfc_build_const (type, integer_zero_node));
5068 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5069 gfc_add_expr_to_block (&block, tmp);
5071 else
5073 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
5074 gfc_add_modify (&block, resvar, tmp);
5077 gfc_add_block_to_block (&block, &arrayse.post);
5079 if (maskexpr && maskexpr->rank > 0)
5081 /* We enclose the above in if (mask) {...} . If the mask is an
5082 optional argument, generate
5083 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5084 tree ifmask;
5085 tmp = gfc_finish_block (&block);
5086 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5087 tmp = build3_v (COND_EXPR, ifmask, tmp,
5088 build_empty_stmt (input_location));
5090 else
5091 tmp = gfc_finish_block (&block);
5092 gfc_add_expr_to_block (&body, tmp);
5094 gfc_trans_scalarizing_loops (ploop, &body);
5096 /* For a scalar mask, enclose the loop in an if statement. */
5097 if (maskexpr && maskexpr->rank == 0)
5099 gfc_init_block (&block);
5100 gfc_add_block_to_block (&block, &ploop->pre);
5101 gfc_add_block_to_block (&block, &ploop->post);
5102 tmp = gfc_finish_block (&block);
5104 if (expr->rank > 0)
5106 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
5107 build_empty_stmt (input_location));
5108 gfc_advance_se_ss_chain (se);
5110 else
5112 tree ifmask;
5114 gcc_assert (expr->rank == 0);
5115 gfc_init_se (&maskse, NULL);
5116 gfc_conv_expr_val (&maskse, maskexpr);
5117 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5118 tmp = build3_v (COND_EXPR, ifmask, tmp,
5119 build_empty_stmt (input_location));
5122 gfc_add_expr_to_block (&block, tmp);
5123 gfc_add_block_to_block (&se->pre, &block);
5124 gcc_assert (se->post.head == NULL);
5126 else
5128 gfc_add_block_to_block (&se->pre, &ploop->pre);
5129 gfc_add_block_to_block (&se->pre, &ploop->post);
5132 if (expr->rank == 0)
5133 gfc_cleanup_loop (ploop);
5135 if (norm2)
5137 /* result = scale * sqrt(result). */
5138 tree sqrt;
5139 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
5140 resvar = build_call_expr_loc (input_location,
5141 sqrt, 1, resvar);
5142 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
5145 se->expr = resvar;
5149 /* Inline implementation of the dot_product intrinsic. This function
5150 is based on gfc_conv_intrinsic_arith (the previous function). */
5151 static void
5152 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
5154 tree resvar;
5155 tree type;
5156 stmtblock_t body;
5157 stmtblock_t block;
5158 tree tmp;
5159 gfc_loopinfo loop;
5160 gfc_actual_arglist *actual;
5161 gfc_ss *arrayss1, *arrayss2;
5162 gfc_se arrayse1, arrayse2;
5163 gfc_expr *arrayexpr1, *arrayexpr2;
5165 type = gfc_typenode_for_spec (&expr->ts);
5167 /* Initialize the result. */
5168 resvar = gfc_create_var (type, "val");
5169 if (expr->ts.type == BT_LOGICAL)
5170 tmp = build_int_cst (type, 0);
5171 else
5172 tmp = gfc_build_const (type, integer_zero_node);
5174 gfc_add_modify (&se->pre, resvar, tmp);
5176 /* Walk argument #1. */
5177 actual = expr->value.function.actual;
5178 arrayexpr1 = actual->expr;
5179 arrayss1 = gfc_walk_expr (arrayexpr1);
5180 gcc_assert (arrayss1 != gfc_ss_terminator);
5182 /* Walk argument #2. */
5183 actual = actual->next;
5184 arrayexpr2 = actual->expr;
5185 arrayss2 = gfc_walk_expr (arrayexpr2);
5186 gcc_assert (arrayss2 != gfc_ss_terminator);
5188 /* Initialize the scalarizer. */
5189 gfc_init_loopinfo (&loop);
5190 gfc_add_ss_to_loop (&loop, arrayss1);
5191 gfc_add_ss_to_loop (&loop, arrayss2);
5193 /* Initialize the loop. */
5194 gfc_conv_ss_startstride (&loop);
5195 gfc_conv_loop_setup (&loop, &expr->where);
5197 gfc_mark_ss_chain_used (arrayss1, 1);
5198 gfc_mark_ss_chain_used (arrayss2, 1);
5200 /* Generate the loop body. */
5201 gfc_start_scalarized_body (&loop, &body);
5202 gfc_init_block (&block);
5204 /* Make the tree expression for [conjg(]array1[)]. */
5205 gfc_init_se (&arrayse1, NULL);
5206 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
5207 arrayse1.ss = arrayss1;
5208 gfc_conv_expr_val (&arrayse1, arrayexpr1);
5209 if (expr->ts.type == BT_COMPLEX)
5210 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
5211 arrayse1.expr);
5212 gfc_add_block_to_block (&block, &arrayse1.pre);
5214 /* Make the tree expression for array2. */
5215 gfc_init_se (&arrayse2, NULL);
5216 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
5217 arrayse2.ss = arrayss2;
5218 gfc_conv_expr_val (&arrayse2, arrayexpr2);
5219 gfc_add_block_to_block (&block, &arrayse2.pre);
5221 /* Do the actual product and sum. */
5222 if (expr->ts.type == BT_LOGICAL)
5224 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
5225 arrayse1.expr, arrayse2.expr);
5226 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
5228 else
5230 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
5231 arrayse2.expr);
5232 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
5234 gfc_add_modify (&block, resvar, tmp);
5236 /* Finish up the loop block and the loop. */
5237 tmp = gfc_finish_block (&block);
5238 gfc_add_expr_to_block (&body, tmp);
5240 gfc_trans_scalarizing_loops (&loop, &body);
5241 gfc_add_block_to_block (&se->pre, &loop.pre);
5242 gfc_add_block_to_block (&se->pre, &loop.post);
5243 gfc_cleanup_loop (&loop);
5245 se->expr = resvar;
5249 /* Tells whether the expression E is a reference to an optional variable whose
5250 presence is not known at compile time. Those are variable references without
5251 subreference; if there is a subreference, we can assume the variable is
5252 present. We have to special case full arrays, which we represent with a fake
5253 "full" reference, and class descriptors for which a reference to data is not
5254 really a subreference. */
5256 bool
5257 maybe_absent_optional_variable (gfc_expr *e)
5259 if (!(e && e->expr_type == EXPR_VARIABLE))
5260 return false;
5262 gfc_symbol *sym = e->symtree->n.sym;
5263 if (!sym->attr.optional)
5264 return false;
5266 gfc_ref *ref = e->ref;
5267 if (ref == nullptr)
5268 return true;
5270 if (ref->type == REF_ARRAY
5271 && ref->u.ar.type == AR_FULL
5272 && ref->next == nullptr)
5273 return true;
5275 if (!(sym->ts.type == BT_CLASS
5276 && ref->type == REF_COMPONENT
5277 && ref->u.c.component == CLASS_DATA (sym)))
5278 return false;
5280 gfc_ref *next_ref = ref->next;
5281 if (next_ref == nullptr)
5282 return true;
5284 if (next_ref->type == REF_ARRAY
5285 && next_ref->u.ar.type == AR_FULL
5286 && next_ref->next == nullptr)
5287 return true;
5289 return false;
5293 /* Remove unneeded kind= argument from actual argument list when the
5294 result conversion is dealt with in a different place. */
5296 static void
5297 strip_kind_from_actual (gfc_actual_arglist * actual)
5299 for (gfc_actual_arglist *a = actual; a; a = a->next)
5301 if (a && a->name && strcmp (a->name, "kind") == 0)
5303 gfc_free_expr (a->expr);
5304 a->expr = NULL;
5309 /* Emit code for minloc or maxloc intrinsic. There are many different cases
5310 we need to handle. For performance reasons we sometimes create two
5311 loops instead of one, where the second one is much simpler.
5312 Examples for minloc intrinsic:
5313 A: Result is scalar.
5314 1) Array mask is used and NaNs need to be supported:
5315 limit = Infinity;
5316 pos = 0;
5317 S = from;
5318 while (S <= to) {
5319 if (mask[S]) {
5320 if (pos == 0) pos = S + (1 - from);
5321 if (a[S] <= limit) {
5322 limit = a[S];
5323 pos = S + (1 - from);
5324 goto lab1;
5327 S++;
5329 goto lab2;
5330 lab1:;
5331 while (S <= to) {
5332 if (mask[S])
5333 if (a[S] < limit) {
5334 limit = a[S];
5335 pos = S + (1 - from);
5337 S++;
5339 lab2:;
5340 2) NaNs need to be supported, but it is known at compile time or cheaply
5341 at runtime whether array is nonempty or not:
5342 limit = Infinity;
5343 pos = 0;
5344 S = from;
5345 while (S <= to) {
5346 if (a[S] <= limit) {
5347 limit = a[S];
5348 pos = S + (1 - from);
5349 goto lab1;
5351 S++;
5353 if (from <= to) pos = 1;
5354 goto lab2;
5355 lab1:;
5356 while (S <= to) {
5357 if (a[S] < limit) {
5358 limit = a[S];
5359 pos = S + (1 - from);
5361 S++;
5363 lab2:;
5364 3) NaNs aren't supported, array mask is used:
5365 limit = infinities_supported ? Infinity : huge (limit);
5366 pos = 0;
5367 S = from;
5368 while (S <= to) {
5369 if (mask[S]) {
5370 limit = a[S];
5371 pos = S + (1 - from);
5372 goto lab1;
5374 S++;
5376 goto lab2;
5377 lab1:;
5378 while (S <= to) {
5379 if (mask[S])
5380 if (a[S] < limit) {
5381 limit = a[S];
5382 pos = S + (1 - from);
5384 S++;
5386 lab2:;
5387 4) Same without array mask:
5388 limit = infinities_supported ? Infinity : huge (limit);
5389 pos = (from <= to) ? 1 : 0;
5390 S = from;
5391 while (S <= to) {
5392 if (a[S] < limit) {
5393 limit = a[S];
5394 pos = S + (1 - from);
5396 S++;
5398 B: Array result, non-CHARACTER type, DIM absent
5399 Generate similar code as in the scalar case, using a collection of
5400 variables (one per dimension) instead of a single variable as result.
5401 Picking only cases 1) and 4) with ARRAY of rank 2, the generated code
5402 becomes:
5403 1) Array mask is used and NaNs need to be supported:
5404 limit = Infinity;
5405 pos0 = 0;
5406 pos1 = 0;
5407 S1 = from1;
5408 second_loop_entry = false;
5409 while (S1 <= to1) {
5410 S0 = from0;
5411 while (s0 <= to0 {
5412 if (mask[S1][S0]) {
5413 if (pos0 == 0) {
5414 pos0 = S0 + (1 - from0);
5415 pos1 = S1 + (1 - from1);
5417 if (a[S1][S0] <= limit) {
5418 limit = a[S1][S0];
5419 pos0 = S0 + (1 - from0);
5420 pos1 = S1 + (1 - from1);
5421 second_loop_entry = true;
5422 goto lab1;
5425 S0++;
5427 S1++;
5429 goto lab2;
5430 lab1:;
5431 S1 = second_loop_entry ? S1 : from1;
5432 while (S1 <= to1) {
5433 S0 = second_loop_entry ? S0 : from0;
5434 while (S0 <= to0) {
5435 if (mask[S1][S0])
5436 if (a[S1][S0] < limit) {
5437 limit = a[S1][S0];
5438 pos0 = S + (1 - from0);
5439 pos1 = S + (1 - from1);
5441 second_loop_entry = false;
5442 S0++;
5444 S1++;
5446 lab2:;
5447 result = { pos0, pos1 };
5449 4) NANs aren't supported, no array mask.
5450 limit = infinities_supported ? Infinity : huge (limit);
5451 pos0 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5452 pos1 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5453 S1 = from1;
5454 while (S1 <= to1) {
5455 S0 = from0;
5456 while (S0 <= to0) {
5457 if (a[S1][S0] < limit) {
5458 limit = a[S1][S0];
5459 pos0 = S + (1 - from0);
5460 pos1 = S + (1 - from1);
5462 S0++;
5464 S1++;
5466 result = { pos0, pos1 };
5467 C: Otherwise, a call is generated.
5468 For 2) and 4), if mask is scalar, this all goes into a conditional,
5469 setting pos = 0; in the else branch.
5471 Since we now also support the BACK argument, instead of using
5472 if (a[S] < limit), we now use
5474 if (back)
5475 cond = a[S] <= limit;
5476 else
5477 cond = a[S] < limit;
5478 if (cond) {
5479 ....
5481 The optimizer is smart enough to move the condition out of the loop.
5482 They are now marked as unlikely too for further speedup. */
5484 static void
5485 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
5487 stmtblock_t body;
5488 stmtblock_t block;
5489 stmtblock_t ifblock;
5490 stmtblock_t elseblock;
5491 tree limit;
5492 tree type;
5493 tree tmp;
5494 tree cond;
5495 tree elsetmp;
5496 tree ifbody;
5497 tree offset[GFC_MAX_DIMENSIONS];
5498 tree nonempty;
5499 tree lab1, lab2;
5500 tree b_if, b_else;
5501 tree back;
5502 gfc_loopinfo loop, *ploop;
5503 gfc_actual_arglist *actual, *array_arg, *dim_arg, *mask_arg, *kind_arg;
5504 gfc_actual_arglist *back_arg;
5505 gfc_ss *arrayss = nullptr;
5506 gfc_ss *maskss = nullptr;
5507 gfc_ss *orig_ss = nullptr;
5508 gfc_se arrayse;
5509 gfc_se maskse;
5510 gfc_se nested_se;
5511 gfc_se *base_se;
5512 gfc_expr *arrayexpr;
5513 gfc_expr *maskexpr;
5514 gfc_expr *backexpr;
5515 gfc_se backse;
5516 tree pos[GFC_MAX_DIMENSIONS];
5517 tree idx[GFC_MAX_DIMENSIONS];
5518 tree result_var = NULL_TREE;
5519 int n;
5520 bool optional_mask;
5522 actual = expr->value.function.actual;
5523 array_arg = actual;
5524 dim_arg = array_arg->next;
5525 mask_arg = dim_arg->next;
5526 kind_arg = mask_arg->next;
5527 back_arg = kind_arg->next;
5529 bool dim_present = dim_arg->expr != nullptr;
5530 bool nested_loop = dim_present && expr->rank > 0;
5532 /* The last argument, BACK, is passed by value. Ensure that
5533 by setting its name to %VAL. */
5534 for (gfc_actual_arglist *a = actual; a; a = a->next)
5536 if (a->next == NULL)
5537 a->name = "%VAL";
5540 if (se->ss)
5542 if (se->ss->info->useflags)
5544 if (!dim_present || !gfc_inline_intrinsic_function_p (expr))
5546 /* The code generating and initializing the result array has been
5547 generated already before the scalarization loop, either with a
5548 library function call or with inline code; now we can just use
5549 the result. */
5550 gfc_conv_tmp_array_ref (se);
5551 return;
5554 else if (!gfc_inline_intrinsic_function_p (expr))
5556 gfc_conv_intrinsic_funcall (se, expr);
5557 return;
5561 arrayexpr = actual->expr;
5563 /* Special case for character maxloc. Remove unneeded actual
5564 arguments, then call a library function. */
5566 if (arrayexpr->ts.type == BT_CHARACTER)
5568 gcc_assert (expr->rank == 0);
5570 gfc_actual_arglist *a = actual;
5571 strip_kind_from_actual (a);
5572 while (a)
5574 if (a->name && strcmp (a->name, "dim") == 0)
5576 gfc_free_expr (a->expr);
5577 a->expr = NULL;
5579 a = a->next;
5581 gfc_conv_intrinsic_funcall (se, expr);
5582 return;
5585 type = gfc_typenode_for_spec (&expr->ts);
5587 if (expr->rank > 0 && !dim_present)
5589 gfc_array_spec as;
5590 memset (&as, 0, sizeof (as));
5592 as.rank = 1;
5593 as.lower[0] = gfc_get_int_expr (gfc_index_integer_kind,
5594 &arrayexpr->where,
5595 HOST_WIDE_INT_1);
5596 as.upper[0] = gfc_get_int_expr (gfc_index_integer_kind,
5597 &arrayexpr->where,
5598 arrayexpr->rank);
5600 tree array = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
5602 result_var = gfc_create_var (array, "loc_result");
5605 const int reduction_dimensions = dim_present ? 1 : arrayexpr->rank;
5607 /* Initialize the result. */
5608 for (int i = 0; i < reduction_dimensions; i++)
5610 pos[i] = gfc_create_var (gfc_array_index_type,
5611 gfc_get_string ("pos%d", i));
5612 offset[i] = gfc_create_var (gfc_array_index_type,
5613 gfc_get_string ("offset%d", i));
5614 idx[i] = gfc_create_var (gfc_array_index_type,
5615 gfc_get_string ("idx%d", i));
5618 maskexpr = mask_arg->expr;
5619 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5620 && maskexpr->symtree->n.sym->attr.dummy
5621 && maskexpr->symtree->n.sym->attr.optional;
5622 backexpr = back_arg->expr;
5624 gfc_init_se (&backse, nested_loop ? se : nullptr);
5625 if (backexpr == nullptr)
5626 back = logical_false_node;
5627 else if (maybe_absent_optional_variable (backexpr))
5629 /* This should have been checked already by
5630 maybe_absent_optional_variable. */
5631 gcc_checking_assert (backexpr->expr_type == EXPR_VARIABLE);
5633 gfc_conv_expr (&backse, backexpr);
5634 tree present = gfc_conv_expr_present (backexpr->symtree->n.sym, false);
5635 back = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5636 logical_type_node, present, backse.expr);
5638 else
5640 gfc_conv_expr (&backse, backexpr);
5641 back = backse.expr;
5643 gfc_add_block_to_block (&se->pre, &backse.pre);
5644 back = gfc_evaluate_now_loc (input_location, back, &se->pre);
5645 gfc_add_block_to_block (&se->pre, &backse.post);
5647 if (nested_loop)
5649 gfc_init_se (&nested_se, se);
5650 base_se = &nested_se;
5652 else
5654 /* Walk the arguments. */
5655 arrayss = gfc_walk_expr (arrayexpr);
5656 gcc_assert (arrayss != gfc_ss_terminator);
5658 if (maskexpr && maskexpr->rank != 0)
5660 maskss = gfc_walk_expr (maskexpr);
5661 gcc_assert (maskss != gfc_ss_terminator);
5664 base_se = nullptr;
5667 nonempty = nullptr;
5668 if (!(maskexpr && maskexpr->rank > 0))
5670 mpz_t asize;
5671 bool reduction_size_known;
5673 if (dim_present)
5675 int reduction_dim;
5676 if (dim_arg->expr->expr_type == EXPR_CONSTANT)
5677 reduction_dim = mpz_get_si (dim_arg->expr->value.integer) - 1;
5678 else if (arrayexpr->rank == 1)
5679 reduction_dim = 0;
5680 else
5681 gcc_unreachable ();
5682 reduction_size_known = gfc_array_dimen_size (arrayexpr, reduction_dim,
5683 &asize);
5685 else
5686 reduction_size_known = gfc_array_size (arrayexpr, &asize);
5688 if (reduction_size_known)
5690 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5691 mpz_clear (asize);
5692 nonempty = fold_build2_loc (input_location, GT_EXPR,
5693 logical_type_node, nonempty,
5694 gfc_index_zero_node);
5696 maskss = NULL;
5699 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
5700 switch (arrayexpr->ts.type)
5702 case BT_REAL:
5703 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
5704 break;
5706 case BT_INTEGER:
5707 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5708 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
5709 arrayexpr->ts.kind);
5710 break;
5712 case BT_UNSIGNED:
5713 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
5714 if (op == GT_EXPR)
5716 tmp = gfc_get_unsigned_type (arrayexpr->ts.kind);
5717 tmp = build_int_cst (tmp, 0);
5719 else
5721 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5722 tmp = gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds[n].huge,
5723 expr->ts.kind);
5725 break;
5727 default:
5728 gcc_unreachable ();
5731 /* We start with the most negative possible value for MAXLOC, and the most
5732 positive possible value for MINLOC. The most negative possible value is
5733 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5734 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
5735 with above. */
5736 if (op == GT_EXPR && expr->ts.type != BT_UNSIGNED)
5737 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5738 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
5739 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
5740 build_int_cst (TREE_TYPE (tmp), 1));
5742 gfc_add_modify (&se->pre, limit, tmp);
5744 /* If we are in a case where we generate two sets of loops, the second one
5745 should continue where the first stopped instead of restarting from the
5746 beginning. So nested loops in the second set should have a partial range
5747 on the first iteration, but they should start from the beginning and span
5748 their full range on the following iterations. So we use conditionals in
5749 the loops lower bounds, and use the following variable in those
5750 conditionals to decide whether to use the original loop bound or to use
5751 the index at which the loop from the first set stopped. */
5752 tree second_loop_entry = gfc_create_var (logical_type_node,
5753 "second_loop_entry");
5754 gfc_add_modify (&se->pre, second_loop_entry, logical_false_node);
5756 if (nested_loop)
5758 ploop = enter_nested_loop (&nested_se);
5759 orig_ss = nested_se.ss;
5760 ploop->temp_dim = 1;
5762 else
5764 /* Initialize the scalarizer. */
5765 gfc_init_loopinfo (&loop);
5767 /* We add the mask first because the number of iterations is taken
5768 from the last ss, and this breaks if an absent optional argument
5769 is used for mask. */
5771 if (maskss)
5772 gfc_add_ss_to_loop (&loop, maskss);
5774 gfc_add_ss_to_loop (&loop, arrayss);
5776 /* Initialize the loop. */
5777 gfc_conv_ss_startstride (&loop);
5779 /* The code generated can have more than one loop in sequence (see the
5780 comment at the function header). This doesn't work well with the
5781 scalarizer, which changes arrays' offset when the scalarization loops
5782 are generated (see gfc_trans_preloop_setup). Fortunately, we can use
5783 the scalarizer temporary code to handle multiple loops. Thus, we set
5784 temp_dim here, we call gfc_mark_ss_chain_used with flag=3 later, and
5785 we use gfc_trans_scalarized_loop_boundary even later to restore
5786 offset. */
5787 loop.temp_dim = loop.dimen;
5788 gfc_conv_loop_setup (&loop, &expr->where);
5790 ploop = &loop;
5793 gcc_assert (reduction_dimensions == ploop->dimen);
5795 if (nonempty == NULL && !(maskexpr && maskexpr->rank > 0))
5797 nonempty = logical_true_node;
5799 for (int i = 0; i < ploop->dimen; i++)
5801 if (!(ploop->from[i] && ploop->to[i]))
5803 nonempty = NULL;
5804 break;
5807 tree tmp = fold_build2_loc (input_location, LE_EXPR,
5808 logical_type_node, ploop->from[i],
5809 ploop->to[i]);
5811 nonempty = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5812 logical_type_node, nonempty, tmp);
5816 lab1 = NULL;
5817 lab2 = NULL;
5818 /* Initialize the position to zero, following Fortran 2003. We are free
5819 to do this because Fortran 95 allows the result of an entirely false
5820 mask to be processor dependent. If we know at compile time the array
5821 is non-empty and no MASK is used, we can initialize to 1 to simplify
5822 the inner loop. */
5823 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
5825 tree init = fold_build3_loc (input_location, COND_EXPR,
5826 gfc_array_index_type, nonempty,
5827 gfc_index_one_node,
5828 gfc_index_zero_node);
5829 for (int i = 0; i < ploop->dimen; i++)
5830 gfc_add_modify (&ploop->pre, pos[i], init);
5832 else
5834 for (int i = 0; i < ploop->dimen; i++)
5835 gfc_add_modify (&ploop->pre, pos[i], gfc_index_zero_node);
5836 lab1 = gfc_build_label_decl (NULL_TREE);
5837 TREE_USED (lab1) = 1;
5838 lab2 = gfc_build_label_decl (NULL_TREE);
5839 TREE_USED (lab2) = 1;
5842 /* An offset must be added to the loop
5843 counter to obtain the required position. */
5844 for (int i = 0; i < ploop->dimen; i++)
5846 gcc_assert (ploop->from[i]);
5848 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5849 gfc_index_one_node, ploop->from[i]);
5850 gfc_add_modify (&ploop->pre, offset[i], tmp);
5853 if (!nested_loop)
5855 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
5856 if (maskss)
5857 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
5860 /* Generate the loop body. */
5861 gfc_start_scalarized_body (ploop, &body);
5863 /* If we have a mask, only check this element if the mask is set. */
5864 if (maskexpr && maskexpr->rank > 0)
5866 gfc_init_se (&maskse, base_se);
5867 gfc_copy_loopinfo_to_se (&maskse, ploop);
5868 if (!nested_loop)
5869 maskse.ss = maskss;
5870 gfc_conv_expr_val (&maskse, maskexpr);
5871 gfc_add_block_to_block (&body, &maskse.pre);
5873 gfc_start_block (&block);
5875 else
5876 gfc_init_block (&block);
5878 /* Compare with the current limit. */
5879 gfc_init_se (&arrayse, base_se);
5880 gfc_copy_loopinfo_to_se (&arrayse, ploop);
5881 if (!nested_loop)
5882 arrayse.ss = arrayss;
5883 gfc_conv_expr_val (&arrayse, arrayexpr);
5884 gfc_add_block_to_block (&block, &arrayse.pre);
5886 /* We do the following if this is a more extreme value. */
5887 gfc_start_block (&ifblock);
5889 /* Assign the value to the limit... */
5890 gfc_add_modify (&ifblock, limit, arrayse.expr);
5892 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
5894 stmtblock_t ifblock2;
5895 tree ifbody2;
5897 gfc_start_block (&ifblock2);
5898 for (int i = 0; i < ploop->dimen; i++)
5900 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
5901 ploop->loopvar[i], offset[i]);
5902 gfc_add_modify (&ifblock2, pos[i], tmp);
5904 ifbody2 = gfc_finish_block (&ifblock2);
5906 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5907 pos[0], gfc_index_zero_node);
5908 tmp = build3_v (COND_EXPR, cond, ifbody2,
5909 build_empty_stmt (input_location));
5910 gfc_add_expr_to_block (&block, tmp);
5913 for (int i = 0; i < ploop->dimen; i++)
5915 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
5916 ploop->loopvar[i], offset[i]);
5917 gfc_add_modify (&ifblock, pos[i], tmp);
5918 gfc_add_modify (&ifblock, idx[i], ploop->loopvar[i]);
5921 gfc_add_modify (&ifblock, second_loop_entry, logical_true_node);
5923 if (lab1)
5924 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5926 ifbody = gfc_finish_block (&ifblock);
5928 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5930 if (lab1)
5931 cond = fold_build2_loc (input_location,
5932 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5933 logical_type_node, arrayse.expr, limit);
5934 else
5936 tree ifbody2, elsebody2;
5938 /* We switch to > or >= depending on the value of the BACK argument. */
5939 cond = gfc_create_var (logical_type_node, "cond");
5941 gfc_start_block (&ifblock);
5942 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5943 logical_type_node, arrayse.expr, limit);
5945 gfc_add_modify (&ifblock, cond, b_if);
5946 ifbody2 = gfc_finish_block (&ifblock);
5948 gfc_start_block (&elseblock);
5949 b_else = fold_build2_loc (input_location, op, logical_type_node,
5950 arrayse.expr, limit);
5952 gfc_add_modify (&elseblock, cond, b_else);
5953 elsebody2 = gfc_finish_block (&elseblock);
5955 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5956 back, ifbody2, elsebody2);
5958 gfc_add_expr_to_block (&block, tmp);
5961 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5962 ifbody = build3_v (COND_EXPR, cond, ifbody,
5963 build_empty_stmt (input_location));
5965 gfc_add_expr_to_block (&block, ifbody);
5967 if (maskexpr && maskexpr->rank > 0)
5969 /* We enclose the above in if (mask) {...}. If the mask is an
5970 optional argument, generate IF (.NOT. PRESENT(MASK)
5971 .OR. MASK(I)). */
5973 tree ifmask;
5974 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5975 tmp = gfc_finish_block (&block);
5976 tmp = build3_v (COND_EXPR, ifmask, tmp,
5977 build_empty_stmt (input_location));
5979 else
5980 tmp = gfc_finish_block (&block);
5981 gfc_add_expr_to_block (&body, tmp);
5983 if (lab1)
5985 for (int i = 0; i < ploop->dimen; i++)
5986 ploop->from[i] = fold_build3_loc (input_location, COND_EXPR,
5987 TREE_TYPE (ploop->from[i]),
5988 second_loop_entry, idx[i],
5989 ploop->from[i]);
5991 gfc_trans_scalarized_loop_boundary (ploop, &body);
5993 if (nested_loop)
5995 /* The first loop already advanced the parent se'ss chain, so clear
5996 the parent now to avoid doing it a second time, making the chain
5997 out of sync. */
5998 nested_se.parent = nullptr;
5999 nested_se.ss = orig_ss;
6002 stmtblock_t * const outer_block = &ploop->code[ploop->dimen - 1];
6004 if (HONOR_NANS (DECL_MODE (limit)))
6006 if (nonempty != NULL)
6008 stmtblock_t init_block;
6009 gfc_init_block (&init_block);
6011 for (int i = 0; i < ploop->dimen; i++)
6012 gfc_add_modify (&init_block, pos[i], gfc_index_one_node);
6014 tree ifbody = gfc_finish_block (&init_block);
6015 tmp = build3_v (COND_EXPR, nonempty, ifbody,
6016 build_empty_stmt (input_location));
6017 gfc_add_expr_to_block (outer_block, tmp);
6021 gfc_add_expr_to_block (outer_block, build1_v (GOTO_EXPR, lab2));
6022 gfc_add_expr_to_block (outer_block, build1_v (LABEL_EXPR, lab1));
6024 /* If we have a mask, only check this element if the mask is set. */
6025 if (maskexpr && maskexpr->rank > 0)
6027 gfc_init_se (&maskse, base_se);
6028 gfc_copy_loopinfo_to_se (&maskse, ploop);
6029 if (!nested_loop)
6030 maskse.ss = maskss;
6031 gfc_conv_expr_val (&maskse, maskexpr);
6032 gfc_add_block_to_block (&body, &maskse.pre);
6034 gfc_start_block (&block);
6036 else
6037 gfc_init_block (&block);
6039 /* Compare with the current limit. */
6040 gfc_init_se (&arrayse, base_se);
6041 gfc_copy_loopinfo_to_se (&arrayse, ploop);
6042 if (!nested_loop)
6043 arrayse.ss = arrayss;
6044 gfc_conv_expr_val (&arrayse, arrayexpr);
6045 gfc_add_block_to_block (&block, &arrayse.pre);
6047 /* We do the following if this is a more extreme value. */
6048 gfc_start_block (&ifblock);
6050 /* Assign the value to the limit... */
6051 gfc_add_modify (&ifblock, limit, arrayse.expr);
6053 for (int i = 0; i < ploop->dimen; i++)
6055 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
6056 ploop->loopvar[i], offset[i]);
6057 gfc_add_modify (&ifblock, pos[i], tmp);
6060 ifbody = gfc_finish_block (&ifblock);
6062 /* We switch to > or >= depending on the value of the BACK argument. */
6064 tree ifbody2, elsebody2;
6066 cond = gfc_create_var (logical_type_node, "cond");
6068 gfc_start_block (&ifblock);
6069 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
6070 logical_type_node, arrayse.expr, limit);
6072 gfc_add_modify (&ifblock, cond, b_if);
6073 ifbody2 = gfc_finish_block (&ifblock);
6075 gfc_start_block (&elseblock);
6076 b_else = fold_build2_loc (input_location, op, logical_type_node,
6077 arrayse.expr, limit);
6079 gfc_add_modify (&elseblock, cond, b_else);
6080 elsebody2 = gfc_finish_block (&elseblock);
6082 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
6083 back, ifbody2, elsebody2);
6086 gfc_add_expr_to_block (&block, tmp);
6087 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
6088 tmp = build3_v (COND_EXPR, cond, ifbody,
6089 build_empty_stmt (input_location));
6091 gfc_add_expr_to_block (&block, tmp);
6093 if (maskexpr && maskexpr->rank > 0)
6095 /* We enclose the above in if (mask) {...}. If the mask is
6096 an optional argument, generate IF (.NOT. PRESENT(MASK)
6097 .OR. MASK(I)).*/
6099 tree ifmask;
6100 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6101 tmp = gfc_finish_block (&block);
6102 tmp = build3_v (COND_EXPR, ifmask, tmp,
6103 build_empty_stmt (input_location));
6105 else
6106 tmp = gfc_finish_block (&block);
6108 gfc_add_expr_to_block (&body, tmp);
6109 gfc_add_modify (&body, second_loop_entry, logical_false_node);
6112 gfc_trans_scalarizing_loops (ploop, &body);
6114 if (lab2)
6115 gfc_add_expr_to_block (&ploop->pre, build1_v (LABEL_EXPR, lab2));
6117 /* For a scalar mask, enclose the loop in an if statement. */
6118 if (maskexpr && maskexpr->rank == 0)
6120 tree ifmask;
6122 gfc_init_se (&maskse, nested_loop ? se : nullptr);
6123 gfc_conv_expr_val (&maskse, maskexpr);
6124 gfc_add_block_to_block (&se->pre, &maskse.pre);
6125 gfc_init_block (&block);
6126 gfc_add_block_to_block (&block, &ploop->pre);
6127 gfc_add_block_to_block (&block, &ploop->post);
6128 tmp = gfc_finish_block (&block);
6130 /* For the else part of the scalar mask, just initialize
6131 the pos variable the same way as above. */
6133 gfc_init_block (&elseblock);
6134 for (int i = 0; i < ploop->dimen; i++)
6135 gfc_add_modify (&elseblock, pos[i], gfc_index_zero_node);
6136 elsetmp = gfc_finish_block (&elseblock);
6137 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6138 tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
6139 gfc_add_expr_to_block (&block, tmp);
6140 gfc_add_block_to_block (&se->pre, &block);
6142 else
6144 gfc_add_block_to_block (&se->pre, &ploop->pre);
6145 gfc_add_block_to_block (&se->pre, &ploop->post);
6148 if (!nested_loop)
6149 gfc_cleanup_loop (&loop);
6151 if (!dim_present)
6153 for (int i = 0; i < arrayexpr->rank; i++)
6155 tree res_idx = build_int_cst (gfc_array_index_type, i);
6156 tree res_arr_ref = gfc_build_array_ref (result_var, res_idx,
6157 NULL_TREE, true);
6159 tree value = convert (type, pos[i]);
6160 gfc_add_modify (&se->pre, res_arr_ref, value);
6163 se->expr = result_var;
6165 else
6166 se->expr = convert (type, pos[0]);
6169 /* Emit code for findloc. */
6171 static void
6172 gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
6174 gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
6175 *kind_arg, *back_arg;
6176 gfc_expr *value_expr;
6177 int ikind;
6178 tree resvar;
6179 stmtblock_t block;
6180 stmtblock_t body;
6181 stmtblock_t loopblock;
6182 tree type;
6183 tree tmp;
6184 tree found;
6185 tree forward_branch = NULL_TREE;
6186 tree back_branch;
6187 gfc_loopinfo loop;
6188 gfc_ss *arrayss;
6189 gfc_ss *maskss;
6190 gfc_se arrayse;
6191 gfc_se valuese;
6192 gfc_se maskse;
6193 gfc_se backse;
6194 tree exit_label;
6195 gfc_expr *maskexpr;
6196 tree offset;
6197 int i;
6198 bool optional_mask;
6200 array_arg = expr->value.function.actual;
6201 value_arg = array_arg->next;
6202 dim_arg = value_arg->next;
6203 mask_arg = dim_arg->next;
6204 kind_arg = mask_arg->next;
6205 back_arg = kind_arg->next;
6207 /* Remove kind and set ikind. */
6208 if (kind_arg->expr)
6210 ikind = mpz_get_si (kind_arg->expr->value.integer);
6211 gfc_free_expr (kind_arg->expr);
6212 kind_arg->expr = NULL;
6214 else
6215 ikind = gfc_default_integer_kind;
6217 value_expr = value_arg->expr;
6219 /* Unless it's a string, pass VALUE by value. */
6220 if (value_expr->ts.type != BT_CHARACTER)
6221 value_arg->name = "%VAL";
6223 /* Pass BACK argument by value. */
6224 back_arg->name = "%VAL";
6226 /* Call the library if we have a character function or if
6227 rank > 0. */
6228 if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
6230 se->ignore_optional = 1;
6231 if (expr->rank == 0)
6233 /* Remove dim argument. */
6234 gfc_free_expr (dim_arg->expr);
6235 dim_arg->expr = NULL;
6237 gfc_conv_intrinsic_funcall (se, expr);
6238 return;
6241 type = gfc_get_int_type (ikind);
6243 /* Initialize the result. */
6244 resvar = gfc_create_var (gfc_array_index_type, "pos");
6245 gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
6246 offset = gfc_create_var (gfc_array_index_type, "offset");
6248 maskexpr = mask_arg->expr;
6249 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6250 && maskexpr->symtree->n.sym->attr.dummy
6251 && maskexpr->symtree->n.sym->attr.optional;
6253 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
6255 for (i = 0 ; i < 2; i++)
6257 /* Walk the arguments. */
6258 arrayss = gfc_walk_expr (array_arg->expr);
6259 gcc_assert (arrayss != gfc_ss_terminator);
6261 if (maskexpr && maskexpr->rank != 0)
6263 maskss = gfc_walk_expr (maskexpr);
6264 gcc_assert (maskss != gfc_ss_terminator);
6266 else
6267 maskss = NULL;
6269 /* Initialize the scalarizer. */
6270 gfc_init_loopinfo (&loop);
6271 exit_label = gfc_build_label_decl (NULL_TREE);
6272 TREE_USED (exit_label) = 1;
6274 /* We add the mask first because the number of iterations is
6275 taken from the last ss, and this breaks if an absent
6276 optional argument is used for mask. */
6278 if (maskss)
6279 gfc_add_ss_to_loop (&loop, maskss);
6280 gfc_add_ss_to_loop (&loop, arrayss);
6282 /* Initialize the loop. */
6283 gfc_conv_ss_startstride (&loop);
6284 gfc_conv_loop_setup (&loop, &expr->where);
6286 /* Calculate the offset. */
6287 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6288 gfc_index_one_node, loop.from[0]);
6289 gfc_add_modify (&loop.pre, offset, tmp);
6291 gfc_mark_ss_chain_used (arrayss, 1);
6292 if (maskss)
6293 gfc_mark_ss_chain_used (maskss, 1);
6295 /* The first loop is for BACK=.true. */
6296 if (i == 0)
6297 loop.reverse[0] = GFC_REVERSE_SET;
6299 /* Generate the loop body. */
6300 gfc_start_scalarized_body (&loop, &body);
6302 /* If we have an array mask, only add the element if it is
6303 set. */
6304 if (maskss)
6306 gfc_init_se (&maskse, NULL);
6307 gfc_copy_loopinfo_to_se (&maskse, &loop);
6308 maskse.ss = maskss;
6309 gfc_conv_expr_val (&maskse, maskexpr);
6310 gfc_add_block_to_block (&body, &maskse.pre);
6313 /* If the condition matches then set the return value. */
6314 gfc_start_block (&block);
6316 /* Add the offset. */
6317 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6318 TREE_TYPE (resvar),
6319 loop.loopvar[0], offset);
6320 gfc_add_modify (&block, resvar, tmp);
6321 /* And break out of the loop. */
6322 tmp = build1_v (GOTO_EXPR, exit_label);
6323 gfc_add_expr_to_block (&block, tmp);
6325 found = gfc_finish_block (&block);
6327 /* Check this element. */
6328 gfc_init_se (&arrayse, NULL);
6329 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6330 arrayse.ss = arrayss;
6331 gfc_conv_expr_val (&arrayse, array_arg->expr);
6332 gfc_add_block_to_block (&body, &arrayse.pre);
6334 gfc_init_se (&valuese, NULL);
6335 gfc_conv_expr_val (&valuese, value_arg->expr);
6336 gfc_add_block_to_block (&body, &valuese.pre);
6338 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6339 arrayse.expr, valuese.expr);
6341 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
6342 if (maskss)
6344 /* We enclose the above in if (mask) {...}. If the mask is
6345 an optional argument, generate IF (.NOT. PRESENT(MASK)
6346 .OR. MASK(I)). */
6348 tree ifmask;
6349 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6350 tmp = build3_v (COND_EXPR, ifmask, tmp,
6351 build_empty_stmt (input_location));
6354 gfc_add_expr_to_block (&body, tmp);
6355 gfc_add_block_to_block (&body, &arrayse.post);
6357 gfc_trans_scalarizing_loops (&loop, &body);
6359 /* Add the exit label. */
6360 tmp = build1_v (LABEL_EXPR, exit_label);
6361 gfc_add_expr_to_block (&loop.pre, tmp);
6362 gfc_start_block (&loopblock);
6363 gfc_add_block_to_block (&loopblock, &loop.pre);
6364 gfc_add_block_to_block (&loopblock, &loop.post);
6365 if (i == 0)
6366 forward_branch = gfc_finish_block (&loopblock);
6367 else
6368 back_branch = gfc_finish_block (&loopblock);
6370 gfc_cleanup_loop (&loop);
6373 /* Enclose the two loops in an IF statement. */
6375 gfc_init_se (&backse, NULL);
6376 gfc_conv_expr_val (&backse, back_arg->expr);
6377 gfc_add_block_to_block (&se->pre, &backse.pre);
6378 tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
6380 /* For a scalar mask, enclose the loop in an if statement. */
6381 if (maskexpr && maskss == NULL)
6383 tree ifmask;
6384 tree if_stmt;
6386 gfc_init_se (&maskse, NULL);
6387 gfc_conv_expr_val (&maskse, maskexpr);
6388 gfc_init_block (&block);
6389 gfc_add_expr_to_block (&block, maskse.expr);
6390 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6391 if_stmt = build3_v (COND_EXPR, ifmask, tmp,
6392 build_empty_stmt (input_location));
6393 gfc_add_expr_to_block (&block, if_stmt);
6394 tmp = gfc_finish_block (&block);
6397 gfc_add_expr_to_block (&se->pre, tmp);
6398 se->expr = convert (type, resvar);
6402 /* Emit code for minval or maxval intrinsic. There are many different cases
6403 we need to handle. For performance reasons we sometimes create two
6404 loops instead of one, where the second one is much simpler.
6405 Examples for minval intrinsic:
6406 1) Result is an array, a call is generated
6407 2) Array mask is used and NaNs need to be supported, rank 1:
6408 limit = Infinity;
6409 nonempty = false;
6410 S = from;
6411 while (S <= to) {
6412 if (mask[S]) {
6413 nonempty = true;
6414 if (a[S] <= limit) {
6415 limit = a[S];
6416 S++;
6417 goto lab;
6419 else
6420 S++;
6423 limit = nonempty ? NaN : huge (limit);
6424 lab:
6425 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
6426 3) NaNs need to be supported, but it is known at compile time or cheaply
6427 at runtime whether array is nonempty or not, rank 1:
6428 limit = Infinity;
6429 S = from;
6430 while (S <= to) {
6431 if (a[S] <= limit) {
6432 limit = a[S];
6433 S++;
6434 goto lab;
6436 else
6437 S++;
6439 limit = (from <= to) ? NaN : huge (limit);
6440 lab:
6441 while (S <= to) { limit = min (a[S], limit); S++; }
6442 4) Array mask is used and NaNs need to be supported, rank > 1:
6443 limit = Infinity;
6444 nonempty = false;
6445 fast = false;
6446 S1 = from1;
6447 while (S1 <= to1) {
6448 S2 = from2;
6449 while (S2 <= to2) {
6450 if (mask[S1][S2]) {
6451 if (fast) limit = min (a[S1][S2], limit);
6452 else {
6453 nonempty = true;
6454 if (a[S1][S2] <= limit) {
6455 limit = a[S1][S2];
6456 fast = true;
6460 S2++;
6462 S1++;
6464 if (!fast)
6465 limit = nonempty ? NaN : huge (limit);
6466 5) NaNs need to be supported, but it is known at compile time or cheaply
6467 at runtime whether array is nonempty or not, rank > 1:
6468 limit = Infinity;
6469 fast = false;
6470 S1 = from1;
6471 while (S1 <= to1) {
6472 S2 = from2;
6473 while (S2 <= to2) {
6474 if (fast) limit = min (a[S1][S2], limit);
6475 else {
6476 if (a[S1][S2] <= limit) {
6477 limit = a[S1][S2];
6478 fast = true;
6481 S2++;
6483 S1++;
6485 if (!fast)
6486 limit = (nonempty_array) ? NaN : huge (limit);
6487 6) NaNs aren't supported, but infinities are. Array mask is used:
6488 limit = Infinity;
6489 nonempty = false;
6490 S = from;
6491 while (S <= to) {
6492 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6493 S++;
6495 limit = nonempty ? limit : huge (limit);
6496 7) Same without array mask:
6497 limit = Infinity;
6498 S = from;
6499 while (S <= to) { limit = min (a[S], limit); S++; }
6500 limit = (from <= to) ? limit : huge (limit);
6501 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6502 limit = huge (limit);
6503 S = from;
6504 while (S <= to) { limit = min (a[S], limit); S++); }
6506 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6507 with array mask instead).
6508 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6509 setting limit = huge (limit); in the else branch. */
6511 static void
6512 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
6514 tree limit;
6515 tree type;
6516 tree tmp;
6517 tree ifbody;
6518 tree nonempty;
6519 tree nonempty_var;
6520 tree lab;
6521 tree fast;
6522 tree huge_cst = NULL, nan_cst = NULL;
6523 stmtblock_t body;
6524 stmtblock_t block, block2;
6525 gfc_loopinfo loop;
6526 gfc_actual_arglist *actual;
6527 gfc_ss *arrayss;
6528 gfc_ss *maskss;
6529 gfc_se arrayse;
6530 gfc_se maskse;
6531 gfc_expr *arrayexpr;
6532 gfc_expr *maskexpr;
6533 int n;
6534 bool optional_mask;
6536 if (se->ss)
6538 gfc_conv_intrinsic_funcall (se, expr);
6539 return;
6542 actual = expr->value.function.actual;
6543 arrayexpr = actual->expr;
6545 if (arrayexpr->ts.type == BT_CHARACTER)
6547 gfc_actual_arglist *dim = actual->next;
6548 if (expr->rank == 0 && dim->expr != 0)
6550 gfc_free_expr (dim->expr);
6551 dim->expr = NULL;
6553 gfc_conv_intrinsic_funcall (se, expr);
6554 return;
6557 type = gfc_typenode_for_spec (&expr->ts);
6558 /* Initialize the result. */
6559 limit = gfc_create_var (type, "limit");
6560 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
6561 switch (expr->ts.type)
6563 case BT_REAL:
6564 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
6565 expr->ts.kind, 0);
6566 if (HONOR_INFINITIES (DECL_MODE (limit)))
6568 REAL_VALUE_TYPE real;
6569 real_inf (&real);
6570 tmp = build_real (type, real);
6572 else
6573 tmp = huge_cst;
6574 if (HONOR_NANS (DECL_MODE (limit)))
6575 nan_cst = gfc_build_nan (type, "");
6576 break;
6578 case BT_INTEGER:
6579 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
6580 break;
6582 case BT_UNSIGNED:
6583 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
6584 if (op == GT_EXPR)
6585 tmp = build_int_cst (type, 0);
6586 else
6587 tmp = gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds[n].huge,
6588 expr->ts.kind);
6589 break;
6591 default:
6592 gcc_unreachable ();
6595 /* We start with the most negative possible value for MAXVAL, and the most
6596 positive possible value for MINVAL. The most negative possible value is
6597 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
6598 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
6599 with above. */
6600 if (op == GT_EXPR && expr->ts.type != BT_UNSIGNED)
6602 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
6603 if (huge_cst)
6604 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
6605 TREE_TYPE (huge_cst), huge_cst);
6608 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6609 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6610 tmp, build_int_cst (type, 1));
6612 gfc_add_modify (&se->pre, limit, tmp);
6614 /* Walk the arguments. */
6615 arrayss = gfc_walk_expr (arrayexpr);
6616 gcc_assert (arrayss != gfc_ss_terminator);
6618 actual = actual->next->next;
6619 gcc_assert (actual);
6620 maskexpr = actual->expr;
6621 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6622 && maskexpr->symtree->n.sym->attr.dummy
6623 && maskexpr->symtree->n.sym->attr.optional;
6624 nonempty = NULL;
6625 if (maskexpr && maskexpr->rank != 0)
6627 maskss = gfc_walk_expr (maskexpr);
6628 gcc_assert (maskss != gfc_ss_terminator);
6630 else
6632 mpz_t asize;
6633 if (gfc_array_size (arrayexpr, &asize))
6635 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
6636 mpz_clear (asize);
6637 nonempty = fold_build2_loc (input_location, GT_EXPR,
6638 logical_type_node, nonempty,
6639 gfc_index_zero_node);
6641 maskss = NULL;
6644 /* Initialize the scalarizer. */
6645 gfc_init_loopinfo (&loop);
6647 /* We add the mask first because the number of iterations is taken
6648 from the last ss, and this breaks if an absent optional argument
6649 is used for mask. */
6651 if (maskss)
6652 gfc_add_ss_to_loop (&loop, maskss);
6653 gfc_add_ss_to_loop (&loop, arrayss);
6655 /* Initialize the loop. */
6656 gfc_conv_ss_startstride (&loop);
6658 /* The code generated can have more than one loop in sequence (see the
6659 comment at the function header). This doesn't work well with the
6660 scalarizer, which changes arrays' offset when the scalarization loops
6661 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6662 are currently inlined in the scalar case only. As there is no dependency
6663 to care about in that case, there is no temporary, so that we can use the
6664 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6665 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6666 gfc_trans_scalarized_loop_boundary even later to restore offset.
6667 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6668 should eventually go away. We could either create two loops properly,
6669 or find another way to save/restore the array offsets between the two
6670 loops (without conflicting with temporary management), or use a single
6671 loop minmaxval implementation. See PR 31067. */
6672 loop.temp_dim = loop.dimen;
6673 gfc_conv_loop_setup (&loop, &expr->where);
6675 if (nonempty == NULL && maskss == NULL
6676 && loop.dimen == 1 && loop.from[0] && loop.to[0])
6677 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
6678 loop.from[0], loop.to[0]);
6679 nonempty_var = NULL;
6680 if (nonempty == NULL
6681 && (HONOR_INFINITIES (DECL_MODE (limit))
6682 || HONOR_NANS (DECL_MODE (limit))))
6684 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
6685 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
6686 nonempty = nonempty_var;
6688 lab = NULL;
6689 fast = NULL;
6690 if (HONOR_NANS (DECL_MODE (limit)))
6692 if (loop.dimen == 1)
6694 lab = gfc_build_label_decl (NULL_TREE);
6695 TREE_USED (lab) = 1;
6697 else
6699 fast = gfc_create_var (logical_type_node, "fast");
6700 gfc_add_modify (&se->pre, fast, logical_false_node);
6704 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
6705 if (maskss)
6706 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
6707 /* Generate the loop body. */
6708 gfc_start_scalarized_body (&loop, &body);
6710 /* If we have a mask, only add this element if the mask is set. */
6711 if (maskss)
6713 gfc_init_se (&maskse, NULL);
6714 gfc_copy_loopinfo_to_se (&maskse, &loop);
6715 maskse.ss = maskss;
6716 gfc_conv_expr_val (&maskse, maskexpr);
6717 gfc_add_block_to_block (&body, &maskse.pre);
6719 gfc_start_block (&block);
6721 else
6722 gfc_init_block (&block);
6724 /* Compare with the current limit. */
6725 gfc_init_se (&arrayse, NULL);
6726 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6727 arrayse.ss = arrayss;
6728 gfc_conv_expr_val (&arrayse, arrayexpr);
6729 arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
6730 gfc_add_block_to_block (&block, &arrayse.pre);
6732 gfc_init_block (&block2);
6734 if (nonempty_var)
6735 gfc_add_modify (&block2, nonempty_var, logical_true_node);
6737 if (HONOR_NANS (DECL_MODE (limit)))
6739 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
6740 logical_type_node, arrayse.expr, limit);
6741 if (lab)
6743 stmtblock_t ifblock;
6744 tree inc_loop;
6745 inc_loop = fold_build2_loc (input_location, PLUS_EXPR,
6746 TREE_TYPE (loop.loopvar[0]),
6747 loop.loopvar[0], gfc_index_one_node);
6748 gfc_init_block (&ifblock);
6749 gfc_add_modify (&ifblock, limit, arrayse.expr);
6750 gfc_add_modify (&ifblock, loop.loopvar[0], inc_loop);
6751 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab));
6752 ifbody = gfc_finish_block (&ifblock);
6754 else
6756 stmtblock_t ifblock;
6758 gfc_init_block (&ifblock);
6759 gfc_add_modify (&ifblock, limit, arrayse.expr);
6760 gfc_add_modify (&ifblock, fast, logical_true_node);
6761 ifbody = gfc_finish_block (&ifblock);
6763 tmp = build3_v (COND_EXPR, tmp, ifbody,
6764 build_empty_stmt (input_location));
6765 gfc_add_expr_to_block (&block2, tmp);
6767 else
6769 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6770 signed zeros. */
6771 tmp = fold_build2_loc (input_location,
6772 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6773 type, arrayse.expr, limit);
6774 gfc_add_modify (&block2, limit, tmp);
6777 if (fast)
6779 tree elsebody = gfc_finish_block (&block2);
6781 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6782 signed zeros. */
6783 if (HONOR_NANS (DECL_MODE (limit)))
6785 tmp = fold_build2_loc (input_location, op, logical_type_node,
6786 arrayse.expr, limit);
6787 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6788 ifbody = build3_v (COND_EXPR, tmp, ifbody,
6789 build_empty_stmt (input_location));
6791 else
6793 tmp = fold_build2_loc (input_location,
6794 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6795 type, arrayse.expr, limit);
6796 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6798 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
6799 gfc_add_expr_to_block (&block, tmp);
6801 else
6802 gfc_add_block_to_block (&block, &block2);
6804 gfc_add_block_to_block (&block, &arrayse.post);
6806 tmp = gfc_finish_block (&block);
6807 if (maskss)
6809 /* We enclose the above in if (mask) {...}. If the mask is an
6810 optional argument, generate IF (.NOT. PRESENT(MASK)
6811 .OR. MASK(I)). */
6812 tree ifmask;
6813 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6814 tmp = build3_v (COND_EXPR, ifmask, tmp,
6815 build_empty_stmt (input_location));
6817 gfc_add_expr_to_block (&body, tmp);
6819 if (lab)
6821 gfc_trans_scalarized_loop_boundary (&loop, &body);
6823 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6824 nan_cst, huge_cst);
6825 gfc_add_modify (&loop.code[0], limit, tmp);
6826 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
6828 /* If we have a mask, only add this element if the mask is set. */
6829 if (maskss)
6831 gfc_init_se (&maskse, NULL);
6832 gfc_copy_loopinfo_to_se (&maskse, &loop);
6833 maskse.ss = maskss;
6834 gfc_conv_expr_val (&maskse, maskexpr);
6835 gfc_add_block_to_block (&body, &maskse.pre);
6837 gfc_start_block (&block);
6839 else
6840 gfc_init_block (&block);
6842 /* Compare with the current limit. */
6843 gfc_init_se (&arrayse, NULL);
6844 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6845 arrayse.ss = arrayss;
6846 gfc_conv_expr_val (&arrayse, arrayexpr);
6847 arrayse.expr = gfc_evaluate_now (arrayse.expr, &arrayse.pre);
6848 gfc_add_block_to_block (&block, &arrayse.pre);
6850 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6851 signed zeros. */
6852 if (HONOR_NANS (DECL_MODE (limit)))
6854 tmp = fold_build2_loc (input_location, op, logical_type_node,
6855 arrayse.expr, limit);
6856 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6857 tmp = build3_v (COND_EXPR, tmp, ifbody,
6858 build_empty_stmt (input_location));
6859 gfc_add_expr_to_block (&block, tmp);
6861 else
6863 tmp = fold_build2_loc (input_location,
6864 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6865 type, arrayse.expr, limit);
6866 gfc_add_modify (&block, limit, tmp);
6869 gfc_add_block_to_block (&block, &arrayse.post);
6871 tmp = gfc_finish_block (&block);
6872 if (maskss)
6873 /* We enclose the above in if (mask) {...}. */
6875 tree ifmask;
6876 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6877 tmp = build3_v (COND_EXPR, ifmask, tmp,
6878 build_empty_stmt (input_location));
6881 gfc_add_expr_to_block (&body, tmp);
6882 /* Avoid initializing loopvar[0] again, it should be left where
6883 it finished by the first loop. */
6884 loop.from[0] = loop.loopvar[0];
6886 gfc_trans_scalarizing_loops (&loop, &body);
6888 if (fast)
6890 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6891 nan_cst, huge_cst);
6892 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6893 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
6894 ifbody);
6895 gfc_add_expr_to_block (&loop.pre, tmp);
6897 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
6899 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
6900 huge_cst);
6901 gfc_add_modify (&loop.pre, limit, tmp);
6904 /* For a scalar mask, enclose the loop in an if statement. */
6905 if (maskexpr && maskss == NULL)
6907 tree else_stmt;
6908 tree ifmask;
6910 gfc_init_se (&maskse, NULL);
6911 gfc_conv_expr_val (&maskse, maskexpr);
6912 gfc_init_block (&block);
6913 gfc_add_block_to_block (&block, &loop.pre);
6914 gfc_add_block_to_block (&block, &loop.post);
6915 tmp = gfc_finish_block (&block);
6917 if (HONOR_INFINITIES (DECL_MODE (limit)))
6918 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
6919 else
6920 else_stmt = build_empty_stmt (input_location);
6922 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6923 tmp = build3_v (COND_EXPR, ifmask, tmp, else_stmt);
6924 gfc_add_expr_to_block (&block, tmp);
6925 gfc_add_block_to_block (&se->pre, &block);
6927 else
6929 gfc_add_block_to_block (&se->pre, &loop.pre);
6930 gfc_add_block_to_block (&se->pre, &loop.post);
6933 gfc_cleanup_loop (&loop);
6935 se->expr = limit;
6938 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6939 static void
6940 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
6942 tree args[2];
6943 tree type;
6944 tree tmp;
6946 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6947 type = TREE_TYPE (args[0]);
6949 /* Optionally generate code for runtime argument check. */
6950 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6952 tree below = fold_build2_loc (input_location, LT_EXPR,
6953 logical_type_node, args[1],
6954 build_int_cst (TREE_TYPE (args[1]), 0));
6955 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6956 tree above = fold_build2_loc (input_location, GE_EXPR,
6957 logical_type_node, args[1], nbits);
6958 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6959 logical_type_node, below, above);
6960 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6961 "POS argument (%ld) out of range 0:%ld "
6962 "in intrinsic BTEST",
6963 fold_convert (long_integer_type_node, args[1]),
6964 fold_convert (long_integer_type_node, nbits));
6967 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6968 build_int_cst (type, 1), args[1]);
6969 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
6970 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
6971 build_int_cst (type, 0));
6972 type = gfc_typenode_for_spec (&expr->ts);
6973 se->expr = convert (type, tmp);
6977 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6978 static void
6979 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6981 tree args[2];
6983 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6985 /* Convert both arguments to the unsigned type of the same size. */
6986 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
6987 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
6989 /* If they have unequal type size, convert to the larger one. */
6990 if (TYPE_PRECISION (TREE_TYPE (args[0]))
6991 > TYPE_PRECISION (TREE_TYPE (args[1])))
6992 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
6993 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
6994 > TYPE_PRECISION (TREE_TYPE (args[0])))
6995 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
6997 /* Now, we compare them. */
6998 se->expr = fold_build2_loc (input_location, op, logical_type_node,
6999 args[0], args[1]);
7003 /* Generate code to perform the specified operation. */
7004 static void
7005 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
7007 tree args[2];
7009 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7010 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
7011 args[0], args[1]);
7014 /* Bitwise not. */
7015 static void
7016 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
7018 tree arg;
7020 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7021 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
7022 TREE_TYPE (arg), arg);
7026 /* Generate code for OUT_OF_RANGE. */
7027 static void
7028 gfc_conv_intrinsic_out_of_range (gfc_se * se, gfc_expr * expr)
7030 tree *args;
7031 tree type;
7032 tree tmp = NULL_TREE, tmp1, tmp2;
7033 unsigned int num_args;
7034 int k;
7035 gfc_se rnd_se;
7036 gfc_actual_arglist *arg = expr->value.function.actual;
7037 gfc_expr *x = arg->expr;
7038 gfc_expr *mold = arg->next->expr;
7040 num_args = gfc_intrinsic_argument_list_length (expr);
7041 args = XALLOCAVEC (tree, num_args);
7043 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7045 gfc_init_se (&rnd_se, NULL);
7047 if (num_args == 3)
7049 /* The ROUND argument is optional and shall appear only if X is
7050 of type real and MOLD is of type integer (see edit F23/004). */
7051 gfc_expr *round = arg->next->next->expr;
7052 gfc_conv_expr (&rnd_se, round);
7054 if (round->expr_type == EXPR_VARIABLE
7055 && round->symtree->n.sym->attr.dummy
7056 && round->symtree->n.sym->attr.optional)
7058 tree present = gfc_conv_expr_present (round->symtree->n.sym);
7059 rnd_se.expr = build3_loc (input_location, COND_EXPR,
7060 logical_type_node, present,
7061 rnd_se.expr, logical_false_node);
7062 gfc_add_block_to_block (&se->pre, &rnd_se.pre);
7065 else
7067 /* If ROUND is absent, it is equivalent to having the value false. */
7068 rnd_se.expr = logical_false_node;
7071 type = TREE_TYPE (args[0]);
7072 k = gfc_validate_kind (mold->ts.type, mold->ts.kind, false);
7074 switch (x->ts.type)
7076 case BT_REAL:
7077 /* X may be IEEE infinity or NaN, but the representation of MOLD may not
7078 support infinity or NaN. */
7079 tree finite;
7080 finite = build_call_expr_loc (input_location,
7081 builtin_decl_explicit (BUILT_IN_ISFINITE),
7082 1, args[0]);
7083 finite = convert (logical_type_node, finite);
7085 if (mold->ts.type == BT_REAL)
7087 tmp1 = build1 (ABS_EXPR, type, args[0]);
7088 tmp2 = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].huge,
7089 mold->ts.kind, 0);
7090 tmp = build2 (GT_EXPR, logical_type_node, tmp1,
7091 convert (type, tmp2));
7093 /* Check if MOLD representation supports infinity or NaN. */
7094 bool infnan = (HONOR_INFINITIES (TREE_TYPE (args[1]))
7095 || HONOR_NANS (TREE_TYPE (args[1])));
7096 tmp = build3 (COND_EXPR, logical_type_node, finite, tmp,
7097 infnan ? logical_false_node : logical_true_node);
7099 else
7101 tree rounded;
7102 tree decl;
7104 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, x->ts.kind);
7105 gcc_assert (decl != NULL_TREE);
7107 /* Round or truncate argument X, depending on the optional argument
7108 ROUND (default: .false.). */
7109 tmp1 = build_round_expr (args[0], type);
7110 tmp2 = build_call_expr_loc (input_location, decl, 1, args[0]);
7111 rounded = build3 (COND_EXPR, type, rnd_se.expr, tmp1, tmp2);
7113 if (mold->ts.type == BT_INTEGER)
7115 tmp1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[k].min_int,
7116 x->ts.kind);
7117 tmp2 = gfc_conv_mpz_to_tree (gfc_integer_kinds[k].huge,
7118 x->ts.kind);
7120 else if (mold->ts.type == BT_UNSIGNED)
7122 tmp1 = build_real_from_int_cst (type, integer_zero_node);
7123 tmp2 = gfc_conv_mpz_to_tree (gfc_unsigned_kinds[k].huge,
7124 x->ts.kind);
7126 else
7127 gcc_unreachable ();
7129 tmp1 = build2 (LT_EXPR, logical_type_node, rounded,
7130 convert (type, tmp1));
7131 tmp2 = build2 (GT_EXPR, logical_type_node, rounded,
7132 convert (type, tmp2));
7133 tmp = build2 (TRUTH_ORIF_EXPR, logical_type_node, tmp1, tmp2);
7134 tmp = build2 (TRUTH_ORIF_EXPR, logical_type_node,
7135 build1 (TRUTH_NOT_EXPR, logical_type_node, finite),
7136 tmp);
7138 break;
7140 case BT_INTEGER:
7141 if (mold->ts.type == BT_INTEGER)
7143 tmp1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[k].min_int,
7144 x->ts.kind);
7145 tmp2 = gfc_conv_mpz_to_tree (gfc_integer_kinds[k].huge,
7146 x->ts.kind);
7147 tmp1 = build2 (LT_EXPR, logical_type_node, args[0],
7148 convert (type, tmp1));
7149 tmp2 = build2 (GT_EXPR, logical_type_node, args[0],
7150 convert (type, tmp2));
7151 tmp = build2 (TRUTH_ORIF_EXPR, logical_type_node, tmp1, tmp2);
7153 else if (mold->ts.type == BT_UNSIGNED)
7155 int i = gfc_validate_kind (x->ts.type, x->ts.kind, false);
7156 tmp = build_int_cst (type, 0);
7157 tmp = build2 (LT_EXPR, logical_type_node, args[0], tmp);
7158 if (mpz_cmp (gfc_integer_kinds[i].huge,
7159 gfc_unsigned_kinds[k].huge) > 0)
7161 tmp2 = gfc_conv_mpz_to_tree (gfc_unsigned_kinds[k].huge,
7162 x->ts.kind);
7163 tmp2 = build2 (GT_EXPR, logical_type_node, args[0],
7164 convert (type, tmp2));
7165 tmp = build2 (TRUTH_ORIF_EXPR, logical_type_node, tmp, tmp2);
7168 else if (mold->ts.type == BT_REAL)
7170 tmp2 = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].huge,
7171 mold->ts.kind, 0);
7172 tmp1 = build1 (NEGATE_EXPR, TREE_TYPE (tmp2), tmp2);
7173 tmp1 = build2 (LT_EXPR, logical_type_node, args[0],
7174 convert (type, tmp1));
7175 tmp2 = build2 (GT_EXPR, logical_type_node, args[0],
7176 convert (type, tmp2));
7177 tmp = build2 (TRUTH_ORIF_EXPR, logical_type_node, tmp1, tmp2);
7179 else
7180 gcc_unreachable ();
7181 break;
7183 case BT_UNSIGNED:
7184 if (mold->ts.type == BT_UNSIGNED)
7186 tmp = gfc_conv_mpz_to_tree (gfc_unsigned_kinds[k].huge,
7187 x->ts.kind);
7188 tmp = build2 (GT_EXPR, logical_type_node, args[0],
7189 convert (type, tmp));
7191 else if (mold->ts.type == BT_INTEGER)
7193 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[k].huge,
7194 x->ts.kind);
7195 tmp = build2 (GT_EXPR, logical_type_node, args[0],
7196 convert (type, tmp));
7198 else if (mold->ts.type == BT_REAL)
7200 tmp = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].huge,
7201 mold->ts.kind, 0);
7202 tmp = build2 (GT_EXPR, logical_type_node, args[0],
7203 convert (type, tmp));
7205 else
7206 gcc_unreachable ();
7207 break;
7209 default:
7210 gcc_unreachable ();
7213 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7217 /* Set or clear a single bit. */
7218 static void
7219 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
7221 tree args[2];
7222 tree type;
7223 tree tmp;
7224 enum tree_code op;
7226 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7227 type = TREE_TYPE (args[0]);
7229 /* Optionally generate code for runtime argument check. */
7230 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7232 tree below = fold_build2_loc (input_location, LT_EXPR,
7233 logical_type_node, args[1],
7234 build_int_cst (TREE_TYPE (args[1]), 0));
7235 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
7236 tree above = fold_build2_loc (input_location, GE_EXPR,
7237 logical_type_node, args[1], nbits);
7238 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7239 logical_type_node, below, above);
7240 size_t len_name = strlen (expr->value.function.isym->name);
7241 char *name = XALLOCAVEC (char, len_name + 1);
7242 for (size_t i = 0; i < len_name; i++)
7243 name[i] = TOUPPER (expr->value.function.isym->name[i]);
7244 name[len_name] = '\0';
7245 tree iname = gfc_build_addr_expr (pchar_type_node,
7246 gfc_build_cstring_const (name));
7247 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7248 "POS argument (%ld) out of range 0:%ld "
7249 "in intrinsic %s",
7250 fold_convert (long_integer_type_node, args[1]),
7251 fold_convert (long_integer_type_node, nbits),
7252 iname);
7255 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
7256 build_int_cst (type, 1), args[1]);
7257 if (set)
7258 op = BIT_IOR_EXPR;
7259 else
7261 op = BIT_AND_EXPR;
7262 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
7264 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
7267 /* Extract a sequence of bits.
7268 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
7269 static void
7270 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
7272 tree args[3];
7273 tree type;
7274 tree tmp;
7275 tree mask;
7276 tree num_bits, cond;
7278 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7279 type = TREE_TYPE (args[0]);
7281 /* Optionally generate code for runtime argument check. */
7282 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7284 tree tmp1 = fold_convert (long_integer_type_node, args[1]);
7285 tree tmp2 = fold_convert (long_integer_type_node, args[2]);
7286 tree nbits = build_int_cst (long_integer_type_node,
7287 TYPE_PRECISION (type));
7288 tree below = fold_build2_loc (input_location, LT_EXPR,
7289 logical_type_node, args[1],
7290 build_int_cst (TREE_TYPE (args[1]), 0));
7291 tree above = fold_build2_loc (input_location, GT_EXPR,
7292 logical_type_node, tmp1, nbits);
7293 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7294 logical_type_node, below, above);
7295 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7296 "POS argument (%ld) out of range 0:%ld "
7297 "in intrinsic IBITS", tmp1, nbits);
7298 below = fold_build2_loc (input_location, LT_EXPR,
7299 logical_type_node, args[2],
7300 build_int_cst (TREE_TYPE (args[2]), 0));
7301 above = fold_build2_loc (input_location, GT_EXPR,
7302 logical_type_node, tmp2, nbits);
7303 scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7304 logical_type_node, below, above);
7305 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7306 "LEN argument (%ld) out of range 0:%ld "
7307 "in intrinsic IBITS", tmp2, nbits);
7308 above = fold_build2_loc (input_location, PLUS_EXPR,
7309 long_integer_type_node, tmp1, tmp2);
7310 scond = fold_build2_loc (input_location, GT_EXPR,
7311 logical_type_node, above, nbits);
7312 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7313 "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
7314 "in intrinsic IBITS", tmp1, tmp2, nbits);
7317 /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
7318 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7319 special case. See also gfc_conv_intrinsic_ishft (). */
7320 num_bits = build_int_cst (TREE_TYPE (args[2]), TYPE_PRECISION (type));
7322 mask = build_int_cst (type, -1);
7323 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
7324 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[2],
7325 num_bits);
7326 mask = fold_build3_loc (input_location, COND_EXPR, type, cond,
7327 build_int_cst (type, 0), mask);
7328 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
7330 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
7332 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
7335 static void
7336 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
7337 bool arithmetic)
7339 tree args[2], type, num_bits, cond;
7340 tree bigshift;
7341 bool do_convert = false;
7343 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7345 args[0] = gfc_evaluate_now (args[0], &se->pre);
7346 args[1] = gfc_evaluate_now (args[1], &se->pre);
7347 type = TREE_TYPE (args[0]);
7349 if (!arithmetic)
7351 args[0] = fold_convert (unsigned_type_for (type), args[0]);
7352 do_convert = true;
7354 else
7355 gcc_assert (right_shift);
7357 if (flag_unsigned && arithmetic && expr->ts.type == BT_UNSIGNED)
7359 do_convert = true;
7360 args[0] = fold_convert (signed_type_for (type), args[0]);
7363 se->expr = fold_build2_loc (input_location,
7364 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
7365 TREE_TYPE (args[0]), args[0], args[1]);
7367 if (do_convert)
7368 se->expr = fold_convert (type, se->expr);
7370 if (!arithmetic)
7371 bigshift = build_int_cst (type, 0);
7372 else
7374 tree nonneg = fold_build2_loc (input_location, GE_EXPR,
7375 logical_type_node, args[0],
7376 build_int_cst (TREE_TYPE (args[0]), 0));
7377 bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
7378 build_int_cst (type, 0),
7379 build_int_cst (type, -1));
7382 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7383 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7384 special case. */
7385 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
7387 /* Optionally generate code for runtime argument check. */
7388 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7390 tree below = fold_build2_loc (input_location, LT_EXPR,
7391 logical_type_node, args[1],
7392 build_int_cst (TREE_TYPE (args[1]), 0));
7393 tree above = fold_build2_loc (input_location, GT_EXPR,
7394 logical_type_node, args[1], num_bits);
7395 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7396 logical_type_node, below, above);
7397 size_t len_name = strlen (expr->value.function.isym->name);
7398 char *name = XALLOCAVEC (char, len_name + 1);
7399 for (size_t i = 0; i < len_name; i++)
7400 name[i] = TOUPPER (expr->value.function.isym->name[i]);
7401 name[len_name] = '\0';
7402 tree iname = gfc_build_addr_expr (pchar_type_node,
7403 gfc_build_cstring_const (name));
7404 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7405 "SHIFT argument (%ld) out of range 0:%ld "
7406 "in intrinsic %s",
7407 fold_convert (long_integer_type_node, args[1]),
7408 fold_convert (long_integer_type_node, num_bits),
7409 iname);
7412 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7413 args[1], num_bits);
7415 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7416 bigshift, se->expr);
7419 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
7421 : ((shift >= 0) ? i << shift : i >> -shift)
7422 where all shifts are logical shifts. */
7423 static void
7424 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
7426 tree args[2];
7427 tree type;
7428 tree utype;
7429 tree tmp;
7430 tree width;
7431 tree num_bits;
7432 tree cond;
7433 tree lshift;
7434 tree rshift;
7436 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7438 args[0] = gfc_evaluate_now (args[0], &se->pre);
7439 args[1] = gfc_evaluate_now (args[1], &se->pre);
7441 type = TREE_TYPE (args[0]);
7442 utype = unsigned_type_for (type);
7444 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
7445 args[1]);
7447 /* Left shift if positive. */
7448 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
7450 /* Right shift if negative.
7451 We convert to an unsigned type because we want a logical shift.
7452 The standard doesn't define the case of shifting negative
7453 numbers, and we try to be compatible with other compilers, most
7454 notably g77, here. */
7455 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
7456 utype, convert (utype, args[0]), width));
7458 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
7459 build_int_cst (TREE_TYPE (args[1]), 0));
7460 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
7462 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7463 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7464 special case. */
7465 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
7467 /* Optionally generate code for runtime argument check. */
7468 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7470 tree outside = fold_build2_loc (input_location, GT_EXPR,
7471 logical_type_node, width, num_bits);
7472 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
7473 "SHIFT argument (%ld) out of range -%ld:%ld "
7474 "in intrinsic ISHFT",
7475 fold_convert (long_integer_type_node, args[1]),
7476 fold_convert (long_integer_type_node, num_bits),
7477 fold_convert (long_integer_type_node, num_bits));
7480 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
7481 num_bits);
7482 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7483 build_int_cst (type, 0), tmp);
7487 /* Circular shift. AKA rotate or barrel shift. */
7489 static void
7490 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
7492 tree *args;
7493 tree type;
7494 tree tmp;
7495 tree lrot;
7496 tree rrot;
7497 tree zero;
7498 tree nbits;
7499 unsigned int num_args;
7501 num_args = gfc_intrinsic_argument_list_length (expr);
7502 args = XALLOCAVEC (tree, num_args);
7504 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7506 type = TREE_TYPE (args[0]);
7507 nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type));
7509 if (num_args == 3)
7511 gfc_expr *size = expr->value.function.actual->next->next->expr;
7513 /* Use a library function for the 3 parameter version. */
7514 tree int4type = gfc_get_int_type (4);
7516 /* Treat optional SIZE argument when it is passed as an optional
7517 dummy. If SIZE is absent, the default value is BIT_SIZE(I). */
7518 if (size->expr_type == EXPR_VARIABLE
7519 && size->symtree->n.sym->attr.dummy
7520 && size->symtree->n.sym->attr.optional)
7522 tree type_of_size = TREE_TYPE (args[2]);
7523 args[2] = build3_loc (input_location, COND_EXPR, type_of_size,
7524 gfc_conv_expr_present (size->symtree->n.sym),
7525 args[2], fold_convert (type_of_size, nbits));
7528 /* We convert the first argument to at least 4 bytes, and
7529 convert back afterwards. This removes the need for library
7530 functions for all argument sizes, and function will be
7531 aligned to at least 32 bits, so there's no loss. */
7532 if (expr->ts.kind < 4)
7533 args[0] = convert (int4type, args[0]);
7535 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
7536 need loads of library functions. They cannot have values >
7537 BIT_SIZE (I) so the conversion is safe. */
7538 args[1] = convert (int4type, args[1]);
7539 args[2] = convert (int4type, args[2]);
7541 /* Optionally generate code for runtime argument check. */
7542 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7544 tree size = fold_convert (long_integer_type_node, args[2]);
7545 tree below = fold_build2_loc (input_location, LE_EXPR,
7546 logical_type_node, size,
7547 build_int_cst (TREE_TYPE (args[1]), 0));
7548 tree above = fold_build2_loc (input_location, GT_EXPR,
7549 logical_type_node, size, nbits);
7550 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7551 logical_type_node, below, above);
7552 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7553 "SIZE argument (%ld) out of range 1:%ld "
7554 "in intrinsic ISHFTC", size, nbits);
7555 tree width = fold_convert (long_integer_type_node, args[1]);
7556 width = fold_build1_loc (input_location, ABS_EXPR,
7557 long_integer_type_node, width);
7558 scond = fold_build2_loc (input_location, GT_EXPR,
7559 logical_type_node, width, size);
7560 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7561 "SHIFT argument (%ld) out of range -%ld:%ld "
7562 "in intrinsic ISHFTC",
7563 fold_convert (long_integer_type_node, args[1]),
7564 size, size);
7567 switch (expr->ts.kind)
7569 case 1:
7570 case 2:
7571 case 4:
7572 tmp = gfor_fndecl_math_ishftc4;
7573 break;
7574 case 8:
7575 tmp = gfor_fndecl_math_ishftc8;
7576 break;
7577 case 16:
7578 tmp = gfor_fndecl_math_ishftc16;
7579 break;
7580 default:
7581 gcc_unreachable ();
7583 se->expr = build_call_expr_loc (input_location,
7584 tmp, 3, args[0], args[1], args[2]);
7585 /* Convert the result back to the original type, if we extended
7586 the first argument's width above. */
7587 if (expr->ts.kind < 4)
7588 se->expr = convert (type, se->expr);
7590 return;
7593 /* Evaluate arguments only once. */
7594 args[0] = gfc_evaluate_now (args[0], &se->pre);
7595 args[1] = gfc_evaluate_now (args[1], &se->pre);
7597 /* Optionally generate code for runtime argument check. */
7598 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7600 tree width = fold_convert (long_integer_type_node, args[1]);
7601 width = fold_build1_loc (input_location, ABS_EXPR,
7602 long_integer_type_node, width);
7603 tree outside = fold_build2_loc (input_location, GT_EXPR,
7604 logical_type_node, width, nbits);
7605 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
7606 "SHIFT argument (%ld) out of range -%ld:%ld "
7607 "in intrinsic ISHFTC",
7608 fold_convert (long_integer_type_node, args[1]),
7609 nbits, nbits);
7612 /* Rotate left if positive. */
7613 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
7615 /* Rotate right if negative. */
7616 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
7617 args[1]);
7618 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
7620 zero = build_int_cst (TREE_TYPE (args[1]), 0);
7621 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
7622 zero);
7623 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
7625 /* Do nothing if shift == 0. */
7626 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
7627 zero);
7628 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
7629 rrot);
7633 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
7634 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
7636 The conditional expression is necessary because the result of LEADZ(0)
7637 is defined, but the result of __builtin_clz(0) is undefined for most
7638 targets.
7640 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
7641 difference in bit size between the argument of LEADZ and the C int. */
7643 static void
7644 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
7646 tree arg;
7647 tree arg_type;
7648 tree cond;
7649 tree result_type;
7650 tree leadz;
7651 tree bit_size;
7652 tree tmp;
7653 tree func;
7654 int s, argsize;
7656 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7657 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7659 /* Which variant of __builtin_clz* should we call? */
7660 if (argsize <= INT_TYPE_SIZE)
7662 arg_type = unsigned_type_node;
7663 func = builtin_decl_explicit (BUILT_IN_CLZ);
7665 else if (argsize <= LONG_TYPE_SIZE)
7667 arg_type = long_unsigned_type_node;
7668 func = builtin_decl_explicit (BUILT_IN_CLZL);
7670 else if (argsize <= LONG_LONG_TYPE_SIZE)
7672 arg_type = long_long_unsigned_type_node;
7673 func = builtin_decl_explicit (BUILT_IN_CLZLL);
7675 else
7677 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7678 arg_type = gfc_build_uint_type (argsize);
7679 func = NULL_TREE;
7682 /* Convert the actual argument twice: first, to the unsigned type of the
7683 same size; then, to the proper argument type for the built-in
7684 function. But the return type is of the default INTEGER kind. */
7685 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7686 arg = fold_convert (arg_type, arg);
7687 arg = gfc_evaluate_now (arg, &se->pre);
7688 result_type = gfc_get_int_type (gfc_default_integer_kind);
7690 /* Compute LEADZ for the case i .ne. 0. */
7691 if (func)
7693 s = TYPE_PRECISION (arg_type) - argsize;
7694 tmp = fold_convert (result_type,
7695 build_call_expr_loc (input_location, func,
7696 1, arg));
7697 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
7698 tmp, build_int_cst (result_type, s));
7700 else
7702 /* We end up here if the argument type is larger than 'long long'.
7703 We generate this code:
7705 if (x & (ULL_MAX << ULL_SIZE) != 0)
7706 return clzll ((unsigned long long) (x >> ULLSIZE));
7707 else
7708 return ULL_SIZE + clzll ((unsigned long long) x);
7709 where ULL_MAX is the largest value that a ULL_MAX can hold
7710 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7711 is the bit-size of the long long type (64 in this example). */
7712 tree ullsize, ullmax, tmp1, tmp2, btmp;
7714 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7715 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7716 long_long_unsigned_type_node,
7717 build_int_cst (long_long_unsigned_type_node,
7718 0));
7720 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
7721 fold_convert (arg_type, ullmax), ullsize);
7722 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
7723 arg, cond);
7724 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7725 cond, build_int_cst (arg_type, 0));
7727 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7728 arg, ullsize);
7729 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7730 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7731 tmp1 = fold_convert (result_type,
7732 build_call_expr_loc (input_location, btmp, 1, tmp1));
7734 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7735 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7736 tmp2 = fold_convert (result_type,
7737 build_call_expr_loc (input_location, btmp, 1, tmp2));
7738 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7739 tmp2, ullsize);
7741 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
7742 cond, tmp1, tmp2);
7745 /* Build BIT_SIZE. */
7746 bit_size = build_int_cst (result_type, argsize);
7748 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7749 arg, build_int_cst (arg_type, 0));
7750 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7751 bit_size, leadz);
7755 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7757 The conditional expression is necessary because the result of TRAILZ(0)
7758 is defined, but the result of __builtin_ctz(0) is undefined for most
7759 targets. */
7761 static void
7762 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
7764 tree arg;
7765 tree arg_type;
7766 tree cond;
7767 tree result_type;
7768 tree trailz;
7769 tree bit_size;
7770 tree func;
7771 int argsize;
7773 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7774 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7776 /* Which variant of __builtin_ctz* should we call? */
7777 if (argsize <= INT_TYPE_SIZE)
7779 arg_type = unsigned_type_node;
7780 func = builtin_decl_explicit (BUILT_IN_CTZ);
7782 else if (argsize <= LONG_TYPE_SIZE)
7784 arg_type = long_unsigned_type_node;
7785 func = builtin_decl_explicit (BUILT_IN_CTZL);
7787 else if (argsize <= LONG_LONG_TYPE_SIZE)
7789 arg_type = long_long_unsigned_type_node;
7790 func = builtin_decl_explicit (BUILT_IN_CTZLL);
7792 else
7794 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7795 arg_type = gfc_build_uint_type (argsize);
7796 func = NULL_TREE;
7799 /* Convert the actual argument twice: first, to the unsigned type of the
7800 same size; then, to the proper argument type for the built-in
7801 function. But the return type is of the default INTEGER kind. */
7802 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7803 arg = fold_convert (arg_type, arg);
7804 arg = gfc_evaluate_now (arg, &se->pre);
7805 result_type = gfc_get_int_type (gfc_default_integer_kind);
7807 /* Compute TRAILZ for the case i .ne. 0. */
7808 if (func)
7809 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
7810 func, 1, arg));
7811 else
7813 /* We end up here if the argument type is larger than 'long long'.
7814 We generate this code:
7816 if ((x & ULL_MAX) == 0)
7817 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7818 else
7819 return ctzll ((unsigned long long) x);
7821 where ULL_MAX is the largest value that a ULL_MAX can hold
7822 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7823 is the bit-size of the long long type (64 in this example). */
7824 tree ullsize, ullmax, tmp1, tmp2, btmp;
7826 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7827 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7828 long_long_unsigned_type_node,
7829 build_int_cst (long_long_unsigned_type_node, 0));
7831 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
7832 fold_convert (arg_type, ullmax));
7833 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
7834 build_int_cst (arg_type, 0));
7836 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7837 arg, ullsize);
7838 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7839 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7840 tmp1 = fold_convert (result_type,
7841 build_call_expr_loc (input_location, btmp, 1, tmp1));
7842 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7843 tmp1, ullsize);
7845 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7846 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7847 tmp2 = fold_convert (result_type,
7848 build_call_expr_loc (input_location, btmp, 1, tmp2));
7850 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
7851 cond, tmp1, tmp2);
7854 /* Build BIT_SIZE. */
7855 bit_size = build_int_cst (result_type, argsize);
7857 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7858 arg, build_int_cst (arg_type, 0));
7859 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7860 bit_size, trailz);
7863 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7864 for types larger than "long long", we call the long long built-in for
7865 the lower and higher bits and combine the result. */
7867 static void
7868 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
7870 tree arg;
7871 tree arg_type;
7872 tree result_type;
7873 tree func;
7874 int argsize;
7876 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7877 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7878 result_type = gfc_get_int_type (gfc_default_integer_kind);
7880 /* Which variant of the builtin should we call? */
7881 if (argsize <= INT_TYPE_SIZE)
7883 arg_type = unsigned_type_node;
7884 func = builtin_decl_explicit (parity
7885 ? BUILT_IN_PARITY
7886 : BUILT_IN_POPCOUNT);
7888 else if (argsize <= LONG_TYPE_SIZE)
7890 arg_type = long_unsigned_type_node;
7891 func = builtin_decl_explicit (parity
7892 ? BUILT_IN_PARITYL
7893 : BUILT_IN_POPCOUNTL);
7895 else if (argsize <= LONG_LONG_TYPE_SIZE)
7897 arg_type = long_long_unsigned_type_node;
7898 func = builtin_decl_explicit (parity
7899 ? BUILT_IN_PARITYLL
7900 : BUILT_IN_POPCOUNTLL);
7902 else
7904 /* Our argument type is larger than 'long long', which mean none
7905 of the POPCOUNT builtins covers it. We thus call the 'long long'
7906 variant multiple times, and add the results. */
7907 tree utype, arg2, call1, call2;
7909 /* For now, we only cover the case where argsize is twice as large
7910 as 'long long'. */
7911 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7913 func = builtin_decl_explicit (parity
7914 ? BUILT_IN_PARITYLL
7915 : BUILT_IN_POPCOUNTLL);
7917 /* Convert it to an integer, and store into a variable. */
7918 utype = gfc_build_uint_type (argsize);
7919 arg = fold_convert (utype, arg);
7920 arg = gfc_evaluate_now (arg, &se->pre);
7922 /* Call the builtin twice. */
7923 call1 = build_call_expr_loc (input_location, func, 1,
7924 fold_convert (long_long_unsigned_type_node,
7925 arg));
7927 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
7928 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
7929 call2 = build_call_expr_loc (input_location, func, 1,
7930 fold_convert (long_long_unsigned_type_node,
7931 arg2));
7933 /* Combine the results. */
7934 if (parity)
7935 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR,
7936 integer_type_node, call1, call2);
7937 else
7938 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7939 integer_type_node, call1, call2);
7941 se->expr = convert (result_type, se->expr);
7942 return;
7945 /* Convert the actual argument twice: first, to the unsigned type of the
7946 same size; then, to the proper argument type for the built-in
7947 function. */
7948 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7949 arg = fold_convert (arg_type, arg);
7951 se->expr = fold_convert (result_type,
7952 build_call_expr_loc (input_location, func, 1, arg));
7956 /* Process an intrinsic with unspecified argument-types that has an optional
7957 argument (which could be of type character), e.g. EOSHIFT. For those, we
7958 need to append the string length of the optional argument if it is not
7959 present and the type is really character.
7960 primary specifies the position (starting at 1) of the non-optional argument
7961 specifying the type and optional gives the position of the optional
7962 argument in the arglist. */
7964 static void
7965 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
7966 unsigned primary, unsigned optional)
7968 gfc_actual_arglist* prim_arg;
7969 gfc_actual_arglist* opt_arg;
7970 unsigned cur_pos;
7971 gfc_actual_arglist* arg;
7972 gfc_symbol* sym;
7973 vec<tree, va_gc> *append_args;
7975 /* Find the two arguments given as position. */
7976 cur_pos = 0;
7977 prim_arg = NULL;
7978 opt_arg = NULL;
7979 for (arg = expr->value.function.actual; arg; arg = arg->next)
7981 ++cur_pos;
7983 if (cur_pos == primary)
7984 prim_arg = arg;
7985 if (cur_pos == optional)
7986 opt_arg = arg;
7988 if (cur_pos >= primary && cur_pos >= optional)
7989 break;
7991 gcc_assert (prim_arg);
7992 gcc_assert (prim_arg->expr);
7993 gcc_assert (opt_arg);
7995 /* If we do have type CHARACTER and the optional argument is really absent,
7996 append a dummy 0 as string length. */
7997 append_args = NULL;
7998 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
8000 tree dummy;
8002 dummy = build_int_cst (gfc_charlen_type_node, 0);
8003 vec_alloc (append_args, 1);
8004 append_args->quick_push (dummy);
8007 /* Build the call itself. */
8008 gcc_assert (!se->ignore_optional);
8009 sym = gfc_get_symbol_for_expr (expr, false);
8010 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
8011 append_args);
8012 gfc_free_symbol (sym);
8015 /* The length of a character string. */
8016 static void
8017 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
8019 tree len;
8020 tree type;
8021 tree decl;
8022 gfc_symbol *sym;
8023 gfc_se argse;
8024 gfc_expr *arg;
8026 gcc_assert (!se->ss);
8028 arg = expr->value.function.actual->expr;
8030 type = gfc_typenode_for_spec (&expr->ts);
8031 switch (arg->expr_type)
8033 case EXPR_CONSTANT:
8034 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
8035 break;
8037 case EXPR_ARRAY:
8038 /* Obtain the string length from the function used by
8039 trans-array.cc(gfc_trans_array_constructor). */
8040 len = NULL_TREE;
8041 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
8042 break;
8044 case EXPR_VARIABLE:
8045 if (arg->ref == NULL
8046 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
8048 /* This doesn't catch all cases.
8049 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
8050 and the surrounding thread. */
8051 sym = arg->symtree->n.sym;
8052 decl = gfc_get_symbol_decl (sym);
8053 if (decl == current_function_decl && sym->attr.function
8054 && (sym->result == sym))
8055 decl = gfc_get_fake_result_decl (sym, 0);
8057 len = sym->ts.u.cl->backend_decl;
8058 gcc_assert (len);
8059 break;
8062 /* Fall through. */
8064 default:
8065 gfc_init_se (&argse, se);
8066 if (arg->rank == 0)
8067 gfc_conv_expr (&argse, arg);
8068 else
8069 gfc_conv_expr_descriptor (&argse, arg);
8070 gfc_add_block_to_block (&se->pre, &argse.pre);
8071 gfc_add_block_to_block (&se->post, &argse.post);
8072 len = argse.string_length;
8073 break;
8075 se->expr = convert (type, len);
8078 /* The length of a character string not including trailing blanks. */
8079 static void
8080 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
8082 int kind = expr->value.function.actual->expr->ts.kind;
8083 tree args[2], type, fndecl;
8085 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8086 type = gfc_typenode_for_spec (&expr->ts);
8088 if (kind == 1)
8089 fndecl = gfor_fndecl_string_len_trim;
8090 else if (kind == 4)
8091 fndecl = gfor_fndecl_string_len_trim_char4;
8092 else
8093 gcc_unreachable ();
8095 se->expr = build_call_expr_loc (input_location,
8096 fndecl, 2, args[0], args[1]);
8097 se->expr = convert (type, se->expr);
8101 /* Returns the starting position of a substring within a string. */
8103 static void
8104 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
8105 tree function)
8107 tree logical4_type_node = gfc_get_logical_type (4);
8108 tree type;
8109 tree fndecl;
8110 tree *args;
8111 unsigned int num_args;
8113 args = XALLOCAVEC (tree, 5);
8115 /* Get number of arguments; characters count double due to the
8116 string length argument. Kind= is not passed to the library
8117 and thus ignored. */
8118 if (expr->value.function.actual->next->next->expr == NULL)
8119 num_args = 4;
8120 else
8121 num_args = 5;
8123 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8124 type = gfc_typenode_for_spec (&expr->ts);
8126 if (num_args == 4)
8127 args[4] = build_int_cst (logical4_type_node, 0);
8128 else
8129 args[4] = convert (logical4_type_node, args[4]);
8131 fndecl = build_addr (function);
8132 se->expr = build_call_array_loc (input_location,
8133 TREE_TYPE (TREE_TYPE (function)), fndecl,
8134 5, args);
8135 se->expr = convert (type, se->expr);
8139 /* The ascii value for a single character. */
8140 static void
8141 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
8143 tree args[3], type, pchartype;
8144 int nargs;
8146 nargs = gfc_intrinsic_argument_list_length (expr);
8147 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
8148 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
8149 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
8150 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
8151 type = gfc_typenode_for_spec (&expr->ts);
8153 se->expr = build_fold_indirect_ref_loc (input_location,
8154 args[1]);
8155 se->expr = convert (type, se->expr);
8159 /* Intrinsic ISNAN calls __builtin_isnan. */
8161 static void
8162 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
8164 tree arg;
8166 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8167 se->expr = build_call_expr_loc (input_location,
8168 builtin_decl_explicit (BUILT_IN_ISNAN),
8169 1, arg);
8170 STRIP_TYPE_NOPS (se->expr);
8171 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8175 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
8176 their argument against a constant integer value. */
8178 static void
8179 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
8181 tree arg;
8183 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8184 se->expr = fold_build2_loc (input_location, EQ_EXPR,
8185 gfc_typenode_for_spec (&expr->ts),
8186 arg, build_int_cst (TREE_TYPE (arg), value));
8191 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
8193 static void
8194 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
8196 tree tsource;
8197 tree fsource;
8198 tree mask;
8199 tree type;
8200 tree len, len2;
8201 tree *args;
8202 unsigned int num_args;
8204 num_args = gfc_intrinsic_argument_list_length (expr);
8205 args = XALLOCAVEC (tree, num_args);
8207 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8208 if (expr->ts.type != BT_CHARACTER)
8210 tsource = args[0];
8211 fsource = args[1];
8212 mask = args[2];
8214 else
8216 /* We do the same as in the non-character case, but the argument
8217 list is different because of the string length arguments. We
8218 also have to set the string length for the result. */
8219 len = args[0];
8220 tsource = args[1];
8221 len2 = args[2];
8222 fsource = args[3];
8223 mask = args[4];
8225 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
8226 &se->pre);
8227 se->string_length = len;
8229 tsource = gfc_evaluate_now (tsource, &se->pre);
8230 fsource = gfc_evaluate_now (fsource, &se->pre);
8231 mask = gfc_evaluate_now (mask, &se->pre);
8232 type = TREE_TYPE (tsource);
8233 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
8234 fold_convert (type, fsource));
8238 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
8240 static void
8241 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
8243 tree args[3], mask, type;
8245 gfc_conv_intrinsic_function_args (se, expr, args, 3);
8246 mask = gfc_evaluate_now (args[2], &se->pre);
8248 type = TREE_TYPE (args[0]);
8249 gcc_assert (TREE_TYPE (args[1]) == type);
8250 gcc_assert (TREE_TYPE (mask) == type);
8252 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
8253 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
8254 fold_build1_loc (input_location, BIT_NOT_EXPR,
8255 type, mask));
8256 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
8257 args[0], args[1]);
8261 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
8262 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
8264 static void
8265 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
8267 tree arg, allones, type, utype, res, cond, bitsize;
8268 int i;
8270 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8271 arg = gfc_evaluate_now (arg, &se->pre);
8273 type = gfc_get_int_type (expr->ts.kind);
8274 utype = unsigned_type_for (type);
8276 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
8277 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
8279 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
8280 build_int_cst (utype, 0));
8282 if (left)
8284 /* Left-justified mask. */
8285 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
8286 bitsize, arg);
8287 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
8288 fold_convert (utype, res));
8290 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
8291 smaller than type width. */
8292 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8293 build_int_cst (TREE_TYPE (arg), 0));
8294 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
8295 build_int_cst (utype, 0), res);
8297 else
8299 /* Right-justified mask. */
8300 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
8301 fold_convert (utype, arg));
8302 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
8304 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
8305 strictly smaller than type width. */
8306 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8307 arg, bitsize);
8308 res = fold_build3_loc (input_location, COND_EXPR, utype,
8309 cond, allones, res);
8312 se->expr = fold_convert (type, res);
8316 /* FRACTION (s) is translated into:
8317 isfinite (s) ? frexp (s, &dummy_int) : NaN */
8318 static void
8319 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
8321 tree arg, type, tmp, res, frexp, cond;
8323 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8325 type = gfc_typenode_for_spec (&expr->ts);
8326 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8327 arg = gfc_evaluate_now (arg, &se->pre);
8329 cond = build_call_expr_loc (input_location,
8330 builtin_decl_explicit (BUILT_IN_ISFINITE),
8331 1, arg);
8333 tmp = gfc_create_var (integer_type_node, NULL);
8334 res = build_call_expr_loc (input_location, frexp, 2,
8335 fold_convert (type, arg),
8336 gfc_build_addr_expr (NULL_TREE, tmp));
8337 res = fold_convert (type, res);
8339 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
8340 cond, res, gfc_build_nan (type, ""));
8344 /* NEAREST (s, dir) is translated into
8345 tmp = copysign (HUGE_VAL, dir);
8346 return nextafter (s, tmp);
8348 static void
8349 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
8351 tree args[2], type, tmp, nextafter, copysign, huge_val;
8353 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
8354 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
8356 type = gfc_typenode_for_spec (&expr->ts);
8357 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8359 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
8360 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
8361 fold_convert (type, args[1]));
8362 se->expr = build_call_expr_loc (input_location, nextafter, 2,
8363 fold_convert (type, args[0]), tmp);
8364 se->expr = fold_convert (type, se->expr);
8368 /* SPACING (s) is translated into
8369 int e;
8370 if (!isfinite (s))
8371 res = NaN;
8372 else if (s == 0)
8373 res = tiny;
8374 else
8376 frexp (s, &e);
8377 e = e - prec;
8378 e = MAX_EXPR (e, emin);
8379 res = scalbn (1., e);
8381 return res;
8383 where prec is the precision of s, gfc_real_kinds[k].digits,
8384 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
8385 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
8387 static void
8388 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
8390 tree arg, type, prec, emin, tiny, res, e;
8391 tree cond, nan, tmp, frexp, scalbn;
8392 int k;
8393 stmtblock_t block;
8395 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
8396 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
8397 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
8398 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
8400 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8401 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8403 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8404 arg = gfc_evaluate_now (arg, &se->pre);
8406 type = gfc_typenode_for_spec (&expr->ts);
8407 e = gfc_create_var (integer_type_node, NULL);
8408 res = gfc_create_var (type, NULL);
8411 /* Build the block for s /= 0. */
8412 gfc_start_block (&block);
8413 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
8414 gfc_build_addr_expr (NULL_TREE, e));
8415 gfc_add_expr_to_block (&block, tmp);
8417 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
8418 prec);
8419 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
8420 integer_type_node, tmp, emin));
8422 tmp = build_call_expr_loc (input_location, scalbn, 2,
8423 build_real_from_int_cst (type, integer_one_node), e);
8424 gfc_add_modify (&block, res, tmp);
8426 /* Finish by building the IF statement for value zero. */
8427 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8428 build_real_from_int_cst (type, integer_zero_node));
8429 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
8430 gfc_finish_block (&block));
8432 /* And deal with infinities and NaNs. */
8433 cond = build_call_expr_loc (input_location,
8434 builtin_decl_explicit (BUILT_IN_ISFINITE),
8435 1, arg);
8436 nan = gfc_build_nan (type, "");
8437 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
8439 gfc_add_expr_to_block (&se->pre, tmp);
8440 se->expr = res;
8444 /* RRSPACING (s) is translated into
8445 int e;
8446 real x;
8447 x = fabs (s);
8448 if (isfinite (x))
8450 if (x != 0)
8452 frexp (s, &e);
8453 x = scalbn (x, precision - e);
8456 else
8457 x = NaN;
8458 return x;
8460 where precision is gfc_real_kinds[k].digits. */
8462 static void
8463 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
8465 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
8466 int prec, k;
8467 stmtblock_t block;
8469 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
8470 prec = gfc_real_kinds[k].digits;
8472 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8473 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8474 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
8476 type = gfc_typenode_for_spec (&expr->ts);
8477 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8478 arg = gfc_evaluate_now (arg, &se->pre);
8480 e = gfc_create_var (integer_type_node, NULL);
8481 x = gfc_create_var (type, NULL);
8482 gfc_add_modify (&se->pre, x,
8483 build_call_expr_loc (input_location, fabs, 1, arg));
8486 gfc_start_block (&block);
8487 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
8488 gfc_build_addr_expr (NULL_TREE, e));
8489 gfc_add_expr_to_block (&block, tmp);
8491 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
8492 build_int_cst (integer_type_node, prec), e);
8493 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
8494 gfc_add_modify (&block, x, tmp);
8495 stmt = gfc_finish_block (&block);
8497 /* if (x != 0) */
8498 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
8499 build_real_from_int_cst (type, integer_zero_node));
8500 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
8502 /* And deal with infinities and NaNs. */
8503 cond = build_call_expr_loc (input_location,
8504 builtin_decl_explicit (BUILT_IN_ISFINITE),
8505 1, x);
8506 nan = gfc_build_nan (type, "");
8507 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
8509 gfc_add_expr_to_block (&se->pre, tmp);
8510 se->expr = fold_convert (type, x);
8514 /* SCALE (s, i) is translated into scalbn (s, i). */
8515 static void
8516 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
8518 tree args[2], type, scalbn;
8520 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8522 type = gfc_typenode_for_spec (&expr->ts);
8523 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8524 se->expr = build_call_expr_loc (input_location, scalbn, 2,
8525 fold_convert (type, args[0]),
8526 fold_convert (integer_type_node, args[1]));
8527 se->expr = fold_convert (type, se->expr);
8531 /* SET_EXPONENT (s, i) is translated into
8532 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
8533 static void
8534 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
8536 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
8538 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8539 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8541 type = gfc_typenode_for_spec (&expr->ts);
8542 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8543 args[0] = gfc_evaluate_now (args[0], &se->pre);
8545 tmp = gfc_create_var (integer_type_node, NULL);
8546 tmp = build_call_expr_loc (input_location, frexp, 2,
8547 fold_convert (type, args[0]),
8548 gfc_build_addr_expr (NULL_TREE, tmp));
8549 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
8550 fold_convert (integer_type_node, args[1]));
8551 res = fold_convert (type, res);
8553 /* Call to isfinite */
8554 cond = build_call_expr_loc (input_location,
8555 builtin_decl_explicit (BUILT_IN_ISFINITE),
8556 1, args[0]);
8557 nan = gfc_build_nan (type, "");
8559 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
8560 res, nan);
8564 static void
8565 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
8567 gfc_actual_arglist *actual;
8568 tree arg1;
8569 tree type;
8570 tree size;
8571 gfc_se argse;
8572 gfc_expr *e;
8573 gfc_symbol *sym = NULL;
8575 gfc_init_se (&argse, NULL);
8576 actual = expr->value.function.actual;
8578 if (actual->expr->ts.type == BT_CLASS)
8579 gfc_add_class_array_ref (actual->expr);
8581 e = actual->expr;
8583 /* These are emerging from the interface mapping, when a class valued
8584 function appears as the rhs in a realloc on assign statement, where
8585 the size of the result is that of one of the actual arguments. */
8586 if (e->expr_type == EXPR_VARIABLE
8587 && e->symtree->n.sym->ns == NULL /* This is distinctive! */
8588 && e->symtree->n.sym->ts.type == BT_CLASS
8589 && e->ref && e->ref->type == REF_COMPONENT
8590 && strcmp (e->ref->u.c.component->name, "_data") == 0)
8591 sym = e->symtree->n.sym;
8593 if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
8594 && e
8595 && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
8597 symbol_attribute attr;
8598 char *msg;
8599 tree temp;
8600 tree cond;
8602 if (e->symtree->n.sym && IS_CLASS_ARRAY (e->symtree->n.sym))
8604 attr = CLASS_DATA (e->symtree->n.sym)->attr;
8605 attr.pointer = attr.class_pointer;
8607 else
8608 attr = gfc_expr_attr (e);
8610 if (attr.allocatable)
8611 msg = xasprintf ("Allocatable argument '%s' is not allocated",
8612 e->symtree->n.sym->name);
8613 else if (attr.pointer)
8614 msg = xasprintf ("Pointer argument '%s' is not associated",
8615 e->symtree->n.sym->name);
8616 else
8617 goto end_arg_check;
8619 if (sym)
8621 temp = gfc_class_data_get (sym->backend_decl);
8622 temp = gfc_conv_descriptor_data_get (temp);
8624 else
8626 argse.descriptor_only = 1;
8627 gfc_conv_expr_descriptor (&argse, actual->expr);
8628 temp = gfc_conv_descriptor_data_get (argse.expr);
8631 cond = fold_build2_loc (input_location, EQ_EXPR,
8632 logical_type_node, temp,
8633 fold_convert (TREE_TYPE (temp),
8634 null_pointer_node));
8635 gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
8637 free (msg);
8639 end_arg_check:
8641 argse.data_not_needed = 1;
8642 if (gfc_is_class_array_function (e))
8644 /* For functions that return a class array conv_expr_descriptor is not
8645 able to get the descriptor right. Therefore this special case. */
8646 gfc_conv_expr_reference (&argse, e);
8647 argse.expr = gfc_class_data_get (argse.expr);
8649 else if (sym && sym->backend_decl)
8651 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
8652 argse.expr = gfc_class_data_get (sym->backend_decl);
8654 else
8655 gfc_conv_expr_descriptor (&argse, actual->expr);
8656 gfc_add_block_to_block (&se->pre, &argse.pre);
8657 gfc_add_block_to_block (&se->post, &argse.post);
8658 arg1 = argse.expr;
8660 actual = actual->next;
8661 if (actual->expr)
8663 stmtblock_t block;
8664 gfc_init_block (&block);
8665 gfc_init_se (&argse, NULL);
8666 gfc_conv_expr_type (&argse, actual->expr,
8667 gfc_array_index_type);
8668 gfc_add_block_to_block (&block, &argse.pre);
8669 tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8670 argse.expr, gfc_index_one_node);
8671 size = gfc_tree_array_size (&block, arg1, e, tmp);
8673 /* Unusually, for an intrinsic, size does not exclude
8674 an optional arg2, so we must test for it. */
8675 if (actual->expr->expr_type == EXPR_VARIABLE
8676 && actual->expr->symtree->n.sym->attr.dummy
8677 && actual->expr->symtree->n.sym->attr.optional)
8679 tree cond;
8680 stmtblock_t block2;
8681 gfc_init_block (&block2);
8682 gfc_init_se (&argse, NULL);
8683 argse.want_pointer = 1;
8684 argse.data_not_needed = 1;
8685 gfc_conv_expr (&argse, actual->expr);
8686 gfc_add_block_to_block (&se->pre, &argse.pre);
8687 /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8688 case; size_var can be used in both blocks. */
8689 tree size_var = gfc_create_var (TREE_TYPE (size), "size");
8690 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8691 TREE_TYPE (size_var), size_var, size);
8692 gfc_add_expr_to_block (&block, tmp);
8693 size = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
8694 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8695 TREE_TYPE (size_var), size_var, size);
8696 gfc_add_expr_to_block (&block2, tmp);
8697 cond = gfc_conv_expr_present (actual->expr->symtree->n.sym);
8698 tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
8699 gfc_finish_block (&block2));
8700 gfc_add_expr_to_block (&se->pre, tmp);
8701 size = size_var;
8703 else
8704 gfc_add_block_to_block (&se->pre, &block);
8706 else
8707 size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
8708 type = gfc_typenode_for_spec (&expr->ts);
8709 se->expr = convert (type, size);
8713 /* Helper function to compute the size of a character variable,
8714 excluding the terminating null characters. The result has
8715 gfc_array_index_type type. */
8717 tree
8718 size_of_string_in_bytes (int kind, tree string_length)
8720 tree bytesize;
8721 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
8723 bytesize = build_int_cst (gfc_array_index_type,
8724 gfc_character_kinds[i].bit_size / 8);
8726 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8727 bytesize,
8728 fold_convert (gfc_array_index_type, string_length));
8732 static void
8733 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
8735 gfc_expr *arg;
8736 gfc_se argse;
8737 tree source_bytes;
8738 tree tmp;
8739 tree lower;
8740 tree upper;
8741 tree byte_size;
8742 tree field;
8743 int n;
8745 gfc_init_se (&argse, NULL);
8746 arg = expr->value.function.actual->expr;
8748 if (arg->rank || arg->ts.type == BT_ASSUMED)
8749 gfc_conv_expr_descriptor (&argse, arg);
8750 else
8751 gfc_conv_expr_reference (&argse, arg);
8753 if (arg->ts.type == BT_ASSUMED)
8755 /* This only works if an array descriptor has been passed; thus, extract
8756 the size from the descriptor. */
8757 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
8758 == TYPE_PRECISION (size_type_node));
8759 tmp = arg->symtree->n.sym->backend_decl;
8760 tmp = DECL_LANG_SPECIFIC (tmp)
8761 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
8762 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
8763 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
8764 tmp = build_fold_indirect_ref_loc (input_location, tmp);
8766 tmp = gfc_conv_descriptor_dtype (tmp);
8767 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8768 GFC_DTYPE_ELEM_LEN);
8769 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
8770 tmp, field, NULL_TREE);
8772 byte_size = fold_convert (gfc_array_index_type, tmp);
8774 else if (arg->ts.type == BT_CLASS)
8776 /* Conv_expr_descriptor returns a component_ref to _data component of the
8777 class object. The class object may be a non-pointer object, e.g.
8778 located on the stack, or a memory location pointed to, e.g. a
8779 parameter, i.e., an indirect_ref. */
8780 if (POINTER_TYPE_P (TREE_TYPE (argse.expr))
8781 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse.expr))))
8782 byte_size
8783 = gfc_class_vtab_size_get (build_fold_indirect_ref (argse.expr));
8784 else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse.expr)))
8785 byte_size = gfc_class_vtab_size_get (argse.expr);
8786 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse.expr))
8787 && TREE_CODE (argse.expr) == COMPONENT_REF)
8788 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8789 else if (arg->rank > 0
8790 || (arg->rank == 0
8791 && arg->ref && arg->ref->type == REF_COMPONENT))
8793 /* The scalarizer added an additional temp. To get the class' vptr
8794 one has to look at the original backend_decl. */
8795 if (argse.class_container)
8796 byte_size = gfc_class_vtab_size_get (argse.class_container);
8797 else if (DECL_LANG_SPECIFIC (arg->symtree->n.sym->backend_decl))
8798 byte_size = gfc_class_vtab_size_get (
8799 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
8800 else
8801 gcc_unreachable ();
8803 else
8804 gcc_unreachable ();
8806 else
8808 if (arg->ts.type == BT_CHARACTER)
8809 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8810 else
8812 if (arg->rank == 0)
8813 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8814 argse.expr));
8815 else
8816 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
8817 byte_size = fold_convert (gfc_array_index_type,
8818 size_in_bytes (byte_size));
8822 if (arg->rank == 0)
8823 se->expr = byte_size;
8824 else
8826 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
8827 gfc_add_modify (&argse.pre, source_bytes, byte_size);
8829 if (arg->rank == -1)
8831 tree cond, loop_var, exit_label;
8832 stmtblock_t body;
8834 tmp = fold_convert (gfc_array_index_type,
8835 gfc_conv_descriptor_rank (argse.expr));
8836 loop_var = gfc_create_var (gfc_array_index_type, "i");
8837 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
8838 exit_label = gfc_build_label_decl (NULL_TREE);
8840 /* Create loop:
8841 for (;;)
8843 if (i >= rank)
8844 goto exit;
8845 source_bytes = source_bytes * array.dim[i].extent;
8846 i = i + 1;
8848 exit: */
8849 gfc_start_block (&body);
8850 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
8851 loop_var, tmp);
8852 tmp = build1_v (GOTO_EXPR, exit_label);
8853 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
8854 cond, tmp, build_empty_stmt (input_location));
8855 gfc_add_expr_to_block (&body, tmp);
8857 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
8858 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
8859 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8860 tmp = fold_build2_loc (input_location, MULT_EXPR,
8861 gfc_array_index_type, tmp, source_bytes);
8862 gfc_add_modify (&body, source_bytes, tmp);
8864 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8865 gfc_array_index_type, loop_var,
8866 gfc_index_one_node);
8867 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
8869 tmp = gfc_finish_block (&body);
8871 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
8872 tmp);
8873 gfc_add_expr_to_block (&argse.pre, tmp);
8875 tmp = build1_v (LABEL_EXPR, exit_label);
8876 gfc_add_expr_to_block (&argse.pre, tmp);
8878 else
8880 /* Obtain the size of the array in bytes. */
8881 for (n = 0; n < arg->rank; n++)
8883 tree idx;
8884 idx = gfc_rank_cst[n];
8885 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8886 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8887 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8888 tmp = fold_build2_loc (input_location, MULT_EXPR,
8889 gfc_array_index_type, tmp, source_bytes);
8890 gfc_add_modify (&argse.pre, source_bytes, tmp);
8893 se->expr = source_bytes;
8896 gfc_add_block_to_block (&se->pre, &argse.pre);
8900 static void
8901 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
8903 gfc_expr *arg;
8904 gfc_se argse;
8905 tree type, result_type, tmp, class_decl = NULL;
8906 gfc_symbol *sym;
8907 bool unlimited = false;
8909 arg = expr->value.function.actual->expr;
8911 gfc_init_se (&argse, NULL);
8912 result_type = gfc_get_int_type (expr->ts.kind);
8914 if (arg->rank == 0)
8916 if (arg->ts.type == BT_CLASS)
8918 unlimited = UNLIMITED_POLY (arg);
8919 gfc_add_vptr_component (arg);
8920 gfc_add_size_component (arg);
8921 gfc_conv_expr (&argse, arg);
8922 tmp = fold_convert (result_type, argse.expr);
8923 class_decl = gfc_get_class_from_expr (argse.expr);
8924 goto done;
8927 gfc_conv_expr_reference (&argse, arg);
8928 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8929 argse.expr));
8931 else
8933 argse.want_pointer = 0;
8934 gfc_conv_expr_descriptor (&argse, arg);
8935 sym = arg->expr_type == EXPR_VARIABLE ? arg->symtree->n.sym : NULL;
8936 if (arg->ts.type == BT_CLASS)
8938 unlimited = UNLIMITED_POLY (arg);
8939 if (TREE_CODE (argse.expr) == COMPONENT_REF)
8940 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8941 else if (arg->rank > 0 && sym
8942 && DECL_LANG_SPECIFIC (sym->backend_decl))
8943 tmp = gfc_class_vtab_size_get (
8944 GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl));
8945 else
8946 gcc_unreachable ();
8947 tmp = fold_convert (result_type, tmp);
8948 class_decl = gfc_get_class_from_expr (argse.expr);
8949 goto done;
8951 type = gfc_get_element_type (TREE_TYPE (argse.expr));
8954 /* Obtain the argument's word length. */
8955 if (arg->ts.type == BT_CHARACTER)
8956 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8957 else
8958 tmp = size_in_bytes (type);
8959 tmp = fold_convert (result_type, tmp);
8961 done:
8962 if (unlimited && class_decl)
8963 tmp = gfc_resize_class_size_with_len (NULL, class_decl, tmp);
8965 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
8966 build_int_cst (result_type, BITS_PER_UNIT));
8967 gfc_add_block_to_block (&se->pre, &argse.pre);
8971 /* Intrinsic string comparison functions. */
8973 static void
8974 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
8976 tree args[4];
8978 gfc_conv_intrinsic_function_args (se, expr, args, 4);
8980 se->expr
8981 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
8982 expr->value.function.actual->expr->ts.kind,
8983 op);
8984 se->expr = fold_build2_loc (input_location, op,
8985 gfc_typenode_for_spec (&expr->ts), se->expr,
8986 build_int_cst (TREE_TYPE (se->expr), 0));
8989 /* Generate a call to the adjustl/adjustr library function. */
8990 static void
8991 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
8993 tree args[3];
8994 tree len;
8995 tree type;
8996 tree var;
8997 tree tmp;
8999 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
9000 len = args[1];
9002 type = TREE_TYPE (args[2]);
9003 var = gfc_conv_string_tmp (se, type, len);
9004 args[0] = var;
9006 tmp = build_call_expr_loc (input_location,
9007 fndecl, 3, args[0], args[1], args[2]);
9008 gfc_add_expr_to_block (&se->pre, tmp);
9009 se->expr = var;
9010 se->string_length = len;
9014 /* Generate code for the TRANSFER intrinsic:
9015 For scalar results:
9016 DEST = TRANSFER (SOURCE, MOLD)
9017 where:
9018 typeof<DEST> = typeof<MOLD>
9019 and:
9020 MOLD is scalar.
9022 For array results:
9023 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
9024 where:
9025 typeof<DEST> = typeof<MOLD>
9026 and:
9027 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
9028 sizeof (DEST(0) * SIZE). */
9029 static void
9030 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
9032 tree tmp;
9033 tree tmpdecl;
9034 tree ptr;
9035 tree extent;
9036 tree source;
9037 tree source_type;
9038 tree source_bytes;
9039 tree mold_type;
9040 tree dest_word_len;
9041 tree size_words;
9042 tree size_bytes;
9043 tree upper;
9044 tree lower;
9045 tree stmt;
9046 tree class_ref = NULL_TREE;
9047 gfc_actual_arglist *arg;
9048 gfc_se argse;
9049 gfc_array_info *info;
9050 stmtblock_t block;
9051 int n;
9052 bool scalar_mold;
9053 gfc_expr *source_expr, *mold_expr, *class_expr;
9055 info = NULL;
9056 if (se->loop)
9057 info = &se->ss->info->data.array;
9059 /* Convert SOURCE. The output from this stage is:-
9060 source_bytes = length of the source in bytes
9061 source = pointer to the source data. */
9062 arg = expr->value.function.actual;
9063 source_expr = arg->expr;
9065 /* Ensure double transfer through LOGICAL preserves all
9066 the needed bits. */
9067 if (arg->expr->expr_type == EXPR_FUNCTION
9068 && arg->expr->value.function.esym == NULL
9069 && arg->expr->value.function.isym != NULL
9070 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
9071 && arg->expr->ts.type == BT_LOGICAL
9072 && expr->ts.type != arg->expr->ts.type)
9073 arg->expr->value.function.name = "__transfer_in_transfer";
9075 gfc_init_se (&argse, NULL);
9077 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
9079 /* Obtain the pointer to source and the length of source in bytes. */
9080 if (arg->expr->rank == 0)
9082 gfc_conv_expr_reference (&argse, arg->expr);
9083 if (arg->expr->ts.type == BT_CLASS)
9085 tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
9086 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
9088 source = gfc_class_data_get (tmp);
9089 class_ref = tmp;
9091 else
9093 /* Array elements are evaluated as a reference to the data.
9094 To obtain the vptr for the element size, the argument
9095 expression must be stripped to the class reference and
9096 re-evaluated. The pre and post blocks are not needed. */
9097 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
9098 source = argse.expr;
9099 class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
9100 gfc_init_se (&argse, NULL);
9101 gfc_conv_expr (&argse, class_expr);
9102 class_ref = argse.expr;
9105 else
9106 source = argse.expr;
9108 /* Obtain the source word length. */
9109 switch (arg->expr->ts.type)
9111 case BT_CHARACTER:
9112 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
9113 argse.string_length);
9114 break;
9115 case BT_CLASS:
9116 if (class_ref != NULL_TREE)
9118 tmp = gfc_class_vtab_size_get (class_ref);
9119 if (UNLIMITED_POLY (source_expr))
9120 tmp = gfc_resize_class_size_with_len (NULL, class_ref, tmp);
9122 else
9124 tmp = gfc_class_vtab_size_get (argse.expr);
9125 if (UNLIMITED_POLY (source_expr))
9126 tmp = gfc_resize_class_size_with_len (NULL, argse.expr, tmp);
9128 break;
9129 default:
9130 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
9131 source));
9132 tmp = fold_convert (gfc_array_index_type,
9133 size_in_bytes (source_type));
9134 break;
9137 else
9139 argse.want_pointer = 0;
9140 gfc_conv_expr_descriptor (&argse, arg->expr);
9141 source = gfc_conv_descriptor_data_get (argse.expr);
9142 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
9144 /* Repack the source if not simply contiguous. */
9145 if (!gfc_is_simply_contiguous (arg->expr, false, true))
9147 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
9149 if (warn_array_temporaries)
9150 gfc_warning (OPT_Warray_temporaries,
9151 "Creating array temporary at %L", &expr->where);
9153 source = build_call_expr_loc (input_location,
9154 gfor_fndecl_in_pack, 1, tmp);
9155 source = gfc_evaluate_now (source, &argse.pre);
9157 /* Free the temporary. */
9158 gfc_start_block (&block);
9159 tmp = gfc_call_free (source);
9160 gfc_add_expr_to_block (&block, tmp);
9161 stmt = gfc_finish_block (&block);
9163 /* Clean up if it was repacked. */
9164 gfc_init_block (&block);
9165 tmp = gfc_conv_array_data (argse.expr);
9166 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9167 source, tmp);
9168 tmp = build3_v (COND_EXPR, tmp, stmt,
9169 build_empty_stmt (input_location));
9170 gfc_add_expr_to_block (&block, tmp);
9171 gfc_add_block_to_block (&block, &se->post);
9172 gfc_init_block (&se->post);
9173 gfc_add_block_to_block (&se->post, &block);
9176 /* Obtain the source word length. */
9177 if (arg->expr->ts.type == BT_CHARACTER)
9178 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
9179 argse.string_length);
9180 else if (arg->expr->ts.type == BT_CLASS)
9182 class_ref = TREE_OPERAND (argse.expr, 0);
9183 tmp = gfc_class_vtab_size_get (class_ref);
9184 if (UNLIMITED_POLY (arg->expr))
9185 tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp);
9187 else
9188 tmp = fold_convert (gfc_array_index_type,
9189 size_in_bytes (source_type));
9191 /* Obtain the size of the array in bytes. */
9192 extent = gfc_create_var (gfc_array_index_type, NULL);
9193 for (n = 0; n < arg->expr->rank; n++)
9195 tree idx;
9196 idx = gfc_rank_cst[n];
9197 gfc_add_modify (&argse.pre, source_bytes, tmp);
9198 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
9199 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
9200 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9201 gfc_array_index_type, upper, lower);
9202 gfc_add_modify (&argse.pre, extent, tmp);
9203 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9204 gfc_array_index_type, extent,
9205 gfc_index_one_node);
9206 tmp = fold_build2_loc (input_location, MULT_EXPR,
9207 gfc_array_index_type, tmp, source_bytes);
9211 gfc_add_modify (&argse.pre, source_bytes, tmp);
9212 gfc_add_block_to_block (&se->pre, &argse.pre);
9213 gfc_add_block_to_block (&se->post, &argse.post);
9215 /* Now convert MOLD. The outputs are:
9216 mold_type = the TREE type of MOLD
9217 dest_word_len = destination word length in bytes. */
9218 arg = arg->next;
9219 mold_expr = arg->expr;
9221 gfc_init_se (&argse, NULL);
9223 scalar_mold = arg->expr->rank == 0;
9225 if (arg->expr->rank == 0)
9227 gfc_conv_expr_reference (&argse, mold_expr);
9228 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
9229 argse.expr));
9231 else
9233 argse.want_pointer = 0;
9234 gfc_conv_expr_descriptor (&argse, mold_expr);
9235 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
9238 gfc_add_block_to_block (&se->pre, &argse.pre);
9239 gfc_add_block_to_block (&se->post, &argse.post);
9241 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
9243 /* If this TRANSFER is nested in another TRANSFER, use a type
9244 that preserves all bits. */
9245 if (mold_expr->ts.type == BT_LOGICAL)
9246 mold_type = gfc_get_int_type (mold_expr->ts.kind);
9249 /* Obtain the destination word length. */
9250 switch (mold_expr->ts.type)
9252 case BT_CHARACTER:
9253 tmp = size_of_string_in_bytes (mold_expr->ts.kind, argse.string_length);
9254 mold_type = gfc_get_character_type_len (mold_expr->ts.kind,
9255 argse.string_length);
9256 break;
9257 case BT_CLASS:
9258 if (scalar_mold)
9259 class_ref = argse.expr;
9260 else
9261 class_ref = TREE_OPERAND (argse.expr, 0);
9262 tmp = gfc_class_vtab_size_get (class_ref);
9263 if (UNLIMITED_POLY (arg->expr))
9264 tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp);
9265 break;
9266 default:
9267 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
9268 break;
9271 /* Do not fix dest_word_len if it is a variable, since the temporary can wind
9272 up being used before the assignment. */
9273 if (mold_expr->ts.type == BT_CHARACTER && mold_expr->ts.deferred)
9274 dest_word_len = tmp;
9275 else
9277 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
9278 gfc_add_modify (&se->pre, dest_word_len, tmp);
9281 /* Finally convert SIZE, if it is present. */
9282 arg = arg->next;
9283 size_words = gfc_create_var (gfc_array_index_type, NULL);
9285 if (arg->expr)
9287 gfc_init_se (&argse, NULL);
9288 gfc_conv_expr_reference (&argse, arg->expr);
9289 tmp = convert (gfc_array_index_type,
9290 build_fold_indirect_ref_loc (input_location,
9291 argse.expr));
9292 gfc_add_block_to_block (&se->pre, &argse.pre);
9293 gfc_add_block_to_block (&se->post, &argse.post);
9295 else
9296 tmp = NULL_TREE;
9298 /* Separate array and scalar results. */
9299 if (scalar_mold && tmp == NULL_TREE)
9300 goto scalar_transfer;
9302 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
9303 if (tmp != NULL_TREE)
9304 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
9305 tmp, dest_word_len);
9306 else
9307 tmp = source_bytes;
9309 gfc_add_modify (&se->pre, size_bytes, tmp);
9310 gfc_add_modify (&se->pre, size_words,
9311 fold_build2_loc (input_location, CEIL_DIV_EXPR,
9312 gfc_array_index_type,
9313 size_bytes, dest_word_len));
9315 /* Evaluate the bounds of the result. If the loop range exists, we have
9316 to check if it is too large. If so, we modify loop->to be consistent
9317 with min(size, size(source)). Otherwise, size is made consistent with
9318 the loop range, so that the right number of bytes is transferred.*/
9319 n = se->loop->order[0];
9320 if (se->loop->to[n] != NULL_TREE)
9322 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9323 se->loop->to[n], se->loop->from[n]);
9324 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
9325 tmp, gfc_index_one_node);
9326 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
9327 tmp, size_words);
9328 gfc_add_modify (&se->pre, size_words, tmp);
9329 gfc_add_modify (&se->pre, size_bytes,
9330 fold_build2_loc (input_location, MULT_EXPR,
9331 gfc_array_index_type,
9332 size_words, dest_word_len));
9333 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
9334 size_words, se->loop->from[n]);
9335 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9336 upper, gfc_index_one_node);
9338 else
9340 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9341 size_words, gfc_index_one_node);
9342 se->loop->from[n] = gfc_index_zero_node;
9345 se->loop->to[n] = upper;
9347 /* Build a destination descriptor, using the pointer, source, as the
9348 data field. */
9349 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
9350 NULL_TREE, false, true, false, &expr->where);
9352 /* Cast the pointer to the result. */
9353 tmp = gfc_conv_descriptor_data_get (info->descriptor);
9354 tmp = fold_convert (pvoid_type_node, tmp);
9356 /* Use memcpy to do the transfer. */
9358 = build_call_expr_loc (input_location,
9359 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
9360 fold_convert (pvoid_type_node, source),
9361 fold_convert (size_type_node,
9362 fold_build2_loc (input_location,
9363 MIN_EXPR,
9364 gfc_array_index_type,
9365 size_bytes,
9366 source_bytes)));
9367 gfc_add_expr_to_block (&se->pre, tmp);
9369 se->expr = info->descriptor;
9370 if (expr->ts.type == BT_CHARACTER)
9372 tmp = fold_convert (gfc_charlen_type_node,
9373 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
9374 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
9375 gfc_charlen_type_node,
9376 dest_word_len, tmp);
9379 return;
9381 /* Deal with scalar results. */
9382 scalar_transfer:
9383 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
9384 dest_word_len, source_bytes);
9385 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
9386 extent, gfc_index_zero_node);
9388 if (expr->ts.type == BT_CHARACTER)
9390 tree direct, indirect, free;
9392 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
9393 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
9394 "transfer");
9396 /* If source is longer than the destination, use a pointer to
9397 the source directly. */
9398 gfc_init_block (&block);
9399 gfc_add_modify (&block, tmpdecl, ptr);
9400 direct = gfc_finish_block (&block);
9402 /* Otherwise, allocate a string with the length of the destination
9403 and copy the source into it. */
9404 gfc_init_block (&block);
9405 tmp = gfc_get_pchar_type (expr->ts.kind);
9406 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
9407 gfc_add_modify (&block, tmpdecl,
9408 fold_convert (TREE_TYPE (ptr), tmp));
9409 tmp = build_call_expr_loc (input_location,
9410 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
9411 fold_convert (pvoid_type_node, tmpdecl),
9412 fold_convert (pvoid_type_node, ptr),
9413 fold_convert (size_type_node, extent));
9414 gfc_add_expr_to_block (&block, tmp);
9415 indirect = gfc_finish_block (&block);
9417 /* Wrap it up with the condition. */
9418 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
9419 dest_word_len, source_bytes);
9420 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
9421 gfc_add_expr_to_block (&se->pre, tmp);
9423 /* Free the temporary string, if necessary. */
9424 free = gfc_call_free (tmpdecl);
9425 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9426 dest_word_len, source_bytes);
9427 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
9428 gfc_add_expr_to_block (&se->post, tmp);
9430 se->expr = tmpdecl;
9431 tmp = fold_convert (gfc_charlen_type_node,
9432 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
9433 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
9434 gfc_charlen_type_node,
9435 dest_word_len, tmp);
9437 else
9439 tmpdecl = gfc_create_var (mold_type, "transfer");
9441 ptr = convert (build_pointer_type (mold_type), source);
9443 /* For CLASS results, allocate the needed memory first. */
9444 if (mold_expr->ts.type == BT_CLASS)
9446 tree cdata;
9447 cdata = gfc_class_data_get (tmpdecl);
9448 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
9449 gfc_add_modify (&se->pre, cdata, tmp);
9452 /* Use memcpy to do the transfer. */
9453 if (mold_expr->ts.type == BT_CLASS)
9454 tmp = gfc_class_data_get (tmpdecl);
9455 else
9456 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
9458 tmp = build_call_expr_loc (input_location,
9459 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
9460 fold_convert (pvoid_type_node, tmp),
9461 fold_convert (pvoid_type_node, ptr),
9462 fold_convert (size_type_node, extent));
9463 gfc_add_expr_to_block (&se->pre, tmp);
9465 /* For CLASS results, set the _vptr. */
9466 if (mold_expr->ts.type == BT_CLASS)
9467 gfc_reset_vptr (&se->pre, nullptr, tmpdecl, source_expr->ts.u.derived);
9469 se->expr = tmpdecl;
9474 /* Generate a call to caf_is_present. */
9476 static tree
9477 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
9479 tree caf_reference, caf_decl, token, image_index;
9481 /* Compile the reference chain. */
9482 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
9483 gcc_assert (caf_reference != NULL_TREE);
9485 caf_decl = gfc_get_tree_for_caf_expr (expr);
9486 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9487 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9488 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
9489 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
9490 expr);
9492 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
9493 3, token, image_index, caf_reference);
9497 /* Test whether this ref-chain refs this image only. */
9499 static bool
9500 caf_this_image_ref (gfc_ref *ref)
9502 for ( ; ref; ref = ref->next)
9503 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
9504 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
9506 return false;
9510 /* Generate code for the ALLOCATED intrinsic.
9511 Generate inline code that directly check the address of the argument. */
9513 static void
9514 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
9516 gfc_se arg1se;
9517 tree tmp;
9518 bool coindexed_caf_comp = false;
9519 gfc_expr *e = expr->value.function.actual->expr;
9521 gfc_init_se (&arg1se, NULL);
9522 if (e->ts.type == BT_CLASS)
9524 /* Make sure that class array expressions have both a _data
9525 component reference and an array reference.... */
9526 if (CLASS_DATA (e)->attr.dimension)
9527 gfc_add_class_array_ref (e);
9528 /* .... whilst scalars only need the _data component. */
9529 else
9530 gfc_add_data_component (e);
9533 /* When 'e' references an allocatable component in a coarray, then call
9534 the caf-library function caf_is_present (). */
9535 if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
9536 && e->value.function.isym
9537 && e->value.function.isym->id == GFC_ISYM_CAF_GET)
9539 e = e->value.function.actual->expr;
9540 if (gfc_expr_attr (e).codimension)
9542 /* Last partref is the coindexed coarray. As coarrays are collectively
9543 (de)allocated, the allocation status must be the same as the one of
9544 the local allocation. Convert to local access. */
9545 for (gfc_ref *ref = e->ref; ref; ref = ref->next)
9546 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
9548 for (int i = ref->u.ar.dimen;
9549 i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
9550 ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
9551 break;
9554 else if (!caf_this_image_ref (e->ref))
9555 coindexed_caf_comp = true;
9557 if (coindexed_caf_comp)
9558 tmp = trans_caf_is_present (se, e);
9559 else
9561 if (e->rank == 0)
9563 /* Allocatable scalar. */
9564 arg1se.want_pointer = 1;
9565 gfc_conv_expr (&arg1se, e);
9566 tmp = arg1se.expr;
9568 else
9570 /* Allocatable array. */
9571 arg1se.descriptor_only = 1;
9572 gfc_conv_expr_descriptor (&arg1se, e);
9573 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
9576 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
9577 fold_convert (TREE_TYPE (tmp), null_pointer_node));
9580 /* Components of pointer array references sometimes come back with a pre block. */
9581 if (arg1se.pre.head)
9582 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9584 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9588 /* Generate code for the ASSOCIATED intrinsic.
9589 If both POINTER and TARGET are arrays, generate a call to library function
9590 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
9591 In other cases, generate inline code that directly compare the address of
9592 POINTER with the address of TARGET. */
9594 static void
9595 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
9597 gfc_actual_arglist *arg1;
9598 gfc_actual_arglist *arg2;
9599 gfc_se arg1se;
9600 gfc_se arg2se;
9601 tree tmp2;
9602 tree tmp;
9603 tree nonzero_arraylen = NULL_TREE;
9604 gfc_ss *ss;
9605 bool scalar;
9607 gfc_init_se (&arg1se, NULL);
9608 gfc_init_se (&arg2se, NULL);
9609 arg1 = expr->value.function.actual;
9610 arg2 = arg1->next;
9612 /* Check whether the expression is a scalar or not; we cannot use
9613 arg1->expr->rank as it can be nonzero for proc pointers. */
9614 ss = gfc_walk_expr (arg1->expr);
9615 scalar = ss == gfc_ss_terminator;
9616 if (!scalar)
9617 gfc_free_ss_chain (ss);
9619 if (!arg2->expr)
9621 /* No optional target. */
9622 if (scalar)
9624 /* A pointer to a scalar. */
9625 arg1se.want_pointer = 1;
9626 gfc_conv_expr (&arg1se, arg1->expr);
9627 if (arg1->expr->symtree->n.sym->attr.proc_pointer
9628 && arg1->expr->symtree->n.sym->attr.dummy)
9629 arg1se.expr = build_fold_indirect_ref_loc (input_location,
9630 arg1se.expr);
9631 if (arg1->expr->ts.type == BT_CLASS)
9633 tmp2 = gfc_class_data_get (arg1se.expr);
9634 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
9635 tmp2 = gfc_conv_descriptor_data_get (tmp2);
9637 else
9638 tmp2 = arg1se.expr;
9640 else
9642 /* A pointer to an array. */
9643 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
9644 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
9646 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9647 gfc_add_block_to_block (&se->post, &arg1se.post);
9648 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
9649 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
9650 se->expr = tmp;
9652 else
9654 /* An optional target. */
9655 if (arg2->expr->ts.type == BT_CLASS
9656 && arg2->expr->expr_type != EXPR_FUNCTION)
9657 gfc_add_data_component (arg2->expr);
9659 if (scalar)
9661 /* A pointer to a scalar. */
9662 arg1se.want_pointer = 1;
9663 gfc_conv_expr (&arg1se, arg1->expr);
9664 if (arg1->expr->symtree->n.sym->attr.proc_pointer
9665 && arg1->expr->symtree->n.sym->attr.dummy)
9666 arg1se.expr = build_fold_indirect_ref_loc (input_location,
9667 arg1se.expr);
9668 if (arg1->expr->ts.type == BT_CLASS)
9669 arg1se.expr = gfc_class_data_get (arg1se.expr);
9671 arg2se.want_pointer = 1;
9672 gfc_conv_expr (&arg2se, arg2->expr);
9673 if (arg2->expr->symtree->n.sym->attr.proc_pointer
9674 && arg2->expr->symtree->n.sym->attr.dummy)
9675 arg2se.expr = build_fold_indirect_ref_loc (input_location,
9676 arg2se.expr);
9677 if (arg2->expr->ts.type == BT_CLASS)
9679 arg2se.expr = gfc_evaluate_now (arg2se.expr, &arg2se.pre);
9680 arg2se.expr = gfc_class_data_get (arg2se.expr);
9682 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9683 gfc_add_block_to_block (&se->post, &arg1se.post);
9684 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9685 gfc_add_block_to_block (&se->post, &arg2se.post);
9686 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9687 arg1se.expr, arg2se.expr);
9688 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9689 arg1se.expr, null_pointer_node);
9690 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9691 logical_type_node, tmp, tmp2);
9693 else
9695 /* An array pointer of zero length is not associated if target is
9696 present. */
9697 arg1se.descriptor_only = 1;
9698 gfc_conv_expr_lhs (&arg1se, arg1->expr);
9699 if (arg1->expr->rank == -1)
9701 tmp = gfc_conv_descriptor_rank (arg1se.expr);
9702 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9703 TREE_TYPE (tmp), tmp,
9704 build_int_cst (TREE_TYPE (tmp), 1));
9706 else
9707 tmp = gfc_rank_cst[arg1->expr->rank - 1];
9708 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
9709 if (arg2->expr->rank != 0)
9710 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
9711 logical_type_node, tmp,
9712 build_int_cst (TREE_TYPE (tmp), 0));
9714 /* A pointer to an array, call library function _gfor_associated. */
9715 arg1se.want_pointer = 1;
9716 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
9717 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9718 gfc_add_block_to_block (&se->post, &arg1se.post);
9720 arg2se.want_pointer = 1;
9721 arg2se.force_no_tmp = 1;
9722 if (arg2->expr->rank != 0)
9723 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
9724 else
9726 gfc_conv_expr (&arg2se, arg2->expr);
9727 arg2se.expr
9728 = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
9729 gfc_expr_attr (arg2->expr));
9730 arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
9732 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9733 gfc_add_block_to_block (&se->post, &arg2se.post);
9734 se->expr = build_call_expr_loc (input_location,
9735 gfor_fndecl_associated, 2,
9736 arg1se.expr, arg2se.expr);
9737 se->expr = convert (logical_type_node, se->expr);
9738 if (arg2->expr->rank != 0)
9739 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9740 logical_type_node, se->expr,
9741 nonzero_arraylen);
9744 /* If target is present zero character length pointers cannot
9745 be associated. */
9746 if (arg1->expr->ts.type == BT_CHARACTER)
9748 tmp = arg1se.string_length;
9749 tmp = fold_build2_loc (input_location, NE_EXPR,
9750 logical_type_node, tmp,
9751 build_zero_cst (TREE_TYPE (tmp)));
9752 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9753 logical_type_node, se->expr, tmp);
9757 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9761 /* Generate code for the SAME_TYPE_AS intrinsic.
9762 Generate inline code that directly checks the vindices. */
9764 static void
9765 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
9767 gfc_expr *a, *b;
9768 gfc_se se1, se2;
9769 tree tmp;
9770 tree conda = NULL_TREE, condb = NULL_TREE;
9772 gfc_init_se (&se1, NULL);
9773 gfc_init_se (&se2, NULL);
9775 a = expr->value.function.actual->expr;
9776 b = expr->value.function.actual->next->expr;
9778 bool unlimited_poly_a = UNLIMITED_POLY (a);
9779 bool unlimited_poly_b = UNLIMITED_POLY (b);
9780 if (unlimited_poly_a)
9782 se1.want_pointer = 1;
9783 gfc_add_vptr_component (a);
9785 else if (a->ts.type == BT_CLASS)
9787 gfc_add_vptr_component (a);
9788 gfc_add_hash_component (a);
9790 else if (a->ts.type == BT_DERIVED)
9791 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9792 a->ts.u.derived->hash_value);
9794 if (unlimited_poly_b)
9796 se2.want_pointer = 1;
9797 gfc_add_vptr_component (b);
9799 else if (b->ts.type == BT_CLASS)
9801 gfc_add_vptr_component (b);
9802 gfc_add_hash_component (b);
9804 else if (b->ts.type == BT_DERIVED)
9805 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9806 b->ts.u.derived->hash_value);
9808 gfc_conv_expr (&se1, a);
9809 gfc_conv_expr (&se2, b);
9811 if (unlimited_poly_a)
9813 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9814 se1.expr,
9815 build_int_cst (TREE_TYPE (se1.expr), 0));
9816 se1.expr = gfc_vptr_hash_get (se1.expr);
9819 if (unlimited_poly_b)
9821 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9822 se2.expr,
9823 build_int_cst (TREE_TYPE (se2.expr), 0));
9824 se2.expr = gfc_vptr_hash_get (se2.expr);
9827 tmp = fold_build2_loc (input_location, EQ_EXPR,
9828 logical_type_node, se1.expr,
9829 fold_convert (TREE_TYPE (se1.expr), se2.expr));
9831 if (conda)
9832 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9833 logical_type_node, conda, tmp);
9835 if (condb)
9836 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9837 logical_type_node, condb, tmp);
9839 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9843 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9845 static void
9846 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
9848 tree args[2];
9850 gfc_conv_intrinsic_function_args (se, expr, args, 2);
9851 se->expr = build_call_expr_loc (input_location,
9852 gfor_fndecl_sc_kind, 2, args[0], args[1]);
9853 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9857 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9859 static void
9860 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
9862 tree arg, type;
9864 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9866 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
9867 type = gfc_get_int_type (4);
9868 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
9870 /* Convert it to the required type. */
9871 type = gfc_typenode_for_spec (&expr->ts);
9872 se->expr = build_call_expr_loc (input_location,
9873 gfor_fndecl_si_kind, 1, arg);
9874 se->expr = fold_convert (type, se->expr);
9878 /* Generate code for SELECTED_LOGICAL_KIND (BITS) intrinsic function. */
9880 static void
9881 gfc_conv_intrinsic_sl_kind (gfc_se *se, gfc_expr *expr)
9883 tree arg, type;
9885 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9887 /* The argument to SELECTED_LOGICAL_KIND is INTEGER(4). */
9888 type = gfc_get_int_type (4);
9889 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
9891 /* Convert it to the required type. */
9892 type = gfc_typenode_for_spec (&expr->ts);
9893 se->expr = build_call_expr_loc (input_location,
9894 gfor_fndecl_sl_kind, 1, arg);
9895 se->expr = fold_convert (type, se->expr);
9899 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
9901 static void
9902 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
9904 gfc_actual_arglist *actual;
9905 tree type;
9906 gfc_se argse;
9907 vec<tree, va_gc> *args = NULL;
9909 for (actual = expr->value.function.actual; actual; actual = actual->next)
9911 gfc_init_se (&argse, se);
9913 /* Pass a NULL pointer for an absent arg. */
9914 if (actual->expr == NULL)
9915 argse.expr = null_pointer_node;
9916 else
9918 gfc_typespec ts;
9919 gfc_clear_ts (&ts);
9921 if (actual->expr->ts.kind != gfc_c_int_kind)
9923 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9924 ts.type = BT_INTEGER;
9925 ts.kind = gfc_c_int_kind;
9926 gfc_convert_type (actual->expr, &ts, 2);
9928 gfc_conv_expr_reference (&argse, actual->expr);
9931 gfc_add_block_to_block (&se->pre, &argse.pre);
9932 gfc_add_block_to_block (&se->post, &argse.post);
9933 vec_safe_push (args, argse.expr);
9936 /* Convert it to the required type. */
9937 type = gfc_typenode_for_spec (&expr->ts);
9938 se->expr = build_call_expr_loc_vec (input_location,
9939 gfor_fndecl_sr_kind, args);
9940 se->expr = fold_convert (type, se->expr);
9944 /* Generate code for TRIM (A) intrinsic function. */
9946 static void
9947 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
9949 tree var;
9950 tree len;
9951 tree addr;
9952 tree tmp;
9953 tree cond;
9954 tree fndecl;
9955 tree function;
9956 tree *args;
9957 unsigned int num_args;
9959 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
9960 args = XALLOCAVEC (tree, num_args);
9962 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
9963 addr = gfc_build_addr_expr (ppvoid_type_node, var);
9964 len = gfc_create_var (gfc_charlen_type_node, "len");
9966 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
9967 args[0] = gfc_build_addr_expr (NULL_TREE, len);
9968 args[1] = addr;
9970 if (expr->ts.kind == 1)
9971 function = gfor_fndecl_string_trim;
9972 else if (expr->ts.kind == 4)
9973 function = gfor_fndecl_string_trim_char4;
9974 else
9975 gcc_unreachable ();
9977 fndecl = build_addr (function);
9978 tmp = build_call_array_loc (input_location,
9979 TREE_TYPE (TREE_TYPE (function)), fndecl,
9980 num_args, args);
9981 gfc_add_expr_to_block (&se->pre, tmp);
9983 /* Free the temporary afterwards, if necessary. */
9984 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9985 len, build_int_cst (TREE_TYPE (len), 0));
9986 tmp = gfc_call_free (var);
9987 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
9988 gfc_add_expr_to_block (&se->post, tmp);
9990 se->expr = var;
9991 se->string_length = len;
9995 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9997 static void
9998 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
10000 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
10001 tree type, cond, tmp, count, exit_label, n, max, largest;
10002 tree size;
10003 stmtblock_t block, body;
10004 int i;
10006 /* We store in charsize the size of a character. */
10007 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
10008 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
10010 /* Get the arguments. */
10011 gfc_conv_intrinsic_function_args (se, expr, args, 3);
10012 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
10013 src = args[1];
10014 ncopies = gfc_evaluate_now (args[2], &se->pre);
10015 ncopies_type = TREE_TYPE (ncopies);
10017 /* Check that NCOPIES is not negative. */
10018 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
10019 build_int_cst (ncopies_type, 0));
10020 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
10021 "Argument NCOPIES of REPEAT intrinsic is negative "
10022 "(its value is %ld)",
10023 fold_convert (long_integer_type_node, ncopies));
10025 /* If the source length is zero, any non negative value of NCOPIES
10026 is valid, and nothing happens. */
10027 n = gfc_create_var (ncopies_type, "ncopies");
10028 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
10029 size_zero_node);
10030 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
10031 build_int_cst (ncopies_type, 0), ncopies);
10032 gfc_add_modify (&se->pre, n, tmp);
10033 ncopies = n;
10035 /* Check that ncopies is not too large: ncopies should be less than
10036 (or equal to) MAX / slen, where MAX is the maximal integer of
10037 the gfc_charlen_type_node type. If slen == 0, we need a special
10038 case to avoid the division by zero. */
10039 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
10040 fold_convert (sizetype,
10041 TYPE_MAX_VALUE (gfc_charlen_type_node)),
10042 slen);
10043 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
10044 ? sizetype : ncopies_type;
10045 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
10046 fold_convert (largest, ncopies),
10047 fold_convert (largest, max));
10048 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
10049 size_zero_node);
10050 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
10051 logical_false_node, cond);
10052 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
10053 "Argument NCOPIES of REPEAT intrinsic is too large");
10055 /* Compute the destination length. */
10056 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
10057 fold_convert (gfc_charlen_type_node, slen),
10058 fold_convert (gfc_charlen_type_node, ncopies));
10059 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
10060 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
10062 /* Generate the code to do the repeat operation:
10063 for (i = 0; i < ncopies; i++)
10064 memmove (dest + (i * slen * size), src, slen*size); */
10065 gfc_start_block (&block);
10066 count = gfc_create_var (sizetype, "count");
10067 gfc_add_modify (&block, count, size_zero_node);
10068 exit_label = gfc_build_label_decl (NULL_TREE);
10070 /* Start the loop body. */
10071 gfc_start_block (&body);
10073 /* Exit the loop if count >= ncopies. */
10074 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
10075 fold_convert (sizetype, ncopies));
10076 tmp = build1_v (GOTO_EXPR, exit_label);
10077 TREE_USED (exit_label) = 1;
10078 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
10079 build_empty_stmt (input_location));
10080 gfc_add_expr_to_block (&body, tmp);
10082 /* Call memmove (dest + (i*slen*size), src, slen*size). */
10083 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
10084 count);
10085 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
10086 size);
10087 tmp = fold_build_pointer_plus_loc (input_location,
10088 fold_convert (pvoid_type_node, dest), tmp);
10089 tmp = build_call_expr_loc (input_location,
10090 builtin_decl_explicit (BUILT_IN_MEMMOVE),
10091 3, tmp, src,
10092 fold_build2_loc (input_location, MULT_EXPR,
10093 size_type_node, slen, size));
10094 gfc_add_expr_to_block (&body, tmp);
10096 /* Increment count. */
10097 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
10098 count, size_one_node);
10099 gfc_add_modify (&body, count, tmp);
10101 /* Build the loop. */
10102 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
10103 gfc_add_expr_to_block (&block, tmp);
10105 /* Add the exit label. */
10106 tmp = build1_v (LABEL_EXPR, exit_label);
10107 gfc_add_expr_to_block (&block, tmp);
10109 /* Finish the block. */
10110 tmp = gfc_finish_block (&block);
10111 gfc_add_expr_to_block (&se->pre, tmp);
10113 /* Set the result value. */
10114 se->expr = dest;
10115 se->string_length = dlen;
10119 /* Generate code for the IARGC intrinsic. */
10121 static void
10122 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
10124 tree tmp;
10125 tree fndecl;
10126 tree type;
10128 /* Call the library function. This always returns an INTEGER(4). */
10129 fndecl = gfor_fndecl_iargc;
10130 tmp = build_call_expr_loc (input_location,
10131 fndecl, 0);
10133 /* Convert it to the required type. */
10134 type = gfc_typenode_for_spec (&expr->ts);
10135 tmp = fold_convert (type, tmp);
10137 se->expr = tmp;
10141 /* Generate code for the KILL intrinsic. */
10143 static void
10144 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
10146 tree *args;
10147 tree int4_type_node = gfc_get_int_type (4);
10148 tree pid;
10149 tree sig;
10150 tree tmp;
10151 unsigned int num_args;
10153 num_args = gfc_intrinsic_argument_list_length (expr);
10154 args = XALLOCAVEC (tree, num_args);
10155 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
10157 /* Convert PID to a INTEGER(4) entity. */
10158 pid = convert (int4_type_node, args[0]);
10160 /* Convert SIG to a INTEGER(4) entity. */
10161 sig = convert (int4_type_node, args[1]);
10163 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
10165 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
10169 static tree
10170 conv_intrinsic_kill_sub (gfc_code *code)
10172 stmtblock_t block;
10173 gfc_se se, se_stat;
10174 tree int4_type_node = gfc_get_int_type (4);
10175 tree pid;
10176 tree sig;
10177 tree statp;
10178 tree tmp;
10180 /* Make the function call. */
10181 gfc_init_block (&block);
10182 gfc_init_se (&se, NULL);
10184 /* Convert PID to a INTEGER(4) entity. */
10185 gfc_conv_expr (&se, code->ext.actual->expr);
10186 gfc_add_block_to_block (&block, &se.pre);
10187 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
10188 gfc_add_block_to_block (&block, &se.post);
10190 /* Convert SIG to a INTEGER(4) entity. */
10191 gfc_conv_expr (&se, code->ext.actual->next->expr);
10192 gfc_add_block_to_block (&block, &se.pre);
10193 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
10194 gfc_add_block_to_block (&block, &se.post);
10196 /* Deal with an optional STATUS. */
10197 if (code->ext.actual->next->next->expr)
10199 gfc_init_se (&se_stat, NULL);
10200 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
10201 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
10203 else
10204 statp = NULL_TREE;
10206 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
10207 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
10209 gfc_add_expr_to_block (&block, tmp);
10211 if (statp && statp != se_stat.expr)
10212 gfc_add_modify (&block, se_stat.expr,
10213 fold_convert (TREE_TYPE (se_stat.expr), statp));
10215 return gfc_finish_block (&block);
10220 /* The loc intrinsic returns the address of its argument as
10221 gfc_index_integer_kind integer. */
10223 static void
10224 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
10226 tree temp_var;
10227 gfc_expr *arg_expr;
10229 gcc_assert (!se->ss);
10231 arg_expr = expr->value.function.actual->expr;
10232 if (arg_expr->rank == 0)
10234 if (arg_expr->ts.type == BT_CLASS)
10235 gfc_add_data_component (arg_expr);
10236 gfc_conv_expr_reference (se, arg_expr);
10238 else
10239 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
10240 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
10242 /* Create a temporary variable for loc return value. Without this,
10243 we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
10244 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
10245 gfc_add_modify (&se->pre, temp_var, se->expr);
10246 se->expr = temp_var;
10250 /* Specialized trim for f_c_string. */
10252 static void
10253 conv_trim (gfc_se *tse, gfc_se *str)
10255 tree cond, plen, pvar, tlen, ttmp, tvar;
10257 tlen = gfc_create_var (gfc_charlen_type_node, "tlen");
10258 plen = gfc_build_addr_expr (NULL_TREE, tlen);
10260 tvar = gfc_create_var (pchar_type_node, "tstr");
10261 pvar = gfc_build_addr_expr (ppvoid_type_node, tvar);
10263 ttmp = build_call_expr_loc (input_location, gfor_fndecl_string_trim, 4,
10264 plen, pvar, str->string_length, str->expr);
10266 gfc_add_expr_to_block (&tse->pre, ttmp);
10268 /* Free the temporary afterwards, if necessary. */
10269 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
10270 tlen, build_int_cst (TREE_TYPE (tlen), 0));
10271 ttmp = gfc_call_free (tvar);
10272 ttmp = build3_v (COND_EXPR, cond, ttmp, build_empty_stmt (input_location));
10273 gfc_add_expr_to_block (&tse->post, ttmp);
10275 tse->expr = tvar;
10276 tse->string_length = tlen;
10280 /* The following routine generates code for the intrinsic functions from
10281 the ISO_C_BINDING module: C_LOC, C_FUNLOC, C_ASSOCIATED, and
10282 F_C_STRING. */
10284 static void
10285 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
10287 gfc_actual_arglist *arg = expr->value.function.actual;
10289 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
10291 if (arg->expr->rank == 0)
10292 gfc_conv_expr_reference (se, arg->expr);
10293 else if (gfc_is_simply_contiguous (arg->expr, false, false))
10294 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
10295 else
10297 gfc_conv_expr_descriptor (se, arg->expr);
10298 se->expr = gfc_conv_descriptor_data_get (se->expr);
10301 /* TODO -- the following two lines shouldn't be necessary, but if
10302 they're removed, a bug is exposed later in the code path.
10303 This workaround was thus introduced, but will have to be
10304 removed; please see PR 35150 for details about the issue. */
10305 se->expr = convert (pvoid_type_node, se->expr);
10306 se->expr = gfc_evaluate_now (se->expr, &se->pre);
10308 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
10309 gfc_conv_expr_reference (se, arg->expr);
10310 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
10312 gfc_se arg1se;
10313 gfc_se arg2se;
10315 /* Build the addr_expr for the first argument. The argument is
10316 already an *address* so we don't need to set want_pointer in
10317 the gfc_se. */
10318 gfc_init_se (&arg1se, NULL);
10319 gfc_conv_expr (&arg1se, arg->expr);
10320 gfc_add_block_to_block (&se->pre, &arg1se.pre);
10321 gfc_add_block_to_block (&se->post, &arg1se.post);
10323 /* See if we were given two arguments. */
10324 if (arg->next->expr == NULL)
10325 /* Only given one arg so generate a null and do a
10326 not-equal comparison against the first arg. */
10327 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10328 arg1se.expr,
10329 fold_convert (TREE_TYPE (arg1se.expr),
10330 null_pointer_node));
10331 else
10333 tree eq_expr;
10334 tree not_null_expr;
10336 /* Given two arguments so build the arg2se from second arg. */
10337 gfc_init_se (&arg2se, NULL);
10338 gfc_conv_expr (&arg2se, arg->next->expr);
10339 gfc_add_block_to_block (&se->pre, &arg2se.pre);
10340 gfc_add_block_to_block (&se->post, &arg2se.post);
10342 /* Generate test to compare that the two args are equal. */
10343 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10344 arg1se.expr, arg2se.expr);
10345 /* Generate test to ensure that the first arg is not null. */
10346 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
10347 logical_type_node,
10348 arg1se.expr, null_pointer_node);
10350 /* Finally, the generated test must check that both arg1 is not
10351 NULL and that it is equal to the second arg. */
10352 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10353 logical_type_node,
10354 not_null_expr, eq_expr);
10357 else if (expr->value.function.isym->id == GFC_ISYM_F_C_STRING)
10359 /* There are three cases:
10360 f_c_string(string) -> trim(string) // c_null_char
10361 f_c_string(string, .false.) -> trim(string) // c_null_char
10362 f_c_string(string, .true.) -> string // c_null_char */
10364 gfc_se lse, rse, tse;
10365 tree len, tmp, var;
10366 gfc_expr *string = arg->expr;
10367 gfc_expr *asis = arg->next->expr;
10368 gfc_expr *cnc;
10370 /* Convert string. */
10371 gfc_init_se (&lse, se);
10372 gfc_conv_expr (&lse, string);
10373 gfc_conv_string_parameter (&lse);
10375 /* Create a string for C_NULL_CHAR and convert it. */
10376 cnc = gfc_get_character_expr (gfc_default_character_kind,
10377 &string->where, "\0", 1);
10378 gfc_init_se (&rse, se);
10379 gfc_conv_expr (&rse, cnc);
10380 gfc_conv_string_parameter (&rse);
10381 gfc_free_expr (cnc);
10383 #ifdef cnode
10384 #undef cnode
10385 #endif
10386 #define cnode gfc_charlen_type_node
10387 if (asis)
10389 stmtblock_t block;
10390 gfc_se asis_se, vse;
10391 tree elen, evar, tlen, tvar;
10392 tree else_branch, then_branch;
10394 elen = evar = tlen = tvar = NULL_TREE;
10396 /* f_c_string(string, .true.) -> string // c_null_char */
10398 gfc_init_block (&block);
10400 gfc_add_block_to_block (&block, &lse.pre);
10401 gfc_add_block_to_block (&block, &rse.pre);
10403 tlen = fold_build2_loc (input_location, PLUS_EXPR, cnode,
10404 fold_convert (cnode, lse.string_length),
10405 fold_convert (cnode, rse.string_length));
10407 gfc_init_se (&vse, se);
10408 tvar = gfc_conv_string_tmp (&vse, pchar_type_node, tlen);
10409 gfc_add_block_to_block (&block, &vse.pre);
10411 tmp = build_call_expr_loc (input_location, gfor_fndecl_concat_string,
10412 6, tlen, tvar,
10413 lse.string_length, lse.expr,
10414 rse.string_length, rse.expr);
10415 gfc_add_expr_to_block (&block, tmp);
10417 then_branch = gfc_finish_block (&block);
10419 /* f_c_string(string, .false.) = trim(string) // c_null_char */
10421 gfc_init_block (&block);
10423 gfc_init_se (&tse, se);
10424 conv_trim (&tse, &lse);
10425 gfc_add_block_to_block (&block, &tse.pre);
10426 gfc_add_block_to_block (&block, &rse.pre);
10428 elen = fold_build2_loc (input_location, PLUS_EXPR, cnode,
10429 fold_convert (cnode, tse.string_length),
10430 fold_convert (cnode, rse.string_length));
10432 gfc_init_se (&vse, se);
10433 evar = gfc_conv_string_tmp (&vse, pchar_type_node, elen);
10434 gfc_add_block_to_block (&block, &vse.pre);
10436 tmp = build_call_expr_loc (input_location, gfor_fndecl_concat_string,
10437 6, elen, evar,
10438 tse.string_length, tse.expr,
10439 rse.string_length, rse.expr);
10440 gfc_add_expr_to_block (&block, tmp);
10442 else_branch = gfc_finish_block (&block);
10444 gfc_init_se (&asis_se, se);
10445 gfc_conv_expr (&asis_se, asis);
10446 if (asis->expr_type == EXPR_VARIABLE
10447 && asis->symtree->n.sym->attr.dummy
10448 && asis->symtree->n.sym->attr.optional)
10450 tree present = gfc_conv_expr_present (asis->symtree->n.sym);
10451 asis_se.expr = build3_loc (input_location, COND_EXPR,
10452 logical_type_node, present,
10453 asis_se.expr,
10454 build_int_cst (logical_type_node, 0));
10456 gfc_add_block_to_block (&se->pre, &asis_se.pre);
10457 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
10458 asis_se.expr, then_branch, else_branch);
10460 gfc_add_expr_to_block (&se->pre, tmp);
10462 var = fold_build3_loc (input_location, COND_EXPR, pchar_type_node,
10463 asis_se.expr, tvar, evar);
10464 gfc_add_expr_to_block (&se->pre, var);
10466 len = fold_build3_loc (input_location, COND_EXPR, cnode,
10467 asis_se.expr, tlen, elen);
10468 gfc_add_expr_to_block (&se->pre, len);
10470 else
10472 /* f_c_string(string) = trim(string) // c_null_char */
10474 gfc_add_block_to_block (&se->pre, &lse.pre);
10475 gfc_add_block_to_block (&se->pre, &rse.pre);
10477 gfc_init_se (&tse, se);
10478 conv_trim (&tse, &lse);
10479 gfc_add_block_to_block (&se->pre, &tse.pre);
10480 gfc_add_block_to_block (&se->post, &tse.post);
10482 len = fold_build2_loc (input_location, PLUS_EXPR, cnode,
10483 fold_convert (cnode, tse.string_length),
10484 fold_convert (cnode, rse.string_length));
10486 var = gfc_conv_string_tmp (se, pchar_type_node, len);
10488 tmp = build_call_expr_loc (input_location, gfor_fndecl_concat_string,
10489 6, len, var,
10490 tse.string_length, tse.expr,
10491 rse.string_length, rse.expr);
10492 gfc_add_expr_to_block (&se->pre, tmp);
10495 se->expr = var;
10496 se->string_length = len;
10498 #undef cnode
10500 else
10501 gcc_unreachable ();
10505 /* The following routine generates code for the intrinsic
10506 subroutines from the ISO_C_BINDING module:
10507 * C_F_POINTER
10508 * C_F_PROCPOINTER. */
10510 static tree
10511 conv_isocbinding_subroutine (gfc_code *code)
10513 gfc_se se;
10514 gfc_se cptrse;
10515 gfc_se fptrse;
10516 gfc_se shapese;
10517 gfc_ss *shape_ss;
10518 tree desc, dim, tmp, stride, offset;
10519 stmtblock_t body, block;
10520 gfc_loopinfo loop;
10521 gfc_actual_arglist *arg = code->ext.actual;
10523 gfc_init_se (&se, NULL);
10524 gfc_init_se (&cptrse, NULL);
10525 gfc_conv_expr (&cptrse, arg->expr);
10526 gfc_add_block_to_block (&se.pre, &cptrse.pre);
10527 gfc_add_block_to_block (&se.post, &cptrse.post);
10529 gfc_init_se (&fptrse, NULL);
10530 if (arg->next->expr->rank == 0)
10532 fptrse.want_pointer = 1;
10533 gfc_conv_expr (&fptrse, arg->next->expr);
10534 gfc_add_block_to_block (&se.pre, &fptrse.pre);
10535 gfc_add_block_to_block (&se.post, &fptrse.post);
10536 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
10537 && arg->next->expr->symtree->n.sym->attr.dummy)
10538 fptrse.expr = build_fold_indirect_ref_loc (input_location,
10539 fptrse.expr);
10540 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
10541 TREE_TYPE (fptrse.expr),
10542 fptrse.expr,
10543 fold_convert (TREE_TYPE (fptrse.expr),
10544 cptrse.expr));
10545 gfc_add_expr_to_block (&se.pre, se.expr);
10546 gfc_add_block_to_block (&se.pre, &se.post);
10547 return gfc_finish_block (&se.pre);
10550 gfc_start_block (&block);
10552 /* Get the descriptor of the Fortran pointer. */
10553 fptrse.descriptor_only = 1;
10554 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
10555 gfc_add_block_to_block (&block, &fptrse.pre);
10556 desc = fptrse.expr;
10558 /* Set the span field. */
10559 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
10560 tmp = fold_convert (gfc_array_index_type, tmp);
10561 gfc_conv_descriptor_span_set (&block, desc, tmp);
10563 /* Set data value, dtype, and offset. */
10564 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
10565 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
10566 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
10567 gfc_get_dtype (TREE_TYPE (desc)));
10569 /* Start scalarization of the bounds, using the shape argument. */
10571 shape_ss = gfc_walk_expr (arg->next->next->expr);
10572 gcc_assert (shape_ss != gfc_ss_terminator);
10573 gfc_init_se (&shapese, NULL);
10575 gfc_init_loopinfo (&loop);
10576 gfc_add_ss_to_loop (&loop, shape_ss);
10577 gfc_conv_ss_startstride (&loop);
10578 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
10579 gfc_mark_ss_chain_used (shape_ss, 1);
10581 gfc_copy_loopinfo_to_se (&shapese, &loop);
10582 shapese.ss = shape_ss;
10584 stride = gfc_create_var (gfc_array_index_type, "stride");
10585 offset = gfc_create_var (gfc_array_index_type, "offset");
10586 gfc_add_modify (&block, stride, gfc_index_one_node);
10587 gfc_add_modify (&block, offset, gfc_index_zero_node);
10589 /* Loop body. */
10590 gfc_start_scalarized_body (&loop, &body);
10592 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
10593 loop.loopvar[0], loop.from[0]);
10595 /* Set bounds and stride. */
10596 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
10597 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
10599 gfc_conv_expr (&shapese, arg->next->next->expr);
10600 gfc_add_block_to_block (&body, &shapese.pre);
10601 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
10602 gfc_add_block_to_block (&body, &shapese.post);
10604 /* Calculate offset. */
10605 gfc_add_modify (&body, offset,
10606 fold_build2_loc (input_location, PLUS_EXPR,
10607 gfc_array_index_type, offset, stride));
10608 /* Update stride. */
10609 gfc_add_modify (&body, stride,
10610 fold_build2_loc (input_location, MULT_EXPR,
10611 gfc_array_index_type, stride,
10612 fold_convert (gfc_array_index_type,
10613 shapese.expr)));
10614 /* Finish scalarization loop. */
10615 gfc_trans_scalarizing_loops (&loop, &body);
10616 gfc_add_block_to_block (&block, &loop.pre);
10617 gfc_add_block_to_block (&block, &loop.post);
10618 gfc_add_block_to_block (&block, &fptrse.post);
10619 gfc_cleanup_loop (&loop);
10621 gfc_add_modify (&block, offset,
10622 fold_build1_loc (input_location, NEGATE_EXPR,
10623 gfc_array_index_type, offset));
10624 gfc_conv_descriptor_offset_set (&block, desc, offset);
10626 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
10627 gfc_add_block_to_block (&se.pre, &se.post);
10628 return gfc_finish_block (&se.pre);
10632 /* Save and restore floating-point state. */
10634 tree
10635 gfc_save_fp_state (stmtblock_t *block)
10637 tree type, fpstate, tmp;
10639 type = build_array_type (char_type_node,
10640 build_range_type (size_type_node, size_zero_node,
10641 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
10642 fpstate = gfc_create_var (type, "fpstate");
10643 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
10645 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
10646 1, fpstate);
10647 gfc_add_expr_to_block (block, tmp);
10649 return fpstate;
10653 void
10654 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
10656 tree tmp;
10658 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
10659 1, fpstate);
10660 gfc_add_expr_to_block (block, tmp);
10664 /* Generate code for arguments of IEEE functions. */
10666 static void
10667 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
10668 int nargs)
10670 gfc_actual_arglist *actual;
10671 gfc_expr *e;
10672 gfc_se argse;
10673 int arg;
10675 actual = expr->value.function.actual;
10676 for (arg = 0; arg < nargs; arg++, actual = actual->next)
10678 gcc_assert (actual);
10679 e = actual->expr;
10681 gfc_init_se (&argse, se);
10682 gfc_conv_expr_val (&argse, e);
10684 gfc_add_block_to_block (&se->pre, &argse.pre);
10685 gfc_add_block_to_block (&se->post, &argse.post);
10686 argarray[arg] = argse.expr;
10691 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE
10692 and IEEE_UNORDERED, which translate directly to GCC type-generic
10693 built-ins. */
10695 static void
10696 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
10697 enum built_in_function code, int nargs)
10699 tree args[2];
10700 gcc_assert ((unsigned) nargs <= ARRAY_SIZE (args));
10702 conv_ieee_function_args (se, expr, args, nargs);
10703 se->expr = build_call_expr_loc_array (input_location,
10704 builtin_decl_explicit (code),
10705 nargs, args);
10706 STRIP_TYPE_NOPS (se->expr);
10707 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10711 /* Generate code for intrinsics IEEE_SIGNBIT. */
10713 static void
10714 conv_intrinsic_ieee_signbit (gfc_se * se, gfc_expr * expr)
10716 tree arg, signbit;
10718 conv_ieee_function_args (se, expr, &arg, 1);
10719 signbit = build_call_expr_loc (input_location,
10720 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10721 1, arg);
10722 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10723 signbit, integer_zero_node);
10724 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), signbit);
10728 /* Generate code for IEEE_IS_NORMAL intrinsic:
10729 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
10731 static void
10732 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
10734 tree arg, isnormal, iszero;
10736 /* Convert arg, evaluate it only once. */
10737 conv_ieee_function_args (se, expr, &arg, 1);
10738 arg = gfc_evaluate_now (arg, &se->pre);
10740 isnormal = build_call_expr_loc (input_location,
10741 builtin_decl_explicit (BUILT_IN_ISNORMAL),
10742 1, arg);
10743 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
10744 build_real_from_int_cst (TREE_TYPE (arg),
10745 integer_zero_node));
10746 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10747 logical_type_node, isnormal, iszero);
10748 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10752 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
10753 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
10755 static void
10756 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
10758 tree arg, signbit, isnan;
10760 /* Convert arg, evaluate it only once. */
10761 conv_ieee_function_args (se, expr, &arg, 1);
10762 arg = gfc_evaluate_now (arg, &se->pre);
10764 isnan = build_call_expr_loc (input_location,
10765 builtin_decl_explicit (BUILT_IN_ISNAN),
10766 1, arg);
10767 STRIP_TYPE_NOPS (isnan);
10769 signbit = build_call_expr_loc (input_location,
10770 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10771 1, arg);
10772 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10773 signbit, integer_zero_node);
10775 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10776 logical_type_node, signbit,
10777 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
10778 TREE_TYPE(isnan), isnan));
10780 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10784 /* Generate code for IEEE_LOGB and IEEE_RINT. */
10786 static void
10787 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
10788 enum built_in_function code)
10790 tree arg, decl, call, fpstate;
10791 int argprec;
10793 conv_ieee_function_args (se, expr, &arg, 1);
10794 argprec = TYPE_PRECISION (TREE_TYPE (arg));
10795 decl = builtin_decl_for_precision (code, argprec);
10797 /* Save floating-point state. */
10798 fpstate = gfc_save_fp_state (&se->pre);
10800 /* Make the function call. */
10801 call = build_call_expr_loc (input_location, decl, 1, arg);
10802 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
10804 /* Restore floating-point state. */
10805 gfc_restore_fp_state (&se->post, fpstate);
10809 /* Generate code for IEEE_REM. */
10811 static void
10812 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
10814 tree args[2], decl, call, fpstate;
10815 int argprec;
10817 conv_ieee_function_args (se, expr, args, 2);
10819 /* If arguments have unequal size, convert them to the larger. */
10820 if (TYPE_PRECISION (TREE_TYPE (args[0]))
10821 > TYPE_PRECISION (TREE_TYPE (args[1])))
10822 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
10823 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
10824 > TYPE_PRECISION (TREE_TYPE (args[0])))
10825 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
10827 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10828 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
10830 /* Save floating-point state. */
10831 fpstate = gfc_save_fp_state (&se->pre);
10833 /* Make the function call. */
10834 call = build_call_expr_loc_array (input_location, decl, 2, args);
10835 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10837 /* Restore floating-point state. */
10838 gfc_restore_fp_state (&se->post, fpstate);
10842 /* Generate code for IEEE_NEXT_AFTER. */
10844 static void
10845 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
10847 tree args[2], decl, call, fpstate;
10848 int argprec;
10850 conv_ieee_function_args (se, expr, args, 2);
10852 /* Result has the characteristics of first argument. */
10853 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
10854 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10855 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
10857 /* Save floating-point state. */
10858 fpstate = gfc_save_fp_state (&se->pre);
10860 /* Make the function call. */
10861 call = build_call_expr_loc_array (input_location, decl, 2, args);
10862 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10864 /* Restore floating-point state. */
10865 gfc_restore_fp_state (&se->post, fpstate);
10869 /* Generate code for IEEE_SCALB. */
10871 static void
10872 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
10874 tree args[2], decl, call, huge, type;
10875 int argprec, n;
10877 conv_ieee_function_args (se, expr, args, 2);
10879 /* Result has the characteristics of first argument. */
10880 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10881 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
10883 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
10885 /* We need to fold the integer into the range of a C int. */
10886 args[1] = gfc_evaluate_now (args[1], &se->pre);
10887 type = TREE_TYPE (args[1]);
10889 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
10890 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
10891 gfc_c_int_kind);
10892 huge = fold_convert (type, huge);
10893 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
10894 huge);
10895 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
10896 fold_build1_loc (input_location, NEGATE_EXPR,
10897 type, huge));
10900 args[1] = fold_convert (integer_type_node, args[1]);
10902 /* Make the function call. */
10903 call = build_call_expr_loc_array (input_location, decl, 2, args);
10904 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10908 /* Generate code for IEEE_COPY_SIGN. */
10910 static void
10911 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
10913 tree args[2], decl, sign;
10914 int argprec;
10916 conv_ieee_function_args (se, expr, args, 2);
10918 /* Get the sign of the second argument. */
10919 sign = build_call_expr_loc (input_location,
10920 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10921 1, args[1]);
10922 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10923 sign, integer_zero_node);
10925 /* Create a value of one, with the right sign. */
10926 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
10927 sign,
10928 fold_build1_loc (input_location, NEGATE_EXPR,
10929 integer_type_node,
10930 integer_one_node),
10931 integer_one_node);
10932 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
10934 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10935 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
10937 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
10941 /* Generate code for IEEE_CLASS. */
10943 static void
10944 conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
10946 tree arg, c, t1, t2, t3, t4;
10948 /* Convert arg, evaluate it only once. */
10949 conv_ieee_function_args (se, expr, &arg, 1);
10950 arg = gfc_evaluate_now (arg, &se->pre);
10952 c = build_call_expr_loc (input_location,
10953 builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
10954 build_int_cst (integer_type_node, IEEE_QUIET_NAN),
10955 build_int_cst (integer_type_node,
10956 IEEE_POSITIVE_INF),
10957 build_int_cst (integer_type_node,
10958 IEEE_POSITIVE_NORMAL),
10959 build_int_cst (integer_type_node,
10960 IEEE_POSITIVE_DENORMAL),
10961 build_int_cst (integer_type_node,
10962 IEEE_POSITIVE_ZERO),
10963 arg);
10964 c = gfc_evaluate_now (c, &se->pre);
10965 t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10966 c, build_int_cst (integer_type_node,
10967 IEEE_QUIET_NAN));
10968 t2 = build_call_expr_loc (input_location,
10969 builtin_decl_explicit (BUILT_IN_ISSIGNALING), 1,
10970 arg);
10971 t2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10972 t2, build_zero_cst (TREE_TYPE (t2)));
10973 t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10974 logical_type_node, t1, t2);
10975 t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10976 c, build_int_cst (integer_type_node,
10977 IEEE_POSITIVE_ZERO));
10978 t4 = build_call_expr_loc (input_location,
10979 builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
10980 arg);
10981 t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10982 t4, build_zero_cst (TREE_TYPE (t4)));
10983 t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10984 logical_type_node, t3, t4);
10985 int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
10986 gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
10987 gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
10988 gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
10989 gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
10990 gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
10991 t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
10992 build_int_cst (TREE_TYPE (c), s), c);
10993 t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
10994 t3, t4, c);
10995 t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
10996 build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
10997 t3);
10998 tree type = gfc_typenode_for_spec (&expr->ts);
10999 /* Perform a quick sanity check that the return type is
11000 IEEE_CLASS_TYPE derived type defined in
11001 libgfortran/ieee/ieee_arithmetic.F90
11002 Primarily check that it is a derived type with a single
11003 member in it. */
11004 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
11005 tree field = NULL_TREE;
11006 for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
11007 if (TREE_CODE (f) == FIELD_DECL)
11009 gcc_assert (field == NULL_TREE);
11010 field = f;
11012 gcc_assert (field);
11013 t1 = fold_convert (TREE_TYPE (field), t1);
11014 se->expr = build_constructor_single (type, field, t1);
11018 /* Generate code for IEEE_VALUE. */
11020 static void
11021 conv_intrinsic_ieee_value (gfc_se *se, gfc_expr *expr)
11023 tree args[2], arg, ret, tmp;
11024 stmtblock_t body;
11026 /* Convert args, evaluate the second one only once. */
11027 conv_ieee_function_args (se, expr, args, 2);
11028 arg = gfc_evaluate_now (args[1], &se->pre);
11030 tree type = TREE_TYPE (arg);
11031 /* Perform a quick sanity check that the second argument's type is
11032 IEEE_CLASS_TYPE derived type defined in
11033 libgfortran/ieee/ieee_arithmetic.F90
11034 Primarily check that it is a derived type with a single
11035 member in it. */
11036 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
11037 tree field = NULL_TREE;
11038 for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
11039 if (TREE_CODE (f) == FIELD_DECL)
11041 gcc_assert (field == NULL_TREE);
11042 field = f;
11044 gcc_assert (field);
11045 arg = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
11046 arg, field, NULL_TREE);
11047 arg = gfc_evaluate_now (arg, &se->pre);
11049 type = gfc_typenode_for_spec (&expr->ts);
11050 gcc_assert (SCALAR_FLOAT_TYPE_P (type));
11051 ret = gfc_create_var (type, NULL);
11053 gfc_init_block (&body);
11055 tree end_label = gfc_build_label_decl (NULL_TREE);
11056 for (int c = IEEE_SIGNALING_NAN; c <= IEEE_POSITIVE_INF; ++c)
11058 tree label = gfc_build_label_decl (NULL_TREE);
11059 tree low = build_int_cst (TREE_TYPE (arg), c);
11060 tmp = build_case_label (low, low, label);
11061 gfc_add_expr_to_block (&body, tmp);
11063 REAL_VALUE_TYPE real;
11064 int k;
11065 switch (c)
11067 case IEEE_SIGNALING_NAN:
11068 real_nan (&real, "", 0, TYPE_MODE (type));
11069 break;
11070 case IEEE_QUIET_NAN:
11071 real_nan (&real, "", 1, TYPE_MODE (type));
11072 break;
11073 case IEEE_NEGATIVE_INF:
11074 real_inf (&real);
11075 real = real_value_negate (&real);
11076 break;
11077 case IEEE_NEGATIVE_NORMAL:
11078 real_from_integer (&real, TYPE_MODE (type), -42, SIGNED);
11079 break;
11080 case IEEE_NEGATIVE_DENORMAL:
11081 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
11082 real_from_mpfr (&real, gfc_real_kinds[k].tiny,
11083 type, GFC_RND_MODE);
11084 real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
11085 real = real_value_negate (&real);
11086 break;
11087 case IEEE_NEGATIVE_ZERO:
11088 real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
11089 real = real_value_negate (&real);
11090 break;
11091 case IEEE_POSITIVE_ZERO:
11092 /* Make this also the default: label. The other possibility
11093 would be to add a separate default: label followed by
11094 __builtin_unreachable (). */
11095 label = gfc_build_label_decl (NULL_TREE);
11096 tmp = build_case_label (NULL_TREE, NULL_TREE, label);
11097 gfc_add_expr_to_block (&body, tmp);
11098 real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
11099 break;
11100 case IEEE_POSITIVE_DENORMAL:
11101 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
11102 real_from_mpfr (&real, gfc_real_kinds[k].tiny,
11103 type, GFC_RND_MODE);
11104 real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
11105 break;
11106 case IEEE_POSITIVE_NORMAL:
11107 real_from_integer (&real, TYPE_MODE (type), 42, SIGNED);
11108 break;
11109 case IEEE_POSITIVE_INF:
11110 real_inf (&real);
11111 break;
11112 default:
11113 gcc_unreachable ();
11116 tree val = build_real (type, real);
11117 gfc_add_modify (&body, ret, val);
11119 tmp = build1_v (GOTO_EXPR, end_label);
11120 gfc_add_expr_to_block (&body, tmp);
11123 tmp = gfc_finish_block (&body);
11124 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, arg, tmp);
11125 gfc_add_expr_to_block (&se->pre, tmp);
11127 tmp = build1_v (LABEL_EXPR, end_label);
11128 gfc_add_expr_to_block (&se->pre, tmp);
11130 se->expr = ret;
11134 /* Generate code for IEEE_FMA. */
11136 static void
11137 conv_intrinsic_ieee_fma (gfc_se * se, gfc_expr * expr)
11139 tree args[3], decl, call;
11140 int argprec;
11142 conv_ieee_function_args (se, expr, args, 3);
11144 /* All three arguments should have the same type. */
11145 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[1])));
11146 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[2])));
11148 /* Call the type-generic FMA built-in. */
11149 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
11150 decl = builtin_decl_for_precision (BUILT_IN_FMA, argprec);
11151 call = build_call_expr_loc_array (input_location, decl, 3, args);
11153 /* Convert to the final type. */
11154 se->expr = fold_convert (TREE_TYPE (args[0]), call);
11158 /* Generate code for IEEE_{MIN,MAX}_NUM{,_MAG}. */
11160 static void
11161 conv_intrinsic_ieee_minmax (gfc_se * se, gfc_expr * expr, int max,
11162 const char *name)
11164 tree args[2], func;
11165 built_in_function fn;
11167 conv_ieee_function_args (se, expr, args, 2);
11168 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[1])));
11169 args[0] = gfc_evaluate_now (args[0], &se->pre);
11170 args[1] = gfc_evaluate_now (args[1], &se->pre);
11172 if (startswith (name, "mag"))
11174 /* IEEE_MIN_NUM_MAG and IEEE_MAX_NUM_MAG translate to C functions
11175 fminmag() and fmaxmag(), which do not exist as built-ins.
11177 Following glibc, we emit this:
11179 fminmag (x, y) {
11180 ax = ABS (x);
11181 ay = ABS (y);
11182 if (isless (ax, ay))
11183 return x;
11184 else if (isgreater (ax, ay))
11185 return y;
11186 else if (ax == ay)
11187 return x < y ? x : y;
11188 else if (issignaling (x) || issignaling (y))
11189 return x + y;
11190 else
11191 return isnan (y) ? x : y;
11194 fmaxmag (x, y) {
11195 ax = ABS (x);
11196 ay = ABS (y);
11197 if (isgreater (ax, ay))
11198 return x;
11199 else if (isless (ax, ay))
11200 return y;
11201 else if (ax == ay)
11202 return x > y ? x : y;
11203 else if (issignaling (x) || issignaling (y))
11204 return x + y;
11205 else
11206 return isnan (y) ? x : y;
11211 tree abs0, abs1, sig0, sig1;
11212 tree cond1, cond2, cond3, cond4, cond5;
11213 tree res;
11214 tree type = TREE_TYPE (args[0]);
11216 func = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
11217 abs0 = build_call_expr_loc (input_location, func, 1, args[0]);
11218 abs1 = build_call_expr_loc (input_location, func, 1, args[1]);
11219 abs0 = gfc_evaluate_now (abs0, &se->pre);
11220 abs1 = gfc_evaluate_now (abs1, &se->pre);
11222 cond5 = build_call_expr_loc (input_location,
11223 builtin_decl_explicit (BUILT_IN_ISNAN),
11224 1, args[1]);
11225 res = fold_build3_loc (input_location, COND_EXPR, type, cond5,
11226 args[0], args[1]);
11228 sig0 = build_call_expr_loc (input_location,
11229 builtin_decl_explicit (BUILT_IN_ISSIGNALING),
11230 1, args[0]);
11231 sig1 = build_call_expr_loc (input_location,
11232 builtin_decl_explicit (BUILT_IN_ISSIGNALING),
11233 1, args[1]);
11234 cond4 = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
11235 logical_type_node, sig0, sig1);
11236 res = fold_build3_loc (input_location, COND_EXPR, type, cond4,
11237 fold_build2_loc (input_location, PLUS_EXPR,
11238 type, args[0], args[1]),
11239 res);
11241 cond3 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
11242 abs0, abs1);
11243 res = fold_build3_loc (input_location, COND_EXPR, type, cond3,
11244 fold_build2_loc (input_location,
11245 max ? MAX_EXPR : MIN_EXPR,
11246 type, args[0], args[1]),
11247 res);
11249 func = builtin_decl_explicit (max ? BUILT_IN_ISLESS : BUILT_IN_ISGREATER);
11250 cond2 = build_call_expr_loc (input_location, func, 2, abs0, abs1);
11251 res = fold_build3_loc (input_location, COND_EXPR, type, cond2,
11252 args[1], res);
11254 func = builtin_decl_explicit (max ? BUILT_IN_ISGREATER : BUILT_IN_ISLESS);
11255 cond1 = build_call_expr_loc (input_location, func, 2, abs0, abs1);
11256 res = fold_build3_loc (input_location, COND_EXPR, type, cond1,
11257 args[0], res);
11259 se->expr = res;
11261 else
11263 /* IEEE_MIN_NUM and IEEE_MAX_NUM translate to fmin() and fmax(). */
11264 fn = max ? BUILT_IN_FMAX : BUILT_IN_FMIN;
11265 func = gfc_builtin_decl_for_float_kind (fn, expr->ts.kind);
11266 se->expr = build_call_expr_loc_array (input_location, func, 2, args);
11271 /* Generate code for comparison functions IEEE_QUIET_* and
11272 IEEE_SIGNALING_*. */
11274 static void
11275 conv_intrinsic_ieee_comparison (gfc_se * se, gfc_expr * expr, int signaling,
11276 const char *name)
11278 tree args[2];
11279 tree arg1, arg2, res;
11281 /* Evaluate arguments only once. */
11282 conv_ieee_function_args (se, expr, args, 2);
11283 arg1 = gfc_evaluate_now (args[0], &se->pre);
11284 arg2 = gfc_evaluate_now (args[1], &se->pre);
11286 if (startswith (name, "eq"))
11288 if (signaling)
11289 res = build_call_expr_loc (input_location,
11290 builtin_decl_explicit (BUILT_IN_ISEQSIG),
11291 2, arg1, arg2);
11292 else
11293 res = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
11294 arg1, arg2);
11296 else if (startswith (name, "ne"))
11298 if (signaling)
11300 res = build_call_expr_loc (input_location,
11301 builtin_decl_explicit (BUILT_IN_ISEQSIG),
11302 2, arg1, arg2);
11303 res = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
11304 logical_type_node, res);
11306 else
11307 res = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
11308 arg1, arg2);
11310 else if (startswith (name, "ge"))
11312 if (signaling)
11313 res = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
11314 arg1, arg2);
11315 else
11316 res = build_call_expr_loc (input_location,
11317 builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL),
11318 2, arg1, arg2);
11320 else if (startswith (name, "gt"))
11322 if (signaling)
11323 res = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
11324 arg1, arg2);
11325 else
11326 res = build_call_expr_loc (input_location,
11327 builtin_decl_explicit (BUILT_IN_ISGREATER),
11328 2, arg1, arg2);
11330 else if (startswith (name, "le"))
11332 if (signaling)
11333 res = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
11334 arg1, arg2);
11335 else
11336 res = build_call_expr_loc (input_location,
11337 builtin_decl_explicit (BUILT_IN_ISLESSEQUAL),
11338 2, arg1, arg2);
11340 else if (startswith (name, "lt"))
11342 if (signaling)
11343 res = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
11344 arg1, arg2);
11345 else
11346 res = build_call_expr_loc (input_location,
11347 builtin_decl_explicit (BUILT_IN_ISLESS),
11348 2, arg1, arg2);
11350 else
11351 gcc_unreachable ();
11353 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), res);
11357 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
11358 module. */
11360 bool
11361 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
11363 const char *name = expr->value.function.name;
11365 if (startswith (name, "_gfortran_ieee_is_nan"))
11366 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
11367 else if (startswith (name, "_gfortran_ieee_is_finite"))
11368 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
11369 else if (startswith (name, "_gfortran_ieee_unordered"))
11370 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
11371 else if (startswith (name, "_gfortran_ieee_signbit"))
11372 conv_intrinsic_ieee_signbit (se, expr);
11373 else if (startswith (name, "_gfortran_ieee_is_normal"))
11374 conv_intrinsic_ieee_is_normal (se, expr);
11375 else if (startswith (name, "_gfortran_ieee_is_negative"))
11376 conv_intrinsic_ieee_is_negative (se, expr);
11377 else if (startswith (name, "_gfortran_ieee_copy_sign"))
11378 conv_intrinsic_ieee_copy_sign (se, expr);
11379 else if (startswith (name, "_gfortran_ieee_scalb"))
11380 conv_intrinsic_ieee_scalb (se, expr);
11381 else if (startswith (name, "_gfortran_ieee_next_after"))
11382 conv_intrinsic_ieee_next_after (se, expr);
11383 else if (startswith (name, "_gfortran_ieee_rem"))
11384 conv_intrinsic_ieee_rem (se, expr);
11385 else if (startswith (name, "_gfortran_ieee_logb"))
11386 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
11387 else if (startswith (name, "_gfortran_ieee_rint"))
11388 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
11389 else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
11390 conv_intrinsic_ieee_class (se, expr);
11391 else if (startswith (name, "ieee_value_") && ISDIGIT (name[11]))
11392 conv_intrinsic_ieee_value (se, expr);
11393 else if (startswith (name, "_gfortran_ieee_fma"))
11394 conv_intrinsic_ieee_fma (se, expr);
11395 else if (startswith (name, "_gfortran_ieee_min_num_"))
11396 conv_intrinsic_ieee_minmax (se, expr, 0, name + 23);
11397 else if (startswith (name, "_gfortran_ieee_max_num_"))
11398 conv_intrinsic_ieee_minmax (se, expr, 1, name + 23);
11399 else if (startswith (name, "_gfortran_ieee_quiet_"))
11400 conv_intrinsic_ieee_comparison (se, expr, 0, name + 21);
11401 else if (startswith (name, "_gfortran_ieee_signaling_"))
11402 conv_intrinsic_ieee_comparison (se, expr, 1, name + 25);
11403 else
11404 /* It is not among the functions we translate directly. We return
11405 false, so a library function call is emitted. */
11406 return false;
11408 return true;
11412 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
11414 static void
11415 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
11417 tree arg, res, restype;
11419 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
11420 arg = fold_convert (size_type_node, arg);
11421 res = build_call_expr_loc (input_location,
11422 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
11423 restype = gfc_typenode_for_spec (&expr->ts);
11424 se->expr = fold_convert (restype, res);
11428 /* Generate code for an intrinsic function. Some map directly to library
11429 calls, others get special handling. In some cases the name of the function
11430 used depends on the type specifiers. */
11432 void
11433 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
11435 const char *name;
11436 int lib, kind;
11437 tree fndecl;
11439 name = &expr->value.function.name[2];
11441 if (expr->rank > 0)
11443 lib = gfc_is_intrinsic_libcall (expr);
11444 if (lib != 0)
11446 if (lib == 1)
11447 se->ignore_optional = 1;
11449 switch (expr->value.function.isym->id)
11451 case GFC_ISYM_EOSHIFT:
11452 case GFC_ISYM_PACK:
11453 case GFC_ISYM_RESHAPE:
11454 /* For all of those the first argument specifies the type and the
11455 third is optional. */
11456 conv_generic_with_optional_char_arg (se, expr, 1, 3);
11457 break;
11459 case GFC_ISYM_FINDLOC:
11460 gfc_conv_intrinsic_findloc (se, expr);
11461 break;
11463 case GFC_ISYM_MINLOC:
11464 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
11465 break;
11467 case GFC_ISYM_MAXLOC:
11468 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
11469 break;
11471 default:
11472 gfc_conv_intrinsic_funcall (se, expr);
11473 break;
11476 return;
11480 switch (expr->value.function.isym->id)
11482 case GFC_ISYM_NONE:
11483 gcc_unreachable ();
11485 case GFC_ISYM_REPEAT:
11486 gfc_conv_intrinsic_repeat (se, expr);
11487 break;
11489 case GFC_ISYM_TRIM:
11490 gfc_conv_intrinsic_trim (se, expr);
11491 break;
11493 case GFC_ISYM_SC_KIND:
11494 gfc_conv_intrinsic_sc_kind (se, expr);
11495 break;
11497 case GFC_ISYM_SI_KIND:
11498 gfc_conv_intrinsic_si_kind (se, expr);
11499 break;
11501 case GFC_ISYM_SL_KIND:
11502 gfc_conv_intrinsic_sl_kind (se, expr);
11503 break;
11505 case GFC_ISYM_SR_KIND:
11506 gfc_conv_intrinsic_sr_kind (se, expr);
11507 break;
11509 case GFC_ISYM_EXPONENT:
11510 gfc_conv_intrinsic_exponent (se, expr);
11511 break;
11513 case GFC_ISYM_SCAN:
11514 kind = expr->value.function.actual->expr->ts.kind;
11515 if (kind == 1)
11516 fndecl = gfor_fndecl_string_scan;
11517 else if (kind == 4)
11518 fndecl = gfor_fndecl_string_scan_char4;
11519 else
11520 gcc_unreachable ();
11522 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11523 break;
11525 case GFC_ISYM_VERIFY:
11526 kind = expr->value.function.actual->expr->ts.kind;
11527 if (kind == 1)
11528 fndecl = gfor_fndecl_string_verify;
11529 else if (kind == 4)
11530 fndecl = gfor_fndecl_string_verify_char4;
11531 else
11532 gcc_unreachable ();
11534 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11535 break;
11537 case GFC_ISYM_ALLOCATED:
11538 gfc_conv_allocated (se, expr);
11539 break;
11541 case GFC_ISYM_ASSOCIATED:
11542 gfc_conv_associated(se, expr);
11543 break;
11545 case GFC_ISYM_SAME_TYPE_AS:
11546 gfc_conv_same_type_as (se, expr);
11547 break;
11549 case GFC_ISYM_ABS:
11550 gfc_conv_intrinsic_abs (se, expr);
11551 break;
11553 case GFC_ISYM_ADJUSTL:
11554 if (expr->ts.kind == 1)
11555 fndecl = gfor_fndecl_adjustl;
11556 else if (expr->ts.kind == 4)
11557 fndecl = gfor_fndecl_adjustl_char4;
11558 else
11559 gcc_unreachable ();
11561 gfc_conv_intrinsic_adjust (se, expr, fndecl);
11562 break;
11564 case GFC_ISYM_ADJUSTR:
11565 if (expr->ts.kind == 1)
11566 fndecl = gfor_fndecl_adjustr;
11567 else if (expr->ts.kind == 4)
11568 fndecl = gfor_fndecl_adjustr_char4;
11569 else
11570 gcc_unreachable ();
11572 gfc_conv_intrinsic_adjust (se, expr, fndecl);
11573 break;
11575 case GFC_ISYM_AIMAG:
11576 gfc_conv_intrinsic_imagpart (se, expr);
11577 break;
11579 case GFC_ISYM_AINT:
11580 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
11581 break;
11583 case GFC_ISYM_ALL:
11584 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
11585 break;
11587 case GFC_ISYM_ANINT:
11588 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
11589 break;
11591 case GFC_ISYM_AND:
11592 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
11593 break;
11595 case GFC_ISYM_ANY:
11596 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
11597 break;
11599 case GFC_ISYM_ACOSD:
11600 case GFC_ISYM_ASIND:
11601 case GFC_ISYM_ATAND:
11602 gfc_conv_intrinsic_atrigd (se, expr, expr->value.function.isym->id);
11603 break;
11605 case GFC_ISYM_COTAN:
11606 gfc_conv_intrinsic_cotan (se, expr);
11607 break;
11609 case GFC_ISYM_COTAND:
11610 gfc_conv_intrinsic_cotand (se, expr);
11611 break;
11613 case GFC_ISYM_ATAN2D:
11614 gfc_conv_intrinsic_atan2d (se, expr);
11615 break;
11617 case GFC_ISYM_BTEST:
11618 gfc_conv_intrinsic_btest (se, expr);
11619 break;
11621 case GFC_ISYM_BGE:
11622 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
11623 break;
11625 case GFC_ISYM_BGT:
11626 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
11627 break;
11629 case GFC_ISYM_BLE:
11630 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
11631 break;
11633 case GFC_ISYM_BLT:
11634 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
11635 break;
11637 case GFC_ISYM_C_ASSOCIATED:
11638 case GFC_ISYM_C_FUNLOC:
11639 case GFC_ISYM_C_LOC:
11640 case GFC_ISYM_F_C_STRING:
11641 conv_isocbinding_function (se, expr);
11642 break;
11644 case GFC_ISYM_ACHAR:
11645 case GFC_ISYM_CHAR:
11646 gfc_conv_intrinsic_char (se, expr);
11647 break;
11649 case GFC_ISYM_CONVERSION:
11650 case GFC_ISYM_DBLE:
11651 case GFC_ISYM_DFLOAT:
11652 case GFC_ISYM_FLOAT:
11653 case GFC_ISYM_LOGICAL:
11654 case GFC_ISYM_REAL:
11655 case GFC_ISYM_REALPART:
11656 case GFC_ISYM_SNGL:
11657 gfc_conv_intrinsic_conversion (se, expr);
11658 break;
11660 /* Integer conversions are handled separately to make sure we get the
11661 correct rounding mode. */
11662 case GFC_ISYM_INT:
11663 case GFC_ISYM_INT2:
11664 case GFC_ISYM_INT8:
11665 case GFC_ISYM_LONG:
11666 case GFC_ISYM_UINT:
11667 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
11668 break;
11670 case GFC_ISYM_NINT:
11671 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
11672 break;
11674 case GFC_ISYM_CEILING:
11675 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
11676 break;
11678 case GFC_ISYM_FLOOR:
11679 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
11680 break;
11682 case GFC_ISYM_MOD:
11683 gfc_conv_intrinsic_mod (se, expr, 0);
11684 break;
11686 case GFC_ISYM_MODULO:
11687 gfc_conv_intrinsic_mod (se, expr, 1);
11688 break;
11690 case GFC_ISYM_CAF_GET:
11691 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, false, NULL);
11692 break;
11694 case GFC_ISYM_CMPLX:
11695 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
11696 break;
11698 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
11699 gfc_conv_intrinsic_iargc (se, expr);
11700 break;
11702 case GFC_ISYM_COMPLEX:
11703 gfc_conv_intrinsic_cmplx (se, expr, 1);
11704 break;
11706 case GFC_ISYM_CONJG:
11707 gfc_conv_intrinsic_conjg (se, expr);
11708 break;
11710 case GFC_ISYM_COUNT:
11711 gfc_conv_intrinsic_count (se, expr);
11712 break;
11714 case GFC_ISYM_CTIME:
11715 gfc_conv_intrinsic_ctime (se, expr);
11716 break;
11718 case GFC_ISYM_DIM:
11719 gfc_conv_intrinsic_dim (se, expr);
11720 break;
11722 case GFC_ISYM_DOT_PRODUCT:
11723 gfc_conv_intrinsic_dot_product (se, expr);
11724 break;
11726 case GFC_ISYM_DPROD:
11727 gfc_conv_intrinsic_dprod (se, expr);
11728 break;
11730 case GFC_ISYM_DSHIFTL:
11731 gfc_conv_intrinsic_dshift (se, expr, true);
11732 break;
11734 case GFC_ISYM_DSHIFTR:
11735 gfc_conv_intrinsic_dshift (se, expr, false);
11736 break;
11738 case GFC_ISYM_FDATE:
11739 gfc_conv_intrinsic_fdate (se, expr);
11740 break;
11742 case GFC_ISYM_FRACTION:
11743 gfc_conv_intrinsic_fraction (se, expr);
11744 break;
11746 case GFC_ISYM_IALL:
11747 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
11748 break;
11750 case GFC_ISYM_IAND:
11751 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
11752 break;
11754 case GFC_ISYM_IANY:
11755 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
11756 break;
11758 case GFC_ISYM_IBCLR:
11759 gfc_conv_intrinsic_singlebitop (se, expr, 0);
11760 break;
11762 case GFC_ISYM_IBITS:
11763 gfc_conv_intrinsic_ibits (se, expr);
11764 break;
11766 case GFC_ISYM_IBSET:
11767 gfc_conv_intrinsic_singlebitop (se, expr, 1);
11768 break;
11770 case GFC_ISYM_IACHAR:
11771 case GFC_ISYM_ICHAR:
11772 /* We assume ASCII character sequence. */
11773 gfc_conv_intrinsic_ichar (se, expr);
11774 break;
11776 case GFC_ISYM_IARGC:
11777 gfc_conv_intrinsic_iargc (se, expr);
11778 break;
11780 case GFC_ISYM_IEOR:
11781 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
11782 break;
11784 case GFC_ISYM_INDEX:
11785 kind = expr->value.function.actual->expr->ts.kind;
11786 if (kind == 1)
11787 fndecl = gfor_fndecl_string_index;
11788 else if (kind == 4)
11789 fndecl = gfor_fndecl_string_index_char4;
11790 else
11791 gcc_unreachable ();
11793 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11794 break;
11796 case GFC_ISYM_IOR:
11797 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
11798 break;
11800 case GFC_ISYM_IPARITY:
11801 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
11802 break;
11804 case GFC_ISYM_IS_IOSTAT_END:
11805 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
11806 break;
11808 case GFC_ISYM_IS_IOSTAT_EOR:
11809 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
11810 break;
11812 case GFC_ISYM_IS_CONTIGUOUS:
11813 gfc_conv_intrinsic_is_contiguous (se, expr);
11814 break;
11816 case GFC_ISYM_ISNAN:
11817 gfc_conv_intrinsic_isnan (se, expr);
11818 break;
11820 case GFC_ISYM_KILL:
11821 conv_intrinsic_kill (se, expr);
11822 break;
11824 case GFC_ISYM_LSHIFT:
11825 gfc_conv_intrinsic_shift (se, expr, false, false);
11826 break;
11828 case GFC_ISYM_RSHIFT:
11829 gfc_conv_intrinsic_shift (se, expr, true, true);
11830 break;
11832 case GFC_ISYM_SHIFTA:
11833 gfc_conv_intrinsic_shift (se, expr, true, true);
11834 break;
11836 case GFC_ISYM_SHIFTL:
11837 gfc_conv_intrinsic_shift (se, expr, false, false);
11838 break;
11840 case GFC_ISYM_SHIFTR:
11841 gfc_conv_intrinsic_shift (se, expr, true, false);
11842 break;
11844 case GFC_ISYM_ISHFT:
11845 gfc_conv_intrinsic_ishft (se, expr);
11846 break;
11848 case GFC_ISYM_ISHFTC:
11849 gfc_conv_intrinsic_ishftc (se, expr);
11850 break;
11852 case GFC_ISYM_LEADZ:
11853 gfc_conv_intrinsic_leadz (se, expr);
11854 break;
11856 case GFC_ISYM_TRAILZ:
11857 gfc_conv_intrinsic_trailz (se, expr);
11858 break;
11860 case GFC_ISYM_POPCNT:
11861 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
11862 break;
11864 case GFC_ISYM_POPPAR:
11865 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
11866 break;
11868 case GFC_ISYM_LBOUND:
11869 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND);
11870 break;
11872 case GFC_ISYM_LCOBOUND:
11873 conv_intrinsic_cobound (se, expr);
11874 break;
11876 case GFC_ISYM_TRANSPOSE:
11877 /* The scalarizer has already been set up for reversed dimension access
11878 order ; now we just get the argument value normally. */
11879 gfc_conv_expr (se, expr->value.function.actual->expr);
11880 break;
11882 case GFC_ISYM_LEN:
11883 gfc_conv_intrinsic_len (se, expr);
11884 break;
11886 case GFC_ISYM_LEN_TRIM:
11887 gfc_conv_intrinsic_len_trim (se, expr);
11888 break;
11890 case GFC_ISYM_LGE:
11891 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
11892 break;
11894 case GFC_ISYM_LGT:
11895 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
11896 break;
11898 case GFC_ISYM_LLE:
11899 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
11900 break;
11902 case GFC_ISYM_LLT:
11903 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
11904 break;
11906 case GFC_ISYM_MALLOC:
11907 gfc_conv_intrinsic_malloc (se, expr);
11908 break;
11910 case GFC_ISYM_MASKL:
11911 gfc_conv_intrinsic_mask (se, expr, 1);
11912 break;
11914 case GFC_ISYM_MASKR:
11915 gfc_conv_intrinsic_mask (se, expr, 0);
11916 break;
11918 case GFC_ISYM_MAX:
11919 if (expr->ts.type == BT_CHARACTER)
11920 gfc_conv_intrinsic_minmax_char (se, expr, 1);
11921 else
11922 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
11923 break;
11925 case GFC_ISYM_MAXLOC:
11926 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
11927 break;
11929 case GFC_ISYM_FINDLOC:
11930 gfc_conv_intrinsic_findloc (se, expr);
11931 break;
11933 case GFC_ISYM_MAXVAL:
11934 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
11935 break;
11937 case GFC_ISYM_MERGE:
11938 gfc_conv_intrinsic_merge (se, expr);
11939 break;
11941 case GFC_ISYM_MERGE_BITS:
11942 gfc_conv_intrinsic_merge_bits (se, expr);
11943 break;
11945 case GFC_ISYM_MIN:
11946 if (expr->ts.type == BT_CHARACTER)
11947 gfc_conv_intrinsic_minmax_char (se, expr, -1);
11948 else
11949 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
11950 break;
11952 case GFC_ISYM_MINLOC:
11953 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
11954 break;
11956 case GFC_ISYM_MINVAL:
11957 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
11958 break;
11960 case GFC_ISYM_NEAREST:
11961 gfc_conv_intrinsic_nearest (se, expr);
11962 break;
11964 case GFC_ISYM_NORM2:
11965 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
11966 break;
11968 case GFC_ISYM_NOT:
11969 gfc_conv_intrinsic_not (se, expr);
11970 break;
11972 case GFC_ISYM_OR:
11973 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
11974 break;
11976 case GFC_ISYM_OUT_OF_RANGE:
11977 gfc_conv_intrinsic_out_of_range (se, expr);
11978 break;
11980 case GFC_ISYM_PARITY:
11981 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
11982 break;
11984 case GFC_ISYM_PRESENT:
11985 gfc_conv_intrinsic_present (se, expr);
11986 break;
11988 case GFC_ISYM_PRODUCT:
11989 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
11990 break;
11992 case GFC_ISYM_RANK:
11993 gfc_conv_intrinsic_rank (se, expr);
11994 break;
11996 case GFC_ISYM_RRSPACING:
11997 gfc_conv_intrinsic_rrspacing (se, expr);
11998 break;
12000 case GFC_ISYM_SET_EXPONENT:
12001 gfc_conv_intrinsic_set_exponent (se, expr);
12002 break;
12004 case GFC_ISYM_SCALE:
12005 gfc_conv_intrinsic_scale (se, expr);
12006 break;
12008 case GFC_ISYM_SHAPE:
12009 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE);
12010 break;
12012 case GFC_ISYM_SIGN:
12013 gfc_conv_intrinsic_sign (se, expr);
12014 break;
12016 case GFC_ISYM_SIZE:
12017 gfc_conv_intrinsic_size (se, expr);
12018 break;
12020 case GFC_ISYM_SIZEOF:
12021 case GFC_ISYM_C_SIZEOF:
12022 gfc_conv_intrinsic_sizeof (se, expr);
12023 break;
12025 case GFC_ISYM_STORAGE_SIZE:
12026 gfc_conv_intrinsic_storage_size (se, expr);
12027 break;
12029 case GFC_ISYM_SPACING:
12030 gfc_conv_intrinsic_spacing (se, expr);
12031 break;
12033 case GFC_ISYM_STRIDE:
12034 conv_intrinsic_stride (se, expr);
12035 break;
12037 case GFC_ISYM_SUM:
12038 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
12039 break;
12041 case GFC_ISYM_TEAM_NUMBER:
12042 conv_intrinsic_team_number (se, expr);
12043 break;
12045 case GFC_ISYM_TRANSFER:
12046 if (se->ss && se->ss->info->useflags)
12047 /* Access the previously obtained result. */
12048 gfc_conv_tmp_array_ref (se);
12049 else
12050 gfc_conv_intrinsic_transfer (se, expr);
12051 break;
12053 case GFC_ISYM_TTYNAM:
12054 gfc_conv_intrinsic_ttynam (se, expr);
12055 break;
12057 case GFC_ISYM_UBOUND:
12058 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND);
12059 break;
12061 case GFC_ISYM_UCOBOUND:
12062 conv_intrinsic_cobound (se, expr);
12063 break;
12065 case GFC_ISYM_XOR:
12066 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
12067 break;
12069 case GFC_ISYM_LOC:
12070 gfc_conv_intrinsic_loc (se, expr);
12071 break;
12073 case GFC_ISYM_THIS_IMAGE:
12074 /* For num_images() == 1, handle as LCOBOUND. */
12075 if (expr->value.function.actual->expr
12076 && flag_coarray == GFC_FCOARRAY_SINGLE)
12077 conv_intrinsic_cobound (se, expr);
12078 else
12079 trans_this_image (se, expr);
12080 break;
12082 case GFC_ISYM_IMAGE_INDEX:
12083 trans_image_index (se, expr);
12084 break;
12086 case GFC_ISYM_IMAGE_STATUS:
12087 conv_intrinsic_image_status (se, expr);
12088 break;
12090 case GFC_ISYM_NUM_IMAGES:
12091 trans_num_images (se, expr);
12092 break;
12094 case GFC_ISYM_ACCESS:
12095 case GFC_ISYM_CHDIR:
12096 case GFC_ISYM_CHMOD:
12097 case GFC_ISYM_DTIME:
12098 case GFC_ISYM_ETIME:
12099 case GFC_ISYM_EXTENDS_TYPE_OF:
12100 case GFC_ISYM_FGET:
12101 case GFC_ISYM_FGETC:
12102 case GFC_ISYM_FNUM:
12103 case GFC_ISYM_FPUT:
12104 case GFC_ISYM_FPUTC:
12105 case GFC_ISYM_FSTAT:
12106 case GFC_ISYM_FTELL:
12107 case GFC_ISYM_GETCWD:
12108 case GFC_ISYM_GETGID:
12109 case GFC_ISYM_GETPID:
12110 case GFC_ISYM_GETUID:
12111 case GFC_ISYM_HOSTNM:
12112 case GFC_ISYM_IERRNO:
12113 case GFC_ISYM_IRAND:
12114 case GFC_ISYM_ISATTY:
12115 case GFC_ISYM_JN2:
12116 case GFC_ISYM_LINK:
12117 case GFC_ISYM_LSTAT:
12118 case GFC_ISYM_MATMUL:
12119 case GFC_ISYM_MCLOCK:
12120 case GFC_ISYM_MCLOCK8:
12121 case GFC_ISYM_RAND:
12122 case GFC_ISYM_RENAME:
12123 case GFC_ISYM_SECOND:
12124 case GFC_ISYM_SECNDS:
12125 case GFC_ISYM_SIGNAL:
12126 case GFC_ISYM_STAT:
12127 case GFC_ISYM_SYMLNK:
12128 case GFC_ISYM_SYSTEM:
12129 case GFC_ISYM_TIME:
12130 case GFC_ISYM_TIME8:
12131 case GFC_ISYM_UMASK:
12132 case GFC_ISYM_UNLINK:
12133 case GFC_ISYM_YN2:
12134 gfc_conv_intrinsic_funcall (se, expr);
12135 break;
12137 case GFC_ISYM_EOSHIFT:
12138 case GFC_ISYM_PACK:
12139 case GFC_ISYM_RESHAPE:
12140 /* For those, expr->rank should always be >0 and thus the if above the
12141 switch should have matched. */
12142 gcc_unreachable ();
12143 break;
12145 default:
12146 gfc_conv_intrinsic_lib_function (se, expr);
12147 break;
12152 static gfc_ss *
12153 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
12155 gfc_ss *arg_ss, *tmp_ss;
12156 gfc_actual_arglist *arg;
12158 arg = expr->value.function.actual;
12160 gcc_assert (arg->expr);
12162 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
12163 gcc_assert (arg_ss != gfc_ss_terminator);
12165 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
12167 if (tmp_ss->info->type != GFC_SS_SCALAR
12168 && tmp_ss->info->type != GFC_SS_REFERENCE)
12170 gcc_assert (tmp_ss->dimen == 2);
12172 /* We just invert dimensions. */
12173 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
12176 /* Stop when tmp_ss points to the last valid element of the chain... */
12177 if (tmp_ss->next == gfc_ss_terminator)
12178 break;
12181 /* ... so that we can attach the rest of the chain to it. */
12182 tmp_ss->next = ss;
12184 return arg_ss;
12188 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
12189 This has the side effect of reversing the nested list, so there is no
12190 need to call gfc_reverse_ss on it (the given list is assumed not to be
12191 reversed yet). */
12193 static gfc_ss *
12194 nest_loop_dimension (gfc_ss *ss, int dim)
12196 int ss_dim, i;
12197 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
12198 gfc_loopinfo *new_loop;
12200 gcc_assert (ss != gfc_ss_terminator);
12202 for (; ss != gfc_ss_terminator; ss = ss->next)
12204 new_ss = gfc_get_ss ();
12205 new_ss->next = prev_ss;
12206 new_ss->parent = ss;
12207 new_ss->info = ss->info;
12208 new_ss->info->refcount++;
12209 if (ss->dimen != 0)
12211 gcc_assert (ss->info->type != GFC_SS_SCALAR
12212 && ss->info->type != GFC_SS_REFERENCE);
12214 new_ss->dimen = 1;
12215 new_ss->dim[0] = ss->dim[dim];
12217 gcc_assert (dim < ss->dimen);
12219 ss_dim = --ss->dimen;
12220 for (i = dim; i < ss_dim; i++)
12221 ss->dim[i] = ss->dim[i + 1];
12223 ss->dim[ss_dim] = 0;
12225 prev_ss = new_ss;
12227 if (ss->nested_ss)
12229 ss->nested_ss->parent = new_ss;
12230 new_ss->nested_ss = ss->nested_ss;
12232 ss->nested_ss = new_ss;
12235 new_loop = gfc_get_loopinfo ();
12236 gfc_init_loopinfo (new_loop);
12238 gcc_assert (prev_ss != NULL);
12239 gcc_assert (prev_ss != gfc_ss_terminator);
12240 gfc_add_ss_to_loop (new_loop, prev_ss);
12241 return new_ss->parent;
12245 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
12246 is to be inlined. */
12248 static gfc_ss *
12249 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
12251 gfc_ss *tmp_ss, *tail, *array_ss;
12252 gfc_actual_arglist *arg1, *arg2, *arg3;
12253 int sum_dim;
12254 bool scalar_mask = false;
12256 /* The rank of the result will be determined later. */
12257 arg1 = expr->value.function.actual;
12258 arg2 = arg1->next;
12259 arg3 = arg2->next;
12260 gcc_assert (arg3 != NULL);
12262 if (expr->rank == 0)
12263 return ss;
12265 tmp_ss = gfc_ss_terminator;
12267 if (arg3->expr)
12269 gfc_ss *mask_ss;
12271 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
12272 if (mask_ss == tmp_ss)
12273 scalar_mask = 1;
12275 tmp_ss = mask_ss;
12278 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
12279 gcc_assert (array_ss != tmp_ss);
12281 /* Odd thing: If the mask is scalar, it is used by the frontend after
12282 the array (to make an if around the nested loop). Thus it shall
12283 be after array_ss once the gfc_ss list is reversed. */
12284 if (scalar_mask)
12285 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
12286 else
12287 tmp_ss = array_ss;
12289 /* "Hide" the dimension on which we will sum in the first arg's scalarization
12290 chain. */
12291 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
12292 tail = nest_loop_dimension (tmp_ss, sum_dim);
12293 tail->next = ss;
12295 return tmp_ss;
12299 /* Create the gfc_ss list for the arguments to MINLOC or MAXLOC when the
12300 function is to be inlined. */
12302 static gfc_ss *
12303 walk_inline_intrinsic_minmaxloc (gfc_ss *ss, gfc_expr *expr ATTRIBUTE_UNUSED)
12305 if (expr->rank == 0)
12306 return ss;
12308 gfc_actual_arglist *array_arg = expr->value.function.actual;
12309 gfc_actual_arglist *dim_arg = array_arg->next;
12310 gfc_actual_arglist *mask_arg = dim_arg->next;
12311 gfc_actual_arglist *kind_arg = mask_arg->next;
12312 gfc_actual_arglist *back_arg = kind_arg->next;
12314 gfc_expr *array = array_arg->expr;
12315 gfc_expr *dim = dim_arg->expr;
12316 gfc_expr *mask = mask_arg->expr;
12317 gfc_expr *back = back_arg->expr;
12319 if (dim == nullptr)
12320 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
12322 gfc_ss *tmp_ss = gfc_ss_terminator;
12324 bool scalar_mask = false;
12325 if (mask)
12327 gfc_ss *mask_ss = gfc_walk_subexpr (tmp_ss, mask);
12328 if (mask_ss == tmp_ss)
12329 scalar_mask = true;
12330 else if (maybe_absent_optional_variable (mask))
12331 mask_ss->info->can_be_null_ref = true;
12333 tmp_ss = mask_ss;
12336 gfc_ss *array_ss = gfc_walk_subexpr (tmp_ss, array);
12337 gcc_assert (array_ss != tmp_ss);
12339 tmp_ss = array_ss;
12341 /* Move the dimension on which we will sum to a separate nested scalarization
12342 chain, "hiding" that dimension from the outer scalarization. */
12343 int dim_val = mpz_get_si (dim->value.integer);
12344 gfc_ss *tail = nest_loop_dimension (tmp_ss, dim_val - 1);
12346 if (back && array->rank > 1)
12348 /* If there are nested scalarization loops, include BACK in the
12349 scalarization chains to avoid evaluating it multiple times in a loop.
12350 Otherwise, prefer to handle it outside of scalarization. */
12351 gfc_ss *back_ss = gfc_get_scalar_ss (ss, back);
12352 back_ss->info->type = GFC_SS_REFERENCE;
12353 if (maybe_absent_optional_variable (back))
12354 back_ss->info->can_be_null_ref = true;
12356 tail->next = back_ss;
12358 else
12359 tail->next = ss;
12361 if (scalar_mask)
12363 tmp_ss = gfc_get_scalar_ss (tmp_ss, mask);
12364 /* MASK can be a forwarded optional argument, so make the necessary setup
12365 to avoid the scalarizer generating any unguarded pointer dereference in
12366 that case. */
12367 tmp_ss->info->type = GFC_SS_REFERENCE;
12368 if (maybe_absent_optional_variable (mask))
12369 tmp_ss->info->can_be_null_ref = true;
12372 return tmp_ss;
12376 static gfc_ss *
12377 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
12380 switch (expr->value.function.isym->id)
12382 case GFC_ISYM_PRODUCT:
12383 case GFC_ISYM_SUM:
12384 return walk_inline_intrinsic_arith (ss, expr);
12386 case GFC_ISYM_TRANSPOSE:
12387 return walk_inline_intrinsic_transpose (ss, expr);
12389 case GFC_ISYM_MAXLOC:
12390 case GFC_ISYM_MINLOC:
12391 return walk_inline_intrinsic_minmaxloc (ss, expr);
12393 default:
12394 gcc_unreachable ();
12396 gcc_unreachable ();
12400 /* This generates code to execute before entering the scalarization loop.
12401 Currently does nothing. */
12403 void
12404 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
12406 switch (ss->info->expr->value.function.isym->id)
12408 case GFC_ISYM_UBOUND:
12409 case GFC_ISYM_LBOUND:
12410 case GFC_ISYM_UCOBOUND:
12411 case GFC_ISYM_LCOBOUND:
12412 case GFC_ISYM_MAXLOC:
12413 case GFC_ISYM_MINLOC:
12414 case GFC_ISYM_THIS_IMAGE:
12415 case GFC_ISYM_SHAPE:
12416 break;
12418 default:
12419 gcc_unreachable ();
12424 /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
12425 one parameter are expanded into code inside the scalarization loop. */
12427 static gfc_ss *
12428 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
12430 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
12431 gfc_add_class_array_ref (expr->value.function.actual->expr);
12433 /* The two argument version returns a scalar. */
12434 if (expr->value.function.isym->id != GFC_ISYM_SHAPE
12435 && expr->value.function.actual->next->expr)
12436 return ss;
12438 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
12442 /* Walk an intrinsic array libcall. */
12444 static gfc_ss *
12445 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
12447 gcc_assert (expr->rank > 0);
12448 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
12452 /* Return whether the function call expression EXPR will be expanded
12453 inline by gfc_conv_intrinsic_function. */
12455 bool
12456 gfc_inline_intrinsic_function_p (gfc_expr *expr)
12458 gfc_actual_arglist *args, *dim_arg, *mask_arg;
12459 gfc_expr *maskexpr;
12461 gfc_intrinsic_sym *isym = expr->value.function.isym;
12462 if (!isym)
12463 return false;
12465 switch (isym->id)
12467 case GFC_ISYM_PRODUCT:
12468 case GFC_ISYM_SUM:
12469 /* Disable inline expansion if code size matters. */
12470 if (optimize_size)
12471 return false;
12473 args = expr->value.function.actual;
12474 dim_arg = args->next;
12476 /* We need to be able to subset the SUM argument at compile-time. */
12477 if (dim_arg->expr && dim_arg->expr->expr_type != EXPR_CONSTANT)
12478 return false;
12480 /* FIXME: If MASK is optional for a more than two-dimensional
12481 argument, the scalarizer gets confused if the mask is
12482 absent. See PR 82995. For now, fall back to the library
12483 function. */
12485 mask_arg = dim_arg->next;
12486 maskexpr = mask_arg->expr;
12488 if (expr->rank > 0 && maskexpr && maskexpr->expr_type == EXPR_VARIABLE
12489 && maskexpr->symtree->n.sym->attr.dummy
12490 && maskexpr->symtree->n.sym->attr.optional)
12491 return false;
12493 return true;
12495 case GFC_ISYM_TRANSPOSE:
12496 return true;
12498 case GFC_ISYM_MINLOC:
12499 case GFC_ISYM_MAXLOC:
12501 if ((isym->id == GFC_ISYM_MINLOC
12502 && (flag_inline_intrinsics
12503 & GFC_FLAG_INLINE_INTRINSIC_MINLOC) == 0)
12504 || (isym->id == GFC_ISYM_MAXLOC
12505 && (flag_inline_intrinsics
12506 & GFC_FLAG_INLINE_INTRINSIC_MAXLOC) == 0))
12507 return false;
12509 gfc_actual_arglist *array_arg = expr->value.function.actual;
12510 gfc_actual_arglist *dim_arg = array_arg->next;
12512 gfc_expr *array = array_arg->expr;
12513 gfc_expr *dim = dim_arg->expr;
12515 if (!(array->ts.type == BT_INTEGER
12516 || array->ts.type == BT_REAL))
12517 return false;
12519 if (array->rank == 1)
12520 return true;
12522 if (dim != nullptr
12523 && dim->expr_type != EXPR_CONSTANT)
12524 return false;
12526 return true;
12529 default:
12530 return false;
12535 /* Returns nonzero if the specified intrinsic function call maps directly to
12536 an external library call. Should only be used for functions that return
12537 arrays. */
12540 gfc_is_intrinsic_libcall (gfc_expr * expr)
12542 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
12543 gcc_assert (expr->rank > 0);
12545 if (gfc_inline_intrinsic_function_p (expr))
12546 return 0;
12548 switch (expr->value.function.isym->id)
12550 case GFC_ISYM_ALL:
12551 case GFC_ISYM_ANY:
12552 case GFC_ISYM_COUNT:
12553 case GFC_ISYM_FINDLOC:
12554 case GFC_ISYM_JN2:
12555 case GFC_ISYM_IANY:
12556 case GFC_ISYM_IALL:
12557 case GFC_ISYM_IPARITY:
12558 case GFC_ISYM_MATMUL:
12559 case GFC_ISYM_MAXLOC:
12560 case GFC_ISYM_MAXVAL:
12561 case GFC_ISYM_MINLOC:
12562 case GFC_ISYM_MINVAL:
12563 case GFC_ISYM_NORM2:
12564 case GFC_ISYM_PARITY:
12565 case GFC_ISYM_PRODUCT:
12566 case GFC_ISYM_SUM:
12567 case GFC_ISYM_SPREAD:
12568 case GFC_ISYM_YN2:
12569 /* Ignore absent optional parameters. */
12570 return 1;
12572 case GFC_ISYM_CSHIFT:
12573 case GFC_ISYM_EOSHIFT:
12574 case GFC_ISYM_GET_TEAM:
12575 case GFC_ISYM_FAILED_IMAGES:
12576 case GFC_ISYM_STOPPED_IMAGES:
12577 case GFC_ISYM_PACK:
12578 case GFC_ISYM_RESHAPE:
12579 case GFC_ISYM_UNPACK:
12580 /* Pass absent optional parameters. */
12581 return 2;
12583 default:
12584 return 0;
12588 /* Walk an intrinsic function. */
12589 gfc_ss *
12590 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
12591 gfc_intrinsic_sym * isym)
12593 gcc_assert (isym);
12595 if (isym->elemental)
12596 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
12597 expr->value.function.isym,
12598 GFC_SS_SCALAR);
12600 if (expr->rank == 0 && expr->corank == 0)
12601 return ss;
12603 if (gfc_inline_intrinsic_function_p (expr))
12604 return walk_inline_intrinsic_function (ss, expr);
12606 if (expr->rank != 0 && gfc_is_intrinsic_libcall (expr))
12607 return gfc_walk_intrinsic_libfunc (ss, expr);
12609 /* Special cases. */
12610 switch (isym->id)
12612 case GFC_ISYM_LBOUND:
12613 case GFC_ISYM_LCOBOUND:
12614 case GFC_ISYM_UBOUND:
12615 case GFC_ISYM_UCOBOUND:
12616 case GFC_ISYM_THIS_IMAGE:
12617 case GFC_ISYM_SHAPE:
12618 return gfc_walk_intrinsic_bound (ss, expr);
12620 case GFC_ISYM_TRANSFER:
12621 case GFC_ISYM_CAF_GET:
12622 return gfc_walk_intrinsic_libfunc (ss, expr);
12624 default:
12625 /* This probably meant someone forgot to add an intrinsic to the above
12626 list(s) when they implemented it, or something's gone horribly
12627 wrong. */
12628 gcc_unreachable ();
12632 static tree
12633 conv_co_collective (gfc_code *code)
12635 gfc_se argse;
12636 stmtblock_t block, post_block;
12637 tree fndecl, array = NULL_TREE, strlen, image_index, stat, errmsg, errmsg_len;
12638 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
12640 gfc_start_block (&block);
12641 gfc_init_block (&post_block);
12643 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
12645 opr_expr = code->ext.actual->next->expr;
12646 image_idx_expr = code->ext.actual->next->next->expr;
12647 stat_expr = code->ext.actual->next->next->next->expr;
12648 errmsg_expr = code->ext.actual->next->next->next->next->expr;
12650 else
12652 opr_expr = NULL;
12653 image_idx_expr = code->ext.actual->next->expr;
12654 stat_expr = code->ext.actual->next->next->expr;
12655 errmsg_expr = code->ext.actual->next->next->next->expr;
12658 /* stat. */
12659 if (stat_expr)
12661 gfc_init_se (&argse, NULL);
12662 gfc_conv_expr (&argse, stat_expr);
12663 gfc_add_block_to_block (&block, &argse.pre);
12664 gfc_add_block_to_block (&post_block, &argse.post);
12665 stat = argse.expr;
12666 if (flag_coarray != GFC_FCOARRAY_SINGLE)
12667 stat = gfc_build_addr_expr (NULL_TREE, stat);
12669 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
12670 stat = NULL_TREE;
12671 else
12672 stat = null_pointer_node;
12674 /* Early exit for GFC_FCOARRAY_SINGLE. */
12675 if (flag_coarray == GFC_FCOARRAY_SINGLE)
12677 if (stat != NULL_TREE)
12679 /* For optional stats, check the pointer is valid before zero'ing. */
12680 if (gfc_expr_attr (stat_expr).optional)
12682 tree tmp;
12683 stmtblock_t ass_block;
12684 gfc_start_block (&ass_block);
12685 gfc_add_modify (&ass_block, stat,
12686 fold_convert (TREE_TYPE (stat),
12687 integer_zero_node));
12688 tmp = fold_build2 (NE_EXPR, logical_type_node,
12689 gfc_build_addr_expr (NULL_TREE, stat),
12690 null_pointer_node);
12691 tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
12692 gfc_finish_block (&ass_block),
12693 build_empty_stmt (input_location));
12694 gfc_add_expr_to_block (&block, tmp);
12696 else
12697 gfc_add_modify (&block, stat,
12698 fold_convert (TREE_TYPE (stat), integer_zero_node));
12700 return gfc_finish_block (&block);
12703 gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED
12704 ? code->ext.actual->expr->ts.u.derived : NULL;
12706 /* Handle the array. */
12707 gfc_init_se (&argse, NULL);
12708 if (!derived || !derived->attr.alloc_comp
12709 || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST)
12711 if (code->ext.actual->expr->rank == 0)
12713 symbol_attribute attr;
12714 gfc_clear_attr (&attr);
12715 gfc_init_se (&argse, NULL);
12716 gfc_conv_expr (&argse, code->ext.actual->expr);
12717 gfc_add_block_to_block (&block, &argse.pre);
12718 gfc_add_block_to_block (&post_block, &argse.post);
12719 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
12720 array = gfc_build_addr_expr (NULL_TREE, array);
12722 else
12724 argse.want_pointer = 1;
12725 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
12726 array = argse.expr;
12730 gfc_add_block_to_block (&block, &argse.pre);
12731 gfc_add_block_to_block (&post_block, &argse.post);
12733 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
12734 strlen = argse.string_length;
12735 else
12736 strlen = integer_zero_node;
12738 /* image_index. */
12739 if (image_idx_expr)
12741 gfc_init_se (&argse, NULL);
12742 gfc_conv_expr (&argse, image_idx_expr);
12743 gfc_add_block_to_block (&block, &argse.pre);
12744 gfc_add_block_to_block (&post_block, &argse.post);
12745 image_index = fold_convert (integer_type_node, argse.expr);
12747 else
12748 image_index = integer_zero_node;
12750 /* errmsg. */
12751 if (errmsg_expr)
12753 gfc_init_se (&argse, NULL);
12754 gfc_conv_expr (&argse, errmsg_expr);
12755 gfc_add_block_to_block (&block, &argse.pre);
12756 gfc_add_block_to_block (&post_block, &argse.post);
12757 errmsg = argse.expr;
12758 errmsg_len = fold_convert (size_type_node, argse.string_length);
12760 else
12762 errmsg = null_pointer_node;
12763 errmsg_len = build_zero_cst (size_type_node);
12766 /* Generate the function call. */
12767 switch (code->resolved_isym->id)
12769 case GFC_ISYM_CO_BROADCAST:
12770 fndecl = gfor_fndecl_co_broadcast;
12771 break;
12772 case GFC_ISYM_CO_MAX:
12773 fndecl = gfor_fndecl_co_max;
12774 break;
12775 case GFC_ISYM_CO_MIN:
12776 fndecl = gfor_fndecl_co_min;
12777 break;
12778 case GFC_ISYM_CO_REDUCE:
12779 fndecl = gfor_fndecl_co_reduce;
12780 break;
12781 case GFC_ISYM_CO_SUM:
12782 fndecl = gfor_fndecl_co_sum;
12783 break;
12784 default:
12785 gcc_unreachable ();
12788 if (derived && derived->attr.alloc_comp
12789 && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
12790 /* The derived type has the attribute 'alloc_comp'. */
12792 tree tmp = gfc_bcast_alloc_comp (derived, code->ext.actual->expr,
12793 code->ext.actual->expr->rank,
12794 image_index, stat, errmsg, errmsg_len);
12795 gfc_add_expr_to_block (&block, tmp);
12797 else
12799 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
12800 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
12801 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
12802 image_index, stat, errmsg, errmsg_len);
12803 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
12804 fndecl = build_call_expr_loc (input_location, fndecl, 6, array,
12805 image_index, stat, errmsg,
12806 strlen, errmsg_len);
12807 else
12809 tree opr, opr_flags;
12811 // FIXME: Handle TS29113's bind(C) strings with descriptor.
12812 int opr_flag_int;
12813 if (gfc_is_proc_ptr_comp (opr_expr))
12815 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
12816 opr_flag_int = sym->attr.dimension
12817 || (sym->ts.type == BT_CHARACTER
12818 && !sym->attr.is_bind_c)
12819 ? GFC_CAF_BYREF : 0;
12820 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
12821 && !sym->attr.is_bind_c
12822 ? GFC_CAF_HIDDENLEN : 0;
12823 opr_flag_int |= sym->formal->sym->attr.value
12824 ? GFC_CAF_ARG_VALUE : 0;
12826 else
12828 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
12829 ? GFC_CAF_BYREF : 0;
12830 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
12831 && !opr_expr->symtree->n.sym->attr.is_bind_c
12832 ? GFC_CAF_HIDDENLEN : 0;
12833 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
12834 ? GFC_CAF_ARG_VALUE : 0;
12836 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
12837 gfc_conv_expr (&argse, opr_expr);
12838 opr = argse.expr;
12839 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr,
12840 opr_flags, image_index, stat, errmsg,
12841 strlen, errmsg_len);
12845 gfc_add_expr_to_block (&block, fndecl);
12846 gfc_add_block_to_block (&block, &post_block);
12848 return gfc_finish_block (&block);
12852 static tree
12853 conv_intrinsic_atomic_op (gfc_code *code)
12855 gfc_se argse;
12856 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
12857 stmtblock_t block, post_block;
12858 gfc_expr *atom_expr = code->ext.actual->expr;
12859 gfc_expr *stat_expr;
12860 built_in_function fn;
12862 if (atom_expr->expr_type == EXPR_FUNCTION
12863 && atom_expr->value.function.isym
12864 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12865 atom_expr = atom_expr->value.function.actual->expr;
12867 gfc_start_block (&block);
12868 gfc_init_block (&post_block);
12870 gfc_init_se (&argse, NULL);
12871 argse.want_pointer = 1;
12872 gfc_conv_expr (&argse, atom_expr);
12873 gfc_add_block_to_block (&block, &argse.pre);
12874 gfc_add_block_to_block (&post_block, &argse.post);
12875 atom = argse.expr;
12877 gfc_init_se (&argse, NULL);
12878 if (flag_coarray == GFC_FCOARRAY_LIB
12879 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
12880 argse.want_pointer = 1;
12881 gfc_conv_expr (&argse, code->ext.actual->next->expr);
12882 gfc_add_block_to_block (&block, &argse.pre);
12883 gfc_add_block_to_block (&post_block, &argse.post);
12884 value = argse.expr;
12886 switch (code->resolved_isym->id)
12888 case GFC_ISYM_ATOMIC_ADD:
12889 case GFC_ISYM_ATOMIC_AND:
12890 case GFC_ISYM_ATOMIC_DEF:
12891 case GFC_ISYM_ATOMIC_OR:
12892 case GFC_ISYM_ATOMIC_XOR:
12893 stat_expr = code->ext.actual->next->next->expr;
12894 if (flag_coarray == GFC_FCOARRAY_LIB)
12895 old = null_pointer_node;
12896 break;
12897 default:
12898 gfc_init_se (&argse, NULL);
12899 if (flag_coarray == GFC_FCOARRAY_LIB)
12900 argse.want_pointer = 1;
12901 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
12902 gfc_add_block_to_block (&block, &argse.pre);
12903 gfc_add_block_to_block (&post_block, &argse.post);
12904 old = argse.expr;
12905 stat_expr = code->ext.actual->next->next->next->expr;
12908 /* STAT= */
12909 if (stat_expr != NULL)
12911 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
12912 gfc_init_se (&argse, NULL);
12913 if (flag_coarray == GFC_FCOARRAY_LIB)
12914 argse.want_pointer = 1;
12915 gfc_conv_expr_val (&argse, stat_expr);
12916 gfc_add_block_to_block (&block, &argse.pre);
12917 gfc_add_block_to_block (&post_block, &argse.post);
12918 stat = argse.expr;
12920 else if (flag_coarray == GFC_FCOARRAY_LIB)
12921 stat = null_pointer_node;
12923 if (flag_coarray == GFC_FCOARRAY_LIB)
12925 tree image_index, caf_decl, offset, token;
12926 int op;
12928 switch (code->resolved_isym->id)
12930 case GFC_ISYM_ATOMIC_ADD:
12931 case GFC_ISYM_ATOMIC_FETCH_ADD:
12932 op = (int) GFC_CAF_ATOMIC_ADD;
12933 break;
12934 case GFC_ISYM_ATOMIC_AND:
12935 case GFC_ISYM_ATOMIC_FETCH_AND:
12936 op = (int) GFC_CAF_ATOMIC_AND;
12937 break;
12938 case GFC_ISYM_ATOMIC_OR:
12939 case GFC_ISYM_ATOMIC_FETCH_OR:
12940 op = (int) GFC_CAF_ATOMIC_OR;
12941 break;
12942 case GFC_ISYM_ATOMIC_XOR:
12943 case GFC_ISYM_ATOMIC_FETCH_XOR:
12944 op = (int) GFC_CAF_ATOMIC_XOR;
12945 break;
12946 case GFC_ISYM_ATOMIC_DEF:
12947 op = 0; /* Unused. */
12948 break;
12949 default:
12950 gcc_unreachable ();
12953 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
12954 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
12955 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
12957 if (gfc_is_coindexed (atom_expr))
12958 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
12959 else
12960 image_index = integer_zero_node;
12962 if (!POINTER_TYPE_P (TREE_TYPE (value)))
12964 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
12965 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
12966 value = gfc_build_addr_expr (NULL_TREE, tmp);
12969 gfc_init_se (&argse, NULL);
12970 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
12971 atom_expr);
12973 gfc_add_block_to_block (&block, &argse.pre);
12974 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
12975 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
12976 token, offset, image_index, value, stat,
12977 build_int_cst (integer_type_node,
12978 (int) atom_expr->ts.type),
12979 build_int_cst (integer_type_node,
12980 (int) atom_expr->ts.kind));
12981 else
12982 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
12983 build_int_cst (integer_type_node, op),
12984 token, offset, image_index, value, old, stat,
12985 build_int_cst (integer_type_node,
12986 (int) atom_expr->ts.type),
12987 build_int_cst (integer_type_node,
12988 (int) atom_expr->ts.kind));
12990 gfc_add_expr_to_block (&block, tmp);
12991 gfc_add_block_to_block (&block, &argse.post);
12992 gfc_add_block_to_block (&block, &post_block);
12993 return gfc_finish_block (&block);
12997 switch (code->resolved_isym->id)
12999 case GFC_ISYM_ATOMIC_ADD:
13000 case GFC_ISYM_ATOMIC_FETCH_ADD:
13001 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
13002 break;
13003 case GFC_ISYM_ATOMIC_AND:
13004 case GFC_ISYM_ATOMIC_FETCH_AND:
13005 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
13006 break;
13007 case GFC_ISYM_ATOMIC_DEF:
13008 fn = BUILT_IN_ATOMIC_STORE_N;
13009 break;
13010 case GFC_ISYM_ATOMIC_OR:
13011 case GFC_ISYM_ATOMIC_FETCH_OR:
13012 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
13013 break;
13014 case GFC_ISYM_ATOMIC_XOR:
13015 case GFC_ISYM_ATOMIC_FETCH_XOR:
13016 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
13017 break;
13018 default:
13019 gcc_unreachable ();
13022 tmp = TREE_TYPE (TREE_TYPE (atom));
13023 fn = (built_in_function) ((int) fn
13024 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
13025 + 1);
13026 tree itype = TREE_TYPE (TREE_TYPE (atom));
13027 tmp = builtin_decl_explicit (fn);
13029 switch (code->resolved_isym->id)
13031 case GFC_ISYM_ATOMIC_ADD:
13032 case GFC_ISYM_ATOMIC_AND:
13033 case GFC_ISYM_ATOMIC_DEF:
13034 case GFC_ISYM_ATOMIC_OR:
13035 case GFC_ISYM_ATOMIC_XOR:
13036 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
13037 fold_convert (itype, value),
13038 build_int_cst (NULL, MEMMODEL_RELAXED));
13039 gfc_add_expr_to_block (&block, tmp);
13040 break;
13041 default:
13042 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
13043 fold_convert (itype, value),
13044 build_int_cst (NULL, MEMMODEL_RELAXED));
13045 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
13046 break;
13049 if (stat != NULL_TREE)
13050 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
13051 gfc_add_block_to_block (&block, &post_block);
13052 return gfc_finish_block (&block);
13056 static tree
13057 conv_intrinsic_atomic_ref (gfc_code *code)
13059 gfc_se argse;
13060 tree tmp, atom, value, stat = NULL_TREE;
13061 stmtblock_t block, post_block;
13062 built_in_function fn;
13063 gfc_expr *atom_expr = code->ext.actual->next->expr;
13065 if (atom_expr->expr_type == EXPR_FUNCTION
13066 && atom_expr->value.function.isym
13067 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
13068 atom_expr = atom_expr->value.function.actual->expr;
13070 gfc_start_block (&block);
13071 gfc_init_block (&post_block);
13072 gfc_init_se (&argse, NULL);
13073 argse.want_pointer = 1;
13074 gfc_conv_expr (&argse, atom_expr);
13075 gfc_add_block_to_block (&block, &argse.pre);
13076 gfc_add_block_to_block (&post_block, &argse.post);
13077 atom = argse.expr;
13079 gfc_init_se (&argse, NULL);
13080 if (flag_coarray == GFC_FCOARRAY_LIB
13081 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
13082 argse.want_pointer = 1;
13083 gfc_conv_expr (&argse, code->ext.actual->expr);
13084 gfc_add_block_to_block (&block, &argse.pre);
13085 gfc_add_block_to_block (&post_block, &argse.post);
13086 value = argse.expr;
13088 /* STAT= */
13089 if (code->ext.actual->next->next->expr != NULL)
13091 gcc_assert (code->ext.actual->next->next->expr->expr_type
13092 == EXPR_VARIABLE);
13093 gfc_init_se (&argse, NULL);
13094 if (flag_coarray == GFC_FCOARRAY_LIB)
13095 argse.want_pointer = 1;
13096 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
13097 gfc_add_block_to_block (&block, &argse.pre);
13098 gfc_add_block_to_block (&post_block, &argse.post);
13099 stat = argse.expr;
13101 else if (flag_coarray == GFC_FCOARRAY_LIB)
13102 stat = null_pointer_node;
13104 if (flag_coarray == GFC_FCOARRAY_LIB)
13106 tree image_index, caf_decl, offset, token;
13107 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
13109 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
13110 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
13111 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
13113 if (gfc_is_coindexed (atom_expr))
13114 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
13115 else
13116 image_index = integer_zero_node;
13118 gfc_init_se (&argse, NULL);
13119 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
13120 atom_expr);
13121 gfc_add_block_to_block (&block, &argse.pre);
13123 /* Different type, need type conversion. */
13124 if (!POINTER_TYPE_P (TREE_TYPE (value)))
13126 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
13127 orig_value = value;
13128 value = gfc_build_addr_expr (NULL_TREE, vardecl);
13131 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
13132 token, offset, image_index, value, stat,
13133 build_int_cst (integer_type_node,
13134 (int) atom_expr->ts.type),
13135 build_int_cst (integer_type_node,
13136 (int) atom_expr->ts.kind));
13137 gfc_add_expr_to_block (&block, tmp);
13138 if (vardecl != NULL_TREE)
13139 gfc_add_modify (&block, orig_value,
13140 fold_convert (TREE_TYPE (orig_value), vardecl));
13141 gfc_add_block_to_block (&block, &argse.post);
13142 gfc_add_block_to_block (&block, &post_block);
13143 return gfc_finish_block (&block);
13146 tmp = TREE_TYPE (TREE_TYPE (atom));
13147 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
13148 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
13149 + 1);
13150 tmp = builtin_decl_explicit (fn);
13151 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
13152 build_int_cst (integer_type_node,
13153 MEMMODEL_RELAXED));
13154 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
13156 if (stat != NULL_TREE)
13157 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
13158 gfc_add_block_to_block (&block, &post_block);
13159 return gfc_finish_block (&block);
13163 static tree
13164 conv_intrinsic_atomic_cas (gfc_code *code)
13166 gfc_se argse;
13167 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
13168 stmtblock_t block, post_block;
13169 built_in_function fn;
13170 gfc_expr *atom_expr = code->ext.actual->expr;
13172 if (atom_expr->expr_type == EXPR_FUNCTION
13173 && atom_expr->value.function.isym
13174 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
13175 atom_expr = atom_expr->value.function.actual->expr;
13177 gfc_init_block (&block);
13178 gfc_init_block (&post_block);
13179 gfc_init_se (&argse, NULL);
13180 argse.want_pointer = 1;
13181 gfc_conv_expr (&argse, atom_expr);
13182 atom = argse.expr;
13184 gfc_init_se (&argse, NULL);
13185 if (flag_coarray == GFC_FCOARRAY_LIB)
13186 argse.want_pointer = 1;
13187 gfc_conv_expr (&argse, code->ext.actual->next->expr);
13188 gfc_add_block_to_block (&block, &argse.pre);
13189 gfc_add_block_to_block (&post_block, &argse.post);
13190 old = argse.expr;
13192 gfc_init_se (&argse, NULL);
13193 if (flag_coarray == GFC_FCOARRAY_LIB)
13194 argse.want_pointer = 1;
13195 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
13196 gfc_add_block_to_block (&block, &argse.pre);
13197 gfc_add_block_to_block (&post_block, &argse.post);
13198 comp = argse.expr;
13200 gfc_init_se (&argse, NULL);
13201 if (flag_coarray == GFC_FCOARRAY_LIB
13202 && code->ext.actual->next->next->next->expr->ts.kind
13203 == atom_expr->ts.kind)
13204 argse.want_pointer = 1;
13205 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
13206 gfc_add_block_to_block (&block, &argse.pre);
13207 gfc_add_block_to_block (&post_block, &argse.post);
13208 new_val = argse.expr;
13210 /* STAT= */
13211 if (code->ext.actual->next->next->next->next->expr != NULL)
13213 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
13214 == EXPR_VARIABLE);
13215 gfc_init_se (&argse, NULL);
13216 if (flag_coarray == GFC_FCOARRAY_LIB)
13217 argse.want_pointer = 1;
13218 gfc_conv_expr_val (&argse,
13219 code->ext.actual->next->next->next->next->expr);
13220 gfc_add_block_to_block (&block, &argse.pre);
13221 gfc_add_block_to_block (&post_block, &argse.post);
13222 stat = argse.expr;
13224 else if (flag_coarray == GFC_FCOARRAY_LIB)
13225 stat = null_pointer_node;
13227 if (flag_coarray == GFC_FCOARRAY_LIB)
13229 tree image_index, caf_decl, offset, token;
13231 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
13232 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
13233 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
13235 if (gfc_is_coindexed (atom_expr))
13236 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
13237 else
13238 image_index = integer_zero_node;
13240 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
13242 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
13243 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
13244 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
13247 /* Convert a constant to a pointer. */
13248 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
13250 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
13251 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
13252 comp = gfc_build_addr_expr (NULL_TREE, tmp);
13255 gfc_init_se (&argse, NULL);
13256 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
13257 atom_expr);
13258 gfc_add_block_to_block (&block, &argse.pre);
13260 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
13261 token, offset, image_index, old, comp, new_val,
13262 stat, build_int_cst (integer_type_node,
13263 (int) atom_expr->ts.type),
13264 build_int_cst (integer_type_node,
13265 (int) atom_expr->ts.kind));
13266 gfc_add_expr_to_block (&block, tmp);
13267 gfc_add_block_to_block (&block, &argse.post);
13268 gfc_add_block_to_block (&block, &post_block);
13269 return gfc_finish_block (&block);
13272 tmp = TREE_TYPE (TREE_TYPE (atom));
13273 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
13274 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
13275 + 1);
13276 tmp = builtin_decl_explicit (fn);
13278 gfc_add_modify (&block, old, comp);
13279 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
13280 gfc_build_addr_expr (NULL, old),
13281 fold_convert (TREE_TYPE (old), new_val),
13282 boolean_false_node,
13283 build_int_cst (NULL, MEMMODEL_RELAXED),
13284 build_int_cst (NULL, MEMMODEL_RELAXED));
13285 gfc_add_expr_to_block (&block, tmp);
13287 if (stat != NULL_TREE)
13288 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
13289 gfc_add_block_to_block (&block, &post_block);
13290 return gfc_finish_block (&block);
13293 static tree
13294 conv_intrinsic_event_query (gfc_code *code)
13296 gfc_se se, argse;
13297 tree stat = NULL_TREE, stat2 = NULL_TREE;
13298 tree count = NULL_TREE, count2 = NULL_TREE;
13300 gfc_expr *event_expr = code->ext.actual->expr;
13302 if (code->ext.actual->next->next->expr)
13304 gcc_assert (code->ext.actual->next->next->expr->expr_type
13305 == EXPR_VARIABLE);
13306 gfc_init_se (&argse, NULL);
13307 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
13308 stat = argse.expr;
13310 else if (flag_coarray == GFC_FCOARRAY_LIB)
13311 stat = null_pointer_node;
13313 if (code->ext.actual->next->expr)
13315 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
13316 gfc_init_se (&argse, NULL);
13317 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
13318 count = argse.expr;
13321 gfc_start_block (&se.pre);
13322 if (flag_coarray == GFC_FCOARRAY_LIB)
13324 tree tmp, token, image_index;
13325 tree index = build_zero_cst (gfc_array_index_type);
13327 if (event_expr->expr_type == EXPR_FUNCTION
13328 && event_expr->value.function.isym
13329 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
13330 event_expr = event_expr->value.function.actual->expr;
13332 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
13334 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
13335 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
13336 != INTMOD_ISO_FORTRAN_ENV
13337 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
13338 != ISOFORTRAN_EVENT_TYPE)
13340 gfc_error ("Sorry, the event component of derived type at %L is not "
13341 "yet supported", &event_expr->where);
13342 return NULL_TREE;
13345 if (gfc_is_coindexed (event_expr))
13347 gfc_error ("The event variable at %L shall not be coindexed",
13348 &event_expr->where);
13349 return NULL_TREE;
13352 image_index = integer_zero_node;
13354 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
13355 event_expr);
13357 /* For arrays, obtain the array index. */
13358 if (gfc_expr_attr (event_expr).dimension)
13360 tree desc, tmp, extent, lbound, ubound;
13361 gfc_array_ref *ar, ar2;
13362 int i;
13364 /* TODO: Extend this, once DT components are supported. */
13365 ar = &event_expr->ref->u.ar;
13366 ar2 = *ar;
13367 memset (ar, '\0', sizeof (*ar));
13368 ar->as = ar2.as;
13369 ar->type = AR_FULL;
13371 gfc_init_se (&argse, NULL);
13372 argse.descriptor_only = 1;
13373 gfc_conv_expr_descriptor (&argse, event_expr);
13374 gfc_add_block_to_block (&se.pre, &argse.pre);
13375 desc = argse.expr;
13376 *ar = ar2;
13378 extent = build_one_cst (gfc_array_index_type);
13379 for (i = 0; i < ar->dimen; i++)
13381 gfc_init_se (&argse, NULL);
13382 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
13383 gfc_add_block_to_block (&argse.pre, &argse.pre);
13384 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
13385 tmp = fold_build2_loc (input_location, MINUS_EXPR,
13386 TREE_TYPE (lbound), argse.expr, lbound);
13387 tmp = fold_build2_loc (input_location, MULT_EXPR,
13388 TREE_TYPE (tmp), extent, tmp);
13389 index = fold_build2_loc (input_location, PLUS_EXPR,
13390 TREE_TYPE (tmp), index, tmp);
13391 if (i < ar->dimen - 1)
13393 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
13394 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
13395 extent = fold_build2_loc (input_location, MULT_EXPR,
13396 TREE_TYPE (tmp), extent, tmp);
13401 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
13403 count2 = count;
13404 count = gfc_create_var (integer_type_node, "count");
13407 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
13409 stat2 = stat;
13410 stat = gfc_create_var (integer_type_node, "stat");
13413 index = fold_convert (size_type_node, index);
13414 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
13415 token, index, image_index, count
13416 ? gfc_build_addr_expr (NULL, count) : count,
13417 stat != null_pointer_node
13418 ? gfc_build_addr_expr (NULL, stat) : stat);
13419 gfc_add_expr_to_block (&se.pre, tmp);
13421 if (count2 != NULL_TREE)
13422 gfc_add_modify (&se.pre, count2,
13423 fold_convert (TREE_TYPE (count2), count));
13425 if (stat2 != NULL_TREE)
13426 gfc_add_modify (&se.pre, stat2,
13427 fold_convert (TREE_TYPE (stat2), stat));
13429 return gfc_finish_block (&se.pre);
13432 gfc_init_se (&argse, NULL);
13433 gfc_conv_expr_val (&argse, code->ext.actual->expr);
13434 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
13436 if (stat != NULL_TREE)
13437 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
13439 return gfc_finish_block (&se.pre);
13443 /* This is a peculiar case because of the need to do dependency checking.
13444 It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
13445 a special case and this function called instead of
13446 gfc_conv_procedure_call. */
13447 void
13448 gfc_conv_intrinsic_mvbits (gfc_se *se, gfc_actual_arglist *actual_args,
13449 gfc_loopinfo *loop)
13451 gfc_actual_arglist *actual;
13452 gfc_se argse[5];
13453 gfc_expr *arg[5];
13454 gfc_ss *lss;
13455 int n;
13457 tree from, frompos, len, to, topos;
13458 tree lenmask, oldbits, newbits, bitsize;
13459 tree type, utype, above, mask1, mask2;
13461 if (loop)
13462 lss = loop->ss;
13463 else
13464 lss = gfc_ss_terminator;
13466 actual = actual_args;
13467 for (n = 0; n < 5; n++, actual = actual->next)
13469 arg[n] = actual->expr;
13470 gfc_init_se (&argse[n], NULL);
13472 if (lss != gfc_ss_terminator)
13474 gfc_copy_loopinfo_to_se (&argse[n], loop);
13475 /* Find the ss for the expression if it is there. */
13476 argse[n].ss = lss;
13477 gfc_mark_ss_chain_used (lss, 1);
13480 gfc_conv_expr (&argse[n], arg[n]);
13482 if (loop)
13483 lss = argse[n].ss;
13486 from = argse[0].expr;
13487 frompos = argse[1].expr;
13488 len = argse[2].expr;
13489 to = argse[3].expr;
13490 topos = argse[4].expr;
13492 /* The type of the result (TO). */
13493 type = TREE_TYPE (to);
13494 bitsize = build_int_cst (integer_type_node, TYPE_PRECISION (type));
13496 /* Optionally generate code for runtime argument check. */
13497 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
13499 tree nbits, below, ccond;
13500 tree fp = fold_convert (long_integer_type_node, frompos);
13501 tree ln = fold_convert (long_integer_type_node, len);
13502 tree tp = fold_convert (long_integer_type_node, topos);
13503 below = fold_build2_loc (input_location, LT_EXPR,
13504 logical_type_node, frompos,
13505 build_int_cst (TREE_TYPE (frompos), 0));
13506 above = fold_build2_loc (input_location, GT_EXPR,
13507 logical_type_node, frompos,
13508 fold_convert (TREE_TYPE (frompos), bitsize));
13509 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
13510 logical_type_node, below, above);
13511 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
13512 &arg[1]->where,
13513 "FROMPOS argument (%ld) out of range 0:%d "
13514 "in intrinsic MVBITS", fp, bitsize);
13515 below = fold_build2_loc (input_location, LT_EXPR,
13516 logical_type_node, len,
13517 build_int_cst (TREE_TYPE (len), 0));
13518 above = fold_build2_loc (input_location, GT_EXPR,
13519 logical_type_node, len,
13520 fold_convert (TREE_TYPE (len), bitsize));
13521 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
13522 logical_type_node, below, above);
13523 gfc_trans_runtime_check (true, false, ccond, &argse[2].pre,
13524 &arg[2]->where,
13525 "LEN argument (%ld) out of range 0:%d "
13526 "in intrinsic MVBITS", ln, bitsize);
13527 below = fold_build2_loc (input_location, LT_EXPR,
13528 logical_type_node, topos,
13529 build_int_cst (TREE_TYPE (topos), 0));
13530 above = fold_build2_loc (input_location, GT_EXPR,
13531 logical_type_node, topos,
13532 fold_convert (TREE_TYPE (topos), bitsize));
13533 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
13534 logical_type_node, below, above);
13535 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
13536 &arg[4]->where,
13537 "TOPOS argument (%ld) out of range 0:%d "
13538 "in intrinsic MVBITS", tp, bitsize);
13540 /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
13541 integers. Additions below cannot overflow. */
13542 nbits = fold_convert (long_integer_type_node, bitsize);
13543 above = fold_build2_loc (input_location, PLUS_EXPR,
13544 long_integer_type_node, fp, ln);
13545 ccond = fold_build2_loc (input_location, GT_EXPR,
13546 logical_type_node, above, nbits);
13547 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
13548 &arg[1]->where,
13549 "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
13550 "in intrinsic MVBITS", fp, ln, bitsize);
13551 above = fold_build2_loc (input_location, PLUS_EXPR,
13552 long_integer_type_node, tp, ln);
13553 ccond = fold_build2_loc (input_location, GT_EXPR,
13554 logical_type_node, above, nbits);
13555 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
13556 &arg[4]->where,
13557 "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
13558 "in intrinsic MVBITS", tp, ln, bitsize);
13561 for (n = 0; n < 5; n++)
13563 gfc_add_block_to_block (&se->pre, &argse[n].pre);
13564 gfc_add_block_to_block (&se->post, &argse[n].post);
13567 /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
13568 above = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
13569 len, fold_convert (TREE_TYPE (len), bitsize));
13570 mask1 = build_int_cst (type, -1);
13571 mask2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13572 build_int_cst (type, 1), len);
13573 mask2 = fold_build2_loc (input_location, MINUS_EXPR, type,
13574 mask2, build_int_cst (type, 1));
13575 lenmask = fold_build3_loc (input_location, COND_EXPR, type,
13576 above, mask1, mask2);
13578 /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
13579 * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
13580 * not strictly necessary; artificial bits from rshift will be masked. */
13581 utype = unsigned_type_for (type);
13582 newbits = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
13583 fold_convert (utype, from), frompos);
13584 newbits = fold_build2_loc (input_location, BIT_AND_EXPR, type,
13585 fold_convert (type, newbits), lenmask);
13586 newbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13587 newbits, topos);
13589 /* oldbits = TO & (~(lenmask << TOPOS)). */
13590 oldbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13591 lenmask, topos);
13592 oldbits = fold_build1_loc (input_location, BIT_NOT_EXPR, type, oldbits);
13593 oldbits = fold_build2_loc (input_location, BIT_AND_EXPR, type, oldbits, to);
13595 /* TO = newbits | oldbits. */
13596 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
13597 oldbits, newbits);
13599 /* Return the assignment. */
13600 se->expr = fold_build2_loc (input_location, MODIFY_EXPR,
13601 void_type_node, to, se->expr);
13605 static tree
13606 conv_intrinsic_move_alloc (gfc_code *code)
13608 stmtblock_t block;
13609 gfc_expr *from_expr, *to_expr;
13610 gfc_se from_se, to_se;
13611 tree tmp, to_tree, from_tree;
13612 bool coarray, from_is_class, from_is_scalar;
13614 gfc_start_block (&block);
13616 from_expr = code->ext.actual->expr;
13617 to_expr = code->ext.actual->next->expr;
13619 gfc_init_se (&from_se, NULL);
13620 gfc_init_se (&to_se, NULL);
13622 gcc_assert (from_expr->ts.type != BT_CLASS || to_expr->ts.type == BT_CLASS);
13623 coarray = from_expr->corank != 0;
13625 from_is_class = from_expr->ts.type == BT_CLASS;
13626 from_is_scalar = from_expr->rank == 0 && !coarray;
13627 if (to_expr->ts.type == BT_CLASS || from_is_scalar)
13629 from_se.want_pointer = 1;
13630 if (from_is_scalar)
13631 gfc_conv_expr (&from_se, from_expr);
13632 else
13633 gfc_conv_expr_descriptor (&from_se, from_expr);
13634 if (from_is_class)
13635 from_tree = gfc_class_data_get (from_se.expr);
13636 else
13638 gfc_symbol *vtab;
13639 from_tree = from_se.expr;
13641 if (to_expr->ts.type == BT_CLASS)
13643 vtab = gfc_find_vtab (&from_expr->ts);
13644 gcc_assert (vtab);
13645 from_se.expr = gfc_get_symbol_decl (vtab);
13648 gfc_add_block_to_block (&block, &from_se.pre);
13650 to_se.want_pointer = 1;
13651 if (to_expr->rank == 0)
13652 gfc_conv_expr (&to_se, to_expr);
13653 else
13654 gfc_conv_expr_descriptor (&to_se, to_expr);
13655 if (to_expr->ts.type == BT_CLASS)
13656 to_tree = gfc_class_data_get (to_se.expr);
13657 else
13658 to_tree = to_se.expr;
13659 gfc_add_block_to_block (&block, &to_se.pre);
13661 /* Deallocate "to". */
13662 if (to_expr->rank == 0)
13665 = gfc_deallocate_scalar_with_status (to_tree, NULL_TREE, NULL_TREE,
13666 true, to_expr, to_expr->ts);
13667 gfc_add_expr_to_block (&block, tmp);
13670 if (from_is_scalar)
13672 /* Assign (_data) pointers. */
13673 gfc_add_modify_loc (input_location, &block, to_tree,
13674 fold_convert (TREE_TYPE (to_tree), from_tree));
13676 /* Set "from" to NULL. */
13677 gfc_add_modify_loc (input_location, &block, from_tree,
13678 fold_convert (TREE_TYPE (from_tree),
13679 null_pointer_node));
13681 gfc_add_block_to_block (&block, &from_se.post);
13683 gfc_add_block_to_block (&block, &to_se.post);
13685 /* Set _vptr. */
13686 if (to_expr->ts.type == BT_CLASS)
13688 gfc_class_set_vptr (&block, to_se.expr, from_se.expr);
13689 if (from_is_class)
13690 gfc_reset_vptr (&block, from_expr);
13691 if (UNLIMITED_POLY (to_expr))
13693 tree to_len = gfc_class_len_get (to_se.class_container);
13694 tmp = from_expr->ts.type == BT_CHARACTER && from_se.string_length
13695 ? from_se.string_length
13696 : size_zero_node;
13697 gfc_add_modify_loc (input_location, &block, to_len,
13698 fold_convert (TREE_TYPE (to_len), tmp));
13702 if (from_is_scalar)
13704 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
13706 gfc_add_modify_loc (input_location, &block, to_se.string_length,
13707 fold_convert (TREE_TYPE (to_se.string_length),
13708 from_se.string_length));
13709 if (from_expr->ts.deferred)
13710 gfc_add_modify_loc (
13711 input_location, &block, from_se.string_length,
13712 build_int_cst (TREE_TYPE (from_se.string_length), 0));
13714 if (UNLIMITED_POLY (from_expr))
13715 gfc_reset_len (&block, from_expr);
13717 return gfc_finish_block (&block);
13720 gfc_init_se (&to_se, NULL);
13721 gfc_init_se (&from_se, NULL);
13724 /* Deallocate "to". */
13725 if (from_expr->rank == 0)
13727 to_se.want_coarray = 1;
13728 from_se.want_coarray = 1;
13730 gfc_conv_expr_descriptor (&to_se, to_expr);
13731 gfc_conv_expr_descriptor (&from_se, from_expr);
13733 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
13734 is an image control "statement", cf. IR F08/0040 in 12-006A. */
13735 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
13737 tree cond;
13739 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
13740 NULL_TREE, NULL_TREE, true, to_expr,
13741 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
13742 gfc_add_expr_to_block (&block, tmp);
13744 tmp = gfc_conv_descriptor_data_get (to_se.expr);
13745 cond = fold_build2_loc (input_location, EQ_EXPR,
13746 logical_type_node, tmp,
13747 fold_convert (TREE_TYPE (tmp),
13748 null_pointer_node));
13749 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
13750 3, null_pointer_node, null_pointer_node,
13751 integer_zero_node);
13753 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
13754 tmp, build_empty_stmt (input_location));
13755 gfc_add_expr_to_block (&block, tmp);
13757 else
13759 if (to_expr->ts.type == BT_DERIVED
13760 && to_expr->ts.u.derived->attr.alloc_comp)
13762 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
13763 to_se.expr, to_expr->rank);
13764 gfc_add_expr_to_block (&block, tmp);
13767 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
13768 NULL_TREE, NULL_TREE, true, to_expr,
13769 GFC_CAF_COARRAY_NOCOARRAY);
13770 gfc_add_expr_to_block (&block, tmp);
13773 /* Copy the array descriptor data. */
13774 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
13776 /* Set "from" to NULL. */
13777 tmp = gfc_conv_descriptor_data_get (from_se.expr);
13778 gfc_add_modify_loc (input_location, &block, tmp,
13779 fold_convert (TREE_TYPE (tmp), null_pointer_node));
13782 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
13784 gfc_add_modify_loc (input_location, &block, to_se.string_length,
13785 fold_convert (TREE_TYPE (to_se.string_length),
13786 from_se.string_length));
13787 if (from_expr->ts.deferred)
13788 gfc_add_modify_loc (input_location, &block, from_se.string_length,
13789 build_int_cst (TREE_TYPE (from_se.string_length), 0));
13792 return gfc_finish_block (&block);
13796 tree
13797 gfc_conv_intrinsic_subroutine (gfc_code *code)
13799 tree res;
13801 gcc_assert (code->resolved_isym);
13803 switch (code->resolved_isym->id)
13805 case GFC_ISYM_MOVE_ALLOC:
13806 res = conv_intrinsic_move_alloc (code);
13807 break;
13809 case GFC_ISYM_ATOMIC_CAS:
13810 res = conv_intrinsic_atomic_cas (code);
13811 break;
13813 case GFC_ISYM_ATOMIC_ADD:
13814 case GFC_ISYM_ATOMIC_AND:
13815 case GFC_ISYM_ATOMIC_DEF:
13816 case GFC_ISYM_ATOMIC_OR:
13817 case GFC_ISYM_ATOMIC_XOR:
13818 case GFC_ISYM_ATOMIC_FETCH_ADD:
13819 case GFC_ISYM_ATOMIC_FETCH_AND:
13820 case GFC_ISYM_ATOMIC_FETCH_OR:
13821 case GFC_ISYM_ATOMIC_FETCH_XOR:
13822 res = conv_intrinsic_atomic_op (code);
13823 break;
13825 case GFC_ISYM_ATOMIC_REF:
13826 res = conv_intrinsic_atomic_ref (code);
13827 break;
13829 case GFC_ISYM_EVENT_QUERY:
13830 res = conv_intrinsic_event_query (code);
13831 break;
13833 case GFC_ISYM_C_F_POINTER:
13834 case GFC_ISYM_C_F_PROCPOINTER:
13835 res = conv_isocbinding_subroutine (code);
13836 break;
13838 case GFC_ISYM_CAF_SEND:
13839 res = conv_caf_send (code);
13840 break;
13842 case GFC_ISYM_CO_BROADCAST:
13843 case GFC_ISYM_CO_MIN:
13844 case GFC_ISYM_CO_MAX:
13845 case GFC_ISYM_CO_REDUCE:
13846 case GFC_ISYM_CO_SUM:
13847 res = conv_co_collective (code);
13848 break;
13850 case GFC_ISYM_FREE:
13851 res = conv_intrinsic_free (code);
13852 break;
13854 case GFC_ISYM_RANDOM_INIT:
13855 res = conv_intrinsic_random_init (code);
13856 break;
13858 case GFC_ISYM_KILL:
13859 res = conv_intrinsic_kill_sub (code);
13860 break;
13862 case GFC_ISYM_MVBITS:
13863 res = NULL_TREE;
13864 break;
13866 case GFC_ISYM_SYSTEM_CLOCK:
13867 res = conv_intrinsic_system_clock (code);
13868 break;
13870 default:
13871 res = NULL_TREE;
13872 break;
13875 return res;
13878 #include "gt-fortran-trans-intrinsic.h"