20180-12-08 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob40a74916bb835727d4fae7f204e3c476c396a043
1 /* Intrinsic translation
2 Copyright (C) 2002-2018 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.c-- 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 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
45 /* This maps Fortran intrinsic math functions to external library or GCC
46 builtin functions. */
47 typedef struct GTY(()) gfc_intrinsic_map_t {
48 /* The explicit enum is required to work around inadequacies in the
49 garbage collection/gengtype parsing mechanism. */
50 enum gfc_isym_id id;
52 /* Enum value from the "language-independent", aka C-centric, part
53 of gcc, or END_BUILTINS of no such value set. */
54 enum built_in_function float_built_in;
55 enum built_in_function double_built_in;
56 enum built_in_function long_double_built_in;
57 enum built_in_function complex_float_built_in;
58 enum built_in_function complex_double_built_in;
59 enum built_in_function complex_long_double_built_in;
61 /* True if the naming pattern is to prepend "c" for complex and
62 append "f" for kind=4. False if the naming pattern is to
63 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
64 bool libm_name;
66 /* True if a complex version of the function exists. */
67 bool complex_available;
69 /* True if the function should be marked const. */
70 bool is_constant;
72 /* The base library name of this function. */
73 const char *name;
75 /* Cache decls created for the various operand types. */
76 tree real4_decl;
77 tree real8_decl;
78 tree real10_decl;
79 tree real16_decl;
80 tree complex4_decl;
81 tree complex8_decl;
82 tree complex10_decl;
83 tree complex16_decl;
85 gfc_intrinsic_map_t;
87 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
88 defines complex variants of all of the entries in mathbuiltins.def
89 except for atan2. */
90 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
91 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
92 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
93 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
94 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
96 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
97 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
98 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
99 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
100 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
102 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
103 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
105 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
106 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
108 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
109 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
110 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
111 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
112 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
114 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
116 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
117 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
118 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
119 #include "mathbuiltins.def"
121 /* Functions in libgfortran. */
122 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
124 /* End the list. */
125 LIB_FUNCTION (NONE, NULL, false)
128 #undef OTHER_BUILTIN
129 #undef LIB_FUNCTION
130 #undef DEFINE_MATH_BUILTIN
131 #undef DEFINE_MATH_BUILTIN_C
134 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
137 /* Find the correct variant of a given builtin from its argument. */
138 static tree
139 builtin_decl_for_precision (enum built_in_function base_built_in,
140 int precision)
142 enum built_in_function i = END_BUILTINS;
144 gfc_intrinsic_map_t *m;
145 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
148 if (precision == TYPE_PRECISION (float_type_node))
149 i = m->float_built_in;
150 else if (precision == TYPE_PRECISION (double_type_node))
151 i = m->double_built_in;
152 else if (precision == TYPE_PRECISION (long_double_type_node))
153 i = m->long_double_built_in;
154 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
156 /* Special treatment, because it is not exactly a built-in, but
157 a library function. */
158 return m->real16_decl;
161 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
165 tree
166 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
167 int kind)
169 int i = gfc_validate_kind (BT_REAL, kind, false);
171 if (gfc_real_kinds[i].c_float128)
173 /* For __float128, the story is a bit different, because we return
174 a decl to a library function rather than a built-in. */
175 gfc_intrinsic_map_t *m;
176 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
179 return m->real16_decl;
182 return builtin_decl_for_precision (double_built_in,
183 gfc_real_kinds[i].mode_precision);
187 /* Evaluate the arguments to an intrinsic function. The value
188 of NARGS may be less than the actual number of arguments in EXPR
189 to allow optional "KIND" arguments that are not included in the
190 generated code to be ignored. */
192 static void
193 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
194 tree *argarray, int nargs)
196 gfc_actual_arglist *actual;
197 gfc_expr *e;
198 gfc_intrinsic_arg *formal;
199 gfc_se argse;
200 int curr_arg;
202 formal = expr->value.function.isym->formal;
203 actual = expr->value.function.actual;
205 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
206 actual = actual->next,
207 formal = formal ? formal->next : NULL)
209 gcc_assert (actual);
210 e = actual->expr;
211 /* Skip omitted optional arguments. */
212 if (!e)
214 --curr_arg;
215 continue;
218 /* Evaluate the parameter. This will substitute scalarized
219 references automatically. */
220 gfc_init_se (&argse, se);
222 if (e->ts.type == BT_CHARACTER)
224 gfc_conv_expr (&argse, e);
225 gfc_conv_string_parameter (&argse);
226 argarray[curr_arg++] = argse.string_length;
227 gcc_assert (curr_arg < nargs);
229 else
230 gfc_conv_expr_val (&argse, e);
232 /* If an optional argument is itself an optional dummy argument,
233 check its presence and substitute a null if absent. */
234 if (e->expr_type == EXPR_VARIABLE
235 && e->symtree->n.sym->attr.optional
236 && formal
237 && formal->optional)
238 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
240 gfc_add_block_to_block (&se->pre, &argse.pre);
241 gfc_add_block_to_block (&se->post, &argse.post);
242 argarray[curr_arg] = argse.expr;
246 /* Count the number of actual arguments to the intrinsic function EXPR
247 including any "hidden" string length arguments. */
249 static unsigned int
250 gfc_intrinsic_argument_list_length (gfc_expr *expr)
252 int n = 0;
253 gfc_actual_arglist *actual;
255 for (actual = expr->value.function.actual; actual; actual = actual->next)
257 if (!actual->expr)
258 continue;
260 if (actual->expr->ts.type == BT_CHARACTER)
261 n += 2;
262 else
263 n++;
266 return n;
270 /* Conversions between different types are output by the frontend as
271 intrinsic functions. We implement these directly with inline code. */
273 static void
274 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
276 tree type;
277 tree *args;
278 int nargs;
280 nargs = gfc_intrinsic_argument_list_length (expr);
281 args = XALLOCAVEC (tree, nargs);
283 /* Evaluate all the arguments passed. Whilst we're only interested in the
284 first one here, there are other parts of the front-end that assume this
285 and will trigger an ICE if it's not the case. */
286 type = gfc_typenode_for_spec (&expr->ts);
287 gcc_assert (expr->value.function.actual->expr);
288 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
290 /* Conversion between character kinds involves a call to a library
291 function. */
292 if (expr->ts.type == BT_CHARACTER)
294 tree fndecl, var, addr, tmp;
296 if (expr->ts.kind == 1
297 && expr->value.function.actual->expr->ts.kind == 4)
298 fndecl = gfor_fndecl_convert_char4_to_char1;
299 else if (expr->ts.kind == 4
300 && expr->value.function.actual->expr->ts.kind == 1)
301 fndecl = gfor_fndecl_convert_char1_to_char4;
302 else
303 gcc_unreachable ();
305 /* Create the variable storing the converted value. */
306 type = gfc_get_pchar_type (expr->ts.kind);
307 var = gfc_create_var (type, "str");
308 addr = gfc_build_addr_expr (build_pointer_type (type), var);
310 /* Call the library function that will perform the conversion. */
311 gcc_assert (nargs >= 2);
312 tmp = build_call_expr_loc (input_location,
313 fndecl, 3, addr, args[0], args[1]);
314 gfc_add_expr_to_block (&se->pre, tmp);
316 /* Free the temporary afterwards. */
317 tmp = gfc_call_free (var);
318 gfc_add_expr_to_block (&se->post, tmp);
320 se->expr = var;
321 se->string_length = args[0];
323 return;
326 /* Conversion from complex to non-complex involves taking the real
327 component of the value. */
328 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
329 && expr->ts.type != BT_COMPLEX)
331 tree artype;
333 artype = TREE_TYPE (TREE_TYPE (args[0]));
334 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
335 args[0]);
338 se->expr = convert (type, args[0]);
341 /* This is needed because the gcc backend only implements
342 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
343 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
344 Similarly for CEILING. */
346 static tree
347 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
349 tree tmp;
350 tree cond;
351 tree argtype;
352 tree intval;
354 argtype = TREE_TYPE (arg);
355 arg = gfc_evaluate_now (arg, pblock);
357 intval = convert (type, arg);
358 intval = gfc_evaluate_now (intval, pblock);
360 tmp = convert (argtype, intval);
361 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
362 logical_type_node, tmp, arg);
364 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
365 intval, build_int_cst (type, 1));
366 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
367 return tmp;
371 /* Round to nearest integer, away from zero. */
373 static tree
374 build_round_expr (tree arg, tree restype)
376 tree argtype;
377 tree fn;
378 int argprec, resprec;
380 argtype = TREE_TYPE (arg);
381 argprec = TYPE_PRECISION (argtype);
382 resprec = TYPE_PRECISION (restype);
384 /* Depending on the type of the result, choose the int intrinsic
385 (iround, available only as a builtin, therefore cannot use it for
386 __float128), long int intrinsic (lround family) or long long
387 intrinsic (llround). We might also need to convert the result
388 afterwards. */
389 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
390 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
391 else if (resprec <= LONG_TYPE_SIZE)
392 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
393 else if (resprec <= LONG_LONG_TYPE_SIZE)
394 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
395 else
396 gcc_unreachable ();
398 return fold_convert (restype, build_call_expr_loc (input_location,
399 fn, 1, arg));
403 /* Convert a real to an integer using a specific rounding mode.
404 Ideally we would just build the corresponding GENERIC node,
405 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
407 static tree
408 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
409 enum rounding_mode op)
411 switch (op)
413 case RND_FLOOR:
414 return build_fixbound_expr (pblock, arg, type, 0);
416 case RND_CEIL:
417 return build_fixbound_expr (pblock, arg, type, 1);
419 case RND_ROUND:
420 return build_round_expr (arg, type);
422 case RND_TRUNC:
423 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
425 default:
426 gcc_unreachable ();
431 /* Round a real value using the specified rounding mode.
432 We use a temporary integer of that same kind size as the result.
433 Values larger than those that can be represented by this kind are
434 unchanged, as they will not be accurate enough to represent the
435 rounding.
436 huge = HUGE (KIND (a))
437 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
440 static void
441 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
443 tree type;
444 tree itype;
445 tree arg[2];
446 tree tmp;
447 tree cond;
448 tree decl;
449 mpfr_t huge;
450 int n, nargs;
451 int kind;
453 kind = expr->ts.kind;
454 nargs = gfc_intrinsic_argument_list_length (expr);
456 decl = NULL_TREE;
457 /* We have builtin functions for some cases. */
458 switch (op)
460 case RND_ROUND:
461 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
462 break;
464 case RND_TRUNC:
465 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
466 break;
468 default:
469 gcc_unreachable ();
472 /* Evaluate the argument. */
473 gcc_assert (expr->value.function.actual->expr);
474 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
476 /* Use a builtin function if one exists. */
477 if (decl != NULL_TREE)
479 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
480 return;
483 /* This code is probably redundant, but we'll keep it lying around just
484 in case. */
485 type = gfc_typenode_for_spec (&expr->ts);
486 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
488 /* Test if the value is too large to handle sensibly. */
489 gfc_set_model_kind (kind);
490 mpfr_init (huge);
491 n = gfc_validate_kind (BT_INTEGER, kind, false);
492 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
493 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
494 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
495 tmp);
497 mpfr_neg (huge, huge, GFC_RND_MODE);
498 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
499 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
500 tmp);
501 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
502 cond, tmp);
503 itype = gfc_get_int_type (kind);
505 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
506 tmp = convert (type, tmp);
507 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
508 arg[0]);
509 mpfr_clear (huge);
513 /* Convert to an integer using the specified rounding mode. */
515 static void
516 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
518 tree type;
519 tree *args;
520 int nargs;
522 nargs = gfc_intrinsic_argument_list_length (expr);
523 args = XALLOCAVEC (tree, nargs);
525 /* Evaluate the argument, we process all arguments even though we only
526 use the first one for code generation purposes. */
527 type = gfc_typenode_for_spec (&expr->ts);
528 gcc_assert (expr->value.function.actual->expr);
529 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
531 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
533 /* Conversion to a different integer kind. */
534 se->expr = convert (type, args[0]);
536 else
538 /* Conversion from complex to non-complex involves taking the real
539 component of the value. */
540 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
541 && expr->ts.type != BT_COMPLEX)
543 tree artype;
545 artype = TREE_TYPE (TREE_TYPE (args[0]));
546 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
547 args[0]);
550 se->expr = build_fix_expr (&se->pre, args[0], type, op);
555 /* Get the imaginary component of a value. */
557 static void
558 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
560 tree arg;
562 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
563 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
564 TREE_TYPE (TREE_TYPE (arg)), arg);
568 /* Get the complex conjugate of a value. */
570 static void
571 gfc_conv_intrinsic_conjg (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, CONJ_EXPR, TREE_TYPE (arg), arg);
581 static tree
582 define_quad_builtin (const char *name, tree type, bool is_const)
584 tree fndecl;
585 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
586 type);
588 /* Mark the decl as external. */
589 DECL_EXTERNAL (fndecl) = 1;
590 TREE_PUBLIC (fndecl) = 1;
592 /* Mark it __attribute__((const)). */
593 TREE_READONLY (fndecl) = is_const;
595 rest_of_decl_compilation (fndecl, 1, 0);
597 return fndecl;
600 /* Add SIMD attribute for FNDECL built-in if the built-in
601 name is in VECTORIZED_BUILTINS. */
603 static void
604 add_simd_flag_for_built_in (tree fndecl)
606 if (gfc_vectorized_builtins == NULL
607 || fndecl == NULL_TREE)
608 return;
610 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
611 int *clauses = gfc_vectorized_builtins->get (name);
612 if (clauses)
614 for (unsigned i = 0; i < 3; i++)
615 if (*clauses & (1 << i))
617 gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
618 tree omp_clause = NULL_TREE;
619 if (simd_type == SIMD_NONE)
620 ; /* No SIMD clause. */
621 else
623 omp_clause_code code
624 = (simd_type == SIMD_INBRANCH
625 ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
626 omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
627 omp_clause = build_tree_list (NULL_TREE, omp_clause);
630 DECL_ATTRIBUTES (fndecl)
631 = tree_cons (get_identifier ("omp declare simd"), omp_clause,
632 DECL_ATTRIBUTES (fndecl));
637 /* Set SIMD attribute to all built-in functions that are mentioned
638 in gfc_vectorized_builtins vector. */
640 void
641 gfc_adjust_builtins (void)
643 gfc_intrinsic_map_t *m;
644 for (m = gfc_intrinsic_map;
645 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
647 add_simd_flag_for_built_in (m->real4_decl);
648 add_simd_flag_for_built_in (m->complex4_decl);
649 add_simd_flag_for_built_in (m->real8_decl);
650 add_simd_flag_for_built_in (m->complex8_decl);
651 add_simd_flag_for_built_in (m->real10_decl);
652 add_simd_flag_for_built_in (m->complex10_decl);
653 add_simd_flag_for_built_in (m->real16_decl);
654 add_simd_flag_for_built_in (m->complex16_decl);
655 add_simd_flag_for_built_in (m->real16_decl);
656 add_simd_flag_for_built_in (m->complex16_decl);
659 /* Release all strings. */
660 if (gfc_vectorized_builtins != NULL)
662 for (hash_map<nofree_string_hash, int>::iterator it
663 = gfc_vectorized_builtins->begin ();
664 it != gfc_vectorized_builtins->end (); ++it)
665 free (CONST_CAST (char *, (*it).first));
667 delete gfc_vectorized_builtins;
668 gfc_vectorized_builtins = NULL;
672 /* Initialize function decls for library functions. The external functions
673 are created as required. Builtin functions are added here. */
675 void
676 gfc_build_intrinsic_lib_fndecls (void)
678 gfc_intrinsic_map_t *m;
679 tree quad_decls[END_BUILTINS + 1];
681 if (gfc_real16_is_float128)
683 /* If we have soft-float types, we create the decls for their
684 C99-like library functions. For now, we only handle __float128
685 q-suffixed functions. */
687 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
688 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
690 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
692 type = gfc_float128_type_node;
693 complex_type = gfc_complex_float128_type_node;
694 /* type (*) (type) */
695 func_1 = build_function_type_list (type, type, NULL_TREE);
696 /* int (*) (type) */
697 func_iround = build_function_type_list (integer_type_node,
698 type, NULL_TREE);
699 /* long (*) (type) */
700 func_lround = build_function_type_list (long_integer_type_node,
701 type, NULL_TREE);
702 /* long long (*) (type) */
703 func_llround = build_function_type_list (long_long_integer_type_node,
704 type, NULL_TREE);
705 /* type (*) (type, type) */
706 func_2 = build_function_type_list (type, type, type, NULL_TREE);
707 /* type (*) (type, &int) */
708 func_frexp
709 = build_function_type_list (type,
710 type,
711 build_pointer_type (integer_type_node),
712 NULL_TREE);
713 /* type (*) (type, int) */
714 func_scalbn = build_function_type_list (type,
715 type, integer_type_node, NULL_TREE);
716 /* type (*) (complex type) */
717 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
718 /* complex type (*) (complex type, complex type) */
719 func_cpow
720 = build_function_type_list (complex_type,
721 complex_type, complex_type, NULL_TREE);
723 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
724 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
725 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
727 /* Only these built-ins are actually needed here. These are used directly
728 from the code, when calling builtin_decl_for_precision() or
729 builtin_decl_for_float_type(). The others are all constructed by
730 gfc_get_intrinsic_lib_fndecl(). */
731 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
732 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
734 #include "mathbuiltins.def"
736 #undef OTHER_BUILTIN
737 #undef LIB_FUNCTION
738 #undef DEFINE_MATH_BUILTIN
739 #undef DEFINE_MATH_BUILTIN_C
741 /* There is one built-in we defined manually, because it gets called
742 with builtin_decl_for_precision() or builtin_decl_for_float_type()
743 even though it is not an OTHER_BUILTIN: it is SQRT. */
744 quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
748 /* Add GCC builtin functions. */
749 for (m = gfc_intrinsic_map;
750 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
752 if (m->float_built_in != END_BUILTINS)
753 m->real4_decl = builtin_decl_explicit (m->float_built_in);
754 if (m->complex_float_built_in != END_BUILTINS)
755 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
756 if (m->double_built_in != END_BUILTINS)
757 m->real8_decl = builtin_decl_explicit (m->double_built_in);
758 if (m->complex_double_built_in != END_BUILTINS)
759 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
761 /* If real(kind=10) exists, it is always long double. */
762 if (m->long_double_built_in != END_BUILTINS)
763 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
764 if (m->complex_long_double_built_in != END_BUILTINS)
765 m->complex10_decl
766 = builtin_decl_explicit (m->complex_long_double_built_in);
768 if (!gfc_real16_is_float128)
770 if (m->long_double_built_in != END_BUILTINS)
771 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
772 if (m->complex_long_double_built_in != END_BUILTINS)
773 m->complex16_decl
774 = builtin_decl_explicit (m->complex_long_double_built_in);
776 else if (quad_decls[m->double_built_in] != NULL_TREE)
778 /* Quad-precision function calls are constructed when first
779 needed by builtin_decl_for_precision(), except for those
780 that will be used directly (define by OTHER_BUILTIN). */
781 m->real16_decl = quad_decls[m->double_built_in];
783 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
785 /* Same thing for the complex ones. */
786 m->complex16_decl = quad_decls[m->double_built_in];
792 /* Create a fndecl for a simple intrinsic library function. */
794 static tree
795 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
797 tree type;
798 vec<tree, va_gc> *argtypes;
799 tree fndecl;
800 gfc_actual_arglist *actual;
801 tree *pdecl;
802 gfc_typespec *ts;
803 char name[GFC_MAX_SYMBOL_LEN + 3];
805 ts = &expr->ts;
806 if (ts->type == BT_REAL)
808 switch (ts->kind)
810 case 4:
811 pdecl = &m->real4_decl;
812 break;
813 case 8:
814 pdecl = &m->real8_decl;
815 break;
816 case 10:
817 pdecl = &m->real10_decl;
818 break;
819 case 16:
820 pdecl = &m->real16_decl;
821 break;
822 default:
823 gcc_unreachable ();
826 else if (ts->type == BT_COMPLEX)
828 gcc_assert (m->complex_available);
830 switch (ts->kind)
832 case 4:
833 pdecl = &m->complex4_decl;
834 break;
835 case 8:
836 pdecl = &m->complex8_decl;
837 break;
838 case 10:
839 pdecl = &m->complex10_decl;
840 break;
841 case 16:
842 pdecl = &m->complex16_decl;
843 break;
844 default:
845 gcc_unreachable ();
848 else
849 gcc_unreachable ();
851 if (*pdecl)
852 return *pdecl;
854 if (m->libm_name)
856 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
857 if (gfc_real_kinds[n].c_float)
858 snprintf (name, sizeof (name), "%s%s%s",
859 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
860 else if (gfc_real_kinds[n].c_double)
861 snprintf (name, sizeof (name), "%s%s",
862 ts->type == BT_COMPLEX ? "c" : "", m->name);
863 else if (gfc_real_kinds[n].c_long_double)
864 snprintf (name, sizeof (name), "%s%s%s",
865 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
866 else if (gfc_real_kinds[n].c_float128)
867 snprintf (name, sizeof (name), "%s%s%s",
868 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
869 else
870 gcc_unreachable ();
872 else
874 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
875 ts->type == BT_COMPLEX ? 'c' : 'r',
876 ts->kind);
879 argtypes = NULL;
880 for (actual = expr->value.function.actual; actual; actual = actual->next)
882 type = gfc_typenode_for_spec (&actual->expr->ts);
883 vec_safe_push (argtypes, type);
885 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
886 fndecl = build_decl (input_location,
887 FUNCTION_DECL, get_identifier (name), type);
889 /* Mark the decl as external. */
890 DECL_EXTERNAL (fndecl) = 1;
891 TREE_PUBLIC (fndecl) = 1;
893 /* Mark it __attribute__((const)), if possible. */
894 TREE_READONLY (fndecl) = m->is_constant;
896 rest_of_decl_compilation (fndecl, 1, 0);
898 (*pdecl) = fndecl;
899 return fndecl;
903 /* Convert an intrinsic function into an external or builtin call. */
905 static void
906 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
908 gfc_intrinsic_map_t *m;
909 tree fndecl;
910 tree rettype;
911 tree *args;
912 unsigned int num_args;
913 gfc_isym_id id;
915 id = expr->value.function.isym->id;
916 /* Find the entry for this function. */
917 for (m = gfc_intrinsic_map;
918 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
920 if (id == m->id)
921 break;
924 if (m->id == GFC_ISYM_NONE)
926 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
927 expr->value.function.name, id);
930 /* Get the decl and generate the call. */
931 num_args = gfc_intrinsic_argument_list_length (expr);
932 args = XALLOCAVEC (tree, num_args);
934 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
935 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
936 rettype = TREE_TYPE (TREE_TYPE (fndecl));
938 fndecl = build_addr (fndecl);
939 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
943 /* If bounds-checking is enabled, create code to verify at runtime that the
944 string lengths for both expressions are the same (needed for e.g. MERGE).
945 If bounds-checking is not enabled, does nothing. */
947 void
948 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
949 tree a, tree b, stmtblock_t* target)
951 tree cond;
952 tree name;
954 /* If bounds-checking is disabled, do nothing. */
955 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
956 return;
958 /* Compare the two string lengths. */
959 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
961 /* Output the runtime-check. */
962 name = gfc_build_cstring_const (intr_name);
963 name = gfc_build_addr_expr (pchar_type_node, name);
964 gfc_trans_runtime_check (true, false, cond, target, where,
965 "Unequal character lengths (%ld/%ld) in %s",
966 fold_convert (long_integer_type_node, a),
967 fold_convert (long_integer_type_node, b), name);
971 /* The EXPONENT(X) intrinsic function is translated into
972 int ret;
973 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
974 so that if X is a NaN or infinity, the result is HUGE(0).
977 static void
978 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
980 tree arg, type, res, tmp, frexp, cond, huge;
981 int i;
983 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
984 expr->value.function.actual->expr->ts.kind);
986 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
987 arg = gfc_evaluate_now (arg, &se->pre);
989 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
990 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
991 cond = build_call_expr_loc (input_location,
992 builtin_decl_explicit (BUILT_IN_ISFINITE),
993 1, arg);
995 res = gfc_create_var (integer_type_node, NULL);
996 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
997 gfc_build_addr_expr (NULL_TREE, res));
998 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
999 tmp, res);
1000 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
1001 cond, tmp, huge);
1003 type = gfc_typenode_for_spec (&expr->ts);
1004 se->expr = fold_convert (type, se->expr);
1008 /* Fill in the following structure
1009 struct caf_vector_t {
1010 size_t nvec; // size of the vector
1011 union {
1012 struct {
1013 void *vector;
1014 int kind;
1015 } v;
1016 struct {
1017 ptrdiff_t lower_bound;
1018 ptrdiff_t upper_bound;
1019 ptrdiff_t stride;
1020 } triplet;
1021 } u;
1022 } */
1024 static void
1025 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1026 tree lower, tree upper, tree stride,
1027 tree vector, int kind, tree nvec)
1029 tree field, type, tmp;
1031 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
1032 type = TREE_TYPE (desc);
1034 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1035 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1036 desc, field, NULL_TREE);
1037 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
1039 /* Access union. */
1040 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1041 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1042 desc, field, NULL_TREE);
1043 type = TREE_TYPE (desc);
1045 /* Access the inner struct. */
1046 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
1047 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1048 desc, field, NULL_TREE);
1049 type = TREE_TYPE (desc);
1051 if (vector != NULL_TREE)
1053 /* Set vector and kind. */
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), vector));
1058 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1059 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1060 desc, field, NULL_TREE);
1061 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1063 else
1065 /* Set dim.lower/upper/stride. */
1066 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1067 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1068 desc, field, NULL_TREE);
1069 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1071 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1072 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1073 desc, field, NULL_TREE);
1074 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1076 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1077 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1078 desc, field, NULL_TREE);
1079 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1084 static tree
1085 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1087 gfc_se argse;
1088 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1089 tree lbound, ubound, tmp;
1090 int i;
1092 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1094 for (i = 0; i < ar->dimen; i++)
1095 switch (ar->dimen_type[i])
1097 case DIMEN_RANGE:
1098 if (ar->end[i])
1100 gfc_init_se (&argse, NULL);
1101 gfc_conv_expr (&argse, ar->end[i]);
1102 gfc_add_block_to_block (block, &argse.pre);
1103 upper = gfc_evaluate_now (argse.expr, block);
1105 else
1106 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1107 if (ar->stride[i])
1109 gfc_init_se (&argse, NULL);
1110 gfc_conv_expr (&argse, ar->stride[i]);
1111 gfc_add_block_to_block (block, &argse.pre);
1112 stride = gfc_evaluate_now (argse.expr, block);
1114 else
1115 stride = gfc_index_one_node;
1117 /* Fall through. */
1118 case DIMEN_ELEMENT:
1119 if (ar->start[i])
1121 gfc_init_se (&argse, NULL);
1122 gfc_conv_expr (&argse, ar->start[i]);
1123 gfc_add_block_to_block (block, &argse.pre);
1124 lower = gfc_evaluate_now (argse.expr, block);
1126 else
1127 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1128 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1130 upper = lower;
1131 stride = gfc_index_one_node;
1133 vector = NULL_TREE;
1134 nvec = size_zero_node;
1135 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1136 vector, 0, nvec);
1137 break;
1139 case DIMEN_VECTOR:
1140 gfc_init_se (&argse, NULL);
1141 argse.descriptor_only = 1;
1142 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1143 gfc_add_block_to_block (block, &argse.pre);
1144 vector = argse.expr;
1145 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1146 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1147 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1148 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1149 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1150 TREE_TYPE (nvec), nvec, tmp);
1151 lower = gfc_index_zero_node;
1152 upper = gfc_index_zero_node;
1153 stride = gfc_index_zero_node;
1154 vector = gfc_conv_descriptor_data_get (vector);
1155 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1156 vector, ar->start[i]->ts.kind, nvec);
1157 break;
1158 default:
1159 gcc_unreachable();
1161 return gfc_build_addr_expr (NULL_TREE, var);
1165 static tree
1166 compute_component_offset (tree field, tree type)
1168 tree tmp;
1169 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1170 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1172 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1173 DECL_FIELD_BIT_OFFSET (field),
1174 bitsize_unit_node);
1175 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1177 else
1178 return DECL_FIELD_OFFSET (field);
1182 static tree
1183 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1185 gfc_ref *ref = expr->ref, *last_comp_ref;
1186 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1187 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1188 start, end, stride, vector, nvec;
1189 gfc_se se;
1190 bool ref_static_array = false;
1191 tree last_component_ref_tree = NULL_TREE;
1192 int i, last_type_n;
1194 if (expr->symtree)
1196 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1197 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1198 && !expr->symtree->n.sym->attr.pointer;
1201 /* Prevent uninit-warning. */
1202 reference_type = NULL_TREE;
1204 /* Skip refs upto the first coarray-ref. */
1205 last_comp_ref = NULL;
1206 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1208 /* Remember the type of components skipped. */
1209 if (ref->type == REF_COMPONENT)
1210 last_comp_ref = ref;
1211 ref = ref->next;
1213 /* When a component was skipped, get the type information of the last
1214 component ref, else get the type from the symbol. */
1215 if (last_comp_ref)
1217 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1218 last_type_n = last_comp_ref->u.c.component->ts.type;
1220 else
1222 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1223 last_type_n = expr->symtree->n.sym->ts.type;
1226 while (ref)
1228 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1229 && ref->u.ar.dimen == 0)
1231 /* Skip pure coindexes. */
1232 ref = ref->next;
1233 continue;
1235 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1236 reference_type = TREE_TYPE (tmp);
1238 if (caf_ref == NULL_TREE)
1239 caf_ref = tmp;
1241 /* Construct the chain of refs. */
1242 if (prev_caf_ref != NULL_TREE)
1244 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1245 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1246 TREE_TYPE (field), prev_caf_ref, field,
1247 NULL_TREE);
1248 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1249 tmp));
1251 prev_caf_ref = tmp;
1253 switch (ref->type)
1255 case REF_COMPONENT:
1256 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1257 last_type_n = ref->u.c.component->ts.type;
1258 /* Set the type of the ref. */
1259 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1260 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1261 TREE_TYPE (field), prev_caf_ref, field,
1262 NULL_TREE);
1263 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1264 GFC_CAF_REF_COMPONENT));
1266 /* Ref the c in union u. */
1267 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1268 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1269 TREE_TYPE (field), prev_caf_ref, field,
1270 NULL_TREE);
1271 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1272 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1273 TREE_TYPE (field), tmp, field,
1274 NULL_TREE);
1276 /* Set the offset. */
1277 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1278 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1279 TREE_TYPE (field), inner_struct, field,
1280 NULL_TREE);
1281 /* Computing the offset is somewhat harder. The bit_offset has to be
1282 taken into account. When the bit_offset in the field_decl is non-
1283 null, divide it by the bitsize_unit and add it to the regular
1284 offset. */
1285 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1286 TREE_TYPE (tmp));
1287 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1289 /* Set caf_token_offset. */
1290 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1291 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1292 TREE_TYPE (field), inner_struct, field,
1293 NULL_TREE);
1294 if ((ref->u.c.component->attr.allocatable
1295 || ref->u.c.component->attr.pointer)
1296 && ref->u.c.component->attr.dimension)
1298 tree arr_desc_token_offset;
1299 /* Get the token field from the descriptor. */
1300 arr_desc_token_offset = TREE_OPERAND (
1301 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1302 arr_desc_token_offset
1303 = compute_component_offset (arr_desc_token_offset,
1304 TREE_TYPE (tmp));
1305 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1306 TREE_TYPE (tmp2), tmp2,
1307 arr_desc_token_offset);
1309 else if (ref->u.c.component->caf_token)
1310 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1311 TREE_TYPE (tmp));
1312 else
1313 tmp2 = integer_zero_node;
1314 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1316 /* Remember whether this ref was to a non-allocatable/non-pointer
1317 component so the next array ref can be tailored correctly. */
1318 ref_static_array = !ref->u.c.component->attr.allocatable
1319 && !ref->u.c.component->attr.pointer;
1320 last_component_ref_tree = ref_static_array
1321 ? ref->u.c.component->backend_decl : NULL_TREE;
1322 break;
1323 case REF_ARRAY:
1324 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1325 ref_static_array = false;
1326 /* Set the type of the ref. */
1327 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1328 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1329 TREE_TYPE (field), prev_caf_ref, field,
1330 NULL_TREE);
1331 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1332 ref_static_array
1333 ? GFC_CAF_REF_STATIC_ARRAY
1334 : GFC_CAF_REF_ARRAY));
1336 /* Ref the a in union u. */
1337 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1338 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1339 TREE_TYPE (field), prev_caf_ref, field,
1340 NULL_TREE);
1341 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1342 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1343 TREE_TYPE (field), tmp, field,
1344 NULL_TREE);
1346 /* Set the static_array_type in a for static arrays. */
1347 if (ref_static_array)
1349 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1351 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1352 TREE_TYPE (field), inner_struct, field,
1353 NULL_TREE);
1354 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1355 last_type_n));
1357 /* Ref the mode in the inner_struct. */
1358 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1359 mode = fold_build3_loc (input_location, COMPONENT_REF,
1360 TREE_TYPE (field), inner_struct, field,
1361 NULL_TREE);
1362 /* Ref the dim in the inner_struct. */
1363 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1364 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1365 TREE_TYPE (field), inner_struct, field,
1366 NULL_TREE);
1367 for (i = 0; i < ref->u.ar.dimen; ++i)
1369 /* Ref dim i. */
1370 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1371 dim_type = TREE_TYPE (dim);
1372 mode_rhs = start = end = stride = NULL_TREE;
1373 switch (ref->u.ar.dimen_type[i])
1375 case DIMEN_RANGE:
1376 if (ref->u.ar.end[i])
1378 gfc_init_se (&se, NULL);
1379 gfc_conv_expr (&se, ref->u.ar.end[i]);
1380 gfc_add_block_to_block (block, &se.pre);
1381 if (ref_static_array)
1383 /* Make the index zero-based, when reffing a static
1384 array. */
1385 end = se.expr;
1386 gfc_init_se (&se, NULL);
1387 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1388 gfc_add_block_to_block (block, &se.pre);
1389 se.expr = fold_build2 (MINUS_EXPR,
1390 gfc_array_index_type,
1391 end, fold_convert (
1392 gfc_array_index_type,
1393 se.expr));
1395 end = gfc_evaluate_now (fold_convert (
1396 gfc_array_index_type,
1397 se.expr),
1398 block);
1400 else if (ref_static_array)
1401 end = fold_build2 (MINUS_EXPR,
1402 gfc_array_index_type,
1403 gfc_conv_array_ubound (
1404 last_component_ref_tree, i),
1405 gfc_conv_array_lbound (
1406 last_component_ref_tree, i));
1407 else
1409 end = NULL_TREE;
1410 mode_rhs = build_int_cst (unsigned_char_type_node,
1411 GFC_CAF_ARR_REF_OPEN_END);
1413 if (ref->u.ar.stride[i])
1415 gfc_init_se (&se, NULL);
1416 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1417 gfc_add_block_to_block (block, &se.pre);
1418 stride = gfc_evaluate_now (fold_convert (
1419 gfc_array_index_type,
1420 se.expr),
1421 block);
1422 if (ref_static_array)
1424 /* Make the index zero-based, when reffing a static
1425 array. */
1426 stride = fold_build2 (MULT_EXPR,
1427 gfc_array_index_type,
1428 gfc_conv_array_stride (
1429 last_component_ref_tree,
1431 stride);
1432 gcc_assert (end != NULL_TREE);
1433 /* Multiply with the product of array's stride and
1434 the step of the ref to a virtual upper bound.
1435 We can not compute the actual upper bound here or
1436 the caflib would compute the extend
1437 incorrectly. */
1438 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1439 end, gfc_conv_array_stride (
1440 last_component_ref_tree,
1441 i));
1442 end = gfc_evaluate_now (end, block);
1443 stride = gfc_evaluate_now (stride, block);
1446 else if (ref_static_array)
1448 stride = gfc_conv_array_stride (last_component_ref_tree,
1450 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1451 end, stride);
1452 end = gfc_evaluate_now (end, block);
1454 else
1455 /* Always set a ref stride of one to make caflib's
1456 handling easier. */
1457 stride = gfc_index_one_node;
1459 /* Fall through. */
1460 case DIMEN_ELEMENT:
1461 if (ref->u.ar.start[i])
1463 gfc_init_se (&se, NULL);
1464 gfc_conv_expr (&se, ref->u.ar.start[i]);
1465 gfc_add_block_to_block (block, &se.pre);
1466 if (ref_static_array)
1468 /* Make the index zero-based, when reffing a static
1469 array. */
1470 start = fold_convert (gfc_array_index_type, se.expr);
1471 gfc_init_se (&se, NULL);
1472 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1473 gfc_add_block_to_block (block, &se.pre);
1474 se.expr = fold_build2 (MINUS_EXPR,
1475 gfc_array_index_type,
1476 start, fold_convert (
1477 gfc_array_index_type,
1478 se.expr));
1479 /* Multiply with the stride. */
1480 se.expr = fold_build2 (MULT_EXPR,
1481 gfc_array_index_type,
1482 se.expr,
1483 gfc_conv_array_stride (
1484 last_component_ref_tree,
1485 i));
1487 start = gfc_evaluate_now (fold_convert (
1488 gfc_array_index_type,
1489 se.expr),
1490 block);
1491 if (mode_rhs == NULL_TREE)
1492 mode_rhs = build_int_cst (unsigned_char_type_node,
1493 ref->u.ar.dimen_type[i]
1494 == DIMEN_ELEMENT
1495 ? GFC_CAF_ARR_REF_SINGLE
1496 : GFC_CAF_ARR_REF_RANGE);
1498 else if (ref_static_array)
1500 start = integer_zero_node;
1501 mode_rhs = build_int_cst (unsigned_char_type_node,
1502 ref->u.ar.start[i] == NULL
1503 ? GFC_CAF_ARR_REF_FULL
1504 : GFC_CAF_ARR_REF_RANGE);
1506 else if (end == NULL_TREE)
1507 mode_rhs = build_int_cst (unsigned_char_type_node,
1508 GFC_CAF_ARR_REF_FULL);
1509 else
1510 mode_rhs = build_int_cst (unsigned_char_type_node,
1511 GFC_CAF_ARR_REF_OPEN_START);
1513 /* Ref the s in dim. */
1514 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1515 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1516 TREE_TYPE (field), dim, field,
1517 NULL_TREE);
1519 /* Set start in s. */
1520 if (start != NULL_TREE)
1522 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1524 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1525 TREE_TYPE (field), tmp, field,
1526 NULL_TREE);
1527 gfc_add_modify (block, tmp2,
1528 fold_convert (TREE_TYPE (tmp2), start));
1531 /* Set end in s. */
1532 if (end != NULL_TREE)
1534 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1536 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1537 TREE_TYPE (field), tmp, field,
1538 NULL_TREE);
1539 gfc_add_modify (block, tmp2,
1540 fold_convert (TREE_TYPE (tmp2), end));
1543 /* Set end in s. */
1544 if (stride != NULL_TREE)
1546 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1548 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1549 TREE_TYPE (field), tmp, field,
1550 NULL_TREE);
1551 gfc_add_modify (block, tmp2,
1552 fold_convert (TREE_TYPE (tmp2), stride));
1554 break;
1555 case DIMEN_VECTOR:
1556 /* TODO: In case of static array. */
1557 gcc_assert (!ref_static_array);
1558 mode_rhs = build_int_cst (unsigned_char_type_node,
1559 GFC_CAF_ARR_REF_VECTOR);
1560 gfc_init_se (&se, NULL);
1561 se.descriptor_only = 1;
1562 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1563 gfc_add_block_to_block (block, &se.pre);
1564 vector = se.expr;
1565 tmp = gfc_conv_descriptor_lbound_get (vector,
1566 gfc_rank_cst[0]);
1567 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1568 gfc_rank_cst[0]);
1569 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1570 tmp = gfc_conv_descriptor_stride_get (vector,
1571 gfc_rank_cst[0]);
1572 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1573 TREE_TYPE (nvec), nvec, tmp);
1574 vector = gfc_conv_descriptor_data_get (vector);
1576 /* Ref the v in dim. */
1577 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1578 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1579 TREE_TYPE (field), dim, field,
1580 NULL_TREE);
1582 /* Set vector in v. */
1583 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1584 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1585 TREE_TYPE (field), tmp, field,
1586 NULL_TREE);
1587 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1588 vector));
1590 /* Set nvec in v. */
1591 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1592 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1593 TREE_TYPE (field), tmp, field,
1594 NULL_TREE);
1595 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1596 nvec));
1598 /* Set kind in v. */
1599 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1600 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1601 TREE_TYPE (field), tmp, field,
1602 NULL_TREE);
1603 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1604 ref->u.ar.start[i]->ts.kind));
1605 break;
1606 default:
1607 gcc_unreachable ();
1609 /* Set the mode for dim i. */
1610 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1611 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1612 mode_rhs));
1615 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1616 if (i < GFC_MAX_DIMENSIONS)
1618 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1619 gfc_add_modify (block, tmp,
1620 build_int_cst (unsigned_char_type_node,
1621 GFC_CAF_ARR_REF_NONE));
1623 break;
1624 default:
1625 gcc_unreachable ();
1628 /* Set the size of the current type. */
1629 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1630 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1631 prev_caf_ref, field, NULL_TREE);
1632 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1633 TYPE_SIZE_UNIT (last_type)));
1635 ref = ref->next;
1638 if (prev_caf_ref != NULL_TREE)
1640 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1641 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1642 prev_caf_ref, field, NULL_TREE);
1643 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1644 null_pointer_node));
1646 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1647 : NULL_TREE;
1650 /* Get data from a remote coarray. */
1652 static void
1653 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1654 tree may_require_tmp, bool may_realloc,
1655 symbol_attribute *caf_attr)
1657 gfc_expr *array_expr, *tmp_stat;
1658 gfc_se argse;
1659 tree caf_decl, token, offset, image_index, tmp;
1660 tree res_var, dst_var, type, kind, vec, stat;
1661 tree caf_reference;
1662 symbol_attribute caf_attr_store;
1664 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1666 if (se->ss && se->ss->info->useflags)
1668 /* Access the previously obtained result. */
1669 gfc_conv_tmp_array_ref (se);
1670 return;
1673 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1674 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1675 type = gfc_typenode_for_spec (&array_expr->ts);
1677 if (caf_attr == NULL)
1679 caf_attr_store = gfc_caf_attr (array_expr);
1680 caf_attr = &caf_attr_store;
1683 res_var = lhs;
1684 dst_var = lhs;
1686 vec = null_pointer_node;
1687 tmp_stat = gfc_find_stat_co (expr);
1689 if (tmp_stat)
1691 gfc_se stat_se;
1692 gfc_init_se (&stat_se, NULL);
1693 gfc_conv_expr_reference (&stat_se, tmp_stat);
1694 stat = stat_se.expr;
1695 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1696 gfc_add_block_to_block (&se->post, &stat_se.post);
1698 else
1699 stat = null_pointer_node;
1701 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1702 is reallocatable or the right-hand side has allocatable components. */
1703 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1705 /* Get using caf_get_by_ref. */
1706 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1708 if (caf_reference != NULL_TREE)
1710 if (lhs == NULL_TREE)
1712 if (array_expr->ts.type == BT_CHARACTER)
1713 gfc_init_se (&argse, NULL);
1714 if (array_expr->rank == 0)
1716 symbol_attribute attr;
1717 gfc_clear_attr (&attr);
1718 if (array_expr->ts.type == BT_CHARACTER)
1720 res_var = gfc_conv_string_tmp (se,
1721 build_pointer_type (type),
1722 array_expr->ts.u.cl->backend_decl);
1723 argse.string_length = array_expr->ts.u.cl->backend_decl;
1725 else
1726 res_var = gfc_create_var (type, "caf_res");
1727 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1728 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1730 else
1732 /* Create temporary. */
1733 if (array_expr->ts.type == BT_CHARACTER)
1734 gfc_conv_expr_descriptor (&argse, array_expr);
1735 may_realloc = gfc_trans_create_temp_array (&se->pre,
1736 &se->post,
1737 se->ss, type,
1738 NULL_TREE, false,
1739 false, false,
1740 &array_expr->where)
1741 == NULL_TREE;
1742 res_var = se->ss->info->data.array.descriptor;
1743 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1744 if (may_realloc)
1746 tmp = gfc_conv_descriptor_data_get (res_var);
1747 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1748 NULL_TREE, NULL_TREE,
1749 NULL_TREE, true,
1750 NULL,
1751 GFC_CAF_COARRAY_NOCOARRAY);
1752 gfc_add_expr_to_block (&se->post, tmp);
1757 kind = build_int_cst (integer_type_node, expr->ts.kind);
1758 if (lhs_kind == NULL_TREE)
1759 lhs_kind = kind;
1761 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1762 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1763 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1764 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1765 caf_decl);
1766 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1767 array_expr);
1769 /* No overlap possible as we have generated a temporary. */
1770 if (lhs == NULL_TREE)
1771 may_require_tmp = boolean_false_node;
1773 /* It guarantees memory consistency within the same segment. */
1774 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1775 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1776 gfc_build_string_const (1, ""), NULL_TREE,
1777 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1778 NULL_TREE);
1779 ASM_VOLATILE_P (tmp) = 1;
1780 gfc_add_expr_to_block (&se->pre, tmp);
1782 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1783 10, token, image_index, dst_var,
1784 caf_reference, lhs_kind, kind,
1785 may_require_tmp,
1786 may_realloc ? boolean_true_node :
1787 boolean_false_node,
1788 stat, build_int_cst (integer_type_node,
1789 array_expr->ts.type));
1791 gfc_add_expr_to_block (&se->pre, tmp);
1793 if (se->ss)
1794 gfc_advance_se_ss_chain (se);
1796 se->expr = res_var;
1797 if (array_expr->ts.type == BT_CHARACTER)
1798 se->string_length = argse.string_length;
1800 return;
1804 gfc_init_se (&argse, NULL);
1805 if (array_expr->rank == 0)
1807 symbol_attribute attr;
1809 gfc_clear_attr (&attr);
1810 gfc_conv_expr (&argse, array_expr);
1812 if (lhs == NULL_TREE)
1814 gfc_clear_attr (&attr);
1815 if (array_expr->ts.type == BT_CHARACTER)
1816 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1817 argse.string_length);
1818 else
1819 res_var = gfc_create_var (type, "caf_res");
1820 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1821 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1823 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1824 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1826 else
1828 /* If has_vector, pass descriptor for whole array and the
1829 vector bounds separately. */
1830 gfc_array_ref *ar, ar2;
1831 bool has_vector = false;
1833 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1835 has_vector = true;
1836 ar = gfc_find_array_ref (expr);
1837 ar2 = *ar;
1838 memset (ar, '\0', sizeof (*ar));
1839 ar->as = ar2.as;
1840 ar->type = AR_FULL;
1842 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1843 gfc_conv_expr_descriptor (&argse, array_expr);
1844 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1845 has the wrong type if component references are done. */
1846 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1847 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1848 : array_expr->rank,
1849 type));
1850 if (has_vector)
1852 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1853 *ar = ar2;
1856 if (lhs == NULL_TREE)
1858 /* Create temporary. */
1859 for (int n = 0; n < se->ss->loop->dimen; n++)
1860 if (se->loop->to[n] == NULL_TREE)
1862 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1863 gfc_rank_cst[n]);
1864 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1865 gfc_rank_cst[n]);
1867 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1868 NULL_TREE, false, true, false,
1869 &array_expr->where);
1870 res_var = se->ss->info->data.array.descriptor;
1871 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1873 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1876 kind = build_int_cst (integer_type_node, expr->ts.kind);
1877 if (lhs_kind == NULL_TREE)
1878 lhs_kind = kind;
1880 gfc_add_block_to_block (&se->pre, &argse.pre);
1881 gfc_add_block_to_block (&se->post, &argse.post);
1883 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1884 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1885 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1886 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1887 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1888 array_expr);
1890 /* No overlap possible as we have generated a temporary. */
1891 if (lhs == NULL_TREE)
1892 may_require_tmp = boolean_false_node;
1894 /* It guarantees memory consistency within the same segment. */
1895 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1896 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1897 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1898 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1899 ASM_VOLATILE_P (tmp) = 1;
1900 gfc_add_expr_to_block (&se->pre, tmp);
1902 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1903 token, offset, image_index, argse.expr, vec,
1904 dst_var, kind, lhs_kind, may_require_tmp, stat);
1906 gfc_add_expr_to_block (&se->pre, tmp);
1908 if (se->ss)
1909 gfc_advance_se_ss_chain (se);
1911 se->expr = res_var;
1912 if (array_expr->ts.type == BT_CHARACTER)
1913 se->string_length = argse.string_length;
1917 /* Send data to a remote coarray. */
1919 static tree
1920 conv_caf_send (gfc_code *code) {
1921 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1922 gfc_se lhs_se, rhs_se;
1923 stmtblock_t block;
1924 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1925 tree may_require_tmp, src_stat, dst_stat, dst_team;
1926 tree lhs_type = NULL_TREE;
1927 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1928 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1930 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1932 lhs_expr = code->ext.actual->expr;
1933 rhs_expr = code->ext.actual->next->expr;
1934 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1935 ? boolean_false_node : boolean_true_node;
1936 gfc_init_block (&block);
1938 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1939 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1940 src_stat = dst_stat = null_pointer_node;
1941 dst_team = null_pointer_node;
1943 /* LHS. */
1944 gfc_init_se (&lhs_se, NULL);
1945 if (lhs_expr->rank == 0)
1947 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1949 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1950 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1952 else
1954 symbol_attribute attr;
1955 gfc_clear_attr (&attr);
1956 gfc_conv_expr (&lhs_se, lhs_expr);
1957 lhs_type = TREE_TYPE (lhs_se.expr);
1958 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1959 attr);
1960 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1963 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1964 && lhs_caf_attr.codimension)
1966 lhs_se.want_pointer = 1;
1967 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1968 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1969 has the wrong type if component references are done. */
1970 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1971 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1972 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1973 gfc_get_dtype_rank_type (
1974 gfc_has_vector_subscript (lhs_expr)
1975 ? gfc_find_array_ref (lhs_expr)->dimen
1976 : lhs_expr->rank,
1977 lhs_type));
1979 else
1981 bool has_vector = gfc_has_vector_subscript (lhs_expr);
1983 if (gfc_is_coindexed (lhs_expr) || !has_vector)
1985 /* If has_vector, pass descriptor for whole array and the
1986 vector bounds separately. */
1987 gfc_array_ref *ar, ar2;
1988 bool has_tmp_lhs_array = false;
1989 if (has_vector)
1991 has_tmp_lhs_array = true;
1992 ar = gfc_find_array_ref (lhs_expr);
1993 ar2 = *ar;
1994 memset (ar, '\0', sizeof (*ar));
1995 ar->as = ar2.as;
1996 ar->type = AR_FULL;
1998 lhs_se.want_pointer = 1;
1999 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2000 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2001 that has the wrong type if component references are done. */
2002 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2003 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2004 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2005 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2006 : lhs_expr->rank,
2007 lhs_type));
2008 if (has_tmp_lhs_array)
2010 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2011 *ar = ar2;
2014 else
2016 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2017 indexed array expression. This is rewritten to:
2019 tmp_array = arr2[...]
2020 arr1 ([...]) = tmp_array
2022 because using the standard gfc_conv_expr (lhs_expr) did the
2023 assignment with lhs and rhs exchanged. */
2025 gfc_ss *lss_for_tmparray, *lss_real;
2026 gfc_loopinfo loop;
2027 gfc_se se;
2028 stmtblock_t body;
2029 tree tmparr_desc, src;
2030 tree index = gfc_index_zero_node;
2031 tree stride = gfc_index_zero_node;
2032 int n;
2034 /* Walk both sides of the assignment, once to get the shape of the
2035 temporary array to create right. */
2036 lss_for_tmparray = gfc_walk_expr (lhs_expr);
2037 /* And a second time to be able to create an assignment of the
2038 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2039 the tree in the descriptor with the one for the temporary
2040 array. */
2041 lss_real = gfc_walk_expr (lhs_expr);
2042 gfc_init_loopinfo (&loop);
2043 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2044 gfc_add_ss_to_loop (&loop, lss_real);
2045 gfc_conv_ss_startstride (&loop);
2046 gfc_conv_loop_setup (&loop, &lhs_expr->where);
2047 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2048 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2049 lss_for_tmparray, lhs_type, NULL_TREE,
2050 false, true, false,
2051 &lhs_expr->where);
2052 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2053 gfc_start_scalarized_body (&loop, &body);
2054 gfc_init_se (&se, NULL);
2055 gfc_copy_loopinfo_to_se (&se, &loop);
2056 se.ss = lss_real;
2057 gfc_conv_expr (&se, lhs_expr);
2058 gfc_add_block_to_block (&body, &se.pre);
2060 /* Walk over all indexes of the loop. */
2061 for (n = loop.dimen - 1; n > 0; --n)
2063 tmp = loop.loopvar[n];
2064 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2065 gfc_array_index_type, tmp, loop.from[n]);
2066 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2067 gfc_array_index_type, tmp, index);
2069 stride = fold_build2_loc (input_location, MINUS_EXPR,
2070 gfc_array_index_type,
2071 loop.to[n - 1], loop.from[n - 1]);
2072 stride = fold_build2_loc (input_location, PLUS_EXPR,
2073 gfc_array_index_type,
2074 stride, gfc_index_one_node);
2076 index = fold_build2_loc (input_location, MULT_EXPR,
2077 gfc_array_index_type, tmp, stride);
2080 index = fold_build2_loc (input_location, MINUS_EXPR,
2081 gfc_array_index_type,
2082 index, loop.from[0]);
2084 index = fold_build2_loc (input_location, PLUS_EXPR,
2085 gfc_array_index_type,
2086 loop.loopvar[0], index);
2088 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2089 src = gfc_build_array_ref (src, index, NULL);
2090 /* Now create the assignment of lhs_expr = tmp_array. */
2091 gfc_add_modify (&body, se.expr, src);
2092 gfc_add_block_to_block (&body, &se.post);
2093 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2094 gfc_trans_scalarizing_loops (&loop, &body);
2095 gfc_add_block_to_block (&loop.pre, &loop.post);
2096 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2097 gfc_free_ss (lss_for_tmparray);
2098 gfc_free_ss (lss_real);
2102 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2104 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2105 temporary and a loop. */
2106 if (!gfc_is_coindexed (lhs_expr)
2107 && (!lhs_caf_attr.codimension
2108 || !(lhs_expr->rank > 0
2109 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2111 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2112 gcc_assert (gfc_is_coindexed (rhs_expr));
2113 gfc_init_se (&rhs_se, NULL);
2114 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2116 gfc_se scal_se;
2117 gfc_init_se (&scal_se, NULL);
2118 scal_se.want_pointer = 1;
2119 gfc_conv_expr (&scal_se, lhs_expr);
2120 /* Ensure scalar on lhs is allocated. */
2121 gfc_add_block_to_block (&block, &scal_se.pre);
2123 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2124 TYPE_SIZE_UNIT (
2125 gfc_typenode_for_spec (&lhs_expr->ts)),
2126 NULL_TREE);
2127 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2128 null_pointer_node);
2129 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2130 tmp, gfc_finish_block (&scal_se.pre),
2131 build_empty_stmt (input_location));
2132 gfc_add_expr_to_block (&block, tmp);
2134 else
2135 lhs_may_realloc = lhs_may_realloc
2136 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2137 gfc_add_block_to_block (&block, &lhs_se.pre);
2138 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2139 may_require_tmp, lhs_may_realloc,
2140 &rhs_caf_attr);
2141 gfc_add_block_to_block (&block, &rhs_se.pre);
2142 gfc_add_block_to_block (&block, &rhs_se.post);
2143 gfc_add_block_to_block (&block, &lhs_se.post);
2144 return gfc_finish_block (&block);
2147 gfc_add_block_to_block (&block, &lhs_se.pre);
2149 /* Obtain token, offset and image index for the LHS. */
2150 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2151 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2152 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2153 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2154 tmp = lhs_se.expr;
2155 if (lhs_caf_attr.alloc_comp)
2156 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2157 NULL);
2158 else
2159 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2160 lhs_expr);
2161 lhs_se.expr = tmp;
2163 /* RHS. */
2164 gfc_init_se (&rhs_se, NULL);
2165 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2166 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2167 rhs_expr = rhs_expr->value.function.actual->expr;
2168 if (rhs_expr->rank == 0)
2170 symbol_attribute attr;
2171 gfc_clear_attr (&attr);
2172 gfc_conv_expr (&rhs_se, rhs_expr);
2173 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2174 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2176 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2177 && rhs_caf_attr.codimension)
2179 tree tmp2;
2180 rhs_se.want_pointer = 1;
2181 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2182 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2183 has the wrong type if component references are done. */
2184 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2185 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2186 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2187 gfc_get_dtype_rank_type (
2188 gfc_has_vector_subscript (rhs_expr)
2189 ? gfc_find_array_ref (rhs_expr)->dimen
2190 : rhs_expr->rank,
2191 tmp2));
2193 else
2195 /* If has_vector, pass descriptor for whole array and the
2196 vector bounds separately. */
2197 gfc_array_ref *ar, ar2;
2198 bool has_vector = false;
2199 tree tmp2;
2201 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2203 has_vector = true;
2204 ar = gfc_find_array_ref (rhs_expr);
2205 ar2 = *ar;
2206 memset (ar, '\0', sizeof (*ar));
2207 ar->as = ar2.as;
2208 ar->type = AR_FULL;
2210 rhs_se.want_pointer = 1;
2211 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2212 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2213 has the wrong type if component references are done. */
2214 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2215 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2216 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2217 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2218 : rhs_expr->rank,
2219 tmp2));
2220 if (has_vector)
2222 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2223 *ar = ar2;
2227 gfc_add_block_to_block (&block, &rhs_se.pre);
2229 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2231 tmp_stat = gfc_find_stat_co (lhs_expr);
2233 if (tmp_stat)
2235 gfc_se stat_se;
2236 gfc_init_se (&stat_se, NULL);
2237 gfc_conv_expr_reference (&stat_se, tmp_stat);
2238 dst_stat = stat_se.expr;
2239 gfc_add_block_to_block (&block, &stat_se.pre);
2240 gfc_add_block_to_block (&block, &stat_se.post);
2243 tmp_team = gfc_find_team_co (lhs_expr);
2245 if (tmp_team)
2247 gfc_se team_se;
2248 gfc_init_se (&team_se, NULL);
2249 gfc_conv_expr_reference (&team_se, tmp_team);
2250 dst_team = team_se.expr;
2251 gfc_add_block_to_block (&block, &team_se.pre);
2252 gfc_add_block_to_block (&block, &team_se.post);
2255 if (!gfc_is_coindexed (rhs_expr))
2257 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2259 tree reference, dst_realloc;
2260 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2261 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2262 : boolean_false_node;
2263 tmp = build_call_expr_loc (input_location,
2264 gfor_fndecl_caf_send_by_ref,
2265 10, token, image_index, rhs_se.expr,
2266 reference, lhs_kind, rhs_kind,
2267 may_require_tmp, dst_realloc, src_stat,
2268 build_int_cst (integer_type_node,
2269 lhs_expr->ts.type));
2271 else
2272 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2273 token, offset, image_index, lhs_se.expr, vec,
2274 rhs_se.expr, lhs_kind, rhs_kind,
2275 may_require_tmp, src_stat, dst_team);
2277 else
2279 tree rhs_token, rhs_offset, rhs_image_index;
2281 /* It guarantees memory consistency within the same segment. */
2282 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2283 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2284 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2285 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2286 ASM_VOLATILE_P (tmp) = 1;
2287 gfc_add_expr_to_block (&block, tmp);
2289 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2290 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2291 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2292 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2293 tmp = rhs_se.expr;
2294 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2296 tmp_stat = gfc_find_stat_co (lhs_expr);
2298 if (tmp_stat)
2300 gfc_se stat_se;
2301 gfc_init_se (&stat_se, NULL);
2302 gfc_conv_expr_reference (&stat_se, tmp_stat);
2303 src_stat = stat_se.expr;
2304 gfc_add_block_to_block (&block, &stat_se.pre);
2305 gfc_add_block_to_block (&block, &stat_se.post);
2308 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2309 NULL_TREE, NULL);
2310 tree lhs_reference, rhs_reference;
2311 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2312 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2313 tmp = build_call_expr_loc (input_location,
2314 gfor_fndecl_caf_sendget_by_ref, 13,
2315 token, image_index, lhs_reference,
2316 rhs_token, rhs_image_index, rhs_reference,
2317 lhs_kind, rhs_kind, may_require_tmp,
2318 dst_stat, src_stat,
2319 build_int_cst (integer_type_node,
2320 lhs_expr->ts.type),
2321 build_int_cst (integer_type_node,
2322 rhs_expr->ts.type));
2324 else
2326 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2327 tmp, rhs_expr);
2328 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2329 14, token, offset, image_index,
2330 lhs_se.expr, vec, rhs_token, rhs_offset,
2331 rhs_image_index, tmp, rhs_vec, lhs_kind,
2332 rhs_kind, may_require_tmp, src_stat);
2335 gfc_add_expr_to_block (&block, tmp);
2336 gfc_add_block_to_block (&block, &lhs_se.post);
2337 gfc_add_block_to_block (&block, &rhs_se.post);
2339 /* It guarantees memory consistency within the same segment. */
2340 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2341 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2342 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2343 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2344 ASM_VOLATILE_P (tmp) = 1;
2345 gfc_add_expr_to_block (&block, tmp);
2347 return gfc_finish_block (&block);
2351 static void
2352 trans_this_image (gfc_se * se, gfc_expr *expr)
2354 stmtblock_t loop;
2355 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2356 lbound, ubound, extent, ml;
2357 gfc_se argse;
2358 int rank, corank;
2359 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2361 if (expr->value.function.actual->expr
2362 && !gfc_is_coarray (expr->value.function.actual->expr))
2363 distance = expr->value.function.actual->expr;
2365 /* The case -fcoarray=single is handled elsewhere. */
2366 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2368 /* Argument-free version: THIS_IMAGE(). */
2369 if (distance || expr->value.function.actual->expr == NULL)
2371 if (distance)
2373 gfc_init_se (&argse, NULL);
2374 gfc_conv_expr_val (&argse, distance);
2375 gfc_add_block_to_block (&se->pre, &argse.pre);
2376 gfc_add_block_to_block (&se->post, &argse.post);
2377 tmp = fold_convert (integer_type_node, argse.expr);
2379 else
2380 tmp = integer_zero_node;
2381 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2382 tmp);
2383 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2384 tmp);
2385 return;
2388 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2390 type = gfc_get_int_type (gfc_default_integer_kind);
2391 corank = gfc_get_corank (expr->value.function.actual->expr);
2392 rank = expr->value.function.actual->expr->rank;
2394 /* Obtain the descriptor of the COARRAY. */
2395 gfc_init_se (&argse, NULL);
2396 argse.want_coarray = 1;
2397 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2398 gfc_add_block_to_block (&se->pre, &argse.pre);
2399 gfc_add_block_to_block (&se->post, &argse.post);
2400 desc = argse.expr;
2402 if (se->ss)
2404 /* Create an implicit second parameter from the loop variable. */
2405 gcc_assert (!expr->value.function.actual->next->expr);
2406 gcc_assert (corank > 0);
2407 gcc_assert (se->loop->dimen == 1);
2408 gcc_assert (se->ss->info->expr == expr);
2410 dim_arg = se->loop->loopvar[0];
2411 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2412 gfc_array_index_type, dim_arg,
2413 build_int_cst (TREE_TYPE (dim_arg), 1));
2414 gfc_advance_se_ss_chain (se);
2416 else
2418 /* Use the passed DIM= argument. */
2419 gcc_assert (expr->value.function.actual->next->expr);
2420 gfc_init_se (&argse, NULL);
2421 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2422 gfc_array_index_type);
2423 gfc_add_block_to_block (&se->pre, &argse.pre);
2424 dim_arg = argse.expr;
2426 if (INTEGER_CST_P (dim_arg))
2428 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2429 || wi::gtu_p (wi::to_wide (dim_arg),
2430 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2431 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2432 "dimension index", expr->value.function.isym->name,
2433 &expr->where);
2435 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2437 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2438 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2439 dim_arg,
2440 build_int_cst (TREE_TYPE (dim_arg), 1));
2441 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2442 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2443 dim_arg, tmp);
2444 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2445 logical_type_node, cond, tmp);
2446 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2447 gfc_msg_fault);
2451 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2452 one always has a dim_arg argument.
2454 m = this_image() - 1
2455 if (corank == 1)
2457 sub(1) = m + lcobound(corank)
2458 return;
2460 i = rank
2461 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2462 for (;;)
2464 extent = gfc_extent(i)
2465 ml = m
2466 m = m/extent
2467 if (i >= min_var)
2468 goto exit_label
2471 exit_label:
2472 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2473 : m + lcobound(corank)
2476 /* this_image () - 1. */
2477 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2478 integer_zero_node);
2479 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2480 fold_convert (type, tmp), build_int_cst (type, 1));
2481 if (corank == 1)
2483 /* sub(1) = m + lcobound(corank). */
2484 lbound = gfc_conv_descriptor_lbound_get (desc,
2485 build_int_cst (TREE_TYPE (gfc_array_index_type),
2486 corank+rank-1));
2487 lbound = fold_convert (type, lbound);
2488 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2490 se->expr = tmp;
2491 return;
2494 m = gfc_create_var (type, NULL);
2495 ml = gfc_create_var (type, NULL);
2496 loop_var = gfc_create_var (integer_type_node, NULL);
2497 min_var = gfc_create_var (integer_type_node, NULL);
2499 /* m = this_image () - 1. */
2500 gfc_add_modify (&se->pre, m, tmp);
2502 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2503 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2504 fold_convert (integer_type_node, dim_arg),
2505 build_int_cst (integer_type_node, rank - 1));
2506 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2507 build_int_cst (integer_type_node, rank + corank - 2),
2508 tmp);
2509 gfc_add_modify (&se->pre, min_var, tmp);
2511 /* i = rank. */
2512 tmp = build_int_cst (integer_type_node, rank);
2513 gfc_add_modify (&se->pre, loop_var, tmp);
2515 exit_label = gfc_build_label_decl (NULL_TREE);
2516 TREE_USED (exit_label) = 1;
2518 /* Loop body. */
2519 gfc_init_block (&loop);
2521 /* ml = m. */
2522 gfc_add_modify (&loop, ml, m);
2524 /* extent = ... */
2525 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2526 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2527 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2528 extent = fold_convert (type, extent);
2530 /* m = m/extent. */
2531 gfc_add_modify (&loop, m,
2532 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2533 m, extent));
2535 /* Exit condition: if (i >= min_var) goto exit_label. */
2536 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2537 min_var);
2538 tmp = build1_v (GOTO_EXPR, exit_label);
2539 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2540 build_empty_stmt (input_location));
2541 gfc_add_expr_to_block (&loop, tmp);
2543 /* Increment loop variable: i++. */
2544 gfc_add_modify (&loop, loop_var,
2545 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2546 loop_var,
2547 build_int_cst (integer_type_node, 1)));
2549 /* Making the loop... actually loop! */
2550 tmp = gfc_finish_block (&loop);
2551 tmp = build1_v (LOOP_EXPR, tmp);
2552 gfc_add_expr_to_block (&se->pre, tmp);
2554 /* The exit label. */
2555 tmp = build1_v (LABEL_EXPR, exit_label);
2556 gfc_add_expr_to_block (&se->pre, tmp);
2558 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2559 : m + lcobound(corank) */
2561 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2562 build_int_cst (TREE_TYPE (dim_arg), corank));
2564 lbound = gfc_conv_descriptor_lbound_get (desc,
2565 fold_build2_loc (input_location, PLUS_EXPR,
2566 gfc_array_index_type, dim_arg,
2567 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2568 lbound = fold_convert (type, lbound);
2570 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2571 fold_build2_loc (input_location, MULT_EXPR, type,
2572 m, extent));
2573 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2575 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2576 fold_build2_loc (input_location, PLUS_EXPR, type,
2577 m, lbound));
2581 /* Convert a call to image_status. */
2583 static void
2584 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2586 unsigned int num_args;
2587 tree *args, tmp;
2589 num_args = gfc_intrinsic_argument_list_length (expr);
2590 args = XALLOCAVEC (tree, num_args);
2591 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2592 /* In args[0] the number of the image the status is desired for has to be
2593 given. */
2595 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2597 tree arg;
2598 arg = gfc_evaluate_now (args[0], &se->pre);
2599 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2600 fold_convert (integer_type_node, arg),
2601 integer_one_node);
2602 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2603 tmp, integer_zero_node,
2604 build_int_cst (integer_type_node,
2605 GFC_STAT_STOPPED_IMAGE));
2607 else if (flag_coarray == GFC_FCOARRAY_LIB)
2608 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2609 args[0], build_int_cst (integer_type_node, -1));
2610 else
2611 gcc_unreachable ();
2613 se->expr = tmp;
2616 static void
2617 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2619 unsigned int num_args;
2621 tree *args, tmp;
2623 num_args = gfc_intrinsic_argument_list_length (expr);
2624 args = XALLOCAVEC (tree, num_args);
2625 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2627 if (flag_coarray ==
2628 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2630 tree arg;
2632 arg = gfc_evaluate_now (args[0], &se->pre);
2633 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2634 fold_convert (integer_type_node, arg),
2635 integer_one_node);
2636 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2637 tmp, integer_zero_node,
2638 build_int_cst (integer_type_node,
2639 GFC_STAT_STOPPED_IMAGE));
2641 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2643 // the value -1 represents that no team has been created yet
2644 tmp = build_int_cst (integer_type_node, -1);
2646 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2647 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2648 args[0], build_int_cst (integer_type_node, -1));
2649 else if (flag_coarray == GFC_FCOARRAY_LIB)
2650 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2651 integer_zero_node, build_int_cst (integer_type_node, -1));
2652 else
2653 gcc_unreachable ();
2655 se->expr = tmp;
2659 static void
2660 trans_image_index (gfc_se * se, gfc_expr *expr)
2662 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2663 tmp, invalid_bound;
2664 gfc_se argse, subse;
2665 int rank, corank, codim;
2667 type = gfc_get_int_type (gfc_default_integer_kind);
2668 corank = gfc_get_corank (expr->value.function.actual->expr);
2669 rank = expr->value.function.actual->expr->rank;
2671 /* Obtain the descriptor of the COARRAY. */
2672 gfc_init_se (&argse, NULL);
2673 argse.want_coarray = 1;
2674 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2675 gfc_add_block_to_block (&se->pre, &argse.pre);
2676 gfc_add_block_to_block (&se->post, &argse.post);
2677 desc = argse.expr;
2679 /* Obtain a handle to the SUB argument. */
2680 gfc_init_se (&subse, NULL);
2681 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2682 gfc_add_block_to_block (&se->pre, &subse.pre);
2683 gfc_add_block_to_block (&se->post, &subse.post);
2684 subdesc = build_fold_indirect_ref_loc (input_location,
2685 gfc_conv_descriptor_data_get (subse.expr));
2687 /* Fortran 2008 does not require that the values remain in the cobounds,
2688 thus we need explicitly check this - and return 0 if they are exceeded. */
2690 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2691 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2692 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2693 fold_convert (gfc_array_index_type, tmp),
2694 lbound);
2696 for (codim = corank + rank - 2; codim >= rank; codim--)
2698 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2699 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2700 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2701 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2702 fold_convert (gfc_array_index_type, tmp),
2703 lbound);
2704 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2705 logical_type_node, invalid_bound, cond);
2706 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2707 fold_convert (gfc_array_index_type, tmp),
2708 ubound);
2709 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2710 logical_type_node, invalid_bound, cond);
2713 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2715 /* See Fortran 2008, C.10 for the following algorithm. */
2717 /* coindex = sub(corank) - lcobound(n). */
2718 coindex = fold_convert (gfc_array_index_type,
2719 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2720 NULL));
2721 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2722 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2723 fold_convert (gfc_array_index_type, coindex),
2724 lbound);
2726 for (codim = corank + rank - 2; codim >= rank; codim--)
2728 tree extent, ubound;
2730 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2731 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2732 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2733 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2735 /* coindex *= extent. */
2736 coindex = fold_build2_loc (input_location, MULT_EXPR,
2737 gfc_array_index_type, coindex, extent);
2739 /* coindex += sub(codim). */
2740 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2741 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2742 gfc_array_index_type, coindex,
2743 fold_convert (gfc_array_index_type, tmp));
2745 /* coindex -= lbound(codim). */
2746 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2747 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2748 gfc_array_index_type, coindex, lbound);
2751 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2752 fold_convert(type, coindex),
2753 build_int_cst (type, 1));
2755 /* Return 0 if "coindex" exceeds num_images(). */
2757 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2758 num_images = build_int_cst (type, 1);
2759 else
2761 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2762 integer_zero_node,
2763 build_int_cst (integer_type_node, -1));
2764 num_images = fold_convert (type, tmp);
2767 tmp = gfc_create_var (type, NULL);
2768 gfc_add_modify (&se->pre, tmp, coindex);
2770 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2771 num_images);
2772 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2773 cond,
2774 fold_convert (logical_type_node, invalid_bound));
2775 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2776 build_int_cst (type, 0), tmp);
2779 static void
2780 trans_num_images (gfc_se * se, gfc_expr *expr)
2782 tree tmp, distance, failed;
2783 gfc_se argse;
2785 if (expr->value.function.actual->expr)
2787 gfc_init_se (&argse, NULL);
2788 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2789 gfc_add_block_to_block (&se->pre, &argse.pre);
2790 gfc_add_block_to_block (&se->post, &argse.post);
2791 distance = fold_convert (integer_type_node, argse.expr);
2793 else
2794 distance = integer_zero_node;
2796 if (expr->value.function.actual->next->expr)
2798 gfc_init_se (&argse, NULL);
2799 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2800 gfc_add_block_to_block (&se->pre, &argse.pre);
2801 gfc_add_block_to_block (&se->post, &argse.post);
2802 failed = fold_convert (integer_type_node, argse.expr);
2804 else
2805 failed = build_int_cst (integer_type_node, -1);
2806 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2807 distance, failed);
2808 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2812 static void
2813 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2815 gfc_se argse;
2817 gfc_init_se (&argse, NULL);
2818 argse.data_not_needed = 1;
2819 argse.descriptor_only = 1;
2821 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2822 gfc_add_block_to_block (&se->pre, &argse.pre);
2823 gfc_add_block_to_block (&se->post, &argse.post);
2825 se->expr = gfc_conv_descriptor_rank (argse.expr);
2826 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2827 se->expr);
2831 /* Evaluate a single upper or lower bound. */
2832 /* TODO: bound intrinsic generates way too much unnecessary code. */
2834 static void
2835 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2837 gfc_actual_arglist *arg;
2838 gfc_actual_arglist *arg2;
2839 tree desc;
2840 tree type;
2841 tree bound;
2842 tree tmp;
2843 tree cond, cond1, cond3, cond4, size;
2844 tree ubound;
2845 tree lbound;
2846 gfc_se argse;
2847 gfc_array_spec * as;
2848 bool assumed_rank_lb_one;
2850 arg = expr->value.function.actual;
2851 arg2 = arg->next;
2853 if (se->ss)
2855 /* Create an implicit second parameter from the loop variable. */
2856 gcc_assert (!arg2->expr);
2857 gcc_assert (se->loop->dimen == 1);
2858 gcc_assert (se->ss->info->expr == expr);
2859 gfc_advance_se_ss_chain (se);
2860 bound = se->loop->loopvar[0];
2861 bound = fold_build2_loc (input_location, MINUS_EXPR,
2862 gfc_array_index_type, bound,
2863 se->loop->from[0]);
2865 else
2867 /* use the passed argument. */
2868 gcc_assert (arg2->expr);
2869 gfc_init_se (&argse, NULL);
2870 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2871 gfc_add_block_to_block (&se->pre, &argse.pre);
2872 bound = argse.expr;
2873 /* Convert from one based to zero based. */
2874 bound = fold_build2_loc (input_location, MINUS_EXPR,
2875 gfc_array_index_type, bound,
2876 gfc_index_one_node);
2879 /* TODO: don't re-evaluate the descriptor on each iteration. */
2880 /* Get a descriptor for the first parameter. */
2881 gfc_init_se (&argse, NULL);
2882 gfc_conv_expr_descriptor (&argse, arg->expr);
2883 gfc_add_block_to_block (&se->pre, &argse.pre);
2884 gfc_add_block_to_block (&se->post, &argse.post);
2886 desc = argse.expr;
2888 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2890 if (INTEGER_CST_P (bound))
2892 if (((!as || as->type != AS_ASSUMED_RANK)
2893 && wi::geu_p (wi::to_wide (bound),
2894 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2895 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2896 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2897 "dimension index", upper ? "UBOUND" : "LBOUND",
2898 &expr->where);
2901 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2903 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2905 bound = gfc_evaluate_now (bound, &se->pre);
2906 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2907 bound, build_int_cst (TREE_TYPE (bound), 0));
2908 if (as && as->type == AS_ASSUMED_RANK)
2909 tmp = gfc_conv_descriptor_rank (desc);
2910 else
2911 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2912 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2913 bound, fold_convert(TREE_TYPE (bound), tmp));
2914 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2915 logical_type_node, cond, tmp);
2916 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2917 gfc_msg_fault);
2921 /* Take care of the lbound shift for assumed-rank arrays, which are
2922 nonallocatable and nonpointers. Those has a lbound of 1. */
2923 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2924 && ((arg->expr->ts.type != BT_CLASS
2925 && !arg->expr->symtree->n.sym->attr.allocatable
2926 && !arg->expr->symtree->n.sym->attr.pointer)
2927 || (arg->expr->ts.type == BT_CLASS
2928 && !CLASS_DATA (arg->expr)->attr.allocatable
2929 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2931 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2932 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2934 /* 13.14.53: Result value for LBOUND
2936 Case (i): For an array section or for an array expression other than a
2937 whole array or array structure component, LBOUND(ARRAY, DIM)
2938 has the value 1. For a whole array or array structure
2939 component, LBOUND(ARRAY, DIM) has the value:
2940 (a) equal to the lower bound for subscript DIM of ARRAY if
2941 dimension DIM of ARRAY does not have extent zero
2942 or if ARRAY is an assumed-size array of rank DIM,
2943 or (b) 1 otherwise.
2945 13.14.113: Result value for UBOUND
2947 Case (i): For an array section or for an array expression other than a
2948 whole array or array structure component, UBOUND(ARRAY, DIM)
2949 has the value equal to the number of elements in the given
2950 dimension; otherwise, it has a value equal to the upper bound
2951 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2952 not have size zero and has value zero if dimension DIM has
2953 size zero. */
2955 if (!upper && assumed_rank_lb_one)
2956 se->expr = gfc_index_one_node;
2957 else if (as)
2959 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2961 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2962 ubound, lbound);
2963 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2964 stride, gfc_index_zero_node);
2965 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2966 logical_type_node, cond3, cond1);
2967 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2968 stride, gfc_index_zero_node);
2970 if (upper)
2972 tree cond5;
2973 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2974 logical_type_node, cond3, cond4);
2975 cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2976 gfc_index_one_node, lbound);
2977 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2978 logical_type_node, cond4, cond5);
2980 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2981 logical_type_node, cond, cond5);
2983 if (assumed_rank_lb_one)
2985 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2986 gfc_array_index_type, ubound, lbound);
2987 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2988 gfc_array_index_type, tmp, gfc_index_one_node);
2990 else
2991 tmp = ubound;
2993 se->expr = fold_build3_loc (input_location, COND_EXPR,
2994 gfc_array_index_type, cond,
2995 tmp, gfc_index_zero_node);
2997 else
2999 if (as->type == AS_ASSUMED_SIZE)
3000 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3001 bound, build_int_cst (TREE_TYPE (bound),
3002 arg->expr->rank - 1));
3003 else
3004 cond = logical_false_node;
3006 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3007 logical_type_node, cond3, cond4);
3008 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3009 logical_type_node, cond, cond1);
3011 se->expr = fold_build3_loc (input_location, COND_EXPR,
3012 gfc_array_index_type, cond,
3013 lbound, gfc_index_one_node);
3016 else
3018 if (upper)
3020 size = fold_build2_loc (input_location, MINUS_EXPR,
3021 gfc_array_index_type, ubound, lbound);
3022 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
3023 gfc_array_index_type, size,
3024 gfc_index_one_node);
3025 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3026 gfc_array_index_type, se->expr,
3027 gfc_index_zero_node);
3029 else
3030 se->expr = gfc_index_one_node;
3033 type = gfc_typenode_for_spec (&expr->ts);
3034 se->expr = convert (type, se->expr);
3038 static void
3039 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3041 gfc_actual_arglist *arg;
3042 gfc_actual_arglist *arg2;
3043 gfc_se argse;
3044 tree bound, resbound, resbound2, desc, cond, tmp;
3045 tree type;
3046 int corank;
3048 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
3049 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
3050 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
3052 arg = expr->value.function.actual;
3053 arg2 = arg->next;
3055 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
3056 corank = gfc_get_corank (arg->expr);
3058 gfc_init_se (&argse, NULL);
3059 argse.want_coarray = 1;
3061 gfc_conv_expr_descriptor (&argse, arg->expr);
3062 gfc_add_block_to_block (&se->pre, &argse.pre);
3063 gfc_add_block_to_block (&se->post, &argse.post);
3064 desc = argse.expr;
3066 if (se->ss)
3068 /* Create an implicit second parameter from the loop variable. */
3069 gcc_assert (!arg2->expr);
3070 gcc_assert (corank > 0);
3071 gcc_assert (se->loop->dimen == 1);
3072 gcc_assert (se->ss->info->expr == expr);
3074 bound = se->loop->loopvar[0];
3075 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3076 bound, gfc_rank_cst[arg->expr->rank]);
3077 gfc_advance_se_ss_chain (se);
3079 else
3081 /* use the passed argument. */
3082 gcc_assert (arg2->expr);
3083 gfc_init_se (&argse, NULL);
3084 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3085 gfc_add_block_to_block (&se->pre, &argse.pre);
3086 bound = argse.expr;
3088 if (INTEGER_CST_P (bound))
3090 if (wi::ltu_p (wi::to_wide (bound), 1)
3091 || wi::gtu_p (wi::to_wide (bound),
3092 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3093 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3094 "dimension index", expr->value.function.isym->name,
3095 &expr->where);
3097 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3099 bound = gfc_evaluate_now (bound, &se->pre);
3100 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3101 bound, build_int_cst (TREE_TYPE (bound), 1));
3102 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3103 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3104 bound, tmp);
3105 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3106 logical_type_node, cond, tmp);
3107 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3108 gfc_msg_fault);
3112 /* Subtract 1 to get to zero based and add dimensions. */
3113 switch (arg->expr->rank)
3115 case 0:
3116 bound = fold_build2_loc (input_location, MINUS_EXPR,
3117 gfc_array_index_type, bound,
3118 gfc_index_one_node);
3119 case 1:
3120 break;
3121 default:
3122 bound = fold_build2_loc (input_location, PLUS_EXPR,
3123 gfc_array_index_type, bound,
3124 gfc_rank_cst[arg->expr->rank - 1]);
3128 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3130 /* Handle UCOBOUND with special handling of the last codimension. */
3131 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3133 /* Last codimension: For -fcoarray=single just return
3134 the lcobound - otherwise add
3135 ceiling (real (num_images ()) / real (size)) - 1
3136 = (num_images () + size - 1) / size - 1
3137 = (num_images - 1) / size(),
3138 where size is the product of the extent of all but the last
3139 codimension. */
3141 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3143 tree cosize;
3145 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3146 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3147 2, integer_zero_node,
3148 build_int_cst (integer_type_node, -1));
3149 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3150 gfc_array_index_type,
3151 fold_convert (gfc_array_index_type, tmp),
3152 build_int_cst (gfc_array_index_type, 1));
3153 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3154 gfc_array_index_type, tmp,
3155 fold_convert (gfc_array_index_type, cosize));
3156 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3157 gfc_array_index_type, resbound, tmp);
3159 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3161 /* ubound = lbound + num_images() - 1. */
3162 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3163 2, integer_zero_node,
3164 build_int_cst (integer_type_node, -1));
3165 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3166 gfc_array_index_type,
3167 fold_convert (gfc_array_index_type, tmp),
3168 build_int_cst (gfc_array_index_type, 1));
3169 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3170 gfc_array_index_type, resbound, tmp);
3173 if (corank > 1)
3175 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3176 bound,
3177 build_int_cst (TREE_TYPE (bound),
3178 arg->expr->rank + corank - 1));
3180 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3181 se->expr = fold_build3_loc (input_location, COND_EXPR,
3182 gfc_array_index_type, cond,
3183 resbound, resbound2);
3185 else
3186 se->expr = resbound;
3188 else
3189 se->expr = resbound;
3191 type = gfc_typenode_for_spec (&expr->ts);
3192 se->expr = convert (type, se->expr);
3196 static void
3197 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3199 gfc_actual_arglist *array_arg;
3200 gfc_actual_arglist *dim_arg;
3201 gfc_se argse;
3202 tree desc, tmp;
3204 array_arg = expr->value.function.actual;
3205 dim_arg = array_arg->next;
3207 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3209 gfc_init_se (&argse, NULL);
3210 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3211 gfc_add_block_to_block (&se->pre, &argse.pre);
3212 gfc_add_block_to_block (&se->post, &argse.post);
3213 desc = argse.expr;
3215 gcc_assert (dim_arg->expr);
3216 gfc_init_se (&argse, NULL);
3217 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3218 gfc_add_block_to_block (&se->pre, &argse.pre);
3219 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3220 argse.expr, gfc_index_one_node);
3221 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3224 static void
3225 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3227 tree arg, cabs;
3229 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3231 switch (expr->value.function.actual->expr->ts.type)
3233 case BT_INTEGER:
3234 case BT_REAL:
3235 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3236 arg);
3237 break;
3239 case BT_COMPLEX:
3240 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3241 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3242 break;
3244 default:
3245 gcc_unreachable ();
3250 /* Create a complex value from one or two real components. */
3252 static void
3253 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3255 tree real;
3256 tree imag;
3257 tree type;
3258 tree *args;
3259 unsigned int num_args;
3261 num_args = gfc_intrinsic_argument_list_length (expr);
3262 args = XALLOCAVEC (tree, num_args);
3264 type = gfc_typenode_for_spec (&expr->ts);
3265 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3266 real = convert (TREE_TYPE (type), args[0]);
3267 if (both)
3268 imag = convert (TREE_TYPE (type), args[1]);
3269 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3271 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3272 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3273 imag = convert (TREE_TYPE (type), imag);
3275 else
3276 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3278 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3282 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3283 MODULO(A, P) = A - FLOOR (A / P) * P
3285 The obvious algorithms above are numerically instable for large
3286 arguments, hence these intrinsics are instead implemented via calls
3287 to the fmod family of functions. It is the responsibility of the
3288 user to ensure that the second argument is non-zero. */
3290 static void
3291 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3293 tree type;
3294 tree tmp;
3295 tree test;
3296 tree test2;
3297 tree fmod;
3298 tree zero;
3299 tree args[2];
3301 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3303 switch (expr->ts.type)
3305 case BT_INTEGER:
3306 /* Integer case is easy, we've got a builtin op. */
3307 type = TREE_TYPE (args[0]);
3309 if (modulo)
3310 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3311 args[0], args[1]);
3312 else
3313 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3314 args[0], args[1]);
3315 break;
3317 case BT_REAL:
3318 fmod = NULL_TREE;
3319 /* Check if we have a builtin fmod. */
3320 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3322 /* The builtin should always be available. */
3323 gcc_assert (fmod != NULL_TREE);
3325 tmp = build_addr (fmod);
3326 se->expr = build_call_array_loc (input_location,
3327 TREE_TYPE (TREE_TYPE (fmod)),
3328 tmp, 2, args);
3329 if (modulo == 0)
3330 return;
3332 type = TREE_TYPE (args[0]);
3334 args[0] = gfc_evaluate_now (args[0], &se->pre);
3335 args[1] = gfc_evaluate_now (args[1], &se->pre);
3337 /* Definition:
3338 modulo = arg - floor (arg/arg2) * arg2
3340 In order to calculate the result accurately, we use the fmod
3341 function as follows.
3343 res = fmod (arg, arg2);
3344 if (res)
3346 if ((arg < 0) xor (arg2 < 0))
3347 res += arg2;
3349 else
3350 res = copysign (0., arg2);
3352 => As two nested ternary exprs:
3354 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3355 : copysign (0., arg2);
3359 zero = gfc_build_const (type, integer_zero_node);
3360 tmp = gfc_evaluate_now (se->expr, &se->pre);
3361 if (!flag_signed_zeros)
3363 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3364 args[0], zero);
3365 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3366 args[1], zero);
3367 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3368 logical_type_node, test, test2);
3369 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3370 tmp, zero);
3371 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3372 logical_type_node, test, test2);
3373 test = gfc_evaluate_now (test, &se->pre);
3374 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3375 fold_build2_loc (input_location,
3376 PLUS_EXPR,
3377 type, tmp, args[1]),
3378 tmp);
3380 else
3382 tree expr1, copysign, cscall;
3383 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3384 expr->ts.kind);
3385 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3386 args[0], zero);
3387 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3388 args[1], zero);
3389 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3390 logical_type_node, test, test2);
3391 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3392 fold_build2_loc (input_location,
3393 PLUS_EXPR,
3394 type, tmp, args[1]),
3395 tmp);
3396 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3397 tmp, zero);
3398 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3399 args[1]);
3400 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3401 expr1, cscall);
3403 return;
3405 default:
3406 gcc_unreachable ();
3410 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3411 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3412 where the right shifts are logical (i.e. 0's are shifted in).
3413 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3414 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3415 DSHIFTL(I,J,0) = I
3416 DSHIFTL(I,J,BITSIZE) = J
3417 DSHIFTR(I,J,0) = J
3418 DSHIFTR(I,J,BITSIZE) = I. */
3420 static void
3421 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3423 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3424 tree args[3], cond, tmp;
3425 int bitsize;
3427 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3429 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3430 type = TREE_TYPE (args[0]);
3431 bitsize = TYPE_PRECISION (type);
3432 utype = unsigned_type_for (type);
3433 stype = TREE_TYPE (args[2]);
3435 arg1 = gfc_evaluate_now (args[0], &se->pre);
3436 arg2 = gfc_evaluate_now (args[1], &se->pre);
3437 shift = gfc_evaluate_now (args[2], &se->pre);
3439 /* The generic case. */
3440 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3441 build_int_cst (stype, bitsize), shift);
3442 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3443 arg1, dshiftl ? shift : tmp);
3445 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3446 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3447 right = fold_convert (type, right);
3449 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3451 /* Special cases. */
3452 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3453 build_int_cst (stype, 0));
3454 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3455 dshiftl ? arg1 : arg2, res);
3457 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3458 build_int_cst (stype, bitsize));
3459 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3460 dshiftl ? arg2 : arg1, res);
3462 se->expr = res;
3466 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3468 static void
3469 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3471 tree val;
3472 tree tmp;
3473 tree type;
3474 tree zero;
3475 tree args[2];
3477 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3478 type = TREE_TYPE (args[0]);
3480 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3481 val = gfc_evaluate_now (val, &se->pre);
3483 zero = gfc_build_const (type, integer_zero_node);
3484 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3485 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3489 /* SIGN(A, B) is absolute value of A times sign of B.
3490 The real value versions use library functions to ensure the correct
3491 handling of negative zero. Integer case implemented as:
3492 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3495 static void
3496 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3498 tree tmp;
3499 tree type;
3500 tree args[2];
3502 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3503 if (expr->ts.type == BT_REAL)
3505 tree abs;
3507 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3508 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3510 /* We explicitly have to ignore the minus sign. We do so by using
3511 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3512 if (!flag_sign_zero
3513 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3515 tree cond, zero;
3516 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3517 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3518 args[1], zero);
3519 se->expr = fold_build3_loc (input_location, COND_EXPR,
3520 TREE_TYPE (args[0]), cond,
3521 build_call_expr_loc (input_location, abs, 1,
3522 args[0]),
3523 build_call_expr_loc (input_location, tmp, 2,
3524 args[0], args[1]));
3526 else
3527 se->expr = build_call_expr_loc (input_location, tmp, 2,
3528 args[0], args[1]);
3529 return;
3532 /* Having excluded floating point types, we know we are now dealing
3533 with signed integer types. */
3534 type = TREE_TYPE (args[0]);
3536 /* Args[0] is used multiple times below. */
3537 args[0] = gfc_evaluate_now (args[0], &se->pre);
3539 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3540 the signs of A and B are the same, and of all ones if they differ. */
3541 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3542 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3543 build_int_cst (type, TYPE_PRECISION (type) - 1));
3544 tmp = gfc_evaluate_now (tmp, &se->pre);
3546 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3547 is all ones (i.e. -1). */
3548 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3549 fold_build2_loc (input_location, PLUS_EXPR,
3550 type, args[0], tmp), tmp);
3554 /* Test for the presence of an optional argument. */
3556 static void
3557 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3559 gfc_expr *arg;
3561 arg = expr->value.function.actual->expr;
3562 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3563 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3564 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3568 /* Calculate the double precision product of two single precision values. */
3570 static void
3571 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3573 tree type;
3574 tree args[2];
3576 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3578 /* Convert the args to double precision before multiplying. */
3579 type = gfc_typenode_for_spec (&expr->ts);
3580 args[0] = convert (type, args[0]);
3581 args[1] = convert (type, args[1]);
3582 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3583 args[1]);
3587 /* Return a length one character string containing an ascii character. */
3589 static void
3590 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3592 tree arg[2];
3593 tree var;
3594 tree type;
3595 unsigned int num_args;
3597 num_args = gfc_intrinsic_argument_list_length (expr);
3598 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3600 type = gfc_get_char_type (expr->ts.kind);
3601 var = gfc_create_var (type, "char");
3603 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3604 gfc_add_modify (&se->pre, var, arg[0]);
3605 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3606 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3610 static void
3611 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3613 tree var;
3614 tree len;
3615 tree tmp;
3616 tree cond;
3617 tree fndecl;
3618 tree *args;
3619 unsigned int num_args;
3621 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3622 args = XALLOCAVEC (tree, num_args);
3624 var = gfc_create_var (pchar_type_node, "pstr");
3625 len = gfc_create_var (gfc_charlen_type_node, "len");
3627 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3628 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3629 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3631 fndecl = build_addr (gfor_fndecl_ctime);
3632 tmp = build_call_array_loc (input_location,
3633 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3634 fndecl, num_args, args);
3635 gfc_add_expr_to_block (&se->pre, tmp);
3637 /* Free the temporary afterwards, if necessary. */
3638 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3639 len, build_int_cst (TREE_TYPE (len), 0));
3640 tmp = gfc_call_free (var);
3641 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3642 gfc_add_expr_to_block (&se->post, tmp);
3644 se->expr = var;
3645 se->string_length = len;
3649 static void
3650 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3652 tree var;
3653 tree len;
3654 tree tmp;
3655 tree cond;
3656 tree fndecl;
3657 tree *args;
3658 unsigned int num_args;
3660 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3661 args = XALLOCAVEC (tree, num_args);
3663 var = gfc_create_var (pchar_type_node, "pstr");
3664 len = gfc_create_var (gfc_charlen_type_node, "len");
3666 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3667 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3668 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3670 fndecl = build_addr (gfor_fndecl_fdate);
3671 tmp = build_call_array_loc (input_location,
3672 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3673 fndecl, num_args, args);
3674 gfc_add_expr_to_block (&se->pre, tmp);
3676 /* Free the temporary afterwards, if necessary. */
3677 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3678 len, build_int_cst (TREE_TYPE (len), 0));
3679 tmp = gfc_call_free (var);
3680 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3681 gfc_add_expr_to_block (&se->post, tmp);
3683 se->expr = var;
3684 se->string_length = len;
3688 /* Generate a direct call to free() for the FREE subroutine. */
3690 static tree
3691 conv_intrinsic_free (gfc_code *code)
3693 stmtblock_t block;
3694 gfc_se argse;
3695 tree arg, call;
3697 gfc_init_se (&argse, NULL);
3698 gfc_conv_expr (&argse, code->ext.actual->expr);
3699 arg = fold_convert (ptr_type_node, argse.expr);
3701 gfc_init_block (&block);
3702 call = build_call_expr_loc (input_location,
3703 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3704 gfc_add_expr_to_block (&block, call);
3705 return gfc_finish_block (&block);
3709 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3710 handling seeding on coarray images. */
3712 static tree
3713 conv_intrinsic_random_init (gfc_code *code)
3715 stmtblock_t block;
3716 gfc_se se;
3717 tree arg1, arg2, arg3, tmp;
3718 tree logical4_type_node = gfc_get_logical_type (4);
3720 /* Make the function call. */
3721 gfc_init_block (&block);
3722 gfc_init_se (&se, NULL);
3724 /* Convert REPEATABLE to a LOGICAL(4) entity. */
3725 gfc_conv_expr (&se, code->ext.actual->expr);
3726 gfc_add_block_to_block (&block, &se.pre);
3727 arg1 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3728 gfc_add_block_to_block (&block, &se.post);
3730 /* Convert IMAGE_DISTINCT to a LOGICAL(4) entity. */
3731 gfc_conv_expr (&se, code->ext.actual->next->expr);
3732 gfc_add_block_to_block (&block, &se.pre);
3733 arg2 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3734 gfc_add_block_to_block (&block, &se.post);
3736 /* Create the hidden argument. For non-coarray codes and -fcoarray=single,
3737 simply set this to 0. For -fcoarray=lib, generate a call to
3738 THIS_IMAGE() without arguments. */
3739 arg3 = build_int_cst (gfc_get_int_type (4), 0);
3740 if (flag_coarray == GFC_FCOARRAY_LIB)
3742 arg3 = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image,
3743 1, arg3);
3744 se.expr = fold_convert (gfc_get_int_type (4), arg3);
3747 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init, 3,
3748 arg1, arg2, arg3);
3749 gfc_add_expr_to_block (&block, tmp);
3751 return gfc_finish_block (&block);
3755 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3756 conversions. */
3758 static tree
3759 conv_intrinsic_system_clock (gfc_code *code)
3761 stmtblock_t block;
3762 gfc_se count_se, count_rate_se, count_max_se;
3763 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3764 tree tmp;
3765 int least;
3767 gfc_expr *count = code->ext.actual->expr;
3768 gfc_expr *count_rate = code->ext.actual->next->expr;
3769 gfc_expr *count_max = code->ext.actual->next->next->expr;
3771 /* Evaluate our arguments. */
3772 if (count)
3774 gfc_init_se (&count_se, NULL);
3775 gfc_conv_expr (&count_se, count);
3778 if (count_rate)
3780 gfc_init_se (&count_rate_se, NULL);
3781 gfc_conv_expr (&count_rate_se, count_rate);
3784 if (count_max)
3786 gfc_init_se (&count_max_se, NULL);
3787 gfc_conv_expr (&count_max_se, count_max);
3790 /* Find the smallest kind found of the arguments. */
3791 least = 16;
3792 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3793 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3794 : least;
3795 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3796 : least;
3798 /* Prepare temporary variables. */
3800 if (count)
3802 if (least >= 8)
3803 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3804 else if (least == 4)
3805 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3806 else if (count->ts.kind == 1)
3807 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3808 count->ts.kind);
3809 else
3810 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3811 count->ts.kind);
3814 if (count_rate)
3816 if (least >= 8)
3817 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3818 else if (least == 4)
3819 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3820 else
3821 arg2 = integer_zero_node;
3824 if (count_max)
3826 if (least >= 8)
3827 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3828 else if (least == 4)
3829 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3830 else
3831 arg3 = integer_zero_node;
3834 /* Make the function call. */
3835 gfc_init_block (&block);
3837 if (least <= 2)
3839 if (least == 1)
3841 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3842 : null_pointer_node;
3843 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3844 : null_pointer_node;
3845 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3846 : null_pointer_node;
3849 if (least == 2)
3851 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3852 : null_pointer_node;
3853 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3854 : null_pointer_node;
3855 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3856 : null_pointer_node;
3859 else
3861 if (least == 4)
3863 tmp = build_call_expr_loc (input_location,
3864 gfor_fndecl_system_clock4, 3,
3865 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3866 : null_pointer_node,
3867 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3868 : null_pointer_node,
3869 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3870 : null_pointer_node);
3871 gfc_add_expr_to_block (&block, tmp);
3873 /* Handle kind>=8, 10, or 16 arguments */
3874 if (least >= 8)
3876 tmp = build_call_expr_loc (input_location,
3877 gfor_fndecl_system_clock8, 3,
3878 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3879 : null_pointer_node,
3880 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3881 : null_pointer_node,
3882 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3883 : null_pointer_node);
3884 gfc_add_expr_to_block (&block, tmp);
3888 /* And store values back if needed. */
3889 if (arg1 && arg1 != count_se.expr)
3890 gfc_add_modify (&block, count_se.expr,
3891 fold_convert (TREE_TYPE (count_se.expr), arg1));
3892 if (arg2 && arg2 != count_rate_se.expr)
3893 gfc_add_modify (&block, count_rate_se.expr,
3894 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3895 if (arg3 && arg3 != count_max_se.expr)
3896 gfc_add_modify (&block, count_max_se.expr,
3897 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3899 return gfc_finish_block (&block);
3903 /* Return a character string containing the tty name. */
3905 static void
3906 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3908 tree var;
3909 tree len;
3910 tree tmp;
3911 tree cond;
3912 tree fndecl;
3913 tree *args;
3914 unsigned int num_args;
3916 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3917 args = XALLOCAVEC (tree, num_args);
3919 var = gfc_create_var (pchar_type_node, "pstr");
3920 len = gfc_create_var (gfc_charlen_type_node, "len");
3922 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3923 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3924 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3926 fndecl = build_addr (gfor_fndecl_ttynam);
3927 tmp = build_call_array_loc (input_location,
3928 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3929 fndecl, num_args, args);
3930 gfc_add_expr_to_block (&se->pre, tmp);
3932 /* Free the temporary afterwards, if necessary. */
3933 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3934 len, build_int_cst (TREE_TYPE (len), 0));
3935 tmp = gfc_call_free (var);
3936 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3937 gfc_add_expr_to_block (&se->post, tmp);
3939 se->expr = var;
3940 se->string_length = len;
3944 /* Get the minimum/maximum value of all the parameters.
3945 minmax (a1, a2, a3, ...)
3947 mvar = a1;
3948 mvar = COMP (mvar, a2)
3949 mvar = COMP (mvar, a3)
3951 return mvar;
3953 Where COMP is MIN/MAX_EXPR for integral types or when we don't
3954 care about NaNs, or IFN_FMIN/MAX when the target has support for
3955 fast NaN-honouring min/max. When neither holds expand a sequence
3956 of explicit comparisons. */
3958 /* TODO: Mismatching types can occur when specific names are used.
3959 These should be handled during resolution. */
3960 static void
3961 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3963 tree tmp;
3964 tree mvar;
3965 tree val;
3966 tree *args;
3967 tree type;
3968 gfc_actual_arglist *argexpr;
3969 unsigned int i, nargs;
3971 nargs = gfc_intrinsic_argument_list_length (expr);
3972 args = XALLOCAVEC (tree, nargs);
3974 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3975 type = gfc_typenode_for_spec (&expr->ts);
3977 argexpr = expr->value.function.actual;
3978 if (TREE_TYPE (args[0]) != type)
3979 args[0] = convert (type, args[0]);
3980 /* Only evaluate the argument once. */
3981 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3982 args[0] = gfc_evaluate_now (args[0], &se->pre);
3984 mvar = gfc_create_var (type, "M");
3985 gfc_add_modify (&se->pre, mvar, args[0]);
3987 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
3989 tree cond = NULL_TREE;
3990 val = args[i];
3992 /* Handle absent optional arguments by ignoring the comparison. */
3993 if (argexpr->expr->expr_type == EXPR_VARIABLE
3994 && argexpr->expr->symtree->n.sym->attr.optional
3995 && TREE_CODE (val) == INDIRECT_REF)
3997 cond = fold_build2_loc (input_location,
3998 NE_EXPR, logical_type_node,
3999 TREE_OPERAND (val, 0),
4000 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
4002 else if (!VAR_P (val) && !TREE_CONSTANT (val))
4003 /* Only evaluate the argument once. */
4004 val = gfc_evaluate_now (val, &se->pre);
4006 tree calc;
4007 /* For floating point types, the question is what MAX(a, NaN) or
4008 MIN(a, NaN) should return (where "a" is a normal number).
4009 There are valid usecase for returning either one, but the
4010 Fortran standard doesn't specify which one should be chosen.
4011 Also, there is no consensus among other tested compilers. In
4012 short, it's a mess. So lets just do whatever is fastest. */
4013 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
4014 calc = fold_build2_loc (input_location, code, type,
4015 convert (type, val), mvar);
4016 tmp = build2_v (MODIFY_EXPR, mvar, calc);
4018 if (cond != NULL_TREE)
4019 tmp = build3_v (COND_EXPR, cond, tmp,
4020 build_empty_stmt (input_location));
4021 gfc_add_expr_to_block (&se->pre, tmp);
4023 se->expr = mvar;
4027 /* Generate library calls for MIN and MAX intrinsics for character
4028 variables. */
4029 static void
4030 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4032 tree *args;
4033 tree var, len, fndecl, tmp, cond, function;
4034 unsigned int nargs;
4036 nargs = gfc_intrinsic_argument_list_length (expr);
4037 args = XALLOCAVEC (tree, nargs + 4);
4038 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4040 /* Create the result variables. */
4041 len = gfc_create_var (gfc_charlen_type_node, "len");
4042 args[0] = gfc_build_addr_expr (NULL_TREE, len);
4043 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4044 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
4045 args[2] = build_int_cst (integer_type_node, op);
4046 args[3] = build_int_cst (integer_type_node, nargs / 2);
4048 if (expr->ts.kind == 1)
4049 function = gfor_fndecl_string_minmax;
4050 else if (expr->ts.kind == 4)
4051 function = gfor_fndecl_string_minmax_char4;
4052 else
4053 gcc_unreachable ();
4055 /* Make the function call. */
4056 fndecl = build_addr (function);
4057 tmp = build_call_array_loc (input_location,
4058 TREE_TYPE (TREE_TYPE (function)), fndecl,
4059 nargs + 4, args);
4060 gfc_add_expr_to_block (&se->pre, tmp);
4062 /* Free the temporary afterwards, if necessary. */
4063 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4064 len, build_int_cst (TREE_TYPE (len), 0));
4065 tmp = gfc_call_free (var);
4066 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4067 gfc_add_expr_to_block (&se->post, tmp);
4069 se->expr = var;
4070 se->string_length = len;
4074 /* Create a symbol node for this intrinsic. The symbol from the frontend
4075 has the generic name. */
4077 static gfc_symbol *
4078 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4080 gfc_symbol *sym;
4082 /* TODO: Add symbols for intrinsic function to the global namespace. */
4083 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4084 sym = gfc_new_symbol (expr->value.function.name, NULL);
4086 sym->ts = expr->ts;
4087 sym->attr.external = 1;
4088 sym->attr.function = 1;
4089 sym->attr.always_explicit = 1;
4090 sym->attr.proc = PROC_INTRINSIC;
4091 sym->attr.flavor = FL_PROCEDURE;
4092 sym->result = sym;
4093 if (expr->rank > 0)
4095 sym->attr.dimension = 1;
4096 sym->as = gfc_get_array_spec ();
4097 sym->as->type = AS_ASSUMED_SHAPE;
4098 sym->as->rank = expr->rank;
4101 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4102 ignore_optional ? expr->value.function.actual
4103 : NULL);
4105 return sym;
4108 /* Generate a call to an external intrinsic function. */
4109 static void
4110 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4112 gfc_symbol *sym;
4113 vec<tree, va_gc> *append_args;
4115 gcc_assert (!se->ss || se->ss->info->expr == expr);
4117 if (se->ss)
4118 gcc_assert (expr->rank > 0);
4119 else
4120 gcc_assert (expr->rank == 0);
4122 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4124 /* Calls to libgfortran_matmul need to be appended special arguments,
4125 to be able to call the BLAS ?gemm functions if required and possible. */
4126 append_args = NULL;
4127 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4128 && !expr->external_blas
4129 && sym->ts.type != BT_LOGICAL)
4131 tree cint = gfc_get_int_type (gfc_c_int_kind);
4133 if (flag_external_blas
4134 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4135 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4137 tree gemm_fndecl;
4139 if (sym->ts.type == BT_REAL)
4141 if (sym->ts.kind == 4)
4142 gemm_fndecl = gfor_fndecl_sgemm;
4143 else
4144 gemm_fndecl = gfor_fndecl_dgemm;
4146 else
4148 if (sym->ts.kind == 4)
4149 gemm_fndecl = gfor_fndecl_cgemm;
4150 else
4151 gemm_fndecl = gfor_fndecl_zgemm;
4154 vec_alloc (append_args, 3);
4155 append_args->quick_push (build_int_cst (cint, 1));
4156 append_args->quick_push (build_int_cst (cint,
4157 flag_blas_matmul_limit));
4158 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4159 gemm_fndecl));
4161 else
4163 vec_alloc (append_args, 3);
4164 append_args->quick_push (build_int_cst (cint, 0));
4165 append_args->quick_push (build_int_cst (cint, 0));
4166 append_args->quick_push (null_pointer_node);
4170 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4171 append_args);
4172 gfc_free_symbol (sym);
4175 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4176 Implemented as
4177 any(a)
4179 forall (i=...)
4180 if (a[i] != 0)
4181 return 1
4182 end forall
4183 return 0
4185 all(a)
4187 forall (i=...)
4188 if (a[i] == 0)
4189 return 0
4190 end forall
4191 return 1
4194 static void
4195 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4197 tree resvar;
4198 stmtblock_t block;
4199 stmtblock_t body;
4200 tree type;
4201 tree tmp;
4202 tree found;
4203 gfc_loopinfo loop;
4204 gfc_actual_arglist *actual;
4205 gfc_ss *arrayss;
4206 gfc_se arrayse;
4207 tree exit_label;
4209 if (se->ss)
4211 gfc_conv_intrinsic_funcall (se, expr);
4212 return;
4215 actual = expr->value.function.actual;
4216 type = gfc_typenode_for_spec (&expr->ts);
4217 /* Initialize the result. */
4218 resvar = gfc_create_var (type, "test");
4219 if (op == EQ_EXPR)
4220 tmp = convert (type, boolean_true_node);
4221 else
4222 tmp = convert (type, boolean_false_node);
4223 gfc_add_modify (&se->pre, resvar, tmp);
4225 /* Walk the arguments. */
4226 arrayss = gfc_walk_expr (actual->expr);
4227 gcc_assert (arrayss != gfc_ss_terminator);
4229 /* Initialize the scalarizer. */
4230 gfc_init_loopinfo (&loop);
4231 exit_label = gfc_build_label_decl (NULL_TREE);
4232 TREE_USED (exit_label) = 1;
4233 gfc_add_ss_to_loop (&loop, arrayss);
4235 /* Initialize the loop. */
4236 gfc_conv_ss_startstride (&loop);
4237 gfc_conv_loop_setup (&loop, &expr->where);
4239 gfc_mark_ss_chain_used (arrayss, 1);
4240 /* Generate the loop body. */
4241 gfc_start_scalarized_body (&loop, &body);
4243 /* If the condition matches then set the return value. */
4244 gfc_start_block (&block);
4245 if (op == EQ_EXPR)
4246 tmp = convert (type, boolean_false_node);
4247 else
4248 tmp = convert (type, boolean_true_node);
4249 gfc_add_modify (&block, resvar, tmp);
4251 /* And break out of the loop. */
4252 tmp = build1_v (GOTO_EXPR, exit_label);
4253 gfc_add_expr_to_block (&block, tmp);
4255 found = gfc_finish_block (&block);
4257 /* Check this element. */
4258 gfc_init_se (&arrayse, NULL);
4259 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4260 arrayse.ss = arrayss;
4261 gfc_conv_expr_val (&arrayse, actual->expr);
4263 gfc_add_block_to_block (&body, &arrayse.pre);
4264 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4265 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4266 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4267 gfc_add_expr_to_block (&body, tmp);
4268 gfc_add_block_to_block (&body, &arrayse.post);
4270 gfc_trans_scalarizing_loops (&loop, &body);
4272 /* Add the exit label. */
4273 tmp = build1_v (LABEL_EXPR, exit_label);
4274 gfc_add_expr_to_block (&loop.pre, tmp);
4276 gfc_add_block_to_block (&se->pre, &loop.pre);
4277 gfc_add_block_to_block (&se->pre, &loop.post);
4278 gfc_cleanup_loop (&loop);
4280 se->expr = resvar;
4283 /* COUNT(A) = Number of true elements in A. */
4284 static void
4285 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4287 tree resvar;
4288 tree type;
4289 stmtblock_t body;
4290 tree tmp;
4291 gfc_loopinfo loop;
4292 gfc_actual_arglist *actual;
4293 gfc_ss *arrayss;
4294 gfc_se arrayse;
4296 if (se->ss)
4298 gfc_conv_intrinsic_funcall (se, expr);
4299 return;
4302 actual = expr->value.function.actual;
4304 type = gfc_typenode_for_spec (&expr->ts);
4305 /* Initialize the result. */
4306 resvar = gfc_create_var (type, "count");
4307 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4309 /* Walk the arguments. */
4310 arrayss = gfc_walk_expr (actual->expr);
4311 gcc_assert (arrayss != gfc_ss_terminator);
4313 /* Initialize the scalarizer. */
4314 gfc_init_loopinfo (&loop);
4315 gfc_add_ss_to_loop (&loop, arrayss);
4317 /* Initialize the loop. */
4318 gfc_conv_ss_startstride (&loop);
4319 gfc_conv_loop_setup (&loop, &expr->where);
4321 gfc_mark_ss_chain_used (arrayss, 1);
4322 /* Generate the loop body. */
4323 gfc_start_scalarized_body (&loop, &body);
4325 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4326 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4327 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4329 gfc_init_se (&arrayse, NULL);
4330 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4331 arrayse.ss = arrayss;
4332 gfc_conv_expr_val (&arrayse, actual->expr);
4333 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4334 build_empty_stmt (input_location));
4336 gfc_add_block_to_block (&body, &arrayse.pre);
4337 gfc_add_expr_to_block (&body, tmp);
4338 gfc_add_block_to_block (&body, &arrayse.post);
4340 gfc_trans_scalarizing_loops (&loop, &body);
4342 gfc_add_block_to_block (&se->pre, &loop.pre);
4343 gfc_add_block_to_block (&se->pre, &loop.post);
4344 gfc_cleanup_loop (&loop);
4346 se->expr = resvar;
4350 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4351 struct and return the corresponding loopinfo. */
4353 static gfc_loopinfo *
4354 enter_nested_loop (gfc_se *se)
4356 se->ss = se->ss->nested_ss;
4357 gcc_assert (se->ss == se->ss->loop->ss);
4359 return se->ss->loop;
4363 /* Inline implementation of the sum and product intrinsics. */
4364 static void
4365 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4366 bool norm2)
4368 tree resvar;
4369 tree scale = NULL_TREE;
4370 tree type;
4371 stmtblock_t body;
4372 stmtblock_t block;
4373 tree tmp;
4374 gfc_loopinfo loop, *ploop;
4375 gfc_actual_arglist *arg_array, *arg_mask;
4376 gfc_ss *arrayss = NULL;
4377 gfc_ss *maskss = NULL;
4378 gfc_se arrayse;
4379 gfc_se maskse;
4380 gfc_se *parent_se;
4381 gfc_expr *arrayexpr;
4382 gfc_expr *maskexpr;
4384 if (expr->rank > 0)
4386 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4387 parent_se = se;
4389 else
4390 parent_se = NULL;
4392 type = gfc_typenode_for_spec (&expr->ts);
4393 /* Initialize the result. */
4394 resvar = gfc_create_var (type, "val");
4395 if (norm2)
4397 /* result = 0.0;
4398 scale = 1.0. */
4399 scale = gfc_create_var (type, "scale");
4400 gfc_add_modify (&se->pre, scale,
4401 gfc_build_const (type, integer_one_node));
4402 tmp = gfc_build_const (type, integer_zero_node);
4404 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4405 tmp = gfc_build_const (type, integer_zero_node);
4406 else if (op == NE_EXPR)
4407 /* PARITY. */
4408 tmp = convert (type, boolean_false_node);
4409 else if (op == BIT_AND_EXPR)
4410 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4411 type, integer_one_node));
4412 else
4413 tmp = gfc_build_const (type, integer_one_node);
4415 gfc_add_modify (&se->pre, resvar, tmp);
4417 arg_array = expr->value.function.actual;
4419 arrayexpr = arg_array->expr;
4421 if (op == NE_EXPR || norm2)
4422 /* PARITY and NORM2. */
4423 maskexpr = NULL;
4424 else
4426 arg_mask = arg_array->next->next;
4427 gcc_assert (arg_mask != NULL);
4428 maskexpr = arg_mask->expr;
4431 if (expr->rank == 0)
4433 /* Walk the arguments. */
4434 arrayss = gfc_walk_expr (arrayexpr);
4435 gcc_assert (arrayss != gfc_ss_terminator);
4437 if (maskexpr && maskexpr->rank > 0)
4439 maskss = gfc_walk_expr (maskexpr);
4440 gcc_assert (maskss != gfc_ss_terminator);
4442 else
4443 maskss = NULL;
4445 /* Initialize the scalarizer. */
4446 gfc_init_loopinfo (&loop);
4447 gfc_add_ss_to_loop (&loop, arrayss);
4448 if (maskexpr && maskexpr->rank > 0)
4449 gfc_add_ss_to_loop (&loop, maskss);
4451 /* Initialize the loop. */
4452 gfc_conv_ss_startstride (&loop);
4453 gfc_conv_loop_setup (&loop, &expr->where);
4455 gfc_mark_ss_chain_used (arrayss, 1);
4456 if (maskexpr && maskexpr->rank > 0)
4457 gfc_mark_ss_chain_used (maskss, 1);
4459 ploop = &loop;
4461 else
4462 /* All the work has been done in the parent loops. */
4463 ploop = enter_nested_loop (se);
4465 gcc_assert (ploop);
4467 /* Generate the loop body. */
4468 gfc_start_scalarized_body (ploop, &body);
4470 /* If we have a mask, only add this element if the mask is set. */
4471 if (maskexpr && maskexpr->rank > 0)
4473 gfc_init_se (&maskse, parent_se);
4474 gfc_copy_loopinfo_to_se (&maskse, ploop);
4475 if (expr->rank == 0)
4476 maskse.ss = maskss;
4477 gfc_conv_expr_val (&maskse, maskexpr);
4478 gfc_add_block_to_block (&body, &maskse.pre);
4480 gfc_start_block (&block);
4482 else
4483 gfc_init_block (&block);
4485 /* Do the actual summation/product. */
4486 gfc_init_se (&arrayse, parent_se);
4487 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4488 if (expr->rank == 0)
4489 arrayse.ss = arrayss;
4490 gfc_conv_expr_val (&arrayse, arrayexpr);
4491 gfc_add_block_to_block (&block, &arrayse.pre);
4493 if (norm2)
4495 /* if (x (i) != 0.0)
4497 absX = abs(x(i))
4498 if (absX > scale)
4500 val = scale/absX;
4501 result = 1.0 + result * val * val;
4502 scale = absX;
4504 else
4506 val = absX/scale;
4507 result += val * val;
4509 } */
4510 tree res1, res2, cond, absX, val;
4511 stmtblock_t ifblock1, ifblock2, ifblock3;
4513 gfc_init_block (&ifblock1);
4515 absX = gfc_create_var (type, "absX");
4516 gfc_add_modify (&ifblock1, absX,
4517 fold_build1_loc (input_location, ABS_EXPR, type,
4518 arrayse.expr));
4519 val = gfc_create_var (type, "val");
4520 gfc_add_expr_to_block (&ifblock1, val);
4522 gfc_init_block (&ifblock2);
4523 gfc_add_modify (&ifblock2, val,
4524 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4525 absX));
4526 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4527 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4528 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4529 gfc_build_const (type, integer_one_node));
4530 gfc_add_modify (&ifblock2, resvar, res1);
4531 gfc_add_modify (&ifblock2, scale, absX);
4532 res1 = gfc_finish_block (&ifblock2);
4534 gfc_init_block (&ifblock3);
4535 gfc_add_modify (&ifblock3, val,
4536 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4537 scale));
4538 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4539 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4540 gfc_add_modify (&ifblock3, resvar, res2);
4541 res2 = gfc_finish_block (&ifblock3);
4543 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4544 absX, scale);
4545 tmp = build3_v (COND_EXPR, cond, res1, res2);
4546 gfc_add_expr_to_block (&ifblock1, tmp);
4547 tmp = gfc_finish_block (&ifblock1);
4549 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4550 arrayse.expr,
4551 gfc_build_const (type, integer_zero_node));
4553 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4554 gfc_add_expr_to_block (&block, tmp);
4556 else
4558 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4559 gfc_add_modify (&block, resvar, tmp);
4562 gfc_add_block_to_block (&block, &arrayse.post);
4564 if (maskexpr && maskexpr->rank > 0)
4566 /* We enclose the above in if (mask) {...} . */
4568 tmp = gfc_finish_block (&block);
4569 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4570 build_empty_stmt (input_location));
4572 else
4573 tmp = gfc_finish_block (&block);
4574 gfc_add_expr_to_block (&body, tmp);
4576 gfc_trans_scalarizing_loops (ploop, &body);
4578 /* For a scalar mask, enclose the loop in an if statement. */
4579 if (maskexpr && maskexpr->rank == 0)
4581 gfc_init_block (&block);
4582 gfc_add_block_to_block (&block, &ploop->pre);
4583 gfc_add_block_to_block (&block, &ploop->post);
4584 tmp = gfc_finish_block (&block);
4586 if (expr->rank > 0)
4588 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4589 build_empty_stmt (input_location));
4590 gfc_advance_se_ss_chain (se);
4592 else
4594 gcc_assert (expr->rank == 0);
4595 gfc_init_se (&maskse, NULL);
4596 gfc_conv_expr_val (&maskse, maskexpr);
4597 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4598 build_empty_stmt (input_location));
4601 gfc_add_expr_to_block (&block, tmp);
4602 gfc_add_block_to_block (&se->pre, &block);
4603 gcc_assert (se->post.head == NULL);
4605 else
4607 gfc_add_block_to_block (&se->pre, &ploop->pre);
4608 gfc_add_block_to_block (&se->pre, &ploop->post);
4611 if (expr->rank == 0)
4612 gfc_cleanup_loop (ploop);
4614 if (norm2)
4616 /* result = scale * sqrt(result). */
4617 tree sqrt;
4618 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4619 resvar = build_call_expr_loc (input_location,
4620 sqrt, 1, resvar);
4621 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4624 se->expr = resvar;
4628 /* Inline implementation of the dot_product intrinsic. This function
4629 is based on gfc_conv_intrinsic_arith (the previous function). */
4630 static void
4631 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4633 tree resvar;
4634 tree type;
4635 stmtblock_t body;
4636 stmtblock_t block;
4637 tree tmp;
4638 gfc_loopinfo loop;
4639 gfc_actual_arglist *actual;
4640 gfc_ss *arrayss1, *arrayss2;
4641 gfc_se arrayse1, arrayse2;
4642 gfc_expr *arrayexpr1, *arrayexpr2;
4644 type = gfc_typenode_for_spec (&expr->ts);
4646 /* Initialize the result. */
4647 resvar = gfc_create_var (type, "val");
4648 if (expr->ts.type == BT_LOGICAL)
4649 tmp = build_int_cst (type, 0);
4650 else
4651 tmp = gfc_build_const (type, integer_zero_node);
4653 gfc_add_modify (&se->pre, resvar, tmp);
4655 /* Walk argument #1. */
4656 actual = expr->value.function.actual;
4657 arrayexpr1 = actual->expr;
4658 arrayss1 = gfc_walk_expr (arrayexpr1);
4659 gcc_assert (arrayss1 != gfc_ss_terminator);
4661 /* Walk argument #2. */
4662 actual = actual->next;
4663 arrayexpr2 = actual->expr;
4664 arrayss2 = gfc_walk_expr (arrayexpr2);
4665 gcc_assert (arrayss2 != gfc_ss_terminator);
4667 /* Initialize the scalarizer. */
4668 gfc_init_loopinfo (&loop);
4669 gfc_add_ss_to_loop (&loop, arrayss1);
4670 gfc_add_ss_to_loop (&loop, arrayss2);
4672 /* Initialize the loop. */
4673 gfc_conv_ss_startstride (&loop);
4674 gfc_conv_loop_setup (&loop, &expr->where);
4676 gfc_mark_ss_chain_used (arrayss1, 1);
4677 gfc_mark_ss_chain_used (arrayss2, 1);
4679 /* Generate the loop body. */
4680 gfc_start_scalarized_body (&loop, &body);
4681 gfc_init_block (&block);
4683 /* Make the tree expression for [conjg(]array1[)]. */
4684 gfc_init_se (&arrayse1, NULL);
4685 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4686 arrayse1.ss = arrayss1;
4687 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4688 if (expr->ts.type == BT_COMPLEX)
4689 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4690 arrayse1.expr);
4691 gfc_add_block_to_block (&block, &arrayse1.pre);
4693 /* Make the tree expression for array2. */
4694 gfc_init_se (&arrayse2, NULL);
4695 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4696 arrayse2.ss = arrayss2;
4697 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4698 gfc_add_block_to_block (&block, &arrayse2.pre);
4700 /* Do the actual product and sum. */
4701 if (expr->ts.type == BT_LOGICAL)
4703 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4704 arrayse1.expr, arrayse2.expr);
4705 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4707 else
4709 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4710 arrayse2.expr);
4711 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4713 gfc_add_modify (&block, resvar, tmp);
4715 /* Finish up the loop block and the loop. */
4716 tmp = gfc_finish_block (&block);
4717 gfc_add_expr_to_block (&body, tmp);
4719 gfc_trans_scalarizing_loops (&loop, &body);
4720 gfc_add_block_to_block (&se->pre, &loop.pre);
4721 gfc_add_block_to_block (&se->pre, &loop.post);
4722 gfc_cleanup_loop (&loop);
4724 se->expr = resvar;
4728 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4729 we need to handle. For performance reasons we sometimes create two
4730 loops instead of one, where the second one is much simpler.
4731 Examples for minloc intrinsic:
4732 1) Result is an array, a call is generated
4733 2) Array mask is used and NaNs need to be supported:
4734 limit = Infinity;
4735 pos = 0;
4736 S = from;
4737 while (S <= to) {
4738 if (mask[S]) {
4739 if (pos == 0) pos = S + (1 - from);
4740 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4742 S++;
4744 goto lab2;
4745 lab1:;
4746 while (S <= to) {
4747 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4748 S++;
4750 lab2:;
4751 3) NaNs need to be supported, but it is known at compile time or cheaply
4752 at runtime whether array is nonempty or not:
4753 limit = Infinity;
4754 pos = 0;
4755 S = from;
4756 while (S <= to) {
4757 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4758 S++;
4760 if (from <= to) pos = 1;
4761 goto lab2;
4762 lab1:;
4763 while (S <= to) {
4764 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4765 S++;
4767 lab2:;
4768 4) NaNs aren't supported, array mask is used:
4769 limit = infinities_supported ? Infinity : huge (limit);
4770 pos = 0;
4771 S = from;
4772 while (S <= to) {
4773 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4774 S++;
4776 goto lab2;
4777 lab1:;
4778 while (S <= to) {
4779 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4780 S++;
4782 lab2:;
4783 5) Same without array mask:
4784 limit = infinities_supported ? Infinity : huge (limit);
4785 pos = (from <= to) ? 1 : 0;
4786 S = from;
4787 while (S <= to) {
4788 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4789 S++;
4791 For 3) and 5), if mask is scalar, this all goes into a conditional,
4792 setting pos = 0; in the else branch.
4794 Since we now also support the BACK argument, instead of using
4795 if (a[S] < limit), we now use
4797 if (back)
4798 cond = a[S] <= limit;
4799 else
4800 cond = a[S] < limit;
4801 if (cond) {
4802 ....
4804 The optimizer is smart enough to move the condition out of the loop.
4805 The are now marked as unlikely to for further speedup. */
4807 static void
4808 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4810 stmtblock_t body;
4811 stmtblock_t block;
4812 stmtblock_t ifblock;
4813 stmtblock_t elseblock;
4814 tree limit;
4815 tree type;
4816 tree tmp;
4817 tree cond;
4818 tree elsetmp;
4819 tree ifbody;
4820 tree offset;
4821 tree nonempty;
4822 tree lab1, lab2;
4823 tree b_if, b_else;
4824 gfc_loopinfo loop;
4825 gfc_actual_arglist *actual;
4826 gfc_ss *arrayss;
4827 gfc_ss *maskss;
4828 gfc_se arrayse;
4829 gfc_se maskse;
4830 gfc_expr *arrayexpr;
4831 gfc_expr *maskexpr;
4832 gfc_expr *backexpr;
4833 gfc_se backse;
4834 tree pos;
4835 int n;
4837 actual = expr->value.function.actual;
4839 /* The last argument, BACK, is passed by value. Ensure that
4840 by setting its name to %VAL. */
4841 for (gfc_actual_arglist *a = actual; a; a = a->next)
4843 if (a->next == NULL)
4844 a->name = "%VAL";
4847 if (se->ss)
4849 gfc_conv_intrinsic_funcall (se, expr);
4850 return;
4853 arrayexpr = actual->expr;
4855 /* Special case for character maxloc. Remove unneeded actual
4856 arguments, then call a library function. */
4858 if (arrayexpr->ts.type == BT_CHARACTER)
4860 gfc_actual_arglist *a, *b;
4861 a = actual;
4862 while (a->next)
4864 b = a->next;
4865 if (b->expr == NULL || strcmp (b->name, "dim") == 0)
4867 a->next = b->next;
4868 b->next = NULL;
4869 gfc_free_actual_arglist (b);
4871 else
4872 a = b;
4874 gfc_conv_intrinsic_funcall (se, expr);
4875 return;
4878 /* Initialize the result. */
4879 pos = gfc_create_var (gfc_array_index_type, "pos");
4880 offset = gfc_create_var (gfc_array_index_type, "offset");
4881 type = gfc_typenode_for_spec (&expr->ts);
4883 /* Walk the arguments. */
4884 arrayss = gfc_walk_expr (arrayexpr);
4885 gcc_assert (arrayss != gfc_ss_terminator);
4887 actual = actual->next->next;
4888 gcc_assert (actual);
4889 maskexpr = actual->expr;
4890 backexpr = actual->next->next->expr;
4891 nonempty = NULL;
4892 if (maskexpr && maskexpr->rank != 0)
4894 maskss = gfc_walk_expr (maskexpr);
4895 gcc_assert (maskss != gfc_ss_terminator);
4897 else
4899 mpz_t asize;
4900 if (gfc_array_size (arrayexpr, &asize))
4902 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4903 mpz_clear (asize);
4904 nonempty = fold_build2_loc (input_location, GT_EXPR,
4905 logical_type_node, nonempty,
4906 gfc_index_zero_node);
4908 maskss = NULL;
4911 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4912 switch (arrayexpr->ts.type)
4914 case BT_REAL:
4915 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4916 break;
4918 case BT_INTEGER:
4919 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4920 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4921 arrayexpr->ts.kind);
4922 break;
4924 default:
4925 gcc_unreachable ();
4928 /* We start with the most negative possible value for MAXLOC, and the most
4929 positive possible value for MINLOC. The most negative possible value is
4930 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4931 possible value is HUGE in both cases. */
4932 if (op == GT_EXPR)
4933 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4934 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4935 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4936 build_int_cst (TREE_TYPE (tmp), 1));
4938 gfc_add_modify (&se->pre, limit, tmp);
4940 /* Initialize the scalarizer. */
4941 gfc_init_loopinfo (&loop);
4942 gfc_add_ss_to_loop (&loop, arrayss);
4943 if (maskss)
4944 gfc_add_ss_to_loop (&loop, maskss);
4946 /* Initialize the loop. */
4947 gfc_conv_ss_startstride (&loop);
4949 /* The code generated can have more than one loop in sequence (see the
4950 comment at the function header). This doesn't work well with the
4951 scalarizer, which changes arrays' offset when the scalarization loops
4952 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4953 are currently inlined in the scalar case only (for which loop is of rank
4954 one). As there is no dependency to care about in that case, there is no
4955 temporary, so that we can use the scalarizer temporary code to handle
4956 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4957 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4958 to restore offset.
4959 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4960 should eventually go away. We could either create two loops properly,
4961 or find another way to save/restore the array offsets between the two
4962 loops (without conflicting with temporary management), or use a single
4963 loop minmaxloc implementation. See PR 31067. */
4964 loop.temp_dim = loop.dimen;
4965 gfc_conv_loop_setup (&loop, &expr->where);
4967 gcc_assert (loop.dimen == 1);
4968 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4969 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4970 loop.from[0], loop.to[0]);
4972 lab1 = NULL;
4973 lab2 = NULL;
4974 /* Initialize the position to zero, following Fortran 2003. We are free
4975 to do this because Fortran 95 allows the result of an entirely false
4976 mask to be processor dependent. If we know at compile time the array
4977 is non-empty and no MASK is used, we can initialize to 1 to simplify
4978 the inner loop. */
4979 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4980 gfc_add_modify (&loop.pre, pos,
4981 fold_build3_loc (input_location, COND_EXPR,
4982 gfc_array_index_type,
4983 nonempty, gfc_index_one_node,
4984 gfc_index_zero_node));
4985 else
4987 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4988 lab1 = gfc_build_label_decl (NULL_TREE);
4989 TREE_USED (lab1) = 1;
4990 lab2 = gfc_build_label_decl (NULL_TREE);
4991 TREE_USED (lab2) = 1;
4994 /* An offset must be added to the loop
4995 counter to obtain the required position. */
4996 gcc_assert (loop.from[0]);
4998 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4999 gfc_index_one_node, loop.from[0]);
5000 gfc_add_modify (&loop.pre, offset, tmp);
5002 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
5003 if (maskss)
5004 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
5005 /* Generate the loop body. */
5006 gfc_start_scalarized_body (&loop, &body);
5008 /* If we have a mask, only check this element if the mask is set. */
5009 if (maskss)
5011 gfc_init_se (&maskse, NULL);
5012 gfc_copy_loopinfo_to_se (&maskse, &loop);
5013 maskse.ss = maskss;
5014 gfc_conv_expr_val (&maskse, maskexpr);
5015 gfc_add_block_to_block (&body, &maskse.pre);
5017 gfc_start_block (&block);
5019 else
5020 gfc_init_block (&block);
5022 /* Compare with the current limit. */
5023 gfc_init_se (&arrayse, NULL);
5024 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5025 arrayse.ss = arrayss;
5026 gfc_conv_expr_val (&arrayse, arrayexpr);
5027 gfc_add_block_to_block (&block, &arrayse.pre);
5029 gfc_init_se (&backse, NULL);
5030 gfc_conv_expr_val (&backse, backexpr);
5031 gfc_add_block_to_block (&block, &backse.pre);
5033 /* We do the following if this is a more extreme value. */
5034 gfc_start_block (&ifblock);
5036 /* Assign the value to the limit... */
5037 gfc_add_modify (&ifblock, limit, arrayse.expr);
5039 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
5041 stmtblock_t ifblock2;
5042 tree ifbody2;
5044 gfc_start_block (&ifblock2);
5045 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5046 loop.loopvar[0], offset);
5047 gfc_add_modify (&ifblock2, pos, tmp);
5048 ifbody2 = gfc_finish_block (&ifblock2);
5049 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
5050 gfc_index_zero_node);
5051 tmp = build3_v (COND_EXPR, cond, ifbody2,
5052 build_empty_stmt (input_location));
5053 gfc_add_expr_to_block (&block, tmp);
5056 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5057 loop.loopvar[0], offset);
5058 gfc_add_modify (&ifblock, pos, tmp);
5060 if (lab1)
5061 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5063 ifbody = gfc_finish_block (&ifblock);
5065 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5067 if (lab1)
5068 cond = fold_build2_loc (input_location,
5069 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5070 logical_type_node, arrayse.expr, limit);
5071 else
5073 tree ifbody2, elsebody2;
5075 /* We switch to > or >= depending on the value of the BACK argument. */
5076 cond = gfc_create_var (logical_type_node, "cond");
5078 gfc_start_block (&ifblock);
5079 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5080 logical_type_node, arrayse.expr, limit);
5082 gfc_add_modify (&ifblock, cond, b_if);
5083 ifbody2 = gfc_finish_block (&ifblock);
5085 gfc_start_block (&elseblock);
5086 b_else = fold_build2_loc (input_location, op, logical_type_node,
5087 arrayse.expr, limit);
5089 gfc_add_modify (&elseblock, cond, b_else);
5090 elsebody2 = gfc_finish_block (&elseblock);
5092 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5093 backse.expr, ifbody2, elsebody2);
5095 gfc_add_expr_to_block (&block, tmp);
5098 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5099 ifbody = build3_v (COND_EXPR, cond, ifbody,
5100 build_empty_stmt (input_location));
5102 gfc_add_expr_to_block (&block, ifbody);
5104 if (maskss)
5106 /* We enclose the above in if (mask) {...}. */
5107 tmp = gfc_finish_block (&block);
5109 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5110 build_empty_stmt (input_location));
5112 else
5113 tmp = gfc_finish_block (&block);
5114 gfc_add_expr_to_block (&body, tmp);
5116 if (lab1)
5118 gfc_trans_scalarized_loop_boundary (&loop, &body);
5120 if (HONOR_NANS (DECL_MODE (limit)))
5122 if (nonempty != NULL)
5124 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
5125 tmp = build3_v (COND_EXPR, nonempty, ifbody,
5126 build_empty_stmt (input_location));
5127 gfc_add_expr_to_block (&loop.code[0], tmp);
5131 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
5132 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
5134 /* If we have a mask, only check this element if the mask is set. */
5135 if (maskss)
5137 gfc_init_se (&maskse, NULL);
5138 gfc_copy_loopinfo_to_se (&maskse, &loop);
5139 maskse.ss = maskss;
5140 gfc_conv_expr_val (&maskse, maskexpr);
5141 gfc_add_block_to_block (&body, &maskse.pre);
5143 gfc_start_block (&block);
5145 else
5146 gfc_init_block (&block);
5148 /* Compare with the current limit. */
5149 gfc_init_se (&arrayse, NULL);
5150 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5151 arrayse.ss = arrayss;
5152 gfc_conv_expr_val (&arrayse, arrayexpr);
5153 gfc_add_block_to_block (&block, &arrayse.pre);
5155 /* We do the following if this is a more extreme value. */
5156 gfc_start_block (&ifblock);
5158 /* Assign the value to the limit... */
5159 gfc_add_modify (&ifblock, limit, arrayse.expr);
5161 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5162 loop.loopvar[0], offset);
5163 gfc_add_modify (&ifblock, pos, tmp);
5165 ifbody = gfc_finish_block (&ifblock);
5167 /* We switch to > or >= depending on the value of the BACK argument. */
5169 tree ifbody2, elsebody2;
5171 cond = gfc_create_var (logical_type_node, "cond");
5173 gfc_start_block (&ifblock);
5174 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5175 logical_type_node, arrayse.expr, limit);
5177 gfc_add_modify (&ifblock, cond, b_if);
5178 ifbody2 = gfc_finish_block (&ifblock);
5180 gfc_start_block (&elseblock);
5181 b_else = fold_build2_loc (input_location, op, logical_type_node,
5182 arrayse.expr, limit);
5184 gfc_add_modify (&elseblock, cond, b_else);
5185 elsebody2 = gfc_finish_block (&elseblock);
5187 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5188 backse.expr, ifbody2, elsebody2);
5191 gfc_add_expr_to_block (&block, tmp);
5192 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5193 tmp = build3_v (COND_EXPR, cond, ifbody,
5194 build_empty_stmt (input_location));
5196 gfc_add_expr_to_block (&block, tmp);
5198 if (maskss)
5200 /* We enclose the above in if (mask) {...}. */
5201 tmp = gfc_finish_block (&block);
5203 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5204 build_empty_stmt (input_location));
5206 else
5207 tmp = gfc_finish_block (&block);
5208 gfc_add_expr_to_block (&body, tmp);
5209 /* Avoid initializing loopvar[0] again, it should be left where
5210 it finished by the first loop. */
5211 loop.from[0] = loop.loopvar[0];
5214 gfc_trans_scalarizing_loops (&loop, &body);
5216 if (lab2)
5217 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5219 /* For a scalar mask, enclose the loop in an if statement. */
5220 if (maskexpr && maskss == NULL)
5222 gfc_init_se (&maskse, NULL);
5223 gfc_conv_expr_val (&maskse, maskexpr);
5224 gfc_init_block (&block);
5225 gfc_add_block_to_block (&block, &loop.pre);
5226 gfc_add_block_to_block (&block, &loop.post);
5227 tmp = gfc_finish_block (&block);
5229 /* For the else part of the scalar mask, just initialize
5230 the pos variable the same way as above. */
5232 gfc_init_block (&elseblock);
5233 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
5234 elsetmp = gfc_finish_block (&elseblock);
5236 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
5237 gfc_add_expr_to_block (&block, tmp);
5238 gfc_add_block_to_block (&se->pre, &block);
5240 else
5242 gfc_add_block_to_block (&se->pre, &loop.pre);
5243 gfc_add_block_to_block (&se->pre, &loop.post);
5245 gfc_cleanup_loop (&loop);
5247 se->expr = convert (type, pos);
5250 /* Emit code for findloc. */
5252 static void
5253 gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
5255 gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
5256 *kind_arg, *back_arg;
5257 gfc_expr *value_expr;
5258 int ikind;
5259 tree resvar;
5260 stmtblock_t block;
5261 stmtblock_t body;
5262 stmtblock_t loopblock;
5263 tree type;
5264 tree tmp;
5265 tree found;
5266 tree forward_branch;
5267 tree back_branch;
5268 gfc_loopinfo loop;
5269 gfc_ss *arrayss;
5270 gfc_ss *maskss;
5271 gfc_se arrayse;
5272 gfc_se valuese;
5273 gfc_se maskse;
5274 gfc_se backse;
5275 tree exit_label;
5276 gfc_expr *maskexpr;
5277 tree offset;
5278 int i;
5280 array_arg = expr->value.function.actual;
5281 value_arg = array_arg->next;
5282 dim_arg = value_arg->next;
5283 mask_arg = dim_arg->next;
5284 kind_arg = mask_arg->next;
5285 back_arg = kind_arg->next;
5287 /* Remove kind and set ikind. */
5288 if (kind_arg->expr)
5290 ikind = mpz_get_si (kind_arg->expr->value.integer);
5291 gfc_free_expr (kind_arg->expr);
5292 kind_arg->expr = NULL;
5294 else
5295 ikind = gfc_default_integer_kind;
5297 value_expr = value_arg->expr;
5299 /* Unless it's a string, pass VALUE by value. */
5300 if (value_expr->ts.type != BT_CHARACTER)
5301 value_arg->name = "%VAL";
5303 /* Pass BACK argument by value. */
5304 back_arg->name = "%VAL";
5306 /* Call the library if we have a character function or if
5307 rank > 0. */
5308 if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
5310 se->ignore_optional = 1;
5311 if (expr->rank == 0)
5313 /* Remove dim argument. */
5314 gfc_free_expr (dim_arg->expr);
5315 dim_arg->expr = NULL;
5317 gfc_conv_intrinsic_funcall (se, expr);
5318 return;
5321 type = gfc_get_int_type (ikind);
5323 /* Initialize the result. */
5324 resvar = gfc_create_var (gfc_array_index_type, "pos");
5325 gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
5326 offset = gfc_create_var (gfc_array_index_type, "offset");
5328 maskexpr = mask_arg->expr;
5330 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
5332 for (i = 0 ; i < 2; i++)
5334 /* Walk the arguments. */
5335 arrayss = gfc_walk_expr (array_arg->expr);
5336 gcc_assert (arrayss != gfc_ss_terminator);
5338 if (maskexpr && maskexpr->rank != 0)
5340 maskss = gfc_walk_expr (maskexpr);
5341 gcc_assert (maskss != gfc_ss_terminator);
5343 else
5344 maskss = NULL;
5346 /* Initialize the scalarizer. */
5347 gfc_init_loopinfo (&loop);
5348 exit_label = gfc_build_label_decl (NULL_TREE);
5349 TREE_USED (exit_label) = 1;
5350 gfc_add_ss_to_loop (&loop, arrayss);
5351 if (maskss)
5352 gfc_add_ss_to_loop (&loop, maskss);
5354 /* Initialize the loop. */
5355 gfc_conv_ss_startstride (&loop);
5356 gfc_conv_loop_setup (&loop, &expr->where);
5358 /* Calculate the offset. */
5359 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5360 gfc_index_one_node, loop.from[0]);
5361 gfc_add_modify (&loop.pre, offset, tmp);
5363 gfc_mark_ss_chain_used (arrayss, 1);
5364 if (maskss)
5365 gfc_mark_ss_chain_used (maskss, 1);
5367 /* The first loop is for BACK=.true. */
5368 if (i == 0)
5369 loop.reverse[0] = GFC_REVERSE_SET;
5371 /* Generate the loop body. */
5372 gfc_start_scalarized_body (&loop, &body);
5374 /* If we have an array mask, only add the element if it is
5375 set. */
5376 if (maskss)
5378 gfc_init_se (&maskse, NULL);
5379 gfc_copy_loopinfo_to_se (&maskse, &loop);
5380 maskse.ss = maskss;
5381 gfc_conv_expr_val (&maskse, maskexpr);
5382 gfc_add_block_to_block (&body, &maskse.pre);
5385 /* If the condition matches then set the return value. */
5386 gfc_start_block (&block);
5388 /* Add the offset. */
5389 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5390 TREE_TYPE (resvar),
5391 loop.loopvar[0], offset);
5392 gfc_add_modify (&block, resvar, tmp);
5393 /* And break out of the loop. */
5394 tmp = build1_v (GOTO_EXPR, exit_label);
5395 gfc_add_expr_to_block (&block, tmp);
5397 found = gfc_finish_block (&block);
5399 /* Check this element. */
5400 gfc_init_se (&arrayse, NULL);
5401 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5402 arrayse.ss = arrayss;
5403 gfc_conv_expr_val (&arrayse, array_arg->expr);
5404 gfc_add_block_to_block (&body, &arrayse.pre);
5406 gfc_init_se (&valuese, NULL);
5407 gfc_conv_expr_val (&valuese, value_arg->expr);
5408 gfc_add_block_to_block (&body, &valuese.pre);
5410 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5411 arrayse.expr, valuese.expr);
5413 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
5414 if (maskss)
5415 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5416 build_empty_stmt (input_location));
5418 gfc_add_expr_to_block (&body, tmp);
5419 gfc_add_block_to_block (&body, &arrayse.post);
5421 gfc_trans_scalarizing_loops (&loop, &body);
5423 /* Add the exit label. */
5424 tmp = build1_v (LABEL_EXPR, exit_label);
5425 gfc_add_expr_to_block (&loop.pre, tmp);
5426 gfc_start_block (&loopblock);
5427 gfc_add_block_to_block (&loopblock, &loop.pre);
5428 gfc_add_block_to_block (&loopblock, &loop.post);
5429 if (i == 0)
5430 forward_branch = gfc_finish_block (&loopblock);
5431 else
5432 back_branch = gfc_finish_block (&loopblock);
5434 gfc_cleanup_loop (&loop);
5437 /* Enclose the two loops in an IF statement. */
5439 gfc_init_se (&backse, NULL);
5440 gfc_conv_expr_val (&backse, back_arg->expr);
5441 gfc_add_block_to_block (&se->pre, &backse.pre);
5442 tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
5444 /* For a scalar mask, enclose the loop in an if statement. */
5445 if (maskexpr && maskss == NULL)
5447 tree if_stmt;
5448 gfc_init_se (&maskse, NULL);
5449 gfc_conv_expr_val (&maskse, maskexpr);
5450 gfc_init_block (&block);
5451 gfc_add_expr_to_block (&block, maskse.expr);
5452 if_stmt = build3_v (COND_EXPR, maskse.expr, tmp,
5453 build_empty_stmt (input_location));
5454 gfc_add_expr_to_block (&block, if_stmt);
5455 tmp = gfc_finish_block (&block);
5458 gfc_add_expr_to_block (&se->pre, tmp);
5459 se->expr = convert (type, resvar);
5463 /* Emit code for minval or maxval intrinsic. There are many different cases
5464 we need to handle. For performance reasons we sometimes create two
5465 loops instead of one, where the second one is much simpler.
5466 Examples for minval intrinsic:
5467 1) Result is an array, a call is generated
5468 2) Array mask is used and NaNs need to be supported, rank 1:
5469 limit = Infinity;
5470 nonempty = false;
5471 S = from;
5472 while (S <= to) {
5473 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5474 S++;
5476 limit = nonempty ? NaN : huge (limit);
5477 lab:
5478 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5479 3) NaNs need to be supported, but it is known at compile time or cheaply
5480 at runtime whether array is nonempty or not, rank 1:
5481 limit = Infinity;
5482 S = from;
5483 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5484 limit = (from <= to) ? NaN : huge (limit);
5485 lab:
5486 while (S <= to) { limit = min (a[S], limit); S++; }
5487 4) Array mask is used and NaNs need to be supported, rank > 1:
5488 limit = Infinity;
5489 nonempty = false;
5490 fast = false;
5491 S1 = from1;
5492 while (S1 <= to1) {
5493 S2 = from2;
5494 while (S2 <= to2) {
5495 if (mask[S1][S2]) {
5496 if (fast) limit = min (a[S1][S2], limit);
5497 else {
5498 nonempty = true;
5499 if (a[S1][S2] <= limit) {
5500 limit = a[S1][S2];
5501 fast = true;
5505 S2++;
5507 S1++;
5509 if (!fast)
5510 limit = nonempty ? NaN : huge (limit);
5511 5) NaNs need to be supported, but it is known at compile time or cheaply
5512 at runtime whether array is nonempty or not, rank > 1:
5513 limit = Infinity;
5514 fast = false;
5515 S1 = from1;
5516 while (S1 <= to1) {
5517 S2 = from2;
5518 while (S2 <= to2) {
5519 if (fast) limit = min (a[S1][S2], limit);
5520 else {
5521 if (a[S1][S2] <= limit) {
5522 limit = a[S1][S2];
5523 fast = true;
5526 S2++;
5528 S1++;
5530 if (!fast)
5531 limit = (nonempty_array) ? NaN : huge (limit);
5532 6) NaNs aren't supported, but infinities are. Array mask is used:
5533 limit = Infinity;
5534 nonempty = false;
5535 S = from;
5536 while (S <= to) {
5537 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5538 S++;
5540 limit = nonempty ? limit : huge (limit);
5541 7) Same without array mask:
5542 limit = Infinity;
5543 S = from;
5544 while (S <= to) { limit = min (a[S], limit); S++; }
5545 limit = (from <= to) ? limit : huge (limit);
5546 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5547 limit = huge (limit);
5548 S = from;
5549 while (S <= to) { limit = min (a[S], limit); S++); }
5551 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5552 with array mask instead).
5553 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5554 setting limit = huge (limit); in the else branch. */
5556 static void
5557 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
5559 tree limit;
5560 tree type;
5561 tree tmp;
5562 tree ifbody;
5563 tree nonempty;
5564 tree nonempty_var;
5565 tree lab;
5566 tree fast;
5567 tree huge_cst = NULL, nan_cst = NULL;
5568 stmtblock_t body;
5569 stmtblock_t block, block2;
5570 gfc_loopinfo loop;
5571 gfc_actual_arglist *actual;
5572 gfc_ss *arrayss;
5573 gfc_ss *maskss;
5574 gfc_se arrayse;
5575 gfc_se maskse;
5576 gfc_expr *arrayexpr;
5577 gfc_expr *maskexpr;
5578 int n;
5580 if (se->ss)
5582 gfc_conv_intrinsic_funcall (se, expr);
5583 return;
5586 actual = expr->value.function.actual;
5587 arrayexpr = actual->expr;
5589 if (arrayexpr->ts.type == BT_CHARACTER)
5591 gfc_actual_arglist *a2, *a3;
5592 a2 = actual->next; /* dim */
5593 a3 = a2->next; /* mask */
5594 if (a2->expr == NULL || expr->rank == 0)
5596 if (a3->expr == NULL)
5597 actual->next = NULL;
5598 else
5600 actual->next = a3;
5601 a2->next = NULL;
5603 gfc_free_actual_arglist (a2);
5605 else
5606 if (a3->expr == NULL)
5608 a2->next = NULL;
5609 gfc_free_actual_arglist (a3);
5611 gfc_conv_intrinsic_funcall (se, expr);
5612 return;
5614 type = gfc_typenode_for_spec (&expr->ts);
5615 /* Initialize the result. */
5616 limit = gfc_create_var (type, "limit");
5617 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5618 switch (expr->ts.type)
5620 case BT_REAL:
5621 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5622 expr->ts.kind, 0);
5623 if (HONOR_INFINITIES (DECL_MODE (limit)))
5625 REAL_VALUE_TYPE real;
5626 real_inf (&real);
5627 tmp = build_real (type, real);
5629 else
5630 tmp = huge_cst;
5631 if (HONOR_NANS (DECL_MODE (limit)))
5632 nan_cst = gfc_build_nan (type, "");
5633 break;
5635 case BT_INTEGER:
5636 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5637 break;
5639 default:
5640 gcc_unreachable ();
5643 /* We start with the most negative possible value for MAXVAL, and the most
5644 positive possible value for MINVAL. The most negative possible value is
5645 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5646 possible value is HUGE in both cases. */
5647 if (op == GT_EXPR)
5649 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5650 if (huge_cst)
5651 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5652 TREE_TYPE (huge_cst), huge_cst);
5655 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5656 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5657 tmp, build_int_cst (type, 1));
5659 gfc_add_modify (&se->pre, limit, tmp);
5661 /* Walk the arguments. */
5662 arrayss = gfc_walk_expr (arrayexpr);
5663 gcc_assert (arrayss != gfc_ss_terminator);
5665 actual = actual->next->next;
5666 gcc_assert (actual);
5667 maskexpr = actual->expr;
5668 nonempty = NULL;
5669 if (maskexpr && maskexpr->rank != 0)
5671 maskss = gfc_walk_expr (maskexpr);
5672 gcc_assert (maskss != gfc_ss_terminator);
5674 else
5676 mpz_t asize;
5677 if (gfc_array_size (arrayexpr, &asize))
5679 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5680 mpz_clear (asize);
5681 nonempty = fold_build2_loc (input_location, GT_EXPR,
5682 logical_type_node, nonempty,
5683 gfc_index_zero_node);
5685 maskss = NULL;
5688 /* Initialize the scalarizer. */
5689 gfc_init_loopinfo (&loop);
5690 gfc_add_ss_to_loop (&loop, arrayss);
5691 if (maskss)
5692 gfc_add_ss_to_loop (&loop, maskss);
5694 /* Initialize the loop. */
5695 gfc_conv_ss_startstride (&loop);
5697 /* The code generated can have more than one loop in sequence (see the
5698 comment at the function header). This doesn't work well with the
5699 scalarizer, which changes arrays' offset when the scalarization loops
5700 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5701 are currently inlined in the scalar case only. As there is no dependency
5702 to care about in that case, there is no temporary, so that we can use the
5703 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5704 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5705 gfc_trans_scalarized_loop_boundary even later to restore offset.
5706 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5707 should eventually go away. We could either create two loops properly,
5708 or find another way to save/restore the array offsets between the two
5709 loops (without conflicting with temporary management), or use a single
5710 loop minmaxval implementation. See PR 31067. */
5711 loop.temp_dim = loop.dimen;
5712 gfc_conv_loop_setup (&loop, &expr->where);
5714 if (nonempty == NULL && maskss == NULL
5715 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5716 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5717 loop.from[0], loop.to[0]);
5718 nonempty_var = NULL;
5719 if (nonempty == NULL
5720 && (HONOR_INFINITIES (DECL_MODE (limit))
5721 || HONOR_NANS (DECL_MODE (limit))))
5723 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5724 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5725 nonempty = nonempty_var;
5727 lab = NULL;
5728 fast = NULL;
5729 if (HONOR_NANS (DECL_MODE (limit)))
5731 if (loop.dimen == 1)
5733 lab = gfc_build_label_decl (NULL_TREE);
5734 TREE_USED (lab) = 1;
5736 else
5738 fast = gfc_create_var (logical_type_node, "fast");
5739 gfc_add_modify (&se->pre, fast, logical_false_node);
5743 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5744 if (maskss)
5745 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5746 /* Generate the loop body. */
5747 gfc_start_scalarized_body (&loop, &body);
5749 /* If we have a mask, only add this element if the mask is set. */
5750 if (maskss)
5752 gfc_init_se (&maskse, NULL);
5753 gfc_copy_loopinfo_to_se (&maskse, &loop);
5754 maskse.ss = maskss;
5755 gfc_conv_expr_val (&maskse, maskexpr);
5756 gfc_add_block_to_block (&body, &maskse.pre);
5758 gfc_start_block (&block);
5760 else
5761 gfc_init_block (&block);
5763 /* Compare with the current limit. */
5764 gfc_init_se (&arrayse, NULL);
5765 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5766 arrayse.ss = arrayss;
5767 gfc_conv_expr_val (&arrayse, arrayexpr);
5768 gfc_add_block_to_block (&block, &arrayse.pre);
5770 gfc_init_block (&block2);
5772 if (nonempty_var)
5773 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5775 if (HONOR_NANS (DECL_MODE (limit)))
5777 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5778 logical_type_node, arrayse.expr, limit);
5779 if (lab)
5780 ifbody = build1_v (GOTO_EXPR, lab);
5781 else
5783 stmtblock_t ifblock;
5785 gfc_init_block (&ifblock);
5786 gfc_add_modify (&ifblock, limit, arrayse.expr);
5787 gfc_add_modify (&ifblock, fast, logical_true_node);
5788 ifbody = gfc_finish_block (&ifblock);
5790 tmp = build3_v (COND_EXPR, tmp, ifbody,
5791 build_empty_stmt (input_location));
5792 gfc_add_expr_to_block (&block2, tmp);
5794 else
5796 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5797 signed zeros. */
5798 tmp = fold_build2_loc (input_location,
5799 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5800 type, arrayse.expr, limit);
5801 gfc_add_modify (&block2, limit, tmp);
5804 if (fast)
5806 tree elsebody = gfc_finish_block (&block2);
5808 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5809 signed zeros. */
5810 if (HONOR_NANS (DECL_MODE (limit)))
5812 tmp = fold_build2_loc (input_location, op, logical_type_node,
5813 arrayse.expr, limit);
5814 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5815 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5816 build_empty_stmt (input_location));
5818 else
5820 tmp = fold_build2_loc (input_location,
5821 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5822 type, arrayse.expr, limit);
5823 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5825 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5826 gfc_add_expr_to_block (&block, tmp);
5828 else
5829 gfc_add_block_to_block (&block, &block2);
5831 gfc_add_block_to_block (&block, &arrayse.post);
5833 tmp = gfc_finish_block (&block);
5834 if (maskss)
5835 /* We enclose the above in if (mask) {...}. */
5836 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5837 build_empty_stmt (input_location));
5838 gfc_add_expr_to_block (&body, tmp);
5840 if (lab)
5842 gfc_trans_scalarized_loop_boundary (&loop, &body);
5844 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5845 nan_cst, huge_cst);
5846 gfc_add_modify (&loop.code[0], limit, tmp);
5847 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5849 /* If we have a mask, only add this element if the mask is set. */
5850 if (maskss)
5852 gfc_init_se (&maskse, NULL);
5853 gfc_copy_loopinfo_to_se (&maskse, &loop);
5854 maskse.ss = maskss;
5855 gfc_conv_expr_val (&maskse, maskexpr);
5856 gfc_add_block_to_block (&body, &maskse.pre);
5858 gfc_start_block (&block);
5860 else
5861 gfc_init_block (&block);
5863 /* Compare with the current limit. */
5864 gfc_init_se (&arrayse, NULL);
5865 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5866 arrayse.ss = arrayss;
5867 gfc_conv_expr_val (&arrayse, arrayexpr);
5868 gfc_add_block_to_block (&block, &arrayse.pre);
5870 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5871 signed zeros. */
5872 if (HONOR_NANS (DECL_MODE (limit)))
5874 tmp = fold_build2_loc (input_location, op, logical_type_node,
5875 arrayse.expr, limit);
5876 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5877 tmp = build3_v (COND_EXPR, tmp, ifbody,
5878 build_empty_stmt (input_location));
5879 gfc_add_expr_to_block (&block, tmp);
5881 else
5883 tmp = fold_build2_loc (input_location,
5884 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5885 type, arrayse.expr, limit);
5886 gfc_add_modify (&block, limit, tmp);
5889 gfc_add_block_to_block (&block, &arrayse.post);
5891 tmp = gfc_finish_block (&block);
5892 if (maskss)
5893 /* We enclose the above in if (mask) {...}. */
5894 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5895 build_empty_stmt (input_location));
5896 gfc_add_expr_to_block (&body, tmp);
5897 /* Avoid initializing loopvar[0] again, it should be left where
5898 it finished by the first loop. */
5899 loop.from[0] = loop.loopvar[0];
5901 gfc_trans_scalarizing_loops (&loop, &body);
5903 if (fast)
5905 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5906 nan_cst, huge_cst);
5907 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5908 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5909 ifbody);
5910 gfc_add_expr_to_block (&loop.pre, tmp);
5912 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5914 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5915 huge_cst);
5916 gfc_add_modify (&loop.pre, limit, tmp);
5919 /* For a scalar mask, enclose the loop in an if statement. */
5920 if (maskexpr && maskss == NULL)
5922 tree else_stmt;
5924 gfc_init_se (&maskse, NULL);
5925 gfc_conv_expr_val (&maskse, maskexpr);
5926 gfc_init_block (&block);
5927 gfc_add_block_to_block (&block, &loop.pre);
5928 gfc_add_block_to_block (&block, &loop.post);
5929 tmp = gfc_finish_block (&block);
5931 if (HONOR_INFINITIES (DECL_MODE (limit)))
5932 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5933 else
5934 else_stmt = build_empty_stmt (input_location);
5935 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5936 gfc_add_expr_to_block (&block, tmp);
5937 gfc_add_block_to_block (&se->pre, &block);
5939 else
5941 gfc_add_block_to_block (&se->pre, &loop.pre);
5942 gfc_add_block_to_block (&se->pre, &loop.post);
5945 gfc_cleanup_loop (&loop);
5947 se->expr = limit;
5950 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5951 static void
5952 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5954 tree args[2];
5955 tree type;
5956 tree tmp;
5958 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5959 type = TREE_TYPE (args[0]);
5961 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5962 build_int_cst (type, 1), args[1]);
5963 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5964 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5965 build_int_cst (type, 0));
5966 type = gfc_typenode_for_spec (&expr->ts);
5967 se->expr = convert (type, tmp);
5971 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5972 static void
5973 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5975 tree args[2];
5977 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5979 /* Convert both arguments to the unsigned type of the same size. */
5980 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5981 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5983 /* If they have unequal type size, convert to the larger one. */
5984 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5985 > TYPE_PRECISION (TREE_TYPE (args[1])))
5986 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5987 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5988 > TYPE_PRECISION (TREE_TYPE (args[0])))
5989 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5991 /* Now, we compare them. */
5992 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5993 args[0], args[1]);
5997 /* Generate code to perform the specified operation. */
5998 static void
5999 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
6001 tree args[2];
6003 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6004 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
6005 args[0], args[1]);
6008 /* Bitwise not. */
6009 static void
6010 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
6012 tree arg;
6014 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6015 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
6016 TREE_TYPE (arg), arg);
6019 /* Set or clear a single bit. */
6020 static void
6021 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
6023 tree args[2];
6024 tree type;
6025 tree tmp;
6026 enum tree_code op;
6028 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6029 type = TREE_TYPE (args[0]);
6031 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6032 build_int_cst (type, 1), args[1]);
6033 if (set)
6034 op = BIT_IOR_EXPR;
6035 else
6037 op = BIT_AND_EXPR;
6038 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
6040 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
6043 /* Extract a sequence of bits.
6044 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
6045 static void
6046 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
6048 tree args[3];
6049 tree type;
6050 tree tmp;
6051 tree mask;
6053 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6054 type = TREE_TYPE (args[0]);
6056 mask = build_int_cst (type, -1);
6057 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
6058 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
6060 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
6062 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
6065 static void
6066 gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
6068 gfc_actual_arglist *s, *k;
6069 gfc_expr *e;
6071 /* Remove the KIND argument, if present. */
6072 s = expr->value.function.actual;
6073 k = s->next;
6074 e = k->expr;
6075 gfc_free_expr (e);
6076 k->expr = NULL;
6078 gfc_conv_intrinsic_funcall (se, expr);
6081 static void
6082 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
6083 bool arithmetic)
6085 tree args[2], type, num_bits, cond;
6087 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6089 args[0] = gfc_evaluate_now (args[0], &se->pre);
6090 args[1] = gfc_evaluate_now (args[1], &se->pre);
6091 type = TREE_TYPE (args[0]);
6093 if (!arithmetic)
6094 args[0] = fold_convert (unsigned_type_for (type), args[0]);
6095 else
6096 gcc_assert (right_shift);
6098 se->expr = fold_build2_loc (input_location,
6099 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
6100 TREE_TYPE (args[0]), args[0], args[1]);
6102 if (!arithmetic)
6103 se->expr = fold_convert (type, se->expr);
6105 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6106 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6107 special case. */
6108 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6109 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6110 args[1], num_bits);
6112 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6113 build_int_cst (type, 0), se->expr);
6116 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
6118 : ((shift >= 0) ? i << shift : i >> -shift)
6119 where all shifts are logical shifts. */
6120 static void
6121 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
6123 tree args[2];
6124 tree type;
6125 tree utype;
6126 tree tmp;
6127 tree width;
6128 tree num_bits;
6129 tree cond;
6130 tree lshift;
6131 tree rshift;
6133 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6135 args[0] = gfc_evaluate_now (args[0], &se->pre);
6136 args[1] = gfc_evaluate_now (args[1], &se->pre);
6138 type = TREE_TYPE (args[0]);
6139 utype = unsigned_type_for (type);
6141 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
6142 args[1]);
6144 /* Left shift if positive. */
6145 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
6147 /* Right shift if negative.
6148 We convert to an unsigned type because we want a logical shift.
6149 The standard doesn't define the case of shifting negative
6150 numbers, and we try to be compatible with other compilers, most
6151 notably g77, here. */
6152 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
6153 utype, convert (utype, args[0]), width));
6155 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
6156 build_int_cst (TREE_TYPE (args[1]), 0));
6157 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
6159 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6160 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6161 special case. */
6162 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6163 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
6164 num_bits);
6165 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6166 build_int_cst (type, 0), tmp);
6170 /* Circular shift. AKA rotate or barrel shift. */
6172 static void
6173 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
6175 tree *args;
6176 tree type;
6177 tree tmp;
6178 tree lrot;
6179 tree rrot;
6180 tree zero;
6181 unsigned int num_args;
6183 num_args = gfc_intrinsic_argument_list_length (expr);
6184 args = XALLOCAVEC (tree, num_args);
6186 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6188 if (num_args == 3)
6190 /* Use a library function for the 3 parameter version. */
6191 tree int4type = gfc_get_int_type (4);
6193 type = TREE_TYPE (args[0]);
6194 /* We convert the first argument to at least 4 bytes, and
6195 convert back afterwards. This removes the need for library
6196 functions for all argument sizes, and function will be
6197 aligned to at least 32 bits, so there's no loss. */
6198 if (expr->ts.kind < 4)
6199 args[0] = convert (int4type, args[0]);
6201 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
6202 need loads of library functions. They cannot have values >
6203 BIT_SIZE (I) so the conversion is safe. */
6204 args[1] = convert (int4type, args[1]);
6205 args[2] = convert (int4type, args[2]);
6207 switch (expr->ts.kind)
6209 case 1:
6210 case 2:
6211 case 4:
6212 tmp = gfor_fndecl_math_ishftc4;
6213 break;
6214 case 8:
6215 tmp = gfor_fndecl_math_ishftc8;
6216 break;
6217 case 16:
6218 tmp = gfor_fndecl_math_ishftc16;
6219 break;
6220 default:
6221 gcc_unreachable ();
6223 se->expr = build_call_expr_loc (input_location,
6224 tmp, 3, args[0], args[1], args[2]);
6225 /* Convert the result back to the original type, if we extended
6226 the first argument's width above. */
6227 if (expr->ts.kind < 4)
6228 se->expr = convert (type, se->expr);
6230 return;
6232 type = TREE_TYPE (args[0]);
6234 /* Evaluate arguments only once. */
6235 args[0] = gfc_evaluate_now (args[0], &se->pre);
6236 args[1] = gfc_evaluate_now (args[1], &se->pre);
6238 /* Rotate left if positive. */
6239 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
6241 /* Rotate right if negative. */
6242 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
6243 args[1]);
6244 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
6246 zero = build_int_cst (TREE_TYPE (args[1]), 0);
6247 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
6248 zero);
6249 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
6251 /* Do nothing if shift == 0. */
6252 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
6253 zero);
6254 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
6255 rrot);
6259 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
6260 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
6262 The conditional expression is necessary because the result of LEADZ(0)
6263 is defined, but the result of __builtin_clz(0) is undefined for most
6264 targets.
6266 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
6267 difference in bit size between the argument of LEADZ and the C int. */
6269 static void
6270 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
6272 tree arg;
6273 tree arg_type;
6274 tree cond;
6275 tree result_type;
6276 tree leadz;
6277 tree bit_size;
6278 tree tmp;
6279 tree func;
6280 int s, argsize;
6282 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6283 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6285 /* Which variant of __builtin_clz* should we call? */
6286 if (argsize <= INT_TYPE_SIZE)
6288 arg_type = unsigned_type_node;
6289 func = builtin_decl_explicit (BUILT_IN_CLZ);
6291 else if (argsize <= LONG_TYPE_SIZE)
6293 arg_type = long_unsigned_type_node;
6294 func = builtin_decl_explicit (BUILT_IN_CLZL);
6296 else if (argsize <= LONG_LONG_TYPE_SIZE)
6298 arg_type = long_long_unsigned_type_node;
6299 func = builtin_decl_explicit (BUILT_IN_CLZLL);
6301 else
6303 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6304 arg_type = gfc_build_uint_type (argsize);
6305 func = NULL_TREE;
6308 /* Convert the actual argument twice: first, to the unsigned type of the
6309 same size; then, to the proper argument type for the built-in
6310 function. But the return type is of the default INTEGER kind. */
6311 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6312 arg = fold_convert (arg_type, arg);
6313 arg = gfc_evaluate_now (arg, &se->pre);
6314 result_type = gfc_get_int_type (gfc_default_integer_kind);
6316 /* Compute LEADZ for the case i .ne. 0. */
6317 if (func)
6319 s = TYPE_PRECISION (arg_type) - argsize;
6320 tmp = fold_convert (result_type,
6321 build_call_expr_loc (input_location, func,
6322 1, arg));
6323 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
6324 tmp, build_int_cst (result_type, s));
6326 else
6328 /* We end up here if the argument type is larger than 'long long'.
6329 We generate this code:
6331 if (x & (ULL_MAX << ULL_SIZE) != 0)
6332 return clzll ((unsigned long long) (x >> ULLSIZE));
6333 else
6334 return ULL_SIZE + clzll ((unsigned long long) x);
6335 where ULL_MAX is the largest value that a ULL_MAX can hold
6336 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6337 is the bit-size of the long long type (64 in this example). */
6338 tree ullsize, ullmax, tmp1, tmp2, btmp;
6340 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6341 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6342 long_long_unsigned_type_node,
6343 build_int_cst (long_long_unsigned_type_node,
6344 0));
6346 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
6347 fold_convert (arg_type, ullmax), ullsize);
6348 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
6349 arg, cond);
6350 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6351 cond, build_int_cst (arg_type, 0));
6353 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6354 arg, ullsize);
6355 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6356 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6357 tmp1 = fold_convert (result_type,
6358 build_call_expr_loc (input_location, btmp, 1, tmp1));
6360 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6361 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6362 tmp2 = fold_convert (result_type,
6363 build_call_expr_loc (input_location, btmp, 1, tmp2));
6364 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6365 tmp2, ullsize);
6367 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
6368 cond, tmp1, tmp2);
6371 /* Build BIT_SIZE. */
6372 bit_size = build_int_cst (result_type, argsize);
6374 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6375 arg, build_int_cst (arg_type, 0));
6376 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6377 bit_size, leadz);
6381 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6383 The conditional expression is necessary because the result of TRAILZ(0)
6384 is defined, but the result of __builtin_ctz(0) is undefined for most
6385 targets. */
6387 static void
6388 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
6390 tree arg;
6391 tree arg_type;
6392 tree cond;
6393 tree result_type;
6394 tree trailz;
6395 tree bit_size;
6396 tree func;
6397 int argsize;
6399 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6400 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6402 /* Which variant of __builtin_ctz* should we call? */
6403 if (argsize <= INT_TYPE_SIZE)
6405 arg_type = unsigned_type_node;
6406 func = builtin_decl_explicit (BUILT_IN_CTZ);
6408 else if (argsize <= LONG_TYPE_SIZE)
6410 arg_type = long_unsigned_type_node;
6411 func = builtin_decl_explicit (BUILT_IN_CTZL);
6413 else if (argsize <= LONG_LONG_TYPE_SIZE)
6415 arg_type = long_long_unsigned_type_node;
6416 func = builtin_decl_explicit (BUILT_IN_CTZLL);
6418 else
6420 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6421 arg_type = gfc_build_uint_type (argsize);
6422 func = NULL_TREE;
6425 /* Convert the actual argument twice: first, to the unsigned type of the
6426 same size; then, to the proper argument type for the built-in
6427 function. But the return type is of the default INTEGER kind. */
6428 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6429 arg = fold_convert (arg_type, arg);
6430 arg = gfc_evaluate_now (arg, &se->pre);
6431 result_type = gfc_get_int_type (gfc_default_integer_kind);
6433 /* Compute TRAILZ for the case i .ne. 0. */
6434 if (func)
6435 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
6436 func, 1, arg));
6437 else
6439 /* We end up here if the argument type is larger than 'long long'.
6440 We generate this code:
6442 if ((x & ULL_MAX) == 0)
6443 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6444 else
6445 return ctzll ((unsigned long long) x);
6447 where ULL_MAX is the largest value that a ULL_MAX can hold
6448 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6449 is the bit-size of the long long type (64 in this example). */
6450 tree ullsize, ullmax, tmp1, tmp2, btmp;
6452 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6453 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6454 long_long_unsigned_type_node,
6455 build_int_cst (long_long_unsigned_type_node, 0));
6457 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
6458 fold_convert (arg_type, ullmax));
6459 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
6460 build_int_cst (arg_type, 0));
6462 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6463 arg, ullsize);
6464 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6465 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6466 tmp1 = fold_convert (result_type,
6467 build_call_expr_loc (input_location, btmp, 1, tmp1));
6468 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6469 tmp1, ullsize);
6471 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6472 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6473 tmp2 = fold_convert (result_type,
6474 build_call_expr_loc (input_location, btmp, 1, tmp2));
6476 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
6477 cond, tmp1, tmp2);
6480 /* Build BIT_SIZE. */
6481 bit_size = build_int_cst (result_type, argsize);
6483 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6484 arg, build_int_cst (arg_type, 0));
6485 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6486 bit_size, trailz);
6489 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6490 for types larger than "long long", we call the long long built-in for
6491 the lower and higher bits and combine the result. */
6493 static void
6494 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
6496 tree arg;
6497 tree arg_type;
6498 tree result_type;
6499 tree func;
6500 int argsize;
6502 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6503 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6504 result_type = gfc_get_int_type (gfc_default_integer_kind);
6506 /* Which variant of the builtin should we call? */
6507 if (argsize <= INT_TYPE_SIZE)
6509 arg_type = unsigned_type_node;
6510 func = builtin_decl_explicit (parity
6511 ? BUILT_IN_PARITY
6512 : BUILT_IN_POPCOUNT);
6514 else if (argsize <= LONG_TYPE_SIZE)
6516 arg_type = long_unsigned_type_node;
6517 func = builtin_decl_explicit (parity
6518 ? BUILT_IN_PARITYL
6519 : BUILT_IN_POPCOUNTL);
6521 else if (argsize <= LONG_LONG_TYPE_SIZE)
6523 arg_type = long_long_unsigned_type_node;
6524 func = builtin_decl_explicit (parity
6525 ? BUILT_IN_PARITYLL
6526 : BUILT_IN_POPCOUNTLL);
6528 else
6530 /* Our argument type is larger than 'long long', which mean none
6531 of the POPCOUNT builtins covers it. We thus call the 'long long'
6532 variant multiple times, and add the results. */
6533 tree utype, arg2, call1, call2;
6535 /* For now, we only cover the case where argsize is twice as large
6536 as 'long long'. */
6537 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6539 func = builtin_decl_explicit (parity
6540 ? BUILT_IN_PARITYLL
6541 : BUILT_IN_POPCOUNTLL);
6543 /* Convert it to an integer, and store into a variable. */
6544 utype = gfc_build_uint_type (argsize);
6545 arg = fold_convert (utype, arg);
6546 arg = gfc_evaluate_now (arg, &se->pre);
6548 /* Call the builtin twice. */
6549 call1 = build_call_expr_loc (input_location, func, 1,
6550 fold_convert (long_long_unsigned_type_node,
6551 arg));
6553 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
6554 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
6555 call2 = build_call_expr_loc (input_location, func, 1,
6556 fold_convert (long_long_unsigned_type_node,
6557 arg2));
6559 /* Combine the results. */
6560 if (parity)
6561 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
6562 call1, call2);
6563 else
6564 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6565 call1, call2);
6567 return;
6570 /* Convert the actual argument twice: first, to the unsigned type of the
6571 same size; then, to the proper argument type for the built-in
6572 function. */
6573 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6574 arg = fold_convert (arg_type, arg);
6576 se->expr = fold_convert (result_type,
6577 build_call_expr_loc (input_location, func, 1, arg));
6581 /* Process an intrinsic with unspecified argument-types that has an optional
6582 argument (which could be of type character), e.g. EOSHIFT. For those, we
6583 need to append the string length of the optional argument if it is not
6584 present and the type is really character.
6585 primary specifies the position (starting at 1) of the non-optional argument
6586 specifying the type and optional gives the position of the optional
6587 argument in the arglist. */
6589 static void
6590 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
6591 unsigned primary, unsigned optional)
6593 gfc_actual_arglist* prim_arg;
6594 gfc_actual_arglist* opt_arg;
6595 unsigned cur_pos;
6596 gfc_actual_arglist* arg;
6597 gfc_symbol* sym;
6598 vec<tree, va_gc> *append_args;
6600 /* Find the two arguments given as position. */
6601 cur_pos = 0;
6602 prim_arg = NULL;
6603 opt_arg = NULL;
6604 for (arg = expr->value.function.actual; arg; arg = arg->next)
6606 ++cur_pos;
6608 if (cur_pos == primary)
6609 prim_arg = arg;
6610 if (cur_pos == optional)
6611 opt_arg = arg;
6613 if (cur_pos >= primary && cur_pos >= optional)
6614 break;
6616 gcc_assert (prim_arg);
6617 gcc_assert (prim_arg->expr);
6618 gcc_assert (opt_arg);
6620 /* If we do have type CHARACTER and the optional argument is really absent,
6621 append a dummy 0 as string length. */
6622 append_args = NULL;
6623 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6625 tree dummy;
6627 dummy = build_int_cst (gfc_charlen_type_node, 0);
6628 vec_alloc (append_args, 1);
6629 append_args->quick_push (dummy);
6632 /* Build the call itself. */
6633 gcc_assert (!se->ignore_optional);
6634 sym = gfc_get_symbol_for_expr (expr, false);
6635 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6636 append_args);
6637 gfc_free_symbol (sym);
6640 /* The length of a character string. */
6641 static void
6642 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6644 tree len;
6645 tree type;
6646 tree decl;
6647 gfc_symbol *sym;
6648 gfc_se argse;
6649 gfc_expr *arg;
6651 gcc_assert (!se->ss);
6653 arg = expr->value.function.actual->expr;
6655 type = gfc_typenode_for_spec (&expr->ts);
6656 switch (arg->expr_type)
6658 case EXPR_CONSTANT:
6659 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6660 break;
6662 case EXPR_ARRAY:
6663 /* Obtain the string length from the function used by
6664 trans-array.c(gfc_trans_array_constructor). */
6665 len = NULL_TREE;
6666 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6667 break;
6669 case EXPR_VARIABLE:
6670 if (arg->ref == NULL
6671 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6673 /* This doesn't catch all cases.
6674 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6675 and the surrounding thread. */
6676 sym = arg->symtree->n.sym;
6677 decl = gfc_get_symbol_decl (sym);
6678 if (decl == current_function_decl && sym->attr.function
6679 && (sym->result == sym))
6680 decl = gfc_get_fake_result_decl (sym, 0);
6682 len = sym->ts.u.cl->backend_decl;
6683 gcc_assert (len);
6684 break;
6687 /* Fall through. */
6689 default:
6690 gfc_init_se (&argse, se);
6691 if (arg->rank == 0)
6692 gfc_conv_expr (&argse, arg);
6693 else
6694 gfc_conv_expr_descriptor (&argse, arg);
6695 gfc_add_block_to_block (&se->pre, &argse.pre);
6696 gfc_add_block_to_block (&se->post, &argse.post);
6697 len = argse.string_length;
6698 break;
6700 se->expr = convert (type, len);
6703 /* The length of a character string not including trailing blanks. */
6704 static void
6705 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6707 int kind = expr->value.function.actual->expr->ts.kind;
6708 tree args[2], type, fndecl;
6710 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6711 type = gfc_typenode_for_spec (&expr->ts);
6713 if (kind == 1)
6714 fndecl = gfor_fndecl_string_len_trim;
6715 else if (kind == 4)
6716 fndecl = gfor_fndecl_string_len_trim_char4;
6717 else
6718 gcc_unreachable ();
6720 se->expr = build_call_expr_loc (input_location,
6721 fndecl, 2, args[0], args[1]);
6722 se->expr = convert (type, se->expr);
6726 /* Returns the starting position of a substring within a string. */
6728 static void
6729 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6730 tree function)
6732 tree logical4_type_node = gfc_get_logical_type (4);
6733 tree type;
6734 tree fndecl;
6735 tree *args;
6736 unsigned int num_args;
6738 args = XALLOCAVEC (tree, 5);
6740 /* Get number of arguments; characters count double due to the
6741 string length argument. Kind= is not passed to the library
6742 and thus ignored. */
6743 if (expr->value.function.actual->next->next->expr == NULL)
6744 num_args = 4;
6745 else
6746 num_args = 5;
6748 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6749 type = gfc_typenode_for_spec (&expr->ts);
6751 if (num_args == 4)
6752 args[4] = build_int_cst (logical4_type_node, 0);
6753 else
6754 args[4] = convert (logical4_type_node, args[4]);
6756 fndecl = build_addr (function);
6757 se->expr = build_call_array_loc (input_location,
6758 TREE_TYPE (TREE_TYPE (function)), fndecl,
6759 5, args);
6760 se->expr = convert (type, se->expr);
6764 /* The ascii value for a single character. */
6765 static void
6766 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6768 tree args[3], type, pchartype;
6769 int nargs;
6771 nargs = gfc_intrinsic_argument_list_length (expr);
6772 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6773 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6774 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6775 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6776 type = gfc_typenode_for_spec (&expr->ts);
6778 se->expr = build_fold_indirect_ref_loc (input_location,
6779 args[1]);
6780 se->expr = convert (type, se->expr);
6784 /* Intrinsic ISNAN calls __builtin_isnan. */
6786 static void
6787 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6789 tree arg;
6791 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6792 se->expr = build_call_expr_loc (input_location,
6793 builtin_decl_explicit (BUILT_IN_ISNAN),
6794 1, arg);
6795 STRIP_TYPE_NOPS (se->expr);
6796 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6800 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6801 their argument against a constant integer value. */
6803 static void
6804 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6806 tree arg;
6808 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6809 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6810 gfc_typenode_for_spec (&expr->ts),
6811 arg, build_int_cst (TREE_TYPE (arg), value));
6816 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6818 static void
6819 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6821 tree tsource;
6822 tree fsource;
6823 tree mask;
6824 tree type;
6825 tree len, len2;
6826 tree *args;
6827 unsigned int num_args;
6829 num_args = gfc_intrinsic_argument_list_length (expr);
6830 args = XALLOCAVEC (tree, num_args);
6832 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6833 if (expr->ts.type != BT_CHARACTER)
6835 tsource = args[0];
6836 fsource = args[1];
6837 mask = args[2];
6839 else
6841 /* We do the same as in the non-character case, but the argument
6842 list is different because of the string length arguments. We
6843 also have to set the string length for the result. */
6844 len = args[0];
6845 tsource = args[1];
6846 len2 = args[2];
6847 fsource = args[3];
6848 mask = args[4];
6850 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6851 &se->pre);
6852 se->string_length = len;
6854 type = TREE_TYPE (tsource);
6855 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6856 fold_convert (type, fsource));
6860 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6862 static void
6863 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6865 tree args[3], mask, type;
6867 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6868 mask = gfc_evaluate_now (args[2], &se->pre);
6870 type = TREE_TYPE (args[0]);
6871 gcc_assert (TREE_TYPE (args[1]) == type);
6872 gcc_assert (TREE_TYPE (mask) == type);
6874 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6875 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6876 fold_build1_loc (input_location, BIT_NOT_EXPR,
6877 type, mask));
6878 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6879 args[0], args[1]);
6883 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6884 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6886 static void
6887 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6889 tree arg, allones, type, utype, res, cond, bitsize;
6890 int i;
6892 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6893 arg = gfc_evaluate_now (arg, &se->pre);
6895 type = gfc_get_int_type (expr->ts.kind);
6896 utype = unsigned_type_for (type);
6898 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6899 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6901 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6902 build_int_cst (utype, 0));
6904 if (left)
6906 /* Left-justified mask. */
6907 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6908 bitsize, arg);
6909 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6910 fold_convert (utype, res));
6912 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6913 smaller than type width. */
6914 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6915 build_int_cst (TREE_TYPE (arg), 0));
6916 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6917 build_int_cst (utype, 0), res);
6919 else
6921 /* Right-justified mask. */
6922 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6923 fold_convert (utype, arg));
6924 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6926 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6927 strictly smaller than type width. */
6928 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6929 arg, bitsize);
6930 res = fold_build3_loc (input_location, COND_EXPR, utype,
6931 cond, allones, res);
6934 se->expr = fold_convert (type, res);
6938 /* FRACTION (s) is translated into:
6939 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6940 static void
6941 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6943 tree arg, type, tmp, res, frexp, cond;
6945 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6947 type = gfc_typenode_for_spec (&expr->ts);
6948 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6949 arg = gfc_evaluate_now (arg, &se->pre);
6951 cond = build_call_expr_loc (input_location,
6952 builtin_decl_explicit (BUILT_IN_ISFINITE),
6953 1, arg);
6955 tmp = gfc_create_var (integer_type_node, NULL);
6956 res = build_call_expr_loc (input_location, frexp, 2,
6957 fold_convert (type, arg),
6958 gfc_build_addr_expr (NULL_TREE, tmp));
6959 res = fold_convert (type, res);
6961 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6962 cond, res, gfc_build_nan (type, ""));
6966 /* NEAREST (s, dir) is translated into
6967 tmp = copysign (HUGE_VAL, dir);
6968 return nextafter (s, tmp);
6970 static void
6971 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6973 tree args[2], type, tmp, nextafter, copysign, huge_val;
6975 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6976 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6978 type = gfc_typenode_for_spec (&expr->ts);
6979 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6981 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6982 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6983 fold_convert (type, args[1]));
6984 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6985 fold_convert (type, args[0]), tmp);
6986 se->expr = fold_convert (type, se->expr);
6990 /* SPACING (s) is translated into
6991 int e;
6992 if (!isfinite (s))
6993 res = NaN;
6994 else if (s == 0)
6995 res = tiny;
6996 else
6998 frexp (s, &e);
6999 e = e - prec;
7000 e = MAX_EXPR (e, emin);
7001 res = scalbn (1., e);
7003 return res;
7005 where prec is the precision of s, gfc_real_kinds[k].digits,
7006 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
7007 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
7009 static void
7010 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
7012 tree arg, type, prec, emin, tiny, res, e;
7013 tree cond, nan, tmp, frexp, scalbn;
7014 int k;
7015 stmtblock_t block;
7017 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
7018 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
7019 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
7020 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
7022 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7023 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7025 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7026 arg = gfc_evaluate_now (arg, &se->pre);
7028 type = gfc_typenode_for_spec (&expr->ts);
7029 e = gfc_create_var (integer_type_node, NULL);
7030 res = gfc_create_var (type, NULL);
7033 /* Build the block for s /= 0. */
7034 gfc_start_block (&block);
7035 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7036 gfc_build_addr_expr (NULL_TREE, e));
7037 gfc_add_expr_to_block (&block, tmp);
7039 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
7040 prec);
7041 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
7042 integer_type_node, tmp, emin));
7044 tmp = build_call_expr_loc (input_location, scalbn, 2,
7045 build_real_from_int_cst (type, integer_one_node), e);
7046 gfc_add_modify (&block, res, tmp);
7048 /* Finish by building the IF statement for value zero. */
7049 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
7050 build_real_from_int_cst (type, integer_zero_node));
7051 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
7052 gfc_finish_block (&block));
7054 /* And deal with infinities and NaNs. */
7055 cond = build_call_expr_loc (input_location,
7056 builtin_decl_explicit (BUILT_IN_ISFINITE),
7057 1, arg);
7058 nan = gfc_build_nan (type, "");
7059 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
7061 gfc_add_expr_to_block (&se->pre, tmp);
7062 se->expr = res;
7066 /* RRSPACING (s) is translated into
7067 int e;
7068 real x;
7069 x = fabs (s);
7070 if (isfinite (x))
7072 if (x != 0)
7074 frexp (s, &e);
7075 x = scalbn (x, precision - e);
7078 else
7079 x = NaN;
7080 return x;
7082 where precision is gfc_real_kinds[k].digits. */
7084 static void
7085 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
7087 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
7088 int prec, k;
7089 stmtblock_t block;
7091 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
7092 prec = gfc_real_kinds[k].digits;
7094 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7095 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7096 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
7098 type = gfc_typenode_for_spec (&expr->ts);
7099 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7100 arg = gfc_evaluate_now (arg, &se->pre);
7102 e = gfc_create_var (integer_type_node, NULL);
7103 x = gfc_create_var (type, NULL);
7104 gfc_add_modify (&se->pre, x,
7105 build_call_expr_loc (input_location, fabs, 1, arg));
7108 gfc_start_block (&block);
7109 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7110 gfc_build_addr_expr (NULL_TREE, e));
7111 gfc_add_expr_to_block (&block, tmp);
7113 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
7114 build_int_cst (integer_type_node, prec), e);
7115 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
7116 gfc_add_modify (&block, x, tmp);
7117 stmt = gfc_finish_block (&block);
7119 /* if (x != 0) */
7120 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
7121 build_real_from_int_cst (type, integer_zero_node));
7122 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
7124 /* And deal with infinities and NaNs. */
7125 cond = build_call_expr_loc (input_location,
7126 builtin_decl_explicit (BUILT_IN_ISFINITE),
7127 1, x);
7128 nan = gfc_build_nan (type, "");
7129 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
7131 gfc_add_expr_to_block (&se->pre, tmp);
7132 se->expr = fold_convert (type, x);
7136 /* SCALE (s, i) is translated into scalbn (s, i). */
7137 static void
7138 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
7140 tree args[2], type, scalbn;
7142 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7144 type = gfc_typenode_for_spec (&expr->ts);
7145 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7146 se->expr = build_call_expr_loc (input_location, scalbn, 2,
7147 fold_convert (type, args[0]),
7148 fold_convert (integer_type_node, args[1]));
7149 se->expr = fold_convert (type, se->expr);
7153 /* SET_EXPONENT (s, i) is translated into
7154 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
7155 static void
7156 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
7158 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
7160 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7161 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7163 type = gfc_typenode_for_spec (&expr->ts);
7164 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7165 args[0] = gfc_evaluate_now (args[0], &se->pre);
7167 tmp = gfc_create_var (integer_type_node, NULL);
7168 tmp = build_call_expr_loc (input_location, frexp, 2,
7169 fold_convert (type, args[0]),
7170 gfc_build_addr_expr (NULL_TREE, tmp));
7171 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
7172 fold_convert (integer_type_node, args[1]));
7173 res = fold_convert (type, res);
7175 /* Call to isfinite */
7176 cond = build_call_expr_loc (input_location,
7177 builtin_decl_explicit (BUILT_IN_ISFINITE),
7178 1, args[0]);
7179 nan = gfc_build_nan (type, "");
7181 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7182 res, nan);
7186 static void
7187 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
7189 gfc_actual_arglist *actual;
7190 tree arg1;
7191 tree type;
7192 tree fncall0;
7193 tree fncall1;
7194 gfc_se argse;
7196 gfc_init_se (&argse, NULL);
7197 actual = expr->value.function.actual;
7199 if (actual->expr->ts.type == BT_CLASS)
7200 gfc_add_class_array_ref (actual->expr);
7202 argse.data_not_needed = 1;
7203 if (gfc_is_class_array_function (actual->expr))
7205 /* For functions that return a class array conv_expr_descriptor is not
7206 able to get the descriptor right. Therefore this special case. */
7207 gfc_conv_expr_reference (&argse, actual->expr);
7208 argse.expr = gfc_build_addr_expr (NULL_TREE,
7209 gfc_class_data_get (argse.expr));
7211 else
7213 argse.want_pointer = 1;
7214 gfc_conv_expr_descriptor (&argse, actual->expr);
7216 gfc_add_block_to_block (&se->pre, &argse.pre);
7217 gfc_add_block_to_block (&se->post, &argse.post);
7218 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
7220 /* Build the call to size0. */
7221 fncall0 = build_call_expr_loc (input_location,
7222 gfor_fndecl_size0, 1, arg1);
7224 actual = actual->next;
7226 if (actual->expr)
7228 gfc_init_se (&argse, NULL);
7229 gfc_conv_expr_type (&argse, actual->expr,
7230 gfc_array_index_type);
7231 gfc_add_block_to_block (&se->pre, &argse.pre);
7233 /* Unusually, for an intrinsic, size does not exclude
7234 an optional arg2, so we must test for it. */
7235 if (actual->expr->expr_type == EXPR_VARIABLE
7236 && actual->expr->symtree->n.sym->attr.dummy
7237 && actual->expr->symtree->n.sym->attr.optional)
7239 tree tmp;
7240 /* Build the call to size1. */
7241 fncall1 = build_call_expr_loc (input_location,
7242 gfor_fndecl_size1, 2,
7243 arg1, argse.expr);
7245 gfc_init_se (&argse, NULL);
7246 argse.want_pointer = 1;
7247 argse.data_not_needed = 1;
7248 gfc_conv_expr (&argse, actual->expr);
7249 gfc_add_block_to_block (&se->pre, &argse.pre);
7250 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7251 argse.expr, null_pointer_node);
7252 tmp = gfc_evaluate_now (tmp, &se->pre);
7253 se->expr = fold_build3_loc (input_location, COND_EXPR,
7254 pvoid_type_node, tmp, fncall1, fncall0);
7256 else
7258 se->expr = NULL_TREE;
7259 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
7260 gfc_array_index_type,
7261 argse.expr, gfc_index_one_node);
7264 else if (expr->value.function.actual->expr->rank == 1)
7266 argse.expr = gfc_index_zero_node;
7267 se->expr = NULL_TREE;
7269 else
7270 se->expr = fncall0;
7272 if (se->expr == NULL_TREE)
7274 tree ubound, lbound;
7276 arg1 = build_fold_indirect_ref_loc (input_location,
7277 arg1);
7278 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
7279 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
7280 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
7281 gfc_array_index_type, ubound, lbound);
7282 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7283 gfc_array_index_type,
7284 se->expr, gfc_index_one_node);
7285 se->expr = fold_build2_loc (input_location, MAX_EXPR,
7286 gfc_array_index_type, se->expr,
7287 gfc_index_zero_node);
7290 type = gfc_typenode_for_spec (&expr->ts);
7291 se->expr = convert (type, se->expr);
7295 /* Helper function to compute the size of a character variable,
7296 excluding the terminating null characters. The result has
7297 gfc_array_index_type type. */
7299 tree
7300 size_of_string_in_bytes (int kind, tree string_length)
7302 tree bytesize;
7303 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
7305 bytesize = build_int_cst (gfc_array_index_type,
7306 gfc_character_kinds[i].bit_size / 8);
7308 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7309 bytesize,
7310 fold_convert (gfc_array_index_type, string_length));
7314 static void
7315 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
7317 gfc_expr *arg;
7318 gfc_se argse;
7319 tree source_bytes;
7320 tree tmp;
7321 tree lower;
7322 tree upper;
7323 tree byte_size;
7324 tree field;
7325 int n;
7327 gfc_init_se (&argse, NULL);
7328 arg = expr->value.function.actual->expr;
7330 if (arg->rank || arg->ts.type == BT_ASSUMED)
7331 gfc_conv_expr_descriptor (&argse, arg);
7332 else
7333 gfc_conv_expr_reference (&argse, arg);
7335 if (arg->ts.type == BT_ASSUMED)
7337 /* This only works if an array descriptor has been passed; thus, extract
7338 the size from the descriptor. */
7339 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
7340 == TYPE_PRECISION (size_type_node));
7341 tmp = arg->symtree->n.sym->backend_decl;
7342 tmp = DECL_LANG_SPECIFIC (tmp)
7343 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
7344 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
7345 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
7346 tmp = build_fold_indirect_ref_loc (input_location, tmp);
7348 tmp = gfc_conv_descriptor_dtype (tmp);
7349 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
7350 GFC_DTYPE_ELEM_LEN);
7351 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
7352 tmp, field, NULL_TREE);
7354 byte_size = fold_convert (gfc_array_index_type, tmp);
7356 else if (arg->ts.type == BT_CLASS)
7358 /* Conv_expr_descriptor returns a component_ref to _data component of the
7359 class object. The class object may be a non-pointer object, e.g.
7360 located on the stack, or a memory location pointed to, e.g. a
7361 parameter, i.e., an indirect_ref. */
7362 if (arg->rank < 0
7363 || (arg->rank > 0 && !VAR_P (argse.expr)
7364 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
7365 && GFC_DECL_CLASS (TREE_OPERAND (
7366 TREE_OPERAND (argse.expr, 0), 0)))
7367 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
7368 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7369 else if (arg->rank > 0
7370 || (arg->rank == 0
7371 && arg->ref && arg->ref->type == REF_COMPONENT))
7372 /* The scalarizer added an additional temp. To get the class' vptr
7373 one has to look at the original backend_decl. */
7374 byte_size = gfc_class_vtab_size_get (
7375 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7376 else
7377 byte_size = gfc_class_vtab_size_get (argse.expr);
7379 else
7381 if (arg->ts.type == BT_CHARACTER)
7382 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7383 else
7385 if (arg->rank == 0)
7386 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7387 argse.expr));
7388 else
7389 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
7390 byte_size = fold_convert (gfc_array_index_type,
7391 size_in_bytes (byte_size));
7395 if (arg->rank == 0)
7396 se->expr = byte_size;
7397 else
7399 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
7400 gfc_add_modify (&argse.pre, source_bytes, byte_size);
7402 if (arg->rank == -1)
7404 tree cond, loop_var, exit_label;
7405 stmtblock_t body;
7407 tmp = fold_convert (gfc_array_index_type,
7408 gfc_conv_descriptor_rank (argse.expr));
7409 loop_var = gfc_create_var (gfc_array_index_type, "i");
7410 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
7411 exit_label = gfc_build_label_decl (NULL_TREE);
7413 /* Create loop:
7414 for (;;)
7416 if (i >= rank)
7417 goto exit;
7418 source_bytes = source_bytes * array.dim[i].extent;
7419 i = i + 1;
7421 exit: */
7422 gfc_start_block (&body);
7423 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7424 loop_var, tmp);
7425 tmp = build1_v (GOTO_EXPR, exit_label);
7426 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7427 cond, tmp, build_empty_stmt (input_location));
7428 gfc_add_expr_to_block (&body, tmp);
7430 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
7431 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
7432 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7433 tmp = fold_build2_loc (input_location, MULT_EXPR,
7434 gfc_array_index_type, tmp, source_bytes);
7435 gfc_add_modify (&body, source_bytes, tmp);
7437 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7438 gfc_array_index_type, loop_var,
7439 gfc_index_one_node);
7440 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
7442 tmp = gfc_finish_block (&body);
7444 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
7445 tmp);
7446 gfc_add_expr_to_block (&argse.pre, tmp);
7448 tmp = build1_v (LABEL_EXPR, exit_label);
7449 gfc_add_expr_to_block (&argse.pre, tmp);
7451 else
7453 /* Obtain the size of the array in bytes. */
7454 for (n = 0; n < arg->rank; n++)
7456 tree idx;
7457 idx = gfc_rank_cst[n];
7458 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7459 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7460 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7461 tmp = fold_build2_loc (input_location, MULT_EXPR,
7462 gfc_array_index_type, tmp, source_bytes);
7463 gfc_add_modify (&argse.pre, source_bytes, tmp);
7466 se->expr = source_bytes;
7469 gfc_add_block_to_block (&se->pre, &argse.pre);
7473 static void
7474 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
7476 gfc_expr *arg;
7477 gfc_se argse;
7478 tree type, result_type, tmp;
7480 arg = expr->value.function.actual->expr;
7482 gfc_init_se (&argse, NULL);
7483 result_type = gfc_get_int_type (expr->ts.kind);
7485 if (arg->rank == 0)
7487 if (arg->ts.type == BT_CLASS)
7489 gfc_add_vptr_component (arg);
7490 gfc_add_size_component (arg);
7491 gfc_conv_expr (&argse, arg);
7492 tmp = fold_convert (result_type, argse.expr);
7493 goto done;
7496 gfc_conv_expr_reference (&argse, arg);
7497 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7498 argse.expr));
7500 else
7502 argse.want_pointer = 0;
7503 gfc_conv_expr_descriptor (&argse, arg);
7504 if (arg->ts.type == BT_CLASS)
7506 if (arg->rank > 0)
7507 tmp = gfc_class_vtab_size_get (
7508 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7509 else
7510 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7511 tmp = fold_convert (result_type, tmp);
7512 goto done;
7514 type = gfc_get_element_type (TREE_TYPE (argse.expr));
7517 /* Obtain the argument's word length. */
7518 if (arg->ts.type == BT_CHARACTER)
7519 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7520 else
7521 tmp = size_in_bytes (type);
7522 tmp = fold_convert (result_type, tmp);
7524 done:
7525 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
7526 build_int_cst (result_type, BITS_PER_UNIT));
7527 gfc_add_block_to_block (&se->pre, &argse.pre);
7531 /* Intrinsic string comparison functions. */
7533 static void
7534 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
7536 tree args[4];
7538 gfc_conv_intrinsic_function_args (se, expr, args, 4);
7540 se->expr
7541 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
7542 expr->value.function.actual->expr->ts.kind,
7543 op);
7544 se->expr = fold_build2_loc (input_location, op,
7545 gfc_typenode_for_spec (&expr->ts), se->expr,
7546 build_int_cst (TREE_TYPE (se->expr), 0));
7549 /* Generate a call to the adjustl/adjustr library function. */
7550 static void
7551 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
7553 tree args[3];
7554 tree len;
7555 tree type;
7556 tree var;
7557 tree tmp;
7559 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
7560 len = args[1];
7562 type = TREE_TYPE (args[2]);
7563 var = gfc_conv_string_tmp (se, type, len);
7564 args[0] = var;
7566 tmp = build_call_expr_loc (input_location,
7567 fndecl, 3, args[0], args[1], args[2]);
7568 gfc_add_expr_to_block (&se->pre, tmp);
7569 se->expr = var;
7570 se->string_length = len;
7574 /* Generate code for the TRANSFER intrinsic:
7575 For scalar results:
7576 DEST = TRANSFER (SOURCE, MOLD)
7577 where:
7578 typeof<DEST> = typeof<MOLD>
7579 and:
7580 MOLD is scalar.
7582 For array results:
7583 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7584 where:
7585 typeof<DEST> = typeof<MOLD>
7586 and:
7587 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7588 sizeof (DEST(0) * SIZE). */
7589 static void
7590 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
7592 tree tmp;
7593 tree tmpdecl;
7594 tree ptr;
7595 tree extent;
7596 tree source;
7597 tree source_type;
7598 tree source_bytes;
7599 tree mold_type;
7600 tree dest_word_len;
7601 tree size_words;
7602 tree size_bytes;
7603 tree upper;
7604 tree lower;
7605 tree stmt;
7606 tree class_ref = NULL_TREE;
7607 gfc_actual_arglist *arg;
7608 gfc_se argse;
7609 gfc_array_info *info;
7610 stmtblock_t block;
7611 int n;
7612 bool scalar_mold;
7613 gfc_expr *source_expr, *mold_expr, *class_expr;
7615 info = NULL;
7616 if (se->loop)
7617 info = &se->ss->info->data.array;
7619 /* Convert SOURCE. The output from this stage is:-
7620 source_bytes = length of the source in bytes
7621 source = pointer to the source data. */
7622 arg = expr->value.function.actual;
7623 source_expr = arg->expr;
7625 /* Ensure double transfer through LOGICAL preserves all
7626 the needed bits. */
7627 if (arg->expr->expr_type == EXPR_FUNCTION
7628 && arg->expr->value.function.esym == NULL
7629 && arg->expr->value.function.isym != NULL
7630 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7631 && arg->expr->ts.type == BT_LOGICAL
7632 && expr->ts.type != arg->expr->ts.type)
7633 arg->expr->value.function.name = "__transfer_in_transfer";
7635 gfc_init_se (&argse, NULL);
7637 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7639 /* Obtain the pointer to source and the length of source in bytes. */
7640 if (arg->expr->rank == 0)
7642 gfc_conv_expr_reference (&argse, arg->expr);
7643 if (arg->expr->ts.type == BT_CLASS)
7645 tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
7646 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
7647 source = gfc_class_data_get (tmp);
7648 else
7650 /* Array elements are evaluated as a reference to the data.
7651 To obtain the vptr for the element size, the argument
7652 expression must be stripped to the class reference and
7653 re-evaluated. The pre and post blocks are not needed. */
7654 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
7655 source = argse.expr;
7656 class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
7657 gfc_init_se (&argse, NULL);
7658 gfc_conv_expr (&argse, class_expr);
7659 class_ref = argse.expr;
7662 else
7663 source = argse.expr;
7665 /* Obtain the source word length. */
7666 switch (arg->expr->ts.type)
7668 case BT_CHARACTER:
7669 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7670 argse.string_length);
7671 break;
7672 case BT_CLASS:
7673 if (class_ref != NULL_TREE)
7674 tmp = gfc_class_vtab_size_get (class_ref);
7675 else
7676 tmp = gfc_class_vtab_size_get (argse.expr);
7677 break;
7678 default:
7679 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7680 source));
7681 tmp = fold_convert (gfc_array_index_type,
7682 size_in_bytes (source_type));
7683 break;
7686 else
7688 argse.want_pointer = 0;
7689 gfc_conv_expr_descriptor (&argse, arg->expr);
7690 source = gfc_conv_descriptor_data_get (argse.expr);
7691 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7693 /* Repack the source if not simply contiguous. */
7694 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7696 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7698 if (warn_array_temporaries)
7699 gfc_warning (OPT_Warray_temporaries,
7700 "Creating array temporary at %L", &expr->where);
7702 source = build_call_expr_loc (input_location,
7703 gfor_fndecl_in_pack, 1, tmp);
7704 source = gfc_evaluate_now (source, &argse.pre);
7706 /* Free the temporary. */
7707 gfc_start_block (&block);
7708 tmp = gfc_call_free (source);
7709 gfc_add_expr_to_block (&block, tmp);
7710 stmt = gfc_finish_block (&block);
7712 /* Clean up if it was repacked. */
7713 gfc_init_block (&block);
7714 tmp = gfc_conv_array_data (argse.expr);
7715 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7716 source, tmp);
7717 tmp = build3_v (COND_EXPR, tmp, stmt,
7718 build_empty_stmt (input_location));
7719 gfc_add_expr_to_block (&block, tmp);
7720 gfc_add_block_to_block (&block, &se->post);
7721 gfc_init_block (&se->post);
7722 gfc_add_block_to_block (&se->post, &block);
7725 /* Obtain the source word length. */
7726 if (arg->expr->ts.type == BT_CHARACTER)
7727 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7728 argse.string_length);
7729 else
7730 tmp = fold_convert (gfc_array_index_type,
7731 size_in_bytes (source_type));
7733 /* Obtain the size of the array in bytes. */
7734 extent = gfc_create_var (gfc_array_index_type, NULL);
7735 for (n = 0; n < arg->expr->rank; n++)
7737 tree idx;
7738 idx = gfc_rank_cst[n];
7739 gfc_add_modify (&argse.pre, source_bytes, tmp);
7740 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7741 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7742 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7743 gfc_array_index_type, upper, lower);
7744 gfc_add_modify (&argse.pre, extent, tmp);
7745 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7746 gfc_array_index_type, extent,
7747 gfc_index_one_node);
7748 tmp = fold_build2_loc (input_location, MULT_EXPR,
7749 gfc_array_index_type, tmp, source_bytes);
7753 gfc_add_modify (&argse.pre, source_bytes, tmp);
7754 gfc_add_block_to_block (&se->pre, &argse.pre);
7755 gfc_add_block_to_block (&se->post, &argse.post);
7757 /* Now convert MOLD. The outputs are:
7758 mold_type = the TREE type of MOLD
7759 dest_word_len = destination word length in bytes. */
7760 arg = arg->next;
7761 mold_expr = arg->expr;
7763 gfc_init_se (&argse, NULL);
7765 scalar_mold = arg->expr->rank == 0;
7767 if (arg->expr->rank == 0)
7769 gfc_conv_expr_reference (&argse, arg->expr);
7770 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7771 argse.expr));
7773 else
7775 gfc_init_se (&argse, NULL);
7776 argse.want_pointer = 0;
7777 gfc_conv_expr_descriptor (&argse, arg->expr);
7778 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7781 gfc_add_block_to_block (&se->pre, &argse.pre);
7782 gfc_add_block_to_block (&se->post, &argse.post);
7784 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7786 /* If this TRANSFER is nested in another TRANSFER, use a type
7787 that preserves all bits. */
7788 if (arg->expr->ts.type == BT_LOGICAL)
7789 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7792 /* Obtain the destination word length. */
7793 switch (arg->expr->ts.type)
7795 case BT_CHARACTER:
7796 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7797 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7798 break;
7799 case BT_CLASS:
7800 tmp = gfc_class_vtab_size_get (argse.expr);
7801 break;
7802 default:
7803 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7804 break;
7806 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7807 gfc_add_modify (&se->pre, dest_word_len, tmp);
7809 /* Finally convert SIZE, if it is present. */
7810 arg = arg->next;
7811 size_words = gfc_create_var (gfc_array_index_type, NULL);
7813 if (arg->expr)
7815 gfc_init_se (&argse, NULL);
7816 gfc_conv_expr_reference (&argse, arg->expr);
7817 tmp = convert (gfc_array_index_type,
7818 build_fold_indirect_ref_loc (input_location,
7819 argse.expr));
7820 gfc_add_block_to_block (&se->pre, &argse.pre);
7821 gfc_add_block_to_block (&se->post, &argse.post);
7823 else
7824 tmp = NULL_TREE;
7826 /* Separate array and scalar results. */
7827 if (scalar_mold && tmp == NULL_TREE)
7828 goto scalar_transfer;
7830 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7831 if (tmp != NULL_TREE)
7832 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7833 tmp, dest_word_len);
7834 else
7835 tmp = source_bytes;
7837 gfc_add_modify (&se->pre, size_bytes, tmp);
7838 gfc_add_modify (&se->pre, size_words,
7839 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7840 gfc_array_index_type,
7841 size_bytes, dest_word_len));
7843 /* Evaluate the bounds of the result. If the loop range exists, we have
7844 to check if it is too large. If so, we modify loop->to be consistent
7845 with min(size, size(source)). Otherwise, size is made consistent with
7846 the loop range, so that the right number of bytes is transferred.*/
7847 n = se->loop->order[0];
7848 if (se->loop->to[n] != NULL_TREE)
7850 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7851 se->loop->to[n], se->loop->from[n]);
7852 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7853 tmp, gfc_index_one_node);
7854 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7855 tmp, size_words);
7856 gfc_add_modify (&se->pre, size_words, tmp);
7857 gfc_add_modify (&se->pre, size_bytes,
7858 fold_build2_loc (input_location, MULT_EXPR,
7859 gfc_array_index_type,
7860 size_words, dest_word_len));
7861 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7862 size_words, se->loop->from[n]);
7863 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7864 upper, gfc_index_one_node);
7866 else
7868 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7869 size_words, gfc_index_one_node);
7870 se->loop->from[n] = gfc_index_zero_node;
7873 se->loop->to[n] = upper;
7875 /* Build a destination descriptor, using the pointer, source, as the
7876 data field. */
7877 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7878 NULL_TREE, false, true, false, &expr->where);
7880 /* Cast the pointer to the result. */
7881 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7882 tmp = fold_convert (pvoid_type_node, tmp);
7884 /* Use memcpy to do the transfer. */
7886 = build_call_expr_loc (input_location,
7887 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7888 fold_convert (pvoid_type_node, source),
7889 fold_convert (size_type_node,
7890 fold_build2_loc (input_location,
7891 MIN_EXPR,
7892 gfc_array_index_type,
7893 size_bytes,
7894 source_bytes)));
7895 gfc_add_expr_to_block (&se->pre, tmp);
7897 se->expr = info->descriptor;
7898 if (expr->ts.type == BT_CHARACTER)
7899 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7901 return;
7903 /* Deal with scalar results. */
7904 scalar_transfer:
7905 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7906 dest_word_len, source_bytes);
7907 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7908 extent, gfc_index_zero_node);
7910 if (expr->ts.type == BT_CHARACTER)
7912 tree direct, indirect, free;
7914 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7915 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7916 "transfer");
7918 /* If source is longer than the destination, use a pointer to
7919 the source directly. */
7920 gfc_init_block (&block);
7921 gfc_add_modify (&block, tmpdecl, ptr);
7922 direct = gfc_finish_block (&block);
7924 /* Otherwise, allocate a string with the length of the destination
7925 and copy the source into it. */
7926 gfc_init_block (&block);
7927 tmp = gfc_get_pchar_type (expr->ts.kind);
7928 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7929 gfc_add_modify (&block, tmpdecl,
7930 fold_convert (TREE_TYPE (ptr), tmp));
7931 tmp = build_call_expr_loc (input_location,
7932 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7933 fold_convert (pvoid_type_node, tmpdecl),
7934 fold_convert (pvoid_type_node, ptr),
7935 fold_convert (size_type_node, extent));
7936 gfc_add_expr_to_block (&block, tmp);
7937 indirect = gfc_finish_block (&block);
7939 /* Wrap it up with the condition. */
7940 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7941 dest_word_len, source_bytes);
7942 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7943 gfc_add_expr_to_block (&se->pre, tmp);
7945 /* Free the temporary string, if necessary. */
7946 free = gfc_call_free (tmpdecl);
7947 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7948 dest_word_len, source_bytes);
7949 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7950 gfc_add_expr_to_block (&se->post, tmp);
7952 se->expr = tmpdecl;
7953 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7955 else
7957 tmpdecl = gfc_create_var (mold_type, "transfer");
7959 ptr = convert (build_pointer_type (mold_type), source);
7961 /* For CLASS results, allocate the needed memory first. */
7962 if (mold_expr->ts.type == BT_CLASS)
7964 tree cdata;
7965 cdata = gfc_class_data_get (tmpdecl);
7966 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7967 gfc_add_modify (&se->pre, cdata, tmp);
7970 /* Use memcpy to do the transfer. */
7971 if (mold_expr->ts.type == BT_CLASS)
7972 tmp = gfc_class_data_get (tmpdecl);
7973 else
7974 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7976 tmp = build_call_expr_loc (input_location,
7977 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7978 fold_convert (pvoid_type_node, tmp),
7979 fold_convert (pvoid_type_node, ptr),
7980 fold_convert (size_type_node, extent));
7981 gfc_add_expr_to_block (&se->pre, tmp);
7983 /* For CLASS results, set the _vptr. */
7984 if (mold_expr->ts.type == BT_CLASS)
7986 tree vptr;
7987 gfc_symbol *vtab;
7988 vptr = gfc_class_vptr_get (tmpdecl);
7989 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7990 gcc_assert (vtab);
7991 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7992 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7995 se->expr = tmpdecl;
8000 /* Generate a call to caf_is_present. */
8002 static tree
8003 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
8005 tree caf_reference, caf_decl, token, image_index;
8007 /* Compile the reference chain. */
8008 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
8009 gcc_assert (caf_reference != NULL_TREE);
8011 caf_decl = gfc_get_tree_for_caf_expr (expr);
8012 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8013 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8014 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
8015 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
8016 expr);
8018 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
8019 3, token, image_index, caf_reference);
8023 /* Test whether this ref-chain refs this image only. */
8025 static bool
8026 caf_this_image_ref (gfc_ref *ref)
8028 for ( ; ref; ref = ref->next)
8029 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
8030 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
8032 return false;
8036 /* Generate code for the ALLOCATED intrinsic.
8037 Generate inline code that directly check the address of the argument. */
8039 static void
8040 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
8042 gfc_actual_arglist *arg1;
8043 gfc_se arg1se;
8044 tree tmp;
8045 symbol_attribute caf_attr;
8047 gfc_init_se (&arg1se, NULL);
8048 arg1 = expr->value.function.actual;
8050 if (arg1->expr->ts.type == BT_CLASS)
8052 /* Make sure that class array expressions have both a _data
8053 component reference and an array reference.... */
8054 if (CLASS_DATA (arg1->expr)->attr.dimension)
8055 gfc_add_class_array_ref (arg1->expr);
8056 /* .... whilst scalars only need the _data component. */
8057 else
8058 gfc_add_data_component (arg1->expr);
8061 /* When arg1 references an allocatable component in a coarray, then call
8062 the caf-library function caf_is_present (). */
8063 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
8064 && arg1->expr->value.function.isym
8065 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
8066 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
8067 else
8068 gfc_clear_attr (&caf_attr);
8069 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
8070 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
8071 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
8072 else
8074 if (arg1->expr->rank == 0)
8076 /* Allocatable scalar. */
8077 arg1se.want_pointer = 1;
8078 gfc_conv_expr (&arg1se, arg1->expr);
8079 tmp = arg1se.expr;
8081 else
8083 /* Allocatable array. */
8084 arg1se.descriptor_only = 1;
8085 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
8086 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
8089 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
8090 fold_convert (TREE_TYPE (tmp), null_pointer_node));
8093 /* Components of pointer array references sometimes come back with a pre block. */
8094 if (arg1se.pre.head)
8095 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8097 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8101 /* Generate code for the ASSOCIATED intrinsic.
8102 If both POINTER and TARGET are arrays, generate a call to library function
8103 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
8104 In other cases, generate inline code that directly compare the address of
8105 POINTER with the address of TARGET. */
8107 static void
8108 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
8110 gfc_actual_arglist *arg1;
8111 gfc_actual_arglist *arg2;
8112 gfc_se arg1se;
8113 gfc_se arg2se;
8114 tree tmp2;
8115 tree tmp;
8116 tree nonzero_charlen;
8117 tree nonzero_arraylen;
8118 gfc_ss *ss;
8119 bool scalar;
8121 gfc_init_se (&arg1se, NULL);
8122 gfc_init_se (&arg2se, NULL);
8123 arg1 = expr->value.function.actual;
8124 arg2 = arg1->next;
8126 /* Check whether the expression is a scalar or not; we cannot use
8127 arg1->expr->rank as it can be nonzero for proc pointers. */
8128 ss = gfc_walk_expr (arg1->expr);
8129 scalar = ss == gfc_ss_terminator;
8130 if (!scalar)
8131 gfc_free_ss_chain (ss);
8133 if (!arg2->expr)
8135 /* No optional target. */
8136 if (scalar)
8138 /* A pointer to a scalar. */
8139 arg1se.want_pointer = 1;
8140 gfc_conv_expr (&arg1se, arg1->expr);
8141 if (arg1->expr->symtree->n.sym->attr.proc_pointer
8142 && arg1->expr->symtree->n.sym->attr.dummy)
8143 arg1se.expr = build_fold_indirect_ref_loc (input_location,
8144 arg1se.expr);
8145 if (arg1->expr->ts.type == BT_CLASS)
8147 tmp2 = gfc_class_data_get (arg1se.expr);
8148 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
8149 tmp2 = gfc_conv_descriptor_data_get (tmp2);
8151 else
8152 tmp2 = arg1se.expr;
8154 else
8156 /* A pointer to an array. */
8157 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
8158 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
8160 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8161 gfc_add_block_to_block (&se->post, &arg1se.post);
8162 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
8163 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
8164 se->expr = tmp;
8166 else
8168 /* An optional target. */
8169 if (arg2->expr->ts.type == BT_CLASS)
8170 gfc_add_data_component (arg2->expr);
8172 nonzero_charlen = NULL_TREE;
8173 if (arg1->expr->ts.type == BT_CHARACTER)
8174 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
8175 logical_type_node,
8176 arg1->expr->ts.u.cl->backend_decl,
8177 build_zero_cst
8178 (TREE_TYPE (arg1->expr->ts.u.cl->backend_decl)));
8179 if (scalar)
8181 /* A pointer to a scalar. */
8182 arg1se.want_pointer = 1;
8183 gfc_conv_expr (&arg1se, arg1->expr);
8184 if (arg1->expr->symtree->n.sym->attr.proc_pointer
8185 && arg1->expr->symtree->n.sym->attr.dummy)
8186 arg1se.expr = build_fold_indirect_ref_loc (input_location,
8187 arg1se.expr);
8188 if (arg1->expr->ts.type == BT_CLASS)
8189 arg1se.expr = gfc_class_data_get (arg1se.expr);
8191 arg2se.want_pointer = 1;
8192 gfc_conv_expr (&arg2se, arg2->expr);
8193 if (arg2->expr->symtree->n.sym->attr.proc_pointer
8194 && arg2->expr->symtree->n.sym->attr.dummy)
8195 arg2se.expr = build_fold_indirect_ref_loc (input_location,
8196 arg2se.expr);
8197 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8198 gfc_add_block_to_block (&se->post, &arg1se.post);
8199 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8200 gfc_add_block_to_block (&se->post, &arg2se.post);
8201 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8202 arg1se.expr, arg2se.expr);
8203 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8204 arg1se.expr, null_pointer_node);
8205 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8206 logical_type_node, tmp, tmp2);
8208 else
8210 /* An array pointer of zero length is not associated if target is
8211 present. */
8212 arg1se.descriptor_only = 1;
8213 gfc_conv_expr_lhs (&arg1se, arg1->expr);
8214 if (arg1->expr->rank == -1)
8216 tmp = gfc_conv_descriptor_rank (arg1se.expr);
8217 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8218 TREE_TYPE (tmp), tmp, gfc_index_one_node);
8220 else
8221 tmp = gfc_rank_cst[arg1->expr->rank - 1];
8222 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
8223 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
8224 logical_type_node, tmp,
8225 build_int_cst (TREE_TYPE (tmp), 0));
8227 /* A pointer to an array, call library function _gfor_associated. */
8228 arg1se.want_pointer = 1;
8229 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
8230 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8231 gfc_add_block_to_block (&se->post, &arg1se.post);
8233 arg2se.want_pointer = 1;
8234 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
8235 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8236 gfc_add_block_to_block (&se->post, &arg2se.post);
8237 se->expr = build_call_expr_loc (input_location,
8238 gfor_fndecl_associated, 2,
8239 arg1se.expr, arg2se.expr);
8240 se->expr = convert (logical_type_node, se->expr);
8241 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8242 logical_type_node, se->expr,
8243 nonzero_arraylen);
8246 /* If target is present zero character length pointers cannot
8247 be associated. */
8248 if (nonzero_charlen != NULL_TREE)
8249 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8250 logical_type_node,
8251 se->expr, nonzero_charlen);
8254 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8258 /* Generate code for the SAME_TYPE_AS intrinsic.
8259 Generate inline code that directly checks the vindices. */
8261 static void
8262 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
8264 gfc_expr *a, *b;
8265 gfc_se se1, se2;
8266 tree tmp;
8267 tree conda = NULL_TREE, condb = NULL_TREE;
8269 gfc_init_se (&se1, NULL);
8270 gfc_init_se (&se2, NULL);
8272 a = expr->value.function.actual->expr;
8273 b = expr->value.function.actual->next->expr;
8275 if (UNLIMITED_POLY (a))
8277 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
8278 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8279 tmp, build_int_cst (TREE_TYPE (tmp), 0));
8282 if (UNLIMITED_POLY (b))
8284 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
8285 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8286 tmp, build_int_cst (TREE_TYPE (tmp), 0));
8289 if (a->ts.type == BT_CLASS)
8291 gfc_add_vptr_component (a);
8292 gfc_add_hash_component (a);
8294 else if (a->ts.type == BT_DERIVED)
8295 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8296 a->ts.u.derived->hash_value);
8298 if (b->ts.type == BT_CLASS)
8300 gfc_add_vptr_component (b);
8301 gfc_add_hash_component (b);
8303 else if (b->ts.type == BT_DERIVED)
8304 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8305 b->ts.u.derived->hash_value);
8307 gfc_conv_expr (&se1, a);
8308 gfc_conv_expr (&se2, b);
8310 tmp = fold_build2_loc (input_location, EQ_EXPR,
8311 logical_type_node, se1.expr,
8312 fold_convert (TREE_TYPE (se1.expr), se2.expr));
8314 if (conda)
8315 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8316 logical_type_node, conda, tmp);
8318 if (condb)
8319 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8320 logical_type_node, condb, tmp);
8322 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8326 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
8328 static void
8329 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
8331 tree args[2];
8333 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8334 se->expr = build_call_expr_loc (input_location,
8335 gfor_fndecl_sc_kind, 2, args[0], args[1]);
8336 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8340 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
8342 static void
8343 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
8345 tree arg, type;
8347 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8349 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
8350 type = gfc_get_int_type (4);
8351 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
8353 /* Convert it to the required type. */
8354 type = gfc_typenode_for_spec (&expr->ts);
8355 se->expr = build_call_expr_loc (input_location,
8356 gfor_fndecl_si_kind, 1, arg);
8357 se->expr = fold_convert (type, se->expr);
8361 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
8363 static void
8364 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
8366 gfc_actual_arglist *actual;
8367 tree type;
8368 gfc_se argse;
8369 vec<tree, va_gc> *args = NULL;
8371 for (actual = expr->value.function.actual; actual; actual = actual->next)
8373 gfc_init_se (&argse, se);
8375 /* Pass a NULL pointer for an absent arg. */
8376 if (actual->expr == NULL)
8377 argse.expr = null_pointer_node;
8378 else
8380 gfc_typespec ts;
8381 gfc_clear_ts (&ts);
8383 if (actual->expr->ts.kind != gfc_c_int_kind)
8385 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
8386 ts.type = BT_INTEGER;
8387 ts.kind = gfc_c_int_kind;
8388 gfc_convert_type (actual->expr, &ts, 2);
8390 gfc_conv_expr_reference (&argse, actual->expr);
8393 gfc_add_block_to_block (&se->pre, &argse.pre);
8394 gfc_add_block_to_block (&se->post, &argse.post);
8395 vec_safe_push (args, argse.expr);
8398 /* Convert it to the required type. */
8399 type = gfc_typenode_for_spec (&expr->ts);
8400 se->expr = build_call_expr_loc_vec (input_location,
8401 gfor_fndecl_sr_kind, args);
8402 se->expr = fold_convert (type, se->expr);
8406 /* Generate code for TRIM (A) intrinsic function. */
8408 static void
8409 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
8411 tree var;
8412 tree len;
8413 tree addr;
8414 tree tmp;
8415 tree cond;
8416 tree fndecl;
8417 tree function;
8418 tree *args;
8419 unsigned int num_args;
8421 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
8422 args = XALLOCAVEC (tree, num_args);
8424 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
8425 addr = gfc_build_addr_expr (ppvoid_type_node, var);
8426 len = gfc_create_var (gfc_charlen_type_node, "len");
8428 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
8429 args[0] = gfc_build_addr_expr (NULL_TREE, len);
8430 args[1] = addr;
8432 if (expr->ts.kind == 1)
8433 function = gfor_fndecl_string_trim;
8434 else if (expr->ts.kind == 4)
8435 function = gfor_fndecl_string_trim_char4;
8436 else
8437 gcc_unreachable ();
8439 fndecl = build_addr (function);
8440 tmp = build_call_array_loc (input_location,
8441 TREE_TYPE (TREE_TYPE (function)), fndecl,
8442 num_args, args);
8443 gfc_add_expr_to_block (&se->pre, tmp);
8445 /* Free the temporary afterwards, if necessary. */
8446 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8447 len, build_int_cst (TREE_TYPE (len), 0));
8448 tmp = gfc_call_free (var);
8449 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
8450 gfc_add_expr_to_block (&se->post, tmp);
8452 se->expr = var;
8453 se->string_length = len;
8457 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8459 static void
8460 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
8462 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
8463 tree type, cond, tmp, count, exit_label, n, max, largest;
8464 tree size;
8465 stmtblock_t block, body;
8466 int i;
8468 /* We store in charsize the size of a character. */
8469 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
8470 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
8472 /* Get the arguments. */
8473 gfc_conv_intrinsic_function_args (se, expr, args, 3);
8474 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
8475 src = args[1];
8476 ncopies = gfc_evaluate_now (args[2], &se->pre);
8477 ncopies_type = TREE_TYPE (ncopies);
8479 /* Check that NCOPIES is not negative. */
8480 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
8481 build_int_cst (ncopies_type, 0));
8482 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8483 "Argument NCOPIES of REPEAT intrinsic is negative "
8484 "(its value is %ld)",
8485 fold_convert (long_integer_type_node, ncopies));
8487 /* If the source length is zero, any non negative value of NCOPIES
8488 is valid, and nothing happens. */
8489 n = gfc_create_var (ncopies_type, "ncopies");
8490 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8491 size_zero_node);
8492 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
8493 build_int_cst (ncopies_type, 0), ncopies);
8494 gfc_add_modify (&se->pre, n, tmp);
8495 ncopies = n;
8497 /* Check that ncopies is not too large: ncopies should be less than
8498 (or equal to) MAX / slen, where MAX is the maximal integer of
8499 the gfc_charlen_type_node type. If slen == 0, we need a special
8500 case to avoid the division by zero. */
8501 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
8502 fold_convert (sizetype,
8503 TYPE_MAX_VALUE (gfc_charlen_type_node)),
8504 slen);
8505 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
8506 ? sizetype : ncopies_type;
8507 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8508 fold_convert (largest, ncopies),
8509 fold_convert (largest, max));
8510 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8511 size_zero_node);
8512 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
8513 logical_false_node, cond);
8514 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8515 "Argument NCOPIES of REPEAT intrinsic is too large");
8517 /* Compute the destination length. */
8518 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
8519 fold_convert (gfc_charlen_type_node, slen),
8520 fold_convert (gfc_charlen_type_node, ncopies));
8521 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
8522 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
8524 /* Generate the code to do the repeat operation:
8525 for (i = 0; i < ncopies; i++)
8526 memmove (dest + (i * slen * size), src, slen*size); */
8527 gfc_start_block (&block);
8528 count = gfc_create_var (sizetype, "count");
8529 gfc_add_modify (&block, count, size_zero_node);
8530 exit_label = gfc_build_label_decl (NULL_TREE);
8532 /* Start the loop body. */
8533 gfc_start_block (&body);
8535 /* Exit the loop if count >= ncopies. */
8536 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
8537 fold_convert (sizetype, ncopies));
8538 tmp = build1_v (GOTO_EXPR, exit_label);
8539 TREE_USED (exit_label) = 1;
8540 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
8541 build_empty_stmt (input_location));
8542 gfc_add_expr_to_block (&body, tmp);
8544 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8545 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
8546 count);
8547 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
8548 size);
8549 tmp = fold_build_pointer_plus_loc (input_location,
8550 fold_convert (pvoid_type_node, dest), tmp);
8551 tmp = build_call_expr_loc (input_location,
8552 builtin_decl_explicit (BUILT_IN_MEMMOVE),
8553 3, tmp, src,
8554 fold_build2_loc (input_location, MULT_EXPR,
8555 size_type_node, slen, size));
8556 gfc_add_expr_to_block (&body, tmp);
8558 /* Increment count. */
8559 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
8560 count, size_one_node);
8561 gfc_add_modify (&body, count, tmp);
8563 /* Build the loop. */
8564 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
8565 gfc_add_expr_to_block (&block, tmp);
8567 /* Add the exit label. */
8568 tmp = build1_v (LABEL_EXPR, exit_label);
8569 gfc_add_expr_to_block (&block, tmp);
8571 /* Finish the block. */
8572 tmp = gfc_finish_block (&block);
8573 gfc_add_expr_to_block (&se->pre, tmp);
8575 /* Set the result value. */
8576 se->expr = dest;
8577 se->string_length = dlen;
8581 /* Generate code for the IARGC intrinsic. */
8583 static void
8584 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
8586 tree tmp;
8587 tree fndecl;
8588 tree type;
8590 /* Call the library function. This always returns an INTEGER(4). */
8591 fndecl = gfor_fndecl_iargc;
8592 tmp = build_call_expr_loc (input_location,
8593 fndecl, 0);
8595 /* Convert it to the required type. */
8596 type = gfc_typenode_for_spec (&expr->ts);
8597 tmp = fold_convert (type, tmp);
8599 se->expr = tmp;
8603 /* Generate code for the KILL intrinsic. */
8605 static void
8606 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
8608 tree *args;
8609 tree int4_type_node = gfc_get_int_type (4);
8610 tree pid;
8611 tree sig;
8612 tree tmp;
8613 unsigned int num_args;
8615 num_args = gfc_intrinsic_argument_list_length (expr);
8616 args = XALLOCAVEC (tree, num_args);
8617 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8619 /* Convert PID to a INTEGER(4) entity. */
8620 pid = convert (int4_type_node, args[0]);
8622 /* Convert SIG to a INTEGER(4) entity. */
8623 sig = convert (int4_type_node, args[1]);
8625 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
8627 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
8631 static tree
8632 conv_intrinsic_kill_sub (gfc_code *code)
8634 stmtblock_t block;
8635 gfc_se se, se_stat;
8636 tree int4_type_node = gfc_get_int_type (4);
8637 tree pid;
8638 tree sig;
8639 tree statp;
8640 tree tmp;
8642 /* Make the function call. */
8643 gfc_init_block (&block);
8644 gfc_init_se (&se, NULL);
8646 /* Convert PID to a INTEGER(4) entity. */
8647 gfc_conv_expr (&se, code->ext.actual->expr);
8648 gfc_add_block_to_block (&block, &se.pre);
8649 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8650 gfc_add_block_to_block (&block, &se.post);
8652 /* Convert SIG to a INTEGER(4) entity. */
8653 gfc_conv_expr (&se, code->ext.actual->next->expr);
8654 gfc_add_block_to_block (&block, &se.pre);
8655 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8656 gfc_add_block_to_block (&block, &se.post);
8658 /* Deal with an optional STATUS. */
8659 if (code->ext.actual->next->next->expr)
8661 gfc_init_se (&se_stat, NULL);
8662 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
8663 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
8665 else
8666 statp = NULL_TREE;
8668 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
8669 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
8671 gfc_add_expr_to_block (&block, tmp);
8673 if (statp && statp != se_stat.expr)
8674 gfc_add_modify (&block, se_stat.expr,
8675 fold_convert (TREE_TYPE (se_stat.expr), statp));
8677 return gfc_finish_block (&block);
8682 /* The loc intrinsic returns the address of its argument as
8683 gfc_index_integer_kind integer. */
8685 static void
8686 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8688 tree temp_var;
8689 gfc_expr *arg_expr;
8691 gcc_assert (!se->ss);
8693 arg_expr = expr->value.function.actual->expr;
8694 if (arg_expr->rank == 0)
8696 if (arg_expr->ts.type == BT_CLASS)
8697 gfc_add_data_component (arg_expr);
8698 gfc_conv_expr_reference (se, arg_expr);
8700 else
8701 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8702 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8704 /* Create a temporary variable for loc return value. Without this,
8705 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8706 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8707 gfc_add_modify (&se->pre, temp_var, se->expr);
8708 se->expr = temp_var;
8712 /* The following routine generates code for the intrinsic
8713 functions from the ISO_C_BINDING module:
8714 * C_LOC
8715 * C_FUNLOC
8716 * C_ASSOCIATED */
8718 static void
8719 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8721 gfc_actual_arglist *arg = expr->value.function.actual;
8723 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8725 if (arg->expr->rank == 0)
8726 gfc_conv_expr_reference (se, arg->expr);
8727 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8728 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8729 else
8731 gfc_conv_expr_descriptor (se, arg->expr);
8732 se->expr = gfc_conv_descriptor_data_get (se->expr);
8735 /* TODO -- the following two lines shouldn't be necessary, but if
8736 they're removed, a bug is exposed later in the code path.
8737 This workaround was thus introduced, but will have to be
8738 removed; please see PR 35150 for details about the issue. */
8739 se->expr = convert (pvoid_type_node, se->expr);
8740 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8742 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8743 gfc_conv_expr_reference (se, arg->expr);
8744 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8746 gfc_se arg1se;
8747 gfc_se arg2se;
8749 /* Build the addr_expr for the first argument. The argument is
8750 already an *address* so we don't need to set want_pointer in
8751 the gfc_se. */
8752 gfc_init_se (&arg1se, NULL);
8753 gfc_conv_expr (&arg1se, arg->expr);
8754 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8755 gfc_add_block_to_block (&se->post, &arg1se.post);
8757 /* See if we were given two arguments. */
8758 if (arg->next->expr == NULL)
8759 /* Only given one arg so generate a null and do a
8760 not-equal comparison against the first arg. */
8761 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8762 arg1se.expr,
8763 fold_convert (TREE_TYPE (arg1se.expr),
8764 null_pointer_node));
8765 else
8767 tree eq_expr;
8768 tree not_null_expr;
8770 /* Given two arguments so build the arg2se from second arg. */
8771 gfc_init_se (&arg2se, NULL);
8772 gfc_conv_expr (&arg2se, arg->next->expr);
8773 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8774 gfc_add_block_to_block (&se->post, &arg2se.post);
8776 /* Generate test to compare that the two args are equal. */
8777 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8778 arg1se.expr, arg2se.expr);
8779 /* Generate test to ensure that the first arg is not null. */
8780 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8781 logical_type_node,
8782 arg1se.expr, null_pointer_node);
8784 /* Finally, the generated test must check that both arg1 is not
8785 NULL and that it is equal to the second arg. */
8786 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8787 logical_type_node,
8788 not_null_expr, eq_expr);
8791 else
8792 gcc_unreachable ();
8796 /* The following routine generates code for the intrinsic
8797 subroutines from the ISO_C_BINDING module:
8798 * C_F_POINTER
8799 * C_F_PROCPOINTER. */
8801 static tree
8802 conv_isocbinding_subroutine (gfc_code *code)
8804 gfc_se se;
8805 gfc_se cptrse;
8806 gfc_se fptrse;
8807 gfc_se shapese;
8808 gfc_ss *shape_ss;
8809 tree desc, dim, tmp, stride, offset;
8810 stmtblock_t body, block;
8811 gfc_loopinfo loop;
8812 gfc_actual_arglist *arg = code->ext.actual;
8814 gfc_init_se (&se, NULL);
8815 gfc_init_se (&cptrse, NULL);
8816 gfc_conv_expr (&cptrse, arg->expr);
8817 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8818 gfc_add_block_to_block (&se.post, &cptrse.post);
8820 gfc_init_se (&fptrse, NULL);
8821 if (arg->next->expr->rank == 0)
8823 fptrse.want_pointer = 1;
8824 gfc_conv_expr (&fptrse, arg->next->expr);
8825 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8826 gfc_add_block_to_block (&se.post, &fptrse.post);
8827 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8828 && arg->next->expr->symtree->n.sym->attr.dummy)
8829 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8830 fptrse.expr);
8831 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8832 TREE_TYPE (fptrse.expr),
8833 fptrse.expr,
8834 fold_convert (TREE_TYPE (fptrse.expr),
8835 cptrse.expr));
8836 gfc_add_expr_to_block (&se.pre, se.expr);
8837 gfc_add_block_to_block (&se.pre, &se.post);
8838 return gfc_finish_block (&se.pre);
8841 gfc_start_block (&block);
8843 /* Get the descriptor of the Fortran pointer. */
8844 fptrse.descriptor_only = 1;
8845 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8846 gfc_add_block_to_block (&block, &fptrse.pre);
8847 desc = fptrse.expr;
8849 /* Set the span field. */
8850 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8851 tmp = fold_convert (gfc_array_index_type, tmp);
8852 gfc_conv_descriptor_span_set (&block, desc, tmp);
8854 /* Set data value, dtype, and offset. */
8855 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8856 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8857 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8858 gfc_get_dtype (TREE_TYPE (desc)));
8860 /* Start scalarization of the bounds, using the shape argument. */
8862 shape_ss = gfc_walk_expr (arg->next->next->expr);
8863 gcc_assert (shape_ss != gfc_ss_terminator);
8864 gfc_init_se (&shapese, NULL);
8866 gfc_init_loopinfo (&loop);
8867 gfc_add_ss_to_loop (&loop, shape_ss);
8868 gfc_conv_ss_startstride (&loop);
8869 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8870 gfc_mark_ss_chain_used (shape_ss, 1);
8872 gfc_copy_loopinfo_to_se (&shapese, &loop);
8873 shapese.ss = shape_ss;
8875 stride = gfc_create_var (gfc_array_index_type, "stride");
8876 offset = gfc_create_var (gfc_array_index_type, "offset");
8877 gfc_add_modify (&block, stride, gfc_index_one_node);
8878 gfc_add_modify (&block, offset, gfc_index_zero_node);
8880 /* Loop body. */
8881 gfc_start_scalarized_body (&loop, &body);
8883 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8884 loop.loopvar[0], loop.from[0]);
8886 /* Set bounds and stride. */
8887 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8888 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8890 gfc_conv_expr (&shapese, arg->next->next->expr);
8891 gfc_add_block_to_block (&body, &shapese.pre);
8892 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8893 gfc_add_block_to_block (&body, &shapese.post);
8895 /* Calculate offset. */
8896 gfc_add_modify (&body, offset,
8897 fold_build2_loc (input_location, PLUS_EXPR,
8898 gfc_array_index_type, offset, stride));
8899 /* Update stride. */
8900 gfc_add_modify (&body, stride,
8901 fold_build2_loc (input_location, MULT_EXPR,
8902 gfc_array_index_type, stride,
8903 fold_convert (gfc_array_index_type,
8904 shapese.expr)));
8905 /* Finish scalarization loop. */
8906 gfc_trans_scalarizing_loops (&loop, &body);
8907 gfc_add_block_to_block (&block, &loop.pre);
8908 gfc_add_block_to_block (&block, &loop.post);
8909 gfc_add_block_to_block (&block, &fptrse.post);
8910 gfc_cleanup_loop (&loop);
8912 gfc_add_modify (&block, offset,
8913 fold_build1_loc (input_location, NEGATE_EXPR,
8914 gfc_array_index_type, offset));
8915 gfc_conv_descriptor_offset_set (&block, desc, offset);
8917 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8918 gfc_add_block_to_block (&se.pre, &se.post);
8919 return gfc_finish_block (&se.pre);
8923 /* Save and restore floating-point state. */
8925 tree
8926 gfc_save_fp_state (stmtblock_t *block)
8928 tree type, fpstate, tmp;
8930 type = build_array_type (char_type_node,
8931 build_range_type (size_type_node, size_zero_node,
8932 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8933 fpstate = gfc_create_var (type, "fpstate");
8934 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8936 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8937 1, fpstate);
8938 gfc_add_expr_to_block (block, tmp);
8940 return fpstate;
8944 void
8945 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8947 tree tmp;
8949 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8950 1, fpstate);
8951 gfc_add_expr_to_block (block, tmp);
8955 /* Generate code for arguments of IEEE functions. */
8957 static void
8958 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8959 int nargs)
8961 gfc_actual_arglist *actual;
8962 gfc_expr *e;
8963 gfc_se argse;
8964 int arg;
8966 actual = expr->value.function.actual;
8967 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8969 gcc_assert (actual);
8970 e = actual->expr;
8972 gfc_init_se (&argse, se);
8973 gfc_conv_expr_val (&argse, e);
8975 gfc_add_block_to_block (&se->pre, &argse.pre);
8976 gfc_add_block_to_block (&se->post, &argse.post);
8977 argarray[arg] = argse.expr;
8982 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8983 and IEEE_UNORDERED, which translate directly to GCC type-generic
8984 built-ins. */
8986 static void
8987 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8988 enum built_in_function code, int nargs)
8990 tree args[2];
8991 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8993 conv_ieee_function_args (se, expr, args, nargs);
8994 se->expr = build_call_expr_loc_array (input_location,
8995 builtin_decl_explicit (code),
8996 nargs, args);
8997 STRIP_TYPE_NOPS (se->expr);
8998 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9002 /* Generate code for IEEE_IS_NORMAL intrinsic:
9003 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
9005 static void
9006 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
9008 tree arg, isnormal, iszero;
9010 /* Convert arg, evaluate it only once. */
9011 conv_ieee_function_args (se, expr, &arg, 1);
9012 arg = gfc_evaluate_now (arg, &se->pre);
9014 isnormal = build_call_expr_loc (input_location,
9015 builtin_decl_explicit (BUILT_IN_ISNORMAL),
9016 1, arg);
9017 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
9018 build_real_from_int_cst (TREE_TYPE (arg),
9019 integer_zero_node));
9020 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9021 logical_type_node, isnormal, iszero);
9022 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9026 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
9027 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
9029 static void
9030 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
9032 tree arg, signbit, isnan;
9034 /* Convert arg, evaluate it only once. */
9035 conv_ieee_function_args (se, expr, &arg, 1);
9036 arg = gfc_evaluate_now (arg, &se->pre);
9038 isnan = build_call_expr_loc (input_location,
9039 builtin_decl_explicit (BUILT_IN_ISNAN),
9040 1, arg);
9041 STRIP_TYPE_NOPS (isnan);
9043 signbit = build_call_expr_loc (input_location,
9044 builtin_decl_explicit (BUILT_IN_SIGNBIT),
9045 1, arg);
9046 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9047 signbit, integer_zero_node);
9049 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9050 logical_type_node, signbit,
9051 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
9052 TREE_TYPE(isnan), isnan));
9054 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9058 /* Generate code for IEEE_LOGB and IEEE_RINT. */
9060 static void
9061 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
9062 enum built_in_function code)
9064 tree arg, decl, call, fpstate;
9065 int argprec;
9067 conv_ieee_function_args (se, expr, &arg, 1);
9068 argprec = TYPE_PRECISION (TREE_TYPE (arg));
9069 decl = builtin_decl_for_precision (code, argprec);
9071 /* Save floating-point state. */
9072 fpstate = gfc_save_fp_state (&se->pre);
9074 /* Make the function call. */
9075 call = build_call_expr_loc (input_location, decl, 1, arg);
9076 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
9078 /* Restore floating-point state. */
9079 gfc_restore_fp_state (&se->post, fpstate);
9083 /* Generate code for IEEE_REM. */
9085 static void
9086 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
9088 tree args[2], decl, call, fpstate;
9089 int argprec;
9091 conv_ieee_function_args (se, expr, args, 2);
9093 /* If arguments have unequal size, convert them to the larger. */
9094 if (TYPE_PRECISION (TREE_TYPE (args[0]))
9095 > TYPE_PRECISION (TREE_TYPE (args[1])))
9096 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9097 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
9098 > TYPE_PRECISION (TREE_TYPE (args[0])))
9099 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
9101 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9102 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
9104 /* Save floating-point state. */
9105 fpstate = gfc_save_fp_state (&se->pre);
9107 /* Make the function call. */
9108 call = build_call_expr_loc_array (input_location, decl, 2, args);
9109 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9111 /* Restore floating-point state. */
9112 gfc_restore_fp_state (&se->post, fpstate);
9116 /* Generate code for IEEE_NEXT_AFTER. */
9118 static void
9119 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
9121 tree args[2], decl, call, fpstate;
9122 int argprec;
9124 conv_ieee_function_args (se, expr, args, 2);
9126 /* Result has the characteristics of first argument. */
9127 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9128 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9129 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
9131 /* Save floating-point state. */
9132 fpstate = gfc_save_fp_state (&se->pre);
9134 /* Make the function call. */
9135 call = build_call_expr_loc_array (input_location, decl, 2, args);
9136 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9138 /* Restore floating-point state. */
9139 gfc_restore_fp_state (&se->post, fpstate);
9143 /* Generate code for IEEE_SCALB. */
9145 static void
9146 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
9148 tree args[2], decl, call, huge, type;
9149 int argprec, n;
9151 conv_ieee_function_args (se, expr, args, 2);
9153 /* Result has the characteristics of first argument. */
9154 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9155 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
9157 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
9159 /* We need to fold the integer into the range of a C int. */
9160 args[1] = gfc_evaluate_now (args[1], &se->pre);
9161 type = TREE_TYPE (args[1]);
9163 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
9164 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
9165 gfc_c_int_kind);
9166 huge = fold_convert (type, huge);
9167 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
9168 huge);
9169 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
9170 fold_build1_loc (input_location, NEGATE_EXPR,
9171 type, huge));
9174 args[1] = fold_convert (integer_type_node, args[1]);
9176 /* Make the function call. */
9177 call = build_call_expr_loc_array (input_location, decl, 2, args);
9178 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9182 /* Generate code for IEEE_COPY_SIGN. */
9184 static void
9185 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
9187 tree args[2], decl, sign;
9188 int argprec;
9190 conv_ieee_function_args (se, expr, args, 2);
9192 /* Get the sign of the second argument. */
9193 sign = build_call_expr_loc (input_location,
9194 builtin_decl_explicit (BUILT_IN_SIGNBIT),
9195 1, args[1]);
9196 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9197 sign, integer_zero_node);
9199 /* Create a value of one, with the right sign. */
9200 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
9201 sign,
9202 fold_build1_loc (input_location, NEGATE_EXPR,
9203 integer_type_node,
9204 integer_one_node),
9205 integer_one_node);
9206 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
9208 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9209 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
9211 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
9215 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
9216 module. */
9218 bool
9219 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
9221 const char *name = expr->value.function.name;
9223 if (gfc_str_startswith (name, "_gfortran_ieee_is_nan"))
9224 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
9225 else if (gfc_str_startswith (name, "_gfortran_ieee_is_finite"))
9226 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
9227 else if (gfc_str_startswith (name, "_gfortran_ieee_unordered"))
9228 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
9229 else if (gfc_str_startswith (name, "_gfortran_ieee_is_normal"))
9230 conv_intrinsic_ieee_is_normal (se, expr);
9231 else if (gfc_str_startswith (name, "_gfortran_ieee_is_negative"))
9232 conv_intrinsic_ieee_is_negative (se, expr);
9233 else if (gfc_str_startswith (name, "_gfortran_ieee_copy_sign"))
9234 conv_intrinsic_ieee_copy_sign (se, expr);
9235 else if (gfc_str_startswith (name, "_gfortran_ieee_scalb"))
9236 conv_intrinsic_ieee_scalb (se, expr);
9237 else if (gfc_str_startswith (name, "_gfortran_ieee_next_after"))
9238 conv_intrinsic_ieee_next_after (se, expr);
9239 else if (gfc_str_startswith (name, "_gfortran_ieee_rem"))
9240 conv_intrinsic_ieee_rem (se, expr);
9241 else if (gfc_str_startswith (name, "_gfortran_ieee_logb"))
9242 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
9243 else if (gfc_str_startswith (name, "_gfortran_ieee_rint"))
9244 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
9245 else
9246 /* It is not among the functions we translate directly. We return
9247 false, so a library function call is emitted. */
9248 return false;
9250 return true;
9254 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
9256 static void
9257 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
9259 tree arg, res, restype;
9261 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9262 arg = fold_convert (size_type_node, arg);
9263 res = build_call_expr_loc (input_location,
9264 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
9265 restype = gfc_typenode_for_spec (&expr->ts);
9266 se->expr = fold_convert (restype, res);
9270 /* Generate code for an intrinsic function. Some map directly to library
9271 calls, others get special handling. In some cases the name of the function
9272 used depends on the type specifiers. */
9274 void
9275 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
9277 const char *name;
9278 int lib, kind;
9279 tree fndecl;
9281 name = &expr->value.function.name[2];
9283 if (expr->rank > 0)
9285 lib = gfc_is_intrinsic_libcall (expr);
9286 if (lib != 0)
9288 if (lib == 1)
9289 se->ignore_optional = 1;
9291 switch (expr->value.function.isym->id)
9293 case GFC_ISYM_EOSHIFT:
9294 case GFC_ISYM_PACK:
9295 case GFC_ISYM_RESHAPE:
9296 /* For all of those the first argument specifies the type and the
9297 third is optional. */
9298 conv_generic_with_optional_char_arg (se, expr, 1, 3);
9299 break;
9301 case GFC_ISYM_FINDLOC:
9302 gfc_conv_intrinsic_findloc (se, expr);
9303 break;
9305 case GFC_ISYM_MINLOC:
9306 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9307 break;
9309 case GFC_ISYM_MAXLOC:
9310 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9311 break;
9313 case GFC_ISYM_SHAPE:
9314 gfc_conv_intrinsic_shape (se, expr);
9315 break;
9317 default:
9318 gfc_conv_intrinsic_funcall (se, expr);
9319 break;
9322 return;
9326 switch (expr->value.function.isym->id)
9328 case GFC_ISYM_NONE:
9329 gcc_unreachable ();
9331 case GFC_ISYM_REPEAT:
9332 gfc_conv_intrinsic_repeat (se, expr);
9333 break;
9335 case GFC_ISYM_TRIM:
9336 gfc_conv_intrinsic_trim (se, expr);
9337 break;
9339 case GFC_ISYM_SC_KIND:
9340 gfc_conv_intrinsic_sc_kind (se, expr);
9341 break;
9343 case GFC_ISYM_SI_KIND:
9344 gfc_conv_intrinsic_si_kind (se, expr);
9345 break;
9347 case GFC_ISYM_SR_KIND:
9348 gfc_conv_intrinsic_sr_kind (se, expr);
9349 break;
9351 case GFC_ISYM_EXPONENT:
9352 gfc_conv_intrinsic_exponent (se, expr);
9353 break;
9355 case GFC_ISYM_SCAN:
9356 kind = expr->value.function.actual->expr->ts.kind;
9357 if (kind == 1)
9358 fndecl = gfor_fndecl_string_scan;
9359 else if (kind == 4)
9360 fndecl = gfor_fndecl_string_scan_char4;
9361 else
9362 gcc_unreachable ();
9364 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9365 break;
9367 case GFC_ISYM_VERIFY:
9368 kind = expr->value.function.actual->expr->ts.kind;
9369 if (kind == 1)
9370 fndecl = gfor_fndecl_string_verify;
9371 else if (kind == 4)
9372 fndecl = gfor_fndecl_string_verify_char4;
9373 else
9374 gcc_unreachable ();
9376 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9377 break;
9379 case GFC_ISYM_ALLOCATED:
9380 gfc_conv_allocated (se, expr);
9381 break;
9383 case GFC_ISYM_ASSOCIATED:
9384 gfc_conv_associated(se, expr);
9385 break;
9387 case GFC_ISYM_SAME_TYPE_AS:
9388 gfc_conv_same_type_as (se, expr);
9389 break;
9391 case GFC_ISYM_ABS:
9392 gfc_conv_intrinsic_abs (se, expr);
9393 break;
9395 case GFC_ISYM_ADJUSTL:
9396 if (expr->ts.kind == 1)
9397 fndecl = gfor_fndecl_adjustl;
9398 else if (expr->ts.kind == 4)
9399 fndecl = gfor_fndecl_adjustl_char4;
9400 else
9401 gcc_unreachable ();
9403 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9404 break;
9406 case GFC_ISYM_ADJUSTR:
9407 if (expr->ts.kind == 1)
9408 fndecl = gfor_fndecl_adjustr;
9409 else if (expr->ts.kind == 4)
9410 fndecl = gfor_fndecl_adjustr_char4;
9411 else
9412 gcc_unreachable ();
9414 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9415 break;
9417 case GFC_ISYM_AIMAG:
9418 gfc_conv_intrinsic_imagpart (se, expr);
9419 break;
9421 case GFC_ISYM_AINT:
9422 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
9423 break;
9425 case GFC_ISYM_ALL:
9426 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
9427 break;
9429 case GFC_ISYM_ANINT:
9430 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
9431 break;
9433 case GFC_ISYM_AND:
9434 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9435 break;
9437 case GFC_ISYM_ANY:
9438 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
9439 break;
9441 case GFC_ISYM_BTEST:
9442 gfc_conv_intrinsic_btest (se, expr);
9443 break;
9445 case GFC_ISYM_BGE:
9446 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
9447 break;
9449 case GFC_ISYM_BGT:
9450 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
9451 break;
9453 case GFC_ISYM_BLE:
9454 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
9455 break;
9457 case GFC_ISYM_BLT:
9458 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
9459 break;
9461 case GFC_ISYM_C_ASSOCIATED:
9462 case GFC_ISYM_C_FUNLOC:
9463 case GFC_ISYM_C_LOC:
9464 conv_isocbinding_function (se, expr);
9465 break;
9467 case GFC_ISYM_ACHAR:
9468 case GFC_ISYM_CHAR:
9469 gfc_conv_intrinsic_char (se, expr);
9470 break;
9472 case GFC_ISYM_CONVERSION:
9473 case GFC_ISYM_REAL:
9474 case GFC_ISYM_LOGICAL:
9475 case GFC_ISYM_DBLE:
9476 gfc_conv_intrinsic_conversion (se, expr);
9477 break;
9479 /* Integer conversions are handled separately to make sure we get the
9480 correct rounding mode. */
9481 case GFC_ISYM_INT:
9482 case GFC_ISYM_INT2:
9483 case GFC_ISYM_INT8:
9484 case GFC_ISYM_LONG:
9485 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
9486 break;
9488 case GFC_ISYM_NINT:
9489 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
9490 break;
9492 case GFC_ISYM_CEILING:
9493 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
9494 break;
9496 case GFC_ISYM_FLOOR:
9497 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
9498 break;
9500 case GFC_ISYM_MOD:
9501 gfc_conv_intrinsic_mod (se, expr, 0);
9502 break;
9504 case GFC_ISYM_MODULO:
9505 gfc_conv_intrinsic_mod (se, expr, 1);
9506 break;
9508 case GFC_ISYM_CAF_GET:
9509 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
9510 false, NULL);
9511 break;
9513 case GFC_ISYM_CMPLX:
9514 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
9515 break;
9517 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
9518 gfc_conv_intrinsic_iargc (se, expr);
9519 break;
9521 case GFC_ISYM_COMPLEX:
9522 gfc_conv_intrinsic_cmplx (se, expr, 1);
9523 break;
9525 case GFC_ISYM_CONJG:
9526 gfc_conv_intrinsic_conjg (se, expr);
9527 break;
9529 case GFC_ISYM_COUNT:
9530 gfc_conv_intrinsic_count (se, expr);
9531 break;
9533 case GFC_ISYM_CTIME:
9534 gfc_conv_intrinsic_ctime (se, expr);
9535 break;
9537 case GFC_ISYM_DIM:
9538 gfc_conv_intrinsic_dim (se, expr);
9539 break;
9541 case GFC_ISYM_DOT_PRODUCT:
9542 gfc_conv_intrinsic_dot_product (se, expr);
9543 break;
9545 case GFC_ISYM_DPROD:
9546 gfc_conv_intrinsic_dprod (se, expr);
9547 break;
9549 case GFC_ISYM_DSHIFTL:
9550 gfc_conv_intrinsic_dshift (se, expr, true);
9551 break;
9553 case GFC_ISYM_DSHIFTR:
9554 gfc_conv_intrinsic_dshift (se, expr, false);
9555 break;
9557 case GFC_ISYM_FDATE:
9558 gfc_conv_intrinsic_fdate (se, expr);
9559 break;
9561 case GFC_ISYM_FRACTION:
9562 gfc_conv_intrinsic_fraction (se, expr);
9563 break;
9565 case GFC_ISYM_IALL:
9566 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9567 break;
9569 case GFC_ISYM_IAND:
9570 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9571 break;
9573 case GFC_ISYM_IANY:
9574 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9575 break;
9577 case GFC_ISYM_IBCLR:
9578 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9579 break;
9581 case GFC_ISYM_IBITS:
9582 gfc_conv_intrinsic_ibits (se, expr);
9583 break;
9585 case GFC_ISYM_IBSET:
9586 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9587 break;
9589 case GFC_ISYM_IACHAR:
9590 case GFC_ISYM_ICHAR:
9591 /* We assume ASCII character sequence. */
9592 gfc_conv_intrinsic_ichar (se, expr);
9593 break;
9595 case GFC_ISYM_IARGC:
9596 gfc_conv_intrinsic_iargc (se, expr);
9597 break;
9599 case GFC_ISYM_IEOR:
9600 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9601 break;
9603 case GFC_ISYM_INDEX:
9604 kind = expr->value.function.actual->expr->ts.kind;
9605 if (kind == 1)
9606 fndecl = gfor_fndecl_string_index;
9607 else if (kind == 4)
9608 fndecl = gfor_fndecl_string_index_char4;
9609 else
9610 gcc_unreachable ();
9612 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9613 break;
9615 case GFC_ISYM_IOR:
9616 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9617 break;
9619 case GFC_ISYM_IPARITY:
9620 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9621 break;
9623 case GFC_ISYM_IS_IOSTAT_END:
9624 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9625 break;
9627 case GFC_ISYM_IS_IOSTAT_EOR:
9628 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9629 break;
9631 case GFC_ISYM_ISNAN:
9632 gfc_conv_intrinsic_isnan (se, expr);
9633 break;
9635 case GFC_ISYM_KILL:
9636 conv_intrinsic_kill (se, expr);
9637 break;
9639 case GFC_ISYM_LSHIFT:
9640 gfc_conv_intrinsic_shift (se, expr, false, false);
9641 break;
9643 case GFC_ISYM_RSHIFT:
9644 gfc_conv_intrinsic_shift (se, expr, true, true);
9645 break;
9647 case GFC_ISYM_SHIFTA:
9648 gfc_conv_intrinsic_shift (se, expr, true, true);
9649 break;
9651 case GFC_ISYM_SHIFTL:
9652 gfc_conv_intrinsic_shift (se, expr, false, false);
9653 break;
9655 case GFC_ISYM_SHIFTR:
9656 gfc_conv_intrinsic_shift (se, expr, true, false);
9657 break;
9659 case GFC_ISYM_ISHFT:
9660 gfc_conv_intrinsic_ishft (se, expr);
9661 break;
9663 case GFC_ISYM_ISHFTC:
9664 gfc_conv_intrinsic_ishftc (se, expr);
9665 break;
9667 case GFC_ISYM_LEADZ:
9668 gfc_conv_intrinsic_leadz (se, expr);
9669 break;
9671 case GFC_ISYM_TRAILZ:
9672 gfc_conv_intrinsic_trailz (se, expr);
9673 break;
9675 case GFC_ISYM_POPCNT:
9676 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9677 break;
9679 case GFC_ISYM_POPPAR:
9680 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9681 break;
9683 case GFC_ISYM_LBOUND:
9684 gfc_conv_intrinsic_bound (se, expr, 0);
9685 break;
9687 case GFC_ISYM_LCOBOUND:
9688 conv_intrinsic_cobound (se, expr);
9689 break;
9691 case GFC_ISYM_TRANSPOSE:
9692 /* The scalarizer has already been set up for reversed dimension access
9693 order ; now we just get the argument value normally. */
9694 gfc_conv_expr (se, expr->value.function.actual->expr);
9695 break;
9697 case GFC_ISYM_LEN:
9698 gfc_conv_intrinsic_len (se, expr);
9699 break;
9701 case GFC_ISYM_LEN_TRIM:
9702 gfc_conv_intrinsic_len_trim (se, expr);
9703 break;
9705 case GFC_ISYM_LGE:
9706 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9707 break;
9709 case GFC_ISYM_LGT:
9710 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9711 break;
9713 case GFC_ISYM_LLE:
9714 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9715 break;
9717 case GFC_ISYM_LLT:
9718 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9719 break;
9721 case GFC_ISYM_MALLOC:
9722 gfc_conv_intrinsic_malloc (se, expr);
9723 break;
9725 case GFC_ISYM_MASKL:
9726 gfc_conv_intrinsic_mask (se, expr, 1);
9727 break;
9729 case GFC_ISYM_MASKR:
9730 gfc_conv_intrinsic_mask (se, expr, 0);
9731 break;
9733 case GFC_ISYM_MAX:
9734 if (expr->ts.type == BT_CHARACTER)
9735 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9736 else
9737 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9738 break;
9740 case GFC_ISYM_MAXLOC:
9741 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9742 break;
9744 case GFC_ISYM_FINDLOC:
9745 gfc_conv_intrinsic_findloc (se, expr);
9746 break;
9748 case GFC_ISYM_MAXVAL:
9749 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9750 break;
9752 case GFC_ISYM_MERGE:
9753 gfc_conv_intrinsic_merge (se, expr);
9754 break;
9756 case GFC_ISYM_MERGE_BITS:
9757 gfc_conv_intrinsic_merge_bits (se, expr);
9758 break;
9760 case GFC_ISYM_MIN:
9761 if (expr->ts.type == BT_CHARACTER)
9762 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9763 else
9764 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9765 break;
9767 case GFC_ISYM_MINLOC:
9768 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9769 break;
9771 case GFC_ISYM_MINVAL:
9772 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9773 break;
9775 case GFC_ISYM_NEAREST:
9776 gfc_conv_intrinsic_nearest (se, expr);
9777 break;
9779 case GFC_ISYM_NORM2:
9780 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9781 break;
9783 case GFC_ISYM_NOT:
9784 gfc_conv_intrinsic_not (se, expr);
9785 break;
9787 case GFC_ISYM_OR:
9788 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9789 break;
9791 case GFC_ISYM_PARITY:
9792 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9793 break;
9795 case GFC_ISYM_PRESENT:
9796 gfc_conv_intrinsic_present (se, expr);
9797 break;
9799 case GFC_ISYM_PRODUCT:
9800 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9801 break;
9803 case GFC_ISYM_RANK:
9804 gfc_conv_intrinsic_rank (se, expr);
9805 break;
9807 case GFC_ISYM_RRSPACING:
9808 gfc_conv_intrinsic_rrspacing (se, expr);
9809 break;
9811 case GFC_ISYM_SET_EXPONENT:
9812 gfc_conv_intrinsic_set_exponent (se, expr);
9813 break;
9815 case GFC_ISYM_SCALE:
9816 gfc_conv_intrinsic_scale (se, expr);
9817 break;
9819 case GFC_ISYM_SIGN:
9820 gfc_conv_intrinsic_sign (se, expr);
9821 break;
9823 case GFC_ISYM_SIZE:
9824 gfc_conv_intrinsic_size (se, expr);
9825 break;
9827 case GFC_ISYM_SIZEOF:
9828 case GFC_ISYM_C_SIZEOF:
9829 gfc_conv_intrinsic_sizeof (se, expr);
9830 break;
9832 case GFC_ISYM_STORAGE_SIZE:
9833 gfc_conv_intrinsic_storage_size (se, expr);
9834 break;
9836 case GFC_ISYM_SPACING:
9837 gfc_conv_intrinsic_spacing (se, expr);
9838 break;
9840 case GFC_ISYM_STRIDE:
9841 conv_intrinsic_stride (se, expr);
9842 break;
9844 case GFC_ISYM_SUM:
9845 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9846 break;
9848 case GFC_ISYM_TEAM_NUMBER:
9849 conv_intrinsic_team_number (se, expr);
9850 break;
9852 case GFC_ISYM_TRANSFER:
9853 if (se->ss && se->ss->info->useflags)
9854 /* Access the previously obtained result. */
9855 gfc_conv_tmp_array_ref (se);
9856 else
9857 gfc_conv_intrinsic_transfer (se, expr);
9858 break;
9860 case GFC_ISYM_TTYNAM:
9861 gfc_conv_intrinsic_ttynam (se, expr);
9862 break;
9864 case GFC_ISYM_UBOUND:
9865 gfc_conv_intrinsic_bound (se, expr, 1);
9866 break;
9868 case GFC_ISYM_UCOBOUND:
9869 conv_intrinsic_cobound (se, expr);
9870 break;
9872 case GFC_ISYM_XOR:
9873 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9874 break;
9876 case GFC_ISYM_LOC:
9877 gfc_conv_intrinsic_loc (se, expr);
9878 break;
9880 case GFC_ISYM_THIS_IMAGE:
9881 /* For num_images() == 1, handle as LCOBOUND. */
9882 if (expr->value.function.actual->expr
9883 && flag_coarray == GFC_FCOARRAY_SINGLE)
9884 conv_intrinsic_cobound (se, expr);
9885 else
9886 trans_this_image (se, expr);
9887 break;
9889 case GFC_ISYM_IMAGE_INDEX:
9890 trans_image_index (se, expr);
9891 break;
9893 case GFC_ISYM_IMAGE_STATUS:
9894 conv_intrinsic_image_status (se, expr);
9895 break;
9897 case GFC_ISYM_NUM_IMAGES:
9898 trans_num_images (se, expr);
9899 break;
9901 case GFC_ISYM_ACCESS:
9902 case GFC_ISYM_CHDIR:
9903 case GFC_ISYM_CHMOD:
9904 case GFC_ISYM_DTIME:
9905 case GFC_ISYM_ETIME:
9906 case GFC_ISYM_EXTENDS_TYPE_OF:
9907 case GFC_ISYM_FGET:
9908 case GFC_ISYM_FGETC:
9909 case GFC_ISYM_FNUM:
9910 case GFC_ISYM_FPUT:
9911 case GFC_ISYM_FPUTC:
9912 case GFC_ISYM_FSTAT:
9913 case GFC_ISYM_FTELL:
9914 case GFC_ISYM_GETCWD:
9915 case GFC_ISYM_GETGID:
9916 case GFC_ISYM_GETPID:
9917 case GFC_ISYM_GETUID:
9918 case GFC_ISYM_HOSTNM:
9919 case GFC_ISYM_IERRNO:
9920 case GFC_ISYM_IRAND:
9921 case GFC_ISYM_ISATTY:
9922 case GFC_ISYM_JN2:
9923 case GFC_ISYM_LINK:
9924 case GFC_ISYM_LSTAT:
9925 case GFC_ISYM_MATMUL:
9926 case GFC_ISYM_MCLOCK:
9927 case GFC_ISYM_MCLOCK8:
9928 case GFC_ISYM_RAND:
9929 case GFC_ISYM_RENAME:
9930 case GFC_ISYM_SECOND:
9931 case GFC_ISYM_SECNDS:
9932 case GFC_ISYM_SIGNAL:
9933 case GFC_ISYM_STAT:
9934 case GFC_ISYM_SYMLNK:
9935 case GFC_ISYM_SYSTEM:
9936 case GFC_ISYM_TIME:
9937 case GFC_ISYM_TIME8:
9938 case GFC_ISYM_UMASK:
9939 case GFC_ISYM_UNLINK:
9940 case GFC_ISYM_YN2:
9941 gfc_conv_intrinsic_funcall (se, expr);
9942 break;
9944 case GFC_ISYM_EOSHIFT:
9945 case GFC_ISYM_PACK:
9946 case GFC_ISYM_RESHAPE:
9947 /* For those, expr->rank should always be >0 and thus the if above the
9948 switch should have matched. */
9949 gcc_unreachable ();
9950 break;
9952 default:
9953 gfc_conv_intrinsic_lib_function (se, expr);
9954 break;
9959 static gfc_ss *
9960 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9962 gfc_ss *arg_ss, *tmp_ss;
9963 gfc_actual_arglist *arg;
9965 arg = expr->value.function.actual;
9967 gcc_assert (arg->expr);
9969 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9970 gcc_assert (arg_ss != gfc_ss_terminator);
9972 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9974 if (tmp_ss->info->type != GFC_SS_SCALAR
9975 && tmp_ss->info->type != GFC_SS_REFERENCE)
9977 gcc_assert (tmp_ss->dimen == 2);
9979 /* We just invert dimensions. */
9980 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9983 /* Stop when tmp_ss points to the last valid element of the chain... */
9984 if (tmp_ss->next == gfc_ss_terminator)
9985 break;
9988 /* ... so that we can attach the rest of the chain to it. */
9989 tmp_ss->next = ss;
9991 return arg_ss;
9995 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9996 This has the side effect of reversing the nested list, so there is no
9997 need to call gfc_reverse_ss on it (the given list is assumed not to be
9998 reversed yet). */
10000 static gfc_ss *
10001 nest_loop_dimension (gfc_ss *ss, int dim)
10003 int ss_dim, i;
10004 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
10005 gfc_loopinfo *new_loop;
10007 gcc_assert (ss != gfc_ss_terminator);
10009 for (; ss != gfc_ss_terminator; ss = ss->next)
10011 new_ss = gfc_get_ss ();
10012 new_ss->next = prev_ss;
10013 new_ss->parent = ss;
10014 new_ss->info = ss->info;
10015 new_ss->info->refcount++;
10016 if (ss->dimen != 0)
10018 gcc_assert (ss->info->type != GFC_SS_SCALAR
10019 && ss->info->type != GFC_SS_REFERENCE);
10021 new_ss->dimen = 1;
10022 new_ss->dim[0] = ss->dim[dim];
10024 gcc_assert (dim < ss->dimen);
10026 ss_dim = --ss->dimen;
10027 for (i = dim; i < ss_dim; i++)
10028 ss->dim[i] = ss->dim[i + 1];
10030 ss->dim[ss_dim] = 0;
10032 prev_ss = new_ss;
10034 if (ss->nested_ss)
10036 ss->nested_ss->parent = new_ss;
10037 new_ss->nested_ss = ss->nested_ss;
10039 ss->nested_ss = new_ss;
10042 new_loop = gfc_get_loopinfo ();
10043 gfc_init_loopinfo (new_loop);
10045 gcc_assert (prev_ss != NULL);
10046 gcc_assert (prev_ss != gfc_ss_terminator);
10047 gfc_add_ss_to_loop (new_loop, prev_ss);
10048 return new_ss->parent;
10052 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
10053 is to be inlined. */
10055 static gfc_ss *
10056 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
10058 gfc_ss *tmp_ss, *tail, *array_ss;
10059 gfc_actual_arglist *arg1, *arg2, *arg3;
10060 int sum_dim;
10061 bool scalar_mask = false;
10063 /* The rank of the result will be determined later. */
10064 arg1 = expr->value.function.actual;
10065 arg2 = arg1->next;
10066 arg3 = arg2->next;
10067 gcc_assert (arg3 != NULL);
10069 if (expr->rank == 0)
10070 return ss;
10072 tmp_ss = gfc_ss_terminator;
10074 if (arg3->expr)
10076 gfc_ss *mask_ss;
10078 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
10079 if (mask_ss == tmp_ss)
10080 scalar_mask = 1;
10082 tmp_ss = mask_ss;
10085 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
10086 gcc_assert (array_ss != tmp_ss);
10088 /* Odd thing: If the mask is scalar, it is used by the frontend after
10089 the array (to make an if around the nested loop). Thus it shall
10090 be after array_ss once the gfc_ss list is reversed. */
10091 if (scalar_mask)
10092 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
10093 else
10094 tmp_ss = array_ss;
10096 /* "Hide" the dimension on which we will sum in the first arg's scalarization
10097 chain. */
10098 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
10099 tail = nest_loop_dimension (tmp_ss, sum_dim);
10100 tail->next = ss;
10102 return tmp_ss;
10106 static gfc_ss *
10107 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
10110 switch (expr->value.function.isym->id)
10112 case GFC_ISYM_PRODUCT:
10113 case GFC_ISYM_SUM:
10114 return walk_inline_intrinsic_arith (ss, expr);
10116 case GFC_ISYM_TRANSPOSE:
10117 return walk_inline_intrinsic_transpose (ss, expr);
10119 default:
10120 gcc_unreachable ();
10122 gcc_unreachable ();
10126 /* This generates code to execute before entering the scalarization loop.
10127 Currently does nothing. */
10129 void
10130 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
10132 switch (ss->info->expr->value.function.isym->id)
10134 case GFC_ISYM_UBOUND:
10135 case GFC_ISYM_LBOUND:
10136 case GFC_ISYM_UCOBOUND:
10137 case GFC_ISYM_LCOBOUND:
10138 case GFC_ISYM_THIS_IMAGE:
10139 break;
10141 default:
10142 gcc_unreachable ();
10147 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
10148 are expanded into code inside the scalarization loop. */
10150 static gfc_ss *
10151 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
10153 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
10154 gfc_add_class_array_ref (expr->value.function.actual->expr);
10156 /* The two argument version returns a scalar. */
10157 if (expr->value.function.actual->next->expr)
10158 return ss;
10160 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
10164 /* Walk an intrinsic array libcall. */
10166 static gfc_ss *
10167 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
10169 gcc_assert (expr->rank > 0);
10170 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
10174 /* Return whether the function call expression EXPR will be expanded
10175 inline by gfc_conv_intrinsic_function. */
10177 bool
10178 gfc_inline_intrinsic_function_p (gfc_expr *expr)
10180 gfc_actual_arglist *args;
10182 if (!expr->value.function.isym)
10183 return false;
10185 switch (expr->value.function.isym->id)
10187 case GFC_ISYM_PRODUCT:
10188 case GFC_ISYM_SUM:
10189 /* Disable inline expansion if code size matters. */
10190 if (optimize_size)
10191 return false;
10193 args = expr->value.function.actual;
10194 /* We need to be able to subset the SUM argument at compile-time. */
10195 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
10196 return false;
10198 return true;
10200 case GFC_ISYM_TRANSPOSE:
10201 return true;
10203 default:
10204 return false;
10209 /* Returns nonzero if the specified intrinsic function call maps directly to
10210 an external library call. Should only be used for functions that return
10211 arrays. */
10214 gfc_is_intrinsic_libcall (gfc_expr * expr)
10216 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
10217 gcc_assert (expr->rank > 0);
10219 if (gfc_inline_intrinsic_function_p (expr))
10220 return 0;
10222 switch (expr->value.function.isym->id)
10224 case GFC_ISYM_ALL:
10225 case GFC_ISYM_ANY:
10226 case GFC_ISYM_COUNT:
10227 case GFC_ISYM_FINDLOC:
10228 case GFC_ISYM_JN2:
10229 case GFC_ISYM_IANY:
10230 case GFC_ISYM_IALL:
10231 case GFC_ISYM_IPARITY:
10232 case GFC_ISYM_MATMUL:
10233 case GFC_ISYM_MAXLOC:
10234 case GFC_ISYM_MAXVAL:
10235 case GFC_ISYM_MINLOC:
10236 case GFC_ISYM_MINVAL:
10237 case GFC_ISYM_NORM2:
10238 case GFC_ISYM_PARITY:
10239 case GFC_ISYM_PRODUCT:
10240 case GFC_ISYM_SUM:
10241 case GFC_ISYM_SHAPE:
10242 case GFC_ISYM_SPREAD:
10243 case GFC_ISYM_YN2:
10244 /* Ignore absent optional parameters. */
10245 return 1;
10247 case GFC_ISYM_CSHIFT:
10248 case GFC_ISYM_EOSHIFT:
10249 case GFC_ISYM_GET_TEAM:
10250 case GFC_ISYM_FAILED_IMAGES:
10251 case GFC_ISYM_STOPPED_IMAGES:
10252 case GFC_ISYM_PACK:
10253 case GFC_ISYM_RESHAPE:
10254 case GFC_ISYM_UNPACK:
10255 /* Pass absent optional parameters. */
10256 return 2;
10258 default:
10259 return 0;
10263 /* Walk an intrinsic function. */
10264 gfc_ss *
10265 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
10266 gfc_intrinsic_sym * isym)
10268 gcc_assert (isym);
10270 if (isym->elemental)
10271 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
10272 NULL, GFC_SS_SCALAR);
10274 if (expr->rank == 0)
10275 return ss;
10277 if (gfc_inline_intrinsic_function_p (expr))
10278 return walk_inline_intrinsic_function (ss, expr);
10280 if (gfc_is_intrinsic_libcall (expr))
10281 return gfc_walk_intrinsic_libfunc (ss, expr);
10283 /* Special cases. */
10284 switch (isym->id)
10286 case GFC_ISYM_LBOUND:
10287 case GFC_ISYM_LCOBOUND:
10288 case GFC_ISYM_UBOUND:
10289 case GFC_ISYM_UCOBOUND:
10290 case GFC_ISYM_THIS_IMAGE:
10291 return gfc_walk_intrinsic_bound (ss, expr);
10293 case GFC_ISYM_TRANSFER:
10294 case GFC_ISYM_CAF_GET:
10295 return gfc_walk_intrinsic_libfunc (ss, expr);
10297 default:
10298 /* This probably meant someone forgot to add an intrinsic to the above
10299 list(s) when they implemented it, or something's gone horribly
10300 wrong. */
10301 gcc_unreachable ();
10306 static tree
10307 conv_co_collective (gfc_code *code)
10309 gfc_se argse;
10310 stmtblock_t block, post_block;
10311 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
10312 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
10314 gfc_start_block (&block);
10315 gfc_init_block (&post_block);
10317 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
10319 opr_expr = code->ext.actual->next->expr;
10320 image_idx_expr = code->ext.actual->next->next->expr;
10321 stat_expr = code->ext.actual->next->next->next->expr;
10322 errmsg_expr = code->ext.actual->next->next->next->next->expr;
10324 else
10326 opr_expr = NULL;
10327 image_idx_expr = code->ext.actual->next->expr;
10328 stat_expr = code->ext.actual->next->next->expr;
10329 errmsg_expr = code->ext.actual->next->next->next->expr;
10332 /* stat. */
10333 if (stat_expr)
10335 gfc_init_se (&argse, NULL);
10336 gfc_conv_expr (&argse, stat_expr);
10337 gfc_add_block_to_block (&block, &argse.pre);
10338 gfc_add_block_to_block (&post_block, &argse.post);
10339 stat = argse.expr;
10340 if (flag_coarray != GFC_FCOARRAY_SINGLE)
10341 stat = gfc_build_addr_expr (NULL_TREE, stat);
10343 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
10344 stat = NULL_TREE;
10345 else
10346 stat = null_pointer_node;
10348 /* Early exit for GFC_FCOARRAY_SINGLE. */
10349 if (flag_coarray == GFC_FCOARRAY_SINGLE)
10351 if (stat != NULL_TREE)
10352 gfc_add_modify (&block, stat,
10353 fold_convert (TREE_TYPE (stat), integer_zero_node));
10354 return gfc_finish_block (&block);
10357 /* Handle the array. */
10358 gfc_init_se (&argse, NULL);
10359 if (code->ext.actual->expr->rank == 0)
10361 symbol_attribute attr;
10362 gfc_clear_attr (&attr);
10363 gfc_init_se (&argse, NULL);
10364 gfc_conv_expr (&argse, code->ext.actual->expr);
10365 gfc_add_block_to_block (&block, &argse.pre);
10366 gfc_add_block_to_block (&post_block, &argse.post);
10367 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
10368 array = gfc_build_addr_expr (NULL_TREE, array);
10370 else
10372 argse.want_pointer = 1;
10373 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
10374 array = argse.expr;
10376 gfc_add_block_to_block (&block, &argse.pre);
10377 gfc_add_block_to_block (&post_block, &argse.post);
10379 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
10380 strlen = argse.string_length;
10381 else
10382 strlen = integer_zero_node;
10384 /* image_index. */
10385 if (image_idx_expr)
10387 gfc_init_se (&argse, NULL);
10388 gfc_conv_expr (&argse, image_idx_expr);
10389 gfc_add_block_to_block (&block, &argse.pre);
10390 gfc_add_block_to_block (&post_block, &argse.post);
10391 image_index = fold_convert (integer_type_node, argse.expr);
10393 else
10394 image_index = integer_zero_node;
10396 /* errmsg. */
10397 if (errmsg_expr)
10399 gfc_init_se (&argse, NULL);
10400 gfc_conv_expr (&argse, errmsg_expr);
10401 gfc_add_block_to_block (&block, &argse.pre);
10402 gfc_add_block_to_block (&post_block, &argse.post);
10403 errmsg = argse.expr;
10404 errmsg_len = fold_convert (size_type_node, argse.string_length);
10406 else
10408 errmsg = null_pointer_node;
10409 errmsg_len = build_zero_cst (size_type_node);
10412 /* Generate the function call. */
10413 switch (code->resolved_isym->id)
10415 case GFC_ISYM_CO_BROADCAST:
10416 fndecl = gfor_fndecl_co_broadcast;
10417 break;
10418 case GFC_ISYM_CO_MAX:
10419 fndecl = gfor_fndecl_co_max;
10420 break;
10421 case GFC_ISYM_CO_MIN:
10422 fndecl = gfor_fndecl_co_min;
10423 break;
10424 case GFC_ISYM_CO_REDUCE:
10425 fndecl = gfor_fndecl_co_reduce;
10426 break;
10427 case GFC_ISYM_CO_SUM:
10428 fndecl = gfor_fndecl_co_sum;
10429 break;
10430 default:
10431 gcc_unreachable ();
10434 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
10435 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
10436 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
10437 image_index, stat, errmsg, errmsg_len);
10438 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
10439 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
10440 stat, errmsg, strlen, errmsg_len);
10441 else
10443 tree opr, opr_flags;
10445 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10446 int opr_flag_int;
10447 if (gfc_is_proc_ptr_comp (opr_expr))
10449 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
10450 opr_flag_int = sym->attr.dimension
10451 || (sym->ts.type == BT_CHARACTER
10452 && !sym->attr.is_bind_c)
10453 ? GFC_CAF_BYREF : 0;
10454 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10455 && !sym->attr.is_bind_c
10456 ? GFC_CAF_HIDDENLEN : 0;
10457 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
10459 else
10461 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
10462 ? GFC_CAF_BYREF : 0;
10463 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10464 && !opr_expr->symtree->n.sym->attr.is_bind_c
10465 ? GFC_CAF_HIDDENLEN : 0;
10466 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
10467 ? GFC_CAF_ARG_VALUE : 0;
10469 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
10470 gfc_conv_expr (&argse, opr_expr);
10471 opr = argse.expr;
10472 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
10473 image_index, stat, errmsg, strlen, errmsg_len);
10476 gfc_add_expr_to_block (&block, fndecl);
10477 gfc_add_block_to_block (&block, &post_block);
10479 return gfc_finish_block (&block);
10483 static tree
10484 conv_intrinsic_atomic_op (gfc_code *code)
10486 gfc_se argse;
10487 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
10488 stmtblock_t block, post_block;
10489 gfc_expr *atom_expr = code->ext.actual->expr;
10490 gfc_expr *stat_expr;
10491 built_in_function fn;
10493 if (atom_expr->expr_type == EXPR_FUNCTION
10494 && atom_expr->value.function.isym
10495 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10496 atom_expr = atom_expr->value.function.actual->expr;
10498 gfc_start_block (&block);
10499 gfc_init_block (&post_block);
10501 gfc_init_se (&argse, NULL);
10502 argse.want_pointer = 1;
10503 gfc_conv_expr (&argse, atom_expr);
10504 gfc_add_block_to_block (&block, &argse.pre);
10505 gfc_add_block_to_block (&post_block, &argse.post);
10506 atom = argse.expr;
10508 gfc_init_se (&argse, NULL);
10509 if (flag_coarray == GFC_FCOARRAY_LIB
10510 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
10511 argse.want_pointer = 1;
10512 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10513 gfc_add_block_to_block (&block, &argse.pre);
10514 gfc_add_block_to_block (&post_block, &argse.post);
10515 value = argse.expr;
10517 switch (code->resolved_isym->id)
10519 case GFC_ISYM_ATOMIC_ADD:
10520 case GFC_ISYM_ATOMIC_AND:
10521 case GFC_ISYM_ATOMIC_DEF:
10522 case GFC_ISYM_ATOMIC_OR:
10523 case GFC_ISYM_ATOMIC_XOR:
10524 stat_expr = code->ext.actual->next->next->expr;
10525 if (flag_coarray == GFC_FCOARRAY_LIB)
10526 old = null_pointer_node;
10527 break;
10528 default:
10529 gfc_init_se (&argse, NULL);
10530 if (flag_coarray == GFC_FCOARRAY_LIB)
10531 argse.want_pointer = 1;
10532 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10533 gfc_add_block_to_block (&block, &argse.pre);
10534 gfc_add_block_to_block (&post_block, &argse.post);
10535 old = argse.expr;
10536 stat_expr = code->ext.actual->next->next->next->expr;
10539 /* STAT= */
10540 if (stat_expr != NULL)
10542 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
10543 gfc_init_se (&argse, NULL);
10544 if (flag_coarray == GFC_FCOARRAY_LIB)
10545 argse.want_pointer = 1;
10546 gfc_conv_expr_val (&argse, stat_expr);
10547 gfc_add_block_to_block (&block, &argse.pre);
10548 gfc_add_block_to_block (&post_block, &argse.post);
10549 stat = argse.expr;
10551 else if (flag_coarray == GFC_FCOARRAY_LIB)
10552 stat = null_pointer_node;
10554 if (flag_coarray == GFC_FCOARRAY_LIB)
10556 tree image_index, caf_decl, offset, token;
10557 int op;
10559 switch (code->resolved_isym->id)
10561 case GFC_ISYM_ATOMIC_ADD:
10562 case GFC_ISYM_ATOMIC_FETCH_ADD:
10563 op = (int) GFC_CAF_ATOMIC_ADD;
10564 break;
10565 case GFC_ISYM_ATOMIC_AND:
10566 case GFC_ISYM_ATOMIC_FETCH_AND:
10567 op = (int) GFC_CAF_ATOMIC_AND;
10568 break;
10569 case GFC_ISYM_ATOMIC_OR:
10570 case GFC_ISYM_ATOMIC_FETCH_OR:
10571 op = (int) GFC_CAF_ATOMIC_OR;
10572 break;
10573 case GFC_ISYM_ATOMIC_XOR:
10574 case GFC_ISYM_ATOMIC_FETCH_XOR:
10575 op = (int) GFC_CAF_ATOMIC_XOR;
10576 break;
10577 case GFC_ISYM_ATOMIC_DEF:
10578 op = 0; /* Unused. */
10579 break;
10580 default:
10581 gcc_unreachable ();
10584 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10585 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10586 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10588 if (gfc_is_coindexed (atom_expr))
10589 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10590 else
10591 image_index = integer_zero_node;
10593 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10595 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10596 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10597 value = gfc_build_addr_expr (NULL_TREE, tmp);
10600 gfc_init_se (&argse, NULL);
10601 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10602 atom_expr);
10604 gfc_add_block_to_block (&block, &argse.pre);
10605 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10606 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10607 token, offset, image_index, value, stat,
10608 build_int_cst (integer_type_node,
10609 (int) atom_expr->ts.type),
10610 build_int_cst (integer_type_node,
10611 (int) atom_expr->ts.kind));
10612 else
10613 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10614 build_int_cst (integer_type_node, op),
10615 token, offset, image_index, value, old, stat,
10616 build_int_cst (integer_type_node,
10617 (int) atom_expr->ts.type),
10618 build_int_cst (integer_type_node,
10619 (int) atom_expr->ts.kind));
10621 gfc_add_expr_to_block (&block, tmp);
10622 gfc_add_block_to_block (&block, &argse.post);
10623 gfc_add_block_to_block (&block, &post_block);
10624 return gfc_finish_block (&block);
10628 switch (code->resolved_isym->id)
10630 case GFC_ISYM_ATOMIC_ADD:
10631 case GFC_ISYM_ATOMIC_FETCH_ADD:
10632 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10633 break;
10634 case GFC_ISYM_ATOMIC_AND:
10635 case GFC_ISYM_ATOMIC_FETCH_AND:
10636 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10637 break;
10638 case GFC_ISYM_ATOMIC_DEF:
10639 fn = BUILT_IN_ATOMIC_STORE_N;
10640 break;
10641 case GFC_ISYM_ATOMIC_OR:
10642 case GFC_ISYM_ATOMIC_FETCH_OR:
10643 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10644 break;
10645 case GFC_ISYM_ATOMIC_XOR:
10646 case GFC_ISYM_ATOMIC_FETCH_XOR:
10647 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10648 break;
10649 default:
10650 gcc_unreachable ();
10653 tmp = TREE_TYPE (TREE_TYPE (atom));
10654 fn = (built_in_function) ((int) fn
10655 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10656 + 1);
10657 tmp = builtin_decl_explicit (fn);
10658 tree itype = TREE_TYPE (TREE_TYPE (atom));
10659 tmp = builtin_decl_explicit (fn);
10661 switch (code->resolved_isym->id)
10663 case GFC_ISYM_ATOMIC_ADD:
10664 case GFC_ISYM_ATOMIC_AND:
10665 case GFC_ISYM_ATOMIC_DEF:
10666 case GFC_ISYM_ATOMIC_OR:
10667 case GFC_ISYM_ATOMIC_XOR:
10668 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10669 fold_convert (itype, value),
10670 build_int_cst (NULL, MEMMODEL_RELAXED));
10671 gfc_add_expr_to_block (&block, tmp);
10672 break;
10673 default:
10674 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10675 fold_convert (itype, value),
10676 build_int_cst (NULL, MEMMODEL_RELAXED));
10677 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10678 break;
10681 if (stat != NULL_TREE)
10682 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10683 gfc_add_block_to_block (&block, &post_block);
10684 return gfc_finish_block (&block);
10688 static tree
10689 conv_intrinsic_atomic_ref (gfc_code *code)
10691 gfc_se argse;
10692 tree tmp, atom, value, stat = NULL_TREE;
10693 stmtblock_t block, post_block;
10694 built_in_function fn;
10695 gfc_expr *atom_expr = code->ext.actual->next->expr;
10697 if (atom_expr->expr_type == EXPR_FUNCTION
10698 && atom_expr->value.function.isym
10699 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10700 atom_expr = atom_expr->value.function.actual->expr;
10702 gfc_start_block (&block);
10703 gfc_init_block (&post_block);
10704 gfc_init_se (&argse, NULL);
10705 argse.want_pointer = 1;
10706 gfc_conv_expr (&argse, atom_expr);
10707 gfc_add_block_to_block (&block, &argse.pre);
10708 gfc_add_block_to_block (&post_block, &argse.post);
10709 atom = argse.expr;
10711 gfc_init_se (&argse, NULL);
10712 if (flag_coarray == GFC_FCOARRAY_LIB
10713 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10714 argse.want_pointer = 1;
10715 gfc_conv_expr (&argse, code->ext.actual->expr);
10716 gfc_add_block_to_block (&block, &argse.pre);
10717 gfc_add_block_to_block (&post_block, &argse.post);
10718 value = argse.expr;
10720 /* STAT= */
10721 if (code->ext.actual->next->next->expr != NULL)
10723 gcc_assert (code->ext.actual->next->next->expr->expr_type
10724 == EXPR_VARIABLE);
10725 gfc_init_se (&argse, NULL);
10726 if (flag_coarray == GFC_FCOARRAY_LIB)
10727 argse.want_pointer = 1;
10728 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10729 gfc_add_block_to_block (&block, &argse.pre);
10730 gfc_add_block_to_block (&post_block, &argse.post);
10731 stat = argse.expr;
10733 else if (flag_coarray == GFC_FCOARRAY_LIB)
10734 stat = null_pointer_node;
10736 if (flag_coarray == GFC_FCOARRAY_LIB)
10738 tree image_index, caf_decl, offset, token;
10739 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10741 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10742 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10743 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10745 if (gfc_is_coindexed (atom_expr))
10746 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10747 else
10748 image_index = integer_zero_node;
10750 gfc_init_se (&argse, NULL);
10751 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10752 atom_expr);
10753 gfc_add_block_to_block (&block, &argse.pre);
10755 /* Different type, need type conversion. */
10756 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10758 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10759 orig_value = value;
10760 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10763 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10764 token, offset, image_index, value, stat,
10765 build_int_cst (integer_type_node,
10766 (int) atom_expr->ts.type),
10767 build_int_cst (integer_type_node,
10768 (int) atom_expr->ts.kind));
10769 gfc_add_expr_to_block (&block, tmp);
10770 if (vardecl != NULL_TREE)
10771 gfc_add_modify (&block, orig_value,
10772 fold_convert (TREE_TYPE (orig_value), vardecl));
10773 gfc_add_block_to_block (&block, &argse.post);
10774 gfc_add_block_to_block (&block, &post_block);
10775 return gfc_finish_block (&block);
10778 tmp = TREE_TYPE (TREE_TYPE (atom));
10779 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10780 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10781 + 1);
10782 tmp = builtin_decl_explicit (fn);
10783 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10784 build_int_cst (integer_type_node,
10785 MEMMODEL_RELAXED));
10786 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10788 if (stat != NULL_TREE)
10789 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10790 gfc_add_block_to_block (&block, &post_block);
10791 return gfc_finish_block (&block);
10795 static tree
10796 conv_intrinsic_atomic_cas (gfc_code *code)
10798 gfc_se argse;
10799 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10800 stmtblock_t block, post_block;
10801 built_in_function fn;
10802 gfc_expr *atom_expr = code->ext.actual->expr;
10804 if (atom_expr->expr_type == EXPR_FUNCTION
10805 && atom_expr->value.function.isym
10806 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10807 atom_expr = atom_expr->value.function.actual->expr;
10809 gfc_init_block (&block);
10810 gfc_init_block (&post_block);
10811 gfc_init_se (&argse, NULL);
10812 argse.want_pointer = 1;
10813 gfc_conv_expr (&argse, atom_expr);
10814 atom = argse.expr;
10816 gfc_init_se (&argse, NULL);
10817 if (flag_coarray == GFC_FCOARRAY_LIB)
10818 argse.want_pointer = 1;
10819 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10820 gfc_add_block_to_block (&block, &argse.pre);
10821 gfc_add_block_to_block (&post_block, &argse.post);
10822 old = argse.expr;
10824 gfc_init_se (&argse, NULL);
10825 if (flag_coarray == GFC_FCOARRAY_LIB)
10826 argse.want_pointer = 1;
10827 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10828 gfc_add_block_to_block (&block, &argse.pre);
10829 gfc_add_block_to_block (&post_block, &argse.post);
10830 comp = argse.expr;
10832 gfc_init_se (&argse, NULL);
10833 if (flag_coarray == GFC_FCOARRAY_LIB
10834 && code->ext.actual->next->next->next->expr->ts.kind
10835 == atom_expr->ts.kind)
10836 argse.want_pointer = 1;
10837 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10838 gfc_add_block_to_block (&block, &argse.pre);
10839 gfc_add_block_to_block (&post_block, &argse.post);
10840 new_val = argse.expr;
10842 /* STAT= */
10843 if (code->ext.actual->next->next->next->next->expr != NULL)
10845 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10846 == EXPR_VARIABLE);
10847 gfc_init_se (&argse, NULL);
10848 if (flag_coarray == GFC_FCOARRAY_LIB)
10849 argse.want_pointer = 1;
10850 gfc_conv_expr_val (&argse,
10851 code->ext.actual->next->next->next->next->expr);
10852 gfc_add_block_to_block (&block, &argse.pre);
10853 gfc_add_block_to_block (&post_block, &argse.post);
10854 stat = argse.expr;
10856 else if (flag_coarray == GFC_FCOARRAY_LIB)
10857 stat = null_pointer_node;
10859 if (flag_coarray == GFC_FCOARRAY_LIB)
10861 tree image_index, caf_decl, offset, token;
10863 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10864 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10865 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10867 if (gfc_is_coindexed (atom_expr))
10868 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10869 else
10870 image_index = integer_zero_node;
10872 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10874 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10875 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10876 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10879 /* Convert a constant to a pointer. */
10880 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10882 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10883 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10884 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10887 gfc_init_se (&argse, NULL);
10888 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10889 atom_expr);
10890 gfc_add_block_to_block (&block, &argse.pre);
10892 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10893 token, offset, image_index, old, comp, new_val,
10894 stat, build_int_cst (integer_type_node,
10895 (int) atom_expr->ts.type),
10896 build_int_cst (integer_type_node,
10897 (int) atom_expr->ts.kind));
10898 gfc_add_expr_to_block (&block, tmp);
10899 gfc_add_block_to_block (&block, &argse.post);
10900 gfc_add_block_to_block (&block, &post_block);
10901 return gfc_finish_block (&block);
10904 tmp = TREE_TYPE (TREE_TYPE (atom));
10905 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10906 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10907 + 1);
10908 tmp = builtin_decl_explicit (fn);
10910 gfc_add_modify (&block, old, comp);
10911 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10912 gfc_build_addr_expr (NULL, old),
10913 fold_convert (TREE_TYPE (old), new_val),
10914 boolean_false_node,
10915 build_int_cst (NULL, MEMMODEL_RELAXED),
10916 build_int_cst (NULL, MEMMODEL_RELAXED));
10917 gfc_add_expr_to_block (&block, tmp);
10919 if (stat != NULL_TREE)
10920 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10921 gfc_add_block_to_block (&block, &post_block);
10922 return gfc_finish_block (&block);
10925 static tree
10926 conv_intrinsic_event_query (gfc_code *code)
10928 gfc_se se, argse;
10929 tree stat = NULL_TREE, stat2 = NULL_TREE;
10930 tree count = NULL_TREE, count2 = NULL_TREE;
10932 gfc_expr *event_expr = code->ext.actual->expr;
10934 if (code->ext.actual->next->next->expr)
10936 gcc_assert (code->ext.actual->next->next->expr->expr_type
10937 == EXPR_VARIABLE);
10938 gfc_init_se (&argse, NULL);
10939 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10940 stat = argse.expr;
10942 else if (flag_coarray == GFC_FCOARRAY_LIB)
10943 stat = null_pointer_node;
10945 if (code->ext.actual->next->expr)
10947 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10948 gfc_init_se (&argse, NULL);
10949 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10950 count = argse.expr;
10953 gfc_start_block (&se.pre);
10954 if (flag_coarray == GFC_FCOARRAY_LIB)
10956 tree tmp, token, image_index;
10957 tree index = build_zero_cst (gfc_array_index_type);
10959 if (event_expr->expr_type == EXPR_FUNCTION
10960 && event_expr->value.function.isym
10961 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10962 event_expr = event_expr->value.function.actual->expr;
10964 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10966 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10967 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10968 != INTMOD_ISO_FORTRAN_ENV
10969 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10970 != ISOFORTRAN_EVENT_TYPE)
10972 gfc_error ("Sorry, the event component of derived type at %L is not "
10973 "yet supported", &event_expr->where);
10974 return NULL_TREE;
10977 if (gfc_is_coindexed (event_expr))
10979 gfc_error ("The event variable at %L shall not be coindexed",
10980 &event_expr->where);
10981 return NULL_TREE;
10984 image_index = integer_zero_node;
10986 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10987 event_expr);
10989 /* For arrays, obtain the array index. */
10990 if (gfc_expr_attr (event_expr).dimension)
10992 tree desc, tmp, extent, lbound, ubound;
10993 gfc_array_ref *ar, ar2;
10994 int i;
10996 /* TODO: Extend this, once DT components are supported. */
10997 ar = &event_expr->ref->u.ar;
10998 ar2 = *ar;
10999 memset (ar, '\0', sizeof (*ar));
11000 ar->as = ar2.as;
11001 ar->type = AR_FULL;
11003 gfc_init_se (&argse, NULL);
11004 argse.descriptor_only = 1;
11005 gfc_conv_expr_descriptor (&argse, event_expr);
11006 gfc_add_block_to_block (&se.pre, &argse.pre);
11007 desc = argse.expr;
11008 *ar = ar2;
11010 extent = build_one_cst (gfc_array_index_type);
11011 for (i = 0; i < ar->dimen; i++)
11013 gfc_init_se (&argse, NULL);
11014 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
11015 gfc_add_block_to_block (&argse.pre, &argse.pre);
11016 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
11017 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11018 TREE_TYPE (lbound), argse.expr, lbound);
11019 tmp = fold_build2_loc (input_location, MULT_EXPR,
11020 TREE_TYPE (tmp), extent, tmp);
11021 index = fold_build2_loc (input_location, PLUS_EXPR,
11022 TREE_TYPE (tmp), index, tmp);
11023 if (i < ar->dimen - 1)
11025 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
11026 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
11027 extent = fold_build2_loc (input_location, MULT_EXPR,
11028 TREE_TYPE (tmp), extent, tmp);
11033 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
11035 count2 = count;
11036 count = gfc_create_var (integer_type_node, "count");
11039 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
11041 stat2 = stat;
11042 stat = gfc_create_var (integer_type_node, "stat");
11045 index = fold_convert (size_type_node, index);
11046 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
11047 token, index, image_index, count
11048 ? gfc_build_addr_expr (NULL, count) : count,
11049 stat != null_pointer_node
11050 ? gfc_build_addr_expr (NULL, stat) : stat);
11051 gfc_add_expr_to_block (&se.pre, tmp);
11053 if (count2 != NULL_TREE)
11054 gfc_add_modify (&se.pre, count2,
11055 fold_convert (TREE_TYPE (count2), count));
11057 if (stat2 != NULL_TREE)
11058 gfc_add_modify (&se.pre, stat2,
11059 fold_convert (TREE_TYPE (stat2), stat));
11061 return gfc_finish_block (&se.pre);
11064 gfc_init_se (&argse, NULL);
11065 gfc_conv_expr_val (&argse, code->ext.actual->expr);
11066 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
11068 if (stat != NULL_TREE)
11069 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
11071 return gfc_finish_block (&se.pre);
11074 static tree
11075 conv_intrinsic_move_alloc (gfc_code *code)
11077 stmtblock_t block;
11078 gfc_expr *from_expr, *to_expr;
11079 gfc_expr *to_expr2, *from_expr2 = NULL;
11080 gfc_se from_se, to_se;
11081 tree tmp;
11082 bool coarray;
11084 gfc_start_block (&block);
11086 from_expr = code->ext.actual->expr;
11087 to_expr = code->ext.actual->next->expr;
11089 gfc_init_se (&from_se, NULL);
11090 gfc_init_se (&to_se, NULL);
11092 gcc_assert (from_expr->ts.type != BT_CLASS
11093 || to_expr->ts.type == BT_CLASS);
11094 coarray = gfc_get_corank (from_expr) != 0;
11096 if (from_expr->rank == 0 && !coarray)
11098 if (from_expr->ts.type != BT_CLASS)
11099 from_expr2 = from_expr;
11100 else
11102 from_expr2 = gfc_copy_expr (from_expr);
11103 gfc_add_data_component (from_expr2);
11106 if (to_expr->ts.type != BT_CLASS)
11107 to_expr2 = to_expr;
11108 else
11110 to_expr2 = gfc_copy_expr (to_expr);
11111 gfc_add_data_component (to_expr2);
11114 from_se.want_pointer = 1;
11115 to_se.want_pointer = 1;
11116 gfc_conv_expr (&from_se, from_expr2);
11117 gfc_conv_expr (&to_se, to_expr2);
11118 gfc_add_block_to_block (&block, &from_se.pre);
11119 gfc_add_block_to_block (&block, &to_se.pre);
11121 /* Deallocate "to". */
11122 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
11123 true, to_expr, to_expr->ts);
11124 gfc_add_expr_to_block (&block, tmp);
11126 /* Assign (_data) pointers. */
11127 gfc_add_modify_loc (input_location, &block, to_se.expr,
11128 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
11130 /* Set "from" to NULL. */
11131 gfc_add_modify_loc (input_location, &block, from_se.expr,
11132 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
11134 gfc_add_block_to_block (&block, &from_se.post);
11135 gfc_add_block_to_block (&block, &to_se.post);
11137 /* Set _vptr. */
11138 if (to_expr->ts.type == BT_CLASS)
11140 gfc_symbol *vtab;
11142 gfc_free_expr (to_expr2);
11143 gfc_init_se (&to_se, NULL);
11144 to_se.want_pointer = 1;
11145 gfc_add_vptr_component (to_expr);
11146 gfc_conv_expr (&to_se, to_expr);
11148 if (from_expr->ts.type == BT_CLASS)
11150 if (UNLIMITED_POLY (from_expr))
11151 vtab = NULL;
11152 else
11154 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
11155 gcc_assert (vtab);
11158 gfc_free_expr (from_expr2);
11159 gfc_init_se (&from_se, NULL);
11160 from_se.want_pointer = 1;
11161 gfc_add_vptr_component (from_expr);
11162 gfc_conv_expr (&from_se, from_expr);
11163 gfc_add_modify_loc (input_location, &block, to_se.expr,
11164 fold_convert (TREE_TYPE (to_se.expr),
11165 from_se.expr));
11167 /* Reset _vptr component to declared type. */
11168 if (vtab == NULL)
11169 /* Unlimited polymorphic. */
11170 gfc_add_modify_loc (input_location, &block, from_se.expr,
11171 fold_convert (TREE_TYPE (from_se.expr),
11172 null_pointer_node));
11173 else
11175 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
11176 gfc_add_modify_loc (input_location, &block, from_se.expr,
11177 fold_convert (TREE_TYPE (from_se.expr), tmp));
11180 else
11182 vtab = gfc_find_vtab (&from_expr->ts);
11183 gcc_assert (vtab);
11184 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
11185 gfc_add_modify_loc (input_location, &block, to_se.expr,
11186 fold_convert (TREE_TYPE (to_se.expr), tmp));
11190 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
11192 gfc_add_modify_loc (input_location, &block, to_se.string_length,
11193 fold_convert (TREE_TYPE (to_se.string_length),
11194 from_se.string_length));
11195 if (from_expr->ts.deferred)
11196 gfc_add_modify_loc (input_location, &block, from_se.string_length,
11197 build_int_cst (TREE_TYPE (from_se.string_length), 0));
11200 return gfc_finish_block (&block);
11203 /* Update _vptr component. */
11204 if (to_expr->ts.type == BT_CLASS)
11206 gfc_symbol *vtab;
11208 to_se.want_pointer = 1;
11209 to_expr2 = gfc_copy_expr (to_expr);
11210 gfc_add_vptr_component (to_expr2);
11211 gfc_conv_expr (&to_se, to_expr2);
11213 if (from_expr->ts.type == BT_CLASS)
11215 if (UNLIMITED_POLY (from_expr))
11216 vtab = NULL;
11217 else
11219 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
11220 gcc_assert (vtab);
11223 from_se.want_pointer = 1;
11224 from_expr2 = gfc_copy_expr (from_expr);
11225 gfc_add_vptr_component (from_expr2);
11226 gfc_conv_expr (&from_se, from_expr2);
11227 gfc_add_modify_loc (input_location, &block, to_se.expr,
11228 fold_convert (TREE_TYPE (to_se.expr),
11229 from_se.expr));
11231 /* Reset _vptr component to declared type. */
11232 if (vtab == NULL)
11233 /* Unlimited polymorphic. */
11234 gfc_add_modify_loc (input_location, &block, from_se.expr,
11235 fold_convert (TREE_TYPE (from_se.expr),
11236 null_pointer_node));
11237 else
11239 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
11240 gfc_add_modify_loc (input_location, &block, from_se.expr,
11241 fold_convert (TREE_TYPE (from_se.expr), tmp));
11244 else
11246 vtab = gfc_find_vtab (&from_expr->ts);
11247 gcc_assert (vtab);
11248 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
11249 gfc_add_modify_loc (input_location, &block, to_se.expr,
11250 fold_convert (TREE_TYPE (to_se.expr), tmp));
11253 gfc_free_expr (to_expr2);
11254 gfc_init_se (&to_se, NULL);
11256 if (from_expr->ts.type == BT_CLASS)
11258 gfc_free_expr (from_expr2);
11259 gfc_init_se (&from_se, NULL);
11264 /* Deallocate "to". */
11265 if (from_expr->rank == 0)
11267 to_se.want_coarray = 1;
11268 from_se.want_coarray = 1;
11270 gfc_conv_expr_descriptor (&to_se, to_expr);
11271 gfc_conv_expr_descriptor (&from_se, from_expr);
11273 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
11274 is an image control "statement", cf. IR F08/0040 in 12-006A. */
11275 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
11277 tree cond;
11279 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
11280 NULL_TREE, NULL_TREE, true, to_expr,
11281 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
11282 gfc_add_expr_to_block (&block, tmp);
11284 tmp = gfc_conv_descriptor_data_get (to_se.expr);
11285 cond = fold_build2_loc (input_location, EQ_EXPR,
11286 logical_type_node, tmp,
11287 fold_convert (TREE_TYPE (tmp),
11288 null_pointer_node));
11289 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
11290 3, null_pointer_node, null_pointer_node,
11291 build_int_cst (integer_type_node, 0));
11293 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
11294 tmp, build_empty_stmt (input_location));
11295 gfc_add_expr_to_block (&block, tmp);
11297 else
11299 if (to_expr->ts.type == BT_DERIVED
11300 && to_expr->ts.u.derived->attr.alloc_comp)
11302 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
11303 to_se.expr, to_expr->rank);
11304 gfc_add_expr_to_block (&block, tmp);
11307 tmp = gfc_conv_descriptor_data_get (to_se.expr);
11308 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
11309 NULL_TREE, true, to_expr,
11310 GFC_CAF_COARRAY_NOCOARRAY);
11311 gfc_add_expr_to_block (&block, tmp);
11314 /* Move the pointer and update the array descriptor data. */
11315 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
11317 /* Set "from" to NULL. */
11318 tmp = gfc_conv_descriptor_data_get (from_se.expr);
11319 gfc_add_modify_loc (input_location, &block, tmp,
11320 fold_convert (TREE_TYPE (tmp), null_pointer_node));
11323 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
11325 gfc_add_modify_loc (input_location, &block, to_se.string_length,
11326 fold_convert (TREE_TYPE (to_se.string_length),
11327 from_se.string_length));
11328 if (from_expr->ts.deferred)
11329 gfc_add_modify_loc (input_location, &block, from_se.string_length,
11330 build_int_cst (TREE_TYPE (from_se.string_length), 0));
11333 return gfc_finish_block (&block);
11337 tree
11338 gfc_conv_intrinsic_subroutine (gfc_code *code)
11340 tree res;
11342 gcc_assert (code->resolved_isym);
11344 switch (code->resolved_isym->id)
11346 case GFC_ISYM_MOVE_ALLOC:
11347 res = conv_intrinsic_move_alloc (code);
11348 break;
11350 case GFC_ISYM_ATOMIC_CAS:
11351 res = conv_intrinsic_atomic_cas (code);
11352 break;
11354 case GFC_ISYM_ATOMIC_ADD:
11355 case GFC_ISYM_ATOMIC_AND:
11356 case GFC_ISYM_ATOMIC_DEF:
11357 case GFC_ISYM_ATOMIC_OR:
11358 case GFC_ISYM_ATOMIC_XOR:
11359 case GFC_ISYM_ATOMIC_FETCH_ADD:
11360 case GFC_ISYM_ATOMIC_FETCH_AND:
11361 case GFC_ISYM_ATOMIC_FETCH_OR:
11362 case GFC_ISYM_ATOMIC_FETCH_XOR:
11363 res = conv_intrinsic_atomic_op (code);
11364 break;
11366 case GFC_ISYM_ATOMIC_REF:
11367 res = conv_intrinsic_atomic_ref (code);
11368 break;
11370 case GFC_ISYM_EVENT_QUERY:
11371 res = conv_intrinsic_event_query (code);
11372 break;
11374 case GFC_ISYM_C_F_POINTER:
11375 case GFC_ISYM_C_F_PROCPOINTER:
11376 res = conv_isocbinding_subroutine (code);
11377 break;
11379 case GFC_ISYM_CAF_SEND:
11380 res = conv_caf_send (code);
11381 break;
11383 case GFC_ISYM_CO_BROADCAST:
11384 case GFC_ISYM_CO_MIN:
11385 case GFC_ISYM_CO_MAX:
11386 case GFC_ISYM_CO_REDUCE:
11387 case GFC_ISYM_CO_SUM:
11388 res = conv_co_collective (code);
11389 break;
11391 case GFC_ISYM_FREE:
11392 res = conv_intrinsic_free (code);
11393 break;
11395 case GFC_ISYM_RANDOM_INIT:
11396 res = conv_intrinsic_random_init (code);
11397 break;
11399 case GFC_ISYM_KILL:
11400 res = conv_intrinsic_kill_sub (code);
11401 break;
11403 case GFC_ISYM_SYSTEM_CLOCK:
11404 res = conv_intrinsic_system_clock (code);
11405 break;
11407 default:
11408 res = NULL_TREE;
11409 break;
11412 return res;
11415 #include "gt-fortran-trans-intrinsic.h"