2018-10-09 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob3bb32b564bc354a24e619b88579392f639b9f3a5
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;
602 /* Initialize function decls for library functions. The external functions
603 are created as required. Builtin functions are added here. */
605 void
606 gfc_build_intrinsic_lib_fndecls (void)
608 gfc_intrinsic_map_t *m;
609 tree quad_decls[END_BUILTINS + 1];
611 if (gfc_real16_is_float128)
613 /* If we have soft-float types, we create the decls for their
614 C99-like library functions. For now, we only handle __float128
615 q-suffixed functions. */
617 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
618 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
620 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
622 type = gfc_float128_type_node;
623 complex_type = gfc_complex_float128_type_node;
624 /* type (*) (type) */
625 func_1 = build_function_type_list (type, type, NULL_TREE);
626 /* int (*) (type) */
627 func_iround = build_function_type_list (integer_type_node,
628 type, NULL_TREE);
629 /* long (*) (type) */
630 func_lround = build_function_type_list (long_integer_type_node,
631 type, NULL_TREE);
632 /* long long (*) (type) */
633 func_llround = build_function_type_list (long_long_integer_type_node,
634 type, NULL_TREE);
635 /* type (*) (type, type) */
636 func_2 = build_function_type_list (type, type, type, NULL_TREE);
637 /* type (*) (type, &int) */
638 func_frexp
639 = build_function_type_list (type,
640 type,
641 build_pointer_type (integer_type_node),
642 NULL_TREE);
643 /* type (*) (type, int) */
644 func_scalbn = build_function_type_list (type,
645 type, integer_type_node, NULL_TREE);
646 /* type (*) (complex type) */
647 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
648 /* complex type (*) (complex type, complex type) */
649 func_cpow
650 = build_function_type_list (complex_type,
651 complex_type, complex_type, NULL_TREE);
653 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
654 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
655 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
657 /* Only these built-ins are actually needed here. These are used directly
658 from the code, when calling builtin_decl_for_precision() or
659 builtin_decl_for_float_type(). The others are all constructed by
660 gfc_get_intrinsic_lib_fndecl(). */
661 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
662 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
664 #include "mathbuiltins.def"
666 #undef OTHER_BUILTIN
667 #undef LIB_FUNCTION
668 #undef DEFINE_MATH_BUILTIN
669 #undef DEFINE_MATH_BUILTIN_C
671 /* There is one built-in we defined manually, because it gets called
672 with builtin_decl_for_precision() or builtin_decl_for_float_type()
673 even though it is not an OTHER_BUILTIN: it is SQRT. */
674 quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
678 /* Add GCC builtin functions. */
679 for (m = gfc_intrinsic_map;
680 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
682 if (m->float_built_in != END_BUILTINS)
683 m->real4_decl = builtin_decl_explicit (m->float_built_in);
684 if (m->complex_float_built_in != END_BUILTINS)
685 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
686 if (m->double_built_in != END_BUILTINS)
687 m->real8_decl = builtin_decl_explicit (m->double_built_in);
688 if (m->complex_double_built_in != END_BUILTINS)
689 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
691 /* If real(kind=10) exists, it is always long double. */
692 if (m->long_double_built_in != END_BUILTINS)
693 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
694 if (m->complex_long_double_built_in != END_BUILTINS)
695 m->complex10_decl
696 = builtin_decl_explicit (m->complex_long_double_built_in);
698 if (!gfc_real16_is_float128)
700 if (m->long_double_built_in != END_BUILTINS)
701 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
702 if (m->complex_long_double_built_in != END_BUILTINS)
703 m->complex16_decl
704 = builtin_decl_explicit (m->complex_long_double_built_in);
706 else if (quad_decls[m->double_built_in] != NULL_TREE)
708 /* Quad-precision function calls are constructed when first
709 needed by builtin_decl_for_precision(), except for those
710 that will be used directly (define by OTHER_BUILTIN). */
711 m->real16_decl = quad_decls[m->double_built_in];
713 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
715 /* Same thing for the complex ones. */
716 m->complex16_decl = quad_decls[m->double_built_in];
722 /* Create a fndecl for a simple intrinsic library function. */
724 static tree
725 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
727 tree type;
728 vec<tree, va_gc> *argtypes;
729 tree fndecl;
730 gfc_actual_arglist *actual;
731 tree *pdecl;
732 gfc_typespec *ts;
733 char name[GFC_MAX_SYMBOL_LEN + 3];
735 ts = &expr->ts;
736 if (ts->type == BT_REAL)
738 switch (ts->kind)
740 case 4:
741 pdecl = &m->real4_decl;
742 break;
743 case 8:
744 pdecl = &m->real8_decl;
745 break;
746 case 10:
747 pdecl = &m->real10_decl;
748 break;
749 case 16:
750 pdecl = &m->real16_decl;
751 break;
752 default:
753 gcc_unreachable ();
756 else if (ts->type == BT_COMPLEX)
758 gcc_assert (m->complex_available);
760 switch (ts->kind)
762 case 4:
763 pdecl = &m->complex4_decl;
764 break;
765 case 8:
766 pdecl = &m->complex8_decl;
767 break;
768 case 10:
769 pdecl = &m->complex10_decl;
770 break;
771 case 16:
772 pdecl = &m->complex16_decl;
773 break;
774 default:
775 gcc_unreachable ();
778 else
779 gcc_unreachable ();
781 if (*pdecl)
782 return *pdecl;
784 if (m->libm_name)
786 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
787 if (gfc_real_kinds[n].c_float)
788 snprintf (name, sizeof (name), "%s%s%s",
789 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
790 else if (gfc_real_kinds[n].c_double)
791 snprintf (name, sizeof (name), "%s%s",
792 ts->type == BT_COMPLEX ? "c" : "", m->name);
793 else if (gfc_real_kinds[n].c_long_double)
794 snprintf (name, sizeof (name), "%s%s%s",
795 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
796 else if (gfc_real_kinds[n].c_float128)
797 snprintf (name, sizeof (name), "%s%s%s",
798 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
799 else
800 gcc_unreachable ();
802 else
804 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
805 ts->type == BT_COMPLEX ? 'c' : 'r',
806 ts->kind);
809 argtypes = NULL;
810 for (actual = expr->value.function.actual; actual; actual = actual->next)
812 type = gfc_typenode_for_spec (&actual->expr->ts);
813 vec_safe_push (argtypes, type);
815 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
816 fndecl = build_decl (input_location,
817 FUNCTION_DECL, get_identifier (name), type);
819 /* Mark the decl as external. */
820 DECL_EXTERNAL (fndecl) = 1;
821 TREE_PUBLIC (fndecl) = 1;
823 /* Mark it __attribute__((const)), if possible. */
824 TREE_READONLY (fndecl) = m->is_constant;
826 rest_of_decl_compilation (fndecl, 1, 0);
828 (*pdecl) = fndecl;
829 return fndecl;
833 /* Convert an intrinsic function into an external or builtin call. */
835 static void
836 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
838 gfc_intrinsic_map_t *m;
839 tree fndecl;
840 tree rettype;
841 tree *args;
842 unsigned int num_args;
843 gfc_isym_id id;
845 id = expr->value.function.isym->id;
846 /* Find the entry for this function. */
847 for (m = gfc_intrinsic_map;
848 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
850 if (id == m->id)
851 break;
854 if (m->id == GFC_ISYM_NONE)
856 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
857 expr->value.function.name, id);
860 /* Get the decl and generate the call. */
861 num_args = gfc_intrinsic_argument_list_length (expr);
862 args = XALLOCAVEC (tree, num_args);
864 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
865 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
866 rettype = TREE_TYPE (TREE_TYPE (fndecl));
868 fndecl = build_addr (fndecl);
869 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
873 /* If bounds-checking is enabled, create code to verify at runtime that the
874 string lengths for both expressions are the same (needed for e.g. MERGE).
875 If bounds-checking is not enabled, does nothing. */
877 void
878 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
879 tree a, tree b, stmtblock_t* target)
881 tree cond;
882 tree name;
884 /* If bounds-checking is disabled, do nothing. */
885 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
886 return;
888 /* Compare the two string lengths. */
889 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
891 /* Output the runtime-check. */
892 name = gfc_build_cstring_const (intr_name);
893 name = gfc_build_addr_expr (pchar_type_node, name);
894 gfc_trans_runtime_check (true, false, cond, target, where,
895 "Unequal character lengths (%ld/%ld) in %s",
896 fold_convert (long_integer_type_node, a),
897 fold_convert (long_integer_type_node, b), name);
901 /* The EXPONENT(X) intrinsic function is translated into
902 int ret;
903 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
904 so that if X is a NaN or infinity, the result is HUGE(0).
907 static void
908 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
910 tree arg, type, res, tmp, frexp, cond, huge;
911 int i;
913 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
914 expr->value.function.actual->expr->ts.kind);
916 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
917 arg = gfc_evaluate_now (arg, &se->pre);
919 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
920 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
921 cond = build_call_expr_loc (input_location,
922 builtin_decl_explicit (BUILT_IN_ISFINITE),
923 1, arg);
925 res = gfc_create_var (integer_type_node, NULL);
926 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
927 gfc_build_addr_expr (NULL_TREE, res));
928 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
929 tmp, res);
930 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
931 cond, tmp, huge);
933 type = gfc_typenode_for_spec (&expr->ts);
934 se->expr = fold_convert (type, se->expr);
938 /* Fill in the following structure
939 struct caf_vector_t {
940 size_t nvec; // size of the vector
941 union {
942 struct {
943 void *vector;
944 int kind;
945 } v;
946 struct {
947 ptrdiff_t lower_bound;
948 ptrdiff_t upper_bound;
949 ptrdiff_t stride;
950 } triplet;
951 } u;
952 } */
954 static void
955 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
956 tree lower, tree upper, tree stride,
957 tree vector, int kind, tree nvec)
959 tree field, type, tmp;
961 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
962 type = TREE_TYPE (desc);
964 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
965 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
966 desc, field, NULL_TREE);
967 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
969 /* Access union. */
970 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
971 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
972 desc, field, NULL_TREE);
973 type = TREE_TYPE (desc);
975 /* Access the inner struct. */
976 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
977 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
978 desc, field, NULL_TREE);
979 type = TREE_TYPE (desc);
981 if (vector != NULL_TREE)
983 /* Set vector and kind. */
984 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
985 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
986 desc, field, NULL_TREE);
987 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
988 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
989 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
990 desc, field, NULL_TREE);
991 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
993 else
995 /* Set dim.lower/upper/stride. */
996 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
997 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
998 desc, field, NULL_TREE);
999 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1001 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1002 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1003 desc, field, NULL_TREE);
1004 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1006 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1007 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1008 desc, field, NULL_TREE);
1009 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1014 static tree
1015 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1017 gfc_se argse;
1018 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1019 tree lbound, ubound, tmp;
1020 int i;
1022 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1024 for (i = 0; i < ar->dimen; i++)
1025 switch (ar->dimen_type[i])
1027 case DIMEN_RANGE:
1028 if (ar->end[i])
1030 gfc_init_se (&argse, NULL);
1031 gfc_conv_expr (&argse, ar->end[i]);
1032 gfc_add_block_to_block (block, &argse.pre);
1033 upper = gfc_evaluate_now (argse.expr, block);
1035 else
1036 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1037 if (ar->stride[i])
1039 gfc_init_se (&argse, NULL);
1040 gfc_conv_expr (&argse, ar->stride[i]);
1041 gfc_add_block_to_block (block, &argse.pre);
1042 stride = gfc_evaluate_now (argse.expr, block);
1044 else
1045 stride = gfc_index_one_node;
1047 /* Fall through. */
1048 case DIMEN_ELEMENT:
1049 if (ar->start[i])
1051 gfc_init_se (&argse, NULL);
1052 gfc_conv_expr (&argse, ar->start[i]);
1053 gfc_add_block_to_block (block, &argse.pre);
1054 lower = gfc_evaluate_now (argse.expr, block);
1056 else
1057 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1058 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1060 upper = lower;
1061 stride = gfc_index_one_node;
1063 vector = NULL_TREE;
1064 nvec = size_zero_node;
1065 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1066 vector, 0, nvec);
1067 break;
1069 case DIMEN_VECTOR:
1070 gfc_init_se (&argse, NULL);
1071 argse.descriptor_only = 1;
1072 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1073 gfc_add_block_to_block (block, &argse.pre);
1074 vector = argse.expr;
1075 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1076 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1077 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1078 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1079 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1080 TREE_TYPE (nvec), nvec, tmp);
1081 lower = gfc_index_zero_node;
1082 upper = gfc_index_zero_node;
1083 stride = gfc_index_zero_node;
1084 vector = gfc_conv_descriptor_data_get (vector);
1085 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1086 vector, ar->start[i]->ts.kind, nvec);
1087 break;
1088 default:
1089 gcc_unreachable();
1091 return gfc_build_addr_expr (NULL_TREE, var);
1095 static tree
1096 compute_component_offset (tree field, tree type)
1098 tree tmp;
1099 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1100 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1102 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1103 DECL_FIELD_BIT_OFFSET (field),
1104 bitsize_unit_node);
1105 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1107 else
1108 return DECL_FIELD_OFFSET (field);
1112 static tree
1113 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1115 gfc_ref *ref = expr->ref, *last_comp_ref;
1116 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1117 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1118 start, end, stride, vector, nvec;
1119 gfc_se se;
1120 bool ref_static_array = false;
1121 tree last_component_ref_tree = NULL_TREE;
1122 int i, last_type_n;
1124 if (expr->symtree)
1126 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1127 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1128 && !expr->symtree->n.sym->attr.pointer;
1131 /* Prevent uninit-warning. */
1132 reference_type = NULL_TREE;
1134 /* Skip refs upto the first coarray-ref. */
1135 last_comp_ref = NULL;
1136 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1138 /* Remember the type of components skipped. */
1139 if (ref->type == REF_COMPONENT)
1140 last_comp_ref = ref;
1141 ref = ref->next;
1143 /* When a component was skipped, get the type information of the last
1144 component ref, else get the type from the symbol. */
1145 if (last_comp_ref)
1147 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1148 last_type_n = last_comp_ref->u.c.component->ts.type;
1150 else
1152 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1153 last_type_n = expr->symtree->n.sym->ts.type;
1156 while (ref)
1158 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1159 && ref->u.ar.dimen == 0)
1161 /* Skip pure coindexes. */
1162 ref = ref->next;
1163 continue;
1165 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1166 reference_type = TREE_TYPE (tmp);
1168 if (caf_ref == NULL_TREE)
1169 caf_ref = tmp;
1171 /* Construct the chain of refs. */
1172 if (prev_caf_ref != NULL_TREE)
1174 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1175 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1176 TREE_TYPE (field), prev_caf_ref, field,
1177 NULL_TREE);
1178 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1179 tmp));
1181 prev_caf_ref = tmp;
1183 switch (ref->type)
1185 case REF_COMPONENT:
1186 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1187 last_type_n = ref->u.c.component->ts.type;
1188 /* Set the type of the ref. */
1189 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1190 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1191 TREE_TYPE (field), prev_caf_ref, field,
1192 NULL_TREE);
1193 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1194 GFC_CAF_REF_COMPONENT));
1196 /* Ref the c in union u. */
1197 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1198 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1199 TREE_TYPE (field), prev_caf_ref, field,
1200 NULL_TREE);
1201 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1202 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1203 TREE_TYPE (field), tmp, field,
1204 NULL_TREE);
1206 /* Set the offset. */
1207 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1208 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1209 TREE_TYPE (field), inner_struct, field,
1210 NULL_TREE);
1211 /* Computing the offset is somewhat harder. The bit_offset has to be
1212 taken into account. When the bit_offset in the field_decl is non-
1213 null, divide it by the bitsize_unit and add it to the regular
1214 offset. */
1215 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1216 TREE_TYPE (tmp));
1217 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1219 /* Set caf_token_offset. */
1220 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1221 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1222 TREE_TYPE (field), inner_struct, field,
1223 NULL_TREE);
1224 if ((ref->u.c.component->attr.allocatable
1225 || ref->u.c.component->attr.pointer)
1226 && ref->u.c.component->attr.dimension)
1228 tree arr_desc_token_offset;
1229 /* Get the token field from the descriptor. */
1230 arr_desc_token_offset = TREE_OPERAND (
1231 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1232 arr_desc_token_offset
1233 = compute_component_offset (arr_desc_token_offset,
1234 TREE_TYPE (tmp));
1235 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1236 TREE_TYPE (tmp2), tmp2,
1237 arr_desc_token_offset);
1239 else if (ref->u.c.component->caf_token)
1240 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1241 TREE_TYPE (tmp));
1242 else
1243 tmp2 = integer_zero_node;
1244 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1246 /* Remember whether this ref was to a non-allocatable/non-pointer
1247 component so the next array ref can be tailored correctly. */
1248 ref_static_array = !ref->u.c.component->attr.allocatable
1249 && !ref->u.c.component->attr.pointer;
1250 last_component_ref_tree = ref_static_array
1251 ? ref->u.c.component->backend_decl : NULL_TREE;
1252 break;
1253 case REF_ARRAY:
1254 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1255 ref_static_array = false;
1256 /* Set the type of the ref. */
1257 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1258 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1259 TREE_TYPE (field), prev_caf_ref, field,
1260 NULL_TREE);
1261 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1262 ref_static_array
1263 ? GFC_CAF_REF_STATIC_ARRAY
1264 : GFC_CAF_REF_ARRAY));
1266 /* Ref the a 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)), 1);
1272 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1273 TREE_TYPE (field), tmp, field,
1274 NULL_TREE);
1276 /* Set the static_array_type in a for static arrays. */
1277 if (ref_static_array)
1279 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1281 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1282 TREE_TYPE (field), inner_struct, field,
1283 NULL_TREE);
1284 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1285 last_type_n));
1287 /* Ref the mode in the inner_struct. */
1288 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1289 mode = fold_build3_loc (input_location, COMPONENT_REF,
1290 TREE_TYPE (field), inner_struct, field,
1291 NULL_TREE);
1292 /* Ref the dim in the inner_struct. */
1293 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1294 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1295 TREE_TYPE (field), inner_struct, field,
1296 NULL_TREE);
1297 for (i = 0; i < ref->u.ar.dimen; ++i)
1299 /* Ref dim i. */
1300 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1301 dim_type = TREE_TYPE (dim);
1302 mode_rhs = start = end = stride = NULL_TREE;
1303 switch (ref->u.ar.dimen_type[i])
1305 case DIMEN_RANGE:
1306 if (ref->u.ar.end[i])
1308 gfc_init_se (&se, NULL);
1309 gfc_conv_expr (&se, ref->u.ar.end[i]);
1310 gfc_add_block_to_block (block, &se.pre);
1311 if (ref_static_array)
1313 /* Make the index zero-based, when reffing a static
1314 array. */
1315 end = se.expr;
1316 gfc_init_se (&se, NULL);
1317 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1318 gfc_add_block_to_block (block, &se.pre);
1319 se.expr = fold_build2 (MINUS_EXPR,
1320 gfc_array_index_type,
1321 end, fold_convert (
1322 gfc_array_index_type,
1323 se.expr));
1325 end = gfc_evaluate_now (fold_convert (
1326 gfc_array_index_type,
1327 se.expr),
1328 block);
1330 else if (ref_static_array)
1331 end = fold_build2 (MINUS_EXPR,
1332 gfc_array_index_type,
1333 gfc_conv_array_ubound (
1334 last_component_ref_tree, i),
1335 gfc_conv_array_lbound (
1336 last_component_ref_tree, i));
1337 else
1339 end = NULL_TREE;
1340 mode_rhs = build_int_cst (unsigned_char_type_node,
1341 GFC_CAF_ARR_REF_OPEN_END);
1343 if (ref->u.ar.stride[i])
1345 gfc_init_se (&se, NULL);
1346 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1347 gfc_add_block_to_block (block, &se.pre);
1348 stride = gfc_evaluate_now (fold_convert (
1349 gfc_array_index_type,
1350 se.expr),
1351 block);
1352 if (ref_static_array)
1354 /* Make the index zero-based, when reffing a static
1355 array. */
1356 stride = fold_build2 (MULT_EXPR,
1357 gfc_array_index_type,
1358 gfc_conv_array_stride (
1359 last_component_ref_tree,
1361 stride);
1362 gcc_assert (end != NULL_TREE);
1363 /* Multiply with the product of array's stride and
1364 the step of the ref to a virtual upper bound.
1365 We can not compute the actual upper bound here or
1366 the caflib would compute the extend
1367 incorrectly. */
1368 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1369 end, gfc_conv_array_stride (
1370 last_component_ref_tree,
1371 i));
1372 end = gfc_evaluate_now (end, block);
1373 stride = gfc_evaluate_now (stride, block);
1376 else if (ref_static_array)
1378 stride = gfc_conv_array_stride (last_component_ref_tree,
1380 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1381 end, stride);
1382 end = gfc_evaluate_now (end, block);
1384 else
1385 /* Always set a ref stride of one to make caflib's
1386 handling easier. */
1387 stride = gfc_index_one_node;
1389 /* Fall through. */
1390 case DIMEN_ELEMENT:
1391 if (ref->u.ar.start[i])
1393 gfc_init_se (&se, NULL);
1394 gfc_conv_expr (&se, ref->u.ar.start[i]);
1395 gfc_add_block_to_block (block, &se.pre);
1396 if (ref_static_array)
1398 /* Make the index zero-based, when reffing a static
1399 array. */
1400 start = fold_convert (gfc_array_index_type, se.expr);
1401 gfc_init_se (&se, NULL);
1402 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1403 gfc_add_block_to_block (block, &se.pre);
1404 se.expr = fold_build2 (MINUS_EXPR,
1405 gfc_array_index_type,
1406 start, fold_convert (
1407 gfc_array_index_type,
1408 se.expr));
1409 /* Multiply with the stride. */
1410 se.expr = fold_build2 (MULT_EXPR,
1411 gfc_array_index_type,
1412 se.expr,
1413 gfc_conv_array_stride (
1414 last_component_ref_tree,
1415 i));
1417 start = gfc_evaluate_now (fold_convert (
1418 gfc_array_index_type,
1419 se.expr),
1420 block);
1421 if (mode_rhs == NULL_TREE)
1422 mode_rhs = build_int_cst (unsigned_char_type_node,
1423 ref->u.ar.dimen_type[i]
1424 == DIMEN_ELEMENT
1425 ? GFC_CAF_ARR_REF_SINGLE
1426 : GFC_CAF_ARR_REF_RANGE);
1428 else if (ref_static_array)
1430 start = integer_zero_node;
1431 mode_rhs = build_int_cst (unsigned_char_type_node,
1432 ref->u.ar.start[i] == NULL
1433 ? GFC_CAF_ARR_REF_FULL
1434 : GFC_CAF_ARR_REF_RANGE);
1436 else if (end == NULL_TREE)
1437 mode_rhs = build_int_cst (unsigned_char_type_node,
1438 GFC_CAF_ARR_REF_FULL);
1439 else
1440 mode_rhs = build_int_cst (unsigned_char_type_node,
1441 GFC_CAF_ARR_REF_OPEN_START);
1443 /* Ref the s in dim. */
1444 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1445 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1446 TREE_TYPE (field), dim, field,
1447 NULL_TREE);
1449 /* Set start in s. */
1450 if (start != NULL_TREE)
1452 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1454 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1455 TREE_TYPE (field), tmp, field,
1456 NULL_TREE);
1457 gfc_add_modify (block, tmp2,
1458 fold_convert (TREE_TYPE (tmp2), start));
1461 /* Set end in s. */
1462 if (end != NULL_TREE)
1464 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1466 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1467 TREE_TYPE (field), tmp, field,
1468 NULL_TREE);
1469 gfc_add_modify (block, tmp2,
1470 fold_convert (TREE_TYPE (tmp2), end));
1473 /* Set end in s. */
1474 if (stride != NULL_TREE)
1476 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1478 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1479 TREE_TYPE (field), tmp, field,
1480 NULL_TREE);
1481 gfc_add_modify (block, tmp2,
1482 fold_convert (TREE_TYPE (tmp2), stride));
1484 break;
1485 case DIMEN_VECTOR:
1486 /* TODO: In case of static array. */
1487 gcc_assert (!ref_static_array);
1488 mode_rhs = build_int_cst (unsigned_char_type_node,
1489 GFC_CAF_ARR_REF_VECTOR);
1490 gfc_init_se (&se, NULL);
1491 se.descriptor_only = 1;
1492 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1493 gfc_add_block_to_block (block, &se.pre);
1494 vector = se.expr;
1495 tmp = gfc_conv_descriptor_lbound_get (vector,
1496 gfc_rank_cst[0]);
1497 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1498 gfc_rank_cst[0]);
1499 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1500 tmp = gfc_conv_descriptor_stride_get (vector,
1501 gfc_rank_cst[0]);
1502 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1503 TREE_TYPE (nvec), nvec, tmp);
1504 vector = gfc_conv_descriptor_data_get (vector);
1506 /* Ref the v in dim. */
1507 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1508 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1509 TREE_TYPE (field), dim, field,
1510 NULL_TREE);
1512 /* Set vector in v. */
1513 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1514 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1515 TREE_TYPE (field), tmp, field,
1516 NULL_TREE);
1517 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1518 vector));
1520 /* Set nvec in v. */
1521 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1522 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1523 TREE_TYPE (field), tmp, field,
1524 NULL_TREE);
1525 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1526 nvec));
1528 /* Set kind in v. */
1529 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1530 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1531 TREE_TYPE (field), tmp, field,
1532 NULL_TREE);
1533 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1534 ref->u.ar.start[i]->ts.kind));
1535 break;
1536 default:
1537 gcc_unreachable ();
1539 /* Set the mode for dim i. */
1540 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1541 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1542 mode_rhs));
1545 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1546 if (i < GFC_MAX_DIMENSIONS)
1548 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1549 gfc_add_modify (block, tmp,
1550 build_int_cst (unsigned_char_type_node,
1551 GFC_CAF_ARR_REF_NONE));
1553 break;
1554 default:
1555 gcc_unreachable ();
1558 /* Set the size of the current type. */
1559 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1560 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1561 prev_caf_ref, field, NULL_TREE);
1562 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1563 TYPE_SIZE_UNIT (last_type)));
1565 ref = ref->next;
1568 if (prev_caf_ref != NULL_TREE)
1570 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1571 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1572 prev_caf_ref, field, NULL_TREE);
1573 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1574 null_pointer_node));
1576 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1577 : NULL_TREE;
1580 /* Get data from a remote coarray. */
1582 static void
1583 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1584 tree may_require_tmp, bool may_realloc,
1585 symbol_attribute *caf_attr)
1587 gfc_expr *array_expr, *tmp_stat;
1588 gfc_se argse;
1589 tree caf_decl, token, offset, image_index, tmp;
1590 tree res_var, dst_var, type, kind, vec, stat;
1591 tree caf_reference;
1592 symbol_attribute caf_attr_store;
1594 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1596 if (se->ss && se->ss->info->useflags)
1598 /* Access the previously obtained result. */
1599 gfc_conv_tmp_array_ref (se);
1600 return;
1603 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1604 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1605 type = gfc_typenode_for_spec (&array_expr->ts);
1607 if (caf_attr == NULL)
1609 caf_attr_store = gfc_caf_attr (array_expr);
1610 caf_attr = &caf_attr_store;
1613 res_var = lhs;
1614 dst_var = lhs;
1616 vec = null_pointer_node;
1617 tmp_stat = gfc_find_stat_co (expr);
1619 if (tmp_stat)
1621 gfc_se stat_se;
1622 gfc_init_se (&stat_se, NULL);
1623 gfc_conv_expr_reference (&stat_se, tmp_stat);
1624 stat = stat_se.expr;
1625 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1626 gfc_add_block_to_block (&se->post, &stat_se.post);
1628 else
1629 stat = null_pointer_node;
1631 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1632 is reallocatable or the right-hand side has allocatable components. */
1633 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1635 /* Get using caf_get_by_ref. */
1636 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1638 if (caf_reference != NULL_TREE)
1640 if (lhs == NULL_TREE)
1642 if (array_expr->ts.type == BT_CHARACTER)
1643 gfc_init_se (&argse, NULL);
1644 if (array_expr->rank == 0)
1646 symbol_attribute attr;
1647 gfc_clear_attr (&attr);
1648 if (array_expr->ts.type == BT_CHARACTER)
1650 res_var = gfc_conv_string_tmp (se,
1651 build_pointer_type (type),
1652 array_expr->ts.u.cl->backend_decl);
1653 argse.string_length = array_expr->ts.u.cl->backend_decl;
1655 else
1656 res_var = gfc_create_var (type, "caf_res");
1657 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1658 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1660 else
1662 /* Create temporary. */
1663 if (array_expr->ts.type == BT_CHARACTER)
1664 gfc_conv_expr_descriptor (&argse, array_expr);
1665 may_realloc = gfc_trans_create_temp_array (&se->pre,
1666 &se->post,
1667 se->ss, type,
1668 NULL_TREE, false,
1669 false, false,
1670 &array_expr->where)
1671 == NULL_TREE;
1672 res_var = se->ss->info->data.array.descriptor;
1673 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1674 if (may_realloc)
1676 tmp = gfc_conv_descriptor_data_get (res_var);
1677 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1678 NULL_TREE, NULL_TREE,
1679 NULL_TREE, true,
1680 NULL,
1681 GFC_CAF_COARRAY_NOCOARRAY);
1682 gfc_add_expr_to_block (&se->post, tmp);
1687 kind = build_int_cst (integer_type_node, expr->ts.kind);
1688 if (lhs_kind == NULL_TREE)
1689 lhs_kind = kind;
1691 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1692 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1693 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1694 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1695 caf_decl);
1696 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1697 array_expr);
1699 /* No overlap possible as we have generated a temporary. */
1700 if (lhs == NULL_TREE)
1701 may_require_tmp = boolean_false_node;
1703 /* It guarantees memory consistency within the same segment. */
1704 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1705 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1706 gfc_build_string_const (1, ""), NULL_TREE,
1707 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1708 NULL_TREE);
1709 ASM_VOLATILE_P (tmp) = 1;
1710 gfc_add_expr_to_block (&se->pre, tmp);
1712 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1713 10, token, image_index, dst_var,
1714 caf_reference, lhs_kind, kind,
1715 may_require_tmp,
1716 may_realloc ? boolean_true_node :
1717 boolean_false_node,
1718 stat, build_int_cst (integer_type_node,
1719 array_expr->ts.type));
1721 gfc_add_expr_to_block (&se->pre, tmp);
1723 if (se->ss)
1724 gfc_advance_se_ss_chain (se);
1726 se->expr = res_var;
1727 if (array_expr->ts.type == BT_CHARACTER)
1728 se->string_length = argse.string_length;
1730 return;
1734 gfc_init_se (&argse, NULL);
1735 if (array_expr->rank == 0)
1737 symbol_attribute attr;
1739 gfc_clear_attr (&attr);
1740 gfc_conv_expr (&argse, array_expr);
1742 if (lhs == NULL_TREE)
1744 gfc_clear_attr (&attr);
1745 if (array_expr->ts.type == BT_CHARACTER)
1746 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1747 argse.string_length);
1748 else
1749 res_var = gfc_create_var (type, "caf_res");
1750 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1751 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1753 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1754 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1756 else
1758 /* If has_vector, pass descriptor for whole array and the
1759 vector bounds separately. */
1760 gfc_array_ref *ar, ar2;
1761 bool has_vector = false;
1763 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1765 has_vector = true;
1766 ar = gfc_find_array_ref (expr);
1767 ar2 = *ar;
1768 memset (ar, '\0', sizeof (*ar));
1769 ar->as = ar2.as;
1770 ar->type = AR_FULL;
1772 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1773 gfc_conv_expr_descriptor (&argse, array_expr);
1774 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1775 has the wrong type if component references are done. */
1776 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1777 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1778 : array_expr->rank,
1779 type));
1780 if (has_vector)
1782 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1783 *ar = ar2;
1786 if (lhs == NULL_TREE)
1788 /* Create temporary. */
1789 for (int n = 0; n < se->ss->loop->dimen; n++)
1790 if (se->loop->to[n] == NULL_TREE)
1792 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1793 gfc_rank_cst[n]);
1794 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1795 gfc_rank_cst[n]);
1797 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1798 NULL_TREE, false, true, false,
1799 &array_expr->where);
1800 res_var = se->ss->info->data.array.descriptor;
1801 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1803 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1806 kind = build_int_cst (integer_type_node, expr->ts.kind);
1807 if (lhs_kind == NULL_TREE)
1808 lhs_kind = kind;
1810 gfc_add_block_to_block (&se->pre, &argse.pre);
1811 gfc_add_block_to_block (&se->post, &argse.post);
1813 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1814 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1815 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1816 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1817 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1818 array_expr);
1820 /* No overlap possible as we have generated a temporary. */
1821 if (lhs == NULL_TREE)
1822 may_require_tmp = boolean_false_node;
1824 /* It guarantees memory consistency within the same segment. */
1825 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1826 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1827 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1828 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1829 ASM_VOLATILE_P (tmp) = 1;
1830 gfc_add_expr_to_block (&se->pre, tmp);
1832 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1833 token, offset, image_index, argse.expr, vec,
1834 dst_var, kind, lhs_kind, may_require_tmp, stat);
1836 gfc_add_expr_to_block (&se->pre, tmp);
1838 if (se->ss)
1839 gfc_advance_se_ss_chain (se);
1841 se->expr = res_var;
1842 if (array_expr->ts.type == BT_CHARACTER)
1843 se->string_length = argse.string_length;
1847 /* Send data to a remote coarray. */
1849 static tree
1850 conv_caf_send (gfc_code *code) {
1851 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1852 gfc_se lhs_se, rhs_se;
1853 stmtblock_t block;
1854 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1855 tree may_require_tmp, src_stat, dst_stat, dst_team;
1856 tree lhs_type = NULL_TREE;
1857 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1858 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1860 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1862 lhs_expr = code->ext.actual->expr;
1863 rhs_expr = code->ext.actual->next->expr;
1864 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1865 ? boolean_false_node : boolean_true_node;
1866 gfc_init_block (&block);
1868 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1869 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1870 src_stat = dst_stat = null_pointer_node;
1871 dst_team = null_pointer_node;
1873 /* LHS. */
1874 gfc_init_se (&lhs_se, NULL);
1875 if (lhs_expr->rank == 0)
1877 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1879 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1880 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1882 else
1884 symbol_attribute attr;
1885 gfc_clear_attr (&attr);
1886 gfc_conv_expr (&lhs_se, lhs_expr);
1887 lhs_type = TREE_TYPE (lhs_se.expr);
1888 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1889 attr);
1890 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1893 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1894 && lhs_caf_attr.codimension)
1896 lhs_se.want_pointer = 1;
1897 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1898 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1899 has the wrong type if component references are done. */
1900 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1901 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1902 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1903 gfc_get_dtype_rank_type (
1904 gfc_has_vector_subscript (lhs_expr)
1905 ? gfc_find_array_ref (lhs_expr)->dimen
1906 : lhs_expr->rank,
1907 lhs_type));
1909 else
1911 bool has_vector = gfc_has_vector_subscript (lhs_expr);
1913 if (gfc_is_coindexed (lhs_expr) || !has_vector)
1915 /* If has_vector, pass descriptor for whole array and the
1916 vector bounds separately. */
1917 gfc_array_ref *ar, ar2;
1918 bool has_tmp_lhs_array = false;
1919 if (has_vector)
1921 has_tmp_lhs_array = true;
1922 ar = gfc_find_array_ref (lhs_expr);
1923 ar2 = *ar;
1924 memset (ar, '\0', sizeof (*ar));
1925 ar->as = ar2.as;
1926 ar->type = AR_FULL;
1928 lhs_se.want_pointer = 1;
1929 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1930 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
1931 that has the wrong type if component references are done. */
1932 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1933 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1934 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1935 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1936 : lhs_expr->rank,
1937 lhs_type));
1938 if (has_tmp_lhs_array)
1940 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1941 *ar = ar2;
1944 else
1946 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
1947 indexed array expression. This is rewritten to:
1949 tmp_array = arr2[...]
1950 arr1 ([...]) = tmp_array
1952 because using the standard gfc_conv_expr (lhs_expr) did the
1953 assignment with lhs and rhs exchanged. */
1955 gfc_ss *lss_for_tmparray, *lss_real;
1956 gfc_loopinfo loop;
1957 gfc_se se;
1958 stmtblock_t body;
1959 tree tmparr_desc, src;
1960 tree index = gfc_index_zero_node;
1961 tree stride = gfc_index_zero_node;
1962 int n;
1964 /* Walk both sides of the assignment, once to get the shape of the
1965 temporary array to create right. */
1966 lss_for_tmparray = gfc_walk_expr (lhs_expr);
1967 /* And a second time to be able to create an assignment of the
1968 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
1969 the tree in the descriptor with the one for the temporary
1970 array. */
1971 lss_real = gfc_walk_expr (lhs_expr);
1972 gfc_init_loopinfo (&loop);
1973 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
1974 gfc_add_ss_to_loop (&loop, lss_real);
1975 gfc_conv_ss_startstride (&loop);
1976 gfc_conv_loop_setup (&loop, &lhs_expr->where);
1977 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1978 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
1979 lss_for_tmparray, lhs_type, NULL_TREE,
1980 false, true, false,
1981 &lhs_expr->where);
1982 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
1983 gfc_start_scalarized_body (&loop, &body);
1984 gfc_init_se (&se, NULL);
1985 gfc_copy_loopinfo_to_se (&se, &loop);
1986 se.ss = lss_real;
1987 gfc_conv_expr (&se, lhs_expr);
1988 gfc_add_block_to_block (&body, &se.pre);
1990 /* Walk over all indexes of the loop. */
1991 for (n = loop.dimen - 1; n > 0; --n)
1993 tmp = loop.loopvar[n];
1994 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1995 gfc_array_index_type, tmp, loop.from[n]);
1996 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1997 gfc_array_index_type, tmp, index);
1999 stride = fold_build2_loc (input_location, MINUS_EXPR,
2000 gfc_array_index_type,
2001 loop.to[n - 1], loop.from[n - 1]);
2002 stride = fold_build2_loc (input_location, PLUS_EXPR,
2003 gfc_array_index_type,
2004 stride, gfc_index_one_node);
2006 index = fold_build2_loc (input_location, MULT_EXPR,
2007 gfc_array_index_type, tmp, stride);
2010 index = fold_build2_loc (input_location, MINUS_EXPR,
2011 gfc_array_index_type,
2012 index, loop.from[0]);
2014 index = fold_build2_loc (input_location, PLUS_EXPR,
2015 gfc_array_index_type,
2016 loop.loopvar[0], index);
2018 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2019 src = gfc_build_array_ref (src, index, NULL);
2020 /* Now create the assignment of lhs_expr = tmp_array. */
2021 gfc_add_modify (&body, se.expr, src);
2022 gfc_add_block_to_block (&body, &se.post);
2023 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2024 gfc_trans_scalarizing_loops (&loop, &body);
2025 gfc_add_block_to_block (&loop.pre, &loop.post);
2026 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2027 gfc_free_ss (lss_for_tmparray);
2028 gfc_free_ss (lss_real);
2032 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2034 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2035 temporary and a loop. */
2036 if (!gfc_is_coindexed (lhs_expr)
2037 && (!lhs_caf_attr.codimension
2038 || !(lhs_expr->rank > 0
2039 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2041 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2042 gcc_assert (gfc_is_coindexed (rhs_expr));
2043 gfc_init_se (&rhs_se, NULL);
2044 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2046 gfc_se scal_se;
2047 gfc_init_se (&scal_se, NULL);
2048 scal_se.want_pointer = 1;
2049 gfc_conv_expr (&scal_se, lhs_expr);
2050 /* Ensure scalar on lhs is allocated. */
2051 gfc_add_block_to_block (&block, &scal_se.pre);
2053 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2054 TYPE_SIZE_UNIT (
2055 gfc_typenode_for_spec (&lhs_expr->ts)),
2056 NULL_TREE);
2057 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2058 null_pointer_node);
2059 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2060 tmp, gfc_finish_block (&scal_se.pre),
2061 build_empty_stmt (input_location));
2062 gfc_add_expr_to_block (&block, tmp);
2064 else
2065 lhs_may_realloc = lhs_may_realloc
2066 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2067 gfc_add_block_to_block (&block, &lhs_se.pre);
2068 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2069 may_require_tmp, lhs_may_realloc,
2070 &rhs_caf_attr);
2071 gfc_add_block_to_block (&block, &rhs_se.pre);
2072 gfc_add_block_to_block (&block, &rhs_se.post);
2073 gfc_add_block_to_block (&block, &lhs_se.post);
2074 return gfc_finish_block (&block);
2077 gfc_add_block_to_block (&block, &lhs_se.pre);
2079 /* Obtain token, offset and image index for the LHS. */
2080 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2081 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2082 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2083 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2084 tmp = lhs_se.expr;
2085 if (lhs_caf_attr.alloc_comp)
2086 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2087 NULL);
2088 else
2089 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2090 lhs_expr);
2091 lhs_se.expr = tmp;
2093 /* RHS. */
2094 gfc_init_se (&rhs_se, NULL);
2095 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2096 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2097 rhs_expr = rhs_expr->value.function.actual->expr;
2098 if (rhs_expr->rank == 0)
2100 symbol_attribute attr;
2101 gfc_clear_attr (&attr);
2102 gfc_conv_expr (&rhs_se, rhs_expr);
2103 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2104 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2106 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2107 && rhs_caf_attr.codimension)
2109 tree tmp2;
2110 rhs_se.want_pointer = 1;
2111 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2112 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2113 has the wrong type if component references are done. */
2114 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2115 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2116 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2117 gfc_get_dtype_rank_type (
2118 gfc_has_vector_subscript (rhs_expr)
2119 ? gfc_find_array_ref (rhs_expr)->dimen
2120 : rhs_expr->rank,
2121 tmp2));
2123 else
2125 /* If has_vector, pass descriptor for whole array and the
2126 vector bounds separately. */
2127 gfc_array_ref *ar, ar2;
2128 bool has_vector = false;
2129 tree tmp2;
2131 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2133 has_vector = true;
2134 ar = gfc_find_array_ref (rhs_expr);
2135 ar2 = *ar;
2136 memset (ar, '\0', sizeof (*ar));
2137 ar->as = ar2.as;
2138 ar->type = AR_FULL;
2140 rhs_se.want_pointer = 1;
2141 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2142 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2143 has the wrong type if component references are done. */
2144 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2145 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2146 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2147 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2148 : rhs_expr->rank,
2149 tmp2));
2150 if (has_vector)
2152 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2153 *ar = ar2;
2157 gfc_add_block_to_block (&block, &rhs_se.pre);
2159 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2161 tmp_stat = gfc_find_stat_co (lhs_expr);
2163 if (tmp_stat)
2165 gfc_se stat_se;
2166 gfc_init_se (&stat_se, NULL);
2167 gfc_conv_expr_reference (&stat_se, tmp_stat);
2168 dst_stat = stat_se.expr;
2169 gfc_add_block_to_block (&block, &stat_se.pre);
2170 gfc_add_block_to_block (&block, &stat_se.post);
2173 tmp_team = gfc_find_team_co (lhs_expr);
2175 if (tmp_team)
2177 gfc_se team_se;
2178 gfc_init_se (&team_se, NULL);
2179 gfc_conv_expr_reference (&team_se, tmp_team);
2180 dst_team = team_se.expr;
2181 gfc_add_block_to_block (&block, &team_se.pre);
2182 gfc_add_block_to_block (&block, &team_se.post);
2185 if (!gfc_is_coindexed (rhs_expr))
2187 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2189 tree reference, dst_realloc;
2190 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2191 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2192 : boolean_false_node;
2193 tmp = build_call_expr_loc (input_location,
2194 gfor_fndecl_caf_send_by_ref,
2195 10, token, image_index, rhs_se.expr,
2196 reference, lhs_kind, rhs_kind,
2197 may_require_tmp, dst_realloc, src_stat,
2198 build_int_cst (integer_type_node,
2199 lhs_expr->ts.type));
2201 else
2202 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2203 token, offset, image_index, lhs_se.expr, vec,
2204 rhs_se.expr, lhs_kind, rhs_kind,
2205 may_require_tmp, src_stat, dst_team);
2207 else
2209 tree rhs_token, rhs_offset, rhs_image_index;
2211 /* It guarantees memory consistency within the same segment. */
2212 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2213 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2214 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2215 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2216 ASM_VOLATILE_P (tmp) = 1;
2217 gfc_add_expr_to_block (&block, tmp);
2219 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2220 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2221 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2222 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2223 tmp = rhs_se.expr;
2224 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2226 tmp_stat = gfc_find_stat_co (lhs_expr);
2228 if (tmp_stat)
2230 gfc_se stat_se;
2231 gfc_init_se (&stat_se, NULL);
2232 gfc_conv_expr_reference (&stat_se, tmp_stat);
2233 src_stat = stat_se.expr;
2234 gfc_add_block_to_block (&block, &stat_se.pre);
2235 gfc_add_block_to_block (&block, &stat_se.post);
2238 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2239 NULL_TREE, NULL);
2240 tree lhs_reference, rhs_reference;
2241 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2242 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2243 tmp = build_call_expr_loc (input_location,
2244 gfor_fndecl_caf_sendget_by_ref, 13,
2245 token, image_index, lhs_reference,
2246 rhs_token, rhs_image_index, rhs_reference,
2247 lhs_kind, rhs_kind, may_require_tmp,
2248 dst_stat, src_stat,
2249 build_int_cst (integer_type_node,
2250 lhs_expr->ts.type),
2251 build_int_cst (integer_type_node,
2252 rhs_expr->ts.type));
2254 else
2256 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2257 tmp, rhs_expr);
2258 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2259 14, token, offset, image_index,
2260 lhs_se.expr, vec, rhs_token, rhs_offset,
2261 rhs_image_index, tmp, rhs_vec, lhs_kind,
2262 rhs_kind, may_require_tmp, src_stat);
2265 gfc_add_expr_to_block (&block, tmp);
2266 gfc_add_block_to_block (&block, &lhs_se.post);
2267 gfc_add_block_to_block (&block, &rhs_se.post);
2269 /* It guarantees memory consistency within the same segment. */
2270 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2271 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2272 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2273 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2274 ASM_VOLATILE_P (tmp) = 1;
2275 gfc_add_expr_to_block (&block, tmp);
2277 return gfc_finish_block (&block);
2281 static void
2282 trans_this_image (gfc_se * se, gfc_expr *expr)
2284 stmtblock_t loop;
2285 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2286 lbound, ubound, extent, ml;
2287 gfc_se argse;
2288 int rank, corank;
2289 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2291 if (expr->value.function.actual->expr
2292 && !gfc_is_coarray (expr->value.function.actual->expr))
2293 distance = expr->value.function.actual->expr;
2295 /* The case -fcoarray=single is handled elsewhere. */
2296 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2298 /* Argument-free version: THIS_IMAGE(). */
2299 if (distance || expr->value.function.actual->expr == NULL)
2301 if (distance)
2303 gfc_init_se (&argse, NULL);
2304 gfc_conv_expr_val (&argse, distance);
2305 gfc_add_block_to_block (&se->pre, &argse.pre);
2306 gfc_add_block_to_block (&se->post, &argse.post);
2307 tmp = fold_convert (integer_type_node, argse.expr);
2309 else
2310 tmp = integer_zero_node;
2311 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2312 tmp);
2313 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2314 tmp);
2315 return;
2318 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2320 type = gfc_get_int_type (gfc_default_integer_kind);
2321 corank = gfc_get_corank (expr->value.function.actual->expr);
2322 rank = expr->value.function.actual->expr->rank;
2324 /* Obtain the descriptor of the COARRAY. */
2325 gfc_init_se (&argse, NULL);
2326 argse.want_coarray = 1;
2327 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2328 gfc_add_block_to_block (&se->pre, &argse.pre);
2329 gfc_add_block_to_block (&se->post, &argse.post);
2330 desc = argse.expr;
2332 if (se->ss)
2334 /* Create an implicit second parameter from the loop variable. */
2335 gcc_assert (!expr->value.function.actual->next->expr);
2336 gcc_assert (corank > 0);
2337 gcc_assert (se->loop->dimen == 1);
2338 gcc_assert (se->ss->info->expr == expr);
2340 dim_arg = se->loop->loopvar[0];
2341 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2342 gfc_array_index_type, dim_arg,
2343 build_int_cst (TREE_TYPE (dim_arg), 1));
2344 gfc_advance_se_ss_chain (se);
2346 else
2348 /* Use the passed DIM= argument. */
2349 gcc_assert (expr->value.function.actual->next->expr);
2350 gfc_init_se (&argse, NULL);
2351 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2352 gfc_array_index_type);
2353 gfc_add_block_to_block (&se->pre, &argse.pre);
2354 dim_arg = argse.expr;
2356 if (INTEGER_CST_P (dim_arg))
2358 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2359 || wi::gtu_p (wi::to_wide (dim_arg),
2360 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2361 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2362 "dimension index", expr->value.function.isym->name,
2363 &expr->where);
2365 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2367 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2368 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2369 dim_arg,
2370 build_int_cst (TREE_TYPE (dim_arg), 1));
2371 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2372 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2373 dim_arg, tmp);
2374 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2375 logical_type_node, cond, tmp);
2376 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2377 gfc_msg_fault);
2381 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2382 one always has a dim_arg argument.
2384 m = this_image() - 1
2385 if (corank == 1)
2387 sub(1) = m + lcobound(corank)
2388 return;
2390 i = rank
2391 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2392 for (;;)
2394 extent = gfc_extent(i)
2395 ml = m
2396 m = m/extent
2397 if (i >= min_var)
2398 goto exit_label
2401 exit_label:
2402 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2403 : m + lcobound(corank)
2406 /* this_image () - 1. */
2407 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2408 integer_zero_node);
2409 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2410 fold_convert (type, tmp), build_int_cst (type, 1));
2411 if (corank == 1)
2413 /* sub(1) = m + lcobound(corank). */
2414 lbound = gfc_conv_descriptor_lbound_get (desc,
2415 build_int_cst (TREE_TYPE (gfc_array_index_type),
2416 corank+rank-1));
2417 lbound = fold_convert (type, lbound);
2418 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2420 se->expr = tmp;
2421 return;
2424 m = gfc_create_var (type, NULL);
2425 ml = gfc_create_var (type, NULL);
2426 loop_var = gfc_create_var (integer_type_node, NULL);
2427 min_var = gfc_create_var (integer_type_node, NULL);
2429 /* m = this_image () - 1. */
2430 gfc_add_modify (&se->pre, m, tmp);
2432 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2433 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2434 fold_convert (integer_type_node, dim_arg),
2435 build_int_cst (integer_type_node, rank - 1));
2436 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2437 build_int_cst (integer_type_node, rank + corank - 2),
2438 tmp);
2439 gfc_add_modify (&se->pre, min_var, tmp);
2441 /* i = rank. */
2442 tmp = build_int_cst (integer_type_node, rank);
2443 gfc_add_modify (&se->pre, loop_var, tmp);
2445 exit_label = gfc_build_label_decl (NULL_TREE);
2446 TREE_USED (exit_label) = 1;
2448 /* Loop body. */
2449 gfc_init_block (&loop);
2451 /* ml = m. */
2452 gfc_add_modify (&loop, ml, m);
2454 /* extent = ... */
2455 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2456 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2457 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2458 extent = fold_convert (type, extent);
2460 /* m = m/extent. */
2461 gfc_add_modify (&loop, m,
2462 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2463 m, extent));
2465 /* Exit condition: if (i >= min_var) goto exit_label. */
2466 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2467 min_var);
2468 tmp = build1_v (GOTO_EXPR, exit_label);
2469 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2470 build_empty_stmt (input_location));
2471 gfc_add_expr_to_block (&loop, tmp);
2473 /* Increment loop variable: i++. */
2474 gfc_add_modify (&loop, loop_var,
2475 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2476 loop_var,
2477 build_int_cst (integer_type_node, 1)));
2479 /* Making the loop... actually loop! */
2480 tmp = gfc_finish_block (&loop);
2481 tmp = build1_v (LOOP_EXPR, tmp);
2482 gfc_add_expr_to_block (&se->pre, tmp);
2484 /* The exit label. */
2485 tmp = build1_v (LABEL_EXPR, exit_label);
2486 gfc_add_expr_to_block (&se->pre, tmp);
2488 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2489 : m + lcobound(corank) */
2491 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2492 build_int_cst (TREE_TYPE (dim_arg), corank));
2494 lbound = gfc_conv_descriptor_lbound_get (desc,
2495 fold_build2_loc (input_location, PLUS_EXPR,
2496 gfc_array_index_type, dim_arg,
2497 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2498 lbound = fold_convert (type, lbound);
2500 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2501 fold_build2_loc (input_location, MULT_EXPR, type,
2502 m, extent));
2503 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2505 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2506 fold_build2_loc (input_location, PLUS_EXPR, type,
2507 m, lbound));
2511 /* Convert a call to image_status. */
2513 static void
2514 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2516 unsigned int num_args;
2517 tree *args, tmp;
2519 num_args = gfc_intrinsic_argument_list_length (expr);
2520 args = XALLOCAVEC (tree, num_args);
2521 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2522 /* In args[0] the number of the image the status is desired for has to be
2523 given. */
2525 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2527 tree arg;
2528 arg = gfc_evaluate_now (args[0], &se->pre);
2529 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2530 fold_convert (integer_type_node, arg),
2531 integer_one_node);
2532 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2533 tmp, integer_zero_node,
2534 build_int_cst (integer_type_node,
2535 GFC_STAT_STOPPED_IMAGE));
2537 else if (flag_coarray == GFC_FCOARRAY_LIB)
2538 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2539 args[0], build_int_cst (integer_type_node, -1));
2540 else
2541 gcc_unreachable ();
2543 se->expr = tmp;
2546 static void
2547 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2549 unsigned int num_args;
2551 tree *args, tmp;
2553 num_args = gfc_intrinsic_argument_list_length (expr);
2554 args = XALLOCAVEC (tree, num_args);
2555 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2557 if (flag_coarray ==
2558 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2560 tree arg;
2562 arg = gfc_evaluate_now (args[0], &se->pre);
2563 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2564 fold_convert (integer_type_node, arg),
2565 integer_one_node);
2566 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2567 tmp, integer_zero_node,
2568 build_int_cst (integer_type_node,
2569 GFC_STAT_STOPPED_IMAGE));
2571 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2573 // the value -1 represents that no team has been created yet
2574 tmp = build_int_cst (integer_type_node, -1);
2576 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2577 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2578 args[0], build_int_cst (integer_type_node, -1));
2579 else if (flag_coarray == GFC_FCOARRAY_LIB)
2580 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2581 integer_zero_node, build_int_cst (integer_type_node, -1));
2582 else
2583 gcc_unreachable ();
2585 se->expr = tmp;
2589 static void
2590 trans_image_index (gfc_se * se, gfc_expr *expr)
2592 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2593 tmp, invalid_bound;
2594 gfc_se argse, subse;
2595 int rank, corank, codim;
2597 type = gfc_get_int_type (gfc_default_integer_kind);
2598 corank = gfc_get_corank (expr->value.function.actual->expr);
2599 rank = expr->value.function.actual->expr->rank;
2601 /* Obtain the descriptor of the COARRAY. */
2602 gfc_init_se (&argse, NULL);
2603 argse.want_coarray = 1;
2604 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2605 gfc_add_block_to_block (&se->pre, &argse.pre);
2606 gfc_add_block_to_block (&se->post, &argse.post);
2607 desc = argse.expr;
2609 /* Obtain a handle to the SUB argument. */
2610 gfc_init_se (&subse, NULL);
2611 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2612 gfc_add_block_to_block (&se->pre, &subse.pre);
2613 gfc_add_block_to_block (&se->post, &subse.post);
2614 subdesc = build_fold_indirect_ref_loc (input_location,
2615 gfc_conv_descriptor_data_get (subse.expr));
2617 /* Fortran 2008 does not require that the values remain in the cobounds,
2618 thus we need explicitly check this - and return 0 if they are exceeded. */
2620 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2621 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2622 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2623 fold_convert (gfc_array_index_type, tmp),
2624 lbound);
2626 for (codim = corank + rank - 2; codim >= rank; codim--)
2628 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2629 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2630 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2631 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2632 fold_convert (gfc_array_index_type, tmp),
2633 lbound);
2634 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2635 logical_type_node, invalid_bound, cond);
2636 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2637 fold_convert (gfc_array_index_type, tmp),
2638 ubound);
2639 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2640 logical_type_node, invalid_bound, cond);
2643 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2645 /* See Fortran 2008, C.10 for the following algorithm. */
2647 /* coindex = sub(corank) - lcobound(n). */
2648 coindex = fold_convert (gfc_array_index_type,
2649 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2650 NULL));
2651 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2652 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2653 fold_convert (gfc_array_index_type, coindex),
2654 lbound);
2656 for (codim = corank + rank - 2; codim >= rank; codim--)
2658 tree extent, ubound;
2660 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2661 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2662 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2663 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2665 /* coindex *= extent. */
2666 coindex = fold_build2_loc (input_location, MULT_EXPR,
2667 gfc_array_index_type, coindex, extent);
2669 /* coindex += sub(codim). */
2670 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2671 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2672 gfc_array_index_type, coindex,
2673 fold_convert (gfc_array_index_type, tmp));
2675 /* coindex -= lbound(codim). */
2676 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2677 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2678 gfc_array_index_type, coindex, lbound);
2681 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2682 fold_convert(type, coindex),
2683 build_int_cst (type, 1));
2685 /* Return 0 if "coindex" exceeds num_images(). */
2687 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2688 num_images = build_int_cst (type, 1);
2689 else
2691 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2692 integer_zero_node,
2693 build_int_cst (integer_type_node, -1));
2694 num_images = fold_convert (type, tmp);
2697 tmp = gfc_create_var (type, NULL);
2698 gfc_add_modify (&se->pre, tmp, coindex);
2700 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2701 num_images);
2702 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2703 cond,
2704 fold_convert (logical_type_node, invalid_bound));
2705 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2706 build_int_cst (type, 0), tmp);
2709 static void
2710 trans_num_images (gfc_se * se, gfc_expr *expr)
2712 tree tmp, distance, failed;
2713 gfc_se argse;
2715 if (expr->value.function.actual->expr)
2717 gfc_init_se (&argse, NULL);
2718 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2719 gfc_add_block_to_block (&se->pre, &argse.pre);
2720 gfc_add_block_to_block (&se->post, &argse.post);
2721 distance = fold_convert (integer_type_node, argse.expr);
2723 else
2724 distance = integer_zero_node;
2726 if (expr->value.function.actual->next->expr)
2728 gfc_init_se (&argse, NULL);
2729 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2730 gfc_add_block_to_block (&se->pre, &argse.pre);
2731 gfc_add_block_to_block (&se->post, &argse.post);
2732 failed = fold_convert (integer_type_node, argse.expr);
2734 else
2735 failed = build_int_cst (integer_type_node, -1);
2736 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2737 distance, failed);
2738 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2742 static void
2743 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2745 gfc_se argse;
2747 gfc_init_se (&argse, NULL);
2748 argse.data_not_needed = 1;
2749 argse.descriptor_only = 1;
2751 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2752 gfc_add_block_to_block (&se->pre, &argse.pre);
2753 gfc_add_block_to_block (&se->post, &argse.post);
2755 se->expr = gfc_conv_descriptor_rank (argse.expr);
2756 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2757 se->expr);
2761 /* Evaluate a single upper or lower bound. */
2762 /* TODO: bound intrinsic generates way too much unnecessary code. */
2764 static void
2765 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2767 gfc_actual_arglist *arg;
2768 gfc_actual_arglist *arg2;
2769 tree desc;
2770 tree type;
2771 tree bound;
2772 tree tmp;
2773 tree cond, cond1, cond3, cond4, size;
2774 tree ubound;
2775 tree lbound;
2776 gfc_se argse;
2777 gfc_array_spec * as;
2778 bool assumed_rank_lb_one;
2780 arg = expr->value.function.actual;
2781 arg2 = arg->next;
2783 if (se->ss)
2785 /* Create an implicit second parameter from the loop variable. */
2786 gcc_assert (!arg2->expr);
2787 gcc_assert (se->loop->dimen == 1);
2788 gcc_assert (se->ss->info->expr == expr);
2789 gfc_advance_se_ss_chain (se);
2790 bound = se->loop->loopvar[0];
2791 bound = fold_build2_loc (input_location, MINUS_EXPR,
2792 gfc_array_index_type, bound,
2793 se->loop->from[0]);
2795 else
2797 /* use the passed argument. */
2798 gcc_assert (arg2->expr);
2799 gfc_init_se (&argse, NULL);
2800 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2801 gfc_add_block_to_block (&se->pre, &argse.pre);
2802 bound = argse.expr;
2803 /* Convert from one based to zero based. */
2804 bound = fold_build2_loc (input_location, MINUS_EXPR,
2805 gfc_array_index_type, bound,
2806 gfc_index_one_node);
2809 /* TODO: don't re-evaluate the descriptor on each iteration. */
2810 /* Get a descriptor for the first parameter. */
2811 gfc_init_se (&argse, NULL);
2812 gfc_conv_expr_descriptor (&argse, arg->expr);
2813 gfc_add_block_to_block (&se->pre, &argse.pre);
2814 gfc_add_block_to_block (&se->post, &argse.post);
2816 desc = argse.expr;
2818 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2820 if (INTEGER_CST_P (bound))
2822 if (((!as || as->type != AS_ASSUMED_RANK)
2823 && wi::geu_p (wi::to_wide (bound),
2824 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2825 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2826 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2827 "dimension index", upper ? "UBOUND" : "LBOUND",
2828 &expr->where);
2831 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2833 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2835 bound = gfc_evaluate_now (bound, &se->pre);
2836 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2837 bound, build_int_cst (TREE_TYPE (bound), 0));
2838 if (as && as->type == AS_ASSUMED_RANK)
2839 tmp = gfc_conv_descriptor_rank (desc);
2840 else
2841 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2842 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2843 bound, fold_convert(TREE_TYPE (bound), tmp));
2844 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2845 logical_type_node, cond, tmp);
2846 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2847 gfc_msg_fault);
2851 /* Take care of the lbound shift for assumed-rank arrays, which are
2852 nonallocatable and nonpointers. Those has a lbound of 1. */
2853 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2854 && ((arg->expr->ts.type != BT_CLASS
2855 && !arg->expr->symtree->n.sym->attr.allocatable
2856 && !arg->expr->symtree->n.sym->attr.pointer)
2857 || (arg->expr->ts.type == BT_CLASS
2858 && !CLASS_DATA (arg->expr)->attr.allocatable
2859 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2861 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2862 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2864 /* 13.14.53: Result value for LBOUND
2866 Case (i): For an array section or for an array expression other than a
2867 whole array or array structure component, LBOUND(ARRAY, DIM)
2868 has the value 1. For a whole array or array structure
2869 component, LBOUND(ARRAY, DIM) has the value:
2870 (a) equal to the lower bound for subscript DIM of ARRAY if
2871 dimension DIM of ARRAY does not have extent zero
2872 or if ARRAY is an assumed-size array of rank DIM,
2873 or (b) 1 otherwise.
2875 13.14.113: Result value for UBOUND
2877 Case (i): For an array section or for an array expression other than a
2878 whole array or array structure component, UBOUND(ARRAY, DIM)
2879 has the value equal to the number of elements in the given
2880 dimension; otherwise, it has a value equal to the upper bound
2881 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2882 not have size zero and has value zero if dimension DIM has
2883 size zero. */
2885 if (!upper && assumed_rank_lb_one)
2886 se->expr = gfc_index_one_node;
2887 else if (as)
2889 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2891 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2892 ubound, lbound);
2893 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2894 stride, gfc_index_zero_node);
2895 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2896 logical_type_node, cond3, cond1);
2897 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2898 stride, gfc_index_zero_node);
2900 if (upper)
2902 tree cond5;
2903 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2904 logical_type_node, cond3, cond4);
2905 cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2906 gfc_index_one_node, lbound);
2907 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2908 logical_type_node, cond4, cond5);
2910 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2911 logical_type_node, cond, cond5);
2913 if (assumed_rank_lb_one)
2915 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2916 gfc_array_index_type, ubound, lbound);
2917 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2918 gfc_array_index_type, tmp, gfc_index_one_node);
2920 else
2921 tmp = ubound;
2923 se->expr = fold_build3_loc (input_location, COND_EXPR,
2924 gfc_array_index_type, cond,
2925 tmp, gfc_index_zero_node);
2927 else
2929 if (as->type == AS_ASSUMED_SIZE)
2930 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2931 bound, build_int_cst (TREE_TYPE (bound),
2932 arg->expr->rank - 1));
2933 else
2934 cond = logical_false_node;
2936 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2937 logical_type_node, cond3, cond4);
2938 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2939 logical_type_node, cond, cond1);
2941 se->expr = fold_build3_loc (input_location, COND_EXPR,
2942 gfc_array_index_type, cond,
2943 lbound, gfc_index_one_node);
2946 else
2948 if (upper)
2950 size = fold_build2_loc (input_location, MINUS_EXPR,
2951 gfc_array_index_type, ubound, lbound);
2952 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2953 gfc_array_index_type, size,
2954 gfc_index_one_node);
2955 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2956 gfc_array_index_type, se->expr,
2957 gfc_index_zero_node);
2959 else
2960 se->expr = gfc_index_one_node;
2963 type = gfc_typenode_for_spec (&expr->ts);
2964 se->expr = convert (type, se->expr);
2968 static void
2969 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2971 gfc_actual_arglist *arg;
2972 gfc_actual_arglist *arg2;
2973 gfc_se argse;
2974 tree bound, resbound, resbound2, desc, cond, tmp;
2975 tree type;
2976 int corank;
2978 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2979 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2980 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2982 arg = expr->value.function.actual;
2983 arg2 = arg->next;
2985 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2986 corank = gfc_get_corank (arg->expr);
2988 gfc_init_se (&argse, NULL);
2989 argse.want_coarray = 1;
2991 gfc_conv_expr_descriptor (&argse, arg->expr);
2992 gfc_add_block_to_block (&se->pre, &argse.pre);
2993 gfc_add_block_to_block (&se->post, &argse.post);
2994 desc = argse.expr;
2996 if (se->ss)
2998 /* Create an implicit second parameter from the loop variable. */
2999 gcc_assert (!arg2->expr);
3000 gcc_assert (corank > 0);
3001 gcc_assert (se->loop->dimen == 1);
3002 gcc_assert (se->ss->info->expr == expr);
3004 bound = se->loop->loopvar[0];
3005 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3006 bound, gfc_rank_cst[arg->expr->rank]);
3007 gfc_advance_se_ss_chain (se);
3009 else
3011 /* use the passed argument. */
3012 gcc_assert (arg2->expr);
3013 gfc_init_se (&argse, NULL);
3014 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3015 gfc_add_block_to_block (&se->pre, &argse.pre);
3016 bound = argse.expr;
3018 if (INTEGER_CST_P (bound))
3020 if (wi::ltu_p (wi::to_wide (bound), 1)
3021 || wi::gtu_p (wi::to_wide (bound),
3022 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3023 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3024 "dimension index", expr->value.function.isym->name,
3025 &expr->where);
3027 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3029 bound = gfc_evaluate_now (bound, &se->pre);
3030 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3031 bound, build_int_cst (TREE_TYPE (bound), 1));
3032 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3033 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3034 bound, tmp);
3035 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3036 logical_type_node, cond, tmp);
3037 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3038 gfc_msg_fault);
3042 /* Subtract 1 to get to zero based and add dimensions. */
3043 switch (arg->expr->rank)
3045 case 0:
3046 bound = fold_build2_loc (input_location, MINUS_EXPR,
3047 gfc_array_index_type, bound,
3048 gfc_index_one_node);
3049 case 1:
3050 break;
3051 default:
3052 bound = fold_build2_loc (input_location, PLUS_EXPR,
3053 gfc_array_index_type, bound,
3054 gfc_rank_cst[arg->expr->rank - 1]);
3058 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3060 /* Handle UCOBOUND with special handling of the last codimension. */
3061 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3063 /* Last codimension: For -fcoarray=single just return
3064 the lcobound - otherwise add
3065 ceiling (real (num_images ()) / real (size)) - 1
3066 = (num_images () + size - 1) / size - 1
3067 = (num_images - 1) / size(),
3068 where size is the product of the extent of all but the last
3069 codimension. */
3071 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3073 tree cosize;
3075 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3076 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3077 2, integer_zero_node,
3078 build_int_cst (integer_type_node, -1));
3079 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3080 gfc_array_index_type,
3081 fold_convert (gfc_array_index_type, tmp),
3082 build_int_cst (gfc_array_index_type, 1));
3083 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3084 gfc_array_index_type, tmp,
3085 fold_convert (gfc_array_index_type, cosize));
3086 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3087 gfc_array_index_type, resbound, tmp);
3089 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3091 /* ubound = lbound + num_images() - 1. */
3092 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3093 2, integer_zero_node,
3094 build_int_cst (integer_type_node, -1));
3095 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3096 gfc_array_index_type,
3097 fold_convert (gfc_array_index_type, tmp),
3098 build_int_cst (gfc_array_index_type, 1));
3099 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3100 gfc_array_index_type, resbound, tmp);
3103 if (corank > 1)
3105 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3106 bound,
3107 build_int_cst (TREE_TYPE (bound),
3108 arg->expr->rank + corank - 1));
3110 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3111 se->expr = fold_build3_loc (input_location, COND_EXPR,
3112 gfc_array_index_type, cond,
3113 resbound, resbound2);
3115 else
3116 se->expr = resbound;
3118 else
3119 se->expr = resbound;
3121 type = gfc_typenode_for_spec (&expr->ts);
3122 se->expr = convert (type, se->expr);
3126 static void
3127 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3129 gfc_actual_arglist *array_arg;
3130 gfc_actual_arglist *dim_arg;
3131 gfc_se argse;
3132 tree desc, tmp;
3134 array_arg = expr->value.function.actual;
3135 dim_arg = array_arg->next;
3137 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3139 gfc_init_se (&argse, NULL);
3140 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3141 gfc_add_block_to_block (&se->pre, &argse.pre);
3142 gfc_add_block_to_block (&se->post, &argse.post);
3143 desc = argse.expr;
3145 gcc_assert (dim_arg->expr);
3146 gfc_init_se (&argse, NULL);
3147 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3148 gfc_add_block_to_block (&se->pre, &argse.pre);
3149 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3150 argse.expr, gfc_index_one_node);
3151 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3154 static void
3155 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3157 tree arg, cabs;
3159 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3161 switch (expr->value.function.actual->expr->ts.type)
3163 case BT_INTEGER:
3164 case BT_REAL:
3165 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3166 arg);
3167 break;
3169 case BT_COMPLEX:
3170 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3171 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3172 break;
3174 default:
3175 gcc_unreachable ();
3180 /* Create a complex value from one or two real components. */
3182 static void
3183 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3185 tree real;
3186 tree imag;
3187 tree type;
3188 tree *args;
3189 unsigned int num_args;
3191 num_args = gfc_intrinsic_argument_list_length (expr);
3192 args = XALLOCAVEC (tree, num_args);
3194 type = gfc_typenode_for_spec (&expr->ts);
3195 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3196 real = convert (TREE_TYPE (type), args[0]);
3197 if (both)
3198 imag = convert (TREE_TYPE (type), args[1]);
3199 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3201 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3202 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3203 imag = convert (TREE_TYPE (type), imag);
3205 else
3206 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3208 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3212 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3213 MODULO(A, P) = A - FLOOR (A / P) * P
3215 The obvious algorithms above are numerically instable for large
3216 arguments, hence these intrinsics are instead implemented via calls
3217 to the fmod family of functions. It is the responsibility of the
3218 user to ensure that the second argument is non-zero. */
3220 static void
3221 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3223 tree type;
3224 tree tmp;
3225 tree test;
3226 tree test2;
3227 tree fmod;
3228 tree zero;
3229 tree args[2];
3231 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3233 switch (expr->ts.type)
3235 case BT_INTEGER:
3236 /* Integer case is easy, we've got a builtin op. */
3237 type = TREE_TYPE (args[0]);
3239 if (modulo)
3240 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3241 args[0], args[1]);
3242 else
3243 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3244 args[0], args[1]);
3245 break;
3247 case BT_REAL:
3248 fmod = NULL_TREE;
3249 /* Check if we have a builtin fmod. */
3250 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3252 /* The builtin should always be available. */
3253 gcc_assert (fmod != NULL_TREE);
3255 tmp = build_addr (fmod);
3256 se->expr = build_call_array_loc (input_location,
3257 TREE_TYPE (TREE_TYPE (fmod)),
3258 tmp, 2, args);
3259 if (modulo == 0)
3260 return;
3262 type = TREE_TYPE (args[0]);
3264 args[0] = gfc_evaluate_now (args[0], &se->pre);
3265 args[1] = gfc_evaluate_now (args[1], &se->pre);
3267 /* Definition:
3268 modulo = arg - floor (arg/arg2) * arg2
3270 In order to calculate the result accurately, we use the fmod
3271 function as follows.
3273 res = fmod (arg, arg2);
3274 if (res)
3276 if ((arg < 0) xor (arg2 < 0))
3277 res += arg2;
3279 else
3280 res = copysign (0., arg2);
3282 => As two nested ternary exprs:
3284 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3285 : copysign (0., arg2);
3289 zero = gfc_build_const (type, integer_zero_node);
3290 tmp = gfc_evaluate_now (se->expr, &se->pre);
3291 if (!flag_signed_zeros)
3293 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3294 args[0], zero);
3295 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3296 args[1], zero);
3297 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3298 logical_type_node, test, test2);
3299 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3300 tmp, zero);
3301 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3302 logical_type_node, test, test2);
3303 test = gfc_evaluate_now (test, &se->pre);
3304 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3305 fold_build2_loc (input_location,
3306 PLUS_EXPR,
3307 type, tmp, args[1]),
3308 tmp);
3310 else
3312 tree expr1, copysign, cscall;
3313 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3314 expr->ts.kind);
3315 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3316 args[0], zero);
3317 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3318 args[1], zero);
3319 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3320 logical_type_node, test, test2);
3321 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3322 fold_build2_loc (input_location,
3323 PLUS_EXPR,
3324 type, tmp, args[1]),
3325 tmp);
3326 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3327 tmp, zero);
3328 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3329 args[1]);
3330 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3331 expr1, cscall);
3333 return;
3335 default:
3336 gcc_unreachable ();
3340 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3341 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3342 where the right shifts are logical (i.e. 0's are shifted in).
3343 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3344 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3345 DSHIFTL(I,J,0) = I
3346 DSHIFTL(I,J,BITSIZE) = J
3347 DSHIFTR(I,J,0) = J
3348 DSHIFTR(I,J,BITSIZE) = I. */
3350 static void
3351 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3353 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3354 tree args[3], cond, tmp;
3355 int bitsize;
3357 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3359 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3360 type = TREE_TYPE (args[0]);
3361 bitsize = TYPE_PRECISION (type);
3362 utype = unsigned_type_for (type);
3363 stype = TREE_TYPE (args[2]);
3365 arg1 = gfc_evaluate_now (args[0], &se->pre);
3366 arg2 = gfc_evaluate_now (args[1], &se->pre);
3367 shift = gfc_evaluate_now (args[2], &se->pre);
3369 /* The generic case. */
3370 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3371 build_int_cst (stype, bitsize), shift);
3372 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3373 arg1, dshiftl ? shift : tmp);
3375 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3376 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3377 right = fold_convert (type, right);
3379 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3381 /* Special cases. */
3382 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3383 build_int_cst (stype, 0));
3384 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3385 dshiftl ? arg1 : arg2, res);
3387 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3388 build_int_cst (stype, bitsize));
3389 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3390 dshiftl ? arg2 : arg1, res);
3392 se->expr = res;
3396 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3398 static void
3399 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3401 tree val;
3402 tree tmp;
3403 tree type;
3404 tree zero;
3405 tree args[2];
3407 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3408 type = TREE_TYPE (args[0]);
3410 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3411 val = gfc_evaluate_now (val, &se->pre);
3413 zero = gfc_build_const (type, integer_zero_node);
3414 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3415 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3419 /* SIGN(A, B) is absolute value of A times sign of B.
3420 The real value versions use library functions to ensure the correct
3421 handling of negative zero. Integer case implemented as:
3422 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3425 static void
3426 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3428 tree tmp;
3429 tree type;
3430 tree args[2];
3432 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3433 if (expr->ts.type == BT_REAL)
3435 tree abs;
3437 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3438 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3440 /* We explicitly have to ignore the minus sign. We do so by using
3441 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3442 if (!flag_sign_zero
3443 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3445 tree cond, zero;
3446 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3447 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3448 args[1], zero);
3449 se->expr = fold_build3_loc (input_location, COND_EXPR,
3450 TREE_TYPE (args[0]), cond,
3451 build_call_expr_loc (input_location, abs, 1,
3452 args[0]),
3453 build_call_expr_loc (input_location, tmp, 2,
3454 args[0], args[1]));
3456 else
3457 se->expr = build_call_expr_loc (input_location, tmp, 2,
3458 args[0], args[1]);
3459 return;
3462 /* Having excluded floating point types, we know we are now dealing
3463 with signed integer types. */
3464 type = TREE_TYPE (args[0]);
3466 /* Args[0] is used multiple times below. */
3467 args[0] = gfc_evaluate_now (args[0], &se->pre);
3469 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3470 the signs of A and B are the same, and of all ones if they differ. */
3471 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3472 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3473 build_int_cst (type, TYPE_PRECISION (type) - 1));
3474 tmp = gfc_evaluate_now (tmp, &se->pre);
3476 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3477 is all ones (i.e. -1). */
3478 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3479 fold_build2_loc (input_location, PLUS_EXPR,
3480 type, args[0], tmp), tmp);
3484 /* Test for the presence of an optional argument. */
3486 static void
3487 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3489 gfc_expr *arg;
3491 arg = expr->value.function.actual->expr;
3492 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3493 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3494 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3498 /* Calculate the double precision product of two single precision values. */
3500 static void
3501 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3503 tree type;
3504 tree args[2];
3506 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3508 /* Convert the args to double precision before multiplying. */
3509 type = gfc_typenode_for_spec (&expr->ts);
3510 args[0] = convert (type, args[0]);
3511 args[1] = convert (type, args[1]);
3512 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3513 args[1]);
3517 /* Return a length one character string containing an ascii character. */
3519 static void
3520 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3522 tree arg[2];
3523 tree var;
3524 tree type;
3525 unsigned int num_args;
3527 num_args = gfc_intrinsic_argument_list_length (expr);
3528 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3530 type = gfc_get_char_type (expr->ts.kind);
3531 var = gfc_create_var (type, "char");
3533 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3534 gfc_add_modify (&se->pre, var, arg[0]);
3535 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3536 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3540 static void
3541 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3543 tree var;
3544 tree len;
3545 tree tmp;
3546 tree cond;
3547 tree fndecl;
3548 tree *args;
3549 unsigned int num_args;
3551 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3552 args = XALLOCAVEC (tree, num_args);
3554 var = gfc_create_var (pchar_type_node, "pstr");
3555 len = gfc_create_var (gfc_charlen_type_node, "len");
3557 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3558 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3559 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3561 fndecl = build_addr (gfor_fndecl_ctime);
3562 tmp = build_call_array_loc (input_location,
3563 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3564 fndecl, num_args, args);
3565 gfc_add_expr_to_block (&se->pre, tmp);
3567 /* Free the temporary afterwards, if necessary. */
3568 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3569 len, build_int_cst (TREE_TYPE (len), 0));
3570 tmp = gfc_call_free (var);
3571 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3572 gfc_add_expr_to_block (&se->post, tmp);
3574 se->expr = var;
3575 se->string_length = len;
3579 static void
3580 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3582 tree var;
3583 tree len;
3584 tree tmp;
3585 tree cond;
3586 tree fndecl;
3587 tree *args;
3588 unsigned int num_args;
3590 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3591 args = XALLOCAVEC (tree, num_args);
3593 var = gfc_create_var (pchar_type_node, "pstr");
3594 len = gfc_create_var (gfc_charlen_type_node, "len");
3596 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3597 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3598 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3600 fndecl = build_addr (gfor_fndecl_fdate);
3601 tmp = build_call_array_loc (input_location,
3602 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3603 fndecl, num_args, args);
3604 gfc_add_expr_to_block (&se->pre, tmp);
3606 /* Free the temporary afterwards, if necessary. */
3607 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3608 len, build_int_cst (TREE_TYPE (len), 0));
3609 tmp = gfc_call_free (var);
3610 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3611 gfc_add_expr_to_block (&se->post, tmp);
3613 se->expr = var;
3614 se->string_length = len;
3618 /* Generate a direct call to free() for the FREE subroutine. */
3620 static tree
3621 conv_intrinsic_free (gfc_code *code)
3623 stmtblock_t block;
3624 gfc_se argse;
3625 tree arg, call;
3627 gfc_init_se (&argse, NULL);
3628 gfc_conv_expr (&argse, code->ext.actual->expr);
3629 arg = fold_convert (ptr_type_node, argse.expr);
3631 gfc_init_block (&block);
3632 call = build_call_expr_loc (input_location,
3633 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3634 gfc_add_expr_to_block (&block, call);
3635 return gfc_finish_block (&block);
3639 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3640 handling seeding on coarray images. */
3642 static tree
3643 conv_intrinsic_random_init (gfc_code *code)
3645 stmtblock_t block;
3646 gfc_se se;
3647 tree arg1, arg2, arg3, tmp;
3648 tree logical4_type_node = gfc_get_logical_type (4);
3650 /* Make the function call. */
3651 gfc_init_block (&block);
3652 gfc_init_se (&se, NULL);
3654 /* Convert REPEATABLE to a LOGICAL(4) entity. */
3655 gfc_conv_expr (&se, code->ext.actual->expr);
3656 gfc_add_block_to_block (&block, &se.pre);
3657 arg1 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3658 gfc_add_block_to_block (&block, &se.post);
3660 /* Convert IMAGE_DISTINCT to a LOGICAL(4) entity. */
3661 gfc_conv_expr (&se, code->ext.actual->next->expr);
3662 gfc_add_block_to_block (&block, &se.pre);
3663 arg2 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3664 gfc_add_block_to_block (&block, &se.post);
3666 /* Create the hidden argument. For non-coarray codes and -fcoarray=single,
3667 simply set this to 0. For -fcoarray=lib, generate a call to
3668 THIS_IMAGE() without arguments. */
3669 arg3 = build_int_cst (gfc_get_int_type (4), 0);
3670 if (flag_coarray == GFC_FCOARRAY_LIB)
3672 arg3 = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image,
3673 1, arg3);
3674 se.expr = fold_convert (gfc_get_int_type (4), arg3);
3677 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init, 3,
3678 arg1, arg2, arg3);
3679 gfc_add_expr_to_block (&block, tmp);
3681 return gfc_finish_block (&block);
3685 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3686 conversions. */
3688 static tree
3689 conv_intrinsic_system_clock (gfc_code *code)
3691 stmtblock_t block;
3692 gfc_se count_se, count_rate_se, count_max_se;
3693 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3694 tree tmp;
3695 int least;
3697 gfc_expr *count = code->ext.actual->expr;
3698 gfc_expr *count_rate = code->ext.actual->next->expr;
3699 gfc_expr *count_max = code->ext.actual->next->next->expr;
3701 /* Evaluate our arguments. */
3702 if (count)
3704 gfc_init_se (&count_se, NULL);
3705 gfc_conv_expr (&count_se, count);
3708 if (count_rate)
3710 gfc_init_se (&count_rate_se, NULL);
3711 gfc_conv_expr (&count_rate_se, count_rate);
3714 if (count_max)
3716 gfc_init_se (&count_max_se, NULL);
3717 gfc_conv_expr (&count_max_se, count_max);
3720 /* Find the smallest kind found of the arguments. */
3721 least = 16;
3722 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3723 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3724 : least;
3725 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3726 : least;
3728 /* Prepare temporary variables. */
3730 if (count)
3732 if (least >= 8)
3733 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3734 else if (least == 4)
3735 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3736 else if (count->ts.kind == 1)
3737 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3738 count->ts.kind);
3739 else
3740 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3741 count->ts.kind);
3744 if (count_rate)
3746 if (least >= 8)
3747 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3748 else if (least == 4)
3749 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3750 else
3751 arg2 = integer_zero_node;
3754 if (count_max)
3756 if (least >= 8)
3757 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3758 else if (least == 4)
3759 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3760 else
3761 arg3 = integer_zero_node;
3764 /* Make the function call. */
3765 gfc_init_block (&block);
3767 if (least <= 2)
3769 if (least == 1)
3771 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3772 : null_pointer_node;
3773 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3774 : null_pointer_node;
3775 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3776 : null_pointer_node;
3779 if (least == 2)
3781 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3782 : null_pointer_node;
3783 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3784 : null_pointer_node;
3785 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3786 : null_pointer_node;
3789 else
3791 if (least == 4)
3793 tmp = build_call_expr_loc (input_location,
3794 gfor_fndecl_system_clock4, 3,
3795 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3796 : null_pointer_node,
3797 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3798 : null_pointer_node,
3799 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3800 : null_pointer_node);
3801 gfc_add_expr_to_block (&block, tmp);
3803 /* Handle kind>=8, 10, or 16 arguments */
3804 if (least >= 8)
3806 tmp = build_call_expr_loc (input_location,
3807 gfor_fndecl_system_clock8, 3,
3808 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3809 : null_pointer_node,
3810 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3811 : null_pointer_node,
3812 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3813 : null_pointer_node);
3814 gfc_add_expr_to_block (&block, tmp);
3818 /* And store values back if needed. */
3819 if (arg1 && arg1 != count_se.expr)
3820 gfc_add_modify (&block, count_se.expr,
3821 fold_convert (TREE_TYPE (count_se.expr), arg1));
3822 if (arg2 && arg2 != count_rate_se.expr)
3823 gfc_add_modify (&block, count_rate_se.expr,
3824 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3825 if (arg3 && arg3 != count_max_se.expr)
3826 gfc_add_modify (&block, count_max_se.expr,
3827 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3829 return gfc_finish_block (&block);
3833 /* Return a character string containing the tty name. */
3835 static void
3836 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3838 tree var;
3839 tree len;
3840 tree tmp;
3841 tree cond;
3842 tree fndecl;
3843 tree *args;
3844 unsigned int num_args;
3846 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3847 args = XALLOCAVEC (tree, num_args);
3849 var = gfc_create_var (pchar_type_node, "pstr");
3850 len = gfc_create_var (gfc_charlen_type_node, "len");
3852 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3853 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3854 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3856 fndecl = build_addr (gfor_fndecl_ttynam);
3857 tmp = build_call_array_loc (input_location,
3858 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3859 fndecl, num_args, args);
3860 gfc_add_expr_to_block (&se->pre, tmp);
3862 /* Free the temporary afterwards, if necessary. */
3863 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3864 len, build_int_cst (TREE_TYPE (len), 0));
3865 tmp = gfc_call_free (var);
3866 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3867 gfc_add_expr_to_block (&se->post, tmp);
3869 se->expr = var;
3870 se->string_length = len;
3874 /* Get the minimum/maximum value of all the parameters.
3875 minmax (a1, a2, a3, ...)
3877 mvar = a1;
3878 mvar = COMP (mvar, a2)
3879 mvar = COMP (mvar, a3)
3881 return mvar;
3883 Where COMP is MIN/MAX_EXPR for integral types or when we don't
3884 care about NaNs, or IFN_FMIN/MAX when the target has support for
3885 fast NaN-honouring min/max. When neither holds expand a sequence
3886 of explicit comparisons. */
3888 /* TODO: Mismatching types can occur when specific names are used.
3889 These should be handled during resolution. */
3890 static void
3891 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3893 tree tmp;
3894 tree mvar;
3895 tree val;
3896 tree *args;
3897 tree type;
3898 gfc_actual_arglist *argexpr;
3899 unsigned int i, nargs;
3901 nargs = gfc_intrinsic_argument_list_length (expr);
3902 args = XALLOCAVEC (tree, nargs);
3904 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3905 type = gfc_typenode_for_spec (&expr->ts);
3907 argexpr = expr->value.function.actual;
3908 if (TREE_TYPE (args[0]) != type)
3909 args[0] = convert (type, args[0]);
3910 /* Only evaluate the argument once. */
3911 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3912 args[0] = gfc_evaluate_now (args[0], &se->pre);
3914 mvar = gfc_create_var (type, "M");
3915 gfc_add_modify (&se->pre, mvar, args[0]);
3917 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
3919 tree cond = NULL_TREE;
3920 val = args[i];
3922 /* Handle absent optional arguments by ignoring the comparison. */
3923 if (argexpr->expr->expr_type == EXPR_VARIABLE
3924 && argexpr->expr->symtree->n.sym->attr.optional
3925 && TREE_CODE (val) == INDIRECT_REF)
3927 cond = fold_build2_loc (input_location,
3928 NE_EXPR, logical_type_node,
3929 TREE_OPERAND (val, 0),
3930 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3932 else if (!VAR_P (val) && !TREE_CONSTANT (val))
3933 /* Only evaluate the argument once. */
3934 val = gfc_evaluate_now (val, &se->pre);
3936 tree calc;
3937 /* For floating point types, the question is what MAX(a, NaN) or
3938 MIN(a, NaN) should return (where "a" is a normal number).
3939 There are valid usecase for returning either one, but the
3940 Fortran standard doesn't specify which one should be chosen.
3941 Also, there is no consensus among other tested compilers. In
3942 short, it's a mess. So lets just do whatever is fastest. */
3943 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
3944 calc = fold_build2_loc (input_location, code, type,
3945 convert (type, val), mvar);
3946 tmp = build2_v (MODIFY_EXPR, mvar, calc);
3948 if (cond != NULL_TREE)
3949 tmp = build3_v (COND_EXPR, cond, tmp,
3950 build_empty_stmt (input_location));
3951 gfc_add_expr_to_block (&se->pre, tmp);
3953 se->expr = mvar;
3957 /* Generate library calls for MIN and MAX intrinsics for character
3958 variables. */
3959 static void
3960 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3962 tree *args;
3963 tree var, len, fndecl, tmp, cond, function;
3964 unsigned int nargs;
3966 nargs = gfc_intrinsic_argument_list_length (expr);
3967 args = XALLOCAVEC (tree, nargs + 4);
3968 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3970 /* Create the result variables. */
3971 len = gfc_create_var (gfc_charlen_type_node, "len");
3972 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3973 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3974 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3975 args[2] = build_int_cst (integer_type_node, op);
3976 args[3] = build_int_cst (integer_type_node, nargs / 2);
3978 if (expr->ts.kind == 1)
3979 function = gfor_fndecl_string_minmax;
3980 else if (expr->ts.kind == 4)
3981 function = gfor_fndecl_string_minmax_char4;
3982 else
3983 gcc_unreachable ();
3985 /* Make the function call. */
3986 fndecl = build_addr (function);
3987 tmp = build_call_array_loc (input_location,
3988 TREE_TYPE (TREE_TYPE (function)), fndecl,
3989 nargs + 4, args);
3990 gfc_add_expr_to_block (&se->pre, tmp);
3992 /* Free the temporary afterwards, if necessary. */
3993 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3994 len, build_int_cst (TREE_TYPE (len), 0));
3995 tmp = gfc_call_free (var);
3996 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3997 gfc_add_expr_to_block (&se->post, tmp);
3999 se->expr = var;
4000 se->string_length = len;
4004 /* Create a symbol node for this intrinsic. The symbol from the frontend
4005 has the generic name. */
4007 static gfc_symbol *
4008 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4010 gfc_symbol *sym;
4012 /* TODO: Add symbols for intrinsic function to the global namespace. */
4013 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4014 sym = gfc_new_symbol (expr->value.function.name, NULL);
4016 sym->ts = expr->ts;
4017 sym->attr.external = 1;
4018 sym->attr.function = 1;
4019 sym->attr.always_explicit = 1;
4020 sym->attr.proc = PROC_INTRINSIC;
4021 sym->attr.flavor = FL_PROCEDURE;
4022 sym->result = sym;
4023 if (expr->rank > 0)
4025 sym->attr.dimension = 1;
4026 sym->as = gfc_get_array_spec ();
4027 sym->as->type = AS_ASSUMED_SHAPE;
4028 sym->as->rank = expr->rank;
4031 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4032 ignore_optional ? expr->value.function.actual
4033 : NULL);
4035 return sym;
4038 /* Generate a call to an external intrinsic function. */
4039 static void
4040 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4042 gfc_symbol *sym;
4043 vec<tree, va_gc> *append_args;
4045 gcc_assert (!se->ss || se->ss->info->expr == expr);
4047 if (se->ss)
4048 gcc_assert (expr->rank > 0);
4049 else
4050 gcc_assert (expr->rank == 0);
4052 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4054 /* Calls to libgfortran_matmul need to be appended special arguments,
4055 to be able to call the BLAS ?gemm functions if required and possible. */
4056 append_args = NULL;
4057 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4058 && !expr->external_blas
4059 && sym->ts.type != BT_LOGICAL)
4061 tree cint = gfc_get_int_type (gfc_c_int_kind);
4063 if (flag_external_blas
4064 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4065 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4067 tree gemm_fndecl;
4069 if (sym->ts.type == BT_REAL)
4071 if (sym->ts.kind == 4)
4072 gemm_fndecl = gfor_fndecl_sgemm;
4073 else
4074 gemm_fndecl = gfor_fndecl_dgemm;
4076 else
4078 if (sym->ts.kind == 4)
4079 gemm_fndecl = gfor_fndecl_cgemm;
4080 else
4081 gemm_fndecl = gfor_fndecl_zgemm;
4084 vec_alloc (append_args, 3);
4085 append_args->quick_push (build_int_cst (cint, 1));
4086 append_args->quick_push (build_int_cst (cint,
4087 flag_blas_matmul_limit));
4088 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4089 gemm_fndecl));
4091 else
4093 vec_alloc (append_args, 3);
4094 append_args->quick_push (build_int_cst (cint, 0));
4095 append_args->quick_push (build_int_cst (cint, 0));
4096 append_args->quick_push (null_pointer_node);
4100 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4101 append_args);
4102 gfc_free_symbol (sym);
4105 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4106 Implemented as
4107 any(a)
4109 forall (i=...)
4110 if (a[i] != 0)
4111 return 1
4112 end forall
4113 return 0
4115 all(a)
4117 forall (i=...)
4118 if (a[i] == 0)
4119 return 0
4120 end forall
4121 return 1
4124 static void
4125 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4127 tree resvar;
4128 stmtblock_t block;
4129 stmtblock_t body;
4130 tree type;
4131 tree tmp;
4132 tree found;
4133 gfc_loopinfo loop;
4134 gfc_actual_arglist *actual;
4135 gfc_ss *arrayss;
4136 gfc_se arrayse;
4137 tree exit_label;
4139 if (se->ss)
4141 gfc_conv_intrinsic_funcall (se, expr);
4142 return;
4145 actual = expr->value.function.actual;
4146 type = gfc_typenode_for_spec (&expr->ts);
4147 /* Initialize the result. */
4148 resvar = gfc_create_var (type, "test");
4149 if (op == EQ_EXPR)
4150 tmp = convert (type, boolean_true_node);
4151 else
4152 tmp = convert (type, boolean_false_node);
4153 gfc_add_modify (&se->pre, resvar, tmp);
4155 /* Walk the arguments. */
4156 arrayss = gfc_walk_expr (actual->expr);
4157 gcc_assert (arrayss != gfc_ss_terminator);
4159 /* Initialize the scalarizer. */
4160 gfc_init_loopinfo (&loop);
4161 exit_label = gfc_build_label_decl (NULL_TREE);
4162 TREE_USED (exit_label) = 1;
4163 gfc_add_ss_to_loop (&loop, arrayss);
4165 /* Initialize the loop. */
4166 gfc_conv_ss_startstride (&loop);
4167 gfc_conv_loop_setup (&loop, &expr->where);
4169 gfc_mark_ss_chain_used (arrayss, 1);
4170 /* Generate the loop body. */
4171 gfc_start_scalarized_body (&loop, &body);
4173 /* If the condition matches then set the return value. */
4174 gfc_start_block (&block);
4175 if (op == EQ_EXPR)
4176 tmp = convert (type, boolean_false_node);
4177 else
4178 tmp = convert (type, boolean_true_node);
4179 gfc_add_modify (&block, resvar, tmp);
4181 /* And break out of the loop. */
4182 tmp = build1_v (GOTO_EXPR, exit_label);
4183 gfc_add_expr_to_block (&block, tmp);
4185 found = gfc_finish_block (&block);
4187 /* Check this element. */
4188 gfc_init_se (&arrayse, NULL);
4189 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4190 arrayse.ss = arrayss;
4191 gfc_conv_expr_val (&arrayse, actual->expr);
4193 gfc_add_block_to_block (&body, &arrayse.pre);
4194 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4195 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4196 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4197 gfc_add_expr_to_block (&body, tmp);
4198 gfc_add_block_to_block (&body, &arrayse.post);
4200 gfc_trans_scalarizing_loops (&loop, &body);
4202 /* Add the exit label. */
4203 tmp = build1_v (LABEL_EXPR, exit_label);
4204 gfc_add_expr_to_block (&loop.pre, tmp);
4206 gfc_add_block_to_block (&se->pre, &loop.pre);
4207 gfc_add_block_to_block (&se->pre, &loop.post);
4208 gfc_cleanup_loop (&loop);
4210 se->expr = resvar;
4213 /* COUNT(A) = Number of true elements in A. */
4214 static void
4215 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4217 tree resvar;
4218 tree type;
4219 stmtblock_t body;
4220 tree tmp;
4221 gfc_loopinfo loop;
4222 gfc_actual_arglist *actual;
4223 gfc_ss *arrayss;
4224 gfc_se arrayse;
4226 if (se->ss)
4228 gfc_conv_intrinsic_funcall (se, expr);
4229 return;
4232 actual = expr->value.function.actual;
4234 type = gfc_typenode_for_spec (&expr->ts);
4235 /* Initialize the result. */
4236 resvar = gfc_create_var (type, "count");
4237 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4239 /* Walk the arguments. */
4240 arrayss = gfc_walk_expr (actual->expr);
4241 gcc_assert (arrayss != gfc_ss_terminator);
4243 /* Initialize the scalarizer. */
4244 gfc_init_loopinfo (&loop);
4245 gfc_add_ss_to_loop (&loop, arrayss);
4247 /* Initialize the loop. */
4248 gfc_conv_ss_startstride (&loop);
4249 gfc_conv_loop_setup (&loop, &expr->where);
4251 gfc_mark_ss_chain_used (arrayss, 1);
4252 /* Generate the loop body. */
4253 gfc_start_scalarized_body (&loop, &body);
4255 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4256 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4257 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4259 gfc_init_se (&arrayse, NULL);
4260 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4261 arrayse.ss = arrayss;
4262 gfc_conv_expr_val (&arrayse, actual->expr);
4263 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4264 build_empty_stmt (input_location));
4266 gfc_add_block_to_block (&body, &arrayse.pre);
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 gfc_add_block_to_block (&se->pre, &loop.pre);
4273 gfc_add_block_to_block (&se->pre, &loop.post);
4274 gfc_cleanup_loop (&loop);
4276 se->expr = resvar;
4280 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4281 struct and return the corresponding loopinfo. */
4283 static gfc_loopinfo *
4284 enter_nested_loop (gfc_se *se)
4286 se->ss = se->ss->nested_ss;
4287 gcc_assert (se->ss == se->ss->loop->ss);
4289 return se->ss->loop;
4293 /* Inline implementation of the sum and product intrinsics. */
4294 static void
4295 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4296 bool norm2)
4298 tree resvar;
4299 tree scale = NULL_TREE;
4300 tree type;
4301 stmtblock_t body;
4302 stmtblock_t block;
4303 tree tmp;
4304 gfc_loopinfo loop, *ploop;
4305 gfc_actual_arglist *arg_array, *arg_mask;
4306 gfc_ss *arrayss = NULL;
4307 gfc_ss *maskss = NULL;
4308 gfc_se arrayse;
4309 gfc_se maskse;
4310 gfc_se *parent_se;
4311 gfc_expr *arrayexpr;
4312 gfc_expr *maskexpr;
4314 if (expr->rank > 0)
4316 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4317 parent_se = se;
4319 else
4320 parent_se = NULL;
4322 type = gfc_typenode_for_spec (&expr->ts);
4323 /* Initialize the result. */
4324 resvar = gfc_create_var (type, "val");
4325 if (norm2)
4327 /* result = 0.0;
4328 scale = 1.0. */
4329 scale = gfc_create_var (type, "scale");
4330 gfc_add_modify (&se->pre, scale,
4331 gfc_build_const (type, integer_one_node));
4332 tmp = gfc_build_const (type, integer_zero_node);
4334 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4335 tmp = gfc_build_const (type, integer_zero_node);
4336 else if (op == NE_EXPR)
4337 /* PARITY. */
4338 tmp = convert (type, boolean_false_node);
4339 else if (op == BIT_AND_EXPR)
4340 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4341 type, integer_one_node));
4342 else
4343 tmp = gfc_build_const (type, integer_one_node);
4345 gfc_add_modify (&se->pre, resvar, tmp);
4347 arg_array = expr->value.function.actual;
4349 arrayexpr = arg_array->expr;
4351 if (op == NE_EXPR || norm2)
4352 /* PARITY and NORM2. */
4353 maskexpr = NULL;
4354 else
4356 arg_mask = arg_array->next->next;
4357 gcc_assert (arg_mask != NULL);
4358 maskexpr = arg_mask->expr;
4361 if (expr->rank == 0)
4363 /* Walk the arguments. */
4364 arrayss = gfc_walk_expr (arrayexpr);
4365 gcc_assert (arrayss != gfc_ss_terminator);
4367 if (maskexpr && maskexpr->rank > 0)
4369 maskss = gfc_walk_expr (maskexpr);
4370 gcc_assert (maskss != gfc_ss_terminator);
4372 else
4373 maskss = NULL;
4375 /* Initialize the scalarizer. */
4376 gfc_init_loopinfo (&loop);
4377 gfc_add_ss_to_loop (&loop, arrayss);
4378 if (maskexpr && maskexpr->rank > 0)
4379 gfc_add_ss_to_loop (&loop, maskss);
4381 /* Initialize the loop. */
4382 gfc_conv_ss_startstride (&loop);
4383 gfc_conv_loop_setup (&loop, &expr->where);
4385 gfc_mark_ss_chain_used (arrayss, 1);
4386 if (maskexpr && maskexpr->rank > 0)
4387 gfc_mark_ss_chain_used (maskss, 1);
4389 ploop = &loop;
4391 else
4392 /* All the work has been done in the parent loops. */
4393 ploop = enter_nested_loop (se);
4395 gcc_assert (ploop);
4397 /* Generate the loop body. */
4398 gfc_start_scalarized_body (ploop, &body);
4400 /* If we have a mask, only add this element if the mask is set. */
4401 if (maskexpr && maskexpr->rank > 0)
4403 gfc_init_se (&maskse, parent_se);
4404 gfc_copy_loopinfo_to_se (&maskse, ploop);
4405 if (expr->rank == 0)
4406 maskse.ss = maskss;
4407 gfc_conv_expr_val (&maskse, maskexpr);
4408 gfc_add_block_to_block (&body, &maskse.pre);
4410 gfc_start_block (&block);
4412 else
4413 gfc_init_block (&block);
4415 /* Do the actual summation/product. */
4416 gfc_init_se (&arrayse, parent_se);
4417 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4418 if (expr->rank == 0)
4419 arrayse.ss = arrayss;
4420 gfc_conv_expr_val (&arrayse, arrayexpr);
4421 gfc_add_block_to_block (&block, &arrayse.pre);
4423 if (norm2)
4425 /* if (x (i) != 0.0)
4427 absX = abs(x(i))
4428 if (absX > scale)
4430 val = scale/absX;
4431 result = 1.0 + result * val * val;
4432 scale = absX;
4434 else
4436 val = absX/scale;
4437 result += val * val;
4439 } */
4440 tree res1, res2, cond, absX, val;
4441 stmtblock_t ifblock1, ifblock2, ifblock3;
4443 gfc_init_block (&ifblock1);
4445 absX = gfc_create_var (type, "absX");
4446 gfc_add_modify (&ifblock1, absX,
4447 fold_build1_loc (input_location, ABS_EXPR, type,
4448 arrayse.expr));
4449 val = gfc_create_var (type, "val");
4450 gfc_add_expr_to_block (&ifblock1, val);
4452 gfc_init_block (&ifblock2);
4453 gfc_add_modify (&ifblock2, val,
4454 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4455 absX));
4456 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4457 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4458 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4459 gfc_build_const (type, integer_one_node));
4460 gfc_add_modify (&ifblock2, resvar, res1);
4461 gfc_add_modify (&ifblock2, scale, absX);
4462 res1 = gfc_finish_block (&ifblock2);
4464 gfc_init_block (&ifblock3);
4465 gfc_add_modify (&ifblock3, val,
4466 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4467 scale));
4468 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4469 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4470 gfc_add_modify (&ifblock3, resvar, res2);
4471 res2 = gfc_finish_block (&ifblock3);
4473 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4474 absX, scale);
4475 tmp = build3_v (COND_EXPR, cond, res1, res2);
4476 gfc_add_expr_to_block (&ifblock1, tmp);
4477 tmp = gfc_finish_block (&ifblock1);
4479 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4480 arrayse.expr,
4481 gfc_build_const (type, integer_zero_node));
4483 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4484 gfc_add_expr_to_block (&block, tmp);
4486 else
4488 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4489 gfc_add_modify (&block, resvar, tmp);
4492 gfc_add_block_to_block (&block, &arrayse.post);
4494 if (maskexpr && maskexpr->rank > 0)
4496 /* We enclose the above in if (mask) {...} . */
4498 tmp = gfc_finish_block (&block);
4499 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4500 build_empty_stmt (input_location));
4502 else
4503 tmp = gfc_finish_block (&block);
4504 gfc_add_expr_to_block (&body, tmp);
4506 gfc_trans_scalarizing_loops (ploop, &body);
4508 /* For a scalar mask, enclose the loop in an if statement. */
4509 if (maskexpr && maskexpr->rank == 0)
4511 gfc_init_block (&block);
4512 gfc_add_block_to_block (&block, &ploop->pre);
4513 gfc_add_block_to_block (&block, &ploop->post);
4514 tmp = gfc_finish_block (&block);
4516 if (expr->rank > 0)
4518 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4519 build_empty_stmt (input_location));
4520 gfc_advance_se_ss_chain (se);
4522 else
4524 gcc_assert (expr->rank == 0);
4525 gfc_init_se (&maskse, NULL);
4526 gfc_conv_expr_val (&maskse, maskexpr);
4527 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4528 build_empty_stmt (input_location));
4531 gfc_add_expr_to_block (&block, tmp);
4532 gfc_add_block_to_block (&se->pre, &block);
4533 gcc_assert (se->post.head == NULL);
4535 else
4537 gfc_add_block_to_block (&se->pre, &ploop->pre);
4538 gfc_add_block_to_block (&se->pre, &ploop->post);
4541 if (expr->rank == 0)
4542 gfc_cleanup_loop (ploop);
4544 if (norm2)
4546 /* result = scale * sqrt(result). */
4547 tree sqrt;
4548 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4549 resvar = build_call_expr_loc (input_location,
4550 sqrt, 1, resvar);
4551 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4554 se->expr = resvar;
4558 /* Inline implementation of the dot_product intrinsic. This function
4559 is based on gfc_conv_intrinsic_arith (the previous function). */
4560 static void
4561 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4563 tree resvar;
4564 tree type;
4565 stmtblock_t body;
4566 stmtblock_t block;
4567 tree tmp;
4568 gfc_loopinfo loop;
4569 gfc_actual_arglist *actual;
4570 gfc_ss *arrayss1, *arrayss2;
4571 gfc_se arrayse1, arrayse2;
4572 gfc_expr *arrayexpr1, *arrayexpr2;
4574 type = gfc_typenode_for_spec (&expr->ts);
4576 /* Initialize the result. */
4577 resvar = gfc_create_var (type, "val");
4578 if (expr->ts.type == BT_LOGICAL)
4579 tmp = build_int_cst (type, 0);
4580 else
4581 tmp = gfc_build_const (type, integer_zero_node);
4583 gfc_add_modify (&se->pre, resvar, tmp);
4585 /* Walk argument #1. */
4586 actual = expr->value.function.actual;
4587 arrayexpr1 = actual->expr;
4588 arrayss1 = gfc_walk_expr (arrayexpr1);
4589 gcc_assert (arrayss1 != gfc_ss_terminator);
4591 /* Walk argument #2. */
4592 actual = actual->next;
4593 arrayexpr2 = actual->expr;
4594 arrayss2 = gfc_walk_expr (arrayexpr2);
4595 gcc_assert (arrayss2 != gfc_ss_terminator);
4597 /* Initialize the scalarizer. */
4598 gfc_init_loopinfo (&loop);
4599 gfc_add_ss_to_loop (&loop, arrayss1);
4600 gfc_add_ss_to_loop (&loop, arrayss2);
4602 /* Initialize the loop. */
4603 gfc_conv_ss_startstride (&loop);
4604 gfc_conv_loop_setup (&loop, &expr->where);
4606 gfc_mark_ss_chain_used (arrayss1, 1);
4607 gfc_mark_ss_chain_used (arrayss2, 1);
4609 /* Generate the loop body. */
4610 gfc_start_scalarized_body (&loop, &body);
4611 gfc_init_block (&block);
4613 /* Make the tree expression for [conjg(]array1[)]. */
4614 gfc_init_se (&arrayse1, NULL);
4615 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4616 arrayse1.ss = arrayss1;
4617 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4618 if (expr->ts.type == BT_COMPLEX)
4619 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4620 arrayse1.expr);
4621 gfc_add_block_to_block (&block, &arrayse1.pre);
4623 /* Make the tree expression for array2. */
4624 gfc_init_se (&arrayse2, NULL);
4625 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4626 arrayse2.ss = arrayss2;
4627 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4628 gfc_add_block_to_block (&block, &arrayse2.pre);
4630 /* Do the actual product and sum. */
4631 if (expr->ts.type == BT_LOGICAL)
4633 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4634 arrayse1.expr, arrayse2.expr);
4635 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4637 else
4639 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4640 arrayse2.expr);
4641 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4643 gfc_add_modify (&block, resvar, tmp);
4645 /* Finish up the loop block and the loop. */
4646 tmp = gfc_finish_block (&block);
4647 gfc_add_expr_to_block (&body, tmp);
4649 gfc_trans_scalarizing_loops (&loop, &body);
4650 gfc_add_block_to_block (&se->pre, &loop.pre);
4651 gfc_add_block_to_block (&se->pre, &loop.post);
4652 gfc_cleanup_loop (&loop);
4654 se->expr = resvar;
4658 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4659 we need to handle. For performance reasons we sometimes create two
4660 loops instead of one, where the second one is much simpler.
4661 Examples for minloc intrinsic:
4662 1) Result is an array, a call is generated
4663 2) Array mask is used and NaNs need to be supported:
4664 limit = Infinity;
4665 pos = 0;
4666 S = from;
4667 while (S <= to) {
4668 if (mask[S]) {
4669 if (pos == 0) pos = S + (1 - from);
4670 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4672 S++;
4674 goto lab2;
4675 lab1:;
4676 while (S <= to) {
4677 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4678 S++;
4680 lab2:;
4681 3) NaNs need to be supported, but it is known at compile time or cheaply
4682 at runtime whether array is nonempty or not:
4683 limit = Infinity;
4684 pos = 0;
4685 S = from;
4686 while (S <= to) {
4687 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4688 S++;
4690 if (from <= to) pos = 1;
4691 goto lab2;
4692 lab1:;
4693 while (S <= to) {
4694 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4695 S++;
4697 lab2:;
4698 4) NaNs aren't supported, array mask is used:
4699 limit = infinities_supported ? Infinity : huge (limit);
4700 pos = 0;
4701 S = from;
4702 while (S <= to) {
4703 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4704 S++;
4706 goto lab2;
4707 lab1:;
4708 while (S <= to) {
4709 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4710 S++;
4712 lab2:;
4713 5) Same without array mask:
4714 limit = infinities_supported ? Infinity : huge (limit);
4715 pos = (from <= to) ? 1 : 0;
4716 S = from;
4717 while (S <= to) {
4718 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4719 S++;
4721 For 3) and 5), if mask is scalar, this all goes into a conditional,
4722 setting pos = 0; in the else branch.
4724 Since we now also support the BACK argument, instead of using
4725 if (a[S] < limit), we now use
4727 if (back)
4728 cond = a[S] <= limit;
4729 else
4730 cond = a[S] < limit;
4731 if (cond) {
4732 ....
4734 The optimizer is smart enough to move the condition out of the loop.
4735 The are now marked as unlikely to for further speedup. */
4737 static void
4738 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4740 stmtblock_t body;
4741 stmtblock_t block;
4742 stmtblock_t ifblock;
4743 stmtblock_t elseblock;
4744 tree limit;
4745 tree type;
4746 tree tmp;
4747 tree cond;
4748 tree elsetmp;
4749 tree ifbody;
4750 tree offset;
4751 tree nonempty;
4752 tree lab1, lab2;
4753 tree b_if, b_else;
4754 gfc_loopinfo loop;
4755 gfc_actual_arglist *actual;
4756 gfc_ss *arrayss;
4757 gfc_ss *maskss;
4758 gfc_se arrayse;
4759 gfc_se maskse;
4760 gfc_expr *arrayexpr;
4761 gfc_expr *maskexpr;
4762 gfc_expr *backexpr;
4763 gfc_se backse;
4764 tree pos;
4765 int n;
4767 actual = expr->value.function.actual;
4769 /* The last argument, BACK, is passed by value. Ensure that
4770 by setting its name to %VAL. */
4771 for (gfc_actual_arglist *a = actual; a; a = a->next)
4773 if (a->next == NULL)
4774 a->name = "%VAL";
4777 if (se->ss)
4779 gfc_conv_intrinsic_funcall (se, expr);
4780 return;
4783 arrayexpr = actual->expr;
4785 /* Special case for character maxloc. Remove unneeded actual
4786 arguments, then call a library function. */
4788 if (arrayexpr->ts.type == BT_CHARACTER)
4790 gfc_actual_arglist *a, *b;
4791 a = actual;
4792 while (a->next)
4794 b = a->next;
4795 if (b->expr == NULL || strcmp (b->name, "dim") == 0)
4797 a->next = b->next;
4798 b->next = NULL;
4799 gfc_free_actual_arglist (b);
4801 else
4802 a = b;
4804 gfc_conv_intrinsic_funcall (se, expr);
4805 return;
4808 /* Initialize the result. */
4809 pos = gfc_create_var (gfc_array_index_type, "pos");
4810 offset = gfc_create_var (gfc_array_index_type, "offset");
4811 type = gfc_typenode_for_spec (&expr->ts);
4813 /* Walk the arguments. */
4814 arrayss = gfc_walk_expr (arrayexpr);
4815 gcc_assert (arrayss != gfc_ss_terminator);
4817 actual = actual->next->next;
4818 gcc_assert (actual);
4819 maskexpr = actual->expr;
4820 backexpr = actual->next->next->expr;
4821 nonempty = NULL;
4822 if (maskexpr && maskexpr->rank != 0)
4824 maskss = gfc_walk_expr (maskexpr);
4825 gcc_assert (maskss != gfc_ss_terminator);
4827 else
4829 mpz_t asize;
4830 if (gfc_array_size (arrayexpr, &asize))
4832 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4833 mpz_clear (asize);
4834 nonempty = fold_build2_loc (input_location, GT_EXPR,
4835 logical_type_node, nonempty,
4836 gfc_index_zero_node);
4838 maskss = NULL;
4841 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4842 switch (arrayexpr->ts.type)
4844 case BT_REAL:
4845 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4846 break;
4848 case BT_INTEGER:
4849 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4850 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4851 arrayexpr->ts.kind);
4852 break;
4854 default:
4855 gcc_unreachable ();
4858 /* We start with the most negative possible value for MAXLOC, and the most
4859 positive possible value for MINLOC. The most negative possible value is
4860 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4861 possible value is HUGE in both cases. */
4862 if (op == GT_EXPR)
4863 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4864 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4865 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4866 build_int_cst (TREE_TYPE (tmp), 1));
4868 gfc_add_modify (&se->pre, limit, tmp);
4870 /* Initialize the scalarizer. */
4871 gfc_init_loopinfo (&loop);
4872 gfc_add_ss_to_loop (&loop, arrayss);
4873 if (maskss)
4874 gfc_add_ss_to_loop (&loop, maskss);
4876 /* Initialize the loop. */
4877 gfc_conv_ss_startstride (&loop);
4879 /* The code generated can have more than one loop in sequence (see the
4880 comment at the function header). This doesn't work well with the
4881 scalarizer, which changes arrays' offset when the scalarization loops
4882 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4883 are currently inlined in the scalar case only (for which loop is of rank
4884 one). As there is no dependency to care about in that case, there is no
4885 temporary, so that we can use the scalarizer temporary code to handle
4886 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4887 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4888 to restore offset.
4889 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4890 should eventually go away. We could either create two loops properly,
4891 or find another way to save/restore the array offsets between the two
4892 loops (without conflicting with temporary management), or use a single
4893 loop minmaxloc implementation. See PR 31067. */
4894 loop.temp_dim = loop.dimen;
4895 gfc_conv_loop_setup (&loop, &expr->where);
4897 gcc_assert (loop.dimen == 1);
4898 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4899 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4900 loop.from[0], loop.to[0]);
4902 lab1 = NULL;
4903 lab2 = NULL;
4904 /* Initialize the position to zero, following Fortran 2003. We are free
4905 to do this because Fortran 95 allows the result of an entirely false
4906 mask to be processor dependent. If we know at compile time the array
4907 is non-empty and no MASK is used, we can initialize to 1 to simplify
4908 the inner loop. */
4909 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4910 gfc_add_modify (&loop.pre, pos,
4911 fold_build3_loc (input_location, COND_EXPR,
4912 gfc_array_index_type,
4913 nonempty, gfc_index_one_node,
4914 gfc_index_zero_node));
4915 else
4917 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4918 lab1 = gfc_build_label_decl (NULL_TREE);
4919 TREE_USED (lab1) = 1;
4920 lab2 = gfc_build_label_decl (NULL_TREE);
4921 TREE_USED (lab2) = 1;
4924 /* An offset must be added to the loop
4925 counter to obtain the required position. */
4926 gcc_assert (loop.from[0]);
4928 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4929 gfc_index_one_node, loop.from[0]);
4930 gfc_add_modify (&loop.pre, offset, tmp);
4932 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4933 if (maskss)
4934 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4935 /* Generate the loop body. */
4936 gfc_start_scalarized_body (&loop, &body);
4938 /* If we have a mask, only check this element if the mask is set. */
4939 if (maskss)
4941 gfc_init_se (&maskse, NULL);
4942 gfc_copy_loopinfo_to_se (&maskse, &loop);
4943 maskse.ss = maskss;
4944 gfc_conv_expr_val (&maskse, maskexpr);
4945 gfc_add_block_to_block (&body, &maskse.pre);
4947 gfc_start_block (&block);
4949 else
4950 gfc_init_block (&block);
4952 /* Compare with the current limit. */
4953 gfc_init_se (&arrayse, NULL);
4954 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4955 arrayse.ss = arrayss;
4956 gfc_conv_expr_val (&arrayse, arrayexpr);
4957 gfc_add_block_to_block (&block, &arrayse.pre);
4959 gfc_init_se (&backse, NULL);
4960 gfc_conv_expr_val (&backse, backexpr);
4961 gfc_add_block_to_block (&block, &backse.pre);
4963 /* We do the following if this is a more extreme value. */
4964 gfc_start_block (&ifblock);
4966 /* Assign the value to the limit... */
4967 gfc_add_modify (&ifblock, limit, arrayse.expr);
4969 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4971 stmtblock_t ifblock2;
4972 tree ifbody2;
4974 gfc_start_block (&ifblock2);
4975 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4976 loop.loopvar[0], offset);
4977 gfc_add_modify (&ifblock2, pos, tmp);
4978 ifbody2 = gfc_finish_block (&ifblock2);
4979 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
4980 gfc_index_zero_node);
4981 tmp = build3_v (COND_EXPR, cond, ifbody2,
4982 build_empty_stmt (input_location));
4983 gfc_add_expr_to_block (&block, tmp);
4986 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4987 loop.loopvar[0], offset);
4988 gfc_add_modify (&ifblock, pos, tmp);
4990 if (lab1)
4991 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
4993 ifbody = gfc_finish_block (&ifblock);
4995 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
4997 if (lab1)
4998 cond = fold_build2_loc (input_location,
4999 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5000 logical_type_node, arrayse.expr, limit);
5001 else
5003 tree ifbody2, elsebody2;
5005 /* We switch to > or >= depending on the value of the BACK argument. */
5006 cond = gfc_create_var (logical_type_node, "cond");
5008 gfc_start_block (&ifblock);
5009 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5010 logical_type_node, arrayse.expr, limit);
5012 gfc_add_modify (&ifblock, cond, b_if);
5013 ifbody2 = gfc_finish_block (&ifblock);
5015 gfc_start_block (&elseblock);
5016 b_else = fold_build2_loc (input_location, op, logical_type_node,
5017 arrayse.expr, limit);
5019 gfc_add_modify (&elseblock, cond, b_else);
5020 elsebody2 = gfc_finish_block (&elseblock);
5022 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5023 backse.expr, ifbody2, elsebody2);
5025 gfc_add_expr_to_block (&block, tmp);
5028 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5029 ifbody = build3_v (COND_EXPR, cond, ifbody,
5030 build_empty_stmt (input_location));
5032 gfc_add_expr_to_block (&block, ifbody);
5034 if (maskss)
5036 /* We enclose the above in if (mask) {...}. */
5037 tmp = gfc_finish_block (&block);
5039 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5040 build_empty_stmt (input_location));
5042 else
5043 tmp = gfc_finish_block (&block);
5044 gfc_add_expr_to_block (&body, tmp);
5046 if (lab1)
5048 gfc_trans_scalarized_loop_boundary (&loop, &body);
5050 if (HONOR_NANS (DECL_MODE (limit)))
5052 if (nonempty != NULL)
5054 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
5055 tmp = build3_v (COND_EXPR, nonempty, ifbody,
5056 build_empty_stmt (input_location));
5057 gfc_add_expr_to_block (&loop.code[0], tmp);
5061 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
5062 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
5064 /* If we have a mask, only check this element if the mask is set. */
5065 if (maskss)
5067 gfc_init_se (&maskse, NULL);
5068 gfc_copy_loopinfo_to_se (&maskse, &loop);
5069 maskse.ss = maskss;
5070 gfc_conv_expr_val (&maskse, maskexpr);
5071 gfc_add_block_to_block (&body, &maskse.pre);
5073 gfc_start_block (&block);
5075 else
5076 gfc_init_block (&block);
5078 /* Compare with the current limit. */
5079 gfc_init_se (&arrayse, NULL);
5080 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5081 arrayse.ss = arrayss;
5082 gfc_conv_expr_val (&arrayse, arrayexpr);
5083 gfc_add_block_to_block (&block, &arrayse.pre);
5085 /* We do the following if this is a more extreme value. */
5086 gfc_start_block (&ifblock);
5088 /* Assign the value to the limit... */
5089 gfc_add_modify (&ifblock, limit, arrayse.expr);
5091 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5092 loop.loopvar[0], offset);
5093 gfc_add_modify (&ifblock, pos, tmp);
5095 ifbody = gfc_finish_block (&ifblock);
5097 /* We switch to > or >= depending on the value of the BACK argument. */
5099 tree ifbody2, elsebody2;
5101 cond = gfc_create_var (logical_type_node, "cond");
5103 gfc_start_block (&ifblock);
5104 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5105 logical_type_node, arrayse.expr, limit);
5107 gfc_add_modify (&ifblock, cond, b_if);
5108 ifbody2 = gfc_finish_block (&ifblock);
5110 gfc_start_block (&elseblock);
5111 b_else = fold_build2_loc (input_location, op, logical_type_node,
5112 arrayse.expr, limit);
5114 gfc_add_modify (&elseblock, cond, b_else);
5115 elsebody2 = gfc_finish_block (&elseblock);
5117 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5118 backse.expr, ifbody2, elsebody2);
5121 gfc_add_expr_to_block (&block, tmp);
5122 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5123 tmp = build3_v (COND_EXPR, cond, ifbody,
5124 build_empty_stmt (input_location));
5126 gfc_add_expr_to_block (&block, tmp);
5128 if (maskss)
5130 /* We enclose the above in if (mask) {...}. */
5131 tmp = gfc_finish_block (&block);
5133 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5134 build_empty_stmt (input_location));
5136 else
5137 tmp = gfc_finish_block (&block);
5138 gfc_add_expr_to_block (&body, tmp);
5139 /* Avoid initializing loopvar[0] again, it should be left where
5140 it finished by the first loop. */
5141 loop.from[0] = loop.loopvar[0];
5144 gfc_trans_scalarizing_loops (&loop, &body);
5146 if (lab2)
5147 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5149 /* For a scalar mask, enclose the loop in an if statement. */
5150 if (maskexpr && maskss == NULL)
5152 gfc_init_se (&maskse, NULL);
5153 gfc_conv_expr_val (&maskse, maskexpr);
5154 gfc_init_block (&block);
5155 gfc_add_block_to_block (&block, &loop.pre);
5156 gfc_add_block_to_block (&block, &loop.post);
5157 tmp = gfc_finish_block (&block);
5159 /* For the else part of the scalar mask, just initialize
5160 the pos variable the same way as above. */
5162 gfc_init_block (&elseblock);
5163 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
5164 elsetmp = gfc_finish_block (&elseblock);
5166 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
5167 gfc_add_expr_to_block (&block, tmp);
5168 gfc_add_block_to_block (&se->pre, &block);
5170 else
5172 gfc_add_block_to_block (&se->pre, &loop.pre);
5173 gfc_add_block_to_block (&se->pre, &loop.post);
5175 gfc_cleanup_loop (&loop);
5177 se->expr = convert (type, pos);
5180 /* Emit code for minval or maxval intrinsic. There are many different cases
5181 we need to handle. For performance reasons we sometimes create two
5182 loops instead of one, where the second one is much simpler.
5183 Examples for minval intrinsic:
5184 1) Result is an array, a call is generated
5185 2) Array mask is used and NaNs need to be supported, rank 1:
5186 limit = Infinity;
5187 nonempty = false;
5188 S = from;
5189 while (S <= to) {
5190 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5191 S++;
5193 limit = nonempty ? NaN : huge (limit);
5194 lab:
5195 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5196 3) NaNs need to be supported, but it is known at compile time or cheaply
5197 at runtime whether array is nonempty or not, rank 1:
5198 limit = Infinity;
5199 S = from;
5200 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5201 limit = (from <= to) ? NaN : huge (limit);
5202 lab:
5203 while (S <= to) { limit = min (a[S], limit); S++; }
5204 4) Array mask is used and NaNs need to be supported, rank > 1:
5205 limit = Infinity;
5206 nonempty = false;
5207 fast = false;
5208 S1 = from1;
5209 while (S1 <= to1) {
5210 S2 = from2;
5211 while (S2 <= to2) {
5212 if (mask[S1][S2]) {
5213 if (fast) limit = min (a[S1][S2], limit);
5214 else {
5215 nonempty = true;
5216 if (a[S1][S2] <= limit) {
5217 limit = a[S1][S2];
5218 fast = true;
5222 S2++;
5224 S1++;
5226 if (!fast)
5227 limit = nonempty ? NaN : huge (limit);
5228 5) NaNs need to be supported, but it is known at compile time or cheaply
5229 at runtime whether array is nonempty or not, rank > 1:
5230 limit = Infinity;
5231 fast = false;
5232 S1 = from1;
5233 while (S1 <= to1) {
5234 S2 = from2;
5235 while (S2 <= to2) {
5236 if (fast) limit = min (a[S1][S2], limit);
5237 else {
5238 if (a[S1][S2] <= limit) {
5239 limit = a[S1][S2];
5240 fast = true;
5243 S2++;
5245 S1++;
5247 if (!fast)
5248 limit = (nonempty_array) ? NaN : huge (limit);
5249 6) NaNs aren't supported, but infinities are. Array mask is used:
5250 limit = Infinity;
5251 nonempty = false;
5252 S = from;
5253 while (S <= to) {
5254 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5255 S++;
5257 limit = nonempty ? limit : huge (limit);
5258 7) Same without array mask:
5259 limit = Infinity;
5260 S = from;
5261 while (S <= to) { limit = min (a[S], limit); S++; }
5262 limit = (from <= to) ? limit : huge (limit);
5263 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5264 limit = huge (limit);
5265 S = from;
5266 while (S <= to) { limit = min (a[S], limit); S++); }
5268 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5269 with array mask instead).
5270 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5271 setting limit = huge (limit); in the else branch. */
5273 static void
5274 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
5276 tree limit;
5277 tree type;
5278 tree tmp;
5279 tree ifbody;
5280 tree nonempty;
5281 tree nonempty_var;
5282 tree lab;
5283 tree fast;
5284 tree huge_cst = NULL, nan_cst = NULL;
5285 stmtblock_t body;
5286 stmtblock_t block, block2;
5287 gfc_loopinfo loop;
5288 gfc_actual_arglist *actual;
5289 gfc_ss *arrayss;
5290 gfc_ss *maskss;
5291 gfc_se arrayse;
5292 gfc_se maskse;
5293 gfc_expr *arrayexpr;
5294 gfc_expr *maskexpr;
5295 int n;
5297 if (se->ss)
5299 gfc_conv_intrinsic_funcall (se, expr);
5300 return;
5303 actual = expr->value.function.actual;
5304 arrayexpr = actual->expr;
5306 if (arrayexpr->ts.type == BT_CHARACTER)
5308 gfc_actual_arglist *a2, *a3;
5309 a2 = actual->next; /* dim */
5310 a3 = a2->next; /* mask */
5311 if (a2->expr == NULL || expr->rank == 0)
5313 if (a3->expr == NULL)
5314 actual->next = NULL;
5315 else
5317 actual->next = a3;
5318 a2->next = NULL;
5320 gfc_free_actual_arglist (a2);
5322 else
5323 if (a3->expr == NULL)
5325 a2->next = NULL;
5326 gfc_free_actual_arglist (a3);
5328 gfc_conv_intrinsic_funcall (se, expr);
5329 return;
5331 type = gfc_typenode_for_spec (&expr->ts);
5332 /* Initialize the result. */
5333 limit = gfc_create_var (type, "limit");
5334 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5335 switch (expr->ts.type)
5337 case BT_REAL:
5338 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5339 expr->ts.kind, 0);
5340 if (HONOR_INFINITIES (DECL_MODE (limit)))
5342 REAL_VALUE_TYPE real;
5343 real_inf (&real);
5344 tmp = build_real (type, real);
5346 else
5347 tmp = huge_cst;
5348 if (HONOR_NANS (DECL_MODE (limit)))
5349 nan_cst = gfc_build_nan (type, "");
5350 break;
5352 case BT_INTEGER:
5353 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5354 break;
5356 default:
5357 gcc_unreachable ();
5360 /* We start with the most negative possible value for MAXVAL, and the most
5361 positive possible value for MINVAL. The most negative possible value is
5362 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5363 possible value is HUGE in both cases. */
5364 if (op == GT_EXPR)
5366 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5367 if (huge_cst)
5368 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5369 TREE_TYPE (huge_cst), huge_cst);
5372 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5373 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5374 tmp, build_int_cst (type, 1));
5376 gfc_add_modify (&se->pre, limit, tmp);
5378 /* Walk the arguments. */
5379 arrayss = gfc_walk_expr (arrayexpr);
5380 gcc_assert (arrayss != gfc_ss_terminator);
5382 actual = actual->next->next;
5383 gcc_assert (actual);
5384 maskexpr = actual->expr;
5385 nonempty = NULL;
5386 if (maskexpr && maskexpr->rank != 0)
5388 maskss = gfc_walk_expr (maskexpr);
5389 gcc_assert (maskss != gfc_ss_terminator);
5391 else
5393 mpz_t asize;
5394 if (gfc_array_size (arrayexpr, &asize))
5396 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5397 mpz_clear (asize);
5398 nonempty = fold_build2_loc (input_location, GT_EXPR,
5399 logical_type_node, nonempty,
5400 gfc_index_zero_node);
5402 maskss = NULL;
5405 /* Initialize the scalarizer. */
5406 gfc_init_loopinfo (&loop);
5407 gfc_add_ss_to_loop (&loop, arrayss);
5408 if (maskss)
5409 gfc_add_ss_to_loop (&loop, maskss);
5411 /* Initialize the loop. */
5412 gfc_conv_ss_startstride (&loop);
5414 /* The code generated can have more than one loop in sequence (see the
5415 comment at the function header). This doesn't work well with the
5416 scalarizer, which changes arrays' offset when the scalarization loops
5417 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5418 are currently inlined in the scalar case only. As there is no dependency
5419 to care about in that case, there is no temporary, so that we can use the
5420 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5421 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5422 gfc_trans_scalarized_loop_boundary even later to restore offset.
5423 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5424 should eventually go away. We could either create two loops properly,
5425 or find another way to save/restore the array offsets between the two
5426 loops (without conflicting with temporary management), or use a single
5427 loop minmaxval implementation. See PR 31067. */
5428 loop.temp_dim = loop.dimen;
5429 gfc_conv_loop_setup (&loop, &expr->where);
5431 if (nonempty == NULL && maskss == NULL
5432 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5433 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5434 loop.from[0], loop.to[0]);
5435 nonempty_var = NULL;
5436 if (nonempty == NULL
5437 && (HONOR_INFINITIES (DECL_MODE (limit))
5438 || HONOR_NANS (DECL_MODE (limit))))
5440 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5441 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5442 nonempty = nonempty_var;
5444 lab = NULL;
5445 fast = NULL;
5446 if (HONOR_NANS (DECL_MODE (limit)))
5448 if (loop.dimen == 1)
5450 lab = gfc_build_label_decl (NULL_TREE);
5451 TREE_USED (lab) = 1;
5453 else
5455 fast = gfc_create_var (logical_type_node, "fast");
5456 gfc_add_modify (&se->pre, fast, logical_false_node);
5460 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5461 if (maskss)
5462 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5463 /* Generate the loop body. */
5464 gfc_start_scalarized_body (&loop, &body);
5466 /* If we have a mask, only add this element if the mask is set. */
5467 if (maskss)
5469 gfc_init_se (&maskse, NULL);
5470 gfc_copy_loopinfo_to_se (&maskse, &loop);
5471 maskse.ss = maskss;
5472 gfc_conv_expr_val (&maskse, maskexpr);
5473 gfc_add_block_to_block (&body, &maskse.pre);
5475 gfc_start_block (&block);
5477 else
5478 gfc_init_block (&block);
5480 /* Compare with the current limit. */
5481 gfc_init_se (&arrayse, NULL);
5482 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5483 arrayse.ss = arrayss;
5484 gfc_conv_expr_val (&arrayse, arrayexpr);
5485 gfc_add_block_to_block (&block, &arrayse.pre);
5487 gfc_init_block (&block2);
5489 if (nonempty_var)
5490 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5492 if (HONOR_NANS (DECL_MODE (limit)))
5494 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5495 logical_type_node, arrayse.expr, limit);
5496 if (lab)
5497 ifbody = build1_v (GOTO_EXPR, lab);
5498 else
5500 stmtblock_t ifblock;
5502 gfc_init_block (&ifblock);
5503 gfc_add_modify (&ifblock, limit, arrayse.expr);
5504 gfc_add_modify (&ifblock, fast, logical_true_node);
5505 ifbody = gfc_finish_block (&ifblock);
5507 tmp = build3_v (COND_EXPR, tmp, ifbody,
5508 build_empty_stmt (input_location));
5509 gfc_add_expr_to_block (&block2, tmp);
5511 else
5513 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5514 signed zeros. */
5515 tmp = fold_build2_loc (input_location,
5516 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5517 type, arrayse.expr, limit);
5518 gfc_add_modify (&block2, limit, tmp);
5521 if (fast)
5523 tree elsebody = gfc_finish_block (&block2);
5525 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5526 signed zeros. */
5527 if (HONOR_NANS (DECL_MODE (limit)))
5529 tmp = fold_build2_loc (input_location, op, logical_type_node,
5530 arrayse.expr, limit);
5531 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5532 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5533 build_empty_stmt (input_location));
5535 else
5537 tmp = fold_build2_loc (input_location,
5538 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5539 type, arrayse.expr, limit);
5540 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5542 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5543 gfc_add_expr_to_block (&block, tmp);
5545 else
5546 gfc_add_block_to_block (&block, &block2);
5548 gfc_add_block_to_block (&block, &arrayse.post);
5550 tmp = gfc_finish_block (&block);
5551 if (maskss)
5552 /* We enclose the above in if (mask) {...}. */
5553 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5554 build_empty_stmt (input_location));
5555 gfc_add_expr_to_block (&body, tmp);
5557 if (lab)
5559 gfc_trans_scalarized_loop_boundary (&loop, &body);
5561 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5562 nan_cst, huge_cst);
5563 gfc_add_modify (&loop.code[0], limit, tmp);
5564 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5566 /* If we have a mask, only add this element if the mask is set. */
5567 if (maskss)
5569 gfc_init_se (&maskse, NULL);
5570 gfc_copy_loopinfo_to_se (&maskse, &loop);
5571 maskse.ss = maskss;
5572 gfc_conv_expr_val (&maskse, maskexpr);
5573 gfc_add_block_to_block (&body, &maskse.pre);
5575 gfc_start_block (&block);
5577 else
5578 gfc_init_block (&block);
5580 /* Compare with the current limit. */
5581 gfc_init_se (&arrayse, NULL);
5582 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5583 arrayse.ss = arrayss;
5584 gfc_conv_expr_val (&arrayse, arrayexpr);
5585 gfc_add_block_to_block (&block, &arrayse.pre);
5587 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5588 signed zeros. */
5589 if (HONOR_NANS (DECL_MODE (limit)))
5591 tmp = fold_build2_loc (input_location, op, logical_type_node,
5592 arrayse.expr, limit);
5593 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5594 tmp = build3_v (COND_EXPR, tmp, ifbody,
5595 build_empty_stmt (input_location));
5596 gfc_add_expr_to_block (&block, tmp);
5598 else
5600 tmp = fold_build2_loc (input_location,
5601 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5602 type, arrayse.expr, limit);
5603 gfc_add_modify (&block, limit, tmp);
5606 gfc_add_block_to_block (&block, &arrayse.post);
5608 tmp = gfc_finish_block (&block);
5609 if (maskss)
5610 /* We enclose the above in if (mask) {...}. */
5611 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5612 build_empty_stmt (input_location));
5613 gfc_add_expr_to_block (&body, tmp);
5614 /* Avoid initializing loopvar[0] again, it should be left where
5615 it finished by the first loop. */
5616 loop.from[0] = loop.loopvar[0];
5618 gfc_trans_scalarizing_loops (&loop, &body);
5620 if (fast)
5622 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5623 nan_cst, huge_cst);
5624 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5625 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5626 ifbody);
5627 gfc_add_expr_to_block (&loop.pre, tmp);
5629 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5631 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5632 huge_cst);
5633 gfc_add_modify (&loop.pre, limit, tmp);
5636 /* For a scalar mask, enclose the loop in an if statement. */
5637 if (maskexpr && maskss == NULL)
5639 tree else_stmt;
5641 gfc_init_se (&maskse, NULL);
5642 gfc_conv_expr_val (&maskse, maskexpr);
5643 gfc_init_block (&block);
5644 gfc_add_block_to_block (&block, &loop.pre);
5645 gfc_add_block_to_block (&block, &loop.post);
5646 tmp = gfc_finish_block (&block);
5648 if (HONOR_INFINITIES (DECL_MODE (limit)))
5649 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5650 else
5651 else_stmt = build_empty_stmt (input_location);
5652 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5653 gfc_add_expr_to_block (&block, tmp);
5654 gfc_add_block_to_block (&se->pre, &block);
5656 else
5658 gfc_add_block_to_block (&se->pre, &loop.pre);
5659 gfc_add_block_to_block (&se->pre, &loop.post);
5662 gfc_cleanup_loop (&loop);
5664 se->expr = limit;
5667 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5668 static void
5669 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5671 tree args[2];
5672 tree type;
5673 tree tmp;
5675 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5676 type = TREE_TYPE (args[0]);
5678 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5679 build_int_cst (type, 1), args[1]);
5680 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5681 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5682 build_int_cst (type, 0));
5683 type = gfc_typenode_for_spec (&expr->ts);
5684 se->expr = convert (type, tmp);
5688 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5689 static void
5690 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5692 tree args[2];
5694 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5696 /* Convert both arguments to the unsigned type of the same size. */
5697 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5698 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5700 /* If they have unequal type size, convert to the larger one. */
5701 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5702 > TYPE_PRECISION (TREE_TYPE (args[1])))
5703 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5704 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5705 > TYPE_PRECISION (TREE_TYPE (args[0])))
5706 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5708 /* Now, we compare them. */
5709 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5710 args[0], args[1]);
5714 /* Generate code to perform the specified operation. */
5715 static void
5716 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5718 tree args[2];
5720 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5721 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5722 args[0], args[1]);
5725 /* Bitwise not. */
5726 static void
5727 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5729 tree arg;
5731 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5732 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5733 TREE_TYPE (arg), arg);
5736 /* Set or clear a single bit. */
5737 static void
5738 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5740 tree args[2];
5741 tree type;
5742 tree tmp;
5743 enum tree_code op;
5745 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5746 type = TREE_TYPE (args[0]);
5748 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5749 build_int_cst (type, 1), args[1]);
5750 if (set)
5751 op = BIT_IOR_EXPR;
5752 else
5754 op = BIT_AND_EXPR;
5755 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5757 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5760 /* Extract a sequence of bits.
5761 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5762 static void
5763 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5765 tree args[3];
5766 tree type;
5767 tree tmp;
5768 tree mask;
5770 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5771 type = TREE_TYPE (args[0]);
5773 mask = build_int_cst (type, -1);
5774 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5775 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5777 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5779 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5782 static void
5783 gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
5785 gfc_actual_arglist *s, *k;
5786 gfc_expr *e;
5788 /* Remove the KIND argument, if present. */
5789 s = expr->value.function.actual;
5790 k = s->next;
5791 e = k->expr;
5792 gfc_free_expr (e);
5793 k->expr = NULL;
5795 gfc_conv_intrinsic_funcall (se, expr);
5798 static void
5799 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5800 bool arithmetic)
5802 tree args[2], type, num_bits, cond;
5804 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5806 args[0] = gfc_evaluate_now (args[0], &se->pre);
5807 args[1] = gfc_evaluate_now (args[1], &se->pre);
5808 type = TREE_TYPE (args[0]);
5810 if (!arithmetic)
5811 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5812 else
5813 gcc_assert (right_shift);
5815 se->expr = fold_build2_loc (input_location,
5816 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5817 TREE_TYPE (args[0]), args[0], args[1]);
5819 if (!arithmetic)
5820 se->expr = fold_convert (type, se->expr);
5822 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5823 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5824 special case. */
5825 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5826 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
5827 args[1], num_bits);
5829 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5830 build_int_cst (type, 0), se->expr);
5833 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5835 : ((shift >= 0) ? i << shift : i >> -shift)
5836 where all shifts are logical shifts. */
5837 static void
5838 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5840 tree args[2];
5841 tree type;
5842 tree utype;
5843 tree tmp;
5844 tree width;
5845 tree num_bits;
5846 tree cond;
5847 tree lshift;
5848 tree rshift;
5850 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5852 args[0] = gfc_evaluate_now (args[0], &se->pre);
5853 args[1] = gfc_evaluate_now (args[1], &se->pre);
5855 type = TREE_TYPE (args[0]);
5856 utype = unsigned_type_for (type);
5858 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5859 args[1]);
5861 /* Left shift if positive. */
5862 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5864 /* Right shift if negative.
5865 We convert to an unsigned type because we want a logical shift.
5866 The standard doesn't define the case of shifting negative
5867 numbers, and we try to be compatible with other compilers, most
5868 notably g77, here. */
5869 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5870 utype, convert (utype, args[0]), width));
5872 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
5873 build_int_cst (TREE_TYPE (args[1]), 0));
5874 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5876 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5877 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5878 special case. */
5879 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5880 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
5881 num_bits);
5882 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5883 build_int_cst (type, 0), tmp);
5887 /* Circular shift. AKA rotate or barrel shift. */
5889 static void
5890 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5892 tree *args;
5893 tree type;
5894 tree tmp;
5895 tree lrot;
5896 tree rrot;
5897 tree zero;
5898 unsigned int num_args;
5900 num_args = gfc_intrinsic_argument_list_length (expr);
5901 args = XALLOCAVEC (tree, num_args);
5903 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5905 if (num_args == 3)
5907 /* Use a library function for the 3 parameter version. */
5908 tree int4type = gfc_get_int_type (4);
5910 type = TREE_TYPE (args[0]);
5911 /* We convert the first argument to at least 4 bytes, and
5912 convert back afterwards. This removes the need for library
5913 functions for all argument sizes, and function will be
5914 aligned to at least 32 bits, so there's no loss. */
5915 if (expr->ts.kind < 4)
5916 args[0] = convert (int4type, args[0]);
5918 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5919 need loads of library functions. They cannot have values >
5920 BIT_SIZE (I) so the conversion is safe. */
5921 args[1] = convert (int4type, args[1]);
5922 args[2] = convert (int4type, args[2]);
5924 switch (expr->ts.kind)
5926 case 1:
5927 case 2:
5928 case 4:
5929 tmp = gfor_fndecl_math_ishftc4;
5930 break;
5931 case 8:
5932 tmp = gfor_fndecl_math_ishftc8;
5933 break;
5934 case 16:
5935 tmp = gfor_fndecl_math_ishftc16;
5936 break;
5937 default:
5938 gcc_unreachable ();
5940 se->expr = build_call_expr_loc (input_location,
5941 tmp, 3, args[0], args[1], args[2]);
5942 /* Convert the result back to the original type, if we extended
5943 the first argument's width above. */
5944 if (expr->ts.kind < 4)
5945 se->expr = convert (type, se->expr);
5947 return;
5949 type = TREE_TYPE (args[0]);
5951 /* Evaluate arguments only once. */
5952 args[0] = gfc_evaluate_now (args[0], &se->pre);
5953 args[1] = gfc_evaluate_now (args[1], &se->pre);
5955 /* Rotate left if positive. */
5956 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5958 /* Rotate right if negative. */
5959 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5960 args[1]);
5961 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5963 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5964 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
5965 zero);
5966 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5968 /* Do nothing if shift == 0. */
5969 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
5970 zero);
5971 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5972 rrot);
5976 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5977 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5979 The conditional expression is necessary because the result of LEADZ(0)
5980 is defined, but the result of __builtin_clz(0) is undefined for most
5981 targets.
5983 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5984 difference in bit size between the argument of LEADZ and the C int. */
5986 static void
5987 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
5989 tree arg;
5990 tree arg_type;
5991 tree cond;
5992 tree result_type;
5993 tree leadz;
5994 tree bit_size;
5995 tree tmp;
5996 tree func;
5997 int s, argsize;
5999 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6000 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6002 /* Which variant of __builtin_clz* should we call? */
6003 if (argsize <= INT_TYPE_SIZE)
6005 arg_type = unsigned_type_node;
6006 func = builtin_decl_explicit (BUILT_IN_CLZ);
6008 else if (argsize <= LONG_TYPE_SIZE)
6010 arg_type = long_unsigned_type_node;
6011 func = builtin_decl_explicit (BUILT_IN_CLZL);
6013 else if (argsize <= LONG_LONG_TYPE_SIZE)
6015 arg_type = long_long_unsigned_type_node;
6016 func = builtin_decl_explicit (BUILT_IN_CLZLL);
6018 else
6020 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6021 arg_type = gfc_build_uint_type (argsize);
6022 func = NULL_TREE;
6025 /* Convert the actual argument twice: first, to the unsigned type of the
6026 same size; then, to the proper argument type for the built-in
6027 function. But the return type is of the default INTEGER kind. */
6028 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6029 arg = fold_convert (arg_type, arg);
6030 arg = gfc_evaluate_now (arg, &se->pre);
6031 result_type = gfc_get_int_type (gfc_default_integer_kind);
6033 /* Compute LEADZ for the case i .ne. 0. */
6034 if (func)
6036 s = TYPE_PRECISION (arg_type) - argsize;
6037 tmp = fold_convert (result_type,
6038 build_call_expr_loc (input_location, func,
6039 1, arg));
6040 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
6041 tmp, build_int_cst (result_type, s));
6043 else
6045 /* We end up here if the argument type is larger than 'long long'.
6046 We generate this code:
6048 if (x & (ULL_MAX << ULL_SIZE) != 0)
6049 return clzll ((unsigned long long) (x >> ULLSIZE));
6050 else
6051 return ULL_SIZE + clzll ((unsigned long long) x);
6052 where ULL_MAX is the largest value that a ULL_MAX can hold
6053 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6054 is the bit-size of the long long type (64 in this example). */
6055 tree ullsize, ullmax, tmp1, tmp2, btmp;
6057 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6058 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6059 long_long_unsigned_type_node,
6060 build_int_cst (long_long_unsigned_type_node,
6061 0));
6063 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
6064 fold_convert (arg_type, ullmax), ullsize);
6065 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
6066 arg, cond);
6067 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6068 cond, build_int_cst (arg_type, 0));
6070 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6071 arg, ullsize);
6072 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6073 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6074 tmp1 = fold_convert (result_type,
6075 build_call_expr_loc (input_location, btmp, 1, tmp1));
6077 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6078 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6079 tmp2 = fold_convert (result_type,
6080 build_call_expr_loc (input_location, btmp, 1, tmp2));
6081 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6082 tmp2, ullsize);
6084 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
6085 cond, tmp1, tmp2);
6088 /* Build BIT_SIZE. */
6089 bit_size = build_int_cst (result_type, argsize);
6091 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6092 arg, build_int_cst (arg_type, 0));
6093 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6094 bit_size, leadz);
6098 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6100 The conditional expression is necessary because the result of TRAILZ(0)
6101 is defined, but the result of __builtin_ctz(0) is undefined for most
6102 targets. */
6104 static void
6105 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
6107 tree arg;
6108 tree arg_type;
6109 tree cond;
6110 tree result_type;
6111 tree trailz;
6112 tree bit_size;
6113 tree func;
6114 int argsize;
6116 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6117 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6119 /* Which variant of __builtin_ctz* should we call? */
6120 if (argsize <= INT_TYPE_SIZE)
6122 arg_type = unsigned_type_node;
6123 func = builtin_decl_explicit (BUILT_IN_CTZ);
6125 else if (argsize <= LONG_TYPE_SIZE)
6127 arg_type = long_unsigned_type_node;
6128 func = builtin_decl_explicit (BUILT_IN_CTZL);
6130 else if (argsize <= LONG_LONG_TYPE_SIZE)
6132 arg_type = long_long_unsigned_type_node;
6133 func = builtin_decl_explicit (BUILT_IN_CTZLL);
6135 else
6137 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6138 arg_type = gfc_build_uint_type (argsize);
6139 func = NULL_TREE;
6142 /* Convert the actual argument twice: first, to the unsigned type of the
6143 same size; then, to the proper argument type for the built-in
6144 function. But the return type is of the default INTEGER kind. */
6145 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6146 arg = fold_convert (arg_type, arg);
6147 arg = gfc_evaluate_now (arg, &se->pre);
6148 result_type = gfc_get_int_type (gfc_default_integer_kind);
6150 /* Compute TRAILZ for the case i .ne. 0. */
6151 if (func)
6152 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
6153 func, 1, arg));
6154 else
6156 /* We end up here if the argument type is larger than 'long long'.
6157 We generate this code:
6159 if ((x & ULL_MAX) == 0)
6160 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6161 else
6162 return ctzll ((unsigned long long) x);
6164 where ULL_MAX is the largest value that a ULL_MAX can hold
6165 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6166 is the bit-size of the long long type (64 in this example). */
6167 tree ullsize, ullmax, tmp1, tmp2, btmp;
6169 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6170 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6171 long_long_unsigned_type_node,
6172 build_int_cst (long_long_unsigned_type_node, 0));
6174 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
6175 fold_convert (arg_type, ullmax));
6176 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
6177 build_int_cst (arg_type, 0));
6179 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6180 arg, ullsize);
6181 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6182 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6183 tmp1 = fold_convert (result_type,
6184 build_call_expr_loc (input_location, btmp, 1, tmp1));
6185 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6186 tmp1, ullsize);
6188 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6189 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6190 tmp2 = fold_convert (result_type,
6191 build_call_expr_loc (input_location, btmp, 1, tmp2));
6193 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
6194 cond, tmp1, tmp2);
6197 /* Build BIT_SIZE. */
6198 bit_size = build_int_cst (result_type, argsize);
6200 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6201 arg, build_int_cst (arg_type, 0));
6202 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6203 bit_size, trailz);
6206 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6207 for types larger than "long long", we call the long long built-in for
6208 the lower and higher bits and combine the result. */
6210 static void
6211 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
6213 tree arg;
6214 tree arg_type;
6215 tree result_type;
6216 tree func;
6217 int argsize;
6219 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6220 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6221 result_type = gfc_get_int_type (gfc_default_integer_kind);
6223 /* Which variant of the builtin should we call? */
6224 if (argsize <= INT_TYPE_SIZE)
6226 arg_type = unsigned_type_node;
6227 func = builtin_decl_explicit (parity
6228 ? BUILT_IN_PARITY
6229 : BUILT_IN_POPCOUNT);
6231 else if (argsize <= LONG_TYPE_SIZE)
6233 arg_type = long_unsigned_type_node;
6234 func = builtin_decl_explicit (parity
6235 ? BUILT_IN_PARITYL
6236 : BUILT_IN_POPCOUNTL);
6238 else if (argsize <= LONG_LONG_TYPE_SIZE)
6240 arg_type = long_long_unsigned_type_node;
6241 func = builtin_decl_explicit (parity
6242 ? BUILT_IN_PARITYLL
6243 : BUILT_IN_POPCOUNTLL);
6245 else
6247 /* Our argument type is larger than 'long long', which mean none
6248 of the POPCOUNT builtins covers it. We thus call the 'long long'
6249 variant multiple times, and add the results. */
6250 tree utype, arg2, call1, call2;
6252 /* For now, we only cover the case where argsize is twice as large
6253 as 'long long'. */
6254 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6256 func = builtin_decl_explicit (parity
6257 ? BUILT_IN_PARITYLL
6258 : BUILT_IN_POPCOUNTLL);
6260 /* Convert it to an integer, and store into a variable. */
6261 utype = gfc_build_uint_type (argsize);
6262 arg = fold_convert (utype, arg);
6263 arg = gfc_evaluate_now (arg, &se->pre);
6265 /* Call the builtin twice. */
6266 call1 = build_call_expr_loc (input_location, func, 1,
6267 fold_convert (long_long_unsigned_type_node,
6268 arg));
6270 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
6271 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
6272 call2 = build_call_expr_loc (input_location, func, 1,
6273 fold_convert (long_long_unsigned_type_node,
6274 arg2));
6276 /* Combine the results. */
6277 if (parity)
6278 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
6279 call1, call2);
6280 else
6281 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6282 call1, call2);
6284 return;
6287 /* Convert the actual argument twice: first, to the unsigned type of the
6288 same size; then, to the proper argument type for the built-in
6289 function. */
6290 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6291 arg = fold_convert (arg_type, arg);
6293 se->expr = fold_convert (result_type,
6294 build_call_expr_loc (input_location, func, 1, arg));
6298 /* Process an intrinsic with unspecified argument-types that has an optional
6299 argument (which could be of type character), e.g. EOSHIFT. For those, we
6300 need to append the string length of the optional argument if it is not
6301 present and the type is really character.
6302 primary specifies the position (starting at 1) of the non-optional argument
6303 specifying the type and optional gives the position of the optional
6304 argument in the arglist. */
6306 static void
6307 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
6308 unsigned primary, unsigned optional)
6310 gfc_actual_arglist* prim_arg;
6311 gfc_actual_arglist* opt_arg;
6312 unsigned cur_pos;
6313 gfc_actual_arglist* arg;
6314 gfc_symbol* sym;
6315 vec<tree, va_gc> *append_args;
6317 /* Find the two arguments given as position. */
6318 cur_pos = 0;
6319 prim_arg = NULL;
6320 opt_arg = NULL;
6321 for (arg = expr->value.function.actual; arg; arg = arg->next)
6323 ++cur_pos;
6325 if (cur_pos == primary)
6326 prim_arg = arg;
6327 if (cur_pos == optional)
6328 opt_arg = arg;
6330 if (cur_pos >= primary && cur_pos >= optional)
6331 break;
6333 gcc_assert (prim_arg);
6334 gcc_assert (prim_arg->expr);
6335 gcc_assert (opt_arg);
6337 /* If we do have type CHARACTER and the optional argument is really absent,
6338 append a dummy 0 as string length. */
6339 append_args = NULL;
6340 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6342 tree dummy;
6344 dummy = build_int_cst (gfc_charlen_type_node, 0);
6345 vec_alloc (append_args, 1);
6346 append_args->quick_push (dummy);
6349 /* Build the call itself. */
6350 gcc_assert (!se->ignore_optional);
6351 sym = gfc_get_symbol_for_expr (expr, false);
6352 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6353 append_args);
6354 gfc_free_symbol (sym);
6357 /* The length of a character string. */
6358 static void
6359 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6361 tree len;
6362 tree type;
6363 tree decl;
6364 gfc_symbol *sym;
6365 gfc_se argse;
6366 gfc_expr *arg;
6368 gcc_assert (!se->ss);
6370 arg = expr->value.function.actual->expr;
6372 type = gfc_typenode_for_spec (&expr->ts);
6373 switch (arg->expr_type)
6375 case EXPR_CONSTANT:
6376 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6377 break;
6379 case EXPR_ARRAY:
6380 /* Obtain the string length from the function used by
6381 trans-array.c(gfc_trans_array_constructor). */
6382 len = NULL_TREE;
6383 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6384 break;
6386 case EXPR_VARIABLE:
6387 if (arg->ref == NULL
6388 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6390 /* This doesn't catch all cases.
6391 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6392 and the surrounding thread. */
6393 sym = arg->symtree->n.sym;
6394 decl = gfc_get_symbol_decl (sym);
6395 if (decl == current_function_decl && sym->attr.function
6396 && (sym->result == sym))
6397 decl = gfc_get_fake_result_decl (sym, 0);
6399 len = sym->ts.u.cl->backend_decl;
6400 gcc_assert (len);
6401 break;
6404 /* Fall through. */
6406 default:
6407 gfc_init_se (&argse, se);
6408 if (arg->rank == 0)
6409 gfc_conv_expr (&argse, arg);
6410 else
6411 gfc_conv_expr_descriptor (&argse, arg);
6412 gfc_add_block_to_block (&se->pre, &argse.pre);
6413 gfc_add_block_to_block (&se->post, &argse.post);
6414 len = argse.string_length;
6415 break;
6417 se->expr = convert (type, len);
6420 /* The length of a character string not including trailing blanks. */
6421 static void
6422 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6424 int kind = expr->value.function.actual->expr->ts.kind;
6425 tree args[2], type, fndecl;
6427 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6428 type = gfc_typenode_for_spec (&expr->ts);
6430 if (kind == 1)
6431 fndecl = gfor_fndecl_string_len_trim;
6432 else if (kind == 4)
6433 fndecl = gfor_fndecl_string_len_trim_char4;
6434 else
6435 gcc_unreachable ();
6437 se->expr = build_call_expr_loc (input_location,
6438 fndecl, 2, args[0], args[1]);
6439 se->expr = convert (type, se->expr);
6443 /* Returns the starting position of a substring within a string. */
6445 static void
6446 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6447 tree function)
6449 tree logical4_type_node = gfc_get_logical_type (4);
6450 tree type;
6451 tree fndecl;
6452 tree *args;
6453 unsigned int num_args;
6455 args = XALLOCAVEC (tree, 5);
6457 /* Get number of arguments; characters count double due to the
6458 string length argument. Kind= is not passed to the library
6459 and thus ignored. */
6460 if (expr->value.function.actual->next->next->expr == NULL)
6461 num_args = 4;
6462 else
6463 num_args = 5;
6465 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6466 type = gfc_typenode_for_spec (&expr->ts);
6468 if (num_args == 4)
6469 args[4] = build_int_cst (logical4_type_node, 0);
6470 else
6471 args[4] = convert (logical4_type_node, args[4]);
6473 fndecl = build_addr (function);
6474 se->expr = build_call_array_loc (input_location,
6475 TREE_TYPE (TREE_TYPE (function)), fndecl,
6476 5, args);
6477 se->expr = convert (type, se->expr);
6481 /* The ascii value for a single character. */
6482 static void
6483 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6485 tree args[3], type, pchartype;
6486 int nargs;
6488 nargs = gfc_intrinsic_argument_list_length (expr);
6489 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6490 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6491 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6492 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6493 type = gfc_typenode_for_spec (&expr->ts);
6495 se->expr = build_fold_indirect_ref_loc (input_location,
6496 args[1]);
6497 se->expr = convert (type, se->expr);
6501 /* Intrinsic ISNAN calls __builtin_isnan. */
6503 static void
6504 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6506 tree arg;
6508 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6509 se->expr = build_call_expr_loc (input_location,
6510 builtin_decl_explicit (BUILT_IN_ISNAN),
6511 1, arg);
6512 STRIP_TYPE_NOPS (se->expr);
6513 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6517 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6518 their argument against a constant integer value. */
6520 static void
6521 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6523 tree arg;
6525 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6526 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6527 gfc_typenode_for_spec (&expr->ts),
6528 arg, build_int_cst (TREE_TYPE (arg), value));
6533 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6535 static void
6536 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6538 tree tsource;
6539 tree fsource;
6540 tree mask;
6541 tree type;
6542 tree len, len2;
6543 tree *args;
6544 unsigned int num_args;
6546 num_args = gfc_intrinsic_argument_list_length (expr);
6547 args = XALLOCAVEC (tree, num_args);
6549 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6550 if (expr->ts.type != BT_CHARACTER)
6552 tsource = args[0];
6553 fsource = args[1];
6554 mask = args[2];
6556 else
6558 /* We do the same as in the non-character case, but the argument
6559 list is different because of the string length arguments. We
6560 also have to set the string length for the result. */
6561 len = args[0];
6562 tsource = args[1];
6563 len2 = args[2];
6564 fsource = args[3];
6565 mask = args[4];
6567 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6568 &se->pre);
6569 se->string_length = len;
6571 type = TREE_TYPE (tsource);
6572 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6573 fold_convert (type, fsource));
6577 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6579 static void
6580 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6582 tree args[3], mask, type;
6584 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6585 mask = gfc_evaluate_now (args[2], &se->pre);
6587 type = TREE_TYPE (args[0]);
6588 gcc_assert (TREE_TYPE (args[1]) == type);
6589 gcc_assert (TREE_TYPE (mask) == type);
6591 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6592 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6593 fold_build1_loc (input_location, BIT_NOT_EXPR,
6594 type, mask));
6595 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6596 args[0], args[1]);
6600 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6601 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6603 static void
6604 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6606 tree arg, allones, type, utype, res, cond, bitsize;
6607 int i;
6609 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6610 arg = gfc_evaluate_now (arg, &se->pre);
6612 type = gfc_get_int_type (expr->ts.kind);
6613 utype = unsigned_type_for (type);
6615 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6616 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6618 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6619 build_int_cst (utype, 0));
6621 if (left)
6623 /* Left-justified mask. */
6624 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6625 bitsize, arg);
6626 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6627 fold_convert (utype, res));
6629 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6630 smaller than type width. */
6631 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6632 build_int_cst (TREE_TYPE (arg), 0));
6633 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6634 build_int_cst (utype, 0), res);
6636 else
6638 /* Right-justified mask. */
6639 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6640 fold_convert (utype, arg));
6641 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6643 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6644 strictly smaller than type width. */
6645 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6646 arg, bitsize);
6647 res = fold_build3_loc (input_location, COND_EXPR, utype,
6648 cond, allones, res);
6651 se->expr = fold_convert (type, res);
6655 /* FRACTION (s) is translated into:
6656 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6657 static void
6658 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6660 tree arg, type, tmp, res, frexp, cond;
6662 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6664 type = gfc_typenode_for_spec (&expr->ts);
6665 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6666 arg = gfc_evaluate_now (arg, &se->pre);
6668 cond = build_call_expr_loc (input_location,
6669 builtin_decl_explicit (BUILT_IN_ISFINITE),
6670 1, arg);
6672 tmp = gfc_create_var (integer_type_node, NULL);
6673 res = build_call_expr_loc (input_location, frexp, 2,
6674 fold_convert (type, arg),
6675 gfc_build_addr_expr (NULL_TREE, tmp));
6676 res = fold_convert (type, res);
6678 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6679 cond, res, gfc_build_nan (type, ""));
6683 /* NEAREST (s, dir) is translated into
6684 tmp = copysign (HUGE_VAL, dir);
6685 return nextafter (s, tmp);
6687 static void
6688 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6690 tree args[2], type, tmp, nextafter, copysign, huge_val;
6692 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6693 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6695 type = gfc_typenode_for_spec (&expr->ts);
6696 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6698 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6699 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6700 fold_convert (type, args[1]));
6701 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6702 fold_convert (type, args[0]), tmp);
6703 se->expr = fold_convert (type, se->expr);
6707 /* SPACING (s) is translated into
6708 int e;
6709 if (!isfinite (s))
6710 res = NaN;
6711 else if (s == 0)
6712 res = tiny;
6713 else
6715 frexp (s, &e);
6716 e = e - prec;
6717 e = MAX_EXPR (e, emin);
6718 res = scalbn (1., e);
6720 return res;
6722 where prec is the precision of s, gfc_real_kinds[k].digits,
6723 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6724 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6726 static void
6727 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6729 tree arg, type, prec, emin, tiny, res, e;
6730 tree cond, nan, tmp, frexp, scalbn;
6731 int k;
6732 stmtblock_t block;
6734 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6735 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6736 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6737 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6739 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6740 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6742 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6743 arg = gfc_evaluate_now (arg, &se->pre);
6745 type = gfc_typenode_for_spec (&expr->ts);
6746 e = gfc_create_var (integer_type_node, NULL);
6747 res = gfc_create_var (type, NULL);
6750 /* Build the block for s /= 0. */
6751 gfc_start_block (&block);
6752 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6753 gfc_build_addr_expr (NULL_TREE, e));
6754 gfc_add_expr_to_block (&block, tmp);
6756 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6757 prec);
6758 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6759 integer_type_node, tmp, emin));
6761 tmp = build_call_expr_loc (input_location, scalbn, 2,
6762 build_real_from_int_cst (type, integer_one_node), e);
6763 gfc_add_modify (&block, res, tmp);
6765 /* Finish by building the IF statement for value zero. */
6766 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6767 build_real_from_int_cst (type, integer_zero_node));
6768 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6769 gfc_finish_block (&block));
6771 /* And deal with infinities and NaNs. */
6772 cond = build_call_expr_loc (input_location,
6773 builtin_decl_explicit (BUILT_IN_ISFINITE),
6774 1, arg);
6775 nan = gfc_build_nan (type, "");
6776 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6778 gfc_add_expr_to_block (&se->pre, tmp);
6779 se->expr = res;
6783 /* RRSPACING (s) is translated into
6784 int e;
6785 real x;
6786 x = fabs (s);
6787 if (isfinite (x))
6789 if (x != 0)
6791 frexp (s, &e);
6792 x = scalbn (x, precision - e);
6795 else
6796 x = NaN;
6797 return x;
6799 where precision is gfc_real_kinds[k].digits. */
6801 static void
6802 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6804 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6805 int prec, k;
6806 stmtblock_t block;
6808 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6809 prec = gfc_real_kinds[k].digits;
6811 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6812 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6813 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6815 type = gfc_typenode_for_spec (&expr->ts);
6816 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6817 arg = gfc_evaluate_now (arg, &se->pre);
6819 e = gfc_create_var (integer_type_node, NULL);
6820 x = gfc_create_var (type, NULL);
6821 gfc_add_modify (&se->pre, x,
6822 build_call_expr_loc (input_location, fabs, 1, arg));
6825 gfc_start_block (&block);
6826 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6827 gfc_build_addr_expr (NULL_TREE, e));
6828 gfc_add_expr_to_block (&block, tmp);
6830 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6831 build_int_cst (integer_type_node, prec), e);
6832 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6833 gfc_add_modify (&block, x, tmp);
6834 stmt = gfc_finish_block (&block);
6836 /* if (x != 0) */
6837 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
6838 build_real_from_int_cst (type, integer_zero_node));
6839 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6841 /* And deal with infinities and NaNs. */
6842 cond = build_call_expr_loc (input_location,
6843 builtin_decl_explicit (BUILT_IN_ISFINITE),
6844 1, x);
6845 nan = gfc_build_nan (type, "");
6846 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6848 gfc_add_expr_to_block (&se->pre, tmp);
6849 se->expr = fold_convert (type, x);
6853 /* SCALE (s, i) is translated into scalbn (s, i). */
6854 static void
6855 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6857 tree args[2], type, scalbn;
6859 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6861 type = gfc_typenode_for_spec (&expr->ts);
6862 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6863 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6864 fold_convert (type, args[0]),
6865 fold_convert (integer_type_node, args[1]));
6866 se->expr = fold_convert (type, se->expr);
6870 /* SET_EXPONENT (s, i) is translated into
6871 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6872 static void
6873 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6875 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6877 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6878 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6880 type = gfc_typenode_for_spec (&expr->ts);
6881 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6882 args[0] = gfc_evaluate_now (args[0], &se->pre);
6884 tmp = gfc_create_var (integer_type_node, NULL);
6885 tmp = build_call_expr_loc (input_location, frexp, 2,
6886 fold_convert (type, args[0]),
6887 gfc_build_addr_expr (NULL_TREE, tmp));
6888 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6889 fold_convert (integer_type_node, args[1]));
6890 res = fold_convert (type, res);
6892 /* Call to isfinite */
6893 cond = build_call_expr_loc (input_location,
6894 builtin_decl_explicit (BUILT_IN_ISFINITE),
6895 1, args[0]);
6896 nan = gfc_build_nan (type, "");
6898 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6899 res, nan);
6903 static void
6904 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6906 gfc_actual_arglist *actual;
6907 tree arg1;
6908 tree type;
6909 tree fncall0;
6910 tree fncall1;
6911 gfc_se argse;
6913 gfc_init_se (&argse, NULL);
6914 actual = expr->value.function.actual;
6916 if (actual->expr->ts.type == BT_CLASS)
6917 gfc_add_class_array_ref (actual->expr);
6919 argse.data_not_needed = 1;
6920 if (gfc_is_class_array_function (actual->expr))
6922 /* For functions that return a class array conv_expr_descriptor is not
6923 able to get the descriptor right. Therefore this special case. */
6924 gfc_conv_expr_reference (&argse, actual->expr);
6925 argse.expr = gfc_build_addr_expr (NULL_TREE,
6926 gfc_class_data_get (argse.expr));
6928 else
6930 argse.want_pointer = 1;
6931 gfc_conv_expr_descriptor (&argse, actual->expr);
6933 gfc_add_block_to_block (&se->pre, &argse.pre);
6934 gfc_add_block_to_block (&se->post, &argse.post);
6935 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6937 /* Build the call to size0. */
6938 fncall0 = build_call_expr_loc (input_location,
6939 gfor_fndecl_size0, 1, arg1);
6941 actual = actual->next;
6943 if (actual->expr)
6945 gfc_init_se (&argse, NULL);
6946 gfc_conv_expr_type (&argse, actual->expr,
6947 gfc_array_index_type);
6948 gfc_add_block_to_block (&se->pre, &argse.pre);
6950 /* Unusually, for an intrinsic, size does not exclude
6951 an optional arg2, so we must test for it. */
6952 if (actual->expr->expr_type == EXPR_VARIABLE
6953 && actual->expr->symtree->n.sym->attr.dummy
6954 && actual->expr->symtree->n.sym->attr.optional)
6956 tree tmp;
6957 /* Build the call to size1. */
6958 fncall1 = build_call_expr_loc (input_location,
6959 gfor_fndecl_size1, 2,
6960 arg1, argse.expr);
6962 gfc_init_se (&argse, NULL);
6963 argse.want_pointer = 1;
6964 argse.data_not_needed = 1;
6965 gfc_conv_expr (&argse, actual->expr);
6966 gfc_add_block_to_block (&se->pre, &argse.pre);
6967 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6968 argse.expr, null_pointer_node);
6969 tmp = gfc_evaluate_now (tmp, &se->pre);
6970 se->expr = fold_build3_loc (input_location, COND_EXPR,
6971 pvoid_type_node, tmp, fncall1, fncall0);
6973 else
6975 se->expr = NULL_TREE;
6976 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
6977 gfc_array_index_type,
6978 argse.expr, gfc_index_one_node);
6981 else if (expr->value.function.actual->expr->rank == 1)
6983 argse.expr = gfc_index_zero_node;
6984 se->expr = NULL_TREE;
6986 else
6987 se->expr = fncall0;
6989 if (se->expr == NULL_TREE)
6991 tree ubound, lbound;
6993 arg1 = build_fold_indirect_ref_loc (input_location,
6994 arg1);
6995 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
6996 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6997 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
6998 gfc_array_index_type, ubound, lbound);
6999 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7000 gfc_array_index_type,
7001 se->expr, gfc_index_one_node);
7002 se->expr = fold_build2_loc (input_location, MAX_EXPR,
7003 gfc_array_index_type, se->expr,
7004 gfc_index_zero_node);
7007 type = gfc_typenode_for_spec (&expr->ts);
7008 se->expr = convert (type, se->expr);
7012 /* Helper function to compute the size of a character variable,
7013 excluding the terminating null characters. The result has
7014 gfc_array_index_type type. */
7016 tree
7017 size_of_string_in_bytes (int kind, tree string_length)
7019 tree bytesize;
7020 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
7022 bytesize = build_int_cst (gfc_array_index_type,
7023 gfc_character_kinds[i].bit_size / 8);
7025 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7026 bytesize,
7027 fold_convert (gfc_array_index_type, string_length));
7031 static void
7032 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
7034 gfc_expr *arg;
7035 gfc_se argse;
7036 tree source_bytes;
7037 tree tmp;
7038 tree lower;
7039 tree upper;
7040 tree byte_size;
7041 tree field;
7042 int n;
7044 gfc_init_se (&argse, NULL);
7045 arg = expr->value.function.actual->expr;
7047 if (arg->rank || arg->ts.type == BT_ASSUMED)
7048 gfc_conv_expr_descriptor (&argse, arg);
7049 else
7050 gfc_conv_expr_reference (&argse, arg);
7052 if (arg->ts.type == BT_ASSUMED)
7054 /* This only works if an array descriptor has been passed; thus, extract
7055 the size from the descriptor. */
7056 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
7057 == TYPE_PRECISION (size_type_node));
7058 tmp = arg->symtree->n.sym->backend_decl;
7059 tmp = DECL_LANG_SPECIFIC (tmp)
7060 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
7061 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
7062 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
7063 tmp = build_fold_indirect_ref_loc (input_location, tmp);
7065 tmp = gfc_conv_descriptor_dtype (tmp);
7066 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
7067 GFC_DTYPE_ELEM_LEN);
7068 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
7069 tmp, field, NULL_TREE);
7071 byte_size = fold_convert (gfc_array_index_type, tmp);
7073 else if (arg->ts.type == BT_CLASS)
7075 /* Conv_expr_descriptor returns a component_ref to _data component of the
7076 class object. The class object may be a non-pointer object, e.g.
7077 located on the stack, or a memory location pointed to, e.g. a
7078 parameter, i.e., an indirect_ref. */
7079 if (arg->rank < 0
7080 || (arg->rank > 0 && !VAR_P (argse.expr)
7081 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
7082 && GFC_DECL_CLASS (TREE_OPERAND (
7083 TREE_OPERAND (argse.expr, 0), 0)))
7084 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
7085 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7086 else if (arg->rank > 0
7087 || (arg->rank == 0
7088 && arg->ref && arg->ref->type == REF_COMPONENT))
7089 /* The scalarizer added an additional temp. To get the class' vptr
7090 one has to look at the original backend_decl. */
7091 byte_size = gfc_class_vtab_size_get (
7092 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7093 else
7094 byte_size = gfc_class_vtab_size_get (argse.expr);
7096 else
7098 if (arg->ts.type == BT_CHARACTER)
7099 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7100 else
7102 if (arg->rank == 0)
7103 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7104 argse.expr));
7105 else
7106 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
7107 byte_size = fold_convert (gfc_array_index_type,
7108 size_in_bytes (byte_size));
7112 if (arg->rank == 0)
7113 se->expr = byte_size;
7114 else
7116 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
7117 gfc_add_modify (&argse.pre, source_bytes, byte_size);
7119 if (arg->rank == -1)
7121 tree cond, loop_var, exit_label;
7122 stmtblock_t body;
7124 tmp = fold_convert (gfc_array_index_type,
7125 gfc_conv_descriptor_rank (argse.expr));
7126 loop_var = gfc_create_var (gfc_array_index_type, "i");
7127 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
7128 exit_label = gfc_build_label_decl (NULL_TREE);
7130 /* Create loop:
7131 for (;;)
7133 if (i >= rank)
7134 goto exit;
7135 source_bytes = source_bytes * array.dim[i].extent;
7136 i = i + 1;
7138 exit: */
7139 gfc_start_block (&body);
7140 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7141 loop_var, tmp);
7142 tmp = build1_v (GOTO_EXPR, exit_label);
7143 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7144 cond, tmp, build_empty_stmt (input_location));
7145 gfc_add_expr_to_block (&body, tmp);
7147 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
7148 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
7149 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7150 tmp = fold_build2_loc (input_location, MULT_EXPR,
7151 gfc_array_index_type, tmp, source_bytes);
7152 gfc_add_modify (&body, source_bytes, tmp);
7154 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7155 gfc_array_index_type, loop_var,
7156 gfc_index_one_node);
7157 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
7159 tmp = gfc_finish_block (&body);
7161 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
7162 tmp);
7163 gfc_add_expr_to_block (&argse.pre, tmp);
7165 tmp = build1_v (LABEL_EXPR, exit_label);
7166 gfc_add_expr_to_block (&argse.pre, tmp);
7168 else
7170 /* Obtain the size of the array in bytes. */
7171 for (n = 0; n < arg->rank; n++)
7173 tree idx;
7174 idx = gfc_rank_cst[n];
7175 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7176 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7177 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7178 tmp = fold_build2_loc (input_location, MULT_EXPR,
7179 gfc_array_index_type, tmp, source_bytes);
7180 gfc_add_modify (&argse.pre, source_bytes, tmp);
7183 se->expr = source_bytes;
7186 gfc_add_block_to_block (&se->pre, &argse.pre);
7190 static void
7191 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
7193 gfc_expr *arg;
7194 gfc_se argse;
7195 tree type, result_type, tmp;
7197 arg = expr->value.function.actual->expr;
7199 gfc_init_se (&argse, NULL);
7200 result_type = gfc_get_int_type (expr->ts.kind);
7202 if (arg->rank == 0)
7204 if (arg->ts.type == BT_CLASS)
7206 gfc_add_vptr_component (arg);
7207 gfc_add_size_component (arg);
7208 gfc_conv_expr (&argse, arg);
7209 tmp = fold_convert (result_type, argse.expr);
7210 goto done;
7213 gfc_conv_expr_reference (&argse, arg);
7214 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7215 argse.expr));
7217 else
7219 argse.want_pointer = 0;
7220 gfc_conv_expr_descriptor (&argse, arg);
7221 if (arg->ts.type == BT_CLASS)
7223 if (arg->rank > 0)
7224 tmp = gfc_class_vtab_size_get (
7225 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7226 else
7227 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7228 tmp = fold_convert (result_type, tmp);
7229 goto done;
7231 type = gfc_get_element_type (TREE_TYPE (argse.expr));
7234 /* Obtain the argument's word length. */
7235 if (arg->ts.type == BT_CHARACTER)
7236 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7237 else
7238 tmp = size_in_bytes (type);
7239 tmp = fold_convert (result_type, tmp);
7241 done:
7242 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
7243 build_int_cst (result_type, BITS_PER_UNIT));
7244 gfc_add_block_to_block (&se->pre, &argse.pre);
7248 /* Intrinsic string comparison functions. */
7250 static void
7251 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
7253 tree args[4];
7255 gfc_conv_intrinsic_function_args (se, expr, args, 4);
7257 se->expr
7258 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
7259 expr->value.function.actual->expr->ts.kind,
7260 op);
7261 se->expr = fold_build2_loc (input_location, op,
7262 gfc_typenode_for_spec (&expr->ts), se->expr,
7263 build_int_cst (TREE_TYPE (se->expr), 0));
7266 /* Generate a call to the adjustl/adjustr library function. */
7267 static void
7268 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
7270 tree args[3];
7271 tree len;
7272 tree type;
7273 tree var;
7274 tree tmp;
7276 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
7277 len = args[1];
7279 type = TREE_TYPE (args[2]);
7280 var = gfc_conv_string_tmp (se, type, len);
7281 args[0] = var;
7283 tmp = build_call_expr_loc (input_location,
7284 fndecl, 3, args[0], args[1], args[2]);
7285 gfc_add_expr_to_block (&se->pre, tmp);
7286 se->expr = var;
7287 se->string_length = len;
7291 /* Generate code for the TRANSFER intrinsic:
7292 For scalar results:
7293 DEST = TRANSFER (SOURCE, MOLD)
7294 where:
7295 typeof<DEST> = typeof<MOLD>
7296 and:
7297 MOLD is scalar.
7299 For array results:
7300 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7301 where:
7302 typeof<DEST> = typeof<MOLD>
7303 and:
7304 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7305 sizeof (DEST(0) * SIZE). */
7306 static void
7307 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
7309 tree tmp;
7310 tree tmpdecl;
7311 tree ptr;
7312 tree extent;
7313 tree source;
7314 tree source_type;
7315 tree source_bytes;
7316 tree mold_type;
7317 tree dest_word_len;
7318 tree size_words;
7319 tree size_bytes;
7320 tree upper;
7321 tree lower;
7322 tree stmt;
7323 tree class_ref = NULL_TREE;
7324 gfc_actual_arglist *arg;
7325 gfc_se argse;
7326 gfc_array_info *info;
7327 stmtblock_t block;
7328 int n;
7329 bool scalar_mold;
7330 gfc_expr *source_expr, *mold_expr, *class_expr;
7332 info = NULL;
7333 if (se->loop)
7334 info = &se->ss->info->data.array;
7336 /* Convert SOURCE. The output from this stage is:-
7337 source_bytes = length of the source in bytes
7338 source = pointer to the source data. */
7339 arg = expr->value.function.actual;
7340 source_expr = arg->expr;
7342 /* Ensure double transfer through LOGICAL preserves all
7343 the needed bits. */
7344 if (arg->expr->expr_type == EXPR_FUNCTION
7345 && arg->expr->value.function.esym == NULL
7346 && arg->expr->value.function.isym != NULL
7347 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7348 && arg->expr->ts.type == BT_LOGICAL
7349 && expr->ts.type != arg->expr->ts.type)
7350 arg->expr->value.function.name = "__transfer_in_transfer";
7352 gfc_init_se (&argse, NULL);
7354 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7356 /* Obtain the pointer to source and the length of source in bytes. */
7357 if (arg->expr->rank == 0)
7359 gfc_conv_expr_reference (&argse, arg->expr);
7360 if (arg->expr->ts.type == BT_CLASS)
7362 tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
7363 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
7364 source = gfc_class_data_get (tmp);
7365 else
7367 /* Array elements are evaluated as a reference to the data.
7368 To obtain the vptr for the element size, the argument
7369 expression must be stripped to the class reference and
7370 re-evaluated. The pre and post blocks are not needed. */
7371 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
7372 source = argse.expr;
7373 class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
7374 gfc_init_se (&argse, NULL);
7375 gfc_conv_expr (&argse, class_expr);
7376 class_ref = argse.expr;
7379 else
7380 source = argse.expr;
7382 /* Obtain the source word length. */
7383 switch (arg->expr->ts.type)
7385 case BT_CHARACTER:
7386 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7387 argse.string_length);
7388 break;
7389 case BT_CLASS:
7390 if (class_ref != NULL_TREE)
7391 tmp = gfc_class_vtab_size_get (class_ref);
7392 else
7393 tmp = gfc_class_vtab_size_get (argse.expr);
7394 break;
7395 default:
7396 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7397 source));
7398 tmp = fold_convert (gfc_array_index_type,
7399 size_in_bytes (source_type));
7400 break;
7403 else
7405 argse.want_pointer = 0;
7406 gfc_conv_expr_descriptor (&argse, arg->expr);
7407 source = gfc_conv_descriptor_data_get (argse.expr);
7408 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7410 /* Repack the source if not simply contiguous. */
7411 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7413 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7415 if (warn_array_temporaries)
7416 gfc_warning (OPT_Warray_temporaries,
7417 "Creating array temporary at %L", &expr->where);
7419 source = build_call_expr_loc (input_location,
7420 gfor_fndecl_in_pack, 1, tmp);
7421 source = gfc_evaluate_now (source, &argse.pre);
7423 /* Free the temporary. */
7424 gfc_start_block (&block);
7425 tmp = gfc_call_free (source);
7426 gfc_add_expr_to_block (&block, tmp);
7427 stmt = gfc_finish_block (&block);
7429 /* Clean up if it was repacked. */
7430 gfc_init_block (&block);
7431 tmp = gfc_conv_array_data (argse.expr);
7432 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7433 source, tmp);
7434 tmp = build3_v (COND_EXPR, tmp, stmt,
7435 build_empty_stmt (input_location));
7436 gfc_add_expr_to_block (&block, tmp);
7437 gfc_add_block_to_block (&block, &se->post);
7438 gfc_init_block (&se->post);
7439 gfc_add_block_to_block (&se->post, &block);
7442 /* Obtain the source word length. */
7443 if (arg->expr->ts.type == BT_CHARACTER)
7444 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7445 argse.string_length);
7446 else
7447 tmp = fold_convert (gfc_array_index_type,
7448 size_in_bytes (source_type));
7450 /* Obtain the size of the array in bytes. */
7451 extent = gfc_create_var (gfc_array_index_type, NULL);
7452 for (n = 0; n < arg->expr->rank; n++)
7454 tree idx;
7455 idx = gfc_rank_cst[n];
7456 gfc_add_modify (&argse.pre, source_bytes, tmp);
7457 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7458 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7459 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7460 gfc_array_index_type, upper, lower);
7461 gfc_add_modify (&argse.pre, extent, tmp);
7462 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7463 gfc_array_index_type, extent,
7464 gfc_index_one_node);
7465 tmp = fold_build2_loc (input_location, MULT_EXPR,
7466 gfc_array_index_type, tmp, source_bytes);
7470 gfc_add_modify (&argse.pre, source_bytes, tmp);
7471 gfc_add_block_to_block (&se->pre, &argse.pre);
7472 gfc_add_block_to_block (&se->post, &argse.post);
7474 /* Now convert MOLD. The outputs are:
7475 mold_type = the TREE type of MOLD
7476 dest_word_len = destination word length in bytes. */
7477 arg = arg->next;
7478 mold_expr = arg->expr;
7480 gfc_init_se (&argse, NULL);
7482 scalar_mold = arg->expr->rank == 0;
7484 if (arg->expr->rank == 0)
7486 gfc_conv_expr_reference (&argse, arg->expr);
7487 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7488 argse.expr));
7490 else
7492 gfc_init_se (&argse, NULL);
7493 argse.want_pointer = 0;
7494 gfc_conv_expr_descriptor (&argse, arg->expr);
7495 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7498 gfc_add_block_to_block (&se->pre, &argse.pre);
7499 gfc_add_block_to_block (&se->post, &argse.post);
7501 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7503 /* If this TRANSFER is nested in another TRANSFER, use a type
7504 that preserves all bits. */
7505 if (arg->expr->ts.type == BT_LOGICAL)
7506 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7509 /* Obtain the destination word length. */
7510 switch (arg->expr->ts.type)
7512 case BT_CHARACTER:
7513 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7514 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7515 break;
7516 case BT_CLASS:
7517 tmp = gfc_class_vtab_size_get (argse.expr);
7518 break;
7519 default:
7520 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7521 break;
7523 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7524 gfc_add_modify (&se->pre, dest_word_len, tmp);
7526 /* Finally convert SIZE, if it is present. */
7527 arg = arg->next;
7528 size_words = gfc_create_var (gfc_array_index_type, NULL);
7530 if (arg->expr)
7532 gfc_init_se (&argse, NULL);
7533 gfc_conv_expr_reference (&argse, arg->expr);
7534 tmp = convert (gfc_array_index_type,
7535 build_fold_indirect_ref_loc (input_location,
7536 argse.expr));
7537 gfc_add_block_to_block (&se->pre, &argse.pre);
7538 gfc_add_block_to_block (&se->post, &argse.post);
7540 else
7541 tmp = NULL_TREE;
7543 /* Separate array and scalar results. */
7544 if (scalar_mold && tmp == NULL_TREE)
7545 goto scalar_transfer;
7547 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7548 if (tmp != NULL_TREE)
7549 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7550 tmp, dest_word_len);
7551 else
7552 tmp = source_bytes;
7554 gfc_add_modify (&se->pre, size_bytes, tmp);
7555 gfc_add_modify (&se->pre, size_words,
7556 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7557 gfc_array_index_type,
7558 size_bytes, dest_word_len));
7560 /* Evaluate the bounds of the result. If the loop range exists, we have
7561 to check if it is too large. If so, we modify loop->to be consistent
7562 with min(size, size(source)). Otherwise, size is made consistent with
7563 the loop range, so that the right number of bytes is transferred.*/
7564 n = se->loop->order[0];
7565 if (se->loop->to[n] != NULL_TREE)
7567 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7568 se->loop->to[n], se->loop->from[n]);
7569 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7570 tmp, gfc_index_one_node);
7571 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7572 tmp, size_words);
7573 gfc_add_modify (&se->pre, size_words, tmp);
7574 gfc_add_modify (&se->pre, size_bytes,
7575 fold_build2_loc (input_location, MULT_EXPR,
7576 gfc_array_index_type,
7577 size_words, dest_word_len));
7578 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7579 size_words, se->loop->from[n]);
7580 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7581 upper, gfc_index_one_node);
7583 else
7585 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7586 size_words, gfc_index_one_node);
7587 se->loop->from[n] = gfc_index_zero_node;
7590 se->loop->to[n] = upper;
7592 /* Build a destination descriptor, using the pointer, source, as the
7593 data field. */
7594 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7595 NULL_TREE, false, true, false, &expr->where);
7597 /* Cast the pointer to the result. */
7598 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7599 tmp = fold_convert (pvoid_type_node, tmp);
7601 /* Use memcpy to do the transfer. */
7603 = build_call_expr_loc (input_location,
7604 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7605 fold_convert (pvoid_type_node, source),
7606 fold_convert (size_type_node,
7607 fold_build2_loc (input_location,
7608 MIN_EXPR,
7609 gfc_array_index_type,
7610 size_bytes,
7611 source_bytes)));
7612 gfc_add_expr_to_block (&se->pre, tmp);
7614 se->expr = info->descriptor;
7615 if (expr->ts.type == BT_CHARACTER)
7616 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7618 return;
7620 /* Deal with scalar results. */
7621 scalar_transfer:
7622 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7623 dest_word_len, source_bytes);
7624 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7625 extent, gfc_index_zero_node);
7627 if (expr->ts.type == BT_CHARACTER)
7629 tree direct, indirect, free;
7631 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7632 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7633 "transfer");
7635 /* If source is longer than the destination, use a pointer to
7636 the source directly. */
7637 gfc_init_block (&block);
7638 gfc_add_modify (&block, tmpdecl, ptr);
7639 direct = gfc_finish_block (&block);
7641 /* Otherwise, allocate a string with the length of the destination
7642 and copy the source into it. */
7643 gfc_init_block (&block);
7644 tmp = gfc_get_pchar_type (expr->ts.kind);
7645 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7646 gfc_add_modify (&block, tmpdecl,
7647 fold_convert (TREE_TYPE (ptr), tmp));
7648 tmp = build_call_expr_loc (input_location,
7649 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7650 fold_convert (pvoid_type_node, tmpdecl),
7651 fold_convert (pvoid_type_node, ptr),
7652 fold_convert (size_type_node, extent));
7653 gfc_add_expr_to_block (&block, tmp);
7654 indirect = gfc_finish_block (&block);
7656 /* Wrap it up with the condition. */
7657 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7658 dest_word_len, source_bytes);
7659 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7660 gfc_add_expr_to_block (&se->pre, tmp);
7662 /* Free the temporary string, if necessary. */
7663 free = gfc_call_free (tmpdecl);
7664 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7665 dest_word_len, source_bytes);
7666 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7667 gfc_add_expr_to_block (&se->post, tmp);
7669 se->expr = tmpdecl;
7670 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7672 else
7674 tmpdecl = gfc_create_var (mold_type, "transfer");
7676 ptr = convert (build_pointer_type (mold_type), source);
7678 /* For CLASS results, allocate the needed memory first. */
7679 if (mold_expr->ts.type == BT_CLASS)
7681 tree cdata;
7682 cdata = gfc_class_data_get (tmpdecl);
7683 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7684 gfc_add_modify (&se->pre, cdata, tmp);
7687 /* Use memcpy to do the transfer. */
7688 if (mold_expr->ts.type == BT_CLASS)
7689 tmp = gfc_class_data_get (tmpdecl);
7690 else
7691 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7693 tmp = build_call_expr_loc (input_location,
7694 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7695 fold_convert (pvoid_type_node, tmp),
7696 fold_convert (pvoid_type_node, ptr),
7697 fold_convert (size_type_node, extent));
7698 gfc_add_expr_to_block (&se->pre, tmp);
7700 /* For CLASS results, set the _vptr. */
7701 if (mold_expr->ts.type == BT_CLASS)
7703 tree vptr;
7704 gfc_symbol *vtab;
7705 vptr = gfc_class_vptr_get (tmpdecl);
7706 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7707 gcc_assert (vtab);
7708 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7709 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7712 se->expr = tmpdecl;
7717 /* Generate a call to caf_is_present. */
7719 static tree
7720 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7722 tree caf_reference, caf_decl, token, image_index;
7724 /* Compile the reference chain. */
7725 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7726 gcc_assert (caf_reference != NULL_TREE);
7728 caf_decl = gfc_get_tree_for_caf_expr (expr);
7729 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7730 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7731 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7732 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7733 expr);
7735 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7736 3, token, image_index, caf_reference);
7740 /* Test whether this ref-chain refs this image only. */
7742 static bool
7743 caf_this_image_ref (gfc_ref *ref)
7745 for ( ; ref; ref = ref->next)
7746 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7747 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7749 return false;
7753 /* Generate code for the ALLOCATED intrinsic.
7754 Generate inline code that directly check the address of the argument. */
7756 static void
7757 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7759 gfc_actual_arglist *arg1;
7760 gfc_se arg1se;
7761 tree tmp;
7762 symbol_attribute caf_attr;
7764 gfc_init_se (&arg1se, NULL);
7765 arg1 = expr->value.function.actual;
7767 if (arg1->expr->ts.type == BT_CLASS)
7769 /* Make sure that class array expressions have both a _data
7770 component reference and an array reference.... */
7771 if (CLASS_DATA (arg1->expr)->attr.dimension)
7772 gfc_add_class_array_ref (arg1->expr);
7773 /* .... whilst scalars only need the _data component. */
7774 else
7775 gfc_add_data_component (arg1->expr);
7778 /* When arg1 references an allocatable component in a coarray, then call
7779 the caf-library function caf_is_present (). */
7780 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7781 && arg1->expr->value.function.isym
7782 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7783 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7784 else
7785 gfc_clear_attr (&caf_attr);
7786 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7787 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7788 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7789 else
7791 if (arg1->expr->rank == 0)
7793 /* Allocatable scalar. */
7794 arg1se.want_pointer = 1;
7795 gfc_conv_expr (&arg1se, arg1->expr);
7796 tmp = arg1se.expr;
7798 else
7800 /* Allocatable array. */
7801 arg1se.descriptor_only = 1;
7802 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7803 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7806 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
7807 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7810 /* Components of pointer array references sometimes come back with a pre block. */
7811 if (arg1se.pre.head)
7812 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7814 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7818 /* Generate code for the ASSOCIATED intrinsic.
7819 If both POINTER and TARGET are arrays, generate a call to library function
7820 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7821 In other cases, generate inline code that directly compare the address of
7822 POINTER with the address of TARGET. */
7824 static void
7825 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7827 gfc_actual_arglist *arg1;
7828 gfc_actual_arglist *arg2;
7829 gfc_se arg1se;
7830 gfc_se arg2se;
7831 tree tmp2;
7832 tree tmp;
7833 tree nonzero_charlen;
7834 tree nonzero_arraylen;
7835 gfc_ss *ss;
7836 bool scalar;
7838 gfc_init_se (&arg1se, NULL);
7839 gfc_init_se (&arg2se, NULL);
7840 arg1 = expr->value.function.actual;
7841 arg2 = arg1->next;
7843 /* Check whether the expression is a scalar or not; we cannot use
7844 arg1->expr->rank as it can be nonzero for proc pointers. */
7845 ss = gfc_walk_expr (arg1->expr);
7846 scalar = ss == gfc_ss_terminator;
7847 if (!scalar)
7848 gfc_free_ss_chain (ss);
7850 if (!arg2->expr)
7852 /* No optional target. */
7853 if (scalar)
7855 /* A pointer to a scalar. */
7856 arg1se.want_pointer = 1;
7857 gfc_conv_expr (&arg1se, arg1->expr);
7858 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7859 && arg1->expr->symtree->n.sym->attr.dummy)
7860 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7861 arg1se.expr);
7862 if (arg1->expr->ts.type == BT_CLASS)
7864 tmp2 = gfc_class_data_get (arg1se.expr);
7865 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7866 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7868 else
7869 tmp2 = arg1se.expr;
7871 else
7873 /* A pointer to an array. */
7874 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7875 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7877 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7878 gfc_add_block_to_block (&se->post, &arg1se.post);
7879 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
7880 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7881 se->expr = tmp;
7883 else
7885 /* An optional target. */
7886 if (arg2->expr->ts.type == BT_CLASS)
7887 gfc_add_data_component (arg2->expr);
7889 nonzero_charlen = NULL_TREE;
7890 if (arg1->expr->ts.type == BT_CHARACTER)
7891 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7892 logical_type_node,
7893 arg1->expr->ts.u.cl->backend_decl,
7894 build_zero_cst
7895 (TREE_TYPE (arg1->expr->ts.u.cl->backend_decl)));
7896 if (scalar)
7898 /* A pointer to a scalar. */
7899 arg1se.want_pointer = 1;
7900 gfc_conv_expr (&arg1se, arg1->expr);
7901 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7902 && arg1->expr->symtree->n.sym->attr.dummy)
7903 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7904 arg1se.expr);
7905 if (arg1->expr->ts.type == BT_CLASS)
7906 arg1se.expr = gfc_class_data_get (arg1se.expr);
7908 arg2se.want_pointer = 1;
7909 gfc_conv_expr (&arg2se, arg2->expr);
7910 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7911 && arg2->expr->symtree->n.sym->attr.dummy)
7912 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7913 arg2se.expr);
7914 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7915 gfc_add_block_to_block (&se->post, &arg1se.post);
7916 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7917 gfc_add_block_to_block (&se->post, &arg2se.post);
7918 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7919 arg1se.expr, arg2se.expr);
7920 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7921 arg1se.expr, null_pointer_node);
7922 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7923 logical_type_node, tmp, tmp2);
7925 else
7927 /* An array pointer of zero length is not associated if target is
7928 present. */
7929 arg1se.descriptor_only = 1;
7930 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7931 if (arg1->expr->rank == -1)
7933 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7934 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7935 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7937 else
7938 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7939 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7940 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7941 logical_type_node, tmp,
7942 build_int_cst (TREE_TYPE (tmp), 0));
7944 /* A pointer to an array, call library function _gfor_associated. */
7945 arg1se.want_pointer = 1;
7946 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7947 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7948 gfc_add_block_to_block (&se->post, &arg1se.post);
7950 arg2se.want_pointer = 1;
7951 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7952 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7953 gfc_add_block_to_block (&se->post, &arg2se.post);
7954 se->expr = build_call_expr_loc (input_location,
7955 gfor_fndecl_associated, 2,
7956 arg1se.expr, arg2se.expr);
7957 se->expr = convert (logical_type_node, se->expr);
7958 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7959 logical_type_node, se->expr,
7960 nonzero_arraylen);
7963 /* If target is present zero character length pointers cannot
7964 be associated. */
7965 if (nonzero_charlen != NULL_TREE)
7966 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7967 logical_type_node,
7968 se->expr, nonzero_charlen);
7971 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7975 /* Generate code for the SAME_TYPE_AS intrinsic.
7976 Generate inline code that directly checks the vindices. */
7978 static void
7979 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7981 gfc_expr *a, *b;
7982 gfc_se se1, se2;
7983 tree tmp;
7984 tree conda = NULL_TREE, condb = NULL_TREE;
7986 gfc_init_se (&se1, NULL);
7987 gfc_init_se (&se2, NULL);
7989 a = expr->value.function.actual->expr;
7990 b = expr->value.function.actual->next->expr;
7992 if (UNLIMITED_POLY (a))
7994 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
7995 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7996 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7999 if (UNLIMITED_POLY (b))
8001 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
8002 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8003 tmp, build_int_cst (TREE_TYPE (tmp), 0));
8006 if (a->ts.type == BT_CLASS)
8008 gfc_add_vptr_component (a);
8009 gfc_add_hash_component (a);
8011 else if (a->ts.type == BT_DERIVED)
8012 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8013 a->ts.u.derived->hash_value);
8015 if (b->ts.type == BT_CLASS)
8017 gfc_add_vptr_component (b);
8018 gfc_add_hash_component (b);
8020 else if (b->ts.type == BT_DERIVED)
8021 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8022 b->ts.u.derived->hash_value);
8024 gfc_conv_expr (&se1, a);
8025 gfc_conv_expr (&se2, b);
8027 tmp = fold_build2_loc (input_location, EQ_EXPR,
8028 logical_type_node, se1.expr,
8029 fold_convert (TREE_TYPE (se1.expr), se2.expr));
8031 if (conda)
8032 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8033 logical_type_node, conda, tmp);
8035 if (condb)
8036 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8037 logical_type_node, condb, tmp);
8039 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8043 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
8045 static void
8046 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
8048 tree args[2];
8050 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8051 se->expr = build_call_expr_loc (input_location,
8052 gfor_fndecl_sc_kind, 2, args[0], args[1]);
8053 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8057 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
8059 static void
8060 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
8062 tree arg, type;
8064 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8066 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
8067 type = gfc_get_int_type (4);
8068 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
8070 /* Convert it to the required type. */
8071 type = gfc_typenode_for_spec (&expr->ts);
8072 se->expr = build_call_expr_loc (input_location,
8073 gfor_fndecl_si_kind, 1, arg);
8074 se->expr = fold_convert (type, se->expr);
8078 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
8080 static void
8081 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
8083 gfc_actual_arglist *actual;
8084 tree type;
8085 gfc_se argse;
8086 vec<tree, va_gc> *args = NULL;
8088 for (actual = expr->value.function.actual; actual; actual = actual->next)
8090 gfc_init_se (&argse, se);
8092 /* Pass a NULL pointer for an absent arg. */
8093 if (actual->expr == NULL)
8094 argse.expr = null_pointer_node;
8095 else
8097 gfc_typespec ts;
8098 gfc_clear_ts (&ts);
8100 if (actual->expr->ts.kind != gfc_c_int_kind)
8102 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
8103 ts.type = BT_INTEGER;
8104 ts.kind = gfc_c_int_kind;
8105 gfc_convert_type (actual->expr, &ts, 2);
8107 gfc_conv_expr_reference (&argse, actual->expr);
8110 gfc_add_block_to_block (&se->pre, &argse.pre);
8111 gfc_add_block_to_block (&se->post, &argse.post);
8112 vec_safe_push (args, argse.expr);
8115 /* Convert it to the required type. */
8116 type = gfc_typenode_for_spec (&expr->ts);
8117 se->expr = build_call_expr_loc_vec (input_location,
8118 gfor_fndecl_sr_kind, args);
8119 se->expr = fold_convert (type, se->expr);
8123 /* Generate code for TRIM (A) intrinsic function. */
8125 static void
8126 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
8128 tree var;
8129 tree len;
8130 tree addr;
8131 tree tmp;
8132 tree cond;
8133 tree fndecl;
8134 tree function;
8135 tree *args;
8136 unsigned int num_args;
8138 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
8139 args = XALLOCAVEC (tree, num_args);
8141 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
8142 addr = gfc_build_addr_expr (ppvoid_type_node, var);
8143 len = gfc_create_var (gfc_charlen_type_node, "len");
8145 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
8146 args[0] = gfc_build_addr_expr (NULL_TREE, len);
8147 args[1] = addr;
8149 if (expr->ts.kind == 1)
8150 function = gfor_fndecl_string_trim;
8151 else if (expr->ts.kind == 4)
8152 function = gfor_fndecl_string_trim_char4;
8153 else
8154 gcc_unreachable ();
8156 fndecl = build_addr (function);
8157 tmp = build_call_array_loc (input_location,
8158 TREE_TYPE (TREE_TYPE (function)), fndecl,
8159 num_args, args);
8160 gfc_add_expr_to_block (&se->pre, tmp);
8162 /* Free the temporary afterwards, if necessary. */
8163 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8164 len, build_int_cst (TREE_TYPE (len), 0));
8165 tmp = gfc_call_free (var);
8166 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
8167 gfc_add_expr_to_block (&se->post, tmp);
8169 se->expr = var;
8170 se->string_length = len;
8174 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8176 static void
8177 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
8179 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
8180 tree type, cond, tmp, count, exit_label, n, max, largest;
8181 tree size;
8182 stmtblock_t block, body;
8183 int i;
8185 /* We store in charsize the size of a character. */
8186 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
8187 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
8189 /* Get the arguments. */
8190 gfc_conv_intrinsic_function_args (se, expr, args, 3);
8191 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
8192 src = args[1];
8193 ncopies = gfc_evaluate_now (args[2], &se->pre);
8194 ncopies_type = TREE_TYPE (ncopies);
8196 /* Check that NCOPIES is not negative. */
8197 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
8198 build_int_cst (ncopies_type, 0));
8199 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8200 "Argument NCOPIES of REPEAT intrinsic is negative "
8201 "(its value is %ld)",
8202 fold_convert (long_integer_type_node, ncopies));
8204 /* If the source length is zero, any non negative value of NCOPIES
8205 is valid, and nothing happens. */
8206 n = gfc_create_var (ncopies_type, "ncopies");
8207 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8208 size_zero_node);
8209 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
8210 build_int_cst (ncopies_type, 0), ncopies);
8211 gfc_add_modify (&se->pre, n, tmp);
8212 ncopies = n;
8214 /* Check that ncopies is not too large: ncopies should be less than
8215 (or equal to) MAX / slen, where MAX is the maximal integer of
8216 the gfc_charlen_type_node type. If slen == 0, we need a special
8217 case to avoid the division by zero. */
8218 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
8219 fold_convert (sizetype,
8220 TYPE_MAX_VALUE (gfc_charlen_type_node)),
8221 slen);
8222 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
8223 ? sizetype : ncopies_type;
8224 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8225 fold_convert (largest, ncopies),
8226 fold_convert (largest, max));
8227 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8228 size_zero_node);
8229 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
8230 logical_false_node, cond);
8231 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8232 "Argument NCOPIES of REPEAT intrinsic is too large");
8234 /* Compute the destination length. */
8235 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
8236 fold_convert (gfc_charlen_type_node, slen),
8237 fold_convert (gfc_charlen_type_node, ncopies));
8238 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
8239 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
8241 /* Generate the code to do the repeat operation:
8242 for (i = 0; i < ncopies; i++)
8243 memmove (dest + (i * slen * size), src, slen*size); */
8244 gfc_start_block (&block);
8245 count = gfc_create_var (sizetype, "count");
8246 gfc_add_modify (&block, count, size_zero_node);
8247 exit_label = gfc_build_label_decl (NULL_TREE);
8249 /* Start the loop body. */
8250 gfc_start_block (&body);
8252 /* Exit the loop if count >= ncopies. */
8253 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
8254 fold_convert (sizetype, ncopies));
8255 tmp = build1_v (GOTO_EXPR, exit_label);
8256 TREE_USED (exit_label) = 1;
8257 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
8258 build_empty_stmt (input_location));
8259 gfc_add_expr_to_block (&body, tmp);
8261 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8262 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
8263 count);
8264 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
8265 size);
8266 tmp = fold_build_pointer_plus_loc (input_location,
8267 fold_convert (pvoid_type_node, dest), tmp);
8268 tmp = build_call_expr_loc (input_location,
8269 builtin_decl_explicit (BUILT_IN_MEMMOVE),
8270 3, tmp, src,
8271 fold_build2_loc (input_location, MULT_EXPR,
8272 size_type_node, slen, size));
8273 gfc_add_expr_to_block (&body, tmp);
8275 /* Increment count. */
8276 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
8277 count, size_one_node);
8278 gfc_add_modify (&body, count, tmp);
8280 /* Build the loop. */
8281 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
8282 gfc_add_expr_to_block (&block, tmp);
8284 /* Add the exit label. */
8285 tmp = build1_v (LABEL_EXPR, exit_label);
8286 gfc_add_expr_to_block (&block, tmp);
8288 /* Finish the block. */
8289 tmp = gfc_finish_block (&block);
8290 gfc_add_expr_to_block (&se->pre, tmp);
8292 /* Set the result value. */
8293 se->expr = dest;
8294 se->string_length = dlen;
8298 /* Generate code for the IARGC intrinsic. */
8300 static void
8301 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
8303 tree tmp;
8304 tree fndecl;
8305 tree type;
8307 /* Call the library function. This always returns an INTEGER(4). */
8308 fndecl = gfor_fndecl_iargc;
8309 tmp = build_call_expr_loc (input_location,
8310 fndecl, 0);
8312 /* Convert it to the required type. */
8313 type = gfc_typenode_for_spec (&expr->ts);
8314 tmp = fold_convert (type, tmp);
8316 se->expr = tmp;
8320 /* Generate code for the KILL intrinsic. */
8322 static void
8323 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
8325 tree *args;
8326 tree int4_type_node = gfc_get_int_type (4);
8327 tree pid;
8328 tree sig;
8329 tree tmp;
8330 unsigned int num_args;
8332 num_args = gfc_intrinsic_argument_list_length (expr);
8333 args = XALLOCAVEC (tree, num_args);
8334 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8336 /* Convert PID to a INTEGER(4) entity. */
8337 pid = convert (int4_type_node, args[0]);
8339 /* Convert SIG to a INTEGER(4) entity. */
8340 sig = convert (int4_type_node, args[1]);
8342 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
8344 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
8348 static tree
8349 conv_intrinsic_kill_sub (gfc_code *code)
8351 stmtblock_t block;
8352 gfc_se se, se_stat;
8353 tree int4_type_node = gfc_get_int_type (4);
8354 tree pid;
8355 tree sig;
8356 tree statp;
8357 tree tmp;
8359 /* Make the function call. */
8360 gfc_init_block (&block);
8361 gfc_init_se (&se, NULL);
8363 /* Convert PID to a INTEGER(4) entity. */
8364 gfc_conv_expr (&se, code->ext.actual->expr);
8365 gfc_add_block_to_block (&block, &se.pre);
8366 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8367 gfc_add_block_to_block (&block, &se.post);
8369 /* Convert SIG to a INTEGER(4) entity. */
8370 gfc_conv_expr (&se, code->ext.actual->next->expr);
8371 gfc_add_block_to_block (&block, &se.pre);
8372 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8373 gfc_add_block_to_block (&block, &se.post);
8375 /* Deal with an optional STATUS. */
8376 if (code->ext.actual->next->next->expr)
8378 gfc_init_se (&se_stat, NULL);
8379 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
8380 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
8382 else
8383 statp = NULL_TREE;
8385 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
8386 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
8388 gfc_add_expr_to_block (&block, tmp);
8390 if (statp && statp != se_stat.expr)
8391 gfc_add_modify (&block, se_stat.expr,
8392 fold_convert (TREE_TYPE (se_stat.expr), statp));
8394 return gfc_finish_block (&block);
8399 /* The loc intrinsic returns the address of its argument as
8400 gfc_index_integer_kind integer. */
8402 static void
8403 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8405 tree temp_var;
8406 gfc_expr *arg_expr;
8408 gcc_assert (!se->ss);
8410 arg_expr = expr->value.function.actual->expr;
8411 if (arg_expr->rank == 0)
8413 if (arg_expr->ts.type == BT_CLASS)
8414 gfc_add_data_component (arg_expr);
8415 gfc_conv_expr_reference (se, arg_expr);
8417 else
8418 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8419 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8421 /* Create a temporary variable for loc return value. Without this,
8422 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8423 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8424 gfc_add_modify (&se->pre, temp_var, se->expr);
8425 se->expr = temp_var;
8429 /* The following routine generates code for the intrinsic
8430 functions from the ISO_C_BINDING module:
8431 * C_LOC
8432 * C_FUNLOC
8433 * C_ASSOCIATED */
8435 static void
8436 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8438 gfc_actual_arglist *arg = expr->value.function.actual;
8440 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8442 if (arg->expr->rank == 0)
8443 gfc_conv_expr_reference (se, arg->expr);
8444 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8445 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8446 else
8448 gfc_conv_expr_descriptor (se, arg->expr);
8449 se->expr = gfc_conv_descriptor_data_get (se->expr);
8452 /* TODO -- the following two lines shouldn't be necessary, but if
8453 they're removed, a bug is exposed later in the code path.
8454 This workaround was thus introduced, but will have to be
8455 removed; please see PR 35150 for details about the issue. */
8456 se->expr = convert (pvoid_type_node, se->expr);
8457 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8459 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8460 gfc_conv_expr_reference (se, arg->expr);
8461 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8463 gfc_se arg1se;
8464 gfc_se arg2se;
8466 /* Build the addr_expr for the first argument. The argument is
8467 already an *address* so we don't need to set want_pointer in
8468 the gfc_se. */
8469 gfc_init_se (&arg1se, NULL);
8470 gfc_conv_expr (&arg1se, arg->expr);
8471 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8472 gfc_add_block_to_block (&se->post, &arg1se.post);
8474 /* See if we were given two arguments. */
8475 if (arg->next->expr == NULL)
8476 /* Only given one arg so generate a null and do a
8477 not-equal comparison against the first arg. */
8478 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8479 arg1se.expr,
8480 fold_convert (TREE_TYPE (arg1se.expr),
8481 null_pointer_node));
8482 else
8484 tree eq_expr;
8485 tree not_null_expr;
8487 /* Given two arguments so build the arg2se from second arg. */
8488 gfc_init_se (&arg2se, NULL);
8489 gfc_conv_expr (&arg2se, arg->next->expr);
8490 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8491 gfc_add_block_to_block (&se->post, &arg2se.post);
8493 /* Generate test to compare that the two args are equal. */
8494 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8495 arg1se.expr, arg2se.expr);
8496 /* Generate test to ensure that the first arg is not null. */
8497 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8498 logical_type_node,
8499 arg1se.expr, null_pointer_node);
8501 /* Finally, the generated test must check that both arg1 is not
8502 NULL and that it is equal to the second arg. */
8503 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8504 logical_type_node,
8505 not_null_expr, eq_expr);
8508 else
8509 gcc_unreachable ();
8513 /* The following routine generates code for the intrinsic
8514 subroutines from the ISO_C_BINDING module:
8515 * C_F_POINTER
8516 * C_F_PROCPOINTER. */
8518 static tree
8519 conv_isocbinding_subroutine (gfc_code *code)
8521 gfc_se se;
8522 gfc_se cptrse;
8523 gfc_se fptrse;
8524 gfc_se shapese;
8525 gfc_ss *shape_ss;
8526 tree desc, dim, tmp, stride, offset;
8527 stmtblock_t body, block;
8528 gfc_loopinfo loop;
8529 gfc_actual_arglist *arg = code->ext.actual;
8531 gfc_init_se (&se, NULL);
8532 gfc_init_se (&cptrse, NULL);
8533 gfc_conv_expr (&cptrse, arg->expr);
8534 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8535 gfc_add_block_to_block (&se.post, &cptrse.post);
8537 gfc_init_se (&fptrse, NULL);
8538 if (arg->next->expr->rank == 0)
8540 fptrse.want_pointer = 1;
8541 gfc_conv_expr (&fptrse, arg->next->expr);
8542 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8543 gfc_add_block_to_block (&se.post, &fptrse.post);
8544 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8545 && arg->next->expr->symtree->n.sym->attr.dummy)
8546 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8547 fptrse.expr);
8548 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8549 TREE_TYPE (fptrse.expr),
8550 fptrse.expr,
8551 fold_convert (TREE_TYPE (fptrse.expr),
8552 cptrse.expr));
8553 gfc_add_expr_to_block (&se.pre, se.expr);
8554 gfc_add_block_to_block (&se.pre, &se.post);
8555 return gfc_finish_block (&se.pre);
8558 gfc_start_block (&block);
8560 /* Get the descriptor of the Fortran pointer. */
8561 fptrse.descriptor_only = 1;
8562 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8563 gfc_add_block_to_block (&block, &fptrse.pre);
8564 desc = fptrse.expr;
8566 /* Set the span field. */
8567 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8568 tmp = fold_convert (gfc_array_index_type, tmp);
8569 gfc_conv_descriptor_span_set (&block, desc, tmp);
8571 /* Set data value, dtype, and offset. */
8572 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8573 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8574 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8575 gfc_get_dtype (TREE_TYPE (desc)));
8577 /* Start scalarization of the bounds, using the shape argument. */
8579 shape_ss = gfc_walk_expr (arg->next->next->expr);
8580 gcc_assert (shape_ss != gfc_ss_terminator);
8581 gfc_init_se (&shapese, NULL);
8583 gfc_init_loopinfo (&loop);
8584 gfc_add_ss_to_loop (&loop, shape_ss);
8585 gfc_conv_ss_startstride (&loop);
8586 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8587 gfc_mark_ss_chain_used (shape_ss, 1);
8589 gfc_copy_loopinfo_to_se (&shapese, &loop);
8590 shapese.ss = shape_ss;
8592 stride = gfc_create_var (gfc_array_index_type, "stride");
8593 offset = gfc_create_var (gfc_array_index_type, "offset");
8594 gfc_add_modify (&block, stride, gfc_index_one_node);
8595 gfc_add_modify (&block, offset, gfc_index_zero_node);
8597 /* Loop body. */
8598 gfc_start_scalarized_body (&loop, &body);
8600 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8601 loop.loopvar[0], loop.from[0]);
8603 /* Set bounds and stride. */
8604 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8605 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8607 gfc_conv_expr (&shapese, arg->next->next->expr);
8608 gfc_add_block_to_block (&body, &shapese.pre);
8609 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8610 gfc_add_block_to_block (&body, &shapese.post);
8612 /* Calculate offset. */
8613 gfc_add_modify (&body, offset,
8614 fold_build2_loc (input_location, PLUS_EXPR,
8615 gfc_array_index_type, offset, stride));
8616 /* Update stride. */
8617 gfc_add_modify (&body, stride,
8618 fold_build2_loc (input_location, MULT_EXPR,
8619 gfc_array_index_type, stride,
8620 fold_convert (gfc_array_index_type,
8621 shapese.expr)));
8622 /* Finish scalarization loop. */
8623 gfc_trans_scalarizing_loops (&loop, &body);
8624 gfc_add_block_to_block (&block, &loop.pre);
8625 gfc_add_block_to_block (&block, &loop.post);
8626 gfc_add_block_to_block (&block, &fptrse.post);
8627 gfc_cleanup_loop (&loop);
8629 gfc_add_modify (&block, offset,
8630 fold_build1_loc (input_location, NEGATE_EXPR,
8631 gfc_array_index_type, offset));
8632 gfc_conv_descriptor_offset_set (&block, desc, offset);
8634 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8635 gfc_add_block_to_block (&se.pre, &se.post);
8636 return gfc_finish_block (&se.pre);
8640 /* Save and restore floating-point state. */
8642 tree
8643 gfc_save_fp_state (stmtblock_t *block)
8645 tree type, fpstate, tmp;
8647 type = build_array_type (char_type_node,
8648 build_range_type (size_type_node, size_zero_node,
8649 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8650 fpstate = gfc_create_var (type, "fpstate");
8651 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8653 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8654 1, fpstate);
8655 gfc_add_expr_to_block (block, tmp);
8657 return fpstate;
8661 void
8662 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8664 tree tmp;
8666 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8667 1, fpstate);
8668 gfc_add_expr_to_block (block, tmp);
8672 /* Generate code for arguments of IEEE functions. */
8674 static void
8675 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8676 int nargs)
8678 gfc_actual_arglist *actual;
8679 gfc_expr *e;
8680 gfc_se argse;
8681 int arg;
8683 actual = expr->value.function.actual;
8684 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8686 gcc_assert (actual);
8687 e = actual->expr;
8689 gfc_init_se (&argse, se);
8690 gfc_conv_expr_val (&argse, e);
8692 gfc_add_block_to_block (&se->pre, &argse.pre);
8693 gfc_add_block_to_block (&se->post, &argse.post);
8694 argarray[arg] = argse.expr;
8699 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8700 and IEEE_UNORDERED, which translate directly to GCC type-generic
8701 built-ins. */
8703 static void
8704 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8705 enum built_in_function code, int nargs)
8707 tree args[2];
8708 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8710 conv_ieee_function_args (se, expr, args, nargs);
8711 se->expr = build_call_expr_loc_array (input_location,
8712 builtin_decl_explicit (code),
8713 nargs, args);
8714 STRIP_TYPE_NOPS (se->expr);
8715 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8719 /* Generate code for IEEE_IS_NORMAL intrinsic:
8720 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8722 static void
8723 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8725 tree arg, isnormal, iszero;
8727 /* Convert arg, evaluate it only once. */
8728 conv_ieee_function_args (se, expr, &arg, 1);
8729 arg = gfc_evaluate_now (arg, &se->pre);
8731 isnormal = build_call_expr_loc (input_location,
8732 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8733 1, arg);
8734 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8735 build_real_from_int_cst (TREE_TYPE (arg),
8736 integer_zero_node));
8737 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8738 logical_type_node, isnormal, iszero);
8739 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8743 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8744 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8746 static void
8747 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8749 tree arg, signbit, isnan;
8751 /* Convert arg, evaluate it only once. */
8752 conv_ieee_function_args (se, expr, &arg, 1);
8753 arg = gfc_evaluate_now (arg, &se->pre);
8755 isnan = build_call_expr_loc (input_location,
8756 builtin_decl_explicit (BUILT_IN_ISNAN),
8757 1, arg);
8758 STRIP_TYPE_NOPS (isnan);
8760 signbit = build_call_expr_loc (input_location,
8761 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8762 1, arg);
8763 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8764 signbit, integer_zero_node);
8766 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8767 logical_type_node, signbit,
8768 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8769 TREE_TYPE(isnan), isnan));
8771 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8775 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8777 static void
8778 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8779 enum built_in_function code)
8781 tree arg, decl, call, fpstate;
8782 int argprec;
8784 conv_ieee_function_args (se, expr, &arg, 1);
8785 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8786 decl = builtin_decl_for_precision (code, argprec);
8788 /* Save floating-point state. */
8789 fpstate = gfc_save_fp_state (&se->pre);
8791 /* Make the function call. */
8792 call = build_call_expr_loc (input_location, decl, 1, arg);
8793 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8795 /* Restore floating-point state. */
8796 gfc_restore_fp_state (&se->post, fpstate);
8800 /* Generate code for IEEE_REM. */
8802 static void
8803 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8805 tree args[2], decl, call, fpstate;
8806 int argprec;
8808 conv_ieee_function_args (se, expr, args, 2);
8810 /* If arguments have unequal size, convert them to the larger. */
8811 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8812 > TYPE_PRECISION (TREE_TYPE (args[1])))
8813 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8814 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8815 > TYPE_PRECISION (TREE_TYPE (args[0])))
8816 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8818 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8819 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8821 /* Save floating-point state. */
8822 fpstate = gfc_save_fp_state (&se->pre);
8824 /* Make the function call. */
8825 call = build_call_expr_loc_array (input_location, decl, 2, args);
8826 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8828 /* Restore floating-point state. */
8829 gfc_restore_fp_state (&se->post, fpstate);
8833 /* Generate code for IEEE_NEXT_AFTER. */
8835 static void
8836 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8838 tree args[2], decl, call, fpstate;
8839 int argprec;
8841 conv_ieee_function_args (se, expr, args, 2);
8843 /* Result has the characteristics of first argument. */
8844 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8845 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8846 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8848 /* Save floating-point state. */
8849 fpstate = gfc_save_fp_state (&se->pre);
8851 /* Make the function call. */
8852 call = build_call_expr_loc_array (input_location, decl, 2, args);
8853 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8855 /* Restore floating-point state. */
8856 gfc_restore_fp_state (&se->post, fpstate);
8860 /* Generate code for IEEE_SCALB. */
8862 static void
8863 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8865 tree args[2], decl, call, huge, type;
8866 int argprec, n;
8868 conv_ieee_function_args (se, expr, args, 2);
8870 /* Result has the characteristics of first argument. */
8871 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8872 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8874 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8876 /* We need to fold the integer into the range of a C int. */
8877 args[1] = gfc_evaluate_now (args[1], &se->pre);
8878 type = TREE_TYPE (args[1]);
8880 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8881 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8882 gfc_c_int_kind);
8883 huge = fold_convert (type, huge);
8884 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8885 huge);
8886 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8887 fold_build1_loc (input_location, NEGATE_EXPR,
8888 type, huge));
8891 args[1] = fold_convert (integer_type_node, args[1]);
8893 /* Make the function call. */
8894 call = build_call_expr_loc_array (input_location, decl, 2, args);
8895 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8899 /* Generate code for IEEE_COPY_SIGN. */
8901 static void
8902 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8904 tree args[2], decl, sign;
8905 int argprec;
8907 conv_ieee_function_args (se, expr, args, 2);
8909 /* Get the sign of the second argument. */
8910 sign = build_call_expr_loc (input_location,
8911 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8912 1, args[1]);
8913 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8914 sign, integer_zero_node);
8916 /* Create a value of one, with the right sign. */
8917 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8918 sign,
8919 fold_build1_loc (input_location, NEGATE_EXPR,
8920 integer_type_node,
8921 integer_one_node),
8922 integer_one_node);
8923 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8925 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8926 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8928 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8932 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8933 module. */
8935 bool
8936 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8938 const char *name = expr->value.function.name;
8940 if (gfc_str_startswith (name, "_gfortran_ieee_is_nan"))
8941 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8942 else if (gfc_str_startswith (name, "_gfortran_ieee_is_finite"))
8943 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8944 else if (gfc_str_startswith (name, "_gfortran_ieee_unordered"))
8945 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8946 else if (gfc_str_startswith (name, "_gfortran_ieee_is_normal"))
8947 conv_intrinsic_ieee_is_normal (se, expr);
8948 else if (gfc_str_startswith (name, "_gfortran_ieee_is_negative"))
8949 conv_intrinsic_ieee_is_negative (se, expr);
8950 else if (gfc_str_startswith (name, "_gfortran_ieee_copy_sign"))
8951 conv_intrinsic_ieee_copy_sign (se, expr);
8952 else if (gfc_str_startswith (name, "_gfortran_ieee_scalb"))
8953 conv_intrinsic_ieee_scalb (se, expr);
8954 else if (gfc_str_startswith (name, "_gfortran_ieee_next_after"))
8955 conv_intrinsic_ieee_next_after (se, expr);
8956 else if (gfc_str_startswith (name, "_gfortran_ieee_rem"))
8957 conv_intrinsic_ieee_rem (se, expr);
8958 else if (gfc_str_startswith (name, "_gfortran_ieee_logb"))
8959 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8960 else if (gfc_str_startswith (name, "_gfortran_ieee_rint"))
8961 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8962 else
8963 /* It is not among the functions we translate directly. We return
8964 false, so a library function call is emitted. */
8965 return false;
8967 return true;
8971 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8973 static void
8974 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8976 tree arg, res, restype;
8978 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8979 arg = fold_convert (size_type_node, arg);
8980 res = build_call_expr_loc (input_location,
8981 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8982 restype = gfc_typenode_for_spec (&expr->ts);
8983 se->expr = fold_convert (restype, res);
8987 /* Generate code for an intrinsic function. Some map directly to library
8988 calls, others get special handling. In some cases the name of the function
8989 used depends on the type specifiers. */
8991 void
8992 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8994 const char *name;
8995 int lib, kind;
8996 tree fndecl;
8998 name = &expr->value.function.name[2];
9000 if (expr->rank > 0)
9002 lib = gfc_is_intrinsic_libcall (expr);
9003 if (lib != 0)
9005 if (lib == 1)
9006 se->ignore_optional = 1;
9008 switch (expr->value.function.isym->id)
9010 case GFC_ISYM_EOSHIFT:
9011 case GFC_ISYM_PACK:
9012 case GFC_ISYM_RESHAPE:
9013 /* For all of those the first argument specifies the type and the
9014 third is optional. */
9015 conv_generic_with_optional_char_arg (se, expr, 1, 3);
9016 break;
9018 case GFC_ISYM_MINLOC:
9019 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9020 break;
9022 case GFC_ISYM_MAXLOC:
9023 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9024 break;
9026 case GFC_ISYM_SHAPE:
9027 gfc_conv_intrinsic_shape (se, expr);
9028 break;
9030 default:
9031 gfc_conv_intrinsic_funcall (se, expr);
9032 break;
9035 return;
9039 switch (expr->value.function.isym->id)
9041 case GFC_ISYM_NONE:
9042 gcc_unreachable ();
9044 case GFC_ISYM_REPEAT:
9045 gfc_conv_intrinsic_repeat (se, expr);
9046 break;
9048 case GFC_ISYM_TRIM:
9049 gfc_conv_intrinsic_trim (se, expr);
9050 break;
9052 case GFC_ISYM_SC_KIND:
9053 gfc_conv_intrinsic_sc_kind (se, expr);
9054 break;
9056 case GFC_ISYM_SI_KIND:
9057 gfc_conv_intrinsic_si_kind (se, expr);
9058 break;
9060 case GFC_ISYM_SR_KIND:
9061 gfc_conv_intrinsic_sr_kind (se, expr);
9062 break;
9064 case GFC_ISYM_EXPONENT:
9065 gfc_conv_intrinsic_exponent (se, expr);
9066 break;
9068 case GFC_ISYM_SCAN:
9069 kind = expr->value.function.actual->expr->ts.kind;
9070 if (kind == 1)
9071 fndecl = gfor_fndecl_string_scan;
9072 else if (kind == 4)
9073 fndecl = gfor_fndecl_string_scan_char4;
9074 else
9075 gcc_unreachable ();
9077 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9078 break;
9080 case GFC_ISYM_VERIFY:
9081 kind = expr->value.function.actual->expr->ts.kind;
9082 if (kind == 1)
9083 fndecl = gfor_fndecl_string_verify;
9084 else if (kind == 4)
9085 fndecl = gfor_fndecl_string_verify_char4;
9086 else
9087 gcc_unreachable ();
9089 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9090 break;
9092 case GFC_ISYM_ALLOCATED:
9093 gfc_conv_allocated (se, expr);
9094 break;
9096 case GFC_ISYM_ASSOCIATED:
9097 gfc_conv_associated(se, expr);
9098 break;
9100 case GFC_ISYM_SAME_TYPE_AS:
9101 gfc_conv_same_type_as (se, expr);
9102 break;
9104 case GFC_ISYM_ABS:
9105 gfc_conv_intrinsic_abs (se, expr);
9106 break;
9108 case GFC_ISYM_ADJUSTL:
9109 if (expr->ts.kind == 1)
9110 fndecl = gfor_fndecl_adjustl;
9111 else if (expr->ts.kind == 4)
9112 fndecl = gfor_fndecl_adjustl_char4;
9113 else
9114 gcc_unreachable ();
9116 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9117 break;
9119 case GFC_ISYM_ADJUSTR:
9120 if (expr->ts.kind == 1)
9121 fndecl = gfor_fndecl_adjustr;
9122 else if (expr->ts.kind == 4)
9123 fndecl = gfor_fndecl_adjustr_char4;
9124 else
9125 gcc_unreachable ();
9127 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9128 break;
9130 case GFC_ISYM_AIMAG:
9131 gfc_conv_intrinsic_imagpart (se, expr);
9132 break;
9134 case GFC_ISYM_AINT:
9135 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
9136 break;
9138 case GFC_ISYM_ALL:
9139 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
9140 break;
9142 case GFC_ISYM_ANINT:
9143 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
9144 break;
9146 case GFC_ISYM_AND:
9147 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9148 break;
9150 case GFC_ISYM_ANY:
9151 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
9152 break;
9154 case GFC_ISYM_BTEST:
9155 gfc_conv_intrinsic_btest (se, expr);
9156 break;
9158 case GFC_ISYM_BGE:
9159 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
9160 break;
9162 case GFC_ISYM_BGT:
9163 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
9164 break;
9166 case GFC_ISYM_BLE:
9167 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
9168 break;
9170 case GFC_ISYM_BLT:
9171 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
9172 break;
9174 case GFC_ISYM_C_ASSOCIATED:
9175 case GFC_ISYM_C_FUNLOC:
9176 case GFC_ISYM_C_LOC:
9177 conv_isocbinding_function (se, expr);
9178 break;
9180 case GFC_ISYM_ACHAR:
9181 case GFC_ISYM_CHAR:
9182 gfc_conv_intrinsic_char (se, expr);
9183 break;
9185 case GFC_ISYM_CONVERSION:
9186 case GFC_ISYM_REAL:
9187 case GFC_ISYM_LOGICAL:
9188 case GFC_ISYM_DBLE:
9189 gfc_conv_intrinsic_conversion (se, expr);
9190 break;
9192 /* Integer conversions are handled separately to make sure we get the
9193 correct rounding mode. */
9194 case GFC_ISYM_INT:
9195 case GFC_ISYM_INT2:
9196 case GFC_ISYM_INT8:
9197 case GFC_ISYM_LONG:
9198 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
9199 break;
9201 case GFC_ISYM_NINT:
9202 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
9203 break;
9205 case GFC_ISYM_CEILING:
9206 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
9207 break;
9209 case GFC_ISYM_FLOOR:
9210 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
9211 break;
9213 case GFC_ISYM_MOD:
9214 gfc_conv_intrinsic_mod (se, expr, 0);
9215 break;
9217 case GFC_ISYM_MODULO:
9218 gfc_conv_intrinsic_mod (se, expr, 1);
9219 break;
9221 case GFC_ISYM_CAF_GET:
9222 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
9223 false, NULL);
9224 break;
9226 case GFC_ISYM_CMPLX:
9227 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
9228 break;
9230 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
9231 gfc_conv_intrinsic_iargc (se, expr);
9232 break;
9234 case GFC_ISYM_COMPLEX:
9235 gfc_conv_intrinsic_cmplx (se, expr, 1);
9236 break;
9238 case GFC_ISYM_CONJG:
9239 gfc_conv_intrinsic_conjg (se, expr);
9240 break;
9242 case GFC_ISYM_COUNT:
9243 gfc_conv_intrinsic_count (se, expr);
9244 break;
9246 case GFC_ISYM_CTIME:
9247 gfc_conv_intrinsic_ctime (se, expr);
9248 break;
9250 case GFC_ISYM_DIM:
9251 gfc_conv_intrinsic_dim (se, expr);
9252 break;
9254 case GFC_ISYM_DOT_PRODUCT:
9255 gfc_conv_intrinsic_dot_product (se, expr);
9256 break;
9258 case GFC_ISYM_DPROD:
9259 gfc_conv_intrinsic_dprod (se, expr);
9260 break;
9262 case GFC_ISYM_DSHIFTL:
9263 gfc_conv_intrinsic_dshift (se, expr, true);
9264 break;
9266 case GFC_ISYM_DSHIFTR:
9267 gfc_conv_intrinsic_dshift (se, expr, false);
9268 break;
9270 case GFC_ISYM_FDATE:
9271 gfc_conv_intrinsic_fdate (se, expr);
9272 break;
9274 case GFC_ISYM_FRACTION:
9275 gfc_conv_intrinsic_fraction (se, expr);
9276 break;
9278 case GFC_ISYM_IALL:
9279 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9280 break;
9282 case GFC_ISYM_IAND:
9283 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9284 break;
9286 case GFC_ISYM_IANY:
9287 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9288 break;
9290 case GFC_ISYM_IBCLR:
9291 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9292 break;
9294 case GFC_ISYM_IBITS:
9295 gfc_conv_intrinsic_ibits (se, expr);
9296 break;
9298 case GFC_ISYM_IBSET:
9299 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9300 break;
9302 case GFC_ISYM_IACHAR:
9303 case GFC_ISYM_ICHAR:
9304 /* We assume ASCII character sequence. */
9305 gfc_conv_intrinsic_ichar (se, expr);
9306 break;
9308 case GFC_ISYM_IARGC:
9309 gfc_conv_intrinsic_iargc (se, expr);
9310 break;
9312 case GFC_ISYM_IEOR:
9313 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9314 break;
9316 case GFC_ISYM_INDEX:
9317 kind = expr->value.function.actual->expr->ts.kind;
9318 if (kind == 1)
9319 fndecl = gfor_fndecl_string_index;
9320 else if (kind == 4)
9321 fndecl = gfor_fndecl_string_index_char4;
9322 else
9323 gcc_unreachable ();
9325 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9326 break;
9328 case GFC_ISYM_IOR:
9329 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9330 break;
9332 case GFC_ISYM_IPARITY:
9333 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9334 break;
9336 case GFC_ISYM_IS_IOSTAT_END:
9337 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9338 break;
9340 case GFC_ISYM_IS_IOSTAT_EOR:
9341 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9342 break;
9344 case GFC_ISYM_ISNAN:
9345 gfc_conv_intrinsic_isnan (se, expr);
9346 break;
9348 case GFC_ISYM_KILL:
9349 conv_intrinsic_kill (se, expr);
9350 break;
9352 case GFC_ISYM_LSHIFT:
9353 gfc_conv_intrinsic_shift (se, expr, false, false);
9354 break;
9356 case GFC_ISYM_RSHIFT:
9357 gfc_conv_intrinsic_shift (se, expr, true, true);
9358 break;
9360 case GFC_ISYM_SHIFTA:
9361 gfc_conv_intrinsic_shift (se, expr, true, true);
9362 break;
9364 case GFC_ISYM_SHIFTL:
9365 gfc_conv_intrinsic_shift (se, expr, false, false);
9366 break;
9368 case GFC_ISYM_SHIFTR:
9369 gfc_conv_intrinsic_shift (se, expr, true, false);
9370 break;
9372 case GFC_ISYM_ISHFT:
9373 gfc_conv_intrinsic_ishft (se, expr);
9374 break;
9376 case GFC_ISYM_ISHFTC:
9377 gfc_conv_intrinsic_ishftc (se, expr);
9378 break;
9380 case GFC_ISYM_LEADZ:
9381 gfc_conv_intrinsic_leadz (se, expr);
9382 break;
9384 case GFC_ISYM_TRAILZ:
9385 gfc_conv_intrinsic_trailz (se, expr);
9386 break;
9388 case GFC_ISYM_POPCNT:
9389 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9390 break;
9392 case GFC_ISYM_POPPAR:
9393 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9394 break;
9396 case GFC_ISYM_LBOUND:
9397 gfc_conv_intrinsic_bound (se, expr, 0);
9398 break;
9400 case GFC_ISYM_LCOBOUND:
9401 conv_intrinsic_cobound (se, expr);
9402 break;
9404 case GFC_ISYM_TRANSPOSE:
9405 /* The scalarizer has already been set up for reversed dimension access
9406 order ; now we just get the argument value normally. */
9407 gfc_conv_expr (se, expr->value.function.actual->expr);
9408 break;
9410 case GFC_ISYM_LEN:
9411 gfc_conv_intrinsic_len (se, expr);
9412 break;
9414 case GFC_ISYM_LEN_TRIM:
9415 gfc_conv_intrinsic_len_trim (se, expr);
9416 break;
9418 case GFC_ISYM_LGE:
9419 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9420 break;
9422 case GFC_ISYM_LGT:
9423 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9424 break;
9426 case GFC_ISYM_LLE:
9427 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9428 break;
9430 case GFC_ISYM_LLT:
9431 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9432 break;
9434 case GFC_ISYM_MALLOC:
9435 gfc_conv_intrinsic_malloc (se, expr);
9436 break;
9438 case GFC_ISYM_MASKL:
9439 gfc_conv_intrinsic_mask (se, expr, 1);
9440 break;
9442 case GFC_ISYM_MASKR:
9443 gfc_conv_intrinsic_mask (se, expr, 0);
9444 break;
9446 case GFC_ISYM_MAX:
9447 if (expr->ts.type == BT_CHARACTER)
9448 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9449 else
9450 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9451 break;
9453 case GFC_ISYM_MAXLOC:
9454 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9455 break;
9457 case GFC_ISYM_MAXVAL:
9458 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9459 break;
9461 case GFC_ISYM_MERGE:
9462 gfc_conv_intrinsic_merge (se, expr);
9463 break;
9465 case GFC_ISYM_MERGE_BITS:
9466 gfc_conv_intrinsic_merge_bits (se, expr);
9467 break;
9469 case GFC_ISYM_MIN:
9470 if (expr->ts.type == BT_CHARACTER)
9471 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9472 else
9473 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9474 break;
9476 case GFC_ISYM_MINLOC:
9477 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9478 break;
9480 case GFC_ISYM_MINVAL:
9481 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9482 break;
9484 case GFC_ISYM_NEAREST:
9485 gfc_conv_intrinsic_nearest (se, expr);
9486 break;
9488 case GFC_ISYM_NORM2:
9489 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9490 break;
9492 case GFC_ISYM_NOT:
9493 gfc_conv_intrinsic_not (se, expr);
9494 break;
9496 case GFC_ISYM_OR:
9497 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9498 break;
9500 case GFC_ISYM_PARITY:
9501 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9502 break;
9504 case GFC_ISYM_PRESENT:
9505 gfc_conv_intrinsic_present (se, expr);
9506 break;
9508 case GFC_ISYM_PRODUCT:
9509 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9510 break;
9512 case GFC_ISYM_RANK:
9513 gfc_conv_intrinsic_rank (se, expr);
9514 break;
9516 case GFC_ISYM_RRSPACING:
9517 gfc_conv_intrinsic_rrspacing (se, expr);
9518 break;
9520 case GFC_ISYM_SET_EXPONENT:
9521 gfc_conv_intrinsic_set_exponent (se, expr);
9522 break;
9524 case GFC_ISYM_SCALE:
9525 gfc_conv_intrinsic_scale (se, expr);
9526 break;
9528 case GFC_ISYM_SIGN:
9529 gfc_conv_intrinsic_sign (se, expr);
9530 break;
9532 case GFC_ISYM_SIZE:
9533 gfc_conv_intrinsic_size (se, expr);
9534 break;
9536 case GFC_ISYM_SIZEOF:
9537 case GFC_ISYM_C_SIZEOF:
9538 gfc_conv_intrinsic_sizeof (se, expr);
9539 break;
9541 case GFC_ISYM_STORAGE_SIZE:
9542 gfc_conv_intrinsic_storage_size (se, expr);
9543 break;
9545 case GFC_ISYM_SPACING:
9546 gfc_conv_intrinsic_spacing (se, expr);
9547 break;
9549 case GFC_ISYM_STRIDE:
9550 conv_intrinsic_stride (se, expr);
9551 break;
9553 case GFC_ISYM_SUM:
9554 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9555 break;
9557 case GFC_ISYM_TEAM_NUMBER:
9558 conv_intrinsic_team_number (se, expr);
9559 break;
9561 case GFC_ISYM_TRANSFER:
9562 if (se->ss && se->ss->info->useflags)
9563 /* Access the previously obtained result. */
9564 gfc_conv_tmp_array_ref (se);
9565 else
9566 gfc_conv_intrinsic_transfer (se, expr);
9567 break;
9569 case GFC_ISYM_TTYNAM:
9570 gfc_conv_intrinsic_ttynam (se, expr);
9571 break;
9573 case GFC_ISYM_UBOUND:
9574 gfc_conv_intrinsic_bound (se, expr, 1);
9575 break;
9577 case GFC_ISYM_UCOBOUND:
9578 conv_intrinsic_cobound (se, expr);
9579 break;
9581 case GFC_ISYM_XOR:
9582 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9583 break;
9585 case GFC_ISYM_LOC:
9586 gfc_conv_intrinsic_loc (se, expr);
9587 break;
9589 case GFC_ISYM_THIS_IMAGE:
9590 /* For num_images() == 1, handle as LCOBOUND. */
9591 if (expr->value.function.actual->expr
9592 && flag_coarray == GFC_FCOARRAY_SINGLE)
9593 conv_intrinsic_cobound (se, expr);
9594 else
9595 trans_this_image (se, expr);
9596 break;
9598 case GFC_ISYM_IMAGE_INDEX:
9599 trans_image_index (se, expr);
9600 break;
9602 case GFC_ISYM_IMAGE_STATUS:
9603 conv_intrinsic_image_status (se, expr);
9604 break;
9606 case GFC_ISYM_NUM_IMAGES:
9607 trans_num_images (se, expr);
9608 break;
9610 case GFC_ISYM_ACCESS:
9611 case GFC_ISYM_CHDIR:
9612 case GFC_ISYM_CHMOD:
9613 case GFC_ISYM_DTIME:
9614 case GFC_ISYM_ETIME:
9615 case GFC_ISYM_EXTENDS_TYPE_OF:
9616 case GFC_ISYM_FGET:
9617 case GFC_ISYM_FGETC:
9618 case GFC_ISYM_FNUM:
9619 case GFC_ISYM_FPUT:
9620 case GFC_ISYM_FPUTC:
9621 case GFC_ISYM_FSTAT:
9622 case GFC_ISYM_FTELL:
9623 case GFC_ISYM_GETCWD:
9624 case GFC_ISYM_GETGID:
9625 case GFC_ISYM_GETPID:
9626 case GFC_ISYM_GETUID:
9627 case GFC_ISYM_HOSTNM:
9628 case GFC_ISYM_IERRNO:
9629 case GFC_ISYM_IRAND:
9630 case GFC_ISYM_ISATTY:
9631 case GFC_ISYM_JN2:
9632 case GFC_ISYM_LINK:
9633 case GFC_ISYM_LSTAT:
9634 case GFC_ISYM_MATMUL:
9635 case GFC_ISYM_MCLOCK:
9636 case GFC_ISYM_MCLOCK8:
9637 case GFC_ISYM_RAND:
9638 case GFC_ISYM_RENAME:
9639 case GFC_ISYM_SECOND:
9640 case GFC_ISYM_SECNDS:
9641 case GFC_ISYM_SIGNAL:
9642 case GFC_ISYM_STAT:
9643 case GFC_ISYM_SYMLNK:
9644 case GFC_ISYM_SYSTEM:
9645 case GFC_ISYM_TIME:
9646 case GFC_ISYM_TIME8:
9647 case GFC_ISYM_UMASK:
9648 case GFC_ISYM_UNLINK:
9649 case GFC_ISYM_YN2:
9650 gfc_conv_intrinsic_funcall (se, expr);
9651 break;
9653 case GFC_ISYM_EOSHIFT:
9654 case GFC_ISYM_PACK:
9655 case GFC_ISYM_RESHAPE:
9656 /* For those, expr->rank should always be >0 and thus the if above the
9657 switch should have matched. */
9658 gcc_unreachable ();
9659 break;
9661 default:
9662 gfc_conv_intrinsic_lib_function (se, expr);
9663 break;
9668 static gfc_ss *
9669 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9671 gfc_ss *arg_ss, *tmp_ss;
9672 gfc_actual_arglist *arg;
9674 arg = expr->value.function.actual;
9676 gcc_assert (arg->expr);
9678 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9679 gcc_assert (arg_ss != gfc_ss_terminator);
9681 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9683 if (tmp_ss->info->type != GFC_SS_SCALAR
9684 && tmp_ss->info->type != GFC_SS_REFERENCE)
9686 gcc_assert (tmp_ss->dimen == 2);
9688 /* We just invert dimensions. */
9689 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9692 /* Stop when tmp_ss points to the last valid element of the chain... */
9693 if (tmp_ss->next == gfc_ss_terminator)
9694 break;
9697 /* ... so that we can attach the rest of the chain to it. */
9698 tmp_ss->next = ss;
9700 return arg_ss;
9704 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9705 This has the side effect of reversing the nested list, so there is no
9706 need to call gfc_reverse_ss on it (the given list is assumed not to be
9707 reversed yet). */
9709 static gfc_ss *
9710 nest_loop_dimension (gfc_ss *ss, int dim)
9712 int ss_dim, i;
9713 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9714 gfc_loopinfo *new_loop;
9716 gcc_assert (ss != gfc_ss_terminator);
9718 for (; ss != gfc_ss_terminator; ss = ss->next)
9720 new_ss = gfc_get_ss ();
9721 new_ss->next = prev_ss;
9722 new_ss->parent = ss;
9723 new_ss->info = ss->info;
9724 new_ss->info->refcount++;
9725 if (ss->dimen != 0)
9727 gcc_assert (ss->info->type != GFC_SS_SCALAR
9728 && ss->info->type != GFC_SS_REFERENCE);
9730 new_ss->dimen = 1;
9731 new_ss->dim[0] = ss->dim[dim];
9733 gcc_assert (dim < ss->dimen);
9735 ss_dim = --ss->dimen;
9736 for (i = dim; i < ss_dim; i++)
9737 ss->dim[i] = ss->dim[i + 1];
9739 ss->dim[ss_dim] = 0;
9741 prev_ss = new_ss;
9743 if (ss->nested_ss)
9745 ss->nested_ss->parent = new_ss;
9746 new_ss->nested_ss = ss->nested_ss;
9748 ss->nested_ss = new_ss;
9751 new_loop = gfc_get_loopinfo ();
9752 gfc_init_loopinfo (new_loop);
9754 gcc_assert (prev_ss != NULL);
9755 gcc_assert (prev_ss != gfc_ss_terminator);
9756 gfc_add_ss_to_loop (new_loop, prev_ss);
9757 return new_ss->parent;
9761 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9762 is to be inlined. */
9764 static gfc_ss *
9765 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9767 gfc_ss *tmp_ss, *tail, *array_ss;
9768 gfc_actual_arglist *arg1, *arg2, *arg3;
9769 int sum_dim;
9770 bool scalar_mask = false;
9772 /* The rank of the result will be determined later. */
9773 arg1 = expr->value.function.actual;
9774 arg2 = arg1->next;
9775 arg3 = arg2->next;
9776 gcc_assert (arg3 != NULL);
9778 if (expr->rank == 0)
9779 return ss;
9781 tmp_ss = gfc_ss_terminator;
9783 if (arg3->expr)
9785 gfc_ss *mask_ss;
9787 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9788 if (mask_ss == tmp_ss)
9789 scalar_mask = 1;
9791 tmp_ss = mask_ss;
9794 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9795 gcc_assert (array_ss != tmp_ss);
9797 /* Odd thing: If the mask is scalar, it is used by the frontend after
9798 the array (to make an if around the nested loop). Thus it shall
9799 be after array_ss once the gfc_ss list is reversed. */
9800 if (scalar_mask)
9801 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9802 else
9803 tmp_ss = array_ss;
9805 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9806 chain. */
9807 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9808 tail = nest_loop_dimension (tmp_ss, sum_dim);
9809 tail->next = ss;
9811 return tmp_ss;
9815 static gfc_ss *
9816 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9819 switch (expr->value.function.isym->id)
9821 case GFC_ISYM_PRODUCT:
9822 case GFC_ISYM_SUM:
9823 return walk_inline_intrinsic_arith (ss, expr);
9825 case GFC_ISYM_TRANSPOSE:
9826 return walk_inline_intrinsic_transpose (ss, expr);
9828 default:
9829 gcc_unreachable ();
9831 gcc_unreachable ();
9835 /* This generates code to execute before entering the scalarization loop.
9836 Currently does nothing. */
9838 void
9839 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9841 switch (ss->info->expr->value.function.isym->id)
9843 case GFC_ISYM_UBOUND:
9844 case GFC_ISYM_LBOUND:
9845 case GFC_ISYM_UCOBOUND:
9846 case GFC_ISYM_LCOBOUND:
9847 case GFC_ISYM_THIS_IMAGE:
9848 break;
9850 default:
9851 gcc_unreachable ();
9856 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9857 are expanded into code inside the scalarization loop. */
9859 static gfc_ss *
9860 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9862 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9863 gfc_add_class_array_ref (expr->value.function.actual->expr);
9865 /* The two argument version returns a scalar. */
9866 if (expr->value.function.actual->next->expr)
9867 return ss;
9869 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9873 /* Walk an intrinsic array libcall. */
9875 static gfc_ss *
9876 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9878 gcc_assert (expr->rank > 0);
9879 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9883 /* Return whether the function call expression EXPR will be expanded
9884 inline by gfc_conv_intrinsic_function. */
9886 bool
9887 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9889 gfc_actual_arglist *args;
9891 if (!expr->value.function.isym)
9892 return false;
9894 switch (expr->value.function.isym->id)
9896 case GFC_ISYM_PRODUCT:
9897 case GFC_ISYM_SUM:
9898 /* Disable inline expansion if code size matters. */
9899 if (optimize_size)
9900 return false;
9902 args = expr->value.function.actual;
9903 /* We need to be able to subset the SUM argument at compile-time. */
9904 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9905 return false;
9907 return true;
9909 case GFC_ISYM_TRANSPOSE:
9910 return true;
9912 default:
9913 return false;
9918 /* Returns nonzero if the specified intrinsic function call maps directly to
9919 an external library call. Should only be used for functions that return
9920 arrays. */
9923 gfc_is_intrinsic_libcall (gfc_expr * expr)
9925 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9926 gcc_assert (expr->rank > 0);
9928 if (gfc_inline_intrinsic_function_p (expr))
9929 return 0;
9931 switch (expr->value.function.isym->id)
9933 case GFC_ISYM_ALL:
9934 case GFC_ISYM_ANY:
9935 case GFC_ISYM_COUNT:
9936 case GFC_ISYM_JN2:
9937 case GFC_ISYM_IANY:
9938 case GFC_ISYM_IALL:
9939 case GFC_ISYM_IPARITY:
9940 case GFC_ISYM_MATMUL:
9941 case GFC_ISYM_MAXLOC:
9942 case GFC_ISYM_MAXVAL:
9943 case GFC_ISYM_MINLOC:
9944 case GFC_ISYM_MINVAL:
9945 case GFC_ISYM_NORM2:
9946 case GFC_ISYM_PARITY:
9947 case GFC_ISYM_PRODUCT:
9948 case GFC_ISYM_SUM:
9949 case GFC_ISYM_SHAPE:
9950 case GFC_ISYM_SPREAD:
9951 case GFC_ISYM_YN2:
9952 /* Ignore absent optional parameters. */
9953 return 1;
9955 case GFC_ISYM_CSHIFT:
9956 case GFC_ISYM_EOSHIFT:
9957 case GFC_ISYM_GET_TEAM:
9958 case GFC_ISYM_FAILED_IMAGES:
9959 case GFC_ISYM_STOPPED_IMAGES:
9960 case GFC_ISYM_PACK:
9961 case GFC_ISYM_RESHAPE:
9962 case GFC_ISYM_UNPACK:
9963 /* Pass absent optional parameters. */
9964 return 2;
9966 default:
9967 return 0;
9971 /* Walk an intrinsic function. */
9972 gfc_ss *
9973 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9974 gfc_intrinsic_sym * isym)
9976 gcc_assert (isym);
9978 if (isym->elemental)
9979 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9980 NULL, GFC_SS_SCALAR);
9982 if (expr->rank == 0)
9983 return ss;
9985 if (gfc_inline_intrinsic_function_p (expr))
9986 return walk_inline_intrinsic_function (ss, expr);
9988 if (gfc_is_intrinsic_libcall (expr))
9989 return gfc_walk_intrinsic_libfunc (ss, expr);
9991 /* Special cases. */
9992 switch (isym->id)
9994 case GFC_ISYM_LBOUND:
9995 case GFC_ISYM_LCOBOUND:
9996 case GFC_ISYM_UBOUND:
9997 case GFC_ISYM_UCOBOUND:
9998 case GFC_ISYM_THIS_IMAGE:
9999 return gfc_walk_intrinsic_bound (ss, expr);
10001 case GFC_ISYM_TRANSFER:
10002 case GFC_ISYM_CAF_GET:
10003 return gfc_walk_intrinsic_libfunc (ss, expr);
10005 default:
10006 /* This probably meant someone forgot to add an intrinsic to the above
10007 list(s) when they implemented it, or something's gone horribly
10008 wrong. */
10009 gcc_unreachable ();
10014 static tree
10015 conv_co_collective (gfc_code *code)
10017 gfc_se argse;
10018 stmtblock_t block, post_block;
10019 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
10020 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
10022 gfc_start_block (&block);
10023 gfc_init_block (&post_block);
10025 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
10027 opr_expr = code->ext.actual->next->expr;
10028 image_idx_expr = code->ext.actual->next->next->expr;
10029 stat_expr = code->ext.actual->next->next->next->expr;
10030 errmsg_expr = code->ext.actual->next->next->next->next->expr;
10032 else
10034 opr_expr = NULL;
10035 image_idx_expr = code->ext.actual->next->expr;
10036 stat_expr = code->ext.actual->next->next->expr;
10037 errmsg_expr = code->ext.actual->next->next->next->expr;
10040 /* stat. */
10041 if (stat_expr)
10043 gfc_init_se (&argse, NULL);
10044 gfc_conv_expr (&argse, stat_expr);
10045 gfc_add_block_to_block (&block, &argse.pre);
10046 gfc_add_block_to_block (&post_block, &argse.post);
10047 stat = argse.expr;
10048 if (flag_coarray != GFC_FCOARRAY_SINGLE)
10049 stat = gfc_build_addr_expr (NULL_TREE, stat);
10051 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
10052 stat = NULL_TREE;
10053 else
10054 stat = null_pointer_node;
10056 /* Early exit for GFC_FCOARRAY_SINGLE. */
10057 if (flag_coarray == GFC_FCOARRAY_SINGLE)
10059 if (stat != NULL_TREE)
10060 gfc_add_modify (&block, stat,
10061 fold_convert (TREE_TYPE (stat), integer_zero_node));
10062 return gfc_finish_block (&block);
10065 /* Handle the array. */
10066 gfc_init_se (&argse, NULL);
10067 if (code->ext.actual->expr->rank == 0)
10069 symbol_attribute attr;
10070 gfc_clear_attr (&attr);
10071 gfc_init_se (&argse, NULL);
10072 gfc_conv_expr (&argse, code->ext.actual->expr);
10073 gfc_add_block_to_block (&block, &argse.pre);
10074 gfc_add_block_to_block (&post_block, &argse.post);
10075 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
10076 array = gfc_build_addr_expr (NULL_TREE, array);
10078 else
10080 argse.want_pointer = 1;
10081 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
10082 array = argse.expr;
10084 gfc_add_block_to_block (&block, &argse.pre);
10085 gfc_add_block_to_block (&post_block, &argse.post);
10087 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
10088 strlen = argse.string_length;
10089 else
10090 strlen = integer_zero_node;
10092 /* image_index. */
10093 if (image_idx_expr)
10095 gfc_init_se (&argse, NULL);
10096 gfc_conv_expr (&argse, image_idx_expr);
10097 gfc_add_block_to_block (&block, &argse.pre);
10098 gfc_add_block_to_block (&post_block, &argse.post);
10099 image_index = fold_convert (integer_type_node, argse.expr);
10101 else
10102 image_index = integer_zero_node;
10104 /* errmsg. */
10105 if (errmsg_expr)
10107 gfc_init_se (&argse, NULL);
10108 gfc_conv_expr (&argse, errmsg_expr);
10109 gfc_add_block_to_block (&block, &argse.pre);
10110 gfc_add_block_to_block (&post_block, &argse.post);
10111 errmsg = argse.expr;
10112 errmsg_len = fold_convert (size_type_node, argse.string_length);
10114 else
10116 errmsg = null_pointer_node;
10117 errmsg_len = build_zero_cst (size_type_node);
10120 /* Generate the function call. */
10121 switch (code->resolved_isym->id)
10123 case GFC_ISYM_CO_BROADCAST:
10124 fndecl = gfor_fndecl_co_broadcast;
10125 break;
10126 case GFC_ISYM_CO_MAX:
10127 fndecl = gfor_fndecl_co_max;
10128 break;
10129 case GFC_ISYM_CO_MIN:
10130 fndecl = gfor_fndecl_co_min;
10131 break;
10132 case GFC_ISYM_CO_REDUCE:
10133 fndecl = gfor_fndecl_co_reduce;
10134 break;
10135 case GFC_ISYM_CO_SUM:
10136 fndecl = gfor_fndecl_co_sum;
10137 break;
10138 default:
10139 gcc_unreachable ();
10142 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
10143 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
10144 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
10145 image_index, stat, errmsg, errmsg_len);
10146 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
10147 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
10148 stat, errmsg, strlen, errmsg_len);
10149 else
10151 tree opr, opr_flags;
10153 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10154 int opr_flag_int;
10155 if (gfc_is_proc_ptr_comp (opr_expr))
10157 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
10158 opr_flag_int = sym->attr.dimension
10159 || (sym->ts.type == BT_CHARACTER
10160 && !sym->attr.is_bind_c)
10161 ? GFC_CAF_BYREF : 0;
10162 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10163 && !sym->attr.is_bind_c
10164 ? GFC_CAF_HIDDENLEN : 0;
10165 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
10167 else
10169 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
10170 ? GFC_CAF_BYREF : 0;
10171 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10172 && !opr_expr->symtree->n.sym->attr.is_bind_c
10173 ? GFC_CAF_HIDDENLEN : 0;
10174 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
10175 ? GFC_CAF_ARG_VALUE : 0;
10177 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
10178 gfc_conv_expr (&argse, opr_expr);
10179 opr = argse.expr;
10180 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
10181 image_index, stat, errmsg, strlen, errmsg_len);
10184 gfc_add_expr_to_block (&block, fndecl);
10185 gfc_add_block_to_block (&block, &post_block);
10187 return gfc_finish_block (&block);
10191 static tree
10192 conv_intrinsic_atomic_op (gfc_code *code)
10194 gfc_se argse;
10195 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
10196 stmtblock_t block, post_block;
10197 gfc_expr *atom_expr = code->ext.actual->expr;
10198 gfc_expr *stat_expr;
10199 built_in_function fn;
10201 if (atom_expr->expr_type == EXPR_FUNCTION
10202 && atom_expr->value.function.isym
10203 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10204 atom_expr = atom_expr->value.function.actual->expr;
10206 gfc_start_block (&block);
10207 gfc_init_block (&post_block);
10209 gfc_init_se (&argse, NULL);
10210 argse.want_pointer = 1;
10211 gfc_conv_expr (&argse, atom_expr);
10212 gfc_add_block_to_block (&block, &argse.pre);
10213 gfc_add_block_to_block (&post_block, &argse.post);
10214 atom = argse.expr;
10216 gfc_init_se (&argse, NULL);
10217 if (flag_coarray == GFC_FCOARRAY_LIB
10218 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
10219 argse.want_pointer = 1;
10220 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10221 gfc_add_block_to_block (&block, &argse.pre);
10222 gfc_add_block_to_block (&post_block, &argse.post);
10223 value = argse.expr;
10225 switch (code->resolved_isym->id)
10227 case GFC_ISYM_ATOMIC_ADD:
10228 case GFC_ISYM_ATOMIC_AND:
10229 case GFC_ISYM_ATOMIC_DEF:
10230 case GFC_ISYM_ATOMIC_OR:
10231 case GFC_ISYM_ATOMIC_XOR:
10232 stat_expr = code->ext.actual->next->next->expr;
10233 if (flag_coarray == GFC_FCOARRAY_LIB)
10234 old = null_pointer_node;
10235 break;
10236 default:
10237 gfc_init_se (&argse, NULL);
10238 if (flag_coarray == GFC_FCOARRAY_LIB)
10239 argse.want_pointer = 1;
10240 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10241 gfc_add_block_to_block (&block, &argse.pre);
10242 gfc_add_block_to_block (&post_block, &argse.post);
10243 old = argse.expr;
10244 stat_expr = code->ext.actual->next->next->next->expr;
10247 /* STAT= */
10248 if (stat_expr != NULL)
10250 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
10251 gfc_init_se (&argse, NULL);
10252 if (flag_coarray == GFC_FCOARRAY_LIB)
10253 argse.want_pointer = 1;
10254 gfc_conv_expr_val (&argse, stat_expr);
10255 gfc_add_block_to_block (&block, &argse.pre);
10256 gfc_add_block_to_block (&post_block, &argse.post);
10257 stat = argse.expr;
10259 else if (flag_coarray == GFC_FCOARRAY_LIB)
10260 stat = null_pointer_node;
10262 if (flag_coarray == GFC_FCOARRAY_LIB)
10264 tree image_index, caf_decl, offset, token;
10265 int op;
10267 switch (code->resolved_isym->id)
10269 case GFC_ISYM_ATOMIC_ADD:
10270 case GFC_ISYM_ATOMIC_FETCH_ADD:
10271 op = (int) GFC_CAF_ATOMIC_ADD;
10272 break;
10273 case GFC_ISYM_ATOMIC_AND:
10274 case GFC_ISYM_ATOMIC_FETCH_AND:
10275 op = (int) GFC_CAF_ATOMIC_AND;
10276 break;
10277 case GFC_ISYM_ATOMIC_OR:
10278 case GFC_ISYM_ATOMIC_FETCH_OR:
10279 op = (int) GFC_CAF_ATOMIC_OR;
10280 break;
10281 case GFC_ISYM_ATOMIC_XOR:
10282 case GFC_ISYM_ATOMIC_FETCH_XOR:
10283 op = (int) GFC_CAF_ATOMIC_XOR;
10284 break;
10285 case GFC_ISYM_ATOMIC_DEF:
10286 op = 0; /* Unused. */
10287 break;
10288 default:
10289 gcc_unreachable ();
10292 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10293 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10294 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10296 if (gfc_is_coindexed (atom_expr))
10297 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10298 else
10299 image_index = integer_zero_node;
10301 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10303 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10304 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10305 value = gfc_build_addr_expr (NULL_TREE, tmp);
10308 gfc_init_se (&argse, NULL);
10309 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10310 atom_expr);
10312 gfc_add_block_to_block (&block, &argse.pre);
10313 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10314 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10315 token, offset, image_index, value, stat,
10316 build_int_cst (integer_type_node,
10317 (int) atom_expr->ts.type),
10318 build_int_cst (integer_type_node,
10319 (int) atom_expr->ts.kind));
10320 else
10321 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10322 build_int_cst (integer_type_node, op),
10323 token, offset, image_index, value, old, stat,
10324 build_int_cst (integer_type_node,
10325 (int) atom_expr->ts.type),
10326 build_int_cst (integer_type_node,
10327 (int) atom_expr->ts.kind));
10329 gfc_add_expr_to_block (&block, tmp);
10330 gfc_add_block_to_block (&block, &argse.post);
10331 gfc_add_block_to_block (&block, &post_block);
10332 return gfc_finish_block (&block);
10336 switch (code->resolved_isym->id)
10338 case GFC_ISYM_ATOMIC_ADD:
10339 case GFC_ISYM_ATOMIC_FETCH_ADD:
10340 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10341 break;
10342 case GFC_ISYM_ATOMIC_AND:
10343 case GFC_ISYM_ATOMIC_FETCH_AND:
10344 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10345 break;
10346 case GFC_ISYM_ATOMIC_DEF:
10347 fn = BUILT_IN_ATOMIC_STORE_N;
10348 break;
10349 case GFC_ISYM_ATOMIC_OR:
10350 case GFC_ISYM_ATOMIC_FETCH_OR:
10351 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10352 break;
10353 case GFC_ISYM_ATOMIC_XOR:
10354 case GFC_ISYM_ATOMIC_FETCH_XOR:
10355 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10356 break;
10357 default:
10358 gcc_unreachable ();
10361 tmp = TREE_TYPE (TREE_TYPE (atom));
10362 fn = (built_in_function) ((int) fn
10363 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10364 + 1);
10365 tmp = builtin_decl_explicit (fn);
10366 tree itype = TREE_TYPE (TREE_TYPE (atom));
10367 tmp = builtin_decl_explicit (fn);
10369 switch (code->resolved_isym->id)
10371 case GFC_ISYM_ATOMIC_ADD:
10372 case GFC_ISYM_ATOMIC_AND:
10373 case GFC_ISYM_ATOMIC_DEF:
10374 case GFC_ISYM_ATOMIC_OR:
10375 case GFC_ISYM_ATOMIC_XOR:
10376 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10377 fold_convert (itype, value),
10378 build_int_cst (NULL, MEMMODEL_RELAXED));
10379 gfc_add_expr_to_block (&block, tmp);
10380 break;
10381 default:
10382 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10383 fold_convert (itype, value),
10384 build_int_cst (NULL, MEMMODEL_RELAXED));
10385 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10386 break;
10389 if (stat != NULL_TREE)
10390 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10391 gfc_add_block_to_block (&block, &post_block);
10392 return gfc_finish_block (&block);
10396 static tree
10397 conv_intrinsic_atomic_ref (gfc_code *code)
10399 gfc_se argse;
10400 tree tmp, atom, value, stat = NULL_TREE;
10401 stmtblock_t block, post_block;
10402 built_in_function fn;
10403 gfc_expr *atom_expr = code->ext.actual->next->expr;
10405 if (atom_expr->expr_type == EXPR_FUNCTION
10406 && atom_expr->value.function.isym
10407 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10408 atom_expr = atom_expr->value.function.actual->expr;
10410 gfc_start_block (&block);
10411 gfc_init_block (&post_block);
10412 gfc_init_se (&argse, NULL);
10413 argse.want_pointer = 1;
10414 gfc_conv_expr (&argse, atom_expr);
10415 gfc_add_block_to_block (&block, &argse.pre);
10416 gfc_add_block_to_block (&post_block, &argse.post);
10417 atom = argse.expr;
10419 gfc_init_se (&argse, NULL);
10420 if (flag_coarray == GFC_FCOARRAY_LIB
10421 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10422 argse.want_pointer = 1;
10423 gfc_conv_expr (&argse, code->ext.actual->expr);
10424 gfc_add_block_to_block (&block, &argse.pre);
10425 gfc_add_block_to_block (&post_block, &argse.post);
10426 value = argse.expr;
10428 /* STAT= */
10429 if (code->ext.actual->next->next->expr != NULL)
10431 gcc_assert (code->ext.actual->next->next->expr->expr_type
10432 == EXPR_VARIABLE);
10433 gfc_init_se (&argse, NULL);
10434 if (flag_coarray == GFC_FCOARRAY_LIB)
10435 argse.want_pointer = 1;
10436 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10437 gfc_add_block_to_block (&block, &argse.pre);
10438 gfc_add_block_to_block (&post_block, &argse.post);
10439 stat = argse.expr;
10441 else if (flag_coarray == GFC_FCOARRAY_LIB)
10442 stat = null_pointer_node;
10444 if (flag_coarray == GFC_FCOARRAY_LIB)
10446 tree image_index, caf_decl, offset, token;
10447 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10449 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10450 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10451 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10453 if (gfc_is_coindexed (atom_expr))
10454 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10455 else
10456 image_index = integer_zero_node;
10458 gfc_init_se (&argse, NULL);
10459 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10460 atom_expr);
10461 gfc_add_block_to_block (&block, &argse.pre);
10463 /* Different type, need type conversion. */
10464 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10466 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10467 orig_value = value;
10468 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10471 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10472 token, offset, image_index, value, stat,
10473 build_int_cst (integer_type_node,
10474 (int) atom_expr->ts.type),
10475 build_int_cst (integer_type_node,
10476 (int) atom_expr->ts.kind));
10477 gfc_add_expr_to_block (&block, tmp);
10478 if (vardecl != NULL_TREE)
10479 gfc_add_modify (&block, orig_value,
10480 fold_convert (TREE_TYPE (orig_value), vardecl));
10481 gfc_add_block_to_block (&block, &argse.post);
10482 gfc_add_block_to_block (&block, &post_block);
10483 return gfc_finish_block (&block);
10486 tmp = TREE_TYPE (TREE_TYPE (atom));
10487 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10488 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10489 + 1);
10490 tmp = builtin_decl_explicit (fn);
10491 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10492 build_int_cst (integer_type_node,
10493 MEMMODEL_RELAXED));
10494 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10496 if (stat != NULL_TREE)
10497 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10498 gfc_add_block_to_block (&block, &post_block);
10499 return gfc_finish_block (&block);
10503 static tree
10504 conv_intrinsic_atomic_cas (gfc_code *code)
10506 gfc_se argse;
10507 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10508 stmtblock_t block, post_block;
10509 built_in_function fn;
10510 gfc_expr *atom_expr = code->ext.actual->expr;
10512 if (atom_expr->expr_type == EXPR_FUNCTION
10513 && atom_expr->value.function.isym
10514 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10515 atom_expr = atom_expr->value.function.actual->expr;
10517 gfc_init_block (&block);
10518 gfc_init_block (&post_block);
10519 gfc_init_se (&argse, NULL);
10520 argse.want_pointer = 1;
10521 gfc_conv_expr (&argse, atom_expr);
10522 atom = argse.expr;
10524 gfc_init_se (&argse, NULL);
10525 if (flag_coarray == GFC_FCOARRAY_LIB)
10526 argse.want_pointer = 1;
10527 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10528 gfc_add_block_to_block (&block, &argse.pre);
10529 gfc_add_block_to_block (&post_block, &argse.post);
10530 old = argse.expr;
10532 gfc_init_se (&argse, NULL);
10533 if (flag_coarray == GFC_FCOARRAY_LIB)
10534 argse.want_pointer = 1;
10535 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10536 gfc_add_block_to_block (&block, &argse.pre);
10537 gfc_add_block_to_block (&post_block, &argse.post);
10538 comp = argse.expr;
10540 gfc_init_se (&argse, NULL);
10541 if (flag_coarray == GFC_FCOARRAY_LIB
10542 && code->ext.actual->next->next->next->expr->ts.kind
10543 == atom_expr->ts.kind)
10544 argse.want_pointer = 1;
10545 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10546 gfc_add_block_to_block (&block, &argse.pre);
10547 gfc_add_block_to_block (&post_block, &argse.post);
10548 new_val = argse.expr;
10550 /* STAT= */
10551 if (code->ext.actual->next->next->next->next->expr != NULL)
10553 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10554 == EXPR_VARIABLE);
10555 gfc_init_se (&argse, NULL);
10556 if (flag_coarray == GFC_FCOARRAY_LIB)
10557 argse.want_pointer = 1;
10558 gfc_conv_expr_val (&argse,
10559 code->ext.actual->next->next->next->next->expr);
10560 gfc_add_block_to_block (&block, &argse.pre);
10561 gfc_add_block_to_block (&post_block, &argse.post);
10562 stat = argse.expr;
10564 else if (flag_coarray == GFC_FCOARRAY_LIB)
10565 stat = null_pointer_node;
10567 if (flag_coarray == GFC_FCOARRAY_LIB)
10569 tree image_index, caf_decl, offset, token;
10571 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10572 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10573 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10575 if (gfc_is_coindexed (atom_expr))
10576 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10577 else
10578 image_index = integer_zero_node;
10580 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10582 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10583 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10584 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10587 /* Convert a constant to a pointer. */
10588 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10590 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10591 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10592 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10595 gfc_init_se (&argse, NULL);
10596 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10597 atom_expr);
10598 gfc_add_block_to_block (&block, &argse.pre);
10600 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10601 token, offset, image_index, old, comp, new_val,
10602 stat, build_int_cst (integer_type_node,
10603 (int) atom_expr->ts.type),
10604 build_int_cst (integer_type_node,
10605 (int) atom_expr->ts.kind));
10606 gfc_add_expr_to_block (&block, tmp);
10607 gfc_add_block_to_block (&block, &argse.post);
10608 gfc_add_block_to_block (&block, &post_block);
10609 return gfc_finish_block (&block);
10612 tmp = TREE_TYPE (TREE_TYPE (atom));
10613 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10614 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10615 + 1);
10616 tmp = builtin_decl_explicit (fn);
10618 gfc_add_modify (&block, old, comp);
10619 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10620 gfc_build_addr_expr (NULL, old),
10621 fold_convert (TREE_TYPE (old), new_val),
10622 boolean_false_node,
10623 build_int_cst (NULL, MEMMODEL_RELAXED),
10624 build_int_cst (NULL, MEMMODEL_RELAXED));
10625 gfc_add_expr_to_block (&block, tmp);
10627 if (stat != NULL_TREE)
10628 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10629 gfc_add_block_to_block (&block, &post_block);
10630 return gfc_finish_block (&block);
10633 static tree
10634 conv_intrinsic_event_query (gfc_code *code)
10636 gfc_se se, argse;
10637 tree stat = NULL_TREE, stat2 = NULL_TREE;
10638 tree count = NULL_TREE, count2 = NULL_TREE;
10640 gfc_expr *event_expr = code->ext.actual->expr;
10642 if (code->ext.actual->next->next->expr)
10644 gcc_assert (code->ext.actual->next->next->expr->expr_type
10645 == EXPR_VARIABLE);
10646 gfc_init_se (&argse, NULL);
10647 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10648 stat = argse.expr;
10650 else if (flag_coarray == GFC_FCOARRAY_LIB)
10651 stat = null_pointer_node;
10653 if (code->ext.actual->next->expr)
10655 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10656 gfc_init_se (&argse, NULL);
10657 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10658 count = argse.expr;
10661 gfc_start_block (&se.pre);
10662 if (flag_coarray == GFC_FCOARRAY_LIB)
10664 tree tmp, token, image_index;
10665 tree index = build_zero_cst (gfc_array_index_type);
10667 if (event_expr->expr_type == EXPR_FUNCTION
10668 && event_expr->value.function.isym
10669 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10670 event_expr = event_expr->value.function.actual->expr;
10672 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10674 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10675 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10676 != INTMOD_ISO_FORTRAN_ENV
10677 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10678 != ISOFORTRAN_EVENT_TYPE)
10680 gfc_error ("Sorry, the event component of derived type at %L is not "
10681 "yet supported", &event_expr->where);
10682 return NULL_TREE;
10685 if (gfc_is_coindexed (event_expr))
10687 gfc_error ("The event variable at %L shall not be coindexed",
10688 &event_expr->where);
10689 return NULL_TREE;
10692 image_index = integer_zero_node;
10694 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10695 event_expr);
10697 /* For arrays, obtain the array index. */
10698 if (gfc_expr_attr (event_expr).dimension)
10700 tree desc, tmp, extent, lbound, ubound;
10701 gfc_array_ref *ar, ar2;
10702 int i;
10704 /* TODO: Extend this, once DT components are supported. */
10705 ar = &event_expr->ref->u.ar;
10706 ar2 = *ar;
10707 memset (ar, '\0', sizeof (*ar));
10708 ar->as = ar2.as;
10709 ar->type = AR_FULL;
10711 gfc_init_se (&argse, NULL);
10712 argse.descriptor_only = 1;
10713 gfc_conv_expr_descriptor (&argse, event_expr);
10714 gfc_add_block_to_block (&se.pre, &argse.pre);
10715 desc = argse.expr;
10716 *ar = ar2;
10718 extent = build_one_cst (gfc_array_index_type);
10719 for (i = 0; i < ar->dimen; i++)
10721 gfc_init_se (&argse, NULL);
10722 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
10723 gfc_add_block_to_block (&argse.pre, &argse.pre);
10724 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10725 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10726 TREE_TYPE (lbound), argse.expr, lbound);
10727 tmp = fold_build2_loc (input_location, MULT_EXPR,
10728 TREE_TYPE (tmp), extent, tmp);
10729 index = fold_build2_loc (input_location, PLUS_EXPR,
10730 TREE_TYPE (tmp), index, tmp);
10731 if (i < ar->dimen - 1)
10733 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10734 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10735 extent = fold_build2_loc (input_location, MULT_EXPR,
10736 TREE_TYPE (tmp), extent, tmp);
10741 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10743 count2 = count;
10744 count = gfc_create_var (integer_type_node, "count");
10747 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10749 stat2 = stat;
10750 stat = gfc_create_var (integer_type_node, "stat");
10753 index = fold_convert (size_type_node, index);
10754 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10755 token, index, image_index, count
10756 ? gfc_build_addr_expr (NULL, count) : count,
10757 stat != null_pointer_node
10758 ? gfc_build_addr_expr (NULL, stat) : stat);
10759 gfc_add_expr_to_block (&se.pre, tmp);
10761 if (count2 != NULL_TREE)
10762 gfc_add_modify (&se.pre, count2,
10763 fold_convert (TREE_TYPE (count2), count));
10765 if (stat2 != NULL_TREE)
10766 gfc_add_modify (&se.pre, stat2,
10767 fold_convert (TREE_TYPE (stat2), stat));
10769 return gfc_finish_block (&se.pre);
10772 gfc_init_se (&argse, NULL);
10773 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10774 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10776 if (stat != NULL_TREE)
10777 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10779 return gfc_finish_block (&se.pre);
10782 static tree
10783 conv_intrinsic_move_alloc (gfc_code *code)
10785 stmtblock_t block;
10786 gfc_expr *from_expr, *to_expr;
10787 gfc_expr *to_expr2, *from_expr2 = NULL;
10788 gfc_se from_se, to_se;
10789 tree tmp;
10790 bool coarray;
10792 gfc_start_block (&block);
10794 from_expr = code->ext.actual->expr;
10795 to_expr = code->ext.actual->next->expr;
10797 gfc_init_se (&from_se, NULL);
10798 gfc_init_se (&to_se, NULL);
10800 gcc_assert (from_expr->ts.type != BT_CLASS
10801 || to_expr->ts.type == BT_CLASS);
10802 coarray = gfc_get_corank (from_expr) != 0;
10804 if (from_expr->rank == 0 && !coarray)
10806 if (from_expr->ts.type != BT_CLASS)
10807 from_expr2 = from_expr;
10808 else
10810 from_expr2 = gfc_copy_expr (from_expr);
10811 gfc_add_data_component (from_expr2);
10814 if (to_expr->ts.type != BT_CLASS)
10815 to_expr2 = to_expr;
10816 else
10818 to_expr2 = gfc_copy_expr (to_expr);
10819 gfc_add_data_component (to_expr2);
10822 from_se.want_pointer = 1;
10823 to_se.want_pointer = 1;
10824 gfc_conv_expr (&from_se, from_expr2);
10825 gfc_conv_expr (&to_se, to_expr2);
10826 gfc_add_block_to_block (&block, &from_se.pre);
10827 gfc_add_block_to_block (&block, &to_se.pre);
10829 /* Deallocate "to". */
10830 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10831 true, to_expr, to_expr->ts);
10832 gfc_add_expr_to_block (&block, tmp);
10834 /* Assign (_data) pointers. */
10835 gfc_add_modify_loc (input_location, &block, to_se.expr,
10836 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10838 /* Set "from" to NULL. */
10839 gfc_add_modify_loc (input_location, &block, from_se.expr,
10840 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10842 gfc_add_block_to_block (&block, &from_se.post);
10843 gfc_add_block_to_block (&block, &to_se.post);
10845 /* Set _vptr. */
10846 if (to_expr->ts.type == BT_CLASS)
10848 gfc_symbol *vtab;
10850 gfc_free_expr (to_expr2);
10851 gfc_init_se (&to_se, NULL);
10852 to_se.want_pointer = 1;
10853 gfc_add_vptr_component (to_expr);
10854 gfc_conv_expr (&to_se, to_expr);
10856 if (from_expr->ts.type == BT_CLASS)
10858 if (UNLIMITED_POLY (from_expr))
10859 vtab = NULL;
10860 else
10862 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10863 gcc_assert (vtab);
10866 gfc_free_expr (from_expr2);
10867 gfc_init_se (&from_se, NULL);
10868 from_se.want_pointer = 1;
10869 gfc_add_vptr_component (from_expr);
10870 gfc_conv_expr (&from_se, from_expr);
10871 gfc_add_modify_loc (input_location, &block, to_se.expr,
10872 fold_convert (TREE_TYPE (to_se.expr),
10873 from_se.expr));
10875 /* Reset _vptr component to declared type. */
10876 if (vtab == NULL)
10877 /* Unlimited polymorphic. */
10878 gfc_add_modify_loc (input_location, &block, from_se.expr,
10879 fold_convert (TREE_TYPE (from_se.expr),
10880 null_pointer_node));
10881 else
10883 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10884 gfc_add_modify_loc (input_location, &block, from_se.expr,
10885 fold_convert (TREE_TYPE (from_se.expr), tmp));
10888 else
10890 vtab = gfc_find_vtab (&from_expr->ts);
10891 gcc_assert (vtab);
10892 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10893 gfc_add_modify_loc (input_location, &block, to_se.expr,
10894 fold_convert (TREE_TYPE (to_se.expr), tmp));
10898 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10900 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10901 fold_convert (TREE_TYPE (to_se.string_length),
10902 from_se.string_length));
10903 if (from_expr->ts.deferred)
10904 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10905 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10908 return gfc_finish_block (&block);
10911 /* Update _vptr component. */
10912 if (to_expr->ts.type == BT_CLASS)
10914 gfc_symbol *vtab;
10916 to_se.want_pointer = 1;
10917 to_expr2 = gfc_copy_expr (to_expr);
10918 gfc_add_vptr_component (to_expr2);
10919 gfc_conv_expr (&to_se, to_expr2);
10921 if (from_expr->ts.type == BT_CLASS)
10923 if (UNLIMITED_POLY (from_expr))
10924 vtab = NULL;
10925 else
10927 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10928 gcc_assert (vtab);
10931 from_se.want_pointer = 1;
10932 from_expr2 = gfc_copy_expr (from_expr);
10933 gfc_add_vptr_component (from_expr2);
10934 gfc_conv_expr (&from_se, from_expr2);
10935 gfc_add_modify_loc (input_location, &block, to_se.expr,
10936 fold_convert (TREE_TYPE (to_se.expr),
10937 from_se.expr));
10939 /* Reset _vptr component to declared type. */
10940 if (vtab == NULL)
10941 /* Unlimited polymorphic. */
10942 gfc_add_modify_loc (input_location, &block, from_se.expr,
10943 fold_convert (TREE_TYPE (from_se.expr),
10944 null_pointer_node));
10945 else
10947 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10948 gfc_add_modify_loc (input_location, &block, from_se.expr,
10949 fold_convert (TREE_TYPE (from_se.expr), tmp));
10952 else
10954 vtab = gfc_find_vtab (&from_expr->ts);
10955 gcc_assert (vtab);
10956 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10957 gfc_add_modify_loc (input_location, &block, to_se.expr,
10958 fold_convert (TREE_TYPE (to_se.expr), tmp));
10961 gfc_free_expr (to_expr2);
10962 gfc_init_se (&to_se, NULL);
10964 if (from_expr->ts.type == BT_CLASS)
10966 gfc_free_expr (from_expr2);
10967 gfc_init_se (&from_se, NULL);
10972 /* Deallocate "to". */
10973 if (from_expr->rank == 0)
10975 to_se.want_coarray = 1;
10976 from_se.want_coarray = 1;
10978 gfc_conv_expr_descriptor (&to_se, to_expr);
10979 gfc_conv_expr_descriptor (&from_se, from_expr);
10981 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10982 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10983 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10985 tree cond;
10987 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10988 NULL_TREE, NULL_TREE, true, to_expr,
10989 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10990 gfc_add_expr_to_block (&block, tmp);
10992 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10993 cond = fold_build2_loc (input_location, EQ_EXPR,
10994 logical_type_node, tmp,
10995 fold_convert (TREE_TYPE (tmp),
10996 null_pointer_node));
10997 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10998 3, null_pointer_node, null_pointer_node,
10999 build_int_cst (integer_type_node, 0));
11001 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
11002 tmp, build_empty_stmt (input_location));
11003 gfc_add_expr_to_block (&block, tmp);
11005 else
11007 if (to_expr->ts.type == BT_DERIVED
11008 && to_expr->ts.u.derived->attr.alloc_comp)
11010 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
11011 to_se.expr, to_expr->rank);
11012 gfc_add_expr_to_block (&block, tmp);
11015 tmp = gfc_conv_descriptor_data_get (to_se.expr);
11016 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
11017 NULL_TREE, true, to_expr,
11018 GFC_CAF_COARRAY_NOCOARRAY);
11019 gfc_add_expr_to_block (&block, tmp);
11022 /* Move the pointer and update the array descriptor data. */
11023 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
11025 /* Set "from" to NULL. */
11026 tmp = gfc_conv_descriptor_data_get (from_se.expr);
11027 gfc_add_modify_loc (input_location, &block, tmp,
11028 fold_convert (TREE_TYPE (tmp), null_pointer_node));
11031 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
11033 gfc_add_modify_loc (input_location, &block, to_se.string_length,
11034 fold_convert (TREE_TYPE (to_se.string_length),
11035 from_se.string_length));
11036 if (from_expr->ts.deferred)
11037 gfc_add_modify_loc (input_location, &block, from_se.string_length,
11038 build_int_cst (TREE_TYPE (from_se.string_length), 0));
11041 return gfc_finish_block (&block);
11045 tree
11046 gfc_conv_intrinsic_subroutine (gfc_code *code)
11048 tree res;
11050 gcc_assert (code->resolved_isym);
11052 switch (code->resolved_isym->id)
11054 case GFC_ISYM_MOVE_ALLOC:
11055 res = conv_intrinsic_move_alloc (code);
11056 break;
11058 case GFC_ISYM_ATOMIC_CAS:
11059 res = conv_intrinsic_atomic_cas (code);
11060 break;
11062 case GFC_ISYM_ATOMIC_ADD:
11063 case GFC_ISYM_ATOMIC_AND:
11064 case GFC_ISYM_ATOMIC_DEF:
11065 case GFC_ISYM_ATOMIC_OR:
11066 case GFC_ISYM_ATOMIC_XOR:
11067 case GFC_ISYM_ATOMIC_FETCH_ADD:
11068 case GFC_ISYM_ATOMIC_FETCH_AND:
11069 case GFC_ISYM_ATOMIC_FETCH_OR:
11070 case GFC_ISYM_ATOMIC_FETCH_XOR:
11071 res = conv_intrinsic_atomic_op (code);
11072 break;
11074 case GFC_ISYM_ATOMIC_REF:
11075 res = conv_intrinsic_atomic_ref (code);
11076 break;
11078 case GFC_ISYM_EVENT_QUERY:
11079 res = conv_intrinsic_event_query (code);
11080 break;
11082 case GFC_ISYM_C_F_POINTER:
11083 case GFC_ISYM_C_F_PROCPOINTER:
11084 res = conv_isocbinding_subroutine (code);
11085 break;
11087 case GFC_ISYM_CAF_SEND:
11088 res = conv_caf_send (code);
11089 break;
11091 case GFC_ISYM_CO_BROADCAST:
11092 case GFC_ISYM_CO_MIN:
11093 case GFC_ISYM_CO_MAX:
11094 case GFC_ISYM_CO_REDUCE:
11095 case GFC_ISYM_CO_SUM:
11096 res = conv_co_collective (code);
11097 break;
11099 case GFC_ISYM_FREE:
11100 res = conv_intrinsic_free (code);
11101 break;
11103 case GFC_ISYM_RANDOM_INIT:
11104 res = conv_intrinsic_random_init (code);
11105 break;
11107 case GFC_ISYM_KILL:
11108 res = conv_intrinsic_kill_sub (code);
11109 break;
11111 case GFC_ISYM_SYSTEM_CLOCK:
11112 res = conv_intrinsic_system_clock (code);
11113 break;
11115 default:
11116 res = NULL_TREE;
11117 break;
11120 return res;
11123 #include "gt-fortran-trans-intrinsic.h"