Fix typo in last ChangeLog entry
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
bloba45aec708fb97b33c38ee07032730e221e129978
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 /* Generate code for the KILL intrinsic. */
8120 static void
8121 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
8123 tree *args;
8124 tree int4_type_node = gfc_get_int_type (4);
8125 tree pid;
8126 tree sig;
8127 tree tmp;
8128 unsigned int num_args;
8130 num_args = gfc_intrinsic_argument_list_length (expr);
8131 args = XALLOCAVEC (tree, num_args);
8132 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8134 /* Convert PID to a INTEGER(4) entity. */
8135 pid = convert (int4_type_node, args[0]);
8137 /* Convert SIG to a INTEGER(4) entity. */
8138 sig = convert (int4_type_node, args[1]);
8140 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
8142 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
8146 static tree
8147 conv_intrinsic_kill_sub (gfc_code *code)
8149 stmtblock_t block;
8150 gfc_se se, se_stat;
8151 tree int4_type_node = gfc_get_int_type (4);
8152 tree pid;
8153 tree sig;
8154 tree statp;
8155 tree tmp;
8157 /* Make the function call. */
8158 gfc_init_block (&block);
8159 gfc_init_se (&se, NULL);
8161 /* Convert PID to a INTEGER(4) entity. */
8162 gfc_conv_expr (&se, code->ext.actual->expr);
8163 gfc_add_block_to_block (&block, &se.pre);
8164 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8165 gfc_add_block_to_block (&block, &se.post);
8167 /* Convert SIG to a INTEGER(4) entity. */
8168 gfc_conv_expr (&se, code->ext.actual->next->expr);
8169 gfc_add_block_to_block (&block, &se.pre);
8170 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8171 gfc_add_block_to_block (&block, &se.post);
8173 /* Deal with an optional STATUS. */
8174 if (code->ext.actual->next->next->expr)
8176 gfc_init_se (&se_stat, NULL);
8177 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
8178 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
8180 else
8181 statp = NULL_TREE;
8183 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
8184 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
8186 gfc_add_expr_to_block (&block, tmp);
8188 if (statp && statp != se_stat.expr)
8189 gfc_add_modify (&block, se_stat.expr,
8190 fold_convert (TREE_TYPE (se_stat.expr), statp));
8192 return gfc_finish_block (&block);
8197 /* The loc intrinsic returns the address of its argument as
8198 gfc_index_integer_kind integer. */
8200 static void
8201 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8203 tree temp_var;
8204 gfc_expr *arg_expr;
8206 gcc_assert (!se->ss);
8208 arg_expr = expr->value.function.actual->expr;
8209 if (arg_expr->rank == 0)
8211 if (arg_expr->ts.type == BT_CLASS)
8212 gfc_add_data_component (arg_expr);
8213 gfc_conv_expr_reference (se, arg_expr);
8215 else
8216 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8217 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8219 /* Create a temporary variable for loc return value. Without this,
8220 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8221 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8222 gfc_add_modify (&se->pre, temp_var, se->expr);
8223 se->expr = temp_var;
8227 /* The following routine generates code for the intrinsic
8228 functions from the ISO_C_BINDING module:
8229 * C_LOC
8230 * C_FUNLOC
8231 * C_ASSOCIATED */
8233 static void
8234 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8236 gfc_actual_arglist *arg = expr->value.function.actual;
8238 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8240 if (arg->expr->rank == 0)
8241 gfc_conv_expr_reference (se, arg->expr);
8242 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8243 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8244 else
8246 gfc_conv_expr_descriptor (se, arg->expr);
8247 se->expr = gfc_conv_descriptor_data_get (se->expr);
8250 /* TODO -- the following two lines shouldn't be necessary, but if
8251 they're removed, a bug is exposed later in the code path.
8252 This workaround was thus introduced, but will have to be
8253 removed; please see PR 35150 for details about the issue. */
8254 se->expr = convert (pvoid_type_node, se->expr);
8255 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8257 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8258 gfc_conv_expr_reference (se, arg->expr);
8259 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8261 gfc_se arg1se;
8262 gfc_se arg2se;
8264 /* Build the addr_expr for the first argument. The argument is
8265 already an *address* so we don't need to set want_pointer in
8266 the gfc_se. */
8267 gfc_init_se (&arg1se, NULL);
8268 gfc_conv_expr (&arg1se, arg->expr);
8269 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8270 gfc_add_block_to_block (&se->post, &arg1se.post);
8272 /* See if we were given two arguments. */
8273 if (arg->next->expr == NULL)
8274 /* Only given one arg so generate a null and do a
8275 not-equal comparison against the first arg. */
8276 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8277 arg1se.expr,
8278 fold_convert (TREE_TYPE (arg1se.expr),
8279 null_pointer_node));
8280 else
8282 tree eq_expr;
8283 tree not_null_expr;
8285 /* Given two arguments so build the arg2se from second arg. */
8286 gfc_init_se (&arg2se, NULL);
8287 gfc_conv_expr (&arg2se, arg->next->expr);
8288 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8289 gfc_add_block_to_block (&se->post, &arg2se.post);
8291 /* Generate test to compare that the two args are equal. */
8292 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8293 arg1se.expr, arg2se.expr);
8294 /* Generate test to ensure that the first arg is not null. */
8295 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8296 logical_type_node,
8297 arg1se.expr, null_pointer_node);
8299 /* Finally, the generated test must check that both arg1 is not
8300 NULL and that it is equal to the second arg. */
8301 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8302 logical_type_node,
8303 not_null_expr, eq_expr);
8306 else
8307 gcc_unreachable ();
8311 /* The following routine generates code for the intrinsic
8312 subroutines from the ISO_C_BINDING module:
8313 * C_F_POINTER
8314 * C_F_PROCPOINTER. */
8316 static tree
8317 conv_isocbinding_subroutine (gfc_code *code)
8319 gfc_se se;
8320 gfc_se cptrse;
8321 gfc_se fptrse;
8322 gfc_se shapese;
8323 gfc_ss *shape_ss;
8324 tree desc, dim, tmp, stride, offset;
8325 stmtblock_t body, block;
8326 gfc_loopinfo loop;
8327 gfc_actual_arglist *arg = code->ext.actual;
8329 gfc_init_se (&se, NULL);
8330 gfc_init_se (&cptrse, NULL);
8331 gfc_conv_expr (&cptrse, arg->expr);
8332 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8333 gfc_add_block_to_block (&se.post, &cptrse.post);
8335 gfc_init_se (&fptrse, NULL);
8336 if (arg->next->expr->rank == 0)
8338 fptrse.want_pointer = 1;
8339 gfc_conv_expr (&fptrse, arg->next->expr);
8340 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8341 gfc_add_block_to_block (&se.post, &fptrse.post);
8342 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8343 && arg->next->expr->symtree->n.sym->attr.dummy)
8344 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8345 fptrse.expr);
8346 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8347 TREE_TYPE (fptrse.expr),
8348 fptrse.expr,
8349 fold_convert (TREE_TYPE (fptrse.expr),
8350 cptrse.expr));
8351 gfc_add_expr_to_block (&se.pre, se.expr);
8352 gfc_add_block_to_block (&se.pre, &se.post);
8353 return gfc_finish_block (&se.pre);
8356 gfc_start_block (&block);
8358 /* Get the descriptor of the Fortran pointer. */
8359 fptrse.descriptor_only = 1;
8360 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8361 gfc_add_block_to_block (&block, &fptrse.pre);
8362 desc = fptrse.expr;
8364 /* Set the span field. */
8365 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8366 tmp = fold_convert (gfc_array_index_type, tmp);
8367 gfc_conv_descriptor_span_set (&block, desc, tmp);
8369 /* Set data value, dtype, and offset. */
8370 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8371 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8372 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8373 gfc_get_dtype (TREE_TYPE (desc)));
8375 /* Start scalarization of the bounds, using the shape argument. */
8377 shape_ss = gfc_walk_expr (arg->next->next->expr);
8378 gcc_assert (shape_ss != gfc_ss_terminator);
8379 gfc_init_se (&shapese, NULL);
8381 gfc_init_loopinfo (&loop);
8382 gfc_add_ss_to_loop (&loop, shape_ss);
8383 gfc_conv_ss_startstride (&loop);
8384 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8385 gfc_mark_ss_chain_used (shape_ss, 1);
8387 gfc_copy_loopinfo_to_se (&shapese, &loop);
8388 shapese.ss = shape_ss;
8390 stride = gfc_create_var (gfc_array_index_type, "stride");
8391 offset = gfc_create_var (gfc_array_index_type, "offset");
8392 gfc_add_modify (&block, stride, gfc_index_one_node);
8393 gfc_add_modify (&block, offset, gfc_index_zero_node);
8395 /* Loop body. */
8396 gfc_start_scalarized_body (&loop, &body);
8398 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8399 loop.loopvar[0], loop.from[0]);
8401 /* Set bounds and stride. */
8402 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8403 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8405 gfc_conv_expr (&shapese, arg->next->next->expr);
8406 gfc_add_block_to_block (&body, &shapese.pre);
8407 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8408 gfc_add_block_to_block (&body, &shapese.post);
8410 /* Calculate offset. */
8411 gfc_add_modify (&body, offset,
8412 fold_build2_loc (input_location, PLUS_EXPR,
8413 gfc_array_index_type, offset, stride));
8414 /* Update stride. */
8415 gfc_add_modify (&body, stride,
8416 fold_build2_loc (input_location, MULT_EXPR,
8417 gfc_array_index_type, stride,
8418 fold_convert (gfc_array_index_type,
8419 shapese.expr)));
8420 /* Finish scalarization loop. */
8421 gfc_trans_scalarizing_loops (&loop, &body);
8422 gfc_add_block_to_block (&block, &loop.pre);
8423 gfc_add_block_to_block (&block, &loop.post);
8424 gfc_add_block_to_block (&block, &fptrse.post);
8425 gfc_cleanup_loop (&loop);
8427 gfc_add_modify (&block, offset,
8428 fold_build1_loc (input_location, NEGATE_EXPR,
8429 gfc_array_index_type, offset));
8430 gfc_conv_descriptor_offset_set (&block, desc, offset);
8432 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8433 gfc_add_block_to_block (&se.pre, &se.post);
8434 return gfc_finish_block (&se.pre);
8438 /* Save and restore floating-point state. */
8440 tree
8441 gfc_save_fp_state (stmtblock_t *block)
8443 tree type, fpstate, tmp;
8445 type = build_array_type (char_type_node,
8446 build_range_type (size_type_node, size_zero_node,
8447 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8448 fpstate = gfc_create_var (type, "fpstate");
8449 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8451 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8452 1, fpstate);
8453 gfc_add_expr_to_block (block, tmp);
8455 return fpstate;
8459 void
8460 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8462 tree tmp;
8464 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8465 1, fpstate);
8466 gfc_add_expr_to_block (block, tmp);
8470 /* Generate code for arguments of IEEE functions. */
8472 static void
8473 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8474 int nargs)
8476 gfc_actual_arglist *actual;
8477 gfc_expr *e;
8478 gfc_se argse;
8479 int arg;
8481 actual = expr->value.function.actual;
8482 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8484 gcc_assert (actual);
8485 e = actual->expr;
8487 gfc_init_se (&argse, se);
8488 gfc_conv_expr_val (&argse, e);
8490 gfc_add_block_to_block (&se->pre, &argse.pre);
8491 gfc_add_block_to_block (&se->post, &argse.post);
8492 argarray[arg] = argse.expr;
8497 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8498 and IEEE_UNORDERED, which translate directly to GCC type-generic
8499 built-ins. */
8501 static void
8502 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8503 enum built_in_function code, int nargs)
8505 tree args[2];
8506 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8508 conv_ieee_function_args (se, expr, args, nargs);
8509 se->expr = build_call_expr_loc_array (input_location,
8510 builtin_decl_explicit (code),
8511 nargs, args);
8512 STRIP_TYPE_NOPS (se->expr);
8513 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8517 /* Generate code for IEEE_IS_NORMAL intrinsic:
8518 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8520 static void
8521 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8523 tree arg, isnormal, iszero;
8525 /* Convert arg, evaluate it only once. */
8526 conv_ieee_function_args (se, expr, &arg, 1);
8527 arg = gfc_evaluate_now (arg, &se->pre);
8529 isnormal = build_call_expr_loc (input_location,
8530 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8531 1, arg);
8532 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8533 build_real_from_int_cst (TREE_TYPE (arg),
8534 integer_zero_node));
8535 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8536 logical_type_node, isnormal, iszero);
8537 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8541 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8542 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8544 static void
8545 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8547 tree arg, signbit, isnan;
8549 /* Convert arg, evaluate it only once. */
8550 conv_ieee_function_args (se, expr, &arg, 1);
8551 arg = gfc_evaluate_now (arg, &se->pre);
8553 isnan = build_call_expr_loc (input_location,
8554 builtin_decl_explicit (BUILT_IN_ISNAN),
8555 1, arg);
8556 STRIP_TYPE_NOPS (isnan);
8558 signbit = build_call_expr_loc (input_location,
8559 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8560 1, arg);
8561 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8562 signbit, integer_zero_node);
8564 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8565 logical_type_node, signbit,
8566 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8567 TREE_TYPE(isnan), isnan));
8569 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8573 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8575 static void
8576 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8577 enum built_in_function code)
8579 tree arg, decl, call, fpstate;
8580 int argprec;
8582 conv_ieee_function_args (se, expr, &arg, 1);
8583 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8584 decl = builtin_decl_for_precision (code, argprec);
8586 /* Save floating-point state. */
8587 fpstate = gfc_save_fp_state (&se->pre);
8589 /* Make the function call. */
8590 call = build_call_expr_loc (input_location, decl, 1, arg);
8591 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8593 /* Restore floating-point state. */
8594 gfc_restore_fp_state (&se->post, fpstate);
8598 /* Generate code for IEEE_REM. */
8600 static void
8601 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8603 tree args[2], decl, call, fpstate;
8604 int argprec;
8606 conv_ieee_function_args (se, expr, args, 2);
8608 /* If arguments have unequal size, convert them to the larger. */
8609 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8610 > TYPE_PRECISION (TREE_TYPE (args[1])))
8611 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8612 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8613 > TYPE_PRECISION (TREE_TYPE (args[0])))
8614 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8616 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8617 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8619 /* Save floating-point state. */
8620 fpstate = gfc_save_fp_state (&se->pre);
8622 /* Make the function call. */
8623 call = build_call_expr_loc_array (input_location, decl, 2, args);
8624 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8626 /* Restore floating-point state. */
8627 gfc_restore_fp_state (&se->post, fpstate);
8631 /* Generate code for IEEE_NEXT_AFTER. */
8633 static void
8634 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8636 tree args[2], decl, call, fpstate;
8637 int argprec;
8639 conv_ieee_function_args (se, expr, args, 2);
8641 /* Result has the characteristics of first argument. */
8642 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8643 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8644 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8646 /* Save floating-point state. */
8647 fpstate = gfc_save_fp_state (&se->pre);
8649 /* Make the function call. */
8650 call = build_call_expr_loc_array (input_location, decl, 2, args);
8651 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8653 /* Restore floating-point state. */
8654 gfc_restore_fp_state (&se->post, fpstate);
8658 /* Generate code for IEEE_SCALB. */
8660 static void
8661 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8663 tree args[2], decl, call, huge, type;
8664 int argprec, n;
8666 conv_ieee_function_args (se, expr, args, 2);
8668 /* Result has the characteristics of first argument. */
8669 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8670 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8672 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8674 /* We need to fold the integer into the range of a C int. */
8675 args[1] = gfc_evaluate_now (args[1], &se->pre);
8676 type = TREE_TYPE (args[1]);
8678 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8679 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8680 gfc_c_int_kind);
8681 huge = fold_convert (type, huge);
8682 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8683 huge);
8684 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8685 fold_build1_loc (input_location, NEGATE_EXPR,
8686 type, huge));
8689 args[1] = fold_convert (integer_type_node, args[1]);
8691 /* Make the function call. */
8692 call = build_call_expr_loc_array (input_location, decl, 2, args);
8693 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8697 /* Generate code for IEEE_COPY_SIGN. */
8699 static void
8700 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8702 tree args[2], decl, sign;
8703 int argprec;
8705 conv_ieee_function_args (se, expr, args, 2);
8707 /* Get the sign of the second argument. */
8708 sign = build_call_expr_loc (input_location,
8709 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8710 1, args[1]);
8711 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8712 sign, integer_zero_node);
8714 /* Create a value of one, with the right sign. */
8715 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8716 sign,
8717 fold_build1_loc (input_location, NEGATE_EXPR,
8718 integer_type_node,
8719 integer_one_node),
8720 integer_one_node);
8721 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8723 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8724 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8726 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8730 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8731 module. */
8733 bool
8734 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8736 const char *name = expr->value.function.name;
8738 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8740 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8741 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8742 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8743 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8744 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8745 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8746 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8747 conv_intrinsic_ieee_is_normal (se, expr);
8748 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8749 conv_intrinsic_ieee_is_negative (se, expr);
8750 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8751 conv_intrinsic_ieee_copy_sign (se, expr);
8752 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8753 conv_intrinsic_ieee_scalb (se, expr);
8754 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8755 conv_intrinsic_ieee_next_after (se, expr);
8756 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8757 conv_intrinsic_ieee_rem (se, expr);
8758 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8759 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8760 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8761 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8762 else
8763 /* It is not among the functions we translate directly. We return
8764 false, so a library function call is emitted. */
8765 return false;
8767 #undef STARTS_WITH
8769 return true;
8773 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8775 static void
8776 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8778 tree arg, res, restype;
8780 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8781 arg = fold_convert (size_type_node, arg);
8782 res = build_call_expr_loc (input_location,
8783 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8784 restype = gfc_typenode_for_spec (&expr->ts);
8785 se->expr = fold_convert (restype, res);
8789 /* Generate code for an intrinsic function. Some map directly to library
8790 calls, others get special handling. In some cases the name of the function
8791 used depends on the type specifiers. */
8793 void
8794 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8796 const char *name;
8797 int lib, kind;
8798 tree fndecl;
8800 name = &expr->value.function.name[2];
8802 if (expr->rank > 0)
8804 lib = gfc_is_intrinsic_libcall (expr);
8805 if (lib != 0)
8807 if (lib == 1)
8808 se->ignore_optional = 1;
8810 switch (expr->value.function.isym->id)
8812 case GFC_ISYM_EOSHIFT:
8813 case GFC_ISYM_PACK:
8814 case GFC_ISYM_RESHAPE:
8815 /* For all of those the first argument specifies the type and the
8816 third is optional. */
8817 conv_generic_with_optional_char_arg (se, expr, 1, 3);
8818 break;
8820 case GFC_ISYM_MINLOC:
8821 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
8822 break;
8824 case GFC_ISYM_MAXLOC:
8825 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
8826 break;
8828 case GFC_ISYM_SHAPE:
8829 gfc_conv_intrinsic_shape (se, expr);
8830 break;
8832 default:
8833 gfc_conv_intrinsic_funcall (se, expr);
8834 break;
8837 return;
8841 switch (expr->value.function.isym->id)
8843 case GFC_ISYM_NONE:
8844 gcc_unreachable ();
8846 case GFC_ISYM_REPEAT:
8847 gfc_conv_intrinsic_repeat (se, expr);
8848 break;
8850 case GFC_ISYM_TRIM:
8851 gfc_conv_intrinsic_trim (se, expr);
8852 break;
8854 case GFC_ISYM_SC_KIND:
8855 gfc_conv_intrinsic_sc_kind (se, expr);
8856 break;
8858 case GFC_ISYM_SI_KIND:
8859 gfc_conv_intrinsic_si_kind (se, expr);
8860 break;
8862 case GFC_ISYM_SR_KIND:
8863 gfc_conv_intrinsic_sr_kind (se, expr);
8864 break;
8866 case GFC_ISYM_EXPONENT:
8867 gfc_conv_intrinsic_exponent (se, expr);
8868 break;
8870 case GFC_ISYM_SCAN:
8871 kind = expr->value.function.actual->expr->ts.kind;
8872 if (kind == 1)
8873 fndecl = gfor_fndecl_string_scan;
8874 else if (kind == 4)
8875 fndecl = gfor_fndecl_string_scan_char4;
8876 else
8877 gcc_unreachable ();
8879 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8880 break;
8882 case GFC_ISYM_VERIFY:
8883 kind = expr->value.function.actual->expr->ts.kind;
8884 if (kind == 1)
8885 fndecl = gfor_fndecl_string_verify;
8886 else if (kind == 4)
8887 fndecl = gfor_fndecl_string_verify_char4;
8888 else
8889 gcc_unreachable ();
8891 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8892 break;
8894 case GFC_ISYM_ALLOCATED:
8895 gfc_conv_allocated (se, expr);
8896 break;
8898 case GFC_ISYM_ASSOCIATED:
8899 gfc_conv_associated(se, expr);
8900 break;
8902 case GFC_ISYM_SAME_TYPE_AS:
8903 gfc_conv_same_type_as (se, expr);
8904 break;
8906 case GFC_ISYM_ABS:
8907 gfc_conv_intrinsic_abs (se, expr);
8908 break;
8910 case GFC_ISYM_ADJUSTL:
8911 if (expr->ts.kind == 1)
8912 fndecl = gfor_fndecl_adjustl;
8913 else if (expr->ts.kind == 4)
8914 fndecl = gfor_fndecl_adjustl_char4;
8915 else
8916 gcc_unreachable ();
8918 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8919 break;
8921 case GFC_ISYM_ADJUSTR:
8922 if (expr->ts.kind == 1)
8923 fndecl = gfor_fndecl_adjustr;
8924 else if (expr->ts.kind == 4)
8925 fndecl = gfor_fndecl_adjustr_char4;
8926 else
8927 gcc_unreachable ();
8929 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8930 break;
8932 case GFC_ISYM_AIMAG:
8933 gfc_conv_intrinsic_imagpart (se, expr);
8934 break;
8936 case GFC_ISYM_AINT:
8937 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
8938 break;
8940 case GFC_ISYM_ALL:
8941 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
8942 break;
8944 case GFC_ISYM_ANINT:
8945 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
8946 break;
8948 case GFC_ISYM_AND:
8949 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8950 break;
8952 case GFC_ISYM_ANY:
8953 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
8954 break;
8956 case GFC_ISYM_BTEST:
8957 gfc_conv_intrinsic_btest (se, expr);
8958 break;
8960 case GFC_ISYM_BGE:
8961 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
8962 break;
8964 case GFC_ISYM_BGT:
8965 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
8966 break;
8968 case GFC_ISYM_BLE:
8969 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
8970 break;
8972 case GFC_ISYM_BLT:
8973 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
8974 break;
8976 case GFC_ISYM_C_ASSOCIATED:
8977 case GFC_ISYM_C_FUNLOC:
8978 case GFC_ISYM_C_LOC:
8979 conv_isocbinding_function (se, expr);
8980 break;
8982 case GFC_ISYM_ACHAR:
8983 case GFC_ISYM_CHAR:
8984 gfc_conv_intrinsic_char (se, expr);
8985 break;
8987 case GFC_ISYM_CONVERSION:
8988 case GFC_ISYM_REAL:
8989 case GFC_ISYM_LOGICAL:
8990 case GFC_ISYM_DBLE:
8991 gfc_conv_intrinsic_conversion (se, expr);
8992 break;
8994 /* Integer conversions are handled separately to make sure we get the
8995 correct rounding mode. */
8996 case GFC_ISYM_INT:
8997 case GFC_ISYM_INT2:
8998 case GFC_ISYM_INT8:
8999 case GFC_ISYM_LONG:
9000 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
9001 break;
9003 case GFC_ISYM_NINT:
9004 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
9005 break;
9007 case GFC_ISYM_CEILING:
9008 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
9009 break;
9011 case GFC_ISYM_FLOOR:
9012 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
9013 break;
9015 case GFC_ISYM_MOD:
9016 gfc_conv_intrinsic_mod (se, expr, 0);
9017 break;
9019 case GFC_ISYM_MODULO:
9020 gfc_conv_intrinsic_mod (se, expr, 1);
9021 break;
9023 case GFC_ISYM_CAF_GET:
9024 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
9025 false, NULL);
9026 break;
9028 case GFC_ISYM_CMPLX:
9029 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
9030 break;
9032 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
9033 gfc_conv_intrinsic_iargc (se, expr);
9034 break;
9036 case GFC_ISYM_COMPLEX:
9037 gfc_conv_intrinsic_cmplx (se, expr, 1);
9038 break;
9040 case GFC_ISYM_CONJG:
9041 gfc_conv_intrinsic_conjg (se, expr);
9042 break;
9044 case GFC_ISYM_COUNT:
9045 gfc_conv_intrinsic_count (se, expr);
9046 break;
9048 case GFC_ISYM_CTIME:
9049 gfc_conv_intrinsic_ctime (se, expr);
9050 break;
9052 case GFC_ISYM_DIM:
9053 gfc_conv_intrinsic_dim (se, expr);
9054 break;
9056 case GFC_ISYM_DOT_PRODUCT:
9057 gfc_conv_intrinsic_dot_product (se, expr);
9058 break;
9060 case GFC_ISYM_DPROD:
9061 gfc_conv_intrinsic_dprod (se, expr);
9062 break;
9064 case GFC_ISYM_DSHIFTL:
9065 gfc_conv_intrinsic_dshift (se, expr, true);
9066 break;
9068 case GFC_ISYM_DSHIFTR:
9069 gfc_conv_intrinsic_dshift (se, expr, false);
9070 break;
9072 case GFC_ISYM_FDATE:
9073 gfc_conv_intrinsic_fdate (se, expr);
9074 break;
9076 case GFC_ISYM_FRACTION:
9077 gfc_conv_intrinsic_fraction (se, expr);
9078 break;
9080 case GFC_ISYM_IALL:
9081 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9082 break;
9084 case GFC_ISYM_IAND:
9085 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9086 break;
9088 case GFC_ISYM_IANY:
9089 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9090 break;
9092 case GFC_ISYM_IBCLR:
9093 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9094 break;
9096 case GFC_ISYM_IBITS:
9097 gfc_conv_intrinsic_ibits (se, expr);
9098 break;
9100 case GFC_ISYM_IBSET:
9101 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9102 break;
9104 case GFC_ISYM_IACHAR:
9105 case GFC_ISYM_ICHAR:
9106 /* We assume ASCII character sequence. */
9107 gfc_conv_intrinsic_ichar (se, expr);
9108 break;
9110 case GFC_ISYM_IARGC:
9111 gfc_conv_intrinsic_iargc (se, expr);
9112 break;
9114 case GFC_ISYM_IEOR:
9115 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9116 break;
9118 case GFC_ISYM_INDEX:
9119 kind = expr->value.function.actual->expr->ts.kind;
9120 if (kind == 1)
9121 fndecl = gfor_fndecl_string_index;
9122 else if (kind == 4)
9123 fndecl = gfor_fndecl_string_index_char4;
9124 else
9125 gcc_unreachable ();
9127 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9128 break;
9130 case GFC_ISYM_IOR:
9131 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9132 break;
9134 case GFC_ISYM_IPARITY:
9135 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9136 break;
9138 case GFC_ISYM_IS_IOSTAT_END:
9139 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9140 break;
9142 case GFC_ISYM_IS_IOSTAT_EOR:
9143 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9144 break;
9146 case GFC_ISYM_ISNAN:
9147 gfc_conv_intrinsic_isnan (se, expr);
9148 break;
9150 case GFC_ISYM_KILL:
9151 conv_intrinsic_kill (se, expr);
9152 break;
9154 case GFC_ISYM_LSHIFT:
9155 gfc_conv_intrinsic_shift (se, expr, false, false);
9156 break;
9158 case GFC_ISYM_RSHIFT:
9159 gfc_conv_intrinsic_shift (se, expr, true, true);
9160 break;
9162 case GFC_ISYM_SHIFTA:
9163 gfc_conv_intrinsic_shift (se, expr, true, true);
9164 break;
9166 case GFC_ISYM_SHIFTL:
9167 gfc_conv_intrinsic_shift (se, expr, false, false);
9168 break;
9170 case GFC_ISYM_SHIFTR:
9171 gfc_conv_intrinsic_shift (se, expr, true, false);
9172 break;
9174 case GFC_ISYM_ISHFT:
9175 gfc_conv_intrinsic_ishft (se, expr);
9176 break;
9178 case GFC_ISYM_ISHFTC:
9179 gfc_conv_intrinsic_ishftc (se, expr);
9180 break;
9182 case GFC_ISYM_LEADZ:
9183 gfc_conv_intrinsic_leadz (se, expr);
9184 break;
9186 case GFC_ISYM_TRAILZ:
9187 gfc_conv_intrinsic_trailz (se, expr);
9188 break;
9190 case GFC_ISYM_POPCNT:
9191 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9192 break;
9194 case GFC_ISYM_POPPAR:
9195 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9196 break;
9198 case GFC_ISYM_LBOUND:
9199 gfc_conv_intrinsic_bound (se, expr, 0);
9200 break;
9202 case GFC_ISYM_LCOBOUND:
9203 conv_intrinsic_cobound (se, expr);
9204 break;
9206 case GFC_ISYM_TRANSPOSE:
9207 /* The scalarizer has already been set up for reversed dimension access
9208 order ; now we just get the argument value normally. */
9209 gfc_conv_expr (se, expr->value.function.actual->expr);
9210 break;
9212 case GFC_ISYM_LEN:
9213 gfc_conv_intrinsic_len (se, expr);
9214 break;
9216 case GFC_ISYM_LEN_TRIM:
9217 gfc_conv_intrinsic_len_trim (se, expr);
9218 break;
9220 case GFC_ISYM_LGE:
9221 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9222 break;
9224 case GFC_ISYM_LGT:
9225 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9226 break;
9228 case GFC_ISYM_LLE:
9229 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9230 break;
9232 case GFC_ISYM_LLT:
9233 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9234 break;
9236 case GFC_ISYM_MALLOC:
9237 gfc_conv_intrinsic_malloc (se, expr);
9238 break;
9240 case GFC_ISYM_MASKL:
9241 gfc_conv_intrinsic_mask (se, expr, 1);
9242 break;
9244 case GFC_ISYM_MASKR:
9245 gfc_conv_intrinsic_mask (se, expr, 0);
9246 break;
9248 case GFC_ISYM_MAX:
9249 if (expr->ts.type == BT_CHARACTER)
9250 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9251 else
9252 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9253 break;
9255 case GFC_ISYM_MAXLOC:
9256 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9257 break;
9259 case GFC_ISYM_MAXVAL:
9260 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9261 break;
9263 case GFC_ISYM_MERGE:
9264 gfc_conv_intrinsic_merge (se, expr);
9265 break;
9267 case GFC_ISYM_MERGE_BITS:
9268 gfc_conv_intrinsic_merge_bits (se, expr);
9269 break;
9271 case GFC_ISYM_MIN:
9272 if (expr->ts.type == BT_CHARACTER)
9273 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9274 else
9275 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9276 break;
9278 case GFC_ISYM_MINLOC:
9279 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9280 break;
9282 case GFC_ISYM_MINVAL:
9283 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9284 break;
9286 case GFC_ISYM_NEAREST:
9287 gfc_conv_intrinsic_nearest (se, expr);
9288 break;
9290 case GFC_ISYM_NORM2:
9291 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9292 break;
9294 case GFC_ISYM_NOT:
9295 gfc_conv_intrinsic_not (se, expr);
9296 break;
9298 case GFC_ISYM_OR:
9299 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9300 break;
9302 case GFC_ISYM_PARITY:
9303 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9304 break;
9306 case GFC_ISYM_PRESENT:
9307 gfc_conv_intrinsic_present (se, expr);
9308 break;
9310 case GFC_ISYM_PRODUCT:
9311 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9312 break;
9314 case GFC_ISYM_RANK:
9315 gfc_conv_intrinsic_rank (se, expr);
9316 break;
9318 case GFC_ISYM_RRSPACING:
9319 gfc_conv_intrinsic_rrspacing (se, expr);
9320 break;
9322 case GFC_ISYM_SET_EXPONENT:
9323 gfc_conv_intrinsic_set_exponent (se, expr);
9324 break;
9326 case GFC_ISYM_SCALE:
9327 gfc_conv_intrinsic_scale (se, expr);
9328 break;
9330 case GFC_ISYM_SIGN:
9331 gfc_conv_intrinsic_sign (se, expr);
9332 break;
9334 case GFC_ISYM_SIZE:
9335 gfc_conv_intrinsic_size (se, expr);
9336 break;
9338 case GFC_ISYM_SIZEOF:
9339 case GFC_ISYM_C_SIZEOF:
9340 gfc_conv_intrinsic_sizeof (se, expr);
9341 break;
9343 case GFC_ISYM_STORAGE_SIZE:
9344 gfc_conv_intrinsic_storage_size (se, expr);
9345 break;
9347 case GFC_ISYM_SPACING:
9348 gfc_conv_intrinsic_spacing (se, expr);
9349 break;
9351 case GFC_ISYM_STRIDE:
9352 conv_intrinsic_stride (se, expr);
9353 break;
9355 case GFC_ISYM_SUM:
9356 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9357 break;
9359 case GFC_ISYM_TEAM_NUMBER:
9360 conv_intrinsic_team_number (se, expr);
9361 break;
9363 case GFC_ISYM_TRANSFER:
9364 if (se->ss && se->ss->info->useflags)
9365 /* Access the previously obtained result. */
9366 gfc_conv_tmp_array_ref (se);
9367 else
9368 gfc_conv_intrinsic_transfer (se, expr);
9369 break;
9371 case GFC_ISYM_TTYNAM:
9372 gfc_conv_intrinsic_ttynam (se, expr);
9373 break;
9375 case GFC_ISYM_UBOUND:
9376 gfc_conv_intrinsic_bound (se, expr, 1);
9377 break;
9379 case GFC_ISYM_UCOBOUND:
9380 conv_intrinsic_cobound (se, expr);
9381 break;
9383 case GFC_ISYM_XOR:
9384 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9385 break;
9387 case GFC_ISYM_LOC:
9388 gfc_conv_intrinsic_loc (se, expr);
9389 break;
9391 case GFC_ISYM_THIS_IMAGE:
9392 /* For num_images() == 1, handle as LCOBOUND. */
9393 if (expr->value.function.actual->expr
9394 && flag_coarray == GFC_FCOARRAY_SINGLE)
9395 conv_intrinsic_cobound (se, expr);
9396 else
9397 trans_this_image (se, expr);
9398 break;
9400 case GFC_ISYM_IMAGE_INDEX:
9401 trans_image_index (se, expr);
9402 break;
9404 case GFC_ISYM_IMAGE_STATUS:
9405 conv_intrinsic_image_status (se, expr);
9406 break;
9408 case GFC_ISYM_NUM_IMAGES:
9409 trans_num_images (se, expr);
9410 break;
9412 case GFC_ISYM_ACCESS:
9413 case GFC_ISYM_CHDIR:
9414 case GFC_ISYM_CHMOD:
9415 case GFC_ISYM_DTIME:
9416 case GFC_ISYM_ETIME:
9417 case GFC_ISYM_EXTENDS_TYPE_OF:
9418 case GFC_ISYM_FGET:
9419 case GFC_ISYM_FGETC:
9420 case GFC_ISYM_FNUM:
9421 case GFC_ISYM_FPUT:
9422 case GFC_ISYM_FPUTC:
9423 case GFC_ISYM_FSTAT:
9424 case GFC_ISYM_FTELL:
9425 case GFC_ISYM_GETCWD:
9426 case GFC_ISYM_GETGID:
9427 case GFC_ISYM_GETPID:
9428 case GFC_ISYM_GETUID:
9429 case GFC_ISYM_HOSTNM:
9430 case GFC_ISYM_IERRNO:
9431 case GFC_ISYM_IRAND:
9432 case GFC_ISYM_ISATTY:
9433 case GFC_ISYM_JN2:
9434 case GFC_ISYM_LINK:
9435 case GFC_ISYM_LSTAT:
9436 case GFC_ISYM_MATMUL:
9437 case GFC_ISYM_MCLOCK:
9438 case GFC_ISYM_MCLOCK8:
9439 case GFC_ISYM_RAND:
9440 case GFC_ISYM_RENAME:
9441 case GFC_ISYM_SECOND:
9442 case GFC_ISYM_SECNDS:
9443 case GFC_ISYM_SIGNAL:
9444 case GFC_ISYM_STAT:
9445 case GFC_ISYM_SYMLNK:
9446 case GFC_ISYM_SYSTEM:
9447 case GFC_ISYM_TIME:
9448 case GFC_ISYM_TIME8:
9449 case GFC_ISYM_UMASK:
9450 case GFC_ISYM_UNLINK:
9451 case GFC_ISYM_YN2:
9452 gfc_conv_intrinsic_funcall (se, expr);
9453 break;
9455 case GFC_ISYM_EOSHIFT:
9456 case GFC_ISYM_PACK:
9457 case GFC_ISYM_RESHAPE:
9458 /* For those, expr->rank should always be >0 and thus the if above the
9459 switch should have matched. */
9460 gcc_unreachable ();
9461 break;
9463 default:
9464 gfc_conv_intrinsic_lib_function (se, expr);
9465 break;
9470 static gfc_ss *
9471 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9473 gfc_ss *arg_ss, *tmp_ss;
9474 gfc_actual_arglist *arg;
9476 arg = expr->value.function.actual;
9478 gcc_assert (arg->expr);
9480 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9481 gcc_assert (arg_ss != gfc_ss_terminator);
9483 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9485 if (tmp_ss->info->type != GFC_SS_SCALAR
9486 && tmp_ss->info->type != GFC_SS_REFERENCE)
9488 gcc_assert (tmp_ss->dimen == 2);
9490 /* We just invert dimensions. */
9491 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9494 /* Stop when tmp_ss points to the last valid element of the chain... */
9495 if (tmp_ss->next == gfc_ss_terminator)
9496 break;
9499 /* ... so that we can attach the rest of the chain to it. */
9500 tmp_ss->next = ss;
9502 return arg_ss;
9506 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9507 This has the side effect of reversing the nested list, so there is no
9508 need to call gfc_reverse_ss on it (the given list is assumed not to be
9509 reversed yet). */
9511 static gfc_ss *
9512 nest_loop_dimension (gfc_ss *ss, int dim)
9514 int ss_dim, i;
9515 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9516 gfc_loopinfo *new_loop;
9518 gcc_assert (ss != gfc_ss_terminator);
9520 for (; ss != gfc_ss_terminator; ss = ss->next)
9522 new_ss = gfc_get_ss ();
9523 new_ss->next = prev_ss;
9524 new_ss->parent = ss;
9525 new_ss->info = ss->info;
9526 new_ss->info->refcount++;
9527 if (ss->dimen != 0)
9529 gcc_assert (ss->info->type != GFC_SS_SCALAR
9530 && ss->info->type != GFC_SS_REFERENCE);
9532 new_ss->dimen = 1;
9533 new_ss->dim[0] = ss->dim[dim];
9535 gcc_assert (dim < ss->dimen);
9537 ss_dim = --ss->dimen;
9538 for (i = dim; i < ss_dim; i++)
9539 ss->dim[i] = ss->dim[i + 1];
9541 ss->dim[ss_dim] = 0;
9543 prev_ss = new_ss;
9545 if (ss->nested_ss)
9547 ss->nested_ss->parent = new_ss;
9548 new_ss->nested_ss = ss->nested_ss;
9550 ss->nested_ss = new_ss;
9553 new_loop = gfc_get_loopinfo ();
9554 gfc_init_loopinfo (new_loop);
9556 gcc_assert (prev_ss != NULL);
9557 gcc_assert (prev_ss != gfc_ss_terminator);
9558 gfc_add_ss_to_loop (new_loop, prev_ss);
9559 return new_ss->parent;
9563 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9564 is to be inlined. */
9566 static gfc_ss *
9567 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9569 gfc_ss *tmp_ss, *tail, *array_ss;
9570 gfc_actual_arglist *arg1, *arg2, *arg3;
9571 int sum_dim;
9572 bool scalar_mask = false;
9574 /* The rank of the result will be determined later. */
9575 arg1 = expr->value.function.actual;
9576 arg2 = arg1->next;
9577 arg3 = arg2->next;
9578 gcc_assert (arg3 != NULL);
9580 if (expr->rank == 0)
9581 return ss;
9583 tmp_ss = gfc_ss_terminator;
9585 if (arg3->expr)
9587 gfc_ss *mask_ss;
9589 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9590 if (mask_ss == tmp_ss)
9591 scalar_mask = 1;
9593 tmp_ss = mask_ss;
9596 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9597 gcc_assert (array_ss != tmp_ss);
9599 /* Odd thing: If the mask is scalar, it is used by the frontend after
9600 the array (to make an if around the nested loop). Thus it shall
9601 be after array_ss once the gfc_ss list is reversed. */
9602 if (scalar_mask)
9603 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9604 else
9605 tmp_ss = array_ss;
9607 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9608 chain. */
9609 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9610 tail = nest_loop_dimension (tmp_ss, sum_dim);
9611 tail->next = ss;
9613 return tmp_ss;
9617 static gfc_ss *
9618 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9621 switch (expr->value.function.isym->id)
9623 case GFC_ISYM_PRODUCT:
9624 case GFC_ISYM_SUM:
9625 return walk_inline_intrinsic_arith (ss, expr);
9627 case GFC_ISYM_TRANSPOSE:
9628 return walk_inline_intrinsic_transpose (ss, expr);
9630 default:
9631 gcc_unreachable ();
9633 gcc_unreachable ();
9637 /* This generates code to execute before entering the scalarization loop.
9638 Currently does nothing. */
9640 void
9641 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9643 switch (ss->info->expr->value.function.isym->id)
9645 case GFC_ISYM_UBOUND:
9646 case GFC_ISYM_LBOUND:
9647 case GFC_ISYM_UCOBOUND:
9648 case GFC_ISYM_LCOBOUND:
9649 case GFC_ISYM_THIS_IMAGE:
9650 break;
9652 default:
9653 gcc_unreachable ();
9658 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9659 are expanded into code inside the scalarization loop. */
9661 static gfc_ss *
9662 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9664 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9665 gfc_add_class_array_ref (expr->value.function.actual->expr);
9667 /* The two argument version returns a scalar. */
9668 if (expr->value.function.actual->next->expr)
9669 return ss;
9671 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9675 /* Walk an intrinsic array libcall. */
9677 static gfc_ss *
9678 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9680 gcc_assert (expr->rank > 0);
9681 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9685 /* Return whether the function call expression EXPR will be expanded
9686 inline by gfc_conv_intrinsic_function. */
9688 bool
9689 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9691 gfc_actual_arglist *args;
9693 if (!expr->value.function.isym)
9694 return false;
9696 switch (expr->value.function.isym->id)
9698 case GFC_ISYM_PRODUCT:
9699 case GFC_ISYM_SUM:
9700 /* Disable inline expansion if code size matters. */
9701 if (optimize_size)
9702 return false;
9704 args = expr->value.function.actual;
9705 /* We need to be able to subset the SUM argument at compile-time. */
9706 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9707 return false;
9709 return true;
9711 case GFC_ISYM_TRANSPOSE:
9712 return true;
9714 default:
9715 return false;
9720 /* Returns nonzero if the specified intrinsic function call maps directly to
9721 an external library call. Should only be used for functions that return
9722 arrays. */
9725 gfc_is_intrinsic_libcall (gfc_expr * expr)
9727 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9728 gcc_assert (expr->rank > 0);
9730 if (gfc_inline_intrinsic_function_p (expr))
9731 return 0;
9733 switch (expr->value.function.isym->id)
9735 case GFC_ISYM_ALL:
9736 case GFC_ISYM_ANY:
9737 case GFC_ISYM_COUNT:
9738 case GFC_ISYM_JN2:
9739 case GFC_ISYM_IANY:
9740 case GFC_ISYM_IALL:
9741 case GFC_ISYM_IPARITY:
9742 case GFC_ISYM_MATMUL:
9743 case GFC_ISYM_MAXLOC:
9744 case GFC_ISYM_MAXVAL:
9745 case GFC_ISYM_MINLOC:
9746 case GFC_ISYM_MINVAL:
9747 case GFC_ISYM_NORM2:
9748 case GFC_ISYM_PARITY:
9749 case GFC_ISYM_PRODUCT:
9750 case GFC_ISYM_SUM:
9751 case GFC_ISYM_SHAPE:
9752 case GFC_ISYM_SPREAD:
9753 case GFC_ISYM_YN2:
9754 /* Ignore absent optional parameters. */
9755 return 1;
9757 case GFC_ISYM_CSHIFT:
9758 case GFC_ISYM_EOSHIFT:
9759 case GFC_ISYM_GET_TEAM:
9760 case GFC_ISYM_FAILED_IMAGES:
9761 case GFC_ISYM_STOPPED_IMAGES:
9762 case GFC_ISYM_PACK:
9763 case GFC_ISYM_RESHAPE:
9764 case GFC_ISYM_UNPACK:
9765 /* Pass absent optional parameters. */
9766 return 2;
9768 default:
9769 return 0;
9773 /* Walk an intrinsic function. */
9774 gfc_ss *
9775 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9776 gfc_intrinsic_sym * isym)
9778 gcc_assert (isym);
9780 if (isym->elemental)
9781 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9782 NULL, GFC_SS_SCALAR);
9784 if (expr->rank == 0)
9785 return ss;
9787 if (gfc_inline_intrinsic_function_p (expr))
9788 return walk_inline_intrinsic_function (ss, expr);
9790 if (gfc_is_intrinsic_libcall (expr))
9791 return gfc_walk_intrinsic_libfunc (ss, expr);
9793 /* Special cases. */
9794 switch (isym->id)
9796 case GFC_ISYM_LBOUND:
9797 case GFC_ISYM_LCOBOUND:
9798 case GFC_ISYM_UBOUND:
9799 case GFC_ISYM_UCOBOUND:
9800 case GFC_ISYM_THIS_IMAGE:
9801 return gfc_walk_intrinsic_bound (ss, expr);
9803 case GFC_ISYM_TRANSFER:
9804 case GFC_ISYM_CAF_GET:
9805 return gfc_walk_intrinsic_libfunc (ss, expr);
9807 default:
9808 /* This probably meant someone forgot to add an intrinsic to the above
9809 list(s) when they implemented it, or something's gone horribly
9810 wrong. */
9811 gcc_unreachable ();
9816 static tree
9817 conv_co_collective (gfc_code *code)
9819 gfc_se argse;
9820 stmtblock_t block, post_block;
9821 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
9822 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
9824 gfc_start_block (&block);
9825 gfc_init_block (&post_block);
9827 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
9829 opr_expr = code->ext.actual->next->expr;
9830 image_idx_expr = code->ext.actual->next->next->expr;
9831 stat_expr = code->ext.actual->next->next->next->expr;
9832 errmsg_expr = code->ext.actual->next->next->next->next->expr;
9834 else
9836 opr_expr = NULL;
9837 image_idx_expr = code->ext.actual->next->expr;
9838 stat_expr = code->ext.actual->next->next->expr;
9839 errmsg_expr = code->ext.actual->next->next->next->expr;
9842 /* stat. */
9843 if (stat_expr)
9845 gfc_init_se (&argse, NULL);
9846 gfc_conv_expr (&argse, stat_expr);
9847 gfc_add_block_to_block (&block, &argse.pre);
9848 gfc_add_block_to_block (&post_block, &argse.post);
9849 stat = argse.expr;
9850 if (flag_coarray != GFC_FCOARRAY_SINGLE)
9851 stat = gfc_build_addr_expr (NULL_TREE, stat);
9853 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
9854 stat = NULL_TREE;
9855 else
9856 stat = null_pointer_node;
9858 /* Early exit for GFC_FCOARRAY_SINGLE. */
9859 if (flag_coarray == GFC_FCOARRAY_SINGLE)
9861 if (stat != NULL_TREE)
9862 gfc_add_modify (&block, stat,
9863 fold_convert (TREE_TYPE (stat), integer_zero_node));
9864 return gfc_finish_block (&block);
9867 /* Handle the array. */
9868 gfc_init_se (&argse, NULL);
9869 if (code->ext.actual->expr->rank == 0)
9871 symbol_attribute attr;
9872 gfc_clear_attr (&attr);
9873 gfc_init_se (&argse, NULL);
9874 gfc_conv_expr (&argse, code->ext.actual->expr);
9875 gfc_add_block_to_block (&block, &argse.pre);
9876 gfc_add_block_to_block (&post_block, &argse.post);
9877 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
9878 array = gfc_build_addr_expr (NULL_TREE, array);
9880 else
9882 argse.want_pointer = 1;
9883 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
9884 array = argse.expr;
9886 gfc_add_block_to_block (&block, &argse.pre);
9887 gfc_add_block_to_block (&post_block, &argse.post);
9889 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
9890 strlen = argse.string_length;
9891 else
9892 strlen = integer_zero_node;
9894 /* image_index. */
9895 if (image_idx_expr)
9897 gfc_init_se (&argse, NULL);
9898 gfc_conv_expr (&argse, image_idx_expr);
9899 gfc_add_block_to_block (&block, &argse.pre);
9900 gfc_add_block_to_block (&post_block, &argse.post);
9901 image_index = fold_convert (integer_type_node, argse.expr);
9903 else
9904 image_index = integer_zero_node;
9906 /* errmsg. */
9907 if (errmsg_expr)
9909 gfc_init_se (&argse, NULL);
9910 gfc_conv_expr (&argse, errmsg_expr);
9911 gfc_add_block_to_block (&block, &argse.pre);
9912 gfc_add_block_to_block (&post_block, &argse.post);
9913 errmsg = argse.expr;
9914 errmsg_len = fold_convert (size_type_node, argse.string_length);
9916 else
9918 errmsg = null_pointer_node;
9919 errmsg_len = build_zero_cst (size_type_node);
9922 /* Generate the function call. */
9923 switch (code->resolved_isym->id)
9925 case GFC_ISYM_CO_BROADCAST:
9926 fndecl = gfor_fndecl_co_broadcast;
9927 break;
9928 case GFC_ISYM_CO_MAX:
9929 fndecl = gfor_fndecl_co_max;
9930 break;
9931 case GFC_ISYM_CO_MIN:
9932 fndecl = gfor_fndecl_co_min;
9933 break;
9934 case GFC_ISYM_CO_REDUCE:
9935 fndecl = gfor_fndecl_co_reduce;
9936 break;
9937 case GFC_ISYM_CO_SUM:
9938 fndecl = gfor_fndecl_co_sum;
9939 break;
9940 default:
9941 gcc_unreachable ();
9944 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
9945 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
9946 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
9947 image_index, stat, errmsg, errmsg_len);
9948 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
9949 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
9950 stat, errmsg, strlen, errmsg_len);
9951 else
9953 tree opr, opr_flags;
9955 // FIXME: Handle TS29113's bind(C) strings with descriptor.
9956 int opr_flag_int;
9957 if (gfc_is_proc_ptr_comp (opr_expr))
9959 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
9960 opr_flag_int = sym->attr.dimension
9961 || (sym->ts.type == BT_CHARACTER
9962 && !sym->attr.is_bind_c)
9963 ? GFC_CAF_BYREF : 0;
9964 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9965 && !sym->attr.is_bind_c
9966 ? GFC_CAF_HIDDENLEN : 0;
9967 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
9969 else
9971 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
9972 ? GFC_CAF_BYREF : 0;
9973 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9974 && !opr_expr->symtree->n.sym->attr.is_bind_c
9975 ? GFC_CAF_HIDDENLEN : 0;
9976 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
9977 ? GFC_CAF_ARG_VALUE : 0;
9979 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
9980 gfc_conv_expr (&argse, opr_expr);
9981 opr = argse.expr;
9982 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
9983 image_index, stat, errmsg, strlen, errmsg_len);
9986 gfc_add_expr_to_block (&block, fndecl);
9987 gfc_add_block_to_block (&block, &post_block);
9989 return gfc_finish_block (&block);
9993 static tree
9994 conv_intrinsic_atomic_op (gfc_code *code)
9996 gfc_se argse;
9997 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
9998 stmtblock_t block, post_block;
9999 gfc_expr *atom_expr = code->ext.actual->expr;
10000 gfc_expr *stat_expr;
10001 built_in_function fn;
10003 if (atom_expr->expr_type == EXPR_FUNCTION
10004 && atom_expr->value.function.isym
10005 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10006 atom_expr = atom_expr->value.function.actual->expr;
10008 gfc_start_block (&block);
10009 gfc_init_block (&post_block);
10011 gfc_init_se (&argse, NULL);
10012 argse.want_pointer = 1;
10013 gfc_conv_expr (&argse, atom_expr);
10014 gfc_add_block_to_block (&block, &argse.pre);
10015 gfc_add_block_to_block (&post_block, &argse.post);
10016 atom = argse.expr;
10018 gfc_init_se (&argse, NULL);
10019 if (flag_coarray == GFC_FCOARRAY_LIB
10020 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
10021 argse.want_pointer = 1;
10022 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10023 gfc_add_block_to_block (&block, &argse.pre);
10024 gfc_add_block_to_block (&post_block, &argse.post);
10025 value = argse.expr;
10027 switch (code->resolved_isym->id)
10029 case GFC_ISYM_ATOMIC_ADD:
10030 case GFC_ISYM_ATOMIC_AND:
10031 case GFC_ISYM_ATOMIC_DEF:
10032 case GFC_ISYM_ATOMIC_OR:
10033 case GFC_ISYM_ATOMIC_XOR:
10034 stat_expr = code->ext.actual->next->next->expr;
10035 if (flag_coarray == GFC_FCOARRAY_LIB)
10036 old = null_pointer_node;
10037 break;
10038 default:
10039 gfc_init_se (&argse, NULL);
10040 if (flag_coarray == GFC_FCOARRAY_LIB)
10041 argse.want_pointer = 1;
10042 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10043 gfc_add_block_to_block (&block, &argse.pre);
10044 gfc_add_block_to_block (&post_block, &argse.post);
10045 old = argse.expr;
10046 stat_expr = code->ext.actual->next->next->next->expr;
10049 /* STAT= */
10050 if (stat_expr != NULL)
10052 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
10053 gfc_init_se (&argse, NULL);
10054 if (flag_coarray == GFC_FCOARRAY_LIB)
10055 argse.want_pointer = 1;
10056 gfc_conv_expr_val (&argse, stat_expr);
10057 gfc_add_block_to_block (&block, &argse.pre);
10058 gfc_add_block_to_block (&post_block, &argse.post);
10059 stat = argse.expr;
10061 else if (flag_coarray == GFC_FCOARRAY_LIB)
10062 stat = null_pointer_node;
10064 if (flag_coarray == GFC_FCOARRAY_LIB)
10066 tree image_index, caf_decl, offset, token;
10067 int op;
10069 switch (code->resolved_isym->id)
10071 case GFC_ISYM_ATOMIC_ADD:
10072 case GFC_ISYM_ATOMIC_FETCH_ADD:
10073 op = (int) GFC_CAF_ATOMIC_ADD;
10074 break;
10075 case GFC_ISYM_ATOMIC_AND:
10076 case GFC_ISYM_ATOMIC_FETCH_AND:
10077 op = (int) GFC_CAF_ATOMIC_AND;
10078 break;
10079 case GFC_ISYM_ATOMIC_OR:
10080 case GFC_ISYM_ATOMIC_FETCH_OR:
10081 op = (int) GFC_CAF_ATOMIC_OR;
10082 break;
10083 case GFC_ISYM_ATOMIC_XOR:
10084 case GFC_ISYM_ATOMIC_FETCH_XOR:
10085 op = (int) GFC_CAF_ATOMIC_XOR;
10086 break;
10087 case GFC_ISYM_ATOMIC_DEF:
10088 op = 0; /* Unused. */
10089 break;
10090 default:
10091 gcc_unreachable ();
10094 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10095 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10096 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10098 if (gfc_is_coindexed (atom_expr))
10099 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10100 else
10101 image_index = integer_zero_node;
10103 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10105 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10106 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10107 value = gfc_build_addr_expr (NULL_TREE, tmp);
10110 gfc_init_se (&argse, NULL);
10111 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10112 atom_expr);
10114 gfc_add_block_to_block (&block, &argse.pre);
10115 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10116 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10117 token, offset, image_index, value, stat,
10118 build_int_cst (integer_type_node,
10119 (int) atom_expr->ts.type),
10120 build_int_cst (integer_type_node,
10121 (int) atom_expr->ts.kind));
10122 else
10123 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10124 build_int_cst (integer_type_node, op),
10125 token, offset, image_index, value, old, stat,
10126 build_int_cst (integer_type_node,
10127 (int) atom_expr->ts.type),
10128 build_int_cst (integer_type_node,
10129 (int) atom_expr->ts.kind));
10131 gfc_add_expr_to_block (&block, tmp);
10132 gfc_add_block_to_block (&block, &argse.post);
10133 gfc_add_block_to_block (&block, &post_block);
10134 return gfc_finish_block (&block);
10138 switch (code->resolved_isym->id)
10140 case GFC_ISYM_ATOMIC_ADD:
10141 case GFC_ISYM_ATOMIC_FETCH_ADD:
10142 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10143 break;
10144 case GFC_ISYM_ATOMIC_AND:
10145 case GFC_ISYM_ATOMIC_FETCH_AND:
10146 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10147 break;
10148 case GFC_ISYM_ATOMIC_DEF:
10149 fn = BUILT_IN_ATOMIC_STORE_N;
10150 break;
10151 case GFC_ISYM_ATOMIC_OR:
10152 case GFC_ISYM_ATOMIC_FETCH_OR:
10153 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10154 break;
10155 case GFC_ISYM_ATOMIC_XOR:
10156 case GFC_ISYM_ATOMIC_FETCH_XOR:
10157 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10158 break;
10159 default:
10160 gcc_unreachable ();
10163 tmp = TREE_TYPE (TREE_TYPE (atom));
10164 fn = (built_in_function) ((int) fn
10165 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10166 + 1);
10167 tmp = builtin_decl_explicit (fn);
10168 tree itype = TREE_TYPE (TREE_TYPE (atom));
10169 tmp = builtin_decl_explicit (fn);
10171 switch (code->resolved_isym->id)
10173 case GFC_ISYM_ATOMIC_ADD:
10174 case GFC_ISYM_ATOMIC_AND:
10175 case GFC_ISYM_ATOMIC_DEF:
10176 case GFC_ISYM_ATOMIC_OR:
10177 case GFC_ISYM_ATOMIC_XOR:
10178 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10179 fold_convert (itype, value),
10180 build_int_cst (NULL, MEMMODEL_RELAXED));
10181 gfc_add_expr_to_block (&block, tmp);
10182 break;
10183 default:
10184 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10185 fold_convert (itype, value),
10186 build_int_cst (NULL, MEMMODEL_RELAXED));
10187 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10188 break;
10191 if (stat != NULL_TREE)
10192 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10193 gfc_add_block_to_block (&block, &post_block);
10194 return gfc_finish_block (&block);
10198 static tree
10199 conv_intrinsic_atomic_ref (gfc_code *code)
10201 gfc_se argse;
10202 tree tmp, atom, value, stat = NULL_TREE;
10203 stmtblock_t block, post_block;
10204 built_in_function fn;
10205 gfc_expr *atom_expr = code->ext.actual->next->expr;
10207 if (atom_expr->expr_type == EXPR_FUNCTION
10208 && atom_expr->value.function.isym
10209 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10210 atom_expr = atom_expr->value.function.actual->expr;
10212 gfc_start_block (&block);
10213 gfc_init_block (&post_block);
10214 gfc_init_se (&argse, NULL);
10215 argse.want_pointer = 1;
10216 gfc_conv_expr (&argse, atom_expr);
10217 gfc_add_block_to_block (&block, &argse.pre);
10218 gfc_add_block_to_block (&post_block, &argse.post);
10219 atom = argse.expr;
10221 gfc_init_se (&argse, NULL);
10222 if (flag_coarray == GFC_FCOARRAY_LIB
10223 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10224 argse.want_pointer = 1;
10225 gfc_conv_expr (&argse, code->ext.actual->expr);
10226 gfc_add_block_to_block (&block, &argse.pre);
10227 gfc_add_block_to_block (&post_block, &argse.post);
10228 value = argse.expr;
10230 /* STAT= */
10231 if (code->ext.actual->next->next->expr != NULL)
10233 gcc_assert (code->ext.actual->next->next->expr->expr_type
10234 == EXPR_VARIABLE);
10235 gfc_init_se (&argse, NULL);
10236 if (flag_coarray == GFC_FCOARRAY_LIB)
10237 argse.want_pointer = 1;
10238 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10239 gfc_add_block_to_block (&block, &argse.pre);
10240 gfc_add_block_to_block (&post_block, &argse.post);
10241 stat = argse.expr;
10243 else if (flag_coarray == GFC_FCOARRAY_LIB)
10244 stat = null_pointer_node;
10246 if (flag_coarray == GFC_FCOARRAY_LIB)
10248 tree image_index, caf_decl, offset, token;
10249 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10251 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10252 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10253 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10255 if (gfc_is_coindexed (atom_expr))
10256 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10257 else
10258 image_index = integer_zero_node;
10260 gfc_init_se (&argse, NULL);
10261 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10262 atom_expr);
10263 gfc_add_block_to_block (&block, &argse.pre);
10265 /* Different type, need type conversion. */
10266 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10268 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10269 orig_value = value;
10270 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10273 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10274 token, offset, image_index, value, stat,
10275 build_int_cst (integer_type_node,
10276 (int) atom_expr->ts.type),
10277 build_int_cst (integer_type_node,
10278 (int) atom_expr->ts.kind));
10279 gfc_add_expr_to_block (&block, tmp);
10280 if (vardecl != NULL_TREE)
10281 gfc_add_modify (&block, orig_value,
10282 fold_convert (TREE_TYPE (orig_value), vardecl));
10283 gfc_add_block_to_block (&block, &argse.post);
10284 gfc_add_block_to_block (&block, &post_block);
10285 return gfc_finish_block (&block);
10288 tmp = TREE_TYPE (TREE_TYPE (atom));
10289 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10290 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10291 + 1);
10292 tmp = builtin_decl_explicit (fn);
10293 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10294 build_int_cst (integer_type_node,
10295 MEMMODEL_RELAXED));
10296 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10298 if (stat != NULL_TREE)
10299 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10300 gfc_add_block_to_block (&block, &post_block);
10301 return gfc_finish_block (&block);
10305 static tree
10306 conv_intrinsic_atomic_cas (gfc_code *code)
10308 gfc_se argse;
10309 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10310 stmtblock_t block, post_block;
10311 built_in_function fn;
10312 gfc_expr *atom_expr = code->ext.actual->expr;
10314 if (atom_expr->expr_type == EXPR_FUNCTION
10315 && atom_expr->value.function.isym
10316 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10317 atom_expr = atom_expr->value.function.actual->expr;
10319 gfc_init_block (&block);
10320 gfc_init_block (&post_block);
10321 gfc_init_se (&argse, NULL);
10322 argse.want_pointer = 1;
10323 gfc_conv_expr (&argse, atom_expr);
10324 atom = argse.expr;
10326 gfc_init_se (&argse, NULL);
10327 if (flag_coarray == GFC_FCOARRAY_LIB)
10328 argse.want_pointer = 1;
10329 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10330 gfc_add_block_to_block (&block, &argse.pre);
10331 gfc_add_block_to_block (&post_block, &argse.post);
10332 old = argse.expr;
10334 gfc_init_se (&argse, NULL);
10335 if (flag_coarray == GFC_FCOARRAY_LIB)
10336 argse.want_pointer = 1;
10337 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10338 gfc_add_block_to_block (&block, &argse.pre);
10339 gfc_add_block_to_block (&post_block, &argse.post);
10340 comp = argse.expr;
10342 gfc_init_se (&argse, NULL);
10343 if (flag_coarray == GFC_FCOARRAY_LIB
10344 && code->ext.actual->next->next->next->expr->ts.kind
10345 == atom_expr->ts.kind)
10346 argse.want_pointer = 1;
10347 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10348 gfc_add_block_to_block (&block, &argse.pre);
10349 gfc_add_block_to_block (&post_block, &argse.post);
10350 new_val = argse.expr;
10352 /* STAT= */
10353 if (code->ext.actual->next->next->next->next->expr != NULL)
10355 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10356 == EXPR_VARIABLE);
10357 gfc_init_se (&argse, NULL);
10358 if (flag_coarray == GFC_FCOARRAY_LIB)
10359 argse.want_pointer = 1;
10360 gfc_conv_expr_val (&argse,
10361 code->ext.actual->next->next->next->next->expr);
10362 gfc_add_block_to_block (&block, &argse.pre);
10363 gfc_add_block_to_block (&post_block, &argse.post);
10364 stat = argse.expr;
10366 else if (flag_coarray == GFC_FCOARRAY_LIB)
10367 stat = null_pointer_node;
10369 if (flag_coarray == GFC_FCOARRAY_LIB)
10371 tree image_index, caf_decl, offset, token;
10373 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10374 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10375 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10377 if (gfc_is_coindexed (atom_expr))
10378 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10379 else
10380 image_index = integer_zero_node;
10382 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10384 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10385 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10386 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10389 /* Convert a constant to a pointer. */
10390 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10392 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10393 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10394 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10397 gfc_init_se (&argse, NULL);
10398 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10399 atom_expr);
10400 gfc_add_block_to_block (&block, &argse.pre);
10402 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10403 token, offset, image_index, old, comp, new_val,
10404 stat, build_int_cst (integer_type_node,
10405 (int) atom_expr->ts.type),
10406 build_int_cst (integer_type_node,
10407 (int) atom_expr->ts.kind));
10408 gfc_add_expr_to_block (&block, tmp);
10409 gfc_add_block_to_block (&block, &argse.post);
10410 gfc_add_block_to_block (&block, &post_block);
10411 return gfc_finish_block (&block);
10414 tmp = TREE_TYPE (TREE_TYPE (atom));
10415 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10416 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10417 + 1);
10418 tmp = builtin_decl_explicit (fn);
10420 gfc_add_modify (&block, old, comp);
10421 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10422 gfc_build_addr_expr (NULL, old),
10423 fold_convert (TREE_TYPE (old), new_val),
10424 boolean_false_node,
10425 build_int_cst (NULL, MEMMODEL_RELAXED),
10426 build_int_cst (NULL, MEMMODEL_RELAXED));
10427 gfc_add_expr_to_block (&block, tmp);
10429 if (stat != NULL_TREE)
10430 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10431 gfc_add_block_to_block (&block, &post_block);
10432 return gfc_finish_block (&block);
10435 static tree
10436 conv_intrinsic_event_query (gfc_code *code)
10438 gfc_se se, argse;
10439 tree stat = NULL_TREE, stat2 = NULL_TREE;
10440 tree count = NULL_TREE, count2 = NULL_TREE;
10442 gfc_expr *event_expr = code->ext.actual->expr;
10444 if (code->ext.actual->next->next->expr)
10446 gcc_assert (code->ext.actual->next->next->expr->expr_type
10447 == EXPR_VARIABLE);
10448 gfc_init_se (&argse, NULL);
10449 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10450 stat = argse.expr;
10452 else if (flag_coarray == GFC_FCOARRAY_LIB)
10453 stat = null_pointer_node;
10455 if (code->ext.actual->next->expr)
10457 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10458 gfc_init_se (&argse, NULL);
10459 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10460 count = argse.expr;
10463 gfc_start_block (&se.pre);
10464 if (flag_coarray == GFC_FCOARRAY_LIB)
10466 tree tmp, token, image_index;
10467 tree index = size_zero_node;
10469 if (event_expr->expr_type == EXPR_FUNCTION
10470 && event_expr->value.function.isym
10471 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10472 event_expr = event_expr->value.function.actual->expr;
10474 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10476 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10477 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10478 != INTMOD_ISO_FORTRAN_ENV
10479 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10480 != ISOFORTRAN_EVENT_TYPE)
10482 gfc_error ("Sorry, the event component of derived type at %L is not "
10483 "yet supported", &event_expr->where);
10484 return NULL_TREE;
10487 if (gfc_is_coindexed (event_expr))
10489 gfc_error ("The event variable at %L shall not be coindexed",
10490 &event_expr->where);
10491 return NULL_TREE;
10494 image_index = integer_zero_node;
10496 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10497 event_expr);
10499 /* For arrays, obtain the array index. */
10500 if (gfc_expr_attr (event_expr).dimension)
10502 tree desc, tmp, extent, lbound, ubound;
10503 gfc_array_ref *ar, ar2;
10504 int i;
10506 /* TODO: Extend this, once DT components are supported. */
10507 ar = &event_expr->ref->u.ar;
10508 ar2 = *ar;
10509 memset (ar, '\0', sizeof (*ar));
10510 ar->as = ar2.as;
10511 ar->type = AR_FULL;
10513 gfc_init_se (&argse, NULL);
10514 argse.descriptor_only = 1;
10515 gfc_conv_expr_descriptor (&argse, event_expr);
10516 gfc_add_block_to_block (&se.pre, &argse.pre);
10517 desc = argse.expr;
10518 *ar = ar2;
10520 extent = integer_one_node;
10521 for (i = 0; i < ar->dimen; i++)
10523 gfc_init_se (&argse, NULL);
10524 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10525 gfc_add_block_to_block (&argse.pre, &argse.pre);
10526 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10527 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10528 integer_type_node, argse.expr,
10529 fold_convert(integer_type_node, lbound));
10530 tmp = fold_build2_loc (input_location, MULT_EXPR,
10531 integer_type_node, extent, tmp);
10532 index = fold_build2_loc (input_location, PLUS_EXPR,
10533 integer_type_node, index, tmp);
10534 if (i < ar->dimen - 1)
10536 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10537 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10538 tmp = fold_convert (integer_type_node, tmp);
10539 extent = fold_build2_loc (input_location, MULT_EXPR,
10540 integer_type_node, extent, tmp);
10545 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10547 count2 = count;
10548 count = gfc_create_var (integer_type_node, "count");
10551 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10553 stat2 = stat;
10554 stat = gfc_create_var (integer_type_node, "stat");
10557 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10558 token, index, image_index, count
10559 ? gfc_build_addr_expr (NULL, count) : count,
10560 stat != null_pointer_node
10561 ? gfc_build_addr_expr (NULL, stat) : stat);
10562 gfc_add_expr_to_block (&se.pre, tmp);
10564 if (count2 != NULL_TREE)
10565 gfc_add_modify (&se.pre, count2,
10566 fold_convert (TREE_TYPE (count2), count));
10568 if (stat2 != NULL_TREE)
10569 gfc_add_modify (&se.pre, stat2,
10570 fold_convert (TREE_TYPE (stat2), stat));
10572 return gfc_finish_block (&se.pre);
10575 gfc_init_se (&argse, NULL);
10576 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10577 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10579 if (stat != NULL_TREE)
10580 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10582 return gfc_finish_block (&se.pre);
10585 static tree
10586 conv_intrinsic_move_alloc (gfc_code *code)
10588 stmtblock_t block;
10589 gfc_expr *from_expr, *to_expr;
10590 gfc_expr *to_expr2, *from_expr2 = NULL;
10591 gfc_se from_se, to_se;
10592 tree tmp;
10593 bool coarray;
10595 gfc_start_block (&block);
10597 from_expr = code->ext.actual->expr;
10598 to_expr = code->ext.actual->next->expr;
10600 gfc_init_se (&from_se, NULL);
10601 gfc_init_se (&to_se, NULL);
10603 gcc_assert (from_expr->ts.type != BT_CLASS
10604 || to_expr->ts.type == BT_CLASS);
10605 coarray = gfc_get_corank (from_expr) != 0;
10607 if (from_expr->rank == 0 && !coarray)
10609 if (from_expr->ts.type != BT_CLASS)
10610 from_expr2 = from_expr;
10611 else
10613 from_expr2 = gfc_copy_expr (from_expr);
10614 gfc_add_data_component (from_expr2);
10617 if (to_expr->ts.type != BT_CLASS)
10618 to_expr2 = to_expr;
10619 else
10621 to_expr2 = gfc_copy_expr (to_expr);
10622 gfc_add_data_component (to_expr2);
10625 from_se.want_pointer = 1;
10626 to_se.want_pointer = 1;
10627 gfc_conv_expr (&from_se, from_expr2);
10628 gfc_conv_expr (&to_se, to_expr2);
10629 gfc_add_block_to_block (&block, &from_se.pre);
10630 gfc_add_block_to_block (&block, &to_se.pre);
10632 /* Deallocate "to". */
10633 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10634 true, to_expr, to_expr->ts);
10635 gfc_add_expr_to_block (&block, tmp);
10637 /* Assign (_data) pointers. */
10638 gfc_add_modify_loc (input_location, &block, to_se.expr,
10639 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10641 /* Set "from" to NULL. */
10642 gfc_add_modify_loc (input_location, &block, from_se.expr,
10643 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10645 gfc_add_block_to_block (&block, &from_se.post);
10646 gfc_add_block_to_block (&block, &to_se.post);
10648 /* Set _vptr. */
10649 if (to_expr->ts.type == BT_CLASS)
10651 gfc_symbol *vtab;
10653 gfc_free_expr (to_expr2);
10654 gfc_init_se (&to_se, NULL);
10655 to_se.want_pointer = 1;
10656 gfc_add_vptr_component (to_expr);
10657 gfc_conv_expr (&to_se, to_expr);
10659 if (from_expr->ts.type == BT_CLASS)
10661 if (UNLIMITED_POLY (from_expr))
10662 vtab = NULL;
10663 else
10665 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10666 gcc_assert (vtab);
10669 gfc_free_expr (from_expr2);
10670 gfc_init_se (&from_se, NULL);
10671 from_se.want_pointer = 1;
10672 gfc_add_vptr_component (from_expr);
10673 gfc_conv_expr (&from_se, from_expr);
10674 gfc_add_modify_loc (input_location, &block, to_se.expr,
10675 fold_convert (TREE_TYPE (to_se.expr),
10676 from_se.expr));
10678 /* Reset _vptr component to declared type. */
10679 if (vtab == NULL)
10680 /* Unlimited polymorphic. */
10681 gfc_add_modify_loc (input_location, &block, from_se.expr,
10682 fold_convert (TREE_TYPE (from_se.expr),
10683 null_pointer_node));
10684 else
10686 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10687 gfc_add_modify_loc (input_location, &block, from_se.expr,
10688 fold_convert (TREE_TYPE (from_se.expr), tmp));
10691 else
10693 vtab = gfc_find_vtab (&from_expr->ts);
10694 gcc_assert (vtab);
10695 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10696 gfc_add_modify_loc (input_location, &block, to_se.expr,
10697 fold_convert (TREE_TYPE (to_se.expr), tmp));
10701 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10703 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10704 fold_convert (TREE_TYPE (to_se.string_length),
10705 from_se.string_length));
10706 if (from_expr->ts.deferred)
10707 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10708 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10711 return gfc_finish_block (&block);
10714 /* Update _vptr component. */
10715 if (to_expr->ts.type == BT_CLASS)
10717 gfc_symbol *vtab;
10719 to_se.want_pointer = 1;
10720 to_expr2 = gfc_copy_expr (to_expr);
10721 gfc_add_vptr_component (to_expr2);
10722 gfc_conv_expr (&to_se, to_expr2);
10724 if (from_expr->ts.type == BT_CLASS)
10726 if (UNLIMITED_POLY (from_expr))
10727 vtab = NULL;
10728 else
10730 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10731 gcc_assert (vtab);
10734 from_se.want_pointer = 1;
10735 from_expr2 = gfc_copy_expr (from_expr);
10736 gfc_add_vptr_component (from_expr2);
10737 gfc_conv_expr (&from_se, from_expr2);
10738 gfc_add_modify_loc (input_location, &block, to_se.expr,
10739 fold_convert (TREE_TYPE (to_se.expr),
10740 from_se.expr));
10742 /* Reset _vptr component to declared type. */
10743 if (vtab == NULL)
10744 /* Unlimited polymorphic. */
10745 gfc_add_modify_loc (input_location, &block, from_se.expr,
10746 fold_convert (TREE_TYPE (from_se.expr),
10747 null_pointer_node));
10748 else
10750 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10751 gfc_add_modify_loc (input_location, &block, from_se.expr,
10752 fold_convert (TREE_TYPE (from_se.expr), tmp));
10755 else
10757 vtab = gfc_find_vtab (&from_expr->ts);
10758 gcc_assert (vtab);
10759 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10760 gfc_add_modify_loc (input_location, &block, to_se.expr,
10761 fold_convert (TREE_TYPE (to_se.expr), tmp));
10764 gfc_free_expr (to_expr2);
10765 gfc_init_se (&to_se, NULL);
10767 if (from_expr->ts.type == BT_CLASS)
10769 gfc_free_expr (from_expr2);
10770 gfc_init_se (&from_se, NULL);
10775 /* Deallocate "to". */
10776 if (from_expr->rank == 0)
10778 to_se.want_coarray = 1;
10779 from_se.want_coarray = 1;
10781 gfc_conv_expr_descriptor (&to_se, to_expr);
10782 gfc_conv_expr_descriptor (&from_se, from_expr);
10784 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10785 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10786 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10788 tree cond;
10790 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10791 NULL_TREE, NULL_TREE, true, to_expr,
10792 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10793 gfc_add_expr_to_block (&block, tmp);
10795 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10796 cond = fold_build2_loc (input_location, EQ_EXPR,
10797 logical_type_node, tmp,
10798 fold_convert (TREE_TYPE (tmp),
10799 null_pointer_node));
10800 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10801 3, null_pointer_node, null_pointer_node,
10802 build_int_cst (integer_type_node, 0));
10804 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
10805 tmp, build_empty_stmt (input_location));
10806 gfc_add_expr_to_block (&block, tmp);
10808 else
10810 if (to_expr->ts.type == BT_DERIVED
10811 && to_expr->ts.u.derived->attr.alloc_comp)
10813 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
10814 to_se.expr, to_expr->rank);
10815 gfc_add_expr_to_block (&block, tmp);
10818 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10819 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
10820 NULL_TREE, true, to_expr,
10821 GFC_CAF_COARRAY_NOCOARRAY);
10822 gfc_add_expr_to_block (&block, tmp);
10825 /* Move the pointer and update the array descriptor data. */
10826 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
10828 /* Set "from" to NULL. */
10829 tmp = gfc_conv_descriptor_data_get (from_se.expr);
10830 gfc_add_modify_loc (input_location, &block, tmp,
10831 fold_convert (TREE_TYPE (tmp), null_pointer_node));
10834 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10836 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10837 fold_convert (TREE_TYPE (to_se.string_length),
10838 from_se.string_length));
10839 if (from_expr->ts.deferred)
10840 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10841 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10844 return gfc_finish_block (&block);
10848 tree
10849 gfc_conv_intrinsic_subroutine (gfc_code *code)
10851 tree res;
10853 gcc_assert (code->resolved_isym);
10855 switch (code->resolved_isym->id)
10857 case GFC_ISYM_MOVE_ALLOC:
10858 res = conv_intrinsic_move_alloc (code);
10859 break;
10861 case GFC_ISYM_ATOMIC_CAS:
10862 res = conv_intrinsic_atomic_cas (code);
10863 break;
10865 case GFC_ISYM_ATOMIC_ADD:
10866 case GFC_ISYM_ATOMIC_AND:
10867 case GFC_ISYM_ATOMIC_DEF:
10868 case GFC_ISYM_ATOMIC_OR:
10869 case GFC_ISYM_ATOMIC_XOR:
10870 case GFC_ISYM_ATOMIC_FETCH_ADD:
10871 case GFC_ISYM_ATOMIC_FETCH_AND:
10872 case GFC_ISYM_ATOMIC_FETCH_OR:
10873 case GFC_ISYM_ATOMIC_FETCH_XOR:
10874 res = conv_intrinsic_atomic_op (code);
10875 break;
10877 case GFC_ISYM_ATOMIC_REF:
10878 res = conv_intrinsic_atomic_ref (code);
10879 break;
10881 case GFC_ISYM_EVENT_QUERY:
10882 res = conv_intrinsic_event_query (code);
10883 break;
10885 case GFC_ISYM_C_F_POINTER:
10886 case GFC_ISYM_C_F_PROCPOINTER:
10887 res = conv_isocbinding_subroutine (code);
10888 break;
10890 case GFC_ISYM_CAF_SEND:
10891 res = conv_caf_send (code);
10892 break;
10894 case GFC_ISYM_CO_BROADCAST:
10895 case GFC_ISYM_CO_MIN:
10896 case GFC_ISYM_CO_MAX:
10897 case GFC_ISYM_CO_REDUCE:
10898 case GFC_ISYM_CO_SUM:
10899 res = conv_co_collective (code);
10900 break;
10902 case GFC_ISYM_FREE:
10903 res = conv_intrinsic_free (code);
10904 break;
10906 case GFC_ISYM_KILL:
10907 res = conv_intrinsic_kill_sub (code);
10908 break;
10910 case GFC_ISYM_SYSTEM_CLOCK:
10911 res = conv_intrinsic_system_clock (code);
10912 break;
10914 default:
10915 res = NULL_TREE;
10916 break;
10919 return res;
10922 #include "gt-fortran-trans-intrinsic.h"