2018-02-25 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob816f3b99ac19cd6740965fa7c2335bd63121b796
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 "tree-nested.h"
35 #include "stor-layout.h"
36 #include "toplev.h" /* For rest_of_decl_compilation. */
37 #include "arith.h"
38 #include "trans-const.h"
39 #include "trans-types.h"
40 #include "trans-array.h"
41 #include "dependency.h" /* For CAF array alias analysis. */
42 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 /* This maps Fortran intrinsic math functions to external library or GCC
45 builtin functions. */
46 typedef struct GTY(()) gfc_intrinsic_map_t {
47 /* The explicit enum is required to work around inadequacies in the
48 garbage collection/gengtype parsing mechanism. */
49 enum gfc_isym_id id;
51 /* Enum value from the "language-independent", aka C-centric, part
52 of gcc, or END_BUILTINS of no such value set. */
53 enum built_in_function float_built_in;
54 enum built_in_function double_built_in;
55 enum built_in_function long_double_built_in;
56 enum built_in_function complex_float_built_in;
57 enum built_in_function complex_double_built_in;
58 enum built_in_function complex_long_double_built_in;
60 /* True if the naming pattern is to prepend "c" for complex and
61 append "f" for kind=4. False if the naming pattern is to
62 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
63 bool libm_name;
65 /* True if a complex version of the function exists. */
66 bool complex_available;
68 /* True if the function should be marked const. */
69 bool is_constant;
71 /* The base library name of this function. */
72 const char *name;
74 /* Cache decls created for the various operand types. */
75 tree real4_decl;
76 tree real8_decl;
77 tree real10_decl;
78 tree real16_decl;
79 tree complex4_decl;
80 tree complex8_decl;
81 tree complex10_decl;
82 tree complex16_decl;
84 gfc_intrinsic_map_t;
86 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
87 defines complex variants of all of the entries in mathbuiltins.def
88 except for atan2. */
89 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
90 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
91 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
92 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
93 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
95 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
96 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
97 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
98 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
99 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
101 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
102 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
103 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
105 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
107 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
108 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
109 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
110 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
111 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
113 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
115 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
116 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
117 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
118 #include "mathbuiltins.def"
120 /* Functions in libgfortran. */
121 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
123 /* End the list. */
124 LIB_FUNCTION (NONE, NULL, false)
127 #undef OTHER_BUILTIN
128 #undef LIB_FUNCTION
129 #undef DEFINE_MATH_BUILTIN
130 #undef DEFINE_MATH_BUILTIN_C
133 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
136 /* Find the correct variant of a given builtin from its argument. */
137 static tree
138 builtin_decl_for_precision (enum built_in_function base_built_in,
139 int precision)
141 enum built_in_function i = END_BUILTINS;
143 gfc_intrinsic_map_t *m;
144 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
147 if (precision == TYPE_PRECISION (float_type_node))
148 i = m->float_built_in;
149 else if (precision == TYPE_PRECISION (double_type_node))
150 i = m->double_built_in;
151 else if (precision == TYPE_PRECISION (long_double_type_node))
152 i = m->long_double_built_in;
153 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
155 /* Special treatment, because it is not exactly a built-in, but
156 a library function. */
157 return m->real16_decl;
160 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
164 tree
165 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
166 int kind)
168 int i = gfc_validate_kind (BT_REAL, kind, false);
170 if (gfc_real_kinds[i].c_float128)
172 /* For __float128, the story is a bit different, because we return
173 a decl to a library function rather than a built-in. */
174 gfc_intrinsic_map_t *m;
175 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
178 return m->real16_decl;
181 return builtin_decl_for_precision (double_built_in,
182 gfc_real_kinds[i].mode_precision);
186 /* Evaluate the arguments to an intrinsic function. The value
187 of NARGS may be less than the actual number of arguments in EXPR
188 to allow optional "KIND" arguments that are not included in the
189 generated code to be ignored. */
191 static void
192 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
193 tree *argarray, int nargs)
195 gfc_actual_arglist *actual;
196 gfc_expr *e;
197 gfc_intrinsic_arg *formal;
198 gfc_se argse;
199 int curr_arg;
201 formal = expr->value.function.isym->formal;
202 actual = expr->value.function.actual;
204 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
205 actual = actual->next,
206 formal = formal ? formal->next : NULL)
208 gcc_assert (actual);
209 e = actual->expr;
210 /* Skip omitted optional arguments. */
211 if (!e)
213 --curr_arg;
214 continue;
217 /* Evaluate the parameter. This will substitute scalarized
218 references automatically. */
219 gfc_init_se (&argse, se);
221 if (e->ts.type == BT_CHARACTER)
223 gfc_conv_expr (&argse, e);
224 gfc_conv_string_parameter (&argse);
225 argarray[curr_arg++] = argse.string_length;
226 gcc_assert (curr_arg < nargs);
228 else
229 gfc_conv_expr_val (&argse, e);
231 /* If an optional argument is itself an optional dummy argument,
232 check its presence and substitute a null if absent. */
233 if (e->expr_type == EXPR_VARIABLE
234 && e->symtree->n.sym->attr.optional
235 && formal
236 && formal->optional)
237 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
239 gfc_add_block_to_block (&se->pre, &argse.pre);
240 gfc_add_block_to_block (&se->post, &argse.post);
241 argarray[curr_arg] = argse.expr;
245 /* Count the number of actual arguments to the intrinsic function EXPR
246 including any "hidden" string length arguments. */
248 static unsigned int
249 gfc_intrinsic_argument_list_length (gfc_expr *expr)
251 int n = 0;
252 gfc_actual_arglist *actual;
254 for (actual = expr->value.function.actual; actual; actual = actual->next)
256 if (!actual->expr)
257 continue;
259 if (actual->expr->ts.type == BT_CHARACTER)
260 n += 2;
261 else
262 n++;
265 return n;
269 /* Conversions between different types are output by the frontend as
270 intrinsic functions. We implement these directly with inline code. */
272 static void
273 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
275 tree type;
276 tree *args;
277 int nargs;
279 nargs = gfc_intrinsic_argument_list_length (expr);
280 args = XALLOCAVEC (tree, nargs);
282 /* Evaluate all the arguments passed. Whilst we're only interested in the
283 first one here, there are other parts of the front-end that assume this
284 and will trigger an ICE if it's not the case. */
285 type = gfc_typenode_for_spec (&expr->ts);
286 gcc_assert (expr->value.function.actual->expr);
287 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
289 /* Conversion between character kinds involves a call to a library
290 function. */
291 if (expr->ts.type == BT_CHARACTER)
293 tree fndecl, var, addr, tmp;
295 if (expr->ts.kind == 1
296 && expr->value.function.actual->expr->ts.kind == 4)
297 fndecl = gfor_fndecl_convert_char4_to_char1;
298 else if (expr->ts.kind == 4
299 && expr->value.function.actual->expr->ts.kind == 1)
300 fndecl = gfor_fndecl_convert_char1_to_char4;
301 else
302 gcc_unreachable ();
304 /* Create the variable storing the converted value. */
305 type = gfc_get_pchar_type (expr->ts.kind);
306 var = gfc_create_var (type, "str");
307 addr = gfc_build_addr_expr (build_pointer_type (type), var);
309 /* Call the library function that will perform the conversion. */
310 gcc_assert (nargs >= 2);
311 tmp = build_call_expr_loc (input_location,
312 fndecl, 3, addr, args[0], args[1]);
313 gfc_add_expr_to_block (&se->pre, tmp);
315 /* Free the temporary afterwards. */
316 tmp = gfc_call_free (var);
317 gfc_add_expr_to_block (&se->post, tmp);
319 se->expr = var;
320 se->string_length = args[0];
322 return;
325 /* Conversion from complex to non-complex involves taking the real
326 component of the value. */
327 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
328 && expr->ts.type != BT_COMPLEX)
330 tree artype;
332 artype = TREE_TYPE (TREE_TYPE (args[0]));
333 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
334 args[0]);
337 se->expr = convert (type, args[0]);
340 /* This is needed because the gcc backend only implements
341 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
342 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
343 Similarly for CEILING. */
345 static tree
346 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
348 tree tmp;
349 tree cond;
350 tree argtype;
351 tree intval;
353 argtype = TREE_TYPE (arg);
354 arg = gfc_evaluate_now (arg, pblock);
356 intval = convert (type, arg);
357 intval = gfc_evaluate_now (intval, pblock);
359 tmp = convert (argtype, intval);
360 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
361 logical_type_node, tmp, arg);
363 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
364 intval, build_int_cst (type, 1));
365 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
366 return tmp;
370 /* Round to nearest integer, away from zero. */
372 static tree
373 build_round_expr (tree arg, tree restype)
375 tree argtype;
376 tree fn;
377 int argprec, resprec;
379 argtype = TREE_TYPE (arg);
380 argprec = TYPE_PRECISION (argtype);
381 resprec = TYPE_PRECISION (restype);
383 /* Depending on the type of the result, choose the int intrinsic
384 (iround, available only as a builtin, therefore cannot use it for
385 __float128), long int intrinsic (lround family) or long long
386 intrinsic (llround). We might also need to convert the result
387 afterwards. */
388 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
389 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
390 else if (resprec <= LONG_TYPE_SIZE)
391 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
392 else if (resprec <= LONG_LONG_TYPE_SIZE)
393 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
394 else
395 gcc_unreachable ();
397 return fold_convert (restype, build_call_expr_loc (input_location,
398 fn, 1, arg));
402 /* Convert a real to an integer using a specific rounding mode.
403 Ideally we would just build the corresponding GENERIC node,
404 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
406 static tree
407 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
408 enum rounding_mode op)
410 switch (op)
412 case RND_FLOOR:
413 return build_fixbound_expr (pblock, arg, type, 0);
415 case RND_CEIL:
416 return build_fixbound_expr (pblock, arg, type, 1);
418 case RND_ROUND:
419 return build_round_expr (arg, type);
421 case RND_TRUNC:
422 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
424 default:
425 gcc_unreachable ();
430 /* Round a real value using the specified rounding mode.
431 We use a temporary integer of that same kind size as the result.
432 Values larger than those that can be represented by this kind are
433 unchanged, as they will not be accurate enough to represent the
434 rounding.
435 huge = HUGE (KIND (a))
436 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
439 static void
440 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
442 tree type;
443 tree itype;
444 tree arg[2];
445 tree tmp;
446 tree cond;
447 tree decl;
448 mpfr_t huge;
449 int n, nargs;
450 int kind;
452 kind = expr->ts.kind;
453 nargs = gfc_intrinsic_argument_list_length (expr);
455 decl = NULL_TREE;
456 /* We have builtin functions for some cases. */
457 switch (op)
459 case RND_ROUND:
460 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
461 break;
463 case RND_TRUNC:
464 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
465 break;
467 default:
468 gcc_unreachable ();
471 /* Evaluate the argument. */
472 gcc_assert (expr->value.function.actual->expr);
473 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
475 /* Use a builtin function if one exists. */
476 if (decl != NULL_TREE)
478 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
479 return;
482 /* This code is probably redundant, but we'll keep it lying around just
483 in case. */
484 type = gfc_typenode_for_spec (&expr->ts);
485 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
487 /* Test if the value is too large to handle sensibly. */
488 gfc_set_model_kind (kind);
489 mpfr_init (huge);
490 n = gfc_validate_kind (BT_INTEGER, kind, false);
491 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
492 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
493 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
494 tmp);
496 mpfr_neg (huge, huge, GFC_RND_MODE);
497 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
498 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
499 tmp);
500 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
501 cond, tmp);
502 itype = gfc_get_int_type (kind);
504 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
505 tmp = convert (type, tmp);
506 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
507 arg[0]);
508 mpfr_clear (huge);
512 /* Convert to an integer using the specified rounding mode. */
514 static void
515 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
517 tree type;
518 tree *args;
519 int nargs;
521 nargs = gfc_intrinsic_argument_list_length (expr);
522 args = XALLOCAVEC (tree, nargs);
524 /* Evaluate the argument, we process all arguments even though we only
525 use the first one for code generation purposes. */
526 type = gfc_typenode_for_spec (&expr->ts);
527 gcc_assert (expr->value.function.actual->expr);
528 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
530 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
532 /* Conversion to a different integer kind. */
533 se->expr = convert (type, args[0]);
535 else
537 /* Conversion from complex to non-complex involves taking the real
538 component of the value. */
539 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
540 && expr->ts.type != BT_COMPLEX)
542 tree artype;
544 artype = TREE_TYPE (TREE_TYPE (args[0]));
545 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
546 args[0]);
549 se->expr = build_fix_expr (&se->pre, args[0], type, op);
554 /* Get the imaginary component of a value. */
556 static void
557 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
559 tree arg;
561 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
562 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
563 TREE_TYPE (TREE_TYPE (arg)), arg);
567 /* Get the complex conjugate of a value. */
569 static void
570 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
572 tree arg;
574 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
575 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
580 static tree
581 define_quad_builtin (const char *name, tree type, bool is_const)
583 tree fndecl;
584 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
585 type);
587 /* Mark the decl as external. */
588 DECL_EXTERNAL (fndecl) = 1;
589 TREE_PUBLIC (fndecl) = 1;
591 /* Mark it __attribute__((const)). */
592 TREE_READONLY (fndecl) = is_const;
594 rest_of_decl_compilation (fndecl, 1, 0);
596 return fndecl;
601 /* Initialize function decls for library functions. The external functions
602 are created as required. Builtin functions are added here. */
604 void
605 gfc_build_intrinsic_lib_fndecls (void)
607 gfc_intrinsic_map_t *m;
608 tree quad_decls[END_BUILTINS + 1];
610 if (gfc_real16_is_float128)
612 /* If we have soft-float types, we create the decls for their
613 C99-like library functions. For now, we only handle __float128
614 q-suffixed functions. */
616 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
617 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
619 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
621 type = gfc_float128_type_node;
622 complex_type = gfc_complex_float128_type_node;
623 /* type (*) (type) */
624 func_1 = build_function_type_list (type, type, NULL_TREE);
625 /* int (*) (type) */
626 func_iround = build_function_type_list (integer_type_node,
627 type, NULL_TREE);
628 /* long (*) (type) */
629 func_lround = build_function_type_list (long_integer_type_node,
630 type, NULL_TREE);
631 /* long long (*) (type) */
632 func_llround = build_function_type_list (long_long_integer_type_node,
633 type, NULL_TREE);
634 /* type (*) (type, type) */
635 func_2 = build_function_type_list (type, type, type, NULL_TREE);
636 /* type (*) (type, &int) */
637 func_frexp
638 = build_function_type_list (type,
639 type,
640 build_pointer_type (integer_type_node),
641 NULL_TREE);
642 /* type (*) (type, int) */
643 func_scalbn = build_function_type_list (type,
644 type, integer_type_node, NULL_TREE);
645 /* type (*) (complex type) */
646 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
647 /* complex type (*) (complex type, complex type) */
648 func_cpow
649 = build_function_type_list (complex_type,
650 complex_type, complex_type, NULL_TREE);
652 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
653 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
654 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
656 /* Only these built-ins are actually needed here. These are used directly
657 from the code, when calling builtin_decl_for_precision() or
658 builtin_decl_for_float_type(). The others are all constructed by
659 gfc_get_intrinsic_lib_fndecl(). */
660 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
661 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
663 #include "mathbuiltins.def"
665 #undef OTHER_BUILTIN
666 #undef LIB_FUNCTION
667 #undef DEFINE_MATH_BUILTIN
668 #undef DEFINE_MATH_BUILTIN_C
670 /* There is one built-in we defined manually, because it gets called
671 with builtin_decl_for_precision() or builtin_decl_for_float_type()
672 even though it is not an OTHER_BUILTIN: it is SQRT. */
673 quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
677 /* Add GCC builtin functions. */
678 for (m = gfc_intrinsic_map;
679 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
681 if (m->float_built_in != END_BUILTINS)
682 m->real4_decl = builtin_decl_explicit (m->float_built_in);
683 if (m->complex_float_built_in != END_BUILTINS)
684 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
685 if (m->double_built_in != END_BUILTINS)
686 m->real8_decl = builtin_decl_explicit (m->double_built_in);
687 if (m->complex_double_built_in != END_BUILTINS)
688 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
690 /* If real(kind=10) exists, it is always long double. */
691 if (m->long_double_built_in != END_BUILTINS)
692 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
693 if (m->complex_long_double_built_in != END_BUILTINS)
694 m->complex10_decl
695 = builtin_decl_explicit (m->complex_long_double_built_in);
697 if (!gfc_real16_is_float128)
699 if (m->long_double_built_in != END_BUILTINS)
700 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
701 if (m->complex_long_double_built_in != END_BUILTINS)
702 m->complex16_decl
703 = builtin_decl_explicit (m->complex_long_double_built_in);
705 else if (quad_decls[m->double_built_in] != NULL_TREE)
707 /* Quad-precision function calls are constructed when first
708 needed by builtin_decl_for_precision(), except for those
709 that will be used directly (define by OTHER_BUILTIN). */
710 m->real16_decl = quad_decls[m->double_built_in];
712 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
714 /* Same thing for the complex ones. */
715 m->complex16_decl = quad_decls[m->double_built_in];
721 /* Create a fndecl for a simple intrinsic library function. */
723 static tree
724 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
726 tree type;
727 vec<tree, va_gc> *argtypes;
728 tree fndecl;
729 gfc_actual_arglist *actual;
730 tree *pdecl;
731 gfc_typespec *ts;
732 char name[GFC_MAX_SYMBOL_LEN + 3];
734 ts = &expr->ts;
735 if (ts->type == BT_REAL)
737 switch (ts->kind)
739 case 4:
740 pdecl = &m->real4_decl;
741 break;
742 case 8:
743 pdecl = &m->real8_decl;
744 break;
745 case 10:
746 pdecl = &m->real10_decl;
747 break;
748 case 16:
749 pdecl = &m->real16_decl;
750 break;
751 default:
752 gcc_unreachable ();
755 else if (ts->type == BT_COMPLEX)
757 gcc_assert (m->complex_available);
759 switch (ts->kind)
761 case 4:
762 pdecl = &m->complex4_decl;
763 break;
764 case 8:
765 pdecl = &m->complex8_decl;
766 break;
767 case 10:
768 pdecl = &m->complex10_decl;
769 break;
770 case 16:
771 pdecl = &m->complex16_decl;
772 break;
773 default:
774 gcc_unreachable ();
777 else
778 gcc_unreachable ();
780 if (*pdecl)
781 return *pdecl;
783 if (m->libm_name)
785 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
786 if (gfc_real_kinds[n].c_float)
787 snprintf (name, sizeof (name), "%s%s%s",
788 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
789 else if (gfc_real_kinds[n].c_double)
790 snprintf (name, sizeof (name), "%s%s",
791 ts->type == BT_COMPLEX ? "c" : "", m->name);
792 else if (gfc_real_kinds[n].c_long_double)
793 snprintf (name, sizeof (name), "%s%s%s",
794 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
795 else if (gfc_real_kinds[n].c_float128)
796 snprintf (name, sizeof (name), "%s%s%s",
797 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
798 else
799 gcc_unreachable ();
801 else
803 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
804 ts->type == BT_COMPLEX ? 'c' : 'r',
805 ts->kind);
808 argtypes = NULL;
809 for (actual = expr->value.function.actual; actual; actual = actual->next)
811 type = gfc_typenode_for_spec (&actual->expr->ts);
812 vec_safe_push (argtypes, type);
814 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
815 fndecl = build_decl (input_location,
816 FUNCTION_DECL, get_identifier (name), type);
818 /* Mark the decl as external. */
819 DECL_EXTERNAL (fndecl) = 1;
820 TREE_PUBLIC (fndecl) = 1;
822 /* Mark it __attribute__((const)), if possible. */
823 TREE_READONLY (fndecl) = m->is_constant;
825 rest_of_decl_compilation (fndecl, 1, 0);
827 (*pdecl) = fndecl;
828 return fndecl;
832 /* Convert an intrinsic function into an external or builtin call. */
834 static void
835 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
837 gfc_intrinsic_map_t *m;
838 tree fndecl;
839 tree rettype;
840 tree *args;
841 unsigned int num_args;
842 gfc_isym_id id;
844 id = expr->value.function.isym->id;
845 /* Find the entry for this function. */
846 for (m = gfc_intrinsic_map;
847 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
849 if (id == m->id)
850 break;
853 if (m->id == GFC_ISYM_NONE)
855 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
856 expr->value.function.name, id);
859 /* Get the decl and generate the call. */
860 num_args = gfc_intrinsic_argument_list_length (expr);
861 args = XALLOCAVEC (tree, num_args);
863 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
864 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
865 rettype = TREE_TYPE (TREE_TYPE (fndecl));
867 fndecl = build_addr (fndecl);
868 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
872 /* If bounds-checking is enabled, create code to verify at runtime that the
873 string lengths for both expressions are the same (needed for e.g. MERGE).
874 If bounds-checking is not enabled, does nothing. */
876 void
877 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
878 tree a, tree b, stmtblock_t* target)
880 tree cond;
881 tree name;
883 /* If bounds-checking is disabled, do nothing. */
884 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
885 return;
887 /* Compare the two string lengths. */
888 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
890 /* Output the runtime-check. */
891 name = gfc_build_cstring_const (intr_name);
892 name = gfc_build_addr_expr (pchar_type_node, name);
893 gfc_trans_runtime_check (true, false, cond, target, where,
894 "Unequal character lengths (%ld/%ld) in %s",
895 fold_convert (long_integer_type_node, a),
896 fold_convert (long_integer_type_node, b), name);
900 /* The EXPONENT(X) intrinsic function is translated into
901 int ret;
902 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
903 so that if X is a NaN or infinity, the result is HUGE(0).
906 static void
907 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
909 tree arg, type, res, tmp, frexp, cond, huge;
910 int i;
912 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
913 expr->value.function.actual->expr->ts.kind);
915 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
916 arg = gfc_evaluate_now (arg, &se->pre);
918 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
919 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
920 cond = build_call_expr_loc (input_location,
921 builtin_decl_explicit (BUILT_IN_ISFINITE),
922 1, arg);
924 res = gfc_create_var (integer_type_node, NULL);
925 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
926 gfc_build_addr_expr (NULL_TREE, res));
927 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
928 tmp, res);
929 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
930 cond, tmp, huge);
932 type = gfc_typenode_for_spec (&expr->ts);
933 se->expr = fold_convert (type, se->expr);
937 /* Fill in the following structure
938 struct caf_vector_t {
939 size_t nvec; // size of the vector
940 union {
941 struct {
942 void *vector;
943 int kind;
944 } v;
945 struct {
946 ptrdiff_t lower_bound;
947 ptrdiff_t upper_bound;
948 ptrdiff_t stride;
949 } triplet;
950 } u;
951 } */
953 static void
954 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
955 tree lower, tree upper, tree stride,
956 tree vector, int kind, tree nvec)
958 tree field, type, tmp;
960 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
961 type = TREE_TYPE (desc);
963 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
964 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
965 desc, field, NULL_TREE);
966 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
968 /* Access union. */
969 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
970 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
971 desc, field, NULL_TREE);
972 type = TREE_TYPE (desc);
974 /* Access the inner struct. */
975 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
976 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
977 desc, field, NULL_TREE);
978 type = TREE_TYPE (desc);
980 if (vector != NULL_TREE)
982 /* Set vector and kind. */
983 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
984 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
985 desc, field, NULL_TREE);
986 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
987 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
988 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
989 desc, field, NULL_TREE);
990 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
992 else
994 /* Set dim.lower/upper/stride. */
995 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
996 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
997 desc, field, NULL_TREE);
998 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1000 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1001 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1002 desc, field, NULL_TREE);
1003 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1005 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1006 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1007 desc, field, NULL_TREE);
1008 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1013 static tree
1014 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1016 gfc_se argse;
1017 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1018 tree lbound, ubound, tmp;
1019 int i;
1021 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1023 for (i = 0; i < ar->dimen; i++)
1024 switch (ar->dimen_type[i])
1026 case DIMEN_RANGE:
1027 if (ar->end[i])
1029 gfc_init_se (&argse, NULL);
1030 gfc_conv_expr (&argse, ar->end[i]);
1031 gfc_add_block_to_block (block, &argse.pre);
1032 upper = gfc_evaluate_now (argse.expr, block);
1034 else
1035 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1036 if (ar->stride[i])
1038 gfc_init_se (&argse, NULL);
1039 gfc_conv_expr (&argse, ar->stride[i]);
1040 gfc_add_block_to_block (block, &argse.pre);
1041 stride = gfc_evaluate_now (argse.expr, block);
1043 else
1044 stride = gfc_index_one_node;
1046 /* Fall through. */
1047 case DIMEN_ELEMENT:
1048 if (ar->start[i])
1050 gfc_init_se (&argse, NULL);
1051 gfc_conv_expr (&argse, ar->start[i]);
1052 gfc_add_block_to_block (block, &argse.pre);
1053 lower = gfc_evaluate_now (argse.expr, block);
1055 else
1056 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1057 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1059 upper = lower;
1060 stride = gfc_index_one_node;
1062 vector = NULL_TREE;
1063 nvec = size_zero_node;
1064 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1065 vector, 0, nvec);
1066 break;
1068 case DIMEN_VECTOR:
1069 gfc_init_se (&argse, NULL);
1070 argse.descriptor_only = 1;
1071 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1072 gfc_add_block_to_block (block, &argse.pre);
1073 vector = argse.expr;
1074 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1075 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1076 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1077 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1078 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1079 TREE_TYPE (nvec), nvec, tmp);
1080 lower = gfc_index_zero_node;
1081 upper = gfc_index_zero_node;
1082 stride = gfc_index_zero_node;
1083 vector = gfc_conv_descriptor_data_get (vector);
1084 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1085 vector, ar->start[i]->ts.kind, nvec);
1086 break;
1087 default:
1088 gcc_unreachable();
1090 return gfc_build_addr_expr (NULL_TREE, var);
1094 static tree
1095 compute_component_offset (tree field, tree type)
1097 tree tmp;
1098 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1099 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1101 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1102 DECL_FIELD_BIT_OFFSET (field),
1103 bitsize_unit_node);
1104 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1106 else
1107 return DECL_FIELD_OFFSET (field);
1111 static tree
1112 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1114 gfc_ref *ref = expr->ref, *last_comp_ref;
1115 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1116 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1117 start, end, stride, vector, nvec;
1118 gfc_se se;
1119 bool ref_static_array = false;
1120 tree last_component_ref_tree = NULL_TREE;
1121 int i, last_type_n;
1123 if (expr->symtree)
1125 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1126 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1127 && !expr->symtree->n.sym->attr.pointer;
1130 /* Prevent uninit-warning. */
1131 reference_type = NULL_TREE;
1133 /* Skip refs upto the first coarray-ref. */
1134 last_comp_ref = NULL;
1135 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1137 /* Remember the type of components skipped. */
1138 if (ref->type == REF_COMPONENT)
1139 last_comp_ref = ref;
1140 ref = ref->next;
1142 /* When a component was skipped, get the type information of the last
1143 component ref, else get the type from the symbol. */
1144 if (last_comp_ref)
1146 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1147 last_type_n = last_comp_ref->u.c.component->ts.type;
1149 else
1151 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1152 last_type_n = expr->symtree->n.sym->ts.type;
1155 while (ref)
1157 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1158 && ref->u.ar.dimen == 0)
1160 /* Skip pure coindexes. */
1161 ref = ref->next;
1162 continue;
1164 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1165 reference_type = TREE_TYPE (tmp);
1167 if (caf_ref == NULL_TREE)
1168 caf_ref = tmp;
1170 /* Construct the chain of refs. */
1171 if (prev_caf_ref != NULL_TREE)
1173 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1174 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1175 TREE_TYPE (field), prev_caf_ref, field,
1176 NULL_TREE);
1177 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1178 tmp));
1180 prev_caf_ref = tmp;
1182 switch (ref->type)
1184 case REF_COMPONENT:
1185 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1186 last_type_n = ref->u.c.component->ts.type;
1187 /* Set the type of the ref. */
1188 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1189 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1190 TREE_TYPE (field), prev_caf_ref, field,
1191 NULL_TREE);
1192 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1193 GFC_CAF_REF_COMPONENT));
1195 /* Ref the c in union u. */
1196 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1197 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1198 TREE_TYPE (field), prev_caf_ref, field,
1199 NULL_TREE);
1200 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1201 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1202 TREE_TYPE (field), tmp, field,
1203 NULL_TREE);
1205 /* Set the offset. */
1206 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1207 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1208 TREE_TYPE (field), inner_struct, field,
1209 NULL_TREE);
1210 /* Computing the offset is somewhat harder. The bit_offset has to be
1211 taken into account. When the bit_offset in the field_decl is non-
1212 null, divide it by the bitsize_unit and add it to the regular
1213 offset. */
1214 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1215 TREE_TYPE (tmp));
1216 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1218 /* Set caf_token_offset. */
1219 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1220 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1221 TREE_TYPE (field), inner_struct, field,
1222 NULL_TREE);
1223 if ((ref->u.c.component->attr.allocatable
1224 || ref->u.c.component->attr.pointer)
1225 && ref->u.c.component->attr.dimension)
1227 tree arr_desc_token_offset;
1228 /* Get the token field from the descriptor. */
1229 arr_desc_token_offset = TREE_OPERAND (
1230 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1231 arr_desc_token_offset
1232 = compute_component_offset (arr_desc_token_offset,
1233 TREE_TYPE (tmp));
1234 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1235 TREE_TYPE (tmp2), tmp2,
1236 arr_desc_token_offset);
1238 else if (ref->u.c.component->caf_token)
1239 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1240 TREE_TYPE (tmp));
1241 else
1242 tmp2 = integer_zero_node;
1243 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1245 /* Remember whether this ref was to a non-allocatable/non-pointer
1246 component so the next array ref can be tailored correctly. */
1247 ref_static_array = !ref->u.c.component->attr.allocatable
1248 && !ref->u.c.component->attr.pointer;
1249 last_component_ref_tree = ref_static_array
1250 ? ref->u.c.component->backend_decl : NULL_TREE;
1251 break;
1252 case REF_ARRAY:
1253 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1254 ref_static_array = false;
1255 /* Set the type of the ref. */
1256 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1257 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1258 TREE_TYPE (field), prev_caf_ref, field,
1259 NULL_TREE);
1260 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1261 ref_static_array
1262 ? GFC_CAF_REF_STATIC_ARRAY
1263 : GFC_CAF_REF_ARRAY));
1265 /* Ref the a in union u. */
1266 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1267 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1268 TREE_TYPE (field), prev_caf_ref, field,
1269 NULL_TREE);
1270 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1271 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1272 TREE_TYPE (field), tmp, field,
1273 NULL_TREE);
1275 /* Set the static_array_type in a for static arrays. */
1276 if (ref_static_array)
1278 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1280 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1281 TREE_TYPE (field), inner_struct, field,
1282 NULL_TREE);
1283 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1284 last_type_n));
1286 /* Ref the mode in the inner_struct. */
1287 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1288 mode = fold_build3_loc (input_location, COMPONENT_REF,
1289 TREE_TYPE (field), inner_struct, field,
1290 NULL_TREE);
1291 /* Ref the dim in the inner_struct. */
1292 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1293 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1294 TREE_TYPE (field), inner_struct, field,
1295 NULL_TREE);
1296 for (i = 0; i < ref->u.ar.dimen; ++i)
1298 /* Ref dim i. */
1299 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1300 dim_type = TREE_TYPE (dim);
1301 mode_rhs = start = end = stride = NULL_TREE;
1302 switch (ref->u.ar.dimen_type[i])
1304 case DIMEN_RANGE:
1305 if (ref->u.ar.end[i])
1307 gfc_init_se (&se, NULL);
1308 gfc_conv_expr (&se, ref->u.ar.end[i]);
1309 gfc_add_block_to_block (block, &se.pre);
1310 if (ref_static_array)
1312 /* Make the index zero-based, when reffing a static
1313 array. */
1314 end = se.expr;
1315 gfc_init_se (&se, NULL);
1316 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1317 gfc_add_block_to_block (block, &se.pre);
1318 se.expr = fold_build2 (MINUS_EXPR,
1319 gfc_array_index_type,
1320 end, fold_convert (
1321 gfc_array_index_type,
1322 se.expr));
1324 end = gfc_evaluate_now (fold_convert (
1325 gfc_array_index_type,
1326 se.expr),
1327 block);
1329 else if (ref_static_array)
1330 end = fold_build2 (MINUS_EXPR,
1331 gfc_array_index_type,
1332 gfc_conv_array_ubound (
1333 last_component_ref_tree, i),
1334 gfc_conv_array_lbound (
1335 last_component_ref_tree, i));
1336 else
1338 end = NULL_TREE;
1339 mode_rhs = build_int_cst (unsigned_char_type_node,
1340 GFC_CAF_ARR_REF_OPEN_END);
1342 if (ref->u.ar.stride[i])
1344 gfc_init_se (&se, NULL);
1345 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1346 gfc_add_block_to_block (block, &se.pre);
1347 stride = gfc_evaluate_now (fold_convert (
1348 gfc_array_index_type,
1349 se.expr),
1350 block);
1351 if (ref_static_array)
1353 /* Make the index zero-based, when reffing a static
1354 array. */
1355 stride = fold_build2 (MULT_EXPR,
1356 gfc_array_index_type,
1357 gfc_conv_array_stride (
1358 last_component_ref_tree,
1360 stride);
1361 gcc_assert (end != NULL_TREE);
1362 /* Multiply with the product of array's stride and
1363 the step of the ref to a virtual upper bound.
1364 We can not compute the actual upper bound here or
1365 the caflib would compute the extend
1366 incorrectly. */
1367 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1368 end, gfc_conv_array_stride (
1369 last_component_ref_tree,
1370 i));
1371 end = gfc_evaluate_now (end, block);
1372 stride = gfc_evaluate_now (stride, block);
1375 else if (ref_static_array)
1377 stride = gfc_conv_array_stride (last_component_ref_tree,
1379 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1380 end, stride);
1381 end = gfc_evaluate_now (end, block);
1383 else
1384 /* Always set a ref stride of one to make caflib's
1385 handling easier. */
1386 stride = gfc_index_one_node;
1388 /* Fall through. */
1389 case DIMEN_ELEMENT:
1390 if (ref->u.ar.start[i])
1392 gfc_init_se (&se, NULL);
1393 gfc_conv_expr (&se, ref->u.ar.start[i]);
1394 gfc_add_block_to_block (block, &se.pre);
1395 if (ref_static_array)
1397 /* Make the index zero-based, when reffing a static
1398 array. */
1399 start = fold_convert (gfc_array_index_type, se.expr);
1400 gfc_init_se (&se, NULL);
1401 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1402 gfc_add_block_to_block (block, &se.pre);
1403 se.expr = fold_build2 (MINUS_EXPR,
1404 gfc_array_index_type,
1405 start, fold_convert (
1406 gfc_array_index_type,
1407 se.expr));
1408 /* Multiply with the stride. */
1409 se.expr = fold_build2 (MULT_EXPR,
1410 gfc_array_index_type,
1411 se.expr,
1412 gfc_conv_array_stride (
1413 last_component_ref_tree,
1414 i));
1416 start = gfc_evaluate_now (fold_convert (
1417 gfc_array_index_type,
1418 se.expr),
1419 block);
1420 if (mode_rhs == NULL_TREE)
1421 mode_rhs = build_int_cst (unsigned_char_type_node,
1422 ref->u.ar.dimen_type[i]
1423 == DIMEN_ELEMENT
1424 ? GFC_CAF_ARR_REF_SINGLE
1425 : GFC_CAF_ARR_REF_RANGE);
1427 else if (ref_static_array)
1429 start = integer_zero_node;
1430 mode_rhs = build_int_cst (unsigned_char_type_node,
1431 ref->u.ar.start[i] == NULL
1432 ? GFC_CAF_ARR_REF_FULL
1433 : GFC_CAF_ARR_REF_RANGE);
1435 else if (end == NULL_TREE)
1436 mode_rhs = build_int_cst (unsigned_char_type_node,
1437 GFC_CAF_ARR_REF_FULL);
1438 else
1439 mode_rhs = build_int_cst (unsigned_char_type_node,
1440 GFC_CAF_ARR_REF_OPEN_START);
1442 /* Ref the s in dim. */
1443 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1444 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1445 TREE_TYPE (field), dim, field,
1446 NULL_TREE);
1448 /* Set start in s. */
1449 if (start != NULL_TREE)
1451 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1453 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1454 TREE_TYPE (field), tmp, field,
1455 NULL_TREE);
1456 gfc_add_modify (block, tmp2,
1457 fold_convert (TREE_TYPE (tmp2), start));
1460 /* Set end in s. */
1461 if (end != NULL_TREE)
1463 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1465 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1466 TREE_TYPE (field), tmp, field,
1467 NULL_TREE);
1468 gfc_add_modify (block, tmp2,
1469 fold_convert (TREE_TYPE (tmp2), end));
1472 /* Set end in s. */
1473 if (stride != NULL_TREE)
1475 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1477 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1478 TREE_TYPE (field), tmp, field,
1479 NULL_TREE);
1480 gfc_add_modify (block, tmp2,
1481 fold_convert (TREE_TYPE (tmp2), stride));
1483 break;
1484 case DIMEN_VECTOR:
1485 /* TODO: In case of static array. */
1486 gcc_assert (!ref_static_array);
1487 mode_rhs = build_int_cst (unsigned_char_type_node,
1488 GFC_CAF_ARR_REF_VECTOR);
1489 gfc_init_se (&se, NULL);
1490 se.descriptor_only = 1;
1491 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1492 gfc_add_block_to_block (block, &se.pre);
1493 vector = se.expr;
1494 tmp = gfc_conv_descriptor_lbound_get (vector,
1495 gfc_rank_cst[0]);
1496 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1497 gfc_rank_cst[0]);
1498 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1499 tmp = gfc_conv_descriptor_stride_get (vector,
1500 gfc_rank_cst[0]);
1501 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1502 TREE_TYPE (nvec), nvec, tmp);
1503 vector = gfc_conv_descriptor_data_get (vector);
1505 /* Ref the v in dim. */
1506 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1507 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1508 TREE_TYPE (field), dim, field,
1509 NULL_TREE);
1511 /* Set vector in v. */
1512 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1513 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1514 TREE_TYPE (field), tmp, field,
1515 NULL_TREE);
1516 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1517 vector));
1519 /* Set nvec in v. */
1520 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1521 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1522 TREE_TYPE (field), tmp, field,
1523 NULL_TREE);
1524 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1525 nvec));
1527 /* Set kind in v. */
1528 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1529 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1530 TREE_TYPE (field), tmp, field,
1531 NULL_TREE);
1532 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1533 ref->u.ar.start[i]->ts.kind));
1534 break;
1535 default:
1536 gcc_unreachable ();
1538 /* Set the mode for dim i. */
1539 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1540 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1541 mode_rhs));
1544 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1545 if (i < GFC_MAX_DIMENSIONS)
1547 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1548 gfc_add_modify (block, tmp,
1549 build_int_cst (unsigned_char_type_node,
1550 GFC_CAF_ARR_REF_NONE));
1552 break;
1553 default:
1554 gcc_unreachable ();
1557 /* Set the size of the current type. */
1558 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1559 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1560 prev_caf_ref, field, NULL_TREE);
1561 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1562 TYPE_SIZE_UNIT (last_type)));
1564 ref = ref->next;
1567 if (prev_caf_ref != NULL_TREE)
1569 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1570 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1571 prev_caf_ref, field, NULL_TREE);
1572 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1573 null_pointer_node));
1575 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1576 : NULL_TREE;
1579 /* Get data from a remote coarray. */
1581 static void
1582 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1583 tree may_require_tmp, bool may_realloc,
1584 symbol_attribute *caf_attr)
1586 gfc_expr *array_expr, *tmp_stat;
1587 gfc_se argse;
1588 tree caf_decl, token, offset, image_index, tmp;
1589 tree res_var, dst_var, type, kind, vec, stat;
1590 tree caf_reference;
1591 symbol_attribute caf_attr_store;
1593 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1595 if (se->ss && se->ss->info->useflags)
1597 /* Access the previously obtained result. */
1598 gfc_conv_tmp_array_ref (se);
1599 return;
1602 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1603 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1604 type = gfc_typenode_for_spec (&array_expr->ts);
1606 if (caf_attr == NULL)
1608 caf_attr_store = gfc_caf_attr (array_expr);
1609 caf_attr = &caf_attr_store;
1612 res_var = lhs;
1613 dst_var = lhs;
1615 vec = null_pointer_node;
1616 tmp_stat = gfc_find_stat_co (expr);
1618 if (tmp_stat)
1620 gfc_se stat_se;
1621 gfc_init_se (&stat_se, NULL);
1622 gfc_conv_expr_reference (&stat_se, tmp_stat);
1623 stat = stat_se.expr;
1624 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1625 gfc_add_block_to_block (&se->post, &stat_se.post);
1627 else
1628 stat = null_pointer_node;
1630 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1631 is reallocatable or the right-hand side has allocatable components. */
1632 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1634 /* Get using caf_get_by_ref. */
1635 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1637 if (caf_reference != NULL_TREE)
1639 if (lhs == NULL_TREE)
1641 if (array_expr->ts.type == BT_CHARACTER)
1642 gfc_init_se (&argse, NULL);
1643 if (array_expr->rank == 0)
1645 symbol_attribute attr;
1646 gfc_clear_attr (&attr);
1647 if (array_expr->ts.type == BT_CHARACTER)
1649 res_var = gfc_conv_string_tmp (se,
1650 build_pointer_type (type),
1651 array_expr->ts.u.cl->backend_decl);
1652 argse.string_length = array_expr->ts.u.cl->backend_decl;
1654 else
1655 res_var = gfc_create_var (type, "caf_res");
1656 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1657 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1659 else
1661 /* Create temporary. */
1662 if (array_expr->ts.type == BT_CHARACTER)
1663 gfc_conv_expr_descriptor (&argse, array_expr);
1664 may_realloc = gfc_trans_create_temp_array (&se->pre,
1665 &se->post,
1666 se->ss, type,
1667 NULL_TREE, false,
1668 false, false,
1669 &array_expr->where)
1670 == NULL_TREE;
1671 res_var = se->ss->info->data.array.descriptor;
1672 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1673 if (may_realloc)
1675 tmp = gfc_conv_descriptor_data_get (res_var);
1676 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1677 NULL_TREE, NULL_TREE,
1678 NULL_TREE, true,
1679 NULL,
1680 GFC_CAF_COARRAY_NOCOARRAY);
1681 gfc_add_expr_to_block (&se->post, tmp);
1686 kind = build_int_cst (integer_type_node, expr->ts.kind);
1687 if (lhs_kind == NULL_TREE)
1688 lhs_kind = kind;
1690 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1691 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1692 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1693 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1694 caf_decl);
1695 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1696 array_expr);
1698 /* No overlap possible as we have generated a temporary. */
1699 if (lhs == NULL_TREE)
1700 may_require_tmp = boolean_false_node;
1702 /* It guarantees memory consistency within the same segment. */
1703 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1704 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1705 gfc_build_string_const (1, ""), NULL_TREE,
1706 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1707 NULL_TREE);
1708 ASM_VOLATILE_P (tmp) = 1;
1709 gfc_add_expr_to_block (&se->pre, tmp);
1711 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1712 10, token, image_index, dst_var,
1713 caf_reference, lhs_kind, kind,
1714 may_require_tmp,
1715 may_realloc ? boolean_true_node :
1716 boolean_false_node,
1717 stat, build_int_cst (integer_type_node,
1718 array_expr->ts.type));
1720 gfc_add_expr_to_block (&se->pre, tmp);
1722 if (se->ss)
1723 gfc_advance_se_ss_chain (se);
1725 se->expr = res_var;
1726 if (array_expr->ts.type == BT_CHARACTER)
1727 se->string_length = argse.string_length;
1729 return;
1733 gfc_init_se (&argse, NULL);
1734 if (array_expr->rank == 0)
1736 symbol_attribute attr;
1738 gfc_clear_attr (&attr);
1739 gfc_conv_expr (&argse, array_expr);
1741 if (lhs == NULL_TREE)
1743 gfc_clear_attr (&attr);
1744 if (array_expr->ts.type == BT_CHARACTER)
1745 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1746 argse.string_length);
1747 else
1748 res_var = gfc_create_var (type, "caf_res");
1749 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1750 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1752 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1753 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1755 else
1757 /* If has_vector, pass descriptor for whole array and the
1758 vector bounds separately. */
1759 gfc_array_ref *ar, ar2;
1760 bool has_vector = false;
1762 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1764 has_vector = true;
1765 ar = gfc_find_array_ref (expr);
1766 ar2 = *ar;
1767 memset (ar, '\0', sizeof (*ar));
1768 ar->as = ar2.as;
1769 ar->type = AR_FULL;
1771 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1772 gfc_conv_expr_descriptor (&argse, array_expr);
1773 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1774 has the wrong type if component references are done. */
1775 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1776 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1777 : array_expr->rank,
1778 type));
1779 if (has_vector)
1781 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1782 *ar = ar2;
1785 if (lhs == NULL_TREE)
1787 /* Create temporary. */
1788 for (int n = 0; n < se->ss->loop->dimen; n++)
1789 if (se->loop->to[n] == NULL_TREE)
1791 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1792 gfc_rank_cst[n]);
1793 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1794 gfc_rank_cst[n]);
1796 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1797 NULL_TREE, false, true, false,
1798 &array_expr->where);
1799 res_var = se->ss->info->data.array.descriptor;
1800 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1802 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1805 kind = build_int_cst (integer_type_node, expr->ts.kind);
1806 if (lhs_kind == NULL_TREE)
1807 lhs_kind = kind;
1809 gfc_add_block_to_block (&se->pre, &argse.pre);
1810 gfc_add_block_to_block (&se->post, &argse.post);
1812 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1813 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1814 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1815 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1816 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1817 array_expr);
1819 /* No overlap possible as we have generated a temporary. */
1820 if (lhs == NULL_TREE)
1821 may_require_tmp = boolean_false_node;
1823 /* It guarantees memory consistency within the same segment. */
1824 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1825 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1826 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1827 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1828 ASM_VOLATILE_P (tmp) = 1;
1829 gfc_add_expr_to_block (&se->pre, tmp);
1831 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1832 token, offset, image_index, argse.expr, vec,
1833 dst_var, kind, lhs_kind, may_require_tmp, stat);
1835 gfc_add_expr_to_block (&se->pre, tmp);
1837 if (se->ss)
1838 gfc_advance_se_ss_chain (se);
1840 se->expr = res_var;
1841 if (array_expr->ts.type == BT_CHARACTER)
1842 se->string_length = argse.string_length;
1846 /* Send data to a remote coarray. */
1848 static tree
1849 conv_caf_send (gfc_code *code) {
1850 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1851 gfc_se lhs_se, rhs_se;
1852 stmtblock_t block;
1853 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1854 tree may_require_tmp, src_stat, dst_stat, dst_team;
1855 tree lhs_type = NULL_TREE;
1856 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1857 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1859 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1861 lhs_expr = code->ext.actual->expr;
1862 rhs_expr = code->ext.actual->next->expr;
1863 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, false) == 0
1864 ? boolean_false_node : boolean_true_node;
1865 gfc_init_block (&block);
1867 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1868 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1869 src_stat = dst_stat = null_pointer_node;
1870 dst_team = null_pointer_node;
1872 /* LHS. */
1873 gfc_init_se (&lhs_se, NULL);
1874 if (lhs_expr->rank == 0)
1876 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1878 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1879 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1881 else
1883 symbol_attribute attr;
1884 gfc_clear_attr (&attr);
1885 gfc_conv_expr (&lhs_se, lhs_expr);
1886 lhs_type = TREE_TYPE (lhs_se.expr);
1887 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1888 attr);
1889 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1892 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1893 && lhs_caf_attr.codimension)
1895 lhs_se.want_pointer = 1;
1896 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1897 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1898 has the wrong type if component references are done. */
1899 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1900 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1901 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1902 gfc_get_dtype_rank_type (
1903 gfc_has_vector_subscript (lhs_expr)
1904 ? gfc_find_array_ref (lhs_expr)->dimen
1905 : lhs_expr->rank,
1906 lhs_type));
1908 else
1910 /* If has_vector, pass descriptor for whole array and the
1911 vector bounds separately. */
1912 gfc_array_ref *ar, ar2;
1913 bool has_vector = false;
1915 if (gfc_is_coindexed (lhs_expr) && gfc_has_vector_subscript (lhs_expr))
1917 has_vector = true;
1918 ar = gfc_find_array_ref (lhs_expr);
1919 ar2 = *ar;
1920 memset (ar, '\0', sizeof (*ar));
1921 ar->as = ar2.as;
1922 ar->type = AR_FULL;
1924 lhs_se.want_pointer = 1;
1925 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1926 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1927 has the wrong type if component references are done. */
1928 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1929 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1930 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1931 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1932 : lhs_expr->rank,
1933 lhs_type));
1934 if (has_vector)
1936 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1937 *ar = ar2;
1941 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
1943 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1944 temporary and a loop. */
1945 if (!gfc_is_coindexed (lhs_expr)
1946 && (!lhs_caf_attr.codimension
1947 || !(lhs_expr->rank > 0
1948 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
1950 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
1951 gcc_assert (gfc_is_coindexed (rhs_expr));
1952 gfc_init_se (&rhs_se, NULL);
1953 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
1955 gfc_se scal_se;
1956 gfc_init_se (&scal_se, NULL);
1957 scal_se.want_pointer = 1;
1958 gfc_conv_expr (&scal_se, lhs_expr);
1959 /* Ensure scalar on lhs is allocated. */
1960 gfc_add_block_to_block (&block, &scal_se.pre);
1962 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
1963 TYPE_SIZE_UNIT (
1964 gfc_typenode_for_spec (&lhs_expr->ts)),
1965 NULL_TREE);
1966 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
1967 null_pointer_node);
1968 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1969 tmp, gfc_finish_block (&scal_se.pre),
1970 build_empty_stmt (input_location));
1971 gfc_add_expr_to_block (&block, tmp);
1973 else
1974 lhs_may_realloc = lhs_may_realloc
1975 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
1976 gfc_add_block_to_block (&block, &lhs_se.pre);
1977 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1978 may_require_tmp, lhs_may_realloc,
1979 &rhs_caf_attr);
1980 gfc_add_block_to_block (&block, &rhs_se.pre);
1981 gfc_add_block_to_block (&block, &rhs_se.post);
1982 gfc_add_block_to_block (&block, &lhs_se.post);
1983 return gfc_finish_block (&block);
1986 gfc_add_block_to_block (&block, &lhs_se.pre);
1988 /* Obtain token, offset and image index for the LHS. */
1989 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
1990 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1991 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1992 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
1993 tmp = lhs_se.expr;
1994 if (lhs_caf_attr.alloc_comp)
1995 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
1996 NULL);
1997 else
1998 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
1999 lhs_expr);
2000 lhs_se.expr = tmp;
2002 /* RHS. */
2003 gfc_init_se (&rhs_se, NULL);
2004 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2005 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2006 rhs_expr = rhs_expr->value.function.actual->expr;
2007 if (rhs_expr->rank == 0)
2009 symbol_attribute attr;
2010 gfc_clear_attr (&attr);
2011 gfc_conv_expr (&rhs_se, rhs_expr);
2012 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2013 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2015 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2016 && rhs_caf_attr.codimension)
2018 tree tmp2;
2019 rhs_se.want_pointer = 1;
2020 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2021 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2022 has the wrong type if component references are done. */
2023 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2024 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2025 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2026 gfc_get_dtype_rank_type (
2027 gfc_has_vector_subscript (rhs_expr)
2028 ? gfc_find_array_ref (rhs_expr)->dimen
2029 : rhs_expr->rank,
2030 tmp2));
2032 else
2034 /* If has_vector, pass descriptor for whole array and the
2035 vector bounds separately. */
2036 gfc_array_ref *ar, ar2;
2037 bool has_vector = false;
2038 tree tmp2;
2040 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2042 has_vector = true;
2043 ar = gfc_find_array_ref (rhs_expr);
2044 ar2 = *ar;
2045 memset (ar, '\0', sizeof (*ar));
2046 ar->as = ar2.as;
2047 ar->type = AR_FULL;
2049 rhs_se.want_pointer = 1;
2050 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2051 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2052 has the wrong type if component references are done. */
2053 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2054 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2055 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2056 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2057 : rhs_expr->rank,
2058 tmp2));
2059 if (has_vector)
2061 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2062 *ar = ar2;
2066 gfc_add_block_to_block (&block, &rhs_se.pre);
2068 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2070 tmp_stat = gfc_find_stat_co (lhs_expr);
2072 if (tmp_stat)
2074 gfc_se stat_se;
2075 gfc_init_se (&stat_se, NULL);
2076 gfc_conv_expr_reference (&stat_se, tmp_stat);
2077 dst_stat = stat_se.expr;
2078 gfc_add_block_to_block (&block, &stat_se.pre);
2079 gfc_add_block_to_block (&block, &stat_se.post);
2082 tmp_team = gfc_find_team_co (lhs_expr);
2084 if (tmp_team)
2086 gfc_se team_se;
2087 gfc_init_se (&team_se, NULL);
2088 gfc_conv_expr_reference (&team_se, tmp_team);
2089 dst_team = team_se.expr;
2090 gfc_add_block_to_block (&block, &team_se.pre);
2091 gfc_add_block_to_block (&block, &team_se.post);
2094 if (!gfc_is_coindexed (rhs_expr))
2096 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2098 tree reference, dst_realloc;
2099 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2100 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2101 : boolean_false_node;
2102 tmp = build_call_expr_loc (input_location,
2103 gfor_fndecl_caf_send_by_ref,
2104 10, token, image_index, rhs_se.expr,
2105 reference, lhs_kind, rhs_kind,
2106 may_require_tmp, dst_realloc, src_stat,
2107 build_int_cst (integer_type_node,
2108 lhs_expr->ts.type));
2110 else
2111 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2112 token, offset, image_index, lhs_se.expr, vec,
2113 rhs_se.expr, lhs_kind, rhs_kind,
2114 may_require_tmp, src_stat, dst_team);
2116 else
2118 tree rhs_token, rhs_offset, rhs_image_index;
2120 /* It guarantees memory consistency within the same segment. */
2121 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2122 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2123 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2124 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2125 ASM_VOLATILE_P (tmp) = 1;
2126 gfc_add_expr_to_block (&block, tmp);
2128 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2129 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2130 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2131 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2132 tmp = rhs_se.expr;
2133 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2135 tmp_stat = gfc_find_stat_co (lhs_expr);
2137 if (tmp_stat)
2139 gfc_se stat_se;
2140 gfc_init_se (&stat_se, NULL);
2141 gfc_conv_expr_reference (&stat_se, tmp_stat);
2142 src_stat = stat_se.expr;
2143 gfc_add_block_to_block (&block, &stat_se.pre);
2144 gfc_add_block_to_block (&block, &stat_se.post);
2147 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2148 NULL_TREE, NULL);
2149 tree lhs_reference, rhs_reference;
2150 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2151 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2152 tmp = build_call_expr_loc (input_location,
2153 gfor_fndecl_caf_sendget_by_ref, 13,
2154 token, image_index, lhs_reference,
2155 rhs_token, rhs_image_index, rhs_reference,
2156 lhs_kind, rhs_kind, may_require_tmp,
2157 dst_stat, src_stat,
2158 build_int_cst (integer_type_node,
2159 lhs_expr->ts.type),
2160 build_int_cst (integer_type_node,
2161 rhs_expr->ts.type));
2163 else
2165 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2166 tmp, rhs_expr);
2167 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2168 14, token, offset, image_index,
2169 lhs_se.expr, vec, rhs_token, rhs_offset,
2170 rhs_image_index, tmp, rhs_vec, lhs_kind,
2171 rhs_kind, may_require_tmp, src_stat);
2174 gfc_add_expr_to_block (&block, tmp);
2175 gfc_add_block_to_block (&block, &lhs_se.post);
2176 gfc_add_block_to_block (&block, &rhs_se.post);
2178 /* It guarantees memory consistency within the same segment. */
2179 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2180 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2181 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2182 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2183 ASM_VOLATILE_P (tmp) = 1;
2184 gfc_add_expr_to_block (&block, tmp);
2186 return gfc_finish_block (&block);
2190 static void
2191 trans_this_image (gfc_se * se, gfc_expr *expr)
2193 stmtblock_t loop;
2194 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2195 lbound, ubound, extent, ml;
2196 gfc_se argse;
2197 int rank, corank;
2198 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2200 if (expr->value.function.actual->expr
2201 && !gfc_is_coarray (expr->value.function.actual->expr))
2202 distance = expr->value.function.actual->expr;
2204 /* The case -fcoarray=single is handled elsewhere. */
2205 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2207 /* Argument-free version: THIS_IMAGE(). */
2208 if (distance || expr->value.function.actual->expr == NULL)
2210 if (distance)
2212 gfc_init_se (&argse, NULL);
2213 gfc_conv_expr_val (&argse, distance);
2214 gfc_add_block_to_block (&se->pre, &argse.pre);
2215 gfc_add_block_to_block (&se->post, &argse.post);
2216 tmp = fold_convert (integer_type_node, argse.expr);
2218 else
2219 tmp = integer_zero_node;
2220 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2221 tmp);
2222 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2223 tmp);
2224 return;
2227 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2229 type = gfc_get_int_type (gfc_default_integer_kind);
2230 corank = gfc_get_corank (expr->value.function.actual->expr);
2231 rank = expr->value.function.actual->expr->rank;
2233 /* Obtain the descriptor of the COARRAY. */
2234 gfc_init_se (&argse, NULL);
2235 argse.want_coarray = 1;
2236 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2237 gfc_add_block_to_block (&se->pre, &argse.pre);
2238 gfc_add_block_to_block (&se->post, &argse.post);
2239 desc = argse.expr;
2241 if (se->ss)
2243 /* Create an implicit second parameter from the loop variable. */
2244 gcc_assert (!expr->value.function.actual->next->expr);
2245 gcc_assert (corank > 0);
2246 gcc_assert (se->loop->dimen == 1);
2247 gcc_assert (se->ss->info->expr == expr);
2249 dim_arg = se->loop->loopvar[0];
2250 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2251 gfc_array_index_type, dim_arg,
2252 build_int_cst (TREE_TYPE (dim_arg), 1));
2253 gfc_advance_se_ss_chain (se);
2255 else
2257 /* Use the passed DIM= argument. */
2258 gcc_assert (expr->value.function.actual->next->expr);
2259 gfc_init_se (&argse, NULL);
2260 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2261 gfc_array_index_type);
2262 gfc_add_block_to_block (&se->pre, &argse.pre);
2263 dim_arg = argse.expr;
2265 if (INTEGER_CST_P (dim_arg))
2267 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2268 || wi::gtu_p (wi::to_wide (dim_arg),
2269 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2270 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2271 "dimension index", expr->value.function.isym->name,
2272 &expr->where);
2274 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2276 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2277 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2278 dim_arg,
2279 build_int_cst (TREE_TYPE (dim_arg), 1));
2280 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2281 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2282 dim_arg, tmp);
2283 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2284 logical_type_node, cond, tmp);
2285 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2286 gfc_msg_fault);
2290 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2291 one always has a dim_arg argument.
2293 m = this_image() - 1
2294 if (corank == 1)
2296 sub(1) = m + lcobound(corank)
2297 return;
2299 i = rank
2300 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2301 for (;;)
2303 extent = gfc_extent(i)
2304 ml = m
2305 m = m/extent
2306 if (i >= min_var)
2307 goto exit_label
2310 exit_label:
2311 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2312 : m + lcobound(corank)
2315 /* this_image () - 1. */
2316 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2317 integer_zero_node);
2318 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2319 fold_convert (type, tmp), build_int_cst (type, 1));
2320 if (corank == 1)
2322 /* sub(1) = m + lcobound(corank). */
2323 lbound = gfc_conv_descriptor_lbound_get (desc,
2324 build_int_cst (TREE_TYPE (gfc_array_index_type),
2325 corank+rank-1));
2326 lbound = fold_convert (type, lbound);
2327 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2329 se->expr = tmp;
2330 return;
2333 m = gfc_create_var (type, NULL);
2334 ml = gfc_create_var (type, NULL);
2335 loop_var = gfc_create_var (integer_type_node, NULL);
2336 min_var = gfc_create_var (integer_type_node, NULL);
2338 /* m = this_image () - 1. */
2339 gfc_add_modify (&se->pre, m, tmp);
2341 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2342 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2343 fold_convert (integer_type_node, dim_arg),
2344 build_int_cst (integer_type_node, rank - 1));
2345 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2346 build_int_cst (integer_type_node, rank + corank - 2),
2347 tmp);
2348 gfc_add_modify (&se->pre, min_var, tmp);
2350 /* i = rank. */
2351 tmp = build_int_cst (integer_type_node, rank);
2352 gfc_add_modify (&se->pre, loop_var, tmp);
2354 exit_label = gfc_build_label_decl (NULL_TREE);
2355 TREE_USED (exit_label) = 1;
2357 /* Loop body. */
2358 gfc_init_block (&loop);
2360 /* ml = m. */
2361 gfc_add_modify (&loop, ml, m);
2363 /* extent = ... */
2364 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2365 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2366 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2367 extent = fold_convert (type, extent);
2369 /* m = m/extent. */
2370 gfc_add_modify (&loop, m,
2371 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2372 m, extent));
2374 /* Exit condition: if (i >= min_var) goto exit_label. */
2375 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2376 min_var);
2377 tmp = build1_v (GOTO_EXPR, exit_label);
2378 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2379 build_empty_stmt (input_location));
2380 gfc_add_expr_to_block (&loop, tmp);
2382 /* Increment loop variable: i++. */
2383 gfc_add_modify (&loop, loop_var,
2384 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2385 loop_var,
2386 build_int_cst (integer_type_node, 1)));
2388 /* Making the loop... actually loop! */
2389 tmp = gfc_finish_block (&loop);
2390 tmp = build1_v (LOOP_EXPR, tmp);
2391 gfc_add_expr_to_block (&se->pre, tmp);
2393 /* The exit label. */
2394 tmp = build1_v (LABEL_EXPR, exit_label);
2395 gfc_add_expr_to_block (&se->pre, tmp);
2397 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2398 : m + lcobound(corank) */
2400 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2401 build_int_cst (TREE_TYPE (dim_arg), corank));
2403 lbound = gfc_conv_descriptor_lbound_get (desc,
2404 fold_build2_loc (input_location, PLUS_EXPR,
2405 gfc_array_index_type, dim_arg,
2406 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2407 lbound = fold_convert (type, lbound);
2409 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2410 fold_build2_loc (input_location, MULT_EXPR, type,
2411 m, extent));
2412 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2414 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2415 fold_build2_loc (input_location, PLUS_EXPR, type,
2416 m, lbound));
2420 /* Convert a call to image_status. */
2422 static void
2423 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2425 unsigned int num_args;
2426 tree *args, tmp;
2428 num_args = gfc_intrinsic_argument_list_length (expr);
2429 args = XALLOCAVEC (tree, num_args);
2430 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2431 /* In args[0] the number of the image the status is desired for has to be
2432 given. */
2434 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2436 tree arg;
2437 arg = gfc_evaluate_now (args[0], &se->pre);
2438 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2439 fold_convert (integer_type_node, arg),
2440 integer_one_node);
2441 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2442 tmp, integer_zero_node,
2443 build_int_cst (integer_type_node,
2444 GFC_STAT_STOPPED_IMAGE));
2446 else if (flag_coarray == GFC_FCOARRAY_LIB)
2447 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2448 args[0], build_int_cst (integer_type_node, -1));
2449 else
2450 gcc_unreachable ();
2452 se->expr = tmp;
2455 static void
2456 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2458 unsigned int num_args;
2460 tree *args, tmp;
2462 num_args = gfc_intrinsic_argument_list_length (expr);
2463 args = XALLOCAVEC (tree, num_args);
2464 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2466 if (flag_coarray ==
2467 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2469 tree arg;
2471 arg = gfc_evaluate_now (args[0], &se->pre);
2472 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2473 fold_convert (integer_type_node, arg),
2474 integer_one_node);
2475 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2476 tmp, integer_zero_node,
2477 build_int_cst (integer_type_node,
2478 GFC_STAT_STOPPED_IMAGE));
2480 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2482 // the value -1 represents that no team has been created yet
2483 tmp = build_int_cst (integer_type_node, -1);
2485 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2486 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2487 args[0], build_int_cst (integer_type_node, -1));
2488 else if (flag_coarray == GFC_FCOARRAY_LIB)
2489 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2490 integer_zero_node, build_int_cst (integer_type_node, -1));
2491 else
2492 gcc_unreachable ();
2494 se->expr = tmp;
2498 static void
2499 trans_image_index (gfc_se * se, gfc_expr *expr)
2501 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2502 tmp, invalid_bound;
2503 gfc_se argse, subse;
2504 int rank, corank, codim;
2506 type = gfc_get_int_type (gfc_default_integer_kind);
2507 corank = gfc_get_corank (expr->value.function.actual->expr);
2508 rank = expr->value.function.actual->expr->rank;
2510 /* Obtain the descriptor of the COARRAY. */
2511 gfc_init_se (&argse, NULL);
2512 argse.want_coarray = 1;
2513 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2514 gfc_add_block_to_block (&se->pre, &argse.pre);
2515 gfc_add_block_to_block (&se->post, &argse.post);
2516 desc = argse.expr;
2518 /* Obtain a handle to the SUB argument. */
2519 gfc_init_se (&subse, NULL);
2520 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2521 gfc_add_block_to_block (&se->pre, &subse.pre);
2522 gfc_add_block_to_block (&se->post, &subse.post);
2523 subdesc = build_fold_indirect_ref_loc (input_location,
2524 gfc_conv_descriptor_data_get (subse.expr));
2526 /* Fortran 2008 does not require that the values remain in the cobounds,
2527 thus we need explicitly check this - and return 0 if they are exceeded. */
2529 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2530 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2531 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2532 fold_convert (gfc_array_index_type, tmp),
2533 lbound);
2535 for (codim = corank + rank - 2; codim >= rank; codim--)
2537 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2538 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2539 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2540 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2541 fold_convert (gfc_array_index_type, tmp),
2542 lbound);
2543 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2544 logical_type_node, invalid_bound, cond);
2545 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2546 fold_convert (gfc_array_index_type, tmp),
2547 ubound);
2548 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2549 logical_type_node, invalid_bound, cond);
2552 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2554 /* See Fortran 2008, C.10 for the following algorithm. */
2556 /* coindex = sub(corank) - lcobound(n). */
2557 coindex = fold_convert (gfc_array_index_type,
2558 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2559 NULL));
2560 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2561 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2562 fold_convert (gfc_array_index_type, coindex),
2563 lbound);
2565 for (codim = corank + rank - 2; codim >= rank; codim--)
2567 tree extent, ubound;
2569 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2570 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2571 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2572 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2574 /* coindex *= extent. */
2575 coindex = fold_build2_loc (input_location, MULT_EXPR,
2576 gfc_array_index_type, coindex, extent);
2578 /* coindex += sub(codim). */
2579 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2580 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2581 gfc_array_index_type, coindex,
2582 fold_convert (gfc_array_index_type, tmp));
2584 /* coindex -= lbound(codim). */
2585 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2586 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2587 gfc_array_index_type, coindex, lbound);
2590 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2591 fold_convert(type, coindex),
2592 build_int_cst (type, 1));
2594 /* Return 0 if "coindex" exceeds num_images(). */
2596 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2597 num_images = build_int_cst (type, 1);
2598 else
2600 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2601 integer_zero_node,
2602 build_int_cst (integer_type_node, -1));
2603 num_images = fold_convert (type, tmp);
2606 tmp = gfc_create_var (type, NULL);
2607 gfc_add_modify (&se->pre, tmp, coindex);
2609 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2610 num_images);
2611 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2612 cond,
2613 fold_convert (logical_type_node, invalid_bound));
2614 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2615 build_int_cst (type, 0), tmp);
2618 static void
2619 trans_num_images (gfc_se * se, gfc_expr *expr)
2621 tree tmp, distance, failed;
2622 gfc_se argse;
2624 if (expr->value.function.actual->expr)
2626 gfc_init_se (&argse, NULL);
2627 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2628 gfc_add_block_to_block (&se->pre, &argse.pre);
2629 gfc_add_block_to_block (&se->post, &argse.post);
2630 distance = fold_convert (integer_type_node, argse.expr);
2632 else
2633 distance = integer_zero_node;
2635 if (expr->value.function.actual->next->expr)
2637 gfc_init_se (&argse, NULL);
2638 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2639 gfc_add_block_to_block (&se->pre, &argse.pre);
2640 gfc_add_block_to_block (&se->post, &argse.post);
2641 failed = fold_convert (integer_type_node, argse.expr);
2643 else
2644 failed = build_int_cst (integer_type_node, -1);
2645 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2646 distance, failed);
2647 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2651 static void
2652 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2654 gfc_se argse;
2656 gfc_init_se (&argse, NULL);
2657 argse.data_not_needed = 1;
2658 argse.descriptor_only = 1;
2660 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2661 gfc_add_block_to_block (&se->pre, &argse.pre);
2662 gfc_add_block_to_block (&se->post, &argse.post);
2664 se->expr = gfc_conv_descriptor_rank (argse.expr);
2665 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2666 se->expr);
2670 /* Evaluate a single upper or lower bound. */
2671 /* TODO: bound intrinsic generates way too much unnecessary code. */
2673 static void
2674 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2676 gfc_actual_arglist *arg;
2677 gfc_actual_arglist *arg2;
2678 tree desc;
2679 tree type;
2680 tree bound;
2681 tree tmp;
2682 tree cond, cond1, cond3, cond4, size;
2683 tree ubound;
2684 tree lbound;
2685 gfc_se argse;
2686 gfc_array_spec * as;
2687 bool assumed_rank_lb_one;
2689 arg = expr->value.function.actual;
2690 arg2 = arg->next;
2692 if (se->ss)
2694 /* Create an implicit second parameter from the loop variable. */
2695 gcc_assert (!arg2->expr);
2696 gcc_assert (se->loop->dimen == 1);
2697 gcc_assert (se->ss->info->expr == expr);
2698 gfc_advance_se_ss_chain (se);
2699 bound = se->loop->loopvar[0];
2700 bound = fold_build2_loc (input_location, MINUS_EXPR,
2701 gfc_array_index_type, bound,
2702 se->loop->from[0]);
2704 else
2706 /* use the passed argument. */
2707 gcc_assert (arg2->expr);
2708 gfc_init_se (&argse, NULL);
2709 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2710 gfc_add_block_to_block (&se->pre, &argse.pre);
2711 bound = argse.expr;
2712 /* Convert from one based to zero based. */
2713 bound = fold_build2_loc (input_location, MINUS_EXPR,
2714 gfc_array_index_type, bound,
2715 gfc_index_one_node);
2718 /* TODO: don't re-evaluate the descriptor on each iteration. */
2719 /* Get a descriptor for the first parameter. */
2720 gfc_init_se (&argse, NULL);
2721 gfc_conv_expr_descriptor (&argse, arg->expr);
2722 gfc_add_block_to_block (&se->pre, &argse.pre);
2723 gfc_add_block_to_block (&se->post, &argse.post);
2725 desc = argse.expr;
2727 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2729 if (INTEGER_CST_P (bound))
2731 if (((!as || as->type != AS_ASSUMED_RANK)
2732 && wi::geu_p (wi::to_wide (bound),
2733 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2734 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2735 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2736 "dimension index", upper ? "UBOUND" : "LBOUND",
2737 &expr->where);
2740 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2742 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2744 bound = gfc_evaluate_now (bound, &se->pre);
2745 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2746 bound, build_int_cst (TREE_TYPE (bound), 0));
2747 if (as && as->type == AS_ASSUMED_RANK)
2748 tmp = gfc_conv_descriptor_rank (desc);
2749 else
2750 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2751 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2752 bound, fold_convert(TREE_TYPE (bound), tmp));
2753 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2754 logical_type_node, cond, tmp);
2755 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2756 gfc_msg_fault);
2760 /* Take care of the lbound shift for assumed-rank arrays, which are
2761 nonallocatable and nonpointers. Those has a lbound of 1. */
2762 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2763 && ((arg->expr->ts.type != BT_CLASS
2764 && !arg->expr->symtree->n.sym->attr.allocatable
2765 && !arg->expr->symtree->n.sym->attr.pointer)
2766 || (arg->expr->ts.type == BT_CLASS
2767 && !CLASS_DATA (arg->expr)->attr.allocatable
2768 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2770 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2771 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2773 /* 13.14.53: Result value for LBOUND
2775 Case (i): For an array section or for an array expression other than a
2776 whole array or array structure component, LBOUND(ARRAY, DIM)
2777 has the value 1. For a whole array or array structure
2778 component, LBOUND(ARRAY, DIM) has the value:
2779 (a) equal to the lower bound for subscript DIM of ARRAY if
2780 dimension DIM of ARRAY does not have extent zero
2781 or if ARRAY is an assumed-size array of rank DIM,
2782 or (b) 1 otherwise.
2784 13.14.113: Result value for UBOUND
2786 Case (i): For an array section or for an array expression other than a
2787 whole array or array structure component, UBOUND(ARRAY, DIM)
2788 has the value equal to the number of elements in the given
2789 dimension; otherwise, it has a value equal to the upper bound
2790 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2791 not have size zero and has value zero if dimension DIM has
2792 size zero. */
2794 if (!upper && assumed_rank_lb_one)
2795 se->expr = gfc_index_one_node;
2796 else if (as)
2798 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2800 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2801 ubound, lbound);
2802 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2803 stride, gfc_index_zero_node);
2804 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2805 logical_type_node, cond3, cond1);
2806 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2807 stride, gfc_index_zero_node);
2809 if (upper)
2811 tree cond5;
2812 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2813 logical_type_node, cond3, cond4);
2814 cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2815 gfc_index_one_node, lbound);
2816 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2817 logical_type_node, cond4, cond5);
2819 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2820 logical_type_node, cond, cond5);
2822 if (assumed_rank_lb_one)
2824 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2825 gfc_array_index_type, ubound, lbound);
2826 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2827 gfc_array_index_type, tmp, gfc_index_one_node);
2829 else
2830 tmp = ubound;
2832 se->expr = fold_build3_loc (input_location, COND_EXPR,
2833 gfc_array_index_type, cond,
2834 tmp, gfc_index_zero_node);
2836 else
2838 if (as->type == AS_ASSUMED_SIZE)
2839 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2840 bound, build_int_cst (TREE_TYPE (bound),
2841 arg->expr->rank - 1));
2842 else
2843 cond = logical_false_node;
2845 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2846 logical_type_node, cond3, cond4);
2847 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2848 logical_type_node, cond, cond1);
2850 se->expr = fold_build3_loc (input_location, COND_EXPR,
2851 gfc_array_index_type, cond,
2852 lbound, gfc_index_one_node);
2855 else
2857 if (upper)
2859 size = fold_build2_loc (input_location, MINUS_EXPR,
2860 gfc_array_index_type, ubound, lbound);
2861 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2862 gfc_array_index_type, size,
2863 gfc_index_one_node);
2864 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2865 gfc_array_index_type, se->expr,
2866 gfc_index_zero_node);
2868 else
2869 se->expr = gfc_index_one_node;
2872 type = gfc_typenode_for_spec (&expr->ts);
2873 se->expr = convert (type, se->expr);
2877 static void
2878 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2880 gfc_actual_arglist *arg;
2881 gfc_actual_arglist *arg2;
2882 gfc_se argse;
2883 tree bound, resbound, resbound2, desc, cond, tmp;
2884 tree type;
2885 int corank;
2887 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2888 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2889 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2891 arg = expr->value.function.actual;
2892 arg2 = arg->next;
2894 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2895 corank = gfc_get_corank (arg->expr);
2897 gfc_init_se (&argse, NULL);
2898 argse.want_coarray = 1;
2900 gfc_conv_expr_descriptor (&argse, arg->expr);
2901 gfc_add_block_to_block (&se->pre, &argse.pre);
2902 gfc_add_block_to_block (&se->post, &argse.post);
2903 desc = argse.expr;
2905 if (se->ss)
2907 /* Create an implicit second parameter from the loop variable. */
2908 gcc_assert (!arg2->expr);
2909 gcc_assert (corank > 0);
2910 gcc_assert (se->loop->dimen == 1);
2911 gcc_assert (se->ss->info->expr == expr);
2913 bound = se->loop->loopvar[0];
2914 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2915 bound, gfc_rank_cst[arg->expr->rank]);
2916 gfc_advance_se_ss_chain (se);
2918 else
2920 /* use the passed argument. */
2921 gcc_assert (arg2->expr);
2922 gfc_init_se (&argse, NULL);
2923 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2924 gfc_add_block_to_block (&se->pre, &argse.pre);
2925 bound = argse.expr;
2927 if (INTEGER_CST_P (bound))
2929 if (wi::ltu_p (wi::to_wide (bound), 1)
2930 || wi::gtu_p (wi::to_wide (bound),
2931 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2932 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2933 "dimension index", expr->value.function.isym->name,
2934 &expr->where);
2936 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2938 bound = gfc_evaluate_now (bound, &se->pre);
2939 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2940 bound, build_int_cst (TREE_TYPE (bound), 1));
2941 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2942 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2943 bound, tmp);
2944 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2945 logical_type_node, cond, tmp);
2946 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2947 gfc_msg_fault);
2951 /* Subtract 1 to get to zero based and add dimensions. */
2952 switch (arg->expr->rank)
2954 case 0:
2955 bound = fold_build2_loc (input_location, MINUS_EXPR,
2956 gfc_array_index_type, bound,
2957 gfc_index_one_node);
2958 case 1:
2959 break;
2960 default:
2961 bound = fold_build2_loc (input_location, PLUS_EXPR,
2962 gfc_array_index_type, bound,
2963 gfc_rank_cst[arg->expr->rank - 1]);
2967 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2969 /* Handle UCOBOUND with special handling of the last codimension. */
2970 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2972 /* Last codimension: For -fcoarray=single just return
2973 the lcobound - otherwise add
2974 ceiling (real (num_images ()) / real (size)) - 1
2975 = (num_images () + size - 1) / size - 1
2976 = (num_images - 1) / size(),
2977 where size is the product of the extent of all but the last
2978 codimension. */
2980 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
2982 tree cosize;
2984 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
2985 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2986 2, integer_zero_node,
2987 build_int_cst (integer_type_node, -1));
2988 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2989 gfc_array_index_type,
2990 fold_convert (gfc_array_index_type, tmp),
2991 build_int_cst (gfc_array_index_type, 1));
2992 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
2993 gfc_array_index_type, tmp,
2994 fold_convert (gfc_array_index_type, cosize));
2995 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2996 gfc_array_index_type, resbound, tmp);
2998 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3000 /* ubound = lbound + num_images() - 1. */
3001 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3002 2, integer_zero_node,
3003 build_int_cst (integer_type_node, -1));
3004 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3005 gfc_array_index_type,
3006 fold_convert (gfc_array_index_type, tmp),
3007 build_int_cst (gfc_array_index_type, 1));
3008 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3009 gfc_array_index_type, resbound, tmp);
3012 if (corank > 1)
3014 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3015 bound,
3016 build_int_cst (TREE_TYPE (bound),
3017 arg->expr->rank + corank - 1));
3019 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3020 se->expr = fold_build3_loc (input_location, COND_EXPR,
3021 gfc_array_index_type, cond,
3022 resbound, resbound2);
3024 else
3025 se->expr = resbound;
3027 else
3028 se->expr = resbound;
3030 type = gfc_typenode_for_spec (&expr->ts);
3031 se->expr = convert (type, se->expr);
3035 static void
3036 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3038 gfc_actual_arglist *array_arg;
3039 gfc_actual_arglist *dim_arg;
3040 gfc_se argse;
3041 tree desc, tmp;
3043 array_arg = expr->value.function.actual;
3044 dim_arg = array_arg->next;
3046 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3048 gfc_init_se (&argse, NULL);
3049 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3050 gfc_add_block_to_block (&se->pre, &argse.pre);
3051 gfc_add_block_to_block (&se->post, &argse.post);
3052 desc = argse.expr;
3054 gcc_assert (dim_arg->expr);
3055 gfc_init_se (&argse, NULL);
3056 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3057 gfc_add_block_to_block (&se->pre, &argse.pre);
3058 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3059 argse.expr, gfc_index_one_node);
3060 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3063 static void
3064 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3066 tree arg, cabs;
3068 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3070 switch (expr->value.function.actual->expr->ts.type)
3072 case BT_INTEGER:
3073 case BT_REAL:
3074 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3075 arg);
3076 break;
3078 case BT_COMPLEX:
3079 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3080 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3081 break;
3083 default:
3084 gcc_unreachable ();
3089 /* Create a complex value from one or two real components. */
3091 static void
3092 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3094 tree real;
3095 tree imag;
3096 tree type;
3097 tree *args;
3098 unsigned int num_args;
3100 num_args = gfc_intrinsic_argument_list_length (expr);
3101 args = XALLOCAVEC (tree, num_args);
3103 type = gfc_typenode_for_spec (&expr->ts);
3104 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3105 real = convert (TREE_TYPE (type), args[0]);
3106 if (both)
3107 imag = convert (TREE_TYPE (type), args[1]);
3108 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3110 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3111 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3112 imag = convert (TREE_TYPE (type), imag);
3114 else
3115 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3117 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3121 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3122 MODULO(A, P) = A - FLOOR (A / P) * P
3124 The obvious algorithms above are numerically instable for large
3125 arguments, hence these intrinsics are instead implemented via calls
3126 to the fmod family of functions. It is the responsibility of the
3127 user to ensure that the second argument is non-zero. */
3129 static void
3130 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3132 tree type;
3133 tree tmp;
3134 tree test;
3135 tree test2;
3136 tree fmod;
3137 tree zero;
3138 tree args[2];
3140 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3142 switch (expr->ts.type)
3144 case BT_INTEGER:
3145 /* Integer case is easy, we've got a builtin op. */
3146 type = TREE_TYPE (args[0]);
3148 if (modulo)
3149 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3150 args[0], args[1]);
3151 else
3152 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3153 args[0], args[1]);
3154 break;
3156 case BT_REAL:
3157 fmod = NULL_TREE;
3158 /* Check if we have a builtin fmod. */
3159 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3161 /* The builtin should always be available. */
3162 gcc_assert (fmod != NULL_TREE);
3164 tmp = build_addr (fmod);
3165 se->expr = build_call_array_loc (input_location,
3166 TREE_TYPE (TREE_TYPE (fmod)),
3167 tmp, 2, args);
3168 if (modulo == 0)
3169 return;
3171 type = TREE_TYPE (args[0]);
3173 args[0] = gfc_evaluate_now (args[0], &se->pre);
3174 args[1] = gfc_evaluate_now (args[1], &se->pre);
3176 /* Definition:
3177 modulo = arg - floor (arg/arg2) * arg2
3179 In order to calculate the result accurately, we use the fmod
3180 function as follows.
3182 res = fmod (arg, arg2);
3183 if (res)
3185 if ((arg < 0) xor (arg2 < 0))
3186 res += arg2;
3188 else
3189 res = copysign (0., arg2);
3191 => As two nested ternary exprs:
3193 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3194 : copysign (0., arg2);
3198 zero = gfc_build_const (type, integer_zero_node);
3199 tmp = gfc_evaluate_now (se->expr, &se->pre);
3200 if (!flag_signed_zeros)
3202 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3203 args[0], zero);
3204 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3205 args[1], zero);
3206 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3207 logical_type_node, test, test2);
3208 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3209 tmp, zero);
3210 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3211 logical_type_node, test, test2);
3212 test = gfc_evaluate_now (test, &se->pre);
3213 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3214 fold_build2_loc (input_location,
3215 PLUS_EXPR,
3216 type, tmp, args[1]),
3217 tmp);
3219 else
3221 tree expr1, copysign, cscall;
3222 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3223 expr->ts.kind);
3224 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3225 args[0], zero);
3226 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3227 args[1], zero);
3228 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3229 logical_type_node, test, test2);
3230 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3231 fold_build2_loc (input_location,
3232 PLUS_EXPR,
3233 type, tmp, args[1]),
3234 tmp);
3235 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3236 tmp, zero);
3237 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3238 args[1]);
3239 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3240 expr1, cscall);
3242 return;
3244 default:
3245 gcc_unreachable ();
3249 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3250 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3251 where the right shifts are logical (i.e. 0's are shifted in).
3252 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3253 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3254 DSHIFTL(I,J,0) = I
3255 DSHIFTL(I,J,BITSIZE) = J
3256 DSHIFTR(I,J,0) = J
3257 DSHIFTR(I,J,BITSIZE) = I. */
3259 static void
3260 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3262 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3263 tree args[3], cond, tmp;
3264 int bitsize;
3266 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3268 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3269 type = TREE_TYPE (args[0]);
3270 bitsize = TYPE_PRECISION (type);
3271 utype = unsigned_type_for (type);
3272 stype = TREE_TYPE (args[2]);
3274 arg1 = gfc_evaluate_now (args[0], &se->pre);
3275 arg2 = gfc_evaluate_now (args[1], &se->pre);
3276 shift = gfc_evaluate_now (args[2], &se->pre);
3278 /* The generic case. */
3279 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3280 build_int_cst (stype, bitsize), shift);
3281 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3282 arg1, dshiftl ? shift : tmp);
3284 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3285 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3286 right = fold_convert (type, right);
3288 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3290 /* Special cases. */
3291 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3292 build_int_cst (stype, 0));
3293 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3294 dshiftl ? arg1 : arg2, res);
3296 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3297 build_int_cst (stype, bitsize));
3298 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3299 dshiftl ? arg2 : arg1, res);
3301 se->expr = res;
3305 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3307 static void
3308 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3310 tree val;
3311 tree tmp;
3312 tree type;
3313 tree zero;
3314 tree args[2];
3316 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3317 type = TREE_TYPE (args[0]);
3319 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3320 val = gfc_evaluate_now (val, &se->pre);
3322 zero = gfc_build_const (type, integer_zero_node);
3323 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3324 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3328 /* SIGN(A, B) is absolute value of A times sign of B.
3329 The real value versions use library functions to ensure the correct
3330 handling of negative zero. Integer case implemented as:
3331 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3334 static void
3335 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3337 tree tmp;
3338 tree type;
3339 tree args[2];
3341 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3342 if (expr->ts.type == BT_REAL)
3344 tree abs;
3346 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3347 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3349 /* We explicitly have to ignore the minus sign. We do so by using
3350 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3351 if (!flag_sign_zero
3352 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3354 tree cond, zero;
3355 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3356 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3357 args[1], zero);
3358 se->expr = fold_build3_loc (input_location, COND_EXPR,
3359 TREE_TYPE (args[0]), cond,
3360 build_call_expr_loc (input_location, abs, 1,
3361 args[0]),
3362 build_call_expr_loc (input_location, tmp, 2,
3363 args[0], args[1]));
3365 else
3366 se->expr = build_call_expr_loc (input_location, tmp, 2,
3367 args[0], args[1]);
3368 return;
3371 /* Having excluded floating point types, we know we are now dealing
3372 with signed integer types. */
3373 type = TREE_TYPE (args[0]);
3375 /* Args[0] is used multiple times below. */
3376 args[0] = gfc_evaluate_now (args[0], &se->pre);
3378 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3379 the signs of A and B are the same, and of all ones if they differ. */
3380 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3381 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3382 build_int_cst (type, TYPE_PRECISION (type) - 1));
3383 tmp = gfc_evaluate_now (tmp, &se->pre);
3385 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3386 is all ones (i.e. -1). */
3387 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3388 fold_build2_loc (input_location, PLUS_EXPR,
3389 type, args[0], tmp), tmp);
3393 /* Test for the presence of an optional argument. */
3395 static void
3396 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3398 gfc_expr *arg;
3400 arg = expr->value.function.actual->expr;
3401 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3402 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3403 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3407 /* Calculate the double precision product of two single precision values. */
3409 static void
3410 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3412 tree type;
3413 tree args[2];
3415 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3417 /* Convert the args to double precision before multiplying. */
3418 type = gfc_typenode_for_spec (&expr->ts);
3419 args[0] = convert (type, args[0]);
3420 args[1] = convert (type, args[1]);
3421 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3422 args[1]);
3426 /* Return a length one character string containing an ascii character. */
3428 static void
3429 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3431 tree arg[2];
3432 tree var;
3433 tree type;
3434 unsigned int num_args;
3436 num_args = gfc_intrinsic_argument_list_length (expr);
3437 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3439 type = gfc_get_char_type (expr->ts.kind);
3440 var = gfc_create_var (type, "char");
3442 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3443 gfc_add_modify (&se->pre, var, arg[0]);
3444 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3445 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3449 static void
3450 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3452 tree var;
3453 tree len;
3454 tree tmp;
3455 tree cond;
3456 tree fndecl;
3457 tree *args;
3458 unsigned int num_args;
3460 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3461 args = XALLOCAVEC (tree, num_args);
3463 var = gfc_create_var (pchar_type_node, "pstr");
3464 len = gfc_create_var (gfc_charlen_type_node, "len");
3466 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3467 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3468 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3470 fndecl = build_addr (gfor_fndecl_ctime);
3471 tmp = build_call_array_loc (input_location,
3472 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3473 fndecl, num_args, args);
3474 gfc_add_expr_to_block (&se->pre, tmp);
3476 /* Free the temporary afterwards, if necessary. */
3477 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3478 len, build_int_cst (TREE_TYPE (len), 0));
3479 tmp = gfc_call_free (var);
3480 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3481 gfc_add_expr_to_block (&se->post, tmp);
3483 se->expr = var;
3484 se->string_length = len;
3488 static void
3489 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3491 tree var;
3492 tree len;
3493 tree tmp;
3494 tree cond;
3495 tree fndecl;
3496 tree *args;
3497 unsigned int num_args;
3499 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3500 args = XALLOCAVEC (tree, num_args);
3502 var = gfc_create_var (pchar_type_node, "pstr");
3503 len = gfc_create_var (gfc_charlen_type_node, "len");
3505 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3506 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3507 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3509 fndecl = build_addr (gfor_fndecl_fdate);
3510 tmp = build_call_array_loc (input_location,
3511 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3512 fndecl, num_args, args);
3513 gfc_add_expr_to_block (&se->pre, tmp);
3515 /* Free the temporary afterwards, if necessary. */
3516 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3517 len, build_int_cst (TREE_TYPE (len), 0));
3518 tmp = gfc_call_free (var);
3519 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3520 gfc_add_expr_to_block (&se->post, tmp);
3522 se->expr = var;
3523 se->string_length = len;
3527 /* Generate a direct call to free() for the FREE subroutine. */
3529 static tree
3530 conv_intrinsic_free (gfc_code *code)
3532 stmtblock_t block;
3533 gfc_se argse;
3534 tree arg, call;
3536 gfc_init_se (&argse, NULL);
3537 gfc_conv_expr (&argse, code->ext.actual->expr);
3538 arg = fold_convert (ptr_type_node, argse.expr);
3540 gfc_init_block (&block);
3541 call = build_call_expr_loc (input_location,
3542 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3543 gfc_add_expr_to_block (&block, call);
3544 return gfc_finish_block (&block);
3548 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3549 conversions. */
3551 static tree
3552 conv_intrinsic_system_clock (gfc_code *code)
3554 stmtblock_t block;
3555 gfc_se count_se, count_rate_se, count_max_se;
3556 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3557 tree tmp;
3558 int least;
3560 gfc_expr *count = code->ext.actual->expr;
3561 gfc_expr *count_rate = code->ext.actual->next->expr;
3562 gfc_expr *count_max = code->ext.actual->next->next->expr;
3564 /* Evaluate our arguments. */
3565 if (count)
3567 gfc_init_se (&count_se, NULL);
3568 gfc_conv_expr (&count_se, count);
3571 if (count_rate)
3573 gfc_init_se (&count_rate_se, NULL);
3574 gfc_conv_expr (&count_rate_se, count_rate);
3577 if (count_max)
3579 gfc_init_se (&count_max_se, NULL);
3580 gfc_conv_expr (&count_max_se, count_max);
3583 /* Find the smallest kind found of the arguments. */
3584 least = 16;
3585 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3586 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3587 : least;
3588 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3589 : least;
3591 /* Prepare temporary variables. */
3593 if (count)
3595 if (least >= 8)
3596 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3597 else if (least == 4)
3598 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3599 else if (count->ts.kind == 1)
3600 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3601 count->ts.kind);
3602 else
3603 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3604 count->ts.kind);
3607 if (count_rate)
3609 if (least >= 8)
3610 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3611 else if (least == 4)
3612 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3613 else
3614 arg2 = integer_zero_node;
3617 if (count_max)
3619 if (least >= 8)
3620 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3621 else if (least == 4)
3622 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3623 else
3624 arg3 = integer_zero_node;
3627 /* Make the function call. */
3628 gfc_init_block (&block);
3630 if (least <= 2)
3632 if (least == 1)
3634 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3635 : null_pointer_node;
3636 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3637 : null_pointer_node;
3638 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3639 : null_pointer_node;
3642 if (least == 2)
3644 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3645 : null_pointer_node;
3646 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3647 : null_pointer_node;
3648 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3649 : null_pointer_node;
3652 else
3654 if (least == 4)
3656 tmp = build_call_expr_loc (input_location,
3657 gfor_fndecl_system_clock4, 3,
3658 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3659 : null_pointer_node,
3660 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3661 : null_pointer_node,
3662 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3663 : null_pointer_node);
3664 gfc_add_expr_to_block (&block, tmp);
3666 /* Handle kind>=8, 10, or 16 arguments */
3667 if (least >= 8)
3669 tmp = build_call_expr_loc (input_location,
3670 gfor_fndecl_system_clock8, 3,
3671 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3672 : null_pointer_node,
3673 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3674 : null_pointer_node,
3675 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3676 : null_pointer_node);
3677 gfc_add_expr_to_block (&block, tmp);
3681 /* And store values back if needed. */
3682 if (arg1 && arg1 != count_se.expr)
3683 gfc_add_modify (&block, count_se.expr,
3684 fold_convert (TREE_TYPE (count_se.expr), arg1));
3685 if (arg2 && arg2 != count_rate_se.expr)
3686 gfc_add_modify (&block, count_rate_se.expr,
3687 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3688 if (arg3 && arg3 != count_max_se.expr)
3689 gfc_add_modify (&block, count_max_se.expr,
3690 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3692 return gfc_finish_block (&block);
3696 /* Return a character string containing the tty name. */
3698 static void
3699 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3701 tree var;
3702 tree len;
3703 tree tmp;
3704 tree cond;
3705 tree fndecl;
3706 tree *args;
3707 unsigned int num_args;
3709 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3710 args = XALLOCAVEC (tree, num_args);
3712 var = gfc_create_var (pchar_type_node, "pstr");
3713 len = gfc_create_var (gfc_charlen_type_node, "len");
3715 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3716 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3717 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3719 fndecl = build_addr (gfor_fndecl_ttynam);
3720 tmp = build_call_array_loc (input_location,
3721 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3722 fndecl, num_args, args);
3723 gfc_add_expr_to_block (&se->pre, tmp);
3725 /* Free the temporary afterwards, if necessary. */
3726 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3727 len, build_int_cst (TREE_TYPE (len), 0));
3728 tmp = gfc_call_free (var);
3729 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3730 gfc_add_expr_to_block (&se->post, tmp);
3732 se->expr = var;
3733 se->string_length = len;
3737 /* Get the minimum/maximum value of all the parameters.
3738 minmax (a1, a2, a3, ...)
3740 mvar = a1;
3741 if (a2 .op. mvar || isnan (mvar))
3742 mvar = a2;
3743 if (a3 .op. mvar || isnan (mvar))
3744 mvar = a3;
3746 return mvar
3750 /* TODO: Mismatching types can occur when specific names are used.
3751 These should be handled during resolution. */
3752 static void
3753 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3755 tree tmp;
3756 tree mvar;
3757 tree val;
3758 tree thencase;
3759 tree *args;
3760 tree type;
3761 gfc_actual_arglist *argexpr;
3762 unsigned int i, nargs;
3764 nargs = gfc_intrinsic_argument_list_length (expr);
3765 args = XALLOCAVEC (tree, nargs);
3767 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3768 type = gfc_typenode_for_spec (&expr->ts);
3770 argexpr = expr->value.function.actual;
3771 if (TREE_TYPE (args[0]) != type)
3772 args[0] = convert (type, args[0]);
3773 /* Only evaluate the argument once. */
3774 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3775 args[0] = gfc_evaluate_now (args[0], &se->pre);
3777 mvar = gfc_create_var (type, "M");
3778 gfc_add_modify (&se->pre, mvar, args[0]);
3779 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
3781 tree cond, isnan;
3783 val = args[i];
3785 /* Handle absent optional arguments by ignoring the comparison. */
3786 if (argexpr->expr->expr_type == EXPR_VARIABLE
3787 && argexpr->expr->symtree->n.sym->attr.optional
3788 && TREE_CODE (val) == INDIRECT_REF)
3789 cond = fold_build2_loc (input_location,
3790 NE_EXPR, logical_type_node,
3791 TREE_OPERAND (val, 0),
3792 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3793 else
3795 cond = NULL_TREE;
3797 /* Only evaluate the argument once. */
3798 if (!VAR_P (val) && !TREE_CONSTANT (val))
3799 val = gfc_evaluate_now (val, &se->pre);
3802 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
3804 tmp = fold_build2_loc (input_location, op, logical_type_node,
3805 convert (type, val), mvar);
3807 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3808 __builtin_isnan might be made dependent on that module being loaded,
3809 to help performance of programs that don't rely on IEEE semantics. */
3810 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
3812 isnan = build_call_expr_loc (input_location,
3813 builtin_decl_explicit (BUILT_IN_ISNAN),
3814 1, mvar);
3815 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3816 logical_type_node, tmp,
3817 fold_convert (logical_type_node, isnan));
3819 tmp = build3_v (COND_EXPR, tmp, thencase,
3820 build_empty_stmt (input_location));
3822 if (cond != NULL_TREE)
3823 tmp = build3_v (COND_EXPR, cond, tmp,
3824 build_empty_stmt (input_location));
3826 gfc_add_expr_to_block (&se->pre, tmp);
3827 argexpr = argexpr->next;
3829 se->expr = mvar;
3833 /* Generate library calls for MIN and MAX intrinsics for character
3834 variables. */
3835 static void
3836 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3838 tree *args;
3839 tree var, len, fndecl, tmp, cond, function;
3840 unsigned int nargs;
3842 nargs = gfc_intrinsic_argument_list_length (expr);
3843 args = XALLOCAVEC (tree, nargs + 4);
3844 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3846 /* Create the result variables. */
3847 len = gfc_create_var (gfc_charlen_type_node, "len");
3848 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3849 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3850 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3851 args[2] = build_int_cst (integer_type_node, op);
3852 args[3] = build_int_cst (integer_type_node, nargs / 2);
3854 if (expr->ts.kind == 1)
3855 function = gfor_fndecl_string_minmax;
3856 else if (expr->ts.kind == 4)
3857 function = gfor_fndecl_string_minmax_char4;
3858 else
3859 gcc_unreachable ();
3861 /* Make the function call. */
3862 fndecl = build_addr (function);
3863 tmp = build_call_array_loc (input_location,
3864 TREE_TYPE (TREE_TYPE (function)), fndecl,
3865 nargs + 4, args);
3866 gfc_add_expr_to_block (&se->pre, tmp);
3868 /* Free the temporary afterwards, if necessary. */
3869 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3870 len, build_int_cst (TREE_TYPE (len), 0));
3871 tmp = gfc_call_free (var);
3872 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3873 gfc_add_expr_to_block (&se->post, tmp);
3875 se->expr = var;
3876 se->string_length = len;
3880 /* Create a symbol node for this intrinsic. The symbol from the frontend
3881 has the generic name. */
3883 static gfc_symbol *
3884 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
3886 gfc_symbol *sym;
3888 /* TODO: Add symbols for intrinsic function to the global namespace. */
3889 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
3890 sym = gfc_new_symbol (expr->value.function.name, NULL);
3892 sym->ts = expr->ts;
3893 sym->attr.external = 1;
3894 sym->attr.function = 1;
3895 sym->attr.always_explicit = 1;
3896 sym->attr.proc = PROC_INTRINSIC;
3897 sym->attr.flavor = FL_PROCEDURE;
3898 sym->result = sym;
3899 if (expr->rank > 0)
3901 sym->attr.dimension = 1;
3902 sym->as = gfc_get_array_spec ();
3903 sym->as->type = AS_ASSUMED_SHAPE;
3904 sym->as->rank = expr->rank;
3907 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3908 ignore_optional ? expr->value.function.actual
3909 : NULL);
3911 return sym;
3914 /* Generate a call to an external intrinsic function. */
3915 static void
3916 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
3918 gfc_symbol *sym;
3919 vec<tree, va_gc> *append_args;
3921 gcc_assert (!se->ss || se->ss->info->expr == expr);
3923 if (se->ss)
3924 gcc_assert (expr->rank > 0);
3925 else
3926 gcc_assert (expr->rank == 0);
3928 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
3930 /* Calls to libgfortran_matmul need to be appended special arguments,
3931 to be able to call the BLAS ?gemm functions if required and possible. */
3932 append_args = NULL;
3933 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
3934 && sym->ts.type != BT_LOGICAL)
3936 tree cint = gfc_get_int_type (gfc_c_int_kind);
3938 if (flag_external_blas
3939 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
3940 && (sym->ts.kind == 4 || sym->ts.kind == 8))
3942 tree gemm_fndecl;
3944 if (sym->ts.type == BT_REAL)
3946 if (sym->ts.kind == 4)
3947 gemm_fndecl = gfor_fndecl_sgemm;
3948 else
3949 gemm_fndecl = gfor_fndecl_dgemm;
3951 else
3953 if (sym->ts.kind == 4)
3954 gemm_fndecl = gfor_fndecl_cgemm;
3955 else
3956 gemm_fndecl = gfor_fndecl_zgemm;
3959 vec_alloc (append_args, 3);
3960 append_args->quick_push (build_int_cst (cint, 1));
3961 append_args->quick_push (build_int_cst (cint,
3962 flag_blas_matmul_limit));
3963 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3964 gemm_fndecl));
3966 else
3968 vec_alloc (append_args, 3);
3969 append_args->quick_push (build_int_cst (cint, 0));
3970 append_args->quick_push (build_int_cst (cint, 0));
3971 append_args->quick_push (null_pointer_node);
3975 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3976 append_args);
3977 gfc_free_symbol (sym);
3980 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3981 Implemented as
3982 any(a)
3984 forall (i=...)
3985 if (a[i] != 0)
3986 return 1
3987 end forall
3988 return 0
3990 all(a)
3992 forall (i=...)
3993 if (a[i] == 0)
3994 return 0
3995 end forall
3996 return 1
3999 static void
4000 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4002 tree resvar;
4003 stmtblock_t block;
4004 stmtblock_t body;
4005 tree type;
4006 tree tmp;
4007 tree found;
4008 gfc_loopinfo loop;
4009 gfc_actual_arglist *actual;
4010 gfc_ss *arrayss;
4011 gfc_se arrayse;
4012 tree exit_label;
4014 if (se->ss)
4016 gfc_conv_intrinsic_funcall (se, expr);
4017 return;
4020 actual = expr->value.function.actual;
4021 type = gfc_typenode_for_spec (&expr->ts);
4022 /* Initialize the result. */
4023 resvar = gfc_create_var (type, "test");
4024 if (op == EQ_EXPR)
4025 tmp = convert (type, boolean_true_node);
4026 else
4027 tmp = convert (type, boolean_false_node);
4028 gfc_add_modify (&se->pre, resvar, tmp);
4030 /* Walk the arguments. */
4031 arrayss = gfc_walk_expr (actual->expr);
4032 gcc_assert (arrayss != gfc_ss_terminator);
4034 /* Initialize the scalarizer. */
4035 gfc_init_loopinfo (&loop);
4036 exit_label = gfc_build_label_decl (NULL_TREE);
4037 TREE_USED (exit_label) = 1;
4038 gfc_add_ss_to_loop (&loop, arrayss);
4040 /* Initialize the loop. */
4041 gfc_conv_ss_startstride (&loop);
4042 gfc_conv_loop_setup (&loop, &expr->where);
4044 gfc_mark_ss_chain_used (arrayss, 1);
4045 /* Generate the loop body. */
4046 gfc_start_scalarized_body (&loop, &body);
4048 /* If the condition matches then set the return value. */
4049 gfc_start_block (&block);
4050 if (op == EQ_EXPR)
4051 tmp = convert (type, boolean_false_node);
4052 else
4053 tmp = convert (type, boolean_true_node);
4054 gfc_add_modify (&block, resvar, tmp);
4056 /* And break out of the loop. */
4057 tmp = build1_v (GOTO_EXPR, exit_label);
4058 gfc_add_expr_to_block (&block, tmp);
4060 found = gfc_finish_block (&block);
4062 /* Check this element. */
4063 gfc_init_se (&arrayse, NULL);
4064 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4065 arrayse.ss = arrayss;
4066 gfc_conv_expr_val (&arrayse, actual->expr);
4068 gfc_add_block_to_block (&body, &arrayse.pre);
4069 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4070 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4071 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4072 gfc_add_expr_to_block (&body, tmp);
4073 gfc_add_block_to_block (&body, &arrayse.post);
4075 gfc_trans_scalarizing_loops (&loop, &body);
4077 /* Add the exit label. */
4078 tmp = build1_v (LABEL_EXPR, exit_label);
4079 gfc_add_expr_to_block (&loop.pre, tmp);
4081 gfc_add_block_to_block (&se->pre, &loop.pre);
4082 gfc_add_block_to_block (&se->pre, &loop.post);
4083 gfc_cleanup_loop (&loop);
4085 se->expr = resvar;
4088 /* COUNT(A) = Number of true elements in A. */
4089 static void
4090 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4092 tree resvar;
4093 tree type;
4094 stmtblock_t body;
4095 tree tmp;
4096 gfc_loopinfo loop;
4097 gfc_actual_arglist *actual;
4098 gfc_ss *arrayss;
4099 gfc_se arrayse;
4101 if (se->ss)
4103 gfc_conv_intrinsic_funcall (se, expr);
4104 return;
4107 actual = expr->value.function.actual;
4109 type = gfc_typenode_for_spec (&expr->ts);
4110 /* Initialize the result. */
4111 resvar = gfc_create_var (type, "count");
4112 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4114 /* Walk the arguments. */
4115 arrayss = gfc_walk_expr (actual->expr);
4116 gcc_assert (arrayss != gfc_ss_terminator);
4118 /* Initialize the scalarizer. */
4119 gfc_init_loopinfo (&loop);
4120 gfc_add_ss_to_loop (&loop, arrayss);
4122 /* Initialize the loop. */
4123 gfc_conv_ss_startstride (&loop);
4124 gfc_conv_loop_setup (&loop, &expr->where);
4126 gfc_mark_ss_chain_used (arrayss, 1);
4127 /* Generate the loop body. */
4128 gfc_start_scalarized_body (&loop, &body);
4130 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4131 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4132 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4134 gfc_init_se (&arrayse, NULL);
4135 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4136 arrayse.ss = arrayss;
4137 gfc_conv_expr_val (&arrayse, actual->expr);
4138 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4139 build_empty_stmt (input_location));
4141 gfc_add_block_to_block (&body, &arrayse.pre);
4142 gfc_add_expr_to_block (&body, tmp);
4143 gfc_add_block_to_block (&body, &arrayse.post);
4145 gfc_trans_scalarizing_loops (&loop, &body);
4147 gfc_add_block_to_block (&se->pre, &loop.pre);
4148 gfc_add_block_to_block (&se->pre, &loop.post);
4149 gfc_cleanup_loop (&loop);
4151 se->expr = resvar;
4155 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4156 struct and return the corresponding loopinfo. */
4158 static gfc_loopinfo *
4159 enter_nested_loop (gfc_se *se)
4161 se->ss = se->ss->nested_ss;
4162 gcc_assert (se->ss == se->ss->loop->ss);
4164 return se->ss->loop;
4168 /* Inline implementation of the sum and product intrinsics. */
4169 static void
4170 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4171 bool norm2)
4173 tree resvar;
4174 tree scale = NULL_TREE;
4175 tree type;
4176 stmtblock_t body;
4177 stmtblock_t block;
4178 tree tmp;
4179 gfc_loopinfo loop, *ploop;
4180 gfc_actual_arglist *arg_array, *arg_mask;
4181 gfc_ss *arrayss = NULL;
4182 gfc_ss *maskss = NULL;
4183 gfc_se arrayse;
4184 gfc_se maskse;
4185 gfc_se *parent_se;
4186 gfc_expr *arrayexpr;
4187 gfc_expr *maskexpr;
4189 if (expr->rank > 0)
4191 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4192 parent_se = se;
4194 else
4195 parent_se = NULL;
4197 type = gfc_typenode_for_spec (&expr->ts);
4198 /* Initialize the result. */
4199 resvar = gfc_create_var (type, "val");
4200 if (norm2)
4202 /* result = 0.0;
4203 scale = 1.0. */
4204 scale = gfc_create_var (type, "scale");
4205 gfc_add_modify (&se->pre, scale,
4206 gfc_build_const (type, integer_one_node));
4207 tmp = gfc_build_const (type, integer_zero_node);
4209 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4210 tmp = gfc_build_const (type, integer_zero_node);
4211 else if (op == NE_EXPR)
4212 /* PARITY. */
4213 tmp = convert (type, boolean_false_node);
4214 else if (op == BIT_AND_EXPR)
4215 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4216 type, integer_one_node));
4217 else
4218 tmp = gfc_build_const (type, integer_one_node);
4220 gfc_add_modify (&se->pre, resvar, tmp);
4222 arg_array = expr->value.function.actual;
4224 arrayexpr = arg_array->expr;
4226 if (op == NE_EXPR || norm2)
4227 /* PARITY and NORM2. */
4228 maskexpr = NULL;
4229 else
4231 arg_mask = arg_array->next->next;
4232 gcc_assert (arg_mask != NULL);
4233 maskexpr = arg_mask->expr;
4236 if (expr->rank == 0)
4238 /* Walk the arguments. */
4239 arrayss = gfc_walk_expr (arrayexpr);
4240 gcc_assert (arrayss != gfc_ss_terminator);
4242 if (maskexpr && maskexpr->rank > 0)
4244 maskss = gfc_walk_expr (maskexpr);
4245 gcc_assert (maskss != gfc_ss_terminator);
4247 else
4248 maskss = NULL;
4250 /* Initialize the scalarizer. */
4251 gfc_init_loopinfo (&loop);
4252 gfc_add_ss_to_loop (&loop, arrayss);
4253 if (maskexpr && maskexpr->rank > 0)
4254 gfc_add_ss_to_loop (&loop, maskss);
4256 /* Initialize the loop. */
4257 gfc_conv_ss_startstride (&loop);
4258 gfc_conv_loop_setup (&loop, &expr->where);
4260 gfc_mark_ss_chain_used (arrayss, 1);
4261 if (maskexpr && maskexpr->rank > 0)
4262 gfc_mark_ss_chain_used (maskss, 1);
4264 ploop = &loop;
4266 else
4267 /* All the work has been done in the parent loops. */
4268 ploop = enter_nested_loop (se);
4270 gcc_assert (ploop);
4272 /* Generate the loop body. */
4273 gfc_start_scalarized_body (ploop, &body);
4275 /* If we have a mask, only add this element if the mask is set. */
4276 if (maskexpr && maskexpr->rank > 0)
4278 gfc_init_se (&maskse, parent_se);
4279 gfc_copy_loopinfo_to_se (&maskse, ploop);
4280 if (expr->rank == 0)
4281 maskse.ss = maskss;
4282 gfc_conv_expr_val (&maskse, maskexpr);
4283 gfc_add_block_to_block (&body, &maskse.pre);
4285 gfc_start_block (&block);
4287 else
4288 gfc_init_block (&block);
4290 /* Do the actual summation/product. */
4291 gfc_init_se (&arrayse, parent_se);
4292 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4293 if (expr->rank == 0)
4294 arrayse.ss = arrayss;
4295 gfc_conv_expr_val (&arrayse, arrayexpr);
4296 gfc_add_block_to_block (&block, &arrayse.pre);
4298 if (norm2)
4300 /* if (x (i) != 0.0)
4302 absX = abs(x(i))
4303 if (absX > scale)
4305 val = scale/absX;
4306 result = 1.0 + result * val * val;
4307 scale = absX;
4309 else
4311 val = absX/scale;
4312 result += val * val;
4314 } */
4315 tree res1, res2, cond, absX, val;
4316 stmtblock_t ifblock1, ifblock2, ifblock3;
4318 gfc_init_block (&ifblock1);
4320 absX = gfc_create_var (type, "absX");
4321 gfc_add_modify (&ifblock1, absX,
4322 fold_build1_loc (input_location, ABS_EXPR, type,
4323 arrayse.expr));
4324 val = gfc_create_var (type, "val");
4325 gfc_add_expr_to_block (&ifblock1, val);
4327 gfc_init_block (&ifblock2);
4328 gfc_add_modify (&ifblock2, val,
4329 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4330 absX));
4331 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4332 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4333 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4334 gfc_build_const (type, integer_one_node));
4335 gfc_add_modify (&ifblock2, resvar, res1);
4336 gfc_add_modify (&ifblock2, scale, absX);
4337 res1 = gfc_finish_block (&ifblock2);
4339 gfc_init_block (&ifblock3);
4340 gfc_add_modify (&ifblock3, val,
4341 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4342 scale));
4343 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4344 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4345 gfc_add_modify (&ifblock3, resvar, res2);
4346 res2 = gfc_finish_block (&ifblock3);
4348 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4349 absX, scale);
4350 tmp = build3_v (COND_EXPR, cond, res1, res2);
4351 gfc_add_expr_to_block (&ifblock1, tmp);
4352 tmp = gfc_finish_block (&ifblock1);
4354 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4355 arrayse.expr,
4356 gfc_build_const (type, integer_zero_node));
4358 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4359 gfc_add_expr_to_block (&block, tmp);
4361 else
4363 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4364 gfc_add_modify (&block, resvar, tmp);
4367 gfc_add_block_to_block (&block, &arrayse.post);
4369 if (maskexpr && maskexpr->rank > 0)
4371 /* We enclose the above in if (mask) {...} . */
4373 tmp = gfc_finish_block (&block);
4374 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4375 build_empty_stmt (input_location));
4377 else
4378 tmp = gfc_finish_block (&block);
4379 gfc_add_expr_to_block (&body, tmp);
4381 gfc_trans_scalarizing_loops (ploop, &body);
4383 /* For a scalar mask, enclose the loop in an if statement. */
4384 if (maskexpr && maskexpr->rank == 0)
4386 gfc_init_block (&block);
4387 gfc_add_block_to_block (&block, &ploop->pre);
4388 gfc_add_block_to_block (&block, &ploop->post);
4389 tmp = gfc_finish_block (&block);
4391 if (expr->rank > 0)
4393 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4394 build_empty_stmt (input_location));
4395 gfc_advance_se_ss_chain (se);
4397 else
4399 gcc_assert (expr->rank == 0);
4400 gfc_init_se (&maskse, NULL);
4401 gfc_conv_expr_val (&maskse, maskexpr);
4402 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4403 build_empty_stmt (input_location));
4406 gfc_add_expr_to_block (&block, tmp);
4407 gfc_add_block_to_block (&se->pre, &block);
4408 gcc_assert (se->post.head == NULL);
4410 else
4412 gfc_add_block_to_block (&se->pre, &ploop->pre);
4413 gfc_add_block_to_block (&se->pre, &ploop->post);
4416 if (expr->rank == 0)
4417 gfc_cleanup_loop (ploop);
4419 if (norm2)
4421 /* result = scale * sqrt(result). */
4422 tree sqrt;
4423 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4424 resvar = build_call_expr_loc (input_location,
4425 sqrt, 1, resvar);
4426 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4429 se->expr = resvar;
4433 /* Inline implementation of the dot_product intrinsic. This function
4434 is based on gfc_conv_intrinsic_arith (the previous function). */
4435 static void
4436 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4438 tree resvar;
4439 tree type;
4440 stmtblock_t body;
4441 stmtblock_t block;
4442 tree tmp;
4443 gfc_loopinfo loop;
4444 gfc_actual_arglist *actual;
4445 gfc_ss *arrayss1, *arrayss2;
4446 gfc_se arrayse1, arrayse2;
4447 gfc_expr *arrayexpr1, *arrayexpr2;
4449 type = gfc_typenode_for_spec (&expr->ts);
4451 /* Initialize the result. */
4452 resvar = gfc_create_var (type, "val");
4453 if (expr->ts.type == BT_LOGICAL)
4454 tmp = build_int_cst (type, 0);
4455 else
4456 tmp = gfc_build_const (type, integer_zero_node);
4458 gfc_add_modify (&se->pre, resvar, tmp);
4460 /* Walk argument #1. */
4461 actual = expr->value.function.actual;
4462 arrayexpr1 = actual->expr;
4463 arrayss1 = gfc_walk_expr (arrayexpr1);
4464 gcc_assert (arrayss1 != gfc_ss_terminator);
4466 /* Walk argument #2. */
4467 actual = actual->next;
4468 arrayexpr2 = actual->expr;
4469 arrayss2 = gfc_walk_expr (arrayexpr2);
4470 gcc_assert (arrayss2 != gfc_ss_terminator);
4472 /* Initialize the scalarizer. */
4473 gfc_init_loopinfo (&loop);
4474 gfc_add_ss_to_loop (&loop, arrayss1);
4475 gfc_add_ss_to_loop (&loop, arrayss2);
4477 /* Initialize the loop. */
4478 gfc_conv_ss_startstride (&loop);
4479 gfc_conv_loop_setup (&loop, &expr->where);
4481 gfc_mark_ss_chain_used (arrayss1, 1);
4482 gfc_mark_ss_chain_used (arrayss2, 1);
4484 /* Generate the loop body. */
4485 gfc_start_scalarized_body (&loop, &body);
4486 gfc_init_block (&block);
4488 /* Make the tree expression for [conjg(]array1[)]. */
4489 gfc_init_se (&arrayse1, NULL);
4490 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4491 arrayse1.ss = arrayss1;
4492 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4493 if (expr->ts.type == BT_COMPLEX)
4494 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4495 arrayse1.expr);
4496 gfc_add_block_to_block (&block, &arrayse1.pre);
4498 /* Make the tree expression for array2. */
4499 gfc_init_se (&arrayse2, NULL);
4500 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4501 arrayse2.ss = arrayss2;
4502 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4503 gfc_add_block_to_block (&block, &arrayse2.pre);
4505 /* Do the actual product and sum. */
4506 if (expr->ts.type == BT_LOGICAL)
4508 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4509 arrayse1.expr, arrayse2.expr);
4510 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4512 else
4514 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4515 arrayse2.expr);
4516 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4518 gfc_add_modify (&block, resvar, tmp);
4520 /* Finish up the loop block and the loop. */
4521 tmp = gfc_finish_block (&block);
4522 gfc_add_expr_to_block (&body, tmp);
4524 gfc_trans_scalarizing_loops (&loop, &body);
4525 gfc_add_block_to_block (&se->pre, &loop.pre);
4526 gfc_add_block_to_block (&se->pre, &loop.post);
4527 gfc_cleanup_loop (&loop);
4529 se->expr = resvar;
4533 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4534 we need to handle. For performance reasons we sometimes create two
4535 loops instead of one, where the second one is much simpler.
4536 Examples for minloc intrinsic:
4537 1) Result is an array, a call is generated
4538 2) Array mask is used and NaNs need to be supported:
4539 limit = Infinity;
4540 pos = 0;
4541 S = from;
4542 while (S <= to) {
4543 if (mask[S]) {
4544 if (pos == 0) pos = S + (1 - from);
4545 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4547 S++;
4549 goto lab2;
4550 lab1:;
4551 while (S <= to) {
4552 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4553 S++;
4555 lab2:;
4556 3) NaNs need to be supported, but it is known at compile time or cheaply
4557 at runtime whether array is nonempty or not:
4558 limit = Infinity;
4559 pos = 0;
4560 S = from;
4561 while (S <= to) {
4562 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4563 S++;
4565 if (from <= to) pos = 1;
4566 goto lab2;
4567 lab1:;
4568 while (S <= to) {
4569 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4570 S++;
4572 lab2:;
4573 4) NaNs aren't supported, array mask is used:
4574 limit = infinities_supported ? Infinity : huge (limit);
4575 pos = 0;
4576 S = from;
4577 while (S <= to) {
4578 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4579 S++;
4581 goto lab2;
4582 lab1:;
4583 while (S <= to) {
4584 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4585 S++;
4587 lab2:;
4588 5) Same without array mask:
4589 limit = infinities_supported ? Infinity : huge (limit);
4590 pos = (from <= to) ? 1 : 0;
4591 S = from;
4592 while (S <= to) {
4593 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4594 S++;
4596 For 3) and 5), if mask is scalar, this all goes into a conditional,
4597 setting pos = 0; in the else branch. */
4599 static void
4600 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4602 stmtblock_t body;
4603 stmtblock_t block;
4604 stmtblock_t ifblock;
4605 stmtblock_t elseblock;
4606 tree limit;
4607 tree type;
4608 tree tmp;
4609 tree cond;
4610 tree elsetmp;
4611 tree ifbody;
4612 tree offset;
4613 tree nonempty;
4614 tree lab1, lab2;
4615 gfc_loopinfo loop;
4616 gfc_actual_arglist *actual;
4617 gfc_ss *arrayss;
4618 gfc_ss *maskss;
4619 gfc_se arrayse;
4620 gfc_se maskse;
4621 gfc_expr *arrayexpr;
4622 gfc_expr *maskexpr;
4623 tree pos;
4624 int n;
4626 actual = expr->value.function.actual;
4628 /* The last argument, BACK, is passed by value. Ensure that
4629 by setting its name to %VAL. */
4630 for (gfc_actual_arglist *a = actual; a; a = a->next)
4632 if (a->next == NULL)
4633 a->name = "%VAL";
4636 if (se->ss)
4638 gfc_conv_intrinsic_funcall (se, expr);
4639 return;
4642 arrayexpr = actual->expr;
4644 /* Special case for character maxloc. Remove unneeded actual
4645 arguments, then call a library function. */
4647 if (arrayexpr->ts.type == BT_CHARACTER)
4649 gfc_actual_arglist *a, *b;
4650 a = actual;
4651 while (a->next)
4653 b = a->next;
4654 if (b->expr == NULL || strcmp (b->name, "dim") == 0)
4656 a->next = b->next;
4657 b->next = NULL;
4658 gfc_free_actual_arglist (b);
4660 else
4661 a = b;
4663 gfc_conv_intrinsic_funcall (se, expr);
4664 return;
4667 /* Initialize the result. */
4668 pos = gfc_create_var (gfc_array_index_type, "pos");
4669 offset = gfc_create_var (gfc_array_index_type, "offset");
4670 type = gfc_typenode_for_spec (&expr->ts);
4672 /* Walk the arguments. */
4673 arrayss = gfc_walk_expr (arrayexpr);
4674 gcc_assert (arrayss != gfc_ss_terminator);
4676 actual = actual->next->next;
4677 gcc_assert (actual);
4678 maskexpr = actual->expr;
4679 nonempty = NULL;
4680 if (maskexpr && maskexpr->rank != 0)
4682 maskss = gfc_walk_expr (maskexpr);
4683 gcc_assert (maskss != gfc_ss_terminator);
4685 else
4687 mpz_t asize;
4688 if (gfc_array_size (arrayexpr, &asize))
4690 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4691 mpz_clear (asize);
4692 nonempty = fold_build2_loc (input_location, GT_EXPR,
4693 logical_type_node, nonempty,
4694 gfc_index_zero_node);
4696 maskss = NULL;
4699 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4700 switch (arrayexpr->ts.type)
4702 case BT_REAL:
4703 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4704 break;
4706 case BT_INTEGER:
4707 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4708 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4709 arrayexpr->ts.kind);
4710 break;
4712 default:
4713 gcc_unreachable ();
4716 /* We start with the most negative possible value for MAXLOC, and the most
4717 positive possible value for MINLOC. The most negative possible value is
4718 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4719 possible value is HUGE in both cases. */
4720 if (op == GT_EXPR)
4721 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4722 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4723 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4724 build_int_cst (TREE_TYPE (tmp), 1));
4726 gfc_add_modify (&se->pre, limit, tmp);
4728 /* Initialize the scalarizer. */
4729 gfc_init_loopinfo (&loop);
4730 gfc_add_ss_to_loop (&loop, arrayss);
4731 if (maskss)
4732 gfc_add_ss_to_loop (&loop, maskss);
4734 /* Initialize the loop. */
4735 gfc_conv_ss_startstride (&loop);
4737 /* The code generated can have more than one loop in sequence (see the
4738 comment at the function header). This doesn't work well with the
4739 scalarizer, which changes arrays' offset when the scalarization loops
4740 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4741 are currently inlined in the scalar case only (for which loop is of rank
4742 one). As there is no dependency to care about in that case, there is no
4743 temporary, so that we can use the scalarizer temporary code to handle
4744 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4745 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4746 to restore offset.
4747 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4748 should eventually go away. We could either create two loops properly,
4749 or find another way to save/restore the array offsets between the two
4750 loops (without conflicting with temporary management), or use a single
4751 loop minmaxloc implementation. See PR 31067. */
4752 loop.temp_dim = loop.dimen;
4753 gfc_conv_loop_setup (&loop, &expr->where);
4755 gcc_assert (loop.dimen == 1);
4756 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4757 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4758 loop.from[0], loop.to[0]);
4760 lab1 = NULL;
4761 lab2 = NULL;
4762 /* Initialize the position to zero, following Fortran 2003. We are free
4763 to do this because Fortran 95 allows the result of an entirely false
4764 mask to be processor dependent. If we know at compile time the array
4765 is non-empty and no MASK is used, we can initialize to 1 to simplify
4766 the inner loop. */
4767 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4768 gfc_add_modify (&loop.pre, pos,
4769 fold_build3_loc (input_location, COND_EXPR,
4770 gfc_array_index_type,
4771 nonempty, gfc_index_one_node,
4772 gfc_index_zero_node));
4773 else
4775 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4776 lab1 = gfc_build_label_decl (NULL_TREE);
4777 TREE_USED (lab1) = 1;
4778 lab2 = gfc_build_label_decl (NULL_TREE);
4779 TREE_USED (lab2) = 1;
4782 /* An offset must be added to the loop
4783 counter to obtain the required position. */
4784 gcc_assert (loop.from[0]);
4786 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4787 gfc_index_one_node, loop.from[0]);
4788 gfc_add_modify (&loop.pre, offset, tmp);
4790 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4791 if (maskss)
4792 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4793 /* Generate the loop body. */
4794 gfc_start_scalarized_body (&loop, &body);
4796 /* If we have a mask, only check this element if the mask is set. */
4797 if (maskss)
4799 gfc_init_se (&maskse, NULL);
4800 gfc_copy_loopinfo_to_se (&maskse, &loop);
4801 maskse.ss = maskss;
4802 gfc_conv_expr_val (&maskse, maskexpr);
4803 gfc_add_block_to_block (&body, &maskse.pre);
4805 gfc_start_block (&block);
4807 else
4808 gfc_init_block (&block);
4810 /* Compare with the current limit. */
4811 gfc_init_se (&arrayse, NULL);
4812 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4813 arrayse.ss = arrayss;
4814 gfc_conv_expr_val (&arrayse, arrayexpr);
4815 gfc_add_block_to_block (&block, &arrayse.pre);
4817 /* We do the following if this is a more extreme value. */
4818 gfc_start_block (&ifblock);
4820 /* Assign the value to the limit... */
4821 gfc_add_modify (&ifblock, limit, arrayse.expr);
4823 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4825 stmtblock_t ifblock2;
4826 tree ifbody2;
4828 gfc_start_block (&ifblock2);
4829 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4830 loop.loopvar[0], offset);
4831 gfc_add_modify (&ifblock2, pos, tmp);
4832 ifbody2 = gfc_finish_block (&ifblock2);
4833 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
4834 gfc_index_zero_node);
4835 tmp = build3_v (COND_EXPR, cond, ifbody2,
4836 build_empty_stmt (input_location));
4837 gfc_add_expr_to_block (&block, tmp);
4840 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4841 loop.loopvar[0], offset);
4842 gfc_add_modify (&ifblock, pos, tmp);
4844 if (lab1)
4845 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
4847 ifbody = gfc_finish_block (&ifblock);
4849 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
4851 if (lab1)
4852 cond = fold_build2_loc (input_location,
4853 op == GT_EXPR ? GE_EXPR : LE_EXPR,
4854 logical_type_node, arrayse.expr, limit);
4855 else
4856 cond = fold_build2_loc (input_location, op, logical_type_node,
4857 arrayse.expr, limit);
4859 ifbody = build3_v (COND_EXPR, cond, ifbody,
4860 build_empty_stmt (input_location));
4862 gfc_add_expr_to_block (&block, ifbody);
4864 if (maskss)
4866 /* We enclose the above in if (mask) {...}. */
4867 tmp = gfc_finish_block (&block);
4869 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4870 build_empty_stmt (input_location));
4872 else
4873 tmp = gfc_finish_block (&block);
4874 gfc_add_expr_to_block (&body, tmp);
4876 if (lab1)
4878 gfc_trans_scalarized_loop_boundary (&loop, &body);
4880 if (HONOR_NANS (DECL_MODE (limit)))
4882 if (nonempty != NULL)
4884 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
4885 tmp = build3_v (COND_EXPR, nonempty, ifbody,
4886 build_empty_stmt (input_location));
4887 gfc_add_expr_to_block (&loop.code[0], tmp);
4891 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
4892 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
4894 /* If we have a mask, only check this element if the mask is set. */
4895 if (maskss)
4897 gfc_init_se (&maskse, NULL);
4898 gfc_copy_loopinfo_to_se (&maskse, &loop);
4899 maskse.ss = maskss;
4900 gfc_conv_expr_val (&maskse, maskexpr);
4901 gfc_add_block_to_block (&body, &maskse.pre);
4903 gfc_start_block (&block);
4905 else
4906 gfc_init_block (&block);
4908 /* Compare with the current limit. */
4909 gfc_init_se (&arrayse, NULL);
4910 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4911 arrayse.ss = arrayss;
4912 gfc_conv_expr_val (&arrayse, arrayexpr);
4913 gfc_add_block_to_block (&block, &arrayse.pre);
4915 /* We do the following if this is a more extreme value. */
4916 gfc_start_block (&ifblock);
4918 /* Assign the value to the limit... */
4919 gfc_add_modify (&ifblock, limit, arrayse.expr);
4921 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4922 loop.loopvar[0], offset);
4923 gfc_add_modify (&ifblock, pos, tmp);
4925 ifbody = gfc_finish_block (&ifblock);
4927 cond = fold_build2_loc (input_location, op, logical_type_node,
4928 arrayse.expr, limit);
4930 tmp = build3_v (COND_EXPR, cond, ifbody,
4931 build_empty_stmt (input_location));
4932 gfc_add_expr_to_block (&block, tmp);
4934 if (maskss)
4936 /* We enclose the above in if (mask) {...}. */
4937 tmp = gfc_finish_block (&block);
4939 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4940 build_empty_stmt (input_location));
4942 else
4943 tmp = gfc_finish_block (&block);
4944 gfc_add_expr_to_block (&body, tmp);
4945 /* Avoid initializing loopvar[0] again, it should be left where
4946 it finished by the first loop. */
4947 loop.from[0] = loop.loopvar[0];
4950 gfc_trans_scalarizing_loops (&loop, &body);
4952 if (lab2)
4953 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
4955 /* For a scalar mask, enclose the loop in an if statement. */
4956 if (maskexpr && maskss == NULL)
4958 gfc_init_se (&maskse, NULL);
4959 gfc_conv_expr_val (&maskse, maskexpr);
4960 gfc_init_block (&block);
4961 gfc_add_block_to_block (&block, &loop.pre);
4962 gfc_add_block_to_block (&block, &loop.post);
4963 tmp = gfc_finish_block (&block);
4965 /* For the else part of the scalar mask, just initialize
4966 the pos variable the same way as above. */
4968 gfc_init_block (&elseblock);
4969 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
4970 elsetmp = gfc_finish_block (&elseblock);
4972 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
4973 gfc_add_expr_to_block (&block, tmp);
4974 gfc_add_block_to_block (&se->pre, &block);
4976 else
4978 gfc_add_block_to_block (&se->pre, &loop.pre);
4979 gfc_add_block_to_block (&se->pre, &loop.post);
4981 gfc_cleanup_loop (&loop);
4983 se->expr = convert (type, pos);
4986 /* Emit code for minval or maxval intrinsic. There are many different cases
4987 we need to handle. For performance reasons we sometimes create two
4988 loops instead of one, where the second one is much simpler.
4989 Examples for minval intrinsic:
4990 1) Result is an array, a call is generated
4991 2) Array mask is used and NaNs need to be supported, rank 1:
4992 limit = Infinity;
4993 nonempty = false;
4994 S = from;
4995 while (S <= to) {
4996 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4997 S++;
4999 limit = nonempty ? NaN : huge (limit);
5000 lab:
5001 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5002 3) NaNs need to be supported, but it is known at compile time or cheaply
5003 at runtime whether array is nonempty or not, rank 1:
5004 limit = Infinity;
5005 S = from;
5006 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5007 limit = (from <= to) ? NaN : huge (limit);
5008 lab:
5009 while (S <= to) { limit = min (a[S], limit); S++; }
5010 4) Array mask is used and NaNs need to be supported, rank > 1:
5011 limit = Infinity;
5012 nonempty = false;
5013 fast = false;
5014 S1 = from1;
5015 while (S1 <= to1) {
5016 S2 = from2;
5017 while (S2 <= to2) {
5018 if (mask[S1][S2]) {
5019 if (fast) limit = min (a[S1][S2], limit);
5020 else {
5021 nonempty = true;
5022 if (a[S1][S2] <= limit) {
5023 limit = a[S1][S2];
5024 fast = true;
5028 S2++;
5030 S1++;
5032 if (!fast)
5033 limit = nonempty ? NaN : huge (limit);
5034 5) NaNs need to be supported, but it is known at compile time or cheaply
5035 at runtime whether array is nonempty or not, rank > 1:
5036 limit = Infinity;
5037 fast = false;
5038 S1 = from1;
5039 while (S1 <= to1) {
5040 S2 = from2;
5041 while (S2 <= to2) {
5042 if (fast) limit = min (a[S1][S2], limit);
5043 else {
5044 if (a[S1][S2] <= limit) {
5045 limit = a[S1][S2];
5046 fast = true;
5049 S2++;
5051 S1++;
5053 if (!fast)
5054 limit = (nonempty_array) ? NaN : huge (limit);
5055 6) NaNs aren't supported, but infinities are. Array mask is used:
5056 limit = Infinity;
5057 nonempty = false;
5058 S = from;
5059 while (S <= to) {
5060 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5061 S++;
5063 limit = nonempty ? limit : huge (limit);
5064 7) Same without array mask:
5065 limit = Infinity;
5066 S = from;
5067 while (S <= to) { limit = min (a[S], limit); S++; }
5068 limit = (from <= to) ? limit : huge (limit);
5069 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5070 limit = huge (limit);
5071 S = from;
5072 while (S <= to) { limit = min (a[S], limit); S++); }
5074 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5075 with array mask instead).
5076 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5077 setting limit = huge (limit); in the else branch. */
5079 static void
5080 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
5082 tree limit;
5083 tree type;
5084 tree tmp;
5085 tree ifbody;
5086 tree nonempty;
5087 tree nonempty_var;
5088 tree lab;
5089 tree fast;
5090 tree huge_cst = NULL, nan_cst = NULL;
5091 stmtblock_t body;
5092 stmtblock_t block, block2;
5093 gfc_loopinfo loop;
5094 gfc_actual_arglist *actual;
5095 gfc_ss *arrayss;
5096 gfc_ss *maskss;
5097 gfc_se arrayse;
5098 gfc_se maskse;
5099 gfc_expr *arrayexpr;
5100 gfc_expr *maskexpr;
5101 int n;
5103 if (se->ss)
5105 gfc_conv_intrinsic_funcall (se, expr);
5106 return;
5109 actual = expr->value.function.actual;
5110 arrayexpr = actual->expr;
5112 if (arrayexpr->ts.type == BT_CHARACTER)
5114 gfc_actual_arglist *a2, *a3;
5115 a2 = actual->next; /* dim */
5116 a3 = a2->next; /* mask */
5117 if (a2->expr == NULL || expr->rank == 0)
5119 if (a3->expr == NULL)
5120 actual->next = NULL;
5121 else
5123 actual->next = a3;
5124 a2->next = NULL;
5126 gfc_free_actual_arglist (a2);
5128 else
5129 if (a3->expr == NULL)
5131 a2->next = NULL;
5132 gfc_free_actual_arglist (a3);
5134 gfc_conv_intrinsic_funcall (se, expr);
5135 return;
5137 type = gfc_typenode_for_spec (&expr->ts);
5138 /* Initialize the result. */
5139 limit = gfc_create_var (type, "limit");
5140 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5141 switch (expr->ts.type)
5143 case BT_REAL:
5144 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5145 expr->ts.kind, 0);
5146 if (HONOR_INFINITIES (DECL_MODE (limit)))
5148 REAL_VALUE_TYPE real;
5149 real_inf (&real);
5150 tmp = build_real (type, real);
5152 else
5153 tmp = huge_cst;
5154 if (HONOR_NANS (DECL_MODE (limit)))
5155 nan_cst = gfc_build_nan (type, "");
5156 break;
5158 case BT_INTEGER:
5159 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5160 break;
5162 default:
5163 gcc_unreachable ();
5166 /* We start with the most negative possible value for MAXVAL, and the most
5167 positive possible value for MINVAL. The most negative possible value is
5168 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5169 possible value is HUGE in both cases. */
5170 if (op == GT_EXPR)
5172 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5173 if (huge_cst)
5174 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5175 TREE_TYPE (huge_cst), huge_cst);
5178 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5179 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5180 tmp, build_int_cst (type, 1));
5182 gfc_add_modify (&se->pre, limit, tmp);
5184 /* Walk the arguments. */
5185 arrayss = gfc_walk_expr (arrayexpr);
5186 gcc_assert (arrayss != gfc_ss_terminator);
5188 actual = actual->next->next;
5189 gcc_assert (actual);
5190 maskexpr = actual->expr;
5191 nonempty = NULL;
5192 if (maskexpr && maskexpr->rank != 0)
5194 maskss = gfc_walk_expr (maskexpr);
5195 gcc_assert (maskss != gfc_ss_terminator);
5197 else
5199 mpz_t asize;
5200 if (gfc_array_size (arrayexpr, &asize))
5202 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5203 mpz_clear (asize);
5204 nonempty = fold_build2_loc (input_location, GT_EXPR,
5205 logical_type_node, nonempty,
5206 gfc_index_zero_node);
5208 maskss = NULL;
5211 /* Initialize the scalarizer. */
5212 gfc_init_loopinfo (&loop);
5213 gfc_add_ss_to_loop (&loop, arrayss);
5214 if (maskss)
5215 gfc_add_ss_to_loop (&loop, maskss);
5217 /* Initialize the loop. */
5218 gfc_conv_ss_startstride (&loop);
5220 /* The code generated can have more than one loop in sequence (see the
5221 comment at the function header). This doesn't work well with the
5222 scalarizer, which changes arrays' offset when the scalarization loops
5223 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5224 are currently inlined in the scalar case only. As there is no dependency
5225 to care about in that case, there is no temporary, so that we can use the
5226 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5227 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5228 gfc_trans_scalarized_loop_boundary even later to restore offset.
5229 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5230 should eventually go away. We could either create two loops properly,
5231 or find another way to save/restore the array offsets between the two
5232 loops (without conflicting with temporary management), or use a single
5233 loop minmaxval implementation. See PR 31067. */
5234 loop.temp_dim = loop.dimen;
5235 gfc_conv_loop_setup (&loop, &expr->where);
5237 if (nonempty == NULL && maskss == NULL
5238 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5239 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5240 loop.from[0], loop.to[0]);
5241 nonempty_var = NULL;
5242 if (nonempty == NULL
5243 && (HONOR_INFINITIES (DECL_MODE (limit))
5244 || HONOR_NANS (DECL_MODE (limit))))
5246 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5247 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5248 nonempty = nonempty_var;
5250 lab = NULL;
5251 fast = NULL;
5252 if (HONOR_NANS (DECL_MODE (limit)))
5254 if (loop.dimen == 1)
5256 lab = gfc_build_label_decl (NULL_TREE);
5257 TREE_USED (lab) = 1;
5259 else
5261 fast = gfc_create_var (logical_type_node, "fast");
5262 gfc_add_modify (&se->pre, fast, logical_false_node);
5266 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5267 if (maskss)
5268 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5269 /* Generate the loop body. */
5270 gfc_start_scalarized_body (&loop, &body);
5272 /* If we have a mask, only add this element if the mask is set. */
5273 if (maskss)
5275 gfc_init_se (&maskse, NULL);
5276 gfc_copy_loopinfo_to_se (&maskse, &loop);
5277 maskse.ss = maskss;
5278 gfc_conv_expr_val (&maskse, maskexpr);
5279 gfc_add_block_to_block (&body, &maskse.pre);
5281 gfc_start_block (&block);
5283 else
5284 gfc_init_block (&block);
5286 /* Compare with the current limit. */
5287 gfc_init_se (&arrayse, NULL);
5288 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5289 arrayse.ss = arrayss;
5290 gfc_conv_expr_val (&arrayse, arrayexpr);
5291 gfc_add_block_to_block (&block, &arrayse.pre);
5293 gfc_init_block (&block2);
5295 if (nonempty_var)
5296 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5298 if (HONOR_NANS (DECL_MODE (limit)))
5300 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5301 logical_type_node, arrayse.expr, limit);
5302 if (lab)
5303 ifbody = build1_v (GOTO_EXPR, lab);
5304 else
5306 stmtblock_t ifblock;
5308 gfc_init_block (&ifblock);
5309 gfc_add_modify (&ifblock, limit, arrayse.expr);
5310 gfc_add_modify (&ifblock, fast, logical_true_node);
5311 ifbody = gfc_finish_block (&ifblock);
5313 tmp = build3_v (COND_EXPR, tmp, ifbody,
5314 build_empty_stmt (input_location));
5315 gfc_add_expr_to_block (&block2, tmp);
5317 else
5319 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5320 signed zeros. */
5321 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5323 tmp = fold_build2_loc (input_location, op, logical_type_node,
5324 arrayse.expr, limit);
5325 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5326 tmp = build3_v (COND_EXPR, tmp, ifbody,
5327 build_empty_stmt (input_location));
5328 gfc_add_expr_to_block (&block2, tmp);
5330 else
5332 tmp = fold_build2_loc (input_location,
5333 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5334 type, arrayse.expr, limit);
5335 gfc_add_modify (&block2, limit, tmp);
5339 if (fast)
5341 tree elsebody = gfc_finish_block (&block2);
5343 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5344 signed zeros. */
5345 if (HONOR_NANS (DECL_MODE (limit))
5346 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5348 tmp = fold_build2_loc (input_location, op, logical_type_node,
5349 arrayse.expr, limit);
5350 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5351 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5352 build_empty_stmt (input_location));
5354 else
5356 tmp = fold_build2_loc (input_location,
5357 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5358 type, arrayse.expr, limit);
5359 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5361 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5362 gfc_add_expr_to_block (&block, tmp);
5364 else
5365 gfc_add_block_to_block (&block, &block2);
5367 gfc_add_block_to_block (&block, &arrayse.post);
5369 tmp = gfc_finish_block (&block);
5370 if (maskss)
5371 /* We enclose the above in if (mask) {...}. */
5372 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5373 build_empty_stmt (input_location));
5374 gfc_add_expr_to_block (&body, tmp);
5376 if (lab)
5378 gfc_trans_scalarized_loop_boundary (&loop, &body);
5380 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5381 nan_cst, huge_cst);
5382 gfc_add_modify (&loop.code[0], limit, tmp);
5383 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5385 /* If we have a mask, only add this element if the mask is set. */
5386 if (maskss)
5388 gfc_init_se (&maskse, NULL);
5389 gfc_copy_loopinfo_to_se (&maskse, &loop);
5390 maskse.ss = maskss;
5391 gfc_conv_expr_val (&maskse, maskexpr);
5392 gfc_add_block_to_block (&body, &maskse.pre);
5394 gfc_start_block (&block);
5396 else
5397 gfc_init_block (&block);
5399 /* Compare with the current limit. */
5400 gfc_init_se (&arrayse, NULL);
5401 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5402 arrayse.ss = arrayss;
5403 gfc_conv_expr_val (&arrayse, arrayexpr);
5404 gfc_add_block_to_block (&block, &arrayse.pre);
5406 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5407 signed zeros. */
5408 if (HONOR_NANS (DECL_MODE (limit))
5409 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5411 tmp = fold_build2_loc (input_location, op, logical_type_node,
5412 arrayse.expr, limit);
5413 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5414 tmp = build3_v (COND_EXPR, tmp, ifbody,
5415 build_empty_stmt (input_location));
5416 gfc_add_expr_to_block (&block, tmp);
5418 else
5420 tmp = fold_build2_loc (input_location,
5421 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5422 type, arrayse.expr, limit);
5423 gfc_add_modify (&block, limit, tmp);
5426 gfc_add_block_to_block (&block, &arrayse.post);
5428 tmp = gfc_finish_block (&block);
5429 if (maskss)
5430 /* We enclose the above in if (mask) {...}. */
5431 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5432 build_empty_stmt (input_location));
5433 gfc_add_expr_to_block (&body, tmp);
5434 /* Avoid initializing loopvar[0] again, it should be left where
5435 it finished by the first loop. */
5436 loop.from[0] = loop.loopvar[0];
5438 gfc_trans_scalarizing_loops (&loop, &body);
5440 if (fast)
5442 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5443 nan_cst, huge_cst);
5444 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5445 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5446 ifbody);
5447 gfc_add_expr_to_block (&loop.pre, tmp);
5449 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5451 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5452 huge_cst);
5453 gfc_add_modify (&loop.pre, limit, tmp);
5456 /* For a scalar mask, enclose the loop in an if statement. */
5457 if (maskexpr && maskss == NULL)
5459 tree else_stmt;
5461 gfc_init_se (&maskse, NULL);
5462 gfc_conv_expr_val (&maskse, maskexpr);
5463 gfc_init_block (&block);
5464 gfc_add_block_to_block (&block, &loop.pre);
5465 gfc_add_block_to_block (&block, &loop.post);
5466 tmp = gfc_finish_block (&block);
5468 if (HONOR_INFINITIES (DECL_MODE (limit)))
5469 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5470 else
5471 else_stmt = build_empty_stmt (input_location);
5472 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5473 gfc_add_expr_to_block (&block, tmp);
5474 gfc_add_block_to_block (&se->pre, &block);
5476 else
5478 gfc_add_block_to_block (&se->pre, &loop.pre);
5479 gfc_add_block_to_block (&se->pre, &loop.post);
5482 gfc_cleanup_loop (&loop);
5484 se->expr = limit;
5487 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5488 static void
5489 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5491 tree args[2];
5492 tree type;
5493 tree tmp;
5495 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5496 type = TREE_TYPE (args[0]);
5498 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5499 build_int_cst (type, 1), args[1]);
5500 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5501 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5502 build_int_cst (type, 0));
5503 type = gfc_typenode_for_spec (&expr->ts);
5504 se->expr = convert (type, tmp);
5508 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5509 static void
5510 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5512 tree args[2];
5514 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5516 /* Convert both arguments to the unsigned type of the same size. */
5517 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5518 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5520 /* If they have unequal type size, convert to the larger one. */
5521 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5522 > TYPE_PRECISION (TREE_TYPE (args[1])))
5523 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5524 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5525 > TYPE_PRECISION (TREE_TYPE (args[0])))
5526 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5528 /* Now, we compare them. */
5529 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5530 args[0], args[1]);
5534 /* Generate code to perform the specified operation. */
5535 static void
5536 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5538 tree args[2];
5540 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5541 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5542 args[0], args[1]);
5545 /* Bitwise not. */
5546 static void
5547 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5549 tree arg;
5551 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5552 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5553 TREE_TYPE (arg), arg);
5556 /* Set or clear a single bit. */
5557 static void
5558 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5560 tree args[2];
5561 tree type;
5562 tree tmp;
5563 enum tree_code op;
5565 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5566 type = TREE_TYPE (args[0]);
5568 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5569 build_int_cst (type, 1), args[1]);
5570 if (set)
5571 op = BIT_IOR_EXPR;
5572 else
5574 op = BIT_AND_EXPR;
5575 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5577 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5580 /* Extract a sequence of bits.
5581 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5582 static void
5583 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5585 tree args[3];
5586 tree type;
5587 tree tmp;
5588 tree mask;
5590 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5591 type = TREE_TYPE (args[0]);
5593 mask = build_int_cst (type, -1);
5594 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5595 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5597 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5599 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5602 static void
5603 gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
5605 gfc_actual_arglist *s, *k;
5606 gfc_expr *e;
5608 /* Remove the KIND argument, if present. */
5609 s = expr->value.function.actual;
5610 k = s->next;
5611 e = k->expr;
5612 gfc_free_expr (e);
5613 k->expr = NULL;
5615 gfc_conv_intrinsic_funcall (se, expr);
5618 static void
5619 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5620 bool arithmetic)
5622 tree args[2], type, num_bits, cond;
5624 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5626 args[0] = gfc_evaluate_now (args[0], &se->pre);
5627 args[1] = gfc_evaluate_now (args[1], &se->pre);
5628 type = TREE_TYPE (args[0]);
5630 if (!arithmetic)
5631 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5632 else
5633 gcc_assert (right_shift);
5635 se->expr = fold_build2_loc (input_location,
5636 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5637 TREE_TYPE (args[0]), args[0], args[1]);
5639 if (!arithmetic)
5640 se->expr = fold_convert (type, se->expr);
5642 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5643 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5644 special case. */
5645 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5646 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
5647 args[1], num_bits);
5649 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5650 build_int_cst (type, 0), se->expr);
5653 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5655 : ((shift >= 0) ? i << shift : i >> -shift)
5656 where all shifts are logical shifts. */
5657 static void
5658 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5660 tree args[2];
5661 tree type;
5662 tree utype;
5663 tree tmp;
5664 tree width;
5665 tree num_bits;
5666 tree cond;
5667 tree lshift;
5668 tree rshift;
5670 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5672 args[0] = gfc_evaluate_now (args[0], &se->pre);
5673 args[1] = gfc_evaluate_now (args[1], &se->pre);
5675 type = TREE_TYPE (args[0]);
5676 utype = unsigned_type_for (type);
5678 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5679 args[1]);
5681 /* Left shift if positive. */
5682 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5684 /* Right shift if negative.
5685 We convert to an unsigned type because we want a logical shift.
5686 The standard doesn't define the case of shifting negative
5687 numbers, and we try to be compatible with other compilers, most
5688 notably g77, here. */
5689 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5690 utype, convert (utype, args[0]), width));
5692 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
5693 build_int_cst (TREE_TYPE (args[1]), 0));
5694 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5696 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5697 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5698 special case. */
5699 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5700 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
5701 num_bits);
5702 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5703 build_int_cst (type, 0), tmp);
5707 /* Circular shift. AKA rotate or barrel shift. */
5709 static void
5710 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5712 tree *args;
5713 tree type;
5714 tree tmp;
5715 tree lrot;
5716 tree rrot;
5717 tree zero;
5718 unsigned int num_args;
5720 num_args = gfc_intrinsic_argument_list_length (expr);
5721 args = XALLOCAVEC (tree, num_args);
5723 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5725 if (num_args == 3)
5727 /* Use a library function for the 3 parameter version. */
5728 tree int4type = gfc_get_int_type (4);
5730 type = TREE_TYPE (args[0]);
5731 /* We convert the first argument to at least 4 bytes, and
5732 convert back afterwards. This removes the need for library
5733 functions for all argument sizes, and function will be
5734 aligned to at least 32 bits, so there's no loss. */
5735 if (expr->ts.kind < 4)
5736 args[0] = convert (int4type, args[0]);
5738 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5739 need loads of library functions. They cannot have values >
5740 BIT_SIZE (I) so the conversion is safe. */
5741 args[1] = convert (int4type, args[1]);
5742 args[2] = convert (int4type, args[2]);
5744 switch (expr->ts.kind)
5746 case 1:
5747 case 2:
5748 case 4:
5749 tmp = gfor_fndecl_math_ishftc4;
5750 break;
5751 case 8:
5752 tmp = gfor_fndecl_math_ishftc8;
5753 break;
5754 case 16:
5755 tmp = gfor_fndecl_math_ishftc16;
5756 break;
5757 default:
5758 gcc_unreachable ();
5760 se->expr = build_call_expr_loc (input_location,
5761 tmp, 3, args[0], args[1], args[2]);
5762 /* Convert the result back to the original type, if we extended
5763 the first argument's width above. */
5764 if (expr->ts.kind < 4)
5765 se->expr = convert (type, se->expr);
5767 return;
5769 type = TREE_TYPE (args[0]);
5771 /* Evaluate arguments only once. */
5772 args[0] = gfc_evaluate_now (args[0], &se->pre);
5773 args[1] = gfc_evaluate_now (args[1], &se->pre);
5775 /* Rotate left if positive. */
5776 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5778 /* Rotate right if negative. */
5779 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5780 args[1]);
5781 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5783 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5784 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
5785 zero);
5786 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5788 /* Do nothing if shift == 0. */
5789 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
5790 zero);
5791 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5792 rrot);
5796 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5797 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5799 The conditional expression is necessary because the result of LEADZ(0)
5800 is defined, but the result of __builtin_clz(0) is undefined for most
5801 targets.
5803 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5804 difference in bit size between the argument of LEADZ and the C int. */
5806 static void
5807 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
5809 tree arg;
5810 tree arg_type;
5811 tree cond;
5812 tree result_type;
5813 tree leadz;
5814 tree bit_size;
5815 tree tmp;
5816 tree func;
5817 int s, argsize;
5819 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5820 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5822 /* Which variant of __builtin_clz* should we call? */
5823 if (argsize <= INT_TYPE_SIZE)
5825 arg_type = unsigned_type_node;
5826 func = builtin_decl_explicit (BUILT_IN_CLZ);
5828 else if (argsize <= LONG_TYPE_SIZE)
5830 arg_type = long_unsigned_type_node;
5831 func = builtin_decl_explicit (BUILT_IN_CLZL);
5833 else if (argsize <= LONG_LONG_TYPE_SIZE)
5835 arg_type = long_long_unsigned_type_node;
5836 func = builtin_decl_explicit (BUILT_IN_CLZLL);
5838 else
5840 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5841 arg_type = gfc_build_uint_type (argsize);
5842 func = NULL_TREE;
5845 /* Convert the actual argument twice: first, to the unsigned type of the
5846 same size; then, to the proper argument type for the built-in
5847 function. But the return type is of the default INTEGER kind. */
5848 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5849 arg = fold_convert (arg_type, arg);
5850 arg = gfc_evaluate_now (arg, &se->pre);
5851 result_type = gfc_get_int_type (gfc_default_integer_kind);
5853 /* Compute LEADZ for the case i .ne. 0. */
5854 if (func)
5856 s = TYPE_PRECISION (arg_type) - argsize;
5857 tmp = fold_convert (result_type,
5858 build_call_expr_loc (input_location, func,
5859 1, arg));
5860 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
5861 tmp, build_int_cst (result_type, s));
5863 else
5865 /* We end up here if the argument type is larger than 'long long'.
5866 We generate this code:
5868 if (x & (ULL_MAX << ULL_SIZE) != 0)
5869 return clzll ((unsigned long long) (x >> ULLSIZE));
5870 else
5871 return ULL_SIZE + clzll ((unsigned long long) x);
5872 where ULL_MAX is the largest value that a ULL_MAX can hold
5873 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5874 is the bit-size of the long long type (64 in this example). */
5875 tree ullsize, ullmax, tmp1, tmp2, btmp;
5877 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5878 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5879 long_long_unsigned_type_node,
5880 build_int_cst (long_long_unsigned_type_node,
5881 0));
5883 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
5884 fold_convert (arg_type, ullmax), ullsize);
5885 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
5886 arg, cond);
5887 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5888 cond, build_int_cst (arg_type, 0));
5890 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5891 arg, ullsize);
5892 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5893 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5894 tmp1 = fold_convert (result_type,
5895 build_call_expr_loc (input_location, btmp, 1, tmp1));
5897 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5898 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5899 tmp2 = fold_convert (result_type,
5900 build_call_expr_loc (input_location, btmp, 1, tmp2));
5901 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5902 tmp2, ullsize);
5904 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
5905 cond, tmp1, tmp2);
5908 /* Build BIT_SIZE. */
5909 bit_size = build_int_cst (result_type, argsize);
5911 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5912 arg, build_int_cst (arg_type, 0));
5913 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5914 bit_size, leadz);
5918 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
5920 The conditional expression is necessary because the result of TRAILZ(0)
5921 is defined, but the result of __builtin_ctz(0) is undefined for most
5922 targets. */
5924 static void
5925 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
5927 tree arg;
5928 tree arg_type;
5929 tree cond;
5930 tree result_type;
5931 tree trailz;
5932 tree bit_size;
5933 tree func;
5934 int argsize;
5936 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5937 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5939 /* Which variant of __builtin_ctz* should we call? */
5940 if (argsize <= INT_TYPE_SIZE)
5942 arg_type = unsigned_type_node;
5943 func = builtin_decl_explicit (BUILT_IN_CTZ);
5945 else if (argsize <= LONG_TYPE_SIZE)
5947 arg_type = long_unsigned_type_node;
5948 func = builtin_decl_explicit (BUILT_IN_CTZL);
5950 else if (argsize <= LONG_LONG_TYPE_SIZE)
5952 arg_type = long_long_unsigned_type_node;
5953 func = builtin_decl_explicit (BUILT_IN_CTZLL);
5955 else
5957 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5958 arg_type = gfc_build_uint_type (argsize);
5959 func = NULL_TREE;
5962 /* Convert the actual argument twice: first, to the unsigned type of the
5963 same size; then, to the proper argument type for the built-in
5964 function. But the return type is of the default INTEGER kind. */
5965 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5966 arg = fold_convert (arg_type, arg);
5967 arg = gfc_evaluate_now (arg, &se->pre);
5968 result_type = gfc_get_int_type (gfc_default_integer_kind);
5970 /* Compute TRAILZ for the case i .ne. 0. */
5971 if (func)
5972 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
5973 func, 1, arg));
5974 else
5976 /* We end up here if the argument type is larger than 'long long'.
5977 We generate this code:
5979 if ((x & ULL_MAX) == 0)
5980 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
5981 else
5982 return ctzll ((unsigned long long) x);
5984 where ULL_MAX is the largest value that a ULL_MAX can hold
5985 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5986 is the bit-size of the long long type (64 in this example). */
5987 tree ullsize, ullmax, tmp1, tmp2, btmp;
5989 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5990 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5991 long_long_unsigned_type_node,
5992 build_int_cst (long_long_unsigned_type_node, 0));
5994 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
5995 fold_convert (arg_type, ullmax));
5996 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
5997 build_int_cst (arg_type, 0));
5999 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6000 arg, ullsize);
6001 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6002 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6003 tmp1 = fold_convert (result_type,
6004 build_call_expr_loc (input_location, btmp, 1, tmp1));
6005 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6006 tmp1, ullsize);
6008 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6009 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6010 tmp2 = fold_convert (result_type,
6011 build_call_expr_loc (input_location, btmp, 1, tmp2));
6013 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
6014 cond, tmp1, tmp2);
6017 /* Build BIT_SIZE. */
6018 bit_size = build_int_cst (result_type, argsize);
6020 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6021 arg, build_int_cst (arg_type, 0));
6022 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6023 bit_size, trailz);
6026 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6027 for types larger than "long long", we call the long long built-in for
6028 the lower and higher bits and combine the result. */
6030 static void
6031 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
6033 tree arg;
6034 tree arg_type;
6035 tree result_type;
6036 tree func;
6037 int argsize;
6039 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6040 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6041 result_type = gfc_get_int_type (gfc_default_integer_kind);
6043 /* Which variant of the builtin should we call? */
6044 if (argsize <= INT_TYPE_SIZE)
6046 arg_type = unsigned_type_node;
6047 func = builtin_decl_explicit (parity
6048 ? BUILT_IN_PARITY
6049 : BUILT_IN_POPCOUNT);
6051 else if (argsize <= LONG_TYPE_SIZE)
6053 arg_type = long_unsigned_type_node;
6054 func = builtin_decl_explicit (parity
6055 ? BUILT_IN_PARITYL
6056 : BUILT_IN_POPCOUNTL);
6058 else if (argsize <= LONG_LONG_TYPE_SIZE)
6060 arg_type = long_long_unsigned_type_node;
6061 func = builtin_decl_explicit (parity
6062 ? BUILT_IN_PARITYLL
6063 : BUILT_IN_POPCOUNTLL);
6065 else
6067 /* Our argument type is larger than 'long long', which mean none
6068 of the POPCOUNT builtins covers it. We thus call the 'long long'
6069 variant multiple times, and add the results. */
6070 tree utype, arg2, call1, call2;
6072 /* For now, we only cover the case where argsize is twice as large
6073 as 'long long'. */
6074 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6076 func = builtin_decl_explicit (parity
6077 ? BUILT_IN_PARITYLL
6078 : BUILT_IN_POPCOUNTLL);
6080 /* Convert it to an integer, and store into a variable. */
6081 utype = gfc_build_uint_type (argsize);
6082 arg = fold_convert (utype, arg);
6083 arg = gfc_evaluate_now (arg, &se->pre);
6085 /* Call the builtin twice. */
6086 call1 = build_call_expr_loc (input_location, func, 1,
6087 fold_convert (long_long_unsigned_type_node,
6088 arg));
6090 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
6091 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
6092 call2 = build_call_expr_loc (input_location, func, 1,
6093 fold_convert (long_long_unsigned_type_node,
6094 arg2));
6096 /* Combine the results. */
6097 if (parity)
6098 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
6099 call1, call2);
6100 else
6101 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6102 call1, call2);
6104 return;
6107 /* Convert the actual argument twice: first, to the unsigned type of the
6108 same size; then, to the proper argument type for the built-in
6109 function. */
6110 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6111 arg = fold_convert (arg_type, arg);
6113 se->expr = fold_convert (result_type,
6114 build_call_expr_loc (input_location, func, 1, arg));
6118 /* Process an intrinsic with unspecified argument-types that has an optional
6119 argument (which could be of type character), e.g. EOSHIFT. For those, we
6120 need to append the string length of the optional argument if it is not
6121 present and the type is really character.
6122 primary specifies the position (starting at 1) of the non-optional argument
6123 specifying the type and optional gives the position of the optional
6124 argument in the arglist. */
6126 static void
6127 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
6128 unsigned primary, unsigned optional)
6130 gfc_actual_arglist* prim_arg;
6131 gfc_actual_arglist* opt_arg;
6132 unsigned cur_pos;
6133 gfc_actual_arglist* arg;
6134 gfc_symbol* sym;
6135 vec<tree, va_gc> *append_args;
6137 /* Find the two arguments given as position. */
6138 cur_pos = 0;
6139 prim_arg = NULL;
6140 opt_arg = NULL;
6141 for (arg = expr->value.function.actual; arg; arg = arg->next)
6143 ++cur_pos;
6145 if (cur_pos == primary)
6146 prim_arg = arg;
6147 if (cur_pos == optional)
6148 opt_arg = arg;
6150 if (cur_pos >= primary && cur_pos >= optional)
6151 break;
6153 gcc_assert (prim_arg);
6154 gcc_assert (prim_arg->expr);
6155 gcc_assert (opt_arg);
6157 /* If we do have type CHARACTER and the optional argument is really absent,
6158 append a dummy 0 as string length. */
6159 append_args = NULL;
6160 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6162 tree dummy;
6164 dummy = build_int_cst (gfc_charlen_type_node, 0);
6165 vec_alloc (append_args, 1);
6166 append_args->quick_push (dummy);
6169 /* Build the call itself. */
6170 gcc_assert (!se->ignore_optional);
6171 sym = gfc_get_symbol_for_expr (expr, false);
6172 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6173 append_args);
6174 gfc_free_symbol (sym);
6177 /* The length of a character string. */
6178 static void
6179 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6181 tree len;
6182 tree type;
6183 tree decl;
6184 gfc_symbol *sym;
6185 gfc_se argse;
6186 gfc_expr *arg;
6188 gcc_assert (!se->ss);
6190 arg = expr->value.function.actual->expr;
6192 type = gfc_typenode_for_spec (&expr->ts);
6193 switch (arg->expr_type)
6195 case EXPR_CONSTANT:
6196 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6197 break;
6199 case EXPR_ARRAY:
6200 /* Obtain the string length from the function used by
6201 trans-array.c(gfc_trans_array_constructor). */
6202 len = NULL_TREE;
6203 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6204 break;
6206 case EXPR_VARIABLE:
6207 if (arg->ref == NULL
6208 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6210 /* This doesn't catch all cases.
6211 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6212 and the surrounding thread. */
6213 sym = arg->symtree->n.sym;
6214 decl = gfc_get_symbol_decl (sym);
6215 if (decl == current_function_decl && sym->attr.function
6216 && (sym->result == sym))
6217 decl = gfc_get_fake_result_decl (sym, 0);
6219 len = sym->ts.u.cl->backend_decl;
6220 gcc_assert (len);
6221 break;
6224 /* Fall through. */
6226 default:
6227 /* Anybody stupid enough to do this deserves inefficient code. */
6228 gfc_init_se (&argse, se);
6229 if (arg->rank == 0)
6230 gfc_conv_expr (&argse, arg);
6231 else
6232 gfc_conv_expr_descriptor (&argse, arg);
6233 gfc_add_block_to_block (&se->pre, &argse.pre);
6234 gfc_add_block_to_block (&se->post, &argse.post);
6235 len = argse.string_length;
6236 break;
6238 se->expr = convert (type, len);
6241 /* The length of a character string not including trailing blanks. */
6242 static void
6243 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6245 int kind = expr->value.function.actual->expr->ts.kind;
6246 tree args[2], type, fndecl;
6248 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6249 type = gfc_typenode_for_spec (&expr->ts);
6251 if (kind == 1)
6252 fndecl = gfor_fndecl_string_len_trim;
6253 else if (kind == 4)
6254 fndecl = gfor_fndecl_string_len_trim_char4;
6255 else
6256 gcc_unreachable ();
6258 se->expr = build_call_expr_loc (input_location,
6259 fndecl, 2, args[0], args[1]);
6260 se->expr = convert (type, se->expr);
6264 /* Returns the starting position of a substring within a string. */
6266 static void
6267 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6268 tree function)
6270 tree logical4_type_node = gfc_get_logical_type (4);
6271 tree type;
6272 tree fndecl;
6273 tree *args;
6274 unsigned int num_args;
6276 args = XALLOCAVEC (tree, 5);
6278 /* Get number of arguments; characters count double due to the
6279 string length argument. Kind= is not passed to the library
6280 and thus ignored. */
6281 if (expr->value.function.actual->next->next->expr == NULL)
6282 num_args = 4;
6283 else
6284 num_args = 5;
6286 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6287 type = gfc_typenode_for_spec (&expr->ts);
6289 if (num_args == 4)
6290 args[4] = build_int_cst (logical4_type_node, 0);
6291 else
6292 args[4] = convert (logical4_type_node, args[4]);
6294 fndecl = build_addr (function);
6295 se->expr = build_call_array_loc (input_location,
6296 TREE_TYPE (TREE_TYPE (function)), fndecl,
6297 5, args);
6298 se->expr = convert (type, se->expr);
6302 /* The ascii value for a single character. */
6303 static void
6304 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6306 tree args[3], type, pchartype;
6307 int nargs;
6309 nargs = gfc_intrinsic_argument_list_length (expr);
6310 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6311 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6312 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6313 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6314 type = gfc_typenode_for_spec (&expr->ts);
6316 se->expr = build_fold_indirect_ref_loc (input_location,
6317 args[1]);
6318 se->expr = convert (type, se->expr);
6322 /* Intrinsic ISNAN calls __builtin_isnan. */
6324 static void
6325 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6327 tree arg;
6329 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6330 se->expr = build_call_expr_loc (input_location,
6331 builtin_decl_explicit (BUILT_IN_ISNAN),
6332 1, arg);
6333 STRIP_TYPE_NOPS (se->expr);
6334 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6338 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6339 their argument against a constant integer value. */
6341 static void
6342 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6344 tree arg;
6346 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6347 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6348 gfc_typenode_for_spec (&expr->ts),
6349 arg, build_int_cst (TREE_TYPE (arg), value));
6354 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6356 static void
6357 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6359 tree tsource;
6360 tree fsource;
6361 tree mask;
6362 tree type;
6363 tree len, len2;
6364 tree *args;
6365 unsigned int num_args;
6367 num_args = gfc_intrinsic_argument_list_length (expr);
6368 args = XALLOCAVEC (tree, num_args);
6370 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6371 if (expr->ts.type != BT_CHARACTER)
6373 tsource = args[0];
6374 fsource = args[1];
6375 mask = args[2];
6377 else
6379 /* We do the same as in the non-character case, but the argument
6380 list is different because of the string length arguments. We
6381 also have to set the string length for the result. */
6382 len = args[0];
6383 tsource = args[1];
6384 len2 = args[2];
6385 fsource = args[3];
6386 mask = args[4];
6388 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6389 &se->pre);
6390 se->string_length = len;
6392 type = TREE_TYPE (tsource);
6393 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6394 fold_convert (type, fsource));
6398 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6400 static void
6401 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6403 tree args[3], mask, type;
6405 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6406 mask = gfc_evaluate_now (args[2], &se->pre);
6408 type = TREE_TYPE (args[0]);
6409 gcc_assert (TREE_TYPE (args[1]) == type);
6410 gcc_assert (TREE_TYPE (mask) == type);
6412 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6413 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6414 fold_build1_loc (input_location, BIT_NOT_EXPR,
6415 type, mask));
6416 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6417 args[0], args[1]);
6421 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6422 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6424 static void
6425 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6427 tree arg, allones, type, utype, res, cond, bitsize;
6428 int i;
6430 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6431 arg = gfc_evaluate_now (arg, &se->pre);
6433 type = gfc_get_int_type (expr->ts.kind);
6434 utype = unsigned_type_for (type);
6436 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6437 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6439 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6440 build_int_cst (utype, 0));
6442 if (left)
6444 /* Left-justified mask. */
6445 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6446 bitsize, arg);
6447 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6448 fold_convert (utype, res));
6450 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6451 smaller than type width. */
6452 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6453 build_int_cst (TREE_TYPE (arg), 0));
6454 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6455 build_int_cst (utype, 0), res);
6457 else
6459 /* Right-justified mask. */
6460 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6461 fold_convert (utype, arg));
6462 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6464 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6465 strictly smaller than type width. */
6466 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6467 arg, bitsize);
6468 res = fold_build3_loc (input_location, COND_EXPR, utype,
6469 cond, allones, res);
6472 se->expr = fold_convert (type, res);
6476 /* FRACTION (s) is translated into:
6477 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6478 static void
6479 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6481 tree arg, type, tmp, res, frexp, cond;
6483 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6485 type = gfc_typenode_for_spec (&expr->ts);
6486 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6487 arg = gfc_evaluate_now (arg, &se->pre);
6489 cond = build_call_expr_loc (input_location,
6490 builtin_decl_explicit (BUILT_IN_ISFINITE),
6491 1, arg);
6493 tmp = gfc_create_var (integer_type_node, NULL);
6494 res = build_call_expr_loc (input_location, frexp, 2,
6495 fold_convert (type, arg),
6496 gfc_build_addr_expr (NULL_TREE, tmp));
6497 res = fold_convert (type, res);
6499 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6500 cond, res, gfc_build_nan (type, ""));
6504 /* NEAREST (s, dir) is translated into
6505 tmp = copysign (HUGE_VAL, dir);
6506 return nextafter (s, tmp);
6508 static void
6509 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6511 tree args[2], type, tmp, nextafter, copysign, huge_val;
6513 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6514 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6516 type = gfc_typenode_for_spec (&expr->ts);
6517 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6519 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6520 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6521 fold_convert (type, args[1]));
6522 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6523 fold_convert (type, args[0]), tmp);
6524 se->expr = fold_convert (type, se->expr);
6528 /* SPACING (s) is translated into
6529 int e;
6530 if (!isfinite (s))
6531 res = NaN;
6532 else if (s == 0)
6533 res = tiny;
6534 else
6536 frexp (s, &e);
6537 e = e - prec;
6538 e = MAX_EXPR (e, emin);
6539 res = scalbn (1., e);
6541 return res;
6543 where prec is the precision of s, gfc_real_kinds[k].digits,
6544 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6545 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6547 static void
6548 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6550 tree arg, type, prec, emin, tiny, res, e;
6551 tree cond, nan, tmp, frexp, scalbn;
6552 int k;
6553 stmtblock_t block;
6555 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6556 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6557 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6558 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6560 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6561 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6563 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6564 arg = gfc_evaluate_now (arg, &se->pre);
6566 type = gfc_typenode_for_spec (&expr->ts);
6567 e = gfc_create_var (integer_type_node, NULL);
6568 res = gfc_create_var (type, NULL);
6571 /* Build the block for s /= 0. */
6572 gfc_start_block (&block);
6573 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6574 gfc_build_addr_expr (NULL_TREE, e));
6575 gfc_add_expr_to_block (&block, tmp);
6577 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6578 prec);
6579 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6580 integer_type_node, tmp, emin));
6582 tmp = build_call_expr_loc (input_location, scalbn, 2,
6583 build_real_from_int_cst (type, integer_one_node), e);
6584 gfc_add_modify (&block, res, tmp);
6586 /* Finish by building the IF statement for value zero. */
6587 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6588 build_real_from_int_cst (type, integer_zero_node));
6589 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6590 gfc_finish_block (&block));
6592 /* And deal with infinities and NaNs. */
6593 cond = build_call_expr_loc (input_location,
6594 builtin_decl_explicit (BUILT_IN_ISFINITE),
6595 1, arg);
6596 nan = gfc_build_nan (type, "");
6597 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6599 gfc_add_expr_to_block (&se->pre, tmp);
6600 se->expr = res;
6604 /* RRSPACING (s) is translated into
6605 int e;
6606 real x;
6607 x = fabs (s);
6608 if (isfinite (x))
6610 if (x != 0)
6612 frexp (s, &e);
6613 x = scalbn (x, precision - e);
6616 else
6617 x = NaN;
6618 return x;
6620 where precision is gfc_real_kinds[k].digits. */
6622 static void
6623 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6625 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6626 int prec, k;
6627 stmtblock_t block;
6629 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6630 prec = gfc_real_kinds[k].digits;
6632 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6633 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6634 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6636 type = gfc_typenode_for_spec (&expr->ts);
6637 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6638 arg = gfc_evaluate_now (arg, &se->pre);
6640 e = gfc_create_var (integer_type_node, NULL);
6641 x = gfc_create_var (type, NULL);
6642 gfc_add_modify (&se->pre, x,
6643 build_call_expr_loc (input_location, fabs, 1, arg));
6646 gfc_start_block (&block);
6647 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6648 gfc_build_addr_expr (NULL_TREE, e));
6649 gfc_add_expr_to_block (&block, tmp);
6651 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6652 build_int_cst (integer_type_node, prec), e);
6653 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6654 gfc_add_modify (&block, x, tmp);
6655 stmt = gfc_finish_block (&block);
6657 /* if (x != 0) */
6658 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
6659 build_real_from_int_cst (type, integer_zero_node));
6660 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6662 /* And deal with infinities and NaNs. */
6663 cond = build_call_expr_loc (input_location,
6664 builtin_decl_explicit (BUILT_IN_ISFINITE),
6665 1, x);
6666 nan = gfc_build_nan (type, "");
6667 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6669 gfc_add_expr_to_block (&se->pre, tmp);
6670 se->expr = fold_convert (type, x);
6674 /* SCALE (s, i) is translated into scalbn (s, i). */
6675 static void
6676 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6678 tree args[2], type, scalbn;
6680 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6682 type = gfc_typenode_for_spec (&expr->ts);
6683 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6684 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6685 fold_convert (type, args[0]),
6686 fold_convert (integer_type_node, args[1]));
6687 se->expr = fold_convert (type, se->expr);
6691 /* SET_EXPONENT (s, i) is translated into
6692 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6693 static void
6694 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6696 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6698 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6699 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6701 type = gfc_typenode_for_spec (&expr->ts);
6702 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6703 args[0] = gfc_evaluate_now (args[0], &se->pre);
6705 tmp = gfc_create_var (integer_type_node, NULL);
6706 tmp = build_call_expr_loc (input_location, frexp, 2,
6707 fold_convert (type, args[0]),
6708 gfc_build_addr_expr (NULL_TREE, tmp));
6709 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6710 fold_convert (integer_type_node, args[1]));
6711 res = fold_convert (type, res);
6713 /* Call to isfinite */
6714 cond = build_call_expr_loc (input_location,
6715 builtin_decl_explicit (BUILT_IN_ISFINITE),
6716 1, args[0]);
6717 nan = gfc_build_nan (type, "");
6719 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6720 res, nan);
6724 static void
6725 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6727 gfc_actual_arglist *actual;
6728 tree arg1;
6729 tree type;
6730 tree fncall0;
6731 tree fncall1;
6732 gfc_se argse;
6734 gfc_init_se (&argse, NULL);
6735 actual = expr->value.function.actual;
6737 if (actual->expr->ts.type == BT_CLASS)
6738 gfc_add_class_array_ref (actual->expr);
6740 argse.data_not_needed = 1;
6741 if (gfc_is_class_array_function (actual->expr))
6743 /* For functions that return a class array conv_expr_descriptor is not
6744 able to get the descriptor right. Therefore this special case. */
6745 gfc_conv_expr_reference (&argse, actual->expr);
6746 argse.expr = gfc_build_addr_expr (NULL_TREE,
6747 gfc_class_data_get (argse.expr));
6749 else
6751 argse.want_pointer = 1;
6752 gfc_conv_expr_descriptor (&argse, actual->expr);
6754 gfc_add_block_to_block (&se->pre, &argse.pre);
6755 gfc_add_block_to_block (&se->post, &argse.post);
6756 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6758 /* Build the call to size0. */
6759 fncall0 = build_call_expr_loc (input_location,
6760 gfor_fndecl_size0, 1, arg1);
6762 actual = actual->next;
6764 if (actual->expr)
6766 gfc_init_se (&argse, NULL);
6767 gfc_conv_expr_type (&argse, actual->expr,
6768 gfc_array_index_type);
6769 gfc_add_block_to_block (&se->pre, &argse.pre);
6771 /* Unusually, for an intrinsic, size does not exclude
6772 an optional arg2, so we must test for it. */
6773 if (actual->expr->expr_type == EXPR_VARIABLE
6774 && actual->expr->symtree->n.sym->attr.dummy
6775 && actual->expr->symtree->n.sym->attr.optional)
6777 tree tmp;
6778 /* Build the call to size1. */
6779 fncall1 = build_call_expr_loc (input_location,
6780 gfor_fndecl_size1, 2,
6781 arg1, argse.expr);
6783 gfc_init_se (&argse, NULL);
6784 argse.want_pointer = 1;
6785 argse.data_not_needed = 1;
6786 gfc_conv_expr (&argse, actual->expr);
6787 gfc_add_block_to_block (&se->pre, &argse.pre);
6788 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6789 argse.expr, null_pointer_node);
6790 tmp = gfc_evaluate_now (tmp, &se->pre);
6791 se->expr = fold_build3_loc (input_location, COND_EXPR,
6792 pvoid_type_node, tmp, fncall1, fncall0);
6794 else
6796 se->expr = NULL_TREE;
6797 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
6798 gfc_array_index_type,
6799 argse.expr, gfc_index_one_node);
6802 else if (expr->value.function.actual->expr->rank == 1)
6804 argse.expr = gfc_index_zero_node;
6805 se->expr = NULL_TREE;
6807 else
6808 se->expr = fncall0;
6810 if (se->expr == NULL_TREE)
6812 tree ubound, lbound;
6814 arg1 = build_fold_indirect_ref_loc (input_location,
6815 arg1);
6816 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
6817 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6818 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
6819 gfc_array_index_type, ubound, lbound);
6820 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
6821 gfc_array_index_type,
6822 se->expr, gfc_index_one_node);
6823 se->expr = fold_build2_loc (input_location, MAX_EXPR,
6824 gfc_array_index_type, se->expr,
6825 gfc_index_zero_node);
6828 type = gfc_typenode_for_spec (&expr->ts);
6829 se->expr = convert (type, se->expr);
6833 /* Helper function to compute the size of a character variable,
6834 excluding the terminating null characters. The result has
6835 gfc_array_index_type type. */
6837 tree
6838 size_of_string_in_bytes (int kind, tree string_length)
6840 tree bytesize;
6841 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
6843 bytesize = build_int_cst (gfc_array_index_type,
6844 gfc_character_kinds[i].bit_size / 8);
6846 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6847 bytesize,
6848 fold_convert (gfc_array_index_type, string_length));
6852 static void
6853 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
6855 gfc_expr *arg;
6856 gfc_se argse;
6857 tree source_bytes;
6858 tree tmp;
6859 tree lower;
6860 tree upper;
6861 tree byte_size;
6862 tree field;
6863 int n;
6865 gfc_init_se (&argse, NULL);
6866 arg = expr->value.function.actual->expr;
6868 if (arg->rank || arg->ts.type == BT_ASSUMED)
6869 gfc_conv_expr_descriptor (&argse, arg);
6870 else
6871 gfc_conv_expr_reference (&argse, arg);
6873 if (arg->ts.type == BT_ASSUMED)
6875 /* This only works if an array descriptor has been passed; thus, extract
6876 the size from the descriptor. */
6877 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
6878 == TYPE_PRECISION (size_type_node));
6879 tmp = arg->symtree->n.sym->backend_decl;
6880 tmp = DECL_LANG_SPECIFIC (tmp)
6881 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
6882 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
6883 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
6884 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6886 tmp = gfc_conv_descriptor_dtype (tmp);
6887 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
6888 GFC_DTYPE_ELEM_LEN);
6889 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
6890 tmp, field, NULL_TREE);
6892 byte_size = fold_convert (gfc_array_index_type, tmp);
6894 else if (arg->ts.type == BT_CLASS)
6896 /* Conv_expr_descriptor returns a component_ref to _data component of the
6897 class object. The class object may be a non-pointer object, e.g.
6898 located on the stack, or a memory location pointed to, e.g. a
6899 parameter, i.e., an indirect_ref. */
6900 if (arg->rank < 0
6901 || (arg->rank > 0 && !VAR_P (argse.expr)
6902 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
6903 && GFC_DECL_CLASS (TREE_OPERAND (
6904 TREE_OPERAND (argse.expr, 0), 0)))
6905 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
6906 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6907 else if (arg->rank > 0
6908 || (arg->rank == 0
6909 && arg->ref && arg->ref->type == REF_COMPONENT))
6910 /* The scalarizer added an additional temp. To get the class' vptr
6911 one has to look at the original backend_decl. */
6912 byte_size = gfc_class_vtab_size_get (
6913 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
6914 else
6915 byte_size = gfc_class_vtab_size_get (argse.expr);
6917 else
6919 if (arg->ts.type == BT_CHARACTER)
6920 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6921 else
6923 if (arg->rank == 0)
6924 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6925 argse.expr));
6926 else
6927 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
6928 byte_size = fold_convert (gfc_array_index_type,
6929 size_in_bytes (byte_size));
6933 if (arg->rank == 0)
6934 se->expr = byte_size;
6935 else
6937 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
6938 gfc_add_modify (&argse.pre, source_bytes, byte_size);
6940 if (arg->rank == -1)
6942 tree cond, loop_var, exit_label;
6943 stmtblock_t body;
6945 tmp = fold_convert (gfc_array_index_type,
6946 gfc_conv_descriptor_rank (argse.expr));
6947 loop_var = gfc_create_var (gfc_array_index_type, "i");
6948 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
6949 exit_label = gfc_build_label_decl (NULL_TREE);
6951 /* Create loop:
6952 for (;;)
6954 if (i >= rank)
6955 goto exit;
6956 source_bytes = source_bytes * array.dim[i].extent;
6957 i = i + 1;
6959 exit: */
6960 gfc_start_block (&body);
6961 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6962 loop_var, tmp);
6963 tmp = build1_v (GOTO_EXPR, exit_label);
6964 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6965 cond, tmp, build_empty_stmt (input_location));
6966 gfc_add_expr_to_block (&body, tmp);
6968 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
6969 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
6970 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6971 tmp = fold_build2_loc (input_location, MULT_EXPR,
6972 gfc_array_index_type, tmp, source_bytes);
6973 gfc_add_modify (&body, source_bytes, tmp);
6975 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6976 gfc_array_index_type, loop_var,
6977 gfc_index_one_node);
6978 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
6980 tmp = gfc_finish_block (&body);
6982 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
6983 tmp);
6984 gfc_add_expr_to_block (&argse.pre, tmp);
6986 tmp = build1_v (LABEL_EXPR, exit_label);
6987 gfc_add_expr_to_block (&argse.pre, tmp);
6989 else
6991 /* Obtain the size of the array in bytes. */
6992 for (n = 0; n < arg->rank; n++)
6994 tree idx;
6995 idx = gfc_rank_cst[n];
6996 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6997 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6998 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6999 tmp = fold_build2_loc (input_location, MULT_EXPR,
7000 gfc_array_index_type, tmp, source_bytes);
7001 gfc_add_modify (&argse.pre, source_bytes, tmp);
7004 se->expr = source_bytes;
7007 gfc_add_block_to_block (&se->pre, &argse.pre);
7011 static void
7012 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
7014 gfc_expr *arg;
7015 gfc_se argse;
7016 tree type, result_type, tmp;
7018 arg = expr->value.function.actual->expr;
7020 gfc_init_se (&argse, NULL);
7021 result_type = gfc_get_int_type (expr->ts.kind);
7023 if (arg->rank == 0)
7025 if (arg->ts.type == BT_CLASS)
7027 gfc_add_vptr_component (arg);
7028 gfc_add_size_component (arg);
7029 gfc_conv_expr (&argse, arg);
7030 tmp = fold_convert (result_type, argse.expr);
7031 goto done;
7034 gfc_conv_expr_reference (&argse, arg);
7035 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7036 argse.expr));
7038 else
7040 argse.want_pointer = 0;
7041 gfc_conv_expr_descriptor (&argse, arg);
7042 if (arg->ts.type == BT_CLASS)
7044 if (arg->rank > 0)
7045 tmp = gfc_class_vtab_size_get (
7046 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7047 else
7048 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7049 tmp = fold_convert (result_type, tmp);
7050 goto done;
7052 type = gfc_get_element_type (TREE_TYPE (argse.expr));
7055 /* Obtain the argument's word length. */
7056 if (arg->ts.type == BT_CHARACTER)
7057 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7058 else
7059 tmp = size_in_bytes (type);
7060 tmp = fold_convert (result_type, tmp);
7062 done:
7063 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
7064 build_int_cst (result_type, BITS_PER_UNIT));
7065 gfc_add_block_to_block (&se->pre, &argse.pre);
7069 /* Intrinsic string comparison functions. */
7071 static void
7072 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
7074 tree args[4];
7076 gfc_conv_intrinsic_function_args (se, expr, args, 4);
7078 se->expr
7079 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
7080 expr->value.function.actual->expr->ts.kind,
7081 op);
7082 se->expr = fold_build2_loc (input_location, op,
7083 gfc_typenode_for_spec (&expr->ts), se->expr,
7084 build_int_cst (TREE_TYPE (se->expr), 0));
7087 /* Generate a call to the adjustl/adjustr library function. */
7088 static void
7089 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
7091 tree args[3];
7092 tree len;
7093 tree type;
7094 tree var;
7095 tree tmp;
7097 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
7098 len = args[1];
7100 type = TREE_TYPE (args[2]);
7101 var = gfc_conv_string_tmp (se, type, len);
7102 args[0] = var;
7104 tmp = build_call_expr_loc (input_location,
7105 fndecl, 3, args[0], args[1], args[2]);
7106 gfc_add_expr_to_block (&se->pre, tmp);
7107 se->expr = var;
7108 se->string_length = len;
7112 /* Generate code for the TRANSFER intrinsic:
7113 For scalar results:
7114 DEST = TRANSFER (SOURCE, MOLD)
7115 where:
7116 typeof<DEST> = typeof<MOLD>
7117 and:
7118 MOLD is scalar.
7120 For array results:
7121 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7122 where:
7123 typeof<DEST> = typeof<MOLD>
7124 and:
7125 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7126 sizeof (DEST(0) * SIZE). */
7127 static void
7128 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
7130 tree tmp;
7131 tree tmpdecl;
7132 tree ptr;
7133 tree extent;
7134 tree source;
7135 tree source_type;
7136 tree source_bytes;
7137 tree mold_type;
7138 tree dest_word_len;
7139 tree size_words;
7140 tree size_bytes;
7141 tree upper;
7142 tree lower;
7143 tree stmt;
7144 gfc_actual_arglist *arg;
7145 gfc_se argse;
7146 gfc_array_info *info;
7147 stmtblock_t block;
7148 int n;
7149 bool scalar_mold;
7150 gfc_expr *source_expr, *mold_expr;
7152 info = NULL;
7153 if (se->loop)
7154 info = &se->ss->info->data.array;
7156 /* Convert SOURCE. The output from this stage is:-
7157 source_bytes = length of the source in bytes
7158 source = pointer to the source data. */
7159 arg = expr->value.function.actual;
7160 source_expr = arg->expr;
7162 /* Ensure double transfer through LOGICAL preserves all
7163 the needed bits. */
7164 if (arg->expr->expr_type == EXPR_FUNCTION
7165 && arg->expr->value.function.esym == NULL
7166 && arg->expr->value.function.isym != NULL
7167 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7168 && arg->expr->ts.type == BT_LOGICAL
7169 && expr->ts.type != arg->expr->ts.type)
7170 arg->expr->value.function.name = "__transfer_in_transfer";
7172 gfc_init_se (&argse, NULL);
7174 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7176 /* Obtain the pointer to source and the length of source in bytes. */
7177 if (arg->expr->rank == 0)
7179 gfc_conv_expr_reference (&argse, arg->expr);
7180 if (arg->expr->ts.type == BT_CLASS)
7181 source = gfc_class_data_get (argse.expr);
7182 else
7183 source = argse.expr;
7185 /* Obtain the source word length. */
7186 switch (arg->expr->ts.type)
7188 case BT_CHARACTER:
7189 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7190 argse.string_length);
7191 break;
7192 case BT_CLASS:
7193 tmp = gfc_class_vtab_size_get (argse.expr);
7194 break;
7195 default:
7196 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7197 source));
7198 tmp = fold_convert (gfc_array_index_type,
7199 size_in_bytes (source_type));
7200 break;
7203 else
7205 argse.want_pointer = 0;
7206 gfc_conv_expr_descriptor (&argse, arg->expr);
7207 source = gfc_conv_descriptor_data_get (argse.expr);
7208 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7210 /* Repack the source if not simply contiguous. */
7211 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7213 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7215 if (warn_array_temporaries)
7216 gfc_warning (OPT_Warray_temporaries,
7217 "Creating array temporary at %L", &expr->where);
7219 source = build_call_expr_loc (input_location,
7220 gfor_fndecl_in_pack, 1, tmp);
7221 source = gfc_evaluate_now (source, &argse.pre);
7223 /* Free the temporary. */
7224 gfc_start_block (&block);
7225 tmp = gfc_call_free (source);
7226 gfc_add_expr_to_block (&block, tmp);
7227 stmt = gfc_finish_block (&block);
7229 /* Clean up if it was repacked. */
7230 gfc_init_block (&block);
7231 tmp = gfc_conv_array_data (argse.expr);
7232 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7233 source, tmp);
7234 tmp = build3_v (COND_EXPR, tmp, stmt,
7235 build_empty_stmt (input_location));
7236 gfc_add_expr_to_block (&block, tmp);
7237 gfc_add_block_to_block (&block, &se->post);
7238 gfc_init_block (&se->post);
7239 gfc_add_block_to_block (&se->post, &block);
7242 /* Obtain the source word length. */
7243 if (arg->expr->ts.type == BT_CHARACTER)
7244 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7245 argse.string_length);
7246 else
7247 tmp = fold_convert (gfc_array_index_type,
7248 size_in_bytes (source_type));
7250 /* Obtain the size of the array in bytes. */
7251 extent = gfc_create_var (gfc_array_index_type, NULL);
7252 for (n = 0; n < arg->expr->rank; n++)
7254 tree idx;
7255 idx = gfc_rank_cst[n];
7256 gfc_add_modify (&argse.pre, source_bytes, tmp);
7257 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7258 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7259 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7260 gfc_array_index_type, upper, lower);
7261 gfc_add_modify (&argse.pre, extent, tmp);
7262 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7263 gfc_array_index_type, extent,
7264 gfc_index_one_node);
7265 tmp = fold_build2_loc (input_location, MULT_EXPR,
7266 gfc_array_index_type, tmp, source_bytes);
7270 gfc_add_modify (&argse.pre, source_bytes, tmp);
7271 gfc_add_block_to_block (&se->pre, &argse.pre);
7272 gfc_add_block_to_block (&se->post, &argse.post);
7274 /* Now convert MOLD. The outputs are:
7275 mold_type = the TREE type of MOLD
7276 dest_word_len = destination word length in bytes. */
7277 arg = arg->next;
7278 mold_expr = arg->expr;
7280 gfc_init_se (&argse, NULL);
7282 scalar_mold = arg->expr->rank == 0;
7284 if (arg->expr->rank == 0)
7286 gfc_conv_expr_reference (&argse, arg->expr);
7287 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7288 argse.expr));
7290 else
7292 gfc_init_se (&argse, NULL);
7293 argse.want_pointer = 0;
7294 gfc_conv_expr_descriptor (&argse, arg->expr);
7295 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7298 gfc_add_block_to_block (&se->pre, &argse.pre);
7299 gfc_add_block_to_block (&se->post, &argse.post);
7301 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7303 /* If this TRANSFER is nested in another TRANSFER, use a type
7304 that preserves all bits. */
7305 if (arg->expr->ts.type == BT_LOGICAL)
7306 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7309 /* Obtain the destination word length. */
7310 switch (arg->expr->ts.type)
7312 case BT_CHARACTER:
7313 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7314 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7315 break;
7316 case BT_CLASS:
7317 tmp = gfc_class_vtab_size_get (argse.expr);
7318 break;
7319 default:
7320 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7321 break;
7323 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7324 gfc_add_modify (&se->pre, dest_word_len, tmp);
7326 /* Finally convert SIZE, if it is present. */
7327 arg = arg->next;
7328 size_words = gfc_create_var (gfc_array_index_type, NULL);
7330 if (arg->expr)
7332 gfc_init_se (&argse, NULL);
7333 gfc_conv_expr_reference (&argse, arg->expr);
7334 tmp = convert (gfc_array_index_type,
7335 build_fold_indirect_ref_loc (input_location,
7336 argse.expr));
7337 gfc_add_block_to_block (&se->pre, &argse.pre);
7338 gfc_add_block_to_block (&se->post, &argse.post);
7340 else
7341 tmp = NULL_TREE;
7343 /* Separate array and scalar results. */
7344 if (scalar_mold && tmp == NULL_TREE)
7345 goto scalar_transfer;
7347 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7348 if (tmp != NULL_TREE)
7349 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7350 tmp, dest_word_len);
7351 else
7352 tmp = source_bytes;
7354 gfc_add_modify (&se->pre, size_bytes, tmp);
7355 gfc_add_modify (&se->pre, size_words,
7356 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7357 gfc_array_index_type,
7358 size_bytes, dest_word_len));
7360 /* Evaluate the bounds of the result. If the loop range exists, we have
7361 to check if it is too large. If so, we modify loop->to be consistent
7362 with min(size, size(source)). Otherwise, size is made consistent with
7363 the loop range, so that the right number of bytes is transferred.*/
7364 n = se->loop->order[0];
7365 if (se->loop->to[n] != NULL_TREE)
7367 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7368 se->loop->to[n], se->loop->from[n]);
7369 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7370 tmp, gfc_index_one_node);
7371 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7372 tmp, size_words);
7373 gfc_add_modify (&se->pre, size_words, tmp);
7374 gfc_add_modify (&se->pre, size_bytes,
7375 fold_build2_loc (input_location, MULT_EXPR,
7376 gfc_array_index_type,
7377 size_words, dest_word_len));
7378 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7379 size_words, se->loop->from[n]);
7380 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7381 upper, gfc_index_one_node);
7383 else
7385 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7386 size_words, gfc_index_one_node);
7387 se->loop->from[n] = gfc_index_zero_node;
7390 se->loop->to[n] = upper;
7392 /* Build a destination descriptor, using the pointer, source, as the
7393 data field. */
7394 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7395 NULL_TREE, false, true, false, &expr->where);
7397 /* Cast the pointer to the result. */
7398 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7399 tmp = fold_convert (pvoid_type_node, tmp);
7401 /* Use memcpy to do the transfer. */
7403 = build_call_expr_loc (input_location,
7404 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7405 fold_convert (pvoid_type_node, source),
7406 fold_convert (size_type_node,
7407 fold_build2_loc (input_location,
7408 MIN_EXPR,
7409 gfc_array_index_type,
7410 size_bytes,
7411 source_bytes)));
7412 gfc_add_expr_to_block (&se->pre, tmp);
7414 se->expr = info->descriptor;
7415 if (expr->ts.type == BT_CHARACTER)
7416 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7418 return;
7420 /* Deal with scalar results. */
7421 scalar_transfer:
7422 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7423 dest_word_len, source_bytes);
7424 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7425 extent, gfc_index_zero_node);
7427 if (expr->ts.type == BT_CHARACTER)
7429 tree direct, indirect, free;
7431 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7432 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7433 "transfer");
7435 /* If source is longer than the destination, use a pointer to
7436 the source directly. */
7437 gfc_init_block (&block);
7438 gfc_add_modify (&block, tmpdecl, ptr);
7439 direct = gfc_finish_block (&block);
7441 /* Otherwise, allocate a string with the length of the destination
7442 and copy the source into it. */
7443 gfc_init_block (&block);
7444 tmp = gfc_get_pchar_type (expr->ts.kind);
7445 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7446 gfc_add_modify (&block, tmpdecl,
7447 fold_convert (TREE_TYPE (ptr), tmp));
7448 tmp = build_call_expr_loc (input_location,
7449 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7450 fold_convert (pvoid_type_node, tmpdecl),
7451 fold_convert (pvoid_type_node, ptr),
7452 fold_convert (size_type_node, extent));
7453 gfc_add_expr_to_block (&block, tmp);
7454 indirect = gfc_finish_block (&block);
7456 /* Wrap it up with the condition. */
7457 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7458 dest_word_len, source_bytes);
7459 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7460 gfc_add_expr_to_block (&se->pre, tmp);
7462 /* Free the temporary string, if necessary. */
7463 free = gfc_call_free (tmpdecl);
7464 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7465 dest_word_len, source_bytes);
7466 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7467 gfc_add_expr_to_block (&se->post, tmp);
7469 se->expr = tmpdecl;
7470 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7472 else
7474 tmpdecl = gfc_create_var (mold_type, "transfer");
7476 ptr = convert (build_pointer_type (mold_type), source);
7478 /* For CLASS results, allocate the needed memory first. */
7479 if (mold_expr->ts.type == BT_CLASS)
7481 tree cdata;
7482 cdata = gfc_class_data_get (tmpdecl);
7483 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7484 gfc_add_modify (&se->pre, cdata, tmp);
7487 /* Use memcpy to do the transfer. */
7488 if (mold_expr->ts.type == BT_CLASS)
7489 tmp = gfc_class_data_get (tmpdecl);
7490 else
7491 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7493 tmp = build_call_expr_loc (input_location,
7494 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7495 fold_convert (pvoid_type_node, tmp),
7496 fold_convert (pvoid_type_node, ptr),
7497 fold_convert (size_type_node, extent));
7498 gfc_add_expr_to_block (&se->pre, tmp);
7500 /* For CLASS results, set the _vptr. */
7501 if (mold_expr->ts.type == BT_CLASS)
7503 tree vptr;
7504 gfc_symbol *vtab;
7505 vptr = gfc_class_vptr_get (tmpdecl);
7506 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7507 gcc_assert (vtab);
7508 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7509 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7512 se->expr = tmpdecl;
7517 /* Generate a call to caf_is_present. */
7519 static tree
7520 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7522 tree caf_reference, caf_decl, token, image_index;
7524 /* Compile the reference chain. */
7525 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7526 gcc_assert (caf_reference != NULL_TREE);
7528 caf_decl = gfc_get_tree_for_caf_expr (expr);
7529 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7530 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7531 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7532 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7533 expr);
7535 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7536 3, token, image_index, caf_reference);
7540 /* Test whether this ref-chain refs this image only. */
7542 static bool
7543 caf_this_image_ref (gfc_ref *ref)
7545 for ( ; ref; ref = ref->next)
7546 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7547 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7549 return false;
7553 /* Generate code for the ALLOCATED intrinsic.
7554 Generate inline code that directly check the address of the argument. */
7556 static void
7557 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7559 gfc_actual_arglist *arg1;
7560 gfc_se arg1se;
7561 tree tmp;
7562 symbol_attribute caf_attr;
7564 gfc_init_se (&arg1se, NULL);
7565 arg1 = expr->value.function.actual;
7567 if (arg1->expr->ts.type == BT_CLASS)
7569 /* Make sure that class array expressions have both a _data
7570 component reference and an array reference.... */
7571 if (CLASS_DATA (arg1->expr)->attr.dimension)
7572 gfc_add_class_array_ref (arg1->expr);
7573 /* .... whilst scalars only need the _data component. */
7574 else
7575 gfc_add_data_component (arg1->expr);
7578 /* When arg1 references an allocatable component in a coarray, then call
7579 the caf-library function caf_is_present (). */
7580 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7581 && arg1->expr->value.function.isym
7582 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7583 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7584 else
7585 gfc_clear_attr (&caf_attr);
7586 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7587 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7588 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7589 else
7591 if (arg1->expr->rank == 0)
7593 /* Allocatable scalar. */
7594 arg1se.want_pointer = 1;
7595 gfc_conv_expr (&arg1se, arg1->expr);
7596 tmp = arg1se.expr;
7598 else
7600 /* Allocatable array. */
7601 arg1se.descriptor_only = 1;
7602 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7603 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7606 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
7607 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7610 /* Components of pointer array references sometimes come back with a pre block. */
7611 if (arg1se.pre.head)
7612 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7614 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7618 /* Generate code for the ASSOCIATED intrinsic.
7619 If both POINTER and TARGET are arrays, generate a call to library function
7620 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7621 In other cases, generate inline code that directly compare the address of
7622 POINTER with the address of TARGET. */
7624 static void
7625 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7627 gfc_actual_arglist *arg1;
7628 gfc_actual_arglist *arg2;
7629 gfc_se arg1se;
7630 gfc_se arg2se;
7631 tree tmp2;
7632 tree tmp;
7633 tree nonzero_charlen;
7634 tree nonzero_arraylen;
7635 gfc_ss *ss;
7636 bool scalar;
7638 gfc_init_se (&arg1se, NULL);
7639 gfc_init_se (&arg2se, NULL);
7640 arg1 = expr->value.function.actual;
7641 arg2 = arg1->next;
7643 /* Check whether the expression is a scalar or not; we cannot use
7644 arg1->expr->rank as it can be nonzero for proc pointers. */
7645 ss = gfc_walk_expr (arg1->expr);
7646 scalar = ss == gfc_ss_terminator;
7647 if (!scalar)
7648 gfc_free_ss_chain (ss);
7650 if (!arg2->expr)
7652 /* No optional target. */
7653 if (scalar)
7655 /* A pointer to a scalar. */
7656 arg1se.want_pointer = 1;
7657 gfc_conv_expr (&arg1se, arg1->expr);
7658 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7659 && arg1->expr->symtree->n.sym->attr.dummy)
7660 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7661 arg1se.expr);
7662 if (arg1->expr->ts.type == BT_CLASS)
7664 tmp2 = gfc_class_data_get (arg1se.expr);
7665 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7666 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7668 else
7669 tmp2 = arg1se.expr;
7671 else
7673 /* A pointer to an array. */
7674 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7675 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7677 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7678 gfc_add_block_to_block (&se->post, &arg1se.post);
7679 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
7680 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7681 se->expr = tmp;
7683 else
7685 /* An optional target. */
7686 if (arg2->expr->ts.type == BT_CLASS)
7687 gfc_add_data_component (arg2->expr);
7689 nonzero_charlen = NULL_TREE;
7690 if (arg1->expr->ts.type == BT_CHARACTER)
7691 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7692 logical_type_node,
7693 arg1->expr->ts.u.cl->backend_decl,
7694 build_zero_cst
7695 (TREE_TYPE (arg1->expr->ts.u.cl->backend_decl)));
7696 if (scalar)
7698 /* A pointer to a scalar. */
7699 arg1se.want_pointer = 1;
7700 gfc_conv_expr (&arg1se, arg1->expr);
7701 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7702 && arg1->expr->symtree->n.sym->attr.dummy)
7703 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7704 arg1se.expr);
7705 if (arg1->expr->ts.type == BT_CLASS)
7706 arg1se.expr = gfc_class_data_get (arg1se.expr);
7708 arg2se.want_pointer = 1;
7709 gfc_conv_expr (&arg2se, arg2->expr);
7710 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7711 && arg2->expr->symtree->n.sym->attr.dummy)
7712 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7713 arg2se.expr);
7714 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7715 gfc_add_block_to_block (&se->post, &arg1se.post);
7716 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7717 gfc_add_block_to_block (&se->post, &arg2se.post);
7718 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7719 arg1se.expr, arg2se.expr);
7720 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7721 arg1se.expr, null_pointer_node);
7722 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7723 logical_type_node, tmp, tmp2);
7725 else
7727 /* An array pointer of zero length is not associated if target is
7728 present. */
7729 arg1se.descriptor_only = 1;
7730 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7731 if (arg1->expr->rank == -1)
7733 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7734 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7735 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7737 else
7738 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7739 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7740 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7741 logical_type_node, tmp,
7742 build_int_cst (TREE_TYPE (tmp), 0));
7744 /* A pointer to an array, call library function _gfor_associated. */
7745 arg1se.want_pointer = 1;
7746 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7748 arg2se.want_pointer = 1;
7749 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7750 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7751 gfc_add_block_to_block (&se->post, &arg2se.post);
7752 se->expr = build_call_expr_loc (input_location,
7753 gfor_fndecl_associated, 2,
7754 arg1se.expr, arg2se.expr);
7755 se->expr = convert (logical_type_node, se->expr);
7756 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7757 logical_type_node, se->expr,
7758 nonzero_arraylen);
7761 /* If target is present zero character length pointers cannot
7762 be associated. */
7763 if (nonzero_charlen != NULL_TREE)
7764 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7765 logical_type_node,
7766 se->expr, nonzero_charlen);
7769 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7773 /* Generate code for the SAME_TYPE_AS intrinsic.
7774 Generate inline code that directly checks the vindices. */
7776 static void
7777 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7779 gfc_expr *a, *b;
7780 gfc_se se1, se2;
7781 tree tmp;
7782 tree conda = NULL_TREE, condb = NULL_TREE;
7784 gfc_init_se (&se1, NULL);
7785 gfc_init_se (&se2, NULL);
7787 a = expr->value.function.actual->expr;
7788 b = expr->value.function.actual->next->expr;
7790 if (UNLIMITED_POLY (a))
7792 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
7793 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7794 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7797 if (UNLIMITED_POLY (b))
7799 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
7800 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7801 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7804 if (a->ts.type == BT_CLASS)
7806 gfc_add_vptr_component (a);
7807 gfc_add_hash_component (a);
7809 else if (a->ts.type == BT_DERIVED)
7810 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7811 a->ts.u.derived->hash_value);
7813 if (b->ts.type == BT_CLASS)
7815 gfc_add_vptr_component (b);
7816 gfc_add_hash_component (b);
7818 else if (b->ts.type == BT_DERIVED)
7819 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7820 b->ts.u.derived->hash_value);
7822 gfc_conv_expr (&se1, a);
7823 gfc_conv_expr (&se2, b);
7825 tmp = fold_build2_loc (input_location, EQ_EXPR,
7826 logical_type_node, se1.expr,
7827 fold_convert (TREE_TYPE (se1.expr), se2.expr));
7829 if (conda)
7830 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7831 logical_type_node, conda, tmp);
7833 if (condb)
7834 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7835 logical_type_node, condb, tmp);
7837 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7841 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
7843 static void
7844 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
7846 tree args[2];
7848 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7849 se->expr = build_call_expr_loc (input_location,
7850 gfor_fndecl_sc_kind, 2, args[0], args[1]);
7851 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7855 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
7857 static void
7858 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
7860 tree arg, type;
7862 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7864 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
7865 type = gfc_get_int_type (4);
7866 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
7868 /* Convert it to the required type. */
7869 type = gfc_typenode_for_spec (&expr->ts);
7870 se->expr = build_call_expr_loc (input_location,
7871 gfor_fndecl_si_kind, 1, arg);
7872 se->expr = fold_convert (type, se->expr);
7876 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
7878 static void
7879 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
7881 gfc_actual_arglist *actual;
7882 tree type;
7883 gfc_se argse;
7884 vec<tree, va_gc> *args = NULL;
7886 for (actual = expr->value.function.actual; actual; actual = actual->next)
7888 gfc_init_se (&argse, se);
7890 /* Pass a NULL pointer for an absent arg. */
7891 if (actual->expr == NULL)
7892 argse.expr = null_pointer_node;
7893 else
7895 gfc_typespec ts;
7896 gfc_clear_ts (&ts);
7898 if (actual->expr->ts.kind != gfc_c_int_kind)
7900 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
7901 ts.type = BT_INTEGER;
7902 ts.kind = gfc_c_int_kind;
7903 gfc_convert_type (actual->expr, &ts, 2);
7905 gfc_conv_expr_reference (&argse, actual->expr);
7908 gfc_add_block_to_block (&se->pre, &argse.pre);
7909 gfc_add_block_to_block (&se->post, &argse.post);
7910 vec_safe_push (args, argse.expr);
7913 /* Convert it to the required type. */
7914 type = gfc_typenode_for_spec (&expr->ts);
7915 se->expr = build_call_expr_loc_vec (input_location,
7916 gfor_fndecl_sr_kind, args);
7917 se->expr = fold_convert (type, se->expr);
7921 /* Generate code for TRIM (A) intrinsic function. */
7923 static void
7924 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
7926 tree var;
7927 tree len;
7928 tree addr;
7929 tree tmp;
7930 tree cond;
7931 tree fndecl;
7932 tree function;
7933 tree *args;
7934 unsigned int num_args;
7936 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
7937 args = XALLOCAVEC (tree, num_args);
7939 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
7940 addr = gfc_build_addr_expr (ppvoid_type_node, var);
7941 len = gfc_create_var (gfc_charlen_type_node, "len");
7943 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
7944 args[0] = gfc_build_addr_expr (NULL_TREE, len);
7945 args[1] = addr;
7947 if (expr->ts.kind == 1)
7948 function = gfor_fndecl_string_trim;
7949 else if (expr->ts.kind == 4)
7950 function = gfor_fndecl_string_trim_char4;
7951 else
7952 gcc_unreachable ();
7954 fndecl = build_addr (function);
7955 tmp = build_call_array_loc (input_location,
7956 TREE_TYPE (TREE_TYPE (function)), fndecl,
7957 num_args, args);
7958 gfc_add_expr_to_block (&se->pre, tmp);
7960 /* Free the temporary afterwards, if necessary. */
7961 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7962 len, build_int_cst (TREE_TYPE (len), 0));
7963 tmp = gfc_call_free (var);
7964 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
7965 gfc_add_expr_to_block (&se->post, tmp);
7967 se->expr = var;
7968 se->string_length = len;
7972 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
7974 static void
7975 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
7977 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
7978 tree type, cond, tmp, count, exit_label, n, max, largest;
7979 tree size;
7980 stmtblock_t block, body;
7981 int i;
7983 /* We store in charsize the size of a character. */
7984 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
7985 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
7987 /* Get the arguments. */
7988 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7989 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
7990 src = args[1];
7991 ncopies = gfc_evaluate_now (args[2], &se->pre);
7992 ncopies_type = TREE_TYPE (ncopies);
7994 /* Check that NCOPIES is not negative. */
7995 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
7996 build_int_cst (ncopies_type, 0));
7997 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
7998 "Argument NCOPIES of REPEAT intrinsic is negative "
7999 "(its value is %ld)",
8000 fold_convert (long_integer_type_node, ncopies));
8002 /* If the source length is zero, any non negative value of NCOPIES
8003 is valid, and nothing happens. */
8004 n = gfc_create_var (ncopies_type, "ncopies");
8005 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8006 size_zero_node);
8007 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
8008 build_int_cst (ncopies_type, 0), ncopies);
8009 gfc_add_modify (&se->pre, n, tmp);
8010 ncopies = n;
8012 /* Check that ncopies is not too large: ncopies should be less than
8013 (or equal to) MAX / slen, where MAX is the maximal integer of
8014 the gfc_charlen_type_node type. If slen == 0, we need a special
8015 case to avoid the division by zero. */
8016 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
8017 fold_convert (sizetype,
8018 TYPE_MAX_VALUE (gfc_charlen_type_node)),
8019 slen);
8020 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
8021 ? sizetype : ncopies_type;
8022 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8023 fold_convert (largest, ncopies),
8024 fold_convert (largest, max));
8025 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8026 size_zero_node);
8027 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
8028 logical_false_node, cond);
8029 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8030 "Argument NCOPIES of REPEAT intrinsic is too large");
8032 /* Compute the destination length. */
8033 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
8034 fold_convert (gfc_charlen_type_node, slen),
8035 fold_convert (gfc_charlen_type_node, ncopies));
8036 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
8037 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
8039 /* Generate the code to do the repeat operation:
8040 for (i = 0; i < ncopies; i++)
8041 memmove (dest + (i * slen * size), src, slen*size); */
8042 gfc_start_block (&block);
8043 count = gfc_create_var (sizetype, "count");
8044 gfc_add_modify (&block, count, size_zero_node);
8045 exit_label = gfc_build_label_decl (NULL_TREE);
8047 /* Start the loop body. */
8048 gfc_start_block (&body);
8050 /* Exit the loop if count >= ncopies. */
8051 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
8052 fold_convert (sizetype, ncopies));
8053 tmp = build1_v (GOTO_EXPR, exit_label);
8054 TREE_USED (exit_label) = 1;
8055 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
8056 build_empty_stmt (input_location));
8057 gfc_add_expr_to_block (&body, tmp);
8059 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8060 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
8061 count);
8062 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
8063 size);
8064 tmp = fold_build_pointer_plus_loc (input_location,
8065 fold_convert (pvoid_type_node, dest), tmp);
8066 tmp = build_call_expr_loc (input_location,
8067 builtin_decl_explicit (BUILT_IN_MEMMOVE),
8068 3, tmp, src,
8069 fold_build2_loc (input_location, MULT_EXPR,
8070 size_type_node, slen, size));
8071 gfc_add_expr_to_block (&body, tmp);
8073 /* Increment count. */
8074 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
8075 count, size_one_node);
8076 gfc_add_modify (&body, count, tmp);
8078 /* Build the loop. */
8079 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
8080 gfc_add_expr_to_block (&block, tmp);
8082 /* Add the exit label. */
8083 tmp = build1_v (LABEL_EXPR, exit_label);
8084 gfc_add_expr_to_block (&block, tmp);
8086 /* Finish the block. */
8087 tmp = gfc_finish_block (&block);
8088 gfc_add_expr_to_block (&se->pre, tmp);
8090 /* Set the result value. */
8091 se->expr = dest;
8092 se->string_length = dlen;
8096 /* Generate code for the IARGC intrinsic. */
8098 static void
8099 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
8101 tree tmp;
8102 tree fndecl;
8103 tree type;
8105 /* Call the library function. This always returns an INTEGER(4). */
8106 fndecl = gfor_fndecl_iargc;
8107 tmp = build_call_expr_loc (input_location,
8108 fndecl, 0);
8110 /* Convert it to the required type. */
8111 type = gfc_typenode_for_spec (&expr->ts);
8112 tmp = fold_convert (type, tmp);
8114 se->expr = tmp;
8118 /* The loc intrinsic returns the address of its argument as
8119 gfc_index_integer_kind integer. */
8121 static void
8122 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8124 tree temp_var;
8125 gfc_expr *arg_expr;
8127 gcc_assert (!se->ss);
8129 arg_expr = expr->value.function.actual->expr;
8130 if (arg_expr->rank == 0)
8132 if (arg_expr->ts.type == BT_CLASS)
8133 gfc_add_data_component (arg_expr);
8134 gfc_conv_expr_reference (se, arg_expr);
8136 else
8137 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8138 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8140 /* Create a temporary variable for loc return value. Without this,
8141 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8142 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8143 gfc_add_modify (&se->pre, temp_var, se->expr);
8144 se->expr = temp_var;
8148 /* The following routine generates code for the intrinsic
8149 functions from the ISO_C_BINDING module:
8150 * C_LOC
8151 * C_FUNLOC
8152 * C_ASSOCIATED */
8154 static void
8155 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8157 gfc_actual_arglist *arg = expr->value.function.actual;
8159 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8161 if (arg->expr->rank == 0)
8162 gfc_conv_expr_reference (se, arg->expr);
8163 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8164 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8165 else
8167 gfc_conv_expr_descriptor (se, arg->expr);
8168 se->expr = gfc_conv_descriptor_data_get (se->expr);
8171 /* TODO -- the following two lines shouldn't be necessary, but if
8172 they're removed, a bug is exposed later in the code path.
8173 This workaround was thus introduced, but will have to be
8174 removed; please see PR 35150 for details about the issue. */
8175 se->expr = convert (pvoid_type_node, se->expr);
8176 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8178 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8179 gfc_conv_expr_reference (se, arg->expr);
8180 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8182 gfc_se arg1se;
8183 gfc_se arg2se;
8185 /* Build the addr_expr for the first argument. The argument is
8186 already an *address* so we don't need to set want_pointer in
8187 the gfc_se. */
8188 gfc_init_se (&arg1se, NULL);
8189 gfc_conv_expr (&arg1se, arg->expr);
8190 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8191 gfc_add_block_to_block (&se->post, &arg1se.post);
8193 /* See if we were given two arguments. */
8194 if (arg->next->expr == NULL)
8195 /* Only given one arg so generate a null and do a
8196 not-equal comparison against the first arg. */
8197 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8198 arg1se.expr,
8199 fold_convert (TREE_TYPE (arg1se.expr),
8200 null_pointer_node));
8201 else
8203 tree eq_expr;
8204 tree not_null_expr;
8206 /* Given two arguments so build the arg2se from second arg. */
8207 gfc_init_se (&arg2se, NULL);
8208 gfc_conv_expr (&arg2se, arg->next->expr);
8209 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8210 gfc_add_block_to_block (&se->post, &arg2se.post);
8212 /* Generate test to compare that the two args are equal. */
8213 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8214 arg1se.expr, arg2se.expr);
8215 /* Generate test to ensure that the first arg is not null. */
8216 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8217 logical_type_node,
8218 arg1se.expr, null_pointer_node);
8220 /* Finally, the generated test must check that both arg1 is not
8221 NULL and that it is equal to the second arg. */
8222 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8223 logical_type_node,
8224 not_null_expr, eq_expr);
8227 else
8228 gcc_unreachable ();
8232 /* The following routine generates code for the intrinsic
8233 subroutines from the ISO_C_BINDING module:
8234 * C_F_POINTER
8235 * C_F_PROCPOINTER. */
8237 static tree
8238 conv_isocbinding_subroutine (gfc_code *code)
8240 gfc_se se;
8241 gfc_se cptrse;
8242 gfc_se fptrse;
8243 gfc_se shapese;
8244 gfc_ss *shape_ss;
8245 tree desc, dim, tmp, stride, offset;
8246 stmtblock_t body, block;
8247 gfc_loopinfo loop;
8248 gfc_actual_arglist *arg = code->ext.actual;
8250 gfc_init_se (&se, NULL);
8251 gfc_init_se (&cptrse, NULL);
8252 gfc_conv_expr (&cptrse, arg->expr);
8253 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8254 gfc_add_block_to_block (&se.post, &cptrse.post);
8256 gfc_init_se (&fptrse, NULL);
8257 if (arg->next->expr->rank == 0)
8259 fptrse.want_pointer = 1;
8260 gfc_conv_expr (&fptrse, arg->next->expr);
8261 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8262 gfc_add_block_to_block (&se.post, &fptrse.post);
8263 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8264 && arg->next->expr->symtree->n.sym->attr.dummy)
8265 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8266 fptrse.expr);
8267 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8268 TREE_TYPE (fptrse.expr),
8269 fptrse.expr,
8270 fold_convert (TREE_TYPE (fptrse.expr),
8271 cptrse.expr));
8272 gfc_add_expr_to_block (&se.pre, se.expr);
8273 gfc_add_block_to_block (&se.pre, &se.post);
8274 return gfc_finish_block (&se.pre);
8277 gfc_start_block (&block);
8279 /* Get the descriptor of the Fortran pointer. */
8280 fptrse.descriptor_only = 1;
8281 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8282 gfc_add_block_to_block (&block, &fptrse.pre);
8283 desc = fptrse.expr;
8285 /* Set the span field. */
8286 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8287 tmp = fold_convert (gfc_array_index_type, tmp);
8288 gfc_conv_descriptor_span_set (&block, desc, tmp);
8290 /* Set data value, dtype, and offset. */
8291 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8292 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8293 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8294 gfc_get_dtype (TREE_TYPE (desc)));
8296 /* Start scalarization of the bounds, using the shape argument. */
8298 shape_ss = gfc_walk_expr (arg->next->next->expr);
8299 gcc_assert (shape_ss != gfc_ss_terminator);
8300 gfc_init_se (&shapese, NULL);
8302 gfc_init_loopinfo (&loop);
8303 gfc_add_ss_to_loop (&loop, shape_ss);
8304 gfc_conv_ss_startstride (&loop);
8305 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8306 gfc_mark_ss_chain_used (shape_ss, 1);
8308 gfc_copy_loopinfo_to_se (&shapese, &loop);
8309 shapese.ss = shape_ss;
8311 stride = gfc_create_var (gfc_array_index_type, "stride");
8312 offset = gfc_create_var (gfc_array_index_type, "offset");
8313 gfc_add_modify (&block, stride, gfc_index_one_node);
8314 gfc_add_modify (&block, offset, gfc_index_zero_node);
8316 /* Loop body. */
8317 gfc_start_scalarized_body (&loop, &body);
8319 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8320 loop.loopvar[0], loop.from[0]);
8322 /* Set bounds and stride. */
8323 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8324 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8326 gfc_conv_expr (&shapese, arg->next->next->expr);
8327 gfc_add_block_to_block (&body, &shapese.pre);
8328 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8329 gfc_add_block_to_block (&body, &shapese.post);
8331 /* Calculate offset. */
8332 gfc_add_modify (&body, offset,
8333 fold_build2_loc (input_location, PLUS_EXPR,
8334 gfc_array_index_type, offset, stride));
8335 /* Update stride. */
8336 gfc_add_modify (&body, stride,
8337 fold_build2_loc (input_location, MULT_EXPR,
8338 gfc_array_index_type, stride,
8339 fold_convert (gfc_array_index_type,
8340 shapese.expr)));
8341 /* Finish scalarization loop. */
8342 gfc_trans_scalarizing_loops (&loop, &body);
8343 gfc_add_block_to_block (&block, &loop.pre);
8344 gfc_add_block_to_block (&block, &loop.post);
8345 gfc_add_block_to_block (&block, &fptrse.post);
8346 gfc_cleanup_loop (&loop);
8348 gfc_add_modify (&block, offset,
8349 fold_build1_loc (input_location, NEGATE_EXPR,
8350 gfc_array_index_type, offset));
8351 gfc_conv_descriptor_offset_set (&block, desc, offset);
8353 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8354 gfc_add_block_to_block (&se.pre, &se.post);
8355 return gfc_finish_block (&se.pre);
8359 /* Save and restore floating-point state. */
8361 tree
8362 gfc_save_fp_state (stmtblock_t *block)
8364 tree type, fpstate, tmp;
8366 type = build_array_type (char_type_node,
8367 build_range_type (size_type_node, size_zero_node,
8368 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8369 fpstate = gfc_create_var (type, "fpstate");
8370 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8372 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8373 1, fpstate);
8374 gfc_add_expr_to_block (block, tmp);
8376 return fpstate;
8380 void
8381 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8383 tree tmp;
8385 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8386 1, fpstate);
8387 gfc_add_expr_to_block (block, tmp);
8391 /* Generate code for arguments of IEEE functions. */
8393 static void
8394 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8395 int nargs)
8397 gfc_actual_arglist *actual;
8398 gfc_expr *e;
8399 gfc_se argse;
8400 int arg;
8402 actual = expr->value.function.actual;
8403 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8405 gcc_assert (actual);
8406 e = actual->expr;
8408 gfc_init_se (&argse, se);
8409 gfc_conv_expr_val (&argse, e);
8411 gfc_add_block_to_block (&se->pre, &argse.pre);
8412 gfc_add_block_to_block (&se->post, &argse.post);
8413 argarray[arg] = argse.expr;
8418 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8419 and IEEE_UNORDERED, which translate directly to GCC type-generic
8420 built-ins. */
8422 static void
8423 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8424 enum built_in_function code, int nargs)
8426 tree args[2];
8427 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8429 conv_ieee_function_args (se, expr, args, nargs);
8430 se->expr = build_call_expr_loc_array (input_location,
8431 builtin_decl_explicit (code),
8432 nargs, args);
8433 STRIP_TYPE_NOPS (se->expr);
8434 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8438 /* Generate code for IEEE_IS_NORMAL intrinsic:
8439 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8441 static void
8442 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8444 tree arg, isnormal, iszero;
8446 /* Convert arg, evaluate it only once. */
8447 conv_ieee_function_args (se, expr, &arg, 1);
8448 arg = gfc_evaluate_now (arg, &se->pre);
8450 isnormal = build_call_expr_loc (input_location,
8451 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8452 1, arg);
8453 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8454 build_real_from_int_cst (TREE_TYPE (arg),
8455 integer_zero_node));
8456 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8457 logical_type_node, isnormal, iszero);
8458 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8462 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8463 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8465 static void
8466 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8468 tree arg, signbit, isnan;
8470 /* Convert arg, evaluate it only once. */
8471 conv_ieee_function_args (se, expr, &arg, 1);
8472 arg = gfc_evaluate_now (arg, &se->pre);
8474 isnan = build_call_expr_loc (input_location,
8475 builtin_decl_explicit (BUILT_IN_ISNAN),
8476 1, arg);
8477 STRIP_TYPE_NOPS (isnan);
8479 signbit = build_call_expr_loc (input_location,
8480 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8481 1, arg);
8482 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8483 signbit, integer_zero_node);
8485 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8486 logical_type_node, signbit,
8487 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8488 TREE_TYPE(isnan), isnan));
8490 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8494 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8496 static void
8497 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8498 enum built_in_function code)
8500 tree arg, decl, call, fpstate;
8501 int argprec;
8503 conv_ieee_function_args (se, expr, &arg, 1);
8504 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8505 decl = builtin_decl_for_precision (code, argprec);
8507 /* Save floating-point state. */
8508 fpstate = gfc_save_fp_state (&se->pre);
8510 /* Make the function call. */
8511 call = build_call_expr_loc (input_location, decl, 1, arg);
8512 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8514 /* Restore floating-point state. */
8515 gfc_restore_fp_state (&se->post, fpstate);
8519 /* Generate code for IEEE_REM. */
8521 static void
8522 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8524 tree args[2], decl, call, fpstate;
8525 int argprec;
8527 conv_ieee_function_args (se, expr, args, 2);
8529 /* If arguments have unequal size, convert them to the larger. */
8530 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8531 > TYPE_PRECISION (TREE_TYPE (args[1])))
8532 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8533 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8534 > TYPE_PRECISION (TREE_TYPE (args[0])))
8535 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8537 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8538 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8540 /* Save floating-point state. */
8541 fpstate = gfc_save_fp_state (&se->pre);
8543 /* Make the function call. */
8544 call = build_call_expr_loc_array (input_location, decl, 2, args);
8545 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8547 /* Restore floating-point state. */
8548 gfc_restore_fp_state (&se->post, fpstate);
8552 /* Generate code for IEEE_NEXT_AFTER. */
8554 static void
8555 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8557 tree args[2], decl, call, fpstate;
8558 int argprec;
8560 conv_ieee_function_args (se, expr, args, 2);
8562 /* Result has the characteristics of first argument. */
8563 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8564 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8565 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8567 /* Save floating-point state. */
8568 fpstate = gfc_save_fp_state (&se->pre);
8570 /* Make the function call. */
8571 call = build_call_expr_loc_array (input_location, decl, 2, args);
8572 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8574 /* Restore floating-point state. */
8575 gfc_restore_fp_state (&se->post, fpstate);
8579 /* Generate code for IEEE_SCALB. */
8581 static void
8582 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8584 tree args[2], decl, call, huge, type;
8585 int argprec, n;
8587 conv_ieee_function_args (se, expr, args, 2);
8589 /* Result has the characteristics of first argument. */
8590 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8591 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8593 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8595 /* We need to fold the integer into the range of a C int. */
8596 args[1] = gfc_evaluate_now (args[1], &se->pre);
8597 type = TREE_TYPE (args[1]);
8599 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8600 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8601 gfc_c_int_kind);
8602 huge = fold_convert (type, huge);
8603 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8604 huge);
8605 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8606 fold_build1_loc (input_location, NEGATE_EXPR,
8607 type, huge));
8610 args[1] = fold_convert (integer_type_node, args[1]);
8612 /* Make the function call. */
8613 call = build_call_expr_loc_array (input_location, decl, 2, args);
8614 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8618 /* Generate code for IEEE_COPY_SIGN. */
8620 static void
8621 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8623 tree args[2], decl, sign;
8624 int argprec;
8626 conv_ieee_function_args (se, expr, args, 2);
8628 /* Get the sign of the second argument. */
8629 sign = build_call_expr_loc (input_location,
8630 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8631 1, args[1]);
8632 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8633 sign, integer_zero_node);
8635 /* Create a value of one, with the right sign. */
8636 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8637 sign,
8638 fold_build1_loc (input_location, NEGATE_EXPR,
8639 integer_type_node,
8640 integer_one_node),
8641 integer_one_node);
8642 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8644 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8645 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8647 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8651 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8652 module. */
8654 bool
8655 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8657 const char *name = expr->value.function.name;
8659 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8661 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8662 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8663 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8664 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8665 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8666 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8667 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8668 conv_intrinsic_ieee_is_normal (se, expr);
8669 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8670 conv_intrinsic_ieee_is_negative (se, expr);
8671 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8672 conv_intrinsic_ieee_copy_sign (se, expr);
8673 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8674 conv_intrinsic_ieee_scalb (se, expr);
8675 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8676 conv_intrinsic_ieee_next_after (se, expr);
8677 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8678 conv_intrinsic_ieee_rem (se, expr);
8679 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8680 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8681 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8682 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8683 else
8684 /* It is not among the functions we translate directly. We return
8685 false, so a library function call is emitted. */
8686 return false;
8688 #undef STARTS_WITH
8690 return true;
8694 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8696 static void
8697 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8699 tree arg, res, restype;
8701 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8702 arg = fold_convert (size_type_node, arg);
8703 res = build_call_expr_loc (input_location,
8704 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8705 restype = gfc_typenode_for_spec (&expr->ts);
8706 se->expr = fold_convert (restype, res);
8710 /* Generate code for an intrinsic function. Some map directly to library
8711 calls, others get special handling. In some cases the name of the function
8712 used depends on the type specifiers. */
8714 void
8715 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8717 const char *name;
8718 int lib, kind;
8719 tree fndecl;
8721 name = &expr->value.function.name[2];
8723 if (expr->rank > 0)
8725 lib = gfc_is_intrinsic_libcall (expr);
8726 if (lib != 0)
8728 if (lib == 1)
8729 se->ignore_optional = 1;
8731 switch (expr->value.function.isym->id)
8733 case GFC_ISYM_EOSHIFT:
8734 case GFC_ISYM_PACK:
8735 case GFC_ISYM_RESHAPE:
8736 /* For all of those the first argument specifies the type and the
8737 third is optional. */
8738 conv_generic_with_optional_char_arg (se, expr, 1, 3);
8739 break;
8741 case GFC_ISYM_MINLOC:
8742 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
8743 break;
8745 case GFC_ISYM_MAXLOC:
8746 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
8747 break;
8749 case GFC_ISYM_SHAPE:
8750 gfc_conv_intrinsic_shape (se, expr);
8751 break;
8753 default:
8754 gfc_conv_intrinsic_funcall (se, expr);
8755 break;
8758 return;
8762 switch (expr->value.function.isym->id)
8764 case GFC_ISYM_NONE:
8765 gcc_unreachable ();
8767 case GFC_ISYM_REPEAT:
8768 gfc_conv_intrinsic_repeat (se, expr);
8769 break;
8771 case GFC_ISYM_TRIM:
8772 gfc_conv_intrinsic_trim (se, expr);
8773 break;
8775 case GFC_ISYM_SC_KIND:
8776 gfc_conv_intrinsic_sc_kind (se, expr);
8777 break;
8779 case GFC_ISYM_SI_KIND:
8780 gfc_conv_intrinsic_si_kind (se, expr);
8781 break;
8783 case GFC_ISYM_SR_KIND:
8784 gfc_conv_intrinsic_sr_kind (se, expr);
8785 break;
8787 case GFC_ISYM_EXPONENT:
8788 gfc_conv_intrinsic_exponent (se, expr);
8789 break;
8791 case GFC_ISYM_SCAN:
8792 kind = expr->value.function.actual->expr->ts.kind;
8793 if (kind == 1)
8794 fndecl = gfor_fndecl_string_scan;
8795 else if (kind == 4)
8796 fndecl = gfor_fndecl_string_scan_char4;
8797 else
8798 gcc_unreachable ();
8800 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8801 break;
8803 case GFC_ISYM_VERIFY:
8804 kind = expr->value.function.actual->expr->ts.kind;
8805 if (kind == 1)
8806 fndecl = gfor_fndecl_string_verify;
8807 else if (kind == 4)
8808 fndecl = gfor_fndecl_string_verify_char4;
8809 else
8810 gcc_unreachable ();
8812 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8813 break;
8815 case GFC_ISYM_ALLOCATED:
8816 gfc_conv_allocated (se, expr);
8817 break;
8819 case GFC_ISYM_ASSOCIATED:
8820 gfc_conv_associated(se, expr);
8821 break;
8823 case GFC_ISYM_SAME_TYPE_AS:
8824 gfc_conv_same_type_as (se, expr);
8825 break;
8827 case GFC_ISYM_ABS:
8828 gfc_conv_intrinsic_abs (se, expr);
8829 break;
8831 case GFC_ISYM_ADJUSTL:
8832 if (expr->ts.kind == 1)
8833 fndecl = gfor_fndecl_adjustl;
8834 else if (expr->ts.kind == 4)
8835 fndecl = gfor_fndecl_adjustl_char4;
8836 else
8837 gcc_unreachable ();
8839 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8840 break;
8842 case GFC_ISYM_ADJUSTR:
8843 if (expr->ts.kind == 1)
8844 fndecl = gfor_fndecl_adjustr;
8845 else if (expr->ts.kind == 4)
8846 fndecl = gfor_fndecl_adjustr_char4;
8847 else
8848 gcc_unreachable ();
8850 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8851 break;
8853 case GFC_ISYM_AIMAG:
8854 gfc_conv_intrinsic_imagpart (se, expr);
8855 break;
8857 case GFC_ISYM_AINT:
8858 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
8859 break;
8861 case GFC_ISYM_ALL:
8862 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
8863 break;
8865 case GFC_ISYM_ANINT:
8866 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
8867 break;
8869 case GFC_ISYM_AND:
8870 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8871 break;
8873 case GFC_ISYM_ANY:
8874 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
8875 break;
8877 case GFC_ISYM_BTEST:
8878 gfc_conv_intrinsic_btest (se, expr);
8879 break;
8881 case GFC_ISYM_BGE:
8882 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
8883 break;
8885 case GFC_ISYM_BGT:
8886 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
8887 break;
8889 case GFC_ISYM_BLE:
8890 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
8891 break;
8893 case GFC_ISYM_BLT:
8894 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
8895 break;
8897 case GFC_ISYM_C_ASSOCIATED:
8898 case GFC_ISYM_C_FUNLOC:
8899 case GFC_ISYM_C_LOC:
8900 conv_isocbinding_function (se, expr);
8901 break;
8903 case GFC_ISYM_ACHAR:
8904 case GFC_ISYM_CHAR:
8905 gfc_conv_intrinsic_char (se, expr);
8906 break;
8908 case GFC_ISYM_CONVERSION:
8909 case GFC_ISYM_REAL:
8910 case GFC_ISYM_LOGICAL:
8911 case GFC_ISYM_DBLE:
8912 gfc_conv_intrinsic_conversion (se, expr);
8913 break;
8915 /* Integer conversions are handled separately to make sure we get the
8916 correct rounding mode. */
8917 case GFC_ISYM_INT:
8918 case GFC_ISYM_INT2:
8919 case GFC_ISYM_INT8:
8920 case GFC_ISYM_LONG:
8921 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
8922 break;
8924 case GFC_ISYM_NINT:
8925 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
8926 break;
8928 case GFC_ISYM_CEILING:
8929 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
8930 break;
8932 case GFC_ISYM_FLOOR:
8933 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
8934 break;
8936 case GFC_ISYM_MOD:
8937 gfc_conv_intrinsic_mod (se, expr, 0);
8938 break;
8940 case GFC_ISYM_MODULO:
8941 gfc_conv_intrinsic_mod (se, expr, 1);
8942 break;
8944 case GFC_ISYM_CAF_GET:
8945 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
8946 false, NULL);
8947 break;
8949 case GFC_ISYM_CMPLX:
8950 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
8951 break;
8953 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
8954 gfc_conv_intrinsic_iargc (se, expr);
8955 break;
8957 case GFC_ISYM_COMPLEX:
8958 gfc_conv_intrinsic_cmplx (se, expr, 1);
8959 break;
8961 case GFC_ISYM_CONJG:
8962 gfc_conv_intrinsic_conjg (se, expr);
8963 break;
8965 case GFC_ISYM_COUNT:
8966 gfc_conv_intrinsic_count (se, expr);
8967 break;
8969 case GFC_ISYM_CTIME:
8970 gfc_conv_intrinsic_ctime (se, expr);
8971 break;
8973 case GFC_ISYM_DIM:
8974 gfc_conv_intrinsic_dim (se, expr);
8975 break;
8977 case GFC_ISYM_DOT_PRODUCT:
8978 gfc_conv_intrinsic_dot_product (se, expr);
8979 break;
8981 case GFC_ISYM_DPROD:
8982 gfc_conv_intrinsic_dprod (se, expr);
8983 break;
8985 case GFC_ISYM_DSHIFTL:
8986 gfc_conv_intrinsic_dshift (se, expr, true);
8987 break;
8989 case GFC_ISYM_DSHIFTR:
8990 gfc_conv_intrinsic_dshift (se, expr, false);
8991 break;
8993 case GFC_ISYM_FDATE:
8994 gfc_conv_intrinsic_fdate (se, expr);
8995 break;
8997 case GFC_ISYM_FRACTION:
8998 gfc_conv_intrinsic_fraction (se, expr);
8999 break;
9001 case GFC_ISYM_IALL:
9002 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9003 break;
9005 case GFC_ISYM_IAND:
9006 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9007 break;
9009 case GFC_ISYM_IANY:
9010 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9011 break;
9013 case GFC_ISYM_IBCLR:
9014 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9015 break;
9017 case GFC_ISYM_IBITS:
9018 gfc_conv_intrinsic_ibits (se, expr);
9019 break;
9021 case GFC_ISYM_IBSET:
9022 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9023 break;
9025 case GFC_ISYM_IACHAR:
9026 case GFC_ISYM_ICHAR:
9027 /* We assume ASCII character sequence. */
9028 gfc_conv_intrinsic_ichar (se, expr);
9029 break;
9031 case GFC_ISYM_IARGC:
9032 gfc_conv_intrinsic_iargc (se, expr);
9033 break;
9035 case GFC_ISYM_IEOR:
9036 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9037 break;
9039 case GFC_ISYM_INDEX:
9040 kind = expr->value.function.actual->expr->ts.kind;
9041 if (kind == 1)
9042 fndecl = gfor_fndecl_string_index;
9043 else if (kind == 4)
9044 fndecl = gfor_fndecl_string_index_char4;
9045 else
9046 gcc_unreachable ();
9048 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9049 break;
9051 case GFC_ISYM_IOR:
9052 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9053 break;
9055 case GFC_ISYM_IPARITY:
9056 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9057 break;
9059 case GFC_ISYM_IS_IOSTAT_END:
9060 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9061 break;
9063 case GFC_ISYM_IS_IOSTAT_EOR:
9064 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9065 break;
9067 case GFC_ISYM_ISNAN:
9068 gfc_conv_intrinsic_isnan (se, expr);
9069 break;
9071 case GFC_ISYM_LSHIFT:
9072 gfc_conv_intrinsic_shift (se, expr, false, false);
9073 break;
9075 case GFC_ISYM_RSHIFT:
9076 gfc_conv_intrinsic_shift (se, expr, true, true);
9077 break;
9079 case GFC_ISYM_SHIFTA:
9080 gfc_conv_intrinsic_shift (se, expr, true, true);
9081 break;
9083 case GFC_ISYM_SHIFTL:
9084 gfc_conv_intrinsic_shift (se, expr, false, false);
9085 break;
9087 case GFC_ISYM_SHIFTR:
9088 gfc_conv_intrinsic_shift (se, expr, true, false);
9089 break;
9091 case GFC_ISYM_ISHFT:
9092 gfc_conv_intrinsic_ishft (se, expr);
9093 break;
9095 case GFC_ISYM_ISHFTC:
9096 gfc_conv_intrinsic_ishftc (se, expr);
9097 break;
9099 case GFC_ISYM_LEADZ:
9100 gfc_conv_intrinsic_leadz (se, expr);
9101 break;
9103 case GFC_ISYM_TRAILZ:
9104 gfc_conv_intrinsic_trailz (se, expr);
9105 break;
9107 case GFC_ISYM_POPCNT:
9108 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9109 break;
9111 case GFC_ISYM_POPPAR:
9112 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9113 break;
9115 case GFC_ISYM_LBOUND:
9116 gfc_conv_intrinsic_bound (se, expr, 0);
9117 break;
9119 case GFC_ISYM_LCOBOUND:
9120 conv_intrinsic_cobound (se, expr);
9121 break;
9123 case GFC_ISYM_TRANSPOSE:
9124 /* The scalarizer has already been set up for reversed dimension access
9125 order ; now we just get the argument value normally. */
9126 gfc_conv_expr (se, expr->value.function.actual->expr);
9127 break;
9129 case GFC_ISYM_LEN:
9130 gfc_conv_intrinsic_len (se, expr);
9131 break;
9133 case GFC_ISYM_LEN_TRIM:
9134 gfc_conv_intrinsic_len_trim (se, expr);
9135 break;
9137 case GFC_ISYM_LGE:
9138 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9139 break;
9141 case GFC_ISYM_LGT:
9142 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9143 break;
9145 case GFC_ISYM_LLE:
9146 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9147 break;
9149 case GFC_ISYM_LLT:
9150 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9151 break;
9153 case GFC_ISYM_MALLOC:
9154 gfc_conv_intrinsic_malloc (se, expr);
9155 break;
9157 case GFC_ISYM_MASKL:
9158 gfc_conv_intrinsic_mask (se, expr, 1);
9159 break;
9161 case GFC_ISYM_MASKR:
9162 gfc_conv_intrinsic_mask (se, expr, 0);
9163 break;
9165 case GFC_ISYM_MAX:
9166 if (expr->ts.type == BT_CHARACTER)
9167 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9168 else
9169 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9170 break;
9172 case GFC_ISYM_MAXLOC:
9173 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9174 break;
9176 case GFC_ISYM_MAXVAL:
9177 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9178 break;
9180 case GFC_ISYM_MERGE:
9181 gfc_conv_intrinsic_merge (se, expr);
9182 break;
9184 case GFC_ISYM_MERGE_BITS:
9185 gfc_conv_intrinsic_merge_bits (se, expr);
9186 break;
9188 case GFC_ISYM_MIN:
9189 if (expr->ts.type == BT_CHARACTER)
9190 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9191 else
9192 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9193 break;
9195 case GFC_ISYM_MINLOC:
9196 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9197 break;
9199 case GFC_ISYM_MINVAL:
9200 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9201 break;
9203 case GFC_ISYM_NEAREST:
9204 gfc_conv_intrinsic_nearest (se, expr);
9205 break;
9207 case GFC_ISYM_NORM2:
9208 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9209 break;
9211 case GFC_ISYM_NOT:
9212 gfc_conv_intrinsic_not (se, expr);
9213 break;
9215 case GFC_ISYM_OR:
9216 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9217 break;
9219 case GFC_ISYM_PARITY:
9220 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9221 break;
9223 case GFC_ISYM_PRESENT:
9224 gfc_conv_intrinsic_present (se, expr);
9225 break;
9227 case GFC_ISYM_PRODUCT:
9228 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9229 break;
9231 case GFC_ISYM_RANK:
9232 gfc_conv_intrinsic_rank (se, expr);
9233 break;
9235 case GFC_ISYM_RRSPACING:
9236 gfc_conv_intrinsic_rrspacing (se, expr);
9237 break;
9239 case GFC_ISYM_SET_EXPONENT:
9240 gfc_conv_intrinsic_set_exponent (se, expr);
9241 break;
9243 case GFC_ISYM_SCALE:
9244 gfc_conv_intrinsic_scale (se, expr);
9245 break;
9247 case GFC_ISYM_SIGN:
9248 gfc_conv_intrinsic_sign (se, expr);
9249 break;
9251 case GFC_ISYM_SIZE:
9252 gfc_conv_intrinsic_size (se, expr);
9253 break;
9255 case GFC_ISYM_SIZEOF:
9256 case GFC_ISYM_C_SIZEOF:
9257 gfc_conv_intrinsic_sizeof (se, expr);
9258 break;
9260 case GFC_ISYM_STORAGE_SIZE:
9261 gfc_conv_intrinsic_storage_size (se, expr);
9262 break;
9264 case GFC_ISYM_SPACING:
9265 gfc_conv_intrinsic_spacing (se, expr);
9266 break;
9268 case GFC_ISYM_STRIDE:
9269 conv_intrinsic_stride (se, expr);
9270 break;
9272 case GFC_ISYM_SUM:
9273 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9274 break;
9276 case GFC_ISYM_TEAM_NUMBER:
9277 conv_intrinsic_team_number (se, expr);
9278 break;
9280 case GFC_ISYM_TRANSFER:
9281 if (se->ss && se->ss->info->useflags)
9282 /* Access the previously obtained result. */
9283 gfc_conv_tmp_array_ref (se);
9284 else
9285 gfc_conv_intrinsic_transfer (se, expr);
9286 break;
9288 case GFC_ISYM_TTYNAM:
9289 gfc_conv_intrinsic_ttynam (se, expr);
9290 break;
9292 case GFC_ISYM_UBOUND:
9293 gfc_conv_intrinsic_bound (se, expr, 1);
9294 break;
9296 case GFC_ISYM_UCOBOUND:
9297 conv_intrinsic_cobound (se, expr);
9298 break;
9300 case GFC_ISYM_XOR:
9301 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9302 break;
9304 case GFC_ISYM_LOC:
9305 gfc_conv_intrinsic_loc (se, expr);
9306 break;
9308 case GFC_ISYM_THIS_IMAGE:
9309 /* For num_images() == 1, handle as LCOBOUND. */
9310 if (expr->value.function.actual->expr
9311 && flag_coarray == GFC_FCOARRAY_SINGLE)
9312 conv_intrinsic_cobound (se, expr);
9313 else
9314 trans_this_image (se, expr);
9315 break;
9317 case GFC_ISYM_IMAGE_INDEX:
9318 trans_image_index (se, expr);
9319 break;
9321 case GFC_ISYM_IMAGE_STATUS:
9322 conv_intrinsic_image_status (se, expr);
9323 break;
9325 case GFC_ISYM_NUM_IMAGES:
9326 trans_num_images (se, expr);
9327 break;
9329 case GFC_ISYM_ACCESS:
9330 case GFC_ISYM_CHDIR:
9331 case GFC_ISYM_CHMOD:
9332 case GFC_ISYM_DTIME:
9333 case GFC_ISYM_ETIME:
9334 case GFC_ISYM_EXTENDS_TYPE_OF:
9335 case GFC_ISYM_FGET:
9336 case GFC_ISYM_FGETC:
9337 case GFC_ISYM_FNUM:
9338 case GFC_ISYM_FPUT:
9339 case GFC_ISYM_FPUTC:
9340 case GFC_ISYM_FSTAT:
9341 case GFC_ISYM_FTELL:
9342 case GFC_ISYM_GETCWD:
9343 case GFC_ISYM_GETGID:
9344 case GFC_ISYM_GETPID:
9345 case GFC_ISYM_GETUID:
9346 case GFC_ISYM_HOSTNM:
9347 case GFC_ISYM_KILL:
9348 case GFC_ISYM_IERRNO:
9349 case GFC_ISYM_IRAND:
9350 case GFC_ISYM_ISATTY:
9351 case GFC_ISYM_JN2:
9352 case GFC_ISYM_LINK:
9353 case GFC_ISYM_LSTAT:
9354 case GFC_ISYM_MATMUL:
9355 case GFC_ISYM_MCLOCK:
9356 case GFC_ISYM_MCLOCK8:
9357 case GFC_ISYM_RAND:
9358 case GFC_ISYM_RENAME:
9359 case GFC_ISYM_SECOND:
9360 case GFC_ISYM_SECNDS:
9361 case GFC_ISYM_SIGNAL:
9362 case GFC_ISYM_STAT:
9363 case GFC_ISYM_SYMLNK:
9364 case GFC_ISYM_SYSTEM:
9365 case GFC_ISYM_TIME:
9366 case GFC_ISYM_TIME8:
9367 case GFC_ISYM_UMASK:
9368 case GFC_ISYM_UNLINK:
9369 case GFC_ISYM_YN2:
9370 gfc_conv_intrinsic_funcall (se, expr);
9371 break;
9373 case GFC_ISYM_EOSHIFT:
9374 case GFC_ISYM_PACK:
9375 case GFC_ISYM_RESHAPE:
9376 /* For those, expr->rank should always be >0 and thus the if above the
9377 switch should have matched. */
9378 gcc_unreachable ();
9379 break;
9381 default:
9382 gfc_conv_intrinsic_lib_function (se, expr);
9383 break;
9388 static gfc_ss *
9389 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9391 gfc_ss *arg_ss, *tmp_ss;
9392 gfc_actual_arglist *arg;
9394 arg = expr->value.function.actual;
9396 gcc_assert (arg->expr);
9398 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9399 gcc_assert (arg_ss != gfc_ss_terminator);
9401 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9403 if (tmp_ss->info->type != GFC_SS_SCALAR
9404 && tmp_ss->info->type != GFC_SS_REFERENCE)
9406 gcc_assert (tmp_ss->dimen == 2);
9408 /* We just invert dimensions. */
9409 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9412 /* Stop when tmp_ss points to the last valid element of the chain... */
9413 if (tmp_ss->next == gfc_ss_terminator)
9414 break;
9417 /* ... so that we can attach the rest of the chain to it. */
9418 tmp_ss->next = ss;
9420 return arg_ss;
9424 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9425 This has the side effect of reversing the nested list, so there is no
9426 need to call gfc_reverse_ss on it (the given list is assumed not to be
9427 reversed yet). */
9429 static gfc_ss *
9430 nest_loop_dimension (gfc_ss *ss, int dim)
9432 int ss_dim, i;
9433 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9434 gfc_loopinfo *new_loop;
9436 gcc_assert (ss != gfc_ss_terminator);
9438 for (; ss != gfc_ss_terminator; ss = ss->next)
9440 new_ss = gfc_get_ss ();
9441 new_ss->next = prev_ss;
9442 new_ss->parent = ss;
9443 new_ss->info = ss->info;
9444 new_ss->info->refcount++;
9445 if (ss->dimen != 0)
9447 gcc_assert (ss->info->type != GFC_SS_SCALAR
9448 && ss->info->type != GFC_SS_REFERENCE);
9450 new_ss->dimen = 1;
9451 new_ss->dim[0] = ss->dim[dim];
9453 gcc_assert (dim < ss->dimen);
9455 ss_dim = --ss->dimen;
9456 for (i = dim; i < ss_dim; i++)
9457 ss->dim[i] = ss->dim[i + 1];
9459 ss->dim[ss_dim] = 0;
9461 prev_ss = new_ss;
9463 if (ss->nested_ss)
9465 ss->nested_ss->parent = new_ss;
9466 new_ss->nested_ss = ss->nested_ss;
9468 ss->nested_ss = new_ss;
9471 new_loop = gfc_get_loopinfo ();
9472 gfc_init_loopinfo (new_loop);
9474 gcc_assert (prev_ss != NULL);
9475 gcc_assert (prev_ss != gfc_ss_terminator);
9476 gfc_add_ss_to_loop (new_loop, prev_ss);
9477 return new_ss->parent;
9481 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9482 is to be inlined. */
9484 static gfc_ss *
9485 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9487 gfc_ss *tmp_ss, *tail, *array_ss;
9488 gfc_actual_arglist *arg1, *arg2, *arg3;
9489 int sum_dim;
9490 bool scalar_mask = false;
9492 /* The rank of the result will be determined later. */
9493 arg1 = expr->value.function.actual;
9494 arg2 = arg1->next;
9495 arg3 = arg2->next;
9496 gcc_assert (arg3 != NULL);
9498 if (expr->rank == 0)
9499 return ss;
9501 tmp_ss = gfc_ss_terminator;
9503 if (arg3->expr)
9505 gfc_ss *mask_ss;
9507 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9508 if (mask_ss == tmp_ss)
9509 scalar_mask = 1;
9511 tmp_ss = mask_ss;
9514 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9515 gcc_assert (array_ss != tmp_ss);
9517 /* Odd thing: If the mask is scalar, it is used by the frontend after
9518 the array (to make an if around the nested loop). Thus it shall
9519 be after array_ss once the gfc_ss list is reversed. */
9520 if (scalar_mask)
9521 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9522 else
9523 tmp_ss = array_ss;
9525 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9526 chain. */
9527 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9528 tail = nest_loop_dimension (tmp_ss, sum_dim);
9529 tail->next = ss;
9531 return tmp_ss;
9535 static gfc_ss *
9536 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9539 switch (expr->value.function.isym->id)
9541 case GFC_ISYM_PRODUCT:
9542 case GFC_ISYM_SUM:
9543 return walk_inline_intrinsic_arith (ss, expr);
9545 case GFC_ISYM_TRANSPOSE:
9546 return walk_inline_intrinsic_transpose (ss, expr);
9548 default:
9549 gcc_unreachable ();
9551 gcc_unreachable ();
9555 /* This generates code to execute before entering the scalarization loop.
9556 Currently does nothing. */
9558 void
9559 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9561 switch (ss->info->expr->value.function.isym->id)
9563 case GFC_ISYM_UBOUND:
9564 case GFC_ISYM_LBOUND:
9565 case GFC_ISYM_UCOBOUND:
9566 case GFC_ISYM_LCOBOUND:
9567 case GFC_ISYM_THIS_IMAGE:
9568 break;
9570 default:
9571 gcc_unreachable ();
9576 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9577 are expanded into code inside the scalarization loop. */
9579 static gfc_ss *
9580 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9582 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9583 gfc_add_class_array_ref (expr->value.function.actual->expr);
9585 /* The two argument version returns a scalar. */
9586 if (expr->value.function.actual->next->expr)
9587 return ss;
9589 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9593 /* Walk an intrinsic array libcall. */
9595 static gfc_ss *
9596 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9598 gcc_assert (expr->rank > 0);
9599 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9603 /* Return whether the function call expression EXPR will be expanded
9604 inline by gfc_conv_intrinsic_function. */
9606 bool
9607 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9609 gfc_actual_arglist *args;
9611 if (!expr->value.function.isym)
9612 return false;
9614 switch (expr->value.function.isym->id)
9616 case GFC_ISYM_PRODUCT:
9617 case GFC_ISYM_SUM:
9618 /* Disable inline expansion if code size matters. */
9619 if (optimize_size)
9620 return false;
9622 args = expr->value.function.actual;
9623 /* We need to be able to subset the SUM argument at compile-time. */
9624 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9625 return false;
9627 return true;
9629 case GFC_ISYM_TRANSPOSE:
9630 return true;
9632 default:
9633 return false;
9638 /* Returns nonzero if the specified intrinsic function call maps directly to
9639 an external library call. Should only be used for functions that return
9640 arrays. */
9643 gfc_is_intrinsic_libcall (gfc_expr * expr)
9645 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9646 gcc_assert (expr->rank > 0);
9648 if (gfc_inline_intrinsic_function_p (expr))
9649 return 0;
9651 switch (expr->value.function.isym->id)
9653 case GFC_ISYM_ALL:
9654 case GFC_ISYM_ANY:
9655 case GFC_ISYM_COUNT:
9656 case GFC_ISYM_JN2:
9657 case GFC_ISYM_IANY:
9658 case GFC_ISYM_IALL:
9659 case GFC_ISYM_IPARITY:
9660 case GFC_ISYM_MATMUL:
9661 case GFC_ISYM_MAXLOC:
9662 case GFC_ISYM_MAXVAL:
9663 case GFC_ISYM_MINLOC:
9664 case GFC_ISYM_MINVAL:
9665 case GFC_ISYM_NORM2:
9666 case GFC_ISYM_PARITY:
9667 case GFC_ISYM_PRODUCT:
9668 case GFC_ISYM_SUM:
9669 case GFC_ISYM_SHAPE:
9670 case GFC_ISYM_SPREAD:
9671 case GFC_ISYM_YN2:
9672 /* Ignore absent optional parameters. */
9673 return 1;
9675 case GFC_ISYM_CSHIFT:
9676 case GFC_ISYM_EOSHIFT:
9677 case GFC_ISYM_GET_TEAM:
9678 case GFC_ISYM_FAILED_IMAGES:
9679 case GFC_ISYM_STOPPED_IMAGES:
9680 case GFC_ISYM_PACK:
9681 case GFC_ISYM_RESHAPE:
9682 case GFC_ISYM_UNPACK:
9683 /* Pass absent optional parameters. */
9684 return 2;
9686 default:
9687 return 0;
9691 /* Walk an intrinsic function. */
9692 gfc_ss *
9693 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9694 gfc_intrinsic_sym * isym)
9696 gcc_assert (isym);
9698 if (isym->elemental)
9699 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9700 NULL, GFC_SS_SCALAR);
9702 if (expr->rank == 0)
9703 return ss;
9705 if (gfc_inline_intrinsic_function_p (expr))
9706 return walk_inline_intrinsic_function (ss, expr);
9708 if (gfc_is_intrinsic_libcall (expr))
9709 return gfc_walk_intrinsic_libfunc (ss, expr);
9711 /* Special cases. */
9712 switch (isym->id)
9714 case GFC_ISYM_LBOUND:
9715 case GFC_ISYM_LCOBOUND:
9716 case GFC_ISYM_UBOUND:
9717 case GFC_ISYM_UCOBOUND:
9718 case GFC_ISYM_THIS_IMAGE:
9719 return gfc_walk_intrinsic_bound (ss, expr);
9721 case GFC_ISYM_TRANSFER:
9722 case GFC_ISYM_CAF_GET:
9723 return gfc_walk_intrinsic_libfunc (ss, expr);
9725 default:
9726 /* This probably meant someone forgot to add an intrinsic to the above
9727 list(s) when they implemented it, or something's gone horribly
9728 wrong. */
9729 gcc_unreachable ();
9734 static tree
9735 conv_co_collective (gfc_code *code)
9737 gfc_se argse;
9738 stmtblock_t block, post_block;
9739 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
9740 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
9742 gfc_start_block (&block);
9743 gfc_init_block (&post_block);
9745 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
9747 opr_expr = code->ext.actual->next->expr;
9748 image_idx_expr = code->ext.actual->next->next->expr;
9749 stat_expr = code->ext.actual->next->next->next->expr;
9750 errmsg_expr = code->ext.actual->next->next->next->next->expr;
9752 else
9754 opr_expr = NULL;
9755 image_idx_expr = code->ext.actual->next->expr;
9756 stat_expr = code->ext.actual->next->next->expr;
9757 errmsg_expr = code->ext.actual->next->next->next->expr;
9760 /* stat. */
9761 if (stat_expr)
9763 gfc_init_se (&argse, NULL);
9764 gfc_conv_expr (&argse, stat_expr);
9765 gfc_add_block_to_block (&block, &argse.pre);
9766 gfc_add_block_to_block (&post_block, &argse.post);
9767 stat = argse.expr;
9768 if (flag_coarray != GFC_FCOARRAY_SINGLE)
9769 stat = gfc_build_addr_expr (NULL_TREE, stat);
9771 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
9772 stat = NULL_TREE;
9773 else
9774 stat = null_pointer_node;
9776 /* Early exit for GFC_FCOARRAY_SINGLE. */
9777 if (flag_coarray == GFC_FCOARRAY_SINGLE)
9779 if (stat != NULL_TREE)
9780 gfc_add_modify (&block, stat,
9781 fold_convert (TREE_TYPE (stat), integer_zero_node));
9782 return gfc_finish_block (&block);
9785 /* Handle the array. */
9786 gfc_init_se (&argse, NULL);
9787 if (code->ext.actual->expr->rank == 0)
9789 symbol_attribute attr;
9790 gfc_clear_attr (&attr);
9791 gfc_init_se (&argse, NULL);
9792 gfc_conv_expr (&argse, code->ext.actual->expr);
9793 gfc_add_block_to_block (&block, &argse.pre);
9794 gfc_add_block_to_block (&post_block, &argse.post);
9795 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
9796 array = gfc_build_addr_expr (NULL_TREE, array);
9798 else
9800 argse.want_pointer = 1;
9801 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
9802 array = argse.expr;
9804 gfc_add_block_to_block (&block, &argse.pre);
9805 gfc_add_block_to_block (&post_block, &argse.post);
9807 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
9808 strlen = argse.string_length;
9809 else
9810 strlen = integer_zero_node;
9812 /* image_index. */
9813 if (image_idx_expr)
9815 gfc_init_se (&argse, NULL);
9816 gfc_conv_expr (&argse, image_idx_expr);
9817 gfc_add_block_to_block (&block, &argse.pre);
9818 gfc_add_block_to_block (&post_block, &argse.post);
9819 image_index = fold_convert (integer_type_node, argse.expr);
9821 else
9822 image_index = integer_zero_node;
9824 /* errmsg. */
9825 if (errmsg_expr)
9827 gfc_init_se (&argse, NULL);
9828 gfc_conv_expr (&argse, errmsg_expr);
9829 gfc_add_block_to_block (&block, &argse.pre);
9830 gfc_add_block_to_block (&post_block, &argse.post);
9831 errmsg = argse.expr;
9832 errmsg_len = fold_convert (size_type_node, argse.string_length);
9834 else
9836 errmsg = null_pointer_node;
9837 errmsg_len = build_zero_cst (size_type_node);
9840 /* Generate the function call. */
9841 switch (code->resolved_isym->id)
9843 case GFC_ISYM_CO_BROADCAST:
9844 fndecl = gfor_fndecl_co_broadcast;
9845 break;
9846 case GFC_ISYM_CO_MAX:
9847 fndecl = gfor_fndecl_co_max;
9848 break;
9849 case GFC_ISYM_CO_MIN:
9850 fndecl = gfor_fndecl_co_min;
9851 break;
9852 case GFC_ISYM_CO_REDUCE:
9853 fndecl = gfor_fndecl_co_reduce;
9854 break;
9855 case GFC_ISYM_CO_SUM:
9856 fndecl = gfor_fndecl_co_sum;
9857 break;
9858 default:
9859 gcc_unreachable ();
9862 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
9863 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
9864 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
9865 image_index, stat, errmsg, errmsg_len);
9866 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
9867 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
9868 stat, errmsg, strlen, errmsg_len);
9869 else
9871 tree opr, opr_flags;
9873 // FIXME: Handle TS29113's bind(C) strings with descriptor.
9874 int opr_flag_int;
9875 if (gfc_is_proc_ptr_comp (opr_expr))
9877 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
9878 opr_flag_int = sym->attr.dimension
9879 || (sym->ts.type == BT_CHARACTER
9880 && !sym->attr.is_bind_c)
9881 ? GFC_CAF_BYREF : 0;
9882 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9883 && !sym->attr.is_bind_c
9884 ? GFC_CAF_HIDDENLEN : 0;
9885 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
9887 else
9889 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
9890 ? GFC_CAF_BYREF : 0;
9891 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9892 && !opr_expr->symtree->n.sym->attr.is_bind_c
9893 ? GFC_CAF_HIDDENLEN : 0;
9894 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
9895 ? GFC_CAF_ARG_VALUE : 0;
9897 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
9898 gfc_conv_expr (&argse, opr_expr);
9899 opr = argse.expr;
9900 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
9901 image_index, stat, errmsg, strlen, errmsg_len);
9904 gfc_add_expr_to_block (&block, fndecl);
9905 gfc_add_block_to_block (&block, &post_block);
9907 return gfc_finish_block (&block);
9911 static tree
9912 conv_intrinsic_atomic_op (gfc_code *code)
9914 gfc_se argse;
9915 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
9916 stmtblock_t block, post_block;
9917 gfc_expr *atom_expr = code->ext.actual->expr;
9918 gfc_expr *stat_expr;
9919 built_in_function fn;
9921 if (atom_expr->expr_type == EXPR_FUNCTION
9922 && atom_expr->value.function.isym
9923 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9924 atom_expr = atom_expr->value.function.actual->expr;
9926 gfc_start_block (&block);
9927 gfc_init_block (&post_block);
9929 gfc_init_se (&argse, NULL);
9930 argse.want_pointer = 1;
9931 gfc_conv_expr (&argse, atom_expr);
9932 gfc_add_block_to_block (&block, &argse.pre);
9933 gfc_add_block_to_block (&post_block, &argse.post);
9934 atom = argse.expr;
9936 gfc_init_se (&argse, NULL);
9937 if (flag_coarray == GFC_FCOARRAY_LIB
9938 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
9939 argse.want_pointer = 1;
9940 gfc_conv_expr (&argse, code->ext.actual->next->expr);
9941 gfc_add_block_to_block (&block, &argse.pre);
9942 gfc_add_block_to_block (&post_block, &argse.post);
9943 value = argse.expr;
9945 switch (code->resolved_isym->id)
9947 case GFC_ISYM_ATOMIC_ADD:
9948 case GFC_ISYM_ATOMIC_AND:
9949 case GFC_ISYM_ATOMIC_DEF:
9950 case GFC_ISYM_ATOMIC_OR:
9951 case GFC_ISYM_ATOMIC_XOR:
9952 stat_expr = code->ext.actual->next->next->expr;
9953 if (flag_coarray == GFC_FCOARRAY_LIB)
9954 old = null_pointer_node;
9955 break;
9956 default:
9957 gfc_init_se (&argse, NULL);
9958 if (flag_coarray == GFC_FCOARRAY_LIB)
9959 argse.want_pointer = 1;
9960 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
9961 gfc_add_block_to_block (&block, &argse.pre);
9962 gfc_add_block_to_block (&post_block, &argse.post);
9963 old = argse.expr;
9964 stat_expr = code->ext.actual->next->next->next->expr;
9967 /* STAT= */
9968 if (stat_expr != NULL)
9970 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
9971 gfc_init_se (&argse, NULL);
9972 if (flag_coarray == GFC_FCOARRAY_LIB)
9973 argse.want_pointer = 1;
9974 gfc_conv_expr_val (&argse, stat_expr);
9975 gfc_add_block_to_block (&block, &argse.pre);
9976 gfc_add_block_to_block (&post_block, &argse.post);
9977 stat = argse.expr;
9979 else if (flag_coarray == GFC_FCOARRAY_LIB)
9980 stat = null_pointer_node;
9982 if (flag_coarray == GFC_FCOARRAY_LIB)
9984 tree image_index, caf_decl, offset, token;
9985 int op;
9987 switch (code->resolved_isym->id)
9989 case GFC_ISYM_ATOMIC_ADD:
9990 case GFC_ISYM_ATOMIC_FETCH_ADD:
9991 op = (int) GFC_CAF_ATOMIC_ADD;
9992 break;
9993 case GFC_ISYM_ATOMIC_AND:
9994 case GFC_ISYM_ATOMIC_FETCH_AND:
9995 op = (int) GFC_CAF_ATOMIC_AND;
9996 break;
9997 case GFC_ISYM_ATOMIC_OR:
9998 case GFC_ISYM_ATOMIC_FETCH_OR:
9999 op = (int) GFC_CAF_ATOMIC_OR;
10000 break;
10001 case GFC_ISYM_ATOMIC_XOR:
10002 case GFC_ISYM_ATOMIC_FETCH_XOR:
10003 op = (int) GFC_CAF_ATOMIC_XOR;
10004 break;
10005 case GFC_ISYM_ATOMIC_DEF:
10006 op = 0; /* Unused. */
10007 break;
10008 default:
10009 gcc_unreachable ();
10012 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10013 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10014 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10016 if (gfc_is_coindexed (atom_expr))
10017 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10018 else
10019 image_index = integer_zero_node;
10021 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10023 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10024 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10025 value = gfc_build_addr_expr (NULL_TREE, tmp);
10028 gfc_init_se (&argse, NULL);
10029 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10030 atom_expr);
10032 gfc_add_block_to_block (&block, &argse.pre);
10033 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10034 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10035 token, offset, image_index, value, stat,
10036 build_int_cst (integer_type_node,
10037 (int) atom_expr->ts.type),
10038 build_int_cst (integer_type_node,
10039 (int) atom_expr->ts.kind));
10040 else
10041 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10042 build_int_cst (integer_type_node, op),
10043 token, offset, image_index, value, old, stat,
10044 build_int_cst (integer_type_node,
10045 (int) atom_expr->ts.type),
10046 build_int_cst (integer_type_node,
10047 (int) atom_expr->ts.kind));
10049 gfc_add_expr_to_block (&block, tmp);
10050 gfc_add_block_to_block (&block, &argse.post);
10051 gfc_add_block_to_block (&block, &post_block);
10052 return gfc_finish_block (&block);
10056 switch (code->resolved_isym->id)
10058 case GFC_ISYM_ATOMIC_ADD:
10059 case GFC_ISYM_ATOMIC_FETCH_ADD:
10060 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10061 break;
10062 case GFC_ISYM_ATOMIC_AND:
10063 case GFC_ISYM_ATOMIC_FETCH_AND:
10064 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10065 break;
10066 case GFC_ISYM_ATOMIC_DEF:
10067 fn = BUILT_IN_ATOMIC_STORE_N;
10068 break;
10069 case GFC_ISYM_ATOMIC_OR:
10070 case GFC_ISYM_ATOMIC_FETCH_OR:
10071 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10072 break;
10073 case GFC_ISYM_ATOMIC_XOR:
10074 case GFC_ISYM_ATOMIC_FETCH_XOR:
10075 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10076 break;
10077 default:
10078 gcc_unreachable ();
10081 tmp = TREE_TYPE (TREE_TYPE (atom));
10082 fn = (built_in_function) ((int) fn
10083 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10084 + 1);
10085 tmp = builtin_decl_explicit (fn);
10086 tree itype = TREE_TYPE (TREE_TYPE (atom));
10087 tmp = builtin_decl_explicit (fn);
10089 switch (code->resolved_isym->id)
10091 case GFC_ISYM_ATOMIC_ADD:
10092 case GFC_ISYM_ATOMIC_AND:
10093 case GFC_ISYM_ATOMIC_DEF:
10094 case GFC_ISYM_ATOMIC_OR:
10095 case GFC_ISYM_ATOMIC_XOR:
10096 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10097 fold_convert (itype, value),
10098 build_int_cst (NULL, MEMMODEL_RELAXED));
10099 gfc_add_expr_to_block (&block, tmp);
10100 break;
10101 default:
10102 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10103 fold_convert (itype, value),
10104 build_int_cst (NULL, MEMMODEL_RELAXED));
10105 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10106 break;
10109 if (stat != NULL_TREE)
10110 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10111 gfc_add_block_to_block (&block, &post_block);
10112 return gfc_finish_block (&block);
10116 static tree
10117 conv_intrinsic_atomic_ref (gfc_code *code)
10119 gfc_se argse;
10120 tree tmp, atom, value, stat = NULL_TREE;
10121 stmtblock_t block, post_block;
10122 built_in_function fn;
10123 gfc_expr *atom_expr = code->ext.actual->next->expr;
10125 if (atom_expr->expr_type == EXPR_FUNCTION
10126 && atom_expr->value.function.isym
10127 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10128 atom_expr = atom_expr->value.function.actual->expr;
10130 gfc_start_block (&block);
10131 gfc_init_block (&post_block);
10132 gfc_init_se (&argse, NULL);
10133 argse.want_pointer = 1;
10134 gfc_conv_expr (&argse, atom_expr);
10135 gfc_add_block_to_block (&block, &argse.pre);
10136 gfc_add_block_to_block (&post_block, &argse.post);
10137 atom = argse.expr;
10139 gfc_init_se (&argse, NULL);
10140 if (flag_coarray == GFC_FCOARRAY_LIB
10141 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10142 argse.want_pointer = 1;
10143 gfc_conv_expr (&argse, code->ext.actual->expr);
10144 gfc_add_block_to_block (&block, &argse.pre);
10145 gfc_add_block_to_block (&post_block, &argse.post);
10146 value = argse.expr;
10148 /* STAT= */
10149 if (code->ext.actual->next->next->expr != NULL)
10151 gcc_assert (code->ext.actual->next->next->expr->expr_type
10152 == EXPR_VARIABLE);
10153 gfc_init_se (&argse, NULL);
10154 if (flag_coarray == GFC_FCOARRAY_LIB)
10155 argse.want_pointer = 1;
10156 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10157 gfc_add_block_to_block (&block, &argse.pre);
10158 gfc_add_block_to_block (&post_block, &argse.post);
10159 stat = argse.expr;
10161 else if (flag_coarray == GFC_FCOARRAY_LIB)
10162 stat = null_pointer_node;
10164 if (flag_coarray == GFC_FCOARRAY_LIB)
10166 tree image_index, caf_decl, offset, token;
10167 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10169 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10170 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10171 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10173 if (gfc_is_coindexed (atom_expr))
10174 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10175 else
10176 image_index = integer_zero_node;
10178 gfc_init_se (&argse, NULL);
10179 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10180 atom_expr);
10181 gfc_add_block_to_block (&block, &argse.pre);
10183 /* Different type, need type conversion. */
10184 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10186 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10187 orig_value = value;
10188 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10191 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10192 token, offset, image_index, value, stat,
10193 build_int_cst (integer_type_node,
10194 (int) atom_expr->ts.type),
10195 build_int_cst (integer_type_node,
10196 (int) atom_expr->ts.kind));
10197 gfc_add_expr_to_block (&block, tmp);
10198 if (vardecl != NULL_TREE)
10199 gfc_add_modify (&block, orig_value,
10200 fold_convert (TREE_TYPE (orig_value), vardecl));
10201 gfc_add_block_to_block (&block, &argse.post);
10202 gfc_add_block_to_block (&block, &post_block);
10203 return gfc_finish_block (&block);
10206 tmp = TREE_TYPE (TREE_TYPE (atom));
10207 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10208 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10209 + 1);
10210 tmp = builtin_decl_explicit (fn);
10211 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10212 build_int_cst (integer_type_node,
10213 MEMMODEL_RELAXED));
10214 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10216 if (stat != NULL_TREE)
10217 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10218 gfc_add_block_to_block (&block, &post_block);
10219 return gfc_finish_block (&block);
10223 static tree
10224 conv_intrinsic_atomic_cas (gfc_code *code)
10226 gfc_se argse;
10227 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10228 stmtblock_t block, post_block;
10229 built_in_function fn;
10230 gfc_expr *atom_expr = code->ext.actual->expr;
10232 if (atom_expr->expr_type == EXPR_FUNCTION
10233 && atom_expr->value.function.isym
10234 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10235 atom_expr = atom_expr->value.function.actual->expr;
10237 gfc_init_block (&block);
10238 gfc_init_block (&post_block);
10239 gfc_init_se (&argse, NULL);
10240 argse.want_pointer = 1;
10241 gfc_conv_expr (&argse, atom_expr);
10242 atom = argse.expr;
10244 gfc_init_se (&argse, NULL);
10245 if (flag_coarray == GFC_FCOARRAY_LIB)
10246 argse.want_pointer = 1;
10247 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10248 gfc_add_block_to_block (&block, &argse.pre);
10249 gfc_add_block_to_block (&post_block, &argse.post);
10250 old = argse.expr;
10252 gfc_init_se (&argse, NULL);
10253 if (flag_coarray == GFC_FCOARRAY_LIB)
10254 argse.want_pointer = 1;
10255 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10256 gfc_add_block_to_block (&block, &argse.pre);
10257 gfc_add_block_to_block (&post_block, &argse.post);
10258 comp = argse.expr;
10260 gfc_init_se (&argse, NULL);
10261 if (flag_coarray == GFC_FCOARRAY_LIB
10262 && code->ext.actual->next->next->next->expr->ts.kind
10263 == atom_expr->ts.kind)
10264 argse.want_pointer = 1;
10265 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10266 gfc_add_block_to_block (&block, &argse.pre);
10267 gfc_add_block_to_block (&post_block, &argse.post);
10268 new_val = argse.expr;
10270 /* STAT= */
10271 if (code->ext.actual->next->next->next->next->expr != NULL)
10273 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10274 == EXPR_VARIABLE);
10275 gfc_init_se (&argse, NULL);
10276 if (flag_coarray == GFC_FCOARRAY_LIB)
10277 argse.want_pointer = 1;
10278 gfc_conv_expr_val (&argse,
10279 code->ext.actual->next->next->next->next->expr);
10280 gfc_add_block_to_block (&block, &argse.pre);
10281 gfc_add_block_to_block (&post_block, &argse.post);
10282 stat = argse.expr;
10284 else if (flag_coarray == GFC_FCOARRAY_LIB)
10285 stat = null_pointer_node;
10287 if (flag_coarray == GFC_FCOARRAY_LIB)
10289 tree image_index, caf_decl, offset, token;
10291 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10292 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10293 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10295 if (gfc_is_coindexed (atom_expr))
10296 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10297 else
10298 image_index = integer_zero_node;
10300 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10302 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10303 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10304 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10307 /* Convert a constant to a pointer. */
10308 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10310 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10311 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10312 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10315 gfc_init_se (&argse, NULL);
10316 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10317 atom_expr);
10318 gfc_add_block_to_block (&block, &argse.pre);
10320 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10321 token, offset, image_index, old, comp, new_val,
10322 stat, build_int_cst (integer_type_node,
10323 (int) atom_expr->ts.type),
10324 build_int_cst (integer_type_node,
10325 (int) atom_expr->ts.kind));
10326 gfc_add_expr_to_block (&block, tmp);
10327 gfc_add_block_to_block (&block, &argse.post);
10328 gfc_add_block_to_block (&block, &post_block);
10329 return gfc_finish_block (&block);
10332 tmp = TREE_TYPE (TREE_TYPE (atom));
10333 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10334 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10335 + 1);
10336 tmp = builtin_decl_explicit (fn);
10338 gfc_add_modify (&block, old, comp);
10339 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10340 gfc_build_addr_expr (NULL, old),
10341 fold_convert (TREE_TYPE (old), new_val),
10342 boolean_false_node,
10343 build_int_cst (NULL, MEMMODEL_RELAXED),
10344 build_int_cst (NULL, MEMMODEL_RELAXED));
10345 gfc_add_expr_to_block (&block, tmp);
10347 if (stat != NULL_TREE)
10348 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10349 gfc_add_block_to_block (&block, &post_block);
10350 return gfc_finish_block (&block);
10353 static tree
10354 conv_intrinsic_event_query (gfc_code *code)
10356 gfc_se se, argse;
10357 tree stat = NULL_TREE, stat2 = NULL_TREE;
10358 tree count = NULL_TREE, count2 = NULL_TREE;
10360 gfc_expr *event_expr = code->ext.actual->expr;
10362 if (code->ext.actual->next->next->expr)
10364 gcc_assert (code->ext.actual->next->next->expr->expr_type
10365 == EXPR_VARIABLE);
10366 gfc_init_se (&argse, NULL);
10367 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10368 stat = argse.expr;
10370 else if (flag_coarray == GFC_FCOARRAY_LIB)
10371 stat = null_pointer_node;
10373 if (code->ext.actual->next->expr)
10375 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10376 gfc_init_se (&argse, NULL);
10377 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10378 count = argse.expr;
10381 gfc_start_block (&se.pre);
10382 if (flag_coarray == GFC_FCOARRAY_LIB)
10384 tree tmp, token, image_index;
10385 tree index = size_zero_node;
10387 if (event_expr->expr_type == EXPR_FUNCTION
10388 && event_expr->value.function.isym
10389 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10390 event_expr = event_expr->value.function.actual->expr;
10392 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10394 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10395 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10396 != INTMOD_ISO_FORTRAN_ENV
10397 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10398 != ISOFORTRAN_EVENT_TYPE)
10400 gfc_error ("Sorry, the event component of derived type at %L is not "
10401 "yet supported", &event_expr->where);
10402 return NULL_TREE;
10405 if (gfc_is_coindexed (event_expr))
10407 gfc_error ("The event variable at %L shall not be coindexed",
10408 &event_expr->where);
10409 return NULL_TREE;
10412 image_index = integer_zero_node;
10414 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10415 event_expr);
10417 /* For arrays, obtain the array index. */
10418 if (gfc_expr_attr (event_expr).dimension)
10420 tree desc, tmp, extent, lbound, ubound;
10421 gfc_array_ref *ar, ar2;
10422 int i;
10424 /* TODO: Extend this, once DT components are supported. */
10425 ar = &event_expr->ref->u.ar;
10426 ar2 = *ar;
10427 memset (ar, '\0', sizeof (*ar));
10428 ar->as = ar2.as;
10429 ar->type = AR_FULL;
10431 gfc_init_se (&argse, NULL);
10432 argse.descriptor_only = 1;
10433 gfc_conv_expr_descriptor (&argse, event_expr);
10434 gfc_add_block_to_block (&se.pre, &argse.pre);
10435 desc = argse.expr;
10436 *ar = ar2;
10438 extent = integer_one_node;
10439 for (i = 0; i < ar->dimen; i++)
10441 gfc_init_se (&argse, NULL);
10442 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10443 gfc_add_block_to_block (&argse.pre, &argse.pre);
10444 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10445 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10446 integer_type_node, argse.expr,
10447 fold_convert(integer_type_node, lbound));
10448 tmp = fold_build2_loc (input_location, MULT_EXPR,
10449 integer_type_node, extent, tmp);
10450 index = fold_build2_loc (input_location, PLUS_EXPR,
10451 integer_type_node, index, tmp);
10452 if (i < ar->dimen - 1)
10454 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10455 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10456 tmp = fold_convert (integer_type_node, tmp);
10457 extent = fold_build2_loc (input_location, MULT_EXPR,
10458 integer_type_node, extent, tmp);
10463 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10465 count2 = count;
10466 count = gfc_create_var (integer_type_node, "count");
10469 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10471 stat2 = stat;
10472 stat = gfc_create_var (integer_type_node, "stat");
10475 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10476 token, index, image_index, count
10477 ? gfc_build_addr_expr (NULL, count) : count,
10478 stat != null_pointer_node
10479 ? gfc_build_addr_expr (NULL, stat) : stat);
10480 gfc_add_expr_to_block (&se.pre, tmp);
10482 if (count2 != NULL_TREE)
10483 gfc_add_modify (&se.pre, count2,
10484 fold_convert (TREE_TYPE (count2), count));
10486 if (stat2 != NULL_TREE)
10487 gfc_add_modify (&se.pre, stat2,
10488 fold_convert (TREE_TYPE (stat2), stat));
10490 return gfc_finish_block (&se.pre);
10493 gfc_init_se (&argse, NULL);
10494 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10495 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10497 if (stat != NULL_TREE)
10498 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10500 return gfc_finish_block (&se.pre);
10503 static tree
10504 conv_intrinsic_move_alloc (gfc_code *code)
10506 stmtblock_t block;
10507 gfc_expr *from_expr, *to_expr;
10508 gfc_expr *to_expr2, *from_expr2 = NULL;
10509 gfc_se from_se, to_se;
10510 tree tmp;
10511 bool coarray;
10513 gfc_start_block (&block);
10515 from_expr = code->ext.actual->expr;
10516 to_expr = code->ext.actual->next->expr;
10518 gfc_init_se (&from_se, NULL);
10519 gfc_init_se (&to_se, NULL);
10521 gcc_assert (from_expr->ts.type != BT_CLASS
10522 || to_expr->ts.type == BT_CLASS);
10523 coarray = gfc_get_corank (from_expr) != 0;
10525 if (from_expr->rank == 0 && !coarray)
10527 if (from_expr->ts.type != BT_CLASS)
10528 from_expr2 = from_expr;
10529 else
10531 from_expr2 = gfc_copy_expr (from_expr);
10532 gfc_add_data_component (from_expr2);
10535 if (to_expr->ts.type != BT_CLASS)
10536 to_expr2 = to_expr;
10537 else
10539 to_expr2 = gfc_copy_expr (to_expr);
10540 gfc_add_data_component (to_expr2);
10543 from_se.want_pointer = 1;
10544 to_se.want_pointer = 1;
10545 gfc_conv_expr (&from_se, from_expr2);
10546 gfc_conv_expr (&to_se, to_expr2);
10547 gfc_add_block_to_block (&block, &from_se.pre);
10548 gfc_add_block_to_block (&block, &to_se.pre);
10550 /* Deallocate "to". */
10551 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10552 true, to_expr, to_expr->ts);
10553 gfc_add_expr_to_block (&block, tmp);
10555 /* Assign (_data) pointers. */
10556 gfc_add_modify_loc (input_location, &block, to_se.expr,
10557 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10559 /* Set "from" to NULL. */
10560 gfc_add_modify_loc (input_location, &block, from_se.expr,
10561 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10563 gfc_add_block_to_block (&block, &from_se.post);
10564 gfc_add_block_to_block (&block, &to_se.post);
10566 /* Set _vptr. */
10567 if (to_expr->ts.type == BT_CLASS)
10569 gfc_symbol *vtab;
10571 gfc_free_expr (to_expr2);
10572 gfc_init_se (&to_se, NULL);
10573 to_se.want_pointer = 1;
10574 gfc_add_vptr_component (to_expr);
10575 gfc_conv_expr (&to_se, to_expr);
10577 if (from_expr->ts.type == BT_CLASS)
10579 if (UNLIMITED_POLY (from_expr))
10580 vtab = NULL;
10581 else
10583 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10584 gcc_assert (vtab);
10587 gfc_free_expr (from_expr2);
10588 gfc_init_se (&from_se, NULL);
10589 from_se.want_pointer = 1;
10590 gfc_add_vptr_component (from_expr);
10591 gfc_conv_expr (&from_se, from_expr);
10592 gfc_add_modify_loc (input_location, &block, to_se.expr,
10593 fold_convert (TREE_TYPE (to_se.expr),
10594 from_se.expr));
10596 /* Reset _vptr component to declared type. */
10597 if (vtab == NULL)
10598 /* Unlimited polymorphic. */
10599 gfc_add_modify_loc (input_location, &block, from_se.expr,
10600 fold_convert (TREE_TYPE (from_se.expr),
10601 null_pointer_node));
10602 else
10604 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10605 gfc_add_modify_loc (input_location, &block, from_se.expr,
10606 fold_convert (TREE_TYPE (from_se.expr), tmp));
10609 else
10611 vtab = gfc_find_vtab (&from_expr->ts);
10612 gcc_assert (vtab);
10613 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10614 gfc_add_modify_loc (input_location, &block, to_se.expr,
10615 fold_convert (TREE_TYPE (to_se.expr), tmp));
10619 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10621 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10622 fold_convert (TREE_TYPE (to_se.string_length),
10623 from_se.string_length));
10624 if (from_expr->ts.deferred)
10625 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10626 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10629 return gfc_finish_block (&block);
10632 /* Update _vptr component. */
10633 if (to_expr->ts.type == BT_CLASS)
10635 gfc_symbol *vtab;
10637 to_se.want_pointer = 1;
10638 to_expr2 = gfc_copy_expr (to_expr);
10639 gfc_add_vptr_component (to_expr2);
10640 gfc_conv_expr (&to_se, to_expr2);
10642 if (from_expr->ts.type == BT_CLASS)
10644 if (UNLIMITED_POLY (from_expr))
10645 vtab = NULL;
10646 else
10648 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10649 gcc_assert (vtab);
10652 from_se.want_pointer = 1;
10653 from_expr2 = gfc_copy_expr (from_expr);
10654 gfc_add_vptr_component (from_expr2);
10655 gfc_conv_expr (&from_se, from_expr2);
10656 gfc_add_modify_loc (input_location, &block, to_se.expr,
10657 fold_convert (TREE_TYPE (to_se.expr),
10658 from_se.expr));
10660 /* Reset _vptr component to declared type. */
10661 if (vtab == NULL)
10662 /* Unlimited polymorphic. */
10663 gfc_add_modify_loc (input_location, &block, from_se.expr,
10664 fold_convert (TREE_TYPE (from_se.expr),
10665 null_pointer_node));
10666 else
10668 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10669 gfc_add_modify_loc (input_location, &block, from_se.expr,
10670 fold_convert (TREE_TYPE (from_se.expr), tmp));
10673 else
10675 vtab = gfc_find_vtab (&from_expr->ts);
10676 gcc_assert (vtab);
10677 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10678 gfc_add_modify_loc (input_location, &block, to_se.expr,
10679 fold_convert (TREE_TYPE (to_se.expr), tmp));
10682 gfc_free_expr (to_expr2);
10683 gfc_init_se (&to_se, NULL);
10685 if (from_expr->ts.type == BT_CLASS)
10687 gfc_free_expr (from_expr2);
10688 gfc_init_se (&from_se, NULL);
10693 /* Deallocate "to". */
10694 if (from_expr->rank == 0)
10696 to_se.want_coarray = 1;
10697 from_se.want_coarray = 1;
10699 gfc_conv_expr_descriptor (&to_se, to_expr);
10700 gfc_conv_expr_descriptor (&from_se, from_expr);
10702 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10703 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10704 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10706 tree cond;
10708 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10709 NULL_TREE, NULL_TREE, true, to_expr,
10710 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10711 gfc_add_expr_to_block (&block, tmp);
10713 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10714 cond = fold_build2_loc (input_location, EQ_EXPR,
10715 logical_type_node, tmp,
10716 fold_convert (TREE_TYPE (tmp),
10717 null_pointer_node));
10718 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10719 3, null_pointer_node, null_pointer_node,
10720 build_int_cst (integer_type_node, 0));
10722 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
10723 tmp, build_empty_stmt (input_location));
10724 gfc_add_expr_to_block (&block, tmp);
10726 else
10728 if (to_expr->ts.type == BT_DERIVED
10729 && to_expr->ts.u.derived->attr.alloc_comp)
10731 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
10732 to_se.expr, to_expr->rank);
10733 gfc_add_expr_to_block (&block, tmp);
10736 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10737 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
10738 NULL_TREE, true, to_expr,
10739 GFC_CAF_COARRAY_NOCOARRAY);
10740 gfc_add_expr_to_block (&block, tmp);
10743 /* Move the pointer and update the array descriptor data. */
10744 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
10746 /* Set "from" to NULL. */
10747 tmp = gfc_conv_descriptor_data_get (from_se.expr);
10748 gfc_add_modify_loc (input_location, &block, tmp,
10749 fold_convert (TREE_TYPE (tmp), null_pointer_node));
10752 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10754 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10755 fold_convert (TREE_TYPE (to_se.string_length),
10756 from_se.string_length));
10757 if (from_expr->ts.deferred)
10758 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10759 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10762 return gfc_finish_block (&block);
10766 tree
10767 gfc_conv_intrinsic_subroutine (gfc_code *code)
10769 tree res;
10771 gcc_assert (code->resolved_isym);
10773 switch (code->resolved_isym->id)
10775 case GFC_ISYM_MOVE_ALLOC:
10776 res = conv_intrinsic_move_alloc (code);
10777 break;
10779 case GFC_ISYM_ATOMIC_CAS:
10780 res = conv_intrinsic_atomic_cas (code);
10781 break;
10783 case GFC_ISYM_ATOMIC_ADD:
10784 case GFC_ISYM_ATOMIC_AND:
10785 case GFC_ISYM_ATOMIC_DEF:
10786 case GFC_ISYM_ATOMIC_OR:
10787 case GFC_ISYM_ATOMIC_XOR:
10788 case GFC_ISYM_ATOMIC_FETCH_ADD:
10789 case GFC_ISYM_ATOMIC_FETCH_AND:
10790 case GFC_ISYM_ATOMIC_FETCH_OR:
10791 case GFC_ISYM_ATOMIC_FETCH_XOR:
10792 res = conv_intrinsic_atomic_op (code);
10793 break;
10795 case GFC_ISYM_ATOMIC_REF:
10796 res = conv_intrinsic_atomic_ref (code);
10797 break;
10799 case GFC_ISYM_EVENT_QUERY:
10800 res = conv_intrinsic_event_query (code);
10801 break;
10803 case GFC_ISYM_C_F_POINTER:
10804 case GFC_ISYM_C_F_PROCPOINTER:
10805 res = conv_isocbinding_subroutine (code);
10806 break;
10808 case GFC_ISYM_CAF_SEND:
10809 res = conv_caf_send (code);
10810 break;
10812 case GFC_ISYM_CO_BROADCAST:
10813 case GFC_ISYM_CO_MIN:
10814 case GFC_ISYM_CO_MAX:
10815 case GFC_ISYM_CO_REDUCE:
10816 case GFC_ISYM_CO_SUM:
10817 res = conv_co_collective (code);
10818 break;
10820 case GFC_ISYM_FREE:
10821 res = conv_intrinsic_free (code);
10822 break;
10824 case GFC_ISYM_SYSTEM_CLOCK:
10825 res = conv_intrinsic_system_clock (code);
10826 break;
10828 default:
10829 res = NULL_TREE;
10830 break;
10833 return res;
10836 #include "gt-fortran-trans-intrinsic.h"